- Fix some bugs in NtWaitForDebugEvent which caused debug events to be sent in the...
[reactos.git] / reactos / ntoskrnl / dbgk / dbgkutil.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/dbgk/dbgkutil.c
5 * PURPOSE: User-Mode Debugging Support, Internal Debug Functions.
6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
7 */
8
9 /* INCLUDES ******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 /* FUNCTIONS *****************************************************************/
16
17 HANDLE
18 NTAPI
19 DbgkpSectionToFileHandle(IN PVOID Section)
20 {
21 NTSTATUS Status;
22 POBJECT_NAME_INFORMATION FileName;
23 OBJECT_ATTRIBUTES ObjectAttributes;
24 IO_STATUS_BLOCK IoStatusBlock;
25 HANDLE Handle;
26 PAGED_CODE();
27
28 /* Get the filename of the section */
29 Status = MmGetFileNameForSection(Section, &FileName);
30 if (!NT_SUCCESS(Status)) return NULL;
31
32 /* Initialize object attributes */
33 InitializeObjectAttributes(&ObjectAttributes,
34 &FileName->Name,
35 OBJ_CASE_INSENSITIVE |
36 OBJ_FORCE_ACCESS_CHECK |
37 OBJ_KERNEL_HANDLE,
38 NULL,
39 NULL);
40
41 /* Open the file */
42 Status = ZwOpenFile(&Handle,
43 GENERIC_READ | SYNCHRONIZE,
44 &ObjectAttributes,
45 &IoStatusBlock,
46 FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
47 FILE_SYNCHRONOUS_IO_NONALERT);
48
49 /* Free the name and return the handle if we succeeded */
50 ExFreePool(FileName);
51 if (!NT_SUCCESS(Status)) return NULL;
52 return Handle;
53 }
54
55 BOOLEAN
56 NTAPI
57 DbgkpSuspendProcess(VOID)
58 {
59 PAGED_CODE();
60
61 /* Make sure this isn't a deleted process */
62 if (PsGetCurrentProcess()->ProcessDelete)
63 {
64 /* Freeze all the threads */
65 KeFreezeAllThreads();
66 return TRUE;
67 }
68 else
69 {
70 /* No suspend was done */
71 return FALSE;
72 }
73 }
74
75 VOID
76 NTAPI
77 DbgkpResumeProcess(VOID)
78 {
79 PAGED_CODE();
80
81 /* Thaw all the threads */
82 KeThawAllThreads();
83 }
84
85 VOID
86 NTAPI
87 DbgkCreateThread(PVOID StartAddress)
88 {
89 PETHREAD Thread = PsGetCurrentThread();
90 PEPROCESS Process = PsGetCurrentProcess();
91 ULONG ProcessFlags;
92 IMAGE_INFO ImageInfo;
93 PIMAGE_NT_HEADERS NtHeader;
94 POBJECT_NAME_INFORMATION ModuleName;
95 UNICODE_STRING NtDllName;
96 NTSTATUS Status;
97 PVOID DebugPort;
98 DBGKM_MSG ApiMessage;
99 PDBGKM_CREATE_THREAD CreateThread = &ApiMessage.CreateThread;
100 PDBGKM_CREATE_PROCESS CreateProcess = &ApiMessage.CreateProcess;
101 PDBGKM_LOAD_DLL LoadDll = &ApiMessage.LoadDll;
102 OBJECT_ATTRIBUTES ObjectAttributes;
103 IO_STATUS_BLOCK IoStatusBlock;
104 PTEB Teb;
105 PAGED_CODE();
106
107 /* Check if this process has already been notified */
108 ProcessFlags = InterlockedAnd((PLONG)&Process->Flags,
109 PSF_CREATE_REPORTED_BIT |
110 PSF_IMAGE_NOTIFY_DONE_BIT);
111 if (!(ProcessFlags & PSF_IMAGE_NOTIFY_DONE_BIT) && (PsImageNotifyEnabled))
112 {
113 /* It hasn't.. set up the image info for the process */
114 ImageInfo.Properties = 0;
115 ImageInfo.ImageAddressingMode = IMAGE_ADDRESSING_MODE_32BIT;
116 ImageInfo.ImageBase = Process->SectionBaseAddress;
117 ImageInfo.ImageSize = 0;
118 ImageInfo.ImageSelector = 0;
119 ImageInfo.ImageSectionNumber = 0;
120
121 /* Get the NT Headers */
122 NtHeader = RtlImageNtHeader(Process->SectionBaseAddress);
123 if (NtHeader)
124 {
125 /* Set image size */
126 ImageInfo.ImageSize = NtHeader->OptionalHeader.SizeOfImage;
127 }
128
129 /* Get the image name */
130 Status = MmGetFileNameForSection(Process->SectionObject, &ModuleName);
131 if (NT_SUCCESS(Status))
132 {
133 /* Call the notify routines and free the name */
134 PspRunLoadImageNotifyRoutines(&ModuleName->Name,
135 Process->UniqueProcessId,
136 &ImageInfo);
137 ExFreePool(ModuleName);
138 }
139 else
140 {
141 /* Call the notify routines */
142 PspRunLoadImageNotifyRoutines(NULL,
143 Process->UniqueProcessId,
144 &ImageInfo);
145 }
146
147 /* Setup the info for ntdll.dll */
148 ImageInfo.Properties = 0;
149 ImageInfo.ImageAddressingMode = IMAGE_ADDRESSING_MODE_32BIT;
150 ImageInfo.ImageBase = PspSystemDllBase;
151 ImageInfo.ImageSize = 0;
152 ImageInfo.ImageSelector = 0;
153 ImageInfo.ImageSectionNumber = 0;
154
155 /* Get the NT Headers */
156 NtHeader = RtlImageNtHeader(PspSystemDllBase);
157 if (NtHeader)
158 {
159 /* Set image size */
160 ImageInfo.ImageSize = NtHeader->OptionalHeader.SizeOfImage;
161 }
162
163 /* Call the notify routines */
164 RtlInitUnicodeString(&NtDllName,
165 L"\\SystemRoot\\System32\\ntdll.dll");
166 PspRunLoadImageNotifyRoutines(&NtDllName,
167 Process->UniqueProcessId,
168 &ImageInfo);
169 }
170
171 /* Fail if we have no port */
172 DebugPort = Process->DebugPort;
173 if (!DebugPort) return;
174
175 /* Check if create was not already reported */
176 if (!(ProcessFlags & PSF_CREATE_REPORTED_BIT))
177 {
178 /* Setup the information structure for the new thread */
179 CreateThread->SubSystemKey = 0;
180 CreateThread->StartAddress = NULL;
181
182 /* And for the new process */
183 CreateProcess->SubSystemKey = 0;
184 CreateProcess->FileHandle = DbgkpSectionToFileHandle(Process->
185 SectionObject);
186 CreateProcess->BaseOfImage = Process->SectionBaseAddress;
187 CreateProcess->DebugInfoFileOffset = 0;
188 CreateProcess->DebugInfoSize = 0;
189
190 /* Get the NT Header */
191 NtHeader = RtlImageNtHeader(Process->SectionBaseAddress);
192 if (NtHeader)
193 {
194 /* Fill out data from the header */
195 CreateThread->StartAddress = (PVOID)((ULONG_PTR)NtHeader->
196 OptionalHeader.ImageBase +
197 NtHeader->OptionalHeader.
198 AddressOfEntryPoint);
199 CreateProcess->DebugInfoFileOffset = NtHeader->FileHeader.
200 PointerToSymbolTable;
201 CreateProcess->DebugInfoSize = NtHeader->FileHeader.
202 NumberOfSymbols;
203 }
204
205 /* Setup the API Message */
206 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
207 (8 + sizeof(DBGKM_CREATE_PROCESS));
208 ApiMessage.h.u2.ZeroInit = LPC_DEBUG_EVENT;
209 ApiMessage.ApiNumber = DbgKmCreateProcessApi;
210
211 /* Send the message */
212 DbgkpSendApiMessage(&ApiMessage, FALSE);
213
214 /* Close the handle */
215 ObCloseHandle(CreateProcess->FileHandle, KernelMode);
216
217 /* Setup the parameters */
218 LoadDll->BaseOfDll = PspSystemDllBase;
219 LoadDll->DebugInfoFileOffset = 0;
220 LoadDll->DebugInfoSize = 0;
221 LoadDll->NamePointer = NULL;
222
223 /* Get the NT Headers */
224 NtHeader = RtlImageNtHeader(PspSystemDllBase);
225 if (NtHeader)
226 {
227 /* Fill out debug information */
228 LoadDll->DebugInfoFileOffset = NtHeader->
229 FileHeader.PointerToSymbolTable;
230 LoadDll->DebugInfoSize = NtHeader->FileHeader.NumberOfSymbols;
231 }
232
233 /* Get the TEB */
234 Teb = Thread->Tcb.Teb;
235 if (Teb)
236 {
237 /* Copy the system library name and link to it */
238 wcsncpy(Teb->StaticUnicodeBuffer,
239 L"ntdll.dll",
240 sizeof(Teb->StaticUnicodeBuffer));
241 Teb->Tib.ArbitraryUserPointer = Teb->StaticUnicodeBuffer;
242
243 /* Return it in the debug event as well */
244 LoadDll->NamePointer = Teb->Tib.ArbitraryUserPointer;
245 }
246
247 /* Get a handle */
248 InitializeObjectAttributes(&ObjectAttributes,
249 &PsNtDllPathName,
250 OBJ_CASE_INSENSITIVE |
251 OBJ_KERNEL_HANDLE |
252 OBJ_FORCE_ACCESS_CHECK,
253 NULL,
254 NULL);
255 Status = ZwOpenFile(&LoadDll->FileHandle,
256 GENERIC_READ | SYNCHRONIZE,
257 &ObjectAttributes,
258 &IoStatusBlock,
259 FILE_SHARE_DELETE |
260 FILE_SHARE_READ |
261 FILE_SHARE_WRITE,
262 FILE_SYNCHRONOUS_IO_NONALERT);
263 if (NT_SUCCESS(Status))
264 {
265 /* Setup the API Message */
266 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
267 (8 + sizeof(DBGKM_LOAD_DLL));
268 ApiMessage.h.u2.ZeroInit = LPC_DEBUG_EVENT;
269 ApiMessage.ApiNumber = DbgKmLoadDllApi;
270
271 /* Send the message */
272 DbgkpSendApiMessage(&ApiMessage, TRUE);
273
274 /* Close the handle */
275 ObCloseHandle(LoadDll->FileHandle, KernelMode);
276 }
277 }
278 else
279 {
280 /* Otherwise, do it just for the thread */
281 CreateThread->SubSystemKey = 0;
282 CreateThread->StartAddress = NULL;
283
284 /* Setup the API Message */
285 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
286 (8 + sizeof(DBGKM_CREATE_THREAD));
287 ApiMessage.h.u2.ZeroInit = LPC_DEBUG_EVENT;
288 ApiMessage.ApiNumber = DbgKmCreateThreadApi;
289
290 /* Send the message */
291 DbgkpSendApiMessage(&ApiMessage, TRUE);
292 }
293 }
294
295 VOID
296 NTAPI
297 DbgkExitProcess(IN NTSTATUS ExitStatus)
298 {
299 DBGKM_MSG ApiMessage;
300 PDBGKM_EXIT_PROCESS ExitProcess = &ApiMessage.ExitProcess;
301 PEPROCESS Process = PsGetCurrentProcess();
302 PETHREAD Thread = PsGetCurrentThread();
303 PAGED_CODE();
304
305 /* Check if this thread is hidden, doesn't have a debug port, or died */
306 if ((Thread->HideFromDebugger) ||
307 !(Process->DebugPort) ||
308 (Thread->DeadThread))
309 {
310 /* Don't notify the debugger */
311 return;
312 }
313
314 /* Set the exit status */
315 ExitProcess->ExitStatus = ExitStatus;
316
317 /* Setup the API Message */
318 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
319 (8 + sizeof(DBGKM_EXIT_PROCESS));
320 ApiMessage.h.u2.ZeroInit = LPC_DEBUG_EVENT;
321 ApiMessage.ApiNumber = DbgKmExitProcessApi;
322
323 /* Set the current exit time */
324 KeQuerySystemTime(&Process->ExitTime);
325
326 /* Send the message */
327 DbgkpSendApiMessage(&ApiMessage, FALSE);
328 }
329
330 VOID
331 NTAPI
332 DbgkExitThread(IN NTSTATUS ExitStatus)
333 {
334 DBGKM_MSG ApiMessage;
335 PDBGKM_EXIT_THREAD ExitThread = &ApiMessage.ExitThread;
336 PEPROCESS Process = PsGetCurrentProcess();
337 PETHREAD Thread = PsGetCurrentThread();
338 BOOLEAN Suspended;
339 PAGED_CODE();
340
341 /* Check if this thread is hidden, doesn't have a debug port, or died */
342 if ((Thread->HideFromDebugger) ||
343 !(Process->DebugPort) ||
344 (Thread->DeadThread))
345 {
346 /* Don't notify the debugger */
347 return;
348 }
349
350 /* Set the exit status */
351 ExitThread->ExitStatus = ExitStatus;
352
353 /* Setup the API Message */
354 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
355 (8 + sizeof(DBGKM_EXIT_THREAD));
356 ApiMessage.h.u2.ZeroInit = LPC_DEBUG_EVENT;
357 ApiMessage.ApiNumber = DbgKmExitThreadApi;
358
359 /* Suspend the process */
360 Suspended = DbgkpSuspendProcess();
361
362 /* Send the message */
363 DbgkpSendApiMessage(&ApiMessage, FALSE);
364
365 /* Resume the process if needed */
366 if (Suspended) DbgkpResumeProcess();
367 }
368
369 VOID
370 NTAPI
371 DbgkMapViewOfSection(IN HANDLE SectionHandle,
372 IN PVOID BaseAddress,
373 IN ULONG SectionOffset,
374 IN ULONG_PTR ViewSize)
375 {
376 DBGKM_MSG ApiMessage;
377 PDBGKM_LOAD_DLL LoadDll = &ApiMessage.LoadDll;
378 PEPROCESS Process = PsGetCurrentProcess();
379 PETHREAD Thread = PsGetCurrentThread();
380 PIMAGE_NT_HEADERS NtHeader;
381 PAGED_CODE();
382
383 /* Check if this thread is hidden, doesn't have a debug port, or died */
384 if ((Thread->HideFromDebugger) ||
385 !(Process->DebugPort) ||
386 (Thread->DeadThread) ||
387 (KeGetPreviousMode() == KernelMode))
388 {
389 /* Don't notify the debugger */
390 return;
391 }
392
393 /* Setup the parameters */
394 LoadDll->FileHandle = DbgkpSectionToFileHandle(SectionHandle);
395 LoadDll->BaseOfDll = BaseAddress;
396 LoadDll->DebugInfoFileOffset = 0;
397 LoadDll->DebugInfoSize = 0;
398
399 /* Get the NT Headers */
400 NtHeader = RtlImageNtHeader(BaseAddress);
401 if (NtHeader)
402 {
403 /* Fill out debug information */
404 LoadDll->DebugInfoFileOffset = NtHeader->FileHeader.
405 PointerToSymbolTable;
406 LoadDll->DebugInfoSize = NtHeader->FileHeader.NumberOfSymbols;
407 }
408
409 /* Setup the API Message */
410 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
411 (8 + sizeof(DBGKM_LOAD_DLL));
412 ApiMessage.h.u2.ZeroInit = LPC_DEBUG_EVENT;
413 ApiMessage.ApiNumber = DbgKmLoadDllApi;
414
415 /* Send the message */
416 DbgkpSendApiMessage(&ApiMessage, TRUE);
417
418 /* Close the handle */
419 ObCloseHandle(LoadDll->FileHandle, KernelMode);
420 }
421
422 VOID
423 NTAPI
424 DbgkUnMapViewOfSection(IN PVOID BaseAddress)
425 {
426 DBGKM_MSG ApiMessage;
427 PDBGKM_UNLOAD_DLL UnloadDll = &ApiMessage.UnloadDll;
428 PEPROCESS Process = PsGetCurrentProcess();
429 PETHREAD Thread = PsGetCurrentThread();
430 PAGED_CODE();
431
432 /* Check if this thread is hidden, doesn't have a debug port, or died */
433 if ((Thread->HideFromDebugger) ||
434 !(Process->DebugPort) ||
435 (Thread->DeadThread) ||
436 (KeGetPreviousMode() == KernelMode))
437 {
438 /* Don't notify the debugger */
439 return;
440 }
441
442 /* Set the DLL Base */
443 UnloadDll->BaseAddress = BaseAddress;
444
445 /* Setup the API Message */
446 ApiMessage.h.u1.Length = sizeof(DBGKM_MSG) << 16 |
447 (8 + sizeof(DBGKM_UNLOAD_DLL));
448 ApiMessage.h.u2.ZeroInit = LPC_DEBUG_EVENT;
449 ApiMessage.ApiNumber = DbgKmUnloadDllApi;
450
451 /* Send the message */
452 DbgkpSendApiMessage(&ApiMessage, TRUE);
453 }
454
455 /* EOF */