ntdll: Add a test for NtNotifyChangeDirectoryFile.
[wine/multimedia.git] / dlls / ntdll / sec.c
blob8fd21f733d4e78f9998c70bcf69ab26e802a5baa
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <time.h>
29 #include <ctype.h>
30 #include <math.h>
31 #ifdef HAVE_UNISTD_H
32 # include <unistd.h>
33 #endif
35 #include "ntstatus.h"
36 #define WIN32_NO_STATUS
37 #include "windef.h"
38 #include "wine/exception.h"
39 #include "ntdll_misc.h"
40 #include "excpt.h"
41 #include "wine/library.h"
42 #include "wine/unicode.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
47 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
49 /* helper function to copy an ACL */
50 static BOOLEAN copy_acl(DWORD nDestinationAclLength, PACL pDestinationAcl, PACL pSourceAcl)
52 DWORD size;
54 if (!pSourceAcl || !RtlValidAcl(pSourceAcl))
55 return FALSE;
57 size = ((ACL *)pSourceAcl)->AclSize;
58 if (nDestinationAclLength < size)
59 return FALSE;
61 memmove(pDestinationAcl, pSourceAcl, size);
62 return TRUE;
65 /* generically adds an ACE to an ACL */
66 static NTSTATUS add_access_ace(PACL pAcl, DWORD dwAceRevision, DWORD dwAceFlags,
67 DWORD dwAccessMask, PSID pSid, DWORD dwAceType)
69 ACE_HEADER *pAceHeader;
70 DWORD dwLengthSid;
71 DWORD dwAceSize;
72 DWORD *pAccessMask;
73 DWORD *pSidStart;
75 if (!RtlValidSid(pSid))
76 return STATUS_INVALID_SID;
78 if (pAcl->AclRevision > MAX_ACL_REVISION || dwAceRevision > MAX_ACL_REVISION)
79 return STATUS_REVISION_MISMATCH;
81 if (!RtlValidAcl(pAcl))
82 return STATUS_INVALID_ACL;
84 if (!RtlFirstFreeAce(pAcl, &pAceHeader))
85 return STATUS_INVALID_ACL;
87 if (!pAceHeader)
88 return STATUS_ALLOTTED_SPACE_EXCEEDED;
90 /* calculate generic size of the ACE */
91 dwLengthSid = RtlLengthSid(pSid);
92 dwAceSize = sizeof(ACE_HEADER) + sizeof(DWORD) + dwLengthSid;
93 if ((char *)pAceHeader + dwAceSize > (char *)pAcl + pAcl->AclSize)
94 return STATUS_ALLOTTED_SPACE_EXCEEDED;
96 /* fill the new ACE */
97 pAceHeader->AceType = dwAceType;
98 pAceHeader->AceFlags = dwAceFlags;
99 pAceHeader->AceSize = dwAceSize;
101 /* skip past the ACE_HEADER of the ACE */
102 pAccessMask = (DWORD *)(pAceHeader + 1);
103 *pAccessMask = dwAccessMask;
105 /* skip past ACE->Mask */
106 pSidStart = pAccessMask + 1;
107 RtlCopySid(dwLengthSid, (PSID)pSidStart, pSid);
109 pAcl->AclRevision = max(pAcl->AclRevision, dwAceRevision);
110 pAcl->AceCount++;
112 return STATUS_SUCCESS;
116 * SID FUNCTIONS
119 /******************************************************************************
120 * RtlAllocateAndInitializeSid [NTDLL.@]
123 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
124 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
125 BYTE nSubAuthorityCount,
126 DWORD nSubAuthority0, DWORD nSubAuthority1,
127 DWORD nSubAuthority2, DWORD nSubAuthority3,
128 DWORD nSubAuthority4, DWORD nSubAuthority5,
129 DWORD nSubAuthority6, DWORD nSubAuthority7,
130 PSID *pSid )
132 SID *tmp_sid;
134 TRACE("(%p, 0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p)\n",
135 pIdentifierAuthority,nSubAuthorityCount,
136 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
137 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
139 if (nSubAuthorityCount > 8) return STATUS_INVALID_SID;
141 if (!(tmp_sid= RtlAllocateHeap( GetProcessHeap(), 0,
142 RtlLengthRequiredSid(nSubAuthorityCount))))
143 return STATUS_NO_MEMORY;
145 tmp_sid->Revision = SID_REVISION;
147 if (pIdentifierAuthority)
148 memcpy(&tmp_sid->IdentifierAuthority, pIdentifierAuthority, sizeof(SID_IDENTIFIER_AUTHORITY));
149 tmp_sid->SubAuthorityCount = nSubAuthorityCount;
151 switch( nSubAuthorityCount )
153 case 8: tmp_sid->SubAuthority[7]= nSubAuthority7;
154 case 7: tmp_sid->SubAuthority[6]= nSubAuthority6;
155 case 6: tmp_sid->SubAuthority[5]= nSubAuthority5;
156 case 5: tmp_sid->SubAuthority[4]= nSubAuthority4;
157 case 4: tmp_sid->SubAuthority[3]= nSubAuthority3;
158 case 3: tmp_sid->SubAuthority[2]= nSubAuthority2;
159 case 2: tmp_sid->SubAuthority[1]= nSubAuthority1;
160 case 1: tmp_sid->SubAuthority[0]= nSubAuthority0;
161 break;
163 *pSid = tmp_sid;
164 return STATUS_SUCCESS;
167 /******************************************************************************
168 * RtlEqualSid [NTDLL.@]
170 * Determine if two SIDs are equal.
172 * PARAMS
173 * pSid1 [I] Source SID
174 * pSid2 [I] SID to compare with
176 * RETURNS
177 * TRUE, if pSid1 is equal to pSid2,
178 * FALSE otherwise.
180 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
182 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
183 return FALSE;
185 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
186 return FALSE;
188 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
189 return FALSE;
191 return TRUE;
194 /******************************************************************************
195 * RtlEqualPrefixSid [NTDLL.@]
197 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
199 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
200 return FALSE;
202 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
203 return FALSE;
205 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
206 return FALSE;
208 return TRUE;
212 /******************************************************************************
213 * RtlFreeSid [NTDLL.@]
215 * Free the resources used by a SID.
217 * PARAMS
218 * pSid [I] SID to Free.
220 * RETURNS
221 * STATUS_SUCCESS.
223 DWORD WINAPI RtlFreeSid(PSID pSid)
225 TRACE("(%p)\n", pSid);
226 RtlFreeHeap( GetProcessHeap(), 0, pSid );
227 return STATUS_SUCCESS;
230 /**************************************************************************
231 * RtlLengthRequiredSid [NTDLL.@]
233 * Determine the amount of memory a SID will use
235 * PARAMS
236 * nrofsubauths [I] Number of Sub Authorities in the SID.
238 * RETURNS
239 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
241 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
243 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
246 /**************************************************************************
247 * RtlLengthSid [NTDLL.@]
249 * Determine the amount of memory a SID is using
251 * PARAMS
252 * pSid [I] SID to get the size of.
254 * RETURNS
255 * The size, in bytes, of pSid.
257 DWORD WINAPI RtlLengthSid(PSID pSid)
259 TRACE("sid=%p\n",pSid);
260 if (!pSid) return 0;
261 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
264 /**************************************************************************
265 * RtlInitializeSid [NTDLL.@]
267 * Initialise a SID.
269 * PARAMS
270 * pSid [I] SID to initialise
271 * pIdentifierAuthority [I] Identifier Authority
272 * nSubAuthorityCount [I] Number of Sub Authorities
274 * RETURNS
275 * Success: TRUE. pSid is initialised with the details given.
276 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
278 BOOL WINAPI RtlInitializeSid(
279 PSID pSid,
280 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
281 BYTE nSubAuthorityCount)
283 int i;
284 SID* pisid=pSid;
286 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
287 return FALSE;
289 pisid->Revision = SID_REVISION;
290 pisid->SubAuthorityCount = nSubAuthorityCount;
291 if (pIdentifierAuthority)
292 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
294 for (i = 0; i < nSubAuthorityCount; i++)
295 *RtlSubAuthoritySid(pSid, i) = 0;
297 return TRUE;
300 /**************************************************************************
301 * RtlSubAuthoritySid [NTDLL.@]
303 * Return the Sub Authority of a SID
305 * PARAMS
306 * pSid [I] SID to get the Sub Authority from.
307 * nSubAuthority [I] Sub Authority number.
309 * RETURNS
310 * A pointer to The Sub Authority value of pSid.
312 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
314 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
317 /**************************************************************************
318 * RtlIdentifierAuthoritySid [NTDLL.@]
320 * Return the Identifier Authority of a SID.
322 * PARAMS
323 * pSid [I] SID to get the Identifier Authority from.
325 * RETURNS
326 * A pointer to the Identifier Authority value of pSid.
328 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
330 return &(((SID*)pSid)->IdentifierAuthority);
333 /**************************************************************************
334 * RtlSubAuthorityCountSid [NTDLL.@]
336 * Get the number of Sub Authorities in a SID.
338 * PARAMS
339 * pSid [I] SID to get the count from.
341 * RETURNS
342 * A pointer to the Sub Authority count of pSid.
344 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
346 return &(((SID*)pSid)->SubAuthorityCount);
349 /**************************************************************************
350 * RtlCopySid [NTDLL.@]
352 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
354 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
355 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
356 return FALSE;
358 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
359 return FALSE;
361 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
362 return TRUE;
364 /******************************************************************************
365 * RtlValidSid [NTDLL.@]
367 * Determine if a SID is valid.
369 * PARAMS
370 * pSid [I] SID to check
372 * RETURNS
373 * TRUE if pSid is valid,
374 * FALSE otherwise.
376 BOOLEAN WINAPI RtlValidSid( PSID pSid )
378 BOOL ret;
379 __TRY
381 ret = TRUE;
382 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
383 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
385 ret = FALSE;
388 __EXCEPT_PAGE_FAULT
390 WARN("(%p): invalid pointer!\n", pSid);
391 return FALSE;
393 __ENDTRY
394 return ret;
399 * security descriptor functions
402 /**************************************************************************
403 * RtlCreateSecurityDescriptor [NTDLL.@]
405 * Initialise a SECURITY_DESCRIPTOR.
407 * PARAMS
408 * lpsd [O] Descriptor to initialise.
409 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
411 * RETURNS
412 * Success: STATUS_SUCCESS.
413 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
415 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
416 PSECURITY_DESCRIPTOR lpsd,
417 DWORD rev)
419 if (rev!=SECURITY_DESCRIPTOR_REVISION)
420 return STATUS_UNKNOWN_REVISION;
421 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
422 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
423 return STATUS_SUCCESS;
426 /**************************************************************************
427 * RtlCopySecurityDescriptor [NTDLL.@]
429 * Copies an absolute or sefl-relative SECURITY_DESCRIPTOR.
431 * PARAMS
432 * pSourceSD [O] SD to copy from.
433 * pDestinationSD [I] Destination SD.
435 * RETURNS
436 * Success: STATUS_SUCCESS.
437 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
439 NTSTATUS WINAPI RtlCopySecurityDescriptor(PSECURITY_DESCRIPTOR pSourceSD, PSECURITY_DESCRIPTOR pDestinationSD)
441 SECURITY_DESCRIPTOR *srcSD = (SECURITY_DESCRIPTOR *)pSourceSD;
442 SECURITY_DESCRIPTOR *destSD = (SECURITY_DESCRIPTOR *)pDestinationSD;
443 PSID Owner, Group;
444 PACL Dacl, Sacl;
445 BOOLEAN defaulted, present;
446 DWORD length;
447 BOOL isSelfRelative = srcSD->Control & SE_SELF_RELATIVE;
449 if (srcSD->Revision != SECURITY_DESCRIPTOR_REVISION)
450 return STATUS_UNKNOWN_REVISION;
452 /* copy initial data */
453 destSD->Revision = srcSD->Revision;
454 destSD->Sbz1 = srcSD->Sbz1;
455 destSD->Control = srcSD->Control;
457 /* copy Owner */
458 RtlGetOwnerSecurityDescriptor(pSourceSD, &Owner, &defaulted);
459 length = RtlLengthSid(Owner);
461 if (isSelfRelative)
463 destSD->Owner = srcSD->Owner;
464 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Owner, Owner);
466 else
468 destSD->Owner = RtlAllocateHeap(GetProcessHeap(), 0, length);
469 RtlCopySid(length, destSD->Owner, Owner);
472 /* copy Group */
473 RtlGetGroupSecurityDescriptor(pSourceSD, &Group, &defaulted);
474 length = RtlLengthSid(Group);
476 if (isSelfRelative)
478 destSD->Group = srcSD->Group;
479 RtlCopySid(length, (LPBYTE)destSD + (DWORD)destSD->Group, Group);
481 else
483 destSD->Group = RtlAllocateHeap(GetProcessHeap(), 0, length);
484 RtlCopySid(length, destSD->Group, Group);
487 /* copy Dacl */
488 if (srcSD->Control & SE_DACL_PRESENT)
490 RtlGetDaclSecurityDescriptor(pSourceSD, &present, &Dacl, &defaulted);
491 length = Dacl->AclSize;
493 if (isSelfRelative)
495 destSD->Dacl = srcSD->Dacl;
496 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Dacl), Dacl);
498 else
500 destSD->Dacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
501 copy_acl(length, destSD->Dacl, Dacl);
505 /* copy Sacl */
506 if (srcSD->Control & SE_SACL_PRESENT)
508 RtlGetSaclSecurityDescriptor(pSourceSD, &present, &Sacl, &defaulted);
509 length = Sacl->AclSize;
511 if (isSelfRelative)
513 destSD->Sacl = srcSD->Sacl;
514 copy_acl(length, (PACL)((LPBYTE)destSD + (DWORD)destSD->Sacl), Sacl);
516 else
518 destSD->Sacl = RtlAllocateHeap(GetProcessHeap(), 0, length);
519 copy_acl(length, destSD->Sacl, Sacl);
523 return STATUS_SUCCESS;
526 /**************************************************************************
527 * RtlValidSecurityDescriptor [NTDLL.@]
529 * Determine if a SECURITY_DESCRIPTOR is valid.
531 * PARAMS
532 * SecurityDescriptor [I] Descriptor to check.
534 * RETURNS
535 * Success: STATUS_SUCCESS.
536 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
538 NTSTATUS WINAPI RtlValidSecurityDescriptor(
539 PSECURITY_DESCRIPTOR SecurityDescriptor)
541 if ( ! SecurityDescriptor )
542 return STATUS_INVALID_SECURITY_DESCR;
543 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
544 return STATUS_UNKNOWN_REVISION;
546 return STATUS_SUCCESS;
549 /**************************************************************************
550 * RtlLengthSecurityDescriptor [NTDLL.@]
552 ULONG WINAPI RtlLengthSecurityDescriptor(
553 PSECURITY_DESCRIPTOR pSecurityDescriptor)
555 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
556 ULONG offset = 0;
557 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
559 if ( lpsd == NULL )
560 return 0;
562 if ( lpsd->Control & SE_SELF_RELATIVE)
563 offset = (ULONG) lpsd;
565 if ( lpsd->Owner != NULL )
566 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
568 if ( lpsd->Group != NULL )
569 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
571 if ( (lpsd->Control & SE_SACL_PRESENT) &&
572 lpsd->Sacl != NULL )
573 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
575 if ( (lpsd->Control & SE_DACL_PRESENT) &&
576 lpsd->Dacl != NULL )
577 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
579 return Size;
582 /******************************************************************************
583 * RtlGetDaclSecurityDescriptor [NTDLL.@]
586 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
587 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
588 OUT PBOOLEAN lpbDaclPresent,
589 OUT PACL *pDacl,
590 OUT PBOOLEAN lpbDaclDefaulted)
592 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
594 TRACE("(%p,%p,%p,%p)\n",
595 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
597 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
598 return STATUS_UNKNOWN_REVISION ;
600 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
602 if ( SE_SELF_RELATIVE & lpsd->Control)
603 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
604 else
605 *pDacl = lpsd->Dacl;
607 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
610 return STATUS_SUCCESS;
613 /**************************************************************************
614 * RtlSetDaclSecurityDescriptor [NTDLL.@]
616 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
617 PSECURITY_DESCRIPTOR pSecurityDescriptor,
618 BOOLEAN daclpresent,
619 PACL dacl,
620 BOOLEAN dacldefaulted )
622 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
624 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
625 return STATUS_UNKNOWN_REVISION;
626 if (lpsd->Control & SE_SELF_RELATIVE)
627 return STATUS_INVALID_SECURITY_DESCR;
629 if (!daclpresent)
630 { lpsd->Control &= ~SE_DACL_PRESENT;
631 return TRUE;
634 lpsd->Control |= SE_DACL_PRESENT;
635 lpsd->Dacl = dacl;
637 if (dacldefaulted)
638 lpsd->Control |= SE_DACL_DEFAULTED;
639 else
640 lpsd->Control &= ~SE_DACL_DEFAULTED;
642 return STATUS_SUCCESS;
645 /******************************************************************************
646 * RtlGetSaclSecurityDescriptor [NTDLL.@]
649 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
650 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
651 OUT PBOOLEAN lpbSaclPresent,
652 OUT PACL *pSacl,
653 OUT PBOOLEAN lpbSaclDefaulted)
655 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
657 TRACE("(%p,%p,%p,%p)\n",
658 pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
660 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
661 return STATUS_UNKNOWN_REVISION;
663 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
665 if (SE_SELF_RELATIVE & lpsd->Control)
666 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Sacl);
667 else
668 *pSacl = lpsd->Sacl;
670 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
673 return STATUS_SUCCESS;
676 /**************************************************************************
677 * RtlSetSaclSecurityDescriptor [NTDLL.@]
679 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
680 PSECURITY_DESCRIPTOR pSecurityDescriptor,
681 BOOLEAN saclpresent,
682 PACL sacl,
683 BOOLEAN sacldefaulted)
685 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
687 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
688 return STATUS_UNKNOWN_REVISION;
689 if (lpsd->Control & SE_SELF_RELATIVE)
690 return STATUS_INVALID_SECURITY_DESCR;
691 if (!saclpresent) {
692 lpsd->Control &= ~SE_SACL_PRESENT;
693 return 0;
695 lpsd->Control |= SE_SACL_PRESENT;
696 lpsd->Sacl = sacl;
697 if (sacldefaulted)
698 lpsd->Control |= SE_SACL_DEFAULTED;
699 else
700 lpsd->Control &= ~SE_SACL_DEFAULTED;
701 return STATUS_SUCCESS;
704 /**************************************************************************
705 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
707 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
708 PSECURITY_DESCRIPTOR pSecurityDescriptor,
709 PSID *Owner,
710 PBOOLEAN OwnerDefaulted)
712 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
714 if ( !lpsd || !Owner || !OwnerDefaulted )
715 return STATUS_INVALID_PARAMETER;
717 if (lpsd->Owner != NULL)
719 if (lpsd->Control & SE_SELF_RELATIVE)
720 *Owner = (PSID)((LPBYTE)lpsd +
721 (ULONG)lpsd->Owner);
722 else
723 *Owner = lpsd->Owner;
725 if ( lpsd->Control & SE_OWNER_DEFAULTED )
726 *OwnerDefaulted = TRUE;
727 else
728 *OwnerDefaulted = FALSE;
730 else
731 *Owner = NULL;
733 return STATUS_SUCCESS;
736 /**************************************************************************
737 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
739 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
740 PSECURITY_DESCRIPTOR pSecurityDescriptor,
741 PSID owner,
742 BOOLEAN ownerdefaulted)
744 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
746 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
747 return STATUS_UNKNOWN_REVISION;
748 if (lpsd->Control & SE_SELF_RELATIVE)
749 return STATUS_INVALID_SECURITY_DESCR;
751 lpsd->Owner = owner;
752 if (ownerdefaulted)
753 lpsd->Control |= SE_OWNER_DEFAULTED;
754 else
755 lpsd->Control &= ~SE_OWNER_DEFAULTED;
756 return STATUS_SUCCESS;
759 /**************************************************************************
760 * RtlSetGroupSecurityDescriptor [NTDLL.@]
762 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
763 PSECURITY_DESCRIPTOR pSecurityDescriptor,
764 PSID group,
765 BOOLEAN groupdefaulted)
767 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
769 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
770 return STATUS_UNKNOWN_REVISION;
771 if (lpsd->Control & SE_SELF_RELATIVE)
772 return STATUS_INVALID_SECURITY_DESCR;
774 lpsd->Group = group;
775 if (groupdefaulted)
776 lpsd->Control |= SE_GROUP_DEFAULTED;
777 else
778 lpsd->Control &= ~SE_GROUP_DEFAULTED;
779 return STATUS_SUCCESS;
782 /**************************************************************************
783 * RtlGetGroupSecurityDescriptor [NTDLL.@]
785 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
786 PSECURITY_DESCRIPTOR pSecurityDescriptor,
787 PSID *Group,
788 PBOOLEAN GroupDefaulted)
790 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
792 if ( !lpsd || !Group || !GroupDefaulted )
793 return STATUS_INVALID_PARAMETER;
795 if (lpsd->Group != NULL)
797 if (lpsd->Control & SE_SELF_RELATIVE)
798 *Group = (PSID)((LPBYTE)lpsd +
799 (ULONG)lpsd->Group);
800 else
801 *Group = lpsd->Group;
803 if ( lpsd->Control & SE_GROUP_DEFAULTED )
804 *GroupDefaulted = TRUE;
805 else
806 *GroupDefaulted = FALSE;
808 else
809 *Group = NULL;
811 return STATUS_SUCCESS;
814 /**************************************************************************
815 * RtlMakeSelfRelativeSD [NTDLL.@]
817 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
818 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
819 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
820 IN OUT LPDWORD lpdwBufferLength)
822 ULONG offsetRel;
823 ULONG length;
824 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
825 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
827 TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
828 lpdwBufferLength ? *lpdwBufferLength: -1);
830 if (!lpdwBufferLength || !pAbs)
831 return STATUS_INVALID_PARAMETER;
833 length = RtlLengthSecurityDescriptor(pAbs);
834 if (*lpdwBufferLength < length)
836 *lpdwBufferLength = length;
837 return STATUS_BUFFER_TOO_SMALL;
840 if (!pRel)
841 return STATUS_INVALID_PARAMETER;
843 if (pAbs->Control & SE_SELF_RELATIVE)
845 memcpy(pRel, pAbs, length);
846 return STATUS_SUCCESS;
849 pRel->Revision = pAbs->Revision;
850 pRel->Sbz1 = pAbs->Sbz1;
851 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
853 offsetRel = sizeof(SECURITY_DESCRIPTOR);
854 pRel->Owner = (PSID) offsetRel;
855 length = RtlLengthSid(pAbs->Owner);
856 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
858 offsetRel += length;
859 pRel->Group = (PSID) offsetRel;
860 length = RtlLengthSid(pAbs->Group);
861 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
863 if (pRel->Control & SE_SACL_PRESENT)
865 offsetRel += length;
866 pRel->Sacl = (PACL) offsetRel;
867 length = pAbs->Sacl->AclSize;
868 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
870 else
872 pRel->Sacl = NULL;
875 if (pRel->Control & SE_DACL_PRESENT)
877 offsetRel += length;
878 pRel->Dacl = (PACL) offsetRel;
879 length = pAbs->Dacl->AclSize;
880 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
882 else
884 pRel->Dacl = NULL;
887 return STATUS_SUCCESS;
891 /**************************************************************************
892 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
894 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
895 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
896 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
897 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
898 OUT PACL pDacl,
899 OUT LPDWORD lpdwDaclSize,
900 OUT PACL pSacl,
901 OUT LPDWORD lpdwSaclSize,
902 OUT PSID pOwner,
903 OUT LPDWORD lpdwOwnerSize,
904 OUT PSID pPrimaryGroup,
905 OUT LPDWORD lpdwPrimaryGroupSize)
907 NTSTATUS status = STATUS_SUCCESS;
908 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
909 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
911 if (!pRel ||
912 !lpdwAbsoluteSecurityDescriptorSize ||
913 !lpdwDaclSize ||
914 !lpdwSaclSize ||
915 !lpdwOwnerSize ||
916 !lpdwPrimaryGroupSize ||
917 ~pRel->Control & SE_SELF_RELATIVE)
918 return STATUS_INVALID_PARAMETER;
920 /* Confirm buffers are sufficiently large */
921 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
923 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
924 status = STATUS_BUFFER_TOO_SMALL;
927 if (pRel->Control & SE_DACL_PRESENT &&
928 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
930 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
931 status = STATUS_BUFFER_TOO_SMALL;
934 if (pRel->Control & SE_SACL_PRESENT &&
935 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
937 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
938 status = STATUS_BUFFER_TOO_SMALL;
941 if (pRel->Owner &&
942 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
944 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
945 status = STATUS_BUFFER_TOO_SMALL;
948 if (pRel->Group &&
949 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
951 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
952 status = STATUS_BUFFER_TOO_SMALL;
955 if (status != STATUS_SUCCESS)
956 return status;
958 /* Copy structures */
959 pAbs->Revision = pRel->Revision;
960 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
962 if (pRel->Control & SE_SACL_PRESENT)
964 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
966 memcpy(pSacl, pAcl, pAcl->AclSize);
967 pAbs->Sacl = pSacl;
970 if (pRel->Control & SE_DACL_PRESENT)
972 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
973 memcpy(pDacl, pAcl, pAcl->AclSize);
974 pAbs->Dacl = pDacl;
977 if (pRel->Owner)
979 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
980 memcpy(pOwner, psid, RtlLengthSid(psid));
981 pAbs->Owner = pOwner;
984 if (pRel->Group)
986 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
987 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
988 pAbs->Group = pPrimaryGroup;
991 return status;
994 /******************************************************************************
995 * RtlGetControlSecurityDescriptor (NTDLL.@)
997 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
998 PSECURITY_DESCRIPTOR pSecurityDescriptor,
999 PSECURITY_DESCRIPTOR_CONTROL pControl,
1000 LPDWORD lpdwRevision)
1002 SECURITY_DESCRIPTOR *lpsd = pSecurityDescriptor;
1004 TRACE("(%p,%p,%p)\n",pSecurityDescriptor,pControl,lpdwRevision);
1006 *lpdwRevision = lpsd->Revision;
1008 if (*lpdwRevision != SECURITY_DESCRIPTOR_REVISION)
1009 return STATUS_UNKNOWN_REVISION;
1011 *pControl = lpsd->Control;
1013 return STATUS_SUCCESS;
1017 /**************************************************************************
1018 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
1020 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
1021 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
1022 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
1023 PULONG BufferLength)
1025 SECURITY_DESCRIPTOR *abs = AbsoluteSecurityDescriptor;
1027 TRACE("%p %p %p\n", AbsoluteSecurityDescriptor,
1028 SelfRelativeSecurityDescriptor, BufferLength);
1030 if (abs->Control & SE_SELF_RELATIVE)
1031 return STATUS_BAD_DESCRIPTOR_FORMAT;
1033 return RtlMakeSelfRelativeSD(AbsoluteSecurityDescriptor,
1034 SelfRelativeSecurityDescriptor, BufferLength);
1039 * access control list's
1042 /**************************************************************************
1043 * RtlCreateAcl [NTDLL.@]
1045 * NOTES
1046 * This should return NTSTATUS
1048 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
1050 TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
1052 if (rev!=ACL_REVISION)
1053 return STATUS_INVALID_PARAMETER;
1054 if (size<sizeof(ACL))
1055 return STATUS_BUFFER_TOO_SMALL;
1056 if (size>0xFFFF)
1057 return STATUS_INVALID_PARAMETER;
1059 memset(acl,'\0',sizeof(ACL));
1060 acl->AclRevision = rev;
1061 acl->AclSize = size;
1062 acl->AceCount = 0;
1063 return STATUS_SUCCESS;
1066 /**************************************************************************
1067 * RtlFirstFreeAce [NTDLL.@]
1068 * looks for the AceCount+1 ACE, and if it is still within the alloced
1069 * ACL, return a pointer to it
1071 BOOLEAN WINAPI RtlFirstFreeAce(
1072 PACL acl,
1073 PACE_HEADER *x)
1075 PACE_HEADER ace;
1076 int i;
1078 *x = 0;
1079 ace = (PACE_HEADER)(acl+1);
1080 for (i=0;i<acl->AceCount;i++) {
1081 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1082 return 0;
1083 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1085 if ((BYTE *)ace >= (BYTE *)acl + acl->AclSize)
1086 return 0;
1087 *x = ace;
1088 return 1;
1091 /**************************************************************************
1092 * RtlAddAce [NTDLL.@]
1094 NTSTATUS WINAPI RtlAddAce(
1095 PACL acl,
1096 DWORD rev,
1097 DWORD xnrofaces,
1098 PACE_HEADER acestart,
1099 DWORD acelen)
1101 PACE_HEADER ace,targetace;
1102 int nrofaces;
1104 if (acl->AclRevision != ACL_REVISION)
1105 return STATUS_INVALID_PARAMETER;
1106 if (!RtlFirstFreeAce(acl,&targetace))
1107 return STATUS_INVALID_PARAMETER;
1108 nrofaces=0;ace=acestart;
1109 while (((BYTE *)ace - (BYTE *)acestart) < acelen) {
1110 nrofaces++;
1111 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1113 if ((BYTE *)targetace + acelen > (BYTE *)acl + acl->AclSize) /* too much aces */
1114 return STATUS_INVALID_PARAMETER;
1115 memcpy((LPBYTE)targetace,acestart,acelen);
1116 acl->AceCount+=nrofaces;
1117 return STATUS_SUCCESS;
1120 /**************************************************************************
1121 * RtlDeleteAce [NTDLL.@]
1123 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
1125 NTSTATUS status;
1126 PACE_HEADER pAce;
1128 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
1130 if (STATUS_SUCCESS == status)
1132 PACE_HEADER pcAce;
1133 DWORD len = 0;
1135 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
1136 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
1138 len += pcAce->AceSize;
1139 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
1142 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
1143 pAcl->AceCount--;
1146 TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\n", pAcl, dwAceIndex, status);
1148 return status;
1151 /******************************************************************************
1152 * RtlAddAccessAllowedAce [NTDLL.@]
1154 NTSTATUS WINAPI RtlAddAccessAllowedAce(
1155 IN OUT PACL pAcl,
1156 IN DWORD dwAceRevision,
1157 IN DWORD AccessMask,
1158 IN PSID pSid)
1160 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1163 /******************************************************************************
1164 * RtlAddAccessAllowedAceEx [NTDLL.@]
1166 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1167 IN OUT PACL pAcl,
1168 IN DWORD dwAceRevision,
1169 IN DWORD AceFlags,
1170 IN DWORD AccessMask,
1171 IN PSID pSid)
1173 TRACE("(%p,0x%08lx,0x%08lx,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1175 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1176 AccessMask, pSid, ACCESS_ALLOWED_ACE_TYPE);
1179 /******************************************************************************
1180 * RtlAddAccessDeniedAce [NTDLL.@]
1182 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1183 IN OUT PACL pAcl,
1184 IN DWORD dwAceRevision,
1185 IN DWORD AccessMask,
1186 IN PSID pSid)
1188 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1191 /******************************************************************************
1192 * RtlAddAccessDeniedAceEx [NTDLL.@]
1194 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1195 IN OUT PACL pAcl,
1196 IN DWORD dwAceRevision,
1197 IN DWORD AceFlags,
1198 IN DWORD AccessMask,
1199 IN PSID pSid)
1201 TRACE("(%p,0x%08lx,0x%08lx,%p)\n", pAcl, dwAceRevision, AccessMask, pSid);
1203 return add_access_ace(pAcl, dwAceRevision, AceFlags,
1204 AccessMask, pSid, ACCESS_DENIED_ACE_TYPE);
1207 /**************************************************************************
1208 * RtlAddAuditAccessAce [NTDLL.@]
1210 NTSTATUS WINAPI RtlAddAuditAccessAce(
1211 IN OUT PACL pAcl,
1212 IN DWORD dwAceRevision,
1213 IN DWORD dwAccessMask,
1214 IN PSID pSid,
1215 IN BOOL bAuditSuccess,
1216 IN BOOL bAuditFailure)
1218 DWORD dwAceFlags = 0;
1220 TRACE("(%p,%ld,%ld,%p,%u,%u)\n",pAcl,dwAceRevision,dwAccessMask,
1221 pSid,bAuditSuccess,bAuditFailure);
1223 if (bAuditSuccess)
1224 dwAceFlags |= SUCCESSFUL_ACCESS_ACE_FLAG;
1226 if (bAuditFailure)
1227 dwAceFlags |= FAILED_ACCESS_ACE_FLAG;
1229 return add_access_ace(pAcl, dwAceRevision, dwAceFlags,
1230 dwAccessMask, pSid, SYSTEM_AUDIT_ACE_TYPE);
1233 /******************************************************************************
1234 * RtlValidAcl [NTDLL.@]
1236 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1238 BOOLEAN ret;
1239 TRACE("(%p)\n", pAcl);
1241 __TRY
1243 PACE_HEADER ace;
1244 int i;
1246 if (pAcl->AclRevision != ACL_REVISION)
1247 ret = FALSE;
1248 else
1250 ace = (PACE_HEADER)(pAcl+1);
1251 ret = TRUE;
1252 for (i=0;i<=pAcl->AceCount;i++)
1254 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1256 ret = FALSE;
1257 break;
1259 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1263 __EXCEPT_PAGE_FAULT
1265 WARN("(%p): invalid pointer!\n", pAcl);
1266 return 0;
1268 __ENDTRY
1269 return ret;
1272 /******************************************************************************
1273 * RtlGetAce [NTDLL.@]
1275 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1277 PACE_HEADER ace;
1279 TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1281 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1282 return STATUS_INVALID_PARAMETER;
1284 ace = (PACE_HEADER)(pAcl + 1);
1285 for (;dwAceIndex;dwAceIndex--)
1286 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1288 *pAce = (LPVOID) ace;
1290 return STATUS_SUCCESS;
1294 * misc
1297 /******************************************************************************
1298 * RtlAdjustPrivilege [NTDLL.@]
1300 * Enables or disables a privilege from the calling thread or process.
1302 * PARAMS
1303 * Privilege [I] Privilege index to change.
1304 * Enable [I] If TRUE, then enable the privilege otherwise disable.
1305 * CurrentThread [I] If TRUE, then enable in calling thread, otherwise process.
1306 * Enabled [O] Whether privilege was previously enabled or disabled.
1308 * RETURNS
1309 * Success: STATUS_SUCCESS.
1310 * Failure: NTSTATUS code.
1312 * SEE ALSO
1313 * NtAdjustPrivilegesToken, NtOpenThreadToken, NtOpenProcessToken.
1316 NTSTATUS WINAPI
1317 RtlAdjustPrivilege(ULONG Privilege,
1318 BOOLEAN Enable,
1319 BOOLEAN CurrentThread,
1320 PBOOLEAN Enabled)
1322 TOKEN_PRIVILEGES NewState;
1323 TOKEN_PRIVILEGES OldState;
1324 ULONG ReturnLength;
1325 HANDLE TokenHandle;
1326 NTSTATUS Status;
1328 TRACE("(%ld, %s, %s, %p)\n", Privilege, Enable ? "TRUE" : "FALSE",
1329 CurrentThread ? "TRUE" : "FALSE", Enabled);
1331 if (CurrentThread)
1333 Status = NtOpenThreadToken(GetCurrentThread(),
1334 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1335 FALSE,
1336 &TokenHandle);
1338 else
1340 Status = NtOpenProcessToken(GetCurrentProcess(),
1341 TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
1342 &TokenHandle);
1345 if (!NT_SUCCESS(Status))
1347 WARN("Retrieving token handle failed (Status %lx)\n", Status);
1348 return Status;
1351 OldState.PrivilegeCount = 1;
1353 NewState.PrivilegeCount = 1;
1354 NewState.Privileges[0].Luid.LowPart = Privilege;
1355 NewState.Privileges[0].Luid.HighPart = 0;
1356 NewState.Privileges[0].Attributes = (Enable) ? SE_PRIVILEGE_ENABLED : 0;
1358 Status = NtAdjustPrivilegesToken(TokenHandle,
1359 FALSE,
1360 &NewState,
1361 sizeof(TOKEN_PRIVILEGES),
1362 &OldState,
1363 &ReturnLength);
1364 NtClose (TokenHandle);
1365 if (Status == STATUS_NOT_ALL_ASSIGNED)
1367 TRACE("Failed to assign all privileges\n");
1368 return STATUS_PRIVILEGE_NOT_HELD;
1370 if (!NT_SUCCESS(Status))
1372 WARN("NtAdjustPrivilegesToken() failed (Status %lx)\n", Status);
1373 return Status;
1376 if (OldState.PrivilegeCount == 0)
1377 *Enabled = Enable;
1378 else
1379 *Enabled = (OldState.Privileges[0].Attributes & SE_PRIVILEGE_ENABLED);
1381 return STATUS_SUCCESS;
1384 /******************************************************************************
1385 * RtlImpersonateSelf [NTDLL.@]
1387 * Makes an impersonation token that represents the process user and assigns
1388 * to the current thread.
1390 * PARAMS
1391 * ImpersonationLevel [I] Level at which to impersonate.
1393 * RETURNS
1394 * Success: STATUS_SUCCESS.
1395 * Failure: NTSTATUS code.
1397 NTSTATUS WINAPI
1398 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1400 NTSTATUS Status;
1401 OBJECT_ATTRIBUTES ObjectAttributes;
1402 HANDLE ProcessToken;
1403 HANDLE ImpersonationToken;
1405 TRACE("(%08x)\n", ImpersonationLevel);
1407 Status = NtOpenProcessToken( NtCurrentProcess(), TOKEN_DUPLICATE,
1408 &ProcessToken);
1409 if (Status != STATUS_SUCCESS)
1410 return Status;
1412 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL );
1414 Status = NtDuplicateToken( ProcessToken,
1415 TOKEN_IMPERSONATE,
1416 &ObjectAttributes,
1417 ImpersonationLevel,
1418 TokenImpersonation,
1419 &ImpersonationToken );
1420 if (Status != STATUS_SUCCESS)
1422 NtClose( ProcessToken );
1423 return Status;
1426 Status = NtSetInformationThread( GetCurrentThread(),
1427 ThreadImpersonationToken,
1428 &ImpersonationToken,
1429 sizeof(ImpersonationToken) );
1431 NtClose( ImpersonationToken );
1432 NtClose( ProcessToken );
1434 return Status;
1437 /******************************************************************************
1438 * NtAccessCheck [NTDLL.@]
1439 * ZwAccessCheck [NTDLL.@]
1441 * Checks that a user represented by a token is allowed to access an object
1442 * represented by a security descriptor.
1444 * PARAMS
1445 * SecurityDescriptor [I] The security descriptor of the object to check.
1446 * ClientToken [I] Token of the user accessing the object.
1447 * DesiredAccess [I] The desired access to the object.
1448 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1449 * PrivilegeSet [I/O] Privileges used during the access check.
1450 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1451 * GrantedAccess [O] The actual access rights granted.
1452 * AccessStatus [O] The status of the access check.
1454 * RETURNS
1455 * NTSTATUS code.
1457 * NOTES
1458 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1459 * the maximum access rights allowed by the SD and returns them in
1460 * GrantedAccess.
1461 * The SecurityDescriptor must have a valid owner and groups present,
1462 * otherwise the function will fail.
1464 NTSTATUS WINAPI
1465 NtAccessCheck(
1466 PSECURITY_DESCRIPTOR SecurityDescriptor,
1467 HANDLE ClientToken,
1468 ACCESS_MASK DesiredAccess,
1469 PGENERIC_MAPPING GenericMapping,
1470 PPRIVILEGE_SET PrivilegeSet,
1471 PULONG ReturnLength,
1472 PULONG GrantedAccess,
1473 NTSTATUS *AccessStatus)
1475 NTSTATUS status;
1477 TRACE("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1478 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1479 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1481 SERVER_START_REQ( access_check )
1483 struct security_descriptor sd;
1484 PSID owner;
1485 PSID group;
1486 PACL sacl;
1487 PACL dacl;
1488 BOOLEAN defaulted, present;
1489 DWORD revision;
1490 SECURITY_DESCRIPTOR_CONTROL control;
1492 req->handle = ClientToken;
1493 req->desired_access = DesiredAccess;
1494 req->mapping_read = GenericMapping->GenericRead;
1495 req->mapping_write = GenericMapping->GenericWrite;
1496 req->mapping_execute = GenericMapping->GenericExecute;
1497 req->mapping_all = GenericMapping->GenericAll;
1499 /* marshal security descriptor */
1500 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1501 sd.control = control & ~SE_SELF_RELATIVE;
1502 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1503 sd.owner_len = RtlLengthSid( owner );
1504 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1505 sd.group_len = RtlLengthSid( group );
1506 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1507 sd.sacl_len = (present ? sacl->AclSize : 0);
1508 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1509 sd.dacl_len = (present ? dacl->AclSize : 0);
1511 wine_server_add_data( req, &sd, sizeof(sd) );
1512 wine_server_add_data( req, owner, sd.owner_len );
1513 wine_server_add_data( req, group, sd.group_len );
1514 wine_server_add_data( req, sacl, sd.sacl_len );
1515 wine_server_add_data( req, dacl, sd.dacl_len );
1517 wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1519 status = wine_server_call( req );
1521 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1522 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1524 if (status == STATUS_SUCCESS)
1525 *AccessStatus = reply->access_status;
1526 *GrantedAccess = reply->access_granted;
1528 SERVER_END_REQ;
1530 return status;
1533 /******************************************************************************
1534 * NtSetSecurityObject [NTDLL.@]
1536 NTSTATUS WINAPI
1537 NtSetSecurityObject(
1538 IN HANDLE Handle,
1539 IN SECURITY_INFORMATION SecurityInformation,
1540 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1542 FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1543 return STATUS_SUCCESS;
1546 /******************************************************************************
1547 * RtlConvertSidToUnicodeString (NTDLL.@)
1549 * The returned SID is used to access the USER registry hive usually
1551 * the native function returns something like
1552 * "S-1-5-21-0000000000-000000000-0000000000-500";
1554 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1555 PUNICODE_STRING String,
1556 PSID pSid,
1557 BOOLEAN AllocateString)
1559 static const WCHAR formatW[] = {'-','%','u',0};
1560 WCHAR buffer[2 + 10 + 10 + 10 * SID_MAX_SUB_AUTHORITIES];
1561 WCHAR *p = buffer;
1562 const SID *sid = (const SID *)pSid;
1563 DWORD i, len;
1565 *p++ = 'S';
1566 p += sprintfW( p, formatW, sid->Revision );
1567 p += sprintfW( p, formatW, MAKELONG( MAKEWORD( sid->IdentifierAuthority.Value[5],
1568 sid->IdentifierAuthority.Value[4] ),
1569 MAKEWORD( sid->IdentifierAuthority.Value[3],
1570 sid->IdentifierAuthority.Value[2] )));
1571 for (i = 0; i < sid->SubAuthorityCount; i++)
1572 p += sprintfW( p, formatW, sid->SubAuthority[i] );
1574 len = (p + 1 - buffer) * sizeof(WCHAR);
1576 String->Length = len - sizeof(WCHAR);
1577 if (AllocateString)
1579 String->MaximumLength = len;
1580 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1581 return STATUS_NO_MEMORY;
1583 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1585 memcpy( String->Buffer, buffer, len );
1586 return STATUS_SUCCESS;
1589 /******************************************************************************
1590 * RtlQueryInformationAcl (NTDLL.@)
1592 NTSTATUS WINAPI RtlQueryInformationAcl(
1593 PACL pAcl,
1594 LPVOID pAclInformation,
1595 DWORD nAclInformationLength,
1596 ACL_INFORMATION_CLASS dwAclInformationClass)
1598 NTSTATUS status = STATUS_SUCCESS;
1600 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1601 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1603 switch (dwAclInformationClass)
1605 case AclRevisionInformation:
1607 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1609 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1610 status = STATUS_INVALID_PARAMETER;
1611 else
1612 paclrev->AclRevision = pAcl->AclRevision;
1614 break;
1617 case AclSizeInformation:
1619 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1621 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1622 status = STATUS_INVALID_PARAMETER;
1623 else
1625 INT i;
1626 PACE_HEADER ace;
1628 paclsize->AceCount = pAcl->AceCount;
1630 paclsize->AclBytesInUse = 0;
1631 ace = (PACE_HEADER) (pAcl + 1);
1633 for (i = 0; i < pAcl->AceCount; i++)
1635 paclsize->AclBytesInUse += ace->AceSize;
1636 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1639 if (pAcl->AclSize < paclsize->AclBytesInUse)
1641 WARN("Acl has %ld bytes free\n", paclsize->AclBytesFree);
1642 paclsize->AclBytesFree = 0;
1643 paclsize->AclBytesInUse = pAcl->AclSize;
1645 else
1646 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1649 break;
1652 default:
1653 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1654 status = STATUS_INVALID_PARAMETER;
1657 return status;