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 ge 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 withe 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;
835 * access control list's
838 /**************************************************************************
839 * RtlCreateAcl [NTDLL.@]
842 * This should return NTSTATUS
844 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
846 TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
848 if (rev!=ACL_REVISION)
849 return STATUS_INVALID_PARAMETER;
850 if (size<sizeof(ACL))
851 return STATUS_BUFFER_TOO_SMALL;
853 return STATUS_INVALID_PARAMETER;
855 memset(acl,'\0',sizeof(ACL));
856 acl->AclRevision = rev;
859 return STATUS_SUCCESS;
862 /**************************************************************************
863 * RtlFirstFreeAce [NTDLL.@]
864 * looks for the AceCount+1 ACE, and if it is still within the alloced
865 * ACL, return a pointer to it
867 BOOLEAN WINAPI RtlFirstFreeAce(
875 ace = (PACE_HEADER)(acl+1);
876 for (i=0;i<acl->AceCount;i++) {
877 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
879 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
881 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
887 /**************************************************************************
888 * RtlAddAce [NTDLL.@]
890 NTSTATUS WINAPI RtlAddAce(
894 PACE_HEADER acestart,
897 PACE_HEADER ace,targetace;
900 if (acl->AclRevision != ACL_REVISION)
901 return STATUS_INVALID_PARAMETER;
902 if (!RtlFirstFreeAce(acl,&targetace))
903 return STATUS_INVALID_PARAMETER;
904 nrofaces=0;ace=acestart;
905 while (((DWORD)ace-(DWORD)acestart)<acelen) {
907 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
909 if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
910 return STATUS_INVALID_PARAMETER;
911 memcpy((LPBYTE)targetace,acestart,acelen);
912 acl->AceCount+=nrofaces;
913 return STATUS_SUCCESS;
916 /**************************************************************************
917 * RtlDeleteAce [NTDLL.@]
919 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
924 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
926 if (STATUS_SUCCESS == status)
931 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
932 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
934 len += pcAce->AceSize;
935 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
938 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
942 TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\n", pAcl, dwAceIndex, status);
947 /******************************************************************************
948 * RtlAddAccessAllowedAce [NTDLL.@]
950 NTSTATUS WINAPI RtlAddAccessAllowedAce(
952 IN DWORD dwAceRevision,
956 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
959 /******************************************************************************
960 * RtlAddAccessAllowedAceEx [NTDLL.@]
962 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
964 IN DWORD dwAceRevision,
970 ACCESS_ALLOWED_ACE * pAaAce;
973 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
974 pAcl, dwAceRevision, AccessMask, pSid);
976 if (!RtlValidSid(pSid))
977 return STATUS_INVALID_SID;
978 if (!RtlValidAcl(pAcl))
979 return STATUS_INVALID_ACL;
981 dwLengthSid = RtlLengthSid(pSid);
982 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
983 return STATUS_INVALID_ACL;
986 return STATUS_ALLOTTED_SPACE_EXCEEDED;
988 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
989 if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
990 return STATUS_ALLOTTED_SPACE_EXCEEDED;
992 pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
993 pAaAce->Header.AceFlags = AceFlags;
994 pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
995 pAaAce->Mask = AccessMask;
997 RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
998 return STATUS_SUCCESS;
1001 /******************************************************************************
1002 * RtlAddAccessDeniedAce [NTDLL.@]
1004 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1006 IN DWORD dwAceRevision,
1007 IN DWORD AccessMask,
1010 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1013 /******************************************************************************
1014 * RtlAddAccessDeniedAceEx [NTDLL.@]
1016 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1018 IN DWORD dwAceRevision,
1020 IN DWORD AccessMask,
1025 ACCESS_DENIED_ACE * pAdAce;
1027 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1028 pAcl, dwAceRevision, AccessMask, pSid);
1030 if (!RtlValidSid(pSid))
1031 return STATUS_INVALID_SID;
1032 if (!RtlValidAcl(pAcl))
1033 return STATUS_INVALID_ACL;
1035 dwLengthSid = RtlLengthSid(pSid);
1036 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAdAce))
1037 return STATUS_INVALID_ACL;
1040 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1042 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
1043 if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
1044 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1046 pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
1047 pAdAce->Header.AceFlags = AceFlags;
1048 pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
1049 pAdAce->Mask = AccessMask;
1051 RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
1052 return STATUS_SUCCESS;
1055 /******************************************************************************
1056 * RtlValidAcl [NTDLL.@]
1058 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1061 TRACE("(%p)\n", pAcl);
1068 if (pAcl->AclRevision != ACL_REVISION)
1072 ace = (PACE_HEADER)(pAcl+1);
1074 for (i=0;i<=pAcl->AceCount;i++)
1076 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1081 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1085 __EXCEPT(page_fault)
1087 WARN("(%p): invalid pointer!\n", pAcl);
1094 /******************************************************************************
1095 * RtlGetAce [NTDLL.@]
1097 NTSTATUS WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1101 TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1103 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1104 return STATUS_INVALID_PARAMETER;
1106 ace = (PACE_HEADER)(pAcl + 1);
1107 for (;dwAceIndex;dwAceIndex--)
1108 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1110 *pAce = (LPVOID) ace;
1112 return STATUS_SUCCESS;
1119 /******************************************************************************
1120 * RtlAdjustPrivilege [NTDLL.@]
1122 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4)
1124 FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
1128 /******************************************************************************
1129 * RtlImpersonateSelf [NTDLL.@]
1132 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1134 FIXME("(%08x), stub\n", ImpersonationLevel);
1138 /******************************************************************************
1139 * NtAccessCheck [NTDLL.@]
1140 * ZwAccessCheck [NTDLL.@]
1144 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1145 IN HANDLE ClientToken,
1146 IN ACCESS_MASK DesiredAccess,
1147 IN PGENERIC_MAPPING GenericMapping,
1148 OUT PPRIVILEGE_SET PrivilegeSet,
1149 OUT PULONG ReturnLength,
1150 OUT PULONG GrantedAccess,
1151 OUT NTSTATUS *AccessStatus)
1153 FIXME("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1154 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1155 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1156 *AccessStatus = STATUS_SUCCESS;
1157 return STATUS_SUCCESS;
1160 /******************************************************************************
1161 * NtSetSecurityObject [NTDLL.@]
1164 NtSetSecurityObject(
1166 IN SECURITY_INFORMATION SecurityInformation,
1167 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1169 FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1170 return STATUS_SUCCESS;
1173 /******************************************************************************
1174 * RtlGetControlSecurityDescriptor (NTDLL.@)
1177 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1178 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1179 PSECURITY_DESCRIPTOR_CONTROL pControl,
1180 LPDWORD lpdwRevision)
1182 FIXME("(%p,%p,%p),stub!\n",pSecurityDescriptor,pControl,lpdwRevision);
1183 return STATUS_SUCCESS;
1186 /******************************************************************************
1187 * RtlConvertSidToUnicodeString (NTDLL.@)
1189 * The returned SID is used to access the USER registry hive usually
1191 * the native function returns something like
1192 * "S-1-5-21-0000000000-000000000-0000000000-500";
1194 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1195 PUNICODE_STRING String,
1197 BOOLEAN AllocateString)
1199 const char *user = wine_get_user_name();
1200 int len = ntdll_umbstowcs( 0, user, strlen(user)+1, NULL, 0 ) * sizeof(WCHAR);
1202 FIXME("(%p %p %u)\n", String, Sid, AllocateString);
1204 String->Length = len - sizeof(WCHAR);
1207 String->MaximumLength = len;
1208 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1209 return STATUS_NO_MEMORY;
1211 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1213 ntdll_umbstowcs( 0, user, strlen(user)+1, String->Buffer, len/sizeof(WCHAR) );
1214 return STATUS_SUCCESS;
1217 /******************************************************************************
1218 * RtlQueryInformationAcl (NTDLL.@)
1220 NTSTATUS WINAPI RtlQueryInformationAcl(
1222 LPVOID pAclInformation,
1223 DWORD nAclInformationLength,
1224 ACL_INFORMATION_CLASS dwAclInformationClass)
1226 NTSTATUS status = STATUS_SUCCESS;
1228 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1229 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1231 switch (dwAclInformationClass)
1233 case AclRevisionInformation:
1235 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1237 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1238 status = STATUS_INVALID_PARAMETER;
1240 paclrev->AclRevision = pAcl->AclRevision;
1245 case AclSizeInformation:
1247 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1249 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1250 status = STATUS_INVALID_PARAMETER;
1256 paclsize->AceCount = pAcl->AceCount;
1258 paclsize->AclBytesInUse = 0;
1259 ace = (PACE_HEADER) (pAcl + 1);
1261 for (i = 0; i < pAcl->AceCount; i++)
1263 paclsize->AclBytesInUse += ace->AceSize;
1264 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1267 if (pAcl->AclSize < paclsize->AclBytesInUse)
1269 WARN("Acl has %ld bytes free\n", paclsize->AclBytesFree);
1270 paclsize->AclBytesFree = 0;
1271 paclsize->AclBytesInUse = pAcl->AclSize;
1274 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1281 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1282 status = STATUS_INVALID_PARAMETER;