4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
31 #define WIN32_NO_STATUS
33 #include "unix_private.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
39 /***********************************************************************
40 * NtOpenProcessToken (NTDLL.@)
42 NTSTATUS WINAPI
NtOpenProcessToken( HANDLE process
, DWORD access
, HANDLE
*handle
)
44 return NtOpenProcessTokenEx( process
, access
, 0, handle
);
48 /***********************************************************************
49 * NtOpenProcessTokenEx (NTDLL.@)
51 NTSTATUS WINAPI
NtOpenProcessTokenEx( HANDLE process
, DWORD access
, DWORD attributes
, HANDLE
*handle
)
55 TRACE( "(%p,0x%08x,0x%08x,%p)\n", process
, access
, attributes
, handle
);
57 SERVER_START_REQ( open_token
)
59 req
->handle
= wine_server_obj_handle( process
);
61 req
->attributes
= attributes
;
63 ret
= wine_server_call( req
);
64 if (!ret
) *handle
= wine_server_ptr_handle( reply
->token
);
71 /***********************************************************************
72 * NtOpenThreadToken (NTDLL.@)
74 NTSTATUS WINAPI
NtOpenThreadToken( HANDLE thread
, DWORD access
, BOOLEAN self
, HANDLE
*handle
)
76 return NtOpenThreadTokenEx( thread
, access
, self
, 0, handle
);
80 /***********************************************************************
81 * NtOpenThreadTokenEx (NTDLL.@)
83 NTSTATUS WINAPI
NtOpenThreadTokenEx( HANDLE thread
, DWORD access
, BOOLEAN self
, DWORD attributes
,
88 TRACE( "(%p,0x%08x,%u,0x%08x,%p)\n", thread
, access
, self
, attributes
, handle
);
90 SERVER_START_REQ( open_token
)
92 req
->handle
= wine_server_obj_handle( thread
);
94 req
->attributes
= attributes
;
95 req
->flags
= OPEN_TOKEN_THREAD
;
96 if (self
) req
->flags
|= OPEN_TOKEN_AS_SELF
;
97 ret
= wine_server_call( req
);
98 if (!ret
) *handle
= wine_server_ptr_handle( reply
->token
);
105 /***********************************************************************
106 * NtDuplicateToken (NTDLL.@)
108 NTSTATUS WINAPI
NtDuplicateToken( HANDLE token
, ACCESS_MASK access
, OBJECT_ATTRIBUTES
*attr
,
109 SECURITY_IMPERSONATION_LEVEL level
, TOKEN_TYPE type
, HANDLE
*handle
)
113 struct object_attributes
*objattr
;
115 if ((status
= alloc_object_attributes( attr
, &objattr
, &len
))) return status
;
117 if (attr
&& attr
->SecurityQualityOfService
)
119 SECURITY_QUALITY_OF_SERVICE
*qos
= attr
->SecurityQualityOfService
;
120 TRACE( "ObjectAttributes->SecurityQualityOfService = {%d, %d, %d, %s}\n",
121 qos
->Length
, qos
->ImpersonationLevel
, qos
->ContextTrackingMode
,
122 qos
->EffectiveOnly
? "TRUE" : "FALSE");
123 level
= qos
->ImpersonationLevel
;
126 SERVER_START_REQ( duplicate_token
)
128 req
->handle
= wine_server_obj_handle( token
);
129 req
->access
= access
;
130 req
->primary
= (type
== TokenPrimary
);
131 req
->impersonation_level
= level
;
132 wine_server_add_data( req
, objattr
, len
);
133 status
= wine_server_call( req
);
134 if (!status
) *handle
= wine_server_ptr_handle( reply
->new_handle
);
142 /***********************************************************************
143 * NtQueryInformationToken (NTDLL.@)
145 NTSTATUS WINAPI
NtQueryInformationToken( HANDLE token
, TOKEN_INFORMATION_CLASS
class,
146 void *info
, ULONG length
, ULONG
*retlen
)
148 static const ULONG info_len
[] =
153 0, /* TokenPrivileges */
155 0, /* TokenPrimaryGroup */
156 0, /* TokenDefaultDacl */
157 sizeof(TOKEN_SOURCE
), /* TokenSource */
158 sizeof(TOKEN_TYPE
), /* TokenType */
159 sizeof(SECURITY_IMPERSONATION_LEVEL
), /* TokenImpersonationLevel */
160 sizeof(TOKEN_STATISTICS
), /* TokenStatistics */
161 0, /* TokenRestrictedSids */
162 sizeof(DWORD
), /* TokenSessionId */
163 0, /* TokenGroupsAndPrivileges */
164 0, /* TokenSessionReference */
165 0, /* TokenSandBoxInert */
166 0, /* TokenAuditPolicy */
168 sizeof(TOKEN_ELEVATION_TYPE
), /* TokenElevationType */
169 0, /* TokenLinkedToken */
170 sizeof(TOKEN_ELEVATION
), /* TokenElevation */
171 0, /* TokenHasRestrictions */
172 0, /* TokenAccessInformation */
173 0, /* TokenVirtualizationAllowed */
174 sizeof(DWORD
), /* TokenVirtualizationEnabled */
175 sizeof(TOKEN_MANDATORY_LABEL
) + sizeof(SID
), /* TokenIntegrityLevel [sizeof(SID) includes one SubAuthority] */
176 0, /* TokenUIAccess */
177 0, /* TokenMandatoryPolicy */
178 0, /* TokenLogonSid */
179 sizeof(DWORD
), /* TokenIsAppContainer */
180 0, /* TokenCapabilities */
181 sizeof(TOKEN_APPCONTAINER_INFORMATION
) + sizeof(SID
), /* TokenAppContainerSid */
182 0, /* TokenAppContainerNumber */
183 0, /* TokenUserClaimAttributes*/
184 0, /* TokenDeviceClaimAttributes */
185 0, /* TokenRestrictedUserClaimAttributes */
186 0, /* TokenRestrictedDeviceClaimAttributes */
187 0, /* TokenDeviceGroups */
188 0, /* TokenRestrictedDeviceGroups */
189 0, /* TokenSecurityAttributes */
190 0, /* TokenIsRestricted */
191 0 /* TokenProcessTrustLevel */
195 NTSTATUS status
= STATUS_SUCCESS
;
197 TRACE( "(%p,%d,%p,%d,%p)\n", token
, class, info
, length
, retlen
);
199 if (class < MaxTokenInfoClass
) len
= info_len
[class];
200 if (retlen
) *retlen
= len
;
201 if (length
< len
) return STATUS_BUFFER_TOO_SMALL
;
206 SERVER_START_REQ( get_token_sid
)
208 TOKEN_USER
*tuser
= info
;
209 PSID sid
= tuser
+ 1;
210 DWORD sid_len
= length
< sizeof(TOKEN_USER
) ? 0 : length
- sizeof(TOKEN_USER
);
212 req
->handle
= wine_server_obj_handle( token
);
213 req
->which_sid
= class;
214 wine_server_set_reply( req
, sid
, sid_len
);
215 status
= wine_server_call( req
);
216 if (retlen
) *retlen
= reply
->sid_len
+ sizeof(TOKEN_USER
);
217 if (status
== STATUS_SUCCESS
)
219 tuser
->User
.Sid
= sid
;
220 tuser
->User
.Attributes
= 0;
228 /* reply buffer is always shorter than output one */
229 void *buffer
= malloc( length
);
231 SERVER_START_REQ( get_token_groups
)
233 TOKEN_GROUPS
*groups
= info
;
235 req
->handle
= wine_server_obj_handle( token
);
236 wine_server_set_reply( req
, buffer
, length
);
237 status
= wine_server_call( req
);
238 if (status
== STATUS_BUFFER_TOO_SMALL
)
240 if (retlen
) *retlen
= reply
->user_len
;
242 else if (status
== STATUS_SUCCESS
)
244 struct token_groups
*tg
= buffer
;
245 unsigned int *attr
= (unsigned int *)(tg
+ 1);
247 const int non_sid_portion
= (sizeof(struct token_groups
) + tg
->count
* sizeof(unsigned int));
248 SID
*sids
= (SID
*)((char *)info
+ FIELD_OFFSET( TOKEN_GROUPS
, Groups
[tg
->count
] ));
250 if (retlen
) *retlen
= reply
->user_len
;
252 groups
->GroupCount
= tg
->count
;
253 memcpy( sids
, (char *)buffer
+ non_sid_portion
,
254 reply
->user_len
- offsetof( TOKEN_GROUPS
, Groups
[tg
->count
] ));
256 for (i
= 0; i
< tg
->count
; i
++)
258 groups
->Groups
[i
].Attributes
= attr
[i
];
259 groups
->Groups
[i
].Sid
= sids
;
260 sids
= (SID
*)((char *)sids
+ offsetof( SID
, SubAuthority
[sids
->SubAuthorityCount
] ));
263 else if (retlen
) *retlen
= 0;
270 case TokenPrimaryGroup
:
271 SERVER_START_REQ( get_token_sid
)
273 TOKEN_PRIMARY_GROUP
*tgroup
= info
;
274 PSID sid
= tgroup
+ 1;
275 DWORD sid_len
= length
< sizeof(TOKEN_PRIMARY_GROUP
) ? 0 : length
- sizeof(TOKEN_PRIMARY_GROUP
);
277 req
->handle
= wine_server_obj_handle( token
);
278 req
->which_sid
= class;
279 wine_server_set_reply( req
, sid
, sid_len
);
280 status
= wine_server_call( req
);
281 if (retlen
) *retlen
= reply
->sid_len
+ sizeof(TOKEN_PRIMARY_GROUP
);
282 if (status
== STATUS_SUCCESS
) tgroup
->PrimaryGroup
= sid
;
287 case TokenPrivileges
:
288 SERVER_START_REQ( get_token_privileges
)
290 TOKEN_PRIVILEGES
*tpriv
= info
;
291 req
->handle
= wine_server_obj_handle( token
);
292 if (tpriv
&& length
> FIELD_OFFSET( TOKEN_PRIVILEGES
, Privileges
))
293 wine_server_set_reply( req
, tpriv
->Privileges
, length
- FIELD_OFFSET( TOKEN_PRIVILEGES
, Privileges
) );
294 status
= wine_server_call( req
);
295 if (retlen
) *retlen
= FIELD_OFFSET( TOKEN_PRIVILEGES
, Privileges
) + reply
->len
;
296 if (tpriv
) tpriv
->PrivilegeCount
= reply
->len
/ sizeof(LUID_AND_ATTRIBUTES
);
302 SERVER_START_REQ( get_token_sid
)
304 TOKEN_OWNER
*towner
= info
;
305 PSID sid
= towner
+ 1;
306 DWORD sid_len
= length
< sizeof(TOKEN_OWNER
) ? 0 : length
- sizeof(TOKEN_OWNER
);
308 req
->handle
= wine_server_obj_handle( token
);
309 req
->which_sid
= class;
310 wine_server_set_reply( req
, sid
, sid_len
);
311 status
= wine_server_call( req
);
312 if (retlen
) *retlen
= reply
->sid_len
+ sizeof(TOKEN_OWNER
);
313 if (status
== STATUS_SUCCESS
) towner
->Owner
= sid
;
318 case TokenImpersonationLevel
:
319 SERVER_START_REQ( get_token_impersonation_level
)
321 SECURITY_IMPERSONATION_LEVEL
*level
= info
;
322 req
->handle
= wine_server_obj_handle( token
);
323 status
= wine_server_call( req
);
324 if (status
== STATUS_SUCCESS
) *level
= reply
->impersonation_level
;
329 case TokenStatistics
:
330 SERVER_START_REQ( get_token_statistics
)
332 TOKEN_STATISTICS
*statistics
= info
;
333 req
->handle
= wine_server_obj_handle( token
);
334 status
= wine_server_call( req
);
335 if (status
== STATUS_SUCCESS
)
337 statistics
->TokenId
.LowPart
= reply
->token_id
.low_part
;
338 statistics
->TokenId
.HighPart
= reply
->token_id
.high_part
;
339 statistics
->AuthenticationId
.LowPart
= 0; /* FIXME */
340 statistics
->AuthenticationId
.HighPart
= 0; /* FIXME */
341 statistics
->ExpirationTime
.u
.HighPart
= 0x7fffffff;
342 statistics
->ExpirationTime
.u
.LowPart
= 0xffffffff;
343 statistics
->TokenType
= reply
->primary
? TokenPrimary
: TokenImpersonation
;
344 statistics
->ImpersonationLevel
= reply
->impersonation_level
;
346 /* kernel information not relevant to us */
347 statistics
->DynamicCharged
= 0;
348 statistics
->DynamicAvailable
= 0;
350 statistics
->GroupCount
= reply
->group_count
;
351 statistics
->PrivilegeCount
= reply
->privilege_count
;
352 statistics
->ModifiedId
.LowPart
= reply
->modified_id
.low_part
;
353 statistics
->ModifiedId
.HighPart
= reply
->modified_id
.high_part
;
360 SERVER_START_REQ( get_token_statistics
)
362 TOKEN_TYPE
*type
= info
;
363 req
->handle
= wine_server_obj_handle( token
);
364 status
= wine_server_call( req
);
365 if (status
== STATUS_SUCCESS
) *type
= reply
->primary
? TokenPrimary
: TokenImpersonation
;
370 case TokenDefaultDacl
:
371 SERVER_START_REQ( get_token_default_dacl
)
373 TOKEN_DEFAULT_DACL
*default_dacl
= info
;
374 ACL
*acl
= (ACL
*)(default_dacl
+ 1);
375 DWORD acl_len
= length
< sizeof(TOKEN_DEFAULT_DACL
) ? 0 : length
- sizeof(TOKEN_DEFAULT_DACL
);
377 req
->handle
= wine_server_obj_handle( token
);
378 wine_server_set_reply( req
, acl
, acl_len
);
379 status
= wine_server_call( req
);
380 if (retlen
) *retlen
= reply
->acl_len
+ sizeof(TOKEN_DEFAULT_DACL
);
381 if (status
== STATUS_SUCCESS
)
384 default_dacl
->DefaultDacl
= acl
;
386 default_dacl
->DefaultDacl
= NULL
;
392 case TokenElevationType
:
394 TOKEN_ELEVATION_TYPE
*type
= info
;
395 FIXME("QueryInformationToken( ..., TokenElevationType, ...) semi-stub\n");
396 *type
= TokenElevationTypeFull
;
402 TOKEN_ELEVATION
*elevation
= info
;
403 FIXME("QueryInformationToken( ..., TokenElevation, ...) semi-stub\n");
404 elevation
->TokenIsElevated
= TRUE
;
411 FIXME("QueryInformationToken( ..., TokenSessionId, ...) semi-stub\n");
415 case TokenVirtualizationEnabled
:
418 TRACE("QueryInformationToken( ..., TokenVirtualizationEnabled, ...) semi-stub\n");
422 case TokenIntegrityLevel
:
424 /* report always "S-1-16-12288" (high mandatory level) for now */
425 static const SID high_level
= {SID_REVISION
, 1, {SECURITY_MANDATORY_LABEL_AUTHORITY
},
426 {SECURITY_MANDATORY_HIGH_RID
}};
428 TOKEN_MANDATORY_LABEL
*tml
= info
;
431 tml
->Label
.Sid
= psid
;
432 tml
->Label
.Attributes
= SE_GROUP_INTEGRITY
| SE_GROUP_INTEGRITY_ENABLED
;
433 memcpy( psid
, &high_level
, sizeof(SID
) );
437 case TokenAppContainerSid
:
439 TOKEN_APPCONTAINER_INFORMATION
*container
= info
;
440 FIXME("QueryInformationToken( ..., TokenAppContainerSid, ...) semi-stub\n");
441 container
->TokenAppContainer
= NULL
;
445 case TokenIsAppContainer
:
447 TRACE("TokenIsAppContainer semi-stub\n");
453 SERVER_START_REQ( get_token_sid
)
455 TOKEN_GROUPS
* groups
= info
;
456 PSID sid
= groups
+ 1;
457 DWORD sid_len
= length
< sizeof(TOKEN_GROUPS
) ? 0 : length
- sizeof(TOKEN_GROUPS
);
459 req
->handle
= wine_server_obj_handle( token
);
460 req
->which_sid
= class;
461 wine_server_set_reply( req
, sid
, sid_len
);
462 status
= wine_server_call( req
);
463 if (retlen
) *retlen
= reply
->sid_len
+ sizeof(TOKEN_GROUPS
);
464 if (status
== STATUS_SUCCESS
)
466 groups
->GroupCount
= 1;
467 groups
->Groups
[0].Sid
= sid
;
468 groups
->Groups
[0].Attributes
= 0;
475 ERR( "Unhandled token information class %u\n", class );
476 return STATUS_NOT_IMPLEMENTED
;
482 /***********************************************************************
483 * NtSetInformationToken (NTDLL.@)
485 NTSTATUS WINAPI
NtSetInformationToken( HANDLE token
, TOKEN_INFORMATION_CLASS
class,
486 void *info
, ULONG length
)
488 NTSTATUS ret
= STATUS_NOT_IMPLEMENTED
;
490 TRACE( "%p %d %p %u\n", token
, class, info
, length
);
494 case TokenDefaultDacl
:
495 if (length
< sizeof(TOKEN_DEFAULT_DACL
))
497 ret
= STATUS_INFO_LENGTH_MISMATCH
;
502 ret
= STATUS_ACCESS_VIOLATION
;
505 SERVER_START_REQ( set_token_default_dacl
)
507 ACL
*acl
= ((TOKEN_DEFAULT_DACL
*)info
)->DefaultDacl
;
510 if (acl
) size
= acl
->AclSize
;
512 req
->handle
= wine_server_obj_handle( token
);
513 wine_server_add_data( req
, acl
, size
);
514 ret
= wine_server_call( req
);
520 if (length
< sizeof(DWORD
))
522 ret
= STATUS_INFO_LENGTH_MISMATCH
;
527 ret
= STATUS_ACCESS_VIOLATION
;
530 FIXME("TokenSessionId stub!\n");
531 ret
= STATUS_SUCCESS
;
534 case TokenIntegrityLevel
:
535 FIXME( "TokenIntegrityLevel stub!\n" );
536 ret
= STATUS_SUCCESS
;
540 FIXME( "unimplemented class %u\n", class );
547 /***********************************************************************
548 * NtCreateLowBoxToken (NTDLL.@)
550 NTSTATUS WINAPI
NtCreateLowBoxToken( HANDLE
*token_handle
, HANDLE token
, ACCESS_MASK access
,
551 OBJECT_ATTRIBUTES
*attr
, SID
*sid
, ULONG count
,
552 SID_AND_ATTRIBUTES
*capabilities
, ULONG handle_count
, HANDLE
*handle
)
554 FIXME("(%p, %p, %x, %p, %p, %u, %p, %u, %p): stub\n",
555 token_handle
, token
, access
, attr
, sid
, count
, capabilities
, handle_count
, handle
);
557 /* we need to return a NULL handle since later it will be passed to NtClose and that must not fail */
558 *token_handle
= NULL
;
559 return STATUS_SUCCESS
;
563 /***********************************************************************
564 * NtAdjustGroupsToken (NTDLL.@)
566 NTSTATUS WINAPI
NtAdjustGroupsToken( HANDLE token
, BOOLEAN reset
, TOKEN_GROUPS
*groups
,
567 ULONG length
, TOKEN_GROUPS
*prev
, ULONG
*retlen
)
569 FIXME( "%p %d %p %u %p %p\n", token
, reset
, groups
, length
, prev
, retlen
);
570 return STATUS_NOT_IMPLEMENTED
;
574 /***********************************************************************
575 * NtAdjustPrivilegesToken (NTDLL.@)
577 NTSTATUS WINAPI
NtAdjustPrivilegesToken( HANDLE token
, BOOLEAN disable
, TOKEN_PRIVILEGES
*privs
,
578 DWORD length
, TOKEN_PRIVILEGES
*prev
, DWORD
*retlen
)
582 TRACE( "(%p,0x%08x,%p,0x%08x,%p,%p)\n", token
, disable
, privs
, length
, prev
, retlen
);
584 SERVER_START_REQ( adjust_token_privileges
)
586 req
->handle
= wine_server_obj_handle( token
);
587 req
->disable_all
= disable
;
588 req
->get_modified_state
= (prev
!= NULL
);
590 wine_server_add_data( req
, privs
->Privileges
,
591 privs
->PrivilegeCount
* sizeof(privs
->Privileges
[0]) );
592 if (prev
&& length
>= FIELD_OFFSET( TOKEN_PRIVILEGES
, Privileges
))
593 wine_server_set_reply( req
, prev
->Privileges
,
594 length
- FIELD_OFFSET( TOKEN_PRIVILEGES
, Privileges
) );
595 ret
= wine_server_call( req
);
598 if (retlen
) *retlen
= reply
->len
+ FIELD_OFFSET( TOKEN_PRIVILEGES
, Privileges
);
599 prev
->PrivilegeCount
= reply
->len
/ sizeof(LUID_AND_ATTRIBUTES
);
607 /***********************************************************************
608 * NtPrivilegeCheck (NTDLL.@)
610 NTSTATUS WINAPI
NtPrivilegeCheck( HANDLE token
, PRIVILEGE_SET
*privs
, BOOLEAN
*res
)
614 SERVER_START_REQ( check_token_privileges
)
616 req
->handle
= wine_server_obj_handle( token
);
617 req
->all_required
= (privs
->Control
& PRIVILEGE_SET_ALL_NECESSARY
) != 0;
618 wine_server_add_data( req
, privs
->Privilege
, privs
->PrivilegeCount
* sizeof(privs
->Privilege
[0]) );
619 wine_server_set_reply( req
, privs
->Privilege
, privs
->PrivilegeCount
* sizeof(privs
->Privilege
[0]) );
620 status
= wine_server_call( req
);
621 if (status
== STATUS_SUCCESS
) *res
= reply
->has_privileges
!= 0;
628 /***********************************************************************
629 * NtImpersonateAnonymousToken (NTDLL.@)
631 NTSTATUS WINAPI
NtImpersonateAnonymousToken( HANDLE thread
)
633 FIXME( "(%p): stub\n", thread
);
634 return STATUS_NOT_IMPLEMENTED
;
638 /***********************************************************************
639 * NtAccessCheck (NTDLL.@)
641 NTSTATUS WINAPI
NtAccessCheck( PSECURITY_DESCRIPTOR descr
, HANDLE token
, ACCESS_MASK access
,
642 GENERIC_MAPPING
*mapping
, PRIVILEGE_SET
*privs
, ULONG
*retlen
,
643 ULONG
*access_granted
, NTSTATUS
*access_status
)
645 struct object_attributes
*objattr
;
647 OBJECT_ATTRIBUTES attr
;
650 TRACE( "(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
651 descr
, token
, access
, mapping
, privs
, retlen
, access_granted
, access_status
);
653 if (!privs
|| !retlen
) return STATUS_ACCESS_VIOLATION
;
655 /* reuse the object attribute SD marshalling */
656 InitializeObjectAttributes( &attr
, NULL
, 0, 0, descr
);
657 if ((status
= alloc_object_attributes( &attr
, &objattr
, &len
))) return status
;
659 SERVER_START_REQ( access_check
)
661 req
->handle
= wine_server_obj_handle( token
);
662 req
->desired_access
= access
;
663 req
->mapping_read
= mapping
->GenericRead
;
664 req
->mapping_write
= mapping
->GenericWrite
;
665 req
->mapping_execute
= mapping
->GenericExecute
;
666 req
->mapping_all
= mapping
->GenericAll
;
667 wine_server_add_data( req
, objattr
+ 1, objattr
->sd_len
);
668 wine_server_set_reply( req
, privs
->Privilege
, *retlen
- offsetof( PRIVILEGE_SET
, Privilege
) );
670 status
= wine_server_call( req
);
672 *retlen
= offsetof( PRIVILEGE_SET
, Privilege
) + reply
->privileges_len
;
673 privs
->PrivilegeCount
= reply
->privileges_len
/ sizeof(LUID_AND_ATTRIBUTES
);
674 if (status
== STATUS_SUCCESS
)
676 *access_status
= reply
->access_status
;
677 *access_granted
= reply
->access_granted
;
686 /***********************************************************************
687 * NtAccessCheckAndAuditAlarm (NTDLL.@)
689 NTSTATUS WINAPI
NtAccessCheckAndAuditAlarm( UNICODE_STRING
*subsystem
, HANDLE handle
,
690 UNICODE_STRING
*typename
, UNICODE_STRING
*objectname
,
691 PSECURITY_DESCRIPTOR descr
, ACCESS_MASK access
,
692 GENERIC_MAPPING
*mapping
, BOOLEAN creation
,
693 ACCESS_MASK
*access_granted
, BOOLEAN
*access_status
,
696 FIXME( "(%s, %p, %s, %p, 0x%08x, %p, %d, %p, %p, %p), stub\n",
697 debugstr_us(subsystem
), handle
, debugstr_us(typename
), descr
, access
,
698 mapping
, creation
, access_granted
, access_status
, onclose
);
699 return STATUS_NOT_IMPLEMENTED
;
703 /***********************************************************************
704 * NtQuerySecurityObject (NTDLL.@)
706 NTSTATUS WINAPI
NtQuerySecurityObject( HANDLE handle
, SECURITY_INFORMATION info
,
707 PSECURITY_DESCRIPTOR descr
, ULONG length
, ULONG
*retlen
)
709 SECURITY_DESCRIPTOR_RELATIVE
*psd
= descr
;
712 unsigned int buffer_size
= 512;
714 TRACE( "(%p,0x%08x,%p,0x%08x,%p)\n", handle
, info
, descr
, length
, retlen
);
718 if (!(buffer
= malloc( buffer_size
))) return STATUS_NO_MEMORY
;
720 SERVER_START_REQ( get_security_object
)
722 req
->handle
= wine_server_obj_handle( handle
);
723 req
->security_info
= info
;
724 wine_server_set_reply( req
, buffer
, buffer_size
);
725 status
= wine_server_call( req
);
726 buffer_size
= reply
->sd_len
;
730 if (status
== STATUS_BUFFER_TOO_SMALL
)
735 if (status
== STATUS_SUCCESS
)
737 struct security_descriptor
*sd
= buffer
;
739 if (!buffer_size
) memset( sd
, 0, sizeof(*sd
) );
740 *retlen
= sizeof(*psd
) + sd
->owner_len
+ sd
->group_len
+ sd
->sacl_len
+ sd
->dacl_len
;
741 if (length
>= *retlen
)
743 DWORD len
= sizeof(*psd
);
744 memset( psd
, 0, len
);
745 psd
->Revision
= SECURITY_DESCRIPTOR_REVISION
;
746 psd
->Control
= sd
->control
| SE_SELF_RELATIVE
;
747 if (sd
->owner_len
) { psd
->Owner
= len
; len
+= sd
->owner_len
; }
748 if (sd
->group_len
) { psd
->Group
= len
; len
+= sd
->group_len
; }
749 if (sd
->sacl_len
) { psd
->Sacl
= len
; len
+= sd
->sacl_len
; }
750 if (sd
->dacl_len
) { psd
->Dacl
= len
; len
+= sd
->dacl_len
; }
751 /* owner, group, sacl and dacl are the same type as in the server
752 * and in the same order so we copy the memory in one block */
753 memcpy( psd
+ 1, sd
+ 1, len
- sizeof(*psd
) );
755 else status
= STATUS_BUFFER_TOO_SMALL
;
763 /***********************************************************************
764 * NtSetSecurityObject (NTDLL.@)
766 NTSTATUS WINAPI
NtSetSecurityObject( HANDLE handle
, SECURITY_INFORMATION info
, PSECURITY_DESCRIPTOR descr
)
768 struct object_attributes
*objattr
;
769 struct security_descriptor
*sd
;
771 OBJECT_ATTRIBUTES attr
;
774 TRACE( "%p 0x%08x %p\n", handle
, info
, descr
);
776 if (!descr
) return STATUS_ACCESS_VIOLATION
;
778 /* reuse the object attribute SD marshalling */
779 InitializeObjectAttributes( &attr
, NULL
, 0, 0, descr
);
780 if ((status
= alloc_object_attributes( &attr
, &objattr
, &len
))) return status
;
781 sd
= (struct security_descriptor
*)(objattr
+ 1);
782 if (info
& OWNER_SECURITY_INFORMATION
&& !sd
->owner_len
) return STATUS_INVALID_SECURITY_DESCR
;
783 if (info
& GROUP_SECURITY_INFORMATION
&& !sd
->group_len
) return STATUS_INVALID_SECURITY_DESCR
;
784 if (info
& (SACL_SECURITY_INFORMATION
| LABEL_SECURITY_INFORMATION
)) sd
->control
|= SE_SACL_PRESENT
;
785 if (info
& DACL_SECURITY_INFORMATION
) sd
->control
|= SE_DACL_PRESENT
;
787 SERVER_START_REQ( set_security_object
)
789 req
->handle
= wine_server_obj_handle( handle
);
790 req
->security_info
= info
;
791 wine_server_add_data( req
, sd
, objattr
->sd_len
);
792 status
= wine_server_call( req
);
800 /***********************************************************************
801 * NtAllocateLocallyUniqueId (NTDLL.@)
803 NTSTATUS WINAPI
NtAllocateLocallyUniqueId( LUID
*luid
)
807 TRACE( "%p\n", luid
);
809 if (!luid
) return STATUS_ACCESS_VIOLATION
;
811 SERVER_START_REQ( allocate_locally_unique_id
)
813 status
= wine_server_call( req
);
816 luid
->LowPart
= reply
->luid
.low_part
;
817 luid
->HighPart
= reply
->luid
.high_part
;
825 /***********************************************************************
826 * NtAllocateUuids (NTDLL.@)
828 NTSTATUS WINAPI
NtAllocateUuids( ULARGE_INTEGER
*time
, ULONG
*delta
, ULONG
*sequence
, UCHAR
*seed
)
830 FIXME( "(%p,%p,%p,%p), stub.\n", time
, delta
, sequence
, seed
);
831 return STATUS_SUCCESS
;