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)
9 /* INCLUDES ******************************************************************/
15 /* FUNCTIONS *****************************************************************/
19 DbgkpSectionToFileHandle(IN PVOID Section
)
22 POBJECT_NAME_INFORMATION FileName
;
23 OBJECT_ATTRIBUTES ObjectAttributes
;
24 IO_STATUS_BLOCK IoStatusBlock
;
28 /* Get the filename of the section */
29 Status
= MmGetFileNameForSection(Section
, &FileName
);
30 if (!NT_SUCCESS(Status
)) return NULL
;
32 /* Initialize object attributes */
33 InitializeObjectAttributes(&ObjectAttributes
,
35 OBJ_CASE_INSENSITIVE
|
36 OBJ_FORCE_ACCESS_CHECK
|
42 Status
= ZwOpenFile(&Handle
,
43 GENERIC_READ
| SYNCHRONIZE
,
46 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
,
47 FILE_SYNCHRONOUS_IO_NONALERT
);
49 /* Free the name and return the handle if we succeeded */
51 if (!NT_SUCCESS(Status
)) return NULL
;
57 DbgkpSuspendProcess(VOID
)
61 /* Make sure this isn't a deleted process */
62 if (!PsGetCurrentProcess()->ProcessDelete
)
64 /* Freeze all the threads */
70 /* No suspend was done */
77 DbgkpResumeProcess(VOID
)
81 /* Thaw all the threads */
87 DbgkCreateThread(IN PETHREAD Thread
,
88 IN PVOID StartAddress
)
90 PEPROCESS Process
= PsGetCurrentProcess();
93 PIMAGE_NT_HEADERS NtHeader
;
94 POBJECT_NAME_INFORMATION ModuleName
;
95 UNICODE_STRING NtDllName
;
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
;
108 ASSERT(Thread
== PsGetCurrentThread());
110 /* Try ORing in the create reported and image notify flags */
111 ProcessFlags
= PspSetProcessFlag(Process
,
112 PSF_CREATE_REPORTED_BIT
|
113 PSF_IMAGE_NOTIFY_DONE_BIT
);
115 /* Check if we were the first to set them or if another thread raced us */
116 if (!(ProcessFlags
& PSF_IMAGE_NOTIFY_DONE_BIT
) && (PsImageNotifyEnabled
))
118 /* It hasn't.. set up the image info for the process */
119 ImageInfo
.Properties
= 0;
120 ImageInfo
.ImageAddressingMode
= IMAGE_ADDRESSING_MODE_32BIT
;
121 ImageInfo
.ImageBase
= Process
->SectionBaseAddress
;
122 ImageInfo
.ImageSize
= 0;
123 ImageInfo
.ImageSelector
= 0;
124 ImageInfo
.ImageSectionNumber
= 0;
126 /* Get the NT Headers */
127 NtHeader
= RtlImageNtHeader(Process
->SectionBaseAddress
);
131 ImageInfo
.ImageSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
134 /* Get the image name */
135 Status
= MmGetFileNameForSection(Process
->SectionObject
, &ModuleName
);
136 if (NT_SUCCESS(Status
))
138 /* Call the notify routines and free the name */
139 PspRunLoadImageNotifyRoutines(&ModuleName
->Name
,
140 Process
->UniqueProcessId
,
142 ExFreePool(ModuleName
);
146 /* Call the notify routines */
147 PspRunLoadImageNotifyRoutines(NULL
,
148 Process
->UniqueProcessId
,
152 /* Setup the info for ntdll.dll */
153 ImageInfo
.Properties
= 0;
154 ImageInfo
.ImageAddressingMode
= IMAGE_ADDRESSING_MODE_32BIT
;
155 ImageInfo
.ImageBase
= PspSystemDllBase
;
156 ImageInfo
.ImageSize
= 0;
157 ImageInfo
.ImageSelector
= 0;
158 ImageInfo
.ImageSectionNumber
= 0;
160 /* Get the NT Headers */
161 NtHeader
= RtlImageNtHeader(PspSystemDllBase
);
165 ImageInfo
.ImageSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
168 /* Call the notify routines */
169 RtlInitUnicodeString(&NtDllName
,
170 L
"\\SystemRoot\\System32\\ntdll.dll");
171 PspRunLoadImageNotifyRoutines(&NtDllName
,
172 Process
->UniqueProcessId
,
176 /* Fail if we have no port */
177 DebugPort
= Process
->DebugPort
;
178 if (!DebugPort
) return;
180 /* Check if create was not already reported */
181 if (!(ProcessFlags
& PSF_CREATE_REPORTED_BIT
))
183 /* Setup the information structure for the new thread */
184 CreateProcess
->InitialThread
.SubSystemKey
= 0;
185 CreateProcess
->InitialThread
.StartAddress
= NULL
;
187 /* And for the new process */
188 CreateProcess
->SubSystemKey
= 0;
189 CreateProcess
->FileHandle
= DbgkpSectionToFileHandle(Process
->
191 CreateProcess
->BaseOfImage
= Process
->SectionBaseAddress
;
192 CreateProcess
->DebugInfoFileOffset
= 0;
193 CreateProcess
->DebugInfoSize
= 0;
195 /* Get the NT Header */
196 NtHeader
= RtlImageNtHeader(Process
->SectionBaseAddress
);
199 /* Fill out data from the header */
200 CreateProcess
->InitialThread
.StartAddress
=
201 (PVOID
)((ULONG_PTR
)NtHeader
->OptionalHeader
.ImageBase
+
202 NtHeader
->OptionalHeader
.AddressOfEntryPoint
);
203 CreateProcess
->DebugInfoFileOffset
= NtHeader
->FileHeader
.
204 PointerToSymbolTable
;
205 CreateProcess
->DebugInfoSize
= NtHeader
->FileHeader
.
209 /* Setup the API Message */
210 ApiMessage
.h
.u1
.Length
= sizeof(DBGKM_MSG
) << 16 |
211 (8 + sizeof(DBGKM_CREATE_PROCESS
));
212 ApiMessage
.h
.u2
.ZeroInit
= 0;
213 ApiMessage
.h
.u2
.s2
.Type
= LPC_DEBUG_EVENT
;
214 ApiMessage
.ApiNumber
= DbgKmCreateProcessApi
;
216 /* Send the message */
217 DbgkpSendApiMessage(&ApiMessage
, FALSE
);
219 /* Close the handle */
220 ObCloseHandle(CreateProcess
->FileHandle
, KernelMode
);
222 /* Setup the parameters */
223 LoadDll
->BaseOfDll
= PspSystemDllBase
;
224 LoadDll
->DebugInfoFileOffset
= 0;
225 LoadDll
->DebugInfoSize
= 0;
226 LoadDll
->NamePointer
= NULL
;
228 /* Get the NT Headers */
229 NtHeader
= RtlImageNtHeader(PspSystemDllBase
);
232 /* Fill out debug information */
233 LoadDll
->DebugInfoFileOffset
= NtHeader
->
234 FileHeader
.PointerToSymbolTable
;
235 LoadDll
->DebugInfoSize
= NtHeader
->FileHeader
.NumberOfSymbols
;
239 Teb
= Thread
->Tcb
.Teb
;
242 /* Copy the system library name and link to it */
243 wcsncpy(Teb
->StaticUnicodeBuffer
,
245 sizeof(Teb
->StaticUnicodeBuffer
) / sizeof(WCHAR
));
246 Teb
->NtTib
.ArbitraryUserPointer
= Teb
->StaticUnicodeBuffer
;
248 /* Return it in the debug event as well */
249 LoadDll
->NamePointer
= &Teb
->NtTib
.ArbitraryUserPointer
;
253 InitializeObjectAttributes(&ObjectAttributes
,
255 OBJ_CASE_INSENSITIVE
|
257 OBJ_FORCE_ACCESS_CHECK
,
260 Status
= ZwOpenFile(&LoadDll
->FileHandle
,
261 GENERIC_READ
| SYNCHRONIZE
,
267 FILE_SYNCHRONOUS_IO_NONALERT
);
268 if (NT_SUCCESS(Status
))
270 /* Setup the API Message */
271 ApiMessage
.h
.u1
.Length
= sizeof(DBGKM_MSG
) << 16 |
272 (8 + sizeof(DBGKM_LOAD_DLL
));
273 ApiMessage
.h
.u2
.ZeroInit
= 0;
274 ApiMessage
.h
.u2
.s2
.Type
= LPC_DEBUG_EVENT
;
275 ApiMessage
.ApiNumber
= DbgKmLoadDllApi
;
277 /* Send the message */
278 DbgkpSendApiMessage(&ApiMessage
, TRUE
);
280 /* Close the handle */
281 ObCloseHandle(LoadDll
->FileHandle
, KernelMode
);
286 /* Otherwise, do it just for the thread */
287 CreateThread
->SubSystemKey
= 0;
288 CreateThread
->StartAddress
= StartAddress
;
290 /* Setup the API Message */
291 ApiMessage
.h
.u1
.Length
= sizeof(DBGKM_MSG
) << 16 |
292 (8 + sizeof(DBGKM_CREATE_THREAD
));
293 ApiMessage
.h
.u2
.ZeroInit
= 0;
294 ApiMessage
.h
.u2
.s2
.Type
= LPC_DEBUG_EVENT
;
295 ApiMessage
.ApiNumber
= DbgKmCreateThreadApi
;
297 /* Send the message */
298 DbgkpSendApiMessage(&ApiMessage
, TRUE
);
304 DbgkExitProcess(IN NTSTATUS ExitStatus
)
306 DBGKM_MSG ApiMessage
;
307 PDBGKM_EXIT_PROCESS ExitProcess
= &ApiMessage
.ExitProcess
;
308 PEPROCESS Process
= PsGetCurrentProcess();
309 PETHREAD Thread
= PsGetCurrentThread();
312 /* Check if this thread is hidden, doesn't have a debug port, or died */
313 if ((Thread
->HideFromDebugger
) ||
314 !(Process
->DebugPort
) ||
315 (Thread
->DeadThread
))
317 /* Don't notify the debugger */
321 /* Set the exit status */
322 ExitProcess
->ExitStatus
= ExitStatus
;
324 /* Setup the API Message */
325 ApiMessage
.h
.u1
.Length
= sizeof(DBGKM_MSG
) << 16 |
326 (8 + sizeof(DBGKM_EXIT_PROCESS
));
327 ApiMessage
.h
.u2
.ZeroInit
= 0;
328 ApiMessage
.h
.u2
.s2
.Type
= LPC_DEBUG_EVENT
;
329 ApiMessage
.ApiNumber
= DbgKmExitProcessApi
;
331 /* Set the current exit time */
332 KeQuerySystemTime(&Process
->ExitTime
);
334 /* Send the message */
335 DbgkpSendApiMessage(&ApiMessage
, FALSE
);
340 DbgkExitThread(IN NTSTATUS ExitStatus
)
342 DBGKM_MSG ApiMessage
;
343 PDBGKM_EXIT_THREAD ExitThread
= &ApiMessage
.ExitThread
;
344 PEPROCESS Process
= PsGetCurrentProcess();
345 PETHREAD Thread
= PsGetCurrentThread();
349 /* Check if this thread is hidden, doesn't have a debug port, or died */
350 if ((Thread
->HideFromDebugger
) ||
351 !(Process
->DebugPort
) ||
352 (Thread
->DeadThread
))
354 /* Don't notify the debugger */
358 /* Set the exit status */
359 ExitThread
->ExitStatus
= ExitStatus
;
361 /* Setup the API Message */
362 ApiMessage
.h
.u1
.Length
= sizeof(DBGKM_MSG
) << 16 |
363 (8 + sizeof(DBGKM_EXIT_THREAD
));
364 ApiMessage
.h
.u2
.ZeroInit
= 0;
365 ApiMessage
.h
.u2
.s2
.Type
= LPC_DEBUG_EVENT
;
366 ApiMessage
.ApiNumber
= DbgKmExitThreadApi
;
368 /* Suspend the process */
369 Suspended
= DbgkpSuspendProcess();
371 /* Send the message */
372 DbgkpSendApiMessage(&ApiMessage
, FALSE
);
374 /* Resume the process if needed */
375 if (Suspended
) DbgkpResumeProcess();
380 DbgkMapViewOfSection(IN PVOID Section
,
381 IN PVOID BaseAddress
,
382 IN ULONG SectionOffset
,
383 IN ULONG_PTR ViewSize
)
385 DBGKM_MSG ApiMessage
;
386 PDBGKM_LOAD_DLL LoadDll
= &ApiMessage
.LoadDll
;
387 PEPROCESS Process
= PsGetCurrentProcess();
388 PETHREAD Thread
= PsGetCurrentThread();
389 PIMAGE_NT_HEADERS NtHeader
;
391 DBGKTRACE(DBGK_PROCESS_DEBUG
,
392 "Section: %p. Base: %p\n", Section
, BaseAddress
);
394 /* Check if this thread is kernel, hidden or doesn't have a debug port */
395 if ((ExGetPreviousMode() == KernelMode
) ||
396 (Thread
->HideFromDebugger
) ||
397 !(Process
->DebugPort
))
399 /* Don't notify the debugger */
403 /* Setup the parameters */
404 LoadDll
->FileHandle
= DbgkpSectionToFileHandle(Section
);
405 LoadDll
->BaseOfDll
= BaseAddress
;
406 LoadDll
->DebugInfoFileOffset
= 0;
407 LoadDll
->DebugInfoSize
= 0;
409 /* Get the NT Headers */
410 NtHeader
= RtlImageNtHeader(BaseAddress
);
413 /* Fill out debug information */
414 LoadDll
->DebugInfoFileOffset
= NtHeader
->FileHeader
.
415 PointerToSymbolTable
;
416 LoadDll
->DebugInfoSize
= NtHeader
->FileHeader
.NumberOfSymbols
;
419 /* Setup the API Message */
420 ApiMessage
.h
.u1
.Length
= sizeof(DBGKM_MSG
) << 16 |
421 (8 + sizeof(DBGKM_LOAD_DLL
));
422 ApiMessage
.h
.u2
.ZeroInit
= 0;
423 ApiMessage
.h
.u2
.s2
.Type
= LPC_DEBUG_EVENT
;
424 ApiMessage
.ApiNumber
= DbgKmLoadDllApi
;
426 /* Send the message */
427 DbgkpSendApiMessage(&ApiMessage
, TRUE
);
429 /* Close the handle */
430 ObCloseHandle(LoadDll
->FileHandle
, KernelMode
);
435 DbgkUnMapViewOfSection(IN PVOID BaseAddress
)
437 DBGKM_MSG ApiMessage
;
438 PDBGKM_UNLOAD_DLL UnloadDll
= &ApiMessage
.UnloadDll
;
439 PEPROCESS Process
= PsGetCurrentProcess();
440 PETHREAD Thread
= PsGetCurrentThread();
443 /* Check if this thread is kernel, hidden or doesn't have a debug port */
444 if ((ExGetPreviousMode() == KernelMode
) ||
445 (Thread
->HideFromDebugger
) ||
446 !(Process
->DebugPort
))
448 /* Don't notify the debugger */
452 /* Set the DLL Base */
453 UnloadDll
->BaseAddress
= BaseAddress
;
455 /* Setup the API Message */
456 ApiMessage
.h
.u1
.Length
= sizeof(DBGKM_MSG
) << 16 |
457 (8 + sizeof(DBGKM_UNLOAD_DLL
));
458 ApiMessage
.h
.u2
.ZeroInit
= 0;
459 ApiMessage
.h
.u2
.s2
.Type
= LPC_DEBUG_EVENT
;
460 ApiMessage
.ApiNumber
= DbgKmUnloadDllApi
;
462 /* Send the message */
463 DbgkpSendApiMessage(&ApiMessage
, TRUE
);