setupapi: Add pSetupFree|Malloc|Realloc to spec file and forward them.
[wine.git] / dlls / ntdll / sec.c
blobc8e8a4deed5b2a79b682f54bc9780259b99d5367
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 "ntdll_misc.h"
39 #include "wine/exception.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 #define SELF_RELATIVE_FIELD(sd,field) ((BYTE *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
50 /* helper function to retrieve active length of an ACL */
51 static size_t acl_bytesInUse(PACL pAcl)
53 int i;
54 size_t bytesInUse = sizeof(ACL);
55 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
56 for (i = 0; i < pAcl->AceCount; i++)
58 bytesInUse += ace->AceSize;
59 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
61 return bytesInUse;
64 /* helper function to copy an ACL */
65 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
67 DWORD size;
69 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
70 return FALSE;
72 size = pSourceAcl->AclSize;
73 if (nDestinationAclLength < size)
74 return FALSE;
76 memmove(pDestinationAcl, pSourceAcl, size);
77 return TRUE;
80 /* generically adds an ACE to an ACL */
81 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
82 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
84 ACE_HEADER *pAceHeader;
85 DWORD dwLengthSid;
86 DWORD dwAceSize;
87 DWORD *pAccessMask;
88 DWORD *pSidStart;
90 if (!RtlValidSid(pSid))
91 return STATUS_INVALID_SID;
93 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
94 return STATUS_REVISION_MISMATCH;
96 if (!RtlValidAcl(pAcl))
97 return STATUS_INVALID_ACL;
99 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
100 return STATUS_INVALID_ACL;
102 if (!pAceHeader)
103 return STATUS_ALLOTTED_SPACE_EXCEEDED;
105 /* calculate generic size of the ACE */
106 dwLengthSid = RtlLengthSid(pSid);
107 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
108 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
109 return STATUS_ALLOTTED_SPACE_EXCEEDED;
111 /* fill the new ACE */
112 pAceHeader->AceType = dwAceType;
113 pAceHeader->AceFlags = dwAceFlags;
114 pAceHeader->AceSize = dwAceSize;
116 /* skip past the ACE_HEADER of the ACE */
117 pAccessMask = (DWORD *)(pAceHeader + 1);
118 *pAccessMask = dwAccessMask;
120 /* skip past ACE->Mask */
121 pSidStart = pAccessMask + 1;
122 RtlCopySid(dwLengthSid, pSidStart, pSid);
124 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
125 pAcl->AceCount++;
127 return STATUS_SUCCESS;
131 * SID FUNCTIONS
134 /******************************************************************************
135 * RtlAllocateAndInitializeSid [NTDLL.@]
138 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
139 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
140 BYTE nSubAuthorityCount,
141 DWORD nSubAuthority0, DWORD nSubAuthority1,
142 DWORD nSubAuthority2, DWORD nSubAuthority3,
143 DWORD nSubAuthority4, DWORD nSubAuthority5,
144 DWORD nSubAuthority6, DWORD nSubAuthority7,
145 PSID *pSid )
147 SID *tmp_sid;
149 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
150 pIdentifierAuthority,nSubAuthorityCount,
151 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
152 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
154 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
156 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
157 RtlLengthRequiredSid(nSubAuthorityCount))))
158 return STATUS_NO_MEMORY;
160 tmp_sid->Revision = SID_REVISION;
162 if (pIdentifierAuthority)
163 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
164 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
166 switch( nSubAuthorityCount )
168 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
169 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
170 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
171 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
172 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
173 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
174 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
175 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
176 break;
178 *pSid = tmp_sid;
179 return STATUS_SUCCESS;
182 /******************************************************************************
183 * RtlEqualSid [NTDLL.@]
185 * Determine if two SIDs are equal.
187 * PARAMS
188 * pSid1 [I] Source SID
189 * pSid2 [I] SID to compare with
191 * RETURNS
192 * TRUE, if pSid1 is equal to pSid2,
193 * FALSE otherwise.
195 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
197 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
198 return FALSE;
200 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
201 return FALSE;
203 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
204 return FALSE;
206 return TRUE;
209 /******************************************************************************
210 * RtlEqualPrefixSid [NTDLL.@]
212 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
214 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
215 return FALSE;
217 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
218 return FALSE;
220 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
221 return FALSE;
223 return TRUE;
227 /******************************************************************************
228 * RtlFreeSid [NTDLL.@]
230 * Free the resources used by a SID.
232 * PARAMS
233 * pSid [I] SID to Free.
235 * RETURNS
236 * STATUS_SUCCESS.
238 DWORD WINAPI RtlFreeSid(PSID pSid)
240 TRACE("(%p)\n", pSid);
241 RtlFreeHeap( GetProcessHeap(), 0, pSid );
242 return STATUS_SUCCESS;
245 /**************************************************************************
246 * RtlLengthRequiredSid [NTDLL.@]
248 * Determine the amount of memory a SID will use
250 * PARAMS
251 * nrofsubauths [I] Number of Sub Authorities in the SID.
253 * RETURNS
254 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
256 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
258 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
261 /**************************************************************************
262 * RtlLengthSid [NTDLL.@]
264 * Determine the amount of memory a SID is using
266 * PARAMS
267 * pSid [I] SID to get the size of.
269 * RETURNS
270 * The size, in bytes, of pSid.
272 DWORD WINAPI RtlLengthSid(PSID pSid)
274 TRACE("sid=%p\n",pSid);
275 if (!pSid) return 0;
276 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
279 /**************************************************************************
280 * RtlInitializeSid [NTDLL.@]
282 * Initialise a SID.
284 * PARAMS
285 * pSid [I] SID to initialise
286 * pIdentifierAuthority [I] Identifier Authority
287 * nSubAuthorityCount [I] Number of Sub Authorities
289 * RETURNS
290 * Success: TRUE. pSid is initialised with the details given.
291 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
293 BOOL WINAPI RtlInitializeSid(
294 PSID pSid,
295 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
296 BYTE nSubAuthorityCount)
298 int i;
299 SID* pisid=pSid;
301 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
302 return FALSE;
304 pisid->Revision = SID_REVISION;
305 pisid->SubAuthorityCount = nSubAuthorityCount;
306 if (pIdentifierAuthority)
307 pisid->IdentifierAuthority = *pIdentifierAuthority;
309 for (i = 0; i < nSubAuthorityCount; i++)
310 *RtlSubAuthoritySid(pSid, i) = 0;
312 return TRUE;
315 /**************************************************************************
316 * RtlSubAuthoritySid [NTDLL.@]
318 * Return the Sub Authority of a SID
320 * PARAMS
321 * pSid [I] SID to get the Sub Authority from.
322 * nSubAuthority [I] Sub Authority number.
324 * RETURNS
325 * A pointer to The Sub Authority value of pSid.
327 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
329 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
332 /**************************************************************************
333 * RtlIdentifierAuthoritySid [NTDLL.@]
335 * Return the Identifier Authority of a SID.
337 * PARAMS
338 * pSid [I] SID to get the Identifier Authority from.
340 * RETURNS
341 * A pointer to the Identifier Authority value of pSid.
343 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
345 return &(((SID*)pSid)->IdentifierAuthority);
348 /**************************************************************************
349 * RtlSubAuthorityCountSid [NTDLL.@]
351 * Get the number of Sub Authorities in a SID.
353 * PARAMS
354 * pSid [I] SID to get the count from.
356 * RETURNS
357 * A pointer to the Sub Authority count of pSid.
359 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
361 return &(((SID*)pSid)->SubAuthorityCount);
364 /**************************************************************************
365 * RtlCopySid [NTDLL.@]
367 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
369 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
370 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
371 return FALSE;
373 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
374 return FALSE;
376 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
377 return TRUE;
379 /******************************************************************************
380 * RtlValidSid [NTDLL.@]
382 * Determine if a SID is valid.
384 * PARAMS
385 * pSid [I] SID to check
387 * RETURNS
388 * TRUE if pSid is valid,
389 * FALSE otherwise.
391 BOOLEAN WINAPI RtlValidSid( PSID pSid )
393 BOOL ret;
394 __TRY
396 ret = TRUE;
397 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
398 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
400 ret = FALSE;
403 __EXCEPT_PAGE_FAULT
405 WARN("(%p): invalid pointer!\n", pSid);
406 return FALSE;
408 __ENDTRY
409 return ret;
414 * security descriptor functions
417 /**************************************************************************
418 * RtlCreateSecurityDescriptor [NTDLL.@]
420 * Initialise a SECURITY_DESCRIPTOR.
422 * PARAMS
423 * lpsd [O] Descriptor to initialise.
424 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
426 * RETURNS
427 * Success: STATUS_SUCCESS.
428 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
430 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
431 PSECURITY_DESCRIPTOR lpsd,
432 DWORD rev)
434 if (rev!=SECURITY_DESCRIPTOR_REVISION)
435 return STATUS_UNKNOWN_REVISION;
436 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
437 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
438 return STATUS_SUCCESS;
441 /**************************************************************************
442 * RtlCopySecurityDescriptor [NTDLL.@]
444 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
446 * PARAMS
447 * pSourceSD [O] SD to copy from.
448 * pDestinationSD [I] Destination SD.
450 * RETURNS
451 * Success: STATUS_SUCCESS.
452 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
454 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
456 PSID Owner, Group;
457 PACL Dacl, Sacl;
458 DWORD length;
460 if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
462 SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
463 SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
465 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
466 return STATUS_UNKNOWN_REVISION;
468 *dst = *src;
469 if (src->Owner)
471 Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
472 length = RtlLengthSid( Owner );
473 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
475 if (src->Group)
477 Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
478 length = RtlLengthSid( Group );
479 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
481 if ((src->Control & SE_SACL_PRESENT) && src->Sacl)
483 Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
484 copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
486 if ((src->Control & SE_DACL_PRESENT) && src->Dacl)
488 Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
489 copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
492 else
494 SECURITY_DESCRIPTOR *src = pSourceSD;
495 SECURITY_DESCRIPTOR *dst = pDestinationSD;
497 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
498 return STATUS_UNKNOWN_REVISION;
500 *dst = *src;
501 if (src->Owner)
503 length = RtlLengthSid( src->Owner );
504 dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
505 RtlCopySid(length, dst->Owner, src->Owner);
507 if (src->Group)
509 length = RtlLengthSid( src->Group );
510 dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
511 RtlCopySid(length, dst->Group, src->Group);
513 if (src->Control & SE_SACL_PRESENT)
515 length = src->Sacl->AclSize;
516 dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
517 copy_acl(length, dst->Sacl, src->Sacl);
519 if (src->Control & SE_DACL_PRESENT)
521 length = src->Dacl->AclSize;
522 dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
523 copy_acl(length, dst->Dacl, src->Dacl);
527 return STATUS_SUCCESS;
530 /**************************************************************************
531 * RtlValidSecurityDescriptor [NTDLL.@]
533 * Determine if a SECURITY_DESCRIPTOR is valid.
535 * PARAMS
536 * SecurityDescriptor [I] Descriptor to check.
538 * RETURNS
539 * Success: STATUS_SUCCESS.
540 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
542 NTSTATUS WINAPI RtlValidSecurityDescriptor(
543 PSECURITY_DESCRIPTOR SecurityDescriptor)
545 if ( ! SecurityDescriptor )
546 return STATUS_INVALID_SECURITY_DESCR;
547 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
548 return STATUS_UNKNOWN_REVISION;
550 return STATUS_SUCCESS;
553 /**************************************************************************
554 * RtlLengthSecurityDescriptor [NTDLL.@]
556 ULONG WINAPI RtlLengthSecurityDescriptor(
557 PSECURITY_DESCRIPTOR pSecurityDescriptor)
559 ULONG size;
561 if ( pSecurityDescriptor == NULL )
562 return 0;
564 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
566 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
567 size = sizeof(*sd);
568 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
569 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
570 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
571 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
572 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
573 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
575 else
577 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
578 size = sizeof(*sd);
579 if (sd->Owner) size += RtlLengthSid( sd->Owner );
580 if (sd->Group) size += RtlLengthSid( sd->Group );
581 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
582 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
584 return size;
587 /******************************************************************************
588 * RtlGetDaclSecurityDescriptor [NTDLL.@]
591 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
592 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
593 OUT PBOOLEAN lpbDaclPresent,
594 OUT PACL *pDacl,
595 OUT PBOOLEAN lpbDaclDefaulted)
597 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
599 TRACE("(%p,%p,%p,%p)\n",
600 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
602 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
603 return STATUS_UNKNOWN_REVISION ;
605 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
607 if (lpsd->Control & SE_SELF_RELATIVE)
609 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
610 if (sdr->Dacl) *pDacl = (PACL)SELF_RELATIVE_FIELD( sdr, Dacl );
611 else *pDacl = NULL;
613 else *pDacl = lpsd->Dacl;
615 *lpbDaclDefaulted = (lpsd->Control & SE_DACL_DEFAULTED) != 0;
617 else
619 *pDacl = NULL;
620 *lpbDaclDefaulted = 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 (lpsd->Control & SE_SELF_RELATIVE)
681 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
682 if (sdr->Sacl) *pSacl = (PACL)SELF_RELATIVE_FIELD( sdr, Sacl );
683 else *pSacl = NULL;
685 else *pSacl = lpsd->Sacl;
687 *lpbSaclDefaulted = (lpsd->Control & SE_SACL_DEFAULTED) != 0;
689 return STATUS_SUCCESS;
692 /**************************************************************************
693 * RtlSetSaclSecurityDescriptor [NTDLL.@]
695 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
696 PSECURITY_DESCRIPTOR pSecurityDescriptor,
697 BOOLEAN saclpresent,
698 PACL sacl,
699 BOOLEAN sacldefaulted)
701 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
703 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
704 return STATUS_UNKNOWN_REVISION;
705 if (lpsd->Control & SE_SELF_RELATIVE)
706 return STATUS_INVALID_SECURITY_DESCR;
707 if (!saclpresent) {
708 lpsd->Control &= ~SE_SACL_PRESENT;
709 return 0;
711 lpsd->Control |= SE_SACL_PRESENT;
712 lpsd->Sacl = sacl;
713 if (sacldefaulted)
714 lpsd->Control |= SE_SACL_DEFAULTED;
715 else
716 lpsd->Control &= ~SE_SACL_DEFAULTED;
717 return STATUS_SUCCESS;
720 /**************************************************************************
721 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
723 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
724 PSECURITY_DESCRIPTOR pSecurityDescriptor,
725 PSID *Owner,
726 PBOOLEAN OwnerDefaulted)
728 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
730 if ( !lpsd || !Owner || !OwnerDefaulted )
731 return STATUS_INVALID_PARAMETER;
733 if ( lpsd->Control & SE_OWNER_DEFAULTED )
734 *OwnerDefaulted = TRUE;
735 else
736 *OwnerDefaulted = FALSE;
738 if (lpsd->Control & SE_SELF_RELATIVE)
740 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
741 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
742 else *Owner = NULL;
744 else
745 *Owner = lpsd->Owner;
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->Control & SE_SELF_RELATIVE)
816 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
817 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
818 else *Group = NULL;
820 else
821 *Group = lpsd->Group;
823 return STATUS_SUCCESS;
826 /**************************************************************************
827 * RtlMakeSelfRelativeSD [NTDLL.@]
829 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
830 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
831 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
832 IN OUT LPDWORD lpdwBufferLength)
834 DWORD offsetRel;
835 ULONG length;
836 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
837 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
839 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
840 lpdwBufferLength ? *lpdwBufferLength: -1);
842 if (!lpdwBufferLength || !pAbs)
843 return STATUS_INVALID_PARAMETER;
845 length = RtlLengthSecurityDescriptor(pAbs);
846 if (*lpdwBufferLength < length)
848 *lpdwBufferLength = length;
849 return STATUS_BUFFER_TOO_SMALL;
852 if (!pRel)
853 return STATUS_INVALID_PARAMETER;
855 if (pAbs->Control & SE_SELF_RELATIVE)
857 memcpy(pRel, pAbs, length);
858 return STATUS_SUCCESS;
861 pRel->Revision = pAbs->Revision;
862 pRel->Sbz1 = pAbs->Sbz1;
863 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
865 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
866 if (pAbs->Owner)
868 pRel->Owner = offsetRel;
869 length = RtlLengthSid(pAbs->Owner);
870 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
871 offsetRel += length;
873 else
875 pRel->Owner = 0;
878 if (pAbs->Group)
880 pRel->Group = offsetRel;
881 length = RtlLengthSid(pAbs->Group);
882 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
883 offsetRel += length;
885 else
887 pRel->Group = 0;
890 if (pAbs->Sacl)
892 pRel->Sacl = offsetRel;
893 length = pAbs->Sacl->AclSize;
894 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
895 offsetRel += length;
897 else
899 pRel->Sacl = 0;
902 if (pAbs->Dacl)
904 pRel->Dacl = offsetRel;
905 length = pAbs->Dacl->AclSize;
906 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
908 else
910 pRel->Dacl = 0;
913 return STATUS_SUCCESS;
917 /**************************************************************************
918 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
920 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
921 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
922 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
923 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
924 OUT PACL pDacl,
925 OUT LPDWORD lpdwDaclSize,
926 OUT PACL pSacl,
927 OUT LPDWORD lpdwSaclSize,
928 OUT PSID pOwner,
929 OUT LPDWORD lpdwOwnerSize,
930 OUT PSID pPrimaryGroup,
931 OUT LPDWORD lpdwPrimaryGroupSize)
933 NTSTATUS status = STATUS_SUCCESS;
934 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
935 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
937 if (!pRel ||
938 !lpdwAbsoluteSecurityDescriptorSize ||
939 !lpdwDaclSize ||
940 !lpdwSaclSize ||
941 !lpdwOwnerSize ||
942 !lpdwPrimaryGroupSize ||
943 ~pRel->Control & SE_SELF_RELATIVE)
944 return STATUS_INVALID_PARAMETER;
946 /* Confirm buffers are sufficiently large */
947 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
949 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
950 status = STATUS_BUFFER_TOO_SMALL;
953 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
954 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
956 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
957 status = STATUS_BUFFER_TOO_SMALL;
960 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
961 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
963 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
964 status = STATUS_BUFFER_TOO_SMALL;
967 if (pRel->Owner &&
968 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
970 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
971 status = STATUS_BUFFER_TOO_SMALL;
974 if (pRel->Group &&
975 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
977 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
978 status = STATUS_BUFFER_TOO_SMALL;
981 if (status != STATUS_SUCCESS)
982 return status;
984 /* Copy structures, and clear the ones we don't set */
985 pAbs->Revision = pRel->Revision;
986 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
987 pAbs->Sacl = NULL;
988 pAbs->Dacl = NULL;
989 pAbs->Owner = NULL;
990 pAbs->Group = NULL;
992 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
994 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
996 memcpy(pSacl, pAcl, pAcl->AclSize);
997 pAbs->Sacl = pSacl;
1000 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1002 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1003 memcpy(pDacl, pAcl, pAcl->AclSize);
1004 pAbs->Dacl = pDacl;
1007 if (pRel->Owner)
1009 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1010 memcpy(pOwner, psid, RtlLengthSid(psid));
1011 pAbs->Owner = pOwner;
1014 if (pRel->Group)
1016 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1017 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1018 pAbs->Group = pPrimaryGroup;
1021 return status;
1024 /******************************************************************************
1025 * RtlGetControlSecurityDescriptor (NTDLL.@)
1027 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1028 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1029 PSECURITY_DESCRIPTOR_CONTROL pControl,
1030 LPDWORD lpdwRevision)
1032 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1034 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1036 *lpdwRevision = lpsd->Revision;
1038 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1039 return STATUS_UNKNOWN_REVISION;
1041 *pControl = lpsd->Control;
1043 return STATUS_SUCCESS;
1046 /******************************************************************************
1047 * RtlSetControlSecurityDescriptor (NTDLL.@)
1049 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1050 PSECURITY_DESCRIPTOR SecurityDescriptor,
1051 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1052 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1054 SECURITY_DESCRIPTOR_CONTROL const immutable
1055 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1056 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1057 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1058 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1061 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1063 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1064 ControlBitsOfInterest, ControlBitsToSet);
1066 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1067 return STATUS_INVALID_PARAMETER;
1069 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1070 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1072 return STATUS_SUCCESS;
1076 /**************************************************************************
1077 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1079 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1080 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1081 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1082 PULONG BufferLength)
1084 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1086 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1087 SelfRelativeSecurityDescriptor, BufferLength);
1089 if (abs->Control & SE_SELF_RELATIVE)
1090 return STATUS_BAD_DESCRIPTOR_FORMAT;
1092 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1093 SelfRelativeSecurityDescriptor, BufferLength);
1098 * access control list's
1101 /**************************************************************************
1102 * RtlCreateAcl [NTDLL.@]
1104 * NOTES
1105 * This should return NTSTATUS
1107 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1109 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1111 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1112 return STATUS_INVALID_PARAMETER;
1113 if (size<sizeof(ACL))
1114 return STATUS_BUFFER_TOO_SMALL;
1115 if (size>0xFFFF)
1116 return STATUS_INVALID_PARAMETER;
1118 memset(acl,'\0',sizeof(ACL));
1119 acl->AclRevision = rev;
1120 acl->AclSize = size;
1121 acl->AceCount = 0;
1122 return STATUS_SUCCESS;
1125 /**************************************************************************
1126 * RtlFirstFreeAce [NTDLL.@]
1127 * looks for the AceCount+1 ACE, and if it is still within the alloced
1128 * ACL, return a pointer to it
1130 BOOLEAN WINAPI RtlFirstFreeAce(
1131 PACL acl,
1132 PACE_HEADER *x)
1134 PACE_HEADER ace;
1135 int i;
1137 *x = 0;
1138 ace = (PACE_HEADER)(acl+1);
1139 for (i=0;i<acl->AceCount;i++) {
1140 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1141 return 0;
1142 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1144 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1145 return 0;
1146 *x = ace;
1147 return 1;
1150 /**************************************************************************
1151 * RtlAddAce [NTDLL.@]
1153 NTSTATUS WINAPI RtlAddAce(
1154 PACL acl,
1155 DWORD rev,
1156 DWORD xnrofaces,
1157 PACE_HEADER acestart,
1158 DWORD acelen)
1160 PACE_HEADER ace,targetace;
1161 int nrofaces;
1163 if (acl->AclRevision != ACL_REVISION)
1164 return STATUS_INVALID_PARAMETER;
1165 if (!RtlFirstFreeAce(acl,&targetace))
1166 return STATUS_INVALID_PARAMETER;
1167 nrofaces=0;ace=acestart;
1168 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1169 nrofaces++;
1170 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1172 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1173 return STATUS_INVALID_PARAMETER;
1174 memcpy(targetace,acestart,acelen);
1175 acl->AceCount+=nrofaces;
1176 return STATUS_SUCCESS;
1179 /**************************************************************************
1180 * RtlDeleteAce [NTDLL.@]
1182 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1184 NTSTATUS status;
1185 PACE_HEADER pAce;
1187 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1189 if (STATUS_SUCCESS == status)
1191 PACE_HEADER pcAce;
1192 DWORD len = 0;
1194 /* skip over the ACE we are deleting */
1195 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1196 dwAceIndex++;
1198 /* calculate the length of the rest */
1199 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1201 len += pcAce->AceSize;
1202 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1205 /* slide them all backwards */
1206 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1207 pAcl->AceCount--;
1210 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1212 return status;
1215 /******************************************************************************
1216 * RtlAddAccessAllowedAce [NTDLL.@]
1218 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1219 IN OUT PACL pAcl,
1220 IN DWORD dwAceRevision,
1221 IN DWORD AccessMask,
1222 IN PSID pSid)
1224 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1227 /******************************************************************************
1228 * RtlAddAccessAllowedAceEx [NTDLL.@]
1230 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1231 IN OUT PACL pAcl,
1232 IN DWORD dwAceRevision,
1233 IN DWORD AceFlags,
1234 IN DWORD AccessMask,
1235 IN PSID pSid)
1237 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1239 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1240 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1243 /******************************************************************************
1244 * RtlAddAccessDeniedAce [NTDLL.@]
1246 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1247 IN OUT PACL pAcl,
1248 IN DWORD dwAceRevision,
1249 IN DWORD AccessMask,
1250 IN PSID pSid)
1252 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1255 /******************************************************************************
1256 * RtlAddAccessDeniedAceEx [NTDLL.@]
1258 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1259 IN OUT PACL pAcl,
1260 IN DWORD dwAceRevision,
1261 IN DWORD AceFlags,
1262 IN DWORD AccessMask,
1263 IN PSID pSid)
1265 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1267 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1268 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1271 /**************************************************************************
1272 * RtlAddAuditAccessAce [NTDLL.@]
1274 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1275 IN OUT PACL pAcl,
1276 IN DWORD dwAceRevision,
1277 IN DWORD dwAceFlags,
1278 IN DWORD dwAccessMask,
1279 IN PSID pSid,
1280 IN BOOL bAuditSuccess,
1281 IN BOOL bAuditFailure)
1283 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1284 pSid,bAuditSuccess,bAuditFailure);
1286 if (bAuditSuccess)
1287 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1289 if (bAuditFailure)
1290 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1292 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1293 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1296 /**************************************************************************
1297 * RtlAddAuditAccessAce [NTDLL.@]
1299 NTSTATUS WINAPI RtlAddAuditAccessAce(
1300 IN OUT PACL pAcl,
1301 IN DWORD dwAceRevision,
1302 IN DWORD dwAccessMask,
1303 IN PSID pSid,
1304 IN BOOL bAuditSuccess,
1305 IN BOOL bAuditFailure)
1307 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1310 /******************************************************************************
1311 * RtlValidAcl [NTDLL.@]
1313 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1315 BOOLEAN ret;
1316 TRACE("(%p)\n", pAcl);
1318 __TRY
1320 PACE_HEADER ace;
1321 int i;
1323 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1324 pAcl->AclRevision > MAX_ACL_REVISION)
1325 ret = FALSE;
1326 else
1328 ace = (PACE_HEADER)(pAcl+1);
1329 ret = TRUE;
1330 for (i=0;i<=pAcl->AceCount;i++)
1332 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1334 ret = FALSE;
1335 break;
1337 if (i != pAcl->AceCount)
1338 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1342 __EXCEPT_PAGE_FAULT
1344 WARN("(%p): invalid pointer!\n", pAcl);
1345 return 0;
1347 __ENDTRY
1348 return ret;
1351 /******************************************************************************
1352 * RtlGetAce [NTDLL.@]
1354 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1356 PACE_HEADER ace;
1358 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1360 if (dwAceIndex >= pAcl->AceCount)
1361 return STATUS_INVALID_PARAMETER;
1363 ace = (PACE_HEADER)(pAcl + 1);
1364 for (;dwAceIndex;dwAceIndex--)
1365 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1367 *pAce = ace;
1369 return STATUS_SUCCESS;
1373 * misc
1376 /******************************************************************************
1377 * RtlAdjustPrivilege [NTDLL.@]
1379 * Enables or disables a privilege from the calling thread or process.
1381 * PARAMS
1382 * Privilege [I] Privilege index to change.
1383 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1384 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1385 * Enabled [O] Whether privilege was previously enabled or disabled.
1387 * RETURNS
1388 * Success: STATUS_SUCCESS.
1389 * Failure: NTSTATUS code.
1391 * SEE ALSO
1392 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1395 NTSTATUS WINAPI
1396 RtlAdjustPrivilege(ULONG Privilege,
1397 BOOLEAN Enable,
1398 BOOLEAN CurrentThread,
1399 PBOOLEAN Enabled)
1401 TOKEN_PRIVILEGES NewState;
1402 TOKEN_PRIVILEGES OldState;
1403 ULONG ReturnLength;
1404 HANDLE TokenHandle;
1405 NTSTATUS Status;
1407 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1408 CurrentThread ? "TRUE" : "FALSE", Enabled);
1410 if (CurrentThread)
1412 Status = NtOpenThreadToken(GetCurrentThread(),
1413 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1414 FALSE,
1415 &TokenHandle);
1417 else
1419 Status = NtOpenProcessToken(GetCurrentProcess(),
1420 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1421 &TokenHandle);
1424 if (!NT_SUCCESS(Status))
1426 WARN("Retrieving token handle failed (Status %x)\n", Status);
1427 return Status;
1430 OldState.PrivilegeCount = 1;
1432 NewState.PrivilegeCount = 1;
1433 NewState.Privileges[0].Luid.LowPart = Privilege;
1434 NewState.Privileges[0].Luid.HighPart = 0;
1435 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1437 Status = NtAdjustPrivilegesToken(TokenHandle,
1438 FALSE,
1439 &NewState,
1440 sizeof(TOKEN_PRIVILEGES),
1441 &OldState,
1442 &ReturnLength);
1443 NtClose (TokenHandle);
1444 if (Status == STATUS_NOT_ALL_ASSIGNED)
1446 TRACE("Failed to assign all privileges\n");
1447 return STATUS_PRIVILEGE_NOT_HELD;
1449 if (!NT_SUCCESS(Status))
1451 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1452 return Status;
1455 if (OldState.PrivilegeCount == 0)
1456 *Enabled = Enable;
1457 else
1458 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1460 return STATUS_SUCCESS;
1463 /******************************************************************************
1464 * RtlImpersonateSelf [NTDLL.@]
1466 * Makes an impersonation token that represents the process user and assigns
1467 * to the current thread.
1469 * PARAMS
1470 * ImpersonationLevel [I] Level at which to impersonate.
1472 * RETURNS
1473 * Success: STATUS_SUCCESS.
1474 * Failure: NTSTATUS code.
1476 NTSTATUS WINAPI
1477 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1479 NTSTATUS Status;
1480 OBJECT_ATTRIBUTES ObjectAttributes;
1481 HANDLE ProcessToken;
1482 HANDLE ImpersonationToken;
1484 TRACE("(%08x)\n", ImpersonationLevel);
1486 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1487 &ProcessToken);
1488 if (Status != STATUS_SUCCESS)
1489 return Status;
1491 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1493 Status = NtDuplicateToken( ProcessToken,
1494 TOKEN_IMPERSONATE,
1495 &ObjectAttributes,
1496 ImpersonationLevel,
1497 TokenImpersonation,
1498 &ImpersonationToken );
1499 if (Status != STATUS_SUCCESS)
1501 NtClose( ProcessToken );
1502 return Status;
1505 Status = NtSetInformationThread( GetCurrentThread(),
1506 ThreadImpersonationToken,
1507 &ImpersonationToken,
1508 sizeof(ImpersonationToken) );
1510 NtClose( ImpersonationToken );
1511 NtClose( ProcessToken );
1513 return Status;
1516 /******************************************************************************
1517 * NtAccessCheck [NTDLL.@]
1518 * ZwAccessCheck [NTDLL.@]
1520 * Checks that a user represented by a token is allowed to access an object
1521 * represented by a security descriptor.
1523 * PARAMS
1524 * SecurityDescriptor [I] The security descriptor of the object to check.
1525 * ClientToken [I] Token of the user accessing the object.
1526 * DesiredAccess [I] The desired access to the object.
1527 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1528 * PrivilegeSet [I/O] Privileges used during the access check.
1529 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1530 * GrantedAccess [O] The actual access rights granted.
1531 * AccessStatus [O] The status of the access check.
1533 * RETURNS
1534 * NTSTATUS code.
1536 * NOTES
1537 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1538 * the maximum access rights allowed by the SD and returns them in
1539 * GrantedAccess.
1540 * The SecurityDescriptor must have a valid owner and groups present,
1541 * otherwise the function will fail.
1543 NTSTATUS WINAPI
1544 NtAccessCheck(
1545 PSECURITY_DESCRIPTOR SecurityDescriptor,
1546 HANDLE ClientToken,
1547 ACCESS_MASK DesiredAccess,
1548 PGENERIC_MAPPING GenericMapping,
1549 PPRIVILEGE_SET PrivilegeSet,
1550 PULONG ReturnLength,
1551 PULONG GrantedAccess,
1552 NTSTATUS *AccessStatus)
1554 NTSTATUS status;
1556 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1557 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1558 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1560 if (!PrivilegeSet || !ReturnLength)
1561 return STATUS_ACCESS_VIOLATION;
1563 SERVER_START_REQ( access_check )
1565 struct security_descriptor sd;
1566 PSID owner;
1567 PSID group;
1568 PACL sacl;
1569 PACL dacl;
1570 BOOLEAN defaulted, present;
1571 DWORD revision;
1572 SECURITY_DESCRIPTOR_CONTROL control;
1574 req->handle = wine_server_obj_handle( ClientToken );
1575 req->desired_access = DesiredAccess;
1576 req->mapping_read = GenericMapping->GenericRead;
1577 req->mapping_write = GenericMapping->GenericWrite;
1578 req->mapping_execute = GenericMapping->GenericExecute;
1579 req->mapping_all = GenericMapping->GenericAll;
1581 /* marshal security descriptor */
1582 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1583 sd.control = control & ~SE_SELF_RELATIVE;
1584 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1585 sd.owner_len = RtlLengthSid( owner );
1586 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1587 sd.group_len = RtlLengthSid( group );
1588 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1589 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1590 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1591 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1593 wine_server_add_data( req, &sd, sizeof(sd) );
1594 wine_server_add_data( req, owner, sd.owner_len );
1595 wine_server_add_data( req, group, sd.group_len );
1596 wine_server_add_data( req, sacl, sd.sacl_len );
1597 wine_server_add_data( req, dacl, sd.dacl_len );
1599 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1601 status = wine_server_call( req );
1603 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1604 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1606 if (status == STATUS_SUCCESS)
1608 *AccessStatus = reply->access_status;
1609 *GrantedAccess = reply->access_granted;
1612 SERVER_END_REQ;
1614 return status;
1617 /******************************************************************************
1618 * NtSetSecurityObject [NTDLL.@]
1619 * ZwSetSecurityObject [NTDLL.@]
1621 * Sets specified parts of the object's security descriptor.
1623 * PARAMS
1624 * Handle [I] Handle to the object to change security descriptor of.
1625 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1626 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1628 * RETURNS
1629 * NTSTATUS code.
1632 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1633 SECURITY_INFORMATION SecurityInformation,
1634 PSECURITY_DESCRIPTOR SecurityDescriptor)
1636 NTSTATUS status;
1637 struct security_descriptor sd;
1638 PACL dacl = NULL, sacl = NULL;
1639 PSID owner = NULL, group = NULL;
1640 BOOLEAN defaulted, present;
1641 DWORD revision;
1642 SECURITY_DESCRIPTOR_CONTROL control;
1644 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1646 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1648 memset( &sd, 0, sizeof(sd) );
1649 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1650 if (status != STATUS_SUCCESS) return status;
1651 sd.control = control & ~SE_SELF_RELATIVE;
1653 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1655 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1656 if (status != STATUS_SUCCESS) return status;
1657 if (!(sd.owner_len = RtlLengthSid( owner )))
1658 return STATUS_INVALID_SECURITY_DESCR;
1661 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1663 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1664 if (status != STATUS_SUCCESS) return status;
1665 if (!(sd.group_len = RtlLengthSid( group )))
1666 return STATUS_INVALID_SECURITY_DESCR;
1669 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1671 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1672 if (status != STATUS_SUCCESS) return status;
1673 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1674 sd.control |= SE_SACL_PRESENT;
1677 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1679 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1680 if (status != STATUS_SUCCESS) return status;
1681 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1682 sd.control |= SE_DACL_PRESENT;
1685 SERVER_START_REQ( set_security_object )
1687 req->handle = wine_server_obj_handle( Handle );
1688 req->security_info = SecurityInformation;
1690 wine_server_add_data( req, &sd, sizeof(sd) );
1691 wine_server_add_data( req, owner, sd.owner_len );
1692 wine_server_add_data( req, group, sd.group_len );
1693 wine_server_add_data( req, sacl, sd.sacl_len );
1694 wine_server_add_data( req, dacl, sd.dacl_len );
1695 status = wine_server_call( req );
1697 SERVER_END_REQ;
1699 return status;
1702 /******************************************************************************
1703 * RtlConvertSidToUnicodeString (NTDLL.@)
1705 * The returned SID is used to access the USER registry hive usually
1707 * the native function returns something like
1708 * "S-1-5-21-0000000000-000000000-0000000000-500";
1710 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1711 PUNICODE_STRING String,
1712 PSID pSid,
1713 BOOLEAN AllocateString)
1715 static const WCHAR formatW[] = {'-','%','u',0};
1716 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1717 WCHAR *p = buffer;
1718 const SID *sid = pSid;
1719 DWORD i, len;
1721 *p++ = 'S';
1722 p += sprintfW( p, formatW, sid->Revision );
1723 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1724 sid->IdentifierAuthority.Value[4] ),
1725 MAKEWORD( sid->IdentifierAuthority.Value[3],
1726 sid->IdentifierAuthority.Value[2] )));
1727 for (i = 0; i < sid->SubAuthorityCount; i++)
1728 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1730 len = (p + 1 - buffer) * sizeof(WCHAR);
1732 String->Length = len - sizeof(WCHAR);
1733 if (AllocateString)
1735 String->MaximumLength = len;
1736 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1737 return STATUS_NO_MEMORY;
1739 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1741 memcpy( String->Buffer, buffer, len );
1742 return STATUS_SUCCESS;
1745 /******************************************************************************
1746 * RtlQueryInformationAcl (NTDLL.@)
1748 NTSTATUS WINAPI RtlQueryInformationAcl(
1749 PACL pAcl,
1750 LPVOID pAclInformation,
1751 DWORD nAclInformationLength,
1752 ACL_INFORMATION_CLASS dwAclInformationClass)
1754 NTSTATUS status = STATUS_SUCCESS;
1756 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1757 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1759 switch (dwAclInformationClass)
1761 case AclRevisionInformation:
1763 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1765 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1766 status = STATUS_INVALID_PARAMETER;
1767 else
1768 paclrev->AclRevision = pAcl->AclRevision;
1770 break;
1773 case AclSizeInformation:
1775 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1777 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1778 status = STATUS_INVALID_PARAMETER;
1779 else
1781 paclsize->AceCount = pAcl->AceCount;
1782 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1783 if (pAcl->AclSize < paclsize->AclBytesInUse)
1785 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1786 paclsize->AclBytesFree = 0;
1787 paclsize->AclBytesInUse = pAcl->AclSize;
1789 else
1790 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1793 break;
1796 default:
1797 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1798 status = STATUS_INVALID_PARAMETER;
1801 return status;