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"
42 #include "ntdll_misc.h"
44 #include "wine/library.h"
45 #include "wine/debug.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
49 #define NT_SUCCESS(status) (status == STATUS_SUCCESS)
51 /* filter for page-fault exceptions */
52 static WINE_EXCEPTION_FILTER(page_fault)
54 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
55 return EXCEPTION_EXECUTE_HANDLER;
56 return EXCEPTION_CONTINUE_SEARCH;
63 /******************************************************************************
64 * RtlAllocateAndInitializeSid [NTDLL.@]
67 BOOLEAN WINAPI RtlAllocateAndInitializeSid (
68 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
69 BYTE nSubAuthorityCount,
70 DWORD nSubAuthority0, DWORD nSubAuthority1,
71 DWORD nSubAuthority2, DWORD nSubAuthority3,
72 DWORD nSubAuthority4, DWORD nSubAuthority5,
73 DWORD nSubAuthority6, DWORD nSubAuthority7,
77 TRACE("(%p, 0x%04x,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,0x%08lx,%p)\n",
78 pIdentifierAuthority,nSubAuthorityCount,
79 nSubAuthority0, nSubAuthority1, nSubAuthority2, nSubAuthority3,
80 nSubAuthority4, nSubAuthority5, nSubAuthority6, nSubAuthority7, pSid);
82 if (!(*pSid = RtlAllocateHeap( GetProcessHeap(), 0,
83 RtlLengthRequiredSid(nSubAuthorityCount))))
86 ((SID*)*pSid)->Revision = SID_REVISION;
88 if (pIdentifierAuthority)
89 memcpy(&((SID*)*pSid)->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
90 *RtlSubAuthorityCountSid(*pSid) = nSubAuthorityCount;
92 if (nSubAuthorityCount > 0)
93 *RtlSubAuthoritySid(*pSid, 0) = nSubAuthority0;
94 if (nSubAuthorityCount > 1)
95 *RtlSubAuthoritySid(*pSid, 1) = nSubAuthority1;
96 if (nSubAuthorityCount > 2)
97 *RtlSubAuthoritySid(*pSid, 2) = nSubAuthority2;
98 if (nSubAuthorityCount > 3)
99 *RtlSubAuthoritySid(*pSid, 3) = nSubAuthority3;
100 if (nSubAuthorityCount > 4)
101 *RtlSubAuthoritySid(*pSid, 4) = nSubAuthority4;
102 if (nSubAuthorityCount > 5)
103 *RtlSubAuthoritySid(*pSid, 5) = nSubAuthority5;
104 if (nSubAuthorityCount > 6)
105 *RtlSubAuthoritySid(*pSid, 6) = nSubAuthority6;
106 if (nSubAuthorityCount > 7)
107 *RtlSubAuthoritySid(*pSid, 7) = nSubAuthority7;
109 return STATUS_SUCCESS;
111 /******************************************************************************
112 * RtlEqualSid [NTDLL.@]
114 * Determine if two SIDs are equal.
117 * pSid1 [I] Source SID
118 * pSid2 [I] SID to compare with
121 * TRUE, if pSid1 is equal to pSid2,
124 BOOL WINAPI RtlEqualSid( PSID pSid1, PSID pSid2 )
126 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
129 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
132 if (memcmp(pSid1, pSid2, RtlLengthSid(pSid1)) != 0)
138 /******************************************************************************
139 * RtlEqualPrefixSid [NTDLL.@]
141 BOOL WINAPI RtlEqualPrefixSid (PSID pSid1, PSID pSid2)
143 if (!RtlValidSid(pSid1) || !RtlValidSid(pSid2))
146 if (*RtlSubAuthorityCountSid(pSid1) != *RtlSubAuthorityCountSid(pSid2))
149 if (memcmp(pSid1, pSid2, RtlLengthRequiredSid(((SID*)pSid1)->SubAuthorityCount - 1)) != 0)
156 /******************************************************************************
157 * RtlFreeSid [NTDLL.@]
159 * Free the resources used by a SID.
162 * pSid [I] SID to Free.
167 DWORD WINAPI RtlFreeSid(PSID pSid)
169 TRACE("(%p)\n", pSid);
170 RtlFreeHeap( GetProcessHeap(), 0, pSid );
171 return STATUS_SUCCESS;
174 /**************************************************************************
175 * RtlLengthRequiredSid [NTDLL.@]
177 * Determine the amount of memory a SID will use
180 * nrofsubauths [I] Number of Sub Authorities in the SID.
183 * The size, in bytes, of a SID with nrofsubauths Sub Authorities.
185 DWORD WINAPI RtlLengthRequiredSid(DWORD nrofsubauths)
187 return (nrofsubauths-1)*sizeof(DWORD) + sizeof(SID);
190 /**************************************************************************
191 * RtlLengthSid [NTDLL.@]
193 * Determine the amount of memory a SID is using
196 * pSid [I] SID to ge the size of.
199 * The size, in bytes, of pSid.
201 DWORD WINAPI RtlLengthSid(PSID pSid)
203 TRACE("sid=%p\n",pSid);
205 return RtlLengthRequiredSid(*RtlSubAuthorityCountSid(pSid));
208 /**************************************************************************
209 * RtlInitializeSid [NTDLL.@]
214 * pSid [I] SID to initialise
215 * pIdentifierAuthority [I] Identifier Authority
216 * nSubAuthorityCount [I] Number of Sub Authorities
219 * Success: TRUE. pSid is initialised withe the details given.
220 * Failure: FALSE, if nSubAuthorityCount is >= SID_MAX_SUB_AUTHORITIES.
222 BOOL WINAPI RtlInitializeSid(
224 PSID_IDENTIFIER_AUTHORITY pIdentifierAuthority,
225 BYTE nSubAuthorityCount)
230 if (nSubAuthorityCount >= SID_MAX_SUB_AUTHORITIES)
233 pisid->Revision = SID_REVISION;
234 pisid->SubAuthorityCount = nSubAuthorityCount;
235 if (pIdentifierAuthority)
236 memcpy(&pisid->IdentifierAuthority, pIdentifierAuthority, sizeof (SID_IDENTIFIER_AUTHORITY));
238 for (i = 0; i < nSubAuthorityCount; i++)
239 *RtlSubAuthoritySid(pSid, i) = 0;
244 /**************************************************************************
245 * RtlSubAuthoritySid [NTDLL.@]
247 * Return the Sub Authority of a SID
250 * pSid [I] SID to get the Sub Authority from.
251 * nSubAuthority [I] Sub Authority number.
254 * A pointer to The Sub Authority value of pSid.
256 LPDWORD WINAPI RtlSubAuthoritySid( PSID pSid, DWORD nSubAuthority )
258 return &(((SID*)pSid)->SubAuthority[nSubAuthority]);
261 /**************************************************************************
262 * RtlIdentifierAuthoritySid [NTDLL.@]
264 * Return the Identifier Authority of a SID.
267 * pSid [I] SID to get the Identifier Authority from.
270 * A pointer to the Identifier Authority value of pSid.
272 PSID_IDENTIFIER_AUTHORITY WINAPI RtlIdentifierAuthoritySid( PSID pSid )
274 return &(((SID*)pSid)->IdentifierAuthority);
277 /**************************************************************************
278 * RtlSubAuthorityCountSid [NTDLL.@]
280 * Get the number of Sub Authorities in a SID.
283 * pSid [I] SID to get the count from.
286 * A pointer to the Sub Authority count of pSid.
288 LPBYTE WINAPI RtlSubAuthorityCountSid(PSID pSid)
290 return &(((SID*)pSid)->SubAuthorityCount);
293 /**************************************************************************
294 * RtlCopySid [NTDLL.@]
296 DWORD WINAPI RtlCopySid( DWORD nDestinationSidLength, PSID pDestinationSid, PSID pSourceSid )
298 if (!pSourceSid || !RtlValidSid(pSourceSid) ||
299 (nDestinationSidLength < RtlLengthSid(pSourceSid)))
302 if (nDestinationSidLength < (((SID*)pSourceSid)->SubAuthorityCount*4+8))
305 memmove(pDestinationSid, pSourceSid, ((SID*)pSourceSid)->SubAuthorityCount*4+8);
308 /******************************************************************************
309 * RtlValidSid [NTDLL.@]
311 * Determine if a SID is valid.
314 * pSid [I] SID to check
317 * TRUE if pSid is valid,
320 BOOLEAN WINAPI RtlValidSid( PSID pSid )
326 if (!pSid || ((SID*)pSid)->Revision != SID_REVISION ||
327 ((SID*)pSid)->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
334 WARN("(%p): invalid pointer!\n", pSid);
343 * security descriptor functions
346 /**************************************************************************
347 * RtlCreateSecurityDescriptor [NTDLL.@]
349 * Initialise a SECURITY_DESCRIPTOR.
352 * lpsd [O] Descriptor to initialise.
353 * rev [I] Revision, must be set to SECURITY_DESCRIPTOR_REVISION.
356 * Success: STATUS_SUCCESS.
357 * Failure: STATUS_UNKNOWN_REVISION if rev is incorrect.
359 NTSTATUS WINAPI RtlCreateSecurityDescriptor(
360 PSECURITY_DESCRIPTOR lpsd,
363 if (rev!=SECURITY_DESCRIPTOR_REVISION)
364 return STATUS_UNKNOWN_REVISION;
365 memset(lpsd,'\0',sizeof(SECURITY_DESCRIPTOR));
366 ((SECURITY_DESCRIPTOR*)lpsd)->Revision = SECURITY_DESCRIPTOR_REVISION;
367 return STATUS_SUCCESS;
369 /**************************************************************************
370 * RtlValidSecurityDescriptor [NTDLL.@]
372 * Determine if a SECURITY_DESCRIPTOR is valid.
375 * SecurityDescriptor [I] Descriptor to check.
378 * Success: STATUS_SUCCESS.
379 * Failure: STATUS_INVALID_SECURITY_DESCR or STATUS_UNKNOWN_REVISION.
381 NTSTATUS WINAPI RtlValidSecurityDescriptor(
382 PSECURITY_DESCRIPTOR SecurityDescriptor)
384 if ( ! SecurityDescriptor )
385 return STATUS_INVALID_SECURITY_DESCR;
386 if ( ((SECURITY_DESCRIPTOR*)SecurityDescriptor)->Revision != SECURITY_DESCRIPTOR_REVISION )
387 return STATUS_UNKNOWN_REVISION;
389 return STATUS_SUCCESS;
392 /**************************************************************************
393 * RtlLengthSecurityDescriptor [NTDLL.@]
395 ULONG WINAPI RtlLengthSecurityDescriptor(
396 PSECURITY_DESCRIPTOR pSecurityDescriptor)
398 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
400 ULONG Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
405 if ( lpsd->Control & SE_SELF_RELATIVE)
406 offset = (ULONG) lpsd;
408 if ( lpsd->Owner != NULL )
409 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Owner + offset));
411 if ( lpsd->Group != NULL )
412 Size += RtlLengthSid((PSID)((LPBYTE)lpsd->Group + offset));
414 if ( lpsd->Sacl != NULL )
415 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
417 if ( lpsd->Dacl != NULL )
418 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
423 /******************************************************************************
424 * RtlGetDaclSecurityDescriptor [NTDLL.@]
427 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
428 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
429 OUT PBOOLEAN lpbDaclPresent,
431 OUT PBOOLEAN lpbDaclDefaulted)
433 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
435 TRACE("(%p,%p,%p,%p)\n",
436 pSecurityDescriptor, lpbDaclPresent, *pDacl, lpbDaclDefaulted);
438 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
439 return STATUS_UNKNOWN_REVISION ;
441 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
443 if ( SE_SELF_RELATIVE & lpsd->Control)
444 { *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
447 { *pDacl = lpsd->Dacl;
451 *lpbDaclDefaulted = (( SE_DACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
453 return STATUS_SUCCESS;
456 /**************************************************************************
457 * RtlSetDaclSecurityDescriptor [NTDLL.@]
459 NTSTATUS WINAPI RtlSetDaclSecurityDescriptor (
460 PSECURITY_DESCRIPTOR pSecurityDescriptor,
463 BOOLEAN dacldefaulted )
465 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
467 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
468 return STATUS_UNKNOWN_REVISION;
469 if (lpsd->Control & SE_SELF_RELATIVE)
470 return STATUS_INVALID_SECURITY_DESCR;
473 { lpsd->Control &= ~SE_DACL_PRESENT;
477 lpsd->Control |= SE_DACL_PRESENT;
481 lpsd->Control |= SE_DACL_DEFAULTED;
483 lpsd->Control &= ~SE_DACL_DEFAULTED;
485 return STATUS_SUCCESS;
488 /******************************************************************************
489 * RtlGetSaclSecurityDescriptor [NTDLL.@]
492 NTSTATUS WINAPI RtlGetSaclSecurityDescriptor(
493 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
494 OUT PBOOLEAN lpbSaclPresent,
496 OUT PBOOLEAN lpbSaclDefaulted)
498 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
500 TRACE("(%p,%p,%p,%p)\n",
501 pSecurityDescriptor, lpbSaclPresent, *pSacl, lpbSaclDefaulted);
503 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
504 return STATUS_UNKNOWN_REVISION ;
506 if ( (*lpbSaclPresent = (SE_SACL_PRESENT & lpsd->Control) ? 1 : 0) )
508 if ( SE_SELF_RELATIVE & lpsd->Control)
509 { *pSacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Sacl);
512 { *pSacl = lpsd->Sacl;
516 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
518 return STATUS_SUCCESS;
521 /**************************************************************************
522 * RtlSetSaclSecurityDescriptor [NTDLL.@]
524 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
525 PSECURITY_DESCRIPTOR pSecurityDescriptor,
528 BOOLEAN sacldefaulted)
530 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
532 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
533 return STATUS_UNKNOWN_REVISION;
534 if (lpsd->Control & SE_SELF_RELATIVE)
535 return STATUS_INVALID_SECURITY_DESCR;
537 lpsd->Control &= ~SE_SACL_PRESENT;
540 lpsd->Control |= SE_SACL_PRESENT;
543 lpsd->Control |= SE_SACL_DEFAULTED;
545 lpsd->Control &= ~SE_SACL_DEFAULTED;
546 return STATUS_SUCCESS;
549 /**************************************************************************
550 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
552 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
553 PSECURITY_DESCRIPTOR pSecurityDescriptor,
555 PBOOLEAN OwnerDefaulted)
557 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
559 if ( !lpsd || !Owner || !OwnerDefaulted )
560 return STATUS_INVALID_PARAMETER;
562 if (lpsd->Owner != NULL)
564 if (lpsd->Control & SE_SELF_RELATIVE)
565 *Owner = (PSID)((LPBYTE)lpsd +
568 *Owner = lpsd->Owner;
570 if ( lpsd->Control & SE_OWNER_DEFAULTED )
571 *OwnerDefaulted = TRUE;
573 *OwnerDefaulted = FALSE;
578 return STATUS_SUCCESS;
581 /**************************************************************************
582 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
584 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
585 PSECURITY_DESCRIPTOR pSecurityDescriptor,
587 BOOLEAN ownerdefaulted)
589 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
591 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
592 return STATUS_UNKNOWN_REVISION;
593 if (lpsd->Control & SE_SELF_RELATIVE)
594 return STATUS_INVALID_SECURITY_DESCR;
598 lpsd->Control |= SE_OWNER_DEFAULTED;
600 lpsd->Control &= ~SE_OWNER_DEFAULTED;
601 return STATUS_SUCCESS;
604 /**************************************************************************
605 * RtlSetGroupSecurityDescriptor [NTDLL.@]
607 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
608 PSECURITY_DESCRIPTOR pSecurityDescriptor,
610 BOOLEAN groupdefaulted)
612 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
614 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
615 return STATUS_UNKNOWN_REVISION;
616 if (lpsd->Control & SE_SELF_RELATIVE)
617 return STATUS_INVALID_SECURITY_DESCR;
621 lpsd->Control |= SE_GROUP_DEFAULTED;
623 lpsd->Control &= ~SE_GROUP_DEFAULTED;
624 return STATUS_SUCCESS;
626 /**************************************************************************
627 * RtlGetGroupSecurityDescriptor [NTDLL.@]
629 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
630 PSECURITY_DESCRIPTOR pSecurityDescriptor,
632 PBOOLEAN GroupDefaulted)
634 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
636 if ( !lpsd || !Group || !GroupDefaulted )
637 return STATUS_INVALID_PARAMETER;
639 if (lpsd->Group != NULL)
641 if (lpsd->Control & SE_SELF_RELATIVE)
642 *Group = (PSID)((LPBYTE)lpsd +
645 *Group = lpsd->Group;
647 if ( lpsd->Control & SE_GROUP_DEFAULTED )
648 *GroupDefaulted = TRUE;
650 *GroupDefaulted = FALSE;
655 return STATUS_SUCCESS;
658 /**************************************************************************
659 * RtlMakeSelfRelativeSD [NTDLL.@]
661 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
662 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
663 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
664 IN OUT LPDWORD lpdwBufferLength)
668 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
669 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
671 TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
672 lpdwBufferLength ? *lpdwBufferLength: -1);
674 if (!lpdwBufferLength || !pAbs)
675 return STATUS_INVALID_PARAMETER;
677 length = RtlLengthSecurityDescriptor(pAbs);
678 if (*lpdwBufferLength < length)
680 *lpdwBufferLength = length;
681 return STATUS_BUFFER_TOO_SMALL;
685 return STATUS_INVALID_PARAMETER;
687 if (pAbs->Control & SE_SELF_RELATIVE)
689 memcpy(pRel, pAbs, length);
690 return STATUS_SUCCESS;
693 pRel->Revision = pAbs->Revision;
694 pRel->Sbz1 = pAbs->Sbz1;
695 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
697 offsetRel = sizeof(SECURITY_DESCRIPTOR);
698 pRel->Owner = (PSID) offsetRel;
699 length = RtlLengthSid(pAbs->Owner);
700 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
703 pRel->Group = (PSID) offsetRel;
704 length = RtlLengthSid(pAbs->Group);
705 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
707 if (pRel->Control & SE_SACL_PRESENT)
710 pRel->Sacl = (PACL) offsetRel;
711 length = pAbs->Sacl->AclSize;
712 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
719 if (pRel->Control & SE_DACL_PRESENT)
722 pRel->Dacl = (PACL) offsetRel;
723 length = pAbs->Dacl->AclSize;
724 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
731 return STATUS_SUCCESS;
735 /**************************************************************************
736 + * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
738 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
739 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
740 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
741 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
743 OUT LPDWORD lpdwDaclSize,
745 OUT LPDWORD lpdwSaclSize,
747 OUT LPDWORD lpdwOwnerSize,
748 OUT PSID pPrimaryGroup,
749 OUT LPDWORD lpdwPrimaryGroupSize)
751 NTSTATUS status = STATUS_SUCCESS;
752 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
753 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
756 !lpdwAbsoluteSecurityDescriptorSize ||
760 !lpdwPrimaryGroupSize ||
761 ~pRel->Control & SE_SELF_RELATIVE)
762 return STATUS_INVALID_PARAMETER;
764 /* Confirm buffers are sufficiently large */
765 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
767 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
768 status = STATUS_BUFFER_TOO_SMALL;
771 if (pRel->Control & SE_DACL_PRESENT &&
772 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
774 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
775 status = STATUS_BUFFER_TOO_SMALL;
778 if (pRel->Control & SE_SACL_PRESENT &&
779 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
781 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
782 status = STATUS_BUFFER_TOO_SMALL;
786 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
788 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
789 status = STATUS_BUFFER_TOO_SMALL;
793 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
795 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
796 status = STATUS_BUFFER_TOO_SMALL;
799 if (status != STATUS_SUCCESS)
802 /* Copy structures */
803 pAbs->Revision = pRel->Revision;
804 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
806 if (pRel->Control & SE_SACL_PRESENT)
808 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
810 memcpy(pSacl, pAcl, pAcl->AclSize);
814 if (pRel->Control & SE_DACL_PRESENT)
816 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
817 memcpy(pDacl, pAcl, pAcl->AclSize);
823 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
824 memcpy(pOwner, psid, RtlLengthSid(psid));
825 pAbs->Owner = pOwner;
830 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
831 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
832 pAbs->Group = pPrimaryGroup;
839 * access control list's
842 /**************************************************************************
843 * RtlCreateAcl [NTDLL.@]
846 * This should return NTSTATUS
848 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
850 TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
852 if (rev!=ACL_REVISION)
853 return STATUS_INVALID_PARAMETER;
854 if (size<sizeof(ACL))
855 return STATUS_BUFFER_TOO_SMALL;
857 return STATUS_INVALID_PARAMETER;
859 memset(acl,'\0',sizeof(ACL));
860 acl->AclRevision = rev;
863 return STATUS_SUCCESS;
866 /**************************************************************************
867 * RtlFirstFreeAce [NTDLL.@]
868 * looks for the AceCount+1 ACE, and if it is still within the alloced
869 * ACL, return a pointer to it
871 BOOLEAN WINAPI RtlFirstFreeAce(
879 ace = (PACE_HEADER)(acl+1);
880 for (i=0;i<acl->AceCount;i++) {
881 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
883 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
885 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
891 /**************************************************************************
892 * RtlAddAce [NTDLL.@]
894 NTSTATUS WINAPI RtlAddAce(
898 PACE_HEADER acestart,
901 PACE_HEADER ace,targetace;
904 if (acl->AclRevision != ACL_REVISION)
905 return STATUS_INVALID_PARAMETER;
906 if (!RtlFirstFreeAce(acl,&targetace))
907 return STATUS_INVALID_PARAMETER;
908 nrofaces=0;ace=acestart;
909 while (((DWORD)ace-(DWORD)acestart)<acelen) {
911 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
913 if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
914 return STATUS_INVALID_PARAMETER;
915 memcpy((LPBYTE)targetace,acestart,acelen);
916 acl->AceCount+=nrofaces;
917 return STATUS_SUCCESS;
920 /**************************************************************************
921 * RtlDeleteAce [NTDLL.@]
923 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
928 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
930 if (STATUS_SUCCESS == status)
935 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
936 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
938 len += pcAce->AceSize;
939 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
942 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
949 /******************************************************************************
950 * RtlAddAccessAllowedAce [NTDLL.@]
952 NTSTATUS WINAPI RtlAddAccessAllowedAce(
954 IN DWORD dwAceRevision,
958 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
961 /******************************************************************************
962 * RtlAddAccessAllowedAceEx [NTDLL.@]
964 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
966 IN DWORD dwAceRevision,
972 ACCESS_ALLOWED_ACE * pAaAce;
975 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
976 pAcl, dwAceRevision, AccessMask, pSid);
978 if (!RtlValidSid(pSid))
979 return STATUS_INVALID_SID;
980 if (!RtlValidAcl(pAcl))
981 return STATUS_INVALID_ACL;
983 dwLengthSid = RtlLengthSid(pSid);
984 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
985 return STATUS_INVALID_ACL;
988 return STATUS_ALLOTTED_SPACE_EXCEEDED;
990 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
991 if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
992 return STATUS_ALLOTTED_SPACE_EXCEEDED;
994 pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
995 pAaAce->Header.AceFlags = AceFlags;
996 pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
997 pAaAce->Mask = AccessMask;
999 RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
1000 return STATUS_SUCCESS;
1003 /******************************************************************************
1004 * RtlAddAccessDeniedAce [NTDLL.@]
1006 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1008 IN DWORD dwAceRevision,
1009 IN DWORD AccessMask,
1012 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1015 /******************************************************************************
1016 * RtlAddAccessDeniedAceEx [NTDLL.@]
1018 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1020 IN DWORD dwAceRevision,
1022 IN DWORD AccessMask,
1027 ACCESS_DENIED_ACE * pAdAce;
1029 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1030 pAcl, dwAceRevision, AccessMask, pSid);
1032 if (!RtlValidSid(pSid))
1033 return STATUS_INVALID_SID;
1034 if (!RtlValidAcl(pAcl))
1035 return STATUS_INVALID_ACL;
1037 dwLengthSid = RtlLengthSid(pSid);
1038 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAdAce))
1039 return STATUS_INVALID_ACL;
1042 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1044 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
1045 if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
1046 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1048 pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
1049 pAdAce->Header.AceFlags = AceFlags;
1050 pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
1051 pAdAce->Mask = AccessMask;
1053 RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
1054 return STATUS_SUCCESS;
1057 /******************************************************************************
1058 * RtlValidAcl [NTDLL.@]
1060 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1063 TRACE("(%p)\n", pAcl);
1070 if (pAcl->AclRevision != ACL_REVISION)
1074 ace = (PACE_HEADER)(pAcl+1);
1076 for (i=0;i<=pAcl->AceCount;i++)
1078 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1083 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1087 __EXCEPT(page_fault)
1089 WARN("(%p): invalid pointer!\n", pAcl);
1096 /******************************************************************************
1097 * RtlGetAce [NTDLL.@]
1099 DWORD WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1103 TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1105 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1106 return STATUS_INVALID_PARAMETER;
1108 ace = (PACE_HEADER)(pAcl + 1);
1109 for (;dwAceIndex;dwAceIndex--)
1110 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1112 *pAce = (LPVOID) ace;
1114 return STATUS_SUCCESS;
1121 /******************************************************************************
1122 * RtlAdjustPrivilege [NTDLL.@]
1124 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4)
1126 FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
1130 /******************************************************************************
1131 * RtlImpersonateSelf [NTDLL.@]
1134 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1136 FIXME("(%08x), stub\n", ImpersonationLevel);
1140 /******************************************************************************
1141 * NtAccessCheck [NTDLL.@]
1142 * ZwAccessCheck [NTDLL.@]
1146 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1147 IN HANDLE ClientToken,
1148 IN ACCESS_MASK DesiredAccess,
1149 IN PGENERIC_MAPPING GenericMapping,
1150 OUT PPRIVILEGE_SET PrivilegeSet,
1151 OUT PULONG ReturnLength,
1152 OUT PULONG GrantedAccess,
1153 OUT PBOOLEAN AccessStatus)
1155 FIXME("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1156 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1157 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1158 *AccessStatus = TRUE;
1159 return STATUS_SUCCESS;
1162 /******************************************************************************
1163 * NtSetSecurityObject [NTDLL.@]
1166 NtSetSecurityObject(
1168 IN SECURITY_INFORMATION SecurityInformation,
1169 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1171 FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1172 return STATUS_SUCCESS;
1175 /******************************************************************************
1176 * RtlGetControlSecurityDescriptor (NTDLL.@)
1179 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1180 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1181 PSECURITY_DESCRIPTOR_CONTROL pControl,
1182 LPDWORD lpdwRevision)
1184 FIXME("(%p,%p,%p),stub!\n",pSecurityDescriptor,pControl,lpdwRevision);
1185 return STATUS_SUCCESS;
1188 /******************************************************************************
1189 * RtlConvertSidToUnicodeString (NTDLL.@)
1191 * The returned SID is used to access the USER registry hive usually
1193 * the native function returns something like
1194 * "S-1-5-21-0000000000-000000000-0000000000-500";
1196 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1197 PUNICODE_STRING String,
1199 BOOLEAN AllocateString)
1201 const char *user = wine_get_user_name();
1202 int len = ntdll_umbstowcs( 0, user, strlen(user)+1, NULL, 0 ) * sizeof(WCHAR);
1204 FIXME("(%p %p %u)\n", String, Sid, AllocateString);
1206 String->Length = len - sizeof(WCHAR);
1209 String->MaximumLength = len;
1210 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1211 return STATUS_NO_MEMORY;
1213 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1215 ntdll_umbstowcs( 0, user, strlen(user)+1, String->Buffer, len/sizeof(WCHAR) );
1216 return STATUS_SUCCESS;
1219 /******************************************************************************
1220 * RtlQueryInformationAcl (NTDLL.@)
1222 NTSTATUS WINAPI RtlQueryInformationAcl(
1224 LPVOID pAclInformation,
1225 DWORD nAclInformationLength,
1226 ACL_INFORMATION_CLASS dwAclInformationClass)
1228 NTSTATUS status = STATUS_SUCCESS;
1230 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1231 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1233 switch (dwAclInformationClass)
1235 case AclRevisionInformation:
1237 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1239 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1240 status = STATUS_INVALID_PARAMETER;
1242 paclrev->AclRevision = pAcl->AclRevision;
1247 case AclSizeInformation:
1249 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1251 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1252 status = STATUS_INVALID_PARAMETER;
1258 paclsize->AceCount = pAcl->AceCount;
1260 paclsize->AclBytesInUse = 0;
1261 ace = (PACE_HEADER) (pAcl + 1);
1263 for (i = 0; i < pAcl->AceCount; i++)
1265 paclsize->AclBytesInUse += ace->AceSize;
1266 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1269 if (pAcl->AclSize < paclsize->AclBytesInUse)
1271 WARN("Acl has %ld bytes free\n", pAcl->AclSize - paclsize->AclBytesInUse);
1272 paclsize->AclBytesFree = 0;
1273 paclsize->AclBytesInUse = pAcl->AclSize;
1276 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1283 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1284 status = STATUS_INVALID_PARAMETER;