dwrite: Fix recently added script properties.
[wine.git] / dlls / ntdll / sec.c
blob3bc52ac158dc0c0f425973beddb8172506270c1f
1 /*
2 * Security functions
4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <ctype.h>
30 #include <math.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
35 #include "ntstatus.h"
36 #define WIN32_NO_STATUS
37 #include "windef.h"
38 #include "ntdll_misc.h"
39 #include "wine/exception.h"
40 #include "wine/library.h"
41 #include "wine/unicode.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
46 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
48 #define SELF_RELATIVE_FIELD(sd,field) ((BYTE *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
50 /* helper function to retrieve active length of an ACL */
51 static size_t acl_bytesInUse(PACL pAcl)
53 int i;
54 size_t bytesInUse = sizeof(ACL);
55 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
56 for (i = 0; i < pAcl->AceCount; i++)
58 bytesInUse += ace->AceSize;
59 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
61 return bytesInUse;
64 /* helper function to copy an ACL */
65 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
67 DWORD size;
69 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
70 return FALSE;
72 size = pSourceAcl->AclSize;
73 if (nDestinationAclLength < size)
74 return FALSE;
76 memmove(pDestinationAcl, pSourceAcl, size);
77 return TRUE;
80 /* generically adds an ACE to an ACL */
81 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
82 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
84 ACE_HEADER *pAceHeader;
85 DWORD dwLengthSid;
86 DWORD dwAceSize;
87 DWORD *pAccessMask;
88 DWORD *pSidStart;
90 if (!RtlValidSid(pSid))
91 return STATUS_INVALID_SID;
93 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
94 return STATUS_REVISION_MISMATCH;
96 if (!RtlValidAcl(pAcl))
97 return STATUS_INVALID_ACL;
99 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
100 return STATUS_INVALID_ACL;
102 if (!pAceHeader)
103 return STATUS_ALLOTTED_SPACE_EXCEEDED;
105 /* calculate generic size of the ACE */
106 dwLengthSid = RtlLengthSid(pSid);
107 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
108 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
109 return STATUS_ALLOTTED_SPACE_EXCEEDED;
111 /* fill the new ACE */
112 pAceHeader->AceType = dwAceType;
113 pAceHeader->AceFlags = dwAceFlags;
114 pAceHeader->AceSize = dwAceSize;
116 /* skip past the ACE_HEADER of the ACE */
117 pAccessMask = (DWORD *)(pAceHeader + 1);
118 *pAccessMask = dwAccessMask;
120 /* skip past ACE->Mask */
121 pSidStart = pAccessMask + 1;
122 RtlCopySid(dwLengthSid, pSidStart, pSid);
124 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
125 pAcl->AceCount++;
127 return STATUS_SUCCESS;
131 * SID FUNCTIONS
134 /******************************************************************************
135 * RtlAllocateAndInitializeSid [NTDLL.@]
138 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
139 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
140 BYTE nSubAuthorityCount,
141 DWORD nSubAuthority0, DWORD nSubAuthority1,
142 DWORD nSubAuthority2, DWORD nSubAuthority3,
143 DWORD nSubAuthority4, DWORD nSubAuthority5,
144 DWORD nSubAuthority6, DWORD nSubAuthority7,
145 PSID *pSid )
147 SID *tmp_sid;
149 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
150 pIdentifierAuthority,nSubAuthorityCount,
151 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
152 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
154 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
156 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
157 RtlLengthRequiredSid(nSubAuthorityCount))))
158 return STATUS_NO_MEMORY;
160 tmp_sid->Revision = SID_REVISION;
162 if (pIdentifierAuthority)
163 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
164 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
166 switch( nSubAuthorityCount )
168 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
169 /* fall through */
170 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
171 /* fall through */
172 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
173 /* fall through */
174 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
175 /* fall through */
176 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
177 /* fall through */
178 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
179 /* fall through */
180 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
181 /* fall through */
182 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
183 break;
185 *pSid = tmp_sid;
186 return STATUS_SUCCESS;
189 /******************************************************************************
190 * RtlEqualSid [NTDLL.@]
192 * Determine if two SIDs are equal.
194 * PARAMS
195 * pSid1 [I] Source SID
196 * pSid2 [I] SID to compare with
198 * RETURNS
199 * TRUE, if pSid1 is equal to pSid2,
200 * FALSE otherwise.
202 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
204 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
205 return FALSE;
207 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
208 return FALSE;
210 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
211 return FALSE;
213 return TRUE;
216 /******************************************************************************
217 * RtlEqualPrefixSid [NTDLL.@]
219 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
221 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
222 return FALSE;
224 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
225 return FALSE;
227 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
228 return FALSE;
230 return TRUE;
234 /******************************************************************************
235 * RtlFreeSid [NTDLL.@]
237 * Free the resources used by a SID.
239 * PARAMS
240 * pSid [I] SID to Free.
242 * RETURNS
243 * STATUS_SUCCESS.
245 DWORD WINAPI RtlFreeSid(PSID pSid)
247 TRACE("(%p)\n", pSid);
248 RtlFreeHeap( GetProcessHeap(), 0, pSid );
249 return STATUS_SUCCESS;
252 /**************************************************************************
253 * RtlLengthRequiredSid [NTDLL.@]
255 * Determine the amount of memory a SID will use
257 * PARAMS
258 * nrofsubauths [I] Number of Sub Authorities in the SID.
260 * RETURNS
261 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
263 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
265 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
268 /**************************************************************************
269 * RtlLengthSid [NTDLL.@]
271 * Determine the amount of memory a SID is using
273 * PARAMS
274 * pSid [I] SID to get the size of.
276 * RETURNS
277 * The size, in bytes, of pSid.
279 DWORD WINAPI RtlLengthSid(PSID pSid)
281 TRACE("sid=%p\n",pSid);
282 if (!pSid) return 0;
283 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
286 /**************************************************************************
287 * RtlInitializeSid [NTDLL.@]
289 * Initialise a SID.
291 * PARAMS
292 * pSid [I] SID to initialise
293 * pIdentifierAuthority [I] Identifier Authority
294 * nSubAuthorityCount [I] Number of Sub Authorities
296 * RETURNS
297 * Success: TRUE. pSid is initialised with the details given.
298 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
300 BOOL WINAPI RtlInitializeSid(
301 PSID pSid,
302 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
303 BYTE nSubAuthorityCount)
305 int i;
306 SID* pisid=pSid;
308 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
309 return FALSE;
311 pisid->Revision = SID_REVISION;
312 pisid->SubAuthorityCount = nSubAuthorityCount;
313 if (pIdentifierAuthority)
314 pisid->IdentifierAuthority = *pIdentifierAuthority;
316 for (i = 0; i < nSubAuthorityCount; i++)
317 *RtlSubAuthoritySid(pSid, i) = 0;
319 return TRUE;
322 /**************************************************************************
323 * RtlSubAuthoritySid [NTDLL.@]
325 * Return the Sub Authority of a SID
327 * PARAMS
328 * pSid [I] SID to get the Sub Authority from.
329 * nSubAuthority [I] Sub Authority number.
331 * RETURNS
332 * A pointer to The Sub Authority value of pSid.
334 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
336 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
339 /**************************************************************************
340 * RtlIdentifierAuthoritySid [NTDLL.@]
342 * Return the Identifier Authority of a SID.
344 * PARAMS
345 * pSid [I] SID to get the Identifier Authority from.
347 * RETURNS
348 * A pointer to the Identifier Authority value of pSid.
350 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
352 return &(((SID*)pSid)->IdentifierAuthority);
355 /**************************************************************************
356 * RtlSubAuthorityCountSid [NTDLL.@]
358 * Get the number of Sub Authorities in a SID.
360 * PARAMS
361 * pSid [I] SID to get the count from.
363 * RETURNS
364 * A pointer to the Sub Authority count of pSid.
366 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
368 return &(((SID*)pSid)->SubAuthorityCount);
371 /**************************************************************************
372 * RtlCopySid [NTDLL.@]
374 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
376 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
377 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
378 return FALSE;
380 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
381 return FALSE;
383 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
384 return TRUE;
386 /******************************************************************************
387 * RtlValidSid [NTDLL.@]
389 * Determine if a SID is valid.
391 * PARAMS
392 * pSid [I] SID to check
394 * RETURNS
395 * TRUE if pSid is valid,
396 * FALSE otherwise.
398 BOOLEAN WINAPI RtlValidSid( PSID pSid )
400 BOOL ret;
401 __TRY
403 ret = TRUE;
404 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
405 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
407 ret = FALSE;
410 __EXCEPT_PAGE_FAULT
412 WARN("(%p): invalid pointer!\n", pSid);
413 return FALSE;
415 __ENDTRY
416 return ret;
421 * security descriptor functions
424 /**************************************************************************
425 * RtlCreateSecurityDescriptor [NTDLL.@]
427 * Initialise a SECURITY_DESCRIPTOR.
429 * PARAMS
430 * lpsd [O] Descriptor to initialise.
431 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
433 * RETURNS
434 * Success: STATUS_SUCCESS.
435 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
437 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
438 PSECURITY_DESCRIPTOR lpsd,
439 DWORD rev)
441 if (rev!=SECURITY_DESCRIPTOR_REVISION)
442 return STATUS_UNKNOWN_REVISION;
443 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
444 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
445 return STATUS_SUCCESS;
448 /**************************************************************************
449 * RtlCopySecurityDescriptor [NTDLL.@]
451 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
453 * PARAMS
454 * pSourceSD [O] SD to copy from.
455 * pDestinationSD [I] Destination SD.
457 * RETURNS
458 * Success: STATUS_SUCCESS.
459 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
461 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
463 PSID Owner, Group;
464 PACL Dacl, Sacl;
465 DWORD length;
467 if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
469 SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
470 SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
472 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
473 return STATUS_UNKNOWN_REVISION;
475 *dst = *src;
476 if (src->Owner)
478 Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
479 length = RtlLengthSid( Owner );
480 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
482 if (src->Group)
484 Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
485 length = RtlLengthSid( Group );
486 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
488 if ((src->Control & SE_SACL_PRESENT) && src->Sacl)
490 Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
491 copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
493 if ((src->Control & SE_DACL_PRESENT) && src->Dacl)
495 Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
496 copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
499 else
501 SECURITY_DESCRIPTOR *src = pSourceSD;
502 SECURITY_DESCRIPTOR *dst = pDestinationSD;
504 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
505 return STATUS_UNKNOWN_REVISION;
507 *dst = *src;
508 if (src->Owner)
510 length = RtlLengthSid( src->Owner );
511 dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
512 RtlCopySid(length, dst->Owner, src->Owner);
514 if (src->Group)
516 length = RtlLengthSid( src->Group );
517 dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
518 RtlCopySid(length, dst->Group, src->Group);
520 if (src->Control & SE_SACL_PRESENT)
522 length = src->Sacl->AclSize;
523 dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
524 copy_acl(length, dst->Sacl, src->Sacl);
526 if (src->Control & SE_DACL_PRESENT)
528 length = src->Dacl->AclSize;
529 dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
530 copy_acl(length, dst->Dacl, src->Dacl);
534 return STATUS_SUCCESS;
537 /**************************************************************************
538 * RtlValidSecurityDescriptor [NTDLL.@]
540 * Determine if a SECURITY_DESCRIPTOR is valid.
542 * PARAMS
543 * SecurityDescriptor [I] Descriptor to check.
545 * RETURNS
546 * Success: STATUS_SUCCESS.
547 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
549 NTSTATUS WINAPI RtlValidSecurityDescriptor(
550 PSECURITY_DESCRIPTOR SecurityDescriptor)
552 if ( ! SecurityDescriptor )
553 return STATUS_INVALID_SECURITY_DESCR;
554 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
555 return STATUS_UNKNOWN_REVISION;
557 return STATUS_SUCCESS;
560 /**************************************************************************
561 * RtlValidRelativeSecurityDescriptor [NTDLL.@]
563 BOOLEAN WINAPI RtlValidRelativeSecurityDescriptor(PSECURITY_DESCRIPTOR descriptor,
564 ULONG length, SECURITY_INFORMATION info)
566 FIXME("%p,%u,%d: semi-stub\n", descriptor, length, info);
567 return RtlValidSecurityDescriptor(descriptor) == STATUS_SUCCESS;
570 /**************************************************************************
571 * RtlLengthSecurityDescriptor [NTDLL.@]
573 ULONG WINAPI RtlLengthSecurityDescriptor(
574 PSECURITY_DESCRIPTOR pSecurityDescriptor)
576 ULONG size;
578 if ( pSecurityDescriptor == NULL )
579 return 0;
581 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
583 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
584 size = sizeof(*sd);
585 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
586 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
587 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
588 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
589 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
590 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
592 else
594 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
595 size = sizeof(*sd);
596 if (sd->Owner) size += RtlLengthSid( sd->Owner );
597 if (sd->Group) size += RtlLengthSid( sd->Group );
598 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
599 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
601 return size;
604 /******************************************************************************
605 * RtlGetDaclSecurityDescriptor [NTDLL.@]
608 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
609 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
610 OUT PBOOLEAN lpbDaclPresent,
611 OUT PACL *pDacl,
612 OUT PBOOLEAN lpbDaclDefaulted)
614 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
616 TRACE("(%p,%p,%p,%p)\n",
617 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
619 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
620 return STATUS_UNKNOWN_REVISION ;
622 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
624 if (lpsd->Control & SE_SELF_RELATIVE)
626 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
627 if (sdr->Dacl) *pDacl = (PACL)SELF_RELATIVE_FIELD( sdr, Dacl );
628 else *pDacl = NULL;
630 else *pDacl = lpsd->Dacl;
632 *lpbDaclDefaulted = (lpsd->Control & SE_DACL_DEFAULTED) != 0;
634 else
636 *pDacl = NULL;
637 *lpbDaclDefaulted = 0;
640 return STATUS_SUCCESS;
643 /**************************************************************************
644 * RtlSetDaclSecurityDescriptor [NTDLL.@]
646 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
647 PSECURITY_DESCRIPTOR pSecurityDescriptor,
648 BOOLEAN daclpresent,
649 PACL dacl,
650 BOOLEAN dacldefaulted )
652 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
654 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
655 return STATUS_UNKNOWN_REVISION;
656 if (lpsd->Control & SE_SELF_RELATIVE)
657 return STATUS_INVALID_SECURITY_DESCR;
659 if (!daclpresent)
661 lpsd->Control &= ~SE_DACL_PRESENT;
662 return STATUS_SUCCESS;
665 lpsd->Control |= SE_DACL_PRESENT;
666 lpsd->Dacl = dacl;
668 if (dacldefaulted)
669 lpsd->Control |= SE_DACL_DEFAULTED;
670 else
671 lpsd->Control &= ~SE_DACL_DEFAULTED;
673 return STATUS_SUCCESS;
676 /******************************************************************************
677 * RtlGetSaclSecurityDescriptor [NTDLL.@]
680 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
681 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
682 OUT PBOOLEAN lpbSaclPresent,
683 OUT PACL *pSacl,
684 OUT PBOOLEAN lpbSaclDefaulted)
686 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
688 TRACE("(%p,%p,%p,%p)\n",
689 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
691 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
692 return STATUS_UNKNOWN_REVISION;
694 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
696 if (lpsd->Control & SE_SELF_RELATIVE)
698 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
699 if (sdr->Sacl) *pSacl = (PACL)SELF_RELATIVE_FIELD( sdr, Sacl );
700 else *pSacl = NULL;
702 else *pSacl = lpsd->Sacl;
704 *lpbSaclDefaulted = (lpsd->Control & SE_SACL_DEFAULTED) != 0;
706 return STATUS_SUCCESS;
709 /**************************************************************************
710 * RtlSetSaclSecurityDescriptor [NTDLL.@]
712 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
713 PSECURITY_DESCRIPTOR pSecurityDescriptor,
714 BOOLEAN saclpresent,
715 PACL sacl,
716 BOOLEAN sacldefaulted)
718 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
720 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
721 return STATUS_UNKNOWN_REVISION;
722 if (lpsd->Control & SE_SELF_RELATIVE)
723 return STATUS_INVALID_SECURITY_DESCR;
724 if (!saclpresent) {
725 lpsd->Control &= ~SE_SACL_PRESENT;
726 return 0;
728 lpsd->Control |= SE_SACL_PRESENT;
729 lpsd->Sacl = sacl;
730 if (sacldefaulted)
731 lpsd->Control |= SE_SACL_DEFAULTED;
732 else
733 lpsd->Control &= ~SE_SACL_DEFAULTED;
734 return STATUS_SUCCESS;
737 /**************************************************************************
738 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
740 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
741 PSECURITY_DESCRIPTOR pSecurityDescriptor,
742 PSID *Owner,
743 PBOOLEAN OwnerDefaulted)
745 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
747 if ( !lpsd || !Owner || !OwnerDefaulted )
748 return STATUS_INVALID_PARAMETER;
750 if ( lpsd->Control & SE_OWNER_DEFAULTED )
751 *OwnerDefaulted = TRUE;
752 else
753 *OwnerDefaulted = FALSE;
755 if (lpsd->Control & SE_SELF_RELATIVE)
757 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
758 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
759 else *Owner = NULL;
761 else
762 *Owner = lpsd->Owner;
764 return STATUS_SUCCESS;
767 /**************************************************************************
768 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
770 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
771 PSECURITY_DESCRIPTOR pSecurityDescriptor,
772 PSID owner,
773 BOOLEAN ownerdefaulted)
775 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
777 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
778 return STATUS_UNKNOWN_REVISION;
779 if (lpsd->Control & SE_SELF_RELATIVE)
780 return STATUS_INVALID_SECURITY_DESCR;
782 lpsd->Owner = owner;
783 if (ownerdefaulted)
784 lpsd->Control |= SE_OWNER_DEFAULTED;
785 else
786 lpsd->Control &= ~SE_OWNER_DEFAULTED;
787 return STATUS_SUCCESS;
790 /**************************************************************************
791 * RtlSetGroupSecurityDescriptor [NTDLL.@]
793 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
794 PSECURITY_DESCRIPTOR pSecurityDescriptor,
795 PSID group,
796 BOOLEAN groupdefaulted)
798 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
800 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
801 return STATUS_UNKNOWN_REVISION;
802 if (lpsd->Control & SE_SELF_RELATIVE)
803 return STATUS_INVALID_SECURITY_DESCR;
805 lpsd->Group = group;
806 if (groupdefaulted)
807 lpsd->Control |= SE_GROUP_DEFAULTED;
808 else
809 lpsd->Control &= ~SE_GROUP_DEFAULTED;
810 return STATUS_SUCCESS;
813 /**************************************************************************
814 * RtlGetGroupSecurityDescriptor [NTDLL.@]
816 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
817 PSECURITY_DESCRIPTOR pSecurityDescriptor,
818 PSID *Group,
819 PBOOLEAN GroupDefaulted)
821 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
823 if ( !lpsd || !Group || !GroupDefaulted )
824 return STATUS_INVALID_PARAMETER;
826 if ( lpsd->Control & SE_GROUP_DEFAULTED )
827 *GroupDefaulted = TRUE;
828 else
829 *GroupDefaulted = FALSE;
831 if (lpsd->Control & SE_SELF_RELATIVE)
833 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
834 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
835 else *Group = NULL;
837 else
838 *Group = lpsd->Group;
840 return STATUS_SUCCESS;
843 /**************************************************************************
844 * RtlMakeSelfRelativeSD [NTDLL.@]
846 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
847 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
848 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
849 IN OUT LPDWORD lpdwBufferLength)
851 DWORD offsetRel;
852 ULONG length;
853 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
854 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
856 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
857 lpdwBufferLength ? *lpdwBufferLength: -1);
859 if (!lpdwBufferLength || !pAbs)
860 return STATUS_INVALID_PARAMETER;
862 length = RtlLengthSecurityDescriptor(pAbs);
863 if (*lpdwBufferLength < length)
865 *lpdwBufferLength = length;
866 return STATUS_BUFFER_TOO_SMALL;
869 if (!pRel)
870 return STATUS_INVALID_PARAMETER;
872 if (pAbs->Control & SE_SELF_RELATIVE)
874 memcpy(pRel, pAbs, length);
875 return STATUS_SUCCESS;
878 pRel->Revision = pAbs->Revision;
879 pRel->Sbz1 = pAbs->Sbz1;
880 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
882 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
883 if (pAbs->Owner)
885 pRel->Owner = offsetRel;
886 length = RtlLengthSid(pAbs->Owner);
887 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
888 offsetRel += length;
890 else
892 pRel->Owner = 0;
895 if (pAbs->Group)
897 pRel->Group = offsetRel;
898 length = RtlLengthSid(pAbs->Group);
899 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
900 offsetRel += length;
902 else
904 pRel->Group = 0;
907 if (pAbs->Sacl)
909 pRel->Sacl = offsetRel;
910 length = pAbs->Sacl->AclSize;
911 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
912 offsetRel += length;
914 else
916 pRel->Sacl = 0;
919 if (pAbs->Dacl)
921 pRel->Dacl = offsetRel;
922 length = pAbs->Dacl->AclSize;
923 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
925 else
927 pRel->Dacl = 0;
930 return STATUS_SUCCESS;
934 /**************************************************************************
935 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
937 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
938 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
939 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
940 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
941 OUT PACL pDacl,
942 OUT LPDWORD lpdwDaclSize,
943 OUT PACL pSacl,
944 OUT LPDWORD lpdwSaclSize,
945 OUT PSID pOwner,
946 OUT LPDWORD lpdwOwnerSize,
947 OUT PSID pPrimaryGroup,
948 OUT LPDWORD lpdwPrimaryGroupSize)
950 NTSTATUS status = STATUS_SUCCESS;
951 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
952 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
954 if (!pRel ||
955 !lpdwAbsoluteSecurityDescriptorSize ||
956 !lpdwDaclSize ||
957 !lpdwSaclSize ||
958 !lpdwOwnerSize ||
959 !lpdwPrimaryGroupSize ||
960 ~pRel->Control & SE_SELF_RELATIVE)
961 return STATUS_INVALID_PARAMETER;
963 /* Confirm buffers are sufficiently large */
964 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
966 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
967 status = STATUS_BUFFER_TOO_SMALL;
970 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
971 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
973 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
974 status = STATUS_BUFFER_TOO_SMALL;
977 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
978 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
980 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
981 status = STATUS_BUFFER_TOO_SMALL;
984 if (pRel->Owner &&
985 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
987 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
988 status = STATUS_BUFFER_TOO_SMALL;
991 if (pRel->Group &&
992 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
994 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
995 status = STATUS_BUFFER_TOO_SMALL;
998 if (status != STATUS_SUCCESS)
999 return status;
1001 /* Copy structures, and clear the ones we don't set */
1002 pAbs->Revision = pRel->Revision;
1003 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
1004 pAbs->Sacl = NULL;
1005 pAbs->Dacl = NULL;
1006 pAbs->Owner = NULL;
1007 pAbs->Group = NULL;
1009 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
1011 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
1013 memcpy(pSacl, pAcl, pAcl->AclSize);
1014 pAbs->Sacl = pSacl;
1017 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1019 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1020 memcpy(pDacl, pAcl, pAcl->AclSize);
1021 pAbs->Dacl = pDacl;
1024 if (pRel->Owner)
1026 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1027 memcpy(pOwner, psid, RtlLengthSid(psid));
1028 pAbs->Owner = pOwner;
1031 if (pRel->Group)
1033 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1034 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1035 pAbs->Group = pPrimaryGroup;
1038 return status;
1041 /******************************************************************************
1042 * RtlGetControlSecurityDescriptor (NTDLL.@)
1044 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1045 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1046 PSECURITY_DESCRIPTOR_CONTROL pControl,
1047 LPDWORD lpdwRevision)
1049 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1051 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1053 *lpdwRevision = lpsd->Revision;
1055 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1056 return STATUS_UNKNOWN_REVISION;
1058 *pControl = lpsd->Control;
1060 return STATUS_SUCCESS;
1063 /******************************************************************************
1064 * RtlSetControlSecurityDescriptor (NTDLL.@)
1066 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1067 PSECURITY_DESCRIPTOR SecurityDescriptor,
1068 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1069 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1071 SECURITY_DESCRIPTOR_CONTROL const immutable
1072 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1073 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1074 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1075 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1078 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1080 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1081 ControlBitsOfInterest, ControlBitsToSet);
1083 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1084 return STATUS_INVALID_PARAMETER;
1086 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1087 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1089 return STATUS_SUCCESS;
1093 /**************************************************************************
1094 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1096 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1097 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1098 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1099 PULONG BufferLength)
1101 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1103 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1104 SelfRelativeSecurityDescriptor, BufferLength);
1106 if (abs->Control & SE_SELF_RELATIVE)
1107 return STATUS_BAD_DESCRIPTOR_FORMAT;
1109 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1110 SelfRelativeSecurityDescriptor, BufferLength);
1115 * access control list's
1118 /**************************************************************************
1119 * RtlCreateAcl [NTDLL.@]
1121 * NOTES
1122 * This should return NTSTATUS
1124 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1126 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1128 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1129 return STATUS_INVALID_PARAMETER;
1130 if (size<sizeof(ACL))
1131 return STATUS_BUFFER_TOO_SMALL;
1132 if (size>0xFFFF)
1133 return STATUS_INVALID_PARAMETER;
1135 memset(acl,'\0',sizeof(ACL));
1136 acl->AclRevision = rev;
1137 acl->AclSize = size;
1138 acl->AceCount = 0;
1139 return STATUS_SUCCESS;
1142 /**************************************************************************
1143 * RtlFirstFreeAce [NTDLL.@]
1144 * looks for the AceCount+1 ACE, and if it is still within the alloced
1145 * ACL, return a pointer to it
1147 BOOLEAN WINAPI RtlFirstFreeAce(
1148 PACL acl,
1149 PACE_HEADER *x)
1151 PACE_HEADER ace;
1152 int i;
1154 *x = 0;
1155 ace = (PACE_HEADER)(acl+1);
1156 for (i=0;i<acl->AceCount;i++) {
1157 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1158 return FALSE;
1159 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1161 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1162 return FALSE;
1163 *x = ace;
1164 return TRUE;
1167 /**************************************************************************
1168 * RtlAddAce [NTDLL.@]
1170 NTSTATUS WINAPI RtlAddAce(
1171 PACL acl,
1172 DWORD rev,
1173 DWORD xnrofaces,
1174 PACE_HEADER acestart,
1175 DWORD acelen)
1177 PACE_HEADER ace,targetace;
1178 int nrofaces;
1180 if (!RtlValidAcl(acl))
1181 return STATUS_INVALID_PARAMETER;
1182 if (!RtlFirstFreeAce(acl,&targetace))
1183 return STATUS_INVALID_PARAMETER;
1184 nrofaces=0;ace=acestart;
1185 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1186 nrofaces++;
1187 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1189 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1190 return STATUS_INVALID_PARAMETER;
1191 memcpy(targetace,acestart,acelen);
1192 acl->AceCount+=nrofaces;
1193 if (rev > acl->AclRevision)
1194 acl->AclRevision = rev;
1195 return STATUS_SUCCESS;
1198 /**************************************************************************
1199 * RtlDeleteAce [NTDLL.@]
1201 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1203 NTSTATUS status;
1204 PACE_HEADER pAce;
1206 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1208 if (STATUS_SUCCESS == status)
1210 PACE_HEADER pcAce;
1211 DWORD len = 0;
1213 /* skip over the ACE we are deleting */
1214 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1215 dwAceIndex++;
1217 /* calculate the length of the rest */
1218 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1220 len += pcAce->AceSize;
1221 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1224 /* slide them all backwards */
1225 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1226 pAcl->AceCount--;
1229 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1231 return status;
1234 /******************************************************************************
1235 * RtlAddAccessAllowedAce [NTDLL.@]
1237 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1238 IN OUT PACL pAcl,
1239 IN DWORD dwAceRevision,
1240 IN DWORD AccessMask,
1241 IN PSID pSid)
1243 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1246 /******************************************************************************
1247 * RtlAddAccessAllowedAceEx [NTDLL.@]
1249 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1250 IN OUT PACL pAcl,
1251 IN DWORD dwAceRevision,
1252 IN DWORD AceFlags,
1253 IN DWORD AccessMask,
1254 IN PSID pSid)
1256 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1258 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1259 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1262 /******************************************************************************
1263 * RtlAddAccessAllowedObjectAce [NTDLL.@]
1265 NTSTATUS WINAPI RtlAddAccessAllowedObjectAce(
1266 IN OUT PACL pAcl,
1267 IN DWORD dwAceRevision,
1268 IN DWORD dwAceFlags,
1269 IN DWORD dwAccessMask,
1270 IN GUID* pObjectTypeGuid,
1271 IN GUID* pInheritedObjectTypeGuid,
1272 IN PSID pSid)
1274 FIXME("%p %x %x %x %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1275 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1276 return STATUS_NOT_IMPLEMENTED;
1279 /******************************************************************************
1280 * RtlAddAccessDeniedAce [NTDLL.@]
1282 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1283 IN OUT PACL pAcl,
1284 IN DWORD dwAceRevision,
1285 IN DWORD AccessMask,
1286 IN PSID pSid)
1288 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1291 /******************************************************************************
1292 * RtlAddAccessDeniedAceEx [NTDLL.@]
1294 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1295 IN OUT PACL pAcl,
1296 IN DWORD dwAceRevision,
1297 IN DWORD AceFlags,
1298 IN DWORD AccessMask,
1299 IN PSID pSid)
1301 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1303 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1304 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1307 /******************************************************************************
1308 * RtlAddAccessDeniedObjectAce [NTDLL.@]
1310 NTSTATUS WINAPI RtlAddAccessDeniedObjectAce(
1311 IN OUT PACL pAcl,
1312 IN DWORD dwAceRevision,
1313 IN DWORD dwAceFlags,
1314 IN DWORD dwAccessMask,
1315 IN GUID* pObjectTypeGuid,
1316 IN GUID* pInheritedObjectTypeGuid,
1317 IN PSID pSid)
1319 FIXME("%p %x %x %x %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1320 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1321 return STATUS_NOT_IMPLEMENTED;
1324 /**************************************************************************
1325 * RtlAddAuditAccessAce [NTDLL.@]
1327 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1328 IN OUT PACL pAcl,
1329 IN DWORD dwAceRevision,
1330 IN DWORD dwAceFlags,
1331 IN DWORD dwAccessMask,
1332 IN PSID pSid,
1333 IN BOOL bAuditSuccess,
1334 IN BOOL bAuditFailure)
1336 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1337 pSid,bAuditSuccess,bAuditFailure);
1339 if (bAuditSuccess)
1340 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1342 if (bAuditFailure)
1343 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1345 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1346 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1349 /**************************************************************************
1350 * RtlAddAuditAccessAce [NTDLL.@]
1352 NTSTATUS WINAPI RtlAddAuditAccessAce(
1353 IN OUT PACL pAcl,
1354 IN DWORD dwAceRevision,
1355 IN DWORD dwAccessMask,
1356 IN PSID pSid,
1357 IN BOOL bAuditSuccess,
1358 IN BOOL bAuditFailure)
1360 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1363 /******************************************************************************
1364 * RtlAddAuditAccessObjectAce [NTDLL.@]
1366 NTSTATUS WINAPI RtlAddAuditAccessObjectAce(
1367 IN OUT PACL pAcl,
1368 IN DWORD dwAceRevision,
1369 IN DWORD dwAceFlags,
1370 IN DWORD dwAccessMask,
1371 IN GUID* pObjectTypeGuid,
1372 IN GUID* pInheritedObjectTypeGuid,
1373 IN PSID pSid,
1374 IN BOOL bAuditSuccess,
1375 IN BOOL bAuditFailure)
1377 FIXME("%p %x %x %x %p %p %p %d %d - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1378 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid, bAuditSuccess, bAuditFailure);
1379 return STATUS_NOT_IMPLEMENTED;
1382 /******************************************************************************
1383 * RtlValidAcl [NTDLL.@]
1385 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1387 BOOLEAN ret;
1388 TRACE("(%p)\n", pAcl);
1390 __TRY
1392 PACE_HEADER ace;
1393 int i;
1395 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1396 pAcl->AclRevision > MAX_ACL_REVISION)
1397 ret = FALSE;
1398 else
1400 ace = (PACE_HEADER)(pAcl+1);
1401 ret = TRUE;
1402 for (i=0;i<=pAcl->AceCount;i++)
1404 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1406 ret = FALSE;
1407 break;
1409 if (i != pAcl->AceCount)
1410 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1414 __EXCEPT_PAGE_FAULT
1416 WARN("(%p): invalid pointer!\n", pAcl);
1417 return FALSE;
1419 __ENDTRY
1420 return ret;
1423 /******************************************************************************
1424 * RtlGetAce [NTDLL.@]
1426 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1428 PACE_HEADER ace;
1430 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1432 if (dwAceIndex >= pAcl->AceCount)
1433 return STATUS_INVALID_PARAMETER;
1435 ace = (PACE_HEADER)(pAcl + 1);
1436 for (;dwAceIndex;dwAceIndex--)
1437 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1439 *pAce = ace;
1441 return STATUS_SUCCESS;
1445 * misc
1448 /******************************************************************************
1449 * RtlAdjustPrivilege [NTDLL.@]
1451 * Enables or disables a privilege from the calling thread or process.
1453 * PARAMS
1454 * Privilege [I] Privilege index to change.
1455 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1456 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1457 * Enabled [O] Whether privilege was previously enabled or disabled.
1459 * RETURNS
1460 * Success: STATUS_SUCCESS.
1461 * Failure: NTSTATUS code.
1463 * SEE ALSO
1464 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1467 NTSTATUS WINAPI
1468 RtlAdjustPrivilege(ULONG Privilege,
1469 BOOLEAN Enable,
1470 BOOLEAN CurrentThread,
1471 PBOOLEAN Enabled)
1473 TOKEN_PRIVILEGES NewState;
1474 TOKEN_PRIVILEGES OldState;
1475 ULONG ReturnLength;
1476 HANDLE TokenHandle;
1477 NTSTATUS Status;
1479 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1480 CurrentThread ? "TRUE" : "FALSE", Enabled);
1482 if (CurrentThread)
1484 Status = NtOpenThreadToken(GetCurrentThread(),
1485 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1486 FALSE,
1487 &TokenHandle);
1489 else
1491 Status = NtOpenProcessToken(GetCurrentProcess(),
1492 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1493 &TokenHandle);
1496 if (!NT_SUCCESS(Status))
1498 WARN("Retrieving token handle failed (Status %x)\n", Status);
1499 return Status;
1502 OldState.PrivilegeCount = 1;
1504 NewState.PrivilegeCount = 1;
1505 NewState.Privileges[0].Luid.LowPart = Privilege;
1506 NewState.Privileges[0].Luid.HighPart = 0;
1507 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1509 Status = NtAdjustPrivilegesToken(TokenHandle,
1510 FALSE,
1511 &NewState,
1512 sizeof(TOKEN_PRIVILEGES),
1513 &OldState,
1514 &ReturnLength);
1515 NtClose (TokenHandle);
1516 if (Status == STATUS_NOT_ALL_ASSIGNED)
1518 TRACE("Failed to assign all privileges\n");
1519 return STATUS_PRIVILEGE_NOT_HELD;
1521 if (!NT_SUCCESS(Status))
1523 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1524 return Status;
1527 if (OldState.PrivilegeCount == 0)
1528 *Enabled = Enable;
1529 else
1530 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1532 return STATUS_SUCCESS;
1535 /******************************************************************************
1536 * RtlImpersonateSelf [NTDLL.@]
1538 * Makes an impersonation token that represents the process user and assigns
1539 * to the current thread.
1541 * PARAMS
1542 * ImpersonationLevel [I] Level at which to impersonate.
1544 * RETURNS
1545 * Success: STATUS_SUCCESS.
1546 * Failure: NTSTATUS code.
1548 NTSTATUS WINAPI
1549 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1551 NTSTATUS Status;
1552 OBJECT_ATTRIBUTES ObjectAttributes;
1553 HANDLE ProcessToken;
1554 HANDLE ImpersonationToken;
1556 TRACE("(%08x)\n", ImpersonationLevel);
1558 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1559 &ProcessToken);
1560 if (Status != STATUS_SUCCESS)
1561 return Status;
1563 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1565 Status = NtDuplicateToken( ProcessToken,
1566 TOKEN_IMPERSONATE,
1567 &ObjectAttributes,
1568 ImpersonationLevel,
1569 TokenImpersonation,
1570 &ImpersonationToken );
1571 if (Status != STATUS_SUCCESS)
1573 NtClose( ProcessToken );
1574 return Status;
1577 Status = NtSetInformationThread( GetCurrentThread(),
1578 ThreadImpersonationToken,
1579 &ImpersonationToken,
1580 sizeof(ImpersonationToken) );
1582 NtClose( ImpersonationToken );
1583 NtClose( ProcessToken );
1585 return Status;
1588 /******************************************************************************
1589 * NtImpersonateAnonymousToken [NTDLL.@]
1591 NTSTATUS WINAPI
1592 NtImpersonateAnonymousToken(HANDLE thread)
1594 FIXME("(%p): stub\n", thread);
1595 return STATUS_NOT_IMPLEMENTED;
1598 /******************************************************************************
1599 * NtAccessCheck [NTDLL.@]
1600 * ZwAccessCheck [NTDLL.@]
1602 * Checks that a user represented by a token is allowed to access an object
1603 * represented by a security descriptor.
1605 * PARAMS
1606 * SecurityDescriptor [I] The security descriptor of the object to check.
1607 * ClientToken [I] Token of the user accessing the object.
1608 * DesiredAccess [I] The desired access to the object.
1609 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1610 * PrivilegeSet [I/O] Privileges used during the access check.
1611 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1612 * GrantedAccess [O] The actual access rights granted.
1613 * AccessStatus [O] The status of the access check.
1615 * RETURNS
1616 * NTSTATUS code.
1618 * NOTES
1619 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1620 * the maximum access rights allowed by the SD and returns them in
1621 * GrantedAccess.
1622 * The SecurityDescriptor must have a valid owner and groups present,
1623 * otherwise the function will fail.
1625 NTSTATUS WINAPI
1626 NtAccessCheck(
1627 PSECURITY_DESCRIPTOR SecurityDescriptor,
1628 HANDLE ClientToken,
1629 ACCESS_MASK DesiredAccess,
1630 PGENERIC_MAPPING GenericMapping,
1631 PPRIVILEGE_SET PrivilegeSet,
1632 PULONG ReturnLength,
1633 PULONG GrantedAccess,
1634 NTSTATUS *AccessStatus)
1636 NTSTATUS status;
1638 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1639 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1640 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1642 if (!PrivilegeSet || !ReturnLength)
1643 return STATUS_ACCESS_VIOLATION;
1645 SERVER_START_REQ( access_check )
1647 struct security_descriptor sd;
1648 PSID owner;
1649 PSID group;
1650 PACL sacl;
1651 PACL dacl;
1652 BOOLEAN defaulted, present;
1653 DWORD revision;
1654 SECURITY_DESCRIPTOR_CONTROL control;
1656 req->handle = wine_server_obj_handle( ClientToken );
1657 req->desired_access = DesiredAccess;
1658 req->mapping_read = GenericMapping->GenericRead;
1659 req->mapping_write = GenericMapping->GenericWrite;
1660 req->mapping_execute = GenericMapping->GenericExecute;
1661 req->mapping_all = GenericMapping->GenericAll;
1663 /* marshal security descriptor */
1664 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1665 sd.control = control & ~SE_SELF_RELATIVE;
1666 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1667 sd.owner_len = RtlLengthSid( owner );
1668 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1669 sd.group_len = RtlLengthSid( group );
1670 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1671 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1672 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1673 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1675 wine_server_add_data( req, &sd, sizeof(sd) );
1676 wine_server_add_data( req, owner, sd.owner_len );
1677 wine_server_add_data( req, group, sd.group_len );
1678 wine_server_add_data( req, sacl, sd.sacl_len );
1679 wine_server_add_data( req, dacl, sd.dacl_len );
1681 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1683 status = wine_server_call( req );
1685 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1686 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1688 if (status == STATUS_SUCCESS)
1690 *AccessStatus = reply->access_status;
1691 *GrantedAccess = reply->access_granted;
1694 SERVER_END_REQ;
1696 return status;
1699 /******************************************************************************
1700 * NtSetSecurityObject [NTDLL.@]
1701 * ZwSetSecurityObject [NTDLL.@]
1703 * Sets specified parts of the object's security descriptor.
1705 * PARAMS
1706 * Handle [I] Handle to the object to change security descriptor of.
1707 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1708 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1710 * RETURNS
1711 * NTSTATUS code.
1714 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1715 SECURITY_INFORMATION SecurityInformation,
1716 PSECURITY_DESCRIPTOR SecurityDescriptor)
1718 NTSTATUS status;
1719 struct security_descriptor sd;
1720 PACL dacl = NULL, sacl = NULL;
1721 PSID owner = NULL, group = NULL;
1722 BOOLEAN defaulted, present;
1723 DWORD revision;
1724 SECURITY_DESCRIPTOR_CONTROL control;
1726 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1728 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1730 memset( &sd, 0, sizeof(sd) );
1731 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1732 if (status != STATUS_SUCCESS) return status;
1733 sd.control = control & ~SE_SELF_RELATIVE;
1735 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1737 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1738 if (status != STATUS_SUCCESS) return status;
1739 if (!(sd.owner_len = RtlLengthSid( owner )))
1740 return STATUS_INVALID_SECURITY_DESCR;
1743 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1745 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1746 if (status != STATUS_SUCCESS) return status;
1747 if (!(sd.group_len = RtlLengthSid( group )))
1748 return STATUS_INVALID_SECURITY_DESCR;
1751 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1753 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1754 if (status != STATUS_SUCCESS) return status;
1755 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1756 sd.control |= SE_SACL_PRESENT;
1759 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1761 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1762 if (status != STATUS_SUCCESS) return status;
1763 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1764 sd.control |= SE_DACL_PRESENT;
1767 SERVER_START_REQ( set_security_object )
1769 req->handle = wine_server_obj_handle( Handle );
1770 req->security_info = SecurityInformation;
1772 wine_server_add_data( req, &sd, sizeof(sd) );
1773 wine_server_add_data( req, owner, sd.owner_len );
1774 wine_server_add_data( req, group, sd.group_len );
1775 wine_server_add_data( req, sacl, sd.sacl_len );
1776 wine_server_add_data( req, dacl, sd.dacl_len );
1777 status = wine_server_call( req );
1779 SERVER_END_REQ;
1781 return status;
1784 /******************************************************************************
1785 * RtlConvertSidToUnicodeString (NTDLL.@)
1787 * The returned SID is used to access the USER registry hive usually
1789 * the native function returns something like
1790 * "S-1-5-21-0000000000-000000000-0000000000-500";
1792 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1793 PUNICODE_STRING String,
1794 PSID pSid,
1795 BOOLEAN AllocateString)
1797 static const WCHAR formatW[] = {'-','%','u',0};
1798 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1799 WCHAR *p = buffer;
1800 const SID *sid = pSid;
1801 DWORD i, len;
1803 *p++ = 'S';
1804 p += sprintfW( p, formatW, sid->Revision );
1805 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1806 sid->IdentifierAuthority.Value[4] ),
1807 MAKEWORD( sid->IdentifierAuthority.Value[3],
1808 sid->IdentifierAuthority.Value[2] )));
1809 for (i = 0; i < sid->SubAuthorityCount; i++)
1810 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1812 len = (p + 1 - buffer) * sizeof(WCHAR);
1814 String->Length = len - sizeof(WCHAR);
1815 if (AllocateString)
1817 String->MaximumLength = len;
1818 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1819 return STATUS_NO_MEMORY;
1821 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1823 memcpy( String->Buffer, buffer, len );
1824 return STATUS_SUCCESS;
1827 /******************************************************************************
1828 * RtlQueryInformationAcl (NTDLL.@)
1830 NTSTATUS WINAPI RtlQueryInformationAcl(
1831 PACL pAcl,
1832 LPVOID pAclInformation,
1833 DWORD nAclInformationLength,
1834 ACL_INFORMATION_CLASS dwAclInformationClass)
1836 NTSTATUS status = STATUS_SUCCESS;
1838 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1839 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1841 switch (dwAclInformationClass)
1843 case AclRevisionInformation:
1845 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1847 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1848 status = STATUS_INVALID_PARAMETER;
1849 else
1850 paclrev->AclRevision = pAcl->AclRevision;
1852 break;
1855 case AclSizeInformation:
1857 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1859 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1860 status = STATUS_INVALID_PARAMETER;
1861 else
1863 paclsize->AceCount = pAcl->AceCount;
1864 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1865 if (pAcl->AclSize < paclsize->AclBytesInUse)
1867 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1868 paclsize->AclBytesFree = 0;
1869 paclsize->AclBytesInUse = pAcl->AclSize;
1871 else
1872 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1875 break;
1878 default:
1879 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1880 status = STATUS_INVALID_PARAMETER;
1883 return status;
1886 BOOL WINAPI RtlConvertToAutoInheritSecurityObject(
1887 PSECURITY_DESCRIPTOR pdesc,
1888 PSECURITY_DESCRIPTOR cdesc,
1889 PSECURITY_DESCRIPTOR* ndesc,
1890 GUID* objtype,
1891 BOOL isdir,
1892 PGENERIC_MAPPING genmap )
1894 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
1896 return FALSE;