diff --git a/reactos/ntoskrnl/ex/dbgctrl.c b/reactos/ntoskrnl/ex/dbgctrl.c index 86032074c24..f3f25125a79 100644 --- a/reactos/ntoskrnl/ex/dbgctrl.c +++ b/reactos/ntoskrnl/ex/dbgctrl.c @@ -12,8 +12,132 @@ #define NDEBUG #include +/* DATA **********************************************************************/ + +// #ifdef _WINKD_ +/* + * WinDBG Debugger Worker Thread data + */ +WORK_QUEUE_ITEM ExpDebuggerWorkItem; +/* + * The following global variables must be visible through all the kernel + * because WinDBG explicitely search for them inside our symbols. + */ +WINKD_WORKER_STATE ExpDebuggerWork; +PEPROCESS ExpDebuggerProcessAttach; +PEPROCESS ExpDebuggerProcessKill; +ULONG_PTR ExpDebuggerPageIn; +// #endif /* _WINKD_ */ + /* FUNCTIONS *****************************************************************/ +// #ifdef _WINKD_ +/* + * WinDBG Debugger Worker Thread + * + * A worker thread is queued whenever WinDBG wants to attach or kill a user-mode + * process from within live kernel-mode session, and/or page-in an address region. + * + * WinDBG commands: + * .process /i (where is the address of the EPROCESS block for this process) + * .kill ( " " " " ) + * .pagein (where is the address to page in) + * + * The implementation is very naive because the same data is reused, so that if + * the worker thread has not started before WinDBG sends fresh new data again, + * then only the latest data is taken into account. + */ +VOID +NTAPI +ExpDebuggerWorker(IN PVOID Context) +{ + PEPROCESS ProcessToAttach, ProcessToKill; + ULONG_PTR PageInAddress; + PEPROCESS Process; + KAPC_STATE ApcState; + + UNREFERENCED_PARAMETER(Context); + + /* Be sure we were started in an initialized state */ + ASSERTMSG("ExpDebuggerWorker being entered with state != 2\n", + ExpDebuggerWork == WinKdWorkerInitialized); + if (ExpDebuggerWork != WinKdWorkerInitialized) return; + + /* Reset the worker flag to the disabled state */ + ExpDebuggerWork = WinKdWorkerDisabled; + + /* Get the processes to be attached or killed, and the address to page in */ + ProcessToAttach = ExpDebuggerProcessAttach; + ProcessToKill = ExpDebuggerProcessKill; + PageInAddress = ExpDebuggerPageIn; + + /* Reset to their default values */ + ExpDebuggerProcessAttach = NULL; + ExpDebuggerProcessKill = NULL; + ExpDebuggerPageIn = (ULONG_PTR)NULL; + + /* Default to the current process if we don't find the process to be attached or killed */ + Process = NULL; + + /* Check if we need to attach or kill some process */ + if (ProcessToAttach != NULL || ProcessToKill != NULL) + { + /* Find the process in the list */ + Process = PsGetNextProcess(Process); + while (Process) + { + /* Is this the process we want to attach to? */ + if (Process == ProcessToAttach) + { + /* Yes, attach ourselves to it */ + KeStackAttachProcess(&Process->Pcb, &ApcState); + break; + } + /* Or is this the process we want to kill? */ + else if (Process == ProcessToKill) + { + /* Yes, kill and dereference it, then return */ + PsTerminateProcess(Process, DBG_TERMINATE_PROCESS); + ObDereferenceObject(Process); + return; + } + + /* Get the next process */ + Process = PsGetNextProcess(Process); + } + + /* We either have found a process, or we default to the current process */ + } + + /* If we have an address to page in... */ + if (PageInAddress) + { + /* ... try to do it by attempting to read at this address */ + _SEH2_TRY + { + ProbeForReadUchar(PageInAddress); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + DPRINT1("Failed to page in address 0x%p, Status 0x%08lx\n", PageInAddress, _SEH2_GetExceptionCode()); + } + _SEH2_END; + } + + /* Break into the process (or the current one if Process == NULL) */ + DbgBreakPointWithStatus(DBG_STATUS_WORKER); + + /* If we are attached to a process, not the current one... */ + if (Process) + { + /* ... we can detach from the process */ + KeUnstackDetachProcess(&ApcState); + /* Dereference the process which was referenced for us by PsGetNextProcess */ + ObDereferenceObject(Process); + } +} +// #endif /* _WINKD_ */ + /*++ * @name NtSystemDebugControl * @implemented diff --git a/reactos/ntoskrnl/ex/work.c b/reactos/ntoskrnl/ex/work.c index 1ae191d57c6..7d27bbef294 100644 --- a/reactos/ntoskrnl/ex/work.c +++ b/reactos/ntoskrnl/ex/work.c @@ -485,6 +485,19 @@ ExpWorkerThreadBalanceManager(IN PVOID Context) ObDereferenceObject(ExpLastWorkerThread); PsTerminateSystemThread(STATUS_SYSTEM_SHUTDOWN); } + +// #ifdef _WINKD_ + /* + * If WinDBG wants to attach or kill a user-mode process, and/or + * page-in an address region, queue a debugger worker thread. + */ + if (ExpDebuggerWork == WinKdWorkerActivate) + { + ExInitializeWorkItem(&ExpDebuggerWorkItem, ExpDebuggerWorker, NULL); + ExpDebuggerWork = WinKdWorkerInitialized; + ExQueueWorkItem(&ExpDebuggerWorkItem, DelayedWorkQueue); + } +// #endif /* _WINKD_ */ } } @@ -744,4 +757,3 @@ ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, } /* EOF */ - diff --git a/reactos/ntoskrnl/include/internal/dbgk.h b/reactos/ntoskrnl/include/internal/dbgk.h index dfa22a3bbc1..fdab33e80af 100644 --- a/reactos/ntoskrnl/include/internal/dbgk.h +++ b/reactos/ntoskrnl/include/internal/dbgk.h @@ -141,7 +141,7 @@ DbgkOpenProcessDebugPort( IN KPROCESSOR_MODE PreviousMode, OUT HANDLE *DebugHandle ); - + extern ULONG DbgkpTraceLevel; extern POBJECT_TYPE DbgkDebugObjectType; diff --git a/reactos/ntoskrnl/include/internal/ex.h b/reactos/ntoskrnl/include/internal/ex.h index c52aebafd6e..59502f6ba59 100644 --- a/reactos/ntoskrnl/include/internal/ex.h +++ b/reactos/ntoskrnl/include/internal/ex.h @@ -42,6 +42,25 @@ extern UNICODE_STRING CmVersionString; extern UNICODE_STRING CmCSDVersionString; extern CHAR NtBuildLab[]; +// #ifdef _WINKD_ +/* + * WinDBG Debugger Worker Thread data (see dbgctrl.c) + */ +typedef enum _WINKD_WORKER_STATE +{ + WinKdWorkerDisabled = 0, + WinKdWorkerActivate, + WinKdWorkerInitialized +} WINKD_WORKER_STATE; + +extern WORK_QUEUE_ITEM ExpDebuggerWorkItem; +extern WINKD_WORKER_STATE ExpDebuggerWork; +extern PEPROCESS ExpDebuggerProcessAttach; +extern PEPROCESS ExpDebuggerProcessKill; +extern ULONG_PTR ExpDebuggerPageIn; +VOID NTAPI ExpDebuggerWorker(IN PVOID Context); +// #endif /* _WINKD_ */ + #ifdef _WIN64 #define HANDLE_LOW_BITS (PAGE_SHIFT - 4) #define HANDLE_HIGH_BITS (PAGE_SHIFT - 3)