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 #define SELF_RELATIVE_FIELD(sd,field) ((BYTE *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
50 /* helper function to retrieve active length of an ACL */
51 static size_t acl_bytesInUse(PACL pAcl)
54 size_t bytesInUse = sizeof(ACL);
55 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
56 for (i = 0; i < pAcl->AceCount; i++)
58 bytesInUse += ace->AceSize;
59 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
64 /* helper function to copy an ACL */
65 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
69 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
72 size = pSourceAcl->AclSize;
73 if (nDestinationAclLength < size)
76 memmove(pDestinationAcl, pSourceAcl, size);
80 /* generically adds an ACE to an ACL */
81 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
82 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
84 ACE_HEADER *pAceHeader;
90 if (!RtlValidSid(pSid))
91 return STATUS_INVALID_SID;
93 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
94 return STATUS_REVISION_MISMATCH;
96 if (!RtlValidAcl(pAcl))
97 return STATUS_INVALID_ACL;
99 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
100 return STATUS_INVALID_ACL;
103 return STATUS_ALLOTTED_SPACE_EXCEEDED;
105 /* calculate generic size of the ACE */
106 dwLengthSid = RtlLengthSid(pSid);
107 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
108 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
109 return STATUS_ALLOTTED_SPACE_EXCEEDED;
111 /* fill the new ACE */
112 pAceHeader->AceType = dwAceType;
113 pAceHeader->AceFlags = dwAceFlags;
114 pAceHeader->AceSize = dwAceSize;
116 /* skip past the ACE_HEADER of the ACE */
117 pAccessMask = (DWORD *)(pAceHeader + 1);
118 *pAccessMask = dwAccessMask;
120 /* skip past ACE->Mask */
121 pSidStart = pAccessMask + 1;
122 RtlCopySid(dwLengthSid, pSidStart, pSid);
124 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
127 return STATUS_SUCCESS;
134 /******************************************************************************
135 * RtlAllocateAndInitializeSid [NTDLL.@]
138 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
139 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
140 BYTE nSubAuthorityCount,
141 DWORD nSubAuthority0, DWORD nSubAuthority1,
142 DWORD nSubAuthority2, DWORD nSubAuthority3,
143 DWORD nSubAuthority4, DWORD nSubAuthority5,
144 DWORD nSubAuthority6, DWORD nSubAuthority7,
149 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
150 pIdentifierAuthority,nSubAuthorityCount,
151 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
152 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
154 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
156 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
157 RtlLengthRequiredSid(nSubAuthorityCount))))
158 return STATUS_NO_MEMORY;
160 tmp_sid->Revision = SID_REVISION;
162 if (pIdentifierAuthority)
163 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
164 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
166 switch( nSubAuthorityCount )
168 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
169 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
170 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
171 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
172 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
173 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
174 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
175 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
179 return STATUS_SUCCESS;
182 /******************************************************************************
183 * RtlEqualSid [NTDLL.@]
185 * Determine if two SIDs are equal.
188 * pSid1 [I] Source SID
189 * pSid2 [I] SID to compare with
192 * TRUE, if pSid1 is equal to pSid2,
195 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
197 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
200 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
203 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
209 /******************************************************************************
210 * RtlEqualPrefixSid [NTDLL.@]
212 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
214 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
217 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
220 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
227 /******************************************************************************
228 * RtlFreeSid [NTDLL.@]
230 * Free the resources used by a SID.
233 * pSid [I] SID to Free.
238 DWORD WINAPI RtlFreeSid(PSID pSid)
240 TRACE("(%p)\n", pSid);
241 RtlFreeHeap( GetProcessHeap(), 0, pSid );
242 return STATUS_SUCCESS;
245 /**************************************************************************
246 * RtlLengthRequiredSid [NTDLL.@]
248 * Determine the amount of memory a SID will use
251 * nrofsubauths [I] Number of Sub Authorities in the SID.
254 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
256 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
258 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
261 /**************************************************************************
262 * RtlLengthSid [NTDLL.@]
264 * Determine the amount of memory a SID is using
267 * pSid [I] SID to get the size of.
270 * The size, in bytes, of pSid.
272 DWORD WINAPI RtlLengthSid(PSID pSid)
274 TRACE("sid=%p\n",pSid);
276 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
279 /**************************************************************************
280 * RtlInitializeSid [NTDLL.@]
285 * pSid [I] SID to initialise
286 * pIdentifierAuthority [I] Identifier Authority
287 * nSubAuthorityCount [I] Number of Sub Authorities
290 * Success: TRUE. pSid is initialised with the details given.
291 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
293 BOOL WINAPI RtlInitializeSid(
295 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
296 BYTE nSubAuthorityCount)
301 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
304 pisid->Revision = SID_REVISION;
305 pisid->SubAuthorityCount = nSubAuthorityCount;
306 if (pIdentifierAuthority)
307 pisid->IdentifierAuthority = *pIdentifierAuthority;
309 for (i = 0; i < nSubAuthorityCount; i++)
310 *RtlSubAuthoritySid(pSid, i) = 0;
315 /**************************************************************************
316 * RtlSubAuthoritySid [NTDLL.@]
318 * Return the Sub Authority of a SID
321 * pSid [I] SID to get the Sub Authority from.
322 * nSubAuthority [I] Sub Authority number.
325 * A pointer to The Sub Authority value of pSid.
327 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
329 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
332 /**************************************************************************
333 * RtlIdentifierAuthoritySid [NTDLL.@]
335 * Return the Identifier Authority of a SID.
338 * pSid [I] SID to get the Identifier Authority from.
341 * A pointer to the Identifier Authority value of pSid.
343 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
345 return &(((SID*)pSid)->IdentifierAuthority);
348 /**************************************************************************
349 * RtlSubAuthorityCountSid [NTDLL.@]
351 * Get the number of Sub Authorities in a SID.
354 * pSid [I] SID to get the count from.
357 * A pointer to the Sub Authority count of pSid.
359 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
361 return &(((SID*)pSid)->SubAuthorityCount);
364 /**************************************************************************
365 * RtlCopySid [NTDLL.@]
367 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
369 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
370 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
373 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
376 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
379 /******************************************************************************
380 * RtlValidSid [NTDLL.@]
382 * Determine if a SID is valid.
385 * pSid [I] SID to check
388 * TRUE if pSid is valid,
391 BOOLEAN WINAPI RtlValidSid( PSID pSid )
397 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
398 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
405 WARN("(%p): invalid pointer!\n", pSid);
414 * security descriptor functions
417 /**************************************************************************
418 * RtlCreateSecurityDescriptor [NTDLL.@]
420 * Initialise a SECURITY_DESCRIPTOR.
423 * lpsd [O] Descriptor to initialise.
424 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
427 * Success: STATUS_SUCCESS.
428 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
430 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
431 PSECURITY_DESCRIPTOR lpsd,
434 if (rev!=SECURITY_DESCRIPTOR_REVISION)
435 return STATUS_UNKNOWN_REVISION;
436 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
437 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
438 return STATUS_SUCCESS;
441 /**************************************************************************
442 * RtlCopySecurityDescriptor [NTDLL.@]
444 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
447 * pSourceSD [O] SD to copy from.
448 * pDestinationSD [I] Destination SD.
451 * Success: STATUS_SUCCESS.
452 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
454 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
460 if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
462 SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
463 SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
465 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
466 return STATUS_UNKNOWN_REVISION;
471 Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
472 length = RtlLengthSid( Owner );
473 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
477 Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
478 length = RtlLengthSid( Group );
479 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
481 if ((src->Control & SE_SACL_PRESENT) && src->Sacl)
483 Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
484 copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
486 if ((src->Control & SE_DACL_PRESENT) && src->Dacl)
488 Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
489 copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
494 SECURITY_DESCRIPTOR *src = pSourceSD;
495 SECURITY_DESCRIPTOR *dst = pDestinationSD;
497 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
498 return STATUS_UNKNOWN_REVISION;
503 length = RtlLengthSid( src->Owner );
504 dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
505 RtlCopySid(length, dst->Owner, src->Owner);
509 length = RtlLengthSid( src->Group );
510 dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
511 RtlCopySid(length, dst->Group, src->Group);
513 if (src->Control & SE_SACL_PRESENT)
515 length = src->Sacl->AclSize;
516 dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
517 copy_acl(length, dst->Sacl, src->Sacl);
519 if (src->Control & SE_DACL_PRESENT)
521 length = src->Dacl->AclSize;
522 dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
523 copy_acl(length, dst->Dacl, src->Dacl);
527 return STATUS_SUCCESS;
530 /**************************************************************************
531 * RtlValidSecurityDescriptor [NTDLL.@]
533 * Determine if a SECURITY_DESCRIPTOR is valid.
536 * SecurityDescriptor [I] Descriptor to check.
539 * Success: STATUS_SUCCESS.
540 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
542 NTSTATUS WINAPI RtlValidSecurityDescriptor(
543 PSECURITY_DESCRIPTOR SecurityDescriptor)
545 if ( ! SecurityDescriptor )
546 return STATUS_INVALID_SECURITY_DESCR;
547 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
548 return STATUS_UNKNOWN_REVISION;
550 return STATUS_SUCCESS;
553 /**************************************************************************
554 * RtlLengthSecurityDescriptor [NTDLL.@]
556 ULONG WINAPI RtlLengthSecurityDescriptor(
557 PSECURITY_DESCRIPTOR pSecurityDescriptor)
561 if ( pSecurityDescriptor == NULL )
564 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
566 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
568 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
569 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
570 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
571 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
572 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
573 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
577 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
579 if (sd->Owner) size += RtlLengthSid( sd->Owner );
580 if (sd->Group) size += RtlLengthSid( sd->Group );
581 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
582 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
587 /******************************************************************************
588 * RtlGetDaclSecurityDescriptor [NTDLL.@]
591 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
592 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
593 OUT PBOOLEAN lpbDaclPresent,
595 OUT PBOOLEAN lpbDaclDefaulted)
597 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
599 TRACE("(%p,%p,%p,%p)\n",
600 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
602 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
603 return STATUS_UNKNOWN_REVISION ;
605 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
607 if ((SE_SELF_RELATIVE & lpsd->Control) && lpsd->Dacl)
608 *pDacl = (PACL)SELF_RELATIVE_FIELD( lpsd, Dacl );
612 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
617 *lpbDaclDefaulted = 0;
620 return STATUS_SUCCESS;
623 /**************************************************************************
624 * RtlSetDaclSecurityDescriptor [NTDLL.@]
626 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
627 PSECURITY_DESCRIPTOR pSecurityDescriptor,
630 BOOLEAN dacldefaulted )
632 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
634 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
635 return STATUS_UNKNOWN_REVISION;
636 if (lpsd->Control & SE_SELF_RELATIVE)
637 return STATUS_INVALID_SECURITY_DESCR;
641 lpsd->Control &= ~SE_DACL_PRESENT;
642 return STATUS_SUCCESS;
645 lpsd->Control |= SE_DACL_PRESENT;
649 lpsd->Control |= SE_DACL_DEFAULTED;
651 lpsd->Control &= ~SE_DACL_DEFAULTED;
653 return STATUS_SUCCESS;
656 /******************************************************************************
657 * RtlGetSaclSecurityDescriptor [NTDLL.@]
660 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
661 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
662 OUT PBOOLEAN lpbSaclPresent,
664 OUT PBOOLEAN lpbSaclDefaulted)
666 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
668 TRACE("(%p,%p,%p,%p)\n",
669 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
671 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
672 return STATUS_UNKNOWN_REVISION;
674 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
676 if ((SE_SELF_RELATIVE & lpsd->Control) && lpsd->Sacl)
677 *pSacl = (PACL)SELF_RELATIVE_FIELD( lpsd, Sacl );
681 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
683 return STATUS_SUCCESS;
686 /**************************************************************************
687 * RtlSetSaclSecurityDescriptor [NTDLL.@]
689 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
690 PSECURITY_DESCRIPTOR pSecurityDescriptor,
693 BOOLEAN sacldefaulted)
695 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
697 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
698 return STATUS_UNKNOWN_REVISION;
699 if (lpsd->Control & SE_SELF_RELATIVE)
700 return STATUS_INVALID_SECURITY_DESCR;
702 lpsd->Control &= ~SE_SACL_PRESENT;
705 lpsd->Control |= SE_SACL_PRESENT;
708 lpsd->Control |= SE_SACL_DEFAULTED;
710 lpsd->Control &= ~SE_SACL_DEFAULTED;
711 return STATUS_SUCCESS;
714 /**************************************************************************
715 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
717 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
718 PSECURITY_DESCRIPTOR pSecurityDescriptor,
720 PBOOLEAN OwnerDefaulted)
722 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
724 if ( !lpsd || !Owner || !OwnerDefaulted )
725 return STATUS_INVALID_PARAMETER;
727 if ( lpsd->Control & SE_OWNER_DEFAULTED )
728 *OwnerDefaulted = TRUE;
730 *OwnerDefaulted = FALSE;
732 if (lpsd->Control & SE_SELF_RELATIVE)
734 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
735 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
739 *Owner = lpsd->Owner;
741 return STATUS_SUCCESS;
744 /**************************************************************************
745 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
747 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
748 PSECURITY_DESCRIPTOR pSecurityDescriptor,
750 BOOLEAN ownerdefaulted)
752 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
754 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
755 return STATUS_UNKNOWN_REVISION;
756 if (lpsd->Control & SE_SELF_RELATIVE)
757 return STATUS_INVALID_SECURITY_DESCR;
761 lpsd->Control |= SE_OWNER_DEFAULTED;
763 lpsd->Control &= ~SE_OWNER_DEFAULTED;
764 return STATUS_SUCCESS;
767 /**************************************************************************
768 * RtlSetGroupSecurityDescriptor [NTDLL.@]
770 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
771 PSECURITY_DESCRIPTOR pSecurityDescriptor,
773 BOOLEAN groupdefaulted)
775 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
777 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
778 return STATUS_UNKNOWN_REVISION;
779 if (lpsd->Control & SE_SELF_RELATIVE)
780 return STATUS_INVALID_SECURITY_DESCR;
784 lpsd->Control |= SE_GROUP_DEFAULTED;
786 lpsd->Control &= ~SE_GROUP_DEFAULTED;
787 return STATUS_SUCCESS;
790 /**************************************************************************
791 * RtlGetGroupSecurityDescriptor [NTDLL.@]
793 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
794 PSECURITY_DESCRIPTOR pSecurityDescriptor,
796 PBOOLEAN GroupDefaulted)
798 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
800 if ( !lpsd || !Group || !GroupDefaulted )
801 return STATUS_INVALID_PARAMETER;
803 if ( lpsd->Control & SE_GROUP_DEFAULTED )
804 *GroupDefaulted = TRUE;
806 *GroupDefaulted = FALSE;
808 if (lpsd->Control & SE_SELF_RELATIVE)
810 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
811 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
815 *Group = lpsd->Group;
817 return STATUS_SUCCESS;
820 /**************************************************************************
821 * RtlMakeSelfRelativeSD [NTDLL.@]
823 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
824 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
825 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
826 IN OUT LPDWORD lpdwBufferLength)
830 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
831 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
833 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
834 lpdwBufferLength ? *lpdwBufferLength: -1);
836 if (!lpdwBufferLength || !pAbs)
837 return STATUS_INVALID_PARAMETER;
839 length = RtlLengthSecurityDescriptor(pAbs);
840 if (*lpdwBufferLength < length)
842 *lpdwBufferLength = length;
843 return STATUS_BUFFER_TOO_SMALL;
847 return STATUS_INVALID_PARAMETER;
849 if (pAbs->Control & SE_SELF_RELATIVE)
851 memcpy(pRel, pAbs, length);
852 return STATUS_SUCCESS;
855 pRel->Revision = pAbs->Revision;
856 pRel->Sbz1 = pAbs->Sbz1;
857 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
859 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
862 pRel->Owner = offsetRel;
863 length = RtlLengthSid(pAbs->Owner);
864 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
874 pRel->Group = offsetRel;
875 length = RtlLengthSid(pAbs->Group);
876 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
886 pRel->Sacl = offsetRel;
887 length = pAbs->Sacl->AclSize;
888 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
898 pRel->Dacl = offsetRel;
899 length = pAbs->Dacl->AclSize;
900 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
907 return STATUS_SUCCESS;
911 /**************************************************************************
912 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
914 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
915 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
916 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
917 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
919 OUT LPDWORD lpdwDaclSize,
921 OUT LPDWORD lpdwSaclSize,
923 OUT LPDWORD lpdwOwnerSize,
924 OUT PSID pPrimaryGroup,
925 OUT LPDWORD lpdwPrimaryGroupSize)
927 NTSTATUS status = STATUS_SUCCESS;
928 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
929 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
932 !lpdwAbsoluteSecurityDescriptorSize ||
936 !lpdwPrimaryGroupSize ||
937 ~pRel->Control & SE_SELF_RELATIVE)
938 return STATUS_INVALID_PARAMETER;
940 /* Confirm buffers are sufficiently large */
941 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
943 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
944 status = STATUS_BUFFER_TOO_SMALL;
947 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
948 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
950 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
951 status = STATUS_BUFFER_TOO_SMALL;
954 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
955 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
957 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
958 status = STATUS_BUFFER_TOO_SMALL;
962 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
964 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
965 status = STATUS_BUFFER_TOO_SMALL;
969 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
971 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
972 status = STATUS_BUFFER_TOO_SMALL;
975 if (status != STATUS_SUCCESS)
978 /* Copy structures, and clear the ones we don't set */
979 pAbs->Revision = pRel->Revision;
980 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
986 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
988 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
990 memcpy(pSacl, pAcl, pAcl->AclSize);
994 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
996 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
997 memcpy(pDacl, pAcl, pAcl->AclSize);
1003 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1004 memcpy(pOwner, psid, RtlLengthSid(psid));
1005 pAbs->Owner = pOwner;
1010 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1011 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1012 pAbs->Group = pPrimaryGroup;
1018 /******************************************************************************
1019 * RtlGetControlSecurityDescriptor (NTDLL.@)
1021 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1022 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1023 PSECURITY_DESCRIPTOR_CONTROL pControl,
1024 LPDWORD lpdwRevision)
1026 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1028 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1030 *lpdwRevision = lpsd->Revision;
1032 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1033 return STATUS_UNKNOWN_REVISION;
1035 *pControl = lpsd->Control;
1037 return STATUS_SUCCESS;
1040 /******************************************************************************
1041 * RtlSetControlSecurityDescriptor (NTDLL.@)
1043 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1044 PSECURITY_DESCRIPTOR SecurityDescriptor,
1045 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1046 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1048 SECURITY_DESCRIPTOR_CONTROL const immutable
1049 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1050 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1051 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1052 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1055 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1057 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1058 ControlBitsOfInterest, ControlBitsToSet);
1060 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1061 return STATUS_INVALID_PARAMETER;
1063 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1064 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1066 return STATUS_SUCCESS;
1070 /**************************************************************************
1071 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1073 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1074 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1075 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1076 PULONG BufferLength)
1078 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1080 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1081 SelfRelativeSecurityDescriptor, BufferLength);
1083 if (abs->Control & SE_SELF_RELATIVE)
1084 return STATUS_BAD_DESCRIPTOR_FORMAT;
1086 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1087 SelfRelativeSecurityDescriptor, BufferLength);
1092 * access control list's
1095 /**************************************************************************
1096 * RtlCreateAcl [NTDLL.@]
1099 * This should return NTSTATUS
1101 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1103 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1105 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1106 return STATUS_INVALID_PARAMETER;
1107 if (size<sizeof(ACL))
1108 return STATUS_BUFFER_TOO_SMALL;
1110 return STATUS_INVALID_PARAMETER;
1112 memset(acl,'\0',sizeof(ACL));
1113 acl->AclRevision = rev;
1114 acl->AclSize = size;
1116 return STATUS_SUCCESS;
1119 /**************************************************************************
1120 * RtlFirstFreeAce [NTDLL.@]
1121 * looks for the AceCount+1 ACE, and if it is still within the alloced
1122 * ACL, return a pointer to it
1124 BOOLEAN WINAPI RtlFirstFreeAce(
1132 ace = (PACE_HEADER)(acl+1);
1133 for (i=0;i<acl->AceCount;i++) {
1134 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1136 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1138 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1144 /**************************************************************************
1145 * RtlAddAce [NTDLL.@]
1147 NTSTATUS WINAPI RtlAddAce(
1151 PACE_HEADER acestart,
1154 PACE_HEADER ace,targetace;
1157 if (acl->AclRevision != ACL_REVISION)
1158 return STATUS_INVALID_PARAMETER;
1159 if (!RtlFirstFreeAce(acl,&targetace))
1160 return STATUS_INVALID_PARAMETER;
1161 nrofaces=0;ace=acestart;
1162 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1164 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1166 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1167 return STATUS_INVALID_PARAMETER;
1168 memcpy(targetace,acestart,acelen);
1169 acl->AceCount+=nrofaces;
1170 return STATUS_SUCCESS;
1173 /**************************************************************************
1174 * RtlDeleteAce [NTDLL.@]
1176 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1181 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1183 if (STATUS_SUCCESS == status)
1188 /* skip over the ACE we are deleting */
1189 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1192 /* calculate the length of the rest */
1193 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1195 len += pcAce->AceSize;
1196 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1199 /* slide them all backwards */
1200 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1204 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1209 /******************************************************************************
1210 * RtlAddAccessAllowedAce [NTDLL.@]
1212 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1214 IN DWORD dwAceRevision,
1215 IN DWORD AccessMask,
1218 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1221 /******************************************************************************
1222 * RtlAddAccessAllowedAceEx [NTDLL.@]
1224 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1226 IN DWORD dwAceRevision,
1228 IN DWORD AccessMask,
1231 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1233 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1234 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1237 /******************************************************************************
1238 * RtlAddAccessDeniedAce [NTDLL.@]
1240 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1242 IN DWORD dwAceRevision,
1243 IN DWORD AccessMask,
1246 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1249 /******************************************************************************
1250 * RtlAddAccessDeniedAceEx [NTDLL.@]
1252 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1254 IN DWORD dwAceRevision,
1256 IN DWORD AccessMask,
1259 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1261 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1262 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1265 /**************************************************************************
1266 * RtlAddAuditAccessAce [NTDLL.@]
1268 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1270 IN DWORD dwAceRevision,
1271 IN DWORD dwAceFlags,
1272 IN DWORD dwAccessMask,
1274 IN BOOL bAuditSuccess,
1275 IN BOOL bAuditFailure)
1277 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1278 pSid,bAuditSuccess,bAuditFailure);
1281 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1284 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1286 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1287 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1290 /**************************************************************************
1291 * RtlAddAuditAccessAce [NTDLL.@]
1293 NTSTATUS WINAPI RtlAddAuditAccessAce(
1295 IN DWORD dwAceRevision,
1296 IN DWORD dwAccessMask,
1298 IN BOOL bAuditSuccess,
1299 IN BOOL bAuditFailure)
1301 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1304 /******************************************************************************
1305 * RtlValidAcl [NTDLL.@]
1307 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1310 TRACE("(%p)\n", pAcl);
1317 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1318 pAcl->AclRevision > MAX_ACL_REVISION)
1322 ace = (PACE_HEADER)(pAcl+1);
1324 for (i=0;i<=pAcl->AceCount;i++)
1326 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1331 if (i != pAcl->AceCount)
1332 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1338 WARN("(%p): invalid pointer!\n", pAcl);
1345 /******************************************************************************
1346 * RtlGetAce [NTDLL.@]
1348 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1352 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1354 if (dwAceIndex >= pAcl->AceCount)
1355 return STATUS_INVALID_PARAMETER;
1357 ace = (PACE_HEADER)(pAcl + 1);
1358 for (;dwAceIndex;dwAceIndex--)
1359 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1363 return STATUS_SUCCESS;
1370 /******************************************************************************
1371 * RtlAdjustPrivilege [NTDLL.@]
1373 * Enables or disables a privilege from the calling thread or process.
1376 * Privilege [I] Privilege index to change.
1377 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1378 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1379 * Enabled [O] Whether privilege was previously enabled or disabled.
1382 * Success: STATUS_SUCCESS.
1383 * Failure: NTSTATUS code.
1386 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1390 RtlAdjustPrivilege(ULONG Privilege,
1392 BOOLEAN CurrentThread,
1395 TOKEN_PRIVILEGES NewState;
1396 TOKEN_PRIVILEGES OldState;
1401 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1402 CurrentThread ? "TRUE" : "FALSE", Enabled);
1406 Status = NtOpenThreadToken(GetCurrentThread(),
1407 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1413 Status = NtOpenProcessToken(GetCurrentProcess(),
1414 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1418 if (!NT_SUCCESS(Status))
1420 WARN("Retrieving token handle failed (Status %x)\n", Status);
1424 OldState.PrivilegeCount = 1;
1426 NewState.PrivilegeCount = 1;
1427 NewState.Privileges[0].Luid.LowPart = Privilege;
1428 NewState.Privileges[0].Luid.HighPart = 0;
1429 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1431 Status = NtAdjustPrivilegesToken(TokenHandle,
1434 sizeof(TOKEN_PRIVILEGES),
1437 NtClose (TokenHandle);
1438 if (Status == STATUS_NOT_ALL_ASSIGNED)
1440 TRACE("Failed to assign all privileges\n");
1441 return STATUS_PRIVILEGE_NOT_HELD;
1443 if (!NT_SUCCESS(Status))
1445 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1449 if (OldState.PrivilegeCount == 0)
1452 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1454 return STATUS_SUCCESS;
1457 /******************************************************************************
1458 * RtlImpersonateSelf [NTDLL.@]
1460 * Makes an impersonation token that represents the process user and assigns
1461 * to the current thread.
1464 * ImpersonationLevel [I] Level at which to impersonate.
1467 * Success: STATUS_SUCCESS.
1468 * Failure: NTSTATUS code.
1471 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1474 OBJECT_ATTRIBUTES ObjectAttributes;
1475 HANDLE ProcessToken;
1476 HANDLE ImpersonationToken;
1478 TRACE("(%08x)\n", ImpersonationLevel);
1480 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1482 if (Status != STATUS_SUCCESS)
1485 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1487 Status = NtDuplicateToken( ProcessToken,
1492 &ImpersonationToken );
1493 if (Status != STATUS_SUCCESS)
1495 NtClose( ProcessToken );
1499 Status = NtSetInformationThread( GetCurrentThread(),
1500 ThreadImpersonationToken,
1501 &ImpersonationToken,
1502 sizeof(ImpersonationToken) );
1504 NtClose( ImpersonationToken );
1505 NtClose( ProcessToken );
1510 /******************************************************************************
1511 * NtAccessCheck [NTDLL.@]
1512 * ZwAccessCheck [NTDLL.@]
1514 * Checks that a user represented by a token is allowed to access an object
1515 * represented by a security descriptor.
1518 * SecurityDescriptor [I] The security descriptor of the object to check.
1519 * ClientToken [I] Token of the user accessing the object.
1520 * DesiredAccess [I] The desired access to the object.
1521 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1522 * PrivilegeSet [I/O] Privileges used during the access check.
1523 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1524 * GrantedAccess [O] The actual access rights granted.
1525 * AccessStatus [O] The status of the access check.
1531 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1532 * the maximum access rights allowed by the SD and returns them in
1534 * The SecurityDescriptor must have a valid owner and groups present,
1535 * otherwise the function will fail.
1539 PSECURITY_DESCRIPTOR SecurityDescriptor,
1541 ACCESS_MASK DesiredAccess,
1542 PGENERIC_MAPPING GenericMapping,
1543 PPRIVILEGE_SET PrivilegeSet,
1544 PULONG ReturnLength,
1545 PULONG GrantedAccess,
1546 NTSTATUS *AccessStatus)
1550 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1551 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1552 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1554 if (!PrivilegeSet || !ReturnLength)
1555 return STATUS_ACCESS_VIOLATION;
1557 SERVER_START_REQ( access_check )
1559 struct security_descriptor sd;
1564 BOOLEAN defaulted, present;
1566 SECURITY_DESCRIPTOR_CONTROL control;
1568 req->handle = wine_server_obj_handle( ClientToken );
1569 req->desired_access = DesiredAccess;
1570 req->mapping_read = GenericMapping->GenericRead;
1571 req->mapping_write = GenericMapping->GenericWrite;
1572 req->mapping_execute = GenericMapping->GenericExecute;
1573 req->mapping_all = GenericMapping->GenericAll;
1575 /* marshal security descriptor */
1576 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1577 sd.control = control & ~SE_SELF_RELATIVE;
1578 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1579 sd.owner_len = RtlLengthSid( owner );
1580 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1581 sd.group_len = RtlLengthSid( group );
1582 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1583 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1584 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1585 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1587 wine_server_add_data( req, &sd, sizeof(sd) );
1588 wine_server_add_data( req, owner, sd.owner_len );
1589 wine_server_add_data( req, group, sd.group_len );
1590 wine_server_add_data( req, sacl, sd.sacl_len );
1591 wine_server_add_data( req, dacl, sd.dacl_len );
1593 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1595 status = wine_server_call( req );
1597 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1598 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1600 if (status == STATUS_SUCCESS)
1602 *AccessStatus = reply->access_status;
1603 *GrantedAccess = reply->access_granted;
1611 /******************************************************************************
1612 * NtSetSecurityObject [NTDLL.@]
1613 * ZwSetSecurityObject [NTDLL.@]
1615 * Sets specified parts of the object's security descriptor.
1618 * Handle [I] Handle to the object to change security descriptor of.
1619 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1620 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1626 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1627 SECURITY_INFORMATION SecurityInformation,
1628 PSECURITY_DESCRIPTOR SecurityDescriptor)
1631 struct security_descriptor sd;
1632 PACL dacl = NULL, sacl = NULL;
1633 PSID owner = NULL, group = NULL;
1634 BOOLEAN defaulted, present;
1636 SECURITY_DESCRIPTOR_CONTROL control;
1638 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1640 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1642 memset( &sd, 0, sizeof(sd) );
1643 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1644 if (status != STATUS_SUCCESS) return status;
1645 sd.control = control & ~SE_SELF_RELATIVE;
1647 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1649 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1650 if (status != STATUS_SUCCESS) return status;
1651 if (!(sd.owner_len = RtlLengthSid( owner )))
1652 return STATUS_INVALID_SECURITY_DESCR;
1655 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1657 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1658 if (status != STATUS_SUCCESS) return status;
1659 if (!(sd.group_len = RtlLengthSid( group )))
1660 return STATUS_INVALID_SECURITY_DESCR;
1663 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1665 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1666 if (status != STATUS_SUCCESS) return status;
1667 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1668 sd.control |= SE_SACL_PRESENT;
1671 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1673 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1674 if (status != STATUS_SUCCESS) return status;
1675 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1676 sd.control |= SE_DACL_PRESENT;
1679 SERVER_START_REQ( set_security_object )
1681 req->handle = wine_server_obj_handle( Handle );
1682 req->security_info = SecurityInformation;
1684 wine_server_add_data( req, &sd, sizeof(sd) );
1685 wine_server_add_data( req, owner, sd.owner_len );
1686 wine_server_add_data( req, group, sd.group_len );
1687 wine_server_add_data( req, sacl, sd.sacl_len );
1688 wine_server_add_data( req, dacl, sd.dacl_len );
1689 status = wine_server_call( req );
1696 /******************************************************************************
1697 * RtlConvertSidToUnicodeString (NTDLL.@)
1699 * The returned SID is used to access the USER registry hive usually
1701 * the native function returns something like
1702 * "S-1-5-21-0000000000-000000000-0000000000-500";
1704 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1705 PUNICODE_STRING String,
1707 BOOLEAN AllocateString)
1709 static const WCHAR formatW[] = {'-','%','u',0};
1710 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1712 const SID *sid = pSid;
1716 p += sprintfW( p, formatW, sid->Revision );
1717 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1718 sid->IdentifierAuthority.Value[4] ),
1719 MAKEWORD( sid->IdentifierAuthority.Value[3],
1720 sid->IdentifierAuthority.Value[2] )));
1721 for (i = 0; i < sid->SubAuthorityCount; i++)
1722 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1724 len = (p + 1 - buffer) * sizeof(WCHAR);
1726 String->Length = len - sizeof(WCHAR);
1729 String->MaximumLength = len;
1730 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1731 return STATUS_NO_MEMORY;
1733 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1735 memcpy( String->Buffer, buffer, len );
1736 return STATUS_SUCCESS;
1739 /******************************************************************************
1740 * RtlQueryInformationAcl (NTDLL.@)
1742 NTSTATUS WINAPI RtlQueryInformationAcl(
1744 LPVOID pAclInformation,
1745 DWORD nAclInformationLength,
1746 ACL_INFORMATION_CLASS dwAclInformationClass)
1748 NTSTATUS status = STATUS_SUCCESS;
1750 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1751 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1753 switch (dwAclInformationClass)
1755 case AclRevisionInformation:
1757 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1759 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1760 status = STATUS_INVALID_PARAMETER;
1762 paclrev->AclRevision = pAcl->AclRevision;
1767 case AclSizeInformation:
1769 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1771 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1772 status = STATUS_INVALID_PARAMETER;
1775 paclsize->AceCount = pAcl->AceCount;
1776 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1777 if (pAcl->AclSize < paclsize->AclBytesInUse)
1779 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1780 paclsize->AclBytesFree = 0;
1781 paclsize->AclBytesInUse = pAcl->AclSize;
1784 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1791 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1792 status = STATUS_INVALID_PARAMETER;