push bc3e5bf5ba806943a97979264a1f2e4a4dde5c94
[wine/hacks.git] / dlls / ntdll / sec.c
blobaf89b724ea2a68a061120f3efb93eec0a7d123dc
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 "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 /* helper function to copy an ACL */
49 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
51 DWORD size;
53 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
54 return FALSE;
56 size = ((ACL *)pSourceAcl)->AclSize;
57 if (nDestinationAclLength < size)
58 return FALSE;
60 memmove(pDestinationAcl, pSourceAcl, size);
61 return TRUE;
64 /* generically adds an ACE to an ACL */
65 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
66 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
68 ACE_HEADER *pAceHeader;
69 DWORD dwLengthSid;
70 DWORD dwAceSize;
71 DWORD *pAccessMask;
72 DWORD *pSidStart;
74 if (!RtlValidSid(pSid))
75 return STATUS_INVALID_SID;
77 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
78 return STATUS_REVISION_MISMATCH;
80 if (!RtlValidAcl(pAcl))
81 return STATUS_INVALID_ACL;
83 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
84 return STATUS_INVALID_ACL;
86 if (!pAceHeader)
87 return STATUS_ALLOTTED_SPACE_EXCEEDED;
89 /* calculate generic size of the ACE */
90 dwLengthSid = RtlLengthSid(pSid);
91 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
92 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
93 return STATUS_ALLOTTED_SPACE_EXCEEDED;
95 /* fill the new ACE */
96 pAceHeader->AceType = dwAceType;
97 pAceHeader->AceFlags = dwAceFlags;
98 pAceHeader->AceSize = dwAceSize;
100 /* skip past the ACE_HEADER of the ACE */
101 pAccessMask = (DWORD *)(pAceHeader + 1);
102 *pAccessMask = dwAccessMask;
104 /* skip past ACE->Mask */
105 pSidStart = pAccessMask + 1;
106 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
108 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
109 pAcl->AceCount++;
111 return STATUS_SUCCESS;
115 * SID FUNCTIONS
118 /******************************************************************************
119 * RtlAllocateAndInitializeSid [NTDLL.@]
122 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
123 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
124 BYTE nSubAuthorityCount,
125 DWORD nSubAuthority0, DWORD nSubAuthority1,
126 DWORD nSubAuthority2, DWORD nSubAuthority3,
127 DWORD nSubAuthority4, DWORD nSubAuthority5,
128 DWORD nSubAuthority6, DWORD nSubAuthority7,
129 PSID *pSid )
131 SID *tmp_sid;
133 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
134 pIdentifierAuthority,nSubAuthorityCount,
135 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
136 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
138 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
140 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
141 RtlLengthRequiredSid(nSubAuthorityCount))))
142 return STATUS_NO_MEMORY;
144 tmp_sid->Revision = SID_REVISION;
146 if (pIdentifierAuthority)
147 memcpy(&tmp_sid->IdentifierAuthority, pIdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY));
148 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
150 switch( nSubAuthorityCount )
152 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
153 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
154 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
155 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
156 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
157 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
158 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
159 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
160 break;
162 *pSid = tmp_sid;
163 return STATUS_SUCCESS;
166 /******************************************************************************
167 * RtlEqualSid [NTDLL.@]
169 * Determine if two SIDs are equal.
171 * PARAMS
172 * pSid1 [I] Source SID
173 * pSid2 [I] SID to compare with
175 * RETURNS
176 * TRUE, if pSid1 is equal to pSid2,
177 * FALSE otherwise.
179 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
181 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
182 return FALSE;
184 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
185 return FALSE;
187 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
188 return FALSE;
190 return TRUE;
193 /******************************************************************************
194 * RtlEqualPrefixSid [NTDLL.@]
196 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
198 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
199 return FALSE;
201 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
202 return FALSE;
204 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
205 return FALSE;
207 return TRUE;
211 /******************************************************************************
212 * RtlFreeSid [NTDLL.@]
214 * Free the resources used by a SID.
216 * PARAMS
217 * pSid [I] SID to Free.
219 * RETURNS
220 * STATUS_SUCCESS.
222 DWORD WINAPI RtlFreeSid(PSID pSid)
224 TRACE("(%p)\n", pSid);
225 RtlFreeHeap( GetProcessHeap(), 0, pSid );
226 return STATUS_SUCCESS;
229 /**************************************************************************
230 * RtlLengthRequiredSid [NTDLL.@]
232 * Determine the amount of memory a SID will use
234 * PARAMS
235 * nrofsubauths [I] Number of Sub Authorities in the SID.
237 * RETURNS
238 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
240 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
242 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
245 /**************************************************************************
246 * RtlLengthSid [NTDLL.@]
248 * Determine the amount of memory a SID is using
250 * PARAMS
251 * pSid [I] SID to get the size of.
253 * RETURNS
254 * The size, in bytes, of pSid.
256 DWORD WINAPI RtlLengthSid(PSID pSid)
258 TRACE("sid=%p\n",pSid);
259 if (!pSid) return 0;
260 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
263 /**************************************************************************
264 * RtlInitializeSid [NTDLL.@]
266 * Initialise a SID.
268 * PARAMS
269 * pSid [I] SID to initialise
270 * pIdentifierAuthority [I] Identifier Authority
271 * nSubAuthorityCount [I] Number of Sub Authorities
273 * RETURNS
274 * Success: TRUE. pSid is initialised with the details given.
275 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
277 BOOL WINAPI RtlInitializeSid(
278 PSID pSid,
279 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
280 BYTE nSubAuthorityCount)
282 int i;
283 SID* pisid=pSid;
285 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
286 return FALSE;
288 pisid->Revision = SID_REVISION;
289 pisid->SubAuthorityCount = nSubAuthorityCount;
290 if (pIdentifierAuthority)
291 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
293 for (i = 0; i < nSubAuthorityCount; i++)
294 *RtlSubAuthoritySid(pSid, i) = 0;
296 return TRUE;
299 /**************************************************************************
300 * RtlSubAuthoritySid [NTDLL.@]
302 * Return the Sub Authority of a SID
304 * PARAMS
305 * pSid [I] SID to get the Sub Authority from.
306 * nSubAuthority [I] Sub Authority number.
308 * RETURNS
309 * A pointer to The Sub Authority value of pSid.
311 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
313 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
316 /**************************************************************************
317 * RtlIdentifierAuthoritySid [NTDLL.@]
319 * Return the Identifier Authority of a SID.
321 * PARAMS
322 * pSid [I] SID to get the Identifier Authority from.
324 * RETURNS
325 * A pointer to the Identifier Authority value of pSid.
327 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
329 return &(((SID*)pSid)->IdentifierAuthority);
332 /**************************************************************************
333 * RtlSubAuthorityCountSid [NTDLL.@]
335 * Get the number of Sub Authorities in a SID.
337 * PARAMS
338 * pSid [I] SID to get the count from.
340 * RETURNS
341 * A pointer to the Sub Authority count of pSid.
343 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
345 return &(((SID*)pSid)->SubAuthorityCount);
348 /**************************************************************************
349 * RtlCopySid [NTDLL.@]
351 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
353 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
354 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
355 return FALSE;
357 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
358 return FALSE;
360 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
361 return TRUE;
363 /******************************************************************************
364 * RtlValidSid [NTDLL.@]
366 * Determine if a SID is valid.
368 * PARAMS
369 * pSid [I] SID to check
371 * RETURNS
372 * TRUE if pSid is valid,
373 * FALSE otherwise.
375 BOOLEAN WINAPI RtlValidSid( PSID pSid )
377 BOOL ret;
378 __TRY
380 ret = TRUE;
381 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
382 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
384 ret = FALSE;
387 __EXCEPT_PAGE_FAULT
389 WARN("(%p): invalid pointer!\n", pSid);
390 return FALSE;
392 __ENDTRY
393 return ret;
398 * security descriptor functions
401 /**************************************************************************
402 * RtlCreateSecurityDescriptor [NTDLL.@]
404 * Initialise a SECURITY_DESCRIPTOR.
406 * PARAMS
407 * lpsd [O] Descriptor to initialise.
408 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
410 * RETURNS
411 * Success: STATUS_SUCCESS.
412 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
414 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
415 PSECURITY_DESCRIPTOR lpsd,
416 DWORD rev)
418 if (rev!=SECURITY_DESCRIPTOR_REVISION)
419 return STATUS_UNKNOWN_REVISION;
420 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
421 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
422 return STATUS_SUCCESS;
425 /**************************************************************************
426 * RtlCopySecurityDescriptor [NTDLL.@]
428 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
430 * PARAMS
431 * pSourceSD [O] SD to copy from.
432 * pDestinationSD [I] Destination SD.
434 * RETURNS
435 * Success: STATUS_SUCCESS.
436 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
438 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
440 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
441 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
442 PSID Owner, Group;
443 PACL Dacl, Sacl;
444 BOOLEAN defaulted, present;
445 DWORD length;
446 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
448 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
449 return STATUS_UNKNOWN_REVISION;
451 /* copy initial data */
452 destSD->Revision = srcSD->Revision;
453 destSD->Sbz1 = srcSD->Sbz1;
454 destSD->Control = srcSD->Control;
456 /* copy Owner */
457 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
458 length = RtlLengthSid(Owner);
460 if (isSelfRelative)
462 destSD->Owner = srcSD->Owner;
463 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner);
465 else
467 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
468 RtlCopySid(length, destSD->Owner, Owner);
471 /* copy Group */
472 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
473 length = RtlLengthSid(Group);
475 if (isSelfRelative)
477 destSD->Group = srcSD->Group;
478 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
480 else
482 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
483 RtlCopySid(length, destSD->Group, Group);
486 /* copy Dacl */
487 if (srcSD->Control & SE_DACL_PRESENT)
489 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
490 length = Dacl->AclSize;
492 if (isSelfRelative)
494 destSD->Dacl = srcSD->Dacl;
495 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl);
497 else
499 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
500 copy_acl(length, destSD->Dacl, Dacl);
504 /* copy Sacl */
505 if (srcSD->Control & SE_SACL_PRESENT)
507 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
508 length = Sacl->AclSize;
510 if (isSelfRelative)
512 destSD->Sacl = srcSD->Sacl;
513 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl);
515 else
517 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
518 copy_acl(length, destSD->Sacl, Sacl);
522 return STATUS_SUCCESS;
525 /**************************************************************************
526 * RtlValidSecurityDescriptor [NTDLL.@]
528 * Determine if a SECURITY_DESCRIPTOR is valid.
530 * PARAMS
531 * SecurityDescriptor [I] Descriptor to check.
533 * RETURNS
534 * Success: STATUS_SUCCESS.
535 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
537 NTSTATUS WINAPI RtlValidSecurityDescriptor(
538 PSECURITY_DESCRIPTOR SecurityDescriptor)
540 if ( ! SecurityDescriptor )
541 return STATUS_INVALID_SECURITY_DESCR;
542 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
543 return STATUS_UNKNOWN_REVISION;
545 return STATUS_SUCCESS;
548 /**************************************************************************
549 * RtlLengthSecurityDescriptor [NTDLL.@]
551 ULONG WINAPI RtlLengthSecurityDescriptor(
552 PSECURITY_DESCRIPTOR pSecurityDescriptor)
554 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
555 ULONG_PTR offset = 0;
556 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
558 if ( lpsd == NULL )
559 return 0;
561 if ( lpsd->Control & SE_SELF_RELATIVE)
562 offset = (ULONG_PTR) lpsd;
564 if ( lpsd->Owner != NULL )
565 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
567 if ( lpsd->Group != NULL )
568 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
570 if ( (lpsd->Control & SE_SACL_PRESENT) &&
571 lpsd->Sacl != NULL )
572 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
574 if ( (lpsd->Control & SE_DACL_PRESENT) &&
575 lpsd->Dacl != NULL )
576 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
578 return Size;
581 /******************************************************************************
582 * RtlGetDaclSecurityDescriptor [NTDLL.@]
585 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
586 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
587 OUT PBOOLEAN lpbDaclPresent,
588 OUT PACL *pDacl,
589 OUT PBOOLEAN lpbDaclDefaulted)
591 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
593 TRACE("(%p,%p,%p,%p)\n",
594 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
596 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
597 return STATUS_UNKNOWN_REVISION ;
599 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
601 if ( SE_SELF_RELATIVE & lpsd->Control)
602 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Dacl);
603 else
604 *pDacl = lpsd->Dacl;
606 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
609 return STATUS_SUCCESS;
612 /**************************************************************************
613 * RtlSetDaclSecurityDescriptor [NTDLL.@]
615 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
616 PSECURITY_DESCRIPTOR pSecurityDescriptor,
617 BOOLEAN daclpresent,
618 PACL dacl,
619 BOOLEAN dacldefaulted )
621 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
623 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
624 return STATUS_UNKNOWN_REVISION;
625 if (lpsd->Control & SE_SELF_RELATIVE)
626 return STATUS_INVALID_SECURITY_DESCR;
628 if (!daclpresent)
629 { lpsd->Control &= ~SE_DACL_PRESENT;
630 return TRUE;
633 lpsd->Control |= SE_DACL_PRESENT;
634 lpsd->Dacl = dacl;
636 if (dacldefaulted)
637 lpsd->Control |= SE_DACL_DEFAULTED;
638 else
639 lpsd->Control &= ~SE_DACL_DEFAULTED;
641 return STATUS_SUCCESS;
644 /******************************************************************************
645 * RtlGetSaclSecurityDescriptor [NTDLL.@]
648 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
649 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
650 OUT PBOOLEAN lpbSaclPresent,
651 OUT PACL *pSacl,
652 OUT PBOOLEAN lpbSaclDefaulted)
654 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
656 TRACE("(%p,%p,%p,%p)\n",
657 pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
659 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
660 return STATUS_UNKNOWN_REVISION;
662 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
664 if (SE_SELF_RELATIVE & lpsd->Control)
665 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Sacl);
666 else
667 *pSacl = lpsd->Sacl;
669 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
672 return STATUS_SUCCESS;
675 /**************************************************************************
676 * RtlSetSaclSecurityDescriptor [NTDLL.@]
678 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
679 PSECURITY_DESCRIPTOR pSecurityDescriptor,
680 BOOLEAN saclpresent,
681 PACL sacl,
682 BOOLEAN sacldefaulted)
684 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
686 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
687 return STATUS_UNKNOWN_REVISION;
688 if (lpsd->Control & SE_SELF_RELATIVE)
689 return STATUS_INVALID_SECURITY_DESCR;
690 if (!saclpresent) {
691 lpsd->Control &= ~SE_SACL_PRESENT;
692 return 0;
694 lpsd->Control |= SE_SACL_PRESENT;
695 lpsd->Sacl = sacl;
696 if (sacldefaulted)
697 lpsd->Control |= SE_SACL_DEFAULTED;
698 else
699 lpsd->Control &= ~SE_SACL_DEFAULTED;
700 return STATUS_SUCCESS;
703 /**************************************************************************
704 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
706 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
707 PSECURITY_DESCRIPTOR pSecurityDescriptor,
708 PSID *Owner,
709 PBOOLEAN OwnerDefaulted)
711 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
713 if ( !lpsd || !Owner || !OwnerDefaulted )
714 return STATUS_INVALID_PARAMETER;
716 if (lpsd->Owner != NULL)
718 if (lpsd->Control & SE_SELF_RELATIVE)
719 *Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner);
720 else
721 *Owner = lpsd->Owner;
723 if ( lpsd->Control & SE_OWNER_DEFAULTED )
724 *OwnerDefaulted = TRUE;
725 else
726 *OwnerDefaulted = FALSE;
728 else
729 *Owner = NULL;
731 return STATUS_SUCCESS;
734 /**************************************************************************
735 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
737 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
738 PSECURITY_DESCRIPTOR pSecurityDescriptor,
739 PSID owner,
740 BOOLEAN ownerdefaulted)
742 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
744 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
745 return STATUS_UNKNOWN_REVISION;
746 if (lpsd->Control & SE_SELF_RELATIVE)
747 return STATUS_INVALID_SECURITY_DESCR;
749 lpsd->Owner = owner;
750 if (ownerdefaulted)
751 lpsd->Control |= SE_OWNER_DEFAULTED;
752 else
753 lpsd->Control &= ~SE_OWNER_DEFAULTED;
754 return STATUS_SUCCESS;
757 /**************************************************************************
758 * RtlSetGroupSecurityDescriptor [NTDLL.@]
760 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
761 PSECURITY_DESCRIPTOR pSecurityDescriptor,
762 PSID group,
763 BOOLEAN groupdefaulted)
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;
772 lpsd->Group = group;
773 if (groupdefaulted)
774 lpsd->Control |= SE_GROUP_DEFAULTED;
775 else
776 lpsd->Control &= ~SE_GROUP_DEFAULTED;
777 return STATUS_SUCCESS;
780 /**************************************************************************
781 * RtlGetGroupSecurityDescriptor [NTDLL.@]
783 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
784 PSECURITY_DESCRIPTOR pSecurityDescriptor,
785 PSID *Group,
786 PBOOLEAN GroupDefaulted)
788 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
790 if ( !lpsd || !Group || !GroupDefaulted )
791 return STATUS_INVALID_PARAMETER;
793 if (lpsd->Group != NULL)
795 if (lpsd->Control & SE_SELF_RELATIVE)
796 *Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group);
797 else
798 *Group = lpsd->Group;
800 if ( lpsd->Control & SE_GROUP_DEFAULTED )
801 *GroupDefaulted = TRUE;
802 else
803 *GroupDefaulted = FALSE;
805 else
806 *Group = NULL;
808 return STATUS_SUCCESS;
811 /**************************************************************************
812 * RtlMakeSelfRelativeSD [NTDLL.@]
814 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
815 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
816 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
817 IN OUT LPDWORD lpdwBufferLength)
819 ULONG_PTR offsetRel;
820 ULONG length;
821 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
822 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
824 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
825 lpdwBufferLength ? *lpdwBufferLength: -1);
827 if (!lpdwBufferLength || !pAbs)
828 return STATUS_INVALID_PARAMETER;
830 length = RtlLengthSecurityDescriptor(pAbs);
831 if (*lpdwBufferLength < length)
833 *lpdwBufferLength = length;
834 return STATUS_BUFFER_TOO_SMALL;
837 if (!pRel)
838 return STATUS_INVALID_PARAMETER;
840 if (pAbs->Control & SE_SELF_RELATIVE)
842 memcpy(pRel, pAbs, length);
843 return STATUS_SUCCESS;
846 pRel->Revision = pAbs->Revision;
847 pRel->Sbz1 = pAbs->Sbz1;
848 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
850 offsetRel = sizeof(SECURITY_DESCRIPTOR);
851 pRel->Owner = (PSID) offsetRel;
852 length = RtlLengthSid(pAbs->Owner);
853 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
855 offsetRel += length;
856 pRel->Group = (PSID) offsetRel;
857 length = RtlLengthSid(pAbs->Group);
858 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
860 if (pRel->Control & SE_SACL_PRESENT)
862 offsetRel += length;
863 pRel->Sacl = (PACL) offsetRel;
864 length = pAbs->Sacl->AclSize;
865 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
867 else
869 pRel->Sacl = NULL;
872 if (pRel->Control & SE_DACL_PRESENT)
874 offsetRel += length;
875 pRel->Dacl = (PACL) offsetRel;
876 length = pAbs->Dacl->AclSize;
877 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
879 else
881 pRel->Dacl = NULL;
884 return STATUS_SUCCESS;
888 /**************************************************************************
889 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
891 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
892 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
893 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
894 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
895 OUT PACL pDacl,
896 OUT LPDWORD lpdwDaclSize,
897 OUT PACL pSacl,
898 OUT LPDWORD lpdwSaclSize,
899 OUT PSID pOwner,
900 OUT LPDWORD lpdwOwnerSize,
901 OUT PSID pPrimaryGroup,
902 OUT LPDWORD lpdwPrimaryGroupSize)
904 NTSTATUS status = STATUS_SUCCESS;
905 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
906 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
908 if (!pRel ||
909 !lpdwAbsoluteSecurityDescriptorSize ||
910 !lpdwDaclSize ||
911 !lpdwSaclSize ||
912 !lpdwOwnerSize ||
913 !lpdwPrimaryGroupSize ||
914 ~pRel->Control & SE_SELF_RELATIVE)
915 return STATUS_INVALID_PARAMETER;
917 /* Confirm buffers are sufficiently large */
918 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
920 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
921 status = STATUS_BUFFER_TOO_SMALL;
924 if (pRel->Control & SE_DACL_PRESENT &&
925 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize)
927 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize;
928 status = STATUS_BUFFER_TOO_SMALL;
931 if (pRel->Control & SE_SACL_PRESENT &&
932 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize)
934 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize;
935 status = STATUS_BUFFER_TOO_SMALL;
938 if (pRel->Owner &&
939 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)))
941 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel));
942 status = STATUS_BUFFER_TOO_SMALL;
945 if (pRel->Group &&
946 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)))
948 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel));
949 status = STATUS_BUFFER_TOO_SMALL;
952 if (status != STATUS_SUCCESS)
953 return status;
955 /* Copy structures, and clear the ones we don't set */
956 pAbs->Revision = pRel->Revision;
957 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
958 pAbs->Sacl = NULL;
959 pAbs->Dacl = NULL;
960 pAbs->Owner = NULL;
961 pAbs->Group = NULL;
963 if (pRel->Control & SE_SACL_PRESENT)
965 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel);
967 memcpy(pSacl, pAcl, pAcl->AclSize);
968 pAbs->Sacl = pSacl;
971 if (pRel->Control & SE_DACL_PRESENT)
973 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel);
974 memcpy(pDacl, pAcl, pAcl->AclSize);
975 pAbs->Dacl = pDacl;
978 if (pRel->Owner)
980 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel);
981 memcpy(pOwner, psid, RtlLengthSid(psid));
982 pAbs->Owner = pOwner;
985 if (pRel->Group)
987 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel);
988 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
989 pAbs->Group = pPrimaryGroup;
992 return status;
995 /******************************************************************************
996 * RtlGetControlSecurityDescriptor (NTDLL.@)
998 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
999 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1000 PSECURITY_DESCRIPTOR_CONTROL pControl,
1001 LPDWORD lpdwRevision)
1003 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1005 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1007 *lpdwRevision = lpsd->Revision;
1009 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1010 return STATUS_UNKNOWN_REVISION;
1012 *pControl = lpsd->Control;
1014 return STATUS_SUCCESS;
1018 /**************************************************************************
1019 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1021 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1022 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1023 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1024 PULONG BufferLength)
1026 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1028 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1029 SelfRelativeSecurityDescriptor, BufferLength);
1031 if (abs->Control & SE_SELF_RELATIVE)
1032 return STATUS_BAD_DESCRIPTOR_FORMAT;
1034 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1035 SelfRelativeSecurityDescriptor, BufferLength);
1040 * access control list's
1043 /**************************************************************************
1044 * RtlCreateAcl [NTDLL.@]
1046 * NOTES
1047 * This should return NTSTATUS
1049 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1051 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1053 if (rev!=ACL_REVISION)
1054 return STATUS_INVALID_PARAMETER;
1055 if (size<sizeof(ACL))
1056 return STATUS_BUFFER_TOO_SMALL;
1057 if (size>0xFFFF)
1058 return STATUS_INVALID_PARAMETER;
1060 memset(acl,'\0',sizeof(ACL));
1061 acl->AclRevision = rev;
1062 acl->AclSize = size;
1063 acl->AceCount = 0;
1064 return STATUS_SUCCESS;
1067 /**************************************************************************
1068 * RtlFirstFreeAce [NTDLL.@]
1069 * looks for the AceCount+1 ACE, and if it is still within the alloced
1070 * ACL, return a pointer to it
1072 BOOLEAN WINAPI RtlFirstFreeAce(
1073 PACL acl,
1074 PACE_HEADER *x)
1076 PACE_HEADER ace;
1077 int i;
1079 *x = 0;
1080 ace = (PACE_HEADER)(acl+1);
1081 for (i=0;i<acl->AceCount;i++) {
1082 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1083 return 0;
1084 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1086 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1087 return 0;
1088 *x = ace;
1089 return 1;
1092 /**************************************************************************
1093 * RtlAddAce [NTDLL.@]
1095 NTSTATUS WINAPI RtlAddAce(
1096 PACL acl,
1097 DWORD rev,
1098 DWORD xnrofaces,
1099 PACE_HEADER acestart,
1100 DWORD acelen)
1102 PACE_HEADER ace,targetace;
1103 int nrofaces;
1105 if (acl->AclRevision != ACL_REVISION)
1106 return STATUS_INVALID_PARAMETER;
1107 if (!RtlFirstFreeAce(acl,&targetace))
1108 return STATUS_INVALID_PARAMETER;
1109 nrofaces=0;ace=acestart;
1110 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1111 nrofaces++;
1112 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1114 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1115 return STATUS_INVALID_PARAMETER;
1116 memcpy((LPBYTE)targetace,acestart,acelen);
1117 acl->AceCount+=nrofaces;
1118 return STATUS_SUCCESS;
1121 /**************************************************************************
1122 * RtlDeleteAce [NTDLL.@]
1124 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1126 NTSTATUS status;
1127 PACE_HEADER pAce;
1129 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1131 if (STATUS_SUCCESS == status)
1133 PACE_HEADER pcAce;
1134 DWORD len = 0;
1136 /* skip over the ACE we are deleting */
1137 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1138 dwAceIndex++;
1140 /* calculate the length of the rest */
1141 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1143 len += pcAce->AceSize;
1144 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1147 /* slide them all backwards */
1148 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1149 pAcl->AceCount--;
1152 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1154 return status;
1157 /******************************************************************************
1158 * RtlAddAccessAllowedAce [NTDLL.@]
1160 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1161 IN OUT PACL pAcl,
1162 IN DWORD dwAceRevision,
1163 IN DWORD AccessMask,
1164 IN PSID pSid)
1166 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1169 /******************************************************************************
1170 * RtlAddAccessAllowedAceEx [NTDLL.@]
1172 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1173 IN OUT PACL pAcl,
1174 IN DWORD dwAceRevision,
1175 IN DWORD AceFlags,
1176 IN DWORD AccessMask,
1177 IN PSID pSid)
1179 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1181 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1182 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1185 /******************************************************************************
1186 * RtlAddAccessDeniedAce [NTDLL.@]
1188 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1189 IN OUT PACL pAcl,
1190 IN DWORD dwAceRevision,
1191 IN DWORD AccessMask,
1192 IN PSID pSid)
1194 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1197 /******************************************************************************
1198 * RtlAddAccessDeniedAceEx [NTDLL.@]
1200 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1201 IN OUT PACL pAcl,
1202 IN DWORD dwAceRevision,
1203 IN DWORD AceFlags,
1204 IN DWORD AccessMask,
1205 IN PSID pSid)
1207 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1209 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1210 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1213 /**************************************************************************
1214 * RtlAddAuditAccessAce [NTDLL.@]
1216 NTSTATUS WINAPI RtlAddAuditAccessAce(
1217 IN OUT PACL pAcl,
1218 IN DWORD dwAceRevision,
1219 IN DWORD dwAccessMask,
1220 IN PSID pSid,
1221 IN BOOL bAuditSuccess,
1222 IN BOOL bAuditFailure)
1224 DWORD dwAceFlags = 0;
1226 TRACE("(%p,%d,%d,%p,%u,%u)\n",pAcl,dwAceRevision,dwAccessMask,
1227 pSid,bAuditSuccess,bAuditFailure);
1229 if (bAuditSuccess)
1230 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1232 if (bAuditFailure)
1233 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1235 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1236 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1239 /******************************************************************************
1240 * RtlValidAcl [NTDLL.@]
1242 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1244 BOOLEAN ret;
1245 TRACE("(%p)\n", pAcl);
1247 __TRY
1249 PACE_HEADER ace;
1250 int i;
1252 if (pAcl->AclRevision != ACL_REVISION)
1253 ret = FALSE;
1254 else
1256 ace = (PACE_HEADER)(pAcl+1);
1257 ret = TRUE;
1258 for (i=0;i<=pAcl->AceCount;i++)
1260 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1262 ret = FALSE;
1263 break;
1265 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1269 __EXCEPT_PAGE_FAULT
1271 WARN("(%p): invalid pointer!\n", pAcl);
1272 return 0;
1274 __ENDTRY
1275 return ret;
1278 /******************************************************************************
1279 * RtlGetAce [NTDLL.@]
1281 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1283 PACE_HEADER ace;
1285 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1287 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1288 return STATUS_INVALID_PARAMETER;
1290 ace = (PACE_HEADER)(pAcl + 1);
1291 for (;dwAceIndex;dwAceIndex--)
1292 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1294 *pAce = (LPVOID) ace;
1296 return STATUS_SUCCESS;
1300 * misc
1303 /******************************************************************************
1304 * RtlAdjustPrivilege [NTDLL.@]
1306 * Enables or disables a privilege from the calling thread or process.
1308 * PARAMS
1309 * Privilege [I] Privilege index to change.
1310 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1311 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1312 * Enabled [O] Whether privilege was previously enabled or disabled.
1314 * RETURNS
1315 * Success: STATUS_SUCCESS.
1316 * Failure: NTSTATUS code.
1318 * SEE ALSO
1319 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1322 NTSTATUS WINAPI
1323 RtlAdjustPrivilege(ULONG Privilege,
1324 BOOLEAN Enable,
1325 BOOLEAN CurrentThread,
1326 PBOOLEAN Enabled)
1328 TOKEN_PRIVILEGES NewState;
1329 TOKEN_PRIVILEGES OldState;
1330 ULONG ReturnLength;
1331 HANDLE TokenHandle;
1332 NTSTATUS Status;
1334 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1335 CurrentThread ? "TRUE" : "FALSE", Enabled);
1337 if (CurrentThread)
1339 Status = NtOpenThreadToken(GetCurrentThread(),
1340 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1341 FALSE,
1342 &TokenHandle);
1344 else
1346 Status = NtOpenProcessToken(GetCurrentProcess(),
1347 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1348 &TokenHandle);
1351 if (!NT_SUCCESS(Status))
1353 WARN("Retrieving token handle failed (Status %x)\n", Status);
1354 return Status;
1357 OldState.PrivilegeCount = 1;
1359 NewState.PrivilegeCount = 1;
1360 NewState.Privileges[0].Luid.LowPart = Privilege;
1361 NewState.Privileges[0].Luid.HighPart = 0;
1362 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1364 Status = NtAdjustPrivilegesToken(TokenHandle,
1365 FALSE,
1366 &NewState,
1367 sizeof(TOKEN_PRIVILEGES),
1368 &OldState,
1369 &ReturnLength);
1370 NtClose (TokenHandle);
1371 if (Status == STATUS_NOT_ALL_ASSIGNED)
1373 TRACE("Failed to assign all privileges\n");
1374 return STATUS_PRIVILEGE_NOT_HELD;
1376 if (!NT_SUCCESS(Status))
1378 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1379 return Status;
1382 if (OldState.PrivilegeCount == 0)
1383 *Enabled = Enable;
1384 else
1385 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1387 return STATUS_SUCCESS;
1390 /******************************************************************************
1391 * RtlImpersonateSelf [NTDLL.@]
1393 * Makes an impersonation token that represents the process user and assigns
1394 * to the current thread.
1396 * PARAMS
1397 * ImpersonationLevel [I] Level at which to impersonate.
1399 * RETURNS
1400 * Success: STATUS_SUCCESS.
1401 * Failure: NTSTATUS code.
1403 NTSTATUS WINAPI
1404 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1406 NTSTATUS Status;
1407 OBJECT_ATTRIBUTES ObjectAttributes;
1408 HANDLE ProcessToken;
1409 HANDLE ImpersonationToken;
1411 TRACE("(%08x)\n", ImpersonationLevel);
1413 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1414 &ProcessToken);
1415 if (Status != STATUS_SUCCESS)
1416 return Status;
1418 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1420 Status = NtDuplicateToken( ProcessToken,
1421 TOKEN_IMPERSONATE,
1422 &ObjectAttributes,
1423 ImpersonationLevel,
1424 TokenImpersonation,
1425 &ImpersonationToken );
1426 if (Status != STATUS_SUCCESS)
1428 NtClose( ProcessToken );
1429 return Status;
1432 Status = NtSetInformationThread( GetCurrentThread(),
1433 ThreadImpersonationToken,
1434 &ImpersonationToken,
1435 sizeof(ImpersonationToken) );
1437 NtClose( ImpersonationToken );
1438 NtClose( ProcessToken );
1440 return Status;
1443 /******************************************************************************
1444 * NtAccessCheck [NTDLL.@]
1445 * ZwAccessCheck [NTDLL.@]
1447 * Checks that a user represented by a token is allowed to access an object
1448 * represented by a security descriptor.
1450 * PARAMS
1451 * SecurityDescriptor [I] The security descriptor of the object to check.
1452 * ClientToken [I] Token of the user accessing the object.
1453 * DesiredAccess [I] The desired access to the object.
1454 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1455 * PrivilegeSet [I/O] Privileges used during the access check.
1456 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1457 * GrantedAccess [O] The actual access rights granted.
1458 * AccessStatus [O] The status of the access check.
1460 * RETURNS
1461 * NTSTATUS code.
1463 * NOTES
1464 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1465 * the maximum access rights allowed by the SD and returns them in
1466 * GrantedAccess.
1467 * The SecurityDescriptor must have a valid owner and groups present,
1468 * otherwise the function will fail.
1470 NTSTATUS WINAPI
1471 NtAccessCheck(
1472 PSECURITY_DESCRIPTOR SecurityDescriptor,
1473 HANDLE ClientToken,
1474 ACCESS_MASK DesiredAccess,
1475 PGENERIC_MAPPING GenericMapping,
1476 PPRIVILEGE_SET PrivilegeSet,
1477 PULONG ReturnLength,
1478 PULONG GrantedAccess,
1479 NTSTATUS *AccessStatus)
1481 NTSTATUS status;
1483 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1484 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1485 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1487 SERVER_START_REQ( access_check )
1489 struct security_descriptor sd;
1490 PSID owner;
1491 PSID group;
1492 PACL sacl;
1493 PACL dacl;
1494 BOOLEAN defaulted, present;
1495 DWORD revision;
1496 SECURITY_DESCRIPTOR_CONTROL control;
1498 req->handle = ClientToken;
1499 req->desired_access = DesiredAccess;
1500 req->mapping_read = GenericMapping->GenericRead;
1501 req->mapping_write = GenericMapping->GenericWrite;
1502 req->mapping_execute = GenericMapping->GenericExecute;
1503 req->mapping_all = GenericMapping->GenericAll;
1505 /* marshal security descriptor */
1506 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1507 sd.control = control & ~SE_SELF_RELATIVE;
1508 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1509 sd.owner_len = RtlLengthSid( owner );
1510 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1511 sd.group_len = RtlLengthSid( group );
1512 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1513 sd.sacl_len = (present ? sacl->AclSize : 0);
1514 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1515 sd.dacl_len = (present ? dacl->AclSize : 0);
1517 wine_server_add_data( req, &sd, sizeof(sd) );
1518 wine_server_add_data( req, owner, sd.owner_len );
1519 wine_server_add_data( req, group, sd.group_len );
1520 wine_server_add_data( req, sacl, sd.sacl_len );
1521 wine_server_add_data( req, dacl, sd.dacl_len );
1523 wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1525 status = wine_server_call( req );
1527 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1528 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1530 if (status == STATUS_SUCCESS)
1532 *AccessStatus = reply->access_status;
1533 *GrantedAccess = reply->access_granted;
1536 SERVER_END_REQ;
1538 return status;
1541 /******************************************************************************
1542 * NtSetSecurityObject [NTDLL.@]
1543 * ZwSetSecurityObject [NTDLL.@]
1545 * Sets specified parts of the object's security descriptor.
1547 * PARAMS
1548 * Handle [I] Handle to the object to change security descriptor of.
1549 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1550 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1552 * RETURNS
1553 * NTSTATUS code.
1556 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1557 SECURITY_INFORMATION SecurityInformation,
1558 PSECURITY_DESCRIPTOR SecurityDescriptor)
1560 NTSTATUS status;
1561 struct security_descriptor sd;
1562 PACL dacl = NULL, sacl = NULL;
1563 PSID owner = NULL, group = NULL;
1564 BOOLEAN defaulted, present;
1565 DWORD revision;
1566 SECURITY_DESCRIPTOR_CONTROL control;
1568 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1570 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1572 memset( &sd, 0, sizeof(sd) );
1573 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1574 if (status != STATUS_SUCCESS) return status;
1575 sd.control = control & ~SE_SELF_RELATIVE;
1577 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1579 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1580 if (status != STATUS_SUCCESS) return status;
1581 if (!(sd.owner_len = RtlLengthSid( owner )))
1582 return STATUS_INVALID_SECURITY_DESCR;
1585 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1587 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1588 if (status != STATUS_SUCCESS) return status;
1589 if (!(sd.group_len = RtlLengthSid( group )))
1590 return STATUS_INVALID_SECURITY_DESCR;
1593 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1595 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1596 if (status != STATUS_SUCCESS) return status;
1597 sd.sacl_len = (sacl && present) ? sacl->AclSize : 0;
1598 sd.control |= SE_SACL_PRESENT;
1601 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1603 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1604 if (status != STATUS_SUCCESS) return status;
1605 sd.dacl_len = (dacl && present) ? dacl->AclSize : 0;
1606 sd.control |= SE_DACL_PRESENT;
1609 SERVER_START_REQ( set_security_object )
1611 req->handle = Handle;
1612 req->security_info = SecurityInformation;
1614 wine_server_add_data( req, &sd, sizeof(sd) );
1615 wine_server_add_data( req, owner, sd.owner_len );
1616 wine_server_add_data( req, group, sd.group_len );
1617 wine_server_add_data( req, sacl, sd.sacl_len );
1618 wine_server_add_data( req, dacl, sd.dacl_len );
1619 status = wine_server_call( req );
1621 SERVER_END_REQ;
1623 return status;
1626 /******************************************************************************
1627 * RtlConvertSidToUnicodeString (NTDLL.@)
1629 * The returned SID is used to access the USER registry hive usually
1631 * the native function returns something like
1632 * "S-1-5-21-0000000000-000000000-0000000000-500";
1634 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1635 PUNICODE_STRING String,
1636 PSID pSid,
1637 BOOLEAN AllocateString)
1639 static const WCHAR formatW[] = {'-','%','u',0};
1640 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1641 WCHAR *p = buffer;
1642 const SID *sid = (const SID *)pSid;
1643 DWORD i, len;
1645 *p++ = 'S';
1646 p += sprintfW( p, formatW, sid->Revision );
1647 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1648 sid->IdentifierAuthority.Value[4] ),
1649 MAKEWORD( sid->IdentifierAuthority.Value[3],
1650 sid->IdentifierAuthority.Value[2] )));
1651 for (i = 0; i < sid->SubAuthorityCount; i++)
1652 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1654 len = (p + 1 - buffer) * sizeof(WCHAR);
1656 String->Length = len - sizeof(WCHAR);
1657 if (AllocateString)
1659 String->MaximumLength = len;
1660 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1661 return STATUS_NO_MEMORY;
1663 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1665 memcpy( String->Buffer, buffer, len );
1666 return STATUS_SUCCESS;
1669 /******************************************************************************
1670 * RtlQueryInformationAcl (NTDLL.@)
1672 NTSTATUS WINAPI RtlQueryInformationAcl(
1673 PACL pAcl,
1674 LPVOID pAclInformation,
1675 DWORD nAclInformationLength,
1676 ACL_INFORMATION_CLASS dwAclInformationClass)
1678 NTSTATUS status = STATUS_SUCCESS;
1680 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1681 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1683 switch (dwAclInformationClass)
1685 case AclRevisionInformation:
1687 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1689 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1690 status = STATUS_INVALID_PARAMETER;
1691 else
1692 paclrev->AclRevision = pAcl->AclRevision;
1694 break;
1697 case AclSizeInformation:
1699 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1701 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1702 status = STATUS_INVALID_PARAMETER;
1703 else
1705 INT i;
1706 PACE_HEADER ace;
1708 paclsize->AceCount = pAcl->AceCount;
1710 paclsize->AclBytesInUse = 0;
1711 ace = (PACE_HEADER) (pAcl + 1);
1713 for (i = 0; i < pAcl->AceCount; i++)
1715 paclsize->AclBytesInUse += ace->AceSize;
1716 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1719 if (pAcl->AclSize < paclsize->AclBytesInUse)
1721 WARN("Acl has %d bytes free\n", paclsize->AclBytesFree);
1722 paclsize->AclBytesFree = 0;
1723 paclsize->AclBytesInUse = pAcl->AclSize;
1725 else
1726 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1729 break;
1732 default:
1733 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1734 status = STATUS_INVALID_PARAMETER;
1737 return status;