ntdll: Implement NtCreateDebugObject().
[wine.git] / dlls / ntdll / sec.c
blobeccfc82ce8c2a67a9f1a4c69d69661b1fd6cb40d
1 /*
2 * Security functions
4 * Copyright 1996-1998 Marcus Meissner
5 * Copyright 2003 CodeWeavers Inc. (Ulrich Czekalla)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <stdarg.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <time.h>
26 #include <ctype.h>
27 #include <math.h>
29 #include "ntstatus.h"
30 #define WIN32_NO_STATUS
31 #include "windef.h"
32 #include "ntdll_misc.h"
33 #include "wine/exception.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
38 #define SELF_RELATIVE_FIELD(sd,field) ((BYTE *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
40 /* helper function to retrieve active length of an ACL */
41 static size_t acl_bytesInUse(PACL pAcl)
43 int i;
44 size_t bytesInUse = sizeof(ACL);
45 PACE_HEADER ace = (PACE_HEADER) (pAcl + 1);
46 for (i = 0; i < pAcl->AceCount; i++)
48 bytesInUse += ace->AceSize;
49 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
51 return bytesInUse;
54 /* helper function to copy an ACL */
55 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
57 DWORD size;
59 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
60 return FALSE;
62 size = pSourceAcl->AclSize;
63 if (nDestinationAclLength < size)
64 return FALSE;
66 memmove(pDestinationAcl, pSourceAcl, size);
67 return TRUE;
70 /* generically adds an ACE to an ACL */
71 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
72 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
74 ACE_HEADER *pAceHeader;
75 DWORD dwLengthSid;
76 DWORD dwAceSize;
77 DWORD *pAccessMask;
78 DWORD *pSidStart;
80 if (!RtlValidSid(pSid))
81 return STATUS_INVALID_SID;
83 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
84 return STATUS_REVISION_MISMATCH;
86 if (!RtlValidAcl(pAcl))
87 return STATUS_INVALID_ACL;
89 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
90 return STATUS_INVALID_ACL;
92 if (!pAceHeader)
93 return STATUS_ALLOTTED_SPACE_EXCEEDED;
95 /* calculate generic size of the ACE */
96 dwLengthSid = RtlLengthSid(pSid);
97 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
98 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
99 return STATUS_ALLOTTED_SPACE_EXCEEDED;
101 /* fill the new ACE */
102 pAceHeader->AceType = dwAceType;
103 pAceHeader->AceFlags = dwAceFlags;
104 pAceHeader->AceSize = dwAceSize;
106 /* skip past the ACE_HEADER of the ACE */
107 pAccessMask = (DWORD *)(pAceHeader + 1);
108 *pAccessMask = dwAccessMask;
110 /* skip past ACE->Mask */
111 pSidStart = pAccessMask + 1;
112 RtlCopySid(dwLengthSid, pSidStart, pSid);
114 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
115 pAcl->AceCount++;
117 return STATUS_SUCCESS;
121 * SID FUNCTIONS
124 /******************************************************************************
125 * RtlAllocateAndInitializeSid [NTDLL.@]
128 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
129 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
130 BYTE nSubAuthorityCount,
131 DWORD nSubAuthority0, DWORD nSubAuthority1,
132 DWORD nSubAuthority2, DWORD nSubAuthority3,
133 DWORD nSubAuthority4, DWORD nSubAuthority5,
134 DWORD nSubAuthority6, DWORD nSubAuthority7,
135 PSID *pSid )
137 SID *tmp_sid;
139 TRACE("(%p, 0x%04x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,0x%08x,%p)\n",
140 pIdentifierAuthority,nSubAuthorityCount,
141 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
142 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
144 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
146 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
147 RtlLengthRequiredSid(nSubAuthorityCount))))
148 return STATUS_NO_MEMORY;
150 tmp_sid->Revision = SID_REVISION;
152 if (pIdentifierAuthority)
153 tmp_sid->IdentifierAuthority = *pIdentifierAuthority;
154 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
156 switch( nSubAuthorityCount )
158 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
159 /* fall through */
160 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
161 /* fall through */
162 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
163 /* fall through */
164 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
165 /* fall through */
166 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
167 /* fall through */
168 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
169 /* fall through */
170 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
171 /* fall through */
172 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
173 break;
175 *pSid = tmp_sid;
176 return STATUS_SUCCESS;
179 /******************************************************************************
180 * RtlEqualSid [NTDLL.@]
182 * Determine if two SIDs are equal.
184 * PARAMS
185 * pSid1 [I] Source SID
186 * pSid2 [I] SID to compare with
188 * RETURNS
189 * TRUE, if pSid1 is equal to pSid2,
190 * FALSE otherwise.
192 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
194 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
195 return FALSE;
197 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
198 return FALSE;
200 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
201 return FALSE;
203 return TRUE;
206 /******************************************************************************
207 * RtlEqualPrefixSid [NTDLL.@]
209 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
211 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
212 return FALSE;
214 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
215 return FALSE;
217 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
218 return FALSE;
220 return TRUE;
224 /******************************************************************************
225 * RtlFreeSid [NTDLL.@]
227 * Free the resources used by a SID.
229 * PARAMS
230 * pSid [I] SID to Free.
232 * RETURNS
233 * STATUS_SUCCESS.
235 DWORD WINAPI RtlFreeSid(PSID pSid)
237 TRACE("(%p)\n", pSid);
238 RtlFreeHeap( GetProcessHeap(), 0, pSid );
239 return STATUS_SUCCESS;
242 /**************************************************************************
243 * RtlLengthRequiredSid [NTDLL.@]
245 * Determine the amount of memory a SID will use
247 * PARAMS
248 * nrofsubauths [I] Number of Sub Authorities in the SID.
250 * RETURNS
251 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
253 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
255 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
258 /**************************************************************************
259 * RtlLengthSid [NTDLL.@]
261 * Determine the amount of memory a SID is using
263 * PARAMS
264 * pSid [I] SID to get the size of.
266 * RETURNS
267 * The size, in bytes, of pSid.
269 DWORD WINAPI RtlLengthSid(PSID pSid)
271 TRACE("sid=%p\n",pSid);
272 if (!pSid) return 0;
273 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
276 /**************************************************************************
277 * RtlInitializeSid [NTDLL.@]
279 * Initialise a SID.
281 * PARAMS
282 * pSid [I] SID to initialise
283 * pIdentifierAuthority [I] Identifier Authority
284 * nSubAuthorityCount [I] Number of Sub Authorities
286 * RETURNS
287 * Success: TRUE. pSid is initialised with the details given.
288 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
290 BOOL WINAPI RtlInitializeSid(
291 PSID pSid,
292 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
293 BYTE nSubAuthorityCount)
295 int i;
296 SID* pisid=pSid;
298 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
299 return FALSE;
301 pisid->Revision = SID_REVISION;
302 pisid->SubAuthorityCount = nSubAuthorityCount;
303 if (pIdentifierAuthority)
304 pisid->IdentifierAuthority = *pIdentifierAuthority;
306 for (i = 0; i < nSubAuthorityCount; i++)
307 *RtlSubAuthoritySid(pSid, i) = 0;
309 return TRUE;
312 /**************************************************************************
313 * RtlSubAuthoritySid [NTDLL.@]
315 * Return the Sub Authority of a SID
317 * PARAMS
318 * pSid [I] SID to get the Sub Authority from.
319 * nSubAuthority [I] Sub Authority number.
321 * RETURNS
322 * A pointer to The Sub Authority value of pSid.
324 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
326 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
329 /**************************************************************************
330 * RtlIdentifierAuthoritySid [NTDLL.@]
332 * Return the Identifier Authority of a SID.
334 * PARAMS
335 * pSid [I] SID to get the Identifier Authority from.
337 * RETURNS
338 * A pointer to the Identifier Authority value of pSid.
340 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
342 return &(((SID*)pSid)->IdentifierAuthority);
345 /**************************************************************************
346 * RtlSubAuthorityCountSid [NTDLL.@]
348 * Get the number of Sub Authorities in a SID.
350 * PARAMS
351 * pSid [I] SID to get the count from.
353 * RETURNS
354 * A pointer to the Sub Authority count of pSid.
356 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
358 return &(((SID*)pSid)->SubAuthorityCount);
361 /**************************************************************************
362 * RtlCopySid [NTDLL.@]
364 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
366 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
367 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
368 return FALSE;
370 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
371 return FALSE;
373 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
374 return TRUE;
376 /******************************************************************************
377 * RtlValidSid [NTDLL.@]
379 * Determine if a SID is valid.
381 * PARAMS
382 * pSid [I] SID to check
384 * RETURNS
385 * TRUE if pSid is valid,
386 * FALSE otherwise.
388 BOOLEAN WINAPI RtlValidSid( PSID pSid )
390 BOOL ret;
391 __TRY
393 ret = TRUE;
394 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
395 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
397 ret = FALSE;
400 __EXCEPT_PAGE_FAULT
402 WARN("(%p): invalid pointer!\n", pSid);
403 return FALSE;
405 __ENDTRY
406 return ret;
411 * security descriptor functions
414 /**************************************************************************
415 * RtlCreateSecurityDescriptor [NTDLL.@]
417 * Initialise a SECURITY_DESCRIPTOR.
419 * PARAMS
420 * lpsd [O] Descriptor to initialise.
421 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
423 * RETURNS
424 * Success: STATUS_SUCCESS.
425 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
427 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
428 PSECURITY_DESCRIPTOR lpsd,
429 DWORD rev)
431 if (rev!=SECURITY_DESCRIPTOR_REVISION)
432 return STATUS_UNKNOWN_REVISION;
433 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
434 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
435 return STATUS_SUCCESS;
438 /**************************************************************************
439 * RtlCopySecurityDescriptor [NTDLL.@]
441 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
443 * PARAMS
444 * pSourceSD [O] SD to copy from.
445 * pDestinationSD [I] Destination SD.
447 * RETURNS
448 * Success: STATUS_SUCCESS.
449 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
451 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
453 PSID Owner, Group;
454 PACL Dacl, Sacl;
455 DWORD length;
457 if (((SECURITY_DESCRIPTOR *)pSourceSD)->Control & SE_SELF_RELATIVE)
459 SECURITY_DESCRIPTOR_RELATIVE *src = pSourceSD;
460 SECURITY_DESCRIPTOR_RELATIVE *dst = pDestinationSD;
462 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
463 return STATUS_UNKNOWN_REVISION;
465 *dst = *src;
466 if (src->Owner)
468 Owner = (PSID)SELF_RELATIVE_FIELD( src, Owner );
469 length = RtlLengthSid( Owner );
470 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Owner ), Owner);
472 if (src->Group)
474 Group = (PSID)SELF_RELATIVE_FIELD( src, Group );
475 length = RtlLengthSid( Group );
476 RtlCopySid(length, SELF_RELATIVE_FIELD( dst, Group ), Group);
478 if ((src->Control & SE_SACL_PRESENT) && src->Sacl)
480 Sacl = (PACL)SELF_RELATIVE_FIELD( src, Sacl );
481 copy_acl(Sacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Sacl ), Sacl);
483 if ((src->Control & SE_DACL_PRESENT) && src->Dacl)
485 Dacl = (PACL)SELF_RELATIVE_FIELD( src, Dacl );
486 copy_acl(Dacl->AclSize, (PACL)SELF_RELATIVE_FIELD( dst, Dacl ), Dacl);
489 else
491 SECURITY_DESCRIPTOR *src = pSourceSD;
492 SECURITY_DESCRIPTOR *dst = pDestinationSD;
494 if (src->Revision != SECURITY_DESCRIPTOR_REVISION)
495 return STATUS_UNKNOWN_REVISION;
497 *dst = *src;
498 if (src->Owner)
500 length = RtlLengthSid( src->Owner );
501 dst->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
502 RtlCopySid(length, dst->Owner, src->Owner);
504 if (src->Group)
506 length = RtlLengthSid( src->Group );
507 dst->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
508 RtlCopySid(length, dst->Group, src->Group);
510 if (src->Control & SE_SACL_PRESENT)
512 length = src->Sacl->AclSize;
513 dst->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
514 copy_acl(length, dst->Sacl, src->Sacl);
516 if (src->Control & SE_DACL_PRESENT)
518 length = src->Dacl->AclSize;
519 dst->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
520 copy_acl(length, dst->Dacl, src->Dacl);
524 return STATUS_SUCCESS;
527 /**************************************************************************
528 * RtlValidSecurityDescriptor [NTDLL.@]
530 * Determine if a SECURITY_DESCRIPTOR is valid.
532 * PARAMS
533 * SecurityDescriptor [I] Descriptor to check.
535 * RETURNS
536 * Success: STATUS_SUCCESS.
537 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
539 NTSTATUS WINAPI RtlValidSecurityDescriptor(
540 PSECURITY_DESCRIPTOR SecurityDescriptor)
542 if ( ! SecurityDescriptor )
543 return STATUS_INVALID_SECURITY_DESCR;
544 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
545 return STATUS_UNKNOWN_REVISION;
547 return STATUS_SUCCESS;
550 /**************************************************************************
551 * RtlValidRelativeSecurityDescriptor [NTDLL.@]
553 BOOLEAN WINAPI RtlValidRelativeSecurityDescriptor(PSECURITY_DESCRIPTOR descriptor,
554 ULONG length, SECURITY_INFORMATION info)
556 FIXME("%p,%u,%d: semi-stub\n", descriptor, length, info);
557 return RtlValidSecurityDescriptor(descriptor) == STATUS_SUCCESS;
560 /**************************************************************************
561 * RtlLengthSecurityDescriptor [NTDLL.@]
563 ULONG WINAPI RtlLengthSecurityDescriptor(
564 PSECURITY_DESCRIPTOR pSecurityDescriptor)
566 ULONG size;
568 if ( pSecurityDescriptor == NULL )
569 return 0;
571 if (((SECURITY_DESCRIPTOR *)pSecurityDescriptor)->Control & SE_SELF_RELATIVE)
573 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
574 size = sizeof(*sd);
575 if (sd->Owner) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Owner));
576 if (sd->Group) size += RtlLengthSid((PSID)SELF_RELATIVE_FIELD(sd,Group));
577 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl)
578 size += ((PACL)SELF_RELATIVE_FIELD(sd,Sacl))->AclSize;
579 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl)
580 size += ((PACL)SELF_RELATIVE_FIELD(sd,Dacl))->AclSize;
582 else
584 SECURITY_DESCRIPTOR *sd = pSecurityDescriptor;
585 size = sizeof(*sd);
586 if (sd->Owner) size += RtlLengthSid( sd->Owner );
587 if (sd->Group) size += RtlLengthSid( sd->Group );
588 if ((sd->Control & SE_SACL_PRESENT) && sd->Sacl) size += sd->Sacl->AclSize;
589 if ((sd->Control & SE_DACL_PRESENT) && sd->Dacl) size += sd->Dacl->AclSize;
591 return size;
594 /******************************************************************************
595 * RtlGetDaclSecurityDescriptor [NTDLL.@]
598 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
599 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
600 OUT PBOOLEAN lpbDaclPresent,
601 OUT PACL *pDacl,
602 OUT PBOOLEAN lpbDaclDefaulted)
604 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
606 TRACE("(%p,%p,%p,%p)\n",
607 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
609 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
610 return STATUS_UNKNOWN_REVISION ;
612 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
614 if (lpsd->Control & SE_SELF_RELATIVE)
616 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
617 if (sdr->Dacl) *pDacl = (PACL)SELF_RELATIVE_FIELD( sdr, Dacl );
618 else *pDacl = NULL;
620 else *pDacl = lpsd->Dacl;
622 *lpbDaclDefaulted = (lpsd->Control & SE_DACL_DEFAULTED) != 0;
624 else
626 *pDacl = NULL;
627 *lpbDaclDefaulted = 0;
630 return STATUS_SUCCESS;
633 /**************************************************************************
634 * RtlSetDaclSecurityDescriptor [NTDLL.@]
636 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
637 PSECURITY_DESCRIPTOR pSecurityDescriptor,
638 BOOLEAN daclpresent,
639 PACL dacl,
640 BOOLEAN dacldefaulted )
642 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
644 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
645 return STATUS_UNKNOWN_REVISION;
646 if (lpsd->Control & SE_SELF_RELATIVE)
647 return STATUS_INVALID_SECURITY_DESCR;
649 if (!daclpresent)
651 lpsd->Control &= ~SE_DACL_PRESENT;
652 return STATUS_SUCCESS;
655 lpsd->Control |= SE_DACL_PRESENT;
656 lpsd->Dacl = dacl;
658 if (dacldefaulted)
659 lpsd->Control |= SE_DACL_DEFAULTED;
660 else
661 lpsd->Control &= ~SE_DACL_DEFAULTED;
663 return STATUS_SUCCESS;
666 /******************************************************************************
667 * RtlGetSaclSecurityDescriptor [NTDLL.@]
670 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
671 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
672 OUT PBOOLEAN lpbSaclPresent,
673 OUT PACL *pSacl,
674 OUT PBOOLEAN lpbSaclDefaulted)
676 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
678 TRACE("(%p,%p,%p,%p)\n",
679 pSecurityDescriptor, lpbSaclPresent, pSacl, lpbSaclDefaulted);
681 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
682 return STATUS_UNKNOWN_REVISION;
684 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
686 if (lpsd->Control & SE_SELF_RELATIVE)
688 SECURITY_DESCRIPTOR_RELATIVE *sdr = pSecurityDescriptor;
689 if (sdr->Sacl) *pSacl = (PACL)SELF_RELATIVE_FIELD( sdr, Sacl );
690 else *pSacl = NULL;
692 else *pSacl = lpsd->Sacl;
694 *lpbSaclDefaulted = (lpsd->Control & SE_SACL_DEFAULTED) != 0;
696 return STATUS_SUCCESS;
699 /**************************************************************************
700 * RtlSetSaclSecurityDescriptor [NTDLL.@]
702 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
703 PSECURITY_DESCRIPTOR pSecurityDescriptor,
704 BOOLEAN saclpresent,
705 PACL sacl,
706 BOOLEAN sacldefaulted)
708 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
710 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
711 return STATUS_UNKNOWN_REVISION;
712 if (lpsd->Control & SE_SELF_RELATIVE)
713 return STATUS_INVALID_SECURITY_DESCR;
714 if (!saclpresent) {
715 lpsd->Control &= ~SE_SACL_PRESENT;
716 return 0;
718 lpsd->Control |= SE_SACL_PRESENT;
719 lpsd->Sacl = sacl;
720 if (sacldefaulted)
721 lpsd->Control |= SE_SACL_DEFAULTED;
722 else
723 lpsd->Control &= ~SE_SACL_DEFAULTED;
724 return STATUS_SUCCESS;
727 /**************************************************************************
728 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
730 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
731 PSECURITY_DESCRIPTOR pSecurityDescriptor,
732 PSID *Owner,
733 PBOOLEAN OwnerDefaulted)
735 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
737 if ( !lpsd || !Owner || !OwnerDefaulted )
738 return STATUS_INVALID_PARAMETER;
740 if ( lpsd->Control & SE_OWNER_DEFAULTED )
741 *OwnerDefaulted = TRUE;
742 else
743 *OwnerDefaulted = FALSE;
745 if (lpsd->Control & SE_SELF_RELATIVE)
747 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
748 if (sd->Owner) *Owner = (PSID)SELF_RELATIVE_FIELD( sd, Owner );
749 else *Owner = NULL;
751 else
752 *Owner = lpsd->Owner;
754 return STATUS_SUCCESS;
757 /**************************************************************************
758 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
760 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
761 PSECURITY_DESCRIPTOR pSecurityDescriptor,
762 PSID owner,
763 BOOLEAN ownerdefaulted)
765 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
767 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
768 return STATUS_UNKNOWN_REVISION;
769 if (lpsd->Control & SE_SELF_RELATIVE)
770 return STATUS_INVALID_SECURITY_DESCR;
772 lpsd->Owner = owner;
773 if (ownerdefaulted)
774 lpsd->Control |= SE_OWNER_DEFAULTED;
775 else
776 lpsd->Control &= ~SE_OWNER_DEFAULTED;
777 return STATUS_SUCCESS;
780 /**************************************************************************
781 * RtlSetGroupSecurityDescriptor [NTDLL.@]
783 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
784 PSECURITY_DESCRIPTOR pSecurityDescriptor,
785 PSID group,
786 BOOLEAN groupdefaulted)
788 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
790 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
791 return STATUS_UNKNOWN_REVISION;
792 if (lpsd->Control & SE_SELF_RELATIVE)
793 return STATUS_INVALID_SECURITY_DESCR;
795 lpsd->Group = group;
796 if (groupdefaulted)
797 lpsd->Control |= SE_GROUP_DEFAULTED;
798 else
799 lpsd->Control &= ~SE_GROUP_DEFAULTED;
800 return STATUS_SUCCESS;
803 /**************************************************************************
804 * RtlGetGroupSecurityDescriptor [NTDLL.@]
806 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
807 PSECURITY_DESCRIPTOR pSecurityDescriptor,
808 PSID *Group,
809 PBOOLEAN GroupDefaulted)
811 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
813 if ( !lpsd || !Group || !GroupDefaulted )
814 return STATUS_INVALID_PARAMETER;
816 if ( lpsd->Control & SE_GROUP_DEFAULTED )
817 *GroupDefaulted = TRUE;
818 else
819 *GroupDefaulted = FALSE;
821 if (lpsd->Control & SE_SELF_RELATIVE)
823 SECURITY_DESCRIPTOR_RELATIVE *sd = pSecurityDescriptor;
824 if (sd->Group) *Group = (PSID)SELF_RELATIVE_FIELD( sd, Group );
825 else *Group = NULL;
827 else
828 *Group = lpsd->Group;
830 return STATUS_SUCCESS;
833 /**************************************************************************
834 * RtlMakeSelfRelativeSD [NTDLL.@]
836 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
837 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
838 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
839 IN OUT LPDWORD lpdwBufferLength)
841 DWORD offsetRel;
842 ULONG length;
843 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
844 SECURITY_DESCRIPTOR_RELATIVE *pRel = pSelfRelativeSecurityDescriptor;
846 TRACE(" %p %p %p(%d)\n", pAbs, pRel, lpdwBufferLength,
847 lpdwBufferLength ? *lpdwBufferLength: -1);
849 if (!lpdwBufferLength || !pAbs)
850 return STATUS_INVALID_PARAMETER;
852 length = RtlLengthSecurityDescriptor(pAbs);
853 if (!(pAbs->Control & SE_SELF_RELATIVE)) length -= (sizeof(*pAbs) - sizeof(*pRel));
854 if (*lpdwBufferLength < length)
856 *lpdwBufferLength = length;
857 return STATUS_BUFFER_TOO_SMALL;
860 if (!pRel)
861 return STATUS_INVALID_PARAMETER;
863 if (pAbs->Control & SE_SELF_RELATIVE)
865 memcpy(pRel, pAbs, length);
866 return STATUS_SUCCESS;
869 pRel->Revision = pAbs->Revision;
870 pRel->Sbz1 = pAbs->Sbz1;
871 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
873 offsetRel = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
874 if (pAbs->Owner)
876 pRel->Owner = offsetRel;
877 length = RtlLengthSid(pAbs->Owner);
878 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
879 offsetRel += length;
881 else
883 pRel->Owner = 0;
886 if (pAbs->Group)
888 pRel->Group = offsetRel;
889 length = RtlLengthSid(pAbs->Group);
890 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
891 offsetRel += length;
893 else
895 pRel->Group = 0;
898 if (pAbs->Sacl)
900 pRel->Sacl = offsetRel;
901 length = pAbs->Sacl->AclSize;
902 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
903 offsetRel += length;
905 else
907 pRel->Sacl = 0;
910 if (pAbs->Dacl)
912 pRel->Dacl = offsetRel;
913 length = pAbs->Dacl->AclSize;
914 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
916 else
918 pRel->Dacl = 0;
921 return STATUS_SUCCESS;
925 /**************************************************************************
926 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
928 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
929 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
930 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
931 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
932 OUT PACL pDacl,
933 OUT LPDWORD lpdwDaclSize,
934 OUT PACL pSacl,
935 OUT LPDWORD lpdwSaclSize,
936 OUT PSID pOwner,
937 OUT LPDWORD lpdwOwnerSize,
938 OUT PSID pPrimaryGroup,
939 OUT LPDWORD lpdwPrimaryGroupSize)
941 NTSTATUS status = STATUS_SUCCESS;
942 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
943 SECURITY_DESCRIPTOR_RELATIVE* pRel = pSelfRelativeSecurityDescriptor;
945 if (!pRel ||
946 !lpdwAbsoluteSecurityDescriptorSize ||
947 !lpdwDaclSize ||
948 !lpdwSaclSize ||
949 !lpdwOwnerSize ||
950 !lpdwPrimaryGroupSize ||
951 ~pRel->Control & SE_SELF_RELATIVE)
952 return STATUS_INVALID_PARAMETER;
954 /* Confirm buffers are sufficiently large */
955 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
957 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
958 status = STATUS_BUFFER_TOO_SMALL;
961 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl &&
962 *lpdwDaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize)
964 *lpdwDaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Dacl))->AclSize;
965 status = STATUS_BUFFER_TOO_SMALL;
968 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl &&
969 *lpdwSaclSize < ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize)
971 *lpdwSaclSize = ((PACL)SELF_RELATIVE_FIELD(pRel,Sacl))->AclSize;
972 status = STATUS_BUFFER_TOO_SMALL;
975 if (pRel->Owner &&
976 *lpdwOwnerSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner)))
978 *lpdwOwnerSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Owner));
979 status = STATUS_BUFFER_TOO_SMALL;
982 if (pRel->Group &&
983 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group)))
985 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)SELF_RELATIVE_FIELD(pRel,Group));
986 status = STATUS_BUFFER_TOO_SMALL;
989 if (status != STATUS_SUCCESS)
990 return status;
992 /* Copy structures, and clear the ones we don't set */
993 pAbs->Revision = pRel->Revision;
994 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
995 pAbs->Sacl = NULL;
996 pAbs->Dacl = NULL;
997 pAbs->Owner = NULL;
998 pAbs->Group = NULL;
1000 if ((pRel->Control & SE_SACL_PRESENT) && pRel->Sacl)
1002 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Sacl );
1004 memcpy(pSacl, pAcl, pAcl->AclSize);
1005 pAbs->Sacl = pSacl;
1008 if ((pRel->Control & SE_DACL_PRESENT) && pRel->Dacl)
1010 PACL pAcl = (PACL)SELF_RELATIVE_FIELD( pRel, Dacl );
1011 memcpy(pDacl, pAcl, pAcl->AclSize);
1012 pAbs->Dacl = pDacl;
1015 if (pRel->Owner)
1017 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Owner );
1018 memcpy(pOwner, psid, RtlLengthSid(psid));
1019 pAbs->Owner = pOwner;
1022 if (pRel->Group)
1024 PSID psid = (PSID)SELF_RELATIVE_FIELD( pRel, Group );
1025 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
1026 pAbs->Group = pPrimaryGroup;
1029 return status;
1032 /******************************************************************************
1033 * RtlGetControlSecurityDescriptor (NTDLL.@)
1035 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1036 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1037 PSECURITY_DESCRIPTOR_CONTROL pControl,
1038 LPDWORD lpdwRevision)
1040 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1042 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1044 *lpdwRevision = lpsd->Revision;
1046 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1047 return STATUS_UNKNOWN_REVISION;
1049 *pControl = lpsd->Control;
1051 return STATUS_SUCCESS;
1054 /******************************************************************************
1055 * RtlSetControlSecurityDescriptor (NTDLL.@)
1057 NTSTATUS WINAPI RtlSetControlSecurityDescriptor(
1058 PSECURITY_DESCRIPTOR SecurityDescriptor,
1059 SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest,
1060 SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet)
1062 SECURITY_DESCRIPTOR_CONTROL const immutable
1063 = SE_OWNER_DEFAULTED | SE_GROUP_DEFAULTED
1064 | SE_DACL_PRESENT | SE_DACL_DEFAULTED
1065 | SE_SACL_PRESENT | SE_SACL_DEFAULTED
1066 | SE_RM_CONTROL_VALID | SE_SELF_RELATIVE
1069 SECURITY_DESCRIPTOR *lpsd = SecurityDescriptor;
1071 TRACE("(%p 0x%04x 0x%04x)\n", SecurityDescriptor,
1072 ControlBitsOfInterest, ControlBitsToSet);
1074 if ((ControlBitsOfInterest | ControlBitsToSet) & immutable)
1075 return STATUS_INVALID_PARAMETER;
1077 lpsd->Control |= (ControlBitsOfInterest & ControlBitsToSet);
1078 lpsd->Control &= ~(ControlBitsOfInterest & ~ControlBitsToSet);
1080 return STATUS_SUCCESS;
1084 /**************************************************************************
1085 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1087 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1088 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1089 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1090 PULONG BufferLength)
1092 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1094 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1095 SelfRelativeSecurityDescriptor, BufferLength);
1097 if (abs->Control & SE_SELF_RELATIVE)
1098 return STATUS_BAD_DESCRIPTOR_FORMAT;
1100 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1101 SelfRelativeSecurityDescriptor, BufferLength);
1106 * access control list's
1109 /**************************************************************************
1110 * RtlCreateAcl [NTDLL.@]
1112 * NOTES
1113 * This should return NTSTATUS
1115 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1117 TRACE("%p 0x%08x 0x%08x\n", acl, size, rev);
1119 if (rev < MIN_ACL_REVISION || rev > MAX_ACL_REVISION)
1120 return STATUS_INVALID_PARAMETER;
1121 if (size<sizeof(ACL))
1122 return STATUS_BUFFER_TOO_SMALL;
1123 if (size>0xFFFF)
1124 return STATUS_INVALID_PARAMETER;
1126 memset(acl,'\0',sizeof(ACL));
1127 acl->AclRevision = rev;
1128 acl->AclSize = size;
1129 acl->AceCount = 0;
1130 return STATUS_SUCCESS;
1133 /**************************************************************************
1134 * RtlFirstFreeAce [NTDLL.@]
1135 * looks for the AceCount+1 ACE, and if it is still within the alloced
1136 * ACL, return a pointer to it
1138 BOOLEAN WINAPI RtlFirstFreeAce(
1139 PACL acl,
1140 PACE_HEADER *x)
1142 PACE_HEADER ace;
1143 int i;
1145 *x = 0;
1146 ace = (PACE_HEADER)(acl+1);
1147 for (i=0;i<acl->AceCount;i++) {
1148 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1149 return FALSE;
1150 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1152 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1153 return FALSE;
1154 *x = ace;
1155 return TRUE;
1158 /**************************************************************************
1159 * RtlAddAce [NTDLL.@]
1161 NTSTATUS WINAPI RtlAddAce(
1162 PACL acl,
1163 DWORD rev,
1164 DWORD xnrofaces,
1165 PACE_HEADER acestart,
1166 DWORD acelen)
1168 PACE_HEADER ace,targetace;
1169 int nrofaces;
1171 if (!RtlValidAcl(acl))
1172 return STATUS_INVALID_PARAMETER;
1173 if (!RtlFirstFreeAce(acl,&targetace))
1174 return STATUS_INVALID_PARAMETER;
1175 nrofaces=0;ace=acestart;
1176 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1177 nrofaces++;
1178 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1180 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1181 return STATUS_INVALID_PARAMETER;
1182 memcpy(targetace,acestart,acelen);
1183 acl->AceCount+=nrofaces;
1184 if (rev > acl->AclRevision)
1185 acl->AclRevision = rev;
1186 return STATUS_SUCCESS;
1189 /**************************************************************************
1190 * RtlDeleteAce [NTDLL.@]
1192 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1194 NTSTATUS status;
1195 PACE_HEADER pAce;
1197 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1199 if (STATUS_SUCCESS == status)
1201 PACE_HEADER pcAce;
1202 DWORD len = 0;
1204 /* skip over the ACE we are deleting */
1205 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1206 dwAceIndex++;
1208 /* calculate the length of the rest */
1209 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1211 len += pcAce->AceSize;
1212 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1215 /* slide them all backwards */
1216 memmove(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1217 pAcl->AceCount--;
1220 TRACE("pAcl=%p dwAceIndex=%d status=0x%08x\n", pAcl, dwAceIndex, status);
1222 return status;
1225 /******************************************************************************
1226 * RtlAddAccessAllowedAce [NTDLL.@]
1228 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1229 IN OUT PACL pAcl,
1230 IN DWORD dwAceRevision,
1231 IN DWORD AccessMask,
1232 IN PSID pSid)
1234 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1237 /******************************************************************************
1238 * RtlAddAccessAllowedAceEx [NTDLL.@]
1240 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1241 IN OUT PACL pAcl,
1242 IN DWORD dwAceRevision,
1243 IN DWORD AceFlags,
1244 IN DWORD AccessMask,
1245 IN PSID pSid)
1247 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1249 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1250 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1253 /******************************************************************************
1254 * RtlAddAccessAllowedObjectAce [NTDLL.@]
1256 NTSTATUS WINAPI RtlAddAccessAllowedObjectAce(
1257 IN OUT PACL pAcl,
1258 IN DWORD dwAceRevision,
1259 IN DWORD dwAceFlags,
1260 IN DWORD dwAccessMask,
1261 IN GUID* pObjectTypeGuid,
1262 IN GUID* pInheritedObjectTypeGuid,
1263 IN PSID pSid)
1265 FIXME("%p %x %x %x %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1266 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1267 return STATUS_NOT_IMPLEMENTED;
1270 /******************************************************************************
1271 * RtlAddAccessDeniedAce [NTDLL.@]
1273 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1274 IN OUT PACL pAcl,
1275 IN DWORD dwAceRevision,
1276 IN DWORD AccessMask,
1277 IN PSID pSid)
1279 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1282 /******************************************************************************
1283 * RtlAddAccessDeniedAceEx [NTDLL.@]
1285 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1286 IN OUT PACL pAcl,
1287 IN DWORD dwAceRevision,
1288 IN DWORD AceFlags,
1289 IN DWORD AccessMask,
1290 IN PSID pSid)
1292 TRACE("(%p,0x%08x,0x%08x,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1294 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1295 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1298 /******************************************************************************
1299 * RtlAddAccessDeniedObjectAce [NTDLL.@]
1301 NTSTATUS WINAPI RtlAddAccessDeniedObjectAce(
1302 IN OUT PACL pAcl,
1303 IN DWORD dwAceRevision,
1304 IN DWORD dwAceFlags,
1305 IN DWORD dwAccessMask,
1306 IN GUID* pObjectTypeGuid,
1307 IN GUID* pInheritedObjectTypeGuid,
1308 IN PSID pSid)
1310 FIXME("%p %x %x %x %p %p %p - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1311 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid);
1312 return STATUS_NOT_IMPLEMENTED;
1315 /**************************************************************************
1316 * RtlAddAuditAccessAce [NTDLL.@]
1318 NTSTATUS WINAPI RtlAddAuditAccessAceEx(
1319 IN OUT PACL pAcl,
1320 IN DWORD dwAceRevision,
1321 IN DWORD dwAceFlags,
1322 IN DWORD dwAccessMask,
1323 IN PSID pSid,
1324 IN BOOL bAuditSuccess,
1325 IN BOOL bAuditFailure)
1327 TRACE("(%p,%d,0x%08x,0x%08x,%p,%u,%u)\n",pAcl,dwAceRevision,dwAceFlags,dwAccessMask,
1328 pSid,bAuditSuccess,bAuditFailure);
1330 if (bAuditSuccess)
1331 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1333 if (bAuditFailure)
1334 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1336 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1337 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1340 /**************************************************************************
1341 * RtlAddAuditAccessAce [NTDLL.@]
1343 NTSTATUS WINAPI RtlAddAuditAccessAce(
1344 IN OUT PACL pAcl,
1345 IN DWORD dwAceRevision,
1346 IN DWORD dwAccessMask,
1347 IN PSID pSid,
1348 IN BOOL bAuditSuccess,
1349 IN BOOL bAuditFailure)
1351 return RtlAddAuditAccessAceEx(pAcl, dwAceRevision, 0, dwAccessMask, pSid, bAuditSuccess, bAuditFailure);
1354 /******************************************************************************
1355 * RtlAddAuditAccessObjectAce [NTDLL.@]
1357 NTSTATUS WINAPI RtlAddAuditAccessObjectAce(
1358 IN OUT PACL pAcl,
1359 IN DWORD dwAceRevision,
1360 IN DWORD dwAceFlags,
1361 IN DWORD dwAccessMask,
1362 IN GUID* pObjectTypeGuid,
1363 IN GUID* pInheritedObjectTypeGuid,
1364 IN PSID pSid,
1365 IN BOOL bAuditSuccess,
1366 IN BOOL bAuditFailure)
1368 FIXME("%p %x %x %x %p %p %p %d %d - stub\n", pAcl, dwAceRevision, dwAceFlags, dwAccessMask,
1369 pObjectTypeGuid, pInheritedObjectTypeGuid, pSid, bAuditSuccess, bAuditFailure);
1370 return STATUS_NOT_IMPLEMENTED;
1373 /**************************************************************************
1374 * RtlAddMandatoryAce [NTDLL.@]
1376 NTSTATUS WINAPI RtlAddMandatoryAce(
1377 IN OUT PACL pAcl,
1378 IN DWORD dwAceRevision,
1379 IN DWORD dwAceFlags,
1380 IN DWORD dwMandatoryFlags,
1381 IN DWORD dwAceType,
1382 IN PSID pSid)
1384 static const DWORD valid_flags = SYSTEM_MANDATORY_LABEL_NO_WRITE_UP |
1385 SYSTEM_MANDATORY_LABEL_NO_READ_UP |
1386 SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP;
1388 TRACE("(%p, %u, 0x%08x, 0x%08x, %u, %p)\n", pAcl, dwAceRevision, dwAceFlags,
1389 dwMandatoryFlags, dwAceType, pSid);
1391 if (dwAceType != SYSTEM_MANDATORY_LABEL_ACE_TYPE)
1392 return STATUS_INVALID_PARAMETER;
1394 if (dwMandatoryFlags & ~valid_flags)
1395 return STATUS_INVALID_PARAMETER;
1397 return add_access_ace(pAcl, dwAceRevision, dwAceFlags, dwMandatoryFlags, pSid, dwAceType);
1400 /******************************************************************************
1401 * RtlValidAcl [NTDLL.@]
1403 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1405 BOOLEAN ret;
1406 TRACE("(%p)\n", pAcl);
1408 __TRY
1410 PACE_HEADER ace;
1411 int i;
1413 if (pAcl->AclRevision < MIN_ACL_REVISION ||
1414 pAcl->AclRevision > MAX_ACL_REVISION)
1415 ret = FALSE;
1416 else
1418 ace = (PACE_HEADER)(pAcl+1);
1419 ret = TRUE;
1420 for (i=0;i<=pAcl->AceCount;i++)
1422 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1424 ret = FALSE;
1425 break;
1427 if (i != pAcl->AceCount)
1428 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1432 __EXCEPT_PAGE_FAULT
1434 WARN("(%p): invalid pointer!\n", pAcl);
1435 return FALSE;
1437 __ENDTRY
1438 return ret;
1441 /******************************************************************************
1442 * RtlGetAce [NTDLL.@]
1444 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1446 PACE_HEADER ace;
1448 TRACE("(%p,%d,%p)\n",pAcl,dwAceIndex,pAce);
1450 if (dwAceIndex >= pAcl->AceCount)
1451 return STATUS_INVALID_PARAMETER;
1453 ace = (PACE_HEADER)(pAcl + 1);
1454 for (;dwAceIndex;dwAceIndex--)
1455 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1457 *pAce = ace;
1459 return STATUS_SUCCESS;
1463 * misc
1466 /******************************************************************************
1467 * RtlAdjustPrivilege [NTDLL.@]
1469 * Enables or disables a privilege from the calling thread or process.
1471 * PARAMS
1472 * Privilege [I] Privilege index to change.
1473 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1474 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1475 * Enabled [O] Whether privilege was previously enabled or disabled.
1477 * RETURNS
1478 * Success: STATUS_SUCCESS.
1479 * Failure: NTSTATUS code.
1481 * SEE ALSO
1482 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1485 NTSTATUS WINAPI
1486 RtlAdjustPrivilege(ULONG Privilege,
1487 BOOLEAN Enable,
1488 BOOLEAN CurrentThread,
1489 PBOOLEAN Enabled)
1491 TOKEN_PRIVILEGES NewState;
1492 TOKEN_PRIVILEGES OldState;
1493 ULONG ReturnLength;
1494 HANDLE TokenHandle;
1495 NTSTATUS Status;
1497 TRACE("(%d, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1498 CurrentThread ? "TRUE" : "FALSE", Enabled);
1500 if (CurrentThread)
1502 Status = NtOpenThreadToken(GetCurrentThread(),
1503 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1504 FALSE,
1505 &TokenHandle);
1507 else
1509 Status = NtOpenProcessToken(GetCurrentProcess(),
1510 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1511 &TokenHandle);
1514 if (Status)
1516 WARN("Retrieving token handle failed (Status %x)\n", Status);
1517 return Status;
1520 OldState.PrivilegeCount = 1;
1522 NewState.PrivilegeCount = 1;
1523 NewState.Privileges[0].Luid.LowPart = Privilege;
1524 NewState.Privileges[0].Luid.HighPart = 0;
1525 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1527 Status = NtAdjustPrivilegesToken(TokenHandle,
1528 FALSE,
1529 &NewState,
1530 sizeof(TOKEN_PRIVILEGES),
1531 &OldState,
1532 &ReturnLength);
1533 NtClose (TokenHandle);
1534 if (Status == STATUS_NOT_ALL_ASSIGNED)
1536 TRACE("Failed to assign all privileges\n");
1537 return STATUS_PRIVILEGE_NOT_HELD;
1539 if (Status)
1541 WARN("NtAdjustPrivilegesToken() failed (Status %x)\n", Status);
1542 return Status;
1545 if (OldState.PrivilegeCount == 0)
1546 *Enabled = Enable;
1547 else
1548 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1550 return STATUS_SUCCESS;
1553 /******************************************************************************
1554 * RtlImpersonateSelf [NTDLL.@]
1556 * Makes an impersonation token that represents the process user and assigns
1557 * to the current thread.
1559 * PARAMS
1560 * ImpersonationLevel [I] Level at which to impersonate.
1562 * RETURNS
1563 * Success: STATUS_SUCCESS.
1564 * Failure: NTSTATUS code.
1566 NTSTATUS WINAPI
1567 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1569 NTSTATUS Status;
1570 OBJECT_ATTRIBUTES ObjectAttributes;
1571 HANDLE ProcessToken;
1572 HANDLE ImpersonationToken;
1574 TRACE("(%08x)\n", ImpersonationLevel);
1576 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1577 &ProcessToken);
1578 if (Status != STATUS_SUCCESS)
1579 return Status;
1581 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1583 Status = NtDuplicateToken( ProcessToken,
1584 TOKEN_IMPERSONATE,
1585 &ObjectAttributes,
1586 ImpersonationLevel,
1587 TokenImpersonation,
1588 &ImpersonationToken );
1589 if (Status != STATUS_SUCCESS)
1591 NtClose( ProcessToken );
1592 return Status;
1595 Status = NtSetInformationThread( GetCurrentThread(),
1596 ThreadImpersonationToken,
1597 &ImpersonationToken,
1598 sizeof(ImpersonationToken) );
1600 NtClose( ImpersonationToken );
1601 NtClose( ProcessToken );
1603 return Status;
1607 /******************************************************************************
1608 * RtlConvertSidToUnicodeString (NTDLL.@)
1610 * The returned SID is used to access the USER registry hive usually
1612 * the native function returns something like
1613 * "S-1-5-21-0000000000-000000000-0000000000-500";
1615 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1616 PUNICODE_STRING String,
1617 PSID pSid,
1618 BOOLEAN AllocateString)
1620 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1621 WCHAR *p = buffer;
1622 const SID *sid = pSid;
1623 DWORD i, len;
1625 *p++ = 'S';
1626 p += swprintf( p, ARRAY_SIZE(buffer) - (p - buffer), L"-%u", sid->Revision );
1627 p += swprintf( p, ARRAY_SIZE(buffer) - (p - buffer), L"-%u",
1628 MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1629 sid->IdentifierAuthority.Value[4] ),
1630 MAKEWORD( sid->IdentifierAuthority.Value[3],
1631 sid->IdentifierAuthority.Value[2] )));
1632 for (i = 0; i < sid->SubAuthorityCount; i++)
1633 p += swprintf( p, ARRAY_SIZE(buffer) - (p - buffer), L"-%u", sid->SubAuthority[i] );
1635 len = (p + 1 - buffer) * sizeof(WCHAR);
1637 String->Length = len - sizeof(WCHAR);
1638 if (AllocateString)
1640 String->MaximumLength = len;
1641 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1642 return STATUS_NO_MEMORY;
1644 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1646 memcpy( String->Buffer, buffer, len );
1647 return STATUS_SUCCESS;
1650 /******************************************************************************
1651 * RtlQueryInformationAcl (NTDLL.@)
1653 NTSTATUS WINAPI RtlQueryInformationAcl(
1654 PACL pAcl,
1655 LPVOID pAclInformation,
1656 DWORD nAclInformationLength,
1657 ACL_INFORMATION_CLASS dwAclInformationClass)
1659 NTSTATUS status = STATUS_SUCCESS;
1661 TRACE("pAcl=%p pAclInfo=%p len=%d, class=%d\n",
1662 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1664 switch (dwAclInformationClass)
1666 case AclRevisionInformation:
1668 PACL_REVISION_INFORMATION paclrev = pAclInformation;
1670 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1671 status = STATUS_INVALID_PARAMETER;
1672 else
1673 paclrev->AclRevision = pAcl->AclRevision;
1675 break;
1678 case AclSizeInformation:
1680 PACL_SIZE_INFORMATION paclsize = pAclInformation;
1682 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1683 status = STATUS_INVALID_PARAMETER;
1684 else
1686 paclsize->AceCount = pAcl->AceCount;
1687 paclsize->AclBytesInUse = acl_bytesInUse(pAcl);
1688 if (pAcl->AclSize < paclsize->AclBytesInUse)
1690 WARN("Acl uses %d bytes, but only has %d allocated! Returning smaller of the two values.\n", pAcl->AclSize, paclsize->AclBytesInUse);
1691 paclsize->AclBytesFree = 0;
1692 paclsize->AclBytesInUse = pAcl->AclSize;
1694 else
1695 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1698 break;
1701 default:
1702 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1703 status = STATUS_INVALID_PARAMETER;
1706 return status;
1709 NTSTATUS WINAPI RtlConvertToAutoInheritSecurityObject(
1710 PSECURITY_DESCRIPTOR pdesc,
1711 PSECURITY_DESCRIPTOR cdesc,
1712 PSECURITY_DESCRIPTOR* ndesc,
1713 GUID* objtype,
1714 BOOL isdir,
1715 PGENERIC_MAPPING genmap )
1717 FIXME("%p %p %p %p %d %p - stub\n", pdesc, cdesc, ndesc, objtype, isdir, genmap);
1719 return STATUS_NOT_IMPLEMENTED;
1722 /******************************************************************************
1723 * RtlDefaultNpAcl (NTDLL.@)
1725 NTSTATUS WINAPI RtlDefaultNpAcl(PACL *pAcl)
1727 FIXME("%p - stub\n", pAcl);
1729 *pAcl = NULL;
1730 return STATUS_SUCCESS;