mirror of
https://github.com/reactos/reactos.git
synced 2024-12-29 02:25:17 +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 =
|
||||
(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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
NTAPI
|
||||
ObReferenceObjectByPointer(IN PVOID Object,
|
||||
|
@ -228,206 +240,165 @@ Quickie:
|
|||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS STDCALL
|
||||
ObReferenceObjectByHandle(HANDLE Handle,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_TYPE ObjectType,
|
||||
KPROCESSOR_MODE AccessMode,
|
||||
PVOID* Object,
|
||||
POBJECT_HANDLE_INFORMATION HandleInformation)
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
ObReferenceObjectByHandle(IN HANDLE Handle,
|
||||
IN ACCESS_MASK DesiredAccess,
|
||||
IN POBJECT_TYPE ObjectType,
|
||||
IN KPROCESSOR_MODE AccessMode,
|
||||
OUT PVOID* Object,
|
||||
OUT POBJECT_HANDLE_INFORMATION HandleInformation OPTIONAL)
|
||||
{
|
||||
PHANDLE_TABLE_ENTRY HandleEntry;
|
||||
POBJECT_HEADER ObjectHeader;
|
||||
PVOID ObjectBody;
|
||||
ACCESS_MASK GrantedAccess;
|
||||
ULONG Attributes;
|
||||
PEPROCESS CurrentProcess, Process;
|
||||
BOOLEAN AttachedToProcess = FALSE;
|
||||
KAPC_STATE ApcState;
|
||||
|
||||
PEPROCESS CurrentProcess;
|
||||
PVOID HandleTable;
|
||||
PETHREAD CurrentThread;
|
||||
NTSTATUS Status;
|
||||
PAGED_CODE();
|
||||
|
||||
DPRINT("ObReferenceObjectByHandle(Handle %p, DesiredAccess %x, "
|
||||
"ObjectType %p, AccessMode %d, Object %p)\n",Handle,DesiredAccess,
|
||||
ObjectType,AccessMode,Object);
|
||||
/* Fail immediately if the handle is NULL */
|
||||
if (!Handle) return STATUS_INVALID_HANDLE;
|
||||
|
||||
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();
|
||||
|
||||
/*
|
||||
* Handle special handle names
|
||||
*/
|
||||
if (Handle == NtCurrentProcess() &&
|
||||
(ObjectType == PsProcessType || ObjectType == NULL))
|
||||
{
|
||||
/* Reference ourselves */
|
||||
ObReferenceObject(CurrentProcess);
|
||||
|
||||
if (HandleInformation != NULL)
|
||||
/* Check if the caller wanted handle information */
|
||||
if (HandleInformation)
|
||||
{
|
||||
/* Return it */
|
||||
HandleInformation->HandleAttributes = 0;
|
||||
HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS;
|
||||
}
|
||||
|
||||
/* Return the pointer */
|
||||
*Object = CurrentProcess;
|
||||
DPRINT("Referencing current process %p\n", CurrentProcess);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (Handle == NtCurrentProcess())
|
||||
{
|
||||
CHECKPOINT;
|
||||
return(STATUS_OBJECT_TYPE_MISMATCH);
|
||||
/* The caller used this special handle value with a non-process type */
|
||||
return STATUS_OBJECT_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
if (Handle == NtCurrentThread() &&
|
||||
(ObjectType == PsThreadType || ObjectType == NULL))
|
||||
/* Check if the caller wants the current thread */
|
||||
if ((Handle == NtCurrentThread()) &&
|
||||
((ObjectType == PsThreadType) || !(ObjectType)))
|
||||
{
|
||||
PETHREAD CurrentThread = PsGetCurrentThread();
|
||||
/* Get the current thread */
|
||||
CurrentThread = PsGetCurrentThread();
|
||||
|
||||
/* Reference ourselves */
|
||||
ObReferenceObject(CurrentThread);
|
||||
|
||||
if (HandleInformation != NULL)
|
||||
/* Check if the caller wanted handle information */
|
||||
if (HandleInformation)
|
||||
{
|
||||
/* Return it */
|
||||
HandleInformation->HandleAttributes = 0;
|
||||
HandleInformation->GrantedAccess = THREAD_ALL_ACCESS;
|
||||
}
|
||||
|
||||
/* Return the pointer */
|
||||
*Object = CurrentThread;
|
||||
CHECKPOINT;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else if (Handle == NtCurrentThread())
|
||||
{
|
||||
CHECKPOINT;
|
||||
return(STATUS_OBJECT_TYPE_MISMATCH);
|
||||
/* The caller used this special handle value with a non-thread type */
|
||||
return STATUS_OBJECT_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
/* desire as much access rights as possible */
|
||||
if (DesiredAccess & MAXIMUM_ALLOWED)
|
||||
/* Check if this is a kernel handle */
|
||||
if (ObIsKernelHandle(Handle, AccessMode))
|
||||
{
|
||||
DesiredAccess &= ~MAXIMUM_ALLOWED;
|
||||
DesiredAccess |= GENERIC_ALL;
|
||||
}
|
||||
|
||||
if(ObIsKernelHandle(Handle, AccessMode))
|
||||
{
|
||||
Process = PsInitialSystemProcess;
|
||||
/* Use the kernel handle table and get the actual handle value */
|
||||
Handle = ObKernelHandleToHandle(Handle);
|
||||
HandleTable = ObpKernelHandleTable;
|
||||
}
|
||||
else
|
||||
{
|
||||
Process = CurrentProcess;
|
||||
/* Otherwise use this process's handle table */
|
||||
HandleTable = PsGetCurrentProcess()->ObjectTable;
|
||||
}
|
||||
|
||||
/* Enter a critical region while we touch the handle table */
|
||||
KeEnterCriticalRegion();
|
||||
|
||||
if (Process != CurrentProcess)
|
||||
/* Get the handle entry */
|
||||
HandleEntry = ExMapHandleToPointer(HandleTable, Handle);
|
||||
if (HandleEntry)
|
||||
{
|
||||
KeStackAttachProcess(&Process->Pcb,
|
||||
&ApcState);
|
||||
AttachedToProcess = TRUE;
|
||||
}
|
||||
|
||||
HandleEntry = ExMapHandleToPointer(Process->ObjectTable,
|
||||
Handle);
|
||||
if (HandleEntry == NULL)
|
||||
{
|
||||
if (AttachedToProcess)
|
||||
{
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
KeLeaveCriticalRegion();
|
||||
DPRINT("ExMapHandleToPointer() failed for handle 0x%p\n", Handle);
|
||||
return(STATUS_INVALID_HANDLE);
|
||||
}
|
||||
|
||||
/* Get the object header and validate the type*/
|
||||
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)
|
||||
if (!(ObjectType) || (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);
|
||||
}
|
||||
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
return(STATUS_OBJECT_TYPE_MISMATCH);
|
||||
}
|
||||
|
||||
/* map the generic access masks if the caller asks for generic access */
|
||||
if (DesiredAccess & GENERIC_ACCESS)
|
||||
{
|
||||
RtlMapGenericMask(&DesiredAccess,
|
||||
&OBJECT_TO_OBJECT_HEADER(ObjectBody)->Type->TypeInfo.GenericMapping);
|
||||
}
|
||||
|
||||
/* Get the granted access and validate it */
|
||||
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))
|
||||
if ((AccessMode == KernelMode) ||
|
||||
!(~GrantedAccess & DesiredAccess))
|
||||
{
|
||||
ExUnlockHandleTableEntry(Process->ObjectTable,
|
||||
HandleEntry);
|
||||
/* Reference the object directly since we have its header */
|
||||
InterlockedIncrement(&ObjectHeader->PointerCount);
|
||||
|
||||
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 |
|
||||
/* Mask out the internal attributes */
|
||||
Attributes = HandleEntry->ObAttributes &
|
||||
(EX_HANDLE_ENTRY_PROTECTFROMCLOSE |
|
||||
EX_HANDLE_ENTRY_INHERITABLE |
|
||||
EX_HANDLE_ENTRY_AUDITONCLOSE);
|
||||
|
||||
ExUnlockHandleTableEntry(Process->ObjectTable,
|
||||
HandleEntry);
|
||||
|
||||
if (AttachedToProcess)
|
||||
{
|
||||
KeUnstackDetachProcess(&ApcState);
|
||||
}
|
||||
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
if (HandleInformation != NULL)
|
||||
/* Check if the caller wants handle information */
|
||||
if (HandleInformation)
|
||||
{
|
||||
/* Fill out the information */
|
||||
HandleInformation->HandleAttributes = Attributes;
|
||||
HandleInformation->GrantedAccess = GrantedAccess;
|
||||
}
|
||||
|
||||
*Object = ObjectBody;
|
||||
/* Return the pointer */
|
||||
*Object = &ObjectHeader->Body;
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
/* Unlock the handle */
|
||||
ExUnlockHandleTableEntry(HandleTable, HandleEntry);
|
||||
|
||||
/* Return success */
|
||||
KeLeaveCriticalRegion();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Requested access failed */
|
||||
Status = STATUS_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid object type */
|
||||
Status = STATUS_OBJECT_TYPE_MISMATCH;
|
||||
}
|
||||
|
||||
/* Unlock the entry */
|
||||
ExUnlockHandleTableEntry(HandleTable, HandleEntry);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Invalid handle */
|
||||
Status = STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/* Return failure status */
|
||||
KeLeaveCriticalRegion();
|
||||
*Object = NULL;
|
||||
return Status;
|
||||
}
|
||||
|
||||
#ifdef ObDereferenceObject
|
||||
#undef ObDereferenceObject
|
||||
#endif
|
||||
|
||||
VOID STDCALL
|
||||
ObDereferenceObject(IN PVOID Object)
|
||||
{
|
||||
ObfDereferenceObject(Object);
|
||||
}
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue