2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ob/obsecure.c
5 * PURPOSE: SRM Interface of the Object Manager
6 * PROGRAMMERS: Alex Ionescu (alex@relsoft.net)
10 /* INCLUDES *****************************************************************/
16 /* PRIVATE FUNCTIONS *********************************************************/
20 ObAssignObjectSecurityDescriptor(IN PVOID Object
,
21 IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL
,
22 IN POOL_TYPE PoolType
)
24 POBJECT_HEADER ObjectHeader
;
26 PSECURITY_DESCRIPTOR NewSd
;
30 /* Get the object header */
31 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
32 FastRef
= (PEX_FAST_REF
)&ObjectHeader
->SecurityDescriptor
;
33 if (!SecurityDescriptor
)
35 /* Nothing to assign */
36 ExInitializeFastReference(FastRef
, NULL
);
37 return STATUS_SUCCESS
;
40 /* Add it to our internal cache */
41 Status
= ObLogSecurityDescriptor(SecurityDescriptor
,
44 if (NT_SUCCESS(Status
))
46 /* Free the old copy */
47 ExFreePoolWithTag(SecurityDescriptor
, TAG_SD
);
49 /* Set the new pointer */
51 ExInitializeFastReference(FastRef
, NewSd
);
60 ObDeassignSecurity(IN OUT PSECURITY_DESCRIPTOR
*SecurityDescriptor
)
64 PSECURITY_DESCRIPTOR OldSecurityDescriptor
;
66 /* Get the fast reference and capture it */
67 FastRef
= *(PEX_FAST_REF
)SecurityDescriptor
;
69 /* Don't free again later */
70 *SecurityDescriptor
= NULL
;
72 /* Get the descriptor and reference count */
73 OldSecurityDescriptor
= ExGetObjectFastReference(FastRef
);
74 Count
= ExGetCountFastReference(FastRef
);
76 /* Dereference the descriptor */
77 ObDereferenceSecurityDescriptor(OldSecurityDescriptor
, Count
+ 1);
80 return STATUS_SUCCESS
;
85 ObQuerySecurityDescriptorInfo(IN PVOID Object
,
86 IN PSECURITY_INFORMATION SecurityInformation
,
87 OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
89 IN PSECURITY_DESCRIPTOR
*OutputSecurityDescriptor
)
91 POBJECT_HEADER ObjectHeader
;
93 PSECURITY_DESCRIPTOR ObjectSd
;
96 /* Get the object header */
97 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
100 ObjectSd
= ObpReferenceSecurityDescriptor(ObjectHeader
);
102 /* Query the information */
103 Status
= SeQuerySecurityDescriptorInfo(SecurityInformation
,
108 /* Check if we have an object SD and dereference it, if so */
109 if (ObjectSd
) ObDereferenceSecurityDescriptor(ObjectSd
, 1);
117 ObSetSecurityDescriptorInfo(IN PVOID Object
,
118 IN PSECURITY_INFORMATION SecurityInformation
,
119 IN OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
120 IN OUT PSECURITY_DESCRIPTOR
*OutputSecurityDescriptor
,
121 IN POOL_TYPE PoolType
,
122 IN PGENERIC_MAPPING GenericMapping
)
125 POBJECT_HEADER ObjectHeader
;
126 PSECURITY_DESCRIPTOR OldDescriptor
, NewDescriptor
, CachedDescriptor
;
127 PEX_FAST_REF FastRef
;
128 EX_FAST_REF OldValue
;
132 /* Get the object header */
133 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
136 /* Reference the old descriptor */
137 OldDescriptor
= ObpReferenceSecurityDescriptor(ObjectHeader
);
138 NewDescriptor
= OldDescriptor
;
140 /* Set the SD information */
141 Status
= SeSetSecurityDescriptorInfo(Object
,
147 if (NT_SUCCESS(Status
))
149 /* Now add this to the cache */
150 Status
= ObLogSecurityDescriptor(NewDescriptor
,
154 /* Let go of our uncached copy */
155 ExFreePool(NewDescriptor
);
157 /* Check for success */
158 if (NT_SUCCESS(Status
))
161 FastRef
= (PEX_FAST_REF
)OutputSecurityDescriptor
;
162 OldValue
= ExCompareSwapFastReference(FastRef
,
166 /* Get the security descriptor */
167 SecurityDescriptor
= ExGetObjectFastReference(OldValue
);
168 Count
= ExGetCountFastReference(OldValue
);
170 /* Make sure the swap worked */
171 if (SecurityDescriptor
== OldDescriptor
)
174 ObpAcquireObjectLock(ObjectHeader
);
175 ObpReleaseObjectLock(ObjectHeader
);
177 /* And dereference the old one */
178 ObDereferenceSecurityDescriptor(OldDescriptor
, Count
+ 2);
183 /* Someone changed it behind our back -- try again */
184 ObDereferenceSecurityDescriptor(OldDescriptor
, 1);
185 ObDereferenceSecurityDescriptor(CachedDescriptor
,
191 /* We failed, dereference the old one */
192 ObDereferenceSecurityDescriptor(OldDescriptor
, 1);
198 /* We failed, dereference the old one */
199 if (OldDescriptor
) ObDereferenceSecurityDescriptor(OldDescriptor
, 1);
210 ObCheckCreateObjectAccess(IN PVOID Object
,
211 IN ACCESS_MASK CreateAccess
,
212 IN PACCESS_STATE AccessState
,
213 IN PUNICODE_STRING ComponentName
,
215 IN KPROCESSOR_MODE AccessMode
,
216 OUT PNTSTATUS AccessStatus
)
218 POBJECT_HEADER ObjectHeader
;
219 POBJECT_TYPE ObjectType
;
220 PSECURITY_DESCRIPTOR SecurityDescriptor
;
222 BOOLEAN Result
= TRUE
;
223 ACCESS_MASK GrantedAccess
= 0;
224 PPRIVILEGE_SET Privileges
= NULL
;
228 /* Get the header and type */
229 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
230 ObjectType
= ObjectHeader
->Type
;
232 /* Get the security descriptor */
233 Status
= ObGetObjectSecurity(Object
, &SecurityDescriptor
, &SdAllocated
);
234 if (!NT_SUCCESS(Status
))
237 *AccessStatus
= Status
;
241 /* Lock the security context */
242 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
244 /* Check if we have an SD */
245 if (SecurityDescriptor
)
247 /* Now do the entire access check */
248 Result
= SeAccessCheck(SecurityDescriptor
,
249 &AccessState
->SubjectSecurityContext
,
254 &ObjectType
->TypeInfo
.GenericMapping
,
260 /* We got privileges, append them to the access state and free them */
261 Status
= SeAppendPrivileges(AccessState
, Privileges
);
262 SeFreePrivileges(Privileges
);
266 /* We're done, unlock the context and release security */
267 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
268 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
274 ObpCheckTraverseAccess(IN PVOID Object
,
275 IN ACCESS_MASK TraverseAccess
,
276 IN PACCESS_STATE AccessState OPTIONAL
,
278 IN KPROCESSOR_MODE AccessMode
,
279 OUT PNTSTATUS AccessStatus
)
281 POBJECT_HEADER ObjectHeader
;
282 POBJECT_TYPE ObjectType
;
283 PSECURITY_DESCRIPTOR SecurityDescriptor
;
286 ACCESS_MASK GrantedAccess
= 0;
287 PPRIVILEGE_SET Privileges
= NULL
;
291 /* Get the header and type */
292 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
293 ObjectType
= ObjectHeader
->Type
;
295 /* Get the security descriptor */
296 Status
= ObGetObjectSecurity(Object
, &SecurityDescriptor
, &SdAllocated
);
297 if (!NT_SUCCESS(Status
))
300 *AccessStatus
= Status
;
304 /* Lock the security context */
305 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
307 /* Now do the entire access check */
308 Result
= SeAccessCheck(SecurityDescriptor
,
309 &AccessState
->SubjectSecurityContext
,
314 &ObjectType
->TypeInfo
.GenericMapping
,
320 /* We got privileges, append them to the access state and free them */
321 Status
= SeAppendPrivileges(AccessState
, Privileges
);
322 SeFreePrivileges(Privileges
);
325 /* We're done, unlock the context and release security */
326 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
327 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
333 ObpCheckObjectReference(IN PVOID Object
,
334 IN OUT PACCESS_STATE AccessState
,
336 IN KPROCESSOR_MODE AccessMode
,
337 OUT PNTSTATUS AccessStatus
)
339 POBJECT_HEADER ObjectHeader
;
340 POBJECT_TYPE ObjectType
;
341 PSECURITY_DESCRIPTOR SecurityDescriptor
;
344 ACCESS_MASK GrantedAccess
= 0;
345 PPRIVILEGE_SET Privileges
= NULL
;
349 /* Get the header and type */
350 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
351 ObjectType
= ObjectHeader
->Type
;
353 /* Get the security descriptor */
354 Status
= ObGetObjectSecurity(Object
, &SecurityDescriptor
, &SdAllocated
);
355 if (!NT_SUCCESS(Status
))
358 *AccessStatus
= Status
;
362 /* Lock the security context */
363 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
365 /* Now do the entire access check */
366 Result
= SeAccessCheck(SecurityDescriptor
,
367 &AccessState
->SubjectSecurityContext
,
369 AccessState
->RemainingDesiredAccess
,
370 AccessState
->PreviouslyGrantedAccess
,
372 &ObjectType
->TypeInfo
.GenericMapping
,
378 /* Update the access state */
379 AccessState
->RemainingDesiredAccess
&= ~GrantedAccess
;
380 AccessState
->PreviouslyGrantedAccess
|= GrantedAccess
;
383 /* Check if we have an SD */
384 if (SecurityDescriptor
)
388 SeObjectReferenceAuditAlarm(&AccessState
->OperationID
,
391 &AccessState
->SubjectSecurityContext
,
392 AccessState
->RemainingDesiredAccess
|
393 AccessState
->PreviouslyGrantedAccess
,
394 ((PAUX_ACCESS_DATA
)(AccessState
->AuxData
))->
401 /* We're done, unlock the context and release security */
402 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
403 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
408 * @name ObCheckObjectAccess
410 * The ObCheckObjectAccess routine <FILLMEIN>
424 * @param ReturnedStatus
427 * @return TRUE if access was granted, FALSE otherwise.
434 ObCheckObjectAccess(IN PVOID Object
,
435 IN OUT PACCESS_STATE AccessState
,
437 IN KPROCESSOR_MODE AccessMode
,
438 OUT PNTSTATUS ReturnedStatus
)
440 POBJECT_HEADER ObjectHeader
;
441 POBJECT_TYPE ObjectType
;
442 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
446 ACCESS_MASK GrantedAccess
;
447 PPRIVILEGE_SET Privileges
= NULL
;
450 /* Get the object header and type */
451 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
452 ObjectType
= ObjectHeader
->Type
;
454 /* Get security information */
455 Status
= ObGetObjectSecurity(Object
, &SecurityDescriptor
, &SdAllocated
);
456 if (!NT_SUCCESS(Status
))
459 *ReturnedStatus
= Status
;
462 else if (!SecurityDescriptor
)
464 /* Otherwise, if we don't actually have an SD, return success */
465 *ReturnedStatus
= Status
;
469 /* Lock the security context */
470 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
472 /* Now do the entire access check */
473 Result
= SeAccessCheck(SecurityDescriptor
,
474 &AccessState
->SubjectSecurityContext
,
476 AccessState
->RemainingDesiredAccess
,
477 AccessState
->PreviouslyGrantedAccess
,
479 &ObjectType
->TypeInfo
.GenericMapping
,
485 /* We got privileges, append them to the access state and free them */
486 Status
= SeAppendPrivileges(AccessState
, Privileges
);
487 SeFreePrivileges(Privileges
);
490 /* Check if access was granted */
493 /* Update the access state */
494 AccessState
->RemainingDesiredAccess
&= ~(GrantedAccess
|
496 AccessState
->PreviouslyGrantedAccess
|= GrantedAccess
;
500 SeOpenObjectAuditAlarm(&ObjectType
->Name
,
508 &AccessState
->GenerateOnClose
);
510 /* We're done, unlock the context and release security */
511 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
512 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
516 /* PUBLIC FUNCTIONS **********************************************************/
519 * @name ObAssignSecurity
522 * The ObAssignSecurity routine <FILLMEIN>
527 * @param SecurityDescriptor
536 * @return STATUS_SUCCESS or appropriate error value.
543 ObAssignSecurity(IN PACCESS_STATE AccessState
,
544 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
546 IN POBJECT_TYPE Type
)
548 PSECURITY_DESCRIPTOR NewDescriptor
;
553 /* Build the new security descriptor */
554 Status
= SeAssignSecurity(SecurityDescriptor
,
555 AccessState
->SecurityDescriptor
,
557 (Type
== ObDirectoryType
),
558 &AccessState
->SubjectSecurityContext
,
559 &Type
->TypeInfo
.GenericMapping
,
561 if (!NT_SUCCESS(Status
)) return Status
;
563 /* Call the security method */
564 ObpCalloutStart(&CalloutIrql
);
565 Status
= Type
->TypeInfo
.SecurityProcedure(Object
,
566 AssignSecurityDescriptor
,
572 &Type
->TypeInfo
.GenericMapping
);
573 ObpCalloutEnd(CalloutIrql
, "Security", Type
, Object
);
575 /* Check for failure and deassign security if so */
576 if (!NT_SUCCESS(Status
)) SeDeassignSecurity(&NewDescriptor
);
578 /* Return to caller */
583 * @name ObGetObjectSecurity
586 * The ObGetObjectSecurity routine <FILLMEIN>
591 * @param SecurityDescriptor
594 * @param MemoryAllocated
597 * @return STATUS_SUCCESS or appropriate error value.
604 ObGetObjectSecurity(IN PVOID Object
,
605 OUT PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
606 OUT PBOOLEAN MemoryAllocated
)
608 POBJECT_HEADER Header
;
612 SECURITY_INFORMATION SecurityInformation
;
616 /* Get the object header and type */
617 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
620 /* Tell the caller that we didn't have to allocate anything yet */
621 *MemoryAllocated
= FALSE
;
623 /* Check if the object uses default security */
624 if (Type
->TypeInfo
.SecurityProcedure
== SeDefaultObjectMethod
)
626 /* Reference the descriptor */
627 *SecurityDescriptor
= ObpReferenceSecurityDescriptor(Header
);
628 return STATUS_SUCCESS
;
631 /* Set mask to query */
632 SecurityInformation
= OWNER_SECURITY_INFORMATION
|
633 GROUP_SECURITY_INFORMATION
|
634 DACL_SECURITY_INFORMATION
|
635 SACL_SECURITY_INFORMATION
;
637 /* Get the security descriptor size */
638 ObpCalloutStart(&CalloutIrql
);
639 Status
= Type
->TypeInfo
.SecurityProcedure(Object
,
640 QuerySecurityDescriptor
,
641 &SecurityInformation
,
644 &Header
->SecurityDescriptor
,
645 Type
->TypeInfo
.PoolType
,
646 &Type
->TypeInfo
.GenericMapping
);
647 ObpCalloutEnd(CalloutIrql
, "Security", Type
, Object
);
649 /* Check for failure */
650 if (Status
!= STATUS_BUFFER_TOO_SMALL
) return Status
;
652 /* Allocate security descriptor */
653 *SecurityDescriptor
= ExAllocatePoolWithTag(PagedPool
,
656 if (!(*SecurityDescriptor
)) return STATUS_INSUFFICIENT_RESOURCES
;
657 *MemoryAllocated
= TRUE
;
659 /* Query security descriptor */
660 ObpCalloutStart(&CalloutIrql
);
661 Status
= Type
->TypeInfo
.SecurityProcedure(Object
,
662 QuerySecurityDescriptor
,
663 &SecurityInformation
,
666 &Header
->SecurityDescriptor
,
667 Type
->TypeInfo
.PoolType
,
668 &Type
->TypeInfo
.GenericMapping
);
669 ObpCalloutEnd(CalloutIrql
, "Security", Type
, Object
);
671 /* Check for failure */
672 if (!NT_SUCCESS(Status
))
674 /* Free the descriptor and tell the caller we failed */
675 ExFreePoolWithTag(*SecurityDescriptor
, TAG_SEC_QUERY
);
676 *MemoryAllocated
= FALSE
;
684 * @name ObReleaseObjectSecurity
687 * The ObReleaseObjectSecurity routine <FILLMEIN>
689 * @param SecurityDescriptor
692 * @param MemoryAllocated
695 * @return STATUS_SUCCESS or appropriate error value.
702 ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
703 IN BOOLEAN MemoryAllocated
)
707 /* Nothing to do in this case */
708 if (!SecurityDescriptor
) return;
710 /* Check if we had allocated it from memory */
714 ExFreePool(SecurityDescriptor
);
718 /* Otherwise this means we used an internal descriptor */
719 ObDereferenceSecurityDescriptor(SecurityDescriptor
, 1);
724 * @name ObSetSecurityObjectByPointer
727 * The ObSetSecurityObjectByPointer routine <FILLMEIN>
729 * @param SecurityDescriptor
732 * @param MemoryAllocated
735 * @return STATUS_SUCCESS or appropriate error value.
742 ObSetSecurityObjectByPointer(IN PVOID Object
,
743 IN SECURITY_INFORMATION SecurityInformation
,
744 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
747 POBJECT_HEADER Header
;
750 /* Get the header and type */
751 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
755 ASSERT(SecurityDescriptor
);
757 /* Call the security procedure */
758 return Type
->TypeInfo
.SecurityProcedure(Object
,
759 SetSecurityDescriptor
,
760 &SecurityInformation
,
763 &Header
->SecurityDescriptor
,
764 Type
->TypeInfo
.PoolType
,
765 &Type
->TypeInfo
.GenericMapping
);
769 * @name NtQuerySecurityObject
772 * The NtQuerySecurityObject routine <FILLMEIN>
777 * @param SecurityInformation
780 * @param SecurityDescriptor
786 * @param ResultLength
789 * @return STATUS_SUCCESS or appropriate error value.
796 NtQuerySecurityObject(IN HANDLE Handle
,
797 IN SECURITY_INFORMATION SecurityInformation
,
798 OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
800 OUT PULONG ResultLength
)
802 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
804 POBJECT_HEADER Header
;
806 ACCESS_MASK DesiredAccess
;
810 /* Check if we came from user mode */
811 if (PreviousMode
!= KernelMode
)
816 /* Probe the SD and the length pointer */
817 ProbeForWrite(SecurityDescriptor
, Length
, sizeof(ULONG
));
818 ProbeForWriteUlong(ResultLength
);
820 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
822 /* Return the exception code */
823 _SEH2_YIELD(return _SEH2_GetExceptionCode());
828 /* Get the required access rights for the operation */
829 SeQuerySecurityAccessMask(SecurityInformation
, &DesiredAccess
);
831 /* Reference the object */
832 Status
= ObReferenceObjectByHandle(Handle
,
838 if (!NT_SUCCESS(Status
)) return Status
;
840 /* Get the Object Header and Type */
841 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
844 /* Call the security procedure's query function */
845 Status
= Type
->TypeInfo
.SecurityProcedure(Object
,
846 QuerySecurityDescriptor
,
847 &SecurityInformation
,
850 &Header
->SecurityDescriptor
,
851 Type
->TypeInfo
.PoolType
,
852 &Type
->TypeInfo
.GenericMapping
);
854 /* Dereference the object */
855 ObDereferenceObject(Object
);
857 /* Protect write with SEH */
860 /* Return the needed length */
861 *ResultLength
= Length
;
863 _SEH2_EXCEPT(ExSystemExceptionFilter())
865 /* Get the exception code */
866 Status
= _SEH2_GetExceptionCode();
875 * @name NtSetSecurityObject
878 * The NtSetSecurityObject routine <FILLMEIN>
883 * @param SecurityInformation
886 * @param SecurityDescriptor
889 * @return STATUS_SUCCESS or appropriate error value.
896 NtSetSecurityObject(IN HANDLE Handle
,
897 IN SECURITY_INFORMATION SecurityInformation
,
898 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
900 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
902 SECURITY_DESCRIPTOR_RELATIVE
*CapturedDescriptor
;
903 ACCESS_MASK DesiredAccess
= 0;
907 /* Make sure the caller doesn't pass a NULL security descriptor! */
908 if (!SecurityDescriptor
) return STATUS_ACCESS_VIOLATION
;
910 /* Set the required access rights for the operation */
911 SeSetSecurityAccessMask(SecurityInformation
, &DesiredAccess
);
913 /* Reference the object */
914 Status
= ObReferenceObjectByHandle(Handle
,
920 if (NT_SUCCESS(Status
))
922 /* Capture and make a copy of the security descriptor */
923 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
927 (PSECURITY_DESCRIPTOR
*)
928 &CapturedDescriptor
);
929 if (!NT_SUCCESS(Status
))
932 ObDereferenceObject(Object
);
937 ASSERT(CapturedDescriptor
->Control
& SE_SELF_RELATIVE
);
940 * Make sure the security descriptor passed by the caller
941 * is valid for the operation we're about to perform
943 if (((SecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
944 !(CapturedDescriptor
->Owner
)) ||
945 ((SecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
946 !(CapturedDescriptor
->Group
)))
948 /* Set the failure status */
949 Status
= STATUS_INVALID_SECURITY_DESCR
;
954 Status
= ObSetSecurityObjectByPointer(Object
,
959 /* Release the descriptor and return status */
960 SeReleaseSecurityDescriptor((PSECURITY_DESCRIPTOR
)CapturedDescriptor
,
964 /* Now we can dereference the object */
965 ObDereferenceObject(Object
);
972 * @name ObQueryObjectAuditingByHandle
975 * The ObDereferenceSecurityDescriptor routine <FILLMEIN>
977 * @param SecurityDescriptor
983 * @return STATUS_SUCCESS or appropriate error value.
990 ObQueryObjectAuditingByHandle(IN HANDLE Handle
,
991 OUT PBOOLEAN GenerateOnClose
)
993 PHANDLE_TABLE_ENTRY HandleEntry
;
995 NTSTATUS Status
= STATUS_SUCCESS
;
998 /* Check if we're dealing with a kernel handle */
999 if (ObIsKernelHandle(Handle
, ExGetPreviousMode()))
1001 /* Use the kernel table and convert the handle */
1002 HandleTable
= ObpKernelHandleTable
;
1003 Handle
= ObKernelHandleToHandle(Handle
);
1007 /* Use the process's handle table */
1008 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
1011 /* Enter a critical region while we touch the handle table */
1012 KeEnterCriticalRegion();
1014 /* Map the handle */
1015 HandleEntry
= ExMapHandleToPointer(HandleTable
, Handle
);
1018 /* Check if the flag is set */
1019 *GenerateOnClose
= HandleEntry
->ObAttributes
& OBJ_AUDIT_OBJECT_CLOSE
;
1021 /* Unlock the entry */
1022 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
1026 /* Otherwise, fail */
1027 Status
= STATUS_INVALID_HANDLE
;
1030 /* Leave the critical region and return the status */
1031 KeLeaveCriticalRegion();