2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/accesschk.c
5 * PURPOSE: Security manager
7 * PROGRAMMERS: No programmer listed.
10 /* INCLUDES *******************************************************************/
16 /* GLOBALS ********************************************************************/
19 /* PRIVATE FUNCTIONS **********************************************************/
25 SepAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
26 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
27 IN ACCESS_MASK DesiredAccess
,
28 IN POBJECT_TYPE_LIST ObjectTypeList
,
29 IN ULONG ObjectTypeListLength
,
30 IN ACCESS_MASK PreviouslyGrantedAccess
,
31 OUT PPRIVILEGE_SET
* Privileges
,
32 IN PGENERIC_MAPPING GenericMapping
,
33 IN KPROCESSOR_MODE AccessMode
,
34 OUT PACCESS_MASK GrantedAccessList
,
35 OUT PNTSTATUS AccessStatusList
,
36 IN BOOLEAN UseResultList
)
38 ACCESS_MASK RemainingAccess
;
39 ACCESS_MASK TempAccess
;
40 ACCESS_MASK TempGrantedAccess
= 0;
41 ACCESS_MASK TempDeniedAccess
= 0;
43 ULONG i
, ResultListLength
;
52 DPRINT("SepAccessCheck()\n");
54 /* Check for no access desired */
57 /* Check if we had no previous access */
58 if (!PreviouslyGrantedAccess
)
60 /* Then there's nothing to give */
61 Status
= STATUS_ACCESS_DENIED
;
62 goto ReturnCommonStatus
;
65 /* Return the previous access only */
66 Status
= STATUS_SUCCESS
;
68 goto ReturnCommonStatus
;
71 /* Map given accesses */
72 RtlMapGenericMask(&DesiredAccess
, GenericMapping
);
73 if (PreviouslyGrantedAccess
)
74 RtlMapGenericMask(&PreviouslyGrantedAccess
, GenericMapping
);
76 /* Initialize remaining access rights */
77 RemainingAccess
= DesiredAccess
;
79 Token
= SubjectSecurityContext
->ClientToken
?
80 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
82 /* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */
83 Status
= SePrivilegePolicyCheck(&RemainingAccess
,
84 &PreviouslyGrantedAccess
,
89 if (!NT_SUCCESS(Status
))
91 goto ReturnCommonStatus
;
94 /* Succeed if there are no more rights to grant */
95 if (RemainingAccess
== 0)
97 Status
= STATUS_SUCCESS
;
98 goto ReturnCommonStatus
;
102 Status
= RtlGetDaclSecurityDescriptor(SecurityDescriptor
,
106 if (!NT_SUCCESS(Status
))
108 goto ReturnCommonStatus
;
111 /* RULE 1: Grant desired access if the object is unprotected */
112 if (Present
== FALSE
|| Dacl
== NULL
)
114 PreviouslyGrantedAccess
|= RemainingAccess
;
115 if (RemainingAccess
& MAXIMUM_ALLOWED
)
117 PreviouslyGrantedAccess
&= ~MAXIMUM_ALLOWED
;
118 PreviouslyGrantedAccess
|= GenericMapping
->GenericAll
;
121 Status
= STATUS_SUCCESS
;
122 goto ReturnCommonStatus
;
125 /* Deny access if the DACL is empty */
126 if (Dacl
->AceCount
== 0)
128 if (RemainingAccess
== MAXIMUM_ALLOWED
&& PreviouslyGrantedAccess
!= 0)
130 Status
= STATUS_SUCCESS
;
134 PreviouslyGrantedAccess
= 0;
135 Status
= STATUS_ACCESS_DENIED
;
137 goto ReturnCommonStatus
;
140 /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
141 if (DesiredAccess
& MAXIMUM_ALLOWED
)
143 CurrentAce
= (PACE
)(Dacl
+ 1);
144 for (i
= 0; i
< Dacl
->AceCount
; i
++)
146 if (!(CurrentAce
->Header
.AceFlags
& INHERIT_ONLY_ACE
))
148 Sid
= (PSID
)(CurrentAce
+ 1);
149 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
151 if (SepSidInToken(Token
, Sid
))
153 /* Map access rights from the ACE */
154 TempAccess
= CurrentAce
->AccessMask
;
155 RtlMapGenericMask(&TempAccess
, GenericMapping
);
157 /* Deny access rights that have not been granted yet */
158 TempDeniedAccess
|= (TempAccess
& ~TempGrantedAccess
);
161 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
163 if (SepSidInToken(Token
, Sid
))
165 /* Map access rights from the ACE */
166 TempAccess
= CurrentAce
->AccessMask
;
167 RtlMapGenericMask(&TempAccess
, GenericMapping
);
169 /* Grant access rights that have not been denied yet */
170 TempGrantedAccess
|= (TempAccess
& ~TempDeniedAccess
);
175 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce
->Header
.AceType
);
179 /* Get the next ACE */
180 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
183 /* Fail if some rights have not been granted */
184 RemainingAccess
&= ~(MAXIMUM_ALLOWED
| TempGrantedAccess
);
185 if (RemainingAccess
!= 0)
187 PreviouslyGrantedAccess
= 0;
188 Status
= STATUS_ACCESS_DENIED
;
189 goto ReturnCommonStatus
;
192 /* Set granted access right and access status */
193 PreviouslyGrantedAccess
|= TempGrantedAccess
;
194 if (PreviouslyGrantedAccess
!= 0)
196 Status
= STATUS_SUCCESS
;
200 Status
= STATUS_ACCESS_DENIED
;
202 goto ReturnCommonStatus
;
205 /* RULE 4: Grant rights according to the DACL */
206 CurrentAce
= (PACE
)(Dacl
+ 1);
207 for (i
= 0; i
< Dacl
->AceCount
; i
++)
209 if (!(CurrentAce
->Header
.AceFlags
& INHERIT_ONLY_ACE
))
211 Sid
= (PSID
)(CurrentAce
+ 1);
212 if (CurrentAce
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
214 if (SepSidInToken(Token
, Sid
))
216 /* Map access rights from the ACE */
217 TempAccess
= CurrentAce
->AccessMask
;
218 RtlMapGenericMask(&TempAccess
, GenericMapping
);
220 /* Leave if a remaining right must be denied */
221 if (RemainingAccess
& TempAccess
)
225 else if (CurrentAce
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
227 if (SepSidInToken(Token
, Sid
))
229 /* Map access rights from the ACE */
230 TempAccess
= CurrentAce
->AccessMask
;
231 DPRINT("TempAccess 0x%08lx\n", TempAccess
);
232 RtlMapGenericMask(&TempAccess
, GenericMapping
);
234 /* Remove granted rights */
235 DPRINT("RemainingAccess 0x%08lx TempAccess 0x%08lx\n", RemainingAccess
, TempAccess
);
236 RemainingAccess
&= ~TempAccess
;
237 DPRINT("RemainingAccess 0x%08lx\n", RemainingAccess
);
242 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce
->Header
.AceType
);
246 /* Get the next ACE */
247 CurrentAce
= (PACE
)((ULONG_PTR
)CurrentAce
+ CurrentAce
->Header
.AceSize
);
250 DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
251 DesiredAccess
, PreviouslyGrantedAccess
, RemainingAccess
);
253 /* Fail if some rights have not been granted */
254 if (RemainingAccess
!= 0)
256 DPRINT("HACK: RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", RemainingAccess
, DesiredAccess
);
259 Status
= STATUS_ACCESS_DENIED
;
260 goto ReturnCommonStatus
;
264 /* Set granted access rights */
265 PreviouslyGrantedAccess
|= DesiredAccess
;
267 /* Fail if no rights have been granted */
268 if (PreviouslyGrantedAccess
== 0)
270 DPRINT1("PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n", DesiredAccess
);
271 Status
= STATUS_ACCESS_DENIED
;
272 goto ReturnCommonStatus
;
275 Status
= STATUS_SUCCESS
;
276 goto ReturnCommonStatus
;
279 ResultListLength
= UseResultList
? ObjectTypeListLength
: 1;
280 for (i
= 0; i
< ResultListLength
; i
++)
282 GrantedAccessList
[i
] = PreviouslyGrantedAccess
;
283 AccessStatusList
[i
] = Status
;
286 return NT_SUCCESS(Status
);
290 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
292 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
295 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
296 Owner
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Owner
+
297 (ULONG_PTR
)SecurityDescriptor
);
299 Owner
= (PSID
)SecurityDescriptor
->Owner
;
305 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor
)
307 PISECURITY_DESCRIPTOR SecurityDescriptor
= _SecurityDescriptor
;
310 if (SecurityDescriptor
->Control
& SE_SELF_RELATIVE
)
311 Group
= (PSID
)((ULONG_PTR
)SecurityDescriptor
->Group
+
312 (ULONG_PTR
)SecurityDescriptor
);
314 Group
= (PSID
)SecurityDescriptor
->Group
;
321 SepGetPrivilegeSetLength(IN PPRIVILEGE_SET PrivilegeSet
)
323 if (PrivilegeSet
== NULL
)
326 if (PrivilegeSet
->PrivilegeCount
== 0)
327 return (ULONG
)(sizeof(PRIVILEGE_SET
) - sizeof(LUID_AND_ATTRIBUTES
));
329 return (ULONG
)(sizeof(PRIVILEGE_SET
) +
330 (PrivilegeSet
->PrivilegeCount
- 1) * sizeof(LUID_AND_ATTRIBUTES
));
333 /* PUBLIC FUNCTIONS ***********************************************************/
340 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
341 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext
,
342 IN BOOLEAN SubjectContextLocked
,
343 IN ACCESS_MASK DesiredAccess
,
344 IN ACCESS_MASK PreviouslyGrantedAccess
,
345 OUT PPRIVILEGE_SET
* Privileges
,
346 IN PGENERIC_MAPPING GenericMapping
,
347 IN KPROCESSOR_MODE AccessMode
,
348 OUT PACCESS_MASK GrantedAccess
,
349 OUT PNTSTATUS AccessStatus
)
355 /* Check if this is kernel mode */
356 if (AccessMode
== KernelMode
)
358 /* Check if kernel wants everything */
359 if (DesiredAccess
& MAXIMUM_ALLOWED
)
362 *GrantedAccess
= GenericMapping
->GenericAll
;
363 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
364 *GrantedAccess
|= PreviouslyGrantedAccess
;
368 /* Give the desired and previous access */
369 *GrantedAccess
= DesiredAccess
| PreviouslyGrantedAccess
;
373 *AccessStatus
= STATUS_SUCCESS
;
377 /* Check if we didn't get an SD */
378 if (!SecurityDescriptor
)
380 /* Automatic failure */
381 *AccessStatus
= STATUS_ACCESS_DENIED
;
385 /* Check for invalid impersonation */
386 if ((SubjectSecurityContext
->ClientToken
) &&
387 (SubjectSecurityContext
->ImpersonationLevel
< SecurityImpersonation
))
389 *AccessStatus
= STATUS_BAD_IMPERSONATION_LEVEL
;
393 /* Acquire the lock if needed */
394 if (!SubjectContextLocked
)
395 SeLockSubjectContext(SubjectSecurityContext
);
397 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
398 if (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
| MAXIMUM_ALLOWED
))
400 PACCESS_TOKEN Token
= SubjectSecurityContext
->ClientToken
?
401 SubjectSecurityContext
->ClientToken
: SubjectSecurityContext
->PrimaryToken
;
403 if (SepTokenIsOwner(Token
,
407 if (DesiredAccess
& MAXIMUM_ALLOWED
)
408 PreviouslyGrantedAccess
|= (WRITE_DAC
| READ_CONTROL
);
410 PreviouslyGrantedAccess
|= (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
));
412 DesiredAccess
&= ~(WRITE_DAC
| READ_CONTROL
);
416 if (DesiredAccess
== 0)
418 *GrantedAccess
= PreviouslyGrantedAccess
;
419 if (PreviouslyGrantedAccess
== 0)
421 DPRINT1("Request for zero access to an object. Denying.\n");
422 *AccessStatus
= STATUS_ACCESS_DENIED
;
427 *AccessStatus
= STATUS_SUCCESS
;
433 /* Call the internal function */
434 ret
= SepAccessCheck(SecurityDescriptor
,
435 SubjectSecurityContext
,
439 PreviouslyGrantedAccess
,
448 /* Release the lock if needed */
449 if (!SubjectContextLocked
)
450 SeUnlockSubjectContext(SubjectSecurityContext
);
460 SeFastTraverseCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
461 IN PACCESS_STATE AccessState
,
462 IN ACCESS_MASK DesiredAccess
,
463 IN KPROCESSOR_MODE AccessMode
)
471 ASSERT(AccessMode
!= KernelMode
);
473 if (SecurityDescriptor
== NULL
)
477 Dacl
= SepGetDaclFromDescriptor(SecurityDescriptor
);
478 /* If no DACL, grant access */
486 /* Can't perform the check on restricted token */
487 if (AccessState
->Flags
& TOKEN_IS_RESTRICTED
)
490 /* Browse the ACEs */
491 for (AceIndex
= 0, Ace
= (PKNOWN_ACE
)((ULONG_PTR
)Dacl
+ sizeof(ACL
));
492 AceIndex
< Dacl
->AceCount
;
493 AceIndex
++, Ace
= (PKNOWN_ACE
)((ULONG_PTR
)Ace
+ Ace
->Header
.AceSize
))
495 if (Ace
->Header
.AceFlags
& INHERIT_ONLY_ACE
)
498 /* If access-allowed ACE */
499 if (Ace
->Header
.AceType
== ACCESS_ALLOWED_ACE_TYPE
)
501 /* Check if all accesses are granted */
502 if (!(Ace
->Mask
& DesiredAccess
))
505 /* Check SID and grant access if matching */
506 if (RtlEqualSid(SeWorldSid
, &(Ace
->SidStart
)))
509 /* If access-denied ACE */
510 else if (Ace
->Header
.AceType
== ACCESS_DENIED_ACE_TYPE
)
512 /* Here, only check if it denies any access wanted and deny if so */
513 if (Ace
->Mask
& DesiredAccess
)
522 /* SYSTEM CALLS ***************************************************************/
529 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
530 IN HANDLE TokenHandle
,
531 IN ACCESS_MASK DesiredAccess
,
532 IN PGENERIC_MAPPING GenericMapping
,
533 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL
,
534 IN OUT PULONG PrivilegeSetLength
,
535 OUT PACCESS_MASK GrantedAccess
,
536 OUT PNTSTATUS AccessStatus
)
538 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor
= NULL
;
539 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext
;
540 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
541 ACCESS_MASK PreviouslyGrantedAccess
= 0;
542 PPRIVILEGE_SET Privileges
= NULL
;
543 ULONG CapturedPrivilegeSetLength
, RequiredPrivilegeSetLength
;
548 /* Check if this is kernel mode */
549 if (PreviousMode
== KernelMode
)
551 /* Check if kernel wants everything */
552 if (DesiredAccess
& MAXIMUM_ALLOWED
)
555 *GrantedAccess
= GenericMapping
->GenericAll
;
556 *GrantedAccess
|= (DesiredAccess
&~ MAXIMUM_ALLOWED
);
560 /* Just give the desired access */
561 *GrantedAccess
= DesiredAccess
;
565 *AccessStatus
= STATUS_SUCCESS
;
566 return STATUS_SUCCESS
;
569 /* Protect probe in SEH */
572 /* Probe all pointers */
573 ProbeForRead(GenericMapping
, sizeof(GENERIC_MAPPING
), sizeof(ULONG
));
574 ProbeForRead(PrivilegeSetLength
, sizeof(ULONG
), sizeof(ULONG
));
575 ProbeForWrite(PrivilegeSet
, *PrivilegeSetLength
, sizeof(ULONG
));
576 ProbeForWrite(GrantedAccess
, sizeof(ACCESS_MASK
), sizeof(ULONG
));
577 ProbeForWrite(AccessStatus
, sizeof(NTSTATUS
), sizeof(ULONG
));
579 /* Capture the privilege set length and the mapping */
580 CapturedPrivilegeSetLength
= *PrivilegeSetLength
;
582 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
584 /* Return the exception code */
585 _SEH2_YIELD(return _SEH2_GetExceptionCode());
589 /* Check for unmapped access rights */
590 if (DesiredAccess
& (GENERIC_READ
| GENERIC_WRITE
| GENERIC_EXECUTE
| GENERIC_ALL
))
591 return STATUS_GENERIC_NOT_MAPPED
;
593 /* Reference the token */
594 Status
= ObReferenceObjectByHandle(TokenHandle
,
600 if (!NT_SUCCESS(Status
))
602 DPRINT("Failed to reference token (Status %lx)\n", Status
);
606 /* Check token type */
607 if (Token
->TokenType
!= TokenImpersonation
)
609 DPRINT("No impersonation token\n");
610 ObDereferenceObject(Token
);
611 return STATUS_NO_IMPERSONATION_TOKEN
;
614 /* Check the impersonation level */
615 if (Token
->ImpersonationLevel
< SecurityIdentification
)
617 DPRINT("Impersonation level < SecurityIdentification\n");
618 ObDereferenceObject(Token
);
619 return STATUS_BAD_IMPERSONATION_LEVEL
;
622 /* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */
623 Status
= SePrivilegePolicyCheck(&DesiredAccess
,
624 &PreviouslyGrantedAccess
,
629 if (!NT_SUCCESS(Status
))
631 DPRINT("SePrivilegePolicyCheck failed (Status 0x%08lx)\n", Status
);
632 ObDereferenceObject(Token
);
633 *AccessStatus
= Status
;
635 return STATUS_SUCCESS
;
638 /* Check the size of the privilege set and return the privileges */
639 if (Privileges
!= NULL
)
641 DPRINT("Privileges != NULL\n");
643 /* Calculate the required privilege set buffer size */
644 RequiredPrivilegeSetLength
= SepGetPrivilegeSetLength(Privileges
);
646 /* Fail if the privilege set buffer is too small */
647 if (CapturedPrivilegeSetLength
< RequiredPrivilegeSetLength
)
649 ObDereferenceObject(Token
);
650 SeFreePrivileges(Privileges
);
651 *PrivilegeSetLength
= RequiredPrivilegeSetLength
;
652 return STATUS_BUFFER_TOO_SMALL
;
655 /* Copy the privilege set to the caller */
656 RtlCopyMemory(PrivilegeSet
,
658 RequiredPrivilegeSetLength
);
660 /* Free the local privilege set */
661 SeFreePrivileges(Privileges
);
665 DPRINT("Privileges == NULL\n");
667 /* Fail if the privilege set buffer is too small */
668 if (CapturedPrivilegeSetLength
< sizeof(PRIVILEGE_SET
))
670 ObDereferenceObject(Token
);
671 *PrivilegeSetLength
= sizeof(PRIVILEGE_SET
);
672 return STATUS_BUFFER_TOO_SMALL
;
675 /* Initialize the privilege set */
676 PrivilegeSet
->PrivilegeCount
= 0;
677 PrivilegeSet
->Control
= 0;
680 /* Capture the security descriptor */
681 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
685 &CapturedSecurityDescriptor
);
686 if (!NT_SUCCESS(Status
))
688 DPRINT("Failed to capture the Security Descriptor\n");
689 ObDereferenceObject(Token
);
693 /* Check the captured security descriptor */
694 if (CapturedSecurityDescriptor
== NULL
)
696 DPRINT("Security Descriptor is NULL\n");
697 ObDereferenceObject(Token
);
698 return STATUS_INVALID_SECURITY_DESCR
;
701 /* Check security descriptor for valid owner and group */
702 if (SepGetSDOwner(SecurityDescriptor
) == NULL
|| // FIXME: use CapturedSecurityDescriptor
703 SepGetSDGroup(SecurityDescriptor
) == NULL
) // FIXME: use CapturedSecurityDescriptor
705 DPRINT("Security Descriptor does not have a valid group or owner\n");
706 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
,
709 ObDereferenceObject(Token
);
710 return STATUS_INVALID_SECURITY_DESCR
;
713 /* Set up the subject context, and lock it */
714 SeCaptureSubjectContext(&SubjectSecurityContext
);
717 SepAcquireTokenLockShared(Token
);
719 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
720 if (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
| MAXIMUM_ALLOWED
))
722 if (SepTokenIsOwner(Token
, SecurityDescriptor
, FALSE
)) // FIXME: use CapturedSecurityDescriptor
724 if (DesiredAccess
& MAXIMUM_ALLOWED
)
725 PreviouslyGrantedAccess
|= (WRITE_DAC
| READ_CONTROL
);
727 PreviouslyGrantedAccess
|= (DesiredAccess
& (WRITE_DAC
| READ_CONTROL
));
729 DesiredAccess
&= ~(WRITE_DAC
| READ_CONTROL
);
733 if (DesiredAccess
== 0)
735 *GrantedAccess
= PreviouslyGrantedAccess
;
736 *AccessStatus
= STATUS_SUCCESS
;
740 /* Now perform the access check */
741 SepAccessCheck(SecurityDescriptor
, // FIXME: use CapturedSecurityDescriptor
742 &SubjectSecurityContext
,
746 PreviouslyGrantedAccess
,
747 &PrivilegeSet
, //FIXME
755 /* Release subject context and unlock the token */
756 SeReleaseSubjectContext(&SubjectSecurityContext
);
757 SepReleaseTokenLock(Token
);
759 /* Release the captured security descriptor */
760 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor
,
764 /* Dereference the token */
765 ObDereferenceObject(Token
);
767 /* Check succeeded */
768 return STATUS_SUCCESS
;
774 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
775 IN PSID PrincipalSelfSid
,
776 IN HANDLE ClientToken
,
777 IN ACCESS_MASK DesiredAccess
,
778 IN POBJECT_TYPE_LIST ObjectTypeList
,
779 IN ULONG ObjectTypeLength
,
780 IN PGENERIC_MAPPING GenericMapping
,
781 IN PPRIVILEGE_SET PrivilegeSet
,
782 IN OUT PULONG PrivilegeSetLength
,
783 OUT PACCESS_MASK GrantedAccess
,
784 OUT PNTSTATUS AccessStatus
)
787 return STATUS_NOT_IMPLEMENTED
;
792 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
793 IN PSID PrincipalSelfSid
,
794 IN HANDLE ClientToken
,
795 IN ACCESS_MASK DesiredAccess
,
796 IN POBJECT_TYPE_LIST ObjectTypeList
,
797 IN ULONG ObjectTypeLength
,
798 IN PGENERIC_MAPPING GenericMapping
,
799 IN PPRIVILEGE_SET PrivilegeSet
,
800 IN OUT PULONG PrivilegeSetLength
,
801 OUT PACCESS_MASK GrantedAccess
,
802 OUT PNTSTATUS AccessStatus
)
805 return STATUS_NOT_IMPLEMENTED
;