user32: Hook drawing menu buttons.
[wine.git] / dlls / ntdll / sec.c
blobecc3ed8ba95bc1c820c6b735fe9a5839bea7131d
1 /*
2 * Security functions
4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <ctype.h>
27 #include <math.h>
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "windef.h"
32 #include "ntdll_misc.h"
33 #include "wine/exception.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
38 #define SELF_RELATIVE_FIELD(sd,field) ((BYTE *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
40 static const SID world_sid = { SID_REVISION, 1, { SECURITY_WORLD_SID_AUTHORITY} , { SECURITY_WORLD_RID } };
41 static const DWORD world_access_acl_size = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) + sizeof(world_sid) - sizeof(DWORD);
43 static void get_world_access_acl( PACL acl )
45 PACCESS_ALLOWED_ACE ace = (PACCESS_ALLOWED_ACE)(acl + 1);
47 acl->AclRevision = ACL_REVISION;
48 acl->Sbz1 = 0;
49 acl->AclSize = world_access_acl_size;
50 acl->AceCount = 1;
51 acl->Sbz2 = 0;
52 ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
53 ace->Header.AceFlags = CONTAINER_INHERIT_ACE;
54 ace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE) + sizeof(world_sid) - sizeof(DWORD);
55 ace->Mask = 0xf3ffffff; /* Everything except reserved bits */
56 memcpy( &ace->SidStart, &world_sid, sizeof(world_sid) );
59 /* helper function to retrieve active length of an ACL */
60 static size_t acl_bytesInUse(PACL pAcl)
62 int i;
63 size_t bytesInUse = sizeof(ACL);
64 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
65 for (i = 0; i < pAcl->AceCount; i++)
67 bytesInUse += ace->AceSize;
68 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
70 return bytesInUse;
73 /* helper function to copy an ACL */
74 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
76 DWORD size;
78 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
79 return FALSE;
81 size = pSourceAcl->AclSize;
82 if (nDestinationAclLength < size)
83 return FALSE;
85 memmove(pDestinationAcl, pSourceAcl, size);
86 return TRUE;
89 /* generically adds an ACE to an ACL */
90 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
91 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
93 ACE_HEADER *pAceHeader;
94 DWORD dwLengthSid;
95 DWORD dwAceSize;
96 DWORD *pAccessMask;
97 DWORD *pSidStart;
99 if (!RtlValidSid(pSid))
100 return STATUS_INVALID_SID;
102 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
103 return STATUS_REVISION_MISMATCH;
105 if (!RtlValidAcl(pAcl))
106 return STATUS_INVALID_ACL;
108 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
109 return STATUS_INVALID_ACL;
111 if (!pAceHeader)
112 return STATUS_ALLOTTED_SPACE_EXCEEDED;
114 /* calculate generic size of the ACE */
115 dwLengthSid = RtlLengthSid(pSid);
116 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
117 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
118 return STATUS_ALLOTTED_SPACE_EXCEEDED;
120 /* fill the new ACE */
121 pAceHeader->AceType = dwAceType;
122 pAceHeader->AceFlags = dwAceFlags;
123 pAceHeader->AceSize = dwAceSize;
125 /* skip past the ACE_HEADER of the ACE */
126 pAccessMask = (DWORD *)(pAceHeader + 1);
127 *pAccessMask = dwAccessMask;
129 /* skip past ACE->Mask */
130 pSidStart = pAccessMask + 1;
131 RtlCopySid(dwLengthSid, pSidStart, pSid);
133 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
134 pAcl->AceCount++;
136 return STATUS_SUCCESS;
140 * SID FUNCTIONS
143 /******************************************************************************
144 * RtlAllocateAndInitializeSid [NTDLL.@]
147 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
148 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
149 BYTE nSubAuthorityCount,
150 DWORD nSubAuthority0, DWORD nSubAuthority1,
151 DWORD nSubAuthority2, DWORD nSubAuthority3,
152 DWORD nSubAuthority4, DWORD nSubAuthority5,
153 DWORD nSubAuthority6, DWORD nSubAuthority7,
154 PSID *pSid )
156 SID *tmp_sid;
158 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
159 pIdentifierAuthority,nSubAuthorityCount,
160 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
161 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
163 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
165 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
166 RtlLengthRequiredSid(nSubAuthorityCount))))
167 return STATUS_NO_MEMORY;
169 tmp_sid->Revision = SID_REVISION;
171 if (pIdentifierAuthority)
172 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
173 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
175 switch( nSubAuthorityCount )
177 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
178 /* fall through */
179 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
180 /* fall through */
181 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
182 /* fall through */
183 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
184 /* fall through */
185 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
186 /* fall through */
187 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
188 /* fall through */
189 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
190 /* fall through */
191 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
192 break;
194 *pSid = tmp_sid;
195 return STATUS_SUCCESS;
198 /******************************************************************************
199 * RtlEqualSid [NTDLL.@]
201 * Determine if two SIDs are equal.
203 * PARAMS
204 * pSid1 [I] Source SID
205 * pSid2 [I] SID to compare with
207 * RETURNS
208 * TRUE, if pSid1 is equal to pSid2,
209 * FALSE otherwise.
211 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
213 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
214 return FALSE;
216 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
217 return FALSE;
219 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
220 return FALSE;
222 return TRUE;
225 /******************************************************************************
226 * RtlEqualPrefixSid [NTDLL.@]
228 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
230 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
231 return FALSE;
233 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
234 return FALSE;
236 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
237 return FALSE;
239 return TRUE;
243 /******************************************************************************
244 * RtlFreeSid [NTDLL.@]
246 * Free the resources used by a SID.
248 * PARAMS
249 * pSid [I] SID to Free.
251 * RETURNS
252 * STATUS_SUCCESS.
254 DWORD WINAPI RtlFreeSid(PSID pSid)
256 TRACE("(%p)\n", pSid);
257 RtlFreeHeap( GetProcessHeap(), 0, pSid );
258 return STATUS_SUCCESS;
261 /**************************************************************************
262 * RtlLengthRequiredSid [NTDLL.@]
264 * Determine the amount of memory a SID will use
266 * PARAMS
267 * nrofsubauths [I] Number of Sub Authorities in the SID.
269 * RETURNS
270 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
272 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
274 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
277 /**************************************************************************
278 * RtlLengthSid [NTDLL.@]
280 * Determine the amount of memory a SID is using
282 * PARAMS
283 * pSid [I] SID to get the size of.
285 * RETURNS
286 * The size, in bytes, of pSid.
288 DWORD WINAPI RtlLengthSid(PSID pSid)
290 TRACE("sid=%p\n",pSid);
291 if (!pSid) return 0;
292 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
295 /**************************************************************************
296 * RtlInitializeSid [NTDLL.@]
298 * Initialise a SID.
300 * PARAMS
301 * pSid [I] SID to initialise
302 * pIdentifierAuthority [I] Identifier Authority
303 * nSubAuthorityCount [I] Number of Sub Authorities
305 * RETURNS
306 * Success: TRUE. pSid is initialised with the details given.
307 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
309 BOOL WINAPI RtlInitializeSid(
310 PSID pSid,
311 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
312 BYTE nSubAuthorityCount)
314 int i;
315 SID* pisid=pSid;
317 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
318 return FALSE;
320 pisid->Revision = SID_REVISION;
321 pisid->SubAuthorityCount = nSubAuthorityCount;
322 if (pIdentifierAuthority)
323 pisid->IdentifierAuthority = *pIdentifierAuthority;
325 for (i = 0; i < nSubAuthorityCount; i++)
326 *RtlSubAuthoritySid(pSid, i) = 0;
328 return TRUE;
331 /**************************************************************************
332 * RtlSubAuthoritySid [NTDLL.@]
334 * Return the Sub Authority of a SID
336 * PARAMS
337 * pSid [I] SID to get the Sub Authority from.
338 * nSubAuthority [I] Sub Authority number.
340 * RETURNS
341 * A pointer to The Sub Authority value of pSid.
343 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
345 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
348 /**************************************************************************
349 * RtlIdentifierAuthoritySid [NTDLL.@]
351 * Return the Identifier Authority of a SID.
353 * PARAMS
354 * pSid [I] SID to get the Identifier Authority from.
356 * RETURNS
357 * A pointer to the Identifier Authority value of pSid.
359 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
361 return &(((SID*)pSid)->IdentifierAuthority);
364 /**************************************************************************
365 * RtlSubAuthorityCountSid [NTDLL.@]
367 * Get the number of Sub Authorities in a SID.
369 * PARAMS
370 * pSid [I] SID to get the count from.
372 * RETURNS
373 * A pointer to the Sub Authority count of pSid.
375 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
377 return &(((SID*)pSid)->SubAuthorityCount);
380 /**************************************************************************
381 * RtlCopySid [NTDLL.@]
383 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
385 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
386 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
387 return FALSE;
389 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
390 return FALSE;
392 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
393 return TRUE;
395 /******************************************************************************
396 * RtlValidSid [NTDLL.@]
398 * Determine if a SID is valid.
400 * PARAMS
401 * pSid [I] SID to check
403 * RETURNS
404 * TRUE if pSid is valid,
405 * FALSE otherwise.
407 BOOLEAN WINAPI RtlValidSid( PSID pSid )
409 BOOL ret;
410 __TRY
412 ret = TRUE;
413 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
414 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
416 ret = FALSE;
419 __EXCEPT_PAGE_FAULT
421 WARN("(%p): invalid pointer!\n", pSid);
422 return FALSE;
424 __ENDTRY
425 return ret;
430 * security descriptor functions
433 /**************************************************************************
434 * RtlCreateSecurityDescriptor [NTDLL.@]
436 * Initialise a SECURITY_DESCRIPTOR.
438 * PARAMS
439 * lpsd [O] Descriptor to initialise.
440 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
442 * RETURNS
443 * Success: STATUS_SUCCESS.
444 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
446 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
447 PSECURITY_DESCRIPTOR lpsd,
448 DWORD rev)
450 if (rev!=SECURITY_DESCRIPTOR_REVISION)
451 return STATUS_UNKNOWN_REVISION;
452 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
453 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
454 return STATUS_SUCCESS;
457 /**************************************************************************
458 * RtlCopySecurityDescriptor [NTDLL.@]
460 * Copies an absolute or self-relative SECURITY_DESCRIPTOR.
462 * PARAMS
463 * pSourceSD [O] SD to copy from.
464 * pDestinationSD [I] Destination SD.
466 * RETURNS
467 * Success: STATUS_SUCCESS.
468 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
470 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
472 PSID Owner, Group;
473 PACL Dacl, Sacl;
474 DWORD length;
476 if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
478 SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
479 SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
481 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
482 return STATUS_UNKNOWN_REVISION;
484 *dst = *src;
485 if (src->Owner)
487 Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
488 length = RtlLengthSid( Owner );
489 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
491 if (src->Group)
493 Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
494 length = RtlLengthSid( Group );
495 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
497 if ((src->Control & SE_SACL_PRESENT) && src->Sacl)
499 Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
500 copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
502 if ((src->Control & SE_DACL_PRESENT) && src->Dacl)
504 Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
505 copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
508 else
510 SECURITY_DESCRIPTOR *src = pSourceSD;
511 SECURITY_DESCRIPTOR *dst = pDestinationSD;
513 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
514 return STATUS_UNKNOWN_REVISION;
516 *dst = *src;
517 if (src->Owner)
519 length = RtlLengthSid( src->Owner );
520 dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
521 RtlCopySid(length, dst->Owner, src->Owner);
523 if (src->Group)
525 length = RtlLengthSid( src->Group );
526 dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
527 RtlCopySid(length, dst->Group, src->Group);
529 if (src->Control & SE_SACL_PRESENT)
531 length = src->Sacl->AclSize;
532 dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
533 copy_acl(length, dst->Sacl, src->Sacl);
535 if (src->Control & SE_DACL_PRESENT)
537 length = src->Dacl->AclSize;
538 dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
539 copy_acl(length, dst->Dacl, src->Dacl);
543 return STATUS_SUCCESS;
546 /**************************************************************************
547 * RtlValidSecurityDescriptor [NTDLL.@]
549 * Determine if a SECURITY_DESCRIPTOR is valid.
551 * PARAMS
552 * SecurityDescriptor [I] Descriptor to check.
554 * RETURNS
555 * Success: STATUS_SUCCESS.
556 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
558 NTSTATUS WINAPI RtlValidSecurityDescriptor(
559 PSECURITY_DESCRIPTOR SecurityDescriptor)
561 if ( ! SecurityDescriptor )
562 return STATUS_INVALID_SECURITY_DESCR;
563 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
564 return STATUS_UNKNOWN_REVISION;
566 return STATUS_SUCCESS;
569 /**************************************************************************
570 * RtlValidRelativeSecurityDescriptor [NTDLL.@]
572 BOOLEAN WINAPI RtlValidRelativeSecurityDescriptor(PSECURITY_DESCRIPTOR descriptor,
573 ULONG length, SECURITY_INFORMATION info)
575 FIXME("%p,%u,%d: semi-stub\n", descriptor, length, info);
576 return RtlValidSecurityDescriptor(descriptor) == STATUS_SUCCESS;
579 /**************************************************************************
580 * RtlLengthSecurityDescriptor [NTDLL.@]
582 ULONG WINAPI RtlLengthSecurityDescriptor(
583 PSECURITY_DESCRIPTOR pSecurityDescriptor)
585 ULONG size;
587 if ( pSecurityDescriptor == NULL )
588 return 0;
590 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
592 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
593 size = sizeof(*sd);
594 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
595 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
596 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
597 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
598 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
599 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
601 else
603 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
604 size = sizeof(*sd);
605 if (sd->Owner) size += RtlLengthSid( sd->Owner );
606 if (sd->Group) size += RtlLengthSid( sd->Group );
607 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
608 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
610 return size;
613 /******************************************************************************
614 * RtlGetDaclSecurityDescriptor [NTDLL.@]
617 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
618 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
619 OUT PBOOLEAN lpbDaclPresent,
620 OUT PACL *pDacl,
621 OUT PBOOLEAN lpbDaclDefaulted)
623 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
625 TRACE("(%p,%p,%p,%p)\n",
626 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
628 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
629 return STATUS_UNKNOWN_REVISION ;
631 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
633 if (lpsd->Control & SE_SELF_RELATIVE)
635 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
636 if (sdr->Dacl) *pDacl = (PACL)SELF_RELATIVE_FIELD( sdr, Dacl );
637 else *pDacl = NULL;
639 else *pDacl = lpsd->Dacl;
641 *lpbDaclDefaulted = (lpsd->Control & SE_DACL_DEFAULTED) != 0;
643 else
645 *pDacl = NULL;
646 *lpbDaclDefaulted = 0;
649 return STATUS_SUCCESS;
652 /**************************************************************************
653 * RtlSetDaclSecurityDescriptor [NTDLL.@]
655 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
656 PSECURITY_DESCRIPTOR pSecurityDescriptor,
657 BOOLEAN daclpresent,
658 PACL dacl,
659 BOOLEAN dacldefaulted )
661 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
663 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
664 return STATUS_UNKNOWN_REVISION;
665 if (lpsd->Control & SE_SELF_RELATIVE)
666 return STATUS_INVALID_SECURITY_DESCR;
668 if (!daclpresent)
670 lpsd->Control &= ~SE_DACL_PRESENT;
671 return STATUS_SUCCESS;
674 lpsd->Control |= SE_DACL_PRESENT;
675 lpsd->Dacl = dacl;
677 if (dacldefaulted)
678 lpsd->Control |= SE_DACL_DEFAULTED;
679 else
680 lpsd->Control &= ~SE_DACL_DEFAULTED;
682 return STATUS_SUCCESS;
685 /******************************************************************************
686 * RtlGetSaclSecurityDescriptor [NTDLL.@]
689 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
690 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
691 OUT PBOOLEAN lpbSaclPresent,
692 OUT PACL *pSacl,
693 OUT PBOOLEAN lpbSaclDefaulted)
695 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
697 TRACE("(%p,%p,%p,%p)\n",
698 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
700 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
701 return STATUS_UNKNOWN_REVISION;
703 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
705 if (lpsd->Control & SE_SELF_RELATIVE)
707 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
708 if (sdr->Sacl) *pSacl = (PACL)SELF_RELATIVE_FIELD( sdr, Sacl );
709 else *pSacl = NULL;
711 else *pSacl = lpsd->Sacl;
713 *lpbSaclDefaulted = (lpsd->Control & SE_SACL_DEFAULTED) != 0;
715 return STATUS_SUCCESS;
718 /**************************************************************************
719 * RtlSetSaclSecurityDescriptor [NTDLL.@]
721 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
722 PSECURITY_DESCRIPTOR pSecurityDescriptor,
723 BOOLEAN saclpresent,
724 PACL sacl,
725 BOOLEAN sacldefaulted)
727 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
729 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
730 return STATUS_UNKNOWN_REVISION;
731 if (lpsd->Control & SE_SELF_RELATIVE)
732 return STATUS_INVALID_SECURITY_DESCR;
733 if (!saclpresent) {
734 lpsd->Control &= ~SE_SACL_PRESENT;
735 return 0;
737 lpsd->Control |= SE_SACL_PRESENT;
738 lpsd->Sacl = sacl;
739 if (sacldefaulted)
740 lpsd->Control |= SE_SACL_DEFAULTED;
741 else
742 lpsd->Control &= ~SE_SACL_DEFAULTED;
743 return STATUS_SUCCESS;
746 /**************************************************************************
747 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
749 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
750 PSECURITY_DESCRIPTOR pSecurityDescriptor,
751 PSID *Owner,
752 PBOOLEAN OwnerDefaulted)
754 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
756 if ( !lpsd || !Owner || !OwnerDefaulted )
757 return STATUS_INVALID_PARAMETER;
759 if ( lpsd->Control & SE_OWNER_DEFAULTED )
760 *OwnerDefaulted = TRUE;
761 else
762 *OwnerDefaulted = FALSE;
764 if (lpsd->Control & SE_SELF_RELATIVE)
766 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
767 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
768 else *Owner = NULL;
770 else
771 *Owner = lpsd->Owner;
773 return STATUS_SUCCESS;
776 /**************************************************************************
777 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
779 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
780 PSECURITY_DESCRIPTOR pSecurityDescriptor,
781 PSID owner,
782 BOOLEAN ownerdefaulted)
784 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
786 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
787 return STATUS_UNKNOWN_REVISION;
788 if (lpsd->Control & SE_SELF_RELATIVE)
789 return STATUS_INVALID_SECURITY_DESCR;
791 lpsd->Owner = owner;
792 if (ownerdefaulted)
793 lpsd->Control |= SE_OWNER_DEFAULTED;
794 else
795 lpsd->Control &= ~SE_OWNER_DEFAULTED;
796 return STATUS_SUCCESS;
799 /**************************************************************************
800 * RtlSetGroupSecurityDescriptor [NTDLL.@]
802 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
803 PSECURITY_DESCRIPTOR pSecurityDescriptor,
804 PSID group,
805 BOOLEAN groupdefaulted)
807 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
809 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
810 return STATUS_UNKNOWN_REVISION;
811 if (lpsd->Control & SE_SELF_RELATIVE)
812 return STATUS_INVALID_SECURITY_DESCR;
814 lpsd->Group = group;
815 if (groupdefaulted)
816 lpsd->Control |= SE_GROUP_DEFAULTED;
817 else
818 lpsd->Control &= ~SE_GROUP_DEFAULTED;
819 return STATUS_SUCCESS;
822 /**************************************************************************
823 * RtlGetGroupSecurityDescriptor [NTDLL.@]
825 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
826 PSECURITY_DESCRIPTOR pSecurityDescriptor,
827 PSID *Group,
828 PBOOLEAN GroupDefaulted)
830 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
832 if ( !lpsd || !Group || !GroupDefaulted )
833 return STATUS_INVALID_PARAMETER;
835 if ( lpsd->Control & SE_GROUP_DEFAULTED )
836 *GroupDefaulted = TRUE;
837 else
838 *GroupDefaulted = FALSE;
840 if (lpsd->Control & SE_SELF_RELATIVE)
842 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
843 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
844 else *Group = NULL;
846 else
847 *Group = lpsd->Group;
849 return STATUS_SUCCESS;
852 /**************************************************************************
853 * RtlMakeSelfRelativeSD [NTDLL.@]
855 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
856 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
857 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
858 IN OUT LPDWORD lpdwBufferLength)
860 DWORD offsetRel;
861 ULONG length;
862 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
863 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
865 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
866 lpdwBufferLength ? *lpdwBufferLength: -1);
868 if (!lpdwBufferLength || !pAbs)
869 return STATUS_INVALID_PARAMETER;
871 length = RtlLengthSecurityDescriptor(pAbs);
872 if (!(pAbs->Control & SE_SELF_RELATIVE)) length -= (sizeof(*pAbs) - sizeof(*pRel));
873 if (*lpdwBufferLength < length)
875 *lpdwBufferLength = length;
876 return STATUS_BUFFER_TOO_SMALL;
879 if (!pRel)
880 return STATUS_INVALID_PARAMETER;
882 if (pAbs->Control & SE_SELF_RELATIVE)
884 memcpy(pRel, pAbs, length);
885 return STATUS_SUCCESS;
888 pRel->Revision = pAbs->Revision;
889 pRel->Sbz1 = pAbs->Sbz1;
890 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
892 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
893 if (pAbs->Owner)
895 pRel->Owner = offsetRel;
896 length = RtlLengthSid(pAbs->Owner);
897 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
898 offsetRel += length;
900 else
902 pRel->Owner = 0;
905 if (pAbs->Group)
907 pRel->Group = offsetRel;
908 length = RtlLengthSid(pAbs->Group);
909 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
910 offsetRel += length;
912 else
914 pRel->Group = 0;
917 if (pAbs->Sacl)
919 pRel->Sacl = offsetRel;
920 length = pAbs->Sacl->AclSize;
921 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
922 offsetRel += length;
924 else
926 pRel->Sacl = 0;
929 if (pAbs->Dacl)
931 pRel->Dacl = offsetRel;
932 length = pAbs->Dacl->AclSize;
933 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
935 else
937 pRel->Dacl = 0;
940 return STATUS_SUCCESS;
944 /**************************************************************************
945 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
947 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
948 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
949 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
950 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
951 OUT PACL pDacl,
952 OUT LPDWORD lpdwDaclSize,
953 OUT PACL pSacl,
954 OUT LPDWORD lpdwSaclSize,
955 OUT PSID pOwner,
956 OUT LPDWORD lpdwOwnerSize,
957 OUT PSID pPrimaryGroup,
958 OUT LPDWORD lpdwPrimaryGroupSize)
960 NTSTATUS status = STATUS_SUCCESS;
961 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
962 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
964 if (!pRel ||
965 !lpdwAbsoluteSecurityDescriptorSize ||
966 !lpdwDaclSize ||
967 !lpdwSaclSize ||
968 !lpdwOwnerSize ||
969 !lpdwPrimaryGroupSize ||
970 ~pRel->Control & SE_SELF_RELATIVE)
971 return STATUS_INVALID_PARAMETER;
973 /* Confirm buffers are sufficiently large */
974 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
976 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
977 status = STATUS_BUFFER_TOO_SMALL;
980 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
981 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
983 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
984 status = STATUS_BUFFER_TOO_SMALL;
987 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
988 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
990 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
991 status = STATUS_BUFFER_TOO_SMALL;
994 if (pRel->Owner &&
995 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
997 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
998 status = STATUS_BUFFER_TOO_SMALL;
1001 if (pRel->Group &&
1002 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
1004 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
1005 status = STATUS_BUFFER_TOO_SMALL;
1008 if (status != STATUS_SUCCESS)
1009 return status;
1011 /* Copy structures, and clear the ones we don't set */
1012 pAbs->Revision = pRel->Revision;
1013 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
1014 pAbs->Sacl = NULL;
1015 pAbs->Dacl = NULL;
1016 pAbs->Owner = NULL;
1017 pAbs->Group = NULL;
1019 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
1021 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
1023 memcpy(pSacl, pAcl, pAcl->AclSize);
1024 pAbs->Sacl = pSacl;
1027 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1029 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1030 memcpy(pDacl, pAcl, pAcl->AclSize);
1031 pAbs->Dacl = pDacl;
1034 if (pRel->Owner)
1036 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1037 memcpy(pOwner, psid, RtlLengthSid(psid));
1038 pAbs->Owner = pOwner;
1041 if (pRel->Group)
1043 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1044 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1045 pAbs->Group = pPrimaryGroup;
1048 return status;
1051 /******************************************************************************
1052 * RtlGetControlSecurityDescriptor (NTDLL.@)
1054 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1055 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1056 PSECURITY_DESCRIPTOR_CONTROL pControl,
1057 LPDWORD lpdwRevision)
1059 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1061 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1063 *lpdwRevision = lpsd->Revision;
1065 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1066 return STATUS_UNKNOWN_REVISION;
1068 *pControl = lpsd->Control;
1070 return STATUS_SUCCESS;
1073 /******************************************************************************
1074 * RtlSetControlSecurityDescriptor (NTDLL.@)
1076 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1077 PSECURITY_DESCRIPTOR SecurityDescriptor,
1078 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1079 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1081 SECURITY_DESCRIPTOR_CONTROL const immutable
1082 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1083 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1084 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1085 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1088 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1090 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1091 ControlBitsOfInterest, ControlBitsToSet);
1093 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1094 return STATUS_INVALID_PARAMETER;
1096 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1097 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1099 return STATUS_SUCCESS;
1103 /**************************************************************************
1104 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1106 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1107 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1108 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1109 PULONG BufferLength)
1111 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1113 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1114 SelfRelativeSecurityDescriptor, BufferLength);
1116 if (abs->Control & SE_SELF_RELATIVE)
1117 return STATUS_BAD_DESCRIPTOR_FORMAT;
1119 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1120 SelfRelativeSecurityDescriptor, BufferLength);
1123 /******************************************************************************
1124 * RtlNewSecurityObject [NTDLL.@]
1126 NTSTATUS WINAPI RtlNewSecurityObject(PSECURITY_DESCRIPTOR parent, PSECURITY_DESCRIPTOR creator,
1127 PSECURITY_DESCRIPTOR *descr, BOOLEAN is_container, HANDLE token, PGENERIC_MAPPING mapping)
1129 return RtlNewSecurityObjectEx(parent, creator, descr, NULL, is_container, 0, token, mapping);
1132 /******************************************************************************
1133 * RtlNewSecurityObjectEx [NTDLL.@]
1135 NTSTATUS WINAPI RtlNewSecurityObjectEx(PSECURITY_DESCRIPTOR parent, PSECURITY_DESCRIPTOR creator,
1136 PSECURITY_DESCRIPTOR *descr, GUID *type, BOOLEAN is_container, ULONG flags, HANDLE token, PGENERIC_MAPPING mapping )
1138 SECURITY_DESCRIPTOR_RELATIVE *relative;
1139 DWORD needed, offset;
1140 NTSTATUS status;
1141 BYTE *buffer;
1143 FIXME("%p, %p, %p, %p, %d, %#x, %p %p - semi-stub\n", parent, creator, descr, type, is_container, flags, token, mapping);
1145 needed = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
1146 needed += sizeof(world_sid);
1147 needed += sizeof(world_sid);
1148 needed += world_access_acl_size;
1149 needed += world_access_acl_size;
1151 if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, needed ))) return STATUS_NO_MEMORY;
1152 relative = (SECURITY_DESCRIPTOR_RELATIVE *)buffer;
1153 if ((status = RtlCreateSecurityDescriptor( relative, SECURITY_DESCRIPTOR_REVISION )))
1155 RtlFreeHeap( GetProcessHeap(), 0, buffer );
1156 return status;
1158 relative->Control |= SE_SELF_RELATIVE;
1159 offset = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
1161 memcpy( buffer + offset, &world_sid, sizeof(world_sid) );
1162 relative->Owner = offset;
1163 offset += sizeof(world_sid);
1165 memcpy( buffer + offset, &world_sid, sizeof(world_sid) );
1166 relative->Group = offset;
1167 offset += sizeof(world_sid);
1169 get_world_access_acl( (ACL *)(buffer + offset) );
1170 relative->Dacl = offset;
1171 offset += world_access_acl_size;
1173 get_world_access_acl( (ACL *)(buffer + offset) );
1174 relative->Sacl = offset;
1176 *descr = relative;
1177 return STATUS_SUCCESS;
1180 /******************************************************************************
1181 * RtlNewSecurityObjectWithMultipleInheritance [NTDLL.@]
1183 NTSTATUS WINAPI RtlNewSecurityObjectWithMultipleInheritance(PSECURITY_DESCRIPTOR parent, PSECURITY_DESCRIPTOR creator,
1184 PSECURITY_DESCRIPTOR *descr, GUID **types, ULONG count, BOOLEAN is_container, ULONG flags,
1185 HANDLE token, PGENERIC_MAPPING mapping )
1187 FIXME("semi-stub\n");
1188 return RtlNewSecurityObjectEx(parent, creator, descr, NULL, is_container, flags, token, mapping);
1191 /******************************************************************************
1192 * RtlDeleteSecurityObject [NTDLL.@]
1194 NTSTATUS WINAPI RtlDeleteSecurityObject( PSECURITY_DESCRIPTOR *descr )
1196 FIXME("%p stub.\n", descr);
1197 RtlFreeHeap( GetProcessHeap(), 0, *descr );
1198 return STATUS_SUCCESS;
1202 * access control list's
1205 /**************************************************************************
1206 * RtlCreateAcl [NTDLL.@]
1208 * NOTES
1209 * This should return NTSTATUS
1211 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1213 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1215 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1216 return STATUS_INVALID_PARAMETER;
1217 if (size<sizeof(ACL))
1218 return STATUS_BUFFER_TOO_SMALL;
1219 if (size>0xFFFF)
1220 return STATUS_INVALID_PARAMETER;
1222 memset(acl,'\0',sizeof(ACL));
1223 acl->AclRevision = rev;
1224 acl->AclSize = size;
1225 acl->AceCount = 0;
1226 return STATUS_SUCCESS;
1229 /**************************************************************************
1230 * RtlFirstFreeAce [NTDLL.@]
1231 * looks for the AceCount+1 ACE, and if it is still within the alloced
1232 * ACL, return a pointer to it
1234 BOOLEAN WINAPI RtlFirstFreeAce(
1235 PACL acl,
1236 PACE_HEADER *x)
1238 PACE_HEADER ace;
1239 int i;
1241 *x = 0;
1242 ace = (PACE_HEADER)(acl+1);
1243 for (i=0;i<acl->AceCount;i++) {
1244 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1245 return FALSE;
1246 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1248 if ((BYTE *)ace <= (BYTE *)acl + acl->AclSize)
1249 *x = ace;
1250 return TRUE;
1253 /**************************************************************************
1254 * RtlAddAce [NTDLL.@]
1256 NTSTATUS WINAPI RtlAddAce(
1257 PACL acl,
1258 DWORD rev,
1259 DWORD xnrofaces,
1260 PACE_HEADER acestart,
1261 DWORD acelen)
1263 PACE_HEADER ace,targetace;
1264 int nrofaces;
1266 if (!RtlValidAcl(acl))
1267 return STATUS_INVALID_PARAMETER;
1268 if (!RtlFirstFreeAce(acl,&targetace))
1269 return STATUS_INVALID_PARAMETER;
1270 if (!targetace)
1271 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1272 nrofaces=0;ace=acestart;
1273 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1274 nrofaces++;
1275 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1277 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1278 return STATUS_INVALID_PARAMETER;
1279 memcpy(targetace,acestart,acelen);
1280 acl->AceCount+=nrofaces;
1281 if (rev > acl->AclRevision)
1282 acl->AclRevision = rev;
1283 return STATUS_SUCCESS;
1286 /**************************************************************************
1287 * RtlDeleteAce [NTDLL.@]
1289 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1291 NTSTATUS status;
1292 PACE_HEADER pAce;
1294 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1296 if (STATUS_SUCCESS == status)
1298 PACE_HEADER pcAce;
1299 DWORD len = 0;
1301 /* skip over the ACE we are deleting */
1302 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1303 dwAceIndex++;
1305 /* calculate the length of the rest */
1306 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1308 len += pcAce->AceSize;
1309 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1312 /* slide them all backwards */
1313 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1314 pAcl->AceCount--;
1317 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1319 return status;
1322 /******************************************************************************
1323 * RtlAddAccessAllowedAce [NTDLL.@]
1325 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1326 IN OUT PACL pAcl,
1327 IN DWORD dwAceRevision,
1328 IN DWORD AccessMask,
1329 IN PSID pSid)
1331 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1334 /******************************************************************************
1335 * RtlAddAccessAllowedAceEx [NTDLL.@]
1337 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1338 IN OUT PACL pAcl,
1339 IN DWORD dwAceRevision,
1340 IN DWORD AceFlags,
1341 IN DWORD AccessMask,
1342 IN PSID pSid)
1344 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1346 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1347 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1350 /******************************************************************************
1351 * RtlAddAccessAllowedObjectAce [NTDLL.@]
1353 NTSTATUS WINAPI RtlAddAccessAllowedObjectAce(
1354 IN OUT PACL pAcl,
1355 IN DWORD dwAceRevision,
1356 IN DWORD dwAceFlags,
1357 IN DWORD dwAccessMask,
1358 IN GUID* pObjectTypeGuid,
1359 IN GUID* pInheritedObjectTypeGuid,
1360 IN PSID pSid)
1362 FIXME("%p %x %x %x %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1363 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1364 return STATUS_NOT_IMPLEMENTED;
1367 /******************************************************************************
1368 * RtlAddAccessDeniedAce [NTDLL.@]
1370 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1371 IN OUT PACL pAcl,
1372 IN DWORD dwAceRevision,
1373 IN DWORD AccessMask,
1374 IN PSID pSid)
1376 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1379 /******************************************************************************
1380 * RtlAddAccessDeniedAceEx [NTDLL.@]
1382 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1383 IN OUT PACL pAcl,
1384 IN DWORD dwAceRevision,
1385 IN DWORD AceFlags,
1386 IN DWORD AccessMask,
1387 IN PSID pSid)
1389 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1391 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1392 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1395 /******************************************************************************
1396 * RtlAddAccessDeniedObjectAce [NTDLL.@]
1398 NTSTATUS WINAPI RtlAddAccessDeniedObjectAce(
1399 IN OUT PACL pAcl,
1400 IN DWORD dwAceRevision,
1401 IN DWORD dwAceFlags,
1402 IN DWORD dwAccessMask,
1403 IN GUID* pObjectTypeGuid,
1404 IN GUID* pInheritedObjectTypeGuid,
1405 IN PSID pSid)
1407 FIXME("%p %x %x %x %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1408 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1409 return STATUS_NOT_IMPLEMENTED;
1412 /**************************************************************************
1413 * RtlAddAuditAccessAce [NTDLL.@]
1415 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1416 IN OUT PACL pAcl,
1417 IN DWORD dwAceRevision,
1418 IN DWORD dwAceFlags,
1419 IN DWORD dwAccessMask,
1420 IN PSID pSid,
1421 IN BOOL bAuditSuccess,
1422 IN BOOL bAuditFailure)
1424 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1425 pSid,bAuditSuccess,bAuditFailure);
1427 if (bAuditSuccess)
1428 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1430 if (bAuditFailure)
1431 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1433 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1434 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1437 /**************************************************************************
1438 * RtlAddAuditAccessAce [NTDLL.@]
1440 NTSTATUS WINAPI RtlAddAuditAccessAce(
1441 IN OUT PACL pAcl,
1442 IN DWORD dwAceRevision,
1443 IN DWORD dwAccessMask,
1444 IN PSID pSid,
1445 IN BOOL bAuditSuccess,
1446 IN BOOL bAuditFailure)
1448 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1451 /******************************************************************************
1452 * RtlAddAuditAccessObjectAce [NTDLL.@]
1454 NTSTATUS WINAPI RtlAddAuditAccessObjectAce(
1455 IN OUT PACL pAcl,
1456 IN DWORD dwAceRevision,
1457 IN DWORD dwAceFlags,
1458 IN DWORD dwAccessMask,
1459 IN GUID* pObjectTypeGuid,
1460 IN GUID* pInheritedObjectTypeGuid,
1461 IN PSID pSid,
1462 IN BOOL bAuditSuccess,
1463 IN BOOL bAuditFailure)
1465 FIXME("%p %x %x %x %p %p %p %d %d - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1466 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid, bAuditSuccess, bAuditFailure);
1467 return STATUS_NOT_IMPLEMENTED;
1470 /**************************************************************************
1471 * RtlAddMandatoryAce [NTDLL.@]
1473 NTSTATUS WINAPI RtlAddMandatoryAce(
1474 IN OUT PACL pAcl,
1475 IN DWORD dwAceRevision,
1476 IN DWORD dwAceFlags,
1477 IN DWORD dwMandatoryFlags,
1478 IN DWORD dwAceType,
1479 IN PSID pSid)
1481 static const DWORD valid_flags = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP |
1482 SYSTEM_MANDATORY_LABEL_NO_READ_UP |
1483 SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP;
1485 TRACE("(%p, %u, 0x%08x, 0x%08x, %u, %p)\n", pAcl, dwAceRevision, dwAceFlags,
1486 dwMandatoryFlags, dwAceType, pSid);
1488 if (dwAceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE)
1489 return STATUS_INVALID_PARAMETER;
1491 if (dwMandatoryFlags & ~valid_flags)
1492 return STATUS_INVALID_PARAMETER;
1494 return add_access_ace(pAcl, dwAceRevision, dwAceFlags, dwMandatoryFlags, pSid, dwAceType);
1497 /******************************************************************************
1498 * RtlValidAcl [NTDLL.@]
1500 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1502 BOOLEAN ret;
1503 TRACE("(%p)\n", pAcl);
1505 __TRY
1507 PACE_HEADER ace;
1508 int i;
1510 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1511 pAcl->AclRevision > MAX_ACL_REVISION)
1512 ret = FALSE;
1513 else
1515 ace = (PACE_HEADER)(pAcl+1);
1516 ret = TRUE;
1517 for (i=0;i<=pAcl->AceCount;i++)
1519 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1521 ret = FALSE;
1522 break;
1524 if (i != pAcl->AceCount)
1525 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1529 __EXCEPT_PAGE_FAULT
1531 WARN("(%p): invalid pointer!\n", pAcl);
1532 return FALSE;
1534 __ENDTRY
1535 return ret;
1538 /******************************************************************************
1539 * RtlGetAce [NTDLL.@]
1541 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1543 PACE_HEADER ace;
1545 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1547 if (dwAceIndex >= pAcl->AceCount)
1548 return STATUS_INVALID_PARAMETER;
1550 ace = (PACE_HEADER)(pAcl + 1);
1551 for (;dwAceIndex;dwAceIndex--)
1552 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1554 *pAce = ace;
1556 return STATUS_SUCCESS;
1560 * misc
1563 /******************************************************************************
1564 * RtlAdjustPrivilege [NTDLL.@]
1566 * Enables or disables a privilege from the calling thread or process.
1568 * PARAMS
1569 * Privilege [I] Privilege index to change.
1570 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1571 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1572 * Enabled [O] Whether privilege was previously enabled or disabled.
1574 * RETURNS
1575 * Success: STATUS_SUCCESS.
1576 * Failure: NTSTATUS code.
1578 * SEE ALSO
1579 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1582 NTSTATUS WINAPI
1583 RtlAdjustPrivilege(ULONG Privilege,
1584 BOOLEAN Enable,
1585 BOOLEAN CurrentThread,
1586 PBOOLEAN Enabled)
1588 TOKEN_PRIVILEGES NewState;
1589 TOKEN_PRIVILEGES OldState;
1590 ULONG ReturnLength;
1591 HANDLE TokenHandle;
1592 NTSTATUS Status;
1594 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1595 CurrentThread ? "TRUE" : "FALSE", Enabled);
1597 if (CurrentThread)
1599 Status = NtOpenThreadToken(GetCurrentThread(),
1600 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1601 FALSE,
1602 &TokenHandle);
1604 else
1606 Status = NtOpenProcessToken(GetCurrentProcess(),
1607 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1608 &TokenHandle);
1611 if (Status)
1613 WARN("Retrieving token handle failed (Status %x)\n", Status);
1614 return Status;
1617 OldState.PrivilegeCount = 1;
1619 NewState.PrivilegeCount = 1;
1620 NewState.Privileges[0].Luid.LowPart = Privilege;
1621 NewState.Privileges[0].Luid.HighPart = 0;
1622 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1624 Status = NtAdjustPrivilegesToken(TokenHandle,
1625 FALSE,
1626 &NewState,
1627 sizeof(TOKEN_PRIVILEGES),
1628 &OldState,
1629 &ReturnLength);
1630 NtClose (TokenHandle);
1631 if (Status == STATUS_NOT_ALL_ASSIGNED)
1633 TRACE("Failed to assign all privileges\n");
1634 return STATUS_PRIVILEGE_NOT_HELD;
1636 if (Status)
1638 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1639 return Status;
1642 if (OldState.PrivilegeCount == 0)
1643 *Enabled = Enable;
1644 else
1645 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1647 return STATUS_SUCCESS;
1650 /******************************************************************************
1651 * RtlImpersonateSelf [NTDLL.@]
1653 * Makes an impersonation token that represents the process user and assigns
1654 * to the current thread.
1656 * PARAMS
1657 * ImpersonationLevel [I] Level at which to impersonate.
1659 * RETURNS
1660 * Success: STATUS_SUCCESS.
1661 * Failure: NTSTATUS code.
1663 NTSTATUS WINAPI
1664 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1666 NTSTATUS Status;
1667 OBJECT_ATTRIBUTES ObjectAttributes;
1668 HANDLE ProcessToken;
1669 HANDLE ImpersonationToken;
1671 TRACE("(%08x)\n", ImpersonationLevel);
1673 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1674 &ProcessToken);
1675 if (Status != STATUS_SUCCESS)
1676 return Status;
1678 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1680 Status = NtDuplicateToken( ProcessToken,
1681 TOKEN_IMPERSONATE,
1682 &ObjectAttributes,
1683 ImpersonationLevel,
1684 TokenImpersonation,
1685 &ImpersonationToken );
1686 if (Status != STATUS_SUCCESS)
1688 NtClose( ProcessToken );
1689 return Status;
1692 Status = NtSetInformationThread( GetCurrentThread(),
1693 ThreadImpersonationToken,
1694 &ImpersonationToken,
1695 sizeof(ImpersonationToken) );
1697 NtClose( ImpersonationToken );
1698 NtClose( ProcessToken );
1700 return Status;
1704 /******************************************************************************
1705 * RtlConvertSidToUnicodeString (NTDLL.@)
1707 * The returned SID is used to access the USER registry hive usually
1709 * the native function returns something like
1710 * "S-1-5-21-0000000000-000000000-0000000000-500";
1712 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1713 PUNICODE_STRING String,
1714 PSID pSid,
1715 BOOLEAN AllocateString)
1717 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1718 WCHAR *p = buffer;
1719 const SID *sid = pSid;
1720 DWORD i, len;
1722 *p++ = 'S';
1723 p += swprintf( p, ARRAY_SIZE(buffer) - (p - buffer), L"-%u", sid->Revision );
1724 p += swprintf( p, ARRAY_SIZE(buffer) - (p - buffer), L"-%u",
1725 MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1726 sid->IdentifierAuthority.Value[4] ),
1727 MAKEWORD( sid->IdentifierAuthority.Value[3],
1728 sid->IdentifierAuthority.Value[2] )));
1729 for (i = 0; i < sid->SubAuthorityCount; i++)
1730 p += swprintf( p, ARRAY_SIZE(buffer) - (p - buffer), L"-%u", sid->SubAuthority[i] );
1732 len = (p + 1 - buffer) * sizeof(WCHAR);
1734 String->Length = len - sizeof(WCHAR);
1735 if (AllocateString)
1737 String->MaximumLength = len;
1738 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1739 return STATUS_NO_MEMORY;
1741 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1743 memcpy( String->Buffer, buffer, len );
1744 return STATUS_SUCCESS;
1747 /******************************************************************************
1748 * RtlQueryInformationAcl (NTDLL.@)
1750 NTSTATUS WINAPI RtlQueryInformationAcl(
1751 PACL pAcl,
1752 LPVOID pAclInformation,
1753 DWORD nAclInformationLength,
1754 ACL_INFORMATION_CLASS dwAclInformationClass)
1756 NTSTATUS status = STATUS_SUCCESS;
1758 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1759 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1761 switch (dwAclInformationClass)
1763 case AclRevisionInformation:
1765 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1767 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1768 status = STATUS_INVALID_PARAMETER;
1769 else
1770 paclrev->AclRevision = pAcl->AclRevision;
1772 break;
1775 case AclSizeInformation:
1777 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1779 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1780 status = STATUS_INVALID_PARAMETER;
1781 else
1783 paclsize->AceCount = pAcl->AceCount;
1784 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1785 if (pAcl->AclSize < paclsize->AclBytesInUse)
1787 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1788 paclsize->AclBytesFree = 0;
1789 paclsize->AclBytesInUse = pAcl->AclSize;
1791 else
1792 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1795 break;
1798 default:
1799 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1800 status = STATUS_INVALID_PARAMETER;
1803 return status;
1806 NTSTATUS WINAPI RtlConvertToAutoInheritSecurityObject(
1807 PSECURITY_DESCRIPTOR pdesc,
1808 PSECURITY_DESCRIPTOR cdesc,
1809 PSECURITY_DESCRIPTOR* ndesc,
1810 GUID* objtype,
1811 BOOL isdir,
1812 PGENERIC_MAPPING genmap )
1814 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
1816 return STATUS_NOT_IMPLEMENTED;
1819 /******************************************************************************
1820 * RtlDefaultNpAcl (NTDLL.@)
1822 NTSTATUS WINAPI RtlDefaultNpAcl(PACL *pAcl)
1824 FIXME("%p - stub\n", pAcl);
1826 *pAcl = NULL;
1827 return STATUS_SUCCESS;