大槪就是看这个句柄是当前进程的句柄还是当前线程的句柄,最后再看看这AccessMode是内核还是用户态下,内核的话,句柄表就用ObpKernelHandleTable,用户态的话就用当前进程的句柄表
NTSTATUS
ObReferenceObjectByHandle (
__in HANDLE Handle,
__in ACCESS_MASK DesiredAccess,
__in_opt POBJECT_TYPE ObjectType,
__in KPROCESSOR_MODE AccessMode,
__out PVOID *Object,
__out_opt POBJECT_HANDLE_INFORMATION HandleInformation
)
/*++
Routine Description:
Given a handle to an object this routine returns a pointer
to the body of the object with proper ref counts
Arguments:
Handle - Supplies a handle to the object being referenced. It can
also be the result of NtCurrentProcess or NtCurrentThread
DesiredAccess - Supplies the access being requested by the caller
ObjectType - Optionally supplies the type of the object we
are expecting
AccessMode - Supplies the processor mode of the access
Object - Receives a pointer to the object body if the operation
is successful
HandleInformation - Optionally receives information regarding the
input handle.
Return Value:
An appropriate NTSTATUS value
--*/
{
ACCESS_MASK GrantedAccess;
PHANDLE_TABLE HandleTable;
POBJECT_HEADER ObjectHeader;
PHANDLE_TABLE_ENTRY ObjectTableEntry;
PEPROCESS Process;
NTSTATUS Status;
PETHREAD Thread;
ObpValidateIrql("ObReferenceObjectByHandle");
Thread = PsGetCurrentThread ();//得到调用ObReferenceObjectByHandle当前线程
*Object = NULL;
//
// Check is this handle is a kernel handle or one of the two builtin pseudo handles
//
if ((LONG)(ULONG_PTR) Handle < 0) {
//
// If the handle is equal to the current process handle and the object
// type is NULL or type process, then attempt to translate a handle to
// the current process. Otherwise, check if the handle is the current
// thread handle.
//
if (Handle == NtCurrentProcess()) { //如果句柄等于当前进程的句柄
if ((ObjectType == PsProcessType) || (ObjectType == NULL)) {
Process = PsGetCurrentProcessByThread(Thread);//得到当前Eprocess对象
GrantedAccess = Process->GrantedAccess;
if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) ||
(AccessMode == KernelMode)) {
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process);//得到Eprocess对象头
if (ARGUMENT_PRESENT(HandleInformation)) {
HandleInformation->GrantedAccess = GrantedAccess;
HandleInformation->HandleAttributes = 0;
}
ObpIncrPointerCount(ObjectHeader);//增加对象引用计数
*Object = Process;//返回对象体指针
ASSERT( *Object != NULL );
Status = STATUS_SUCCESS;
} else {
Status = STATUS_ACCESS_DENIED;
}
} else {
Status = STATUS_OBJECT_TYPE_MISMATCH;
}
return Status;
//
// If the handle is equal to the current thread handle and the object
// type is NULL or type thread, then attempt to translate a handle to
// the current thread. Otherwise, the we'll try and translate the
// handle
//
} else if (Handle == NtCurrentThread()) {
if ((ObjectType == PsThreadType) || (ObjectType == NULL)) {
GrantedAccess = Thread->GrantedAccess;
if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) ||
(AccessMode == KernelMode)) {
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread);//得到当前线程的对象头
if (ARGUMENT_PRESENT(HandleInformation)) {
HandleInformation->GrantedAccess = GrantedAccess;
HandleInformation->HandleAttributes = 0;
}
ObpIncrPointerCount(ObjectHeader);//增加对象头的引用计数
*Object = Thread;//返回对象体指针
ASSERT( *Object != NULL );
Status = STATUS_SUCCESS;
} else {
Status = STATUS_ACCESS_DENIED;
}
} else {
Status = STATUS_OBJECT_TYPE_MISMATCH;
}
return Status;
} else if (AccessMode == KernelMode)//如果是在内核模式调用的
{
//
// Make the handle look like a regular handle
//
Handle = DecodeKernelHandle( Handle );
//
// The global kernel handle table
//
HandleTable = ObpKernelHandleTable;
} else {
//
// The previous mode was user for this kernel handle value. Reject it here.
//
return STATUS_INVALID_HANDLE;
}
} else {
HandleTable = PsGetCurrentProcessByThread(Thread)->ObjectTable;//否则的话等于当前调用进程的句柄表
}
ASSERT(HandleTable != NULL);
//
// Protect this thread from being suspended while we hold the handle table entry lock
//
KeEnterCriticalRegionThread(&Thread->Tcb);
//
// Translate the specified handle to an object table index.
//
ObjectTableEntry = ExMapHandleToPointerEx ( HandleTable, Handle, AccessMode );//得到Handle_Table_Entry结构指针
//
// Make sure the object table entry really does exist
//
if (ObjectTableEntry != NULL) {
ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES);//得到对象头
//
// Optimize for a successful reference by bringing the object header
// into the cache exclusive.
//
ReadForWriteAccess(ObjectHeader);
if ((ObjectHeader->Type == ObjectType) || (ObjectType == NULL)) {
#if i386
if (NtGlobalFlag & FLG_KERNEL_STACK_TRACE_DB) {
GrantedAccess = ObpTranslateGrantedAccessIndex( ObjectTableEntry->GrantedAccessIndex );
} else {
GrantedAccess = ObpDecodeGrantedAccess(ObjectTableEntry->GrantedAccess);
}
#else
GrantedAccess = ObpDecodeGrantedAccess(ObjectTableEntry->GrantedAccess);
#endif // i386
if ((SeComputeDeniedAccesses(GrantedAccess, DesiredAccess) == 0) ||
(AccessMode == KernelMode)) {
PHANDLE_TABLE_ENTRY_INFO ObjectInfo;
ObjectInfo = ExGetHandleInfo(HandleTable, Handle, TRUE);
//
// Access to the object is allowed. Return the handle
// information is requested, increment the object
// pointer count, unlock the handle table and return
// a success status.
//
// Note that this is the only successful return path
// out of this routine if the user did not specify
// the current process or current thread in the input
// handle.
//
if (ARGUMENT_PRESENT(HandleInformation)) {
HandleInformation->GrantedAccess = GrantedAccess;
HandleInformation->HandleAttributes = ObpGetHandleAttributes(ObjectTableEntry);
}
//
// If this object was audited when it was opened, it may
// be necessary to generate an audit now. Check the audit
// mask that was saved when the handle was created.
//
// It is safe to do this check in a non-atomic fashion,
// because bits will never be added to this mask once it is
// created.
//
if ( (ObjectTableEntry->ObAttributes & OBJ_AUDIT_OBJECT_CLOSE) &&
(ObjectInfo != NULL) &&
(ObjectInfo->AuditMask != 0) &&
(DesiredAccess != 0)) {
ObpAuditObjectAccess( Handle, ObjectInfo, &ObjectHeader->Type->Name, DesiredAccess );
}
ObpIncrPointerCount(ObjectHeader);
ExUnlockHandleTableEntry( HandleTable, ObjectTableEntry );
KeLeaveCriticalRegionThread(&Thread->Tcb);
*Object = &ObjectHeader->Body;
ASSERT( *Object != NULL );
return STATUS_SUCCESS;
} else {
Status = STATUS_ACCESS_DENIED;
}
} else {
Status = STATUS_OBJECT_TYPE_MISMATCH;
}
ExUnlockHandleTableEntry( HandleTable, ObjectTableEntry );
} else {
Status = STATUS_INVALID_HANDLE;
}
KeLeaveCriticalRegionThread(&Thread->Tcb);
return Status;
}