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 #define WIN32_NO_STATUS
38 #include "wine/exception.h"
39 #include "ntdll_misc.h"
41 #include "wine/library.h"
42 #include "wine/unicode.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
47 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
49 /* filter for page-fault exceptions */
50 static WINE_EXCEPTION_FILTER(page_fault)
52 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
53 return EXCEPTION_EXECUTE_HANDLER;
54 return EXCEPTION_CONTINUE_SEARCH;
57 /* helper function to copy an ACL */
58 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
62 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
65 size = ((ACL *)pSourceAcl)->AclSize;
66 if (nDestinationAclLength < size)
69 memmove(pDestinationAcl, pSourceAcl, size);
73 /* generically adds an ACE to an ACL */
74 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
75 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
77 ACE_HEADER *pAceHeader;
83 if (!RtlValidSid(pSid))
84 return STATUS_INVALID_SID;
86 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
87 return STATUS_REVISION_MISMATCH;
89 if (!RtlValidAcl(pAcl))
90 return STATUS_INVALID_ACL;
92 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
93 return STATUS_INVALID_ACL;
96 return STATUS_ALLOTTED_SPACE_EXCEEDED;
98 /* calculate generic size of the ACE */
99 dwLengthSid = RtlLengthSid(pSid);
100 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
101 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
102 return STATUS_ALLOTTED_SPACE_EXCEEDED;
104 /* fill the new ACE */
105 pAceHeader->AceType = dwAceType;
106 pAceHeader->AceFlags = dwAceFlags;
107 pAceHeader->AceSize = dwAceSize;
109 /* skip past the ACE_HEADER of the ACE */
110 pAccessMask = (DWORD *)(pAceHeader + 1);
111 *pAccessMask = dwAccessMask;
113 /* skip past ACE->Mask */
114 pSidStart = pAccessMask + 1;
115 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
117 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
120 return STATUS_SUCCESS;
127 /******************************************************************************
128 * RtlAllocateAndInitializeSid [NTDLL.@]
131 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
132 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
133 BYTE nSubAuthorityCount,
134 DWORD nSubAuthority0, DWORD nSubAuthority1,
135 DWORD nSubAuthority2, DWORD nSubAuthority3,
136 DWORD nSubAuthority4, DWORD nSubAuthority5,
137 DWORD nSubAuthority6, DWORD nSubAuthority7,
142 TRACE("(%p, 0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p)\n",
143 pIdentifierAuthority,nSubAuthorityCount,
144 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
145 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
147 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
149 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
150 RtlLengthRequiredSid(nSubAuthorityCount))))
151 return STATUS_NO_MEMORY;
153 tmp_sid->Revision = SID_REVISION;
155 if (pIdentifierAuthority)
156 memcpy(&tmp_sid->IdentifierAuthority, pIdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY));
157 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
159 switch( nSubAuthorityCount )
161 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
162 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
163 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
164 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
165 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
166 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
167 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
168 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
172 return STATUS_SUCCESS;
175 /******************************************************************************
176 * RtlEqualSid [NTDLL.@]
178 * Determine if two SIDs are equal.
181 * pSid1 [I] Source SID
182 * pSid2 [I] SID to compare with
185 * TRUE, if pSid1 is equal to pSid2,
188 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
190 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
193 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
196 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
202 /******************************************************************************
203 * RtlEqualPrefixSid [NTDLL.@]
205 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
207 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
210 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
213 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
220 /******************************************************************************
221 * RtlFreeSid [NTDLL.@]
223 * Free the resources used by a SID.
226 * pSid [I] SID to Free.
231 DWORD WINAPI RtlFreeSid(PSID pSid)
233 TRACE("(%p)\n", pSid);
234 RtlFreeHeap( GetProcessHeap(), 0, pSid );
235 return STATUS_SUCCESS;
238 /**************************************************************************
239 * RtlLengthRequiredSid [NTDLL.@]
241 * Determine the amount of memory a SID will use
244 * nrofsubauths [I] Number of Sub Authorities in the SID.
247 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
249 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
251 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
254 /**************************************************************************
255 * RtlLengthSid [NTDLL.@]
257 * Determine the amount of memory a SID is using
260 * pSid [I] SID to get the size of.
263 * The size, in bytes, of pSid.
265 DWORD WINAPI RtlLengthSid(PSID pSid)
267 TRACE("sid=%p\n",pSid);
269 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
272 /**************************************************************************
273 * RtlInitializeSid [NTDLL.@]
278 * pSid [I] SID to initialise
279 * pIdentifierAuthority [I] Identifier Authority
280 * nSubAuthorityCount [I] Number of Sub Authorities
283 * Success: TRUE. pSid is initialised with the details given.
284 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
286 BOOL WINAPI RtlInitializeSid(
288 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
289 BYTE nSubAuthorityCount)
294 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
297 pisid->Revision = SID_REVISION;
298 pisid->SubAuthorityCount = nSubAuthorityCount;
299 if (pIdentifierAuthority)
300 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
302 for (i = 0; i < nSubAuthorityCount; i++)
303 *RtlSubAuthoritySid(pSid, i) = 0;
308 /**************************************************************************
309 * RtlSubAuthoritySid [NTDLL.@]
311 * Return the Sub Authority of a SID
314 * pSid [I] SID to get the Sub Authority from.
315 * nSubAuthority [I] Sub Authority number.
318 * A pointer to The Sub Authority value of pSid.
320 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
322 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
325 /**************************************************************************
326 * RtlIdentifierAuthoritySid [NTDLL.@]
328 * Return the Identifier Authority of a SID.
331 * pSid [I] SID to get the Identifier Authority from.
334 * A pointer to the Identifier Authority value of pSid.
336 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
338 return &(((SID*)pSid)->IdentifierAuthority);
341 /**************************************************************************
342 * RtlSubAuthorityCountSid [NTDLL.@]
344 * Get the number of Sub Authorities in a SID.
347 * pSid [I] SID to get the count from.
350 * A pointer to the Sub Authority count of pSid.
352 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
354 return &(((SID*)pSid)->SubAuthorityCount);
357 /**************************************************************************
358 * RtlCopySid [NTDLL.@]
360 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
362 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
363 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
366 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
369 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
372 /******************************************************************************
373 * RtlValidSid [NTDLL.@]
375 * Determine if a SID is valid.
378 * pSid [I] SID to check
381 * TRUE if pSid is valid,
384 BOOLEAN WINAPI RtlValidSid( PSID pSid )
390 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
391 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
398 WARN("(%p): invalid pointer!\n", pSid);
407 * security descriptor functions
410 /**************************************************************************
411 * RtlCreateSecurityDescriptor [NTDLL.@]
413 * Initialise a SECURITY_DESCRIPTOR.
416 * lpsd [O] Descriptor to initialise.
417 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
420 * Success: STATUS_SUCCESS.
421 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
423 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
424 PSECURITY_DESCRIPTOR lpsd,
427 if (rev!=SECURITY_DESCRIPTOR_REVISION)
428 return STATUS_UNKNOWN_REVISION;
429 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
430 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
431 return STATUS_SUCCESS;
434 /**************************************************************************
435 * RtlCopySecurityDescriptor [NTDLL.@]
437 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
440 * pSourceSD [O] SD to copy from.
441 * pDestinationSD [I] Destination SD.
444 * Success: STATUS_SUCCESS.
445 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
447 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
449 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
450 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
453 BOOLEAN defaulted, present;
455 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
457 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
458 return STATUS_UNKNOWN_REVISION;
460 /* copy initial data */
461 destSD->Revision = srcSD->Revision;
462 destSD->Sbz1 = srcSD->Sbz1;
463 destSD->Control = srcSD->Control;
466 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
467 length = RtlLengthSid(Owner);
471 destSD->Owner = srcSD->Owner;
472 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Owner, Owner);
476 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
477 RtlCopySid(length, destSD->Owner, Owner);
481 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
482 length = RtlLengthSid(Group);
486 destSD->Group = srcSD->Group;
487 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Group, Group);
491 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
492 RtlCopySid(length, destSD->Group, Group);
496 if (srcSD->Control & SE_DACL_PRESENT)
498 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
499 length = Dacl->AclSize;
503 destSD->Dacl = srcSD->Dacl;
504 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Dacl), Dacl);
508 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
509 copy_acl(length, destSD->Dacl, Dacl);
514 if (srcSD->Control & SE_SACL_PRESENT)
516 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
517 length = Sacl->AclSize;
521 destSD->Sacl = srcSD->Sacl;
522 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Sacl), Sacl);
526 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
527 copy_acl(length, destSD->Sacl, Sacl);
531 return STATUS_SUCCESS;
534 /**************************************************************************
535 * RtlValidSecurityDescriptor [NTDLL.@]
537 * Determine if a SECURITY_DESCRIPTOR is valid.
540 * SecurityDescriptor [I] Descriptor to check.
543 * Success: STATUS_SUCCESS.
544 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
546 NTSTATUS WINAPI RtlValidSecurityDescriptor(
547 PSECURITY_DESCRIPTOR SecurityDescriptor)
549 if ( ! SecurityDescriptor )
550 return STATUS_INVALID_SECURITY_DESCR;
551 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
552 return STATUS_UNKNOWN_REVISION;
554 return STATUS_SUCCESS;
557 /**************************************************************************
558 * RtlLengthSecurityDescriptor [NTDLL.@]
560 ULONG WINAPI RtlLengthSecurityDescriptor(
561 PSECURITY_DESCRIPTOR pSecurityDescriptor)
563 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
565 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
570 if ( lpsd->Control & SE_SELF_RELATIVE)
571 offset = (ULONG) lpsd;
573 if ( lpsd->Owner != NULL )
574 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
576 if ( lpsd->Group != NULL )
577 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
579 if ( (lpsd->Control & SE_SACL_PRESENT) &&
581 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
583 if ( (lpsd->Control & SE_DACL_PRESENT) &&
585 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
590 /******************************************************************************
591 * RtlGetDaclSecurityDescriptor [NTDLL.@]
594 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
595 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
596 OUT PBOOLEAN lpbDaclPresent,
598 OUT PBOOLEAN lpbDaclDefaulted)
600 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
602 TRACE("(%p,%p,%p,%p)\n",
603 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
605 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
606 return STATUS_UNKNOWN_REVISION ;
608 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
610 if ( SE_SELF_RELATIVE & lpsd->Control)
611 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
615 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
618 return STATUS_SUCCESS;
621 /**************************************************************************
622 * RtlSetDaclSecurityDescriptor [NTDLL.@]
624 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
625 PSECURITY_DESCRIPTOR pSecurityDescriptor,
628 BOOLEAN dacldefaulted )
630 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
632 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
633 return STATUS_UNKNOWN_REVISION;
634 if (lpsd->Control & SE_SELF_RELATIVE)
635 return STATUS_INVALID_SECURITY_DESCR;
638 { lpsd->Control &= ~SE_DACL_PRESENT;
642 lpsd->Control |= SE_DACL_PRESENT;
646 lpsd->Control |= SE_DACL_DEFAULTED;
648 lpsd->Control &= ~SE_DACL_DEFAULTED;
650 return STATUS_SUCCESS;
653 /******************************************************************************
654 * RtlGetSaclSecurityDescriptor [NTDLL.@]
657 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
658 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
659 OUT PBOOLEAN lpbSaclPresent,
661 OUT PBOOLEAN lpbSaclDefaulted)
663 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
665 TRACE("(%p,%p,%p,%p)\n",
666 pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
668 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
669 return STATUS_UNKNOWN_REVISION;
671 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
673 if (SE_SELF_RELATIVE & lpsd->Control)
674 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Sacl);
678 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
681 return STATUS_SUCCESS;
684 /**************************************************************************
685 * RtlSetSaclSecurityDescriptor [NTDLL.@]
687 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
688 PSECURITY_DESCRIPTOR pSecurityDescriptor,
691 BOOLEAN sacldefaulted)
693 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
695 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
696 return STATUS_UNKNOWN_REVISION;
697 if (lpsd->Control & SE_SELF_RELATIVE)
698 return STATUS_INVALID_SECURITY_DESCR;
700 lpsd->Control &= ~SE_SACL_PRESENT;
703 lpsd->Control |= SE_SACL_PRESENT;
706 lpsd->Control |= SE_SACL_DEFAULTED;
708 lpsd->Control &= ~SE_SACL_DEFAULTED;
709 return STATUS_SUCCESS;
712 /**************************************************************************
713 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
715 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
716 PSECURITY_DESCRIPTOR pSecurityDescriptor,
718 PBOOLEAN OwnerDefaulted)
720 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
722 if ( !lpsd || !Owner || !OwnerDefaulted )
723 return STATUS_INVALID_PARAMETER;
725 if (lpsd->Owner != NULL)
727 if (lpsd->Control & SE_SELF_RELATIVE)
728 *Owner = (PSID)((LPBYTE)lpsd +
731 *Owner = lpsd->Owner;
733 if ( lpsd->Control & SE_OWNER_DEFAULTED )
734 *OwnerDefaulted = TRUE;
736 *OwnerDefaulted = FALSE;
741 return STATUS_SUCCESS;
744 /**************************************************************************
745 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
747 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
748 PSECURITY_DESCRIPTOR pSecurityDescriptor,
750 BOOLEAN ownerdefaulted)
752 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
754 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
755 return STATUS_UNKNOWN_REVISION;
756 if (lpsd->Control & SE_SELF_RELATIVE)
757 return STATUS_INVALID_SECURITY_DESCR;
761 lpsd->Control |= SE_OWNER_DEFAULTED;
763 lpsd->Control &= ~SE_OWNER_DEFAULTED;
764 return STATUS_SUCCESS;
767 /**************************************************************************
768 * RtlSetGroupSecurityDescriptor [NTDLL.@]
770 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
771 PSECURITY_DESCRIPTOR pSecurityDescriptor,
773 BOOLEAN groupdefaulted)
775 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
777 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
778 return STATUS_UNKNOWN_REVISION;
779 if (lpsd->Control & SE_SELF_RELATIVE)
780 return STATUS_INVALID_SECURITY_DESCR;
784 lpsd->Control |= SE_GROUP_DEFAULTED;
786 lpsd->Control &= ~SE_GROUP_DEFAULTED;
787 return STATUS_SUCCESS;
790 /**************************************************************************
791 * RtlGetGroupSecurityDescriptor [NTDLL.@]
793 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
794 PSECURITY_DESCRIPTOR pSecurityDescriptor,
796 PBOOLEAN GroupDefaulted)
798 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
800 if ( !lpsd || !Group || !GroupDefaulted )
801 return STATUS_INVALID_PARAMETER;
803 if (lpsd->Group != NULL)
805 if (lpsd->Control & SE_SELF_RELATIVE)
806 *Group = (PSID)((LPBYTE)lpsd +
809 *Group = lpsd->Group;
811 if ( lpsd->Control & SE_GROUP_DEFAULTED )
812 *GroupDefaulted = TRUE;
814 *GroupDefaulted = FALSE;
819 return STATUS_SUCCESS;
822 /**************************************************************************
823 * RtlMakeSelfRelativeSD [NTDLL.@]
825 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
826 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
827 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
828 IN OUT LPDWORD lpdwBufferLength)
832 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
833 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
835 TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
836 lpdwBufferLength ? *lpdwBufferLength: -1);
838 if (!lpdwBufferLength || !pAbs)
839 return STATUS_INVALID_PARAMETER;
841 length = RtlLengthSecurityDescriptor(pAbs);
842 if (*lpdwBufferLength < length)
844 *lpdwBufferLength = length;
845 return STATUS_BUFFER_TOO_SMALL;
849 return STATUS_INVALID_PARAMETER;
851 if (pAbs->Control & SE_SELF_RELATIVE)
853 memcpy(pRel, pAbs, length);
854 return STATUS_SUCCESS;
857 pRel->Revision = pAbs->Revision;
858 pRel->Sbz1 = pAbs->Sbz1;
859 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
861 offsetRel = sizeof(SECURITY_DESCRIPTOR);
862 pRel->Owner = (PSID) offsetRel;
863 length = RtlLengthSid(pAbs->Owner);
864 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
867 pRel->Group = (PSID) offsetRel;
868 length = RtlLengthSid(pAbs->Group);
869 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
871 if (pRel->Control & SE_SACL_PRESENT)
874 pRel->Sacl = (PACL) offsetRel;
875 length = pAbs->Sacl->AclSize;
876 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
883 if (pRel->Control & SE_DACL_PRESENT)
886 pRel->Dacl = (PACL) offsetRel;
887 length = pAbs->Dacl->AclSize;
888 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
895 return STATUS_SUCCESS;
899 /**************************************************************************
900 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
902 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
903 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
904 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
905 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
907 OUT LPDWORD lpdwDaclSize,
909 OUT LPDWORD lpdwSaclSize,
911 OUT LPDWORD lpdwOwnerSize,
912 OUT PSID pPrimaryGroup,
913 OUT LPDWORD lpdwPrimaryGroupSize)
915 NTSTATUS status = STATUS_SUCCESS;
916 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
917 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
920 !lpdwAbsoluteSecurityDescriptorSize ||
924 !lpdwPrimaryGroupSize ||
925 ~pRel->Control & SE_SELF_RELATIVE)
926 return STATUS_INVALID_PARAMETER;
928 /* Confirm buffers are sufficiently large */
929 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
931 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
932 status = STATUS_BUFFER_TOO_SMALL;
935 if (pRel->Control & SE_DACL_PRESENT &&
936 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
938 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
939 status = STATUS_BUFFER_TOO_SMALL;
942 if (pRel->Control & SE_SACL_PRESENT &&
943 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
945 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
946 status = STATUS_BUFFER_TOO_SMALL;
950 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
952 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
953 status = STATUS_BUFFER_TOO_SMALL;
957 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
959 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
960 status = STATUS_BUFFER_TOO_SMALL;
963 if (status != STATUS_SUCCESS)
966 /* Copy structures */
967 pAbs->Revision = pRel->Revision;
968 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
970 if (pRel->Control & SE_SACL_PRESENT)
972 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
974 memcpy(pSacl, pAcl, pAcl->AclSize);
978 if (pRel->Control & SE_DACL_PRESENT)
980 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
981 memcpy(pDacl, pAcl, pAcl->AclSize);
987 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
988 memcpy(pOwner, psid, RtlLengthSid(psid));
989 pAbs->Owner = pOwner;
994 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
995 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
996 pAbs->Group = pPrimaryGroup;
1002 /******************************************************************************
1003 * RtlGetControlSecurityDescriptor (NTDLL.@)
1005 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1006 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1007 PSECURITY_DESCRIPTOR_CONTROL pControl,
1008 LPDWORD lpdwRevision)
1010 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1012 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1014 *lpdwRevision = lpsd->Revision;
1016 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1017 return STATUS_UNKNOWN_REVISION;
1019 *pControl = lpsd->Control;
1021 return STATUS_SUCCESS;
1025 /**************************************************************************
1026 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1028 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1029 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1030 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1031 PULONG BufferLength)
1033 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1035 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1036 SelfRelativeSecurityDescriptor, BufferLength);
1038 if (abs->Control & SE_SELF_RELATIVE)
1039 return STATUS_BAD_DESCRIPTOR_FORMAT;
1041 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1042 SelfRelativeSecurityDescriptor, BufferLength);
1047 * access control list's
1050 /**************************************************************************
1051 * RtlCreateAcl [NTDLL.@]
1054 * This should return NTSTATUS
1056 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1058 TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
1060 if (rev!=ACL_REVISION)
1061 return STATUS_INVALID_PARAMETER;
1062 if (size<sizeof(ACL))
1063 return STATUS_BUFFER_TOO_SMALL;
1065 return STATUS_INVALID_PARAMETER;
1067 memset(acl,'\0',sizeof(ACL));
1068 acl->AclRevision = rev;
1069 acl->AclSize = size;
1071 return STATUS_SUCCESS;
1074 /**************************************************************************
1075 * RtlFirstFreeAce [NTDLL.@]
1076 * looks for the AceCount+1 ACE, and if it is still within the alloced
1077 * ACL, return a pointer to it
1079 BOOLEAN WINAPI RtlFirstFreeAce(
1087 ace = (PACE_HEADER)(acl+1);
1088 for (i=0;i<acl->AceCount;i++) {
1089 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1091 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1093 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1099 /**************************************************************************
1100 * RtlAddAce [NTDLL.@]
1102 NTSTATUS WINAPI RtlAddAce(
1106 PACE_HEADER acestart,
1109 PACE_HEADER ace,targetace;
1112 if (acl->AclRevision != ACL_REVISION)
1113 return STATUS_INVALID_PARAMETER;
1114 if (!RtlFirstFreeAce(acl,&targetace))
1115 return STATUS_INVALID_PARAMETER;
1116 nrofaces=0;ace=acestart;
1117 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1119 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1121 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1122 return STATUS_INVALID_PARAMETER;
1123 memcpy((LPBYTE)targetace,acestart,acelen);
1124 acl->AceCount+=nrofaces;
1125 return STATUS_SUCCESS;
1128 /**************************************************************************
1129 * RtlDeleteAce [NTDLL.@]
1131 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1136 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1138 if (STATUS_SUCCESS == status)
1143 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1144 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1146 len += pcAce->AceSize;
1147 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1150 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1154 TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\n", pAcl, dwAceIndex, status);
1159 /******************************************************************************
1160 * RtlAddAccessAllowedAce [NTDLL.@]
1162 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1164 IN DWORD dwAceRevision,
1165 IN DWORD AccessMask,
1168 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1171 /******************************************************************************
1172 * RtlAddAccessAllowedAceEx [NTDLL.@]
1174 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1176 IN DWORD dwAceRevision,
1178 IN DWORD AccessMask,
1181 TRACE("(%p,0x%08lx,0x%08lx,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1183 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1184 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1187 /******************************************************************************
1188 * RtlAddAccessDeniedAce [NTDLL.@]
1190 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1192 IN DWORD dwAceRevision,
1193 IN DWORD AccessMask,
1196 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1199 /******************************************************************************
1200 * RtlAddAccessDeniedAceEx [NTDLL.@]
1202 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1204 IN DWORD dwAceRevision,
1206 IN DWORD AccessMask,
1209 TRACE("(%p,0x%08lx,0x%08lx,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1211 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1212 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1215 /**************************************************************************
1216 * RtlAddAuditAccessAce [NTDLL.@]
1218 NTSTATUS WINAPI RtlAddAuditAccessAce(
1220 IN DWORD dwAceRevision,
1221 IN DWORD dwAccessMask,
1223 IN BOOL bAuditSuccess,
1224 IN BOOL bAuditFailure)
1226 DWORD dwAceFlags = 0;
1228 TRACE("(%p,%ld,%ld,%p,%u,%u)\n",pAcl,dwAceRevision,dwAccessMask,
1229 pSid,bAuditSuccess,bAuditFailure);
1232 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1235 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1237 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1238 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1241 /******************************************************************************
1242 * RtlValidAcl [NTDLL.@]
1244 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1247 TRACE("(%p)\n", pAcl);
1254 if (pAcl->AclRevision != ACL_REVISION)
1258 ace = (PACE_HEADER)(pAcl+1);
1260 for (i=0;i<=pAcl->AceCount;i++)
1262 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1267 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1271 __EXCEPT(page_fault)
1273 WARN("(%p): invalid pointer!\n", pAcl);
1280 /******************************************************************************
1281 * RtlGetAce [NTDLL.@]
1283 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1287 TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1289 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1290 return STATUS_INVALID_PARAMETER;
1292 ace = (PACE_HEADER)(pAcl + 1);
1293 for (;dwAceIndex;dwAceIndex--)
1294 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1296 *pAce = (LPVOID) ace;
1298 return STATUS_SUCCESS;
1305 /******************************************************************************
1306 * RtlAdjustPrivilege [NTDLL.@]
1308 * Enables or disables a privilege from the calling thread or process.
1311 * Privilege [I] Privilege index to change.
1312 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1313 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1314 * Enabled [O] Whether privilege was previously enabled or disabled.
1317 * Success: STATUS_SUCCESS.
1318 * Failure: NTSTATUS code.
1321 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1325 RtlAdjustPrivilege(ULONG Privilege,
1327 BOOLEAN CurrentThread,
1330 TOKEN_PRIVILEGES NewState;
1331 TOKEN_PRIVILEGES OldState;
1336 TRACE("(%ld, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1337 CurrentThread ? "TRUE" : "FALSE", Enabled);
1341 Status = NtOpenThreadToken(GetCurrentThread(),
1342 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1348 Status = NtOpenProcessToken(GetCurrentProcess(),
1349 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1353 if (!NT_SUCCESS(Status))
1355 WARN("Retrieving token handle failed (Status %lx)\n", Status);
1359 OldState.PrivilegeCount = 1;
1361 NewState.PrivilegeCount = 1;
1362 NewState.Privileges[0].Luid.LowPart = Privilege;
1363 NewState.Privileges[0].Luid.HighPart = 0;
1364 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1366 Status = NtAdjustPrivilegesToken(TokenHandle,
1369 sizeof(TOKEN_PRIVILEGES),
1372 NtClose (TokenHandle);
1373 if (Status == STATUS_NOT_ALL_ASSIGNED)
1375 TRACE("Failed to assign all privileges\n");
1376 return STATUS_PRIVILEGE_NOT_HELD;
1378 if (!NT_SUCCESS(Status))
1380 WARN("NtAdjustPrivilegesToken() failed (Status %lx)\n", Status);
1384 if (OldState.PrivilegeCount == 0)
1387 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1389 return STATUS_SUCCESS;
1392 /******************************************************************************
1393 * RtlImpersonateSelf [NTDLL.@]
1395 * Makes an impersonation token that represents the process user and assigns
1396 * to the current thread.
1399 * ImpersonationLevel [I] Level at which to impersonate.
1402 * Success: STATUS_SUCCESS.
1403 * Failure: NTSTATUS code.
1406 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1409 OBJECT_ATTRIBUTES ObjectAttributes;
1410 HANDLE ProcessToken;
1411 HANDLE ImpersonationToken;
1413 TRACE("(%08x)\n", ImpersonationLevel);
1415 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1417 if (Status != STATUS_SUCCESS)
1420 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1422 Status = NtDuplicateToken( ProcessToken,
1427 &ImpersonationToken );
1428 if (Status != STATUS_SUCCESS)
1430 NtClose( ProcessToken );
1434 Status = NtSetInformationThread( GetCurrentThread(),
1435 ThreadImpersonationToken,
1436 &ImpersonationToken,
1437 sizeof(ImpersonationToken) );
1439 NtClose( ImpersonationToken );
1440 NtClose( ProcessToken );
1445 /******************************************************************************
1446 * NtAccessCheck [NTDLL.@]
1447 * ZwAccessCheck [NTDLL.@]
1449 * Checks that a user represented by a token is allowed to access an object
1450 * represented by a security descriptor.
1453 * SecurityDescriptor [I] The security descriptor of the object to check.
1454 * ClientToken [I] Token of the user accessing the object.
1455 * DesiredAccess [I] The desired access to the object.
1456 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1457 * PrivilegeSet [I/O] Privileges used during the access check.
1458 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1459 * GrantedAccess [O] The actual access rights granted.
1460 * AccessStatus [O] The status of the access check.
1466 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1467 * the maximum access rights allowed by the SD and returns them in
1469 * The SecurityDescriptor must have a valid owner and groups present,
1470 * otherwise the function will fail.
1474 PSECURITY_DESCRIPTOR SecurityDescriptor,
1476 ACCESS_MASK DesiredAccess,
1477 PGENERIC_MAPPING GenericMapping,
1478 PPRIVILEGE_SET PrivilegeSet,
1479 PULONG ReturnLength,
1480 PULONG GrantedAccess,
1481 NTSTATUS *AccessStatus)
1485 TRACE("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1486 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1487 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1489 SERVER_START_REQ( access_check )
1491 struct security_descriptor sd;
1496 BOOLEAN defaulted, present;
1498 SECURITY_DESCRIPTOR_CONTROL control;
1500 req->handle = ClientToken;
1501 req->desired_access = DesiredAccess;
1502 req->mapping_read = GenericMapping->GenericRead;
1503 req->mapping_write = GenericMapping->GenericWrite;
1504 req->mapping_execute = GenericMapping->GenericExecute;
1505 req->mapping_all = GenericMapping->GenericAll;
1507 /* marshal security descriptor */
1508 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1509 sd.control = control & ~SE_SELF_RELATIVE;
1510 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1511 sd.owner_len = RtlLengthSid( owner );
1512 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1513 sd.group_len = RtlLengthSid( group );
1514 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1515 sd.sacl_len = (present ? sacl->AclSize : 0);
1516 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1517 sd.dacl_len = (present ? dacl->AclSize : 0);
1519 wine_server_add_data( req, &sd, sizeof(sd) );
1520 wine_server_add_data( req, owner, sd.owner_len );
1521 wine_server_add_data( req, group, sd.group_len );
1522 wine_server_add_data( req, sacl, sd.sacl_len );
1523 wine_server_add_data( req, dacl, sd.dacl_len );
1525 wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1527 status = wine_server_call( req );
1529 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1530 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1532 if (status == STATUS_SUCCESS)
1533 *AccessStatus = reply->access_status;
1534 *GrantedAccess = reply->access_granted;
1541 /******************************************************************************
1542 * NtSetSecurityObject [NTDLL.@]
1545 NtSetSecurityObject(
1547 IN SECURITY_INFORMATION SecurityInformation,
1548 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1550 FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1551 return STATUS_SUCCESS;
1554 /******************************************************************************
1555 * RtlConvertSidToUnicodeString (NTDLL.@)
1557 * The returned SID is used to access the USER registry hive usually
1559 * the native function returns something like
1560 * "S-1-5-21-0000000000-000000000-0000000000-500";
1562 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1563 PUNICODE_STRING String,
1565 BOOLEAN AllocateString)
1567 static const WCHAR formatW[] = {'-','%','u',0};
1568 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1570 const SID *sid = (const SID *)pSid;
1574 p += sprintfW( p, formatW, sid->Revision );
1575 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1576 sid->IdentifierAuthority.Value[4] ),
1577 MAKEWORD( sid->IdentifierAuthority.Value[3],
1578 sid->IdentifierAuthority.Value[2] )));
1579 for (i = 0; i < sid->SubAuthorityCount; i++)
1580 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1582 len = (p + 1 - buffer) * sizeof(WCHAR);
1584 String->Length = len - sizeof(WCHAR);
1587 String->MaximumLength = len;
1588 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1589 return STATUS_NO_MEMORY;
1591 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1593 memcpy( String->Buffer, buffer, len );
1594 return STATUS_SUCCESS;
1597 /******************************************************************************
1598 * RtlQueryInformationAcl (NTDLL.@)
1600 NTSTATUS WINAPI RtlQueryInformationAcl(
1602 LPVOID pAclInformation,
1603 DWORD nAclInformationLength,
1604 ACL_INFORMATION_CLASS dwAclInformationClass)
1606 NTSTATUS status = STATUS_SUCCESS;
1608 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1609 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1611 switch (dwAclInformationClass)
1613 case AclRevisionInformation:
1615 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1617 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1618 status = STATUS_INVALID_PARAMETER;
1620 paclrev->AclRevision = pAcl->AclRevision;
1625 case AclSizeInformation:
1627 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1629 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1630 status = STATUS_INVALID_PARAMETER;
1636 paclsize->AceCount = pAcl->AceCount;
1638 paclsize->AclBytesInUse = 0;
1639 ace = (PACE_HEADER) (pAcl + 1);
1641 for (i = 0; i < pAcl->AceCount; i++)
1643 paclsize->AclBytesInUse += ace->AceSize;
1644 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1647 if (pAcl->AclSize < paclsize->AclBytesInUse)
1649 WARN("Acl has %ld bytes free\n", paclsize->AclBytesFree);
1650 paclsize->AclBytesFree = 0;
1651 paclsize->AclBytesInUse = pAcl->AclSize;
1654 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1661 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1662 status = STATUS_INVALID_PARAMETER;