ntdll: RtlFirstFreeAce only return FALSE on error.
[wine.git] / dlls / ntdll / sec.c
blob20adc0441587e9af9c240a36016b287d1eb05463
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 /* helper function to retrieve active length of an ACL */
41 static size_t acl_bytesInUse(PACL pAcl)
43 int i;
44 size_t bytesInUse = sizeof(ACL);
45 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
46 for (i = 0; i < pAcl->AceCount; i++)
48 bytesInUse += ace->AceSize;
49 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
51 return bytesInUse;
54 /* helper function to copy an ACL */
55 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
57 DWORD size;
59 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
60 return FALSE;
62 size = pSourceAcl->AclSize;
63 if (nDestinationAclLength < size)
64 return FALSE;
66 memmove(pDestinationAcl, pSourceAcl, size);
67 return TRUE;
70 /* generically adds an ACE to an ACL */
71 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
72 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
74 ACE_HEADER *pAceHeader;
75 DWORD dwLengthSid;
76 DWORD dwAceSize;
77 DWORD *pAccessMask;
78 DWORD *pSidStart;
80 if (!RtlValidSid(pSid))
81 return STATUS_INVALID_SID;
83 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
84 return STATUS_REVISION_MISMATCH;
86 if (!RtlValidAcl(pAcl))
87 return STATUS_INVALID_ACL;
89 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
90 return STATUS_INVALID_ACL;
92 if (!pAceHeader)
93 return STATUS_ALLOTTED_SPACE_EXCEEDED;
95 /* calculate generic size of the ACE */
96 dwLengthSid = RtlLengthSid(pSid);
97 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
98 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
99 return STATUS_ALLOTTED_SPACE_EXCEEDED;
101 /* fill the new ACE */
102 pAceHeader->AceType = dwAceType;
103 pAceHeader->AceFlags = dwAceFlags;
104 pAceHeader->AceSize = dwAceSize;
106 /* skip past the ACE_HEADER of the ACE */
107 pAccessMask = (DWORD *)(pAceHeader + 1);
108 *pAccessMask = dwAccessMask;
110 /* skip past ACE->Mask */
111 pSidStart = pAccessMask + 1;
112 RtlCopySid(dwLengthSid, pSidStart, pSid);
114 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
115 pAcl->AceCount++;
117 return STATUS_SUCCESS;
121 * SID FUNCTIONS
124 /******************************************************************************
125 * RtlAllocateAndInitializeSid [NTDLL.@]
128 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
129 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
130 BYTE nSubAuthorityCount,
131 DWORD nSubAuthority0, DWORD nSubAuthority1,
132 DWORD nSubAuthority2, DWORD nSubAuthority3,
133 DWORD nSubAuthority4, DWORD nSubAuthority5,
134 DWORD nSubAuthority6, DWORD nSubAuthority7,
135 PSID *pSid )
137 SID *tmp_sid;
139 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
140 pIdentifierAuthority,nSubAuthorityCount,
141 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
142 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
144 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
146 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
147 RtlLengthRequiredSid(nSubAuthorityCount))))
148 return STATUS_NO_MEMORY;
150 tmp_sid->Revision = SID_REVISION;
152 if (pIdentifierAuthority)
153 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
154 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
156 switch( nSubAuthorityCount )
158 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
159 /* fall through */
160 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
161 /* fall through */
162 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
163 /* fall through */
164 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
165 /* fall through */
166 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
167 /* fall through */
168 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
169 /* fall through */
170 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
171 /* fall through */
172 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
173 break;
175 *pSid = tmp_sid;
176 return STATUS_SUCCESS;
179 /******************************************************************************
180 * RtlEqualSid [NTDLL.@]
182 * Determine if two SIDs are equal.
184 * PARAMS
185 * pSid1 [I] Source SID
186 * pSid2 [I] SID to compare with
188 * RETURNS
189 * TRUE, if pSid1 is equal to pSid2,
190 * FALSE otherwise.
192 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
194 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
195 return FALSE;
197 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
198 return FALSE;
200 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
201 return FALSE;
203 return TRUE;
206 /******************************************************************************
207 * RtlEqualPrefixSid [NTDLL.@]
209 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
211 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
212 return FALSE;
214 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
215 return FALSE;
217 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
218 return FALSE;
220 return TRUE;
224 /******************************************************************************
225 * RtlFreeSid [NTDLL.@]
227 * Free the resources used by a SID.
229 * PARAMS
230 * pSid [I] SID to Free.
232 * RETURNS
233 * STATUS_SUCCESS.
235 DWORD WINAPI RtlFreeSid(PSID pSid)
237 TRACE("(%p)\n", pSid);
238 RtlFreeHeap( GetProcessHeap(), 0, pSid );
239 return STATUS_SUCCESS;
242 /**************************************************************************
243 * RtlLengthRequiredSid [NTDLL.@]
245 * Determine the amount of memory a SID will use
247 * PARAMS
248 * nrofsubauths [I] Number of Sub Authorities in the SID.
250 * RETURNS
251 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
253 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
255 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
258 /**************************************************************************
259 * RtlLengthSid [NTDLL.@]
261 * Determine the amount of memory a SID is using
263 * PARAMS
264 * pSid [I] SID to get the size of.
266 * RETURNS
267 * The size, in bytes, of pSid.
269 DWORD WINAPI RtlLengthSid(PSID pSid)
271 TRACE("sid=%p\n",pSid);
272 if (!pSid) return 0;
273 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
276 /**************************************************************************
277 * RtlInitializeSid [NTDLL.@]
279 * Initialise a SID.
281 * PARAMS
282 * pSid [I] SID to initialise
283 * pIdentifierAuthority [I] Identifier Authority
284 * nSubAuthorityCount [I] Number of Sub Authorities
286 * RETURNS
287 * Success: TRUE. pSid is initialised with the details given.
288 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
290 BOOL WINAPI RtlInitializeSid(
291 PSID pSid,
292 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
293 BYTE nSubAuthorityCount)
295 int i;
296 SID* pisid=pSid;
298 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
299 return FALSE;
301 pisid->Revision = SID_REVISION;
302 pisid->SubAuthorityCount = nSubAuthorityCount;
303 if (pIdentifierAuthority)
304 pisid->IdentifierAuthority = *pIdentifierAuthority;
306 for (i = 0; i < nSubAuthorityCount; i++)
307 *RtlSubAuthoritySid(pSid, i) = 0;
309 return TRUE;
312 /**************************************************************************
313 * RtlSubAuthoritySid [NTDLL.@]
315 * Return the Sub Authority of a SID
317 * PARAMS
318 * pSid [I] SID to get the Sub Authority from.
319 * nSubAuthority [I] Sub Authority number.
321 * RETURNS
322 * A pointer to The Sub Authority value of pSid.
324 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
326 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
329 /**************************************************************************
330 * RtlIdentifierAuthoritySid [NTDLL.@]
332 * Return the Identifier Authority of a SID.
334 * PARAMS
335 * pSid [I] SID to get the Identifier Authority from.
337 * RETURNS
338 * A pointer to the Identifier Authority value of pSid.
340 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
342 return &(((SID*)pSid)->IdentifierAuthority);
345 /**************************************************************************
346 * RtlSubAuthorityCountSid [NTDLL.@]
348 * Get the number of Sub Authorities in a SID.
350 * PARAMS
351 * pSid [I] SID to get the count from.
353 * RETURNS
354 * A pointer to the Sub Authority count of pSid.
356 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
358 return &(((SID*)pSid)->SubAuthorityCount);
361 /**************************************************************************
362 * RtlCopySid [NTDLL.@]
364 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
366 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
367 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
368 return FALSE;
370 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
371 return FALSE;
373 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
374 return TRUE;
376 /******************************************************************************
377 * RtlValidSid [NTDLL.@]
379 * Determine if a SID is valid.
381 * PARAMS
382 * pSid [I] SID to check
384 * RETURNS
385 * TRUE if pSid is valid,
386 * FALSE otherwise.
388 BOOLEAN WINAPI RtlValidSid( PSID pSid )
390 BOOL ret;
391 __TRY
393 ret = TRUE;
394 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
395 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
397 ret = FALSE;
400 __EXCEPT_PAGE_FAULT
402 WARN("(%p): invalid pointer!\n", pSid);
403 return FALSE;
405 __ENDTRY
406 return ret;
411 * security descriptor functions
414 /**************************************************************************
415 * RtlCreateSecurityDescriptor [NTDLL.@]
417 * Initialise a SECURITY_DESCRIPTOR.
419 * PARAMS
420 * lpsd [O] Descriptor to initialise.
421 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
423 * RETURNS
424 * Success: STATUS_SUCCESS.
425 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
427 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
428 PSECURITY_DESCRIPTOR lpsd,
429 DWORD rev)
431 if (rev!=SECURITY_DESCRIPTOR_REVISION)
432 return STATUS_UNKNOWN_REVISION;
433 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
434 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
435 return STATUS_SUCCESS;
438 /**************************************************************************
439 * RtlCopySecurityDescriptor [NTDLL.@]
441 * Copies an absolute or self-relative SECURITY_DESCRIPTOR.
443 * PARAMS
444 * pSourceSD [O] SD to copy from.
445 * pDestinationSD [I] Destination SD.
447 * RETURNS
448 * Success: STATUS_SUCCESS.
449 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
451 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
453 PSID Owner, Group;
454 PACL Dacl, Sacl;
455 DWORD length;
457 if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
459 SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
460 SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
462 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
463 return STATUS_UNKNOWN_REVISION;
465 *dst = *src;
466 if (src->Owner)
468 Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
469 length = RtlLengthSid( Owner );
470 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
472 if (src->Group)
474 Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
475 length = RtlLengthSid( Group );
476 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
478 if ((src->Control & SE_SACL_PRESENT) && src->Sacl)
480 Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
481 copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
483 if ((src->Control & SE_DACL_PRESENT) && src->Dacl)
485 Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
486 copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
489 else
491 SECURITY_DESCRIPTOR *src = pSourceSD;
492 SECURITY_DESCRIPTOR *dst = pDestinationSD;
494 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
495 return STATUS_UNKNOWN_REVISION;
497 *dst = *src;
498 if (src->Owner)
500 length = RtlLengthSid( src->Owner );
501 dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
502 RtlCopySid(length, dst->Owner, src->Owner);
504 if (src->Group)
506 length = RtlLengthSid( src->Group );
507 dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
508 RtlCopySid(length, dst->Group, src->Group);
510 if (src->Control & SE_SACL_PRESENT)
512 length = src->Sacl->AclSize;
513 dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
514 copy_acl(length, dst->Sacl, src->Sacl);
516 if (src->Control & SE_DACL_PRESENT)
518 length = src->Dacl->AclSize;
519 dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
520 copy_acl(length, dst->Dacl, src->Dacl);
524 return STATUS_SUCCESS;
527 /**************************************************************************
528 * RtlValidSecurityDescriptor [NTDLL.@]
530 * Determine if a SECURITY_DESCRIPTOR is valid.
532 * PARAMS
533 * SecurityDescriptor [I] Descriptor to check.
535 * RETURNS
536 * Success: STATUS_SUCCESS.
537 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
539 NTSTATUS WINAPI RtlValidSecurityDescriptor(
540 PSECURITY_DESCRIPTOR SecurityDescriptor)
542 if ( ! SecurityDescriptor )
543 return STATUS_INVALID_SECURITY_DESCR;
544 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
545 return STATUS_UNKNOWN_REVISION;
547 return STATUS_SUCCESS;
550 /**************************************************************************
551 * RtlValidRelativeSecurityDescriptor [NTDLL.@]
553 BOOLEAN WINAPI RtlValidRelativeSecurityDescriptor(PSECURITY_DESCRIPTOR descriptor,
554 ULONG length, SECURITY_INFORMATION info)
556 FIXME("%p,%u,%d: semi-stub\n", descriptor, length, info);
557 return RtlValidSecurityDescriptor(descriptor) == STATUS_SUCCESS;
560 /**************************************************************************
561 * RtlLengthSecurityDescriptor [NTDLL.@]
563 ULONG WINAPI RtlLengthSecurityDescriptor(
564 PSECURITY_DESCRIPTOR pSecurityDescriptor)
566 ULONG size;
568 if ( pSecurityDescriptor == NULL )
569 return 0;
571 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
573 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
574 size = sizeof(*sd);
575 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
576 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
577 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
578 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
579 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
580 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
582 else
584 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
585 size = sizeof(*sd);
586 if (sd->Owner) size += RtlLengthSid( sd->Owner );
587 if (sd->Group) size += RtlLengthSid( sd->Group );
588 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
589 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
591 return size;
594 /******************************************************************************
595 * RtlGetDaclSecurityDescriptor [NTDLL.@]
598 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
599 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
600 OUT PBOOLEAN lpbDaclPresent,
601 OUT PACL *pDacl,
602 OUT PBOOLEAN lpbDaclDefaulted)
604 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
606 TRACE("(%p,%p,%p,%p)\n",
607 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
609 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
610 return STATUS_UNKNOWN_REVISION ;
612 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
614 if (lpsd->Control & SE_SELF_RELATIVE)
616 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
617 if (sdr->Dacl) *pDacl = (PACL)SELF_RELATIVE_FIELD( sdr, Dacl );
618 else *pDacl = NULL;
620 else *pDacl = lpsd->Dacl;
622 *lpbDaclDefaulted = (lpsd->Control & SE_DACL_DEFAULTED) != 0;
624 else
626 *pDacl = NULL;
627 *lpbDaclDefaulted = 0;
630 return STATUS_SUCCESS;
633 /**************************************************************************
634 * RtlSetDaclSecurityDescriptor [NTDLL.@]
636 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
637 PSECURITY_DESCRIPTOR pSecurityDescriptor,
638 BOOLEAN daclpresent,
639 PACL dacl,
640 BOOLEAN dacldefaulted )
642 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
644 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
645 return STATUS_UNKNOWN_REVISION;
646 if (lpsd->Control & SE_SELF_RELATIVE)
647 return STATUS_INVALID_SECURITY_DESCR;
649 if (!daclpresent)
651 lpsd->Control &= ~SE_DACL_PRESENT;
652 return STATUS_SUCCESS;
655 lpsd->Control |= SE_DACL_PRESENT;
656 lpsd->Dacl = dacl;
658 if (dacldefaulted)
659 lpsd->Control |= SE_DACL_DEFAULTED;
660 else
661 lpsd->Control &= ~SE_DACL_DEFAULTED;
663 return STATUS_SUCCESS;
666 /******************************************************************************
667 * RtlGetSaclSecurityDescriptor [NTDLL.@]
670 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
671 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
672 OUT PBOOLEAN lpbSaclPresent,
673 OUT PACL *pSacl,
674 OUT PBOOLEAN lpbSaclDefaulted)
676 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
678 TRACE("(%p,%p,%p,%p)\n",
679 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
681 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
682 return STATUS_UNKNOWN_REVISION;
684 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
686 if (lpsd->Control & SE_SELF_RELATIVE)
688 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
689 if (sdr->Sacl) *pSacl = (PACL)SELF_RELATIVE_FIELD( sdr, Sacl );
690 else *pSacl = NULL;
692 else *pSacl = lpsd->Sacl;
694 *lpbSaclDefaulted = (lpsd->Control & SE_SACL_DEFAULTED) != 0;
696 return STATUS_SUCCESS;
699 /**************************************************************************
700 * RtlSetSaclSecurityDescriptor [NTDLL.@]
702 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
703 PSECURITY_DESCRIPTOR pSecurityDescriptor,
704 BOOLEAN saclpresent,
705 PACL sacl,
706 BOOLEAN sacldefaulted)
708 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
710 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
711 return STATUS_UNKNOWN_REVISION;
712 if (lpsd->Control & SE_SELF_RELATIVE)
713 return STATUS_INVALID_SECURITY_DESCR;
714 if (!saclpresent) {
715 lpsd->Control &= ~SE_SACL_PRESENT;
716 return 0;
718 lpsd->Control |= SE_SACL_PRESENT;
719 lpsd->Sacl = sacl;
720 if (sacldefaulted)
721 lpsd->Control |= SE_SACL_DEFAULTED;
722 else
723 lpsd->Control &= ~SE_SACL_DEFAULTED;
724 return STATUS_SUCCESS;
727 /**************************************************************************
728 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
730 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
731 PSECURITY_DESCRIPTOR pSecurityDescriptor,
732 PSID *Owner,
733 PBOOLEAN OwnerDefaulted)
735 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
737 if ( !lpsd || !Owner || !OwnerDefaulted )
738 return STATUS_INVALID_PARAMETER;
740 if ( lpsd->Control & SE_OWNER_DEFAULTED )
741 *OwnerDefaulted = TRUE;
742 else
743 *OwnerDefaulted = FALSE;
745 if (lpsd->Control & SE_SELF_RELATIVE)
747 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
748 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
749 else *Owner = NULL;
751 else
752 *Owner = lpsd->Owner;
754 return STATUS_SUCCESS;
757 /**************************************************************************
758 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
760 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
761 PSECURITY_DESCRIPTOR pSecurityDescriptor,
762 PSID owner,
763 BOOLEAN ownerdefaulted)
765 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
767 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
768 return STATUS_UNKNOWN_REVISION;
769 if (lpsd->Control & SE_SELF_RELATIVE)
770 return STATUS_INVALID_SECURITY_DESCR;
772 lpsd->Owner = owner;
773 if (ownerdefaulted)
774 lpsd->Control |= SE_OWNER_DEFAULTED;
775 else
776 lpsd->Control &= ~SE_OWNER_DEFAULTED;
777 return STATUS_SUCCESS;
780 /**************************************************************************
781 * RtlSetGroupSecurityDescriptor [NTDLL.@]
783 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
784 PSECURITY_DESCRIPTOR pSecurityDescriptor,
785 PSID group,
786 BOOLEAN groupdefaulted)
788 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
790 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
791 return STATUS_UNKNOWN_REVISION;
792 if (lpsd->Control & SE_SELF_RELATIVE)
793 return STATUS_INVALID_SECURITY_DESCR;
795 lpsd->Group = group;
796 if (groupdefaulted)
797 lpsd->Control |= SE_GROUP_DEFAULTED;
798 else
799 lpsd->Control &= ~SE_GROUP_DEFAULTED;
800 return STATUS_SUCCESS;
803 /**************************************************************************
804 * RtlGetGroupSecurityDescriptor [NTDLL.@]
806 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
807 PSECURITY_DESCRIPTOR pSecurityDescriptor,
808 PSID *Group,
809 PBOOLEAN GroupDefaulted)
811 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
813 if ( !lpsd || !Group || !GroupDefaulted )
814 return STATUS_INVALID_PARAMETER;
816 if ( lpsd->Control & SE_GROUP_DEFAULTED )
817 *GroupDefaulted = TRUE;
818 else
819 *GroupDefaulted = FALSE;
821 if (lpsd->Control & SE_SELF_RELATIVE)
823 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
824 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
825 else *Group = NULL;
827 else
828 *Group = lpsd->Group;
830 return STATUS_SUCCESS;
833 /**************************************************************************
834 * RtlMakeSelfRelativeSD [NTDLL.@]
836 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
837 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
838 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
839 IN OUT LPDWORD lpdwBufferLength)
841 DWORD offsetRel;
842 ULONG length;
843 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
844 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
846 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
847 lpdwBufferLength ? *lpdwBufferLength: -1);
849 if (!lpdwBufferLength || !pAbs)
850 return STATUS_INVALID_PARAMETER;
852 length = RtlLengthSecurityDescriptor(pAbs);
853 if (!(pAbs->Control & SE_SELF_RELATIVE)) length -= (sizeof(*pAbs) - sizeof(*pRel));
854 if (*lpdwBufferLength < length)
856 *lpdwBufferLength = length;
857 return STATUS_BUFFER_TOO_SMALL;
860 if (!pRel)
861 return STATUS_INVALID_PARAMETER;
863 if (pAbs->Control & SE_SELF_RELATIVE)
865 memcpy(pRel, pAbs, length);
866 return STATUS_SUCCESS;
869 pRel->Revision = pAbs->Revision;
870 pRel->Sbz1 = pAbs->Sbz1;
871 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
873 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
874 if (pAbs->Owner)
876 pRel->Owner = offsetRel;
877 length = RtlLengthSid(pAbs->Owner);
878 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
879 offsetRel += length;
881 else
883 pRel->Owner = 0;
886 if (pAbs->Group)
888 pRel->Group = offsetRel;
889 length = RtlLengthSid(pAbs->Group);
890 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
891 offsetRel += length;
893 else
895 pRel->Group = 0;
898 if (pAbs->Sacl)
900 pRel->Sacl = offsetRel;
901 length = pAbs->Sacl->AclSize;
902 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
903 offsetRel += length;
905 else
907 pRel->Sacl = 0;
910 if (pAbs->Dacl)
912 pRel->Dacl = offsetRel;
913 length = pAbs->Dacl->AclSize;
914 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
916 else
918 pRel->Dacl = 0;
921 return STATUS_SUCCESS;
925 /**************************************************************************
926 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
928 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
929 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
930 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
931 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
932 OUT PACL pDacl,
933 OUT LPDWORD lpdwDaclSize,
934 OUT PACL pSacl,
935 OUT LPDWORD lpdwSaclSize,
936 OUT PSID pOwner,
937 OUT LPDWORD lpdwOwnerSize,
938 OUT PSID pPrimaryGroup,
939 OUT LPDWORD lpdwPrimaryGroupSize)
941 NTSTATUS status = STATUS_SUCCESS;
942 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
943 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
945 if (!pRel ||
946 !lpdwAbsoluteSecurityDescriptorSize ||
947 !lpdwDaclSize ||
948 !lpdwSaclSize ||
949 !lpdwOwnerSize ||
950 !lpdwPrimaryGroupSize ||
951 ~pRel->Control & SE_SELF_RELATIVE)
952 return STATUS_INVALID_PARAMETER;
954 /* Confirm buffers are sufficiently large */
955 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
957 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
958 status = STATUS_BUFFER_TOO_SMALL;
961 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
962 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
964 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
965 status = STATUS_BUFFER_TOO_SMALL;
968 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
969 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
971 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
972 status = STATUS_BUFFER_TOO_SMALL;
975 if (pRel->Owner &&
976 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
978 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
979 status = STATUS_BUFFER_TOO_SMALL;
982 if (pRel->Group &&
983 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
985 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
986 status = STATUS_BUFFER_TOO_SMALL;
989 if (status != STATUS_SUCCESS)
990 return status;
992 /* Copy structures, and clear the ones we don't set */
993 pAbs->Revision = pRel->Revision;
994 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
995 pAbs->Sacl = NULL;
996 pAbs->Dacl = NULL;
997 pAbs->Owner = NULL;
998 pAbs->Group = NULL;
1000 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
1002 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
1004 memcpy(pSacl, pAcl, pAcl->AclSize);
1005 pAbs->Sacl = pSacl;
1008 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1010 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1011 memcpy(pDacl, pAcl, pAcl->AclSize);
1012 pAbs->Dacl = pDacl;
1015 if (pRel->Owner)
1017 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1018 memcpy(pOwner, psid, RtlLengthSid(psid));
1019 pAbs->Owner = pOwner;
1022 if (pRel->Group)
1024 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1025 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1026 pAbs->Group = pPrimaryGroup;
1029 return status;
1032 /******************************************************************************
1033 * RtlGetControlSecurityDescriptor (NTDLL.@)
1035 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1036 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1037 PSECURITY_DESCRIPTOR_CONTROL pControl,
1038 LPDWORD lpdwRevision)
1040 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1042 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1044 *lpdwRevision = lpsd->Revision;
1046 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1047 return STATUS_UNKNOWN_REVISION;
1049 *pControl = lpsd->Control;
1051 return STATUS_SUCCESS;
1054 /******************************************************************************
1055 * RtlSetControlSecurityDescriptor (NTDLL.@)
1057 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1058 PSECURITY_DESCRIPTOR SecurityDescriptor,
1059 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1060 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1062 SECURITY_DESCRIPTOR_CONTROL const immutable
1063 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1064 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1065 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1066 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1069 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1071 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1072 ControlBitsOfInterest, ControlBitsToSet);
1074 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1075 return STATUS_INVALID_PARAMETER;
1077 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1078 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1080 return STATUS_SUCCESS;
1084 /**************************************************************************
1085 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1087 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1088 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1089 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1090 PULONG BufferLength)
1092 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1094 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1095 SelfRelativeSecurityDescriptor, BufferLength);
1097 if (abs->Control & SE_SELF_RELATIVE)
1098 return STATUS_BAD_DESCRIPTOR_FORMAT;
1100 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1101 SelfRelativeSecurityDescriptor, BufferLength);
1106 * access control list's
1109 /**************************************************************************
1110 * RtlCreateAcl [NTDLL.@]
1112 * NOTES
1113 * This should return NTSTATUS
1115 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1117 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1119 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1120 return STATUS_INVALID_PARAMETER;
1121 if (size<sizeof(ACL))
1122 return STATUS_BUFFER_TOO_SMALL;
1123 if (size>0xFFFF)
1124 return STATUS_INVALID_PARAMETER;
1126 memset(acl,'\0',sizeof(ACL));
1127 acl->AclRevision = rev;
1128 acl->AclSize = size;
1129 acl->AceCount = 0;
1130 return STATUS_SUCCESS;
1133 /**************************************************************************
1134 * RtlFirstFreeAce [NTDLL.@]
1135 * looks for the AceCount+1 ACE, and if it is still within the alloced
1136 * ACL, return a pointer to it
1138 BOOLEAN WINAPI RtlFirstFreeAce(
1139 PACL acl,
1140 PACE_HEADER *x)
1142 PACE_HEADER ace;
1143 int i;
1145 *x = 0;
1146 ace = (PACE_HEADER)(acl+1);
1147 for (i=0;i<acl->AceCount;i++) {
1148 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1149 return FALSE;
1150 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1152 if ((BYTE *)ace <= (BYTE *)acl + acl->AclSize)
1153 *x = ace;
1154 return TRUE;
1157 /**************************************************************************
1158 * RtlAddAce [NTDLL.@]
1160 NTSTATUS WINAPI RtlAddAce(
1161 PACL acl,
1162 DWORD rev,
1163 DWORD xnrofaces,
1164 PACE_HEADER acestart,
1165 DWORD acelen)
1167 PACE_HEADER ace,targetace;
1168 int nrofaces;
1170 if (!RtlValidAcl(acl))
1171 return STATUS_INVALID_PARAMETER;
1172 if (!RtlFirstFreeAce(acl,&targetace))
1173 return STATUS_INVALID_PARAMETER;
1174 if (!targetace)
1175 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1176 nrofaces=0;ace=acestart;
1177 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1178 nrofaces++;
1179 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1181 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1182 return STATUS_INVALID_PARAMETER;
1183 memcpy(targetace,acestart,acelen);
1184 acl->AceCount+=nrofaces;
1185 if (rev > acl->AclRevision)
1186 acl->AclRevision = rev;
1187 return STATUS_SUCCESS;
1190 /**************************************************************************
1191 * RtlDeleteAce [NTDLL.@]
1193 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1195 NTSTATUS status;
1196 PACE_HEADER pAce;
1198 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1200 if (STATUS_SUCCESS == status)
1202 PACE_HEADER pcAce;
1203 DWORD len = 0;
1205 /* skip over the ACE we are deleting */
1206 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1207 dwAceIndex++;
1209 /* calculate the length of the rest */
1210 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1212 len += pcAce->AceSize;
1213 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1216 /* slide them all backwards */
1217 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1218 pAcl->AceCount--;
1221 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1223 return status;
1226 /******************************************************************************
1227 * RtlAddAccessAllowedAce [NTDLL.@]
1229 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1230 IN OUT PACL pAcl,
1231 IN DWORD dwAceRevision,
1232 IN DWORD AccessMask,
1233 IN PSID pSid)
1235 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1238 /******************************************************************************
1239 * RtlAddAccessAllowedAceEx [NTDLL.@]
1241 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1242 IN OUT PACL pAcl,
1243 IN DWORD dwAceRevision,
1244 IN DWORD AceFlags,
1245 IN DWORD AccessMask,
1246 IN PSID pSid)
1248 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1250 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1251 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1254 /******************************************************************************
1255 * RtlAddAccessAllowedObjectAce [NTDLL.@]
1257 NTSTATUS WINAPI RtlAddAccessAllowedObjectAce(
1258 IN OUT PACL pAcl,
1259 IN DWORD dwAceRevision,
1260 IN DWORD dwAceFlags,
1261 IN DWORD dwAccessMask,
1262 IN GUID* pObjectTypeGuid,
1263 IN GUID* pInheritedObjectTypeGuid,
1264 IN PSID pSid)
1266 FIXME("%p %x %x %x %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1267 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1268 return STATUS_NOT_IMPLEMENTED;
1271 /******************************************************************************
1272 * RtlAddAccessDeniedAce [NTDLL.@]
1274 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1275 IN OUT PACL pAcl,
1276 IN DWORD dwAceRevision,
1277 IN DWORD AccessMask,
1278 IN PSID pSid)
1280 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1283 /******************************************************************************
1284 * RtlAddAccessDeniedAceEx [NTDLL.@]
1286 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1287 IN OUT PACL pAcl,
1288 IN DWORD dwAceRevision,
1289 IN DWORD AceFlags,
1290 IN DWORD AccessMask,
1291 IN PSID pSid)
1293 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1295 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1296 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1299 /******************************************************************************
1300 * RtlAddAccessDeniedObjectAce [NTDLL.@]
1302 NTSTATUS WINAPI RtlAddAccessDeniedObjectAce(
1303 IN OUT PACL pAcl,
1304 IN DWORD dwAceRevision,
1305 IN DWORD dwAceFlags,
1306 IN DWORD dwAccessMask,
1307 IN GUID* pObjectTypeGuid,
1308 IN GUID* pInheritedObjectTypeGuid,
1309 IN PSID pSid)
1311 FIXME("%p %x %x %x %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1312 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1313 return STATUS_NOT_IMPLEMENTED;
1316 /**************************************************************************
1317 * RtlAddAuditAccessAce [NTDLL.@]
1319 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1320 IN OUT PACL pAcl,
1321 IN DWORD dwAceRevision,
1322 IN DWORD dwAceFlags,
1323 IN DWORD dwAccessMask,
1324 IN PSID pSid,
1325 IN BOOL bAuditSuccess,
1326 IN BOOL bAuditFailure)
1328 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1329 pSid,bAuditSuccess,bAuditFailure);
1331 if (bAuditSuccess)
1332 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1334 if (bAuditFailure)
1335 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1337 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1338 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1341 /**************************************************************************
1342 * RtlAddAuditAccessAce [NTDLL.@]
1344 NTSTATUS WINAPI RtlAddAuditAccessAce(
1345 IN OUT PACL pAcl,
1346 IN DWORD dwAceRevision,
1347 IN DWORD dwAccessMask,
1348 IN PSID pSid,
1349 IN BOOL bAuditSuccess,
1350 IN BOOL bAuditFailure)
1352 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1355 /******************************************************************************
1356 * RtlAddAuditAccessObjectAce [NTDLL.@]
1358 NTSTATUS WINAPI RtlAddAuditAccessObjectAce(
1359 IN OUT PACL pAcl,
1360 IN DWORD dwAceRevision,
1361 IN DWORD dwAceFlags,
1362 IN DWORD dwAccessMask,
1363 IN GUID* pObjectTypeGuid,
1364 IN GUID* pInheritedObjectTypeGuid,
1365 IN PSID pSid,
1366 IN BOOL bAuditSuccess,
1367 IN BOOL bAuditFailure)
1369 FIXME("%p %x %x %x %p %p %p %d %d - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1370 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid, bAuditSuccess, bAuditFailure);
1371 return STATUS_NOT_IMPLEMENTED;
1374 /**************************************************************************
1375 * RtlAddMandatoryAce [NTDLL.@]
1377 NTSTATUS WINAPI RtlAddMandatoryAce(
1378 IN OUT PACL pAcl,
1379 IN DWORD dwAceRevision,
1380 IN DWORD dwAceFlags,
1381 IN DWORD dwMandatoryFlags,
1382 IN DWORD dwAceType,
1383 IN PSID pSid)
1385 static const DWORD valid_flags = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP |
1386 SYSTEM_MANDATORY_LABEL_NO_READ_UP |
1387 SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP;
1389 TRACE("(%p, %u, 0x%08x, 0x%08x, %u, %p)\n", pAcl, dwAceRevision, dwAceFlags,
1390 dwMandatoryFlags, dwAceType, pSid);
1392 if (dwAceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE)
1393 return STATUS_INVALID_PARAMETER;
1395 if (dwMandatoryFlags & ~valid_flags)
1396 return STATUS_INVALID_PARAMETER;
1398 return add_access_ace(pAcl, dwAceRevision, dwAceFlags, dwMandatoryFlags, pSid, dwAceType);
1401 /******************************************************************************
1402 * RtlValidAcl [NTDLL.@]
1404 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1406 BOOLEAN ret;
1407 TRACE("(%p)\n", pAcl);
1409 __TRY
1411 PACE_HEADER ace;
1412 int i;
1414 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1415 pAcl->AclRevision > MAX_ACL_REVISION)
1416 ret = FALSE;
1417 else
1419 ace = (PACE_HEADER)(pAcl+1);
1420 ret = TRUE;
1421 for (i=0;i<=pAcl->AceCount;i++)
1423 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1425 ret = FALSE;
1426 break;
1428 if (i != pAcl->AceCount)
1429 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1433 __EXCEPT_PAGE_FAULT
1435 WARN("(%p): invalid pointer!\n", pAcl);
1436 return FALSE;
1438 __ENDTRY
1439 return ret;
1442 /******************************************************************************
1443 * RtlGetAce [NTDLL.@]
1445 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1447 PACE_HEADER ace;
1449 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1451 if (dwAceIndex >= pAcl->AceCount)
1452 return STATUS_INVALID_PARAMETER;
1454 ace = (PACE_HEADER)(pAcl + 1);
1455 for (;dwAceIndex;dwAceIndex--)
1456 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1458 *pAce = ace;
1460 return STATUS_SUCCESS;
1464 * misc
1467 /******************************************************************************
1468 * RtlAdjustPrivilege [NTDLL.@]
1470 * Enables or disables a privilege from the calling thread or process.
1472 * PARAMS
1473 * Privilege [I] Privilege index to change.
1474 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1475 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1476 * Enabled [O] Whether privilege was previously enabled or disabled.
1478 * RETURNS
1479 * Success: STATUS_SUCCESS.
1480 * Failure: NTSTATUS code.
1482 * SEE ALSO
1483 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1486 NTSTATUS WINAPI
1487 RtlAdjustPrivilege(ULONG Privilege,
1488 BOOLEAN Enable,
1489 BOOLEAN CurrentThread,
1490 PBOOLEAN Enabled)
1492 TOKEN_PRIVILEGES NewState;
1493 TOKEN_PRIVILEGES OldState;
1494 ULONG ReturnLength;
1495 HANDLE TokenHandle;
1496 NTSTATUS Status;
1498 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1499 CurrentThread ? "TRUE" : "FALSE", Enabled);
1501 if (CurrentThread)
1503 Status = NtOpenThreadToken(GetCurrentThread(),
1504 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1505 FALSE,
1506 &TokenHandle);
1508 else
1510 Status = NtOpenProcessToken(GetCurrentProcess(),
1511 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1512 &TokenHandle);
1515 if (Status)
1517 WARN("Retrieving token handle failed (Status %x)\n", Status);
1518 return Status;
1521 OldState.PrivilegeCount = 1;
1523 NewState.PrivilegeCount = 1;
1524 NewState.Privileges[0].Luid.LowPart = Privilege;
1525 NewState.Privileges[0].Luid.HighPart = 0;
1526 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1528 Status = NtAdjustPrivilegesToken(TokenHandle,
1529 FALSE,
1530 &NewState,
1531 sizeof(TOKEN_PRIVILEGES),
1532 &OldState,
1533 &ReturnLength);
1534 NtClose (TokenHandle);
1535 if (Status == STATUS_NOT_ALL_ASSIGNED)
1537 TRACE("Failed to assign all privileges\n");
1538 return STATUS_PRIVILEGE_NOT_HELD;
1540 if (Status)
1542 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1543 return Status;
1546 if (OldState.PrivilegeCount == 0)
1547 *Enabled = Enable;
1548 else
1549 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1551 return STATUS_SUCCESS;
1554 /******************************************************************************
1555 * RtlImpersonateSelf [NTDLL.@]
1557 * Makes an impersonation token that represents the process user and assigns
1558 * to the current thread.
1560 * PARAMS
1561 * ImpersonationLevel [I] Level at which to impersonate.
1563 * RETURNS
1564 * Success: STATUS_SUCCESS.
1565 * Failure: NTSTATUS code.
1567 NTSTATUS WINAPI
1568 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1570 NTSTATUS Status;
1571 OBJECT_ATTRIBUTES ObjectAttributes;
1572 HANDLE ProcessToken;
1573 HANDLE ImpersonationToken;
1575 TRACE("(%08x)\n", ImpersonationLevel);
1577 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1578 &ProcessToken);
1579 if (Status != STATUS_SUCCESS)
1580 return Status;
1582 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1584 Status = NtDuplicateToken( ProcessToken,
1585 TOKEN_IMPERSONATE,
1586 &ObjectAttributes,
1587 ImpersonationLevel,
1588 TokenImpersonation,
1589 &ImpersonationToken );
1590 if (Status != STATUS_SUCCESS)
1592 NtClose( ProcessToken );
1593 return Status;
1596 Status = NtSetInformationThread( GetCurrentThread(),
1597 ThreadImpersonationToken,
1598 &ImpersonationToken,
1599 sizeof(ImpersonationToken) );
1601 NtClose( ImpersonationToken );
1602 NtClose( ProcessToken );
1604 return Status;
1608 /******************************************************************************
1609 * RtlConvertSidToUnicodeString (NTDLL.@)
1611 * The returned SID is used to access the USER registry hive usually
1613 * the native function returns something like
1614 * "S-1-5-21-0000000000-000000000-0000000000-500";
1616 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1617 PUNICODE_STRING String,
1618 PSID pSid,
1619 BOOLEAN AllocateString)
1621 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1622 WCHAR *p = buffer;
1623 const SID *sid = pSid;
1624 DWORD i, len;
1626 *p++ = 'S';
1627 p += swprintf( p, ARRAY_SIZE(buffer) - (p - buffer), L"-%u", sid->Revision );
1628 p += swprintf( p, ARRAY_SIZE(buffer) - (p - buffer), L"-%u",
1629 MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1630 sid->IdentifierAuthority.Value[4] ),
1631 MAKEWORD( sid->IdentifierAuthority.Value[3],
1632 sid->IdentifierAuthority.Value[2] )));
1633 for (i = 0; i < sid->SubAuthorityCount; i++)
1634 p += swprintf( p, ARRAY_SIZE(buffer) - (p - buffer), L"-%u", sid->SubAuthority[i] );
1636 len = (p + 1 - buffer) * sizeof(WCHAR);
1638 String->Length = len - sizeof(WCHAR);
1639 if (AllocateString)
1641 String->MaximumLength = len;
1642 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1643 return STATUS_NO_MEMORY;
1645 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1647 memcpy( String->Buffer, buffer, len );
1648 return STATUS_SUCCESS;
1651 /******************************************************************************
1652 * RtlQueryInformationAcl (NTDLL.@)
1654 NTSTATUS WINAPI RtlQueryInformationAcl(
1655 PACL pAcl,
1656 LPVOID pAclInformation,
1657 DWORD nAclInformationLength,
1658 ACL_INFORMATION_CLASS dwAclInformationClass)
1660 NTSTATUS status = STATUS_SUCCESS;
1662 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1663 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1665 switch (dwAclInformationClass)
1667 case AclRevisionInformation:
1669 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1671 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1672 status = STATUS_INVALID_PARAMETER;
1673 else
1674 paclrev->AclRevision = pAcl->AclRevision;
1676 break;
1679 case AclSizeInformation:
1681 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1683 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1684 status = STATUS_INVALID_PARAMETER;
1685 else
1687 paclsize->AceCount = pAcl->AceCount;
1688 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1689 if (pAcl->AclSize < paclsize->AclBytesInUse)
1691 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1692 paclsize->AclBytesFree = 0;
1693 paclsize->AclBytesInUse = pAcl->AclSize;
1695 else
1696 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1699 break;
1702 default:
1703 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1704 status = STATUS_INVALID_PARAMETER;
1707 return status;
1710 NTSTATUS WINAPI RtlConvertToAutoInheritSecurityObject(
1711 PSECURITY_DESCRIPTOR pdesc,
1712 PSECURITY_DESCRIPTOR cdesc,
1713 PSECURITY_DESCRIPTOR* ndesc,
1714 GUID* objtype,
1715 BOOL isdir,
1716 PGENERIC_MAPPING genmap )
1718 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
1720 return STATUS_NOT_IMPLEMENTED;
1723 /******************************************************************************
1724 * RtlDefaultNpAcl (NTDLL.@)
1726 NTSTATUS WINAPI RtlDefaultNpAcl(PACL *pAcl)
1728 FIXME("%p - stub\n", pAcl);
1730 *pAcl = NULL;
1731 return STATUS_SUCCESS;