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