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 /* We failed, dereference the old one */
150 if (OldDescriptor
) ObDereferenceSecurityDescriptor(OldDescriptor
, 1);
154 /* Now add this to the cache */
155 Status
= ObLogSecurityDescriptor(NewDescriptor
,
159 /* Let go of our uncached copy */
160 ExFreePool(NewDescriptor
);
162 /* Check for success */
163 if (!NT_SUCCESS(Status
))
165 /* We failed, dereference the old one */
166 ObDereferenceSecurityDescriptor(OldDescriptor
, 1);
171 FastRef
= (PEX_FAST_REF
)OutputSecurityDescriptor
;
172 OldValue
= ExCompareSwapFastReference(FastRef
,
176 /* Make sure the swap worked */
177 if (ExGetObjectFastReference(OldValue
) == OldDescriptor
)
180 ObpAcquireObjectLock(ObjectHeader
);
181 ObpReleaseObjectLock(ObjectHeader
);
183 /* And dereference the old one */
184 Count
= ExGetCountFastReference(OldValue
);
185 ObDereferenceSecurityDescriptor(OldDescriptor
, Count
+ 2);
190 /* Someone changed it behind our back -- try again */
191 ObDereferenceSecurityDescriptor(OldDescriptor
, 1);
192 ObDereferenceSecurityDescriptor(CachedDescriptor
,
203 ObCheckCreateObjectAccess(IN PVOID Object
,
204 IN ACCESS_MASK CreateAccess
,
205 IN PACCESS_STATE AccessState
,
206 IN PUNICODE_STRING ComponentName
,
208 IN KPROCESSOR_MODE AccessMode
,
209 OUT PNTSTATUS AccessStatus
)
211 POBJECT_HEADER ObjectHeader
;
212 POBJECT_TYPE ObjectType
;
213 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
215 BOOLEAN Result
= TRUE
;
216 ACCESS_MASK GrantedAccess
= 0;
217 PPRIVILEGE_SET Privileges
= NULL
;
221 /* Get the header and type */
222 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
223 ObjectType
= ObjectHeader
->Type
;
225 /* Get the security descriptor */
226 Status
= ObGetObjectSecurity(Object
, &SecurityDescriptor
, &SdAllocated
);
227 if (!NT_SUCCESS(Status
))
230 *AccessStatus
= Status
;
234 /* Lock the security context */
235 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
237 /* Check if we have an SD */
238 if (SecurityDescriptor
)
240 /* Now do the entire access check */
241 Result
= SeAccessCheck(SecurityDescriptor
,
242 &AccessState
->SubjectSecurityContext
,
247 &ObjectType
->TypeInfo
.GenericMapping
,
253 /* We got privileges, append them to the access state and free them */
254 Status
= SeAppendPrivileges(AccessState
, Privileges
);
255 SeFreePrivileges(Privileges
);
259 /* We're done, unlock the context and release security */
260 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
261 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
267 ObpCheckTraverseAccess(IN PVOID Object
,
268 IN ACCESS_MASK TraverseAccess
,
269 IN PACCESS_STATE AccessState OPTIONAL
,
271 IN KPROCESSOR_MODE AccessMode
,
272 OUT PNTSTATUS AccessStatus
)
274 POBJECT_HEADER ObjectHeader
;
275 POBJECT_TYPE ObjectType
;
276 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
279 ACCESS_MASK GrantedAccess
= 0;
280 PPRIVILEGE_SET Privileges
= NULL
;
284 /* Get the header and type */
285 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
286 ObjectType
= ObjectHeader
->Type
;
288 /* Get the security descriptor */
289 Status
= ObGetObjectSecurity(Object
, &SecurityDescriptor
, &SdAllocated
);
290 if (!NT_SUCCESS(Status
))
293 *AccessStatus
= Status
;
297 /* First try to perform a fast traverse check
298 * If it fails, then the entire access check will
301 Result
= SeFastTraverseCheck(SecurityDescriptor
,
307 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
311 /* Lock the security context */
312 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
314 /* Now do the entire access check */
315 Result
= SeAccessCheck(SecurityDescriptor
,
316 &AccessState
->SubjectSecurityContext
,
321 &ObjectType
->TypeInfo
.GenericMapping
,
327 /* We got privileges, append them to the access state and free them */
328 Status
= SeAppendPrivileges(AccessState
, Privileges
);
329 SeFreePrivileges(Privileges
);
332 /* We're done, unlock the context and release security */
333 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
334 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
340 ObpCheckObjectReference(IN PVOID Object
,
341 IN OUT PACCESS_STATE AccessState
,
343 IN KPROCESSOR_MODE AccessMode
,
344 OUT PNTSTATUS AccessStatus
)
346 POBJECT_HEADER ObjectHeader
;
347 POBJECT_TYPE ObjectType
;
348 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
351 ACCESS_MASK GrantedAccess
= 0;
352 PPRIVILEGE_SET Privileges
= NULL
;
356 /* Get the header and type */
357 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
358 ObjectType
= ObjectHeader
->Type
;
360 /* Get the security descriptor */
361 Status
= ObGetObjectSecurity(Object
, &SecurityDescriptor
, &SdAllocated
);
362 if (!NT_SUCCESS(Status
))
365 *AccessStatus
= Status
;
369 /* Lock the security context */
370 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
372 /* Now do the entire access check */
373 Result
= SeAccessCheck(SecurityDescriptor
,
374 &AccessState
->SubjectSecurityContext
,
376 AccessState
->RemainingDesiredAccess
,
377 AccessState
->PreviouslyGrantedAccess
,
379 &ObjectType
->TypeInfo
.GenericMapping
,
385 /* Update the access state */
386 AccessState
->RemainingDesiredAccess
&= ~GrantedAccess
;
387 AccessState
->PreviouslyGrantedAccess
|= GrantedAccess
;
390 /* Check if we have an SD */
391 if (SecurityDescriptor
)
395 SeObjectReferenceAuditAlarm(&AccessState
->OperationID
,
398 &AccessState
->SubjectSecurityContext
,
399 AccessState
->RemainingDesiredAccess
|
400 AccessState
->PreviouslyGrantedAccess
,
401 ((PAUX_ACCESS_DATA
)(AccessState
->AuxData
))->
408 /* We're done, unlock the context and release security */
409 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
410 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
415 * @name ObCheckObjectAccess
417 * The ObCheckObjectAccess routine <FILLMEIN>
431 * @param ReturnedStatus
434 * @return TRUE if access was granted, FALSE otherwise.
441 ObCheckObjectAccess(IN PVOID Object
,
442 IN OUT PACCESS_STATE AccessState
,
444 IN KPROCESSOR_MODE AccessMode
,
445 OUT PNTSTATUS ReturnedStatus
)
447 POBJECT_HEADER ObjectHeader
;
448 POBJECT_TYPE ObjectType
;
449 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
453 ACCESS_MASK GrantedAccess
;
454 PPRIVILEGE_SET Privileges
= NULL
;
457 /* Get the object header and type */
458 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
459 ObjectType
= ObjectHeader
->Type
;
461 /* Get security information */
462 Status
= ObGetObjectSecurity(Object
, &SecurityDescriptor
, &SdAllocated
);
463 if (!NT_SUCCESS(Status
))
466 *ReturnedStatus
= Status
;
469 else if (!SecurityDescriptor
)
471 /* Otherwise, if we don't actually have an SD, return success */
472 *ReturnedStatus
= Status
;
476 /* Lock the security context */
477 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
479 /* Now do the entire access check */
480 Result
= SeAccessCheck(SecurityDescriptor
,
481 &AccessState
->SubjectSecurityContext
,
483 AccessState
->RemainingDesiredAccess
,
484 AccessState
->PreviouslyGrantedAccess
,
486 &ObjectType
->TypeInfo
.GenericMapping
,
492 /* We got privileges, append them to the access state and free them */
493 Status
= SeAppendPrivileges(AccessState
, Privileges
);
494 SeFreePrivileges(Privileges
);
497 /* Check if access was granted */
500 /* Update the access state */
501 AccessState
->RemainingDesiredAccess
&= ~(GrantedAccess
|
503 AccessState
->PreviouslyGrantedAccess
|= GrantedAccess
;
507 SeOpenObjectAuditAlarm(&ObjectType
->Name
,
515 &AccessState
->GenerateOnClose
);
517 /* We're done, unlock the context and release security */
518 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
519 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
523 /* PUBLIC FUNCTIONS **********************************************************/
526 * @name ObAssignSecurity
529 * The ObAssignSecurity routine <FILLMEIN>
534 * @param SecurityDescriptor
543 * @return STATUS_SUCCESS or appropriate error value.
550 ObAssignSecurity(IN PACCESS_STATE AccessState
,
551 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
553 IN POBJECT_TYPE Type
)
555 PSECURITY_DESCRIPTOR NewDescriptor
;
560 /* Build the new security descriptor */
561 Status
= SeAssignSecurity(SecurityDescriptor
,
562 AccessState
->SecurityDescriptor
,
564 (Type
== ObDirectoryType
),
565 &AccessState
->SubjectSecurityContext
,
566 &Type
->TypeInfo
.GenericMapping
,
568 if (!NT_SUCCESS(Status
)) return Status
;
570 /* Call the security method */
571 ObpCalloutStart(&CalloutIrql
);
572 Status
= Type
->TypeInfo
.SecurityProcedure(Object
,
573 AssignSecurityDescriptor
,
579 &Type
->TypeInfo
.GenericMapping
);
580 ObpCalloutEnd(CalloutIrql
, "Security", Type
, Object
);
582 /* Check for failure and deassign security if so */
583 if (!NT_SUCCESS(Status
)) SeDeassignSecurity(&NewDescriptor
);
585 /* Return to caller */
590 * @name ObGetObjectSecurity
593 * The ObGetObjectSecurity routine <FILLMEIN>
598 * @param SecurityDescriptor
601 * @param MemoryAllocated
604 * @return STATUS_SUCCESS or appropriate error value.
611 ObGetObjectSecurity(IN PVOID Object
,
612 OUT PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
613 OUT PBOOLEAN MemoryAllocated
)
615 POBJECT_HEADER Header
;
619 SECURITY_INFORMATION SecurityInformation
;
623 /* Get the object header and type */
624 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
627 /* Tell the caller that we didn't have to allocate anything yet */
628 *MemoryAllocated
= FALSE
;
630 /* Check if the object uses default security */
631 if (Type
->TypeInfo
.SecurityProcedure
== SeDefaultObjectMethod
)
633 /* Reference the descriptor */
634 *SecurityDescriptor
= ObpReferenceSecurityDescriptor(Header
);
635 return STATUS_SUCCESS
;
638 /* Set mask to query */
639 SecurityInformation
= OWNER_SECURITY_INFORMATION
|
640 GROUP_SECURITY_INFORMATION
|
641 DACL_SECURITY_INFORMATION
|
642 SACL_SECURITY_INFORMATION
;
644 /* Get the security descriptor size */
645 ObpCalloutStart(&CalloutIrql
);
646 Status
= Type
->TypeInfo
.SecurityProcedure(Object
,
647 QuerySecurityDescriptor
,
648 &SecurityInformation
,
651 &Header
->SecurityDescriptor
,
652 Type
->TypeInfo
.PoolType
,
653 &Type
->TypeInfo
.GenericMapping
);
654 ObpCalloutEnd(CalloutIrql
, "Security", Type
, Object
);
656 /* Check for failure */
657 if (Status
!= STATUS_BUFFER_TOO_SMALL
) return Status
;
659 /* Allocate security descriptor */
660 *SecurityDescriptor
= ExAllocatePoolWithTag(PagedPool
,
663 if (!(*SecurityDescriptor
)) return STATUS_INSUFFICIENT_RESOURCES
;
664 *MemoryAllocated
= TRUE
;
666 /* Query security descriptor */
667 ObpCalloutStart(&CalloutIrql
);
668 Status
= Type
->TypeInfo
.SecurityProcedure(Object
,
669 QuerySecurityDescriptor
,
670 &SecurityInformation
,
673 &Header
->SecurityDescriptor
,
674 Type
->TypeInfo
.PoolType
,
675 &Type
->TypeInfo
.GenericMapping
);
676 ObpCalloutEnd(CalloutIrql
, "Security", Type
, Object
);
678 /* Check for failure */
679 if (!NT_SUCCESS(Status
))
681 /* Free the descriptor and tell the caller we failed */
682 ExFreePoolWithTag(*SecurityDescriptor
, TAG_SEC_QUERY
);
683 *MemoryAllocated
= FALSE
;
691 * @name ObReleaseObjectSecurity
694 * The ObReleaseObjectSecurity routine <FILLMEIN>
696 * @param SecurityDescriptor
699 * @param MemoryAllocated
702 * @return STATUS_SUCCESS or appropriate error value.
709 ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
710 IN BOOLEAN MemoryAllocated
)
714 /* Nothing to do in this case */
715 if (!SecurityDescriptor
) return;
717 /* Check if we had allocated it from memory */
721 ExFreePool(SecurityDescriptor
);
725 /* Otherwise this means we used an internal descriptor */
726 ObDereferenceSecurityDescriptor(SecurityDescriptor
, 1);
731 * @name ObSetSecurityObjectByPointer
734 * The ObSetSecurityObjectByPointer routine <FILLMEIN>
736 * @param SecurityDescriptor
739 * @param MemoryAllocated
742 * @return STATUS_SUCCESS or appropriate error value.
749 ObSetSecurityObjectByPointer(IN PVOID Object
,
750 IN SECURITY_INFORMATION SecurityInformation
,
751 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
754 POBJECT_HEADER Header
;
757 /* Get the header and type */
758 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
762 ASSERT(SecurityDescriptor
);
764 /* Call the security procedure */
765 return Type
->TypeInfo
.SecurityProcedure(Object
,
766 SetSecurityDescriptor
,
767 &SecurityInformation
,
770 &Header
->SecurityDescriptor
,
771 Type
->TypeInfo
.PoolType
,
772 &Type
->TypeInfo
.GenericMapping
);
776 * @name NtQuerySecurityObject
779 * The NtQuerySecurityObject routine <FILLMEIN>
784 * @param SecurityInformation
787 * @param SecurityDescriptor
793 * @param ResultLength
796 * @return STATUS_SUCCESS or appropriate error value.
803 NtQuerySecurityObject(IN HANDLE Handle
,
804 IN SECURITY_INFORMATION SecurityInformation
,
805 OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
807 OUT PULONG ResultLength
)
809 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
811 POBJECT_HEADER Header
;
813 ACCESS_MASK DesiredAccess
;
817 /* Check if we came from user mode */
818 if (PreviousMode
!= KernelMode
)
823 /* Probe the SD and the length pointer */
824 ProbeForWrite(SecurityDescriptor
, Length
, sizeof(ULONG
));
825 ProbeForWriteUlong(ResultLength
);
827 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
829 /* Return the exception code */
830 _SEH2_YIELD(return _SEH2_GetExceptionCode());
835 /* Get the required access rights for the operation */
836 SeQuerySecurityAccessMask(SecurityInformation
, &DesiredAccess
);
838 /* Reference the object */
839 Status
= ObReferenceObjectByHandle(Handle
,
845 if (!NT_SUCCESS(Status
)) return Status
;
847 /* Get the Object Header and Type */
848 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
851 /* Call the security procedure's query function */
852 Status
= Type
->TypeInfo
.SecurityProcedure(Object
,
853 QuerySecurityDescriptor
,
854 &SecurityInformation
,
857 &Header
->SecurityDescriptor
,
858 Type
->TypeInfo
.PoolType
,
859 &Type
->TypeInfo
.GenericMapping
);
861 /* Dereference the object */
862 ObDereferenceObject(Object
);
864 /* Protect write with SEH */
867 /* Return the needed length */
868 *ResultLength
= Length
;
870 _SEH2_EXCEPT(ExSystemExceptionFilter())
872 /* Get the exception code */
873 Status
= _SEH2_GetExceptionCode();
882 * @name NtSetSecurityObject
885 * The NtSetSecurityObject routine <FILLMEIN>
890 * @param SecurityInformation
893 * @param SecurityDescriptor
896 * @return STATUS_SUCCESS or appropriate error value.
903 NtSetSecurityObject(IN HANDLE Handle
,
904 IN SECURITY_INFORMATION SecurityInformation
,
905 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
907 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
909 SECURITY_DESCRIPTOR_RELATIVE
*CapturedDescriptor
;
910 ACCESS_MASK DesiredAccess
= 0;
914 /* Make sure the caller doesn't pass a NULL security descriptor! */
915 if (!SecurityDescriptor
) return STATUS_ACCESS_VIOLATION
;
917 /* Set the required access rights for the operation */
918 SeSetSecurityAccessMask(SecurityInformation
, &DesiredAccess
);
920 /* Reference the object */
921 Status
= ObReferenceObjectByHandle(Handle
,
927 if (NT_SUCCESS(Status
))
929 /* Capture and make a copy of the security descriptor */
930 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
934 (PSECURITY_DESCRIPTOR
*)
935 &CapturedDescriptor
);
936 if (!NT_SUCCESS(Status
))
939 ObDereferenceObject(Object
);
944 ASSERT(CapturedDescriptor
->Control
& SE_SELF_RELATIVE
);
947 * Make sure the security descriptor passed by the caller
948 * is valid for the operation we're about to perform
950 if (((SecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
951 !(CapturedDescriptor
->Owner
)) ||
952 ((SecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
953 !(CapturedDescriptor
->Group
)))
955 /* Set the failure status */
956 Status
= STATUS_INVALID_SECURITY_DESCR
;
961 Status
= ObSetSecurityObjectByPointer(Object
,
966 /* Release the descriptor and return status */
967 SeReleaseSecurityDescriptor((PSECURITY_DESCRIPTOR
)CapturedDescriptor
,
971 /* Now we can dereference the object */
972 ObDereferenceObject(Object
);
979 * @name ObQueryObjectAuditingByHandle
982 * The ObDereferenceSecurityDescriptor routine <FILLMEIN>
984 * @param SecurityDescriptor
990 * @return STATUS_SUCCESS or appropriate error value.
997 ObQueryObjectAuditingByHandle(IN HANDLE Handle
,
998 OUT PBOOLEAN GenerateOnClose
)
1000 PHANDLE_TABLE_ENTRY HandleEntry
;
1002 NTSTATUS Status
= STATUS_SUCCESS
;
1005 /* Check if we're dealing with a kernel handle */
1006 if (ObpIsKernelHandle(Handle
, ExGetPreviousMode()))
1008 /* Use the kernel table and convert the handle */
1009 HandleTable
= ObpKernelHandleTable
;
1010 Handle
= ObKernelHandleToHandle(Handle
);
1014 /* Use the process's handle table */
1015 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
1018 /* Enter a critical region while we touch the handle table */
1019 KeEnterCriticalRegion();
1021 /* Map the handle */
1022 HandleEntry
= ExMapHandleToPointer(HandleTable
, Handle
);
1025 /* Check if the flag is set */
1026 *GenerateOnClose
= HandleEntry
->ObAttributes
& OBJ_AUDIT_OBJECT_CLOSE
;
1028 /* Unlock the entry */
1029 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
1033 /* Otherwise, fail */
1034 Status
= STATUS_INVALID_HANDLE
;
1037 /* Leave the critical region and return the status */
1038 KeLeaveCriticalRegion();