push 0f15bbd80d260bbd8adf052e820484a405c49375
[wine/hacks.git] / dlls / ntdll / sec.c
blobfd5ed7a7601840360716266fca2dcbaf959e92ca
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 retrieve active length of an ACL */
49 static size_t acl_bytesInUse(PACL pAcl)
51 int i;
52 size_t bytesInUse = sizeof(ACL);
53 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
54 for (i = 0; i < pAcl->AceCount; i++)
56 bytesInUse += ace->AceSize;
57 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
59 return bytesInUse;
62 /* helper function to copy an ACL */
63 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
65 DWORD size;
67 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
68 return FALSE;
70 size = ((ACL *)pSourceAcl)->AclSize;
71 if (nDestinationAclLength < size)
72 return FALSE;
74 memmove(pDestinationAcl, pSourceAcl, size);
75 return TRUE;
78 /* generically adds an ACE to an ACL */
79 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
80 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
82 ACE_HEADER *pAceHeader;
83 DWORD dwLengthSid;
84 DWORD dwAceSize;
85 DWORD *pAccessMask;
86 DWORD *pSidStart;
88 if (!RtlValidSid(pSid))
89 return STATUS_INVALID_SID;
91 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
92 return STATUS_REVISION_MISMATCH;
94 if (!RtlValidAcl(pAcl))
95 return STATUS_INVALID_ACL;
97 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
98 return STATUS_INVALID_ACL;
100 if (!pAceHeader)
101 return STATUS_ALLOTTED_SPACE_EXCEEDED;
103 /* calculate generic size of the ACE */
104 dwLengthSid = RtlLengthSid(pSid);
105 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
106 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
107 return STATUS_ALLOTTED_SPACE_EXCEEDED;
109 /* fill the new ACE */
110 pAceHeader->AceType = dwAceType;
111 pAceHeader->AceFlags = dwAceFlags;
112 pAceHeader->AceSize = dwAceSize;
114 /* skip past the ACE_HEADER of the ACE */
115 pAccessMask = (DWORD *)(pAceHeader + 1);
116 *pAccessMask = dwAccessMask;
118 /* skip past ACE->Mask */
119 pSidStart = pAccessMask + 1;
120 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
122 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
123 pAcl->AceCount++;
125 return STATUS_SUCCESS;
129 * SID FUNCTIONS
132 /******************************************************************************
133 * RtlAllocateAndInitializeSid [NTDLL.@]
136 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
137 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
138 BYTE nSubAuthorityCount,
139 DWORD nSubAuthority0, DWORD nSubAuthority1,
140 DWORD nSubAuthority2, DWORD nSubAuthority3,
141 DWORD nSubAuthority4, DWORD nSubAuthority5,
142 DWORD nSubAuthority6, DWORD nSubAuthority7,
143 PSID *pSid )
145 SID *tmp_sid;
147 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
148 pIdentifierAuthority,nSubAuthorityCount,
149 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
150 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
152 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
154 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
155 RtlLengthRequiredSid(nSubAuthorityCount))))
156 return STATUS_NO_MEMORY;
158 tmp_sid->Revision = SID_REVISION;
160 if (pIdentifierAuthority)
161 memcpy(&tmp_sid->IdentifierAuthority, pIdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY));
162 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
164 switch( nSubAuthorityCount )
166 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
167 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
168 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
169 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
170 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
171 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
172 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
173 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
174 break;
176 *pSid = tmp_sid;
177 return STATUS_SUCCESS;
180 /******************************************************************************
181 * RtlEqualSid [NTDLL.@]
183 * Determine if two SIDs are equal.
185 * PARAMS
186 * pSid1 [I] Source SID
187 * pSid2 [I] SID to compare with
189 * RETURNS
190 * TRUE, if pSid1 is equal to pSid2,
191 * FALSE otherwise.
193 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
195 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
196 return FALSE;
198 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
199 return FALSE;
201 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
202 return FALSE;
204 return TRUE;
207 /******************************************************************************
208 * RtlEqualPrefixSid [NTDLL.@]
210 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
212 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
213 return FALSE;
215 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
216 return FALSE;
218 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
219 return FALSE;
221 return TRUE;
225 /******************************************************************************
226 * RtlFreeSid [NTDLL.@]
228 * Free the resources used by a SID.
230 * PARAMS
231 * pSid [I] SID to Free.
233 * RETURNS
234 * STATUS_SUCCESS.
236 DWORD WINAPI RtlFreeSid(PSID pSid)
238 TRACE("(%p)\n", pSid);
239 RtlFreeHeap( GetProcessHeap(), 0, pSid );
240 return STATUS_SUCCESS;
243 /**************************************************************************
244 * RtlLengthRequiredSid [NTDLL.@]
246 * Determine the amount of memory a SID will use
248 * PARAMS
249 * nrofsubauths [I] Number of Sub Authorities in the SID.
251 * RETURNS
252 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
254 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
256 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
259 /**************************************************************************
260 * RtlLengthSid [NTDLL.@]
262 * Determine the amount of memory a SID is using
264 * PARAMS
265 * pSid [I] SID to get the size of.
267 * RETURNS
268 * The size, in bytes, of pSid.
270 DWORD WINAPI RtlLengthSid(PSID pSid)
272 TRACE("sid=%p\n",pSid);
273 if (!pSid) return 0;
274 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
277 /**************************************************************************
278 * RtlInitializeSid [NTDLL.@]
280 * Initialise a SID.
282 * PARAMS
283 * pSid [I] SID to initialise
284 * pIdentifierAuthority [I] Identifier Authority
285 * nSubAuthorityCount [I] Number of Sub Authorities
287 * RETURNS
288 * Success: TRUE. pSid is initialised with the details given.
289 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
291 BOOL WINAPI RtlInitializeSid(
292 PSID pSid,
293 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
294 BYTE nSubAuthorityCount)
296 int i;
297 SID* pisid=pSid;
299 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
300 return FALSE;
302 pisid->Revision = SID_REVISION;
303 pisid->SubAuthorityCount = nSubAuthorityCount;
304 if (pIdentifierAuthority)
305 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
307 for (i = 0; i < nSubAuthorityCount; i++)
308 *RtlSubAuthoritySid(pSid, i) = 0;
310 return TRUE;
313 /**************************************************************************
314 * RtlSubAuthoritySid [NTDLL.@]
316 * Return the Sub Authority of a SID
318 * PARAMS
319 * pSid [I] SID to get the Sub Authority from.
320 * nSubAuthority [I] Sub Authority number.
322 * RETURNS
323 * A pointer to The Sub Authority value of pSid.
325 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
327 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
330 /**************************************************************************
331 * RtlIdentifierAuthoritySid [NTDLL.@]
333 * Return the Identifier Authority of a SID.
335 * PARAMS
336 * pSid [I] SID to get the Identifier Authority from.
338 * RETURNS
339 * A pointer to the Identifier Authority value of pSid.
341 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
343 return &(((SID*)pSid)->IdentifierAuthority);
346 /**************************************************************************
347 * RtlSubAuthorityCountSid [NTDLL.@]
349 * Get the number of Sub Authorities in a SID.
351 * PARAMS
352 * pSid [I] SID to get the count from.
354 * RETURNS
355 * A pointer to the Sub Authority count of pSid.
357 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
359 return &(((SID*)pSid)->SubAuthorityCount);
362 /**************************************************************************
363 * RtlCopySid [NTDLL.@]
365 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
367 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
368 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
369 return FALSE;
371 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
372 return FALSE;
374 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
375 return TRUE;
377 /******************************************************************************
378 * RtlValidSid [NTDLL.@]
380 * Determine if a SID is valid.
382 * PARAMS
383 * pSid [I] SID to check
385 * RETURNS
386 * TRUE if pSid is valid,
387 * FALSE otherwise.
389 BOOLEAN WINAPI RtlValidSid( PSID pSid )
391 BOOL ret;
392 __TRY
394 ret = TRUE;
395 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
396 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
398 ret = FALSE;
401 __EXCEPT_PAGE_FAULT
403 WARN("(%p): invalid pointer!\n", pSid);
404 return FALSE;
406 __ENDTRY
407 return ret;
412 * security descriptor functions
415 /**************************************************************************
416 * RtlCreateSecurityDescriptor [NTDLL.@]
418 * Initialise a SECURITY_DESCRIPTOR.
420 * PARAMS
421 * lpsd [O] Descriptor to initialise.
422 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
424 * RETURNS
425 * Success: STATUS_SUCCESS.
426 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
428 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
429 PSECURITY_DESCRIPTOR lpsd,
430 DWORD rev)
432 if (rev!=SECURITY_DESCRIPTOR_REVISION)
433 return STATUS_UNKNOWN_REVISION;
434 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
435 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
436 return STATUS_SUCCESS;
439 /**************************************************************************
440 * RtlCopySecurityDescriptor [NTDLL.@]
442 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
444 * PARAMS
445 * pSourceSD [O] SD to copy from.
446 * pDestinationSD [I] Destination SD.
448 * RETURNS
449 * Success: STATUS_SUCCESS.
450 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
452 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
454 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
455 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
456 PSID Owner, Group;
457 PACL Dacl, Sacl;
458 BOOLEAN defaulted, present;
459 DWORD length;
460 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
462 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
463 return STATUS_UNKNOWN_REVISION;
465 /* copy initial data */
466 destSD->Revision = srcSD->Revision;
467 destSD->Sbz1 = srcSD->Sbz1;
468 destSD->Control = srcSD->Control;
470 /* copy Owner */
471 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
472 length = RtlLengthSid(Owner);
474 if (isSelfRelative)
476 destSD->Owner = srcSD->Owner;
477 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Owner, Owner);
479 else
481 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
482 RtlCopySid(length, destSD->Owner, Owner);
485 /* copy Group */
486 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
487 length = RtlLengthSid(Group);
489 if (isSelfRelative)
491 destSD->Group = srcSD->Group;
492 RtlCopySid(length, (LPBYTE)destSD + (DWORD_PTR)destSD->Group, Group);
494 else
496 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
497 RtlCopySid(length, destSD->Group, Group);
500 /* copy Dacl */
501 if (srcSD->Control & SE_DACL_PRESENT)
503 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
504 length = Dacl->AclSize;
506 if (isSelfRelative)
508 destSD->Dacl = srcSD->Dacl;
509 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Dacl), Dacl);
511 else
513 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
514 copy_acl(length, destSD->Dacl, Dacl);
518 /* copy Sacl */
519 if (srcSD->Control & SE_SACL_PRESENT)
521 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
522 length = Sacl->AclSize;
524 if (isSelfRelative)
526 destSD->Sacl = srcSD->Sacl;
527 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD_PTR)destSD->Sacl), Sacl);
529 else
531 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
532 copy_acl(length, destSD->Sacl, Sacl);
536 return STATUS_SUCCESS;
539 /**************************************************************************
540 * RtlValidSecurityDescriptor [NTDLL.@]
542 * Determine if a SECURITY_DESCRIPTOR is valid.
544 * PARAMS
545 * SecurityDescriptor [I] Descriptor to check.
547 * RETURNS
548 * Success: STATUS_SUCCESS.
549 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
551 NTSTATUS WINAPI RtlValidSecurityDescriptor(
552 PSECURITY_DESCRIPTOR SecurityDescriptor)
554 if ( ! SecurityDescriptor )
555 return STATUS_INVALID_SECURITY_DESCR;
556 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
557 return STATUS_UNKNOWN_REVISION;
559 return STATUS_SUCCESS;
562 /**************************************************************************
563 * RtlLengthSecurityDescriptor [NTDLL.@]
565 ULONG WINAPI RtlLengthSecurityDescriptor(
566 PSECURITY_DESCRIPTOR pSecurityDescriptor)
568 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
569 ULONG_PTR offset = 0;
570 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
572 if ( lpsd == NULL )
573 return 0;
575 if ( lpsd->Control & SE_SELF_RELATIVE)
576 offset = (ULONG_PTR) lpsd;
578 if ( lpsd->Owner != NULL )
579 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
581 if ( lpsd->Group != NULL )
582 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
584 if ( (lpsd->Control & SE_SACL_PRESENT) &&
585 lpsd->Sacl != NULL )
586 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
588 if ( (lpsd->Control & SE_DACL_PRESENT) &&
589 lpsd->Dacl != NULL )
590 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
592 return Size;
595 /******************************************************************************
596 * RtlGetDaclSecurityDescriptor [NTDLL.@]
599 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
600 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
601 OUT PBOOLEAN lpbDaclPresent,
602 OUT PACL *pDacl,
603 OUT PBOOLEAN lpbDaclDefaulted)
605 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
607 TRACE("(%p,%p,%p,%p)\n",
608 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
610 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
611 return STATUS_UNKNOWN_REVISION ;
613 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
615 if ( SE_SELF_RELATIVE & lpsd->Control)
616 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Dacl);
617 else
618 *pDacl = lpsd->Dacl;
620 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
623 return STATUS_SUCCESS;
626 /**************************************************************************
627 * RtlSetDaclSecurityDescriptor [NTDLL.@]
629 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
630 PSECURITY_DESCRIPTOR pSecurityDescriptor,
631 BOOLEAN daclpresent,
632 PACL dacl,
633 BOOLEAN dacldefaulted )
635 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
637 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
638 return STATUS_UNKNOWN_REVISION;
639 if (lpsd->Control & SE_SELF_RELATIVE)
640 return STATUS_INVALID_SECURITY_DESCR;
642 if (!daclpresent)
644 lpsd->Control &= ~SE_DACL_PRESENT;
645 return STATUS_SUCCESS;
648 lpsd->Control |= SE_DACL_PRESENT;
649 lpsd->Dacl = dacl;
651 if (dacldefaulted)
652 lpsd->Control |= SE_DACL_DEFAULTED;
653 else
654 lpsd->Control &= ~SE_DACL_DEFAULTED;
656 return STATUS_SUCCESS;
659 /******************************************************************************
660 * RtlGetSaclSecurityDescriptor [NTDLL.@]
663 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
664 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
665 OUT PBOOLEAN lpbSaclPresent,
666 OUT PACL *pSacl,
667 OUT PBOOLEAN lpbSaclDefaulted)
669 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
671 TRACE("(%p,%p,%p,%p)\n",
672 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
674 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
675 return STATUS_UNKNOWN_REVISION;
677 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
679 if (SE_SELF_RELATIVE & lpsd->Control)
680 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD_PTR)lpsd->Sacl);
681 else
682 *pSacl = lpsd->Sacl;
684 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
687 return STATUS_SUCCESS;
690 /**************************************************************************
691 * RtlSetSaclSecurityDescriptor [NTDLL.@]
693 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
694 PSECURITY_DESCRIPTOR pSecurityDescriptor,
695 BOOLEAN saclpresent,
696 PACL sacl,
697 BOOLEAN sacldefaulted)
699 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
701 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
702 return STATUS_UNKNOWN_REVISION;
703 if (lpsd->Control & SE_SELF_RELATIVE)
704 return STATUS_INVALID_SECURITY_DESCR;
705 if (!saclpresent) {
706 lpsd->Control &= ~SE_SACL_PRESENT;
707 return 0;
709 lpsd->Control |= SE_SACL_PRESENT;
710 lpsd->Sacl = sacl;
711 if (sacldefaulted)
712 lpsd->Control |= SE_SACL_DEFAULTED;
713 else
714 lpsd->Control &= ~SE_SACL_DEFAULTED;
715 return STATUS_SUCCESS;
718 /**************************************************************************
719 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
721 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
722 PSECURITY_DESCRIPTOR pSecurityDescriptor,
723 PSID *Owner,
724 PBOOLEAN OwnerDefaulted)
726 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
728 if ( !lpsd || !Owner || !OwnerDefaulted )
729 return STATUS_INVALID_PARAMETER;
731 if ( lpsd->Control & SE_OWNER_DEFAULTED )
732 *OwnerDefaulted = TRUE;
733 else
734 *OwnerDefaulted = FALSE;
736 if (lpsd->Owner != NULL)
738 if (lpsd->Control & SE_SELF_RELATIVE)
739 *Owner = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Owner);
740 else
741 *Owner = lpsd->Owner;
744 else
745 *Owner = NULL;
747 return STATUS_SUCCESS;
750 /**************************************************************************
751 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
753 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
754 PSECURITY_DESCRIPTOR pSecurityDescriptor,
755 PSID owner,
756 BOOLEAN ownerdefaulted)
758 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
760 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
761 return STATUS_UNKNOWN_REVISION;
762 if (lpsd->Control & SE_SELF_RELATIVE)
763 return STATUS_INVALID_SECURITY_DESCR;
765 lpsd->Owner = owner;
766 if (ownerdefaulted)
767 lpsd->Control |= SE_OWNER_DEFAULTED;
768 else
769 lpsd->Control &= ~SE_OWNER_DEFAULTED;
770 return STATUS_SUCCESS;
773 /**************************************************************************
774 * RtlSetGroupSecurityDescriptor [NTDLL.@]
776 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
777 PSECURITY_DESCRIPTOR pSecurityDescriptor,
778 PSID group,
779 BOOLEAN groupdefaulted)
781 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
783 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
784 return STATUS_UNKNOWN_REVISION;
785 if (lpsd->Control & SE_SELF_RELATIVE)
786 return STATUS_INVALID_SECURITY_DESCR;
788 lpsd->Group = group;
789 if (groupdefaulted)
790 lpsd->Control |= SE_GROUP_DEFAULTED;
791 else
792 lpsd->Control &= ~SE_GROUP_DEFAULTED;
793 return STATUS_SUCCESS;
796 /**************************************************************************
797 * RtlGetGroupSecurityDescriptor [NTDLL.@]
799 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
800 PSECURITY_DESCRIPTOR pSecurityDescriptor,
801 PSID *Group,
802 PBOOLEAN GroupDefaulted)
804 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
806 if ( !lpsd || !Group || !GroupDefaulted )
807 return STATUS_INVALID_PARAMETER;
809 if ( lpsd->Control & SE_GROUP_DEFAULTED )
810 *GroupDefaulted = TRUE;
811 else
812 *GroupDefaulted = FALSE;
814 if (lpsd->Group != NULL)
816 if (lpsd->Control & SE_SELF_RELATIVE)
817 *Group = (PSID)((LPBYTE)lpsd + (ULONG_PTR)lpsd->Group);
818 else
819 *Group = lpsd->Group;
821 else
822 *Group = NULL;
824 return STATUS_SUCCESS;
827 /**************************************************************************
828 * RtlMakeSelfRelativeSD [NTDLL.@]
830 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
831 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
832 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
833 IN OUT LPDWORD lpdwBufferLength)
835 ULONG_PTR offsetRel;
836 ULONG length;
837 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
838 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
840 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
841 lpdwBufferLength ? *lpdwBufferLength: -1);
843 if (!lpdwBufferLength || !pAbs)
844 return STATUS_INVALID_PARAMETER;
846 length = RtlLengthSecurityDescriptor(pAbs);
847 if (*lpdwBufferLength < length)
849 *lpdwBufferLength = length;
850 return STATUS_BUFFER_TOO_SMALL;
853 if (!pRel)
854 return STATUS_INVALID_PARAMETER;
856 if (pAbs->Control & SE_SELF_RELATIVE)
858 memcpy(pRel, pAbs, length);
859 return STATUS_SUCCESS;
862 pRel->Revision = pAbs->Revision;
863 pRel->Sbz1 = pAbs->Sbz1;
864 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
866 offsetRel = sizeof(SECURITY_DESCRIPTOR);
867 if (pAbs->Owner)
869 pRel->Owner = (PSID) offsetRel;
870 length = RtlLengthSid(pAbs->Owner);
871 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
872 offsetRel += length;
874 else
876 pRel->Owner = NULL;
879 if (pAbs->Group)
881 pRel->Group = (PSID) offsetRel;
882 length = RtlLengthSid(pAbs->Group);
883 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
884 offsetRel += length;
886 else
888 pRel->Group = NULL;
891 if (pAbs->Sacl)
893 pRel->Sacl = (PACL) offsetRel;
894 length = pAbs->Sacl->AclSize;
895 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
896 offsetRel += length;
898 else
900 pRel->Sacl = NULL;
903 if (pAbs->Dacl)
905 pRel->Dacl = (PACL) offsetRel;
906 length = pAbs->Dacl->AclSize;
907 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
909 else
911 pRel->Dacl = NULL;
914 return STATUS_SUCCESS;
918 /**************************************************************************
919 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
921 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
922 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
923 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
924 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
925 OUT PACL pDacl,
926 OUT LPDWORD lpdwDaclSize,
927 OUT PACL pSacl,
928 OUT LPDWORD lpdwSaclSize,
929 OUT PSID pOwner,
930 OUT LPDWORD lpdwOwnerSize,
931 OUT PSID pPrimaryGroup,
932 OUT LPDWORD lpdwPrimaryGroupSize)
934 NTSTATUS status = STATUS_SUCCESS;
935 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
936 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
938 if (!pRel ||
939 !lpdwAbsoluteSecurityDescriptorSize ||
940 !lpdwDaclSize ||
941 !lpdwSaclSize ||
942 !lpdwOwnerSize ||
943 !lpdwPrimaryGroupSize ||
944 ~pRel->Control & SE_SELF_RELATIVE)
945 return STATUS_INVALID_PARAMETER;
947 /* Confirm buffers are sufficiently large */
948 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
950 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
951 status = STATUS_BUFFER_TOO_SMALL;
954 if (pRel->Control & SE_DACL_PRESENT &&
955 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize)
957 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel))->AclSize;
958 status = STATUS_BUFFER_TOO_SMALL;
961 if (pRel->Control & SE_SACL_PRESENT &&
962 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize)
964 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel))->AclSize;
965 status = STATUS_BUFFER_TOO_SMALL;
968 if (pRel->Owner &&
969 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel)))
971 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel));
972 status = STATUS_BUFFER_TOO_SMALL;
975 if (pRel->Group &&
976 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel)))
978 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel));
979 status = STATUS_BUFFER_TOO_SMALL;
982 if (status != STATUS_SUCCESS)
983 return status;
985 /* Copy structures, and clear the ones we don't set */
986 pAbs->Revision = pRel->Revision;
987 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
988 pAbs->Sacl = NULL;
989 pAbs->Dacl = NULL;
990 pAbs->Owner = NULL;
991 pAbs->Group = NULL;
993 if (pRel->Control & SE_SACL_PRESENT)
995 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG_PTR)pRel);
997 memcpy(pSacl, pAcl, pAcl->AclSize);
998 pAbs->Sacl = pSacl;
1001 if (pRel->Control & SE_DACL_PRESENT)
1003 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG_PTR)pRel);
1004 memcpy(pDacl, pAcl, pAcl->AclSize);
1005 pAbs->Dacl = pDacl;
1008 if (pRel->Owner)
1010 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG_PTR)pRel);
1011 memcpy(pOwner, psid, RtlLengthSid(psid));
1012 pAbs->Owner = pOwner;
1015 if (pRel->Group)
1017 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG_PTR)pRel);
1018 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1019 pAbs->Group = pPrimaryGroup;
1022 return status;
1025 /******************************************************************************
1026 * RtlGetControlSecurityDescriptor (NTDLL.@)
1028 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1029 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1030 PSECURITY_DESCRIPTOR_CONTROL pControl,
1031 LPDWORD lpdwRevision)
1033 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1035 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1037 *lpdwRevision = lpsd->Revision;
1039 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1040 return STATUS_UNKNOWN_REVISION;
1042 *pControl = lpsd->Control;
1044 return STATUS_SUCCESS;
1047 /******************************************************************************
1048 * RtlSetControlSecurityDescriptor (NTDLL.@)
1050 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1051 PSECURITY_DESCRIPTOR SecurityDescriptor,
1052 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1053 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1055 FIXME("(%p 0x%08x 0x%08x): stub\n", SecurityDescriptor, ControlBitsOfInterest,
1056 ControlBitsToSet);
1057 return STATUS_SUCCESS;
1061 /**************************************************************************
1062 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1064 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1065 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1066 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1067 PULONG BufferLength)
1069 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1071 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1072 SelfRelativeSecurityDescriptor, BufferLength);
1074 if (abs->Control & SE_SELF_RELATIVE)
1075 return STATUS_BAD_DESCRIPTOR_FORMAT;
1077 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1078 SelfRelativeSecurityDescriptor, BufferLength);
1083 * access control list's
1086 /**************************************************************************
1087 * RtlCreateAcl [NTDLL.@]
1089 * NOTES
1090 * This should return NTSTATUS
1092 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1094 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1096 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1097 return STATUS_INVALID_PARAMETER;
1098 if (size<sizeof(ACL))
1099 return STATUS_BUFFER_TOO_SMALL;
1100 if (size>0xFFFF)
1101 return STATUS_INVALID_PARAMETER;
1103 memset(acl,'\0',sizeof(ACL));
1104 acl->AclRevision = rev;
1105 acl->AclSize = size;
1106 acl->AceCount = 0;
1107 return STATUS_SUCCESS;
1110 /**************************************************************************
1111 * RtlFirstFreeAce [NTDLL.@]
1112 * looks for the AceCount+1 ACE, and if it is still within the alloced
1113 * ACL, return a pointer to it
1115 BOOLEAN WINAPI RtlFirstFreeAce(
1116 PACL acl,
1117 PACE_HEADER *x)
1119 PACE_HEADER ace;
1120 int i;
1122 *x = 0;
1123 ace = (PACE_HEADER)(acl+1);
1124 for (i=0;i<acl->AceCount;i++) {
1125 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1126 return 0;
1127 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1129 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1130 return 0;
1131 *x = ace;
1132 return 1;
1135 /**************************************************************************
1136 * RtlAddAce [NTDLL.@]
1138 NTSTATUS WINAPI RtlAddAce(
1139 PACL acl,
1140 DWORD rev,
1141 DWORD xnrofaces,
1142 PACE_HEADER acestart,
1143 DWORD acelen)
1145 PACE_HEADER ace,targetace;
1146 int nrofaces;
1148 if (acl->AclRevision != ACL_REVISION)
1149 return STATUS_INVALID_PARAMETER;
1150 if (!RtlFirstFreeAce(acl,&targetace))
1151 return STATUS_INVALID_PARAMETER;
1152 nrofaces=0;ace=acestart;
1153 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1154 nrofaces++;
1155 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1157 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1158 return STATUS_INVALID_PARAMETER;
1159 memcpy((LPBYTE)targetace,acestart,acelen);
1160 acl->AceCount+=nrofaces;
1161 return STATUS_SUCCESS;
1164 /**************************************************************************
1165 * RtlDeleteAce [NTDLL.@]
1167 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1169 NTSTATUS status;
1170 PACE_HEADER pAce;
1172 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1174 if (STATUS_SUCCESS == status)
1176 PACE_HEADER pcAce;
1177 DWORD len = 0;
1179 /* skip over the ACE we are deleting */
1180 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1181 dwAceIndex++;
1183 /* calculate the length of the rest */
1184 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1186 len += pcAce->AceSize;
1187 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1190 /* slide them all backwards */
1191 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1192 pAcl->AceCount--;
1195 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1197 return status;
1200 /******************************************************************************
1201 * RtlAddAccessAllowedAce [NTDLL.@]
1203 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1204 IN OUT PACL pAcl,
1205 IN DWORD dwAceRevision,
1206 IN DWORD AccessMask,
1207 IN PSID pSid)
1209 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1212 /******************************************************************************
1213 * RtlAddAccessAllowedAceEx [NTDLL.@]
1215 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1216 IN OUT PACL pAcl,
1217 IN DWORD dwAceRevision,
1218 IN DWORD AceFlags,
1219 IN DWORD AccessMask,
1220 IN PSID pSid)
1222 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1224 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1225 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1228 /******************************************************************************
1229 * RtlAddAccessDeniedAce [NTDLL.@]
1231 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1232 IN OUT PACL pAcl,
1233 IN DWORD dwAceRevision,
1234 IN DWORD AccessMask,
1235 IN PSID pSid)
1237 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1240 /******************************************************************************
1241 * RtlAddAccessDeniedAceEx [NTDLL.@]
1243 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1244 IN OUT PACL pAcl,
1245 IN DWORD dwAceRevision,
1246 IN DWORD AceFlags,
1247 IN DWORD AccessMask,
1248 IN PSID pSid)
1250 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1252 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1253 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1256 /**************************************************************************
1257 * RtlAddAuditAccessAce [NTDLL.@]
1259 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1260 IN OUT PACL pAcl,
1261 IN DWORD dwAceRevision,
1262 IN DWORD dwAceFlags,
1263 IN DWORD dwAccessMask,
1264 IN PSID pSid,
1265 IN BOOL bAuditSuccess,
1266 IN BOOL bAuditFailure)
1268 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1269 pSid,bAuditSuccess,bAuditFailure);
1271 if (bAuditSuccess)
1272 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1274 if (bAuditFailure)
1275 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1277 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1278 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1281 /**************************************************************************
1282 * RtlAddAuditAccessAce [NTDLL.@]
1284 NTSTATUS WINAPI RtlAddAuditAccessAce(
1285 IN OUT PACL pAcl,
1286 IN DWORD dwAceRevision,
1287 IN DWORD dwAccessMask,
1288 IN PSID pSid,
1289 IN BOOL bAuditSuccess,
1290 IN BOOL bAuditFailure)
1292 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1295 /******************************************************************************
1296 * RtlValidAcl [NTDLL.@]
1298 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1300 BOOLEAN ret;
1301 TRACE("(%p)\n", pAcl);
1303 __TRY
1305 PACE_HEADER ace;
1306 int i;
1308 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1309 pAcl->AclRevision > MAX_ACL_REVISION)
1310 ret = FALSE;
1311 else
1313 ace = (PACE_HEADER)(pAcl+1);
1314 ret = TRUE;
1315 for (i=0;i<=pAcl->AceCount;i++)
1317 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1319 ret = FALSE;
1320 break;
1322 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1326 __EXCEPT_PAGE_FAULT
1328 WARN("(%p): invalid pointer!\n", pAcl);
1329 return 0;
1331 __ENDTRY
1332 return ret;
1335 /******************************************************************************
1336 * RtlGetAce [NTDLL.@]
1338 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1340 PACE_HEADER ace;
1342 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1344 if (dwAceIndex > pAcl->AceCount)
1345 return STATUS_INVALID_PARAMETER;
1347 ace = (PACE_HEADER)(pAcl + 1);
1348 for (;dwAceIndex;dwAceIndex--)
1349 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1351 *pAce = (LPVOID) ace;
1353 return STATUS_SUCCESS;
1357 * misc
1360 /******************************************************************************
1361 * RtlAdjustPrivilege [NTDLL.@]
1363 * Enables or disables a privilege from the calling thread or process.
1365 * PARAMS
1366 * Privilege [I] Privilege index to change.
1367 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1368 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1369 * Enabled [O] Whether privilege was previously enabled or disabled.
1371 * RETURNS
1372 * Success: STATUS_SUCCESS.
1373 * Failure: NTSTATUS code.
1375 * SEE ALSO
1376 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1379 NTSTATUS WINAPI
1380 RtlAdjustPrivilege(ULONG Privilege,
1381 BOOLEAN Enable,
1382 BOOLEAN CurrentThread,
1383 PBOOLEAN Enabled)
1385 TOKEN_PRIVILEGES NewState;
1386 TOKEN_PRIVILEGES OldState;
1387 ULONG ReturnLength;
1388 HANDLE TokenHandle;
1389 NTSTATUS Status;
1391 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1392 CurrentThread ? "TRUE" : "FALSE", Enabled);
1394 if (CurrentThread)
1396 Status = NtOpenThreadToken(GetCurrentThread(),
1397 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1398 FALSE,
1399 &TokenHandle);
1401 else
1403 Status = NtOpenProcessToken(GetCurrentProcess(),
1404 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1405 &TokenHandle);
1408 if (!NT_SUCCESS(Status))
1410 WARN("Retrieving token handle failed (Status %x)\n", Status);
1411 return Status;
1414 OldState.PrivilegeCount = 1;
1416 NewState.PrivilegeCount = 1;
1417 NewState.Privileges[0].Luid.LowPart = Privilege;
1418 NewState.Privileges[0].Luid.HighPart = 0;
1419 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1421 Status = NtAdjustPrivilegesToken(TokenHandle,
1422 FALSE,
1423 &NewState,
1424 sizeof(TOKEN_PRIVILEGES),
1425 &OldState,
1426 &ReturnLength);
1427 NtClose (TokenHandle);
1428 if (Status == STATUS_NOT_ALL_ASSIGNED)
1430 TRACE("Failed to assign all privileges\n");
1431 return STATUS_PRIVILEGE_NOT_HELD;
1433 if (!NT_SUCCESS(Status))
1435 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1436 return Status;
1439 if (OldState.PrivilegeCount == 0)
1440 *Enabled = Enable;
1441 else
1442 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1444 return STATUS_SUCCESS;
1447 /******************************************************************************
1448 * RtlImpersonateSelf [NTDLL.@]
1450 * Makes an impersonation token that represents the process user and assigns
1451 * to the current thread.
1453 * PARAMS
1454 * ImpersonationLevel [I] Level at which to impersonate.
1456 * RETURNS
1457 * Success: STATUS_SUCCESS.
1458 * Failure: NTSTATUS code.
1460 NTSTATUS WINAPI
1461 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1463 NTSTATUS Status;
1464 OBJECT_ATTRIBUTES ObjectAttributes;
1465 HANDLE ProcessToken;
1466 HANDLE ImpersonationToken;
1468 TRACE("(%08x)\n", ImpersonationLevel);
1470 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1471 &ProcessToken);
1472 if (Status != STATUS_SUCCESS)
1473 return Status;
1475 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1477 Status = NtDuplicateToken( ProcessToken,
1478 TOKEN_IMPERSONATE,
1479 &ObjectAttributes,
1480 ImpersonationLevel,
1481 TokenImpersonation,
1482 &ImpersonationToken );
1483 if (Status != STATUS_SUCCESS)
1485 NtClose( ProcessToken );
1486 return Status;
1489 Status = NtSetInformationThread( GetCurrentThread(),
1490 ThreadImpersonationToken,
1491 &ImpersonationToken,
1492 sizeof(ImpersonationToken) );
1494 NtClose( ImpersonationToken );
1495 NtClose( ProcessToken );
1497 return Status;
1500 /******************************************************************************
1501 * NtAccessCheck [NTDLL.@]
1502 * ZwAccessCheck [NTDLL.@]
1504 * Checks that a user represented by a token is allowed to access an object
1505 * represented by a security descriptor.
1507 * PARAMS
1508 * SecurityDescriptor [I] The security descriptor of the object to check.
1509 * ClientToken [I] Token of the user accessing the object.
1510 * DesiredAccess [I] The desired access to the object.
1511 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1512 * PrivilegeSet [I/O] Privileges used during the access check.
1513 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1514 * GrantedAccess [O] The actual access rights granted.
1515 * AccessStatus [O] The status of the access check.
1517 * RETURNS
1518 * NTSTATUS code.
1520 * NOTES
1521 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1522 * the maximum access rights allowed by the SD and returns them in
1523 * GrantedAccess.
1524 * The SecurityDescriptor must have a valid owner and groups present,
1525 * otherwise the function will fail.
1527 NTSTATUS WINAPI
1528 NtAccessCheck(
1529 PSECURITY_DESCRIPTOR SecurityDescriptor,
1530 HANDLE ClientToken,
1531 ACCESS_MASK DesiredAccess,
1532 PGENERIC_MAPPING GenericMapping,
1533 PPRIVILEGE_SET PrivilegeSet,
1534 PULONG ReturnLength,
1535 PULONG GrantedAccess,
1536 NTSTATUS *AccessStatus)
1538 NTSTATUS status;
1540 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1541 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1542 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1544 SERVER_START_REQ( access_check )
1546 struct security_descriptor sd;
1547 PSID owner;
1548 PSID group;
1549 PACL sacl;
1550 PACL dacl;
1551 BOOLEAN defaulted, present;
1552 DWORD revision;
1553 SECURITY_DESCRIPTOR_CONTROL control;
1555 req->handle = ClientToken;
1556 req->desired_access = DesiredAccess;
1557 req->mapping_read = GenericMapping->GenericRead;
1558 req->mapping_write = GenericMapping->GenericWrite;
1559 req->mapping_execute = GenericMapping->GenericExecute;
1560 req->mapping_all = GenericMapping->GenericAll;
1562 /* marshal security descriptor */
1563 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1564 sd.control = control & ~SE_SELF_RELATIVE;
1565 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1566 sd.owner_len = RtlLengthSid( owner );
1567 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1568 sd.group_len = RtlLengthSid( group );
1569 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1570 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1571 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1572 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1574 wine_server_add_data( req, &sd, sizeof(sd) );
1575 wine_server_add_data( req, owner, sd.owner_len );
1576 wine_server_add_data( req, group, sd.group_len );
1577 wine_server_add_data( req, sacl, sd.sacl_len );
1578 wine_server_add_data( req, dacl, sd.dacl_len );
1580 wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1582 status = wine_server_call( req );
1584 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1585 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1587 if (status == STATUS_SUCCESS)
1589 *AccessStatus = reply->access_status;
1590 *GrantedAccess = reply->access_granted;
1593 SERVER_END_REQ;
1595 return status;
1598 /******************************************************************************
1599 * NtSetSecurityObject [NTDLL.@]
1600 * ZwSetSecurityObject [NTDLL.@]
1602 * Sets specified parts of the object's security descriptor.
1604 * PARAMS
1605 * Handle [I] Handle to the object to change security descriptor of.
1606 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1607 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1609 * RETURNS
1610 * NTSTATUS code.
1613 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1614 SECURITY_INFORMATION SecurityInformation,
1615 PSECURITY_DESCRIPTOR SecurityDescriptor)
1617 NTSTATUS status;
1618 struct security_descriptor sd;
1619 PACL dacl = NULL, sacl = NULL;
1620 PSID owner = NULL, group = NULL;
1621 BOOLEAN defaulted, present;
1622 DWORD revision;
1623 SECURITY_DESCRIPTOR_CONTROL control;
1625 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1627 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1629 memset( &sd, 0, sizeof(sd) );
1630 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1631 if (status != STATUS_SUCCESS) return status;
1632 sd.control = control & ~SE_SELF_RELATIVE;
1634 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1636 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1637 if (status != STATUS_SUCCESS) return status;
1638 if (!(sd.owner_len = RtlLengthSid( owner )))
1639 return STATUS_INVALID_SECURITY_DESCR;
1642 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1644 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1645 if (status != STATUS_SUCCESS) return status;
1646 if (!(sd.group_len = RtlLengthSid( group )))
1647 return STATUS_INVALID_SECURITY_DESCR;
1650 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1652 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1653 if (status != STATUS_SUCCESS) return status;
1654 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1655 sd.control |= SE_SACL_PRESENT;
1658 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1660 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1661 if (status != STATUS_SUCCESS) return status;
1662 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1663 sd.control |= SE_DACL_PRESENT;
1666 SERVER_START_REQ( set_security_object )
1668 req->handle = Handle;
1669 req->security_info = SecurityInformation;
1671 wine_server_add_data( req, &sd, sizeof(sd) );
1672 wine_server_add_data( req, owner, sd.owner_len );
1673 wine_server_add_data( req, group, sd.group_len );
1674 wine_server_add_data( req, sacl, sd.sacl_len );
1675 wine_server_add_data( req, dacl, sd.dacl_len );
1676 status = wine_server_call( req );
1678 SERVER_END_REQ;
1680 return status;
1683 /******************************************************************************
1684 * RtlConvertSidToUnicodeString (NTDLL.@)
1686 * The returned SID is used to access the USER registry hive usually
1688 * the native function returns something like
1689 * "S-1-5-21-0000000000-000000000-0000000000-500";
1691 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1692 PUNICODE_STRING String,
1693 PSID pSid,
1694 BOOLEAN AllocateString)
1696 static const WCHAR formatW[] = {'-','%','u',0};
1697 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1698 WCHAR *p = buffer;
1699 const SID *sid = (const SID *)pSid;
1700 DWORD i, len;
1702 *p++ = 'S';
1703 p += sprintfW( p, formatW, sid->Revision );
1704 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1705 sid->IdentifierAuthority.Value[4] ),
1706 MAKEWORD( sid->IdentifierAuthority.Value[3],
1707 sid->IdentifierAuthority.Value[2] )));
1708 for (i = 0; i < sid->SubAuthorityCount; i++)
1709 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1711 len = (p + 1 - buffer) * sizeof(WCHAR);
1713 String->Length = len - sizeof(WCHAR);
1714 if (AllocateString)
1716 String->MaximumLength = len;
1717 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1718 return STATUS_NO_MEMORY;
1720 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1722 memcpy( String->Buffer, buffer, len );
1723 return STATUS_SUCCESS;
1726 /******************************************************************************
1727 * RtlQueryInformationAcl (NTDLL.@)
1729 NTSTATUS WINAPI RtlQueryInformationAcl(
1730 PACL pAcl,
1731 LPVOID pAclInformation,
1732 DWORD nAclInformationLength,
1733 ACL_INFORMATION_CLASS dwAclInformationClass)
1735 NTSTATUS status = STATUS_SUCCESS;
1737 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1738 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1740 switch (dwAclInformationClass)
1742 case AclRevisionInformation:
1744 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1746 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1747 status = STATUS_INVALID_PARAMETER;
1748 else
1749 paclrev->AclRevision = pAcl->AclRevision;
1751 break;
1754 case AclSizeInformation:
1756 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1758 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1759 status = STATUS_INVALID_PARAMETER;
1760 else
1762 paclsize->AceCount = pAcl->AceCount;
1763 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1764 if (pAcl->AclSize < paclsize->AclBytesInUse)
1766 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1767 paclsize->AclBytesFree = 0;
1768 paclsize->AclBytesInUse = pAcl->AclSize;
1770 else
1771 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1774 break;
1777 default:
1778 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1779 status = STATUS_INVALID_PARAMETER;
1782 return status;