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 "ntdll_misc.h"
39 #include "wine/exception.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 retrieve active length of an ACL */
49 static size_t acl_bytesInUse(PACL pAcl)
52 size_t bytesInUse = sizeof(ACL);
53 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
54 for (i = 0; i < pAcl->AceCount; i++)
56 bytesInUse += ace->AceSize;
57 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
62 /* helper function to copy an ACL */
63 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
67 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
70 size = pSourceAcl->AclSize;
71 if (nDestinationAclLength < size)
74 memmove(pDestinationAcl, pSourceAcl, size);
78 /* generically adds an ACE to an ACL */
79 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
80 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
82 ACE_HEADER *pAceHeader;
88 if (!RtlValidSid(pSid))
89 return STATUS_INVALID_SID;
91 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
92 return STATUS_REVISION_MISMATCH;
94 if (!RtlValidAcl(pAcl))
95 return STATUS_INVALID_ACL;
97 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
98 return STATUS_INVALID_ACL;
101 return STATUS_ALLOTTED_SPACE_EXCEEDED;
103 /* calculate generic size of the ACE */
104 dwLengthSid = RtlLengthSid(pSid);
105 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
106 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
107 return STATUS_ALLOTTED_SPACE_EXCEEDED;
109 /* fill the new ACE */
110 pAceHeader->AceType = dwAceType;
111 pAceHeader->AceFlags = dwAceFlags;
112 pAceHeader->AceSize = dwAceSize;
114 /* skip past the ACE_HEADER of the ACE */
115 pAccessMask = (DWORD *)(pAceHeader + 1);
116 *pAccessMask = dwAccessMask;
118 /* skip past ACE->Mask */
119 pSidStart = pAccessMask + 1;
120 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
122 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
125 return STATUS_SUCCESS;
132 /******************************************************************************
133 * RtlAllocateAndInitializeSid [NTDLL.@]
136 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
137 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
138 BYTE nSubAuthorityCount,
139 DWORD nSubAuthority0, DWORD nSubAuthority1,
140 DWORD nSubAuthority2, DWORD nSubAuthority3,
141 DWORD nSubAuthority4, DWORD nSubAuthority5,
142 DWORD nSubAuthority6, DWORD nSubAuthority7,
147 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
148 pIdentifierAuthority,nSubAuthorityCount,
149 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
150 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
152 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
154 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
155 RtlLengthRequiredSid(nSubAuthorityCount))))
156 return STATUS_NO_MEMORY;
158 tmp_sid->Revision = SID_REVISION;
160 if (pIdentifierAuthority)
161 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
162 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
164 switch( nSubAuthorityCount )
166 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
167 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
168 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
169 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
170 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
171 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
172 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
173 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
177 return STATUS_SUCCESS;
180 /******************************************************************************
181 * RtlEqualSid [NTDLL.@]
183 * Determine if two SIDs are equal.
186 * pSid1 [I] Source SID
187 * pSid2 [I] SID to compare with
190 * TRUE, if pSid1 is equal to pSid2,
193 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
195 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
198 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
201 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
207 /******************************************************************************
208 * RtlEqualPrefixSid [NTDLL.@]
210 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
212 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
215 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
218 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
225 /******************************************************************************
226 * RtlFreeSid [NTDLL.@]
228 * Free the resources used by a SID.
231 * pSid [I] SID to Free.
236 DWORD WINAPI RtlFreeSid(PSID pSid)
238 TRACE("(%p)\n", pSid);
239 RtlFreeHeap( GetProcessHeap(), 0, pSid );
240 return STATUS_SUCCESS;
243 /**************************************************************************
244 * RtlLengthRequiredSid [NTDLL.@]
246 * Determine the amount of memory a SID will use
249 * nrofsubauths [I] Number of Sub Authorities in the SID.
252 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
254 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
256 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
259 /**************************************************************************
260 * RtlLengthSid [NTDLL.@]
262 * Determine the amount of memory a SID is using
265 * pSid [I] SID to get the size of.
268 * The size, in bytes, of pSid.
270 DWORD WINAPI RtlLengthSid(PSID pSid)
272 TRACE("sid=%p\n",pSid);
274 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
277 /**************************************************************************
278 * RtlInitializeSid [NTDLL.@]
283 * pSid [I] SID to initialise
284 * pIdentifierAuthority [I] Identifier Authority
285 * nSubAuthorityCount [I] Number of Sub Authorities
288 * Success: TRUE. pSid is initialised with the details given.
289 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
291 BOOL WINAPI RtlInitializeSid(
293 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
294 BYTE nSubAuthorityCount)
299 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
302 pisid->Revision = SID_REVISION;
303 pisid->SubAuthorityCount = nSubAuthorityCount;
304 if (pIdentifierAuthority)
305 pisid->IdentifierAuthority = *pIdentifierAuthority;
307 for (i = 0; i < nSubAuthorityCount; i++)
308 *RtlSubAuthoritySid(pSid, i) = 0;
313 /**************************************************************************
314 * RtlSubAuthoritySid [NTDLL.@]
316 * Return the Sub Authority of a SID
319 * pSid [I] SID to get the Sub Authority from.
320 * nSubAuthority [I] Sub Authority number.
323 * A pointer to The Sub Authority value of pSid.
325 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
327 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
330 /**************************************************************************
331 * RtlIdentifierAuthoritySid [NTDLL.@]
333 * Return the Identifier Authority of a SID.
336 * pSid [I] SID to get the Identifier Authority from.
339 * A pointer to the Identifier Authority value of pSid.
341 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
343 return &(((SID*)pSid)->IdentifierAuthority);
346 /**************************************************************************
347 * RtlSubAuthorityCountSid [NTDLL.@]
349 * Get the number of Sub Authorities in a SID.
352 * pSid [I] SID to get the count from.
355 * A pointer to the Sub Authority count of pSid.
357 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
359 return &(((SID*)pSid)->SubAuthorityCount);
362 /**************************************************************************
363 * RtlCopySid [NTDLL.@]
365 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
367 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
368 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
371 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
374 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
377 /******************************************************************************
378 * RtlValidSid [NTDLL.@]
380 * Determine if a SID is valid.
383 * pSid [I] SID to check
386 * TRUE if pSid is valid,
389 BOOLEAN WINAPI RtlValidSid( PSID pSid )
395 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
396 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
403 WARN("(%p): invalid pointer!\n", pSid);
412 * security descriptor functions
415 /**************************************************************************
416 * RtlCreateSecurityDescriptor [NTDLL.@]
418 * Initialise a SECURITY_DESCRIPTOR.
421 * lpsd [O] Descriptor to initialise.
422 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
425 * Success: STATUS_SUCCESS.
426 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
428 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
429 PSECURITY_DESCRIPTOR lpsd,
432 if (rev!=SECURITY_DESCRIPTOR_REVISION)
433 return STATUS_UNKNOWN_REVISION;
434 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
435 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
436 return STATUS_SUCCESS;
439 /**************************************************************************
440 * RtlCopySecurityDescriptor [NTDLL.@]
442 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
445 * pSourceSD [O] SD to copy from.
446 * pDestinationSD [I] Destination SD.
449 * Success: STATUS_SUCCESS.
450 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
452 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
454 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
455 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
458 BOOLEAN defaulted, present;
460 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
462 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
463 return STATUS_UNKNOWN_REVISION;
465 /* copy initial data */
466 destSD->Revision = srcSD->Revision;
467 destSD->Sbz1 = srcSD->Sbz1;
468 destSD->Control = srcSD->Control;
471 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
472 length = RtlLengthSid(Owner);
476 destSD->Owner = srcSD->Owner;
477 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner);
481 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
482 RtlCopySid(length, destSD->Owner, Owner);
486 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
487 length = RtlLengthSid(Group);
491 destSD->Group = srcSD->Group;
492 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
496 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
497 RtlCopySid(length, destSD->Group, Group);
501 if (srcSD->Control & SE_DACL_PRESENT)
503 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
504 length = Dacl->AclSize;
508 destSD->Dacl = srcSD->Dacl;
509 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl);
513 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
514 copy_acl(length, destSD->Dacl, Dacl);
519 if (srcSD->Control & SE_SACL_PRESENT)
521 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
522 length = Sacl->AclSize;
526 destSD->Sacl = srcSD->Sacl;
527 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl);
531 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
532 copy_acl(length, destSD->Sacl, Sacl);
536 return STATUS_SUCCESS;
539 /**************************************************************************
540 * RtlValidSecurityDescriptor [NTDLL.@]
542 * Determine if a SECURITY_DESCRIPTOR is valid.
545 * SecurityDescriptor [I] Descriptor to check.
548 * Success: STATUS_SUCCESS.
549 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
551 NTSTATUS WINAPI RtlValidSecurityDescriptor(
552 PSECURITY_DESCRIPTOR SecurityDescriptor)
554 if ( ! SecurityDescriptor )
555 return STATUS_INVALID_SECURITY_DESCR;
556 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
557 return STATUS_UNKNOWN_REVISION;
559 return STATUS_SUCCESS;
562 /**************************************************************************
563 * RtlLengthSecurityDescriptor [NTDLL.@]
565 ULONG WINAPI RtlLengthSecurityDescriptor(
566 PSECURITY_DESCRIPTOR pSecurityDescriptor)
568 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
569 ULONG_PTR offset = 0;
570 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
575 if ( lpsd->Control & SE_SELF_RELATIVE)
576 offset = (ULONG_PTR) lpsd;
578 if ( lpsd->Owner != NULL )
579 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
581 if ( lpsd->Group != NULL )
582 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
584 if ( (lpsd->Control & SE_SACL_PRESENT) &&
586 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
588 if ( (lpsd->Control & SE_DACL_PRESENT) &&
590 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
595 /******************************************************************************
596 * RtlGetDaclSecurityDescriptor [NTDLL.@]
599 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
600 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
601 OUT PBOOLEAN lpbDaclPresent,
603 OUT PBOOLEAN lpbDaclDefaulted)
605 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
607 TRACE("(%p,%p,%p,%p)\n",
608 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
610 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
611 return STATUS_UNKNOWN_REVISION ;
613 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
615 if ( SE_SELF_RELATIVE & lpsd->Control)
616 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Dacl);
620 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
623 return STATUS_SUCCESS;
626 /**************************************************************************
627 * RtlSetDaclSecurityDescriptor [NTDLL.@]
629 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
630 PSECURITY_DESCRIPTOR pSecurityDescriptor,
633 BOOLEAN dacldefaulted )
635 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
637 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
638 return STATUS_UNKNOWN_REVISION;
639 if (lpsd->Control & SE_SELF_RELATIVE)
640 return STATUS_INVALID_SECURITY_DESCR;
644 lpsd->Control &= ~SE_DACL_PRESENT;
645 return STATUS_SUCCESS;
648 lpsd->Control |= SE_DACL_PRESENT;
652 lpsd->Control |= SE_DACL_DEFAULTED;
654 lpsd->Control &= ~SE_DACL_DEFAULTED;
656 return STATUS_SUCCESS;
659 /******************************************************************************
660 * RtlGetSaclSecurityDescriptor [NTDLL.@]
663 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
664 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
665 OUT PBOOLEAN lpbSaclPresent,
667 OUT PBOOLEAN lpbSaclDefaulted)
669 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
671 TRACE("(%p,%p,%p,%p)\n",
672 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
674 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
675 return STATUS_UNKNOWN_REVISION;
677 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
679 if (SE_SELF_RELATIVE & lpsd->Control)
680 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Sacl);
684 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
687 return STATUS_SUCCESS;
690 /**************************************************************************
691 * RtlSetSaclSecurityDescriptor [NTDLL.@]
693 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
694 PSECURITY_DESCRIPTOR pSecurityDescriptor,
697 BOOLEAN sacldefaulted)
699 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
701 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
702 return STATUS_UNKNOWN_REVISION;
703 if (lpsd->Control & SE_SELF_RELATIVE)
704 return STATUS_INVALID_SECURITY_DESCR;
706 lpsd->Control &= ~SE_SACL_PRESENT;
709 lpsd->Control |= SE_SACL_PRESENT;
712 lpsd->Control |= SE_SACL_DEFAULTED;
714 lpsd->Control &= ~SE_SACL_DEFAULTED;
715 return STATUS_SUCCESS;
718 /**************************************************************************
719 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
721 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
722 PSECURITY_DESCRIPTOR pSecurityDescriptor,
724 PBOOLEAN OwnerDefaulted)
726 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
728 if ( !lpsd || !Owner || !OwnerDefaulted )
729 return STATUS_INVALID_PARAMETER;
731 if ( lpsd->Control & SE_OWNER_DEFAULTED )
732 *OwnerDefaulted = TRUE;
734 *OwnerDefaulted = FALSE;
736 if (lpsd->Owner != NULL)
738 if (lpsd->Control & SE_SELF_RELATIVE)
739 *Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner);
741 *Owner = lpsd->Owner;
747 return STATUS_SUCCESS;
750 /**************************************************************************
751 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
753 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
754 PSECURITY_DESCRIPTOR pSecurityDescriptor,
756 BOOLEAN ownerdefaulted)
758 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
760 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
761 return STATUS_UNKNOWN_REVISION;
762 if (lpsd->Control & SE_SELF_RELATIVE)
763 return STATUS_INVALID_SECURITY_DESCR;
767 lpsd->Control |= SE_OWNER_DEFAULTED;
769 lpsd->Control &= ~SE_OWNER_DEFAULTED;
770 return STATUS_SUCCESS;
773 /**************************************************************************
774 * RtlSetGroupSecurityDescriptor [NTDLL.@]
776 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
777 PSECURITY_DESCRIPTOR pSecurityDescriptor,
779 BOOLEAN groupdefaulted)
781 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
783 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
784 return STATUS_UNKNOWN_REVISION;
785 if (lpsd->Control & SE_SELF_RELATIVE)
786 return STATUS_INVALID_SECURITY_DESCR;
790 lpsd->Control |= SE_GROUP_DEFAULTED;
792 lpsd->Control &= ~SE_GROUP_DEFAULTED;
793 return STATUS_SUCCESS;
796 /**************************************************************************
797 * RtlGetGroupSecurityDescriptor [NTDLL.@]
799 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
800 PSECURITY_DESCRIPTOR pSecurityDescriptor,
802 PBOOLEAN GroupDefaulted)
804 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
806 if ( !lpsd || !Group || !GroupDefaulted )
807 return STATUS_INVALID_PARAMETER;
809 if ( lpsd->Control & SE_GROUP_DEFAULTED )
810 *GroupDefaulted = TRUE;
812 *GroupDefaulted = FALSE;
814 if (lpsd->Group != NULL)
816 if (lpsd->Control & SE_SELF_RELATIVE)
817 *Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group);
819 *Group = lpsd->Group;
824 return STATUS_SUCCESS;
827 /**************************************************************************
828 * RtlMakeSelfRelativeSD [NTDLL.@]
830 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
831 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
832 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
833 IN OUT LPDWORD lpdwBufferLength)
837 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
838 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
840 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
841 lpdwBufferLength ? *lpdwBufferLength: -1);
843 if (!lpdwBufferLength || !pAbs)
844 return STATUS_INVALID_PARAMETER;
846 length = RtlLengthSecurityDescriptor(pAbs);
847 if (*lpdwBufferLength < length)
849 *lpdwBufferLength = length;
850 return STATUS_BUFFER_TOO_SMALL;
854 return STATUS_INVALID_PARAMETER;
856 if (pAbs->Control & SE_SELF_RELATIVE)
858 memcpy(pRel, pAbs, length);
859 return STATUS_SUCCESS;
862 pRel->Revision = pAbs->Revision;
863 pRel->Sbz1 = pAbs->Sbz1;
864 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
866 offsetRel = sizeof(SECURITY_DESCRIPTOR);
869 pRel->Owner = (PSID) offsetRel;
870 length = RtlLengthSid(pAbs->Owner);
871 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
881 pRel->Group = (PSID) offsetRel;
882 length = RtlLengthSid(pAbs->Group);
883 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
893 pRel->Sacl = (PACL) offsetRel;
894 length = pAbs->Sacl->AclSize;
895 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
905 pRel->Dacl = (PACL) offsetRel;
906 length = pAbs->Dacl->AclSize;
907 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
914 return STATUS_SUCCESS;
918 /**************************************************************************
919 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
921 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
922 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
923 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
924 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
926 OUT LPDWORD lpdwDaclSize,
928 OUT LPDWORD lpdwSaclSize,
930 OUT LPDWORD lpdwOwnerSize,
931 OUT PSID pPrimaryGroup,
932 OUT LPDWORD lpdwPrimaryGroupSize)
934 NTSTATUS status = STATUS_SUCCESS;
935 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
936 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
939 !lpdwAbsoluteSecurityDescriptorSize ||
943 !lpdwPrimaryGroupSize ||
944 ~pRel->Control & SE_SELF_RELATIVE)
945 return STATUS_INVALID_PARAMETER;
947 /* Confirm buffers are sufficiently large */
948 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
950 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
951 status = STATUS_BUFFER_TOO_SMALL;
954 if (pRel->Control & SE_DACL_PRESENT &&
955 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize)
957 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize;
958 status = STATUS_BUFFER_TOO_SMALL;
961 if (pRel->Control & SE_SACL_PRESENT &&
962 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize)
964 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize;
965 status = STATUS_BUFFER_TOO_SMALL;
969 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)))
971 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel));
972 status = STATUS_BUFFER_TOO_SMALL;
976 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)))
978 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel));
979 status = STATUS_BUFFER_TOO_SMALL;
982 if (status != STATUS_SUCCESS)
985 /* Copy structures, and clear the ones we don't set */
986 pAbs->Revision = pRel->Revision;
987 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
993 if (pRel->Control & SE_SACL_PRESENT)
995 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel);
997 memcpy(pSacl, pAcl, pAcl->AclSize);
1001 if (pRel->Control & SE_DACL_PRESENT)
1003 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel);
1004 memcpy(pDacl, pAcl, pAcl->AclSize);
1010 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel);
1011 memcpy(pOwner, psid, RtlLengthSid(psid));
1012 pAbs->Owner = pOwner;
1017 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel);
1018 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1019 pAbs->Group = pPrimaryGroup;
1025 /******************************************************************************
1026 * RtlGetControlSecurityDescriptor (NTDLL.@)
1028 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1029 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1030 PSECURITY_DESCRIPTOR_CONTROL pControl,
1031 LPDWORD lpdwRevision)
1033 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1035 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1037 *lpdwRevision = lpsd->Revision;
1039 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1040 return STATUS_UNKNOWN_REVISION;
1042 *pControl = lpsd->Control;
1044 return STATUS_SUCCESS;
1047 /******************************************************************************
1048 * RtlSetControlSecurityDescriptor (NTDLL.@)
1050 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1051 PSECURITY_DESCRIPTOR SecurityDescriptor,
1052 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1053 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1055 SECURITY_DESCRIPTOR_CONTROL const immutable
1056 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1057 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1058 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1059 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1062 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1064 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1065 ControlBitsOfInterest, ControlBitsToSet);
1067 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1068 return STATUS_INVALID_PARAMETER;
1070 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1071 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1073 return STATUS_SUCCESS;
1077 /**************************************************************************
1078 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1080 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1081 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1082 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1083 PULONG BufferLength)
1085 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1087 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1088 SelfRelativeSecurityDescriptor, BufferLength);
1090 if (abs->Control & SE_SELF_RELATIVE)
1091 return STATUS_BAD_DESCRIPTOR_FORMAT;
1093 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1094 SelfRelativeSecurityDescriptor, BufferLength);
1099 * access control list's
1102 /**************************************************************************
1103 * RtlCreateAcl [NTDLL.@]
1106 * This should return NTSTATUS
1108 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1110 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1112 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1113 return STATUS_INVALID_PARAMETER;
1114 if (size<sizeof(ACL))
1115 return STATUS_BUFFER_TOO_SMALL;
1117 return STATUS_INVALID_PARAMETER;
1119 memset(acl,'\0',sizeof(ACL));
1120 acl->AclRevision = rev;
1121 acl->AclSize = size;
1123 return STATUS_SUCCESS;
1126 /**************************************************************************
1127 * RtlFirstFreeAce [NTDLL.@]
1128 * looks for the AceCount+1 ACE, and if it is still within the alloced
1129 * ACL, return a pointer to it
1131 BOOLEAN WINAPI RtlFirstFreeAce(
1139 ace = (PACE_HEADER)(acl+1);
1140 for (i=0;i<acl->AceCount;i++) {
1141 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1143 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1145 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1151 /**************************************************************************
1152 * RtlAddAce [NTDLL.@]
1154 NTSTATUS WINAPI RtlAddAce(
1158 PACE_HEADER acestart,
1161 PACE_HEADER ace,targetace;
1164 if (acl->AclRevision != ACL_REVISION)
1165 return STATUS_INVALID_PARAMETER;
1166 if (!RtlFirstFreeAce(acl,&targetace))
1167 return STATUS_INVALID_PARAMETER;
1168 nrofaces=0;ace=acestart;
1169 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1171 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1173 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1174 return STATUS_INVALID_PARAMETER;
1175 memcpy((LPBYTE)targetace,acestart,acelen);
1176 acl->AceCount+=nrofaces;
1177 return STATUS_SUCCESS;
1180 /**************************************************************************
1181 * RtlDeleteAce [NTDLL.@]
1183 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1188 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1190 if (STATUS_SUCCESS == status)
1195 /* skip over the ACE we are deleting */
1196 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1199 /* calculate the length of the rest */
1200 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1202 len += pcAce->AceSize;
1203 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1206 /* slide them all backwards */
1207 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1211 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1216 /******************************************************************************
1217 * RtlAddAccessAllowedAce [NTDLL.@]
1219 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1221 IN DWORD dwAceRevision,
1222 IN DWORD AccessMask,
1225 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1228 /******************************************************************************
1229 * RtlAddAccessAllowedAceEx [NTDLL.@]
1231 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1233 IN DWORD dwAceRevision,
1235 IN DWORD AccessMask,
1238 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1240 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1241 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1244 /******************************************************************************
1245 * RtlAddAccessDeniedAce [NTDLL.@]
1247 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1249 IN DWORD dwAceRevision,
1250 IN DWORD AccessMask,
1253 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1256 /******************************************************************************
1257 * RtlAddAccessDeniedAceEx [NTDLL.@]
1259 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1261 IN DWORD dwAceRevision,
1263 IN DWORD AccessMask,
1266 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1268 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1269 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1272 /**************************************************************************
1273 * RtlAddAuditAccessAce [NTDLL.@]
1275 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1277 IN DWORD dwAceRevision,
1278 IN DWORD dwAceFlags,
1279 IN DWORD dwAccessMask,
1281 IN BOOL bAuditSuccess,
1282 IN BOOL bAuditFailure)
1284 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1285 pSid,bAuditSuccess,bAuditFailure);
1288 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1291 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1293 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1294 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1297 /**************************************************************************
1298 * RtlAddAuditAccessAce [NTDLL.@]
1300 NTSTATUS WINAPI RtlAddAuditAccessAce(
1302 IN DWORD dwAceRevision,
1303 IN DWORD dwAccessMask,
1305 IN BOOL bAuditSuccess,
1306 IN BOOL bAuditFailure)
1308 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1311 /******************************************************************************
1312 * RtlValidAcl [NTDLL.@]
1314 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1317 TRACE("(%p)\n", pAcl);
1324 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1325 pAcl->AclRevision > MAX_ACL_REVISION)
1329 ace = (PACE_HEADER)(pAcl+1);
1331 for (i=0;i<=pAcl->AceCount;i++)
1333 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1338 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1344 WARN("(%p): invalid pointer!\n", pAcl);
1351 /******************************************************************************
1352 * RtlGetAce [NTDLL.@]
1354 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1358 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1360 if (dwAceIndex >= pAcl->AceCount)
1361 return STATUS_INVALID_PARAMETER;
1363 ace = (PACE_HEADER)(pAcl + 1);
1364 for (;dwAceIndex;dwAceIndex--)
1365 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1367 *pAce = (LPVOID) ace;
1369 return STATUS_SUCCESS;
1376 /******************************************************************************
1377 * RtlAdjustPrivilege [NTDLL.@]
1379 * Enables or disables a privilege from the calling thread or process.
1382 * Privilege [I] Privilege index to change.
1383 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1384 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1385 * Enabled [O] Whether privilege was previously enabled or disabled.
1388 * Success: STATUS_SUCCESS.
1389 * Failure: NTSTATUS code.
1392 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1396 RtlAdjustPrivilege(ULONG Privilege,
1398 BOOLEAN CurrentThread,
1401 TOKEN_PRIVILEGES NewState;
1402 TOKEN_PRIVILEGES OldState;
1407 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1408 CurrentThread ? "TRUE" : "FALSE", Enabled);
1412 Status = NtOpenThreadToken(GetCurrentThread(),
1413 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1419 Status = NtOpenProcessToken(GetCurrentProcess(),
1420 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1424 if (!NT_SUCCESS(Status))
1426 WARN("Retrieving token handle failed (Status %x)\n", Status);
1430 OldState.PrivilegeCount = 1;
1432 NewState.PrivilegeCount = 1;
1433 NewState.Privileges[0].Luid.LowPart = Privilege;
1434 NewState.Privileges[0].Luid.HighPart = 0;
1435 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1437 Status = NtAdjustPrivilegesToken(TokenHandle,
1440 sizeof(TOKEN_PRIVILEGES),
1443 NtClose (TokenHandle);
1444 if (Status == STATUS_NOT_ALL_ASSIGNED)
1446 TRACE("Failed to assign all privileges\n");
1447 return STATUS_PRIVILEGE_NOT_HELD;
1449 if (!NT_SUCCESS(Status))
1451 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1455 if (OldState.PrivilegeCount == 0)
1458 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1460 return STATUS_SUCCESS;
1463 /******************************************************************************
1464 * RtlImpersonateSelf [NTDLL.@]
1466 * Makes an impersonation token that represents the process user and assigns
1467 * to the current thread.
1470 * ImpersonationLevel [I] Level at which to impersonate.
1473 * Success: STATUS_SUCCESS.
1474 * Failure: NTSTATUS code.
1477 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1480 OBJECT_ATTRIBUTES ObjectAttributes;
1481 HANDLE ProcessToken;
1482 HANDLE ImpersonationToken;
1484 TRACE("(%08x)\n", ImpersonationLevel);
1486 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1488 if (Status != STATUS_SUCCESS)
1491 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1493 Status = NtDuplicateToken( ProcessToken,
1498 &ImpersonationToken );
1499 if (Status != STATUS_SUCCESS)
1501 NtClose( ProcessToken );
1505 Status = NtSetInformationThread( GetCurrentThread(),
1506 ThreadImpersonationToken,
1507 &ImpersonationToken,
1508 sizeof(ImpersonationToken) );
1510 NtClose( ImpersonationToken );
1511 NtClose( ProcessToken );
1516 /******************************************************************************
1517 * NtAccessCheck [NTDLL.@]
1518 * ZwAccessCheck [NTDLL.@]
1520 * Checks that a user represented by a token is allowed to access an object
1521 * represented by a security descriptor.
1524 * SecurityDescriptor [I] The security descriptor of the object to check.
1525 * ClientToken [I] Token of the user accessing the object.
1526 * DesiredAccess [I] The desired access to the object.
1527 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1528 * PrivilegeSet [I/O] Privileges used during the access check.
1529 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1530 * GrantedAccess [O] The actual access rights granted.
1531 * AccessStatus [O] The status of the access check.
1537 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1538 * the maximum access rights allowed by the SD and returns them in
1540 * The SecurityDescriptor must have a valid owner and groups present,
1541 * otherwise the function will fail.
1545 PSECURITY_DESCRIPTOR SecurityDescriptor,
1547 ACCESS_MASK DesiredAccess,
1548 PGENERIC_MAPPING GenericMapping,
1549 PPRIVILEGE_SET PrivilegeSet,
1550 PULONG ReturnLength,
1551 PULONG GrantedAccess,
1552 NTSTATUS *AccessStatus)
1556 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1557 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1558 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1560 SERVER_START_REQ( access_check )
1562 struct security_descriptor sd;
1567 BOOLEAN defaulted, present;
1569 SECURITY_DESCRIPTOR_CONTROL control;
1571 req->handle = ClientToken;
1572 req->desired_access = DesiredAccess;
1573 req->mapping_read = GenericMapping->GenericRead;
1574 req->mapping_write = GenericMapping->GenericWrite;
1575 req->mapping_execute = GenericMapping->GenericExecute;
1576 req->mapping_all = GenericMapping->GenericAll;
1578 /* marshal security descriptor */
1579 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1580 sd.control = control & ~SE_SELF_RELATIVE;
1581 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1582 sd.owner_len = RtlLengthSid( owner );
1583 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1584 sd.group_len = RtlLengthSid( group );
1585 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1586 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1587 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1588 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1590 wine_server_add_data( req, &sd, sizeof(sd) );
1591 wine_server_add_data( req, owner, sd.owner_len );
1592 wine_server_add_data( req, group, sd.group_len );
1593 wine_server_add_data( req, sacl, sd.sacl_len );
1594 wine_server_add_data( req, dacl, sd.dacl_len );
1596 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1598 status = wine_server_call( req );
1600 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1601 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1603 if (status == STATUS_SUCCESS)
1605 *AccessStatus = reply->access_status;
1606 *GrantedAccess = reply->access_granted;
1614 /******************************************************************************
1615 * NtSetSecurityObject [NTDLL.@]
1616 * ZwSetSecurityObject [NTDLL.@]
1618 * Sets specified parts of the object's security descriptor.
1621 * Handle [I] Handle to the object to change security descriptor of.
1622 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1623 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1629 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1630 SECURITY_INFORMATION SecurityInformation,
1631 PSECURITY_DESCRIPTOR SecurityDescriptor)
1634 struct security_descriptor sd;
1635 PACL dacl = NULL, sacl = NULL;
1636 PSID owner = NULL, group = NULL;
1637 BOOLEAN defaulted, present;
1639 SECURITY_DESCRIPTOR_CONTROL control;
1641 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1643 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1645 memset( &sd, 0, sizeof(sd) );
1646 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1647 if (status != STATUS_SUCCESS) return status;
1648 sd.control = control & ~SE_SELF_RELATIVE;
1650 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1652 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1653 if (status != STATUS_SUCCESS) return status;
1654 if (!(sd.owner_len = RtlLengthSid( owner )))
1655 return STATUS_INVALID_SECURITY_DESCR;
1658 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1660 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1661 if (status != STATUS_SUCCESS) return status;
1662 if (!(sd.group_len = RtlLengthSid( group )))
1663 return STATUS_INVALID_SECURITY_DESCR;
1666 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1668 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1669 if (status != STATUS_SUCCESS) return status;
1670 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1671 sd.control |= SE_SACL_PRESENT;
1674 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1676 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1677 if (status != STATUS_SUCCESS) return status;
1678 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1679 sd.control |= SE_DACL_PRESENT;
1682 SERVER_START_REQ( set_security_object )
1684 req->handle = Handle;
1685 req->security_info = SecurityInformation;
1687 wine_server_add_data( req, &sd, sizeof(sd) );
1688 wine_server_add_data( req, owner, sd.owner_len );
1689 wine_server_add_data( req, group, sd.group_len );
1690 wine_server_add_data( req, sacl, sd.sacl_len );
1691 wine_server_add_data( req, dacl, sd.dacl_len );
1692 status = wine_server_call( req );
1699 /******************************************************************************
1700 * RtlConvertSidToUnicodeString (NTDLL.@)
1702 * The returned SID is used to access the USER registry hive usually
1704 * the native function returns something like
1705 * "S-1-5-21-0000000000-000000000-0000000000-500";
1707 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1708 PUNICODE_STRING String,
1710 BOOLEAN AllocateString)
1712 static const WCHAR formatW[] = {'-','%','u',0};
1713 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1715 const SID *sid = (const SID *)pSid;
1719 p += sprintfW( p, formatW, sid->Revision );
1720 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1721 sid->IdentifierAuthority.Value[4] ),
1722 MAKEWORD( sid->IdentifierAuthority.Value[3],
1723 sid->IdentifierAuthority.Value[2] )));
1724 for (i = 0; i < sid->SubAuthorityCount; i++)
1725 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1727 len = (p + 1 - buffer) * sizeof(WCHAR);
1729 String->Length = len - sizeof(WCHAR);
1732 String->MaximumLength = len;
1733 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1734 return STATUS_NO_MEMORY;
1736 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1738 memcpy( String->Buffer, buffer, len );
1739 return STATUS_SUCCESS;
1742 /******************************************************************************
1743 * RtlQueryInformationAcl (NTDLL.@)
1745 NTSTATUS WINAPI RtlQueryInformationAcl(
1747 LPVOID pAclInformation,
1748 DWORD nAclInformationLength,
1749 ACL_INFORMATION_CLASS dwAclInformationClass)
1751 NTSTATUS status = STATUS_SUCCESS;
1753 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1754 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1756 switch (dwAclInformationClass)
1758 case AclRevisionInformation:
1760 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1762 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1763 status = STATUS_INVALID_PARAMETER;
1765 paclrev->AclRevision = pAcl->AclRevision;
1770 case AclSizeInformation:
1772 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1774 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1775 status = STATUS_INVALID_PARAMETER;
1778 paclsize->AceCount = pAcl->AceCount;
1779 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1780 if (pAcl->AclSize < paclsize->AclBytesInUse)
1782 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1783 paclsize->AclBytesFree = 0;
1784 paclsize->AclBytesInUse = pAcl->AclSize;
1787 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1794 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1795 status = STATUS_INVALID_PARAMETER;