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 BOOLEAN 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))))
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 DWORD 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->Sacl != NULL )
412 Size += ((PACL)((LPBYTE)lpsd->Sacl + offset))->AclSize;
414 if ( lpsd->Dacl != NULL )
415 Size += ((PACL)((LPBYTE)lpsd->Dacl + offset))->AclSize;
420 /******************************************************************************
421 * RtlGetDaclSecurityDescriptor [NTDLL.@]
424 NTSTATUS WINAPI RtlGetDaclSecurityDescriptor(
425 IN PSECURITY_DESCRIPTOR pSecurityDescriptor,
426 OUT PBOOLEAN lpbDaclPresent,
428 OUT PBOOLEAN lpbDaclDefaulted)
430 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
432 TRACE("(%p,%p,%p,%p)\n",
433 pSecurityDescriptor, lpbDaclPresent, *pDacl, lpbDaclDefaulted);
435 if (lpsd->Revision != SECURITY_DESCRIPTOR_REVISION)
436 return STATUS_UNKNOWN_REVISION ;
438 if ( (*lpbDaclPresent = (SE_DACL_PRESENT & lpsd->Control) ? 1 : 0) )
440 if ( SE_SELF_RELATIVE & lpsd->Control)
441 { *pDacl = (PACL) ((LPBYTE)lpsd + (DWORD)lpsd->Dacl);
444 { *pDacl = lpsd->Dacl;
448 *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);
509 { *pSacl = lpsd->Sacl;
513 *lpbSaclDefaulted = (( SE_SACL_DEFAULTED & lpsd->Control ) ? 1 : 0);
515 return STATUS_SUCCESS;
518 /**************************************************************************
519 * RtlSetSaclSecurityDescriptor [NTDLL.@]
521 NTSTATUS WINAPI RtlSetSaclSecurityDescriptor (
522 PSECURITY_DESCRIPTOR pSecurityDescriptor,
525 BOOLEAN sacldefaulted)
527 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
529 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
530 return STATUS_UNKNOWN_REVISION;
531 if (lpsd->Control & SE_SELF_RELATIVE)
532 return STATUS_INVALID_SECURITY_DESCR;
534 lpsd->Control &= ~SE_SACL_PRESENT;
537 lpsd->Control |= SE_SACL_PRESENT;
540 lpsd->Control |= SE_SACL_DEFAULTED;
542 lpsd->Control &= ~SE_SACL_DEFAULTED;
543 return STATUS_SUCCESS;
546 /**************************************************************************
547 * RtlGetOwnerSecurityDescriptor [NTDLL.@]
549 NTSTATUS WINAPI RtlGetOwnerSecurityDescriptor(
550 PSECURITY_DESCRIPTOR pSecurityDescriptor,
552 PBOOLEAN OwnerDefaulted)
554 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
556 if ( !lpsd || !Owner || !OwnerDefaulted )
557 return STATUS_INVALID_PARAMETER;
559 if (lpsd->Owner != NULL)
561 if (lpsd->Control & SE_SELF_RELATIVE)
562 *Owner = (PSID)((LPBYTE)lpsd +
565 *Owner = lpsd->Owner;
567 if ( lpsd->Control & SE_OWNER_DEFAULTED )
568 *OwnerDefaulted = TRUE;
570 *OwnerDefaulted = FALSE;
575 return STATUS_SUCCESS;
578 /**************************************************************************
579 * RtlSetOwnerSecurityDescriptor [NTDLL.@]
581 NTSTATUS WINAPI RtlSetOwnerSecurityDescriptor(
582 PSECURITY_DESCRIPTOR pSecurityDescriptor,
584 BOOLEAN ownerdefaulted)
586 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
588 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
589 return STATUS_UNKNOWN_REVISION;
590 if (lpsd->Control & SE_SELF_RELATIVE)
591 return STATUS_INVALID_SECURITY_DESCR;
595 lpsd->Control |= SE_OWNER_DEFAULTED;
597 lpsd->Control &= ~SE_OWNER_DEFAULTED;
598 return STATUS_SUCCESS;
601 /**************************************************************************
602 * RtlSetGroupSecurityDescriptor [NTDLL.@]
604 NTSTATUS WINAPI RtlSetGroupSecurityDescriptor (
605 PSECURITY_DESCRIPTOR pSecurityDescriptor,
607 BOOLEAN groupdefaulted)
609 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
611 if (lpsd->Revision!=SECURITY_DESCRIPTOR_REVISION)
612 return STATUS_UNKNOWN_REVISION;
613 if (lpsd->Control & SE_SELF_RELATIVE)
614 return STATUS_INVALID_SECURITY_DESCR;
618 lpsd->Control |= SE_GROUP_DEFAULTED;
620 lpsd->Control &= ~SE_GROUP_DEFAULTED;
621 return STATUS_SUCCESS;
623 /**************************************************************************
624 * RtlGetGroupSecurityDescriptor [NTDLL.@]
626 NTSTATUS WINAPI RtlGetGroupSecurityDescriptor(
627 PSECURITY_DESCRIPTOR pSecurityDescriptor,
629 PBOOLEAN GroupDefaulted)
631 SECURITY_DESCRIPTOR* lpsd=pSecurityDescriptor;
633 if ( !lpsd || !Group || !GroupDefaulted )
634 return STATUS_INVALID_PARAMETER;
636 if (lpsd->Group != NULL)
638 if (lpsd->Control & SE_SELF_RELATIVE)
639 *Group = (PSID)((LPBYTE)lpsd +
642 *Group = lpsd->Group;
644 if ( lpsd->Control & SE_GROUP_DEFAULTED )
645 *GroupDefaulted = TRUE;
647 *GroupDefaulted = FALSE;
652 return STATUS_SUCCESS;
655 /**************************************************************************
656 * RtlMakeSelfRelativeSD [NTDLL.@]
658 NTSTATUS WINAPI RtlMakeSelfRelativeSD(
659 IN PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
660 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
661 IN OUT LPDWORD lpdwBufferLength)
665 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
666 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
668 TRACE(" %p %p %p(%ld)\n", pAbs, pRel, lpdwBufferLength,
669 lpdwBufferLength ? *lpdwBufferLength: -1);
671 if (!lpdwBufferLength || !pAbs)
672 return STATUS_INVALID_PARAMETER;
674 length = RtlLengthSecurityDescriptor(pAbs);
675 if (*lpdwBufferLength < length)
677 *lpdwBufferLength = length;
678 return STATUS_BUFFER_TOO_SMALL;
682 return STATUS_INVALID_PARAMETER;
684 if (pAbs->Control & SE_SELF_RELATIVE)
686 memcpy(pRel, pAbs, length);
687 return STATUS_SUCCESS;
690 pRel->Revision = pAbs->Revision;
691 pRel->Sbz1 = pAbs->Sbz1;
692 pRel->Control = pAbs->Control | SE_SELF_RELATIVE;
694 offsetRel = sizeof(SECURITY_DESCRIPTOR);
695 pRel->Owner = (PSID) offsetRel;
696 length = RtlLengthSid(pAbs->Owner);
697 memcpy((LPBYTE)pRel + offsetRel, pAbs->Owner, length);
700 pRel->Group = (PSID) offsetRel;
701 length = RtlLengthSid(pAbs->Group);
702 memcpy((LPBYTE)pRel + offsetRel, pAbs->Group, length);
704 if (pRel->Control & SE_SACL_PRESENT)
707 pRel->Sacl = (PACL) offsetRel;
708 length = pAbs->Sacl->AclSize;
709 memcpy((LPBYTE)pRel + offsetRel, pAbs->Sacl, length);
716 if (pRel->Control & SE_DACL_PRESENT)
719 pRel->Dacl = (PACL) offsetRel;
720 length = pAbs->Dacl->AclSize;
721 memcpy((LPBYTE)pRel + offsetRel, pAbs->Dacl, length);
728 return STATUS_SUCCESS;
732 /**************************************************************************
733 + * RtlSelfRelativeToAbsoluteSD [NTDLL.@]
735 NTSTATUS WINAPI RtlSelfRelativeToAbsoluteSD(
736 IN PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
737 OUT PSECURITY_DESCRIPTOR pAbsoluteSecurityDescriptor,
738 OUT LPDWORD lpdwAbsoluteSecurityDescriptorSize,
740 OUT LPDWORD lpdwDaclSize,
742 OUT LPDWORD lpdwSaclSize,
744 OUT LPDWORD lpdwOwnerSize,
745 OUT PSID pPrimaryGroup,
746 OUT LPDWORD lpdwPrimaryGroupSize)
748 NTSTATUS status = STATUS_SUCCESS;
749 SECURITY_DESCRIPTOR* pAbs = pAbsoluteSecurityDescriptor;
750 SECURITY_DESCRIPTOR* pRel = pSelfRelativeSecurityDescriptor;
753 !lpdwAbsoluteSecurityDescriptorSize ||
757 !lpdwPrimaryGroupSize ||
758 ~pRel->Control & SE_SELF_RELATIVE)
759 return STATUS_INVALID_PARAMETER;
761 /* Confirm buffers are sufficiently large */
762 if (*lpdwAbsoluteSecurityDescriptorSize < sizeof(SECURITY_DESCRIPTOR))
764 *lpdwAbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
765 status = STATUS_BUFFER_TOO_SMALL;
768 if (pRel->Control & SE_DACL_PRESENT &&
769 *lpdwDaclSize < ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize)
771 *lpdwDaclSize = ((PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel))->AclSize;
772 status = STATUS_BUFFER_TOO_SMALL;
775 if (pRel->Control & SE_SACL_PRESENT &&
776 *lpdwSaclSize < ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize)
778 *lpdwSaclSize = ((PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel))->AclSize;
779 status = STATUS_BUFFER_TOO_SMALL;
783 *lpdwOwnerSize < RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel)))
785 *lpdwOwnerSize = RtlLengthSid((PSID)((LPBYTE)pRel->Owner + (ULONG)pRel));
786 status = STATUS_BUFFER_TOO_SMALL;
790 *lpdwPrimaryGroupSize < RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel)))
792 *lpdwPrimaryGroupSize = RtlLengthSid((PSID)((LPBYTE)pRel->Group + (ULONG)pRel));
793 status = STATUS_BUFFER_TOO_SMALL;
796 if (status != STATUS_SUCCESS)
799 /* Copy structures */
800 pAbs->Revision = pRel->Revision;
801 pAbs->Control = pRel->Control & ~SE_SELF_RELATIVE;
803 if (pRel->Control & SE_SACL_PRESENT)
805 PACL pAcl = (PACL)((LPBYTE)pRel->Sacl + (ULONG)pRel);
807 memcpy(pSacl, pAcl, pAcl->AclSize);
811 if (pRel->Control & SE_DACL_PRESENT)
813 PACL pAcl = (PACL)((LPBYTE)pRel->Dacl + (ULONG)pRel);
814 memcpy(pDacl, pAcl, pAcl->AclSize);
820 PSID psid = (PSID)((LPBYTE)pRel->Owner + (ULONG)pRel);
821 memcpy(pOwner, psid, RtlLengthSid(psid));
822 pAbs->Owner = pOwner;
827 PSID psid = (PSID)((LPBYTE)pRel->Group + (ULONG)pRel);
828 memcpy(pPrimaryGroup, psid, RtlLengthSid(psid));
829 pAbs->Group = pPrimaryGroup;
836 * access control list's
839 /**************************************************************************
840 * RtlCreateAcl [NTDLL.@]
843 * This should return NTSTATUS
845 NTSTATUS WINAPI RtlCreateAcl(PACL acl,DWORD size,DWORD rev)
847 TRACE("%p 0x%08lx 0x%08lx\n", acl, size, rev);
849 if (rev!=ACL_REVISION)
850 return STATUS_INVALID_PARAMETER;
851 if (size<sizeof(ACL))
852 return STATUS_BUFFER_TOO_SMALL;
854 return STATUS_INVALID_PARAMETER;
856 memset(acl,'\0',sizeof(ACL));
857 acl->AclRevision = rev;
860 return STATUS_SUCCESS;
863 /**************************************************************************
864 * RtlFirstFreeAce [NTDLL.@]
865 * looks for the AceCount+1 ACE, and if it is still within the alloced
866 * ACL, return a pointer to it
868 BOOLEAN WINAPI RtlFirstFreeAce(
876 ace = (PACE_HEADER)(acl+1);
877 for (i=0;i<acl->AceCount;i++) {
878 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
880 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
882 if ((DWORD)ace>=(((DWORD)acl)+acl->AclSize))
888 /**************************************************************************
889 * RtlAddAce [NTDLL.@]
891 NTSTATUS WINAPI RtlAddAce(
895 PACE_HEADER acestart,
898 PACE_HEADER ace,targetace;
901 if (acl->AclRevision != ACL_REVISION)
902 return STATUS_INVALID_PARAMETER;
903 if (!RtlFirstFreeAce(acl,&targetace))
904 return STATUS_INVALID_PARAMETER;
905 nrofaces=0;ace=acestart;
906 while (((DWORD)ace-(DWORD)acestart)<acelen) {
908 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
910 if ((DWORD)targetace+acelen>(DWORD)acl+acl->AclSize) /* too much aces */
911 return STATUS_INVALID_PARAMETER;
912 memcpy((LPBYTE)targetace,acestart,acelen);
913 acl->AceCount+=nrofaces;
914 return STATUS_SUCCESS;
917 /**************************************************************************
918 * RtlDeleteAce [NTDLL.@]
920 NTSTATUS WINAPI RtlDeleteAce(PACL pAcl, DWORD dwAceIndex)
925 status = RtlGetAce(pAcl,dwAceIndex,(LPVOID*)&pAce);
927 if (STATUS_SUCCESS == status)
932 pcAce = (PACE_HEADER)(((BYTE*)pAce)+pAce->AceSize);
933 for (; dwAceIndex < pAcl->AceCount; dwAceIndex++)
935 len += pcAce->AceSize;
936 pcAce = (PACE_HEADER)(((BYTE*)pcAce) + pcAce->AceSize);
939 memcpy(pAce, ((BYTE*)pAce)+pAce->AceSize, len);
946 /******************************************************************************
947 * RtlAddAccessAllowedAce [NTDLL.@]
949 NTSTATUS WINAPI RtlAddAccessAllowedAce(
951 IN DWORD dwAceRevision,
955 return RtlAddAccessAllowedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
958 /******************************************************************************
959 * RtlAddAccessAllowedAceEx [NTDLL.@]
961 NTSTATUS WINAPI RtlAddAccessAllowedAceEx(
963 IN DWORD dwAceRevision,
969 ACCESS_ALLOWED_ACE * pAaAce;
972 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
973 pAcl, dwAceRevision, AccessMask, pSid);
975 if (!RtlValidSid(pSid))
976 return STATUS_INVALID_SID;
977 if (!RtlValidAcl(pAcl))
978 return STATUS_INVALID_ACL;
980 dwLengthSid = RtlLengthSid(pSid);
981 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAaAce))
982 return STATUS_INVALID_ACL;
985 return STATUS_ALLOTTED_SPACE_EXCEEDED;
987 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAaAce;
988 if (dwSpaceLeft < sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid)
989 return STATUS_ALLOTTED_SPACE_EXCEEDED;
991 pAaAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
992 pAaAce->Header.AceFlags = AceFlags;
993 pAaAce->Header.AceSize = sizeof(*pAaAce) - sizeof(pAaAce->SidStart) + dwLengthSid;
994 pAaAce->Mask = AccessMask;
996 RtlCopySid(dwLengthSid, (PSID)&pAaAce->SidStart, pSid);
997 return STATUS_SUCCESS;
1000 /******************************************************************************
1001 * RtlAddAccessDeniedAce [NTDLL.@]
1003 NTSTATUS WINAPI RtlAddAccessDeniedAce(
1005 IN DWORD dwAceRevision,
1006 IN DWORD AccessMask,
1009 return RtlAddAccessDeniedAceEx( pAcl, dwAceRevision, 0, AccessMask, pSid);
1012 /******************************************************************************
1013 * RtlAddAccessDeniedAceEx [NTDLL.@]
1015 NTSTATUS WINAPI RtlAddAccessDeniedAceEx(
1017 IN DWORD dwAceRevision,
1019 IN DWORD AccessMask,
1024 ACCESS_DENIED_ACE * pAdAce;
1026 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1027 pAcl, dwAceRevision, AccessMask, pSid);
1029 if (!RtlValidSid(pSid))
1030 return STATUS_INVALID_SID;
1031 if (!RtlValidAcl(pAcl))
1032 return STATUS_INVALID_ACL;
1034 dwLengthSid = RtlLengthSid(pSid);
1035 if (!RtlFirstFreeAce(pAcl, (PACE_HEADER *) &pAdAce))
1036 return STATUS_INVALID_ACL;
1039 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1041 dwSpaceLeft = (DWORD)pAcl + pAcl->AclSize - (DWORD)pAdAce;
1042 if (dwSpaceLeft < sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid)
1043 return STATUS_ALLOTTED_SPACE_EXCEEDED;
1045 pAdAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
1046 pAdAce->Header.AceFlags = AceFlags;
1047 pAdAce->Header.AceSize = sizeof(*pAdAce) - sizeof(pAdAce->SidStart) + dwLengthSid;
1048 pAdAce->Mask = AccessMask;
1050 RtlCopySid(dwLengthSid, (PSID)&pAdAce->SidStart, pSid);
1051 return STATUS_SUCCESS;
1054 /******************************************************************************
1055 * RtlValidAcl [NTDLL.@]
1057 BOOLEAN WINAPI RtlValidAcl(PACL pAcl)
1060 TRACE("(%p)\n", pAcl);
1067 if (pAcl->AclRevision != ACL_REVISION)
1071 ace = (PACE_HEADER)(pAcl+1);
1073 for (i=0;i<=pAcl->AceCount;i++)
1075 if ((char *)ace > (char *)pAcl + pAcl->AclSize)
1080 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1084 __EXCEPT(page_fault)
1086 WARN("(%p): invalid pointer!\n", pAcl);
1093 /******************************************************************************
1094 * RtlGetAce [NTDLL.@]
1096 DWORD WINAPI RtlGetAce(PACL pAcl,DWORD dwAceIndex,LPVOID *pAce )
1100 TRACE("(%p,%ld,%p)\n",pAcl,dwAceIndex,pAce);
1102 if ((dwAceIndex < 0) || (dwAceIndex > pAcl->AceCount))
1103 return STATUS_INVALID_PARAMETER;
1105 ace = (PACE_HEADER)(pAcl + 1);
1106 for (;dwAceIndex;dwAceIndex--)
1107 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1109 *pAce = (LPVOID) ace;
1111 return STATUS_SUCCESS;
1118 /******************************************************************************
1119 * RtlAdjustPrivilege [NTDLL.@]
1121 DWORD WINAPI RtlAdjustPrivilege(DWORD x1,DWORD x2,DWORD x3,DWORD x4)
1123 FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1,x2,x3,x4);
1127 /******************************************************************************
1128 * RtlImpersonateSelf [NTDLL.@]
1131 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel)
1133 FIXME("(%08x), stub\n", ImpersonationLevel);
1137 /******************************************************************************
1138 * NtAccessCheck [NTDLL.@]
1139 * ZwAccessCheck [NTDLL.@]
1143 IN PSECURITY_DESCRIPTOR SecurityDescriptor,
1144 IN HANDLE ClientToken,
1145 IN ACCESS_MASK DesiredAccess,
1146 IN PGENERIC_MAPPING GenericMapping,
1147 OUT PPRIVILEGE_SET PrivilegeSet,
1148 OUT PULONG ReturnLength,
1149 OUT PULONG GrantedAccess,
1150 OUT PBOOLEAN AccessStatus)
1152 FIXME("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1153 SecurityDescriptor, ClientToken, DesiredAccess, GenericMapping,
1154 PrivilegeSet, ReturnLength, GrantedAccess, AccessStatus);
1155 *AccessStatus = TRUE;
1156 return STATUS_SUCCESS;
1159 /******************************************************************************
1160 * NtSetSecurityObject [NTDLL.@]
1163 NtSetSecurityObject(
1165 IN SECURITY_INFORMATION SecurityInformation,
1166 IN PSECURITY_DESCRIPTOR SecurityDescriptor)
1168 FIXME("%p 0x%08lx %p\n", Handle, SecurityInformation, SecurityDescriptor);
1169 return STATUS_SUCCESS;
1172 /******************************************************************************
1173 * RtlGetControlSecurityDescriptor (NTDLL.@)
1176 NTSTATUS WINAPI RtlGetControlSecurityDescriptor(
1177 PSECURITY_DESCRIPTOR pSecurityDescriptor,
1178 PSECURITY_DESCRIPTOR_CONTROL pControl,
1179 LPDWORD lpdwRevision)
1181 FIXME("(%p,%p,%p),stub!\n",pSecurityDescriptor,pControl,lpdwRevision);
1182 return STATUS_SUCCESS;
1185 /******************************************************************************
1186 * RtlConvertSidToUnicodeString (NTDLL.@)
1188 * The returned SID is used to access the USER registry hive usually
1190 * the native function returns something like
1191 * "S-1-5-21-0000000000-000000000-0000000000-500";
1193 NTSTATUS WINAPI RtlConvertSidToUnicodeString(
1194 PUNICODE_STRING String,
1196 BOOLEAN AllocateString)
1198 const char *user = wine_get_user_name();
1199 int len = ntdll_umbstowcs( 0, user, strlen(user)+1, NULL, 0 ) * sizeof(WCHAR);
1201 FIXME("(%p %p %u)\n", String, Sid, AllocateString);
1203 String->Length = len - sizeof(WCHAR);
1206 String->MaximumLength = len;
1207 if (!(String->Buffer = RtlAllocateHeap( GetProcessHeap(), 0, len )))
1208 return STATUS_NO_MEMORY;
1210 else if (len > String->MaximumLength) return STATUS_BUFFER_OVERFLOW;
1212 ntdll_umbstowcs( 0, user, strlen(user)+1, String->Buffer, len/sizeof(WCHAR) );
1213 return STATUS_SUCCESS;
1216 /******************************************************************************
1217 * RtlQueryInformationAcl (NTDLL.@)
1219 NTSTATUS WINAPI RtlQueryInformationAcl(
1221 LPVOID pAclInformation,
1222 DWORD nAclInformationLength,
1223 ACL_INFORMATION_CLASS dwAclInformationClass)
1225 NTSTATUS status = STATUS_SUCCESS;
1227 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1228 pAcl, pAclInformation, nAclInformationLength, dwAclInformationClass);
1230 switch (dwAclInformationClass)
1232 case AclRevisionInformation:
1234 PACL_REVISION_INFORMATION paclrev = (PACL_REVISION_INFORMATION) pAclInformation;
1236 if (nAclInformationLength < sizeof(ACL_REVISION_INFORMATION))
1237 status = STATUS_INVALID_PARAMETER;
1239 paclrev->AclRevision = pAcl->AclRevision;
1244 case AclSizeInformation:
1246 PACL_SIZE_INFORMATION paclsize = (PACL_SIZE_INFORMATION) pAclInformation;
1248 if (nAclInformationLength < sizeof(ACL_SIZE_INFORMATION))
1249 status = STATUS_INVALID_PARAMETER;
1255 paclsize->AceCount = pAcl->AceCount;
1257 paclsize->AclBytesInUse = 0;
1258 ace = (PACE_HEADER) (pAcl + 1);
1260 for (i = 0; i < pAcl->AceCount; i++)
1262 paclsize->AclBytesInUse += ace->AceSize;
1263 ace = (PACE_HEADER)(((BYTE*)ace)+ace->AceSize);
1266 if (pAcl->AclSize < paclsize->AclBytesInUse)
1268 WARN("Acl has %ld bytes free\n", pAcl->AclSize - paclsize->AclBytesInUse);
1269 paclsize->AclBytesFree = 0;
1270 paclsize->AclBytesInUse = pAcl->AclSize;
1273 paclsize->AclBytesFree = pAcl->AclSize - paclsize->AclBytesInUse;
1280 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass);
1281 status = STATUS_INVALID_PARAMETER;