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
= LPC_DEBUG_EVENT
;
213 ApiMessage
.ApiNumber
= DbgKmCreateProcessApi
;
215 /* Send the message */
216 DbgkpSendApiMessage(&ApiMessage
, FALSE
);
218 /* Close the handle */
219 ObCloseHandle(CreateProcess
->FileHandle
, KernelMode
);
221 /* Setup the parameters */
222 LoadDll
->BaseOfDll
= PspSystemDllBase
;
223 LoadDll
->DebugInfoFileOffset
= 0;
224 LoadDll
->DebugInfoSize
= 0;
225 LoadDll
->NamePointer
= NULL
;
227 /* Get the NT Headers */
228 NtHeader
= RtlImageNtHeader(PspSystemDllBase
);
231 /* Fill out debug information */
232 LoadDll
->DebugInfoFileOffset
= NtHeader
->
233 FileHeader
.PointerToSymbolTable
;
234 LoadDll
->DebugInfoSize
= NtHeader
->FileHeader
.NumberOfSymbols
;
238 Teb
= Thread
->Tcb
.Teb
;
241 /* Copy the system library name and link to it */
242 wcsncpy(Teb
->StaticUnicodeBuffer
,
244 sizeof(Teb
->StaticUnicodeBuffer
) / sizeof(WCHAR
));
245 Teb
->Tib
.ArbitraryUserPointer
= Teb
->StaticUnicodeBuffer
;
247 /* Return it in the debug event as well */
248 LoadDll
->NamePointer
= &Teb
->Tib
.ArbitraryUserPointer
;
252 InitializeObjectAttributes(&ObjectAttributes
,
254 OBJ_CASE_INSENSITIVE
|
256 OBJ_FORCE_ACCESS_CHECK
,
259 Status
= ZwOpenFile(&LoadDll
->FileHandle
,
260 GENERIC_READ
| SYNCHRONIZE
,
266 FILE_SYNCHRONOUS_IO_NONALERT
);
267 if (NT_SUCCESS(Status
))
269 /* Setup the API Message */
270 ApiMessage
.h
.u1
.Length
= sizeof(DBGKM_MSG
) << 16 |
271 (8 + sizeof(DBGKM_LOAD_DLL
));
272 ApiMessage
.h
.u2
.ZeroInit
= LPC_DEBUG_EVENT
;
273 ApiMessage
.ApiNumber
= DbgKmLoadDllApi
;
275 /* Send the message */
276 DbgkpSendApiMessage(&ApiMessage
, TRUE
);
278 /* Close the handle */
279 ObCloseHandle(LoadDll
->FileHandle
, KernelMode
);
284 /* Otherwise, do it just for the thread */
285 CreateThread
->SubSystemKey
= 0;
286 CreateThread
->StartAddress
= StartAddress
;
288 /* Setup the API Message */
289 ApiMessage
.h
.u1
.Length
= sizeof(DBGKM_MSG
) << 16 |
290 (8 + sizeof(DBGKM_CREATE_THREAD
));
291 ApiMessage
.h
.u2
.ZeroInit
= LPC_DEBUG_EVENT
;
292 ApiMessage
.ApiNumber
= DbgKmCreateThreadApi
;
294 /* Send the message */
295 DbgkpSendApiMessage(&ApiMessage
, TRUE
);
301 DbgkExitProcess(IN NTSTATUS ExitStatus
)
303 DBGKM_MSG ApiMessage
;
304 PDBGKM_EXIT_PROCESS ExitProcess
= &ApiMessage
.ExitProcess
;
305 PEPROCESS Process
= PsGetCurrentProcess();
306 PETHREAD Thread
= PsGetCurrentThread();
309 /* Check if this thread is hidden, doesn't have a debug port, or died */
310 if ((Thread
->HideFromDebugger
) ||
311 !(Process
->DebugPort
) ||
312 (Thread
->DeadThread
))
314 /* Don't notify the debugger */
318 /* Set the exit status */
319 ExitProcess
->ExitStatus
= ExitStatus
;
321 /* Setup the API Message */
322 ApiMessage
.h
.u1
.Length
= sizeof(DBGKM_MSG
) << 16 |
323 (8 + sizeof(DBGKM_EXIT_PROCESS
));
324 ApiMessage
.h
.u2
.ZeroInit
= LPC_DEBUG_EVENT
;
325 ApiMessage
.ApiNumber
= DbgKmExitProcessApi
;
327 /* Set the current exit time */
328 KeQuerySystemTime(&Process
->ExitTime
);
330 /* Send the message */
331 DbgkpSendApiMessage(&ApiMessage
, FALSE
);
336 DbgkExitThread(IN NTSTATUS ExitStatus
)
338 DBGKM_MSG ApiMessage
;
339 PDBGKM_EXIT_THREAD ExitThread
= &ApiMessage
.ExitThread
;
340 PEPROCESS Process
= PsGetCurrentProcess();
341 PETHREAD Thread
= PsGetCurrentThread();
345 /* Check if this thread is hidden, doesn't have a debug port, or died */
346 if ((Thread
->HideFromDebugger
) ||
347 !(Process
->DebugPort
) ||
348 (Thread
->DeadThread
))
350 /* Don't notify the debugger */
354 /* Set the exit status */
355 ExitThread
->ExitStatus
= ExitStatus
;
357 /* Setup the API Message */
358 ApiMessage
.h
.u1
.Length
= sizeof(DBGKM_MSG
) << 16 |
359 (8 + sizeof(DBGKM_EXIT_THREAD
));
360 ApiMessage
.h
.u2
.ZeroInit
= LPC_DEBUG_EVENT
;
361 ApiMessage
.ApiNumber
= DbgKmExitThreadApi
;
363 /* Suspend the process */
364 Suspended
= DbgkpSuspendProcess();
366 /* Send the message */
367 DbgkpSendApiMessage(&ApiMessage
, FALSE
);
369 /* Resume the process if needed */
370 if (Suspended
) DbgkpResumeProcess();
375 DbgkMapViewOfSection(IN PVOID Section
,
376 IN PVOID BaseAddress
,
377 IN ULONG SectionOffset
,
378 IN ULONG_PTR ViewSize
)
380 DBGKM_MSG ApiMessage
;
381 PDBGKM_LOAD_DLL LoadDll
= &ApiMessage
.LoadDll
;
382 PEPROCESS Process
= PsGetCurrentProcess();
383 PETHREAD Thread
= PsGetCurrentThread();
384 PIMAGE_NT_HEADERS NtHeader
;
386 DBGKTRACE(DBGK_PROCESS_DEBUG
,
387 "Section: %p. Base: %p\n", Section
, BaseAddress
);
389 /* Check if this thread is kernel, hidden or doesn't have a debug port */
390 if ((ExGetPreviousMode() == KernelMode
) ||
391 (Thread
->HideFromDebugger
) ||
392 !(Process
->DebugPort
))
394 /* Don't notify the debugger */
398 /* Setup the parameters */
399 LoadDll
->FileHandle
= DbgkpSectionToFileHandle(Section
);
400 LoadDll
->BaseOfDll
= BaseAddress
;
401 LoadDll
->DebugInfoFileOffset
= 0;
402 LoadDll
->DebugInfoSize
= 0;
404 /* Get the NT Headers */
405 NtHeader
= RtlImageNtHeader(BaseAddress
);
408 /* Fill out debug information */
409 LoadDll
->DebugInfoFileOffset
= NtHeader
->FileHeader
.
410 PointerToSymbolTable
;
411 LoadDll
->DebugInfoSize
= NtHeader
->FileHeader
.NumberOfSymbols
;
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
;
420 /* Send the message */
421 DbgkpSendApiMessage(&ApiMessage
, TRUE
);
423 /* Close the handle */
424 ObCloseHandle(LoadDll
->FileHandle
, KernelMode
);
429 DbgkUnMapViewOfSection(IN PVOID BaseAddress
)
431 DBGKM_MSG ApiMessage
;
432 PDBGKM_UNLOAD_DLL UnloadDll
= &ApiMessage
.UnloadDll
;
433 PEPROCESS Process
= PsGetCurrentProcess();
434 PETHREAD Thread
= PsGetCurrentThread();
437 /* Check if this thread is kernel, hidden or doesn't have a debug port */
438 if ((ExGetPreviousMode() == KernelMode
) ||
439 (Thread
->HideFromDebugger
) ||
440 !(Process
->DebugPort
))
442 /* Don't notify the debugger */
446 /* Set the DLL Base */
447 UnloadDll
->BaseAddress
= BaseAddress
;
449 /* Setup the API Message */
450 ApiMessage
.h
.u1
.Length
= sizeof(DBGKM_MSG
) << 16 |
451 (8 + sizeof(DBGKM_UNLOAD_DLL
));
452 ApiMessage
.h
.u2
.ZeroInit
= LPC_DEBUG_EVENT
;
453 ApiMessage
.ApiNumber
= DbgKmUnloadDllApi
;
455 /* Send the message */
456 DbgkpSendApiMessage(&ApiMessage
, TRUE
);