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 /* helper function to copy an ACL */
50 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
54 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
57 size = ((ACL *)pSourceAcl)->AclSize;
58 if (nDestinationAclLength < size)
61 memmove(pDestinationAcl, pSourceAcl, size);
65 /* generically adds an ACE to an ACL */
66 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
67 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
69 ACE_HEADER *pAceHeader;
75 if (!RtlValidSid(pSid))
76 return STATUS_INVALID_SID;
78 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
79 return STATUS_REVISION_MISMATCH;
81 if (!RtlValidAcl(pAcl))
82 return STATUS_INVALID_ACL;
84 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
85 return STATUS_INVALID_ACL;
88 return STATUS_ALLOTTED_SPACE_EXCEEDED;
90 /* calculate generic size of the ACE */
91 dwLengthSid = RtlLengthSid(pSid);
92 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
93 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
94 return STATUS_ALLOTTED_SPACE_EXCEEDED;
96 /* fill the new ACE */
97 pAceHeader->AceType = dwAceType;
98 pAceHeader->AceFlags = dwAceFlags;
99 pAceHeader->AceSize = dwAceSize;
101 /* skip past the ACE_HEADER of the ACE */
102 pAccessMask = (DWORD *)(pAceHeader + 1);
103 *pAccessMask = dwAccessMask;
105 /* skip past ACE->Mask */
106 pSidStart = pAccessMask + 1;
107 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
109 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
112 return STATUS_SUCCESS;
119 /******************************************************************************
120 * RtlAllocateAndInitializeSid [NTDLL.@]
123 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
124 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
125 BYTE nSubAuthorityCount,
126 DWORD nSubAuthority0, DWORD nSubAuthority1,
127 DWORD nSubAuthority2, DWORD nSubAuthority3,
128 DWORD nSubAuthority4, DWORD nSubAuthority5,
129 DWORD nSubAuthority6, DWORD nSubAuthority7,
134 TRACE("(%p, 0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p)\n",
135 pIdentifierAuthority,nSubAuthorityCount,
136 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
137 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
139 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
141 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
142 RtlLengthRequiredSid(nSubAuthorityCount))))
143 return STATUS_NO_MEMORY;
145 tmp_sid->Revision = SID_REVISION;
147 if (pIdentifierAuthority)
148 memcpy(&tmp_sid->IdentifierAuthority, pIdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY));
149 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
151 switch( nSubAuthorityCount )
153 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
154 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
155 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
156 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
157 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
158 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
159 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
160 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
164 return STATUS_SUCCESS;
167 /******************************************************************************
168 * RtlEqualSid [NTDLL.@]
170 * Determine if two SIDs are equal.
173 * pSid1 [I] Source SID
174 * pSid2 [I] SID to compare with
177 * TRUE, if pSid1 is equal to pSid2,
180 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
182 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
185 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
188 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
194 /******************************************************************************
195 * RtlEqualPrefixSid [NTDLL.@]
197 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
199 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
202 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
205 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
212 /******************************************************************************
213 * RtlFreeSid [NTDLL.@]
215 * Free the resources used by a SID.
218 * pSid [I] SID to Free.
223 DWORD WINAPI RtlFreeSid(PSID pSid)
225 TRACE("(%p)\n", pSid);
226 RtlFreeHeap( GetProcessHeap(), 0, pSid );
227 return STATUS_SUCCESS;
230 /**************************************************************************
231 * RtlLengthRequiredSid [NTDLL.@]
233 * Determine the amount of memory a SID will use
236 * nrofsubauths [I] Number of Sub Authorities in the SID.
239 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
241 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
243 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
246 /**************************************************************************
247 * RtlLengthSid [NTDLL.@]
249 * Determine the amount of memory a SID is using
252 * pSid [I] SID to get the size of.
255 * The size, in bytes, of pSid.
257 DWORD WINAPI RtlLengthSid(PSID pSid)
259 TRACE("sid=%p\n",pSid);
261 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
264 /**************************************************************************
265 * RtlInitializeSid [NTDLL.@]
270 * pSid [I] SID to initialise
271 * pIdentifierAuthority [I] Identifier Authority
272 * nSubAuthorityCount [I] Number of Sub Authorities
275 * Success: TRUE. pSid is initialised with the details given.
276 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
278 BOOL WINAPI RtlInitializeSid(
280 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
281 BYTE nSubAuthorityCount)
286 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
289 pisid->Revision = SID_REVISION;
290 pisid->SubAuthorityCount = nSubAuthorityCount;
291 if (pIdentifierAuthority)
292 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
294 for (i = 0; i < nSubAuthorityCount; i++)
295 *RtlSubAuthoritySid(pSid, i) = 0;
300 /**************************************************************************
301 * RtlSubAuthoritySid [NTDLL.@]
303 * Return the Sub Authority of a SID
306 * pSid [I] SID to get the Sub Authority from.
307 * nSubAuthority [I] Sub Authority number.
310 * A pointer to The Sub Authority value of pSid.
312 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
314 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
317 /**************************************************************************
318 * RtlIdentifierAuthoritySid [NTDLL.@]
320 * Return the Identifier Authority of a SID.
323 * pSid [I] SID to get the Identifier Authority from.
326 * A pointer to the Identifier Authority value of pSid.
328 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
330 return &(((SID*)pSid)->IdentifierAuthority);
333 /**************************************************************************
334 * RtlSubAuthorityCountSid [NTDLL.@]
336 * Get the number of Sub Authorities in a SID.
339 * pSid [I] SID to get the count from.
342 * A pointer to the Sub Authority count of pSid.
344 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
346 return &(((SID*)pSid)->SubAuthorityCount);
349 /**************************************************************************
350 * RtlCopySid [NTDLL.@]
352 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
354 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
355 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
358 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
361 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
364 /******************************************************************************
365 * RtlValidSid [NTDLL.@]
367 * Determine if a SID is valid.
370 * pSid [I] SID to check
373 * TRUE if pSid is valid,
376 BOOLEAN WINAPI RtlValidSid( PSID pSid )
382 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
383 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
390 WARN("(%p): invalid pointer!\n", pSid);
399 * security descriptor functions
402 /**************************************************************************
403 * RtlCreateSecurityDescriptor [NTDLL.@]
405 * Initialise a SECURITY_DESCRIPTOR.
408 * lpsd [O] Descriptor to initialise.
409 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
412 * Success: STATUS_SUCCESS.
413 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
415 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
416 PSECURITY_DESCRIPTOR lpsd,
419 if (rev!=SECURITY_DESCRIPTOR_REVISION)
420 return STATUS_UNKNOWN_REVISION;
421 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
422 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
423 return STATUS_SUCCESS;
426 /**************************************************************************
427 * RtlCopySecurityDescriptor [NTDLL.@]
429 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
432 * pSourceSD [O] SD to copy from.
433 * pDestinationSD [I] Destination SD.
436 * Success: STATUS_SUCCESS.
437 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
439 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
441 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
442 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
445 BOOLEAN defaulted, present;
447 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
449 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
450 return STATUS_UNKNOWN_REVISION;
452 /* copy initial data */
453 destSD->Revision = srcSD->Revision;
454 destSD->Sbz1 = srcSD->Sbz1;
455 destSD->Control = srcSD->Control;
458 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
459 length = RtlLengthSid(Owner);
463 destSD->Owner = srcSD->Owner;
464 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Owner, Owner);
468 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
469 RtlCopySid(length, destSD->Owner, Owner);
473 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
474 length = RtlLengthSid(Group);
478 destSD->Group = srcSD->Group;
479 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Group, Group);
483 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
484 RtlCopySid(length, destSD->Group, Group);
488 if (srcSD->Control & SE_DACL_PRESENT)
490 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
491 length = Dacl->AclSize;
495 destSD->Dacl = srcSD->Dacl;
496 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Dacl), Dacl);
500 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
501 copy_acl(length, destSD->Dacl, Dacl);
506 if (srcSD->Control & SE_SACL_PRESENT)
508 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
509 length = Sacl->AclSize;
513 destSD->Sacl = srcSD->Sacl;
514 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Sacl), Sacl);
518 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
519 copy_acl(length, destSD->Sacl, Sacl);
523 return STATUS_SUCCESS;
526 /**************************************************************************
527 * RtlValidSecurityDescriptor [NTDLL.@]
529 * Determine if a SECURITY_DESCRIPTOR is valid.
532 * SecurityDescriptor [I] Descriptor to check.
535 * Success: STATUS_SUCCESS.
536 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
538 NTSTATUS WINAPI RtlValidSecurityDescriptor(
539 PSECURITY_DESCRIPTOR SecurityDescriptor)
541 if ( ! SecurityDescriptor )
542 return STATUS_INVALID_SECURITY_DESCR;
543 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
544 return STATUS_UNKNOWN_REVISION;
546 return STATUS_SUCCESS;
549 /**************************************************************************
550 * RtlLengthSecurityDescriptor [NTDLL.@]
552 ULONG WINAPI RtlLengthSecurityDescriptor(
553 PSECURITY_DESCRIPTOR pSecurityDescriptor)
555 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
557 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
562 if ( lpsd->Control & SE_SELF_RELATIVE)
563 offset = (ULONG) lpsd;
565 if ( lpsd->Owner != NULL )
566 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
568 if ( lpsd->Group != NULL )
569 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
571 if ( (lpsd->Control & SE_SACL_PRESENT) &&
573 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
575 if ( (lpsd->Control & SE_DACL_PRESENT) &&
577 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
582 /******************************************************************************
583 * RtlGetDaclSecurityDescriptor [NTDLL.@]
586 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
587 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
588 OUT PBOOLEAN lpbDaclPresent,
590 OUT PBOOLEAN lpbDaclDefaulted)
592 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
594 TRACE("(%p,%p,%p,%p)\n",
595 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
597 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
598 return STATUS_UNKNOWN_REVISION ;
600 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
602 if ( SE_SELF_RELATIVE & lpsd->Control)
603 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
607 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
610 return STATUS_SUCCESS;
613 /**************************************************************************
614 * RtlSetDaclSecurityDescriptor [NTDLL.@]
616 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
617 PSECURITY_DESCRIPTOR pSecurityDescriptor,
620 BOOLEAN dacldefaulted )
622 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
624 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
625 return STATUS_UNKNOWN_REVISION;
626 if (lpsd->Control & SE_SELF_RELATIVE)
627 return STATUS_INVALID_SECURITY_DESCR;
630 { lpsd->Control &= ~SE_DACL_PRESENT;
634 lpsd->Control |= SE_DACL_PRESENT;
638 lpsd->Control |= SE_DACL_DEFAULTED;
640 lpsd->Control &= ~SE_DACL_DEFAULTED;
642 return STATUS_SUCCESS;
645 /******************************************************************************
646 * RtlGetSaclSecurityDescriptor [NTDLL.@]
649 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
650 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
651 OUT PBOOLEAN lpbSaclPresent,
653 OUT PBOOLEAN lpbSaclDefaulted)
655 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
657 TRACE("(%p,%p,%p,%p)\n",
658 pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
660 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
661 return STATUS_UNKNOWN_REVISION;
663 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
665 if (SE_SELF_RELATIVE & lpsd->Control)
666 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Sacl);
670 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
673 return STATUS_SUCCESS;
676 /**************************************************************************
677 * RtlSetSaclSecurityDescriptor [NTDLL.@]
679 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
680 PSECURITY_DESCRIPTOR pSecurityDescriptor,
683 BOOLEAN sacldefaulted)
685 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
687 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
688 return STATUS_UNKNOWN_REVISION;
689 if (lpsd->Control & SE_SELF_RELATIVE)
690 return STATUS_INVALID_SECURITY_DESCR;
692 lpsd->Control &= ~SE_SACL_PRESENT;
695 lpsd->Control |= SE_SACL_PRESENT;
698 lpsd->Control |= SE_SACL_DEFAULTED;
700 lpsd->Control &= ~SE_SACL_DEFAULTED;
701 return STATUS_SUCCESS;
704 /**************************************************************************
705 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
707 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
708 PSECURITY_DESCRIPTOR pSecurityDescriptor,
710 PBOOLEAN OwnerDefaulted)
712 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
714 if ( !lpsd || !Owner || !OwnerDefaulted )
715 return STATUS_INVALID_PARAMETER;
717 if (lpsd->Owner != NULL)
719 if (lpsd->Control & SE_SELF_RELATIVE)
720 *Owner = (PSID)((LPBYTE)lpsd +
723 *Owner = lpsd->Owner;
725 if ( lpsd->Control & SE_OWNER_DEFAULTED )
726 *OwnerDefaulted = TRUE;
728 *OwnerDefaulted = FALSE;
733 return STATUS_SUCCESS;
736 /**************************************************************************
737 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
739 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
740 PSECURITY_DESCRIPTOR pSecurityDescriptor,
742 BOOLEAN ownerdefaulted)
744 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
746 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
747 return STATUS_UNKNOWN_REVISION;
748 if (lpsd->Control & SE_SELF_RELATIVE)
749 return STATUS_INVALID_SECURITY_DESCR;
753 lpsd->Control |= SE_OWNER_DEFAULTED;
755 lpsd->Control &= ~SE_OWNER_DEFAULTED;
756 return STATUS_SUCCESS;
759 /**************************************************************************
760 * RtlSetGroupSecurityDescriptor [NTDLL.@]
762 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
763 PSECURITY_DESCRIPTOR pSecurityDescriptor,
765 BOOLEAN groupdefaulted)
767 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
769 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
770 return STATUS_UNKNOWN_REVISION;
771 if (lpsd->Control & SE_SELF_RELATIVE)
772 return STATUS_INVALID_SECURITY_DESCR;
776 lpsd->Control |= SE_GROUP_DEFAULTED;
778 lpsd->Control &= ~SE_GROUP_DEFAULTED;
779 return STATUS_SUCCESS;
782 /**************************************************************************
783 * RtlGetGroupSecurityDescriptor [NTDLL.@]
785 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
786 PSECURITY_DESCRIPTOR pSecurityDescriptor,
788 PBOOLEAN GroupDefaulted)
790 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
792 if ( !lpsd || !Group || !GroupDefaulted )
793 return STATUS_INVALID_PARAMETER;
795 if (lpsd->Group != NULL)
797 if (lpsd->Control & SE_SELF_RELATIVE)
798 *Group = (PSID)((LPBYTE)lpsd +
801 *Group = lpsd->Group;
803 if ( lpsd->Control & SE_GROUP_DEFAULTED )
804 *GroupDefaulted = TRUE;
806 *GroupDefaulted = FALSE;
811 return STATUS_SUCCESS;
814 /**************************************************************************
815 * RtlMakeSelfRelativeSD [NTDLL.@]
817 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
818 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
819 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
820 IN OUT LPDWORD lpdwBufferLength)
824 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
825 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
827 TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
828 lpdwBufferLength ? *lpdwBufferLength: -1);
830 if (!lpdwBufferLength || !pAbs)
831 return STATUS_INVALID_PARAMETER;
833 length = RtlLengthSecurityDescriptor(pAbs);
834 if (*lpdwBufferLength < length)
836 *lpdwBufferLength = length;
837 return STATUS_BUFFER_TOO_SMALL;
841 return STATUS_INVALID_PARAMETER;
843 if (pAbs->Control & SE_SELF_RELATIVE)
845 memcpy(pRel, pAbs, length);
846 return STATUS_SUCCESS;
849 pRel->Revision = pAbs->Revision;
850 pRel->Sbz1 = pAbs->Sbz1;
851 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
853 offsetRel = sizeof(SECURITY_DESCRIPTOR);
854 pRel->Owner = (PSID) offsetRel;
855 length = RtlLengthSid(pAbs->Owner);
856 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
859 pRel->Group = (PSID) offsetRel;
860 length = RtlLengthSid(pAbs->Group);
861 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
863 if (pRel->Control & SE_SACL_PRESENT)
866 pRel->Sacl = (PACL) offsetRel;
867 length = pAbs->Sacl->AclSize;
868 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
875 if (pRel->Control & SE_DACL_PRESENT)
878 pRel->Dacl = (PACL) offsetRel;
879 length = pAbs->Dacl->AclSize;
880 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
887 return STATUS_SUCCESS;
891 /**************************************************************************
892 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
894 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
895 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
896 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
897 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
899 OUT LPDWORD lpdwDaclSize,
901 OUT LPDWORD lpdwSaclSize,
903 OUT LPDWORD lpdwOwnerSize,
904 OUT PSID pPrimaryGroup,
905 OUT LPDWORD lpdwPrimaryGroupSize)
907 NTSTATUS status = STATUS_SUCCESS;
908 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
909 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
912 !lpdwAbsoluteSecurityDescriptorSize ||
916 !lpdwPrimaryGroupSize ||
917 ~pRel->Control & SE_SELF_RELATIVE)
918 return STATUS_INVALID_PARAMETER;
920 /* Confirm buffers are sufficiently large */
921 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
923 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
924 status = STATUS_BUFFER_TOO_SMALL;
927 if (pRel->Control & SE_DACL_PRESENT &&
928 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
930 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
931 status = STATUS_BUFFER_TOO_SMALL;
934 if (pRel->Control & SE_SACL_PRESENT &&
935 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
937 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
938 status = STATUS_BUFFER_TOO_SMALL;
942 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
944 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
945 status = STATUS_BUFFER_TOO_SMALL;
949 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
951 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
952 status = STATUS_BUFFER_TOO_SMALL;
955 if (status != STATUS_SUCCESS)
958 /* Copy structures */
959 pAbs->Revision = pRel->Revision;
960 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
962 if (pRel->Control & SE_SACL_PRESENT)
964 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
966 memcpy(pSacl, pAcl, pAcl->AclSize);
970 if (pRel->Control & SE_DACL_PRESENT)
972 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
973 memcpy(pDacl, pAcl, pAcl->AclSize);
979 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
980 memcpy(pOwner, psid, RtlLengthSid(psid));
981 pAbs->Owner = pOwner;
986 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
987 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
988 pAbs->Group = pPrimaryGroup;
994 /******************************************************************************
995 * RtlGetControlSecurityDescriptor (NTDLL.@)
997 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
998 PSECURITY_DESCRIPTOR pSecurityDescriptor,
999 PSECURITY_DESCRIPTOR_CONTROL pControl,
1000 LPDWORD lpdwRevision)
1002 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1004 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1006 *lpdwRevision = lpsd->Revision;
1008 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1009 return STATUS_UNKNOWN_REVISION;
1011 *pControl = lpsd->Control;
1013 return STATUS_SUCCESS;
1017 /**************************************************************************
1018 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1020 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1021 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1022 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1023 PULONG BufferLength)
1025 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1027 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1028 SelfRelativeSecurityDescriptor, BufferLength);
1030 if (abs->Control & SE_SELF_RELATIVE)
1031 return STATUS_BAD_DESCRIPTOR_FORMAT;
1033 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1034 SelfRelativeSecurityDescriptor, BufferLength);
1039 * access control list's
1042 /**************************************************************************
1043 * RtlCreateAcl [NTDLL.@]
1046 * This should return NTSTATUS
1048 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1050 TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
1052 if (rev!=ACL_REVISION)
1053 return STATUS_INVALID_PARAMETER;
1054 if (size<sizeof(ACL))
1055 return STATUS_BUFFER_TOO_SMALL;
1057 return STATUS_INVALID_PARAMETER;
1059 memset(acl,'\0',sizeof(ACL));
1060 acl->AclRevision = rev;
1061 acl->AclSize = size;
1063 return STATUS_SUCCESS;
1066 /**************************************************************************
1067 * RtlFirstFreeAce [NTDLL.@]
1068 * looks for the AceCount+1 ACE, and if it is still within the alloced
1069 * ACL, return a pointer to it
1071 BOOLEAN WINAPI RtlFirstFreeAce(
1079 ace = (PACE_HEADER)(acl+1);
1080 for (i=0;i<acl->AceCount;i++) {
1081 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1083 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1085 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1091 /**************************************************************************
1092 * RtlAddAce [NTDLL.@]
1094 NTSTATUS WINAPI RtlAddAce(
1098 PACE_HEADER acestart,
1101 PACE_HEADER ace,targetace;
1104 if (acl->AclRevision != ACL_REVISION)
1105 return STATUS_INVALID_PARAMETER;
1106 if (!RtlFirstFreeAce(acl,&targetace))
1107 return STATUS_INVALID_PARAMETER;
1108 nrofaces=0;ace=acestart;
1109 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1111 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1113 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1114 return STATUS_INVALID_PARAMETER;
1115 memcpy((LPBYTE)targetace,acestart,acelen);
1116 acl->AceCount+=nrofaces;
1117 return STATUS_SUCCESS;
1120 /**************************************************************************
1121 * RtlDeleteAce [NTDLL.@]
1123 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1128 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1130 if (STATUS_SUCCESS == status)
1135 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1136 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1138 len += pcAce->AceSize;
1139 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1142 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1146 TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\n", pAcl, dwAceIndex, status);
1151 /******************************************************************************
1152 * RtlAddAccessAllowedAce [NTDLL.@]
1154 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1156 IN DWORD dwAceRevision,
1157 IN DWORD AccessMask,
1160 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1163 /******************************************************************************
1164 * RtlAddAccessAllowedAceEx [NTDLL.@]
1166 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1168 IN DWORD dwAceRevision,
1170 IN DWORD AccessMask,
1173 TRACE("(%p,0x%08lx,0x%08lx,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1175 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1176 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1179 /******************************************************************************
1180 * RtlAddAccessDeniedAce [NTDLL.@]
1182 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1184 IN DWORD dwAceRevision,
1185 IN DWORD AccessMask,
1188 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1191 /******************************************************************************
1192 * RtlAddAccessDeniedAceEx [NTDLL.@]
1194 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1196 IN DWORD dwAceRevision,
1198 IN DWORD AccessMask,
1201 TRACE("(%p,0x%08lx,0x%08lx,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1203 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1204 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1207 /**************************************************************************
1208 * RtlAddAuditAccessAce [NTDLL.@]
1210 NTSTATUS WINAPI RtlAddAuditAccessAce(
1212 IN DWORD dwAceRevision,
1213 IN DWORD dwAccessMask,
1215 IN BOOL bAuditSuccess,
1216 IN BOOL bAuditFailure)
1218 DWORD dwAceFlags = 0;
1220 TRACE("(%p,%ld,%ld,%p,%u,%u)\n",pAcl,dwAceRevision,dwAccessMask,
1221 pSid,bAuditSuccess,bAuditFailure);
1224 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1227 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1229 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1230 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1233 /******************************************************************************
1234 * RtlValidAcl [NTDLL.@]
1236 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1239 TRACE("(%p)\n", pAcl);
1246 if (pAcl->AclRevision != ACL_REVISION)
1250 ace = (PACE_HEADER)(pAcl+1);
1252 for (i=0;i<=pAcl->AceCount;i++)
1254 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1259 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1265 WARN("(%p): invalid pointer!\n", pAcl);
1272 /******************************************************************************
1273 * RtlGetAce [NTDLL.@]
1275 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1279 TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1281 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1282 return STATUS_INVALID_PARAMETER;
1284 ace = (PACE_HEADER)(pAcl + 1);
1285 for (;dwAceIndex;dwAceIndex--)
1286 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1288 *pAce = (LPVOID) ace;
1290 return STATUS_SUCCESS;
1297 /******************************************************************************
1298 * RtlAdjustPrivilege [NTDLL.@]
1300 * Enables or disables a privilege from the calling thread or process.
1303 * Privilege [I] Privilege index to change.
1304 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1305 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1306 * Enabled [O] Whether privilege was previously enabled or disabled.
1309 * Success: STATUS_SUCCESS.
1310 * Failure: NTSTATUS code.
1313 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1317 RtlAdjustPrivilege(ULONG Privilege,
1319 BOOLEAN CurrentThread,
1322 TOKEN_PRIVILEGES NewState;
1323 TOKEN_PRIVILEGES OldState;
1328 TRACE("(%ld, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1329 CurrentThread ? "TRUE" : "FALSE", Enabled);
1333 Status = NtOpenThreadToken(GetCurrentThread(),
1334 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1340 Status = NtOpenProcessToken(GetCurrentProcess(),
1341 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1345 if (!NT_SUCCESS(Status))
1347 WARN("Retrieving token handle failed (Status %lx)\n", Status);
1351 OldState.PrivilegeCount = 1;
1353 NewState.PrivilegeCount = 1;
1354 NewState.Privileges[0].Luid.LowPart = Privilege;
1355 NewState.Privileges[0].Luid.HighPart = 0;
1356 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1358 Status = NtAdjustPrivilegesToken(TokenHandle,
1361 sizeof(TOKEN_PRIVILEGES),
1364 NtClose (TokenHandle);
1365 if (Status == STATUS_NOT_ALL_ASSIGNED)
1367 TRACE("Failed to assign all privileges\n");
1368 return STATUS_PRIVILEGE_NOT_HELD;
1370 if (!NT_SUCCESS(Status))
1372 WARN("NtAdjustPrivilegesToken() failed (Status %lx)\n", Status);
1376 if (OldState.PrivilegeCount == 0)
1379 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1381 return STATUS_SUCCESS;
1384 /******************************************************************************
1385 * RtlImpersonateSelf [NTDLL.@]
1387 * Makes an impersonation token that represents the process user and assigns
1388 * to the current thread.
1391 * ImpersonationLevel [I] Level at which to impersonate.
1394 * Success: STATUS_SUCCESS.
1395 * Failure: NTSTATUS code.
1398 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1401 OBJECT_ATTRIBUTES ObjectAttributes;
1402 HANDLE ProcessToken;
1403 HANDLE ImpersonationToken;
1405 TRACE("(%08x)\n", ImpersonationLevel);
1407 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1409 if (Status != STATUS_SUCCESS)
1412 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1414 Status = NtDuplicateToken( ProcessToken,
1419 &ImpersonationToken );
1420 if (Status != STATUS_SUCCESS)
1422 NtClose( ProcessToken );
1426 Status = NtSetInformationThread( GetCurrentThread(),
1427 ThreadImpersonationToken,
1428 &ImpersonationToken,
1429 sizeof(ImpersonationToken) );
1431 NtClose( ImpersonationToken );
1432 NtClose( ProcessToken );
1437 /******************************************************************************
1438 * NtAccessCheck [NTDLL.@]
1439 * ZwAccessCheck [NTDLL.@]
1441 * Checks that a user represented by a token is allowed to access an object
1442 * represented by a security descriptor.
1445 * SecurityDescriptor [I] The security descriptor of the object to check.
1446 * ClientToken [I] Token of the user accessing the object.
1447 * DesiredAccess [I] The desired access to the object.
1448 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1449 * PrivilegeSet [I/O] Privileges used during the access check.
1450 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1451 * GrantedAccess [O] The actual access rights granted.
1452 * AccessStatus [O] The status of the access check.
1458 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1459 * the maximum access rights allowed by the SD and returns them in
1461 * The SecurityDescriptor must have a valid owner and groups present,
1462 * otherwise the function will fail.
1466 PSECURITY_DESCRIPTOR SecurityDescriptor,
1468 ACCESS_MASK DesiredAccess,
1469 PGENERIC_MAPPING GenericMapping,
1470 PPRIVILEGE_SET PrivilegeSet,
1471 PULONG ReturnLength,
1472 PULONG GrantedAccess,
1473 NTSTATUS *AccessStatus)
1477 TRACE("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1478 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1479 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1481 SERVER_START_REQ( access_check )
1483 struct security_descriptor sd;
1488 BOOLEAN defaulted, present;
1490 SECURITY_DESCRIPTOR_CONTROL control;
1492 req->handle = ClientToken;
1493 req->desired_access = DesiredAccess;
1494 req->mapping_read = GenericMapping->GenericRead;
1495 req->mapping_write = GenericMapping->GenericWrite;
1496 req->mapping_execute = GenericMapping->GenericExecute;
1497 req->mapping_all = GenericMapping->GenericAll;
1499 /* marshal security descriptor */
1500 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1501 sd.control = control & ~SE_SELF_RELATIVE;
1502 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1503 sd.owner_len = RtlLengthSid( owner );
1504 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1505 sd.group_len = RtlLengthSid( group );
1506 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1507 sd.sacl_len = (present ? sacl->AclSize : 0);
1508 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1509 sd.dacl_len = (present ? dacl->AclSize : 0);
1511 wine_server_add_data( req, &sd, sizeof(sd) );
1512 wine_server_add_data( req, owner, sd.owner_len );
1513 wine_server_add_data( req, group, sd.group_len );
1514 wine_server_add_data( req, sacl, sd.sacl_len );
1515 wine_server_add_data( req, dacl, sd.dacl_len );
1517 wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1519 status = wine_server_call( req );
1521 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1522 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1524 if (status == STATUS_SUCCESS)
1525 *AccessStatus = reply->access_status;
1526 *GrantedAccess = reply->access_granted;
1533 /******************************************************************************
1534 * NtSetSecurityObject [NTDLL.@]
1537 NtSetSecurityObject(
1539 IN SECURITY_INFORMATION SecurityInformation,
1540 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1542 FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1543 return STATUS_SUCCESS;
1546 /******************************************************************************
1547 * RtlConvertSidToUnicodeString (NTDLL.@)
1549 * The returned SID is used to access the USER registry hive usually
1551 * the native function returns something like
1552 * "S-1-5-21-0000000000-000000000-0000000000-500";
1554 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1555 PUNICODE_STRING String,
1557 BOOLEAN AllocateString)
1559 static const WCHAR formatW[] = {'-','%','u',0};
1560 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1562 const SID *sid = (const SID *)pSid;
1566 p += sprintfW( p, formatW, sid->Revision );
1567 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1568 sid->IdentifierAuthority.Value[4] ),
1569 MAKEWORD( sid->IdentifierAuthority.Value[3],
1570 sid->IdentifierAuthority.Value[2] )));
1571 for (i = 0; i < sid->SubAuthorityCount; i++)
1572 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1574 len = (p + 1 - buffer) * sizeof(WCHAR);
1576 String->Length = len - sizeof(WCHAR);
1579 String->MaximumLength = len;
1580 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1581 return STATUS_NO_MEMORY;
1583 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1585 memcpy( String->Buffer, buffer, len );
1586 return STATUS_SUCCESS;
1589 /******************************************************************************
1590 * RtlQueryInformationAcl (NTDLL.@)
1592 NTSTATUS WINAPI RtlQueryInformationAcl(
1594 LPVOID pAclInformation,
1595 DWORD nAclInformationLength,
1596 ACL_INFORMATION_CLASS dwAclInformationClass)
1598 NTSTATUS status = STATUS_SUCCESS;
1600 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1601 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1603 switch (dwAclInformationClass)
1605 case AclRevisionInformation:
1607 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1609 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1610 status = STATUS_INVALID_PARAMETER;
1612 paclrev->AclRevision = pAcl->AclRevision;
1617 case AclSizeInformation:
1619 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1621 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1622 status = STATUS_INVALID_PARAMETER;
1628 paclsize->AceCount = pAcl->AceCount;
1630 paclsize->AclBytesInUse = 0;
1631 ace = (PACE_HEADER) (pAcl + 1);
1633 for (i = 0; i < pAcl->AceCount; i++)
1635 paclsize->AclBytesInUse += ace->AceSize;
1636 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1639 if (pAcl->AclSize < paclsize->AclBytesInUse)
1641 WARN("Acl has %ld bytes free\n", paclsize->AclBytesFree);
1642 paclsize->AclBytesFree = 0;
1643 paclsize->AclBytesInUse = pAcl->AclSize;
1646 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1653 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1654 status = STATUS_INVALID_PARAMETER;