push 8794ef13811f1799d6928b27ab1cf994e8ac55b4
[wine/hacks.git] / dlls / ntdll / sec.c
blobb88e198ad0c462d1fafd8866c9bdccdb3746584d
1 /*
2 * Security functions
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
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <ctype.h>
30 #include <math.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
35 #include "ntstatus.h"
36 #define WIN32_NO_STATUS
37 #include "windef.h"
38 #include "wine/exception.h"
39 #include "ntdll_misc.h"
40 #include "excpt.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)
52 DWORD size;
54 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
55 return FALSE;
57 size = ((ACL *)pSourceAcl)->AclSize;
58 if (nDestinationAclLength < size)
59 return FALSE;
61 memmove(pDestinationAcl, pSourceAcl, size);
62 return TRUE;
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;
70 DWORD dwLengthSid;
71 DWORD dwAceSize;
72 DWORD *pAccessMask;
73 DWORD *pSidStart;
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;
87 if (!pAceHeader)
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);
110 pAcl->AceCount++;
112 return STATUS_SUCCESS;
116 * SID FUNCTIONS
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,
130 PSID *pSid )
132 SID *tmp_sid;
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;
161 break;
163 *pSid = tmp_sid;
164 return STATUS_SUCCESS;
167 /******************************************************************************
168 * RtlEqualSid [NTDLL.@]
170 * Determine if two SIDs are equal.
172 * PARAMS
173 * pSid1 [I] Source SID
174 * pSid2 [I] SID to compare with
176 * RETURNS
177 * TRUE, if pSid1 is equal to pSid2,
178 * FALSE otherwise.
180 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
182 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
183 return FALSE;
185 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
186 return FALSE;
188 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
189 return FALSE;
191 return TRUE;
194 /******************************************************************************
195 * RtlEqualPrefixSid [NTDLL.@]
197 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
199 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
200 return FALSE;
202 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
203 return FALSE;
205 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
206 return FALSE;
208 return TRUE;
212 /******************************************************************************
213 * RtlFreeSid [NTDLL.@]
215 * Free the resources used by a SID.
217 * PARAMS
218 * pSid [I] SID to Free.
220 * RETURNS
221 * STATUS_SUCCESS.
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
235 * PARAMS
236 * nrofsubauths [I] Number of Sub Authorities in the SID.
238 * RETURNS
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
251 * PARAMS
252 * pSid [I] SID to get the size of.
254 * RETURNS
255 * The size, in bytes, of pSid.
257 DWORD WINAPI RtlLengthSid(PSID pSid)
259 TRACE("sid=%p\n",pSid);
260 if (!pSid) return 0;
261 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
264 /**************************************************************************
265 * RtlInitializeSid [NTDLL.@]
267 * Initialise a SID.
269 * PARAMS
270 * pSid [I] SID to initialise
271 * pIdentifierAuthority [I] Identifier Authority
272 * nSubAuthorityCount [I] Number of Sub Authorities
274 * RETURNS
275 * Success: TRUE. pSid is initialised with the details given.
276 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
278 BOOL WINAPI RtlInitializeSid(
279 PSID pSid,
280 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
281 BYTE nSubAuthorityCount)
283 int i;
284 SID* pisid=pSid;
286 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
287 return FALSE;
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;
297 return TRUE;
300 /**************************************************************************
301 * RtlSubAuthoritySid [NTDLL.@]
303 * Return the Sub Authority of a SID
305 * PARAMS
306 * pSid [I] SID to get the Sub Authority from.
307 * nSubAuthority [I] Sub Authority number.
309 * RETURNS
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.
322 * PARAMS
323 * pSid [I] SID to get the Identifier Authority from.
325 * RETURNS
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.
338 * PARAMS
339 * pSid [I] SID to get the count from.
341 * RETURNS
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)))
356 return FALSE;
358 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
359 return FALSE;
361 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
362 return TRUE;
364 /******************************************************************************
365 * RtlValidSid [NTDLL.@]
367 * Determine if a SID is valid.
369 * PARAMS
370 * pSid [I] SID to check
372 * RETURNS
373 * TRUE if pSid is valid,
374 * FALSE otherwise.
376 BOOLEAN WINAPI RtlValidSid( PSID pSid )
378 BOOL ret;
379 __TRY
381 ret = TRUE;
382 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
383 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
385 ret = FALSE;
388 __EXCEPT_PAGE_FAULT
390 WARN("(%p): invalid pointer!\n", pSid);
391 return FALSE;
393 __ENDTRY
394 return ret;
399 * security descriptor functions
402 /**************************************************************************
403 * RtlCreateSecurityDescriptor [NTDLL.@]
405 * Initialise a SECURITY_DESCRIPTOR.
407 * PARAMS
408 * lpsd [O] Descriptor to initialise.
409 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
411 * RETURNS
412 * Success: STATUS_SUCCESS.
413 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
415 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
416 PSECURITY_DESCRIPTOR lpsd,
417 DWORD rev)
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.
431 * PARAMS
432 * pSourceSD [O] SD to copy from.
433 * pDestinationSD [I] Destination SD.
435 * RETURNS
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;
443 PSID Owner, Group;
444 PACL Dacl, Sacl;
445 BOOLEAN defaulted, present;
446 DWORD length;
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;
457 /* copy Owner */
458 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
459 length = RtlLengthSid(Owner);
461 if (isSelfRelative)
463 destSD->Owner = srcSD->Owner;
464 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Owner, Owner);
466 else
468 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
469 RtlCopySid(length, destSD->Owner, Owner);
472 /* copy Group */
473 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
474 length = RtlLengthSid(Group);
476 if (isSelfRelative)
478 destSD->Group = srcSD->Group;
479 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Group, Group);
481 else
483 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
484 RtlCopySid(length, destSD->Group, Group);
487 /* copy Dacl */
488 if (srcSD->Control & SE_DACL_PRESENT)
490 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
491 length = Dacl->AclSize;
493 if (isSelfRelative)
495 destSD->Dacl = srcSD->Dacl;
496 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Dacl), Dacl);
498 else
500 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
501 copy_acl(length, destSD->Dacl, Dacl);
505 /* copy Sacl */
506 if (srcSD->Control & SE_SACL_PRESENT)
508 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
509 length = Sacl->AclSize;
511 if (isSelfRelative)
513 destSD->Sacl = srcSD->Sacl;
514 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Sacl), Sacl);
516 else
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.
531 * PARAMS
532 * SecurityDescriptor [I] Descriptor to check.
534 * RETURNS
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;
556 ULONG offset = 0;
557 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
559 if ( lpsd == NULL )
560 return 0;
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) &&
572 lpsd->Sacl != NULL )
573 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
575 if ( (lpsd->Control & SE_DACL_PRESENT) &&
576 lpsd->Dacl != NULL )
577 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
579 return Size;
582 /******************************************************************************
583 * RtlGetDaclSecurityDescriptor [NTDLL.@]
586 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
587 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
588 OUT PBOOLEAN lpbDaclPresent,
589 OUT PACL *pDacl,
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);
604 else
605 *pDacl = 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,
618 BOOLEAN daclpresent,
619 PACL dacl,
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;
629 if (!daclpresent)
630 { lpsd->Control &= ~SE_DACL_PRESENT;
631 return TRUE;
634 lpsd->Control |= SE_DACL_PRESENT;
635 lpsd->Dacl = dacl;
637 if (dacldefaulted)
638 lpsd->Control |= SE_DACL_DEFAULTED;
639 else
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,
652 OUT PACL *pSacl,
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);
667 else
668 *pSacl = 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,
681 BOOLEAN saclpresent,
682 PACL sacl,
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;
691 if (!saclpresent) {
692 lpsd->Control &= ~SE_SACL_PRESENT;
693 return 0;
695 lpsd->Control |= SE_SACL_PRESENT;
696 lpsd->Sacl = sacl;
697 if (sacldefaulted)
698 lpsd->Control |= SE_SACL_DEFAULTED;
699 else
700 lpsd->Control &= ~SE_SACL_DEFAULTED;
701 return STATUS_SUCCESS;
704 /**************************************************************************
705 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
707 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
708 PSECURITY_DESCRIPTOR pSecurityDescriptor,
709 PSID *Owner,
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 +
721 (ULONG)lpsd->Owner);
722 else
723 *Owner = lpsd->Owner;
725 if ( lpsd->Control & SE_OWNER_DEFAULTED )
726 *OwnerDefaulted = TRUE;
727 else
728 *OwnerDefaulted = FALSE;
730 else
731 *Owner = NULL;
733 return STATUS_SUCCESS;
736 /**************************************************************************
737 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
739 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
740 PSECURITY_DESCRIPTOR pSecurityDescriptor,
741 PSID owner,
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;
751 lpsd->Owner = owner;
752 if (ownerdefaulted)
753 lpsd->Control |= SE_OWNER_DEFAULTED;
754 else
755 lpsd->Control &= ~SE_OWNER_DEFAULTED;
756 return STATUS_SUCCESS;
759 /**************************************************************************
760 * RtlSetGroupSecurityDescriptor [NTDLL.@]
762 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
763 PSECURITY_DESCRIPTOR pSecurityDescriptor,
764 PSID group,
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;
774 lpsd->Group = group;
775 if (groupdefaulted)
776 lpsd->Control |= SE_GROUP_DEFAULTED;
777 else
778 lpsd->Control &= ~SE_GROUP_DEFAULTED;
779 return STATUS_SUCCESS;
782 /**************************************************************************
783 * RtlGetGroupSecurityDescriptor [NTDLL.@]
785 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
786 PSECURITY_DESCRIPTOR pSecurityDescriptor,
787 PSID *Group,
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 +
799 (ULONG)lpsd->Group);
800 else
801 *Group = lpsd->Group;
803 if ( lpsd->Control & SE_GROUP_DEFAULTED )
804 *GroupDefaulted = TRUE;
805 else
806 *GroupDefaulted = FALSE;
808 else
809 *Group = NULL;
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)
822 ULONG offsetRel;
823 ULONG length;
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;
840 if (!pRel)
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);
858 offsetRel += 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)
865 offsetRel += length;
866 pRel->Sacl = (PACL) offsetRel;
867 length = pAbs->Sacl->AclSize;
868 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
870 else
872 pRel->Sacl = NULL;
875 if (pRel->Control & SE_DACL_PRESENT)
877 offsetRel += length;
878 pRel->Dacl = (PACL) offsetRel;
879 length = pAbs->Dacl->AclSize;
880 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
882 else
884 pRel->Dacl = NULL;
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,
898 OUT PACL pDacl,
899 OUT LPDWORD lpdwDaclSize,
900 OUT PACL pSacl,
901 OUT LPDWORD lpdwSaclSize,
902 OUT PSID pOwner,
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;
911 if (!pRel ||
912 !lpdwAbsoluteSecurityDescriptorSize ||
913 !lpdwDaclSize ||
914 !lpdwSaclSize ||
915 !lpdwOwnerSize ||
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;
941 if (pRel->Owner &&
942 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
944 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
945 status = STATUS_BUFFER_TOO_SMALL;
948 if (pRel->Group &&
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)
956 return status;
958 /* Copy structures, and clear the ones we don't set */
959 pAbs->Revision = pRel->Revision;
960 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
961 pAbs->Sacl = NULL;
962 pAbs->Dacl = NULL;
963 pAbs->Owner = NULL;
964 pAbs->Group = NULL;
966 if (pRel->Control & SE_SACL_PRESENT)
968 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
970 memcpy(pSacl, pAcl, pAcl->AclSize);
971 pAbs->Sacl = pSacl;
974 if (pRel->Control & SE_DACL_PRESENT)
976 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
977 memcpy(pDacl, pAcl, pAcl->AclSize);
978 pAbs->Dacl = pDacl;
981 if (pRel->Owner)
983 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
984 memcpy(pOwner, psid, RtlLengthSid(psid));
985 pAbs->Owner = pOwner;
988 if (pRel->Group)
990 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
991 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
992 pAbs->Group = pPrimaryGroup;
995 return status;
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.@]
1049 * NOTES
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;
1060 if (size>0xFFFF)
1061 return STATUS_INVALID_PARAMETER;
1063 memset(acl,'\0',sizeof(ACL));
1064 acl->AclRevision = rev;
1065 acl->AclSize = size;
1066 acl->AceCount = 0;
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(
1076 PACL acl,
1077 PACE_HEADER *x)
1079 PACE_HEADER ace;
1080 int i;
1082 *x = 0;
1083 ace = (PACE_HEADER)(acl+1);
1084 for (i=0;i<acl->AceCount;i++) {
1085 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1086 return 0;
1087 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1089 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1090 return 0;
1091 *x = ace;
1092 return 1;
1095 /**************************************************************************
1096 * RtlAddAce [NTDLL.@]
1098 NTSTATUS WINAPI RtlAddAce(
1099 PACL acl,
1100 DWORD rev,
1101 DWORD xnrofaces,
1102 PACE_HEADER acestart,
1103 DWORD acelen)
1105 PACE_HEADER ace,targetace;
1106 int nrofaces;
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) {
1114 nrofaces++;
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)
1129 NTSTATUS status;
1130 PACE_HEADER pAce;
1132 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1134 if (STATUS_SUCCESS == status)
1136 PACE_HEADER pcAce;
1137 DWORD len = 0;
1139 /* skip over the ACE we are deleting */
1140 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1141 dwAceIndex++;
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);
1152 pAcl->AceCount--;
1155 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1157 return status;
1160 /******************************************************************************
1161 * RtlAddAccessAllowedAce [NTDLL.@]
1163 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1164 IN OUT PACL pAcl,
1165 IN DWORD dwAceRevision,
1166 IN DWORD AccessMask,
1167 IN PSID pSid)
1169 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1172 /******************************************************************************
1173 * RtlAddAccessAllowedAceEx [NTDLL.@]
1175 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1176 IN OUT PACL pAcl,
1177 IN DWORD dwAceRevision,
1178 IN DWORD AceFlags,
1179 IN DWORD AccessMask,
1180 IN PSID pSid)
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(
1192 IN OUT PACL pAcl,
1193 IN DWORD dwAceRevision,
1194 IN DWORD AccessMask,
1195 IN PSID pSid)
1197 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1200 /******************************************************************************
1201 * RtlAddAccessDeniedAceEx [NTDLL.@]
1203 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1204 IN OUT PACL pAcl,
1205 IN DWORD dwAceRevision,
1206 IN DWORD AceFlags,
1207 IN DWORD AccessMask,
1208 IN PSID pSid)
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(
1220 IN OUT PACL pAcl,
1221 IN DWORD dwAceRevision,
1222 IN DWORD dwAccessMask,
1223 IN PSID pSid,
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);
1232 if (bAuditSuccess)
1233 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1235 if (bAuditFailure)
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)
1247 BOOLEAN ret;
1248 TRACE("(%p)\n", pAcl);
1250 __TRY
1252 PACE_HEADER ace;
1253 int i;
1255 if (pAcl->AclRevision != ACL_REVISION)
1256 ret = FALSE;
1257 else
1259 ace = (PACE_HEADER)(pAcl+1);
1260 ret = TRUE;
1261 for (i=0;i<=pAcl->AceCount;i++)
1263 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1265 ret = FALSE;
1266 break;
1268 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1272 __EXCEPT_PAGE_FAULT
1274 WARN("(%p): invalid pointer!\n", pAcl);
1275 return 0;
1277 __ENDTRY
1278 return ret;
1281 /******************************************************************************
1282 * RtlGetAce [NTDLL.@]
1284 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1286 PACE_HEADER ace;
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;
1303 * misc
1306 /******************************************************************************
1307 * RtlAdjustPrivilege [NTDLL.@]
1309 * Enables or disables a privilege from the calling thread or process.
1311 * PARAMS
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.
1317 * RETURNS
1318 * Success: STATUS_SUCCESS.
1319 * Failure: NTSTATUS code.
1321 * SEE ALSO
1322 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1325 NTSTATUS WINAPI
1326 RtlAdjustPrivilege(ULONG Privilege,
1327 BOOLEAN Enable,
1328 BOOLEAN CurrentThread,
1329 PBOOLEAN Enabled)
1331 TOKEN_PRIVILEGES NewState;
1332 TOKEN_PRIVILEGES OldState;
1333 ULONG ReturnLength;
1334 HANDLE TokenHandle;
1335 NTSTATUS Status;
1337 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1338 CurrentThread ? "TRUE" : "FALSE", Enabled);
1340 if (CurrentThread)
1342 Status = NtOpenThreadToken(GetCurrentThread(),
1343 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1344 FALSE,
1345 &TokenHandle);
1347 else
1349 Status = NtOpenProcessToken(GetCurrentProcess(),
1350 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1351 &TokenHandle);
1354 if (!NT_SUCCESS(Status))
1356 WARN("Retrieving token handle failed (Status %x)\n", Status);
1357 return 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,
1368 FALSE,
1369 &NewState,
1370 sizeof(TOKEN_PRIVILEGES),
1371 &OldState,
1372 &ReturnLength);
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);
1382 return Status;
1385 if (OldState.PrivilegeCount == 0)
1386 *Enabled = Enable;
1387 else
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.
1399 * PARAMS
1400 * ImpersonationLevel [I] Level at which to impersonate.
1402 * RETURNS
1403 * Success: STATUS_SUCCESS.
1404 * Failure: NTSTATUS code.
1406 NTSTATUS WINAPI
1407 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1409 NTSTATUS Status;
1410 OBJECT_ATTRIBUTES ObjectAttributes;
1411 HANDLE ProcessToken;
1412 HANDLE ImpersonationToken;
1414 TRACE("(%08x)\n", ImpersonationLevel);
1416 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1417 &ProcessToken);
1418 if (Status != STATUS_SUCCESS)
1419 return Status;
1421 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1423 Status = NtDuplicateToken( ProcessToken,
1424 TOKEN_IMPERSONATE,
1425 &ObjectAttributes,
1426 ImpersonationLevel,
1427 TokenImpersonation,
1428 &ImpersonationToken );
1429 if (Status != STATUS_SUCCESS)
1431 NtClose( ProcessToken );
1432 return Status;
1435 Status = NtSetInformationThread( GetCurrentThread(),
1436 ThreadImpersonationToken,
1437 &ImpersonationToken,
1438 sizeof(ImpersonationToken) );
1440 NtClose( ImpersonationToken );
1441 NtClose( ProcessToken );
1443 return Status;
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.
1453 * PARAMS
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.
1463 * RETURNS
1464 * NTSTATUS code.
1466 * NOTES
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
1469 * GrantedAccess.
1470 * The SecurityDescriptor must have a valid owner and groups present,
1471 * otherwise the function will fail.
1473 NTSTATUS WINAPI
1474 NtAccessCheck(
1475 PSECURITY_DESCRIPTOR SecurityDescriptor,
1476 HANDLE ClientToken,
1477 ACCESS_MASK DesiredAccess,
1478 PGENERIC_MAPPING GenericMapping,
1479 PPRIVILEGE_SET PrivilegeSet,
1480 PULONG ReturnLength,
1481 PULONG GrantedAccess,
1482 NTSTATUS *AccessStatus)
1484 NTSTATUS status;
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;
1493 PSID owner;
1494 PSID group;
1495 PACL sacl;
1496 PACL dacl;
1497 BOOLEAN defaulted, present;
1498 DWORD revision;
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;
1539 SERVER_END_REQ;
1541 return status;
1544 /******************************************************************************
1545 * NtSetSecurityObject [NTDLL.@]
1546 * ZwSetSecurityObject [NTDLL.@]
1548 * Sets specified parts of the object's security descriptor.
1550 * PARAMS
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.
1555 * RETURNS
1556 * NTSTATUS code.
1559 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1560 SECURITY_INFORMATION SecurityInformation,
1561 PSECURITY_DESCRIPTOR SecurityDescriptor)
1563 NTSTATUS status;
1564 struct security_descriptor sd;
1565 PACL dacl, sacl;
1566 PSID owner, group;
1567 BOOLEAN defaulted, present;
1568 DWORD revision;
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 );
1624 SERVER_END_REQ;
1626 return status;
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,
1639 PSID pSid,
1640 BOOLEAN AllocateString)
1642 static const WCHAR formatW[] = {'-','%','u',0};
1643 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1644 WCHAR *p = buffer;
1645 const SID *sid = (const SID *)pSid;
1646 DWORD i, len;
1648 *p++ = 'S';
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);
1660 if (AllocateString)
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(
1676 PACL pAcl,
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;
1694 else
1695 paclrev->AclRevision = pAcl->AclRevision;
1697 break;
1700 case AclSizeInformation:
1702 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1704 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1705 status = STATUS_INVALID_PARAMETER;
1706 else
1708 INT i;
1709 PACE_HEADER ace;
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;
1728 else
1729 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1732 break;
1735 default:
1736 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1737 status = STATUS_INVALID_PARAMETER;
1740 return status;