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
;
835 /**************************************************************************
836 * RtlAbsoluteToSelfRelativeSD [NTDLL.@]
838 NTSTATUS WINAPI
RtlAbsoluteToSelfRelativeSD(
839 PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor
,
840 PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor
,
843 FIXME("%p %p %p\n", AbsoluteSecurityDescriptor
,
844 SelfRelativeSecurityDescriptor
, BufferLength
);
845 return STATUS_NOT_IMPLEMENTED
;
850 * access control list's
853 /**************************************************************************
854 * RtlCreateAcl [NTDLL.@]
857 * This should return NTSTATUS
859 NTSTATUS WINAPI
RtlCreateAcl(PACL acl
,DWORD size
,DWORD rev
)
861 TRACE("%p 0x%08lx 0x%08lx\n", acl
, size
, rev
);
863 if (rev
!=ACL_REVISION
)
864 return STATUS_INVALID_PARAMETER
;
865 if (size
<sizeof(ACL
))
866 return STATUS_BUFFER_TOO_SMALL
;
868 return STATUS_INVALID_PARAMETER
;
870 memset(acl
,'\0',sizeof(ACL
));
871 acl
->AclRevision
= rev
;
874 return STATUS_SUCCESS
;
877 /**************************************************************************
878 * RtlFirstFreeAce [NTDLL.@]
879 * looks for the AceCount+1 ACE, and if it is still within the alloced
880 * ACL, return a pointer to it
882 BOOLEAN WINAPI
RtlFirstFreeAce(
890 ace
= (PACE_HEADER
)(acl
+1);
891 for (i
=0;i
<acl
->AceCount
;i
++) {
892 if ((DWORD
)ace
>=(((DWORD
)acl
)+acl
->AclSize
))
894 ace
= (PACE_HEADER
)(((BYTE
*)ace
)+ace
->AceSize
);
896 if ((DWORD
)ace
>=(((DWORD
)acl
)+acl
->AclSize
))
902 /**************************************************************************
903 * RtlAddAce [NTDLL.@]
905 NTSTATUS WINAPI
RtlAddAce(
909 PACE_HEADER acestart
,
912 PACE_HEADER ace
,targetace
;
915 if (acl
->AclRevision
!= ACL_REVISION
)
916 return STATUS_INVALID_PARAMETER
;
917 if (!RtlFirstFreeAce(acl
,&targetace
))
918 return STATUS_INVALID_PARAMETER
;
919 nrofaces
=0;ace
=acestart
;
920 while (((DWORD
)ace
-(DWORD
)acestart
)<acelen
) {
922 ace
= (PACE_HEADER
)(((BYTE
*)ace
)+ace
->AceSize
);
924 if ((DWORD
)targetace
+acelen
>(DWORD
)acl
+acl
->AclSize
) /* too much aces */
925 return STATUS_INVALID_PARAMETER
;
926 memcpy((LPBYTE
)targetace
,acestart
,acelen
);
927 acl
->AceCount
+=nrofaces
;
928 return STATUS_SUCCESS
;
931 /**************************************************************************
932 * RtlDeleteAce [NTDLL.@]
934 NTSTATUS WINAPI
RtlDeleteAce(PACL pAcl
, DWORD dwAceIndex
)
939 status
= RtlGetAce(pAcl
,dwAceIndex
,(LPVOID
*)&pAce
);
941 if (STATUS_SUCCESS
== status
)
946 pcAce
= (PACE_HEADER
)(((BYTE
*)pAce
)+pAce
->AceSize
);
947 for (; dwAceIndex
< pAcl
->AceCount
; dwAceIndex
++)
949 len
+= pcAce
->AceSize
;
950 pcAce
= (PACE_HEADER
)(((BYTE
*)pcAce
) + pcAce
->AceSize
);
953 memcpy(pAce
, ((BYTE
*)pAce
)+pAce
->AceSize
, len
);
957 TRACE("pAcl=%p dwAceIndex=%ld status=0x%08lx\n", pAcl
, dwAceIndex
, status
);
962 /******************************************************************************
963 * RtlAddAccessAllowedAce [NTDLL.@]
965 NTSTATUS WINAPI
RtlAddAccessAllowedAce(
967 IN DWORD dwAceRevision
,
971 return RtlAddAccessAllowedAceEx( pAcl
, dwAceRevision
, 0, AccessMask
, pSid
);
974 /******************************************************************************
975 * RtlAddAccessAllowedAceEx [NTDLL.@]
977 NTSTATUS WINAPI
RtlAddAccessAllowedAceEx(
979 IN DWORD dwAceRevision
,
985 ACCESS_ALLOWED_ACE
* pAaAce
;
988 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
989 pAcl
, dwAceRevision
, AccessMask
, pSid
);
991 if (!RtlValidSid(pSid
))
992 return STATUS_INVALID_SID
;
993 if (!RtlValidAcl(pAcl
))
994 return STATUS_INVALID_ACL
;
996 dwLengthSid
= RtlLengthSid(pSid
);
997 if (!RtlFirstFreeAce(pAcl
, (PACE_HEADER
*) &pAaAce
))
998 return STATUS_INVALID_ACL
;
1001 return STATUS_ALLOTTED_SPACE_EXCEEDED
;
1003 dwSpaceLeft
= (DWORD
)pAcl
+ pAcl
->AclSize
- (DWORD
)pAaAce
;
1004 if (dwSpaceLeft
< sizeof(*pAaAce
) - sizeof(pAaAce
->SidStart
) + dwLengthSid
)
1005 return STATUS_ALLOTTED_SPACE_EXCEEDED
;
1007 pAaAce
->Header
.AceType
= ACCESS_ALLOWED_ACE_TYPE
;
1008 pAaAce
->Header
.AceFlags
= AceFlags
;
1009 pAaAce
->Header
.AceSize
= sizeof(*pAaAce
) - sizeof(pAaAce
->SidStart
) + dwLengthSid
;
1010 pAaAce
->Mask
= AccessMask
;
1012 RtlCopySid(dwLengthSid
, (PSID
)&pAaAce
->SidStart
, pSid
);
1013 return STATUS_SUCCESS
;
1016 /******************************************************************************
1017 * RtlAddAccessDeniedAce [NTDLL.@]
1019 NTSTATUS WINAPI
RtlAddAccessDeniedAce(
1021 IN DWORD dwAceRevision
,
1022 IN DWORD AccessMask
,
1025 return RtlAddAccessDeniedAceEx( pAcl
, dwAceRevision
, 0, AccessMask
, pSid
);
1028 /******************************************************************************
1029 * RtlAddAccessDeniedAceEx [NTDLL.@]
1031 NTSTATUS WINAPI
RtlAddAccessDeniedAceEx(
1033 IN DWORD dwAceRevision
,
1035 IN DWORD AccessMask
,
1040 ACCESS_DENIED_ACE
* pAdAce
;
1042 TRACE("(%p,0x%08lx,0x%08lx,%p)\n",
1043 pAcl
, dwAceRevision
, AccessMask
, pSid
);
1045 if (!RtlValidSid(pSid
))
1046 return STATUS_INVALID_SID
;
1047 if (!RtlValidAcl(pAcl
))
1048 return STATUS_INVALID_ACL
;
1050 dwLengthSid
= RtlLengthSid(pSid
);
1051 if (!RtlFirstFreeAce(pAcl
, (PACE_HEADER
*) &pAdAce
))
1052 return STATUS_INVALID_ACL
;
1055 return STATUS_ALLOTTED_SPACE_EXCEEDED
;
1057 dwSpaceLeft
= (DWORD
)pAcl
+ pAcl
->AclSize
- (DWORD
)pAdAce
;
1058 if (dwSpaceLeft
< sizeof(*pAdAce
) - sizeof(pAdAce
->SidStart
) + dwLengthSid
)
1059 return STATUS_ALLOTTED_SPACE_EXCEEDED
;
1061 pAdAce
->Header
.AceType
= ACCESS_DENIED_ACE_TYPE
;
1062 pAdAce
->Header
.AceFlags
= AceFlags
;
1063 pAdAce
->Header
.AceSize
= sizeof(*pAdAce
) - sizeof(pAdAce
->SidStart
) + dwLengthSid
;
1064 pAdAce
->Mask
= AccessMask
;
1066 RtlCopySid(dwLengthSid
, (PSID
)&pAdAce
->SidStart
, pSid
);
1067 return STATUS_SUCCESS
;
1070 /******************************************************************************
1071 * RtlValidAcl [NTDLL.@]
1073 BOOLEAN WINAPI
RtlValidAcl(PACL pAcl
)
1076 TRACE("(%p)\n", pAcl
);
1083 if (pAcl
->AclRevision
!= ACL_REVISION
)
1087 ace
= (PACE_HEADER
)(pAcl
+1);
1089 for (i
=0;i
<=pAcl
->AceCount
;i
++)
1091 if ((char *)ace
> (char *)pAcl
+ pAcl
->AclSize
)
1096 ace
= (PACE_HEADER
)(((BYTE
*)ace
)+ace
->AceSize
);
1100 __EXCEPT(page_fault
)
1102 WARN("(%p): invalid pointer!\n", pAcl
);
1109 /******************************************************************************
1110 * RtlGetAce [NTDLL.@]
1112 NTSTATUS WINAPI
RtlGetAce(PACL pAcl
,DWORD dwAceIndex
,LPVOID
*pAce
)
1116 TRACE("(%p,%ld,%p)\n",pAcl
,dwAceIndex
,pAce
);
1118 if ((dwAceIndex
< 0) || (dwAceIndex
> pAcl
->AceCount
))
1119 return STATUS_INVALID_PARAMETER
;
1121 ace
= (PACE_HEADER
)(pAcl
+ 1);
1122 for (;dwAceIndex
;dwAceIndex
--)
1123 ace
= (PACE_HEADER
)(((BYTE
*)ace
)+ace
->AceSize
);
1125 *pAce
= (LPVOID
) ace
;
1127 return STATUS_SUCCESS
;
1134 /******************************************************************************
1135 * RtlAdjustPrivilege [NTDLL.@]
1137 DWORD WINAPI
RtlAdjustPrivilege(DWORD x1
,DWORD x2
,DWORD x3
,DWORD x4
)
1139 FIXME("(0x%08lx,0x%08lx,0x%08lx,0x%08lx),stub!\n",x1
,x2
,x3
,x4
);
1143 /******************************************************************************
1144 * RtlImpersonateSelf [NTDLL.@]
1147 RtlImpersonateSelf(SECURITY_IMPERSONATION_LEVEL ImpersonationLevel
)
1149 FIXME("(%08x), stub\n", ImpersonationLevel
);
1153 /******************************************************************************
1154 * NtAccessCheck [NTDLL.@]
1155 * ZwAccessCheck [NTDLL.@]
1157 * Checks that a user represented by a token is allowed to access an object
1158 * represented by a security descriptor.
1161 * SecurityDescriptor [I] The security descriptor of the object to check.
1162 * ClientToken [I] Token of the user accessing the object.
1163 * DesiredAccess [I] The desired access to the object.
1164 * GenericMapping [I] Mapping used to transform access rights in the SD to their specific forms.
1165 * PrivilegeSet [I/O] Privileges used during the access check.
1166 * ReturnLength [O] Number of bytes stored into PrivilegeSet.
1167 * GrantedAccess [O] The actual access rights granted.
1168 * AccessStatus [O] The status of the access check.
1174 * DesiredAccess may be MAXIMUM_ALLOWED, in which case the function determines
1175 * the maximum access rights allowed by the SD and returns them in
1177 * The SecurityDescriptor must have a valid owner and groups present,
1178 * otherwise the function will fail.
1182 PSECURITY_DESCRIPTOR SecurityDescriptor
,
1184 ACCESS_MASK DesiredAccess
,
1185 PGENERIC_MAPPING GenericMapping
,
1186 PPRIVILEGE_SET PrivilegeSet
,
1187 PULONG ReturnLength
,
1188 PULONG GrantedAccess
,
1189 NTSTATUS
*AccessStatus
)
1193 TRACE("(%p, %p, %08lx, %p, %p, %p, %p, %p), stub\n",
1194 SecurityDescriptor
, ClientToken
, DesiredAccess
, GenericMapping
,
1195 PrivilegeSet
, ReturnLength
, GrantedAccess
, AccessStatus
);
1197 SERVER_START_REQ( access_check
)
1199 struct security_descriptor sd
;
1200 const SECURITY_DESCRIPTOR
* RealSD
= (const SECURITY_DESCRIPTOR
*)SecurityDescriptor
;
1202 req
->handle
= ClientToken
;
1203 req
->desired_access
= DesiredAccess
;
1204 req
->mapping_read
= GenericMapping
->GenericRead
;
1205 req
->mapping_write
= GenericMapping
->GenericWrite
;
1206 req
->mapping_execute
= GenericMapping
->GenericExecute
;
1207 req
->mapping_all
= GenericMapping
->GenericAll
;
1209 /* marshal security descriptor */
1210 sd
.control
= RealSD
->Control
;
1211 sd
.owner_len
= RtlLengthSid( RealSD
->Owner
);
1212 sd
.group_len
= RtlLengthSid( RealSD
->Group
);
1213 sd
.sacl_len
= (RealSD
->Sacl
? RealSD
->Sacl
->AclSize
: 0);
1214 sd
.dacl_len
= (RealSD
->Dacl
? RealSD
->Dacl
->AclSize
: 0);
1215 wine_server_add_data( req
, &sd
, sizeof(sd
) );
1216 wine_server_add_data( req
, RealSD
->Owner
, sd
.owner_len
);
1217 wine_server_add_data( req
, RealSD
->Group
, sd
.group_len
);
1218 wine_server_add_data( req
, RealSD
->Sacl
, sd
.sacl_len
);
1219 wine_server_add_data( req
, RealSD
->Dacl
, sd
.dacl_len
);
1221 wine_server_set_reply( req
, &PrivilegeSet
->Privilege
, *ReturnLength
- FIELD_OFFSET( PRIVILEGE_SET
, Privilege
) );
1223 status
= wine_server_call( req
);
1225 *ReturnLength
= FIELD_OFFSET( PRIVILEGE_SET
, Privilege
) + reply
->privileges_len
;
1226 PrivilegeSet
->PrivilegeCount
= reply
->privileges_len
/ sizeof(LUID_AND_ATTRIBUTES
);
1228 if (status
== STATUS_SUCCESS
)
1229 *AccessStatus
= reply
->access_status
;
1230 *GrantedAccess
= reply
->access_granted
;
1237 /******************************************************************************
1238 * NtSetSecurityObject [NTDLL.@]
1241 NtSetSecurityObject(
1243 IN SECURITY_INFORMATION SecurityInformation
,
1244 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
1246 FIXME("%p 0x%08lx %p\n", Handle
, SecurityInformation
, SecurityDescriptor
);
1247 return STATUS_SUCCESS
;
1250 /******************************************************************************
1251 * RtlGetControlSecurityDescriptor (NTDLL.@)
1254 NTSTATUS WINAPI
RtlGetControlSecurityDescriptor(
1255 PSECURITY_DESCRIPTOR pSecurityDescriptor
,
1256 PSECURITY_DESCRIPTOR_CONTROL pControl
,
1257 LPDWORD lpdwRevision
)
1259 FIXME("(%p,%p,%p),stub!\n",pSecurityDescriptor
,pControl
,lpdwRevision
);
1260 return STATUS_SUCCESS
;
1263 /******************************************************************************
1264 * RtlConvertSidToUnicodeString (NTDLL.@)
1266 * The returned SID is used to access the USER registry hive usually
1268 * the native function returns something like
1269 * "S-1-5-21-0000000000-000000000-0000000000-500";
1271 NTSTATUS WINAPI
RtlConvertSidToUnicodeString(
1272 PUNICODE_STRING String
,
1274 BOOLEAN AllocateString
)
1276 const char *user
= wine_get_user_name();
1277 int len
= ntdll_umbstowcs( 0, user
, strlen(user
)+1, NULL
, 0 ) * sizeof(WCHAR
);
1279 FIXME("(%p %p %u)\n", String
, Sid
, AllocateString
);
1281 String
->Length
= len
- sizeof(WCHAR
);
1284 String
->MaximumLength
= len
;
1285 if (!(String
->Buffer
= RtlAllocateHeap( GetProcessHeap(), 0, len
)))
1286 return STATUS_NO_MEMORY
;
1288 else if (len
> String
->MaximumLength
) return STATUS_BUFFER_OVERFLOW
;
1290 ntdll_umbstowcs( 0, user
, strlen(user
)+1, String
->Buffer
, len
/sizeof(WCHAR
) );
1291 return STATUS_SUCCESS
;
1294 /******************************************************************************
1295 * RtlQueryInformationAcl (NTDLL.@)
1297 NTSTATUS WINAPI
RtlQueryInformationAcl(
1299 LPVOID pAclInformation
,
1300 DWORD nAclInformationLength
,
1301 ACL_INFORMATION_CLASS dwAclInformationClass
)
1303 NTSTATUS status
= STATUS_SUCCESS
;
1305 TRACE("pAcl=%p pAclInfo=%p len=%ld, class=%d\n",
1306 pAcl
, pAclInformation
, nAclInformationLength
, dwAclInformationClass
);
1308 switch (dwAclInformationClass
)
1310 case AclRevisionInformation
:
1312 PACL_REVISION_INFORMATION paclrev
= (PACL_REVISION_INFORMATION
) pAclInformation
;
1314 if (nAclInformationLength
< sizeof(ACL_REVISION_INFORMATION
))
1315 status
= STATUS_INVALID_PARAMETER
;
1317 paclrev
->AclRevision
= pAcl
->AclRevision
;
1322 case AclSizeInformation
:
1324 PACL_SIZE_INFORMATION paclsize
= (PACL_SIZE_INFORMATION
) pAclInformation
;
1326 if (nAclInformationLength
< sizeof(ACL_SIZE_INFORMATION
))
1327 status
= STATUS_INVALID_PARAMETER
;
1333 paclsize
->AceCount
= pAcl
->AceCount
;
1335 paclsize
->AclBytesInUse
= 0;
1336 ace
= (PACE_HEADER
) (pAcl
+ 1);
1338 for (i
= 0; i
< pAcl
->AceCount
; i
++)
1340 paclsize
->AclBytesInUse
+= ace
->AceSize
;
1341 ace
= (PACE_HEADER
)(((BYTE
*)ace
)+ace
->AceSize
);
1344 if (pAcl
->AclSize
< paclsize
->AclBytesInUse
)
1346 WARN("Acl has %ld bytes free\n", paclsize
->AclBytesFree
);
1347 paclsize
->AclBytesFree
= 0;
1348 paclsize
->AclBytesInUse
= pAcl
->AclSize
;
1351 paclsize
->AclBytesFree
= pAcl
->AclSize
- paclsize
->AclBytesInUse
;
1358 WARN("Unknown AclInformationClass value: %d\n", dwAclInformationClass
);
1359 status
= STATUS_INVALID_PARAMETER
;