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(PVOID StartAddress
)
89 PETHREAD Thread
= PsGetCurrentThread();
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
;
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
))
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;
121 /* Get the NT Headers */
122 NtHeader
= RtlImageNtHeader(Process
->SectionBaseAddress
);
126 ImageInfo
.ImageSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
129 /* Get the image name */
130 Status
= MmGetFileNameForSection(Process
->SectionObject
, &ModuleName
);
131 if (NT_SUCCESS(Status
))
133 /* Call the notify routines and free the name */
134 PspRunLoadImageNotifyRoutines(&ModuleName
->Name
,
135 Process
->UniqueProcessId
,
137 ExFreePool(ModuleName
);
141 /* Call the notify routines */
142 PspRunLoadImageNotifyRoutines(NULL
,
143 Process
->UniqueProcessId
,
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;
155 /* Get the NT Headers */
156 NtHeader
= RtlImageNtHeader(PspSystemDllBase
);
160 ImageInfo
.ImageSize
= NtHeader
->OptionalHeader
.SizeOfImage
;
163 /* Call the notify routines */
164 RtlInitUnicodeString(&NtDllName
,
165 L
"\\SystemRoot\\System32\\ntdll.dll");
166 PspRunLoadImageNotifyRoutines(&NtDllName
,
167 Process
->UniqueProcessId
,
171 /* Fail if we have no port */
172 DebugPort
= Process
->DebugPort
;
173 if (!DebugPort
) return;
175 /* Check if create was not already reported */
176 if (!(ProcessFlags
& PSF_CREATE_REPORTED_BIT
))
178 /* Setup the information structure for the new thread */
179 CreateThread
->SubSystemKey
= 0;
180 CreateThread
->StartAddress
= NULL
;
182 /* And for the new process */
183 CreateProcess
->SubSystemKey
= 0;
184 CreateProcess
->FileHandle
= DbgkpSectionToFileHandle(Process
->
186 CreateProcess
->BaseOfImage
= Process
->SectionBaseAddress
;
187 CreateProcess
->DebugInfoFileOffset
= 0;
188 CreateProcess
->DebugInfoSize
= 0;
190 /* Get the NT Header */
191 NtHeader
= RtlImageNtHeader(Process
->SectionBaseAddress
);
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
.
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
;
211 /* Send the message */
212 DbgkpSendApiMessage(&ApiMessage
, FALSE
);
214 /* Close the handle */
215 ObCloseHandle(CreateProcess
->FileHandle
, KernelMode
);
217 /* Setup the parameters */
218 LoadDll
->BaseOfDll
= PspSystemDllBase
;
219 LoadDll
->DebugInfoFileOffset
= 0;
220 LoadDll
->DebugInfoSize
= 0;
221 LoadDll
->NamePointer
= NULL
;
223 /* Get the NT Headers */
224 NtHeader
= RtlImageNtHeader(PspSystemDllBase
);
227 /* Fill out debug information */
228 LoadDll
->DebugInfoFileOffset
= NtHeader
->
229 FileHeader
.PointerToSymbolTable
;
230 LoadDll
->DebugInfoSize
= NtHeader
->FileHeader
.NumberOfSymbols
;
234 Teb
= Thread
->Tcb
.Teb
;
237 /* Copy the system library name and link to it */
238 wcsncpy(Teb
->StaticUnicodeBuffer
,
240 sizeof(Teb
->StaticUnicodeBuffer
));
241 Teb
->Tib
.ArbitraryUserPointer
= Teb
->StaticUnicodeBuffer
;
243 /* Return it in the debug event as well */
244 LoadDll
->NamePointer
= Teb
->Tib
.ArbitraryUserPointer
;
248 InitializeObjectAttributes(&ObjectAttributes
,
250 OBJ_CASE_INSENSITIVE
|
252 OBJ_FORCE_ACCESS_CHECK
,
255 Status
= ZwOpenFile(&LoadDll
->FileHandle
,
256 GENERIC_READ
| SYNCHRONIZE
,
262 FILE_SYNCHRONOUS_IO_NONALERT
);
263 if (NT_SUCCESS(Status
))
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
;
271 /* Send the message */
272 DbgkpSendApiMessage(&ApiMessage
, TRUE
);
274 /* Close the handle */
275 ObCloseHandle(LoadDll
->FileHandle
, KernelMode
);
280 /* Otherwise, do it just for the thread */
281 CreateThread
->SubSystemKey
= 0;
282 CreateThread
->StartAddress
= NULL
;
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
;
290 /* Send the message */
291 DbgkpSendApiMessage(&ApiMessage
, TRUE
);
297 DbgkExitProcess(IN NTSTATUS ExitStatus
)
299 DBGKM_MSG ApiMessage
;
300 PDBGKM_EXIT_PROCESS ExitProcess
= &ApiMessage
.ExitProcess
;
301 PEPROCESS Process
= PsGetCurrentProcess();
302 PETHREAD Thread
= PsGetCurrentThread();
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
))
310 /* Don't notify the debugger */
314 /* Set the exit status */
315 ExitProcess
->ExitStatus
= ExitStatus
;
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
;
323 /* Set the current exit time */
324 KeQuerySystemTime(&Process
->ExitTime
);
326 /* Send the message */
327 DbgkpSendApiMessage(&ApiMessage
, FALSE
);
332 DbgkExitThread(IN NTSTATUS ExitStatus
)
334 DBGKM_MSG ApiMessage
;
335 PDBGKM_EXIT_THREAD ExitThread
= &ApiMessage
.ExitThread
;
336 PEPROCESS Process
= PsGetCurrentProcess();
337 PETHREAD Thread
= PsGetCurrentThread();
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
))
346 /* Don't notify the debugger */
350 /* Set the exit status */
351 ExitThread
->ExitStatus
= ExitStatus
;
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
;
359 /* Suspend the process */
360 Suspended
= DbgkpSuspendProcess();
362 /* Send the message */
363 DbgkpSendApiMessage(&ApiMessage
, FALSE
);
365 /* Resume the process if needed */
366 if (Suspended
) DbgkpResumeProcess();
371 DbgkMapViewOfSection(IN HANDLE SectionHandle
,
372 IN PVOID BaseAddress
,
373 IN ULONG SectionOffset
,
374 IN ULONG_PTR ViewSize
)
376 DBGKM_MSG ApiMessage
;
377 PDBGKM_LOAD_DLL LoadDll
= &ApiMessage
.LoadDll
;
378 PEPROCESS Process
= PsGetCurrentProcess();
379 PETHREAD Thread
= PsGetCurrentThread();
380 PIMAGE_NT_HEADERS NtHeader
;
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
))
389 /* Don't notify the debugger */
393 /* Setup the parameters */
394 LoadDll
->FileHandle
= DbgkpSectionToFileHandle(SectionHandle
);
395 LoadDll
->BaseOfDll
= BaseAddress
;
396 LoadDll
->DebugInfoFileOffset
= 0;
397 LoadDll
->DebugInfoSize
= 0;
399 /* Get the NT Headers */
400 NtHeader
= RtlImageNtHeader(BaseAddress
);
403 /* Fill out debug information */
404 LoadDll
->DebugInfoFileOffset
= NtHeader
->FileHeader
.
405 PointerToSymbolTable
;
406 LoadDll
->DebugInfoSize
= NtHeader
->FileHeader
.NumberOfSymbols
;
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
;
415 /* Send the message */
416 DbgkpSendApiMessage(&ApiMessage
, TRUE
);
418 /* Close the handle */
419 ObCloseHandle(LoadDll
->FileHandle
, KernelMode
);
424 DbgkUnMapViewOfSection(IN PVOID BaseAddress
)
426 DBGKM_MSG ApiMessage
;
427 PDBGKM_UNLOAD_DLL UnloadDll
= &ApiMessage
.UnloadDll
;
428 PEPROCESS Process
= PsGetCurrentProcess();
429 PETHREAD Thread
= PsGetCurrentThread();
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
))
438 /* Don't notify the debugger */
442 /* Set the DLL Base */
443 UnloadDll
->BaseAddress
= BaseAddress
;
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
;
451 /* Send the message */
452 DbgkpSendApiMessage(&ApiMessage
, TRUE
);