mirror of
https://github.com/reactos/reactos.git
synced 2025-01-01 03:54:02 +00:00
- Fixed formatting/commented/annotated ObReferenceObjectByHandle.
- Bug fixes: * Remove MAXIMUM_ALLOWED<->GENERIC_ALL conversion, I could find no mention of this in the docs. * Remove GENERIC_ACCESS <-> RtlMapGenericMask conversion, I could find no mention of this in the docs, and this mapping is only required when creating handles, not when referencing pointers. - Optimizations: * Restructure code and remove code which was sometimes duplicated up to 5 times. * Do not attach/detach from the system process, this isn't required since we're merely getting a kernel pointer from the handle netry. * Directly increase the pointer count instead of calling ObReferenceObject, since we already have the object header in a variable. * Cache ObpKernelHandleTable/Process->ObjectTable and use those directly instead of always de-referencing the process. svn path=/trunk/; revision=22231
This commit is contained in:
parent
36f116cdd8
commit
0aeaea0fb7
2 changed files with 119 additions and 140 deletions
|
@ -194,6 +194,14 @@ SmBeginClientInitialization (IN PSM_PORT_MESSAGE Request,
|
||||||
SmpClientDirectory.CandidateClient->ServerProcessId =
|
SmpClientDirectory.CandidateClient->ServerProcessId =
|
||||||
(ULONG) pbi.UniqueProcessId;
|
(ULONG) pbi.UniqueProcessId;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LARGE_INTEGER Fixme;
|
||||||
|
Fixme.QuadPart = -50000000;
|
||||||
|
DPRINT1("WARNING! UniqueProcess IS A THREAD HANDLE!!!\n");
|
||||||
|
NtDelayExecution(FALSE, &Fixme);
|
||||||
|
DPRINT1("FIXME!\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -129,6 +129,18 @@ ObfDereferenceObject(IN PVOID Object)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ObDereferenceObject
|
||||||
|
#undef ObDereferenceObject
|
||||||
|
#endif
|
||||||
|
|
||||||
|
VOID
|
||||||
|
NTAPI
|
||||||
|
ObDereferenceObject(IN PVOID Object)
|
||||||
|
{
|
||||||
|
/* Call the fastcall function */
|
||||||
|
ObfDereferenceObject(Object);
|
||||||
|
}
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
ObReferenceObjectByPointer(IN PVOID Object,
|
ObReferenceObjectByPointer(IN PVOID Object,
|
||||||
|
@ -228,206 +240,165 @@ Quickie:
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS STDCALL
|
NTSTATUS
|
||||||
ObReferenceObjectByHandle(HANDLE Handle,
|
NTAPI
|
||||||
ACCESS_MASK DesiredAccess,
|
ObReferenceObjectByHandle(IN HANDLE Handle,
|
||||||
POBJECT_TYPE ObjectType,
|
IN ACCESS_MASK DesiredAccess,
|
||||||
KPROCESSOR_MODE AccessMode,
|
IN POBJECT_TYPE ObjectType,
|
||||||
PVOID* Object,
|
IN KPROCESSOR_MODE AccessMode,
|
||||||
POBJECT_HANDLE_INFORMATION HandleInformation)
|
OUT PVOID* Object,
|
||||||
|
OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
|
||||||
{
|
{
|
||||||
PHANDLE_TABLE_ENTRY HandleEntry;
|
PHANDLE_TABLE_ENTRY HandleEntry;
|
||||||
POBJECT_HEADER ObjectHeader;
|
POBJECT_HEADER ObjectHeader;
|
||||||
PVOID ObjectBody;
|
|
||||||
ACCESS_MASK GrantedAccess;
|
ACCESS_MASK GrantedAccess;
|
||||||
ULONG Attributes;
|
ULONG Attributes;
|
||||||
PEPROCESS CurrentProcess, Process;
|
PEPROCESS CurrentProcess;
|
||||||
BOOLEAN AttachedToProcess = FALSE;
|
PVOID HandleTable;
|
||||||
KAPC_STATE ApcState;
|
PETHREAD CurrentThread;
|
||||||
|
NTSTATUS Status;
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
|
|
||||||
DPRINT("ObReferenceObjectByHandle(Handle %p, DesiredAccess %x, "
|
/* Fail immediately if the handle is NULL */
|
||||||
"ObjectType %p, AccessMode %d, Object %p)\n",Handle,DesiredAccess,
|
if (!Handle) return STATUS_INVALID_HANDLE;
|
||||||
ObjectType,AccessMode,Object);
|
|
||||||
|
|
||||||
if (Handle == NULL)
|
/* Check if the caller wants the current process */
|
||||||
|
if ((Handle == NtCurrentProcess()) &&
|
||||||
|
((ObjectType == PsProcessType) || !(ObjectType)))
|
||||||
{
|
{
|
||||||
return STATUS_INVALID_HANDLE;
|
/* Get the current process */
|
||||||
}
|
CurrentProcess = PsGetCurrentProcess();
|
||||||
|
|
||||||
CurrentProcess = PsGetCurrentProcess();
|
/* Reference ourselves */
|
||||||
|
|
||||||
/*
|
|
||||||
* Handle special handle names
|
|
||||||
*/
|
|
||||||
if (Handle == NtCurrentProcess() &&
|
|
||||||
(ObjectType == PsProcessType || ObjectType == NULL))
|
|
||||||
{
|
|
||||||
ObReferenceObject(CurrentProcess);
|
ObReferenceObject(CurrentProcess);
|
||||||
|
|
||||||
if (HandleInformation != NULL)
|
/* Check if the caller wanted handle information */
|
||||||
|
if (HandleInformation)
|
||||||
{
|
{
|
||||||
|
/* Return it */
|
||||||
HandleInformation->HandleAttributes = 0;
|
HandleInformation->HandleAttributes = 0;
|
||||||
HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
|
HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the pointer */
|
||||||
*Object = CurrentProcess;
|
*Object = CurrentProcess;
|
||||||
DPRINT("Referencing current process %p\n", CurrentProcess);
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
else if (Handle == NtCurrentProcess())
|
else if (Handle == NtCurrentProcess())
|
||||||
{
|
{
|
||||||
CHECKPOINT;
|
/* The caller used this special handle value with a non-process type */
|
||||||
return(STATUS_OBJECT_TYPE_MISMATCH);
|
return STATUS_OBJECT_TYPE_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Handle == NtCurrentThread() &&
|
/* Check if the caller wants the current thread */
|
||||||
(ObjectType == PsThreadType || ObjectType == NULL))
|
if ((Handle == NtCurrentThread()) &&
|
||||||
|
((ObjectType == PsThreadType) || !(ObjectType)))
|
||||||
{
|
{
|
||||||
PETHREAD CurrentThread = PsGetCurrentThread();
|
/* Get the current thread */
|
||||||
|
CurrentThread = PsGetCurrentThread();
|
||||||
|
|
||||||
|
/* Reference ourselves */
|
||||||
ObReferenceObject(CurrentThread);
|
ObReferenceObject(CurrentThread);
|
||||||
|
|
||||||
if (HandleInformation != NULL)
|
/* Check if the caller wanted handle information */
|
||||||
|
if (HandleInformation)
|
||||||
{
|
{
|
||||||
|
/* Return it */
|
||||||
HandleInformation->HandleAttributes = 0;
|
HandleInformation->HandleAttributes = 0;
|
||||||
HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
|
HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the pointer */
|
||||||
*Object = CurrentThread;
|
*Object = CurrentThread;
|
||||||
CHECKPOINT;
|
|
||||||
return STATUS_SUCCESS;
|
return STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
else if (Handle == NtCurrentThread())
|
else if (Handle == NtCurrentThread())
|
||||||
{
|
{
|
||||||
CHECKPOINT;
|
/* The caller used this special handle value with a non-thread type */
|
||||||
return(STATUS_OBJECT_TYPE_MISMATCH);
|
return STATUS_OBJECT_TYPE_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* desire as much access rights as possible */
|
/* Check if this is a kernel handle */
|
||||||
if (DesiredAccess & MAXIMUM_ALLOWED)
|
if (ObIsKernelHandle(Handle, AccessMode))
|
||||||
{
|
{
|
||||||
DesiredAccess &= ~MAXIMUM_ALLOWED;
|
/* Use the kernel handle table and get the actual handle value */
|
||||||
DesiredAccess |= GENERIC_ALL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(ObIsKernelHandle(Handle, AccessMode))
|
|
||||||
{
|
|
||||||
Process = PsInitialSystemProcess;
|
|
||||||
Handle = ObKernelHandleToHandle(Handle);
|
Handle = ObKernelHandleToHandle(Handle);
|
||||||
|
HandleTable = ObpKernelHandleTable;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Process = CurrentProcess;
|
/* Otherwise use this process's handle table */
|
||||||
|
HandleTable = PsGetCurrentProcess()->ObjectTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Enter a critical region while we touch the handle table */
|
||||||
KeEnterCriticalRegion();
|
KeEnterCriticalRegion();
|
||||||
|
|
||||||
if (Process != CurrentProcess)
|
/* Get the handle entry */
|
||||||
|
HandleEntry = ExMapHandleToPointer(HandleTable, Handle);
|
||||||
|
if (HandleEntry)
|
||||||
{
|
{
|
||||||
KeStackAttachProcess(&Process->Pcb,
|
/* Get the object header and validate the type*/
|
||||||
&ApcState);
|
ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
|
||||||
AttachedToProcess = TRUE;
|
if (!(ObjectType) || (ObjectType == ObjectHeader->Type))
|
||||||
}
|
|
||||||
|
|
||||||
HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
|
|
||||||
Handle);
|
|
||||||
if (HandleEntry == NULL)
|
|
||||||
{
|
|
||||||
if (AttachedToProcess)
|
|
||||||
{
|
{
|
||||||
KeUnstackDetachProcess(&ApcState);
|
/* Get the granted access and validate it */
|
||||||
|
GrantedAccess = HandleEntry->GrantedAccess;
|
||||||
|
if ((AccessMode == KernelMode) ||
|
||||||
|
!(~GrantedAccess & DesiredAccess))
|
||||||
|
{
|
||||||
|
/* Reference the object directly since we have its header */
|
||||||
|
InterlockedIncrement(&ObjectHeader->PointerCount);
|
||||||
|
|
||||||
|
/* Mask out the internal attributes */
|
||||||
|
Attributes = HandleEntry->ObAttributes &
|
||||||
|
(EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
|
||||||
|
EX_HANDLE_ENTRY_INHERITABLE |
|
||||||
|
EX_HANDLE_ENTRY_AUDITONCLOSE);
|
||||||
|
|
||||||
|
/* Check if the caller wants handle information */
|
||||||
|
if (HandleInformation)
|
||||||
|
{
|
||||||
|
/* Fill out the information */
|
||||||
|
HandleInformation->HandleAttributes = Attributes;
|
||||||
|
HandleInformation->GrantedAccess = GrantedAccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the pointer */
|
||||||
|
*Object = &ObjectHeader->Body;
|
||||||
|
|
||||||
|
/* Unlock the handle */
|
||||||
|
ExUnlockHandleTableEntry(HandleTable, HandleEntry);
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
KeLeaveCriticalRegion();
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Requested access failed */
|
||||||
|
Status = STATUS_ACCESS_DENIED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
KeLeaveCriticalRegion();
|
else
|
||||||
DPRINT("ExMapHandleToPointer() failed for handle 0x%p\n", Handle);
|
|
||||||
return(STATUS_INVALID_HANDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectHeader = EX_HTE_TO_HDR(HandleEntry);
|
|
||||||
ObjectBody = &ObjectHeader->Body;
|
|
||||||
|
|
||||||
DPRINT("locked1: ObjectHeader: 0x%p [HT:0x%p]\n", ObjectHeader, Process->ObjectTable);
|
|
||||||
|
|
||||||
if (ObjectType != NULL && ObjectType != ObjectHeader->Type)
|
|
||||||
{
|
|
||||||
DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%p)\n", &ObjectType->Name, ObjectHeader->Type ? &ObjectHeader->Type->Name : NULL, Handle);
|
|
||||||
|
|
||||||
ExUnlockHandleTableEntry(Process->ObjectTable,
|
|
||||||
HandleEntry);
|
|
||||||
|
|
||||||
if (AttachedToProcess)
|
|
||||||
{
|
{
|
||||||
KeUnstackDetachProcess(&ApcState);
|
/* Invalid object type */
|
||||||
|
Status = STATUS_OBJECT_TYPE_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeLeaveCriticalRegion();
|
/* Unlock the entry */
|
||||||
|
ExUnlockHandleTableEntry(HandleTable, HandleEntry);
|
||||||
return(STATUS_OBJECT_TYPE_MISMATCH);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
/* map the generic access masks if the caller asks for generic access */
|
|
||||||
if (DesiredAccess & GENERIC_ACCESS)
|
|
||||||
{
|
{
|
||||||
RtlMapGenericMask(&DesiredAccess,
|
/* Invalid handle */
|
||||||
&OBJECT_TO_OBJECT_HEADER(ObjectBody)->Type->TypeInfo.GenericMapping);
|
Status = STATUS_INVALID_HANDLE;
|
||||||
}
|
|
||||||
|
|
||||||
GrantedAccess = HandleEntry->GrantedAccess;
|
|
||||||
|
|
||||||
/* Unless running as KernelMode, deny access if caller desires more access
|
|
||||||
rights than the handle can grant */
|
|
||||||
if(AccessMode != KernelMode && (~GrantedAccess & DesiredAccess))
|
|
||||||
{
|
|
||||||
ExUnlockHandleTableEntry(Process->ObjectTable,
|
|
||||||
HandleEntry);
|
|
||||||
|
|
||||||
if (AttachedToProcess)
|
|
||||||
{
|
|
||||||
KeUnstackDetachProcess(&ApcState);
|
|
||||||
}
|
|
||||||
|
|
||||||
KeLeaveCriticalRegion();
|
|
||||||
|
|
||||||
DPRINT1("GrantedAccess: 0x%x, ~GrantedAccess: 0x%x, DesiredAccess: 0x%x, denied: 0x%x\n", GrantedAccess, ~GrantedAccess, DesiredAccess, ~GrantedAccess & DesiredAccess);
|
|
||||||
|
|
||||||
return(STATUS_ACCESS_DENIED);
|
|
||||||
}
|
|
||||||
|
|
||||||
ObReferenceObject(ObjectBody);
|
|
||||||
|
|
||||||
Attributes = HandleEntry->ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
|
|
||||||
EX_HANDLE_ENTRY_INHERITABLE |
|
|
||||||
EX_HANDLE_ENTRY_AUDITONCLOSE);
|
|
||||||
|
|
||||||
ExUnlockHandleTableEntry(Process->ObjectTable,
|
|
||||||
HandleEntry);
|
|
||||||
|
|
||||||
if (AttachedToProcess)
|
|
||||||
{
|
|
||||||
KeUnstackDetachProcess(&ApcState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return failure status */
|
||||||
KeLeaveCriticalRegion();
|
KeLeaveCriticalRegion();
|
||||||
|
*Object = NULL;
|
||||||
if (HandleInformation != NULL)
|
return Status;
|
||||||
{
|
|
||||||
HandleInformation->HandleAttributes = Attributes;
|
|
||||||
HandleInformation->GrantedAccess = GrantedAccess;
|
|
||||||
}
|
|
||||||
|
|
||||||
*Object = ObjectBody;
|
|
||||||
|
|
||||||
return(STATUS_SUCCESS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ObDereferenceObject
|
|
||||||
#undef ObDereferenceObject
|
|
||||||
#endif
|
|
||||||
|
|
||||||
VOID STDCALL
|
|
||||||
ObDereferenceObject(IN PVOID Object)
|
|
||||||
{
|
|
||||||
ObfDereferenceObject(Object);
|
|
||||||
}
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Reference in a new issue