riched20: Implement GetForeColor().
[wine.git] / dlls / ntdll / sec.c
blob09177805ac1a1d7d3d92706dc7f0b96dd6444235
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 * 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 (*lpdwBufferLength < length)
855 *lpdwBufferLength = length;
856 return STATUS_BUFFER_TOO_SMALL;
859 if (!pRel)
860 return STATUS_INVALID_PARAMETER;
862 if (pAbs->Control & SE_SELF_RELATIVE)
864 memcpy(pRel, pAbs, length);
865 return STATUS_SUCCESS;
868 pRel->Revision = pAbs->Revision;
869 pRel->Sbz1 = pAbs->Sbz1;
870 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
872 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
873 if (pAbs->Owner)
875 pRel->Owner = offsetRel;
876 length = RtlLengthSid(pAbs->Owner);
877 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
878 offsetRel += length;
880 else
882 pRel->Owner = 0;
885 if (pAbs->Group)
887 pRel->Group = offsetRel;
888 length = RtlLengthSid(pAbs->Group);
889 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
890 offsetRel += length;
892 else
894 pRel->Group = 0;
897 if (pAbs->Sacl)
899 pRel->Sacl = offsetRel;
900 length = pAbs->Sacl->AclSize;
901 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
902 offsetRel += length;
904 else
906 pRel->Sacl = 0;
909 if (pAbs->Dacl)
911 pRel->Dacl = offsetRel;
912 length = pAbs->Dacl->AclSize;
913 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
915 else
917 pRel->Dacl = 0;
920 return STATUS_SUCCESS;
924 /**************************************************************************
925 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
927 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
928 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
929 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
930 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
931 OUT PACL pDacl,
932 OUT LPDWORD lpdwDaclSize,
933 OUT PACL pSacl,
934 OUT LPDWORD lpdwSaclSize,
935 OUT PSID pOwner,
936 OUT LPDWORD lpdwOwnerSize,
937 OUT PSID pPrimaryGroup,
938 OUT LPDWORD lpdwPrimaryGroupSize)
940 NTSTATUS status = STATUS_SUCCESS;
941 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
942 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
944 if (!pRel ||
945 !lpdwAbsoluteSecurityDescriptorSize ||
946 !lpdwDaclSize ||
947 !lpdwSaclSize ||
948 !lpdwOwnerSize ||
949 !lpdwPrimaryGroupSize ||
950 ~pRel->Control & SE_SELF_RELATIVE)
951 return STATUS_INVALID_PARAMETER;
953 /* Confirm buffers are sufficiently large */
954 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
956 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
957 status = STATUS_BUFFER_TOO_SMALL;
960 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
961 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
963 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
964 status = STATUS_BUFFER_TOO_SMALL;
967 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
968 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
970 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
971 status = STATUS_BUFFER_TOO_SMALL;
974 if (pRel->Owner &&
975 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
977 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
978 status = STATUS_BUFFER_TOO_SMALL;
981 if (pRel->Group &&
982 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
984 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
985 status = STATUS_BUFFER_TOO_SMALL;
988 if (status != STATUS_SUCCESS)
989 return status;
991 /* Copy structures, and clear the ones we don't set */
992 pAbs->Revision = pRel->Revision;
993 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
994 pAbs->Sacl = NULL;
995 pAbs->Dacl = NULL;
996 pAbs->Owner = NULL;
997 pAbs->Group = NULL;
999 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
1001 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
1003 memcpy(pSacl, pAcl, pAcl->AclSize);
1004 pAbs->Sacl = pSacl;
1007 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1009 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1010 memcpy(pDacl, pAcl, pAcl->AclSize);
1011 pAbs->Dacl = pDacl;
1014 if (pRel->Owner)
1016 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1017 memcpy(pOwner, psid, RtlLengthSid(psid));
1018 pAbs->Owner = pOwner;
1021 if (pRel->Group)
1023 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1024 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1025 pAbs->Group = pPrimaryGroup;
1028 return status;
1031 /******************************************************************************
1032 * RtlGetControlSecurityDescriptor (NTDLL.@)
1034 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1035 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1036 PSECURITY_DESCRIPTOR_CONTROL pControl,
1037 LPDWORD lpdwRevision)
1039 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1041 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1043 *lpdwRevision = lpsd->Revision;
1045 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1046 return STATUS_UNKNOWN_REVISION;
1048 *pControl = lpsd->Control;
1050 return STATUS_SUCCESS;
1053 /******************************************************************************
1054 * RtlSetControlSecurityDescriptor (NTDLL.@)
1056 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1057 PSECURITY_DESCRIPTOR SecurityDescriptor,
1058 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1059 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1061 SECURITY_DESCRIPTOR_CONTROL const immutable
1062 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1063 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1064 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1065 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1068 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1070 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1071 ControlBitsOfInterest, ControlBitsToSet);
1073 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1074 return STATUS_INVALID_PARAMETER;
1076 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1077 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1079 return STATUS_SUCCESS;
1083 /**************************************************************************
1084 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1086 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1087 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1088 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1089 PULONG BufferLength)
1091 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1093 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1094 SelfRelativeSecurityDescriptor, BufferLength);
1096 if (abs->Control & SE_SELF_RELATIVE)
1097 return STATUS_BAD_DESCRIPTOR_FORMAT;
1099 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1100 SelfRelativeSecurityDescriptor, BufferLength);
1105 * access control list's
1108 /**************************************************************************
1109 * RtlCreateAcl [NTDLL.@]
1111 * NOTES
1112 * This should return NTSTATUS
1114 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1116 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1118 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1119 return STATUS_INVALID_PARAMETER;
1120 if (size<sizeof(ACL))
1121 return STATUS_BUFFER_TOO_SMALL;
1122 if (size>0xFFFF)
1123 return STATUS_INVALID_PARAMETER;
1125 memset(acl,'\0',sizeof(ACL));
1126 acl->AclRevision = rev;
1127 acl->AclSize = size;
1128 acl->AceCount = 0;
1129 return STATUS_SUCCESS;
1132 /**************************************************************************
1133 * RtlFirstFreeAce [NTDLL.@]
1134 * looks for the AceCount+1 ACE, and if it is still within the alloced
1135 * ACL, return a pointer to it
1137 BOOLEAN WINAPI RtlFirstFreeAce(
1138 PACL acl,
1139 PACE_HEADER *x)
1141 PACE_HEADER ace;
1142 int i;
1144 *x = 0;
1145 ace = (PACE_HEADER)(acl+1);
1146 for (i=0;i<acl->AceCount;i++) {
1147 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1148 return FALSE;
1149 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1151 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1152 return FALSE;
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 nrofaces=0;ace=acestart;
1175 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1176 nrofaces++;
1177 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1179 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1180 return STATUS_INVALID_PARAMETER;
1181 memcpy(targetace,acestart,acelen);
1182 acl->AceCount+=nrofaces;
1183 if (rev > acl->AclRevision)
1184 acl->AclRevision = rev;
1185 return STATUS_SUCCESS;
1188 /**************************************************************************
1189 * RtlDeleteAce [NTDLL.@]
1191 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1193 NTSTATUS status;
1194 PACE_HEADER pAce;
1196 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1198 if (STATUS_SUCCESS == status)
1200 PACE_HEADER pcAce;
1201 DWORD len = 0;
1203 /* skip over the ACE we are deleting */
1204 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1205 dwAceIndex++;
1207 /* calculate the length of the rest */
1208 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1210 len += pcAce->AceSize;
1211 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1214 /* slide them all backwards */
1215 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1216 pAcl->AceCount--;
1219 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1221 return status;
1224 /******************************************************************************
1225 * RtlAddAccessAllowedAce [NTDLL.@]
1227 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1228 IN OUT PACL pAcl,
1229 IN DWORD dwAceRevision,
1230 IN DWORD AccessMask,
1231 IN PSID pSid)
1233 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1236 /******************************************************************************
1237 * RtlAddAccessAllowedAceEx [NTDLL.@]
1239 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1240 IN OUT PACL pAcl,
1241 IN DWORD dwAceRevision,
1242 IN DWORD AceFlags,
1243 IN DWORD AccessMask,
1244 IN PSID pSid)
1246 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1248 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1249 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1252 /******************************************************************************
1253 * RtlAddAccessDeniedAce [NTDLL.@]
1255 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1256 IN OUT PACL pAcl,
1257 IN DWORD dwAceRevision,
1258 IN DWORD AccessMask,
1259 IN PSID pSid)
1261 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1264 /******************************************************************************
1265 * RtlAddAccessDeniedAceEx [NTDLL.@]
1267 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1268 IN OUT PACL pAcl,
1269 IN DWORD dwAceRevision,
1270 IN DWORD AceFlags,
1271 IN DWORD AccessMask,
1272 IN PSID pSid)
1274 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1276 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1277 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1280 /**************************************************************************
1281 * RtlAddAuditAccessAce [NTDLL.@]
1283 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1284 IN OUT PACL pAcl,
1285 IN DWORD dwAceRevision,
1286 IN DWORD dwAceFlags,
1287 IN DWORD dwAccessMask,
1288 IN PSID pSid,
1289 IN BOOL bAuditSuccess,
1290 IN BOOL bAuditFailure)
1292 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1293 pSid,bAuditSuccess,bAuditFailure);
1295 if (bAuditSuccess)
1296 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1298 if (bAuditFailure)
1299 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1301 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1302 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1305 /**************************************************************************
1306 * RtlAddAuditAccessAce [NTDLL.@]
1308 NTSTATUS WINAPI RtlAddAuditAccessAce(
1309 IN OUT PACL pAcl,
1310 IN DWORD dwAceRevision,
1311 IN DWORD dwAccessMask,
1312 IN PSID pSid,
1313 IN BOOL bAuditSuccess,
1314 IN BOOL bAuditFailure)
1316 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1319 /******************************************************************************
1320 * RtlValidAcl [NTDLL.@]
1322 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1324 BOOLEAN ret;
1325 TRACE("(%p)\n", pAcl);
1327 __TRY
1329 PACE_HEADER ace;
1330 int i;
1332 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1333 pAcl->AclRevision > MAX_ACL_REVISION)
1334 ret = FALSE;
1335 else
1337 ace = (PACE_HEADER)(pAcl+1);
1338 ret = TRUE;
1339 for (i=0;i<=pAcl->AceCount;i++)
1341 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1343 ret = FALSE;
1344 break;
1346 if (i != pAcl->AceCount)
1347 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1351 __EXCEPT_PAGE_FAULT
1353 WARN("(%p): invalid pointer!\n", pAcl);
1354 return FALSE;
1356 __ENDTRY
1357 return ret;
1360 /******************************************************************************
1361 * RtlGetAce [NTDLL.@]
1363 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1365 PACE_HEADER ace;
1367 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1369 if (dwAceIndex >= pAcl->AceCount)
1370 return STATUS_INVALID_PARAMETER;
1372 ace = (PACE_HEADER)(pAcl + 1);
1373 for (;dwAceIndex;dwAceIndex--)
1374 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1376 *pAce = ace;
1378 return STATUS_SUCCESS;
1382 * misc
1385 /******************************************************************************
1386 * RtlAdjustPrivilege [NTDLL.@]
1388 * Enables or disables a privilege from the calling thread or process.
1390 * PARAMS
1391 * Privilege [I] Privilege index to change.
1392 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1393 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1394 * Enabled [O] Whether privilege was previously enabled or disabled.
1396 * RETURNS
1397 * Success: STATUS_SUCCESS.
1398 * Failure: NTSTATUS code.
1400 * SEE ALSO
1401 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1404 NTSTATUS WINAPI
1405 RtlAdjustPrivilege(ULONG Privilege,
1406 BOOLEAN Enable,
1407 BOOLEAN CurrentThread,
1408 PBOOLEAN Enabled)
1410 TOKEN_PRIVILEGES NewState;
1411 TOKEN_PRIVILEGES OldState;
1412 ULONG ReturnLength;
1413 HANDLE TokenHandle;
1414 NTSTATUS Status;
1416 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1417 CurrentThread ? "TRUE" : "FALSE", Enabled);
1419 if (CurrentThread)
1421 Status = NtOpenThreadToken(GetCurrentThread(),
1422 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1423 FALSE,
1424 &TokenHandle);
1426 else
1428 Status = NtOpenProcessToken(GetCurrentProcess(),
1429 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1430 &TokenHandle);
1433 if (!NT_SUCCESS(Status))
1435 WARN("Retrieving token handle failed (Status %x)\n", Status);
1436 return Status;
1439 OldState.PrivilegeCount = 1;
1441 NewState.PrivilegeCount = 1;
1442 NewState.Privileges[0].Luid.LowPart = Privilege;
1443 NewState.Privileges[0].Luid.HighPart = 0;
1444 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1446 Status = NtAdjustPrivilegesToken(TokenHandle,
1447 FALSE,
1448 &NewState,
1449 sizeof(TOKEN_PRIVILEGES),
1450 &OldState,
1451 &ReturnLength);
1452 NtClose (TokenHandle);
1453 if (Status == STATUS_NOT_ALL_ASSIGNED)
1455 TRACE("Failed to assign all privileges\n");
1456 return STATUS_PRIVILEGE_NOT_HELD;
1458 if (!NT_SUCCESS(Status))
1460 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1461 return Status;
1464 if (OldState.PrivilegeCount == 0)
1465 *Enabled = Enable;
1466 else
1467 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1469 return STATUS_SUCCESS;
1472 /******************************************************************************
1473 * RtlImpersonateSelf [NTDLL.@]
1475 * Makes an impersonation token that represents the process user and assigns
1476 * to the current thread.
1478 * PARAMS
1479 * ImpersonationLevel [I] Level at which to impersonate.
1481 * RETURNS
1482 * Success: STATUS_SUCCESS.
1483 * Failure: NTSTATUS code.
1485 NTSTATUS WINAPI
1486 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1488 NTSTATUS Status;
1489 OBJECT_ATTRIBUTES ObjectAttributes;
1490 HANDLE ProcessToken;
1491 HANDLE ImpersonationToken;
1493 TRACE("(%08x)\n", ImpersonationLevel);
1495 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1496 &ProcessToken);
1497 if (Status != STATUS_SUCCESS)
1498 return Status;
1500 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1502 Status = NtDuplicateToken( ProcessToken,
1503 TOKEN_IMPERSONATE,
1504 &ObjectAttributes,
1505 ImpersonationLevel,
1506 TokenImpersonation,
1507 &ImpersonationToken );
1508 if (Status != STATUS_SUCCESS)
1510 NtClose( ProcessToken );
1511 return Status;
1514 Status = NtSetInformationThread( GetCurrentThread(),
1515 ThreadImpersonationToken,
1516 &ImpersonationToken,
1517 sizeof(ImpersonationToken) );
1519 NtClose( ImpersonationToken );
1520 NtClose( ProcessToken );
1522 return Status;
1525 /******************************************************************************
1526 * NtAccessCheck [NTDLL.@]
1527 * ZwAccessCheck [NTDLL.@]
1529 * Checks that a user represented by a token is allowed to access an object
1530 * represented by a security descriptor.
1532 * PARAMS
1533 * SecurityDescriptor [I] The security descriptor of the object to check.
1534 * ClientToken [I] Token of the user accessing the object.
1535 * DesiredAccess [I] The desired access to the object.
1536 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1537 * PrivilegeSet [I/O] Privileges used during the access check.
1538 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1539 * GrantedAccess [O] The actual access rights granted.
1540 * AccessStatus [O] The status of the access check.
1542 * RETURNS
1543 * NTSTATUS code.
1545 * NOTES
1546 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1547 * the maximum access rights allowed by the SD and returns them in
1548 * GrantedAccess.
1549 * The SecurityDescriptor must have a valid owner and groups present,
1550 * otherwise the function will fail.
1552 NTSTATUS WINAPI
1553 NtAccessCheck(
1554 PSECURITY_DESCRIPTOR SecurityDescriptor,
1555 HANDLE ClientToken,
1556 ACCESS_MASK DesiredAccess,
1557 PGENERIC_MAPPING GenericMapping,
1558 PPRIVILEGE_SET PrivilegeSet,
1559 PULONG ReturnLength,
1560 PULONG GrantedAccess,
1561 NTSTATUS *AccessStatus)
1563 NTSTATUS status;
1565 TRACE("(%p, %p, %08x, %p, %p, %p, %p, %p)\n",
1566 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1567 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1569 if (!PrivilegeSet || !ReturnLength)
1570 return STATUS_ACCESS_VIOLATION;
1572 SERVER_START_REQ( access_check )
1574 struct security_descriptor sd;
1575 PSID owner;
1576 PSID group;
1577 PACL sacl;
1578 PACL dacl;
1579 BOOLEAN defaulted, present;
1580 DWORD revision;
1581 SECURITY_DESCRIPTOR_CONTROL control;
1583 req->handle = wine_server_obj_handle( ClientToken );
1584 req->desired_access = DesiredAccess;
1585 req->mapping_read = GenericMapping->GenericRead;
1586 req->mapping_write = GenericMapping->GenericWrite;
1587 req->mapping_execute = GenericMapping->GenericExecute;
1588 req->mapping_all = GenericMapping->GenericAll;
1590 /* marshal security descriptor */
1591 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1592 sd.control = control & ~SE_SELF_RELATIVE;
1593 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1594 sd.owner_len = RtlLengthSid( owner );
1595 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1596 sd.group_len = RtlLengthSid( group );
1597 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1598 sd.sacl_len = ((present && sacl) ? acl_bytesInUse(sacl) : 0);
1599 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1600 sd.dacl_len = ((present && dacl) ? acl_bytesInUse(dacl) : 0);
1602 wine_server_add_data( req, &sd, sizeof(sd) );
1603 wine_server_add_data( req, owner, sd.owner_len );
1604 wine_server_add_data( req, group, sd.group_len );
1605 wine_server_add_data( req, sacl, sd.sacl_len );
1606 wine_server_add_data( req, dacl, sd.dacl_len );
1608 wine_server_set_reply( req, PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1610 status = wine_server_call( req );
1612 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1613 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1615 if (status == STATUS_SUCCESS)
1617 *AccessStatus = reply->access_status;
1618 *GrantedAccess = reply->access_granted;
1621 SERVER_END_REQ;
1623 return status;
1626 /******************************************************************************
1627 * NtSetSecurityObject [NTDLL.@]
1628 * ZwSetSecurityObject [NTDLL.@]
1630 * Sets specified parts of the object's security descriptor.
1632 * PARAMS
1633 * Handle [I] Handle to the object to change security descriptor of.
1634 * SecurityInformation [I] Specifies which parts of the security descriptor to set.
1635 * SecurityDescriptor [I] New parts of a security descriptor for the object.
1637 * RETURNS
1638 * NTSTATUS code.
1641 NTSTATUS WINAPI NtSetSecurityObject(HANDLE Handle,
1642 SECURITY_INFORMATION SecurityInformation,
1643 PSECURITY_DESCRIPTOR SecurityDescriptor)
1645 NTSTATUS status;
1646 struct security_descriptor sd;
1647 PACL dacl = NULL, sacl = NULL;
1648 PSID owner = NULL, group = NULL;
1649 BOOLEAN defaulted, present;
1650 DWORD revision;
1651 SECURITY_DESCRIPTOR_CONTROL control;
1653 TRACE("%p 0x%08x %p\n", Handle, SecurityInformation, SecurityDescriptor);
1655 if (!SecurityDescriptor) return STATUS_ACCESS_VIOLATION;
1657 memset( &sd, 0, sizeof(sd) );
1658 status = RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1659 if (status != STATUS_SUCCESS) return status;
1660 sd.control = control & ~SE_SELF_RELATIVE;
1662 if (SecurityInformation & OWNER_SECURITY_INFORMATION)
1664 status = RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1665 if (status != STATUS_SUCCESS) return status;
1666 if (!(sd.owner_len = RtlLengthSid( owner )))
1667 return STATUS_INVALID_SECURITY_DESCR;
1670 if (SecurityInformation & GROUP_SECURITY_INFORMATION)
1672 status = RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1673 if (status != STATUS_SUCCESS) return status;
1674 if (!(sd.group_len = RtlLengthSid( group )))
1675 return STATUS_INVALID_SECURITY_DESCR;
1678 if (SecurityInformation & SACL_SECURITY_INFORMATION)
1680 status = RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1681 if (status != STATUS_SUCCESS) return status;
1682 sd.sacl_len = (sacl && present) ? acl_bytesInUse(sacl) : 0;
1683 sd.control |= SE_SACL_PRESENT;
1686 if (SecurityInformation & DACL_SECURITY_INFORMATION)
1688 status = RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1689 if (status != STATUS_SUCCESS) return status;
1690 sd.dacl_len = (dacl && present) ? acl_bytesInUse(dacl) : 0;
1691 sd.control |= SE_DACL_PRESENT;
1694 SERVER_START_REQ( set_security_object )
1696 req->handle = wine_server_obj_handle( Handle );
1697 req->security_info = SecurityInformation;
1699 wine_server_add_data( req, &sd, sizeof(sd) );
1700 wine_server_add_data( req, owner, sd.owner_len );
1701 wine_server_add_data( req, group, sd.group_len );
1702 wine_server_add_data( req, sacl, sd.sacl_len );
1703 wine_server_add_data( req, dacl, sd.dacl_len );
1704 status = wine_server_call( req );
1706 SERVER_END_REQ;
1708 return status;
1711 /******************************************************************************
1712 * RtlConvertSidToUnicodeString (NTDLL.@)
1714 * The returned SID is used to access the USER registry hive usually
1716 * the native function returns something like
1717 * "S-1-5-21-0000000000-000000000-0000000000-500";
1719 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1720 PUNICODE_STRING String,
1721 PSID pSid,
1722 BOOLEAN AllocateString)
1724 static const WCHAR formatW[] = {'-','%','u',0};
1725 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1726 WCHAR *p = buffer;
1727 const SID *sid = pSid;
1728 DWORD i, len;
1730 *p++ = 'S';
1731 p += sprintfW( p, formatW, sid->Revision );
1732 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1733 sid->IdentifierAuthority.Value[4] ),
1734 MAKEWORD( sid->IdentifierAuthority.Value[3],
1735 sid->IdentifierAuthority.Value[2] )));
1736 for (i = 0; i < sid->SubAuthorityCount; i++)
1737 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1739 len = (p + 1 - buffer) * sizeof(WCHAR);
1741 String->Length = len - sizeof(WCHAR);
1742 if (AllocateString)
1744 String->MaximumLength = len;
1745 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1746 return STATUS_NO_MEMORY;
1748 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1750 memcpy( String->Buffer, buffer, len );
1751 return STATUS_SUCCESS;
1754 /******************************************************************************
1755 * RtlQueryInformationAcl (NTDLL.@)
1757 NTSTATUS WINAPI RtlQueryInformationAcl(
1758 PACL pAcl,
1759 LPVOID pAclInformation,
1760 DWORD nAclInformationLength,
1761 ACL_INFORMATION_CLASS dwAclInformationClass)
1763 NTSTATUS status = STATUS_SUCCESS;
1765 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1766 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1768 switch (dwAclInformationClass)
1770 case AclRevisionInformation:
1772 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1774 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1775 status = STATUS_INVALID_PARAMETER;
1776 else
1777 paclrev->AclRevision = pAcl->AclRevision;
1779 break;
1782 case AclSizeInformation:
1784 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1786 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1787 status = STATUS_INVALID_PARAMETER;
1788 else
1790 paclsize->AceCount = pAcl->AceCount;
1791 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1792 if (pAcl->AclSize < paclsize->AclBytesInUse)
1794 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1795 paclsize->AclBytesFree = 0;
1796 paclsize->AclBytesInUse = pAcl->AclSize;
1798 else
1799 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1802 break;
1805 default:
1806 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1807 status = STATUS_INVALID_PARAMETER;
1810 return status;
1813 BOOL WINAPI RtlConvertToAutoInheritSecurityObject(
1814 PSECURITY_DESCRIPTOR pdesc,
1815 PSECURITY_DESCRIPTOR cdesc,
1816 PSECURITY_DESCRIPTOR* ndesc,
1817 GUID* objtype,
1818 BOOL isdir,
1819 PGENERIC_MAPPING genmap )
1821 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
1823 return FALSE;