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 (lpsd->Control & SE_SELF_RELATIVE)
609 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
610 if (sdr->Dacl) *pDacl = (PACL)SELF_RELATIVE_FIELD( sdr, Dacl );
613 else *pDacl = lpsd->Dacl;
615 *lpbDaclDefaulted = (lpsd->Control & SE_DACL_DEFAULTED) != 0;
620 *lpbDaclDefaulted = 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 (lpsd->Control & SE_SELF_RELATIVE)
681 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
682 if (sdr->Sacl) *pSacl = (PACL)SELF_RELATIVE_FIELD( sdr, Sacl );
685 else *pSacl = lpsd->Sacl;
687 *lpbSaclDefaulted = (lpsd->Control & SE_SACL_DEFAULTED) != 0;
689 return STATUS_SUCCESS;
692 /**************************************************************************
693 * RtlSetSaclSecurityDescriptor [NTDLL.@]
695 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
696 PSECURITY_DESCRIPTOR pSecurityDescriptor,
699 BOOLEAN sacldefaulted)
701 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
703 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
704 return STATUS_UNKNOWN_REVISION;
705 if (lpsd->Control & SE_SELF_RELATIVE)
706 return STATUS_INVALID_SECURITY_DESCR;
708 lpsd->Control &= ~SE_SACL_PRESENT;
711 lpsd->Control |= SE_SACL_PRESENT;
714 lpsd->Control |= SE_SACL_DEFAULTED;
716 lpsd->Control &= ~SE_SACL_DEFAULTED;
717 return STATUS_SUCCESS;
720 /**************************************************************************
721 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
723 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
724 PSECURITY_DESCRIPTOR pSecurityDescriptor,
726 PBOOLEAN OwnerDefaulted)
728 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
730 if ( !lpsd || !Owner || !OwnerDefaulted )
731 return STATUS_INVALID_PARAMETER;
733 if ( lpsd->Control & SE_OWNER_DEFAULTED )
734 *OwnerDefaulted = TRUE;
736 *OwnerDefaulted = FALSE;
738 if (lpsd->Control & SE_SELF_RELATIVE)
740 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
741 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
745 *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->Control & SE_SELF_RELATIVE)
816 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
817 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
821 *Group = lpsd->Group;
823 return STATUS_SUCCESS;
826 /**************************************************************************
827 * RtlMakeSelfRelativeSD [NTDLL.@]
829 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
830 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
831 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
832 IN OUT LPDWORD lpdwBufferLength)
836 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
837 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
839 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
840 lpdwBufferLength ? *lpdwBufferLength: -1);
842 if (!lpdwBufferLength || !pAbs)
843 return STATUS_INVALID_PARAMETER;
845 length = RtlLengthSecurityDescriptor(pAbs);
846 if (*lpdwBufferLength < length)
848 *lpdwBufferLength = length;
849 return STATUS_BUFFER_TOO_SMALL;
853 return STATUS_INVALID_PARAMETER;
855 if (pAbs->Control & SE_SELF_RELATIVE)
857 memcpy(pRel, pAbs, length);
858 return STATUS_SUCCESS;
861 pRel->Revision = pAbs->Revision;
862 pRel->Sbz1 = pAbs->Sbz1;
863 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
865 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
868 pRel->Owner = offsetRel;
869 length = RtlLengthSid(pAbs->Owner);
870 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
880 pRel->Group = offsetRel;
881 length = RtlLengthSid(pAbs->Group);
882 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
892 pRel->Sacl = offsetRel;
893 length = pAbs->Sacl->AclSize;
894 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
904 pRel->Dacl = offsetRel;
905 length = pAbs->Dacl->AclSize;
906 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
913 return STATUS_SUCCESS;
917 /**************************************************************************
918 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
920 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
921 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
922 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
923 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
925 OUT LPDWORD lpdwDaclSize,
927 OUT LPDWORD lpdwSaclSize,
929 OUT LPDWORD lpdwOwnerSize,
930 OUT PSID pPrimaryGroup,
931 OUT LPDWORD lpdwPrimaryGroupSize)
933 NTSTATUS status = STATUS_SUCCESS;
934 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
935 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
938 !lpdwAbsoluteSecurityDescriptorSize ||
942 !lpdwPrimaryGroupSize ||
943 ~pRel->Control & SE_SELF_RELATIVE)
944 return STATUS_INVALID_PARAMETER;
946 /* Confirm buffers are sufficiently large */
947 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
949 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
950 status = STATUS_BUFFER_TOO_SMALL;
953 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
954 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
956 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
957 status = STATUS_BUFFER_TOO_SMALL;
960 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
961 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
963 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
964 status = STATUS_BUFFER_TOO_SMALL;
968 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
970 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
971 status = STATUS_BUFFER_TOO_SMALL;
975 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
977 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
978 status = STATUS_BUFFER_TOO_SMALL;
981 if (status != STATUS_SUCCESS)
984 /* Copy structures, and clear the ones we don't set */
985 pAbs->Revision = pRel->Revision;
986 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
992 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
994 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
996 memcpy(pSacl, pAcl, pAcl->AclSize);
1000 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1002 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1003 memcpy(pDacl, pAcl, pAcl->AclSize);
1009 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1010 memcpy(pOwner, psid, RtlLengthSid(psid));
1011 pAbs->Owner = pOwner;
1016 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1017 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1018 pAbs->Group = pPrimaryGroup;
1024 /******************************************************************************
1025 * RtlGetControlSecurityDescriptor (NTDLL.@)
1027 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1028 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1029 PSECURITY_DESCRIPTOR_CONTROL pControl,
1030 LPDWORD lpdwRevision)
1032 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1034 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1036 *lpdwRevision = lpsd->Revision;
1038 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1039 return STATUS_UNKNOWN_REVISION;
1041 *pControl = lpsd->Control;
1043 return STATUS_SUCCESS;
1046 /******************************************************************************
1047 * RtlSetControlSecurityDescriptor (NTDLL.@)
1049 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1050 PSECURITY_DESCRIPTOR SecurityDescriptor,
1051 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1052 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1054 SECURITY_DESCRIPTOR_CONTROL const immutable
1055 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1056 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1057 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1058 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1061 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1063 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1064 ControlBitsOfInterest, ControlBitsToSet);
1066 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1067 return STATUS_INVALID_PARAMETER;
1069 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1070 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1072 return STATUS_SUCCESS;
1076 /**************************************************************************
1077 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1079 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1080 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1081 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1082 PULONG BufferLength)
1084 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1086 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1087 SelfRelativeSecurityDescriptor, BufferLength);
1089 if (abs->Control & SE_SELF_RELATIVE)
1090 return STATUS_BAD_DESCRIPTOR_FORMAT;
1092 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1093 SelfRelativeSecurityDescriptor, BufferLength);
1098 * access control list's
1101 /**************************************************************************
1102 * RtlCreateAcl [NTDLL.@]
1105 * This should return NTSTATUS
1107 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1109 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1111 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1112 return STATUS_INVALID_PARAMETER;
1113 if (size<sizeof(ACL))
1114 return STATUS_BUFFER_TOO_SMALL;
1116 return STATUS_INVALID_PARAMETER;
1118 memset(acl,'\0',sizeof(ACL));
1119 acl->AclRevision = rev;
1120 acl->AclSize = size;
1122 return STATUS_SUCCESS;
1125 /**************************************************************************
1126 * RtlFirstFreeAce [NTDLL.@]
1127 * looks for the AceCount+1 ACE, and if it is still within the alloced
1128 * ACL, return a pointer to it
1130 BOOLEAN WINAPI RtlFirstFreeAce(
1138 ace = (PACE_HEADER)(acl+1);
1139 for (i=0;i<acl->AceCount;i++) {
1140 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1142 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1144 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1150 /**************************************************************************
1151 * RtlAddAce [NTDLL.@]
1153 NTSTATUS WINAPI RtlAddAce(
1157 PACE_HEADER acestart,
1160 PACE_HEADER ace,targetace;
1163 if (acl->AclRevision != ACL_REVISION)
1164 return STATUS_INVALID_PARAMETER;
1165 if (!RtlFirstFreeAce(acl,&targetace))
1166 return STATUS_INVALID_PARAMETER;
1167 nrofaces=0;ace=acestart;
1168 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1170 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1172 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1173 return STATUS_INVALID_PARAMETER;
1174 memcpy(targetace,acestart,acelen);
1175 acl->AceCount+=nrofaces;
1176 return STATUS_SUCCESS;
1179 /**************************************************************************
1180 * RtlDeleteAce [NTDLL.@]
1182 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1187 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1189 if (STATUS_SUCCESS == status)
1194 /* skip over the ACE we are deleting */
1195 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1198 /* calculate the length of the rest */
1199 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1201 len += pcAce->AceSize;
1202 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1205 /* slide them all backwards */
1206 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1210 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1215 /******************************************************************************
1216 * RtlAddAccessAllowedAce [NTDLL.@]
1218 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1220 IN DWORD dwAceRevision,
1221 IN DWORD AccessMask,
1224 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1227 /******************************************************************************
1228 * RtlAddAccessAllowedAceEx [NTDLL.@]
1230 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1232 IN DWORD dwAceRevision,
1234 IN DWORD AccessMask,
1237 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1239 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1240 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1243 /******************************************************************************
1244 * RtlAddAccessDeniedAce [NTDLL.@]
1246 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1248 IN DWORD dwAceRevision,
1249 IN DWORD AccessMask,
1252 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1255 /******************************************************************************
1256 * RtlAddAccessDeniedAceEx [NTDLL.@]
1258 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1260 IN DWORD dwAceRevision,
1262 IN DWORD AccessMask,
1265 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1267 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1268 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1271 /**************************************************************************
1272 * RtlAddAuditAccessAce [NTDLL.@]
1274 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1276 IN DWORD dwAceRevision,
1277 IN DWORD dwAceFlags,
1278 IN DWORD dwAccessMask,
1280 IN BOOL bAuditSuccess,
1281 IN BOOL bAuditFailure)
1283 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1284 pSid,bAuditSuccess,bAuditFailure);
1287 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1290 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1292 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1293 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1296 /**************************************************************************
1297 * RtlAddAuditAccessAce [NTDLL.@]
1299 NTSTATUS WINAPI RtlAddAuditAccessAce(
1301 IN DWORD dwAceRevision,
1302 IN DWORD dwAccessMask,
1304 IN BOOL bAuditSuccess,
1305 IN BOOL bAuditFailure)
1307 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1310 /******************************************************************************
1311 * RtlValidAcl [NTDLL.@]
1313 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1316 TRACE("(%p)\n", pAcl);
1323 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1324 pAcl->AclRevision > MAX_ACL_REVISION)
1328 ace = (PACE_HEADER)(pAcl+1);
1330 for (i=0;i<=pAcl->AceCount;i++)
1332 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1337 if (i != pAcl->AceCount)
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);
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 if (!PrivilegeSet || !ReturnLength)
1561 return STATUS_ACCESS_VIOLATION;
1563 SERVER_START_REQ( access_check )
1565 struct security_descriptor sd;
1570 BOOLEAN defaulted, present;
1572 SECURITY_DESCRIPTOR_CONTROL control;
1574 req->handle = wine_server_obj_handle( ClientToken );
1575 req->desired_access = DesiredAccess;
1576 req->mapping_read = GenericMapping->GenericRead;
1577 req->mapping_write = GenericMapping->GenericWrite;
1578 req->mapping_execute = GenericMapping->GenericExecute;
1579 req->mapping_all = GenericMapping->GenericAll;
1581 /* marshal security descriptor */
1582 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1583 sd.control = control & ~SE_SELF_RELATIVE;
1584 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1585 sd.owner_len = RtlLengthSid( owner );
1586 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1587 sd.group_len = RtlLengthSid( group );
1588 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1589 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1590 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1591 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1593 wine_server_add_data( req, &sd, sizeof(sd) );
1594 wine_server_add_data( req, owner, sd.owner_len );
1595 wine_server_add_data( req, group, sd.group_len );
1596 wine_server_add_data( req, sacl, sd.sacl_len );
1597 wine_server_add_data( req, dacl, sd.dacl_len );
1599 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1601 status = wine_server_call( req );
1603 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1604 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1606 if (status == STATUS_SUCCESS)
1608 *AccessStatus = reply->access_status;
1609 *GrantedAccess = reply->access_granted;
1617 /******************************************************************************
1618 * NtSetSecurityObject [NTDLL.@]
1619 * ZwSetSecurityObject [NTDLL.@]
1621 * Sets specified parts of the object's security descriptor.
1624 * Handle [I] Handle to the object to change security descriptor of.
1625 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1626 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1632 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1633 SECURITY_INFORMATION SecurityInformation,
1634 PSECURITY_DESCRIPTOR SecurityDescriptor)
1637 struct security_descriptor sd;
1638 PACL dacl = NULL, sacl = NULL;
1639 PSID owner = NULL, group = NULL;
1640 BOOLEAN defaulted, present;
1642 SECURITY_DESCRIPTOR_CONTROL control;
1644 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1646 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1648 memset( &sd, 0, sizeof(sd) );
1649 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1650 if (status != STATUS_SUCCESS) return status;
1651 sd.control = control & ~SE_SELF_RELATIVE;
1653 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1655 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1656 if (status != STATUS_SUCCESS) return status;
1657 if (!(sd.owner_len = RtlLengthSid( owner )))
1658 return STATUS_INVALID_SECURITY_DESCR;
1661 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1663 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1664 if (status != STATUS_SUCCESS) return status;
1665 if (!(sd.group_len = RtlLengthSid( group )))
1666 return STATUS_INVALID_SECURITY_DESCR;
1669 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1671 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1672 if (status != STATUS_SUCCESS) return status;
1673 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1674 sd.control |= SE_SACL_PRESENT;
1677 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1679 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1680 if (status != STATUS_SUCCESS) return status;
1681 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1682 sd.control |= SE_DACL_PRESENT;
1685 SERVER_START_REQ( set_security_object )
1687 req->handle = wine_server_obj_handle( Handle );
1688 req->security_info = SecurityInformation;
1690 wine_server_add_data( req, &sd, sizeof(sd) );
1691 wine_server_add_data( req, owner, sd.owner_len );
1692 wine_server_add_data( req, group, sd.group_len );
1693 wine_server_add_data( req, sacl, sd.sacl_len );
1694 wine_server_add_data( req, dacl, sd.dacl_len );
1695 status = wine_server_call( req );
1702 /******************************************************************************
1703 * RtlConvertSidToUnicodeString (NTDLL.@)
1705 * The returned SID is used to access the USER registry hive usually
1707 * the native function returns something like
1708 * "S-1-5-21-0000000000-000000000-0000000000-500";
1710 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1711 PUNICODE_STRING String,
1713 BOOLEAN AllocateString)
1715 static const WCHAR formatW[] = {'-','%','u',0};
1716 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1718 const SID *sid = pSid;
1722 p += sprintfW( p, formatW, sid->Revision );
1723 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1724 sid->IdentifierAuthority.Value[4] ),
1725 MAKEWORD( sid->IdentifierAuthority.Value[3],
1726 sid->IdentifierAuthority.Value[2] )));
1727 for (i = 0; i < sid->SubAuthorityCount; i++)
1728 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1730 len = (p + 1 - buffer) * sizeof(WCHAR);
1732 String->Length = len - sizeof(WCHAR);
1735 String->MaximumLength = len;
1736 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1737 return STATUS_NO_MEMORY;
1739 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1741 memcpy( String->Buffer, buffer, len );
1742 return STATUS_SUCCESS;
1745 /******************************************************************************
1746 * RtlQueryInformationAcl (NTDLL.@)
1748 NTSTATUS WINAPI RtlQueryInformationAcl(
1750 LPVOID pAclInformation,
1751 DWORD nAclInformationLength,
1752 ACL_INFORMATION_CLASS dwAclInformationClass)
1754 NTSTATUS status = STATUS_SUCCESS;
1756 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1757 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1759 switch (dwAclInformationClass)
1761 case AclRevisionInformation:
1763 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1765 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1766 status = STATUS_INVALID_PARAMETER;
1768 paclrev->AclRevision = pAcl->AclRevision;
1773 case AclSizeInformation:
1775 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1777 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1778 status = STATUS_INVALID_PARAMETER;
1781 paclsize->AceCount = pAcl->AceCount;
1782 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1783 if (pAcl->AclSize < paclsize->AclBytesInUse)
1785 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1786 paclsize->AclBytesFree = 0;
1787 paclsize->AclBytesInUse = pAcl->AclSize;
1790 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1797 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1798 status = STATUS_INVALID_PARAMETER;