Dbghelp describes the types of function arguments with a specific
[wine/wine64.git] / dlls / ntdll / sec.c
blobcb13d491dd01793674506d20524da3963d622b7c
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 "windef.h"
36 #include "wine/exception.h"
37 #include "ntdll_misc.h"
38 #include "excpt.h"
39 #include "wine/library.h"
40 #include "wine/unicode.h"
41 #include "wine/debug.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
45 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
47 /* filter for page-fault exceptions */
48 static WINE_EXCEPTION_FILTER(page_fault)
50 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
51 return EXCEPTION_EXECUTE_HANDLER;
52 return EXCEPTION_CONTINUE_SEARCH;
55 /* helper function to copy an ACL */
56 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
58 DWORD size;
60 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
61 return FALSE;
63 size = ((ACL *)pSourceAcl)->AclSize;
64 if (nDestinationAclLength < size)
65 return FALSE;
67 memmove(pDestinationAcl, pSourceAcl, size);
68 return TRUE;
71 /* generically adds an ACE to an ACL */
72 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
73 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
75 ACE_HEADER *pAceHeader;
76 DWORD dwLengthSid;
77 DWORD dwAceSize;
78 DWORD *pAccessMask;
79 DWORD *pSidStart;
81 if (!RtlValidSid(pSid))
82 return STATUS_INVALID_SID;
84 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
85 return STATUS_REVISION_MISMATCH;
87 if (!RtlValidAcl(pAcl))
88 return STATUS_INVALID_ACL;
90 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
91 return STATUS_INVALID_ACL;
93 if (!pAceHeader)
94 return STATUS_ALLOTTED_SPACE_EXCEEDED;
96 /* calculate generic size of the ACE */
97 dwLengthSid = RtlLengthSid(pSid);
98 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
99 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
100 return STATUS_ALLOTTED_SPACE_EXCEEDED;
102 /* fill the new ACE */
103 pAceHeader->AceType = dwAceType;
104 pAceHeader->AceFlags = dwAceFlags;
105 pAceHeader->AceSize = dwAceSize;
107 /* skip past the ACE_HEADER of the ACE */
108 pAccessMask = (DWORD *)(pAceHeader + 1);
109 *pAccessMask = dwAccessMask;
111 /* skip past ACE->Mask */
112 pSidStart = pAccessMask + 1;
113 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
115 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
116 pAcl->AceCount++;
118 return STATUS_SUCCESS;
122 * SID FUNCTIONS
125 /******************************************************************************
126 * RtlAllocateAndInitializeSid [NTDLL.@]
129 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
130 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
131 BYTE nSubAuthorityCount,
132 DWORD nSubAuthority0, DWORD nSubAuthority1,
133 DWORD nSubAuthority2, DWORD nSubAuthority3,
134 DWORD nSubAuthority4, DWORD nSubAuthority5,
135 DWORD nSubAuthority6, DWORD nSubAuthority7,
136 PSID *pSid )
138 SID *tmp_sid;
140 TRACE("(%p, 0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p)\n",
141 pIdentifierAuthority,nSubAuthorityCount,
142 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
143 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
145 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
147 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
148 RtlLengthRequiredSid(nSubAuthorityCount))))
149 return STATUS_NO_MEMORY;
151 tmp_sid->Revision = SID_REVISION;
153 if (pIdentifierAuthority)
154 memcpy(&tmp_sid->IdentifierAuthority, pIdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY));
155 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
157 switch( nSubAuthorityCount )
159 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
160 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
161 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
162 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
163 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
164 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
165 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
166 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
167 break;
169 *pSid = tmp_sid;
170 return STATUS_SUCCESS;
173 /******************************************************************************
174 * RtlEqualSid [NTDLL.@]
176 * Determine if two SIDs are equal.
178 * PARAMS
179 * pSid1 [I] Source SID
180 * pSid2 [I] SID to compare with
182 * RETURNS
183 * TRUE, if pSid1 is equal to pSid2,
184 * FALSE otherwise.
186 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
188 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
189 return FALSE;
191 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
192 return FALSE;
194 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
195 return FALSE;
197 return TRUE;
200 /******************************************************************************
201 * RtlEqualPrefixSid [NTDLL.@]
203 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
205 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
206 return FALSE;
208 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
209 return FALSE;
211 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
212 return FALSE;
214 return TRUE;
218 /******************************************************************************
219 * RtlFreeSid [NTDLL.@]
221 * Free the resources used by a SID.
223 * PARAMS
224 * pSid [I] SID to Free.
226 * RETURNS
227 * STATUS_SUCCESS.
229 DWORD WINAPI RtlFreeSid(PSID pSid)
231 TRACE("(%p)\n", pSid);
232 RtlFreeHeap( GetProcessHeap(), 0, pSid );
233 return STATUS_SUCCESS;
236 /**************************************************************************
237 * RtlLengthRequiredSid [NTDLL.@]
239 * Determine the amount of memory a SID will use
241 * PARAMS
242 * nrofsubauths [I] Number of Sub Authorities in the SID.
244 * RETURNS
245 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
247 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
249 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
252 /**************************************************************************
253 * RtlLengthSid [NTDLL.@]
255 * Determine the amount of memory a SID is using
257 * PARAMS
258 * pSid [I] SID to get the size of.
260 * RETURNS
261 * The size, in bytes, of pSid.
263 DWORD WINAPI RtlLengthSid(PSID pSid)
265 TRACE("sid=%p\n",pSid);
266 if (!pSid) return 0;
267 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
270 /**************************************************************************
271 * RtlInitializeSid [NTDLL.@]
273 * Initialise a SID.
275 * PARAMS
276 * pSid [I] SID to initialise
277 * pIdentifierAuthority [I] Identifier Authority
278 * nSubAuthorityCount [I] Number of Sub Authorities
280 * RETURNS
281 * Success: TRUE. pSid is initialised with the details given.
282 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
284 BOOL WINAPI RtlInitializeSid(
285 PSID pSid,
286 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
287 BYTE nSubAuthorityCount)
289 int i;
290 SID* pisid=pSid;
292 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
293 return FALSE;
295 pisid->Revision = SID_REVISION;
296 pisid->SubAuthorityCount = nSubAuthorityCount;
297 if (pIdentifierAuthority)
298 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
300 for (i = 0; i < nSubAuthorityCount; i++)
301 *RtlSubAuthoritySid(pSid, i) = 0;
303 return TRUE;
306 /**************************************************************************
307 * RtlSubAuthoritySid [NTDLL.@]
309 * Return the Sub Authority of a SID
311 * PARAMS
312 * pSid [I] SID to get the Sub Authority from.
313 * nSubAuthority [I] Sub Authority number.
315 * RETURNS
316 * A pointer to The Sub Authority value of pSid.
318 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
320 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
323 /**************************************************************************
324 * RtlIdentifierAuthoritySid [NTDLL.@]
326 * Return the Identifier Authority of a SID.
328 * PARAMS
329 * pSid [I] SID to get the Identifier Authority from.
331 * RETURNS
332 * A pointer to the Identifier Authority value of pSid.
334 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
336 return &(((SID*)pSid)->IdentifierAuthority);
339 /**************************************************************************
340 * RtlSubAuthorityCountSid [NTDLL.@]
342 * Get the number of Sub Authorities in a SID.
344 * PARAMS
345 * pSid [I] SID to get the count from.
347 * RETURNS
348 * A pointer to the Sub Authority count of pSid.
350 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
352 return &(((SID*)pSid)->SubAuthorityCount);
355 /**************************************************************************
356 * RtlCopySid [NTDLL.@]
358 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
360 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
361 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
362 return FALSE;
364 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
365 return FALSE;
367 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
368 return TRUE;
370 /******************************************************************************
371 * RtlValidSid [NTDLL.@]
373 * Determine if a SID is valid.
375 * PARAMS
376 * pSid [I] SID to check
378 * RETURNS
379 * TRUE if pSid is valid,
380 * FALSE otherwise.
382 BOOLEAN WINAPI RtlValidSid( PSID pSid )
384 BOOL ret;
385 __TRY
387 ret = TRUE;
388 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
389 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
391 ret = FALSE;
394 __EXCEPT(page_fault)
396 WARN("(%p): invalid pointer!\n", pSid);
397 return FALSE;
399 __ENDTRY
400 return ret;
405 * security descriptor functions
408 /**************************************************************************
409 * RtlCreateSecurityDescriptor [NTDLL.@]
411 * Initialise a SECURITY_DESCRIPTOR.
413 * PARAMS
414 * lpsd [O] Descriptor to initialise.
415 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
417 * RETURNS
418 * Success: STATUS_SUCCESS.
419 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
421 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
422 PSECURITY_DESCRIPTOR lpsd,
423 DWORD rev)
425 if (rev!=SECURITY_DESCRIPTOR_REVISION)
426 return STATUS_UNKNOWN_REVISION;
427 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
428 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
429 return STATUS_SUCCESS;
432 /**************************************************************************
433 * RtlCopySecurityDescriptor [NTDLL.@]
435 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
437 * PARAMS
438 * pSourceSD [O] SD to copy from.
439 * pDestinationSD [I] Destination SD.
441 * RETURNS
442 * Success: STATUS_SUCCESS.
443 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
445 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
447 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
448 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
449 PSID Owner, Group;
450 PACL Dacl, Sacl;
451 BOOLEAN defaulted, present;
452 DWORD length;
453 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
455 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
456 return STATUS_UNKNOWN_REVISION;
458 /* copy initial data */
459 destSD->Revision = srcSD->Revision;
460 destSD->Sbz1 = srcSD->Sbz1;
461 destSD->Control = srcSD->Control;
463 /* copy Owner */
464 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
465 length = RtlLengthSid(Owner);
467 if (isSelfRelative)
469 destSD->Owner = srcSD->Owner;
470 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Owner, Owner);
472 else
474 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
475 RtlCopySid(length, destSD->Owner, Owner);
478 /* copy Group */
479 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
480 length = RtlLengthSid(Group);
482 if (isSelfRelative)
484 destSD->Group = srcSD->Group;
485 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Group, Group);
487 else
489 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
490 RtlCopySid(length, destSD->Group, Group);
493 /* copy Dacl */
494 if (srcSD->Control & SE_DACL_PRESENT)
496 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
497 length = Dacl->AclSize;
499 if (isSelfRelative)
501 destSD->Dacl = srcSD->Dacl;
502 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Dacl), Dacl);
504 else
506 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
507 copy_acl(length, destSD->Dacl, Dacl);
511 /* copy Sacl */
512 if (srcSD->Control & SE_SACL_PRESENT)
514 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
515 length = Sacl->AclSize;
517 if (isSelfRelative)
519 destSD->Sacl = srcSD->Sacl;
520 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Sacl), Sacl);
522 else
524 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
525 copy_acl(length, destSD->Sacl, Sacl);
529 return STATUS_SUCCESS;
532 /**************************************************************************
533 * RtlValidSecurityDescriptor [NTDLL.@]
535 * Determine if a SECURITY_DESCRIPTOR is valid.
537 * PARAMS
538 * SecurityDescriptor [I] Descriptor to check.
540 * RETURNS
541 * Success: STATUS_SUCCESS.
542 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
544 NTSTATUS WINAPI RtlValidSecurityDescriptor(
545 PSECURITY_DESCRIPTOR SecurityDescriptor)
547 if ( ! SecurityDescriptor )
548 return STATUS_INVALID_SECURITY_DESCR;
549 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
550 return STATUS_UNKNOWN_REVISION;
552 return STATUS_SUCCESS;
555 /**************************************************************************
556 * RtlLengthSecurityDescriptor [NTDLL.@]
558 ULONG WINAPI RtlLengthSecurityDescriptor(
559 PSECURITY_DESCRIPTOR pSecurityDescriptor)
561 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
562 ULONG offset = 0;
563 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
565 if ( lpsd == NULL )
566 return 0;
568 if ( lpsd->Control & SE_SELF_RELATIVE)
569 offset = (ULONG) lpsd;
571 if ( lpsd->Owner != NULL )
572 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
574 if ( lpsd->Group != NULL )
575 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
577 if ( (lpsd->Control & SE_SACL_PRESENT) &&
578 lpsd->Sacl != NULL )
579 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
581 if ( (lpsd->Control & SE_DACL_PRESENT) &&
582 lpsd->Dacl != NULL )
583 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
585 return Size;
588 /******************************************************************************
589 * RtlGetDaclSecurityDescriptor [NTDLL.@]
592 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
593 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
594 OUT PBOOLEAN lpbDaclPresent,
595 OUT PACL *pDacl,
596 OUT PBOOLEAN lpbDaclDefaulted)
598 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
600 TRACE("(%p,%p,%p,%p)\n",
601 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
603 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
604 return STATUS_UNKNOWN_REVISION ;
606 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
608 if ( SE_SELF_RELATIVE & lpsd->Control)
609 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
610 else
611 *pDacl = lpsd->Dacl;
613 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
616 return STATUS_SUCCESS;
619 /**************************************************************************
620 * RtlSetDaclSecurityDescriptor [NTDLL.@]
622 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
623 PSECURITY_DESCRIPTOR pSecurityDescriptor,
624 BOOLEAN daclpresent,
625 PACL dacl,
626 BOOLEAN dacldefaulted )
628 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
630 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
631 return STATUS_UNKNOWN_REVISION;
632 if (lpsd->Control & SE_SELF_RELATIVE)
633 return STATUS_INVALID_SECURITY_DESCR;
635 if (!daclpresent)
636 { lpsd->Control &= ~SE_DACL_PRESENT;
637 return TRUE;
640 lpsd->Control |= SE_DACL_PRESENT;
641 lpsd->Dacl = dacl;
643 if (dacldefaulted)
644 lpsd->Control |= SE_DACL_DEFAULTED;
645 else
646 lpsd->Control &= ~SE_DACL_DEFAULTED;
648 return STATUS_SUCCESS;
651 /******************************************************************************
652 * RtlGetSaclSecurityDescriptor [NTDLL.@]
655 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
656 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
657 OUT PBOOLEAN lpbSaclPresent,
658 OUT PACL *pSacl,
659 OUT PBOOLEAN lpbSaclDefaulted)
661 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
663 TRACE("(%p,%p,%p,%p)\n",
664 pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
666 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
667 return STATUS_UNKNOWN_REVISION;
669 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
671 if (SE_SELF_RELATIVE & lpsd->Control)
672 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Sacl);
673 else
674 *pSacl = lpsd->Sacl;
676 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
679 return STATUS_SUCCESS;
682 /**************************************************************************
683 * RtlSetSaclSecurityDescriptor [NTDLL.@]
685 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
686 PSECURITY_DESCRIPTOR pSecurityDescriptor,
687 BOOLEAN saclpresent,
688 PACL sacl,
689 BOOLEAN sacldefaulted)
691 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
693 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
694 return STATUS_UNKNOWN_REVISION;
695 if (lpsd->Control & SE_SELF_RELATIVE)
696 return STATUS_INVALID_SECURITY_DESCR;
697 if (!saclpresent) {
698 lpsd->Control &= ~SE_SACL_PRESENT;
699 return 0;
701 lpsd->Control |= SE_SACL_PRESENT;
702 lpsd->Sacl = sacl;
703 if (sacldefaulted)
704 lpsd->Control |= SE_SACL_DEFAULTED;
705 else
706 lpsd->Control &= ~SE_SACL_DEFAULTED;
707 return STATUS_SUCCESS;
710 /**************************************************************************
711 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
713 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
714 PSECURITY_DESCRIPTOR pSecurityDescriptor,
715 PSID *Owner,
716 PBOOLEAN OwnerDefaulted)
718 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
720 if ( !lpsd || !Owner || !OwnerDefaulted )
721 return STATUS_INVALID_PARAMETER;
723 if (lpsd->Owner != NULL)
725 if (lpsd->Control & SE_SELF_RELATIVE)
726 *Owner = (PSID)((LPBYTE)lpsd +
727 (ULONG)lpsd->Owner);
728 else
729 *Owner = lpsd->Owner;
731 if ( lpsd->Control & SE_OWNER_DEFAULTED )
732 *OwnerDefaulted = TRUE;
733 else
734 *OwnerDefaulted = FALSE;
736 else
737 *Owner = NULL;
739 return STATUS_SUCCESS;
742 /**************************************************************************
743 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
745 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
746 PSECURITY_DESCRIPTOR pSecurityDescriptor,
747 PSID owner,
748 BOOLEAN ownerdefaulted)
750 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
752 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
753 return STATUS_UNKNOWN_REVISION;
754 if (lpsd->Control & SE_SELF_RELATIVE)
755 return STATUS_INVALID_SECURITY_DESCR;
757 lpsd->Owner = owner;
758 if (ownerdefaulted)
759 lpsd->Control |= SE_OWNER_DEFAULTED;
760 else
761 lpsd->Control &= ~SE_OWNER_DEFAULTED;
762 return STATUS_SUCCESS;
765 /**************************************************************************
766 * RtlSetGroupSecurityDescriptor [NTDLL.@]
768 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
769 PSECURITY_DESCRIPTOR pSecurityDescriptor,
770 PSID group,
771 BOOLEAN groupdefaulted)
773 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
775 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
776 return STATUS_UNKNOWN_REVISION;
777 if (lpsd->Control & SE_SELF_RELATIVE)
778 return STATUS_INVALID_SECURITY_DESCR;
780 lpsd->Group = group;
781 if (groupdefaulted)
782 lpsd->Control |= SE_GROUP_DEFAULTED;
783 else
784 lpsd->Control &= ~SE_GROUP_DEFAULTED;
785 return STATUS_SUCCESS;
788 /**************************************************************************
789 * RtlGetGroupSecurityDescriptor [NTDLL.@]
791 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
792 PSECURITY_DESCRIPTOR pSecurityDescriptor,
793 PSID *Group,
794 PBOOLEAN GroupDefaulted)
796 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
798 if ( !lpsd || !Group || !GroupDefaulted )
799 return STATUS_INVALID_PARAMETER;
801 if (lpsd->Group != NULL)
803 if (lpsd->Control & SE_SELF_RELATIVE)
804 *Group = (PSID)((LPBYTE)lpsd +
805 (ULONG)lpsd->Group);
806 else
807 *Group = lpsd->Group;
809 if ( lpsd->Control & SE_GROUP_DEFAULTED )
810 *GroupDefaulted = TRUE;
811 else
812 *GroupDefaulted = FALSE;
814 else
815 *Group = NULL;
817 return STATUS_SUCCESS;
820 /**************************************************************************
821 * RtlMakeSelfRelativeSD [NTDLL.@]
823 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
824 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
825 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
826 IN OUT LPDWORD lpdwBufferLength)
828 ULONG offsetRel;
829 ULONG length;
830 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
831 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
833 TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
834 lpdwBufferLength ? *lpdwBufferLength: -1);
836 if (!lpdwBufferLength || !pAbs)
837 return STATUS_INVALID_PARAMETER;
839 length = RtlLengthSecurityDescriptor(pAbs);
840 if (*lpdwBufferLength < length)
842 *lpdwBufferLength = length;
843 return STATUS_BUFFER_TOO_SMALL;
846 if (!pRel)
847 return STATUS_INVALID_PARAMETER;
849 if (pAbs->Control & SE_SELF_RELATIVE)
851 memcpy(pRel, pAbs, length);
852 return STATUS_SUCCESS;
855 pRel->Revision = pAbs->Revision;
856 pRel->Sbz1 = pAbs->Sbz1;
857 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
859 offsetRel = sizeof(SECURITY_DESCRIPTOR);
860 pRel->Owner = (PSID) offsetRel;
861 length = RtlLengthSid(pAbs->Owner);
862 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
864 offsetRel += length;
865 pRel->Group = (PSID) offsetRel;
866 length = RtlLengthSid(pAbs->Group);
867 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
869 if (pRel->Control & SE_SACL_PRESENT)
871 offsetRel += length;
872 pRel->Sacl = (PACL) offsetRel;
873 length = pAbs->Sacl->AclSize;
874 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
876 else
878 pRel->Sacl = NULL;
881 if (pRel->Control & SE_DACL_PRESENT)
883 offsetRel += length;
884 pRel->Dacl = (PACL) offsetRel;
885 length = pAbs->Dacl->AclSize;
886 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
888 else
890 pRel->Dacl = NULL;
893 return STATUS_SUCCESS;
897 /**************************************************************************
898 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
900 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
901 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
902 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
903 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
904 OUT PACL pDacl,
905 OUT LPDWORD lpdwDaclSize,
906 OUT PACL pSacl,
907 OUT LPDWORD lpdwSaclSize,
908 OUT PSID pOwner,
909 OUT LPDWORD lpdwOwnerSize,
910 OUT PSID pPrimaryGroup,
911 OUT LPDWORD lpdwPrimaryGroupSize)
913 NTSTATUS status = STATUS_SUCCESS;
914 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
915 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
917 if (!pRel ||
918 !lpdwAbsoluteSecurityDescriptorSize ||
919 !lpdwDaclSize ||
920 !lpdwSaclSize ||
921 !lpdwOwnerSize ||
922 !lpdwPrimaryGroupSize ||
923 ~pRel->Control & SE_SELF_RELATIVE)
924 return STATUS_INVALID_PARAMETER;
926 /* Confirm buffers are sufficiently large */
927 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
929 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
930 status = STATUS_BUFFER_TOO_SMALL;
933 if (pRel->Control & SE_DACL_PRESENT &&
934 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
936 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
937 status = STATUS_BUFFER_TOO_SMALL;
940 if (pRel->Control & SE_SACL_PRESENT &&
941 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
943 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
944 status = STATUS_BUFFER_TOO_SMALL;
947 if (pRel->Owner &&
948 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
950 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
951 status = STATUS_BUFFER_TOO_SMALL;
954 if (pRel->Group &&
955 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
957 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
958 status = STATUS_BUFFER_TOO_SMALL;
961 if (status != STATUS_SUCCESS)
962 return status;
964 /* Copy structures */
965 pAbs->Revision = pRel->Revision;
966 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
968 if (pRel->Control & SE_SACL_PRESENT)
970 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
972 memcpy(pSacl, pAcl, pAcl->AclSize);
973 pAbs->Sacl = pSacl;
976 if (pRel->Control & SE_DACL_PRESENT)
978 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
979 memcpy(pDacl, pAcl, pAcl->AclSize);
980 pAbs->Dacl = pDacl;
983 if (pRel->Owner)
985 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
986 memcpy(pOwner, psid, RtlLengthSid(psid));
987 pAbs->Owner = pOwner;
990 if (pRel->Group)
992 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
993 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
994 pAbs->Group = pPrimaryGroup;
997 return status;
1000 /******************************************************************************
1001 * RtlGetControlSecurityDescriptor (NTDLL.@)
1003 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1004 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1005 PSECURITY_DESCRIPTOR_CONTROL pControl,
1006 LPDWORD lpdwRevision)
1008 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1010 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1012 *lpdwRevision = lpsd->Revision;
1014 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1015 return STATUS_UNKNOWN_REVISION;
1017 *pControl = lpsd->Control;
1019 return STATUS_SUCCESS;
1023 /**************************************************************************
1024 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1026 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1027 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1028 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1029 PULONG BufferLength)
1031 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1033 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1034 SelfRelativeSecurityDescriptor, BufferLength);
1036 if (abs->Control & SE_SELF_RELATIVE)
1037 return STATUS_BAD_DESCRIPTOR_FORMAT;
1039 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1040 SelfRelativeSecurityDescriptor, BufferLength);
1045 * access control list's
1048 /**************************************************************************
1049 * RtlCreateAcl [NTDLL.@]
1051 * NOTES
1052 * This should return NTSTATUS
1054 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1056 TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
1058 if (rev!=ACL_REVISION)
1059 return STATUS_INVALID_PARAMETER;
1060 if (size<sizeof(ACL))
1061 return STATUS_BUFFER_TOO_SMALL;
1062 if (size>0xFFFF)
1063 return STATUS_INVALID_PARAMETER;
1065 memset(acl,'\0',sizeof(ACL));
1066 acl->AclRevision = rev;
1067 acl->AclSize = size;
1068 acl->AceCount = 0;
1069 return STATUS_SUCCESS;
1072 /**************************************************************************
1073 * RtlFirstFreeAce [NTDLL.@]
1074 * looks for the AceCount+1 ACE, and if it is still within the alloced
1075 * ACL, return a pointer to it
1077 BOOLEAN WINAPI RtlFirstFreeAce(
1078 PACL acl,
1079 PACE_HEADER *x)
1081 PACE_HEADER ace;
1082 int i;
1084 *x = 0;
1085 ace = (PACE_HEADER)(acl+1);
1086 for (i=0;i<acl->AceCount;i++) {
1087 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1088 return 0;
1089 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1091 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1092 return 0;
1093 *x = ace;
1094 return 1;
1097 /**************************************************************************
1098 * RtlAddAce [NTDLL.@]
1100 NTSTATUS WINAPI RtlAddAce(
1101 PACL acl,
1102 DWORD rev,
1103 DWORD xnrofaces,
1104 PACE_HEADER acestart,
1105 DWORD acelen)
1107 PACE_HEADER ace,targetace;
1108 int nrofaces;
1110 if (acl->AclRevision != ACL_REVISION)
1111 return STATUS_INVALID_PARAMETER;
1112 if (!RtlFirstFreeAce(acl,&targetace))
1113 return STATUS_INVALID_PARAMETER;
1114 nrofaces=0;ace=acestart;
1115 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1116 nrofaces++;
1117 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1119 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1120 return STATUS_INVALID_PARAMETER;
1121 memcpy((LPBYTE)targetace,acestart,acelen);
1122 acl->AceCount+=nrofaces;
1123 return STATUS_SUCCESS;
1126 /**************************************************************************
1127 * RtlDeleteAce [NTDLL.@]
1129 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1131 NTSTATUS status;
1132 PACE_HEADER pAce;
1134 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1136 if (STATUS_SUCCESS == status)
1138 PACE_HEADER pcAce;
1139 DWORD len = 0;
1141 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1142 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1144 len += pcAce->AceSize;
1145 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1148 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1149 pAcl->AceCount--;
1152 TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\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%08lx,0x%08lx,%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%08lx,0x%08lx,%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,%ld,%ld,%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,%ld,%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("(%ld, %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 %lx)\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 %lx)\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, %08lx, %p, %p, %p, %p, %p), stub\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)
1531 *AccessStatus = reply->access_status;
1532 *GrantedAccess = reply->access_granted;
1534 SERVER_END_REQ;
1536 return status;
1539 /******************************************************************************
1540 * NtSetSecurityObject [NTDLL.@]
1542 NTSTATUS WINAPI
1543 NtSetSecurityObject(
1544 IN HANDLE Handle,
1545 IN SECURITY_INFORMATION SecurityInformation,
1546 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1548 FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1549 return STATUS_SUCCESS;
1552 /******************************************************************************
1553 * RtlConvertSidToUnicodeString (NTDLL.@)
1555 * The returned SID is used to access the USER registry hive usually
1557 * the native function returns something like
1558 * "S-1-5-21-0000000000-000000000-0000000000-500";
1560 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1561 PUNICODE_STRING String,
1562 PSID pSid,
1563 BOOLEAN AllocateString)
1565 static const WCHAR formatW[] = {'-','%','u',0};
1566 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1567 WCHAR *p = buffer;
1568 const SID *sid = (const SID *)pSid;
1569 DWORD i, len;
1571 *p++ = 'S';
1572 p += sprintfW( p, formatW, sid->Revision );
1573 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1574 sid->IdentifierAuthority.Value[4] ),
1575 MAKEWORD( sid->IdentifierAuthority.Value[3],
1576 sid->IdentifierAuthority.Value[2] )));
1577 for (i = 0; i < sid->SubAuthorityCount; i++)
1578 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1580 len = (p + 1 - buffer) * sizeof(WCHAR);
1582 String->Length = len - sizeof(WCHAR);
1583 if (AllocateString)
1585 String->MaximumLength = len;
1586 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1587 return STATUS_NO_MEMORY;
1589 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1591 memcpy( String->Buffer, buffer, len );
1592 return STATUS_SUCCESS;
1595 /******************************************************************************
1596 * RtlQueryInformationAcl (NTDLL.@)
1598 NTSTATUS WINAPI RtlQueryInformationAcl(
1599 PACL pAcl,
1600 LPVOID pAclInformation,
1601 DWORD nAclInformationLength,
1602 ACL_INFORMATION_CLASS dwAclInformationClass)
1604 NTSTATUS status = STATUS_SUCCESS;
1606 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1607 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1609 switch (dwAclInformationClass)
1611 case AclRevisionInformation:
1613 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1615 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1616 status = STATUS_INVALID_PARAMETER;
1617 else
1618 paclrev->AclRevision = pAcl->AclRevision;
1620 break;
1623 case AclSizeInformation:
1625 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1627 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1628 status = STATUS_INVALID_PARAMETER;
1629 else
1631 INT i;
1632 PACE_HEADER ace;
1634 paclsize->AceCount = pAcl->AceCount;
1636 paclsize->AclBytesInUse = 0;
1637 ace = (PACE_HEADER) (pAcl + 1);
1639 for (i = 0; i < pAcl->AceCount; i++)
1641 paclsize->AclBytesInUse += ace->AceSize;
1642 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1645 if (pAcl->AclSize < paclsize->AclBytesInUse)
1647 WARN("Acl has %ld bytes free\n", paclsize->AclBytesFree);
1648 paclsize->AclBytesFree = 0;
1649 paclsize->AclBytesInUse = pAcl->AclSize;
1651 else
1652 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1655 break;
1658 default:
1659 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1660 status = STATUS_INVALID_PARAMETER;
1663 return status;