4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
36 #define WIN32_NO_STATUS
38 #include "wine/exception.h"
39 #include "ntdll_misc.h"
40 #include "wine/library.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
46 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
48 /* helper function to copy an ACL */
49 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
53 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
56 size = ((ACL *)pSourceAcl)->AclSize;
57 if (nDestinationAclLength < size)
60 memmove(pDestinationAcl, pSourceAcl, size);
64 /* generically adds an ACE to an ACL */
65 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
66 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
68 ACE_HEADER *pAceHeader;
74 if (!RtlValidSid(pSid))
75 return STATUS_INVALID_SID;
77 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
78 return STATUS_REVISION_MISMATCH;
80 if (!RtlValidAcl(pAcl))
81 return STATUS_INVALID_ACL;
83 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
84 return STATUS_INVALID_ACL;
87 return STATUS_ALLOTTED_SPACE_EXCEEDED;
89 /* calculate generic size of the ACE */
90 dwLengthSid = RtlLengthSid(pSid);
91 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
92 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
93 return STATUS_ALLOTTED_SPACE_EXCEEDED;
95 /* fill the new ACE */
96 pAceHeader->AceType = dwAceType;
97 pAceHeader->AceFlags = dwAceFlags;
98 pAceHeader->AceSize = dwAceSize;
100 /* skip past the ACE_HEADER of the ACE */
101 pAccessMask = (DWORD *)(pAceHeader + 1);
102 *pAccessMask = dwAccessMask;
104 /* skip past ACE->Mask */
105 pSidStart = pAccessMask + 1;
106 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
108 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
111 return STATUS_SUCCESS;
118 /******************************************************************************
119 * RtlAllocateAndInitializeSid [NTDLL.@]
122 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
123 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
124 BYTE nSubAuthorityCount,
125 DWORD nSubAuthority0, DWORD nSubAuthority1,
126 DWORD nSubAuthority2, DWORD nSubAuthority3,
127 DWORD nSubAuthority4, DWORD nSubAuthority5,
128 DWORD nSubAuthority6, DWORD nSubAuthority7,
133 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
134 pIdentifierAuthority,nSubAuthorityCount,
135 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
136 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
138 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
140 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
141 RtlLengthRequiredSid(nSubAuthorityCount))))
142 return STATUS_NO_MEMORY;
144 tmp_sid->Revision = SID_REVISION;
146 if (pIdentifierAuthority)
147 memcpy(&tmp_sid->IdentifierAuthority, pIdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY));
148 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
150 switch( nSubAuthorityCount )
152 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
153 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
154 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
155 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
156 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
157 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
158 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
159 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
163 return STATUS_SUCCESS;
166 /******************************************************************************
167 * RtlEqualSid [NTDLL.@]
169 * Determine if two SIDs are equal.
172 * pSid1 [I] Source SID
173 * pSid2 [I] SID to compare with
176 * TRUE, if pSid1 is equal to pSid2,
179 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
181 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
184 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
187 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
193 /******************************************************************************
194 * RtlEqualPrefixSid [NTDLL.@]
196 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
198 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
201 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
204 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
211 /******************************************************************************
212 * RtlFreeSid [NTDLL.@]
214 * Free the resources used by a SID.
217 * pSid [I] SID to Free.
222 DWORD WINAPI RtlFreeSid(PSID pSid)
224 TRACE("(%p)\n", pSid);
225 RtlFreeHeap( GetProcessHeap(), 0, pSid );
226 return STATUS_SUCCESS;
229 /**************************************************************************
230 * RtlLengthRequiredSid [NTDLL.@]
232 * Determine the amount of memory a SID will use
235 * nrofsubauths [I] Number of Sub Authorities in the SID.
238 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
240 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
242 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
245 /**************************************************************************
246 * RtlLengthSid [NTDLL.@]
248 * Determine the amount of memory a SID is using
251 * pSid [I] SID to get the size of.
254 * The size, in bytes, of pSid.
256 DWORD WINAPI RtlLengthSid(PSID pSid)
258 TRACE("sid=%p\n",pSid);
260 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
263 /**************************************************************************
264 * RtlInitializeSid [NTDLL.@]
269 * pSid [I] SID to initialise
270 * pIdentifierAuthority [I] Identifier Authority
271 * nSubAuthorityCount [I] Number of Sub Authorities
274 * Success: TRUE. pSid is initialised with the details given.
275 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
277 BOOL WINAPI RtlInitializeSid(
279 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
280 BYTE nSubAuthorityCount)
285 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
288 pisid->Revision = SID_REVISION;
289 pisid->SubAuthorityCount = nSubAuthorityCount;
290 if (pIdentifierAuthority)
291 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
293 for (i = 0; i < nSubAuthorityCount; i++)
294 *RtlSubAuthoritySid(pSid, i) = 0;
299 /**************************************************************************
300 * RtlSubAuthoritySid [NTDLL.@]
302 * Return the Sub Authority of a SID
305 * pSid [I] SID to get the Sub Authority from.
306 * nSubAuthority [I] Sub Authority number.
309 * A pointer to The Sub Authority value of pSid.
311 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
313 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
316 /**************************************************************************
317 * RtlIdentifierAuthoritySid [NTDLL.@]
319 * Return the Identifier Authority of a SID.
322 * pSid [I] SID to get the Identifier Authority from.
325 * A pointer to the Identifier Authority value of pSid.
327 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
329 return &(((SID*)pSid)->IdentifierAuthority);
332 /**************************************************************************
333 * RtlSubAuthorityCountSid [NTDLL.@]
335 * Get the number of Sub Authorities in a SID.
338 * pSid [I] SID to get the count from.
341 * A pointer to the Sub Authority count of pSid.
343 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
345 return &(((SID*)pSid)->SubAuthorityCount);
348 /**************************************************************************
349 * RtlCopySid [NTDLL.@]
351 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
353 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
354 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
357 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
360 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
363 /******************************************************************************
364 * RtlValidSid [NTDLL.@]
366 * Determine if a SID is valid.
369 * pSid [I] SID to check
372 * TRUE if pSid is valid,
375 BOOLEAN WINAPI RtlValidSid( PSID pSid )
381 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
382 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
389 WARN("(%p): invalid pointer!\n", pSid);
398 * security descriptor functions
401 /**************************************************************************
402 * RtlCreateSecurityDescriptor [NTDLL.@]
404 * Initialise a SECURITY_DESCRIPTOR.
407 * lpsd [O] Descriptor to initialise.
408 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
411 * Success: STATUS_SUCCESS.
412 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
414 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
415 PSECURITY_DESCRIPTOR lpsd,
418 if (rev!=SECURITY_DESCRIPTOR_REVISION)
419 return STATUS_UNKNOWN_REVISION;
420 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
421 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
422 return STATUS_SUCCESS;
425 /**************************************************************************
426 * RtlCopySecurityDescriptor [NTDLL.@]
428 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
431 * pSourceSD [O] SD to copy from.
432 * pDestinationSD [I] Destination SD.
435 * Success: STATUS_SUCCESS.
436 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
438 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
440 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
441 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
444 BOOLEAN defaulted, present;
446 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
448 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
449 return STATUS_UNKNOWN_REVISION;
451 /* copy initial data */
452 destSD->Revision = srcSD->Revision;
453 destSD->Sbz1 = srcSD->Sbz1;
454 destSD->Control = srcSD->Control;
457 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
458 length = RtlLengthSid(Owner);
462 destSD->Owner = srcSD->Owner;
463 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner);
467 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
468 RtlCopySid(length, destSD->Owner, Owner);
472 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
473 length = RtlLengthSid(Group);
477 destSD->Group = srcSD->Group;
478 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
482 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
483 RtlCopySid(length, destSD->Group, Group);
487 if (srcSD->Control & SE_DACL_PRESENT)
489 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
490 length = Dacl->AclSize;
494 destSD->Dacl = srcSD->Dacl;
495 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl);
499 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
500 copy_acl(length, destSD->Dacl, Dacl);
505 if (srcSD->Control & SE_SACL_PRESENT)
507 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
508 length = Sacl->AclSize;
512 destSD->Sacl = srcSD->Sacl;
513 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl);
517 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
518 copy_acl(length, destSD->Sacl, Sacl);
522 return STATUS_SUCCESS;
525 /**************************************************************************
526 * RtlValidSecurityDescriptor [NTDLL.@]
528 * Determine if a SECURITY_DESCRIPTOR is valid.
531 * SecurityDescriptor [I] Descriptor to check.
534 * Success: STATUS_SUCCESS.
535 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
537 NTSTATUS WINAPI RtlValidSecurityDescriptor(
538 PSECURITY_DESCRIPTOR SecurityDescriptor)
540 if ( ! SecurityDescriptor )
541 return STATUS_INVALID_SECURITY_DESCR;
542 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
543 return STATUS_UNKNOWN_REVISION;
545 return STATUS_SUCCESS;
548 /**************************************************************************
549 * RtlLengthSecurityDescriptor [NTDLL.@]
551 ULONG WINAPI RtlLengthSecurityDescriptor(
552 PSECURITY_DESCRIPTOR pSecurityDescriptor)
554 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
555 ULONG_PTR offset = 0;
556 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
561 if ( lpsd->Control & SE_SELF_RELATIVE)
562 offset = (ULONG_PTR) lpsd;
564 if ( lpsd->Owner != NULL )
565 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
567 if ( lpsd->Group != NULL )
568 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
570 if ( (lpsd->Control & SE_SACL_PRESENT) &&
572 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
574 if ( (lpsd->Control & SE_DACL_PRESENT) &&
576 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
581 /******************************************************************************
582 * RtlGetDaclSecurityDescriptor [NTDLL.@]
585 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
586 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
587 OUT PBOOLEAN lpbDaclPresent,
589 OUT PBOOLEAN lpbDaclDefaulted)
591 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
593 TRACE("(%p,%p,%p,%p)\n",
594 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
596 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
597 return STATUS_UNKNOWN_REVISION ;
599 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
601 if ( SE_SELF_RELATIVE & lpsd->Control)
602 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Dacl);
606 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
609 return STATUS_SUCCESS;
612 /**************************************************************************
613 * RtlSetDaclSecurityDescriptor [NTDLL.@]
615 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
616 PSECURITY_DESCRIPTOR pSecurityDescriptor,
619 BOOLEAN dacldefaulted )
621 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
623 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
624 return STATUS_UNKNOWN_REVISION;
625 if (lpsd->Control & SE_SELF_RELATIVE)
626 return STATUS_INVALID_SECURITY_DESCR;
630 lpsd->Control &= ~SE_DACL_PRESENT;
631 return STATUS_SUCCESS;
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_PTR)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->Control & SE_OWNER_DEFAULTED )
718 *OwnerDefaulted = TRUE;
720 *OwnerDefaulted = FALSE;
722 if (lpsd->Owner != NULL)
724 if (lpsd->Control & SE_SELF_RELATIVE)
725 *Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner);
727 *Owner = lpsd->Owner;
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->Control & SE_GROUP_DEFAULTED )
796 *GroupDefaulted = TRUE;
798 *GroupDefaulted = FALSE;
800 if (lpsd->Group != NULL)
802 if (lpsd->Control & SE_SELF_RELATIVE)
803 *Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group);
805 *Group = lpsd->Group;
810 return STATUS_SUCCESS;
813 /**************************************************************************
814 * RtlMakeSelfRelativeSD [NTDLL.@]
816 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
817 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
818 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
819 IN OUT LPDWORD lpdwBufferLength)
823 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
824 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
826 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
827 lpdwBufferLength ? *lpdwBufferLength: -1);
829 if (!lpdwBufferLength || !pAbs)
830 return STATUS_INVALID_PARAMETER;
832 length = RtlLengthSecurityDescriptor(pAbs);
833 if (*lpdwBufferLength < length)
835 *lpdwBufferLength = length;
836 return STATUS_BUFFER_TOO_SMALL;
840 return STATUS_INVALID_PARAMETER;
842 if (pAbs->Control & SE_SELF_RELATIVE)
844 memcpy(pRel, pAbs, length);
845 return STATUS_SUCCESS;
848 pRel->Revision = pAbs->Revision;
849 pRel->Sbz1 = pAbs->Sbz1;
850 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
852 offsetRel = sizeof(SECURITY_DESCRIPTOR);
855 pRel->Owner = (PSID) offsetRel;
856 length = RtlLengthSid(pAbs->Owner);
857 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);
879 pRel->Sacl = (PACL) offsetRel;
880 length = pAbs->Sacl->AclSize;
881 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
891 pRel->Dacl = (PACL) offsetRel;
892 length = pAbs->Dacl->AclSize;
893 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
900 return STATUS_SUCCESS;
904 /**************************************************************************
905 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
907 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
908 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
909 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
910 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
912 OUT LPDWORD lpdwDaclSize,
914 OUT LPDWORD lpdwSaclSize,
916 OUT LPDWORD lpdwOwnerSize,
917 OUT PSID pPrimaryGroup,
918 OUT LPDWORD lpdwPrimaryGroupSize)
920 NTSTATUS status = STATUS_SUCCESS;
921 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
922 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
925 !lpdwAbsoluteSecurityDescriptorSize ||
929 !lpdwPrimaryGroupSize ||
930 ~pRel->Control & SE_SELF_RELATIVE)
931 return STATUS_INVALID_PARAMETER;
933 /* Confirm buffers are sufficiently large */
934 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
936 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
937 status = STATUS_BUFFER_TOO_SMALL;
940 if (pRel->Control & SE_DACL_PRESENT &&
941 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize)
943 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize;
944 status = STATUS_BUFFER_TOO_SMALL;
947 if (pRel->Control & SE_SACL_PRESENT &&
948 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize)
950 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize;
951 status = STATUS_BUFFER_TOO_SMALL;
955 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)))
957 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel));
958 status = STATUS_BUFFER_TOO_SMALL;
962 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)))
964 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel));
965 status = STATUS_BUFFER_TOO_SMALL;
968 if (status != STATUS_SUCCESS)
971 /* Copy structures, and clear the ones we don't set */
972 pAbs->Revision = pRel->Revision;
973 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
979 if (pRel->Control & SE_SACL_PRESENT)
981 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel);
983 memcpy(pSacl, pAcl, pAcl->AclSize);
987 if (pRel->Control & SE_DACL_PRESENT)
989 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel);
990 memcpy(pDacl, pAcl, pAcl->AclSize);
996 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel);
997 memcpy(pOwner, psid, RtlLengthSid(psid));
998 pAbs->Owner = pOwner;
1003 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel);
1004 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1005 pAbs->Group = pPrimaryGroup;
1011 /******************************************************************************
1012 * RtlGetControlSecurityDescriptor (NTDLL.@)
1014 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1015 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1016 PSECURITY_DESCRIPTOR_CONTROL pControl,
1017 LPDWORD lpdwRevision)
1019 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1021 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1023 *lpdwRevision = lpsd->Revision;
1025 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1026 return STATUS_UNKNOWN_REVISION;
1028 *pControl = lpsd->Control;
1030 return STATUS_SUCCESS;
1034 /**************************************************************************
1035 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1037 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1038 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1039 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1040 PULONG BufferLength)
1042 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1044 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1045 SelfRelativeSecurityDescriptor, BufferLength);
1047 if (abs->Control & SE_SELF_RELATIVE)
1048 return STATUS_BAD_DESCRIPTOR_FORMAT;
1050 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1051 SelfRelativeSecurityDescriptor, BufferLength);
1056 * access control list's
1059 /**************************************************************************
1060 * RtlCreateAcl [NTDLL.@]
1063 * This should return NTSTATUS
1065 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1067 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1069 if (rev!=ACL_REVISION)
1070 return STATUS_INVALID_PARAMETER;
1071 if (size<sizeof(ACL))
1072 return STATUS_BUFFER_TOO_SMALL;
1074 return STATUS_INVALID_PARAMETER;
1076 memset(acl,'\0',sizeof(ACL));
1077 acl->AclRevision = rev;
1078 acl->AclSize = size;
1080 return STATUS_SUCCESS;
1083 /**************************************************************************
1084 * RtlFirstFreeAce [NTDLL.@]
1085 * looks for the AceCount+1 ACE, and if it is still within the alloced
1086 * ACL, return a pointer to it
1088 BOOLEAN WINAPI RtlFirstFreeAce(
1096 ace = (PACE_HEADER)(acl+1);
1097 for (i=0;i<acl->AceCount;i++) {
1098 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1100 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1102 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1108 /**************************************************************************
1109 * RtlAddAce [NTDLL.@]
1111 NTSTATUS WINAPI RtlAddAce(
1115 PACE_HEADER acestart,
1118 PACE_HEADER ace,targetace;
1121 if (acl->AclRevision != ACL_REVISION)
1122 return STATUS_INVALID_PARAMETER;
1123 if (!RtlFirstFreeAce(acl,&targetace))
1124 return STATUS_INVALID_PARAMETER;
1125 nrofaces=0;ace=acestart;
1126 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1128 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1130 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1131 return STATUS_INVALID_PARAMETER;
1132 memcpy((LPBYTE)targetace,acestart,acelen);
1133 acl->AceCount+=nrofaces;
1134 return STATUS_SUCCESS;
1137 /**************************************************************************
1138 * RtlDeleteAce [NTDLL.@]
1140 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1145 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1147 if (STATUS_SUCCESS == status)
1152 /* skip over the ACE we are deleting */
1153 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1156 /* calculate the length of the rest */
1157 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1159 len += pcAce->AceSize;
1160 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1163 /* slide them all backwards */
1164 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1168 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1173 /******************************************************************************
1174 * RtlAddAccessAllowedAce [NTDLL.@]
1176 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1178 IN DWORD dwAceRevision,
1179 IN DWORD AccessMask,
1182 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1185 /******************************************************************************
1186 * RtlAddAccessAllowedAceEx [NTDLL.@]
1188 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1190 IN DWORD dwAceRevision,
1192 IN DWORD AccessMask,
1195 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1197 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1198 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1201 /******************************************************************************
1202 * RtlAddAccessDeniedAce [NTDLL.@]
1204 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1206 IN DWORD dwAceRevision,
1207 IN DWORD AccessMask,
1210 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1213 /******************************************************************************
1214 * RtlAddAccessDeniedAceEx [NTDLL.@]
1216 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1218 IN DWORD dwAceRevision,
1220 IN DWORD AccessMask,
1223 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1225 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1226 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1229 /**************************************************************************
1230 * RtlAddAuditAccessAce [NTDLL.@]
1232 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1234 IN DWORD dwAceRevision,
1235 IN DWORD dwAceFlags,
1236 IN DWORD dwAccessMask,
1238 IN BOOL bAuditSuccess,
1239 IN BOOL bAuditFailure)
1241 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1242 pSid,bAuditSuccess,bAuditFailure);
1245 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1248 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1250 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1251 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1254 /**************************************************************************
1255 * RtlAddAuditAccessAce [NTDLL.@]
1257 NTSTATUS WINAPI RtlAddAuditAccessAce(
1259 IN DWORD dwAceRevision,
1260 IN DWORD dwAccessMask,
1262 IN BOOL bAuditSuccess,
1263 IN BOOL bAuditFailure)
1265 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1268 /******************************************************************************
1269 * RtlValidAcl [NTDLL.@]
1271 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1274 TRACE("(%p)\n", pAcl);
1281 if (pAcl->AclRevision != ACL_REVISION)
1285 ace = (PACE_HEADER)(pAcl+1);
1287 for (i=0;i<=pAcl->AceCount;i++)
1289 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1294 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1300 WARN("(%p): invalid pointer!\n", pAcl);
1307 /******************************************************************************
1308 * RtlGetAce [NTDLL.@]
1310 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1314 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1316 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1317 return STATUS_INVALID_PARAMETER;
1319 ace = (PACE_HEADER)(pAcl + 1);
1320 for (;dwAceIndex;dwAceIndex--)
1321 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1323 *pAce = (LPVOID) ace;
1325 return STATUS_SUCCESS;
1332 /******************************************************************************
1333 * RtlAdjustPrivilege [NTDLL.@]
1335 * Enables or disables a privilege from the calling thread or process.
1338 * Privilege [I] Privilege index to change.
1339 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1340 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1341 * Enabled [O] Whether privilege was previously enabled or disabled.
1344 * Success: STATUS_SUCCESS.
1345 * Failure: NTSTATUS code.
1348 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1352 RtlAdjustPrivilege(ULONG Privilege,
1354 BOOLEAN CurrentThread,
1357 TOKEN_PRIVILEGES NewState;
1358 TOKEN_PRIVILEGES OldState;
1363 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1364 CurrentThread ? "TRUE" : "FALSE", Enabled);
1368 Status = NtOpenThreadToken(GetCurrentThread(),
1369 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1375 Status = NtOpenProcessToken(GetCurrentProcess(),
1376 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1380 if (!NT_SUCCESS(Status))
1382 WARN("Retrieving token handle failed (Status %x)\n", Status);
1386 OldState.PrivilegeCount = 1;
1388 NewState.PrivilegeCount = 1;
1389 NewState.Privileges[0].Luid.LowPart = Privilege;
1390 NewState.Privileges[0].Luid.HighPart = 0;
1391 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1393 Status = NtAdjustPrivilegesToken(TokenHandle,
1396 sizeof(TOKEN_PRIVILEGES),
1399 NtClose (TokenHandle);
1400 if (Status == STATUS_NOT_ALL_ASSIGNED)
1402 TRACE("Failed to assign all privileges\n");
1403 return STATUS_PRIVILEGE_NOT_HELD;
1405 if (!NT_SUCCESS(Status))
1407 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1411 if (OldState.PrivilegeCount == 0)
1414 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1416 return STATUS_SUCCESS;
1419 /******************************************************************************
1420 * RtlImpersonateSelf [NTDLL.@]
1422 * Makes an impersonation token that represents the process user and assigns
1423 * to the current thread.
1426 * ImpersonationLevel [I] Level at which to impersonate.
1429 * Success: STATUS_SUCCESS.
1430 * Failure: NTSTATUS code.
1433 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1436 OBJECT_ATTRIBUTES ObjectAttributes;
1437 HANDLE ProcessToken;
1438 HANDLE ImpersonationToken;
1440 TRACE("(%08x)\n", ImpersonationLevel);
1442 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1444 if (Status != STATUS_SUCCESS)
1447 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1449 Status = NtDuplicateToken( ProcessToken,
1454 &ImpersonationToken );
1455 if (Status != STATUS_SUCCESS)
1457 NtClose( ProcessToken );
1461 Status = NtSetInformationThread( GetCurrentThread(),
1462 ThreadImpersonationToken,
1463 &ImpersonationToken,
1464 sizeof(ImpersonationToken) );
1466 NtClose( ImpersonationToken );
1467 NtClose( ProcessToken );
1472 /******************************************************************************
1473 * NtAccessCheck [NTDLL.@]
1474 * ZwAccessCheck [NTDLL.@]
1476 * Checks that a user represented by a token is allowed to access an object
1477 * represented by a security descriptor.
1480 * SecurityDescriptor [I] The security descriptor of the object to check.
1481 * ClientToken [I] Token of the user accessing the object.
1482 * DesiredAccess [I] The desired access to the object.
1483 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1484 * PrivilegeSet [I/O] Privileges used during the access check.
1485 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1486 * GrantedAccess [O] The actual access rights granted.
1487 * AccessStatus [O] The status of the access check.
1493 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1494 * the maximum access rights allowed by the SD and returns them in
1496 * The SecurityDescriptor must have a valid owner and groups present,
1497 * otherwise the function will fail.
1501 PSECURITY_DESCRIPTOR SecurityDescriptor,
1503 ACCESS_MASK DesiredAccess,
1504 PGENERIC_MAPPING GenericMapping,
1505 PPRIVILEGE_SET PrivilegeSet,
1506 PULONG ReturnLength,
1507 PULONG GrantedAccess,
1508 NTSTATUS *AccessStatus)
1512 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1513 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1514 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1516 SERVER_START_REQ( access_check )
1518 struct security_descriptor sd;
1523 BOOLEAN defaulted, present;
1525 SECURITY_DESCRIPTOR_CONTROL control;
1527 req->handle = ClientToken;
1528 req->desired_access = DesiredAccess;
1529 req->mapping_read = GenericMapping->GenericRead;
1530 req->mapping_write = GenericMapping->GenericWrite;
1531 req->mapping_execute = GenericMapping->GenericExecute;
1532 req->mapping_all = GenericMapping->GenericAll;
1534 /* marshal security descriptor */
1535 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1536 sd.control = control & ~SE_SELF_RELATIVE;
1537 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1538 sd.owner_len = RtlLengthSid( owner );
1539 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1540 sd.group_len = RtlLengthSid( group );
1541 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1542 sd.sacl_len = ((present && sacl) ? sacl->AclSize : 0);
1543 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1544 sd.dacl_len = ((present && dacl) ? dacl->AclSize : 0);
1546 wine_server_add_data( req, &sd, sizeof(sd) );
1547 wine_server_add_data( req, owner, sd.owner_len );
1548 wine_server_add_data( req, group, sd.group_len );
1549 wine_server_add_data( req, sacl, sd.sacl_len );
1550 wine_server_add_data( req, dacl, sd.dacl_len );
1552 wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1554 status = wine_server_call( req );
1556 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1557 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1559 if (status == STATUS_SUCCESS)
1561 *AccessStatus = reply->access_status;
1562 *GrantedAccess = reply->access_granted;
1570 /******************************************************************************
1571 * NtSetSecurityObject [NTDLL.@]
1572 * ZwSetSecurityObject [NTDLL.@]
1574 * Sets specified parts of the object's security descriptor.
1577 * Handle [I] Handle to the object to change security descriptor of.
1578 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1579 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1585 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1586 SECURITY_INFORMATION SecurityInformation,
1587 PSECURITY_DESCRIPTOR SecurityDescriptor)
1590 struct security_descriptor sd;
1591 PACL dacl = NULL, sacl = NULL;
1592 PSID owner = NULL, group = NULL;
1593 BOOLEAN defaulted, present;
1595 SECURITY_DESCRIPTOR_CONTROL control;
1597 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1599 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1601 memset( &sd, 0, sizeof(sd) );
1602 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1603 if (status != STATUS_SUCCESS) return status;
1604 sd.control = control & ~SE_SELF_RELATIVE;
1606 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1608 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1609 if (status != STATUS_SUCCESS) return status;
1610 if (!(sd.owner_len = RtlLengthSid( owner )))
1611 return STATUS_INVALID_SECURITY_DESCR;
1614 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1616 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1617 if (status != STATUS_SUCCESS) return status;
1618 if (!(sd.group_len = RtlLengthSid( group )))
1619 return STATUS_INVALID_SECURITY_DESCR;
1622 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1624 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1625 if (status != STATUS_SUCCESS) return status;
1626 sd.sacl_len = (sacl && present) ? sacl->AclSize : 0;
1627 sd.control |= SE_SACL_PRESENT;
1630 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1632 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1633 if (status != STATUS_SUCCESS) return status;
1634 sd.dacl_len = (dacl && present) ? dacl->AclSize : 0;
1635 sd.control |= SE_DACL_PRESENT;
1638 SERVER_START_REQ( set_security_object )
1640 req->handle = Handle;
1641 req->security_info = SecurityInformation;
1643 wine_server_add_data( req, &sd, sizeof(sd) );
1644 wine_server_add_data( req, owner, sd.owner_len );
1645 wine_server_add_data( req, group, sd.group_len );
1646 wine_server_add_data( req, sacl, sd.sacl_len );
1647 wine_server_add_data( req, dacl, sd.dacl_len );
1648 status = wine_server_call( req );
1655 /******************************************************************************
1656 * RtlConvertSidToUnicodeString (NTDLL.@)
1658 * The returned SID is used to access the USER registry hive usually
1660 * the native function returns something like
1661 * "S-1-5-21-0000000000-000000000-0000000000-500";
1663 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1664 PUNICODE_STRING String,
1666 BOOLEAN AllocateString)
1668 static const WCHAR formatW[] = {'-','%','u',0};
1669 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1671 const SID *sid = (const SID *)pSid;
1675 p += sprintfW( p, formatW, sid->Revision );
1676 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1677 sid->IdentifierAuthority.Value[4] ),
1678 MAKEWORD( sid->IdentifierAuthority.Value[3],
1679 sid->IdentifierAuthority.Value[2] )));
1680 for (i = 0; i < sid->SubAuthorityCount; i++)
1681 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1683 len = (p + 1 - buffer) * sizeof(WCHAR);
1685 String->Length = len - sizeof(WCHAR);
1688 String->MaximumLength = len;
1689 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1690 return STATUS_NO_MEMORY;
1692 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1694 memcpy( String->Buffer, buffer, len );
1695 return STATUS_SUCCESS;
1698 /******************************************************************************
1699 * RtlQueryInformationAcl (NTDLL.@)
1701 NTSTATUS WINAPI RtlQueryInformationAcl(
1703 LPVOID pAclInformation,
1704 DWORD nAclInformationLength,
1705 ACL_INFORMATION_CLASS dwAclInformationClass)
1707 NTSTATUS status = STATUS_SUCCESS;
1709 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1710 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1712 switch (dwAclInformationClass)
1714 case AclRevisionInformation:
1716 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1718 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1719 status = STATUS_INVALID_PARAMETER;
1721 paclrev->AclRevision = pAcl->AclRevision;
1726 case AclSizeInformation:
1728 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1730 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1731 status = STATUS_INVALID_PARAMETER;
1737 paclsize->AceCount = pAcl->AceCount;
1739 paclsize->AclBytesInUse = 0;
1740 ace = (PACE_HEADER) (pAcl + 1);
1742 for (i = 0; i < pAcl->AceCount; i++)
1744 paclsize->AclBytesInUse += ace->AceSize;
1745 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1748 if (pAcl->AclSize < paclsize->AclBytesInUse)
1750 WARN("Acl has %d bytes free\n", paclsize->AclBytesFree);
1751 paclsize->AclBytesFree = 0;
1752 paclsize->AclBytesInUse = pAcl->AclSize;
1755 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1762 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1763 status = STATUS_INVALID_PARAMETER;