diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h index 7e539064202..255765fb2e1 100644 --- a/reactos/ntoskrnl/include/internal/ob.h +++ b/reactos/ntoskrnl/include/internal/ob.h @@ -242,6 +242,14 @@ enum extern PDIRECTORY_OBJECT NameSpaceRoot; extern POBJECT_TYPE ObSymbolicLinkType; +extern PHANDLE_TABLE ObpKernelHandleTable; + +#define KERNEL_HANDLE_FLAG (1 << ((sizeof(HANDLE) * 8) - 1)) +#define ObIsKernelHandle(Handle, ProcessorMode) \ + (((ULONG_PTR)(Handle) & KERNEL_HANDLE_FLAG) && \ + ((ProcessorMode) == KernelMode)) +#define ObKernelHandleToHandle(Handle) \ + (HANDLE)((ULONG_PTR)(Handle) & ~KERNEL_HANDLE_FLAG) VOID ObpAddEntryDirectory(PDIRECTORY_OBJECT Parent, POBJECT_HEADER Header, @@ -266,10 +274,6 @@ NTSTATUS ObFindObject(POBJECT_ATTRIBUTES ObjectAttributes, POBJECT_TYPE ObjectType); VOID ObDeleteHandleTable(struct _EPROCESS* Process); -NTSTATUS -ObDeleteHandle(PEPROCESS Process, - HANDLE Handle); - NTSTATUS ObpQueryHandleAttributes(HANDLE Handle, POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo); diff --git a/reactos/ntoskrnl/ob/handle.c b/reactos/ntoskrnl/ob/handle.c index bf59c501975..3756959e8bc 100644 --- a/reactos/ntoskrnl/ob/handle.c +++ b/reactos/ntoskrnl/ob/handle.c @@ -42,6 +42,10 @@ #define GENERIC_ANY (GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | GENERIC_ALL) +/* GLOBALS *****************************************************************/ + +PHANDLE_TABLE ObpKernelHandleTable = NULL; + /* FUNCTIONS ***************************************************************/ VOID @@ -51,7 +55,7 @@ ObKillProcess(PEPROCESS Process) ObDeleteHandleTable(Process); } -VOID +static VOID ObpDecrementHandleCount(PVOID ObjectBody) { POBJECT_HEADER ObjectHeader = BODY_TO_HEADER(ObjectBody); @@ -76,19 +80,28 @@ NTSTATUS ObpQueryHandleAttributes(HANDLE Handle, POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo) { - PEPROCESS Process; + PHANDLE_TABLE HandleTable; PHANDLE_TABLE_ENTRY HandleTableEntry; - LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle); + LONG ExHandle; PAGED_CODE(); DPRINT("ObpQueryHandleAttributes(Handle %x)\n", Handle); + + if(ObIsKernelHandle(Handle, ExGetPreviousMode())) + { + HandleTable = ObpKernelHandleTable; + ExHandle = HANDLE_TO_EX_HANDLE(ObKernelHandleToHandle(Handle)); + } + else + { + HandleTable = PsGetCurrentProcess()->ObjectTable; + ExHandle = HANDLE_TO_EX_HANDLE(Handle); + } KeEnterCriticalRegion(); - Process = PsGetCurrentProcess(); - - HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable, + HandleTableEntry = ExMapHandleToPointer(HandleTable, ExHandle); if (HandleTableEntry == NULL) { @@ -99,7 +112,7 @@ ObpQueryHandleAttributes(HANDLE Handle, HandleInfo->Inherit = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_INHERITABLE) != 0; HandleInfo->ProtectFromClose = (HandleTableEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) != 0; - ExUnlockHandleTableEntry(Process->ObjectTable, + ExUnlockHandleTableEntry(HandleTable, HandleTableEntry); KeLeaveCriticalRegion(); @@ -112,19 +125,28 @@ NTSTATUS ObpSetHandleAttributes(HANDLE Handle, POBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleInfo) { - PEPROCESS Process; + PHANDLE_TABLE HandleTable; PHANDLE_TABLE_ENTRY HandleTableEntry; - LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle); + LONG ExHandle; PAGED_CODE(); DPRINT("ObpSetHandleAttributes(Handle %x)\n", Handle); - Process = PsGetCurrentProcess(); + if(ObIsKernelHandle(Handle, ExGetPreviousMode())) + { + HandleTable = ObpKernelHandleTable; + ExHandle = HANDLE_TO_EX_HANDLE(ObKernelHandleToHandle(Handle)); + } + else + { + HandleTable = PsGetCurrentProcess()->ObjectTable; + ExHandle = HANDLE_TO_EX_HANDLE(Handle); + } KeEnterCriticalRegion(); - HandleTableEntry = ExMapHandleToPointer(Process->ObjectTable, + HandleTableEntry = ExMapHandleToPointer(HandleTable, ExHandle); if (HandleTableEntry == NULL) { @@ -144,7 +166,7 @@ ObpSetHandleAttributes(HANDLE Handle, /* FIXME: Do we need to set anything in the object header??? */ - ExUnlockHandleTableEntry(Process->ObjectTable, + ExUnlockHandleTableEntry(HandleTable, HandleTableEntry); KeLeaveCriticalRegion(); @@ -153,6 +175,54 @@ ObpSetHandleAttributes(HANDLE Handle, } +static NTSTATUS +ObpDeleteHandle(PHANDLE_TABLE HandleTable, + HANDLE Handle) +{ + PHANDLE_TABLE_ENTRY HandleEntry; + PVOID Body; + POBJECT_HEADER ObjectHeader; + LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle); + + PAGED_CODE(); + + DPRINT("ObpDeleteHandle(Handle %x)\n",Handle); + + KeEnterCriticalRegion(); + + HandleEntry = ExMapHandleToPointer(HandleTable, + ExHandle); + if(HandleEntry != NULL) + { + if(HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) + { + ExUnlockHandleTableEntry(HandleTable, + HandleEntry); + + KeLeaveCriticalRegion(); + + return STATUS_HANDLE_NOT_CLOSABLE; + } + + ObjectHeader = EX_HTE_TO_HDR(HandleEntry); + Body = HEADER_TO_BODY(ObjectHeader); + + ObpDecrementHandleCount(Body); + + /* destroy and unlock the handle entry */ + ExDestroyHandleByEntry(HandleTable, + HandleEntry, + ExHandle); + + KeLeaveCriticalRegion(); + + return STATUS_SUCCESS; + } + KeLeaveCriticalRegion(); + return STATUS_INVALID_HANDLE; +} + + NTSTATUS ObDuplicateObject(PEPROCESS SourceProcess, PEPROCESS TargetProcess, @@ -162,19 +232,32 @@ ObDuplicateObject(PEPROCESS SourceProcess, BOOLEAN InheritHandle, ULONG Options) { + PHANDLE_TABLE SourceHandleTable; PHANDLE_TABLE_ENTRY SourceHandleEntry; HANDLE_TABLE_ENTRY NewHandleEntry; PVOID ObjectBody; POBJECT_HEADER ObjectHeader; LONG ExTargetHandle; - LONG ExSourceHandle = HANDLE_TO_EX_HANDLE(SourceHandle); + LONG ExSourceHandle; ULONG NewHandleCount; PAGED_CODE(); + if(ObIsKernelHandle(SourceHandle, ExGetPreviousMode())) + { + SourceHandleTable = ObpKernelHandleTable; + SourceHandle = ObKernelHandleToHandle(SourceHandle); + } + else + { + SourceHandleTable = SourceProcess->ObjectTable; + } + + ExSourceHandle = HANDLE_TO_EX_HANDLE(SourceHandle); + KeEnterCriticalRegion(); - SourceHandleEntry = ExMapHandleToPointer(SourceProcess->ObjectTable, + SourceHandleEntry = ExMapHandleToPointer(SourceHandleTable, ExSourceHandle); if (SourceHandleEntry == NULL) { @@ -219,7 +302,7 @@ ObDuplicateObject(PEPROCESS SourceProcess, NewHandleCount = InterlockedIncrement(&ObjectHeader->HandleCount); ASSERT(NewHandleCount >= 2); - ExUnlockHandleTableEntry(SourceProcess->ObjectTable, + ExUnlockHandleTableEntry(SourceHandleTable, SourceHandleEntry); KeLeaveCriticalRegion(); @@ -231,8 +314,8 @@ ObDuplicateObject(PEPROCESS SourceProcess, { if (Options & DUPLICATE_CLOSE_SOURCE) { - ObDeleteHandle(SourceProcess, - SourceHandle); + ObpDeleteHandle(SourceHandleTable, + SourceHandle); } ObDereferenceObject(ObjectBody); @@ -384,8 +467,8 @@ NtDuplicateObject (IN HANDLE SourceProcessHandle, if (Options & DUPLICATE_CLOSE_SOURCE) { - ObDeleteHandle(SourceProcess, - SourceHandle); + ObpDeleteHandle(SourceProcess->ObjectTable, + SourceHandle); } } } @@ -464,10 +547,7 @@ DuplicateHandleCallback(PHANDLE_TABLE HandleTable, ObjectHeader = EX_HTE_TO_HDR(HandleTableEntry); if(InterlockedIncrement(&ObjectHeader->HandleCount) == 1) { - ObReferenceObjectByPointer(HEADER_TO_BODY(ObjectHeader), - 0, - NULL, - UserMode); + ObReferenceObject(HEADER_TO_BODY(ObjectHeader)); } } @@ -503,54 +583,6 @@ VOID ObCreateHandleTable(PEPROCESS Parent, } -NTSTATUS -ObDeleteHandle(PEPROCESS Process, - HANDLE Handle) -{ - PHANDLE_TABLE_ENTRY HandleEntry; - PVOID Body; - POBJECT_HEADER ObjectHeader; - LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle); - - PAGED_CODE(); - - DPRINT("ObDeleteHandle(Handle %x)\n",Handle); - - KeEnterCriticalRegion(); - - HandleEntry = ExMapHandleToPointer(Process->ObjectTable, - ExHandle); - if(HandleEntry != NULL) - { - if(HandleEntry->u1.ObAttributes & EX_HANDLE_ENTRY_PROTECTFROMCLOSE) - { - ExUnlockHandleTableEntry(Process->ObjectTable, - HandleEntry); - - KeLeaveCriticalRegion(); - - return STATUS_HANDLE_NOT_CLOSABLE; - } - - ObjectHeader = EX_HTE_TO_HDR(HandleEntry); - Body = HEADER_TO_BODY(ObjectHeader); - - ObpDecrementHandleCount(Body); - - /* destroy and unlock the handle entry */ - ExDestroyHandleByEntry(Process->ObjectTable, - HandleEntry, - ExHandle); - - KeLeaveCriticalRegion(); - - return STATUS_SUCCESS; - } - KeLeaveCriticalRegion(); - return STATUS_INVALID_HANDLE; -} - - NTSTATUS ObCreateHandle(PEPROCESS Process, PVOID ObjectBody, @@ -685,11 +717,11 @@ ObReferenceObjectByHandle(HANDLE Handle, { PHANDLE_TABLE_ENTRY HandleEntry; POBJECT_HEADER ObjectHeader; + PHANDLE_TABLE HandleTable; PVOID ObjectBody; ACCESS_MASK GrantedAccess; ULONG Attributes; - NTSTATUS Status; - LONG ExHandle = HANDLE_TO_EX_HANDLE(Handle); + LONG ExHandle; PAGED_CODE(); @@ -703,14 +735,9 @@ ObReferenceObjectByHandle(HANDLE Handle, if (Handle == NtCurrentProcess() && (ObjectType == PsProcessType || ObjectType == NULL)) { - Status = ObReferenceObjectByPointer(PsGetCurrentProcess(), - PROCESS_ALL_ACCESS, - PsProcessType, - UserMode); - if (! NT_SUCCESS(Status)) - { - return Status; - } + PEPROCESS CurrentProcess = PsGetCurrentProcess(); + + ObReferenceObject(CurrentProcess); if (HandleInformation != NULL) { @@ -718,8 +745,8 @@ ObReferenceObjectByHandle(HANDLE Handle, HandleInformation->GrantedAccess = PROCESS_ALL_ACCESS; } - *Object = PsGetCurrentProcess(); - DPRINT("Referencing current process %x\n", PsGetCurrentProcess()); + *Object = CurrentProcess; + DPRINT("Referencing current process %x\n", CurrentProcess); return STATUS_SUCCESS; } else if (Handle == NtCurrentProcess()) @@ -731,14 +758,9 @@ ObReferenceObjectByHandle(HANDLE Handle, if (Handle == NtCurrentThread() && (ObjectType == PsThreadType || ObjectType == NULL)) { - Status = ObReferenceObjectByPointer(PsGetCurrentThread(), - THREAD_ALL_ACCESS, - PsThreadType, - UserMode); - if (! NT_SUCCESS(Status)) - { - return Status; - } + PETHREAD CurrentThread = PsGetCurrentThread(); + + ObReferenceObject(CurrentThread); if (HandleInformation != NULL) { @@ -746,7 +768,7 @@ ObReferenceObjectByHandle(HANDLE Handle, HandleInformation->GrantedAccess = THREAD_ALL_ACCESS; } - *Object = PsGetCurrentThread(); + *Object = CurrentThread; CHECKPOINT; return STATUS_SUCCESS; } @@ -763,9 +785,20 @@ ObReferenceObjectByHandle(HANDLE Handle, DesiredAccess |= GENERIC_ALL; } + if(ObIsKernelHandle(Handle, AccessMode)) + { + HandleTable = ObpKernelHandleTable; + ExHandle = HANDLE_TO_EX_HANDLE(ObKernelHandleToHandle(Handle)); + } + else + { + HandleTable = PsGetCurrentProcess()->ObjectTable; + ExHandle = HANDLE_TO_EX_HANDLE(Handle); + } + KeEnterCriticalRegion(); - HandleEntry = ExMapHandleToPointer(PsGetCurrentProcess()->ObjectTable, + HandleEntry = ExMapHandleToPointer(HandleTable, ExHandle); if (HandleEntry == NULL) { @@ -777,13 +810,13 @@ ObReferenceObjectByHandle(HANDLE Handle, ObjectHeader = EX_HTE_TO_HDR(HandleEntry); ObjectBody = HEADER_TO_BODY(ObjectHeader); - DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader, PsGetCurrentProcess()->ObjectTable); + DPRINT("locked1: ObjectHeader: 0x%x [HT:0x%x]\n", ObjectHeader, HandleTable); if (ObjectType != NULL && ObjectType != ObjectHeader->ObjectType) { DPRINT("ObjectType mismatch: %wZ vs %wZ (handle 0x%x)\n", &ObjectType->TypeName, ObjectHeader->ObjectType ? &ObjectHeader->ObjectType->TypeName : NULL, Handle); - ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable, + ExUnlockHandleTableEntry(HandleTable, HandleEntry); KeLeaveCriticalRegion(); @@ -804,7 +837,7 @@ ObReferenceObjectByHandle(HANDLE Handle, rights than the handle can grant */ if(AccessMode != KernelMode && (~GrantedAccess & DesiredAccess)) { - ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable, + ExUnlockHandleTableEntry(HandleTable, HandleEntry); KeLeaveCriticalRegion(); @@ -814,15 +847,13 @@ ObReferenceObjectByHandle(HANDLE Handle, return(STATUS_ACCESS_DENIED); } - ObReferenceObjectByPointer(ObjectBody, - 0, - NULL, - UserMode); + ObReferenceObject(ObjectBody); + Attributes = HandleEntry->u1.ObAttributes & (EX_HANDLE_ENTRY_PROTECTFROMCLOSE | EX_HANDLE_ENTRY_INHERITABLE | EX_HANDLE_ENTRY_AUDITONCLOSE); - ExUnlockHandleTableEntry(PsGetCurrentProcess()->ObjectTable, + ExUnlockHandleTableEntry(HandleTable, HandleEntry); KeLeaveCriticalRegion(); @@ -858,16 +889,30 @@ ObReferenceObjectByHandle(HANDLE Handle, NTSTATUS STDCALL NtClose(IN HANDLE Handle) { + PHANDLE_TABLE HandleTable; NTSTATUS Status; PAGED_CODE(); - Status = ObDeleteHandle(PsGetCurrentProcess(), - Handle); + if(ObIsKernelHandle(Handle, ExGetPreviousMode())) + { + HandleTable = ObpKernelHandleTable; + Handle = ObKernelHandleToHandle(Handle); + } + else + { + HandleTable = PsGetCurrentProcess()->ObjectTable; + } + + Status = ObpDeleteHandle(HandleTable, + Handle); if (!NT_SUCCESS(Status)) { - if(((PEPROCESS)(KeGetCurrentThread()->ApcState.Process))->ExceptionPort) + if((ExGetPreviousMode() != KernelMode) && + (PsGetCurrentProcess()->ExceptionPort)) + { KeRaiseUserException(Status); + } return Status; } diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index 6211a6a2afc..f4f4692f9bf 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -286,6 +286,7 @@ PspPostInitSystemProcess(VOID) PsInitClientIDManagment(); ObCreateHandleTable(NULL, FALSE, PsInitialSystemProcess); + ObpKernelHandleTable = PsInitialSystemProcess->ObjectTable; Status = PsCreateCidHandle(PsInitialSystemProcess, PsProcessType,