[NTOS]
[reactos.git] / reactos / ntoskrnl / se / accesschk.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/se/accesschk.c
5 * PURPOSE: Security manager
6 *
7 * PROGRAMMERS: No programmer listed.
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #include <ntoskrnl.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 /* GLOBALS ********************************************************************/
17
18
19 /* PRIVATE FUNCTIONS **********************************************************/
20
21 /*
22 * FIXME: Incomplete!
23 */
24 BOOLEAN NTAPI
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)
37 {
38 ACCESS_MASK RemainingAccess;
39 ACCESS_MASK TempAccess;
40 ACCESS_MASK TempGrantedAccess = 0;
41 ACCESS_MASK TempDeniedAccess = 0;
42 PACCESS_TOKEN Token;
43 ULONG i, ResultListLength;
44 PACL Dacl;
45 BOOLEAN Present;
46 BOOLEAN Defaulted;
47 PACE CurrentAce;
48 PSID Sid;
49 NTSTATUS Status;
50 PAGED_CODE();
51
52 DPRINT("SepAccessCheck()\n");
53
54 /* Check for no access desired */
55 if (!DesiredAccess)
56 {
57 /* Check if we had no previous access */
58 if (!PreviouslyGrantedAccess)
59 {
60 /* Then there's nothing to give */
61 Status = STATUS_ACCESS_DENIED;
62 goto ReturnCommonStatus;
63 }
64
65 /* Return the previous access only */
66 Status = STATUS_SUCCESS;
67 *Privileges = NULL;
68 goto ReturnCommonStatus;
69 }
70
71 /* Map given accesses */
72 RtlMapGenericMask(&DesiredAccess, GenericMapping);
73 if (PreviouslyGrantedAccess)
74 RtlMapGenericMask(&PreviouslyGrantedAccess, GenericMapping);
75
76 /* Initialize remaining access rights */
77 RemainingAccess = DesiredAccess;
78
79 Token = SubjectSecurityContext->ClientToken ?
80 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
81
82 /* Check for ACCESS_SYSTEM_SECURITY and WRITE_OWNER access */
83 Status = SePrivilegePolicyCheck(&RemainingAccess,
84 &PreviouslyGrantedAccess,
85 NULL,
86 Token,
87 NULL,
88 UserMode);
89 if (!NT_SUCCESS(Status))
90 {
91 goto ReturnCommonStatus;
92 }
93
94 /* Succeed if there are no more rights to grant */
95 if (RemainingAccess == 0)
96 {
97 Status = STATUS_SUCCESS;
98 goto ReturnCommonStatus;
99 }
100
101 /* Get the DACL */
102 Status = RtlGetDaclSecurityDescriptor(SecurityDescriptor,
103 &Present,
104 &Dacl,
105 &Defaulted);
106 if (!NT_SUCCESS(Status))
107 {
108 goto ReturnCommonStatus;
109 }
110
111 /* RULE 1: Grant desired access if the object is unprotected */
112 if (Present == FALSE || Dacl == NULL)
113 {
114 PreviouslyGrantedAccess |= RemainingAccess;
115 if (RemainingAccess & MAXIMUM_ALLOWED)
116 {
117 PreviouslyGrantedAccess &= ~MAXIMUM_ALLOWED;
118 PreviouslyGrantedAccess |= GenericMapping->GenericAll;
119 }
120
121 Status = STATUS_SUCCESS;
122 goto ReturnCommonStatus;
123 }
124
125 /* Deny access if the DACL is empty */
126 if (Dacl->AceCount == 0)
127 {
128 if (RemainingAccess == MAXIMUM_ALLOWED && PreviouslyGrantedAccess != 0)
129 {
130 Status = STATUS_SUCCESS;
131 }
132 else
133 {
134 PreviouslyGrantedAccess = 0;
135 Status = STATUS_ACCESS_DENIED;
136 }
137 goto ReturnCommonStatus;
138 }
139
140 /* Determine the MAXIMUM_ALLOWED access rights according to the DACL */
141 if (DesiredAccess & MAXIMUM_ALLOWED)
142 {
143 CurrentAce = (PACE)(Dacl + 1);
144 for (i = 0; i < Dacl->AceCount; i++)
145 {
146 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
147 {
148 Sid = (PSID)(CurrentAce + 1);
149 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
150 {
151 if (SepSidInToken(Token, Sid))
152 {
153 /* Map access rights from the ACE */
154 TempAccess = CurrentAce->AccessMask;
155 RtlMapGenericMask(&TempAccess, GenericMapping);
156
157 /* Deny access rights that have not been granted yet */
158 TempDeniedAccess |= (TempAccess & ~TempGrantedAccess);
159 }
160 }
161 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
162 {
163 if (SepSidInToken(Token, Sid))
164 {
165 /* Map access rights from the ACE */
166 TempAccess = CurrentAce->AccessMask;
167 RtlMapGenericMask(&TempAccess, GenericMapping);
168
169 /* Grant access rights that have not been denied yet */
170 TempGrantedAccess |= (TempAccess & ~TempDeniedAccess);
171 }
172 }
173 else
174 {
175 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
176 }
177 }
178
179 /* Get the next ACE */
180 CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
181 }
182
183 /* Fail if some rights have not been granted */
184 RemainingAccess &= ~(MAXIMUM_ALLOWED | TempGrantedAccess);
185 if (RemainingAccess != 0)
186 {
187 PreviouslyGrantedAccess = 0;
188 Status = STATUS_ACCESS_DENIED;
189 goto ReturnCommonStatus;
190 }
191
192 /* Set granted access right and access status */
193 PreviouslyGrantedAccess |= TempGrantedAccess;
194 if (PreviouslyGrantedAccess != 0)
195 {
196 Status = STATUS_SUCCESS;
197 }
198 else
199 {
200 Status = STATUS_ACCESS_DENIED;
201 }
202 goto ReturnCommonStatus;
203 }
204
205 /* RULE 4: Grant rights according to the DACL */
206 CurrentAce = (PACE)(Dacl + 1);
207 for (i = 0; i < Dacl->AceCount; i++)
208 {
209 if (!(CurrentAce->Header.AceFlags & INHERIT_ONLY_ACE))
210 {
211 Sid = (PSID)(CurrentAce + 1);
212 if (CurrentAce->Header.AceType == ACCESS_DENIED_ACE_TYPE)
213 {
214 if (SepSidInToken(Token, Sid))
215 {
216 /* Map access rights from the ACE */
217 TempAccess = CurrentAce->AccessMask;
218 RtlMapGenericMask(&TempAccess, GenericMapping);
219
220 /* Leave if a remaining right must be denied */
221 if (RemainingAccess & TempAccess)
222 break;
223 }
224 }
225 else if (CurrentAce->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
226 {
227 if (SepSidInToken(Token, Sid))
228 {
229 /* Map access rights from the ACE */
230 TempAccess = CurrentAce->AccessMask;
231 DPRINT("TempAccess 0x%08lx\n", TempAccess);
232 RtlMapGenericMask(&TempAccess, GenericMapping);
233
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);
238 }
239 }
240 else
241 {
242 DPRINT1("Unsupported ACE type 0x%lx\n", CurrentAce->Header.AceType);
243 }
244 }
245
246 /* Get the next ACE */
247 CurrentAce = (PACE)((ULONG_PTR)CurrentAce + CurrentAce->Header.AceSize);
248 }
249
250 DPRINT("DesiredAccess %08lx\nPreviouslyGrantedAccess %08lx\nRemainingAccess %08lx\n",
251 DesiredAccess, PreviouslyGrantedAccess, RemainingAccess);
252
253 /* Fail if some rights have not been granted */
254 if (RemainingAccess != 0)
255 {
256 DPRINT("HACK: RemainingAccess = 0x%08lx DesiredAccess = 0x%08lx\n", RemainingAccess, DesiredAccess);
257 #if 0
258 /* HACK HACK HACK */
259 Status = STATUS_ACCESS_DENIED;
260 goto ReturnCommonStatus;
261 #endif
262 }
263
264 /* Set granted access rights */
265 PreviouslyGrantedAccess |= DesiredAccess;
266
267 /* Fail if no rights have been granted */
268 if (PreviouslyGrantedAccess == 0)
269 {
270 DPRINT1("PreviouslyGrantedAccess == 0 DesiredAccess = %08lx\n", DesiredAccess);
271 Status = STATUS_ACCESS_DENIED;
272 goto ReturnCommonStatus;
273 }
274
275 Status = STATUS_SUCCESS;
276 goto ReturnCommonStatus;
277
278 ReturnCommonStatus:
279 ResultListLength = UseResultList ? ObjectTypeListLength : 1;
280 for (i = 0; i < ResultListLength; i++)
281 {
282 GrantedAccessList[i] = PreviouslyGrantedAccess;
283 AccessStatusList[i] = Status;
284 }
285
286 return NT_SUCCESS(Status);
287 }
288
289 static PSID
290 SepGetSDOwner(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
291 {
292 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
293 PSID Owner;
294
295 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
296 Owner = (PSID)((ULONG_PTR)SecurityDescriptor->Owner +
297 (ULONG_PTR)SecurityDescriptor);
298 else
299 Owner = (PSID)SecurityDescriptor->Owner;
300
301 return Owner;
302 }
303
304 static PSID
305 SepGetSDGroup(IN PSECURITY_DESCRIPTOR _SecurityDescriptor)
306 {
307 PISECURITY_DESCRIPTOR SecurityDescriptor = _SecurityDescriptor;
308 PSID Group;
309
310 if (SecurityDescriptor->Control & SE_SELF_RELATIVE)
311 Group = (PSID)((ULONG_PTR)SecurityDescriptor->Group +
312 (ULONG_PTR)SecurityDescriptor);
313 else
314 Group = (PSID)SecurityDescriptor->Group;
315
316 return Group;
317 }
318
319
320 /* PUBLIC FUNCTIONS ***********************************************************/
321
322 /*
323 * @implemented
324 */
325 BOOLEAN
326 NTAPI
327 SeAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
328 IN PSECURITY_SUBJECT_CONTEXT SubjectSecurityContext,
329 IN BOOLEAN SubjectContextLocked,
330 IN ACCESS_MASK DesiredAccess,
331 IN ACCESS_MASK PreviouslyGrantedAccess,
332 OUT PPRIVILEGE_SET* Privileges,
333 IN PGENERIC_MAPPING GenericMapping,
334 IN KPROCESSOR_MODE AccessMode,
335 OUT PACCESS_MASK GrantedAccess,
336 OUT PNTSTATUS AccessStatus)
337 {
338 BOOLEAN ret;
339
340 PAGED_CODE();
341
342 /* Check if this is kernel mode */
343 if (AccessMode == KernelMode)
344 {
345 /* Check if kernel wants everything */
346 if (DesiredAccess & MAXIMUM_ALLOWED)
347 {
348 /* Give it */
349 *GrantedAccess = GenericMapping->GenericAll;
350 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
351 *GrantedAccess |= PreviouslyGrantedAccess;
352 }
353 else
354 {
355 /* Give the desired and previous access */
356 *GrantedAccess = DesiredAccess | PreviouslyGrantedAccess;
357 }
358
359 /* Success */
360 *AccessStatus = STATUS_SUCCESS;
361 return TRUE;
362 }
363
364 /* Check if we didn't get an SD */
365 if (!SecurityDescriptor)
366 {
367 /* Automatic failure */
368 *AccessStatus = STATUS_ACCESS_DENIED;
369 return FALSE;
370 }
371
372 /* Check for invalid impersonation */
373 if ((SubjectSecurityContext->ClientToken) &&
374 (SubjectSecurityContext->ImpersonationLevel < SecurityImpersonation))
375 {
376 *AccessStatus = STATUS_BAD_IMPERSONATION_LEVEL;
377 return FALSE;
378 }
379
380 /* Acquire the lock if needed */
381 if (!SubjectContextLocked)
382 SeLockSubjectContext(SubjectSecurityContext);
383
384 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
385 if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
386 {
387 PACCESS_TOKEN Token = SubjectSecurityContext->ClientToken ?
388 SubjectSecurityContext->ClientToken : SubjectSecurityContext->PrimaryToken;
389
390 if (SepTokenIsOwner(Token,
391 SecurityDescriptor,
392 FALSE))
393 {
394 if (DesiredAccess & MAXIMUM_ALLOWED)
395 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
396 else
397 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
398
399 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
400 }
401 }
402
403 if (DesiredAccess == 0)
404 {
405 *GrantedAccess = PreviouslyGrantedAccess;
406 if (PreviouslyGrantedAccess == 0)
407 {
408 DPRINT1("Request for zero access to an object. Denying.\n");
409 *AccessStatus = STATUS_ACCESS_DENIED;
410 ret = FALSE;
411 }
412 else
413 {
414 *AccessStatus = STATUS_SUCCESS;
415 ret = TRUE;
416 }
417 }
418 else
419 {
420 /* Call the internal function */
421 ret = SepAccessCheck(SecurityDescriptor,
422 SubjectSecurityContext,
423 DesiredAccess,
424 NULL,
425 0,
426 PreviouslyGrantedAccess,
427 Privileges,
428 GenericMapping,
429 AccessMode,
430 GrantedAccess,
431 AccessStatus,
432 FALSE);
433 }
434
435 /* Release the lock if needed */
436 if (!SubjectContextLocked)
437 SeUnlockSubjectContext(SubjectSecurityContext);
438
439 return ret;
440 }
441
442 /*
443 * @implemented
444 */
445 BOOLEAN
446 NTAPI
447 SeFastTraverseCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
448 IN PACCESS_STATE AccessState,
449 IN ACCESS_MASK DesiredAccess,
450 IN KPROCESSOR_MODE AccessMode)
451 {
452 PACL Dacl;
453 ULONG AceIndex;
454 PKNOWN_ACE Ace;
455
456 PAGED_CODE();
457
458 ASSERT(AccessMode != KernelMode);
459
460 if (SecurityDescriptor == NULL)
461 return FALSE;
462
463 /* Get DACL */
464 Dacl = SepGetDaclFromDescriptor(SecurityDescriptor);
465 /* If no DACL, grant access */
466 if (Dacl == NULL)
467 return TRUE;
468
469 /* No ACE -> Deny */
470 if (!Dacl->AceCount)
471 return FALSE;
472
473 /* Can't perform the check on restricted token */
474 if (AccessState->Flags & TOKEN_IS_RESTRICTED)
475 return FALSE;
476
477 /* Browse the ACEs */
478 for (AceIndex = 0, Ace = (PKNOWN_ACE)((ULONG_PTR)Dacl + sizeof(ACL));
479 AceIndex < Dacl->AceCount;
480 AceIndex++, Ace = (PKNOWN_ACE)((ULONG_PTR)Ace + Ace->Header.AceSize))
481 {
482 if (Ace->Header.AceFlags & INHERIT_ONLY_ACE)
483 continue;
484
485 /* If access-allowed ACE */
486 if (Ace->Header.AceType == ACCESS_ALLOWED_ACE_TYPE)
487 {
488 /* Check if all accesses are granted */
489 if (!(Ace->Mask & DesiredAccess))
490 continue;
491
492 /* Check SID and grant access if matching */
493 if (RtlEqualSid(SeWorldSid, &(Ace->SidStart)))
494 return TRUE;
495 }
496 /* If access-denied ACE */
497 else if (Ace->Header.AceType == ACCESS_DENIED_ACE_TYPE)
498 {
499 /* Here, only check if it denies any access wanted and deny if so */
500 if (Ace->Mask & DesiredAccess)
501 return FALSE;
502 }
503 }
504
505 /* Faulty, deny */
506 return FALSE;
507 }
508
509 /* SYSTEM CALLS ***************************************************************/
510
511 /*
512 * @implemented
513 */
514 NTSTATUS
515 NTAPI
516 NtAccessCheck(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
517 IN HANDLE TokenHandle,
518 IN ACCESS_MASK DesiredAccess,
519 IN PGENERIC_MAPPING GenericMapping,
520 OUT PPRIVILEGE_SET PrivilegeSet OPTIONAL,
521 IN OUT PULONG PrivilegeSetLength,
522 OUT PACCESS_MASK GrantedAccess,
523 OUT PNTSTATUS AccessStatus)
524 {
525 PSECURITY_DESCRIPTOR CapturedSecurityDescriptor = NULL;
526 SECURITY_SUBJECT_CONTEXT SubjectSecurityContext;
527 KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
528 ACCESS_MASK PreviouslyGrantedAccess = 0;
529 PTOKEN Token;
530 NTSTATUS Status;
531 PAGED_CODE();
532
533 /* Check if this is kernel mode */
534 if (PreviousMode == KernelMode)
535 {
536 /* Check if kernel wants everything */
537 if (DesiredAccess & MAXIMUM_ALLOWED)
538 {
539 /* Give it */
540 *GrantedAccess = GenericMapping->GenericAll;
541 *GrantedAccess |= (DesiredAccess &~ MAXIMUM_ALLOWED);
542 }
543 else
544 {
545 /* Just give the desired access */
546 *GrantedAccess = DesiredAccess;
547 }
548
549 /* Success */
550 *AccessStatus = STATUS_SUCCESS;
551 return STATUS_SUCCESS;
552 }
553
554 /* Protect probe in SEH */
555 _SEH2_TRY
556 {
557 /* Probe all pointers */
558 ProbeForRead(GenericMapping, sizeof(GENERIC_MAPPING), sizeof(ULONG));
559 ProbeForRead(PrivilegeSetLength, sizeof(ULONG), sizeof(ULONG));
560 ProbeForWrite(PrivilegeSet, *PrivilegeSetLength, sizeof(ULONG));
561 ProbeForWrite(GrantedAccess, sizeof(ACCESS_MASK), sizeof(ULONG));
562 ProbeForWrite(AccessStatus, sizeof(NTSTATUS), sizeof(ULONG));
563
564 /* Initialize the privilege set */
565 PrivilegeSet->PrivilegeCount = 0;
566 }
567 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
568 {
569 /* Return the exception code */
570 _SEH2_YIELD(return _SEH2_GetExceptionCode());
571 }
572 _SEH2_END;
573
574 /* Check for unmapped access rights */
575 if (DesiredAccess & (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL))
576 return STATUS_GENERIC_NOT_MAPPED;
577
578 /* Reference the token */
579 Status = ObReferenceObjectByHandle(TokenHandle,
580 TOKEN_QUERY,
581 SeTokenObjectType,
582 PreviousMode,
583 (PVOID*)&Token,
584 NULL);
585 if (!NT_SUCCESS(Status))
586 {
587 DPRINT("Failed to reference token (Status %lx)\n", Status);
588 return Status;
589 }
590
591 /* Check token type */
592 if (Token->TokenType != TokenImpersonation)
593 {
594 DPRINT("No impersonation token\n");
595 ObDereferenceObject(Token);
596 return STATUS_NO_IMPERSONATION_TOKEN;
597 }
598
599 /* Check the impersonation level */
600 if (Token->ImpersonationLevel < SecurityIdentification)
601 {
602 DPRINT("Impersonation level < SecurityIdentification\n");
603 ObDereferenceObject(Token);
604 return STATUS_BAD_IMPERSONATION_LEVEL;
605 }
606
607 /* Capture the security descriptor */
608 Status = SeCaptureSecurityDescriptor(SecurityDescriptor,
609 PreviousMode,
610 PagedPool,
611 FALSE,
612 &CapturedSecurityDescriptor);
613 if (!NT_SUCCESS(Status))
614 {
615 DPRINT("Failed to capture the Security Descriptor\n");
616 ObDereferenceObject(Token);
617 return Status;
618 }
619
620 /* Check the captured security descriptor */
621 if (CapturedSecurityDescriptor == NULL)
622 {
623 DPRINT("Security Descriptor is NULL\n");
624 ObDereferenceObject(Token);
625 return STATUS_INVALID_SECURITY_DESCR;
626 }
627
628 /* Check security descriptor for valid owner and group */
629 if (SepGetSDOwner(SecurityDescriptor) == NULL || // FIXME: use CapturedSecurityDescriptor
630 SepGetSDGroup(SecurityDescriptor) == NULL) // FIXME: use CapturedSecurityDescriptor
631 {
632 DPRINT("Security Descriptor does not have a valid group or owner\n");
633 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
634 PreviousMode,
635 FALSE);
636 ObDereferenceObject(Token);
637 return STATUS_INVALID_SECURITY_DESCR;
638 }
639
640 /* Set up the subject context, and lock it */
641 SeCaptureSubjectContext(&SubjectSecurityContext);
642
643 /* Lock the token */
644 SepAcquireTokenLockShared(Token);
645
646 /* Check if the token is the owner and grant WRITE_DAC and READ_CONTROL rights */
647 if (DesiredAccess & (WRITE_DAC | READ_CONTROL | MAXIMUM_ALLOWED))
648 {
649 if (SepTokenIsOwner(Token, SecurityDescriptor, FALSE)) // FIXME: use CapturedSecurityDescriptor
650 {
651 if (DesiredAccess & MAXIMUM_ALLOWED)
652 PreviouslyGrantedAccess |= (WRITE_DAC | READ_CONTROL);
653 else
654 PreviouslyGrantedAccess |= (DesiredAccess & (WRITE_DAC | READ_CONTROL));
655
656 DesiredAccess &= ~(WRITE_DAC | READ_CONTROL);
657 }
658 }
659
660 if (DesiredAccess == 0)
661 {
662 *GrantedAccess = PreviouslyGrantedAccess;
663 *AccessStatus = STATUS_SUCCESS;
664 }
665 else
666 {
667 /* Now perform the access check */
668 SepAccessCheck(SecurityDescriptor, // FIXME: use CapturedSecurityDescriptor
669 &SubjectSecurityContext,
670 DesiredAccess,
671 NULL,
672 0,
673 PreviouslyGrantedAccess,
674 &PrivilegeSet, //FIXME
675 GenericMapping,
676 PreviousMode,
677 GrantedAccess,
678 AccessStatus,
679 FALSE);
680 }
681
682 /* Release subject context and unlock the token */
683 SeReleaseSubjectContext(&SubjectSecurityContext);
684 SepReleaseTokenLock(Token);
685
686 /* Release the captured security descriptor */
687 SeReleaseSecurityDescriptor(CapturedSecurityDescriptor,
688 PreviousMode,
689 FALSE);
690
691 /* Dereference the token */
692 ObDereferenceObject(Token);
693
694 /* Check succeeded */
695 return STATUS_SUCCESS;
696 }
697
698
699 NTSTATUS
700 NTAPI
701 NtAccessCheckByType(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
702 IN PSID PrincipalSelfSid,
703 IN HANDLE ClientToken,
704 IN ACCESS_MASK DesiredAccess,
705 IN POBJECT_TYPE_LIST ObjectTypeList,
706 IN ULONG ObjectTypeLength,
707 IN PGENERIC_MAPPING GenericMapping,
708 IN PPRIVILEGE_SET PrivilegeSet,
709 IN OUT PULONG PrivilegeSetLength,
710 OUT PACCESS_MASK GrantedAccess,
711 OUT PNTSTATUS AccessStatus)
712 {
713 UNIMPLEMENTED;
714 return STATUS_NOT_IMPLEMENTED;
715 }
716
717 NTSTATUS
718 NTAPI
719 NtAccessCheckByTypeResultList(IN PSECURITY_DESCRIPTOR SecurityDescriptor,
720 IN PSID PrincipalSelfSid,
721 IN HANDLE ClientToken,
722 IN ACCESS_MASK DesiredAccess,
723 IN POBJECT_TYPE_LIST ObjectTypeList,
724 IN ULONG ObjectTypeLength,
725 IN PGENERIC_MAPPING GenericMapping,
726 IN PPRIVILEGE_SET PrivilegeSet,
727 IN OUT PULONG PrivilegeSetLength,
728 OUT PACCESS_MASK GrantedAccess,
729 OUT PNTSTATUS AccessStatus)
730 {
731 UNIMPLEMENTED;
732 return STATUS_NOT_IMPLEMENTED;
733 }
734
735 /* EOF */