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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "wine/port.h"
36 #include "wine/exception.h"
37 #include "ntdll_misc.h"
39 #include "wine/library.h"
40 #include "wine/unicode.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(ntdll
);
45 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
47 /* filter for page-fault exceptions */
48 static WINE_EXCEPTION_FILTER(page_fault
)
50 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
)
51 return EXCEPTION_EXECUTE_HANDLER
;
52 return EXCEPTION_CONTINUE_SEARCH
;
55 /* helper function to copy an ACL */
56 static BOOLEAN
copy_acl(DWORD nDestinationAclLength
, PACL pDestinationAcl
, PACL pSourceAcl
)
60 if (!pSourceAcl
|| !RtlValidAcl(pSourceAcl
))
63 size
= ((ACL
*)pSourceAcl
)->AclSize
;
64 if (nDestinationAclLength
< size
)
67 memmove(pDestinationAcl
, pSourceAcl
, size
);
71 /* generically adds an ACE to an ACL */
72 static NTSTATUS
add_access_ace(PACL pAcl
, DWORD dwAceRevision
, DWORD dwAceFlags
,
73 DWORD dwAccessMask
, PSID pSid
, DWORD dwAceType
)
75 ACE_HEADER
*pAceHeader
;
81 if (!RtlValidSid(pSid
))
82 return STATUS_INVALID_SID
;
84 if (pAcl
->AclRevision
> MAX_ACL_REVISION
|| dwAceRevision
> MAX_ACL_REVISION
)
85 return STATUS_REVISION_MISMATCH
;
87 if (!RtlValidAcl(pAcl
))
88 return STATUS_INVALID_ACL
;
90 if (!RtlFirstFreeAce(pAcl
, &pAceHeader
))
91 return STATUS_INVALID_ACL
;
94 return STATUS_ALLOTTED_SPACE_EXCEEDED
;
96 /* calculate generic size of the ACE */
97 dwLengthSid
= RtlLengthSid(pSid
);
98 dwAceSize
= sizeof(ACE_HEADER
) + sizeof(DWORD
) + dwLengthSid
;
99 if ((char *)pAceHeader
+ dwAceSize
> (char *)pAcl
+ pAcl
->AclSize
)
100 return STATUS_ALLOTTED_SPACE_EXCEEDED
;
102 /* fill the new ACE */
103 pAceHeader
->AceType
= dwAceType
;
104 pAceHeader
->AceFlags
= dwAceFlags
;
105 pAceHeader
->AceSize
= dwAceSize
;
107 /* skip past the ACE_HEADER of the ACE */
108 pAccessMask
= (DWORD
*)(pAceHeader
+ 1);
109 *pAccessMask
= dwAccessMask
;
111 /* skip past ACE->Mask */
112 pSidStart
= pAccessMask
+ 1;
113 RtlCopySid(dwLengthSid
, (PSID
)pSidStart
, pSid
);
115 pAcl
->AclRevision
= max(pAcl
->AclRevision
, dwAceRevision
);
118 return STATUS_SUCCESS
;
125 /******************************************************************************
126 * RtlAllocateAndInitializeSid [NTDLL.@]
129 NTSTATUS WINAPI
RtlAllocateAndInitializeSid (
130 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority
,
131 BYTE nSubAuthorityCount
,
132 DWORD nSubAuthority0
, DWORD nSubAuthority1
,
133 DWORD nSubAuthority2
, DWORD nSubAuthority3
,
134 DWORD nSubAuthority4
, DWORD nSubAuthority5
,
135 DWORD nSubAuthority6
, DWORD nSubAuthority7
,
139 TRACE("(%p, 0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p)\n",
140 pIdentifierAuthority
,nSubAuthorityCount
,
141 nSubAuthority0
, nSubAuthority1
, nSubAuthority2
, nSubAuthority3
,
142 nSubAuthority4
, nSubAuthority5
, nSubAuthority6
, nSubAuthority7
, pSid
);
144 if (!(*pSid
= RtlAllocateHeap( GetProcessHeap(), 0,
145 RtlLengthRequiredSid(nSubAuthorityCount
))))
146 return STATUS_NO_MEMORY
;
148 ((SID
*)*pSid
)->Revision
= SID_REVISION
;
150 if (pIdentifierAuthority
)
151 memcpy(&((SID
*)*pSid
)->IdentifierAuthority
, pIdentifierAuthority
, sizeof (SID_IDENTIFIER_AUTHORITY
));
152 *RtlSubAuthorityCountSid(*pSid
) = nSubAuthorityCount
;
154 if (nSubAuthorityCount
> 0)
155 *RtlSubAuthoritySid(*pSid
, 0) = nSubAuthority0
;
156 if (nSubAuthorityCount
> 1)
157 *RtlSubAuthoritySid(*pSid
, 1) = nSubAuthority1
;
158 if (nSubAuthorityCount
> 2)
159 *RtlSubAuthoritySid(*pSid
, 2) = nSubAuthority2
;
160 if (nSubAuthorityCount
> 3)
161 *RtlSubAuthoritySid(*pSid
, 3) = nSubAuthority3
;
162 if (nSubAuthorityCount
> 4)
163 *RtlSubAuthoritySid(*pSid
, 4) = nSubAuthority4
;
164 if (nSubAuthorityCount
> 5)
165 *RtlSubAuthoritySid(*pSid
, 5) = nSubAuthority5
;
166 if (nSubAuthorityCount
> 6)
167 *RtlSubAuthoritySid(*pSid
, 6) = nSubAuthority6
;
168 if (nSubAuthorityCount
> 7)
169 *RtlSubAuthoritySid(*pSid
, 7) = nSubAuthority7
;
171 return STATUS_SUCCESS
;
173 /******************************************************************************
174 * RtlEqualSid [NTDLL.@]
176 * Determine if two SIDs are equal.
179 * pSid1 [I] Source SID
180 * pSid2 [I] SID to compare with
183 * TRUE, if pSid1 is equal to pSid2,
186 BOOL WINAPI
RtlEqualSid( PSID pSid1
, PSID pSid2
)
188 if (!RtlValidSid(pSid1
) || !RtlValidSid(pSid2
))
191 if (*RtlSubAuthorityCountSid(pSid1
) != *RtlSubAuthorityCountSid(pSid2
))
194 if (memcmp(pSid1
, pSid2
, RtlLengthSid(pSid1
)) != 0)
200 /******************************************************************************
201 * RtlEqualPrefixSid [NTDLL.@]
203 BOOL WINAPI
RtlEqualPrefixSid (PSID pSid1
, PSID pSid2
)
205 if (!RtlValidSid(pSid1
) || !RtlValidSid(pSid2
))
208 if (*RtlSubAuthorityCountSid(pSid1
) != *RtlSubAuthorityCountSid(pSid2
))
211 if (memcmp(pSid1
, pSid2
, RtlLengthRequiredSid(((SID
*)pSid1
)->SubAuthorityCount
- 1)) != 0)
218 /******************************************************************************
219 * RtlFreeSid [NTDLL.@]
221 * Free the resources used by a SID.
224 * pSid [I] SID to Free.
229 DWORD WINAPI
RtlFreeSid(PSID pSid
)
231 TRACE("(%p)\n", pSid
);
232 RtlFreeHeap( GetProcessHeap(), 0, pSid
);
233 return STATUS_SUCCESS
;
236 /**************************************************************************
237 * RtlLengthRequiredSid [NTDLL.@]
239 * Determine the amount of memory a SID will use
242 * nrofsubauths [I] Number of Sub Authorities in the SID.
245 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
247 DWORD WINAPI
RtlLengthRequiredSid(DWORD nrofsubauths
)
249 return (nrofsubauths
-1)*sizeof(DWORD
) + sizeof(SID
);
252 /**************************************************************************
253 * RtlLengthSid [NTDLL.@]
255 * Determine the amount of memory a SID is using
258 * pSid [I] SID to get the size of.
261 * The size, in bytes, of pSid.
263 DWORD WINAPI
RtlLengthSid(PSID pSid
)
265 TRACE("sid=%p\n",pSid
);
267 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid
));
270 /**************************************************************************
271 * RtlInitializeSid [NTDLL.@]
276 * pSid [I] SID to initialise
277 * pIdentifierAuthority [I] Identifier Authority
278 * nSubAuthorityCount [I] Number of Sub Authorities
281 * Success: TRUE. pSid is initialised with the details given.
282 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
284 BOOL WINAPI
RtlInitializeSid(
286 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority
,
287 BYTE nSubAuthorityCount
)
292 if (nSubAuthorityCount
>= SID_MAX_SUB_AUTHORITIES
)
295 pisid
->Revision
= SID_REVISION
;
296 pisid
->SubAuthorityCount
= nSubAuthorityCount
;
297 if (pIdentifierAuthority
)
298 memcpy(&pisid
->IdentifierAuthority
, pIdentifierAuthority
, sizeof (SID_IDENTIFIER_AUTHORITY
));
300 for (i
= 0; i
< nSubAuthorityCount
; i
++)
301 *RtlSubAuthoritySid(pSid
, i
) = 0;
306 /**************************************************************************
307 * RtlSubAuthoritySid [NTDLL.@]
309 * Return the Sub Authority of a SID
312 * pSid [I] SID to get the Sub Authority from.
313 * nSubAuthority [I] Sub Authority number.
316 * A pointer to The Sub Authority value of pSid.
318 LPDWORD WINAPI
RtlSubAuthoritySid( PSID pSid
, DWORD nSubAuthority
)
320 return &(((SID
*)pSid
)->SubAuthority
[nSubAuthority
]);
323 /**************************************************************************
324 * RtlIdentifierAuthoritySid [NTDLL.@]
326 * Return the Identifier Authority of a SID.
329 * pSid [I] SID to get the Identifier Authority from.
332 * A pointer to the Identifier Authority value of pSid.
334 PSID_IDENTIFIER_AUTHORITY WINAPI
RtlIdentifierAuthoritySid( PSID pSid
)
336 return &(((SID
*)pSid
)->IdentifierAuthority
);
339 /**************************************************************************
340 * RtlSubAuthorityCountSid [NTDLL.@]
342 * Get the number of Sub Authorities in a SID.
345 * pSid [I] SID to get the count from.
348 * A pointer to the Sub Authority count of pSid.
350 LPBYTE WINAPI
RtlSubAuthorityCountSid(PSID pSid
)
352 return &(((SID
*)pSid
)->SubAuthorityCount
);
355 /**************************************************************************
356 * RtlCopySid [NTDLL.@]
358 BOOLEAN WINAPI
RtlCopySid( DWORD nDestinationSidLength
, PSID pDestinationSid
, PSID pSourceSid
)
360 if (!pSourceSid
|| !RtlValidSid(pSourceSid
) ||
361 (nDestinationSidLength
< RtlLengthSid(pSourceSid
)))
364 if (nDestinationSidLength
< (((SID
*)pSourceSid
)->SubAuthorityCount
*4+8))
367 memmove(pDestinationSid
, pSourceSid
, ((SID
*)pSourceSid
)->SubAuthorityCount
*4+8);
370 /******************************************************************************
371 * RtlValidSid [NTDLL.@]
373 * Determine if a SID is valid.
376 * pSid [I] SID to check
379 * TRUE if pSid is valid,
382 BOOLEAN WINAPI
RtlValidSid( PSID pSid
)
388 if (!pSid
|| ((SID
*)pSid
)->Revision
!= SID_REVISION
||
389 ((SID
*)pSid
)->SubAuthorityCount
> SID_MAX_SUB_AUTHORITIES
)
396 WARN("(%p): invalid pointer!\n", pSid
);
405 * security descriptor functions
408 /**************************************************************************
409 * RtlCreateSecurityDescriptor [NTDLL.@]
411 * Initialise a SECURITY_DESCRIPTOR.
414 * lpsd [O] Descriptor to initialise.
415 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
418 * Success: STATUS_SUCCESS.
419 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
421 NTSTATUS WINAPI
RtlCreateSecurityDescriptor(
422 PSECURITY_DESCRIPTOR lpsd
,
425 if (rev
!=SECURITY_DESCRIPTOR_REVISION
)
426 return STATUS_UNKNOWN_REVISION
;
427 memset(lpsd
,'\0',sizeof(SECURITY_DESCRIPTOR
));
428 ((SECURITY_DESCRIPTOR
*)lpsd
)->Revision
= SECURITY_DESCRIPTOR_REVISION
;
429 return STATUS_SUCCESS
;
432 /**************************************************************************
433 * RtlCopySecurityDescriptor [NTDLL.@]
435 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
438 * pSourceSD [O] SD to copy from.
439 * pDestinationSD [I] Destination SD.
442 * Success: STATUS_SUCCESS.
443 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
445 NTSTATUS WINAPI
RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD
, PSECURITY_DESCRIPTOR pDestinationSD
)
447 SECURITY_DESCRIPTOR
*srcSD
= (SECURITY_DESCRIPTOR
*)pSourceSD
;
448 SECURITY_DESCRIPTOR
*destSD
= (SECURITY_DESCRIPTOR
*)pDestinationSD
;
451 BOOLEAN defaulted
, present
;
453 BOOL isSelfRelative
= srcSD
->Control
& SE_SELF_RELATIVE
;
455 if (srcSD
->Revision
!= SECURITY_DESCRIPTOR_REVISION
)
456 return STATUS_UNKNOWN_REVISION
;
458 /* copy initial data */
459 destSD
->Revision
= srcSD
->Revision
;
460 destSD
->Sbz1
= srcSD
->Sbz1
;
461 destSD
->Control
= srcSD
->Control
;
464 RtlGetOwnerSecurityDescriptor(pSourceSD
, &Owner
, &defaulted
);
465 length
= RtlLengthSid(Owner
);
469 destSD
->Owner
= srcSD
->Owner
;
470 RtlCopySid(length
, (LPBYTE
)destSD
+ (DWORD
)destSD
->Owner
, Owner
);
474 destSD
->Owner
= RtlAllocateHeap(GetProcessHeap(), 0, length
);
475 RtlCopySid(length
, destSD
->Owner
, Owner
);
479 RtlGetGroupSecurityDescriptor(pSourceSD
, &Group
, &defaulted
);
480 length
= RtlLengthSid(Group
);
484 destSD
->Group
= srcSD
->Group
;
485 RtlCopySid(length
, (LPBYTE
)destSD
+ (DWORD
)destSD
->Group
, Group
);
489 destSD
->Group
= RtlAllocateHeap(GetProcessHeap(), 0, length
);
490 RtlCopySid(length
, destSD
->Group
, Group
);
494 if (srcSD
->Control
& SE_DACL_PRESENT
)
496 RtlGetDaclSecurityDescriptor(pSourceSD
, &present
, &Dacl
, &defaulted
);
497 length
= Dacl
->AclSize
;
501 destSD
->Dacl
= srcSD
->Dacl
;
502 copy_acl(length
, (PACL
)((LPBYTE
)destSD
+ (DWORD
)destSD
->Dacl
), Dacl
);
506 destSD
->Dacl
= RtlAllocateHeap(GetProcessHeap(), 0, length
);
507 copy_acl(length
, destSD
->Dacl
, Dacl
);
512 if (srcSD
->Control
& SE_SACL_PRESENT
)
514 RtlGetSaclSecurityDescriptor(pSourceSD
, &present
, &Sacl
, &defaulted
);
515 length
= Sacl
->AclSize
;
519 destSD
->Sacl
= srcSD
->Sacl
;
520 copy_acl(length
, (PACL
)((LPBYTE
)destSD
+ (DWORD
)destSD
->Sacl
), Sacl
);
524 destSD
->Sacl
= RtlAllocateHeap(GetProcessHeap(), 0, length
);
525 copy_acl(length
, destSD
->Sacl
, Sacl
);
529 return STATUS_SUCCESS
;
532 /**************************************************************************
533 * RtlValidSecurityDescriptor [NTDLL.@]
535 * Determine if a SECURITY_DESCRIPTOR is valid.
538 * SecurityDescriptor [I] Descriptor to check.
541 * Success: STATUS_SUCCESS.
542 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
544 NTSTATUS WINAPI
RtlValidSecurityDescriptor(
545 PSECURITY_DESCRIPTOR SecurityDescriptor
)
547 if ( ! SecurityDescriptor
)
548 return STATUS_INVALID_SECURITY_DESCR
;
549 if ( ((SECURITY_DESCRIPTOR
*)SecurityDescriptor
)->Revision
!= SECURITY_DESCRIPTOR_REVISION
)
550 return STATUS_UNKNOWN_REVISION
;
552 return STATUS_SUCCESS
;
555 /**************************************************************************
556 * RtlLengthSecurityDescriptor [NTDLL.@]
558 ULONG WINAPI
RtlLengthSecurityDescriptor(
559 PSECURITY_DESCRIPTOR pSecurityDescriptor
)
561 SECURITY_DESCRIPTOR
* lpsd
=pSecurityDescriptor
;
563 ULONG Size
= SECURITY_DESCRIPTOR_MIN_LENGTH
;
568 if ( lpsd
->Control
& SE_SELF_RELATIVE
)
569 offset
= (ULONG
) lpsd
;
571 if ( lpsd
->Owner
!= NULL
)
572 Size
+= RtlLengthSid((PSID
)((LPBYTE
)lpsd
->Owner
+ offset
));
574 if ( lpsd
->Group
!= NULL
)
575 Size
+= RtlLengthSid((PSID
)((LPBYTE
)lpsd
->Group
+ offset
));
577 if ( (lpsd
->Control
& SE_SACL_PRESENT
) &&
579 Size
+= ((PACL
)((LPBYTE
)lpsd
->Sacl
+ offset
))->AclSize
;
581 if ( (lpsd
->Control
& SE_DACL_PRESENT
) &&
583 Size
+= ((PACL
)((LPBYTE
)lpsd
->Dacl
+ offset
))->AclSize
;
588 /******************************************************************************
589 * RtlGetDaclSecurityDescriptor [NTDLL.@]
592 NTSTATUS WINAPI
RtlGetDaclSecurityDescriptor(
593 IN PSECURITY_DESCRIPTOR pSecurityDescriptor
,
594 OUT PBOOLEAN lpbDaclPresent
,
596 OUT PBOOLEAN lpbDaclDefaulted
)
598 SECURITY_DESCRIPTOR
* lpsd
=pSecurityDescriptor
;
600 TRACE("(%p,%p,%p,%p)\n",
601 pSecurityDescriptor
, lpbDaclPresent
, pDacl
, lpbDaclDefaulted
);
603 if (lpsd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
)
604 return STATUS_UNKNOWN_REVISION
;
606 if ( (*lpbDaclPresent
= (SE_DACL_PRESENT
& lpsd
->Control
) ? 1 : 0) )
608 if ( SE_SELF_RELATIVE
& lpsd
->Control
)
609 *pDacl
= (PACL
) ((LPBYTE
)lpsd
+ (DWORD
)lpsd
->Dacl
);
613 *lpbDaclDefaulted
= (( SE_DACL_DEFAULTED
& lpsd
->Control
) ? 1 : 0);
616 return STATUS_SUCCESS
;
619 /**************************************************************************
620 * RtlSetDaclSecurityDescriptor [NTDLL.@]
622 NTSTATUS WINAPI
RtlSetDaclSecurityDescriptor (
623 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
626 BOOLEAN dacldefaulted
)
628 SECURITY_DESCRIPTOR
* lpsd
=pSecurityDescriptor
;
630 if (lpsd
->Revision
!=SECURITY_DESCRIPTOR_REVISION
)
631 return STATUS_UNKNOWN_REVISION
;
632 if (lpsd
->Control
& SE_SELF_RELATIVE
)
633 return STATUS_INVALID_SECURITY_DESCR
;
636 { lpsd
->Control
&= ~SE_DACL_PRESENT
;
640 lpsd
->Control
|= SE_DACL_PRESENT
;
644 lpsd
->Control
|= SE_DACL_DEFAULTED
;
646 lpsd
->Control
&= ~SE_DACL_DEFAULTED
;
648 return STATUS_SUCCESS
;
651 /******************************************************************************
652 * RtlGetSaclSecurityDescriptor [NTDLL.@]
655 NTSTATUS WINAPI
RtlGetSaclSecurityDescriptor(
656 IN PSECURITY_DESCRIPTOR pSecurityDescriptor
,
657 OUT PBOOLEAN lpbSaclPresent
,
659 OUT PBOOLEAN lpbSaclDefaulted
)
661 SECURITY_DESCRIPTOR
* lpsd
=pSecurityDescriptor
;
663 TRACE("(%p,%p,%p,%p)\n",
664 pSecurityDescriptor
, lpbSaclPresent
, *pSacl
, lpbSaclDefaulted
);
666 if (lpsd
->Revision
!= SECURITY_DESCRIPTOR_REVISION
)
667 return STATUS_UNKNOWN_REVISION
;
669 if ( (*lpbSaclPresent
= (SE_SACL_PRESENT
& lpsd
->Control
) ? 1 : 0) )
671 if (SE_SELF_RELATIVE
& lpsd
->Control
)
672 *pSacl
= (PACL
) ((LPBYTE
)lpsd
+ (DWORD
)lpsd
->Sacl
);
676 *lpbSaclDefaulted
= (( SE_SACL_DEFAULTED
& lpsd
->Control
) ? 1 : 0);
679 return STATUS_SUCCESS
;
682 /**************************************************************************
683 * RtlSetSaclSecurityDescriptor [NTDLL.@]
685 NTSTATUS WINAPI
RtlSetSaclSecurityDescriptor (
686 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
689 BOOLEAN sacldefaulted
)
691 SECURITY_DESCRIPTOR
* lpsd
=pSecurityDescriptor
;
693 if (lpsd
->Revision
!=SECURITY_DESCRIPTOR_REVISION
)
694 return STATUS_UNKNOWN_REVISION
;
695 if (lpsd
->Control
& SE_SELF_RELATIVE
)
696 return STATUS_INVALID_SECURITY_DESCR
;
698 lpsd
->Control
&= ~SE_SACL_PRESENT
;
701 lpsd
->Control
|= SE_SACL_PRESENT
;
704 lpsd
->Control
|= SE_SACL_DEFAULTED
;
706 lpsd
->Control
&= ~SE_SACL_DEFAULTED
;
707 return STATUS_SUCCESS
;
710 /**************************************************************************
711 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
713 NTSTATUS WINAPI
RtlGetOwnerSecurityDescriptor(
714 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
716 PBOOLEAN OwnerDefaulted
)
718 SECURITY_DESCRIPTOR
* lpsd
=pSecurityDescriptor
;
720 if ( !lpsd
|| !Owner
|| !OwnerDefaulted
)
721 return STATUS_INVALID_PARAMETER
;
723 if (lpsd
->Owner
!= NULL
)
725 if (lpsd
->Control
& SE_SELF_RELATIVE
)
726 *Owner
= (PSID
)((LPBYTE
)lpsd
+
729 *Owner
= lpsd
->Owner
;
731 if ( lpsd
->Control
& SE_OWNER_DEFAULTED
)
732 *OwnerDefaulted
= TRUE
;
734 *OwnerDefaulted
= FALSE
;
739 return STATUS_SUCCESS
;
742 /**************************************************************************
743 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
745 NTSTATUS WINAPI
RtlSetOwnerSecurityDescriptor(
746 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
748 BOOLEAN ownerdefaulted
)
750 SECURITY_DESCRIPTOR
* lpsd
=pSecurityDescriptor
;
752 if (lpsd
->Revision
!=SECURITY_DESCRIPTOR_REVISION
)
753 return STATUS_UNKNOWN_REVISION
;
754 if (lpsd
->Control
& SE_SELF_RELATIVE
)
755 return STATUS_INVALID_SECURITY_DESCR
;
759 lpsd
->Control
|= SE_OWNER_DEFAULTED
;
761 lpsd
->Control
&= ~SE_OWNER_DEFAULTED
;
762 return STATUS_SUCCESS
;
765 /**************************************************************************
766 * RtlSetGroupSecurityDescriptor [NTDLL.@]
768 NTSTATUS WINAPI
RtlSetGroupSecurityDescriptor (
769 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
771 BOOLEAN groupdefaulted
)
773 SECURITY_DESCRIPTOR
* lpsd
=pSecurityDescriptor
;
775 if (lpsd
->Revision
!=SECURITY_DESCRIPTOR_REVISION
)
776 return STATUS_UNKNOWN_REVISION
;
777 if (lpsd
->Control
& SE_SELF_RELATIVE
)
778 return STATUS_INVALID_SECURITY_DESCR
;
782 lpsd
->Control
|= SE_GROUP_DEFAULTED
;
784 lpsd
->Control
&= ~SE_GROUP_DEFAULTED
;
785 return STATUS_SUCCESS
;
788 /**************************************************************************
789 * RtlGetGroupSecurityDescriptor [NTDLL.@]
791 NTSTATUS WINAPI
RtlGetGroupSecurityDescriptor(
792 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
794 PBOOLEAN GroupDefaulted
)
796 SECURITY_DESCRIPTOR
* lpsd
=pSecurityDescriptor
;
798 if ( !lpsd
|| !Group
|| !GroupDefaulted
)
799 return STATUS_INVALID_PARAMETER
;
801 if (lpsd
->Group
!= NULL
)
803 if (lpsd
->Control
& SE_SELF_RELATIVE
)
804 *Group
= (PSID
)((LPBYTE
)lpsd
+
807 *Group
= lpsd
->Group
;
809 if ( lpsd
->Control
& SE_GROUP_DEFAULTED
)
810 *GroupDefaulted
= TRUE
;
812 *GroupDefaulted
= FALSE
;
817 return STATUS_SUCCESS
;
820 /**************************************************************************
821 * RtlMakeSelfRelativeSD [NTDLL.@]
823 NTSTATUS WINAPI
RtlMakeSelfRelativeSD(
824 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor
,
825 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor
,
826 IN OUT LPDWORD lpdwBufferLength
)
830 SECURITY_DESCRIPTOR
* pAbs
= pAbsoluteSecurityDescriptor
;
831 SECURITY_DESCRIPTOR
* pRel
= pSelfRelativeSecurityDescriptor
;
833 TRACE(" %p %p %p(%ld)\n", pAbs
, pRel
, lpdwBufferLength
,
834 lpdwBufferLength
? *lpdwBufferLength
: -1);
836 if (!lpdwBufferLength
|| !pAbs
)
837 return STATUS_INVALID_PARAMETER
;
839 length
= RtlLengthSecurityDescriptor(pAbs
);
840 if (*lpdwBufferLength
< length
)
842 *lpdwBufferLength
= length
;
843 return STATUS_BUFFER_TOO_SMALL
;
847 return STATUS_INVALID_PARAMETER
;
849 if (pAbs
->Control
& SE_SELF_RELATIVE
)
851 memcpy(pRel
, pAbs
, length
);
852 return STATUS_SUCCESS
;
855 pRel
->Revision
= pAbs
->Revision
;
856 pRel
->Sbz1
= pAbs
->Sbz1
;
857 pRel
->Control
= pAbs
->Control
| SE_SELF_RELATIVE
;
859 offsetRel
= sizeof(SECURITY_DESCRIPTOR
);
860 pRel
->Owner
= (PSID
) offsetRel
;
861 length
= RtlLengthSid(pAbs
->Owner
);
862 memcpy((LPBYTE
)pRel
+ offsetRel
, pAbs
->Owner
, length
);
865 pRel
->Group
= (PSID
) offsetRel
;
866 length
= RtlLengthSid(pAbs
->Group
);
867 memcpy((LPBYTE
)pRel
+ offsetRel
, pAbs
->Group
, length
);
869 if (pRel
->Control
& SE_SACL_PRESENT
)
872 pRel
->Sacl
= (PACL
) offsetRel
;
873 length
= pAbs
->Sacl
->AclSize
;
874 memcpy((LPBYTE
)pRel
+ offsetRel
, pAbs
->Sacl
, length
);
881 if (pRel
->Control
& SE_DACL_PRESENT
)
884 pRel
->Dacl
= (PACL
) offsetRel
;
885 length
= pAbs
->Dacl
->AclSize
;
886 memcpy((LPBYTE
)pRel
+ offsetRel
, pAbs
->Dacl
, length
);
893 return STATUS_SUCCESS
;
897 /**************************************************************************
898 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
900 NTSTATUS WINAPI
RtlSelfRelativeToAbsoluteSD(
901 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor
,
902 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor
,
903 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize
,
905 OUT LPDWORD lpdwDaclSize
,
907 OUT LPDWORD lpdwSaclSize
,
909 OUT LPDWORD lpdwOwnerSize
,
910 OUT PSID pPrimaryGroup
,
911 OUT LPDWORD lpdwPrimaryGroupSize
)
913 NTSTATUS status
= STATUS_SUCCESS
;
914 SECURITY_DESCRIPTOR
* pAbs
= pAbsoluteSecurityDescriptor
;
915 SECURITY_DESCRIPTOR
* pRel
= pSelfRelativeSecurityDescriptor
;
918 !lpdwAbsoluteSecurityDescriptorSize
||
922 !lpdwPrimaryGroupSize
||
923 ~pRel
->Control
& SE_SELF_RELATIVE
)
924 return STATUS_INVALID_PARAMETER
;
926 /* Confirm buffers are sufficiently large */
927 if (*lpdwAbsoluteSecurityDescriptorSize
< sizeof(SECURITY_DESCRIPTOR
))
929 *lpdwAbsoluteSecurityDescriptorSize
= sizeof(SECURITY_DESCRIPTOR
);
930 status
= STATUS_BUFFER_TOO_SMALL
;
933 if (pRel
->Control
& SE_DACL_PRESENT
&&
934 *lpdwDaclSize
< ((PACL
)((LPBYTE
)pRel
->Dacl
+ (ULONG
)pRel
))->AclSize
)
936 *lpdwDaclSize
= ((PACL
)((LPBYTE
)pRel
->Dacl
+ (ULONG
)pRel
))->AclSize
;
937 status
= STATUS_BUFFER_TOO_SMALL
;
940 if (pRel
->Control
& SE_SACL_PRESENT
&&
941 *lpdwSaclSize
< ((PACL
)((LPBYTE
)pRel
->Sacl
+ (ULONG
)pRel
))->AclSize
)
943 *lpdwSaclSize
= ((PACL
)((LPBYTE
)pRel
->Sacl
+ (ULONG
)pRel
))->AclSize
;
944 status
= STATUS_BUFFER_TOO_SMALL
;
948 *lpdwOwnerSize
< RtlLengthSid((PSID
)((LPBYTE
)pRel
->Owner
+ (ULONG
)pRel
)))
950 *lpdwOwnerSize
= RtlLengthSid((PSID
)((LPBYTE
)pRel
->Owner
+ (ULONG
)pRel
));
951 status
= STATUS_BUFFER_TOO_SMALL
;
955 *lpdwPrimaryGroupSize
< RtlLengthSid((PSID
)((LPBYTE
)pRel
->Group
+ (ULONG
)pRel
)))
957 *lpdwPrimaryGroupSize
= RtlLengthSid((PSID
)((LPBYTE
)pRel
->Group
+ (ULONG
)pRel
));
958 status
= STATUS_BUFFER_TOO_SMALL
;
961 if (status
!= STATUS_SUCCESS
)
964 /* Copy structures */
965 pAbs
->Revision
= pRel
->Revision
;
966 pAbs
->Control
= pRel
->Control
& ~SE_SELF_RELATIVE
;
968 if (pRel
->Control
& SE_SACL_PRESENT
)
970 PACL pAcl
= (PACL
)((LPBYTE
)pRel
->Sacl
+ (ULONG
)pRel
);
972 memcpy(pSacl
, pAcl
, pAcl
->AclSize
);
976 if (pRel
->Control
& SE_DACL_PRESENT
)
978 PACL pAcl
= (PACL
)((LPBYTE
)pRel
->Dacl
+ (ULONG
)pRel
);
979 memcpy(pDacl
, pAcl
, pAcl
->AclSize
);
985 PSID psid
= (PSID
)((LPBYTE
)pRel
->Owner
+ (ULONG
)pRel
);
986 memcpy(pOwner
, psid
, RtlLengthSid(psid
));
987 pAbs
->Owner
= pOwner
;
992 PSID psid
= (PSID
)((LPBYTE
)pRel
->Group
+ (ULONG
)pRel
);
993 memcpy(pPrimaryGroup
, psid
, RtlLengthSid(psid
));
994 pAbs
->Group
= pPrimaryGroup
;
1000 /******************************************************************************
1001 * RtlGetControlSecurityDescriptor (NTDLL.@)
1003 NTSTATUS WINAPI
RtlGetControlSecurityDescriptor(
1004 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1005 PSECURITY_DESCRIPTOR_CONTROL pControl
,
1006 LPDWORD lpdwRevision
)
1008 SECURITY_DESCRIPTOR
*lpsd
= pSecurityDescriptor
;
1010 TRACE("(%p,%p,%p)\n",pSecurityDescriptor
,pControl
,lpdwRevision
);
1012 *lpdwRevision
= lpsd
->Revision
;
1014 if (*lpdwRevision
!= SECURITY_DESCRIPTOR_REVISION
)
1015 return STATUS_UNKNOWN_REVISION
;
1017 *pControl
= lpsd
->Control
;
1019 return STATUS_SUCCESS
;
1023 /**************************************************************************
1024 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1026 NTSTATUS WINAPI
RtlAbsoluteToSelfRelativeSD(
1027 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor
,
1028 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor
,
1029 PULONG BufferLength
)
1031 SECURITY_DESCRIPTOR
*abs
= AbsoluteSecurityDescriptor
;
1033 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor
,
1034 SelfRelativeSecurityDescriptor
, BufferLength
);
1036 if (abs
->Control
& SE_SELF_RELATIVE
)
1037 return STATUS_BAD_DESCRIPTOR_FORMAT
;
1039 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor
,
1040 SelfRelativeSecurityDescriptor
, BufferLength
);
1045 * access control list's
1048 /**************************************************************************
1049 * RtlCreateAcl [NTDLL.@]
1052 * This should return NTSTATUS
1054 NTSTATUS WINAPI
RtlCreateAcl(PACL acl
,DWORD size
,DWORD rev
)
1056 TRACE("%p 0x%08lx 0x%08lx\n", acl
, size
, rev
);
1058 if (rev
!=ACL_REVISION
)
1059 return STATUS_INVALID_PARAMETER
;
1060 if (size
<sizeof(ACL
))
1061 return STATUS_BUFFER_TOO_SMALL
;
1063 return STATUS_INVALID_PARAMETER
;
1065 memset(acl
,'\0',sizeof(ACL
));
1066 acl
->AclRevision
= rev
;
1067 acl
->AclSize
= size
;
1069 return STATUS_SUCCESS
;
1072 /**************************************************************************
1073 * RtlFirstFreeAce [NTDLL.@]
1074 * looks for the AceCount+1 ACE, and if it is still within the alloced
1075 * ACL, return a pointer to it
1077 BOOLEAN WINAPI
RtlFirstFreeAce(
1085 ace
= (PACE_HEADER
)(acl
+1);
1086 for (i
=0;i
<acl
->AceCount
;i
++) {
1087 if ((BYTE
*)ace
>= (BYTE
*)acl
+ acl
->AclSize
)
1089 ace
= (PACE_HEADER
)(((BYTE
*)ace
)+ace
->AceSize
);
1091 if ((BYTE
*)ace
>= (BYTE
*)acl
+ acl
->AclSize
)
1097 /**************************************************************************
1098 * RtlAddAce [NTDLL.@]
1100 NTSTATUS WINAPI
RtlAddAce(
1104 PACE_HEADER acestart
,
1107 PACE_HEADER ace
,targetace
;
1110 if (acl
->AclRevision
!= ACL_REVISION
)
1111 return STATUS_INVALID_PARAMETER
;
1112 if (!RtlFirstFreeAce(acl
,&targetace
))
1113 return STATUS_INVALID_PARAMETER
;
1114 nrofaces
=0;ace
=acestart
;
1115 while (((BYTE
*)ace
- (BYTE
*)acestart
) < acelen
) {
1117 ace
= (PACE_HEADER
)(((BYTE
*)ace
)+ace
->AceSize
);
1119 if ((BYTE
*)targetace
+ acelen
> (BYTE
*)acl
+ acl
->AclSize
) /* too much aces */
1120 return STATUS_INVALID_PARAMETER
;
1121 memcpy((LPBYTE
)targetace
,acestart
,acelen
);
1122 acl
->AceCount
+=nrofaces
;
1123 return STATUS_SUCCESS
;
1126 /**************************************************************************
1127 * RtlDeleteAce [NTDLL.@]
1129 NTSTATUS WINAPI
RtlDeleteAce(PACL pAcl
, DWORD dwAceIndex
)
1134 status
= RtlGetAce(pAcl
,dwAceIndex
,(LPVOID
*)&pAce
);
1136 if (STATUS_SUCCESS
== status
)
1141 pcAce
= (PACE_HEADER
)(((BYTE
*)pAce
)+pAce
->AceSize
);
1142 for (; dwAceIndex
< pAcl
->AceCount
; dwAceIndex
++)
1144 len
+= pcAce
->AceSize
;
1145 pcAce
= (PACE_HEADER
)(((BYTE
*)pcAce
) + pcAce
->AceSize
);
1148 memcpy(pAce
, ((BYTE
*)pAce
)+pAce
->AceSize
, len
);
1152 TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\n", pAcl
, dwAceIndex
, status
);
1157 /******************************************************************************
1158 * RtlAddAccessAllowedAce [NTDLL.@]
1160 NTSTATUS WINAPI
RtlAddAccessAllowedAce(
1162 IN DWORD dwAceRevision
,
1163 IN DWORD AccessMask
,
1166 return RtlAddAccessAllowedAceEx( pAcl
, dwAceRevision
, 0, AccessMask
, pSid
);
1169 /******************************************************************************
1170 * RtlAddAccessAllowedAceEx [NTDLL.@]
1172 NTSTATUS WINAPI
RtlAddAccessAllowedAceEx(
1174 IN DWORD dwAceRevision
,
1176 IN DWORD AccessMask
,
1179 TRACE("(%p,0x%08lx,0x%08lx,%p)\n", pAcl
, dwAceRevision
, AccessMask
, pSid
);
1181 return add_access_ace(pAcl
, dwAceRevision
, AceFlags
,
1182 AccessMask
, pSid
, ACCESS_ALLOWED_ACE_TYPE
);
1185 /******************************************************************************
1186 * RtlAddAccessDeniedAce [NTDLL.@]
1188 NTSTATUS WINAPI
RtlAddAccessDeniedAce(
1190 IN DWORD dwAceRevision
,
1191 IN DWORD AccessMask
,
1194 return RtlAddAccessDeniedAceEx( pAcl
, dwAceRevision
, 0, AccessMask
, pSid
);
1197 /******************************************************************************
1198 * RtlAddAccessDeniedAceEx [NTDLL.@]
1200 NTSTATUS WINAPI
RtlAddAccessDeniedAceEx(
1202 IN DWORD dwAceRevision
,
1204 IN DWORD AccessMask
,
1207 TRACE("(%p,0x%08lx,0x%08lx,%p)\n", pAcl
, dwAceRevision
, AccessMask
, pSid
);
1209 return add_access_ace(pAcl
, dwAceRevision
, AceFlags
,
1210 AccessMask
, pSid
, ACCESS_DENIED_ACE_TYPE
);
1213 /**************************************************************************
1214 * RtlAddAuditAccessAce [NTDLL.@]
1216 NTSTATUS WINAPI
RtlAddAuditAccessAce(
1218 IN DWORD dwAceRevision
,
1219 IN DWORD dwAccessMask
,
1221 IN BOOL bAuditSuccess
,
1222 IN BOOL bAuditFailure
)
1224 DWORD dwAceFlags
= 0;
1226 TRACE("(%p,%ld,%ld,%p,%u,%u)\n",pAcl
,dwAceRevision
,dwAccessMask
,
1227 pSid
,bAuditSuccess
,bAuditFailure
);
1230 dwAceFlags
|= SUCCESSFUL_ACCESS_ACE_FLAG
;
1233 dwAceFlags
|= FAILED_ACCESS_ACE_FLAG
;
1235 return add_access_ace(pAcl
, dwAceRevision
, dwAceFlags
,
1236 dwAccessMask
, pSid
, SYSTEM_AUDIT_ACE_TYPE
);
1239 /******************************************************************************
1240 * RtlValidAcl [NTDLL.@]
1242 BOOLEAN WINAPI
RtlValidAcl(PACL pAcl
)
1245 TRACE("(%p)\n", pAcl
);
1252 if (pAcl
->AclRevision
!= ACL_REVISION
)
1256 ace
= (PACE_HEADER
)(pAcl
+1);
1258 for (i
=0;i
<=pAcl
->AceCount
;i
++)
1260 if ((char *)ace
> (char *)pAcl
+ pAcl
->AclSize
)
1265 ace
= (PACE_HEADER
)(((BYTE
*)ace
)+ace
->AceSize
);
1269 __EXCEPT(page_fault
)
1271 WARN("(%p): invalid pointer!\n", pAcl
);
1278 /******************************************************************************
1279 * RtlGetAce [NTDLL.@]
1281 NTSTATUS WINAPI
RtlGetAce(PACL pAcl
,DWORD dwAceIndex
,LPVOID
*pAce
)
1285 TRACE("(%p,%ld,%p)\n",pAcl
,dwAceIndex
,pAce
);
1287 if ((dwAceIndex
< 0) || (dwAceIndex
> pAcl
->AceCount
))
1288 return STATUS_INVALID_PARAMETER
;
1290 ace
= (PACE_HEADER
)(pAcl
+ 1);
1291 for (;dwAceIndex
;dwAceIndex
--)
1292 ace
= (PACE_HEADER
)(((BYTE
*)ace
)+ace
->AceSize
);
1294 *pAce
= (LPVOID
) ace
;
1296 return STATUS_SUCCESS
;
1303 /******************************************************************************
1304 * RtlAdjustPrivilege [NTDLL.@]
1306 * Enables or disables a privilege from the calling thread or process.
1309 * Privilege [I] Privilege index to change.
1310 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1311 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1312 * Enabled [O] Whether privilege was previously enabled or disabled.
1315 * Success: STATUS_SUCCESS.
1316 * Failure: NTSTATUS code.
1319 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1323 RtlAdjustPrivilege(ULONG Privilege
,
1325 BOOLEAN CurrentThread
,
1328 TOKEN_PRIVILEGES NewState
;
1329 TOKEN_PRIVILEGES OldState
;
1334 TRACE("(%ld, %s, %s, %p)\n", Privilege
, Enable
? "TRUE" : "FALSE",
1335 CurrentThread
? "TRUE" : "FALSE", Enabled
);
1339 Status
= NtOpenThreadToken(GetCurrentThread(),
1340 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
1346 Status
= NtOpenProcessToken(GetCurrentProcess(),
1347 TOKEN_ADJUST_PRIVILEGES
| TOKEN_QUERY
,
1351 if (!NT_SUCCESS(Status
))
1353 WARN("Retrieving token handle failed (Status %lx)\n", Status
);
1357 OldState
.PrivilegeCount
= 1;
1359 NewState
.PrivilegeCount
= 1;
1360 NewState
.Privileges
[0].Luid
.LowPart
= Privilege
;
1361 NewState
.Privileges
[0].Luid
.HighPart
= 0;
1362 NewState
.Privileges
[0].Attributes
= (Enable
) ? SE_PRIVILEGE_ENABLED
: 0;
1364 Status
= NtAdjustPrivilegesToken(TokenHandle
,
1367 sizeof(TOKEN_PRIVILEGES
),
1370 NtClose (TokenHandle
);
1371 if (Status
== STATUS_NOT_ALL_ASSIGNED
)
1373 TRACE("Failed to assign all privileges\n");
1374 return STATUS_PRIVILEGE_NOT_HELD
;
1376 if (!NT_SUCCESS(Status
))
1378 WARN("NtAdjustPrivilegesToken() failed (Status %lx)\n", Status
);
1382 if (OldState
.PrivilegeCount
== 0)
1385 *Enabled
= (OldState
.Privileges
[0].Attributes
& SE_PRIVILEGE_ENABLED
);
1387 return STATUS_SUCCESS
;
1390 /******************************************************************************
1391 * RtlImpersonateSelf [NTDLL.@]
1393 * Makes an impersonation token that represents the process user and assigns
1394 * to the current thread.
1397 * ImpersonationLevel [I] Level at which to impersonate.
1400 * Success: STATUS_SUCCESS.
1401 * Failure: NTSTATUS code.
1404 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
1407 OBJECT_ATTRIBUTES ObjectAttributes
;
1408 HANDLE ProcessToken
;
1409 HANDLE ImpersonationToken
;
1411 TRACE("(%08x)\n", ImpersonationLevel
);
1413 Status
= NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE
,
1415 if (Status
!= STATUS_SUCCESS
)
1418 InitializeObjectAttributes( &ObjectAttributes
, NULL
, 0, NULL
, NULL
);
1420 Status
= NtDuplicateToken( ProcessToken
,
1425 &ImpersonationToken
);
1426 if (Status
!= STATUS_SUCCESS
)
1428 NtClose( ProcessToken
);
1432 Status
= NtSetInformationThread( GetCurrentThread(),
1433 ThreadImpersonationToken
,
1434 &ImpersonationToken
,
1435 sizeof(ImpersonationToken
) );
1437 NtClose( ImpersonationToken
);
1438 NtClose( ProcessToken
);
1443 /******************************************************************************
1444 * NtAccessCheck [NTDLL.@]
1445 * ZwAccessCheck [NTDLL.@]
1447 * Checks that a user represented by a token is allowed to access an object
1448 * represented by a security descriptor.
1451 * SecurityDescriptor [I] The security descriptor of the object to check.
1452 * ClientToken [I] Token of the user accessing the object.
1453 * DesiredAccess [I] The desired access to the object.
1454 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1455 * PrivilegeSet [I/O] Privileges used during the access check.
1456 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1457 * GrantedAccess [O] The actual access rights granted.
1458 * AccessStatus [O] The status of the access check.
1464 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1465 * the maximum access rights allowed by the SD and returns them in
1467 * The SecurityDescriptor must have a valid owner and groups present,
1468 * otherwise the function will fail.
1472 PSECURITY_DESCRIPTOR SecurityDescriptor
,
1474 ACCESS_MASK DesiredAccess
,
1475 PGENERIC_MAPPING GenericMapping
,
1476 PPRIVILEGE_SET PrivilegeSet
,
1477 PULONG ReturnLength
,
1478 PULONG GrantedAccess
,
1479 NTSTATUS
*AccessStatus
)
1483 TRACE("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1484 SecurityDescriptor
, ClientToken
, DesiredAccess
, GenericMapping
,
1485 PrivilegeSet
, ReturnLength
, GrantedAccess
, AccessStatus
);
1487 SERVER_START_REQ( access_check
)
1489 struct security_descriptor sd
;
1494 BOOLEAN defaulted
, present
;
1496 SECURITY_DESCRIPTOR_CONTROL control
;
1498 req
->handle
= ClientToken
;
1499 req
->desired_access
= DesiredAccess
;
1500 req
->mapping_read
= GenericMapping
->GenericRead
;
1501 req
->mapping_write
= GenericMapping
->GenericWrite
;
1502 req
->mapping_execute
= GenericMapping
->GenericExecute
;
1503 req
->mapping_all
= GenericMapping
->GenericAll
;
1505 /* marshal security descriptor */
1506 RtlGetControlSecurityDescriptor( SecurityDescriptor
, &control
, &revision
);
1507 sd
.control
= control
& ~SE_SELF_RELATIVE
;
1508 RtlGetOwnerSecurityDescriptor( SecurityDescriptor
, &owner
, &defaulted
);
1509 sd
.owner_len
= RtlLengthSid( owner
);
1510 RtlGetGroupSecurityDescriptor( SecurityDescriptor
, &group
, &defaulted
);
1511 sd
.group_len
= RtlLengthSid( group
);
1512 RtlGetSaclSecurityDescriptor( SecurityDescriptor
, &present
, &sacl
, &defaulted
);
1513 sd
.sacl_len
= (present
? sacl
->AclSize
: 0);
1514 RtlGetDaclSecurityDescriptor( SecurityDescriptor
, &present
, &dacl
, &defaulted
);
1515 sd
.dacl_len
= (present
? dacl
->AclSize
: 0);
1517 wine_server_add_data( req
, &sd
, sizeof(sd
) );
1518 wine_server_add_data( req
, owner
, sd
.owner_len
);
1519 wine_server_add_data( req
, group
, sd
.group_len
);
1520 wine_server_add_data( req
, sacl
, sd
.sacl_len
);
1521 wine_server_add_data( req
, dacl
, sd
.dacl_len
);
1523 wine_server_set_reply( req
, &PrivilegeSet
->Privilege
, *ReturnLength
- FIELD_OFFSET( PRIVILEGE_SET
, Privilege
) );
1525 status
= wine_server_call( req
);
1527 *ReturnLength
= FIELD_OFFSET( PRIVILEGE_SET
, Privilege
) + reply
->privileges_len
;
1528 PrivilegeSet
->PrivilegeCount
= reply
->privileges_len
/ sizeof(LUID_AND_ATTRIBUTES
);
1530 if (status
== STATUS_SUCCESS
)
1531 *AccessStatus
= reply
->access_status
;
1532 *GrantedAccess
= reply
->access_granted
;
1539 /******************************************************************************
1540 * NtSetSecurityObject [NTDLL.@]
1543 NtSetSecurityObject(
1545 IN SECURITY_INFORMATION SecurityInformation
,
1546 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
1548 FIXME("%p 0x%08lx %p\n", Handle
, SecurityInformation
, SecurityDescriptor
);
1549 return STATUS_SUCCESS
;
1552 /******************************************************************************
1553 * RtlConvertSidToUnicodeString (NTDLL.@)
1555 * The returned SID is used to access the USER registry hive usually
1557 * the native function returns something like
1558 * "S-1-5-21-0000000000-000000000-0000000000-500";
1560 NTSTATUS WINAPI
RtlConvertSidToUnicodeString(
1561 PUNICODE_STRING String
,
1563 BOOLEAN AllocateString
)
1565 static const WCHAR formatW
[] = {'-','%','u',0};
1566 WCHAR buffer
[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES
];
1568 const SID
*sid
= (const SID
*)pSid
;
1572 p
+= sprintfW( p
, formatW
, sid
->Revision
);
1573 p
+= sprintfW( p
, formatW
, MAKELONG( MAKEWORD( sid
->IdentifierAuthority
.Value
[5],
1574 sid
->IdentifierAuthority
.Value
[4] ),
1575 MAKEWORD( sid
->IdentifierAuthority
.Value
[3],
1576 sid
->IdentifierAuthority
.Value
[2] )));
1577 for (i
= 0; i
< sid
->SubAuthorityCount
; i
++)
1578 p
+= sprintfW( p
, formatW
, sid
->SubAuthority
[i
] );
1580 len
= (p
+ 1 - buffer
) * sizeof(WCHAR
);
1582 String
->Length
= len
- sizeof(WCHAR
);
1585 String
->MaximumLength
= len
;
1586 if (!(String
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
)))
1587 return STATUS_NO_MEMORY
;
1589 else if (len
> String
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
1591 memcpy( String
->Buffer
, buffer
, len
);
1592 return STATUS_SUCCESS
;
1595 /******************************************************************************
1596 * RtlQueryInformationAcl (NTDLL.@)
1598 NTSTATUS WINAPI
RtlQueryInformationAcl(
1600 LPVOID pAclInformation
,
1601 DWORD nAclInformationLength
,
1602 ACL_INFORMATION_CLASS dwAclInformationClass
)
1604 NTSTATUS status
= STATUS_SUCCESS
;
1606 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1607 pAcl
, pAclInformation
, nAclInformationLength
, dwAclInformationClass
);
1609 switch (dwAclInformationClass
)
1611 case AclRevisionInformation
:
1613 PACL_REVISION_INFORMATION paclrev
= (PACL_REVISION_INFORMATION
) pAclInformation
;
1615 if (nAclInformationLength
< sizeof(ACL_REVISION_INFORMATION
))
1616 status
= STATUS_INVALID_PARAMETER
;
1618 paclrev
->AclRevision
= pAcl
->AclRevision
;
1623 case AclSizeInformation
:
1625 PACL_SIZE_INFORMATION paclsize
= (PACL_SIZE_INFORMATION
) pAclInformation
;
1627 if (nAclInformationLength
< sizeof(ACL_SIZE_INFORMATION
))
1628 status
= STATUS_INVALID_PARAMETER
;
1634 paclsize
->AceCount
= pAcl
->AceCount
;
1636 paclsize
->AclBytesInUse
= 0;
1637 ace
= (PACE_HEADER
) (pAcl
+ 1);
1639 for (i
= 0; i
< pAcl
->AceCount
; i
++)
1641 paclsize
->AclBytesInUse
+= ace
->AceSize
;
1642 ace
= (PACE_HEADER
)(((BYTE
*)ace
)+ace
->AceSize
);
1645 if (pAcl
->AclSize
< paclsize
->AclBytesInUse
)
1647 WARN("Acl has %ld bytes free\n", paclsize
->AclBytesFree
);
1648 paclsize
->AclBytesFree
= 0;
1649 paclsize
->AclBytesInUse
= pAcl
->AclSize
;
1652 paclsize
->AclBytesFree
= pAcl
->AclSize
- paclsize
->AclBytesInUse
;
1659 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass
);
1660 status
= STATUS_INVALID_PARAMETER
;