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;
170 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
172 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
174 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
176 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
178 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
180 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
182 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
186 return STATUS_SUCCESS;
189 /******************************************************************************
190 * RtlEqualSid [NTDLL.@]
192 * Determine if two SIDs are equal.
195 * pSid1 [I] Source SID
196 * pSid2 [I] SID to compare with
199 * TRUE, if pSid1 is equal to pSid2,
202 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
204 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
207 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
210 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
216 /******************************************************************************
217 * RtlEqualPrefixSid [NTDLL.@]
219 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
221 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
224 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
227 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
234 /******************************************************************************
235 * RtlFreeSid [NTDLL.@]
237 * Free the resources used by a SID.
240 * pSid [I] SID to Free.
245 DWORD WINAPI RtlFreeSid(PSID pSid)
247 TRACE("(%p)\n", pSid);
248 RtlFreeHeap( GetProcessHeap(), 0, pSid );
249 return STATUS_SUCCESS;
252 /**************************************************************************
253 * RtlLengthRequiredSid [NTDLL.@]
255 * Determine the amount of memory a SID will use
258 * nrofsubauths [I] Number of Sub Authorities in the SID.
261 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
263 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
265 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
268 /**************************************************************************
269 * RtlLengthSid [NTDLL.@]
271 * Determine the amount of memory a SID is using
274 * pSid [I] SID to get the size of.
277 * The size, in bytes, of pSid.
279 DWORD WINAPI RtlLengthSid(PSID pSid)
281 TRACE("sid=%p\n",pSid);
283 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
286 /**************************************************************************
287 * RtlInitializeSid [NTDLL.@]
292 * pSid [I] SID to initialise
293 * pIdentifierAuthority [I] Identifier Authority
294 * nSubAuthorityCount [I] Number of Sub Authorities
297 * Success: TRUE. pSid is initialised with the details given.
298 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
300 BOOL WINAPI RtlInitializeSid(
302 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
303 BYTE nSubAuthorityCount)
308 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
311 pisid->Revision = SID_REVISION;
312 pisid->SubAuthorityCount = nSubAuthorityCount;
313 if (pIdentifierAuthority)
314 pisid->IdentifierAuthority = *pIdentifierAuthority;
316 for (i = 0; i < nSubAuthorityCount; i++)
317 *RtlSubAuthoritySid(pSid, i) = 0;
322 /**************************************************************************
323 * RtlSubAuthoritySid [NTDLL.@]
325 * Return the Sub Authority of a SID
328 * pSid [I] SID to get the Sub Authority from.
329 * nSubAuthority [I] Sub Authority number.
332 * A pointer to The Sub Authority value of pSid.
334 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
336 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
339 /**************************************************************************
340 * RtlIdentifierAuthoritySid [NTDLL.@]
342 * Return the Identifier Authority of a SID.
345 * pSid [I] SID to get the Identifier Authority from.
348 * A pointer to the Identifier Authority value of pSid.
350 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
352 return &(((SID*)pSid)->IdentifierAuthority);
355 /**************************************************************************
356 * RtlSubAuthorityCountSid [NTDLL.@]
358 * Get the number of Sub Authorities in a SID.
361 * pSid [I] SID to get the count from.
364 * A pointer to the Sub Authority count of pSid.
366 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
368 return &(((SID*)pSid)->SubAuthorityCount);
371 /**************************************************************************
372 * RtlCopySid [NTDLL.@]
374 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
376 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
377 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
380 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
383 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
386 /******************************************************************************
387 * RtlValidSid [NTDLL.@]
389 * Determine if a SID is valid.
392 * pSid [I] SID to check
395 * TRUE if pSid is valid,
398 BOOLEAN WINAPI RtlValidSid( PSID pSid )
404 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
405 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
412 WARN("(%p): invalid pointer!\n", pSid);
421 * security descriptor functions
424 /**************************************************************************
425 * RtlCreateSecurityDescriptor [NTDLL.@]
427 * Initialise a SECURITY_DESCRIPTOR.
430 * lpsd [O] Descriptor to initialise.
431 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
434 * Success: STATUS_SUCCESS.
435 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
437 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
438 PSECURITY_DESCRIPTOR lpsd,
441 if (rev!=SECURITY_DESCRIPTOR_REVISION)
442 return STATUS_UNKNOWN_REVISION;
443 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
444 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
445 return STATUS_SUCCESS;
448 /**************************************************************************
449 * RtlCopySecurityDescriptor [NTDLL.@]
451 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
454 * pSourceSD [O] SD to copy from.
455 * pDestinationSD [I] Destination SD.
458 * Success: STATUS_SUCCESS.
459 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
461 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
467 if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
469 SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
470 SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
472 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
473 return STATUS_UNKNOWN_REVISION;
478 Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
479 length = RtlLengthSid( Owner );
480 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
484 Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
485 length = RtlLengthSid( Group );
486 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
488 if ((src->Control & SE_SACL_PRESENT) && src->Sacl)
490 Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
491 copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
493 if ((src->Control & SE_DACL_PRESENT) && src->Dacl)
495 Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
496 copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
501 SECURITY_DESCRIPTOR *src = pSourceSD;
502 SECURITY_DESCRIPTOR *dst = pDestinationSD;
504 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
505 return STATUS_UNKNOWN_REVISION;
510 length = RtlLengthSid( src->Owner );
511 dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
512 RtlCopySid(length, dst->Owner, src->Owner);
516 length = RtlLengthSid( src->Group );
517 dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
518 RtlCopySid(length, dst->Group, src->Group);
520 if (src->Control & SE_SACL_PRESENT)
522 length = src->Sacl->AclSize;
523 dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
524 copy_acl(length, dst->Sacl, src->Sacl);
526 if (src->Control & SE_DACL_PRESENT)
528 length = src->Dacl->AclSize;
529 dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
530 copy_acl(length, dst->Dacl, src->Dacl);
534 return STATUS_SUCCESS;
537 /**************************************************************************
538 * RtlValidSecurityDescriptor [NTDLL.@]
540 * Determine if a SECURITY_DESCRIPTOR is valid.
543 * SecurityDescriptor [I] Descriptor to check.
546 * Success: STATUS_SUCCESS.
547 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
549 NTSTATUS WINAPI RtlValidSecurityDescriptor(
550 PSECURITY_DESCRIPTOR SecurityDescriptor)
552 if ( ! SecurityDescriptor )
553 return STATUS_INVALID_SECURITY_DESCR;
554 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
555 return STATUS_UNKNOWN_REVISION;
557 return STATUS_SUCCESS;
560 /**************************************************************************
561 * RtlLengthSecurityDescriptor [NTDLL.@]
563 ULONG WINAPI RtlLengthSecurityDescriptor(
564 PSECURITY_DESCRIPTOR pSecurityDescriptor)
568 if ( pSecurityDescriptor == NULL )
571 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
573 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
575 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
576 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
577 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
578 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
579 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
580 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
584 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
586 if (sd->Owner) size += RtlLengthSid( sd->Owner );
587 if (sd->Group) size += RtlLengthSid( sd->Group );
588 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
589 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
594 /******************************************************************************
595 * RtlGetDaclSecurityDescriptor [NTDLL.@]
598 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
599 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
600 OUT PBOOLEAN lpbDaclPresent,
602 OUT PBOOLEAN lpbDaclDefaulted)
604 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
606 TRACE("(%p,%p,%p,%p)\n",
607 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
609 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
610 return STATUS_UNKNOWN_REVISION ;
612 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
614 if (lpsd->Control & SE_SELF_RELATIVE)
616 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
617 if (sdr->Dacl) *pDacl = (PACL)SELF_RELATIVE_FIELD( sdr, Dacl );
620 else *pDacl = lpsd->Dacl;
622 *lpbDaclDefaulted = (lpsd->Control & SE_DACL_DEFAULTED) != 0;
627 *lpbDaclDefaulted = 0;
630 return STATUS_SUCCESS;
633 /**************************************************************************
634 * RtlSetDaclSecurityDescriptor [NTDLL.@]
636 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
637 PSECURITY_DESCRIPTOR pSecurityDescriptor,
640 BOOLEAN dacldefaulted )
642 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
644 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
645 return STATUS_UNKNOWN_REVISION;
646 if (lpsd->Control & SE_SELF_RELATIVE)
647 return STATUS_INVALID_SECURITY_DESCR;
651 lpsd->Control &= ~SE_DACL_PRESENT;
652 return STATUS_SUCCESS;
655 lpsd->Control |= SE_DACL_PRESENT;
659 lpsd->Control |= SE_DACL_DEFAULTED;
661 lpsd->Control &= ~SE_DACL_DEFAULTED;
663 return STATUS_SUCCESS;
666 /******************************************************************************
667 * RtlGetSaclSecurityDescriptor [NTDLL.@]
670 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
671 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
672 OUT PBOOLEAN lpbSaclPresent,
674 OUT PBOOLEAN lpbSaclDefaulted)
676 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
678 TRACE("(%p,%p,%p,%p)\n",
679 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
681 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
682 return STATUS_UNKNOWN_REVISION;
684 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
686 if (lpsd->Control & SE_SELF_RELATIVE)
688 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
689 if (sdr->Sacl) *pSacl = (PACL)SELF_RELATIVE_FIELD( sdr, Sacl );
692 else *pSacl = lpsd->Sacl;
694 *lpbSaclDefaulted = (lpsd->Control & SE_SACL_DEFAULTED) != 0;
696 return STATUS_SUCCESS;
699 /**************************************************************************
700 * RtlSetSaclSecurityDescriptor [NTDLL.@]
702 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
703 PSECURITY_DESCRIPTOR pSecurityDescriptor,
706 BOOLEAN sacldefaulted)
708 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
710 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
711 return STATUS_UNKNOWN_REVISION;
712 if (lpsd->Control & SE_SELF_RELATIVE)
713 return STATUS_INVALID_SECURITY_DESCR;
715 lpsd->Control &= ~SE_SACL_PRESENT;
718 lpsd->Control |= SE_SACL_PRESENT;
721 lpsd->Control |= SE_SACL_DEFAULTED;
723 lpsd->Control &= ~SE_SACL_DEFAULTED;
724 return STATUS_SUCCESS;
727 /**************************************************************************
728 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
730 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
731 PSECURITY_DESCRIPTOR pSecurityDescriptor,
733 PBOOLEAN OwnerDefaulted)
735 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
737 if ( !lpsd || !Owner || !OwnerDefaulted )
738 return STATUS_INVALID_PARAMETER;
740 if ( lpsd->Control & SE_OWNER_DEFAULTED )
741 *OwnerDefaulted = TRUE;
743 *OwnerDefaulted = FALSE;
745 if (lpsd->Control & SE_SELF_RELATIVE)
747 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
748 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
752 *Owner = lpsd->Owner;
754 return STATUS_SUCCESS;
757 /**************************************************************************
758 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
760 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
761 PSECURITY_DESCRIPTOR pSecurityDescriptor,
763 BOOLEAN ownerdefaulted)
765 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
767 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
768 return STATUS_UNKNOWN_REVISION;
769 if (lpsd->Control & SE_SELF_RELATIVE)
770 return STATUS_INVALID_SECURITY_DESCR;
774 lpsd->Control |= SE_OWNER_DEFAULTED;
776 lpsd->Control &= ~SE_OWNER_DEFAULTED;
777 return STATUS_SUCCESS;
780 /**************************************************************************
781 * RtlSetGroupSecurityDescriptor [NTDLL.@]
783 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
784 PSECURITY_DESCRIPTOR pSecurityDescriptor,
786 BOOLEAN groupdefaulted)
788 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
790 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
791 return STATUS_UNKNOWN_REVISION;
792 if (lpsd->Control & SE_SELF_RELATIVE)
793 return STATUS_INVALID_SECURITY_DESCR;
797 lpsd->Control |= SE_GROUP_DEFAULTED;
799 lpsd->Control &= ~SE_GROUP_DEFAULTED;
800 return STATUS_SUCCESS;
803 /**************************************************************************
804 * RtlGetGroupSecurityDescriptor [NTDLL.@]
806 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
807 PSECURITY_DESCRIPTOR pSecurityDescriptor,
809 PBOOLEAN GroupDefaulted)
811 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
813 if ( !lpsd || !Group || !GroupDefaulted )
814 return STATUS_INVALID_PARAMETER;
816 if ( lpsd->Control & SE_GROUP_DEFAULTED )
817 *GroupDefaulted = TRUE;
819 *GroupDefaulted = FALSE;
821 if (lpsd->Control & SE_SELF_RELATIVE)
823 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
824 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
828 *Group = lpsd->Group;
830 return STATUS_SUCCESS;
833 /**************************************************************************
834 * RtlMakeSelfRelativeSD [NTDLL.@]
836 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
837 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
838 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
839 IN OUT LPDWORD lpdwBufferLength)
843 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
844 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
846 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
847 lpdwBufferLength ? *lpdwBufferLength: -1);
849 if (!lpdwBufferLength || !pAbs)
850 return STATUS_INVALID_PARAMETER;
852 length = RtlLengthSecurityDescriptor(pAbs);
853 if (*lpdwBufferLength < length)
855 *lpdwBufferLength = length;
856 return STATUS_BUFFER_TOO_SMALL;
860 return STATUS_INVALID_PARAMETER;
862 if (pAbs->Control & SE_SELF_RELATIVE)
864 memcpy(pRel, pAbs, length);
865 return STATUS_SUCCESS;
868 pRel->Revision = pAbs->Revision;
869 pRel->Sbz1 = pAbs->Sbz1;
870 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
872 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
875 pRel->Owner = offsetRel;
876 length = RtlLengthSid(pAbs->Owner);
877 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
887 pRel->Group = offsetRel;
888 length = RtlLengthSid(pAbs->Group);
889 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
899 pRel->Sacl = offsetRel;
900 length = pAbs->Sacl->AclSize;
901 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
911 pRel->Dacl = offsetRel;
912 length = pAbs->Dacl->AclSize;
913 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
920 return STATUS_SUCCESS;
924 /**************************************************************************
925 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
927 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
928 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
929 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
930 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
932 OUT LPDWORD lpdwDaclSize,
934 OUT LPDWORD lpdwSaclSize,
936 OUT LPDWORD lpdwOwnerSize,
937 OUT PSID pPrimaryGroup,
938 OUT LPDWORD lpdwPrimaryGroupSize)
940 NTSTATUS status = STATUS_SUCCESS;
941 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
942 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
945 !lpdwAbsoluteSecurityDescriptorSize ||
949 !lpdwPrimaryGroupSize ||
950 ~pRel->Control & SE_SELF_RELATIVE)
951 return STATUS_INVALID_PARAMETER;
953 /* Confirm buffers are sufficiently large */
954 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
956 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
957 status = STATUS_BUFFER_TOO_SMALL;
960 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
961 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
963 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
964 status = STATUS_BUFFER_TOO_SMALL;
967 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
968 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
970 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
971 status = STATUS_BUFFER_TOO_SMALL;
975 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
977 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
978 status = STATUS_BUFFER_TOO_SMALL;
982 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
984 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
985 status = STATUS_BUFFER_TOO_SMALL;
988 if (status != STATUS_SUCCESS)
991 /* Copy structures, and clear the ones we don't set */
992 pAbs->Revision = pRel->Revision;
993 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
999 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
1001 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
1003 memcpy(pSacl, pAcl, pAcl->AclSize);
1007 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1009 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1010 memcpy(pDacl, pAcl, pAcl->AclSize);
1016 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1017 memcpy(pOwner, psid, RtlLengthSid(psid));
1018 pAbs->Owner = pOwner;
1023 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1024 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1025 pAbs->Group = pPrimaryGroup;
1031 /******************************************************************************
1032 * RtlGetControlSecurityDescriptor (NTDLL.@)
1034 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1035 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1036 PSECURITY_DESCRIPTOR_CONTROL pControl,
1037 LPDWORD lpdwRevision)
1039 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1041 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1043 *lpdwRevision = lpsd->Revision;
1045 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1046 return STATUS_UNKNOWN_REVISION;
1048 *pControl = lpsd->Control;
1050 return STATUS_SUCCESS;
1053 /******************************************************************************
1054 * RtlSetControlSecurityDescriptor (NTDLL.@)
1056 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1057 PSECURITY_DESCRIPTOR SecurityDescriptor,
1058 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1059 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1061 SECURITY_DESCRIPTOR_CONTROL const immutable
1062 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1063 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1064 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1065 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1068 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1070 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1071 ControlBitsOfInterest, ControlBitsToSet);
1073 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1074 return STATUS_INVALID_PARAMETER;
1076 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1077 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1079 return STATUS_SUCCESS;
1083 /**************************************************************************
1084 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1086 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1087 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1088 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1089 PULONG BufferLength)
1091 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1093 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1094 SelfRelativeSecurityDescriptor, BufferLength);
1096 if (abs->Control & SE_SELF_RELATIVE)
1097 return STATUS_BAD_DESCRIPTOR_FORMAT;
1099 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1100 SelfRelativeSecurityDescriptor, BufferLength);
1105 * access control list's
1108 /**************************************************************************
1109 * RtlCreateAcl [NTDLL.@]
1112 * This should return NTSTATUS
1114 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1116 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1118 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1119 return STATUS_INVALID_PARAMETER;
1120 if (size<sizeof(ACL))
1121 return STATUS_BUFFER_TOO_SMALL;
1123 return STATUS_INVALID_PARAMETER;
1125 memset(acl,'\0',sizeof(ACL));
1126 acl->AclRevision = rev;
1127 acl->AclSize = size;
1129 return STATUS_SUCCESS;
1132 /**************************************************************************
1133 * RtlFirstFreeAce [NTDLL.@]
1134 * looks for the AceCount+1 ACE, and if it is still within the alloced
1135 * ACL, return a pointer to it
1137 BOOLEAN WINAPI RtlFirstFreeAce(
1145 ace = (PACE_HEADER)(acl+1);
1146 for (i=0;i<acl->AceCount;i++) {
1147 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1149 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1151 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1157 /**************************************************************************
1158 * RtlAddAce [NTDLL.@]
1160 NTSTATUS WINAPI RtlAddAce(
1164 PACE_HEADER acestart,
1167 PACE_HEADER ace,targetace;
1170 if (acl->AclRevision != ACL_REVISION)
1171 return STATUS_INVALID_PARAMETER;
1172 if (!RtlFirstFreeAce(acl,&targetace))
1173 return STATUS_INVALID_PARAMETER;
1174 nrofaces=0;ace=acestart;
1175 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1177 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1179 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1180 return STATUS_INVALID_PARAMETER;
1181 memcpy(targetace,acestart,acelen);
1182 acl->AceCount+=nrofaces;
1183 return STATUS_SUCCESS;
1186 /**************************************************************************
1187 * RtlDeleteAce [NTDLL.@]
1189 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1194 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1196 if (STATUS_SUCCESS == status)
1201 /* skip over the ACE we are deleting */
1202 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1205 /* calculate the length of the rest */
1206 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1208 len += pcAce->AceSize;
1209 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1212 /* slide them all backwards */
1213 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1217 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1222 /******************************************************************************
1223 * RtlAddAccessAllowedAce [NTDLL.@]
1225 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1227 IN DWORD dwAceRevision,
1228 IN DWORD AccessMask,
1231 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1234 /******************************************************************************
1235 * RtlAddAccessAllowedAceEx [NTDLL.@]
1237 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1239 IN DWORD dwAceRevision,
1241 IN DWORD AccessMask,
1244 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1246 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1247 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1250 /******************************************************************************
1251 * RtlAddAccessDeniedAce [NTDLL.@]
1253 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1255 IN DWORD dwAceRevision,
1256 IN DWORD AccessMask,
1259 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1262 /******************************************************************************
1263 * RtlAddAccessDeniedAceEx [NTDLL.@]
1265 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1267 IN DWORD dwAceRevision,
1269 IN DWORD AccessMask,
1272 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1274 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1275 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1278 /**************************************************************************
1279 * RtlAddAuditAccessAce [NTDLL.@]
1281 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1283 IN DWORD dwAceRevision,
1284 IN DWORD dwAceFlags,
1285 IN DWORD dwAccessMask,
1287 IN BOOL bAuditSuccess,
1288 IN BOOL bAuditFailure)
1290 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1291 pSid,bAuditSuccess,bAuditFailure);
1294 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1297 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1299 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1300 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1303 /**************************************************************************
1304 * RtlAddAuditAccessAce [NTDLL.@]
1306 NTSTATUS WINAPI RtlAddAuditAccessAce(
1308 IN DWORD dwAceRevision,
1309 IN DWORD dwAccessMask,
1311 IN BOOL bAuditSuccess,
1312 IN BOOL bAuditFailure)
1314 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1317 /******************************************************************************
1318 * RtlValidAcl [NTDLL.@]
1320 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1323 TRACE("(%p)\n", pAcl);
1330 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1331 pAcl->AclRevision > MAX_ACL_REVISION)
1335 ace = (PACE_HEADER)(pAcl+1);
1337 for (i=0;i<=pAcl->AceCount;i++)
1339 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1344 if (i != pAcl->AceCount)
1345 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1351 WARN("(%p): invalid pointer!\n", pAcl);
1358 /******************************************************************************
1359 * RtlGetAce [NTDLL.@]
1361 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1365 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1367 if (dwAceIndex >= pAcl->AceCount)
1368 return STATUS_INVALID_PARAMETER;
1370 ace = (PACE_HEADER)(pAcl + 1);
1371 for (;dwAceIndex;dwAceIndex--)
1372 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1376 return STATUS_SUCCESS;
1383 /******************************************************************************
1384 * RtlAdjustPrivilege [NTDLL.@]
1386 * Enables or disables a privilege from the calling thread or process.
1389 * Privilege [I] Privilege index to change.
1390 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1391 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1392 * Enabled [O] Whether privilege was previously enabled or disabled.
1395 * Success: STATUS_SUCCESS.
1396 * Failure: NTSTATUS code.
1399 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1403 RtlAdjustPrivilege(ULONG Privilege,
1405 BOOLEAN CurrentThread,
1408 TOKEN_PRIVILEGES NewState;
1409 TOKEN_PRIVILEGES OldState;
1414 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1415 CurrentThread ? "TRUE" : "FALSE", Enabled);
1419 Status = NtOpenThreadToken(GetCurrentThread(),
1420 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1426 Status = NtOpenProcessToken(GetCurrentProcess(),
1427 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1431 if (!NT_SUCCESS(Status))
1433 WARN("Retrieving token handle failed (Status %x)\n", Status);
1437 OldState.PrivilegeCount = 1;
1439 NewState.PrivilegeCount = 1;
1440 NewState.Privileges[0].Luid.LowPart = Privilege;
1441 NewState.Privileges[0].Luid.HighPart = 0;
1442 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1444 Status = NtAdjustPrivilegesToken(TokenHandle,
1447 sizeof(TOKEN_PRIVILEGES),
1450 NtClose (TokenHandle);
1451 if (Status == STATUS_NOT_ALL_ASSIGNED)
1453 TRACE("Failed to assign all privileges\n");
1454 return STATUS_PRIVILEGE_NOT_HELD;
1456 if (!NT_SUCCESS(Status))
1458 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1462 if (OldState.PrivilegeCount == 0)
1465 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1467 return STATUS_SUCCESS;
1470 /******************************************************************************
1471 * RtlImpersonateSelf [NTDLL.@]
1473 * Makes an impersonation token that represents the process user and assigns
1474 * to the current thread.
1477 * ImpersonationLevel [I] Level at which to impersonate.
1480 * Success: STATUS_SUCCESS.
1481 * Failure: NTSTATUS code.
1484 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1487 OBJECT_ATTRIBUTES ObjectAttributes;
1488 HANDLE ProcessToken;
1489 HANDLE ImpersonationToken;
1491 TRACE("(%08x)\n", ImpersonationLevel);
1493 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1495 if (Status != STATUS_SUCCESS)
1498 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1500 Status = NtDuplicateToken( ProcessToken,
1505 &ImpersonationToken );
1506 if (Status != STATUS_SUCCESS)
1508 NtClose( ProcessToken );
1512 Status = NtSetInformationThread( GetCurrentThread(),
1513 ThreadImpersonationToken,
1514 &ImpersonationToken,
1515 sizeof(ImpersonationToken) );
1517 NtClose( ImpersonationToken );
1518 NtClose( ProcessToken );
1523 /******************************************************************************
1524 * NtAccessCheck [NTDLL.@]
1525 * ZwAccessCheck [NTDLL.@]
1527 * Checks that a user represented by a token is allowed to access an object
1528 * represented by a security descriptor.
1531 * SecurityDescriptor [I] The security descriptor of the object to check.
1532 * ClientToken [I] Token of the user accessing the object.
1533 * DesiredAccess [I] The desired access to the object.
1534 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1535 * PrivilegeSet [I/O] Privileges used during the access check.
1536 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1537 * GrantedAccess [O] The actual access rights granted.
1538 * AccessStatus [O] The status of the access check.
1544 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1545 * the maximum access rights allowed by the SD and returns them in
1547 * The SecurityDescriptor must have a valid owner and groups present,
1548 * otherwise the function will fail.
1552 PSECURITY_DESCRIPTOR SecurityDescriptor,
1554 ACCESS_MASK DesiredAccess,
1555 PGENERIC_MAPPING GenericMapping,
1556 PPRIVILEGE_SET PrivilegeSet,
1557 PULONG ReturnLength,
1558 PULONG GrantedAccess,
1559 NTSTATUS *AccessStatus)
1563 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1564 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1565 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1567 if (!PrivilegeSet || !ReturnLength)
1568 return STATUS_ACCESS_VIOLATION;
1570 SERVER_START_REQ( access_check )
1572 struct security_descriptor sd;
1577 BOOLEAN defaulted, present;
1579 SECURITY_DESCRIPTOR_CONTROL control;
1581 req->handle = wine_server_obj_handle( ClientToken );
1582 req->desired_access = DesiredAccess;
1583 req->mapping_read = GenericMapping->GenericRead;
1584 req->mapping_write = GenericMapping->GenericWrite;
1585 req->mapping_execute = GenericMapping->GenericExecute;
1586 req->mapping_all = GenericMapping->GenericAll;
1588 /* marshal security descriptor */
1589 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1590 sd.control = control & ~SE_SELF_RELATIVE;
1591 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1592 sd.owner_len = RtlLengthSid( owner );
1593 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1594 sd.group_len = RtlLengthSid( group );
1595 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1596 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1597 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1598 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1600 wine_server_add_data( req, &sd, sizeof(sd) );
1601 wine_server_add_data( req, owner, sd.owner_len );
1602 wine_server_add_data( req, group, sd.group_len );
1603 wine_server_add_data( req, sacl, sd.sacl_len );
1604 wine_server_add_data( req, dacl, sd.dacl_len );
1606 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1608 status = wine_server_call( req );
1610 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1611 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1613 if (status == STATUS_SUCCESS)
1615 *AccessStatus = reply->access_status;
1616 *GrantedAccess = reply->access_granted;
1624 /******************************************************************************
1625 * NtSetSecurityObject [NTDLL.@]
1626 * ZwSetSecurityObject [NTDLL.@]
1628 * Sets specified parts of the object's security descriptor.
1631 * Handle [I] Handle to the object to change security descriptor of.
1632 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1633 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1639 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1640 SECURITY_INFORMATION SecurityInformation,
1641 PSECURITY_DESCRIPTOR SecurityDescriptor)
1644 struct security_descriptor sd;
1645 PACL dacl = NULL, sacl = NULL;
1646 PSID owner = NULL, group = NULL;
1647 BOOLEAN defaulted, present;
1649 SECURITY_DESCRIPTOR_CONTROL control;
1651 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1653 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1655 memset( &sd, 0, sizeof(sd) );
1656 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1657 if (status != STATUS_SUCCESS) return status;
1658 sd.control = control & ~SE_SELF_RELATIVE;
1660 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1662 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1663 if (status != STATUS_SUCCESS) return status;
1664 if (!(sd.owner_len = RtlLengthSid( owner )))
1665 return STATUS_INVALID_SECURITY_DESCR;
1668 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1670 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1671 if (status != STATUS_SUCCESS) return status;
1672 if (!(sd.group_len = RtlLengthSid( group )))
1673 return STATUS_INVALID_SECURITY_DESCR;
1676 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1678 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1679 if (status != STATUS_SUCCESS) return status;
1680 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1681 sd.control |= SE_SACL_PRESENT;
1684 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1686 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1687 if (status != STATUS_SUCCESS) return status;
1688 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1689 sd.control |= SE_DACL_PRESENT;
1692 SERVER_START_REQ( set_security_object )
1694 req->handle = wine_server_obj_handle( Handle );
1695 req->security_info = SecurityInformation;
1697 wine_server_add_data( req, &sd, sizeof(sd) );
1698 wine_server_add_data( req, owner, sd.owner_len );
1699 wine_server_add_data( req, group, sd.group_len );
1700 wine_server_add_data( req, sacl, sd.sacl_len );
1701 wine_server_add_data( req, dacl, sd.dacl_len );
1702 status = wine_server_call( req );
1709 /******************************************************************************
1710 * RtlConvertSidToUnicodeString (NTDLL.@)
1712 * The returned SID is used to access the USER registry hive usually
1714 * the native function returns something like
1715 * "S-1-5-21-0000000000-000000000-0000000000-500";
1717 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1718 PUNICODE_STRING String,
1720 BOOLEAN AllocateString)
1722 static const WCHAR formatW[] = {'-','%','u',0};
1723 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1725 const SID *sid = pSid;
1729 p += sprintfW( p, formatW, sid->Revision );
1730 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1731 sid->IdentifierAuthority.Value[4] ),
1732 MAKEWORD( sid->IdentifierAuthority.Value[3],
1733 sid->IdentifierAuthority.Value[2] )));
1734 for (i = 0; i < sid->SubAuthorityCount; i++)
1735 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1737 len = (p + 1 - buffer) * sizeof(WCHAR);
1739 String->Length = len - sizeof(WCHAR);
1742 String->MaximumLength = len;
1743 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1744 return STATUS_NO_MEMORY;
1746 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1748 memcpy( String->Buffer, buffer, len );
1749 return STATUS_SUCCESS;
1752 /******************************************************************************
1753 * RtlQueryInformationAcl (NTDLL.@)
1755 NTSTATUS WINAPI RtlQueryInformationAcl(
1757 LPVOID pAclInformation,
1758 DWORD nAclInformationLength,
1759 ACL_INFORMATION_CLASS dwAclInformationClass)
1761 NTSTATUS status = STATUS_SUCCESS;
1763 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1764 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1766 switch (dwAclInformationClass)
1768 case AclRevisionInformation:
1770 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1772 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1773 status = STATUS_INVALID_PARAMETER;
1775 paclrev->AclRevision = pAcl->AclRevision;
1780 case AclSizeInformation:
1782 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1784 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1785 status = STATUS_INVALID_PARAMETER;
1788 paclsize->AceCount = pAcl->AceCount;
1789 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1790 if (pAcl->AclSize < paclsize->AclBytesInUse)
1792 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1793 paclsize->AclBytesFree = 0;
1794 paclsize->AclBytesInUse = pAcl->AclSize;
1797 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1804 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1805 status = STATUS_INVALID_PARAMETER;