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
23 #include "wine/port.h"
37 #include "wine/exception.h"
39 #include "ntdll_misc.h"
41 #include "wine/library.h"
42 #include "wine/debug.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
46 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
48 /* filter for page-fault exceptions */
49 static WINE_EXCEPTION_FILTER(page_fault)
51 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
52 return EXCEPTION_EXECUTE_HANDLER;
53 return EXCEPTION_CONTINUE_SEARCH;
60 /******************************************************************************
61 * RtlAllocateAndInitializeSid [NTDLL.@]
64 NTSTATUS WINAPI RtlAllocateAndInitializeSid (
65 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
66 BYTE nSubAuthorityCount,
67 DWORD nSubAuthority0, DWORD nSubAuthority1,
68 DWORD nSubAuthority2, DWORD nSubAuthority3,
69 DWORD nSubAuthority4, DWORD nSubAuthority5,
70 DWORD nSubAuthority6, DWORD nSubAuthority7,
74 TRACE("(%p, 0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p)\n",
75 pIdentifierAuthority,nSubAuthorityCount,
76 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
77 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
79 if (!(*pSid = RtlAllocateHeap( GetProcessHeap(), 0,
80 RtlLengthRequiredSid(nSubAuthorityCount))))
81 return STATUS_NO_MEMORY;
83 ((SID*)*pSid)->Revision = SID_REVISION;
85 if (pIdentifierAuthority)
86 memcpy(&((SID*)*pSid)->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
87 *RtlSubAuthorityCountSid(*pSid) = nSubAuthorityCount;
89 if (nSubAuthorityCount > 0)
90 *RtlSubAuthoritySid(*pSid, 0) = nSubAuthority0;
91 if (nSubAuthorityCount > 1)
92 *RtlSubAuthoritySid(*pSid, 1) = nSubAuthority1;
93 if (nSubAuthorityCount > 2)
94 *RtlSubAuthoritySid(*pSid, 2) = nSubAuthority2;
95 if (nSubAuthorityCount > 3)
96 *RtlSubAuthoritySid(*pSid, 3) = nSubAuthority3;
97 if (nSubAuthorityCount > 4)
98 *RtlSubAuthoritySid(*pSid, 4) = nSubAuthority4;
99 if (nSubAuthorityCount > 5)
100 *RtlSubAuthoritySid(*pSid, 5) = nSubAuthority5;
101 if (nSubAuthorityCount > 6)
102 *RtlSubAuthoritySid(*pSid, 6) = nSubAuthority6;
103 if (nSubAuthorityCount > 7)
104 *RtlSubAuthoritySid(*pSid, 7) = nSubAuthority7;
106 return STATUS_SUCCESS;
108 /******************************************************************************
109 * RtlEqualSid [NTDLL.@]
111 * Determine if two SIDs are equal.
114 * pSid1 [I] Source SID
115 * pSid2 [I] SID to compare with
118 * TRUE, if pSid1 is equal to pSid2,
121 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
123 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
126 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
129 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
135 /******************************************************************************
136 * RtlEqualPrefixSid [NTDLL.@]
138 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
140 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
143 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
146 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
153 /******************************************************************************
154 * RtlFreeSid [NTDLL.@]
156 * Free the resources used by a SID.
159 * pSid [I] SID to Free.
164 DWORD WINAPI RtlFreeSid(PSID pSid)
166 TRACE("(%p)\n", pSid);
167 RtlFreeHeap( GetProcessHeap(), 0, pSid );
168 return STATUS_SUCCESS;
171 /**************************************************************************
172 * RtlLengthRequiredSid [NTDLL.@]
174 * Determine the amount of memory a SID will use
177 * nrofsubauths [I] Number of Sub Authorities in the SID.
180 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
182 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
184 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
187 /**************************************************************************
188 * RtlLengthSid [NTDLL.@]
190 * Determine the amount of memory a SID is using
193 * pSid [I] SID to get the size of.
196 * The size, in bytes, of pSid.
198 DWORD WINAPI RtlLengthSid(PSID pSid)
200 TRACE("sid=%p\n",pSid);
202 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
205 /**************************************************************************
206 * RtlInitializeSid [NTDLL.@]
211 * pSid [I] SID to initialise
212 * pIdentifierAuthority [I] Identifier Authority
213 * nSubAuthorityCount [I] Number of Sub Authorities
216 * Success: TRUE. pSid is initialised with the details given.
217 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
219 BOOL WINAPI RtlInitializeSid(
221 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
222 BYTE nSubAuthorityCount)
227 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
230 pisid->Revision = SID_REVISION;
231 pisid->SubAuthorityCount = nSubAuthorityCount;
232 if (pIdentifierAuthority)
233 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
235 for (i = 0; i < nSubAuthorityCount; i++)
236 *RtlSubAuthoritySid(pSid, i) = 0;
241 /**************************************************************************
242 * RtlSubAuthoritySid [NTDLL.@]
244 * Return the Sub Authority of a SID
247 * pSid [I] SID to get the Sub Authority from.
248 * nSubAuthority [I] Sub Authority number.
251 * A pointer to The Sub Authority value of pSid.
253 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
255 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
258 /**************************************************************************
259 * RtlIdentifierAuthoritySid [NTDLL.@]
261 * Return the Identifier Authority of a SID.
264 * pSid [I] SID to get the Identifier Authority from.
267 * A pointer to the Identifier Authority value of pSid.
269 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
271 return &(((SID*)pSid)->IdentifierAuthority);
274 /**************************************************************************
275 * RtlSubAuthorityCountSid [NTDLL.@]
277 * Get the number of Sub Authorities in a SID.
280 * pSid [I] SID to get the count from.
283 * A pointer to the Sub Authority count of pSid.
285 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
287 return &(((SID*)pSid)->SubAuthorityCount);
290 /**************************************************************************
291 * RtlCopySid [NTDLL.@]
293 BOOLEAN WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
295 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
296 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
299 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
302 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
305 /******************************************************************************
306 * RtlValidSid [NTDLL.@]
308 * Determine if a SID is valid.
311 * pSid [I] SID to check
314 * TRUE if pSid is valid,
317 BOOLEAN WINAPI RtlValidSid( PSID pSid )
323 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
324 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
331 WARN("(%p): invalid pointer!\n", pSid);
340 * security descriptor functions
343 /**************************************************************************
344 * RtlCreateSecurityDescriptor [NTDLL.@]
346 * Initialise a SECURITY_DESCRIPTOR.
349 * lpsd [O] Descriptor to initialise.
350 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
353 * Success: STATUS_SUCCESS.
354 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
356 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
357 PSECURITY_DESCRIPTOR lpsd,
360 if (rev!=SECURITY_DESCRIPTOR_REVISION)
361 return STATUS_UNKNOWN_REVISION;
362 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
363 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
364 return STATUS_SUCCESS;
366 /**************************************************************************
367 * RtlValidSecurityDescriptor [NTDLL.@]
369 * Determine if a SECURITY_DESCRIPTOR is valid.
372 * SecurityDescriptor [I] Descriptor to check.
375 * Success: STATUS_SUCCESS.
376 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
378 NTSTATUS WINAPI RtlValidSecurityDescriptor(
379 PSECURITY_DESCRIPTOR SecurityDescriptor)
381 if ( ! SecurityDescriptor )
382 return STATUS_INVALID_SECURITY_DESCR;
383 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
384 return STATUS_UNKNOWN_REVISION;
386 return STATUS_SUCCESS;
389 /**************************************************************************
390 * RtlLengthSecurityDescriptor [NTDLL.@]
392 ULONG WINAPI RtlLengthSecurityDescriptor(
393 PSECURITY_DESCRIPTOR pSecurityDescriptor)
395 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
397 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
402 if ( lpsd->Control & SE_SELF_RELATIVE)
403 offset = (ULONG) lpsd;
405 if ( lpsd->Owner != NULL )
406 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
408 if ( lpsd->Group != NULL )
409 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
411 if ( (lpsd->Control & SE_SACL_PRESENT) &&
413 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
415 if ( (lpsd->Control & SE_DACL_PRESENT) &&
417 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
422 /******************************************************************************
423 * RtlGetDaclSecurityDescriptor [NTDLL.@]
426 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
427 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
428 OUT PBOOLEAN lpbDaclPresent,
430 OUT PBOOLEAN lpbDaclDefaulted)
432 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
434 TRACE("(%p,%p,%p,%p)\n",
435 pSecurityDescriptor, lpbDaclPresent, pDacl, lpbDaclDefaulted);
437 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
438 return STATUS_UNKNOWN_REVISION ;
440 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
442 if ( SE_SELF_RELATIVE & lpsd->Control)
443 *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
447 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
450 return STATUS_SUCCESS;
453 /**************************************************************************
454 * RtlSetDaclSecurityDescriptor [NTDLL.@]
456 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
457 PSECURITY_DESCRIPTOR pSecurityDescriptor,
460 BOOLEAN dacldefaulted )
462 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
464 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
465 return STATUS_UNKNOWN_REVISION;
466 if (lpsd->Control & SE_SELF_RELATIVE)
467 return STATUS_INVALID_SECURITY_DESCR;
470 { lpsd->Control &= ~SE_DACL_PRESENT;
474 lpsd->Control |= SE_DACL_PRESENT;
478 lpsd->Control |= SE_DACL_DEFAULTED;
480 lpsd->Control &= ~SE_DACL_DEFAULTED;
482 return STATUS_SUCCESS;
485 /******************************************************************************
486 * RtlGetSaclSecurityDescriptor [NTDLL.@]
489 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
490 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
491 OUT PBOOLEAN lpbSaclPresent,
493 OUT PBOOLEAN lpbSaclDefaulted)
495 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
497 TRACE("(%p,%p,%p,%p)\n",
498 pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
500 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
501 return STATUS_UNKNOWN_REVISION;
503 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
505 if (SE_SELF_RELATIVE & lpsd->Control)
506 *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Sacl);
510 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
513 return STATUS_SUCCESS;
516 /**************************************************************************
517 * RtlSetSaclSecurityDescriptor [NTDLL.@]
519 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
520 PSECURITY_DESCRIPTOR pSecurityDescriptor,
523 BOOLEAN sacldefaulted)
525 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
527 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
528 return STATUS_UNKNOWN_REVISION;
529 if (lpsd->Control & SE_SELF_RELATIVE)
530 return STATUS_INVALID_SECURITY_DESCR;
532 lpsd->Control &= ~SE_SACL_PRESENT;
535 lpsd->Control |= SE_SACL_PRESENT;
538 lpsd->Control |= SE_SACL_DEFAULTED;
540 lpsd->Control &= ~SE_SACL_DEFAULTED;
541 return STATUS_SUCCESS;
544 /**************************************************************************
545 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
547 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
548 PSECURITY_DESCRIPTOR pSecurityDescriptor,
550 PBOOLEAN OwnerDefaulted)
552 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
554 if ( !lpsd || !Owner || !OwnerDefaulted )
555 return STATUS_INVALID_PARAMETER;
557 if (lpsd->Owner != NULL)
559 if (lpsd->Control & SE_SELF_RELATIVE)
560 *Owner = (PSID)((LPBYTE)lpsd +
563 *Owner = lpsd->Owner;
565 if ( lpsd->Control & SE_OWNER_DEFAULTED )
566 *OwnerDefaulted = TRUE;
568 *OwnerDefaulted = FALSE;
573 return STATUS_SUCCESS;
576 /**************************************************************************
577 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
579 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
580 PSECURITY_DESCRIPTOR pSecurityDescriptor,
582 BOOLEAN ownerdefaulted)
584 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
586 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
587 return STATUS_UNKNOWN_REVISION;
588 if (lpsd->Control & SE_SELF_RELATIVE)
589 return STATUS_INVALID_SECURITY_DESCR;
593 lpsd->Control |= SE_OWNER_DEFAULTED;
595 lpsd->Control &= ~SE_OWNER_DEFAULTED;
596 return STATUS_SUCCESS;
599 /**************************************************************************
600 * RtlSetGroupSecurityDescriptor [NTDLL.@]
602 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
603 PSECURITY_DESCRIPTOR pSecurityDescriptor,
605 BOOLEAN groupdefaulted)
607 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
609 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
610 return STATUS_UNKNOWN_REVISION;
611 if (lpsd->Control & SE_SELF_RELATIVE)
612 return STATUS_INVALID_SECURITY_DESCR;
616 lpsd->Control |= SE_GROUP_DEFAULTED;
618 lpsd->Control &= ~SE_GROUP_DEFAULTED;
619 return STATUS_SUCCESS;
622 /**************************************************************************
623 * RtlGetGroupSecurityDescriptor [NTDLL.@]
625 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
626 PSECURITY_DESCRIPTOR pSecurityDescriptor,
628 PBOOLEAN GroupDefaulted)
630 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
632 if ( !lpsd || !Group || !GroupDefaulted )
633 return STATUS_INVALID_PARAMETER;
635 if (lpsd->Group != NULL)
637 if (lpsd->Control & SE_SELF_RELATIVE)
638 *Group = (PSID)((LPBYTE)lpsd +
641 *Group = lpsd->Group;
643 if ( lpsd->Control & SE_GROUP_DEFAULTED )
644 *GroupDefaulted = TRUE;
646 *GroupDefaulted = FALSE;
651 return STATUS_SUCCESS;
654 /**************************************************************************
655 * RtlMakeSelfRelativeSD [NTDLL.@]
657 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
658 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
659 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
660 IN OUT LPDWORD lpdwBufferLength)
664 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
665 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
667 TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
668 lpdwBufferLength ? *lpdwBufferLength: -1);
670 if (!lpdwBufferLength || !pAbs)
671 return STATUS_INVALID_PARAMETER;
673 length = RtlLengthSecurityDescriptor(pAbs);
674 if (*lpdwBufferLength < length)
676 *lpdwBufferLength = length;
677 return STATUS_BUFFER_TOO_SMALL;
681 return STATUS_INVALID_PARAMETER;
683 if (pAbs->Control & SE_SELF_RELATIVE)
685 memcpy(pRel, pAbs, length);
686 return STATUS_SUCCESS;
689 pRel->Revision = pAbs->Revision;
690 pRel->Sbz1 = pAbs->Sbz1;
691 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
693 offsetRel = sizeof(SECURITY_DESCRIPTOR);
694 pRel->Owner = (PSID) offsetRel;
695 length = RtlLengthSid(pAbs->Owner);
696 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
699 pRel->Group = (PSID) offsetRel;
700 length = RtlLengthSid(pAbs->Group);
701 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
703 if (pRel->Control & SE_SACL_PRESENT)
706 pRel->Sacl = (PACL) offsetRel;
707 length = pAbs->Sacl->AclSize;
708 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
715 if (pRel->Control & SE_DACL_PRESENT)
718 pRel->Dacl = (PACL) offsetRel;
719 length = pAbs->Dacl->AclSize;
720 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
727 return STATUS_SUCCESS;
731 /**************************************************************************
732 * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
734 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
735 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
736 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
737 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
739 OUT LPDWORD lpdwDaclSize,
741 OUT LPDWORD lpdwSaclSize,
743 OUT LPDWORD lpdwOwnerSize,
744 OUT PSID pPrimaryGroup,
745 OUT LPDWORD lpdwPrimaryGroupSize)
747 NTSTATUS status = STATUS_SUCCESS;
748 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
749 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
752 !lpdwAbsoluteSecurityDescriptorSize ||
756 !lpdwPrimaryGroupSize ||
757 ~pRel->Control & SE_SELF_RELATIVE)
758 return STATUS_INVALID_PARAMETER;
760 /* Confirm buffers are sufficiently large */
761 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
763 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
764 status = STATUS_BUFFER_TOO_SMALL;
767 if (pRel->Control & SE_DACL_PRESENT &&
768 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
770 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
771 status = STATUS_BUFFER_TOO_SMALL;
774 if (pRel->Control & SE_SACL_PRESENT &&
775 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
777 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
778 status = STATUS_BUFFER_TOO_SMALL;
782 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
784 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
785 status = STATUS_BUFFER_TOO_SMALL;
789 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
791 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
792 status = STATUS_BUFFER_TOO_SMALL;
795 if (status != STATUS_SUCCESS)
798 /* Copy structures */
799 pAbs->Revision = pRel->Revision;
800 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
802 if (pRel->Control & SE_SACL_PRESENT)
804 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
806 memcpy(pSacl, pAcl, pAcl->AclSize);
810 if (pRel->Control & SE_DACL_PRESENT)
812 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
813 memcpy(pDacl, pAcl, pAcl->AclSize);
819 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
820 memcpy(pOwner, psid, RtlLengthSid(psid));
821 pAbs->Owner = pOwner;
826 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
827 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
828 pAbs->Group = pPrimaryGroup;
834 /******************************************************************************
835 * RtlGetControlSecurityDescriptor (NTDLL.@)
837 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
838 PSECURITY_DESCRIPTOR pSecurityDescriptor,
839 PSECURITY_DESCRIPTOR_CONTROL pControl,
840 LPDWORD lpdwRevision)
842 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
844 TRACE("(%p,%p,%p),stub!\n",pSecurityDescriptor,pControl,lpdwRevision);
846 if ( !lpsd || !pControl || !lpdwRevision )
847 return STATUS_INVALID_PARAMETER;
849 *lpdwRevision = lpsd->Revision;
850 *pControl = lpsd->Control;
852 return STATUS_SUCCESS;
856 /**************************************************************************
857 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
859 NTSTATUS WINAPI RtlAbsoluteToSelfRelativeSD(
860 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
861 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
864 FIXME("%p %p %p\n", AbsoluteSecurityDescriptor,
865 SelfRelativeSecurityDescriptor, BufferLength);
866 return STATUS_NOT_IMPLEMENTED;
871 * access control list's
874 /**************************************************************************
875 * RtlCreateAcl [NTDLL.@]
878 * This should return NTSTATUS
880 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
882 TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
884 if (rev!=ACL_REVISION)
885 return STATUS_INVALID_PARAMETER;
886 if (size<sizeof(ACL))
887 return STATUS_BUFFER_TOO_SMALL;
889 return STATUS_INVALID_PARAMETER;
891 memset(acl,'\0',sizeof(ACL));
892 acl->AclRevision = rev;
895 return STATUS_SUCCESS;
898 /**************************************************************************
899 * RtlFirstFreeAce [NTDLL.@]
900 * looks for the AceCount+1 ACE, and if it is still within the alloced
901 * ACL, return a pointer to it
903 BOOLEAN WINAPI RtlFirstFreeAce(
911 ace = (PACE_HEADER)(acl+1);
912 for (i=0;i<acl->AceCount;i++) {
913 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
915 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
917 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
923 /**************************************************************************
924 * RtlAddAce [NTDLL.@]
926 NTSTATUS WINAPI RtlAddAce(
930 PACE_HEADER acestart,
933 PACE_HEADER ace,targetace;
936 if (acl->AclRevision != ACL_REVISION)
937 return STATUS_INVALID_PARAMETER;
938 if (!RtlFirstFreeAce(acl,&targetace))
939 return STATUS_INVALID_PARAMETER;
940 nrofaces=0;ace=acestart;
941 while (((DWORD)ace-(DWORD)acestart)<acelen) {
943 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
945 if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
946 return STATUS_INVALID_PARAMETER;
947 memcpy((LPBYTE)targetace,acestart,acelen);
948 acl->AceCount+=nrofaces;
949 return STATUS_SUCCESS;
952 /**************************************************************************
953 * RtlDeleteAce [NTDLL.@]
955 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
960 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
962 if (STATUS_SUCCESS == status)
967 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
968 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
970 len += pcAce->AceSize;
971 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
974 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
978 TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\n", pAcl, dwAceIndex, status);
983 /******************************************************************************
984 * RtlAddAccessAllowedAce [NTDLL.@]
986 NTSTATUS WINAPI RtlAddAccessAllowedAce(
988 IN DWORD dwAceRevision,
992 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
995 /******************************************************************************
996 * RtlAddAccessAllowedAceEx [NTDLL.@]
998 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
1000 IN DWORD dwAceRevision,
1002 IN DWORD AccessMask,
1006 ACCESS_ALLOWED_ACE * pAaAce;
1009 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1010 pAcl, dwAceRevision, AccessMask, pSid);
1012 if (!RtlValidSid(pSid))
1013 return STATUS_INVALID_SID;
1014 if (!RtlValidAcl(pAcl))
1015 return STATUS_INVALID_ACL;
1017 dwLengthSid = RtlLengthSid(pSid);
1018 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
1019 return STATUS_INVALID_ACL;
1022 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1024 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
1025 if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
1026 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1028 pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
1029 pAaAce->Header.AceFlags = AceFlags;
1030 pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
1031 pAaAce->Mask = AccessMask;
1033 RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
1034 return STATUS_SUCCESS;
1037 /******************************************************************************
1038 * RtlAddAccessDeniedAce [NTDLL.@]
1040 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1042 IN DWORD dwAceRevision,
1043 IN DWORD AccessMask,
1046 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1049 /******************************************************************************
1050 * RtlAddAccessDeniedAceEx [NTDLL.@]
1052 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1054 IN DWORD dwAceRevision,
1056 IN DWORD AccessMask,
1061 ACCESS_DENIED_ACE * pAdAce;
1063 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1064 pAcl, dwAceRevision, AccessMask, pSid);
1066 if (!RtlValidSid(pSid))
1067 return STATUS_INVALID_SID;
1068 if (!RtlValidAcl(pAcl))
1069 return STATUS_INVALID_ACL;
1071 dwLengthSid = RtlLengthSid(pSid);
1072 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAdAce))
1073 return STATUS_INVALID_ACL;
1076 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1078 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
1079 if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
1080 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1082 pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
1083 pAdAce->Header.AceFlags = AceFlags;
1084 pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
1085 pAdAce->Mask = AccessMask;
1087 RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
1088 return STATUS_SUCCESS;
1091 /******************************************************************************
1092 * RtlValidAcl [NTDLL.@]
1094 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1097 TRACE("(%p)\n", pAcl);
1104 if (pAcl->AclRevision != ACL_REVISION)
1108 ace = (PACE_HEADER)(pAcl+1);
1110 for (i=0;i<=pAcl->AceCount;i++)
1112 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1117 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1121 __EXCEPT(page_fault)
1123 WARN("(%p): invalid pointer!\n", pAcl);
1130 /******************************************************************************
1131 * RtlGetAce [NTDLL.@]
1133 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1137 TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1139 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1140 return STATUS_INVALID_PARAMETER;
1142 ace = (PACE_HEADER)(pAcl + 1);
1143 for (;dwAceIndex;dwAceIndex--)
1144 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1146 *pAce = (LPVOID) ace;
1148 return STATUS_SUCCESS;
1155 /******************************************************************************
1156 * RtlAdjustPrivilege [NTDLL.@]
1158 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4)
1160 FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
1164 /******************************************************************************
1165 * RtlImpersonateSelf [NTDLL.@]
1168 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1170 FIXME("(%08x), stub\n", ImpersonationLevel);
1174 /******************************************************************************
1175 * NtAccessCheck [NTDLL.@]
1176 * ZwAccessCheck [NTDLL.@]
1178 * Checks that a user represented by a token is allowed to access an object
1179 * represented by a security descriptor.
1182 * SecurityDescriptor [I] The security descriptor of the object to check.
1183 * ClientToken [I] Token of the user accessing the object.
1184 * DesiredAccess [I] The desired access to the object.
1185 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1186 * PrivilegeSet [I/O] Privileges used during the access check.
1187 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1188 * GrantedAccess [O] The actual access rights granted.
1189 * AccessStatus [O] The status of the access check.
1195 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1196 * the maximum access rights allowed by the SD and returns them in
1198 * The SecurityDescriptor must have a valid owner and groups present,
1199 * otherwise the function will fail.
1203 PSECURITY_DESCRIPTOR SecurityDescriptor,
1205 ACCESS_MASK DesiredAccess,
1206 PGENERIC_MAPPING GenericMapping,
1207 PPRIVILEGE_SET PrivilegeSet,
1208 PULONG ReturnLength,
1209 PULONG GrantedAccess,
1210 NTSTATUS *AccessStatus)
1214 TRACE("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1215 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1216 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1218 SERVER_START_REQ( access_check )
1220 struct security_descriptor sd;
1225 BOOLEAN defaulted, present;
1227 SECURITY_DESCRIPTOR_CONTROL control;
1229 req->handle = ClientToken;
1230 req->desired_access = DesiredAccess;
1231 req->mapping_read = GenericMapping->GenericRead;
1232 req->mapping_write = GenericMapping->GenericWrite;
1233 req->mapping_execute = GenericMapping->GenericExecute;
1234 req->mapping_all = GenericMapping->GenericAll;
1236 /* marshal security descriptor */
1237 RtlGetControlSecurityDescriptor( SecurityDescriptor, &control, &revision );
1238 sd.control = control & ~SE_SELF_RELATIVE;
1239 RtlGetOwnerSecurityDescriptor( SecurityDescriptor, &owner, &defaulted );
1240 sd.owner_len = RtlLengthSid( owner );
1241 RtlGetGroupSecurityDescriptor( SecurityDescriptor, &group, &defaulted );
1242 sd.group_len = RtlLengthSid( group );
1243 RtlGetSaclSecurityDescriptor( SecurityDescriptor, &present, &sacl, &defaulted );
1244 sd.sacl_len = (present ? sacl->AclSize : 0);
1245 RtlGetDaclSecurityDescriptor( SecurityDescriptor, &present, &dacl, &defaulted );
1246 sd.dacl_len = (present ? dacl->AclSize : 0);
1248 wine_server_add_data( req, &sd, sizeof(sd) );
1249 wine_server_add_data( req, owner, sd.owner_len );
1250 wine_server_add_data( req, group, sd.group_len );
1251 wine_server_add_data( req, sacl, sd.sacl_len );
1252 wine_server_add_data( req, dacl, sd.dacl_len );
1254 wine_server_set_reply( req, &PrivilegeSet->Privilege, *ReturnLength - FIELD_OFFSET( PRIVILEGE_SET, Privilege ) );
1256 status = wine_server_call( req );
1258 *ReturnLength = FIELD_OFFSET( PRIVILEGE_SET, Privilege ) + reply->privileges_len;
1259 PrivilegeSet->PrivilegeCount = reply->privileges_len / sizeof(LUID_AND_ATTRIBUTES);
1261 if (status == STATUS_SUCCESS)
1262 *AccessStatus = reply->access_status;
1263 *GrantedAccess = reply->access_granted;
1270 /******************************************************************************
1271 * NtSetSecurityObject [NTDLL.@]
1274 NtSetSecurityObject(
1276 IN SECURITY_INFORMATION SecurityInformation,
1277 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1279 FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1280 return STATUS_SUCCESS;
1283 /******************************************************************************
1284 * RtlConvertSidToUnicodeString (NTDLL.@)
1286 * The returned SID is used to access the USER registry hive usually
1288 * the native function returns something like
1289 * "S-1-5-21-0000000000-000000000-0000000000-500";
1291 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1292 PUNICODE_STRING String,
1294 BOOLEAN AllocateString)
1296 const char *user = wine_get_user_name();
1297 int len = ntdll_umbstowcs( 0, user, strlen(user)+1, NULL, 0 ) * sizeof(WCHAR);
1299 FIXME("(%p %p %u)\n", String, Sid, AllocateString);
1301 String->Length = len - sizeof(WCHAR);
1304 String->MaximumLength = len;
1305 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1306 return STATUS_NO_MEMORY;
1308 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1310 ntdll_umbstowcs( 0, user, strlen(user)+1, String->Buffer, len/sizeof(WCHAR) );
1311 return STATUS_SUCCESS;
1314 /******************************************************************************
1315 * RtlQueryInformationAcl (NTDLL.@)
1317 NTSTATUS WINAPI RtlQueryInformationAcl(
1319 LPVOID pAclInformation,
1320 DWORD nAclInformationLength,
1321 ACL_INFORMATION_CLASS dwAclInformationClass)
1323 NTSTATUS status = STATUS_SUCCESS;
1325 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1326 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1328 switch (dwAclInformationClass)
1330 case AclRevisionInformation:
1332 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1334 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1335 status = STATUS_INVALID_PARAMETER;
1337 paclrev->AclRevision = pAcl->AclRevision;
1342 case AclSizeInformation:
1344 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1346 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1347 status = STATUS_INVALID_PARAMETER;
1353 paclsize->AceCount = pAcl->AceCount;
1355 paclsize->AclBytesInUse = 0;
1356 ace = (PACE_HEADER) (pAcl + 1);
1358 for (i = 0; i < pAcl->AceCount; i++)
1360 paclsize->AclBytesInUse += ace->AceSize;
1361 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1364 if (pAcl->AclSize < paclsize->AclBytesInUse)
1366 WARN("Acl has %ld bytes free\n", paclsize->AclBytesFree);
1367 paclsize->AclBytesFree = 0;
1368 paclsize->AclBytesInUse = pAcl->AclSize;
1371 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1378 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1379 status = STATUS_INVALID_PARAMETER;