Remove unused NONAMELESS defines.
[wine.git] / dlls / ntdll / sec.c
blob4188faafb4ba73864504767d579f0055c7e30793
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 <stdarg.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <ctype.h>
27 #include <math.h>
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "windef.h"
32 #include "ntdll_misc.h"
33 #include "wine/exception.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
38 #define SELF_RELATIVE_FIELD(sd,field) ((BYTE *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
40 static const SID world_sid = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
41 static const DWORD world_access_acl_size = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(world_sid) - sizeof(DWORD);
43 static void get_world_access_acl( PACL acl )
45 PACCESS_ALLOWED_ACE ace = (PACCESS_ALLOWED_ACE)(acl + 1);
47 acl->AclRevision = ACL_REVISION;
48 acl->Sbz1 = 0;
49 acl->AclSize = world_access_acl_size;
50 acl->AceCount = 1;
51 acl->Sbz2 = 0;
52 ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
53 ace->Header.AceFlags = CONTAINER_INHERIT_ACE;
54 ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + sizeof(world_sid) - sizeof(DWORD);
55 ace->Mask = 0xf3ffffff; /* Everything except reserved bits */
56 memcpy( &ace->SidStart, &world_sid, sizeof(world_sid) );
59 /* helper function to retrieve active length of an ACL */
60 static size_t acl_bytesInUse(PACL pAcl)
62 int i;
63 size_t bytesInUse = sizeof(ACL);
64 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
65 for (i = 0; i < pAcl->AceCount; i++)
67 bytesInUse += ace->AceSize;
68 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
70 return bytesInUse;
73 /* helper function to copy an ACL */
74 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
76 DWORD size;
78 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
79 return FALSE;
81 size = pSourceAcl->AclSize;
82 if (nDestinationAclLength < size)
83 return FALSE;
85 memmove(pDestinationAcl, pSourceAcl, size);
86 return TRUE;
89 /* generically adds an ACE to an ACL */
90 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
91 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
93 ACE_HEADER *pAceHeader;
94 DWORD dwLengthSid;
95 DWORD dwAceSize;
96 DWORD *pAccessMask;
97 DWORD *pSidStart;
99 if (!RtlValidSid(pSid))
100 return STATUS_INVALID_SID;
102 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
103 return STATUS_REVISION_MISMATCH;
105 if (!RtlValidAcl(pAcl))
106 return STATUS_INVALID_ACL;
108 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
109 return STATUS_INVALID_ACL;
111 if (!pAceHeader)
112 return STATUS_ALLOTTED_SPACE_EXCEEDED;
114 /* calculate generic size of the ACE */
115 dwLengthSid = RtlLengthSid(pSid);
116 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
117 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
118 return STATUS_ALLOTTED_SPACE_EXCEEDED;
120 /* fill the new ACE */
121 pAceHeader->AceType = dwAceType;
122 pAceHeader->AceFlags = dwAceFlags;
123 pAceHeader->AceSize = dwAceSize;
125 /* skip past the ACE_HEADER of the ACE */
126 pAccessMask = (DWORD *)(pAceHeader + 1);
127 *pAccessMask = dwAccessMask;
129 /* skip past ACE->Mask */
130 pSidStart = pAccessMask + 1;
131 RtlCopySid(dwLengthSid, pSidStart, pSid);
133 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
134 pAcl->AceCount++;
136 return STATUS_SUCCESS;
140 * SID FUNCTIONS
143 /******************************************************************************
144 * RtlAllocateAndInitializeSid [NTDLL.@]
147 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
148 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
149 BYTE nSubAuthorityCount,
150 DWORD nSubAuthority0, DWORD nSubAuthority1,
151 DWORD nSubAuthority2, DWORD nSubAuthority3,
152 DWORD nSubAuthority4, DWORD nSubAuthority5,
153 DWORD nSubAuthority6, DWORD nSubAuthority7,
154 PSID *pSid )
156 SID *tmp_sid;
158 TRACE("(%p, 0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p)\n",
159 pIdentifierAuthority,nSubAuthorityCount,
160 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
161 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
163 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
165 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
166 RtlLengthRequiredSid(nSubAuthorityCount))))
167 return STATUS_NO_MEMORY;
169 tmp_sid->Revision = SID_REVISION;
171 if (pIdentifierAuthority)
172 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
173 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
175 switch( nSubAuthorityCount )
177 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
178 /* fall through */
179 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
180 /* fall through */
181 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
182 /* fall through */
183 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
184 /* fall through */
185 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
186 /* fall through */
187 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
188 /* fall through */
189 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
190 /* fall through */
191 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
192 break;
194 *pSid = tmp_sid;
195 return STATUS_SUCCESS;
198 /******************************************************************************
199 * RtlEqualSid [NTDLL.@]
201 * Determine if two SIDs are equal.
203 * PARAMS
204 * pSid1 [I] Source SID
205 * pSid2 [I] SID to compare with
207 * RETURNS
208 * TRUE, if pSid1 is equal to pSid2,
209 * FALSE otherwise.
211 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
213 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
214 return FALSE;
216 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
217 return FALSE;
219 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
220 return FALSE;
222 return TRUE;
225 /******************************************************************************
226 * RtlEqualPrefixSid [NTDLL.@]
228 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
230 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
231 return FALSE;
233 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
234 return FALSE;
236 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
237 return FALSE;
239 return TRUE;
243 /******************************************************************************
244 * RtlFreeSid [NTDLL.@]
246 * Free the resources used by a SID.
248 * PARAMS
249 * pSid [I] SID to Free.
251 * RETURNS
252 * STATUS_SUCCESS.
254 DWORD WINAPI RtlFreeSid(PSID pSid)
256 TRACE("(%p)\n", pSid);
257 RtlFreeHeap( GetProcessHeap(), 0, pSid );
258 return STATUS_SUCCESS;
261 /**************************************************************************
262 * RtlLengthRequiredSid [NTDLL.@]
264 * Determine the amount of memory a SID will use
266 * PARAMS
267 * nrofsubauths [I] Number of Sub Authorities in the SID.
269 * RETURNS
270 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
272 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
274 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
277 /**************************************************************************
278 * RtlLengthSid [NTDLL.@]
280 * Determine the amount of memory a SID is using
282 * PARAMS
283 * pSid [I] SID to get the size of.
285 * RETURNS
286 * The size, in bytes, of pSid.
288 DWORD WINAPI RtlLengthSid(PSID pSid)
290 TRACE("sid=%p\n",pSid);
291 if (!pSid) return 0;
292 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
295 /**************************************************************************
296 * RtlInitializeSid [NTDLL.@]
298 NTSTATUS WINAPI RtlInitializeSid(
299 PSID pSid,
300 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
301 BYTE nSubAuthorityCount)
303 int i;
304 SID* pisid=pSid;
306 if (nSubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
307 return STATUS_INVALID_PARAMETER;
309 pisid->Revision = SID_REVISION;
310 pisid->SubAuthorityCount = nSubAuthorityCount;
311 if (pIdentifierAuthority)
312 pisid->IdentifierAuthority = *pIdentifierAuthority;
314 for (i = 0; i < nSubAuthorityCount; i++)
315 *RtlSubAuthoritySid(pSid, i) = 0;
317 return STATUS_SUCCESS;
320 /**************************************************************************
321 * RtlSubAuthoritySid [NTDLL.@]
323 * Return the Sub Authority of a SID
325 * PARAMS
326 * pSid [I] SID to get the Sub Authority from.
327 * nSubAuthority [I] Sub Authority number.
329 * RETURNS
330 * A pointer to The Sub Authority value of pSid.
332 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
334 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
337 /**************************************************************************
338 * RtlIdentifierAuthoritySid [NTDLL.@]
340 * Return the Identifier Authority of a SID.
342 * PARAMS
343 * pSid [I] SID to get the Identifier Authority from.
345 * RETURNS
346 * A pointer to the Identifier Authority value of pSid.
348 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
350 return &(((SID*)pSid)->IdentifierAuthority);
353 /**************************************************************************
354 * RtlSubAuthorityCountSid [NTDLL.@]
356 * Get the number of Sub Authorities in a SID.
358 * PARAMS
359 * pSid [I] SID to get the count from.
361 * RETURNS
362 * A pointer to the Sub Authority count of pSid.
364 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
366 return &(((SID*)pSid)->SubAuthorityCount);
369 /**************************************************************************
370 * RtlCopySid [NTDLL.@]
372 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
374 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
375 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
376 return FALSE;
378 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
379 return FALSE;
381 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
382 return TRUE;
384 /******************************************************************************
385 * RtlValidSid [NTDLL.@]
387 * Determine if a SID is valid.
389 * PARAMS
390 * pSid [I] SID to check
392 * RETURNS
393 * TRUE if pSid is valid,
394 * FALSE otherwise.
396 BOOLEAN WINAPI RtlValidSid( PSID pSid )
398 BOOL ret;
399 __TRY
401 ret = TRUE;
402 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
403 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
405 ret = FALSE;
408 __EXCEPT_PAGE_FAULT
410 WARN("(%p): invalid pointer!\n", pSid);
411 return FALSE;
413 __ENDTRY
414 return ret;
419 * security descriptor functions
422 /**************************************************************************
423 * RtlCreateSecurityDescriptor [NTDLL.@]
425 * Initialise a SECURITY_DESCRIPTOR.
427 * PARAMS
428 * lpsd [O] Descriptor to initialise.
429 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
431 * RETURNS
432 * Success: STATUS_SUCCESS.
433 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
435 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
436 PSECURITY_DESCRIPTOR lpsd,
437 DWORD rev)
439 if (rev!=SECURITY_DESCRIPTOR_REVISION)
440 return STATUS_UNKNOWN_REVISION;
441 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
442 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
443 return STATUS_SUCCESS;
446 /**************************************************************************
447 * RtlCopySecurityDescriptor [NTDLL.@]
449 * Copies an absolute or self-relative SECURITY_DESCRIPTOR.
451 * PARAMS
452 * pSourceSD [O] SD to copy from.
453 * pDestinationSD [I] Destination SD.
455 * RETURNS
456 * Success: STATUS_SUCCESS.
457 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
459 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
461 PSID Owner, Group;
462 PACL Dacl, Sacl;
463 DWORD length;
465 if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
467 SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
468 SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
470 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
471 return STATUS_UNKNOWN_REVISION;
473 *dst = *src;
474 if (src->Owner)
476 Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
477 length = RtlLengthSid( Owner );
478 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
480 if (src->Group)
482 Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
483 length = RtlLengthSid( Group );
484 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
486 if ((src->Control & SE_SACL_PRESENT) && src->Sacl)
488 Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
489 copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
491 if ((src->Control & SE_DACL_PRESENT) && src->Dacl)
493 Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
494 copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
497 else
499 SECURITY_DESCRIPTOR *src = pSourceSD;
500 SECURITY_DESCRIPTOR *dst = pDestinationSD;
502 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
503 return STATUS_UNKNOWN_REVISION;
505 *dst = *src;
506 if (src->Owner)
508 length = RtlLengthSid( src->Owner );
509 dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
510 RtlCopySid(length, dst->Owner, src->Owner);
512 if (src->Group)
514 length = RtlLengthSid( src->Group );
515 dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
516 RtlCopySid(length, dst->Group, src->Group);
518 if (src->Control & SE_SACL_PRESENT)
520 length = src->Sacl->AclSize;
521 dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
522 copy_acl(length, dst->Sacl, src->Sacl);
524 if (src->Control & SE_DACL_PRESENT)
526 length = src->Dacl->AclSize;
527 dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
528 copy_acl(length, dst->Dacl, src->Dacl);
532 return STATUS_SUCCESS;
535 /**************************************************************************
536 * RtlValidSecurityDescriptor [NTDLL.@]
538 BOOLEAN WINAPI RtlValidSecurityDescriptor(PSECURITY_DESCRIPTOR descriptor)
540 SECURITY_DESCRIPTOR *sd = descriptor;
541 return sd && sd->Revision == SECURITY_DESCRIPTOR_REVISION;
544 /**************************************************************************
545 * RtlValidRelativeSecurityDescriptor [NTDLL.@]
547 BOOLEAN WINAPI RtlValidRelativeSecurityDescriptor(PSECURITY_DESCRIPTOR descriptor,
548 ULONG length, SECURITY_INFORMATION info)
550 FIXME("%p,%lu,%ld: semi-stub\n", descriptor, length, info);
551 return RtlValidSecurityDescriptor(descriptor) == STATUS_SUCCESS;
554 /**************************************************************************
555 * RtlLengthSecurityDescriptor [NTDLL.@]
557 ULONG WINAPI RtlLengthSecurityDescriptor(
558 PSECURITY_DESCRIPTOR pSecurityDescriptor)
560 ULONG size;
562 if ( pSecurityDescriptor == NULL )
563 return 0;
565 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
567 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
568 size = sizeof(*sd);
569 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
570 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
571 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
572 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
573 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
574 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
576 else
578 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
579 size = sizeof(*sd);
580 if (sd->Owner) size += RtlLengthSid( sd->Owner );
581 if (sd->Group) size += RtlLengthSid( sd->Group );
582 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
583 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
585 return size;
588 /******************************************************************************
589 * RtlGetDaclSecurityDescriptor [NTDLL.@]
592 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
593 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
594 OUT PBOOLEAN lpbDaclPresent,
595 OUT PACL *pDacl,
596 OUT PBOOLEAN lpbDaclDefaulted)
598 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
600 TRACE("(%p,%p,%p,%p)\n",
601 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
603 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
604 return STATUS_UNKNOWN_REVISION ;
606 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
608 if (lpsd->Control & SE_SELF_RELATIVE)
610 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
611 if (sdr->Dacl) *pDacl = (PACL)SELF_RELATIVE_FIELD( sdr, Dacl );
612 else *pDacl = NULL;
614 else *pDacl = lpsd->Dacl;
616 *lpbDaclDefaulted = (lpsd->Control & SE_DACL_DEFAULTED) != 0;
618 else
620 *pDacl = NULL;
621 *lpbDaclDefaulted = 0;
624 return STATUS_SUCCESS;
627 /**************************************************************************
628 * RtlSetDaclSecurityDescriptor [NTDLL.@]
630 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
631 PSECURITY_DESCRIPTOR pSecurityDescriptor,
632 BOOLEAN daclpresent,
633 PACL dacl,
634 BOOLEAN dacldefaulted )
636 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
638 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
639 return STATUS_UNKNOWN_REVISION;
640 if (lpsd->Control & SE_SELF_RELATIVE)
641 return STATUS_INVALID_SECURITY_DESCR;
643 if (!daclpresent)
645 lpsd->Control &= ~SE_DACL_PRESENT;
646 return STATUS_SUCCESS;
649 lpsd->Control |= SE_DACL_PRESENT;
650 lpsd->Dacl = dacl;
652 if (dacldefaulted)
653 lpsd->Control |= SE_DACL_DEFAULTED;
654 else
655 lpsd->Control &= ~SE_DACL_DEFAULTED;
657 return STATUS_SUCCESS;
660 /******************************************************************************
661 * RtlGetSaclSecurityDescriptor [NTDLL.@]
664 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
665 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
666 OUT PBOOLEAN lpbSaclPresent,
667 OUT PACL *pSacl,
668 OUT PBOOLEAN lpbSaclDefaulted)
670 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
672 TRACE("(%p,%p,%p,%p)\n",
673 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
675 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
676 return STATUS_UNKNOWN_REVISION;
678 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
680 if (lpsd->Control & SE_SELF_RELATIVE)
682 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
683 if (sdr->Sacl) *pSacl = (PACL)SELF_RELATIVE_FIELD( sdr, Sacl );
684 else *pSacl = NULL;
686 else *pSacl = lpsd->Sacl;
688 *lpbSaclDefaulted = (lpsd->Control & SE_SACL_DEFAULTED) != 0;
690 return STATUS_SUCCESS;
693 /**************************************************************************
694 * RtlSetSaclSecurityDescriptor [NTDLL.@]
696 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
697 PSECURITY_DESCRIPTOR pSecurityDescriptor,
698 BOOLEAN saclpresent,
699 PACL sacl,
700 BOOLEAN sacldefaulted)
702 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
704 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
705 return STATUS_UNKNOWN_REVISION;
706 if (lpsd->Control & SE_SELF_RELATIVE)
707 return STATUS_INVALID_SECURITY_DESCR;
708 if (!saclpresent) {
709 lpsd->Control &= ~SE_SACL_PRESENT;
710 return 0;
712 lpsd->Control |= SE_SACL_PRESENT;
713 lpsd->Sacl = sacl;
714 if (sacldefaulted)
715 lpsd->Control |= SE_SACL_DEFAULTED;
716 else
717 lpsd->Control &= ~SE_SACL_DEFAULTED;
718 return STATUS_SUCCESS;
721 /**************************************************************************
722 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
724 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
725 PSECURITY_DESCRIPTOR pSecurityDescriptor,
726 PSID *Owner,
727 PBOOLEAN OwnerDefaulted)
729 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
731 if ( !lpsd || !Owner || !OwnerDefaulted )
732 return STATUS_INVALID_PARAMETER;
734 if ( lpsd->Control & SE_OWNER_DEFAULTED )
735 *OwnerDefaulted = TRUE;
736 else
737 *OwnerDefaulted = FALSE;
739 if (lpsd->Control & SE_SELF_RELATIVE)
741 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
742 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
743 else *Owner = NULL;
745 else
746 *Owner = lpsd->Owner;
748 return STATUS_SUCCESS;
751 /**************************************************************************
752 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
754 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
755 PSECURITY_DESCRIPTOR pSecurityDescriptor,
756 PSID owner,
757 BOOLEAN ownerdefaulted)
759 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
761 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
762 return STATUS_UNKNOWN_REVISION;
763 if (lpsd->Control & SE_SELF_RELATIVE)
764 return STATUS_INVALID_SECURITY_DESCR;
766 lpsd->Owner = owner;
767 if (ownerdefaulted)
768 lpsd->Control |= SE_OWNER_DEFAULTED;
769 else
770 lpsd->Control &= ~SE_OWNER_DEFAULTED;
771 return STATUS_SUCCESS;
774 /**************************************************************************
775 * RtlSetGroupSecurityDescriptor [NTDLL.@]
777 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
778 PSECURITY_DESCRIPTOR pSecurityDescriptor,
779 PSID group,
780 BOOLEAN groupdefaulted)
782 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
784 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
785 return STATUS_UNKNOWN_REVISION;
786 if (lpsd->Control & SE_SELF_RELATIVE)
787 return STATUS_INVALID_SECURITY_DESCR;
789 lpsd->Group = group;
790 if (groupdefaulted)
791 lpsd->Control |= SE_GROUP_DEFAULTED;
792 else
793 lpsd->Control &= ~SE_GROUP_DEFAULTED;
794 return STATUS_SUCCESS;
797 /**************************************************************************
798 * RtlGetGroupSecurityDescriptor [NTDLL.@]
800 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
801 PSECURITY_DESCRIPTOR pSecurityDescriptor,
802 PSID *Group,
803 PBOOLEAN GroupDefaulted)
805 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
807 if ( !lpsd || !Group || !GroupDefaulted )
808 return STATUS_INVALID_PARAMETER;
810 if ( lpsd->Control & SE_GROUP_DEFAULTED )
811 *GroupDefaulted = TRUE;
812 else
813 *GroupDefaulted = FALSE;
815 if (lpsd->Control & SE_SELF_RELATIVE)
817 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
818 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
819 else *Group = NULL;
821 else
822 *Group = lpsd->Group;
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 DWORD offsetRel;
836 ULONG length;
837 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
838 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
840 TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
841 lpdwBufferLength ? *lpdwBufferLength: -1);
843 if (!lpdwBufferLength || !pAbs)
844 return STATUS_INVALID_PARAMETER;
846 length = RtlLengthSecurityDescriptor(pAbs);
847 if (!(pAbs->Control & SE_SELF_RELATIVE)) length -= (sizeof(*pAbs) - sizeof(*pRel));
848 if (*lpdwBufferLength < length)
850 *lpdwBufferLength = length;
851 return STATUS_BUFFER_TOO_SMALL;
854 if (!pRel)
855 return STATUS_INVALID_PARAMETER;
857 if (pAbs->Control & SE_SELF_RELATIVE)
859 memcpy(pRel, pAbs, length);
860 return STATUS_SUCCESS;
863 pRel->Revision = pAbs->Revision;
864 pRel->Sbz1 = pAbs->Sbz1;
865 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
867 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
868 if (pAbs->Owner)
870 pRel->Owner = offsetRel;
871 length = RtlLengthSid(pAbs->Owner);
872 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
873 offsetRel += length;
875 else
877 pRel->Owner = 0;
880 if (pAbs->Group)
882 pRel->Group = offsetRel;
883 length = RtlLengthSid(pAbs->Group);
884 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
885 offsetRel += length;
887 else
889 pRel->Group = 0;
892 if (pAbs->Sacl)
894 pRel->Sacl = offsetRel;
895 length = pAbs->Sacl->AclSize;
896 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
897 offsetRel += length;
899 else
901 pRel->Sacl = 0;
904 if (pAbs->Dacl)
906 pRel->Dacl = offsetRel;
907 length = pAbs->Dacl->AclSize;
908 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
910 else
912 pRel->Dacl = 0;
915 return STATUS_SUCCESS;
919 /**************************************************************************
920 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
922 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
923 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
924 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
925 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
926 OUT PACL pDacl,
927 OUT LPDWORD lpdwDaclSize,
928 OUT PACL pSacl,
929 OUT LPDWORD lpdwSaclSize,
930 OUT PSID pOwner,
931 OUT LPDWORD lpdwOwnerSize,
932 OUT PSID pPrimaryGroup,
933 OUT LPDWORD lpdwPrimaryGroupSize)
935 NTSTATUS status = STATUS_SUCCESS;
936 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
937 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
939 if (!pRel ||
940 !lpdwAbsoluteSecurityDescriptorSize ||
941 !lpdwDaclSize ||
942 !lpdwSaclSize ||
943 !lpdwOwnerSize ||
944 !lpdwPrimaryGroupSize ||
945 ~pRel->Control & SE_SELF_RELATIVE)
946 return STATUS_INVALID_PARAMETER;
948 /* Confirm buffers are sufficiently large */
949 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
951 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
952 status = STATUS_BUFFER_TOO_SMALL;
955 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
956 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
958 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
959 status = STATUS_BUFFER_TOO_SMALL;
962 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
963 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
965 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
966 status = STATUS_BUFFER_TOO_SMALL;
969 if (pRel->Owner &&
970 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
972 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
973 status = STATUS_BUFFER_TOO_SMALL;
976 if (pRel->Group &&
977 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
979 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
980 status = STATUS_BUFFER_TOO_SMALL;
983 if (status != STATUS_SUCCESS)
984 return status;
986 /* Copy structures, and clear the ones we don't set */
987 pAbs->Revision = pRel->Revision;
988 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
989 pAbs->Sacl = NULL;
990 pAbs->Dacl = NULL;
991 pAbs->Owner = NULL;
992 pAbs->Group = NULL;
994 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
996 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
998 memcpy(pSacl, pAcl, pAcl->AclSize);
999 pAbs->Sacl = pSacl;
1002 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1004 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1005 memcpy(pDacl, pAcl, pAcl->AclSize);
1006 pAbs->Dacl = pDacl;
1009 if (pRel->Owner)
1011 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1012 memcpy(pOwner, psid, RtlLengthSid(psid));
1013 pAbs->Owner = pOwner;
1016 if (pRel->Group)
1018 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1019 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1020 pAbs->Group = pPrimaryGroup;
1023 return status;
1026 /******************************************************************************
1027 * RtlGetControlSecurityDescriptor (NTDLL.@)
1029 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1030 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1031 PSECURITY_DESCRIPTOR_CONTROL pControl,
1032 LPDWORD lpdwRevision)
1034 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1036 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1038 *lpdwRevision = lpsd->Revision;
1040 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1041 return STATUS_UNKNOWN_REVISION;
1043 *pControl = lpsd->Control;
1045 return STATUS_SUCCESS;
1048 /******************************************************************************
1049 * RtlSetControlSecurityDescriptor (NTDLL.@)
1051 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1052 PSECURITY_DESCRIPTOR SecurityDescriptor,
1053 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1054 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1056 SECURITY_DESCRIPTOR_CONTROL const immutable
1057 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1058 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1059 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1060 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1063 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1065 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1066 ControlBitsOfInterest, ControlBitsToSet);
1068 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1069 return STATUS_INVALID_PARAMETER;
1071 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1072 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1074 return STATUS_SUCCESS;
1078 /**************************************************************************
1079 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1081 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1082 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1083 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1084 PULONG BufferLength)
1086 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1088 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1089 SelfRelativeSecurityDescriptor, BufferLength);
1091 if (abs->Control & SE_SELF_RELATIVE)
1092 return STATUS_BAD_DESCRIPTOR_FORMAT;
1094 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1095 SelfRelativeSecurityDescriptor, BufferLength);
1098 /******************************************************************************
1099 * RtlNewSecurityObject [NTDLL.@]
1101 NTSTATUS WINAPI RtlNewSecurityObject(PSECURITY_DESCRIPTOR parent, PSECURITY_DESCRIPTOR creator,
1102 PSECURITY_DESCRIPTOR *descr, BOOLEAN is_container, HANDLE token, PGENERIC_MAPPING mapping)
1104 return RtlNewSecurityObjectEx(parent, creator, descr, NULL, is_container, 0, token, mapping);
1107 /******************************************************************************
1108 * RtlNewSecurityObjectEx [NTDLL.@]
1110 NTSTATUS WINAPI RtlNewSecurityObjectEx(PSECURITY_DESCRIPTOR parent, PSECURITY_DESCRIPTOR creator,
1111 PSECURITY_DESCRIPTOR *descr, GUID *type, BOOLEAN is_container, ULONG flags, HANDLE token, PGENERIC_MAPPING mapping )
1113 SECURITY_DESCRIPTOR_RELATIVE *relative;
1114 DWORD needed, offset;
1115 NTSTATUS status;
1116 BYTE *buffer;
1118 FIXME("%p, %p, %p, %p, %d, %#lx, %p %p - semi-stub\n", parent, creator, descr, type, is_container, flags, token, mapping);
1120 needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
1121 needed += sizeof(world_sid);
1122 needed += sizeof(world_sid);
1123 needed += world_access_acl_size;
1124 needed += world_access_acl_size;
1126 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, needed ))) return STATUS_NO_MEMORY;
1127 relative = (SECURITY_DESCRIPTOR_RELATIVE *)buffer;
1128 if ((status = RtlCreateSecurityDescriptor( relative, SECURITY_DESCRIPTOR_REVISION )))
1130 RtlFreeHeap( GetProcessHeap(), 0, buffer );
1131 return status;
1133 relative->Control |= SE_SELF_RELATIVE;
1134 offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
1136 memcpy( buffer + offset, &world_sid, sizeof(world_sid) );
1137 relative->Owner = offset;
1138 offset += sizeof(world_sid);
1140 memcpy( buffer + offset, &world_sid, sizeof(world_sid) );
1141 relative->Group = offset;
1142 offset += sizeof(world_sid);
1144 get_world_access_acl( (ACL *)(buffer + offset) );
1145 relative->Dacl = offset;
1146 offset += world_access_acl_size;
1148 get_world_access_acl( (ACL *)(buffer + offset) );
1149 relative->Sacl = offset;
1151 *descr = relative;
1152 return STATUS_SUCCESS;
1155 /******************************************************************************
1156 * RtlNewSecurityObjectWithMultipleInheritance [NTDLL.@]
1158 NTSTATUS WINAPI RtlNewSecurityObjectWithMultipleInheritance(PSECURITY_DESCRIPTOR parent, PSECURITY_DESCRIPTOR creator,
1159 PSECURITY_DESCRIPTOR *descr, GUID **types, ULONG count, BOOLEAN is_container, ULONG flags,
1160 HANDLE token, PGENERIC_MAPPING mapping )
1162 FIXME("semi-stub\n");
1163 return RtlNewSecurityObjectEx(parent, creator, descr, NULL, is_container, flags, token, mapping);
1166 /******************************************************************************
1167 * RtlDeleteSecurityObject [NTDLL.@]
1169 NTSTATUS WINAPI RtlDeleteSecurityObject( PSECURITY_DESCRIPTOR *descr )
1171 FIXME("%p stub.\n", descr);
1172 RtlFreeHeap( GetProcessHeap(), 0, *descr );
1173 return STATUS_SUCCESS;
1177 * access control list's
1180 /**************************************************************************
1181 * RtlCreateAcl [NTDLL.@]
1183 * NOTES
1184 * This should return NTSTATUS
1186 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1188 TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
1190 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1191 return STATUS_INVALID_PARAMETER;
1192 if (size<sizeof(ACL))
1193 return STATUS_BUFFER_TOO_SMALL;
1194 if (size>0xFFFF)
1195 return STATUS_INVALID_PARAMETER;
1197 memset(acl,'\0',sizeof(ACL));
1198 acl->AclRevision = rev;
1199 acl->AclSize = size;
1200 acl->AceCount = 0;
1201 return STATUS_SUCCESS;
1204 /**************************************************************************
1205 * RtlFirstFreeAce [NTDLL.@]
1206 * looks for the AceCount+1 ACE, and if it is still within the alloced
1207 * ACL, return a pointer to it
1209 BOOLEAN WINAPI RtlFirstFreeAce(
1210 PACL acl,
1211 PACE_HEADER *x)
1213 PACE_HEADER ace;
1214 int i;
1216 *x = 0;
1217 ace = (PACE_HEADER)(acl+1);
1218 for (i=0;i<acl->AceCount;i++) {
1219 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1220 return FALSE;
1221 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1223 if ((BYTE *)ace <= (BYTE *)acl + acl->AclSize)
1224 *x = ace;
1225 return TRUE;
1228 /**************************************************************************
1229 * RtlAddAce [NTDLL.@]
1231 NTSTATUS WINAPI RtlAddAce(
1232 PACL acl,
1233 DWORD rev,
1234 DWORD xnrofaces,
1235 PACE_HEADER acestart,
1236 DWORD acelen)
1238 PACE_HEADER ace,targetace;
1239 int nrofaces;
1241 if (!RtlValidAcl(acl))
1242 return STATUS_INVALID_PARAMETER;
1243 if (!RtlFirstFreeAce(acl,&targetace))
1244 return STATUS_INVALID_PARAMETER;
1245 if (!targetace)
1246 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1247 nrofaces=0;ace=acestart;
1248 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1249 nrofaces++;
1250 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1252 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1253 return STATUS_INVALID_PARAMETER;
1254 memcpy(targetace,acestart,acelen);
1255 acl->AceCount+=nrofaces;
1256 if (rev > acl->AclRevision)
1257 acl->AclRevision = rev;
1258 return STATUS_SUCCESS;
1261 /**************************************************************************
1262 * RtlDeleteAce [NTDLL.@]
1264 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1266 NTSTATUS status;
1267 PACE_HEADER pAce;
1269 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1271 if (STATUS_SUCCESS == status)
1273 PACE_HEADER pcAce;
1274 DWORD len = 0;
1276 /* skip over the ACE we are deleting */
1277 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1278 dwAceIndex++;
1280 /* calculate the length of the rest */
1281 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1283 len += pcAce->AceSize;
1284 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1287 /* slide them all backwards */
1288 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1289 pAcl->AceCount--;
1292 TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\n", pAcl, dwAceIndex, status);
1294 return status;
1297 /******************************************************************************
1298 * RtlAddAccessAllowedAce [NTDLL.@]
1300 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1301 IN OUT PACL pAcl,
1302 IN DWORD dwAceRevision,
1303 IN DWORD AccessMask,
1304 IN PSID pSid)
1306 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1309 /******************************************************************************
1310 * RtlAddAccessAllowedAceEx [NTDLL.@]
1312 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1313 IN OUT PACL pAcl,
1314 IN DWORD dwAceRevision,
1315 IN DWORD AceFlags,
1316 IN DWORD AccessMask,
1317 IN PSID pSid)
1319 TRACE("(%p,0x%08lx,0x%08lx,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1321 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1322 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1325 /******************************************************************************
1326 * RtlAddAccessAllowedObjectAce [NTDLL.@]
1328 NTSTATUS WINAPI RtlAddAccessAllowedObjectAce(
1329 IN OUT PACL pAcl,
1330 IN DWORD dwAceRevision,
1331 IN DWORD dwAceFlags,
1332 IN DWORD dwAccessMask,
1333 IN GUID* pObjectTypeGuid,
1334 IN GUID* pInheritedObjectTypeGuid,
1335 IN PSID pSid)
1337 FIXME("%p %lx %lx %lx %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1338 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1339 return STATUS_NOT_IMPLEMENTED;
1342 /******************************************************************************
1343 * RtlAddAccessDeniedAce [NTDLL.@]
1345 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1346 IN OUT PACL pAcl,
1347 IN DWORD dwAceRevision,
1348 IN DWORD AccessMask,
1349 IN PSID pSid)
1351 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1354 /******************************************************************************
1355 * RtlAddAccessDeniedAceEx [NTDLL.@]
1357 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1358 IN OUT PACL pAcl,
1359 IN DWORD dwAceRevision,
1360 IN DWORD AceFlags,
1361 IN DWORD AccessMask,
1362 IN PSID pSid)
1364 TRACE("(%p,0x%08lx,0x%08lx,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1366 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1367 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1370 /******************************************************************************
1371 * RtlAddAccessDeniedObjectAce [NTDLL.@]
1373 NTSTATUS WINAPI RtlAddAccessDeniedObjectAce(
1374 IN OUT PACL pAcl,
1375 IN DWORD dwAceRevision,
1376 IN DWORD dwAceFlags,
1377 IN DWORD dwAccessMask,
1378 IN GUID* pObjectTypeGuid,
1379 IN GUID* pInheritedObjectTypeGuid,
1380 IN PSID pSid)
1382 FIXME("%p %lx %lx %lx %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1383 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1384 return STATUS_NOT_IMPLEMENTED;
1387 /**************************************************************************
1388 * RtlAddAuditAccessAce [NTDLL.@]
1390 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1391 IN OUT PACL pAcl,
1392 IN DWORD dwAceRevision,
1393 IN DWORD dwAceFlags,
1394 IN DWORD dwAccessMask,
1395 IN PSID pSid,
1396 IN BOOL bAuditSuccess,
1397 IN BOOL bAuditFailure)
1399 TRACE("(%p,%ld,0x%08lx,0x%08lx,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1400 pSid,bAuditSuccess,bAuditFailure);
1402 if (bAuditSuccess)
1403 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1405 if (bAuditFailure)
1406 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1408 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1409 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1412 /**************************************************************************
1413 * RtlAddAuditAccessAce [NTDLL.@]
1415 NTSTATUS WINAPI RtlAddAuditAccessAce(
1416 IN OUT PACL pAcl,
1417 IN DWORD dwAceRevision,
1418 IN DWORD dwAccessMask,
1419 IN PSID pSid,
1420 IN BOOL bAuditSuccess,
1421 IN BOOL bAuditFailure)
1423 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1426 /******************************************************************************
1427 * RtlAddAuditAccessObjectAce [NTDLL.@]
1429 NTSTATUS WINAPI RtlAddAuditAccessObjectAce(
1430 IN OUT PACL pAcl,
1431 IN DWORD dwAceRevision,
1432 IN DWORD dwAceFlags,
1433 IN DWORD dwAccessMask,
1434 IN GUID* pObjectTypeGuid,
1435 IN GUID* pInheritedObjectTypeGuid,
1436 IN PSID pSid,
1437 IN BOOL bAuditSuccess,
1438 IN BOOL bAuditFailure)
1440 FIXME("%p %lx %lx %lx %p %p %p %d %d - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1441 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid, bAuditSuccess, bAuditFailure);
1442 return STATUS_NOT_IMPLEMENTED;
1445 /**************************************************************************
1446 * RtlAddMandatoryAce [NTDLL.@]
1448 NTSTATUS WINAPI RtlAddMandatoryAce(
1449 IN OUT PACL pAcl,
1450 IN DWORD dwAceRevision,
1451 IN DWORD dwAceFlags,
1452 IN DWORD dwMandatoryFlags,
1453 IN DWORD dwAceType,
1454 IN PSID pSid)
1456 TRACE("(%p, %lu, 0x%08lx, 0x%08lx, %lu, %p)\n",
1457 pAcl, dwAceRevision, dwAceFlags, dwMandatoryFlags, dwAceType, pSid);
1459 if (dwAceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE)
1460 return STATUS_INVALID_PARAMETER;
1461 if (dwMandatoryFlags & ~SYSTEM_MANDATORY_LABEL_VALID_MASK)
1462 return STATUS_INVALID_PARAMETER;
1464 return add_access_ace(pAcl, dwAceRevision, dwAceFlags, dwMandatoryFlags, pSid, dwAceType);
1467 /**************************************************************************
1468 * RtlAddProcessTrustLabelAce [NTDLL.@]
1470 NTSTATUS WINAPI RtlAddProcessTrustLabelAce( ACL *acl, DWORD revision, DWORD flags,
1471 PSID sid, DWORD type, DWORD mask )
1473 TRACE( "%p %lx %lx %p %lx %lx\n", acl, revision, flags, sid, type, mask );
1475 if (type != SYSTEM_PROCESS_TRUST_LABEL_ACE_TYPE) return STATUS_INVALID_PARAMETER;
1476 if (mask & ~SYSTEM_PROCESS_TRUST_LABEL_VALID_MASK) return STATUS_INVALID_PARAMETER;
1478 return add_access_ace( acl, revision, flags, mask, sid, type );
1481 /******************************************************************************
1482 * RtlValidAcl [NTDLL.@]
1484 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1486 BOOLEAN ret;
1487 TRACE("(%p)\n", pAcl);
1489 __TRY
1491 PACE_HEADER ace;
1492 int i;
1494 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1495 pAcl->AclRevision > MAX_ACL_REVISION)
1496 ret = FALSE;
1497 else
1499 ace = (PACE_HEADER)(pAcl+1);
1500 ret = TRUE;
1501 for (i=0;i<=pAcl->AceCount;i++)
1503 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1505 ret = FALSE;
1506 break;
1508 if (i != pAcl->AceCount)
1509 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1513 __EXCEPT_PAGE_FAULT
1515 WARN("(%p): invalid pointer!\n", pAcl);
1516 return FALSE;
1518 __ENDTRY
1519 return ret;
1522 /******************************************************************************
1523 * RtlGetAce [NTDLL.@]
1525 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1527 PACE_HEADER ace;
1529 TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1531 if (dwAceIndex >= pAcl->AceCount)
1532 return STATUS_INVALID_PARAMETER;
1534 ace = (PACE_HEADER)(pAcl + 1);
1535 for (;dwAceIndex;dwAceIndex--)
1536 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1538 *pAce = ace;
1540 return STATUS_SUCCESS;
1544 * misc
1547 /******************************************************************************
1548 * RtlAdjustPrivilege [NTDLL.@]
1550 * Enables or disables a privilege from the calling thread or process.
1552 * PARAMS
1553 * Privilege [I] Privilege index to change.
1554 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1555 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1556 * Enabled [O] Whether privilege was previously enabled or disabled.
1558 * RETURNS
1559 * Success: STATUS_SUCCESS.
1560 * Failure: NTSTATUS code.
1562 * SEE ALSO
1563 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1566 NTSTATUS WINAPI
1567 RtlAdjustPrivilege(ULONG Privilege,
1568 BOOLEAN Enable,
1569 BOOLEAN CurrentThread,
1570 PBOOLEAN Enabled)
1572 TOKEN_PRIVILEGES NewState;
1573 TOKEN_PRIVILEGES OldState;
1574 ULONG ReturnLength;
1575 HANDLE TokenHandle;
1576 NTSTATUS Status;
1578 TRACE("(%ld, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1579 CurrentThread ? "TRUE" : "FALSE", Enabled);
1581 if (CurrentThread)
1583 Status = NtOpenThreadToken(GetCurrentThread(),
1584 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1585 FALSE,
1586 &TokenHandle);
1588 else
1590 Status = NtOpenProcessToken(GetCurrentProcess(),
1591 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1592 &TokenHandle);
1595 if (Status)
1597 WARN("Retrieving token handle failed (Status %lx)\n", Status);
1598 return Status;
1601 OldState.PrivilegeCount = 1;
1603 NewState.PrivilegeCount = 1;
1604 NewState.Privileges[0].Luid.LowPart = Privilege;
1605 NewState.Privileges[0].Luid.HighPart = 0;
1606 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1608 Status = NtAdjustPrivilegesToken(TokenHandle,
1609 FALSE,
1610 &NewState,
1611 sizeof(TOKEN_PRIVILEGES),
1612 &OldState,
1613 &ReturnLength);
1614 NtClose (TokenHandle);
1615 if (Status == STATUS_NOT_ALL_ASSIGNED)
1617 TRACE("Failed to assign all privileges\n");
1618 return STATUS_PRIVILEGE_NOT_HELD;
1620 if (Status)
1622 WARN("NtAdjustPrivilegesToken() failed (Status %lx)\n", Status);
1623 return Status;
1626 if (OldState.PrivilegeCount == 0)
1627 *Enabled = Enable;
1628 else
1629 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1631 return STATUS_SUCCESS;
1634 /******************************************************************************
1635 * RtlImpersonateSelf [NTDLL.@]
1637 * Makes an impersonation token that represents the process user and assigns
1638 * to the current thread.
1640 * PARAMS
1641 * ImpersonationLevel [I] Level at which to impersonate.
1643 * RETURNS
1644 * Success: STATUS_SUCCESS.
1645 * Failure: NTSTATUS code.
1647 NTSTATUS WINAPI
1648 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1650 SECURITY_QUALITY_OF_SERVICE qos;
1651 NTSTATUS Status;
1652 OBJECT_ATTRIBUTES attr;
1653 HANDLE ProcessToken;
1654 HANDLE ImpersonationToken;
1656 TRACE("(%08x)\n", ImpersonationLevel);
1658 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1659 &ProcessToken);
1660 if (Status != STATUS_SUCCESS)
1661 return Status;
1663 qos.Length = sizeof(qos);
1664 qos.ImpersonationLevel = ImpersonationLevel;
1665 qos.ContextTrackingMode = SECURITY_STATIC_TRACKING;
1666 qos.EffectiveOnly = FALSE;
1667 InitializeObjectAttributes( &attr, NULL, 0, NULL, NULL );
1668 attr.SecurityQualityOfService = &qos;
1670 Status = NtDuplicateToken( ProcessToken, TOKEN_IMPERSONATE, &attr, FALSE,
1671 TokenImpersonation, &ImpersonationToken );
1672 if (Status != STATUS_SUCCESS)
1674 NtClose( ProcessToken );
1675 return Status;
1678 Status = NtSetInformationThread( GetCurrentThread(),
1679 ThreadImpersonationToken,
1680 &ImpersonationToken,
1681 sizeof(ImpersonationToken) );
1683 NtClose( ImpersonationToken );
1684 NtClose( ProcessToken );
1686 return Status;
1690 /******************************************************************************
1691 * RtlConvertSidToUnicodeString (NTDLL.@)
1693 * The returned SID is used to access the USER registry hive usually
1695 * the native function returns something like
1696 * "S-1-5-21-0000000000-000000000-0000000000-500";
1698 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1699 PUNICODE_STRING String,
1700 PSID pSid,
1701 BOOLEAN AllocateString)
1703 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1704 WCHAR *p = buffer;
1705 const SID *sid = pSid;
1706 DWORD i, len;
1708 *p++ = 'S';
1709 p += swprintf( p, ARRAY_SIZE(buffer) - (p - buffer), L"-%u", sid->Revision );
1710 p += swprintf( p, ARRAY_SIZE(buffer) - (p - buffer), L"-%u",
1711 MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1712 sid->IdentifierAuthority.Value[4] ),
1713 MAKEWORD( sid->IdentifierAuthority.Value[3],
1714 sid->IdentifierAuthority.Value[2] )));
1715 for (i = 0; i < sid->SubAuthorityCount; i++)
1716 p += swprintf( p, ARRAY_SIZE(buffer) - (p - buffer), L"-%u", sid->SubAuthority[i] );
1718 len = (p + 1 - buffer) * sizeof(WCHAR);
1720 String->Length = len - sizeof(WCHAR);
1721 if (AllocateString)
1723 String->MaximumLength = len;
1724 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1725 return STATUS_NO_MEMORY;
1727 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1729 memcpy( String->Buffer, buffer, len );
1730 return STATUS_SUCCESS;
1733 /******************************************************************************
1734 * RtlQueryInformationAcl (NTDLL.@)
1736 NTSTATUS WINAPI RtlQueryInformationAcl(
1737 PACL pAcl,
1738 LPVOID pAclInformation,
1739 DWORD nAclInformationLength,
1740 ACL_INFORMATION_CLASS dwAclInformationClass)
1742 NTSTATUS status = STATUS_SUCCESS;
1744 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1745 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1747 switch (dwAclInformationClass)
1749 case AclRevisionInformation:
1751 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1753 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1754 status = STATUS_INVALID_PARAMETER;
1755 else
1756 paclrev->AclRevision = pAcl->AclRevision;
1758 break;
1761 case AclSizeInformation:
1763 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1765 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1766 status = STATUS_INVALID_PARAMETER;
1767 else
1769 paclsize->AceCount = pAcl->AceCount;
1770 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1771 if (pAcl->AclSize < paclsize->AclBytesInUse)
1773 WARN("Acl uses %d bytes, but only has %ld allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1774 paclsize->AclBytesFree = 0;
1775 paclsize->AclBytesInUse = pAcl->AclSize;
1777 else
1778 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1781 break;
1784 default:
1785 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1786 status = STATUS_INVALID_PARAMETER;
1789 return status;
1792 NTSTATUS WINAPI RtlConvertToAutoInheritSecurityObject(
1793 PSECURITY_DESCRIPTOR pdesc,
1794 PSECURITY_DESCRIPTOR cdesc,
1795 PSECURITY_DESCRIPTOR* ndesc,
1796 GUID* objtype,
1797 BOOL isdir,
1798 PGENERIC_MAPPING genmap )
1800 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
1802 return STATUS_NOT_IMPLEMENTED;
1805 /******************************************************************************
1806 * RtlDefaultNpAcl (NTDLL.@)
1808 NTSTATUS WINAPI RtlDefaultNpAcl(PACL *pAcl)
1810 FIXME("%p - stub\n", pAcl);
1812 *pAcl = NULL;
1813 return STATUS_SUCCESS;