[NTOS:MM] Quick fix: use SIZE_T instead of ULONG, because ULONG is 32-bit and on...
[reactos.git] / ntoskrnl / ex / dbgctrl.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/ex/dbgctrl.c
5 * PURPOSE: System debug control
6 * PROGRAMMERS: Alex Ionescu
7 */
8
9 /* INCLUDES *****************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* DATA **********************************************************************/
16
17 // #ifdef _WINKD_
18 /*
19 * WinDBG Debugger Worker State Machine data
20 */
21 WORK_QUEUE_ITEM ExpDebuggerWorkItem;
22 /*
23 * The following global variables must be visible through all the kernel
24 * because WinDBG explicitely search for them inside our symbols.
25 */
26 WINKD_WORKER_STATE ExpDebuggerWork;
27 PEPROCESS ExpDebuggerProcessAttach;
28 PEPROCESS ExpDebuggerProcessKill;
29 ULONG_PTR ExpDebuggerPageIn;
30 // #endif /* _WINKD_ */
31
32 /* FUNCTIONS *****************************************************************/
33
34 // #ifdef _WINKD_
35 /*
36 * WinDBG Debugger Worker State Machine
37 *
38 * This functionality is used whenever WinDBG wants to attach or kill a user-mode
39 * process from within live kernel-mode session, and/or page-in an address region.
40 * It is implemented as a state machine: when it is in "Ready" state, WinDBG can
41 * initialize the data for the state machine, then switch its state to "Start".
42 * The worker thread balance manager detects this, switches the state to "Initialized"
43 * and queues a worker thread. As long as the state is not "Ready" again, WinDBG
44 * prevents from requeuing a new thread. When the thread is started, it captures
45 * all the data, then resets the machine state to "Ready", thus allowing WinDBG
46 * to requeue another worker thread.
47 *
48 * WinDBG commands:
49 * .process /i <addr> (where <addr> is the address of the EPROCESS block for this process)
50 * .kill <addr> ( " " " " )
51 * .pagein <addr> (where <addr> is the address to page in)
52 */
53 VOID
54 NTAPI
55 ExpDebuggerWorker(IN PVOID Context)
56 {
57 PEPROCESS ProcessToAttach, ProcessToKill;
58 ULONG_PTR PageInAddress;
59 PEPROCESS Process;
60 KAPC_STATE ApcState;
61
62 UNREFERENCED_PARAMETER(Context);
63
64 /* Be sure we were started in an initialized state */
65 ASSERTMSG("ExpDebuggerWorker being entered in non-initialized state!\n",
66 ExpDebuggerWork == WinKdWorkerInitialized);
67 if (ExpDebuggerWork != WinKdWorkerInitialized)
68 {
69 /* An error happened, so get a chance to restart proper */
70 ExpDebuggerWork = WinKdWorkerReady;
71 return;
72 }
73
74 /* Get the processes to be attached or killed, and the address to page in */
75 ProcessToAttach = ExpDebuggerProcessAttach;
76 ProcessToKill = ExpDebuggerProcessKill;
77 PageInAddress = ExpDebuggerPageIn;
78
79 /* Reset the state machine to its ready state */
80 ExpDebuggerProcessAttach = NULL;
81 ExpDebuggerProcessKill = NULL;
82 ExpDebuggerPageIn = (ULONG_PTR)NULL;
83 ExpDebuggerWork = WinKdWorkerReady;
84
85 /* Default to the current process if we don't find the process to be attached or killed */
86 Process = NULL;
87
88 /* Check if we need to attach or kill some process */
89 if (ProcessToAttach != NULL || ProcessToKill != NULL)
90 {
91 /* Find the process in the list */
92 Process = PsGetNextProcess(Process);
93 while (Process)
94 {
95 /* Is this the process we want to attach to? */
96 if (Process == ProcessToAttach)
97 {
98 /* Yes, attach ourselves to it */
99 KeStackAttachProcess(&Process->Pcb, &ApcState);
100 break;
101 }
102 /* Or is this the process we want to kill? */
103 else if (Process == ProcessToKill)
104 {
105 /* Yes, kill and dereference it, then return */
106 PsTerminateProcess(Process, DBG_TERMINATE_PROCESS);
107 ObDereferenceObject(Process);
108 return;
109 }
110
111 /* Get the next process */
112 Process = PsGetNextProcess(Process);
113 }
114
115 /* We either have found a process, or we default to the current process */
116 }
117
118 /* If we have an address to page in... */
119 if (PageInAddress)
120 {
121 /* ... try to do it by attempting to read at this address */
122 _SEH2_TRY
123 {
124 ProbeForReadUchar(PageInAddress);
125 }
126 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
127 {
128 DPRINT1("Failed to page in address 0x%p, Status 0x%08lx\n", PageInAddress, _SEH2_GetExceptionCode());
129 }
130 _SEH2_END;
131 }
132
133 /* Break into the process (or the current one if Process == NULL) */
134 DbgBreakPointWithStatus(DBG_STATUS_WORKER);
135
136 /* If we are attached to a process, not the current one... */
137 if (Process)
138 {
139 /* ... we can detach from the process */
140 KeUnstackDetachProcess(&ApcState);
141 /* Dereference the process which was referenced for us by PsGetNextProcess */
142 ObDereferenceObject(Process);
143 }
144 }
145 // #endif /* _WINKD_ */
146
147 /*++
148 * @name NtSystemDebugControl
149 * @implemented
150 *
151 * Perform various queries to debugger.
152 * This API is subject to test-case creation to further evaluate its
153 * abilities (if needed to at all)
154 *
155 * See: http://www.osronline.com/showthread.cfm?link=93915
156 * http://void.ru/files/Ntexapi.h
157 * http://www.codeguru.com/code/legacy/system/ntexapi.zip
158 * http://www.securityfocus.com/bid/9694
159 *
160 * @param ControlCode
161 * Description of the parameter. Wrapped to more lines on ~70th
162 * column.
163 *
164 * @param InputBuffer
165 * FILLME
166 *
167 * @param InputBufferLength
168 * FILLME
169 *
170 * @param OutputBuffer
171 * FILLME
172 *
173 * @param OutputBufferLength
174 * FILLME
175 *
176 * @param ReturnLength
177 * FILLME
178 *
179 * @return STATUS_SUCCESS in case of success, proper error code otherwise
180 *
181 * @remarks None
182 *
183 *--*/
184 NTSTATUS
185 NTAPI
186 NtSystemDebugControl(SYSDBG_COMMAND ControlCode,
187 PVOID InputBuffer,
188 ULONG InputBufferLength,
189 PVOID OutputBuffer,
190 ULONG OutputBufferLength,
191 PULONG ReturnLength)
192 {
193 switch (ControlCode)
194 {
195 case SysDbgQueryModuleInformation:
196 case SysDbgQueryTraceInformation:
197 case SysDbgSetTracepoint:
198 case SysDbgSetSpecialCall:
199 case SysDbgClearSpecialCalls:
200 case SysDbgQuerySpecialCalls:
201 case SysDbgQueryVersion:
202 case SysDbgReadVirtual:
203 case SysDbgWriteVirtual:
204 case SysDbgReadPhysical:
205 case SysDbgWritePhysical:
206 case SysDbgReadControlSpace:
207 case SysDbgWriteControlSpace:
208 case SysDbgReadIoSpace:
209 case SysDbgWriteIoSpace:
210 case SysDbgReadMsr:
211 case SysDbgWriteMsr:
212 case SysDbgReadBusData:
213 case SysDbgWriteBusData:
214 case SysDbgCheckLowMemory:
215 case SysDbgGetTriageDump:
216 return STATUS_NOT_IMPLEMENTED;
217 case SysDbgBreakPoint:
218 case SysDbgEnableKernelDebugger:
219 case SysDbgDisableKernelDebugger:
220 case SysDbgGetAutoKdEnable:
221 case SysDbgSetAutoKdEnable:
222 case SysDbgGetPrintBufferSize:
223 case SysDbgSetPrintBufferSize:
224 case SysDbgGetKdUmExceptionEnable:
225 case SysDbgSetKdUmExceptionEnable:
226 case SysDbgGetKdBlockEnable:
227 case SysDbgSetKdBlockEnable:
228 return KdSystemDebugControl(
229 ControlCode,
230 InputBuffer, InputBufferLength,
231 OutputBuffer, OutputBufferLength,
232 ReturnLength, KeGetPreviousMode());
233 default:
234 return STATUS_INVALID_INFO_CLASS;
235 }
236 }