4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "wine/port.h"
36 #define WIN32_NO_STATUS
38 #include "wine/exception.h"
39 #include "ntdll_misc.h"
41 #include "wine/library.h"
42 #include "wine/unicode.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
47 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
49 /* helper function to copy an ACL */
50 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
54 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
57 size = ((ACL *)pSourceAcl)->AclSize;
58 if (nDestinationAclLength < size)
61 memmove(pDestinationAcl, pSourceAcl, size);
65 /* generically adds an ACE to an ACL */
66 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
67 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
69 ACE_HEADER *pAceHeader;
75 if (!RtlValidSid(pSid))
76 return STATUS_INVALID_SID;
78 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
79 return STATUS_REVISION_MISMATCH;
81 if (!RtlValidAcl(pAcl))
82 return STATUS_INVALID_ACL;
84 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
85 return STATUS_INVALID_ACL;
88 return STATUS_ALLOTTED_SPACE_EXCEEDED;
90 /* calculate generic size of the ACE */
91 dwLengthSid = RtlLengthSid(pSid);
92 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
93 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
94 return STATUS_ALLOTTED_SPACE_EXCEEDED;
96 /* fill the new ACE */
97 pAceHeader->AceType = dwAceType;
98 pAceHeader->AceFlags = dwAceFlags;
99 pAceHeader->AceSize = dwAceSize;
101 /* skip past the ACE_HEADER of the ACE */
102 pAccessMask = (DWORD *)(pAceHeader + 1);
103 *pAccessMask = dwAccessMask;
105 /* skip past ACE->Mask */
106 pSidStart = pAccessMask + 1;
107 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
109 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
112 return STATUS_SUCCESS;
119 /******************************************************************************
120 * RtlAllocateAndInitializeSid [NTDLL.@]
123 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
124 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
125 BYTE nSubAuthorityCount,
126 DWORD nSubAuthority0, DWORD nSubAuthority1,
127 DWORD nSubAuthority2, DWORD nSubAuthority3,
128 DWORD nSubAuthority4, DWORD nSubAuthority5,
129 DWORD nSubAuthority6, DWORD nSubAuthority7,
134 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
135 pIdentifierAuthority,nSubAuthorityCount,
136 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
137 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
139 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
141 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
142 RtlLengthRequiredSid(nSubAuthorityCount))))
143 return STATUS_NO_MEMORY;
145 tmp_sid->Revision = SID_REVISION;
147 if (pIdentifierAuthority)
148 memcpy(&tmp_sid->IdentifierAuthority, pIdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY));
149 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
151 switch( nSubAuthorityCount )
153 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
154 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
155 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
156 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
157 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
158 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
159 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
160 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
164 return STATUS_SUCCESS;
167 /******************************************************************************
168 * RtlEqualSid [NTDLL.@]
170 * Determine if two SIDs are equal.
173 * pSid1 [I] Source SID
174 * pSid2 [I] SID to compare with
177 * TRUE, if pSid1 is equal to pSid2,
180 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
182 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
185 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
188 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
194 /******************************************************************************
195 * RtlEqualPrefixSid [NTDLL.@]
197 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
199 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
202 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
205 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
212 /******************************************************************************
213 * RtlFreeSid [NTDLL.@]
215 * Free the resources used by a SID.
218 * pSid [I] SID to Free.
223 DWORD WINAPI RtlFreeSid(PSID pSid)
225 TRACE("(%p)\n", pSid);
226 RtlFreeHeap( GetProcessHeap(), 0, pSid );
227 return STATUS_SUCCESS;
230 /**************************************************************************
231 * RtlLengthRequiredSid [NTDLL.@]
233 * Determine the amount of memory a SID will use
236 * nrofsubauths [I] Number of Sub Authorities in the SID.
239 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
241 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
243 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
246 /**************************************************************************
247 * RtlLengthSid [NTDLL.@]
249 * Determine the amount of memory a SID is using
252 * pSid [I] SID to get the size of.
255 * The size, in bytes, of pSid.
257 DWORD WINAPI RtlLengthSid(PSID pSid)
259 TRACE("sid=%p\n",pSid);
261 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
264 /**************************************************************************
265 * RtlInitializeSid [NTDLL.@]
270 * pSid [I] SID to initialise
271 * pIdentifierAuthority [I] Identifier Authority
272 * nSubAuthorityCount [I] Number of Sub Authorities
275 * Success: TRUE. pSid is initialised with the details given.
276 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
278 BOOL WINAPI RtlInitializeSid(
280 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
281 BYTE nSubAuthorityCount)
286 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
289 pisid->Revision = SID_REVISION;
290 pisid->SubAuthorityCount = nSubAuthorityCount;
291 if (pIdentifierAuthority)
292 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
294 for (i = 0; i < nSubAuthorityCount; i++)
295 *RtlSubAuthoritySid(pSid, i) = 0;
300 /**************************************************************************
301 * RtlSubAuthoritySid [NTDLL.@]
303 * Return the Sub Authority of a SID
306 * pSid [I] SID to get the Sub Authority from.
307 * nSubAuthority [I] Sub Authority number.
310 * A pointer to The Sub Authority value of pSid.
312 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
314 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
317 /**************************************************************************
318 * RtlIdentifierAuthoritySid [NTDLL.@]
320 * Return the Identifier Authority of a SID.
323 * pSid [I] SID to get the Identifier Authority from.
326 * A pointer to the Identifier Authority value of pSid.
328 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
330 return &(((SID*)pSid)->IdentifierAuthority);
333 /**************************************************************************
334 * RtlSubAuthorityCountSid [NTDLL.@]
336 * Get the number of Sub Authorities in a SID.
339 * pSid [I] SID to get the count from.
342 * A pointer to the Sub Authority count of pSid.
344 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
346 return &(((SID*)pSid)->SubAuthorityCount);
349 /**************************************************************************
350 * RtlCopySid [NTDLL.@]
352 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
354 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
355 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
358 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
361 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
364 /******************************************************************************
365 * RtlValidSid [NTDLL.@]
367 * Determine if a SID is valid.
370 * pSid [I] SID to check
373 * TRUE if pSid is valid,
376 BOOLEAN WINAPI RtlValidSid( PSID pSid )
382 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
383 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
390 WARN("(%p): invalid pointer!\n", pSid);
399 * security descriptor functions
402 /**************************************************************************
403 * RtlCreateSecurityDescriptor [NTDLL.@]
405 * Initialise a SECURITY_DESCRIPTOR.
408 * lpsd [O] Descriptor to initialise.
409 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
412 * Success: STATUS_SUCCESS.
413 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
415 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
416 PSECURITY_DESCRIPTOR lpsd,
419 if (rev!=SECURITY_DESCRIPTOR_REVISION)
420 return STATUS_UNKNOWN_REVISION;
421 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
422 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
423 return STATUS_SUCCESS;
426 /**************************************************************************
427 * RtlCopySecurityDescriptor [NTDLL.@]
429 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
432 * pSourceSD [O] SD to copy from.
433 * pDestinationSD [I] Destination SD.
436 * Success: STATUS_SUCCESS.
437 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
439 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
441 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
442 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
445 BOOLEAN defaulted, present;
447 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
449 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
450 return STATUS_UNKNOWN_REVISION;
452 /* copy initial data */
453 destSD->Revision = srcSD->Revision;
454 destSD->Sbz1 = srcSD->Sbz1;
455 destSD->Control = srcSD->Control;
458 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
459 length = RtlLengthSid(Owner);
463 destSD->Owner = srcSD->Owner;
464 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Owner, Owner);
468 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
469 RtlCopySid(length, destSD->Owner, Owner);
473 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
474 length = RtlLengthSid(Group);
478 destSD->Group = srcSD->Group;
479 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Group, Group);
483 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
484 RtlCopySid(length, destSD->Group, Group);
488 if (srcSD->Control & SE_DACL_PRESENT)
490 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
491 length = Dacl->AclSize;
495 destSD->Dacl = srcSD->Dacl;
496 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Dacl), Dacl);
500 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
501 copy_acl(length, destSD->Dacl, Dacl);
506 if (srcSD->Control & SE_SACL_PRESENT)
508 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
509 length = Sacl->AclSize;
513 destSD->Sacl = srcSD->Sacl;
514 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Sacl), Sacl);
518 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
519 copy_acl(length, destSD->Sacl, Sacl);
523 return STATUS_SUCCESS;
526 /**************************************************************************
527 * RtlValidSecurityDescriptor [NTDLL.@]
529 * Determine if a SECURITY_DESCRIPTOR is valid.
532 * SecurityDescriptor [I] Descriptor to check.
535 * Success: STATUS_SUCCESS.
536 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
538 NTSTATUS WINAPI RtlValidSecurityDescriptor(
539 PSECURITY_DESCRIPTOR SecurityDescriptor)
541 if ( ! SecurityDescriptor )
542 return STATUS_INVALID_SECURITY_DESCR;
543 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
544 return STATUS_UNKNOWN_REVISION;
546 return STATUS_SUCCESS;
549 /**************************************************************************
550 * RtlLengthSecurityDescriptor [NTDLL.@]
552 ULONG WINAPI RtlLengthSecurityDescriptor(
553 PSECURITY_DESCRIPTOR pSecurityDescriptor)
555 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
557 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
562 if ( lpsd->Control & SE_SELF_RELATIVE)
563 offset = (ULONG) lpsd;
565 if ( lpsd->Owner != NULL )
566 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
568 if ( lpsd->Group != NULL )
569 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
571 if ( (lpsd->Control & SE_SACL_PRESENT) &&
573 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
575 if ( (lpsd->Control & SE_DACL_PRESENT) &&
577 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
582 /******************************************************************************
583 * RtlGetDaclSecurityDescriptor [NTDLL.@]
586 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
587 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
588 OUT PBOOLEAN lpbDaclPresent,
590 OUT PBOOLEAN lpbDaclDefaulted)
592 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
594 TRACE("(%p,%p,%p,%p)\n",
595 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
597 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
598 return STATUS_UNKNOWN_REVISION ;
600 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
602 if ( SE_SELF_RELATIVE & lpsd->Control)
603 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
607 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
610 return STATUS_SUCCESS;
613 /**************************************************************************
614 * RtlSetDaclSecurityDescriptor [NTDLL.@]
616 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
617 PSECURITY_DESCRIPTOR pSecurityDescriptor,
620 BOOLEAN dacldefaulted )
622 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
624 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
625 return STATUS_UNKNOWN_REVISION;
626 if (lpsd->Control & SE_SELF_RELATIVE)
627 return STATUS_INVALID_SECURITY_DESCR;
630 { lpsd->Control &= ~SE_DACL_PRESENT;
634 lpsd->Control |= SE_DACL_PRESENT;
638 lpsd->Control |= SE_DACL_DEFAULTED;
640 lpsd->Control &= ~SE_DACL_DEFAULTED;
642 return STATUS_SUCCESS;
645 /******************************************************************************
646 * RtlGetSaclSecurityDescriptor [NTDLL.@]
649 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
650 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
651 OUT PBOOLEAN lpbSaclPresent,
653 OUT PBOOLEAN lpbSaclDefaulted)
655 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
657 TRACE("(%p,%p,%p,%p)\n",
658 pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
660 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
661 return STATUS_UNKNOWN_REVISION;
663 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
665 if (SE_SELF_RELATIVE & lpsd->Control)
666 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Sacl);
670 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
673 return STATUS_SUCCESS;
676 /**************************************************************************
677 * RtlSetSaclSecurityDescriptor [NTDLL.@]
679 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
680 PSECURITY_DESCRIPTOR pSecurityDescriptor,
683 BOOLEAN sacldefaulted)
685 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
687 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
688 return STATUS_UNKNOWN_REVISION;
689 if (lpsd->Control & SE_SELF_RELATIVE)
690 return STATUS_INVALID_SECURITY_DESCR;
692 lpsd->Control &= ~SE_SACL_PRESENT;
695 lpsd->Control |= SE_SACL_PRESENT;
698 lpsd->Control |= SE_SACL_DEFAULTED;
700 lpsd->Control &= ~SE_SACL_DEFAULTED;
701 return STATUS_SUCCESS;
704 /**************************************************************************
705 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
707 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
708 PSECURITY_DESCRIPTOR pSecurityDescriptor,
710 PBOOLEAN OwnerDefaulted)
712 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
714 if ( !lpsd || !Owner || !OwnerDefaulted )
715 return STATUS_INVALID_PARAMETER;
717 if (lpsd->Owner != NULL)
719 if (lpsd->Control & SE_SELF_RELATIVE)
720 *Owner = (PSID)((LPBYTE)lpsd +
723 *Owner = lpsd->Owner;
725 if ( lpsd->Control & SE_OWNER_DEFAULTED )
726 *OwnerDefaulted = TRUE;
728 *OwnerDefaulted = FALSE;
733 return STATUS_SUCCESS;
736 /**************************************************************************
737 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
739 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
740 PSECURITY_DESCRIPTOR pSecurityDescriptor,
742 BOOLEAN ownerdefaulted)
744 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
746 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
747 return STATUS_UNKNOWN_REVISION;
748 if (lpsd->Control & SE_SELF_RELATIVE)
749 return STATUS_INVALID_SECURITY_DESCR;
753 lpsd->Control |= SE_OWNER_DEFAULTED;
755 lpsd->Control &= ~SE_OWNER_DEFAULTED;
756 return STATUS_SUCCESS;
759 /**************************************************************************
760 * RtlSetGroupSecurityDescriptor [NTDLL.@]
762 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
763 PSECURITY_DESCRIPTOR pSecurityDescriptor,
765 BOOLEAN groupdefaulted)
767 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
769 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
770 return STATUS_UNKNOWN_REVISION;
771 if (lpsd->Control & SE_SELF_RELATIVE)
772 return STATUS_INVALID_SECURITY_DESCR;
776 lpsd->Control |= SE_GROUP_DEFAULTED;
778 lpsd->Control &= ~SE_GROUP_DEFAULTED;
779 return STATUS_SUCCESS;
782 /**************************************************************************
783 * RtlGetGroupSecurityDescriptor [NTDLL.@]
785 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
786 PSECURITY_DESCRIPTOR pSecurityDescriptor,
788 PBOOLEAN GroupDefaulted)
790 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
792 if ( !lpsd || !Group || !GroupDefaulted )
793 return STATUS_INVALID_PARAMETER;
795 if (lpsd->Group != NULL)
797 if (lpsd->Control & SE_SELF_RELATIVE)
798 *Group = (PSID)((LPBYTE)lpsd +
801 *Group = lpsd->Group;
803 if ( lpsd->Control & SE_GROUP_DEFAULTED )
804 *GroupDefaulted = TRUE;
806 *GroupDefaulted = FALSE;
811 return STATUS_SUCCESS;
814 /**************************************************************************
815 * RtlMakeSelfRelativeSD [NTDLL.@]
817 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
818 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
819 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
820 IN OUT LPDWORD lpdwBufferLength)
824 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
825 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
827 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
828 lpdwBufferLength ? *lpdwBufferLength: -1);
830 if (!lpdwBufferLength || !pAbs)
831 return STATUS_INVALID_PARAMETER;
833 length = RtlLengthSecurityDescriptor(pAbs);
834 if (*lpdwBufferLength < length)
836 *lpdwBufferLength = length;
837 return STATUS_BUFFER_TOO_SMALL;
841 return STATUS_INVALID_PARAMETER;
843 if (pAbs->Control & SE_SELF_RELATIVE)
845 memcpy(pRel, pAbs, length);
846 return STATUS_SUCCESS;
849 pRel->Revision = pAbs->Revision;
850 pRel->Sbz1 = pAbs->Sbz1;
851 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
853 offsetRel = sizeof(SECURITY_DESCRIPTOR);
854 pRel->Owner = (PSID) offsetRel;
855 length = RtlLengthSid(pAbs->Owner);
856 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
859 pRel->Group = (PSID) offsetRel;
860 length = RtlLengthSid(pAbs->Group);
861 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
863 if (pRel->Control & SE_SACL_PRESENT)
866 pRel->Sacl = (PACL) offsetRel;
867 length = pAbs->Sacl->AclSize;
868 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
875 if (pRel->Control & SE_DACL_PRESENT)
878 pRel->Dacl = (PACL) offsetRel;
879 length = pAbs->Dacl->AclSize;
880 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
887 return STATUS_SUCCESS;
891 /**************************************************************************
892 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
894 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
895 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
896 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
897 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
899 OUT LPDWORD lpdwDaclSize,
901 OUT LPDWORD lpdwSaclSize,
903 OUT LPDWORD lpdwOwnerSize,
904 OUT PSID pPrimaryGroup,
905 OUT LPDWORD lpdwPrimaryGroupSize)
907 NTSTATUS status = STATUS_SUCCESS;
908 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
909 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
912 !lpdwAbsoluteSecurityDescriptorSize ||
916 !lpdwPrimaryGroupSize ||
917 ~pRel->Control & SE_SELF_RELATIVE)
918 return STATUS_INVALID_PARAMETER;
920 /* Confirm buffers are sufficiently large */
921 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
923 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
924 status = STATUS_BUFFER_TOO_SMALL;
927 if (pRel->Control & SE_DACL_PRESENT &&
928 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
930 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
931 status = STATUS_BUFFER_TOO_SMALL;
934 if (pRel->Control & SE_SACL_PRESENT &&
935 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
937 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
938 status = STATUS_BUFFER_TOO_SMALL;
942 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
944 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
945 status = STATUS_BUFFER_TOO_SMALL;
949 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
951 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
952 status = STATUS_BUFFER_TOO_SMALL;
955 if (status != STATUS_SUCCESS)
958 /* Copy structures, and clear the ones we don't set */
959 pAbs->Revision = pRel->Revision;
960 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
966 if (pRel->Control & SE_SACL_PRESENT)
968 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
970 memcpy(pSacl, pAcl, pAcl->AclSize);
974 if (pRel->Control & SE_DACL_PRESENT)
976 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
977 memcpy(pDacl, pAcl, pAcl->AclSize);
983 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
984 memcpy(pOwner, psid, RtlLengthSid(psid));
985 pAbs->Owner = pOwner;
990 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
991 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
992 pAbs->Group = pPrimaryGroup;
998 /******************************************************************************
999 * RtlGetControlSecurityDescriptor (NTDLL.@)
1001 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1002 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1003 PSECURITY_DESCRIPTOR_CONTROL pControl,
1004 LPDWORD lpdwRevision)
1006 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1008 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1010 *lpdwRevision = lpsd->Revision;
1012 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1013 return STATUS_UNKNOWN_REVISION;
1015 *pControl = lpsd->Control;
1017 return STATUS_SUCCESS;
1021 /**************************************************************************
1022 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1024 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1025 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1026 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1027 PULONG BufferLength)
1029 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1031 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1032 SelfRelativeSecurityDescriptor, BufferLength);
1034 if (abs->Control & SE_SELF_RELATIVE)
1035 return STATUS_BAD_DESCRIPTOR_FORMAT;
1037 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1038 SelfRelativeSecurityDescriptor, BufferLength);
1043 * access control list's
1046 /**************************************************************************
1047 * RtlCreateAcl [NTDLL.@]
1050 * This should return NTSTATUS
1052 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1054 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1056 if (rev!=ACL_REVISION)
1057 return STATUS_INVALID_PARAMETER;
1058 if (size<sizeof(ACL))
1059 return STATUS_BUFFER_TOO_SMALL;
1061 return STATUS_INVALID_PARAMETER;
1063 memset(acl,'\0',sizeof(ACL));
1064 acl->AclRevision = rev;
1065 acl->AclSize = size;
1067 return STATUS_SUCCESS;
1070 /**************************************************************************
1071 * RtlFirstFreeAce [NTDLL.@]
1072 * looks for the AceCount+1 ACE, and if it is still within the alloced
1073 * ACL, return a pointer to it
1075 BOOLEAN WINAPI RtlFirstFreeAce(
1083 ace = (PACE_HEADER)(acl+1);
1084 for (i=0;i<acl->AceCount;i++) {
1085 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1087 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1089 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1095 /**************************************************************************
1096 * RtlAddAce [NTDLL.@]
1098 NTSTATUS WINAPI RtlAddAce(
1102 PACE_HEADER acestart,
1105 PACE_HEADER ace,targetace;
1108 if (acl->AclRevision != ACL_REVISION)
1109 return STATUS_INVALID_PARAMETER;
1110 if (!RtlFirstFreeAce(acl,&targetace))
1111 return STATUS_INVALID_PARAMETER;
1112 nrofaces=0;ace=acestart;
1113 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1115 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1117 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1118 return STATUS_INVALID_PARAMETER;
1119 memcpy((LPBYTE)targetace,acestart,acelen);
1120 acl->AceCount+=nrofaces;
1121 return STATUS_SUCCESS;
1124 /**************************************************************************
1125 * RtlDeleteAce [NTDLL.@]
1127 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1132 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1134 if (STATUS_SUCCESS == status)
1139 /* skip over the ACE we are deleting */
1140 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1143 /* calculate the length of the rest */
1144 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1146 len += pcAce->AceSize;
1147 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1150 /* slide them all backwards */
1151 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1155 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1160 /******************************************************************************
1161 * RtlAddAccessAllowedAce [NTDLL.@]
1163 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1165 IN DWORD dwAceRevision,
1166 IN DWORD AccessMask,
1169 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1172 /******************************************************************************
1173 * RtlAddAccessAllowedAceEx [NTDLL.@]
1175 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1177 IN DWORD dwAceRevision,
1179 IN DWORD AccessMask,
1182 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1184 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1185 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1188 /******************************************************************************
1189 * RtlAddAccessDeniedAce [NTDLL.@]
1191 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1193 IN DWORD dwAceRevision,
1194 IN DWORD AccessMask,
1197 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1200 /******************************************************************************
1201 * RtlAddAccessDeniedAceEx [NTDLL.@]
1203 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1205 IN DWORD dwAceRevision,
1207 IN DWORD AccessMask,
1210 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1212 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1213 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1216 /**************************************************************************
1217 * RtlAddAuditAccessAce [NTDLL.@]
1219 NTSTATUS WINAPI RtlAddAuditAccessAce(
1221 IN DWORD dwAceRevision,
1222 IN DWORD dwAccessMask,
1224 IN BOOL bAuditSuccess,
1225 IN BOOL bAuditFailure)
1227 DWORD dwAceFlags = 0;
1229 TRACE("(%p,%d,%d,%p,%u,%u)\n",pAcl,dwAceRevision,dwAccessMask,
1230 pSid,bAuditSuccess,bAuditFailure);
1233 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1236 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1238 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1239 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1242 /******************************************************************************
1243 * RtlValidAcl [NTDLL.@]
1245 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1248 TRACE("(%p)\n", pAcl);
1255 if (pAcl->AclRevision != ACL_REVISION)
1259 ace = (PACE_HEADER)(pAcl+1);
1261 for (i=0;i<=pAcl->AceCount;i++)
1263 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1268 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1274 WARN("(%p): invalid pointer!\n", pAcl);
1281 /******************************************************************************
1282 * RtlGetAce [NTDLL.@]
1284 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1288 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1290 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1291 return STATUS_INVALID_PARAMETER;
1293 ace = (PACE_HEADER)(pAcl + 1);
1294 for (;dwAceIndex;dwAceIndex--)
1295 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1297 *pAce = (LPVOID) ace;
1299 return STATUS_SUCCESS;
1306 /******************************************************************************
1307 * RtlAdjustPrivilege [NTDLL.@]
1309 * Enables or disables a privilege from the calling thread or process.
1312 * Privilege [I] Privilege index to change.
1313 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1314 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1315 * Enabled [O] Whether privilege was previously enabled or disabled.
1318 * Success: STATUS_SUCCESS.
1319 * Failure: NTSTATUS code.
1322 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1326 RtlAdjustPrivilege(ULONG Privilege,
1328 BOOLEAN CurrentThread,
1331 TOKEN_PRIVILEGES NewState;
1332 TOKEN_PRIVILEGES OldState;
1337 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1338 CurrentThread ? "TRUE" : "FALSE", Enabled);
1342 Status = NtOpenThreadToken(GetCurrentThread(),
1343 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1349 Status = NtOpenProcessToken(GetCurrentProcess(),
1350 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1354 if (!NT_SUCCESS(Status))
1356 WARN("Retrieving token handle failed (Status %x)\n", Status);
1360 OldState.PrivilegeCount = 1;
1362 NewState.PrivilegeCount = 1;
1363 NewState.Privileges[0].Luid.LowPart = Privilege;
1364 NewState.Privileges[0].Luid.HighPart = 0;
1365 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1367 Status = NtAdjustPrivilegesToken(TokenHandle,
1370 sizeof(TOKEN_PRIVILEGES),
1373 NtClose (TokenHandle);
1374 if (Status == STATUS_NOT_ALL_ASSIGNED)
1376 TRACE("Failed to assign all privileges\n");
1377 return STATUS_PRIVILEGE_NOT_HELD;
1379 if (!NT_SUCCESS(Status))
1381 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1385 if (OldState.PrivilegeCount == 0)
1388 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1390 return STATUS_SUCCESS;
1393 /******************************************************************************
1394 * RtlImpersonateSelf [NTDLL.@]
1396 * Makes an impersonation token that represents the process user and assigns
1397 * to the current thread.
1400 * ImpersonationLevel [I] Level at which to impersonate.
1403 * Success: STATUS_SUCCESS.
1404 * Failure: NTSTATUS code.
1407 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1410 OBJECT_ATTRIBUTES ObjectAttributes;
1411 HANDLE ProcessToken;
1412 HANDLE ImpersonationToken;
1414 TRACE("(%08x)\n", ImpersonationLevel);
1416 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1418 if (Status != STATUS_SUCCESS)
1421 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1423 Status = NtDuplicateToken( ProcessToken,
1428 &ImpersonationToken );
1429 if (Status != STATUS_SUCCESS)
1431 NtClose( ProcessToken );
1435 Status = NtSetInformationThread( GetCurrentThread(),
1436 ThreadImpersonationToken,
1437 &ImpersonationToken,
1438 sizeof(ImpersonationToken) );
1440 NtClose( ImpersonationToken );
1441 NtClose( ProcessToken );
1446 /******************************************************************************
1447 * NtAccessCheck [NTDLL.@]
1448 * ZwAccessCheck [NTDLL.@]
1450 * Checks that a user represented by a token is allowed to access an object
1451 * represented by a security descriptor.
1454 * SecurityDescriptor [I] The security descriptor of the object to check.
1455 * ClientToken [I] Token of the user accessing the object.
1456 * DesiredAccess [I] The desired access to the object.
1457 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1458 * PrivilegeSet [I/O] Privileges used during the access check.
1459 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1460 * GrantedAccess [O] The actual access rights granted.
1461 * AccessStatus [O] The status of the access check.
1467 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1468 * the maximum access rights allowed by the SD and returns them in
1470 * The SecurityDescriptor must have a valid owner and groups present,
1471 * otherwise the function will fail.
1475 PSECURITY_DESCRIPTOR SecurityDescriptor,
1477 ACCESS_MASK DesiredAccess,
1478 PGENERIC_MAPPING GenericMapping,
1479 PPRIVILEGE_SET PrivilegeSet,
1480 PULONG ReturnLength,
1481 PULONG GrantedAccess,
1482 NTSTATUS *AccessStatus)
1486 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1487 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1488 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1490 SERVER_START_REQ( access_check )
1492 struct security_descriptor sd;
1497 BOOLEAN defaulted, present;
1499 SECURITY_DESCRIPTOR_CONTROL control;
1501 req->handle = ClientToken;
1502 req->desired_access = DesiredAccess;
1503 req->mapping_read = GenericMapping->GenericRead;
1504 req->mapping_write = GenericMapping->GenericWrite;
1505 req->mapping_execute = GenericMapping->GenericExecute;
1506 req->mapping_all = GenericMapping->GenericAll;
1508 /* marshal security descriptor */
1509 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1510 sd.control = control & ~SE_SELF_RELATIVE;
1511 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1512 sd.owner_len = RtlLengthSid( owner );
1513 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1514 sd.group_len = RtlLengthSid( group );
1515 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1516 sd.sacl_len = (present ? sacl->AclSize : 0);
1517 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1518 sd.dacl_len = (present ? dacl->AclSize : 0);
1520 wine_server_add_data( req, &sd, sizeof(sd) );
1521 wine_server_add_data( req, owner, sd.owner_len );
1522 wine_server_add_data( req, group, sd.group_len );
1523 wine_server_add_data( req, sacl, sd.sacl_len );
1524 wine_server_add_data( req, dacl, sd.dacl_len );
1526 wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1528 status = wine_server_call( req );
1530 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1531 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1533 if (status == STATUS_SUCCESS)
1535 *AccessStatus = reply->access_status;
1536 *GrantedAccess = reply->access_granted;
1544 /******************************************************************************
1545 * NtSetSecurityObject [NTDLL.@]
1546 * ZwSetSecurityObject [NTDLL.@]
1548 * Sets specified parts of the object's security descriptor.
1551 * Handle [I] Handle to the object to change security descriptor of.
1552 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1553 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1559 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1560 SECURITY_INFORMATION SecurityInformation,
1561 PSECURITY_DESCRIPTOR SecurityDescriptor)
1564 struct security_descriptor sd;
1567 BOOLEAN defaulted, present;
1569 SECURITY_DESCRIPTOR_CONTROL control;
1571 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1573 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1575 memset( &sd, 0, sizeof(sd) );
1576 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1577 if (status != STATUS_SUCCESS) return status;
1578 sd.control = control & ~SE_SELF_RELATIVE;
1580 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1582 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1583 if (status != STATUS_SUCCESS) return status;
1584 if (!(sd.owner_len = RtlLengthSid( owner )))
1585 return STATUS_INVALID_SECURITY_DESCR;
1588 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1590 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1591 if (status != STATUS_SUCCESS) return status;
1592 if (!(sd.group_len = RtlLengthSid( group )))
1593 return STATUS_INVALID_SECURITY_DESCR;
1596 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1598 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1599 if (status != STATUS_SUCCESS) return status;
1600 sd.sacl_len = (sacl && present) ? sacl->AclSize : 0;
1601 sd.control |= SE_SACL_PRESENT;
1604 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1606 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1607 if (status != STATUS_SUCCESS) return status;
1608 sd.dacl_len = (dacl && present) ? dacl->AclSize : 0;
1609 sd.control |= SE_DACL_PRESENT;
1612 SERVER_START_REQ( set_security_object )
1614 req->handle = Handle;
1615 req->security_info = SecurityInformation;
1617 wine_server_add_data( req, &sd, sizeof(sd) );
1618 wine_server_add_data( req, owner, sd.owner_len );
1619 wine_server_add_data( req, group, sd.group_len );
1620 wine_server_add_data( req, sacl, sd.sacl_len );
1621 wine_server_add_data( req, dacl, sd.dacl_len );
1622 status = wine_server_call( req );
1629 /******************************************************************************
1630 * RtlConvertSidToUnicodeString (NTDLL.@)
1632 * The returned SID is used to access the USER registry hive usually
1634 * the native function returns something like
1635 * "S-1-5-21-0000000000-000000000-0000000000-500";
1637 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1638 PUNICODE_STRING String,
1640 BOOLEAN AllocateString)
1642 static const WCHAR formatW[] = {'-','%','u',0};
1643 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1645 const SID *sid = (const SID *)pSid;
1649 p += sprintfW( p, formatW, sid->Revision );
1650 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1651 sid->IdentifierAuthority.Value[4] ),
1652 MAKEWORD( sid->IdentifierAuthority.Value[3],
1653 sid->IdentifierAuthority.Value[2] )));
1654 for (i = 0; i < sid->SubAuthorityCount; i++)
1655 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1657 len = (p + 1 - buffer) * sizeof(WCHAR);
1659 String->Length = len - sizeof(WCHAR);
1662 String->MaximumLength = len;
1663 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1664 return STATUS_NO_MEMORY;
1666 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1668 memcpy( String->Buffer, buffer, len );
1669 return STATUS_SUCCESS;
1672 /******************************************************************************
1673 * RtlQueryInformationAcl (NTDLL.@)
1675 NTSTATUS WINAPI RtlQueryInformationAcl(
1677 LPVOID pAclInformation,
1678 DWORD nAclInformationLength,
1679 ACL_INFORMATION_CLASS dwAclInformationClass)
1681 NTSTATUS status = STATUS_SUCCESS;
1683 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1684 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1686 switch (dwAclInformationClass)
1688 case AclRevisionInformation:
1690 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1692 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1693 status = STATUS_INVALID_PARAMETER;
1695 paclrev->AclRevision = pAcl->AclRevision;
1700 case AclSizeInformation:
1702 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1704 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1705 status = STATUS_INVALID_PARAMETER;
1711 paclsize->AceCount = pAcl->AceCount;
1713 paclsize->AclBytesInUse = 0;
1714 ace = (PACE_HEADER) (pAcl + 1);
1716 for (i = 0; i < pAcl->AceCount; i++)
1718 paclsize->AclBytesInUse += ace->AceSize;
1719 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1722 if (pAcl->AclSize < paclsize->AclBytesInUse)
1724 WARN("Acl has %d bytes free\n", paclsize->AclBytesFree);
1725 paclsize->AclBytesFree = 0;
1726 paclsize->AclBytesInUse = pAcl->AclSize;
1729 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1736 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1737 status = STATUS_INVALID_PARAMETER;