diff --git a/reactos/include/ndk/dbgktypes.h b/reactos/include/ndk/dbgktypes.h index dd49089c308..4fb0ed90eb0 100644 --- a/reactos/include/ndk/dbgktypes.h +++ b/reactos/include/ndk/dbgktypes.h @@ -55,11 +55,11 @@ typedef struct _DEBUG_OBJECT_KILL_PROCESS_ON_EXIT_INFORMATION // // Debug Object // -typedef struct _DBGK_DEBUG_OBJECT +typedef struct _DEBUG_OBJECT { - KEVENT Event; + KEVENT EventsPresent; FAST_MUTEX Mutex; - LIST_ENTRY StateEventListEntry; + LIST_ENTRY EventList; union { ULONG Flags; @@ -69,7 +69,7 @@ typedef struct _DBGK_DEBUG_OBJECT UCHAR KillProcessOnExit:1; }; }; -} DBGK_DEBUG_OBJECT, *PDBGK_DEBUG_OBJECT; +} DEBUG_OBJECT, *PDEBUG_OBJECT; #endif diff --git a/reactos/ntoskrnl/dbgk/debug.c b/reactos/ntoskrnl/dbgk/debug.c index e46cadf277e..1186498526d 100644 --- a/reactos/ntoskrnl/dbgk/debug.c +++ b/reactos/ntoskrnl/dbgk/debug.c @@ -14,7 +14,7 @@ #include POBJECT_TYPE DbgkDebugObjectType; -KGUARDED_MUTEX DbgkpProcessDebugPortMutex; +FAST_MUTEX DbgkpProcessDebugPortMutex; GENERIC_MAPPING DbgkDebugObjectMapping = { @@ -26,58 +26,6 @@ GENERIC_MAPPING DbgkDebugObjectMapping = /* PRIVATE FUNCTIONS *********************************************************/ -VOID -NTAPI -DbgkpDeleteObject(IN PVOID Object) -{ - PDBGK_DEBUG_OBJECT DebugObject = Object; - PAGED_CODE(); - - /* Sanity check */ - ASSERT(IsListEmpty(&DebugObject->StateEventListEntry)); -} - -VOID -NTAPI -DbgkpCloseObject(IN PEPROCESS Process OPTIONAL, - IN PVOID ObjectBody, - IN ACCESS_MASK GrantedAccess, - IN ULONG HandleCount, - IN ULONG SystemHandleCount) -{ - /* FIXME: Implement */ - ASSERT(FALSE); -} - -VOID -INIT_FUNCTION -NTAPI -DbgkInitialize(VOID) -{ - OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; - UNICODE_STRING Name; - PAGED_CODE(); - - /* Initialize the process debug port mutex */ - KeInitializeGuardedMutex(&DbgkpProcessDebugPortMutex); - - /* Create the Event Pair Object Type */ - RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); - RtlInitUnicodeString(&Name, L"DebugObject"); - ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); - ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DBGK_DEBUG_OBJECT); - ObjectTypeInitializer.GenericMapping = DbgkDebugObjectMapping; - ObjectTypeInitializer.PoolType = NonPagedPool; - ObjectTypeInitializer.ValidAccessMask = DEBUG_OBJECT_WAIT_STATE_CHANGE; - ObjectTypeInitializer.UseDefaultObject = TRUE; - ObjectTypeInitializer.CloseProcedure = DbgkpCloseObject; - ObjectTypeInitializer.DeleteProcedure = DbgkpDeleteObject; - ObCreateObjectType(&Name, - &ObjectTypeInitializer, - NULL, - &DbgkDebugObjectType); -} - VOID NTAPI DbgkCopyProcessDebugPort(IN PEPROCESS Process, @@ -107,7 +55,7 @@ DbgkpWakeTarget(IN PDEBUG_EVENT DebugEvent) NTSTATUS NTAPI DbgkpPostFakeProcessCreateMessages(IN PEPROCESS Process, - IN PDBGK_DEBUG_OBJECT DebugObject, + IN PDEBUG_OBJECT DebugObject, IN PETHREAD *LastThread) { /* FIXME: Implement */ @@ -118,7 +66,7 @@ DbgkpPostFakeProcessCreateMessages(IN PEPROCESS Process, NTSTATUS NTAPI DbgkpSetProcessDebugObject(IN PEPROCESS Process, - IN PDBGK_DEBUG_OBJECT DebugObject, + IN PDEBUG_OBJECT DebugObject, IN NTSTATUS MsgStatus, IN PETHREAD LastThread) { @@ -129,7 +77,7 @@ DbgkpSetProcessDebugObject(IN PEPROCESS Process, NTSTATUS NTAPI DbgkClearProcessDebugObject(IN PEPROCESS Process, - IN PDBGK_DEBUG_OBJECT SourceDebugObject) + IN PDEBUG_OBJECT SourceDebugObject) { /* FIXME: TODO */ return STATUS_UNSUCCESSFUL; @@ -149,11 +97,233 @@ NTAPI DbgkpOpenHandles(IN PDBGUI_WAIT_STATE_CHANGE WaitStateChange, IN PEPROCESS Process, IN PETHREAD Thread) +{ + NTSTATUS Status; + HANDLE Handle; + PHANDLE DupHandle; + PAGED_CODE(); + + /* Check which state this is */ + switch (WaitStateChange->NewState) + { + /* New thread */ + case DbgCreateThreadStateChange: + + /* Get handle to thread */ + Status = ObOpenObjectByPointer(Thread, + 0, + NULL, + THREAD_ALL_ACCESS, + PsThreadType, + KernelMode, + &Handle); + if (NT_SUCCESS(Status)) + { + /* Save the thread handle */ + WaitStateChange-> + StateInfo.CreateThread.HandleToThread = Handle; + } + return; + + /* New process */ + case DbgCreateProcessStateChange: + + /* Get handle to thread */ + Status = ObOpenObjectByPointer(Thread, + 0, + NULL, + THREAD_ALL_ACCESS, + PsThreadType, + KernelMode, + &Handle); + if (NT_SUCCESS(Status)) + { + /* Save the thread handle */ + WaitStateChange-> + StateInfo.CreateProcessInfo.HandleToThread = Handle; + } + + /* Get handle to process */ + Status = ObOpenObjectByPointer(Process, + 0, + NULL, + PROCESS_ALL_ACCESS, + PsProcessType, + KernelMode, + &Handle); + if (NT_SUCCESS(Status)) + { + /* Save the process handle */ + WaitStateChange-> + StateInfo.CreateProcessInfo.HandleToProcess = Handle; + } + + /* Fall through to duplicate file handle */ + DupHandle = &WaitStateChange-> + StateInfo.CreateProcessInfo.NewProcess.FileHandle; + break; + + /* DLL Load */ + case DbgLoadDllStateChange: + + /* Fall through to duplicate file handle */ + DupHandle = &WaitStateChange->StateInfo.LoadDll.FileHandle; + + /* Anything else has no handles */ + default: + return; + } + + /* If we got here, then we have to duplicate a handle, possibly */ + Handle = *DupHandle; + if (Handle) + { + /* Duplicate it */ + Status = ObDuplicateObject(PsGetCurrentProcess(), + Handle, + PsGetCurrentProcess(), + DupHandle, + 0, + 0, + DUPLICATE_SAME_ACCESS, + KernelMode); + } +} + +VOID +NTAPI +DbgkpDeleteObject(IN PVOID Object) +{ + PDEBUG_OBJECT DebugObject = Object; + PAGED_CODE(); + + /* Sanity check */ + ASSERT(IsListEmpty(&DebugObject->EventList)); +} + +VOID +NTAPI +DbgkpMarkProcessPeb(IN PEPROCESS Process) { /* FIXME: TODO */ return; } +VOID +NTAPI +DbgkpCloseObject(IN PEPROCESS OwnerProcess OPTIONAL, + IN PVOID ObjectBody, + IN ACCESS_MASK GrantedAccess, + IN ULONG HandleCount, + IN ULONG SystemHandleCount) +{ + PDEBUG_OBJECT DebugObject = ObjectBody; + PEPROCESS Process = NULL; + BOOLEAN DebugPortCleared = FALSE; + PLIST_ENTRY DebugEventList; + PDEBUG_EVENT DebugEvent; + + /* If this isn't the last handle, do nothing */ + if (HandleCount > 1) return; + + /* Otherwise, lock the debug object */ + ExAcquireFastMutex(&DebugObject->Mutex); + + /* Set it as inactive */ + DebugObject->DebuggerInactive = TRUE; + + /* Remove it from the debug event list */ + DebugEventList = DebugObject->EventList.Flink; + InitializeListHead(&DebugObject->EventList); + + /* Release the lock */ + ExReleaseFastMutex(&DebugObject->Mutex); + + /* Signal the wait event */ + KeSetEvent(&DebugObject->EventsPresent, IO_NO_INCREMENT, FALSE); + + /* Start looping each process */ + while ((Process = PsGetNextProcess(Process))) + { + /* Check if the process has us as their debug port */ + if (Process->DebugPort == DebugObject) + { + /* Acquire the process debug port lock */ + ExAcquireFastMutex(&DbgkpProcessDebugPortMutex); + + /* Check if it's still us */ + if (Process->DebugPort == DebugObject) + { + /* Clear it and remember */ + Process->DebugPort = NULL; + DebugPortCleared = TRUE; + } + + /* Release the port lock */ + ExReleaseFastMutex(&DbgkpProcessDebugPortMutex); + + /* Check if we cleared the debug port */ + if (DebugPortCleared) + { + /* Mark this in the PEB */ + DbgkpMarkProcessPeb(OwnerProcess); + + /* Check if we terminate on exit */ + if (DebugObject->KillProcessOnExit) + { + /* Terminate the process */ + PsTerminateProcess(OwnerProcess, STATUS_DEBUGGER_INACTIVE); + } + + /* Dereference the debug object */ + ObDereferenceObject(DebugObject); + } + } + } + + /* Loop debug events */ + while (DebugEventList != &DebugObject->EventList) + { + /* Get the debug event */ + DebugEvent = CONTAINING_RECORD(DebugEventList, DEBUG_EVENT, EventList); + + /* Go to the next entry */ + DebugEventList = DebugEventList->Flink; + + /* Wake it up */ + DebugEvent->Status = STATUS_DEBUGGER_INACTIVE; + DbgkpWakeTarget(DebugEvent); + } +} + +VOID +INIT_FUNCTION +NTAPI +DbgkInitialize(VOID) +{ + OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; + UNICODE_STRING Name; + PAGED_CODE(); + + /* Initialize the process debug port mutex */ + ExInitializeFastMutex(&DbgkpProcessDebugPortMutex); + + /* Create the Debug Object Type */ + RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer)); + RtlInitUnicodeString(&Name, L"DebugObject"); + ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer); + ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DEBUG_OBJECT); + ObjectTypeInitializer.GenericMapping = DbgkDebugObjectMapping; + ObjectTypeInitializer.PoolType = NonPagedPool; + ObjectTypeInitializer.ValidAccessMask = DEBUG_OBJECT_WAIT_STATE_CHANGE; + ObjectTypeInitializer.UseDefaultObject = TRUE; + ObjectTypeInitializer.CloseProcedure = DbgkpCloseObject; + ObjectTypeInitializer.DeleteProcedure = DbgkpDeleteObject; + ObCreateObjectType(&Name, + &ObjectTypeInitializer, + NULL, + &DbgkDebugObjectType); +} /* PUBLIC FUNCTIONS **********************************************************/ @@ -165,7 +335,7 @@ NtCreateDebugObject(OUT PHANDLE DebugHandle, IN BOOLEAN KillProcessOnExit) { KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - PDBGK_DEBUG_OBJECT DebugObject; + PDEBUG_OBJECT DebugObject; HANDLE hDebug; NTSTATUS Status = STATUS_SUCCESS; PAGED_CODE(); @@ -193,7 +363,7 @@ NtCreateDebugObject(OUT PHANDLE DebugHandle, ObjectAttributes, PreviousMode, NULL, - sizeof(PDBGK_DEBUG_OBJECT), + sizeof(PDEBUG_OBJECT), 0, 0, (PVOID*)&DebugObject); @@ -203,10 +373,10 @@ NtCreateDebugObject(OUT PHANDLE DebugHandle, ExInitializeFastMutex(&DebugObject->Mutex); /* Initialize the State Event List */ - InitializeListHead(&DebugObject->StateEventListEntry); + InitializeListHead(&DebugObject->EventList); /* Initialize the Debug Object's Wait Event */ - KeInitializeEvent(&DebugObject->Event, NotificationEvent, 0); + KeInitializeEvent(&DebugObject->EventsPresent, NotificationEvent, 0); /* Set the Flags */ DebugObject->KillProcessOnExit = KillProcessOnExit; @@ -245,7 +415,7 @@ NtDebugContinue(IN HANDLE DebugHandle, IN NTSTATUS ContinueStatus) { KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - PDBGK_DEBUG_OBJECT DebugObject; + PDEBUG_OBJECT DebugObject; NTSTATUS Status = STATUS_SUCCESS; PDEBUG_EVENT DebugEvent = NULL, DebugEventToWake = NULL; PLIST_ENTRY ListHead, NextEntry; @@ -296,7 +466,7 @@ NtDebugContinue(IN HANDLE DebugHandle, ExAcquireFastMutex(&DebugObject->Mutex); /* Loop the state list */ - ListHead = &DebugObject->StateEventListEntry; + ListHead = &DebugObject->EventList; NextEntry = ListHead->Flink; while (ListHead != NextEntry) { @@ -371,7 +541,7 @@ NtDebugActiveProcess(IN HANDLE ProcessHandle, IN HANDLE DebugHandle) { PEPROCESS Process; - PDBGK_DEBUG_OBJECT DebugObject; + PDEBUG_OBJECT DebugObject; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); PETHREAD LastThread; NTSTATUS Status; @@ -435,7 +605,7 @@ NtRemoveProcessDebug(IN HANDLE ProcessHandle, IN HANDLE DebugHandle) { PEPROCESS Process; - PDBGK_DEBUG_OBJECT DebugObject; + PDEBUG_OBJECT DebugObject; KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); NTSTATUS Status; @@ -487,7 +657,7 @@ NtSetInformationDebugObject(IN HANDLE DebugHandle, IN ULONG DebugInformationLength, OUT PULONG ReturnLength OPTIONAL) { - PDBGK_DEBUG_OBJECT DebugObject; + PDEBUG_OBJECT DebugObject; KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); NTSTATUS Status = STATUS_SUCCESS; PDEBUG_OBJECT_KILL_PROCESS_ON_EXIT_INFORMATION DebugInfo = DebugInformation; @@ -522,12 +692,12 @@ NtSetInformationDebugObject(IN HANDLE DebugHandle, if (DebugInfo->KillProcessOnExit) { /* Enable killing the process */ - DebugObject->Flags |= 2; + DebugObject->KillProcessOnExit = TRUE; } else { /* Disable */ - DebugObject->Flags &= ~2; + DebugObject->KillProcessOnExit = FALSE; } /* Release the mutex */ @@ -555,7 +725,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle, PETHREAD Thread; BOOLEAN GotEvent; LARGE_INTEGER NewTime; - PDBGK_DEBUG_OBJECT DebugObject; + PDEBUG_OBJECT DebugObject; DBGUI_WAIT_STATE_CHANGE WaitStateChange; NTSTATUS Status = STATUS_SUCCESS; PDEBUG_EVENT DebugEvent, DebugEvent2; @@ -628,7 +798,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle, ExAcquireFastMutex(&DebugObject->Mutex); /* Check if a debugger is connected */ - if (DebugObject->Flags & 1) + if (DebugObject->DebuggerInactive) { /* Not connected */ Status = STATUS_DEBUGGER_INACTIVE; @@ -636,7 +806,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle, else { /* Loop the events */ - ListHead = &DebugObject->StateEventListEntry; + ListHead = &DebugObject->EventList; NextEntry = ListHead->Flink; while (ListHead != NextEntry) { @@ -702,7 +872,7 @@ NtWaitForDebugEvent(IN HANDLE DebugHandle, else { /* Unsignal the event */ - DebugObject->Event.Header.SignalState = 0; + DebugObject->EventsPresent.Header.SignalState = 0; Status = STATUS_SUCCESS; } } diff --git a/reactos/ntoskrnl/include/internal/dbgk.h b/reactos/ntoskrnl/include/internal/dbgk.h index d3feb09682b..f2f3f39f686 100644 --- a/reactos/ntoskrnl/include/internal/dbgk.h +++ b/reactos/ntoskrnl/include/internal/dbgk.h @@ -3,15 +3,21 @@ VOID NTAPI -DbgkCreateThread(PVOID StartAddress); +DbgkCreateThread( + IN PVOID StartAddress +); VOID NTAPI -DbgkExitProcess(IN NTSTATUS ExitStatus); +DbgkExitProcess( + IN NTSTATUS ExitStatus +); VOID NTAPI -DbgkExitThread(IN NTSTATUS ExitStatus); +DbgkExitThread( + IN NTSTATUS ExitStatus +); VOID NTAPI @@ -28,6 +34,13 @@ DbgkForwardException( IN BOOLEAN SecondChance ); +NTSTATUS +NTAPI +DbgkClearProcessDebugObject( + IN PEPROCESS Process, + IN PDEBUG_OBJECT SourceDebugObject +); + extern POBJECT_TYPE DbgkDebugObjectType; #endif diff --git a/reactos/ntoskrnl/include/internal/ke_x.h b/reactos/ntoskrnl/include/internal/ke_x.h index 6124312a894..f90b97a99f4 100644 --- a/reactos/ntoskrnl/include/internal/ke_x.h +++ b/reactos/ntoskrnl/include/internal/ke_x.h @@ -57,15 +57,15 @@ // #define KeEnterCriticalRegion() \ { \ - PKTHREAD Thread = KeGetCurrentThread(); \ + PKTHREAD _Thread = KeGetCurrentThread(); \ \ /* Sanity checks */ \ - ASSERT(Thread == KeGetCurrentThread()); \ - ASSERT((Thread->KernelApcDisable <= 0) && \ - (Thread->KernelApcDisable != -32768)); \ + ASSERT(_Thread == KeGetCurrentThread()); \ + ASSERT((_Thread->KernelApcDisable <= 0) && \ + (_Thread->KernelApcDisable != -32768)); \ \ /* Disable Kernel APCs */ \ - Thread->KernelApcDisable--; \ + _Thread->KernelApcDisable--; \ } // @@ -73,21 +73,21 @@ // #define KeLeaveCriticalRegion() \ { \ - PKTHREAD Thread = KeGetCurrentThread(); \ + PKTHREAD _Thread = KeGetCurrentThread(); \ \ /* Sanity checks */ \ - ASSERT(Thread == KeGetCurrentThread()); \ - ASSERT(Thread->KernelApcDisable < 0); \ + ASSERT(_Thread == KeGetCurrentThread()); \ + ASSERT(_Thread->KernelApcDisable < 0); \ \ /* Enable Kernel APCs */ \ - Thread->KernelApcDisable++; \ + _Thread->KernelApcDisable++; \ \ /* Check if Kernel APCs are now enabled */ \ - if (!(Thread->KernelApcDisable)) \ + if (!(_Thread->KernelApcDisable)) \ { \ /* Check if we need to request an APC Delivery */ \ - if (!(IsListEmpty(&Thread->ApcState.ApcListHead[KernelMode])) && \ - !(Thread->KernelApcDisable)) \ + if (!(IsListEmpty(&_Thread->ApcState.ApcListHead[KernelMode])) && \ + !(_Thread->KernelApcDisable)) \ { \ /* Check for the right environment */ \ KiCheckForKernelApcDelivery(); \ diff --git a/reactos/ntoskrnl/include/internal/ob.h b/reactos/ntoskrnl/include/internal/ob.h index 0052e69d8cd..cedd438a2a2 100644 --- a/reactos/ntoskrnl/include/internal/ob.h +++ b/reactos/ntoskrnl/include/internal/ob.h @@ -238,6 +238,19 @@ ObClearProcessHandleTable( IN PEPROCESS Process ); +NTSTATUS +NTAPI +ObDuplicateObject( + IN PEPROCESS SourceProcess, + IN HANDLE SourceHandle, + IN PEPROCESS TargetProcess OPTIONAL, + IN PHANDLE TargetHandle OPTIONAL, + IN ACCESS_MASK DesiredAccess, + IN ULONG HandleAttributes, + IN ULONG Options, + IN KPROCESSOR_MODE PreviousMode +); + // // DOS Devices Functions // diff --git a/reactos/ntoskrnl/include/internal/ps.h b/reactos/ntoskrnl/include/internal/ps.h index 2b26031037b..53365057225 100644 --- a/reactos/ntoskrnl/include/internal/ps.h +++ b/reactos/ntoskrnl/include/internal/ps.h @@ -237,6 +237,13 @@ PspExitProcess( IN PEPROCESS Process ); +NTSTATUS +NTAPI +PsTerminateProcess( + IN PEPROCESS Process, + IN NTSTATUS ExitStatus +); + VOID NTAPI PspDeleteProcess( diff --git a/reactos/ntoskrnl/ps/kill.c b/reactos/ntoskrnl/ps/kill.c index b44396071d9..5a28b52ef38 100644 --- a/reactos/ntoskrnl/ps/kill.c +++ b/reactos/ntoskrnl/ps/kill.c @@ -118,6 +118,15 @@ PspTerminateProcess(IN PEPROCESS Process, return STATUS_SUCCESS; } +NTSTATUS +NTAPI +PsTerminateProcess(IN PEPROCESS Process, + IN NTSTATUS ExitStatus) +{ + /* Call the internal API */ + return PspTerminateProcess(Process, ExitStatus); +} + VOID NTAPI PspShutdownProcessManager(VOID) @@ -1116,7 +1125,8 @@ NtTerminateProcess(IN HANDLE ProcessHandle OPTIONAL, /* Check for the DBG_TERMINATE_PROCESS exit code */ if (ExitStatus == DBG_TERMINATE_PROCESS) { - /* FIXME: Disable debugging on this process */ + /* Disable debugging on this process */ + DbgkClearProcessDebugObject(Process, NULL); } } /* Make sure that we got a handle */ diff --git a/reactos/ntoskrnl/ps/process.c b/reactos/ntoskrnl/ps/process.c index c360c18df89..4c46dec4624 100644 --- a/reactos/ntoskrnl/ps/process.c +++ b/reactos/ntoskrnl/ps/process.c @@ -362,7 +362,7 @@ PspCreateProcess(OUT PHANDLE ProcessHandle, HANDLE hProcess; PEPROCESS Process, Parent; PEPORT ExceptionPortObject; - PDBGK_DEBUG_OBJECT DebugObject; + PDEBUG_OBJECT DebugObject; PSECTION_OBJECT SectionObject; NTSTATUS Status, AccessStatus; PHYSICAL_ADDRESS DirectoryTableBase = {{0}};