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
= NULL
;
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
= NULL
;
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 /* First try to perform a fast traverse check
305 * If it fails, then the entire access check will
308 Result
= SeFastTraverseCheck(SecurityDescriptor
,
314 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
318 /* Lock the security context */
319 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
321 /* Now do the entire access check */
322 Result
= SeAccessCheck(SecurityDescriptor
,
323 &AccessState
->SubjectSecurityContext
,
328 &ObjectType
->TypeInfo
.GenericMapping
,
334 /* We got privileges, append them to the access state and free them */
335 Status
= SeAppendPrivileges(AccessState
, Privileges
);
336 SeFreePrivileges(Privileges
);
339 /* We're done, unlock the context and release security */
340 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
341 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
347 ObpCheckObjectReference(IN PVOID Object
,
348 IN OUT PACCESS_STATE AccessState
,
350 IN KPROCESSOR_MODE AccessMode
,
351 OUT PNTSTATUS AccessStatus
)
353 POBJECT_HEADER ObjectHeader
;
354 POBJECT_TYPE ObjectType
;
355 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
358 ACCESS_MASK GrantedAccess
= 0;
359 PPRIVILEGE_SET Privileges
= NULL
;
363 /* Get the header and type */
364 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
365 ObjectType
= ObjectHeader
->Type
;
367 /* Get the security descriptor */
368 Status
= ObGetObjectSecurity(Object
, &SecurityDescriptor
, &SdAllocated
);
369 if (!NT_SUCCESS(Status
))
372 *AccessStatus
= Status
;
376 /* Lock the security context */
377 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
379 /* Now do the entire access check */
380 Result
= SeAccessCheck(SecurityDescriptor
,
381 &AccessState
->SubjectSecurityContext
,
383 AccessState
->RemainingDesiredAccess
,
384 AccessState
->PreviouslyGrantedAccess
,
386 &ObjectType
->TypeInfo
.GenericMapping
,
392 /* Update the access state */
393 AccessState
->RemainingDesiredAccess
&= ~GrantedAccess
;
394 AccessState
->PreviouslyGrantedAccess
|= GrantedAccess
;
397 /* Check if we have an SD */
398 if (SecurityDescriptor
)
402 SeObjectReferenceAuditAlarm(&AccessState
->OperationID
,
405 &AccessState
->SubjectSecurityContext
,
406 AccessState
->RemainingDesiredAccess
|
407 AccessState
->PreviouslyGrantedAccess
,
408 ((PAUX_ACCESS_DATA
)(AccessState
->AuxData
))->
415 /* We're done, unlock the context and release security */
416 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
417 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
422 * @name ObCheckObjectAccess
424 * The ObCheckObjectAccess routine <FILLMEIN>
438 * @param ReturnedStatus
441 * @return TRUE if access was granted, FALSE otherwise.
448 ObCheckObjectAccess(IN PVOID Object
,
449 IN OUT PACCESS_STATE AccessState
,
451 IN KPROCESSOR_MODE AccessMode
,
452 OUT PNTSTATUS ReturnedStatus
)
454 POBJECT_HEADER ObjectHeader
;
455 POBJECT_TYPE ObjectType
;
456 PSECURITY_DESCRIPTOR SecurityDescriptor
= NULL
;
460 ACCESS_MASK GrantedAccess
;
461 PPRIVILEGE_SET Privileges
= NULL
;
464 /* Get the object header and type */
465 ObjectHeader
= OBJECT_TO_OBJECT_HEADER(Object
);
466 ObjectType
= ObjectHeader
->Type
;
468 /* Get security information */
469 Status
= ObGetObjectSecurity(Object
, &SecurityDescriptor
, &SdAllocated
);
470 if (!NT_SUCCESS(Status
))
473 *ReturnedStatus
= Status
;
476 else if (!SecurityDescriptor
)
478 /* Otherwise, if we don't actually have an SD, return success */
479 *ReturnedStatus
= Status
;
483 /* Lock the security context */
484 SeLockSubjectContext(&AccessState
->SubjectSecurityContext
);
486 /* Now do the entire access check */
487 Result
= SeAccessCheck(SecurityDescriptor
,
488 &AccessState
->SubjectSecurityContext
,
490 AccessState
->RemainingDesiredAccess
,
491 AccessState
->PreviouslyGrantedAccess
,
493 &ObjectType
->TypeInfo
.GenericMapping
,
499 /* We got privileges, append them to the access state and free them */
500 Status
= SeAppendPrivileges(AccessState
, Privileges
);
501 SeFreePrivileges(Privileges
);
504 /* Check if access was granted */
507 /* Update the access state */
508 AccessState
->RemainingDesiredAccess
&= ~(GrantedAccess
|
510 AccessState
->PreviouslyGrantedAccess
|= GrantedAccess
;
514 SeOpenObjectAuditAlarm(&ObjectType
->Name
,
522 &AccessState
->GenerateOnClose
);
524 /* We're done, unlock the context and release security */
525 SeUnlockSubjectContext(&AccessState
->SubjectSecurityContext
);
526 ObReleaseObjectSecurity(SecurityDescriptor
, SdAllocated
);
530 /* PUBLIC FUNCTIONS **********************************************************/
533 * @name ObAssignSecurity
536 * The ObAssignSecurity routine <FILLMEIN>
541 * @param SecurityDescriptor
550 * @return STATUS_SUCCESS or appropriate error value.
557 ObAssignSecurity(IN PACCESS_STATE AccessState
,
558 IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
560 IN POBJECT_TYPE Type
)
562 PSECURITY_DESCRIPTOR NewDescriptor
;
567 /* Build the new security descriptor */
568 Status
= SeAssignSecurity(SecurityDescriptor
,
569 AccessState
->SecurityDescriptor
,
571 (Type
== ObDirectoryType
),
572 &AccessState
->SubjectSecurityContext
,
573 &Type
->TypeInfo
.GenericMapping
,
575 if (!NT_SUCCESS(Status
)) return Status
;
577 /* Call the security method */
578 ObpCalloutStart(&CalloutIrql
);
579 Status
= Type
->TypeInfo
.SecurityProcedure(Object
,
580 AssignSecurityDescriptor
,
586 &Type
->TypeInfo
.GenericMapping
);
587 ObpCalloutEnd(CalloutIrql
, "Security", Type
, Object
);
589 /* Check for failure and deassign security if so */
590 if (!NT_SUCCESS(Status
)) SeDeassignSecurity(&NewDescriptor
);
592 /* Return to caller */
597 * @name ObGetObjectSecurity
600 * The ObGetObjectSecurity routine <FILLMEIN>
605 * @param SecurityDescriptor
608 * @param MemoryAllocated
611 * @return STATUS_SUCCESS or appropriate error value.
618 ObGetObjectSecurity(IN PVOID Object
,
619 OUT PSECURITY_DESCRIPTOR
*SecurityDescriptor
,
620 OUT PBOOLEAN MemoryAllocated
)
622 POBJECT_HEADER Header
;
626 SECURITY_INFORMATION SecurityInformation
;
630 /* Get the object header and type */
631 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
634 /* Tell the caller that we didn't have to allocate anything yet */
635 *MemoryAllocated
= FALSE
;
637 /* Check if the object uses default security */
638 if (Type
->TypeInfo
.SecurityProcedure
== SeDefaultObjectMethod
)
640 /* Reference the descriptor */
641 *SecurityDescriptor
= ObpReferenceSecurityDescriptor(Header
);
642 return STATUS_SUCCESS
;
645 /* Set mask to query */
646 SecurityInformation
= OWNER_SECURITY_INFORMATION
|
647 GROUP_SECURITY_INFORMATION
|
648 DACL_SECURITY_INFORMATION
|
649 SACL_SECURITY_INFORMATION
;
651 /* Get the security descriptor size */
652 ObpCalloutStart(&CalloutIrql
);
653 Status
= Type
->TypeInfo
.SecurityProcedure(Object
,
654 QuerySecurityDescriptor
,
655 &SecurityInformation
,
658 &Header
->SecurityDescriptor
,
659 Type
->TypeInfo
.PoolType
,
660 &Type
->TypeInfo
.GenericMapping
);
661 ObpCalloutEnd(CalloutIrql
, "Security", Type
, Object
);
663 /* Check for failure */
664 if (Status
!= STATUS_BUFFER_TOO_SMALL
) return Status
;
666 /* Allocate security descriptor */
667 *SecurityDescriptor
= ExAllocatePoolWithTag(PagedPool
,
670 if (!(*SecurityDescriptor
)) return STATUS_INSUFFICIENT_RESOURCES
;
671 *MemoryAllocated
= TRUE
;
673 /* Query security descriptor */
674 ObpCalloutStart(&CalloutIrql
);
675 Status
= Type
->TypeInfo
.SecurityProcedure(Object
,
676 QuerySecurityDescriptor
,
677 &SecurityInformation
,
680 &Header
->SecurityDescriptor
,
681 Type
->TypeInfo
.PoolType
,
682 &Type
->TypeInfo
.GenericMapping
);
683 ObpCalloutEnd(CalloutIrql
, "Security", Type
, Object
);
685 /* Check for failure */
686 if (!NT_SUCCESS(Status
))
688 /* Free the descriptor and tell the caller we failed */
689 ExFreePoolWithTag(*SecurityDescriptor
, TAG_SEC_QUERY
);
690 *MemoryAllocated
= FALSE
;
698 * @name ObReleaseObjectSecurity
701 * The ObReleaseObjectSecurity routine <FILLMEIN>
703 * @param SecurityDescriptor
706 * @param MemoryAllocated
709 * @return STATUS_SUCCESS or appropriate error value.
716 ObReleaseObjectSecurity(IN PSECURITY_DESCRIPTOR SecurityDescriptor
,
717 IN BOOLEAN MemoryAllocated
)
721 /* Nothing to do in this case */
722 if (!SecurityDescriptor
) return;
724 /* Check if we had allocated it from memory */
728 ExFreePool(SecurityDescriptor
);
732 /* Otherwise this means we used an internal descriptor */
733 ObDereferenceSecurityDescriptor(SecurityDescriptor
, 1);
738 * @name ObSetSecurityObjectByPointer
741 * The ObSetSecurityObjectByPointer routine <FILLMEIN>
743 * @param SecurityDescriptor
746 * @param MemoryAllocated
749 * @return STATUS_SUCCESS or appropriate error value.
756 ObSetSecurityObjectByPointer(IN PVOID Object
,
757 IN SECURITY_INFORMATION SecurityInformation
,
758 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
761 POBJECT_HEADER Header
;
764 /* Get the header and type */
765 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
769 ASSERT(SecurityDescriptor
);
771 /* Call the security procedure */
772 return Type
->TypeInfo
.SecurityProcedure(Object
,
773 SetSecurityDescriptor
,
774 &SecurityInformation
,
777 &Header
->SecurityDescriptor
,
778 Type
->TypeInfo
.PoolType
,
779 &Type
->TypeInfo
.GenericMapping
);
783 * @name NtQuerySecurityObject
786 * The NtQuerySecurityObject routine <FILLMEIN>
791 * @param SecurityInformation
794 * @param SecurityDescriptor
800 * @param ResultLength
803 * @return STATUS_SUCCESS or appropriate error value.
810 NtQuerySecurityObject(IN HANDLE Handle
,
811 IN SECURITY_INFORMATION SecurityInformation
,
812 OUT PSECURITY_DESCRIPTOR SecurityDescriptor
,
814 OUT PULONG ResultLength
)
816 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
818 POBJECT_HEADER Header
;
820 ACCESS_MASK DesiredAccess
;
824 /* Check if we came from user mode */
825 if (PreviousMode
!= KernelMode
)
830 /* Probe the SD and the length pointer */
831 ProbeForWrite(SecurityDescriptor
, Length
, sizeof(ULONG
));
832 ProbeForWriteUlong(ResultLength
);
834 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
836 /* Return the exception code */
837 _SEH2_YIELD(return _SEH2_GetExceptionCode());
842 /* Get the required access rights for the operation */
843 SeQuerySecurityAccessMask(SecurityInformation
, &DesiredAccess
);
845 /* Reference the object */
846 Status
= ObReferenceObjectByHandle(Handle
,
852 if (!NT_SUCCESS(Status
)) return Status
;
854 /* Get the Object Header and Type */
855 Header
= OBJECT_TO_OBJECT_HEADER(Object
);
858 /* Call the security procedure's query function */
859 Status
= Type
->TypeInfo
.SecurityProcedure(Object
,
860 QuerySecurityDescriptor
,
861 &SecurityInformation
,
864 &Header
->SecurityDescriptor
,
865 Type
->TypeInfo
.PoolType
,
866 &Type
->TypeInfo
.GenericMapping
);
868 /* Dereference the object */
869 ObDereferenceObject(Object
);
871 /* Protect write with SEH */
874 /* Return the needed length */
875 *ResultLength
= Length
;
877 _SEH2_EXCEPT(ExSystemExceptionFilter())
879 /* Get the exception code */
880 Status
= _SEH2_GetExceptionCode();
889 * @name NtSetSecurityObject
892 * The NtSetSecurityObject routine <FILLMEIN>
897 * @param SecurityInformation
900 * @param SecurityDescriptor
903 * @return STATUS_SUCCESS or appropriate error value.
910 NtSetSecurityObject(IN HANDLE Handle
,
911 IN SECURITY_INFORMATION SecurityInformation
,
912 IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
914 KPROCESSOR_MODE PreviousMode
= ExGetPreviousMode();
916 SECURITY_DESCRIPTOR_RELATIVE
*CapturedDescriptor
;
917 ACCESS_MASK DesiredAccess
= 0;
921 /* Make sure the caller doesn't pass a NULL security descriptor! */
922 if (!SecurityDescriptor
) return STATUS_ACCESS_VIOLATION
;
924 /* Set the required access rights for the operation */
925 SeSetSecurityAccessMask(SecurityInformation
, &DesiredAccess
);
927 /* Reference the object */
928 Status
= ObReferenceObjectByHandle(Handle
,
934 if (NT_SUCCESS(Status
))
936 /* Capture and make a copy of the security descriptor */
937 Status
= SeCaptureSecurityDescriptor(SecurityDescriptor
,
941 (PSECURITY_DESCRIPTOR
*)
942 &CapturedDescriptor
);
943 if (!NT_SUCCESS(Status
))
946 ObDereferenceObject(Object
);
951 ASSERT(CapturedDescriptor
->Control
& SE_SELF_RELATIVE
);
954 * Make sure the security descriptor passed by the caller
955 * is valid for the operation we're about to perform
957 if (((SecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
958 !(CapturedDescriptor
->Owner
)) ||
959 ((SecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
960 !(CapturedDescriptor
->Group
)))
962 /* Set the failure status */
963 Status
= STATUS_INVALID_SECURITY_DESCR
;
968 Status
= ObSetSecurityObjectByPointer(Object
,
973 /* Release the descriptor and return status */
974 SeReleaseSecurityDescriptor((PSECURITY_DESCRIPTOR
)CapturedDescriptor
,
978 /* Now we can dereference the object */
979 ObDereferenceObject(Object
);
986 * @name ObQueryObjectAuditingByHandle
989 * The ObDereferenceSecurityDescriptor routine <FILLMEIN>
991 * @param SecurityDescriptor
997 * @return STATUS_SUCCESS or appropriate error value.
1004 ObQueryObjectAuditingByHandle(IN HANDLE Handle
,
1005 OUT PBOOLEAN GenerateOnClose
)
1007 PHANDLE_TABLE_ENTRY HandleEntry
;
1009 NTSTATUS Status
= STATUS_SUCCESS
;
1012 /* Check if we're dealing with a kernel handle */
1013 if (ObpIsKernelHandle(Handle
, ExGetPreviousMode()))
1015 /* Use the kernel table and convert the handle */
1016 HandleTable
= ObpKernelHandleTable
;
1017 Handle
= ObKernelHandleToHandle(Handle
);
1021 /* Use the process's handle table */
1022 HandleTable
= PsGetCurrentProcess()->ObjectTable
;
1025 /* Enter a critical region while we touch the handle table */
1026 KeEnterCriticalRegion();
1028 /* Map the handle */
1029 HandleEntry
= ExMapHandleToPointer(HandleTable
, Handle
);
1032 /* Check if the flag is set */
1033 *GenerateOnClose
= HandleEntry
->ObAttributes
& OBJ_AUDIT_OBJECT_CLOSE
;
1035 /* Unlock the entry */
1036 ExUnlockHandleTableEntry(HandleTable
, HandleEntry
);
1040 /* Otherwise, fail */
1041 Status
= STATUS_INVALID_HANDLE
;
1044 /* Leave the critical region and return the status */
1045 KeLeaveCriticalRegion();