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 extern ULONG DbgkpTraceLevel
;
17 /* FUNCTIONS *****************************************************************/
21 DbgkpSectionToFileHandle(IN PVOID Section
)
24 POBJECT_NAME_INFORMATION FileName
;
25 OBJECT_ATTRIBUTES ObjectAttributes
;
26 IO_STATUS_BLOCK IoStatusBlock
;
30 /* Get the filename of the section */
31 Status
= MmGetFileNameForSection(Section
, &FileName
);
32 if (!NT_SUCCESS(Status
)) return NULL
;
34 /* Initialize object attributes */
35 InitializeObjectAttributes(&ObjectAttributes
,
37 OBJ_CASE_INSENSITIVE
|
38 OBJ_FORCE_ACCESS_CHECK
|
44 Status
= ZwOpenFile(&Handle
,
45 GENERIC_READ
| SYNCHRONIZE
,
48 FILE_SHARE_DELETE
| FILE_SHARE_READ
| FILE_SHARE_WRITE
,
49 FILE_SYNCHRONOUS_IO_NONALERT
);
51 /* Free the name and return the handle if we succeeded */
53 if (!NT_SUCCESS(Status
)) return NULL
;
59 DbgkpSuspendProcess(VOID
)
63 /* Make sure this isn't a deleted process */
64 if (!PsGetCurrentProcess()->ProcessDelete
)
66 /* Freeze all the threads */
72 /* No suspend was done */
79 DbgkpResumeProcess(VOID
)
83 /* Thaw all the threads */
89 DbgkCreateThread(PVOID StartAddress
)
91 PETHREAD Thread
= PsGetCurrentThread();
92 PEPROCESS Process
= PsGetCurrentProcess();
95 PIMAGE_NT_HEADERS NtHeader
;
96 POBJECT_NAME_INFORMATION ModuleName
;
97 UNICODE_STRING NtDllName
;
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
;
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
);
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
))
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;
125 /* Get the NT Headers */
126 NtHeader
= RtlImageNtHeader(Process
->SectionBaseAddress
);
130 ImageInfo
.ImageSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
133 /* Get the image name */
134 Status
= MmGetFileNameForSection(Process
->SectionObject
, &ModuleName
);
135 if (NT_SUCCESS(Status
))
137 /* Call the notify routines and free the name */
138 PspRunLoadImageNotifyRoutines(&ModuleName
->Name
,
139 Process
->UniqueProcessId
,
141 ExFreePool(ModuleName
);
145 /* Call the notify routines */
146 PspRunLoadImageNotifyRoutines(NULL
,
147 Process
->UniqueProcessId
,
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;
159 /* Get the NT Headers */
160 NtHeader
= RtlImageNtHeader(PspSystemDllBase
);
164 ImageInfo
.ImageSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
167 /* Call the notify routines */
168 RtlInitUnicodeString(&NtDllName
,
169 L
"\\SystemRoot\\System32\\ntdll.dll");
170 PspRunLoadImageNotifyRoutines(&NtDllName
,
171 Process
->UniqueProcessId
,
175 /* Fail if we have no port */
176 DebugPort
= Process
->DebugPort
;
177 if (!DebugPort
) return;
179 /* Check if create was not already reported */
180 if (!(ProcessFlags
& PSF_CREATE_REPORTED_BIT
))
182 /* Setup the information structure for the new thread */
183 CreateProcess
->InitialThread
.SubSystemKey
= 0;
184 CreateProcess
->InitialThread
.StartAddress
= NULL
;
186 /* And for the new process */
187 CreateProcess
->SubSystemKey
= 0;
188 CreateProcess
->FileHandle
= DbgkpSectionToFileHandle(Process
->
190 CreateProcess
->BaseOfImage
= Process
->SectionBaseAddress
;
191 CreateProcess
->DebugInfoFileOffset
= 0;
192 CreateProcess
->DebugInfoSize
= 0;
194 /* Get the NT Header */
195 NtHeader
= RtlImageNtHeader(Process
->SectionBaseAddress
);
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
.
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
;
214 /* Send the message */
215 DbgkpSendApiMessage(&ApiMessage
, FALSE
);
217 /* Close the handle */
218 ObCloseHandle(CreateProcess
->FileHandle
, KernelMode
);
220 /* Setup the parameters */
221 LoadDll
->BaseOfDll
= PspSystemDllBase
;
222 LoadDll
->DebugInfoFileOffset
= 0;
223 LoadDll
->DebugInfoSize
= 0;
224 LoadDll
->NamePointer
= NULL
;
226 /* Get the NT Headers */
227 NtHeader
= RtlImageNtHeader(PspSystemDllBase
);
230 /* Fill out debug information */
231 LoadDll
->DebugInfoFileOffset
= NtHeader
->
232 FileHeader
.PointerToSymbolTable
;
233 LoadDll
->DebugInfoSize
= NtHeader
->FileHeader
.NumberOfSymbols
;
237 Teb
= Thread
->Tcb
.Teb
;
240 /* Copy the system library name and link to it */
241 wcsncpy(Teb
->StaticUnicodeBuffer
,
243 sizeof(Teb
->StaticUnicodeBuffer
) / sizeof(WCHAR
));
244 Teb
->Tib
.ArbitraryUserPointer
= Teb
->StaticUnicodeBuffer
;
246 /* Return it in the debug event as well */
247 LoadDll
->NamePointer
= &Teb
->Tib
.ArbitraryUserPointer
;
251 InitializeObjectAttributes(&ObjectAttributes
,
253 OBJ_CASE_INSENSITIVE
|
255 OBJ_FORCE_ACCESS_CHECK
,
258 Status
= ZwOpenFile(&LoadDll
->FileHandle
,
259 GENERIC_READ
| SYNCHRONIZE
,
265 FILE_SYNCHRONOUS_IO_NONALERT
);
266 if (NT_SUCCESS(Status
))
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
;
274 /* Send the message */
275 DbgkpSendApiMessage(&ApiMessage
, TRUE
);
277 /* Close the handle */
278 ObCloseHandle(LoadDll
->FileHandle
, KernelMode
);
283 /* Otherwise, do it just for the thread */
284 CreateThread
->SubSystemKey
= 0;
285 CreateThread
->StartAddress
= NULL
;
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
;
293 /* Send the message */
294 DbgkpSendApiMessage(&ApiMessage
, TRUE
);
300 DbgkExitProcess(IN NTSTATUS ExitStatus
)
302 DBGKM_MSG ApiMessage
;
303 PDBGKM_EXIT_PROCESS ExitProcess
= &ApiMessage
.ExitProcess
;
304 PEPROCESS Process
= PsGetCurrentProcess();
305 PETHREAD Thread
= PsGetCurrentThread();
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
))
313 /* Don't notify the debugger */
317 /* Set the exit status */
318 ExitProcess
->ExitStatus
= ExitStatus
;
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
;
326 /* Set the current exit time */
327 KeQuerySystemTime(&Process
->ExitTime
);
329 /* Send the message */
330 DbgkpSendApiMessage(&ApiMessage
, FALSE
);
335 DbgkExitThread(IN NTSTATUS ExitStatus
)
337 DBGKM_MSG ApiMessage
;
338 PDBGKM_EXIT_THREAD ExitThread
= &ApiMessage
.ExitThread
;
339 PEPROCESS Process
= PsGetCurrentProcess();
340 PETHREAD Thread
= PsGetCurrentThread();
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
))
349 /* Don't notify the debugger */
353 /* Set the exit status */
354 ExitThread
->ExitStatus
= ExitStatus
;
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
;
362 /* Suspend the process */
363 Suspended
= DbgkpSuspendProcess();
365 /* Send the message */
366 DbgkpSendApiMessage(&ApiMessage
, FALSE
);
368 /* Resume the process if needed */
369 if (Suspended
) DbgkpResumeProcess();
374 DbgkMapViewOfSection(IN PVOID Section
,
375 IN PVOID BaseAddress
,
376 IN ULONG SectionOffset
,
377 IN ULONG_PTR ViewSize
)
379 DBGKM_MSG ApiMessage
;
380 PDBGKM_LOAD_DLL LoadDll
= &ApiMessage
.LoadDll
;
381 PEPROCESS Process
= PsGetCurrentProcess();
382 PETHREAD Thread
= PsGetCurrentThread();
383 PIMAGE_NT_HEADERS NtHeader
;
385 DBGKTRACE(DBGK_PROCESS_DEBUG
,
386 "Section: %p. Base: %p\n", Section
, BaseAddress
);
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
))
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 hidden, doesn't have a debug port, or died */
438 if ((Thread
->HideFromDebugger
) ||
439 !(Process
->DebugPort
) ||
440 (Thread
->DeadThread
) ||
441 (KeGetPreviousMode() == KernelMode
))
443 /* Don't notify the debugger */
447 /* Set the DLL Base */
448 UnloadDll
->BaseAddress
= BaseAddress
;
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
;
456 /* Send the message */
457 DbgkpSendApiMessage(&ApiMessage
, TRUE
);