summaryrefslogtreecommitdiffstats
path: root/private/ntos/dbgk/dbgkproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/dbgk/dbgkproc.c')
-rw-r--r--private/ntos/dbgk/dbgkproc.c614
1 files changed, 614 insertions, 0 deletions
diff --git a/private/ntos/dbgk/dbgkproc.c b/private/ntos/dbgk/dbgkproc.c
new file mode 100644
index 000000000..007ca2911
--- /dev/null
+++ b/private/ntos/dbgk/dbgkproc.c
@@ -0,0 +1,614 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dbgkproc.c
+
+Abstract:
+
+ This module implements process control primitives for the
+ Dbg component of NT
+
+Author:
+
+ Mark Lucovsky (markl) 19-Jan-1990
+
+Revision History:
+
+--*/
+
+#include "dbgkp.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, DbgkpSuspendProcess)
+#pragma alloc_text(PAGE, DbgkpResumeProcess)
+#pragma alloc_text(PAGE, DbgkpSectionHandleToFileHandle)
+#pragma alloc_text(PAGE, DbgkCreateThread)
+#pragma alloc_text(PAGE, DbgkExitThread)
+#pragma alloc_text(PAGE, DbgkExitProcess)
+#pragma alloc_text(PAGE, DbgkMapViewOfSection)
+#pragma alloc_text(PAGE, DbgkUnMapViewOfSection)
+#endif
+
+VOID
+DbgkpSuspendProcess(
+ IN BOOLEAN CreateDeleteLockHeld
+ )
+
+/*++
+
+Routine Description:
+
+ This function causes all threads in the calling process except for
+ the calling thread to suspend.
+
+Arguments:
+
+ CreateDeleteLockHeld - Supplies a flag that specifies whether or not
+ the caller is holding the process create delete lock. If the
+ caller holds the lock, than this function will not aquire the
+ lock before suspending the process.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PEPROCESS Process;
+
+ PAGED_CODE();
+
+ Process = PsGetCurrentProcess();
+
+ //
+ // Freeze the execution of all threads in the current process, but
+ // the calling thread.
+ //
+ if ( !CreateDeleteLockHeld ) {
+ PsLockProcess(Process,KernelMode,PsLockWaitForever);
+ }
+
+ KeFreezeAllThreads();
+
+ if ( !CreateDeleteLockHeld ) {
+ PsUnlockProcess(Process);
+ }
+
+
+ return;
+}
+
+VOID
+DbgkpResumeProcess(
+ IN BOOLEAN CreateDeleteLockHeld
+ )
+
+/*++
+
+Routine Description:
+
+ This function causes all threads in the calling process except for
+ the calling thread to resume.
+
+Arguments:
+
+ CreateDeleteLockHeld - Supplies a flag that specifies whether or not
+ the caller is holding the process create delete lock. If the
+ caller holds the lock, than this function will not aquire the
+ lock before suspending the process.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PEPROCESS Process;
+
+ PAGED_CODE();
+
+ Process = PsGetCurrentProcess();
+ //
+ // Thaw the execution of all threads in the current process, but
+ // the calling thread.
+ //
+
+ if ( !CreateDeleteLockHeld ) {
+ PsLockProcess(Process,KernelMode,PsLockWaitForever);
+ }
+
+ KeThawAllThreads();
+
+ if ( !CreateDeleteLockHeld ) {
+ PsUnlockProcess(Process);
+ }
+
+ return;
+}
+
+HANDLE
+DbgkpSectionHandleToFileHandle(
+ IN HANDLE SectionHandle
+ )
+
+/*++
+
+Routine Description:
+
+ This function Opens a handle to the file associated with the processes
+ section. The file is opened such that it can be dupped all the way to
+ the UI where the UI can either map the file or read the file to get
+ the debug info.
+
+Arguments:
+
+ SectionHandle - Supplies a handle to the section whose associated file
+ is to be opened.
+
+Return Value:
+
+ NULL - The file could not be opened.
+
+ NON-NULL - Returns a handle to the file associated with the specified
+ section.
+
+--*/
+
+{
+ NTSTATUS Status;
+ ANSI_STRING FileName;
+ UNICODE_STRING UnicodeFileName;
+ OBJECT_ATTRIBUTES Obja;
+ IO_STATUS_BLOCK IoStatusBlock;
+ HANDLE Handle;
+
+ PAGED_CODE();
+
+ Status = MmGetFileNameForSection(SectionHandle, (PSTRING)&FileName);
+ if ( !NT_SUCCESS(Status) ) {
+ return NULL;
+ }
+
+ Status = RtlAnsiStringToUnicodeString(&UnicodeFileName,&FileName,TRUE);
+ ExFreePool(FileName.Buffer);
+ if ( !NT_SUCCESS(Status) ) {
+ return NULL;
+ }
+
+ InitializeObjectAttributes(
+ &Obja,
+ &UnicodeFileName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ Status = ZwOpenFile(
+ &Handle,
+ (ACCESS_MASK)(GENERIC_READ | SYNCHRONIZE),
+ &Obja,
+ &IoStatusBlock,
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ );
+ RtlFreeUnicodeString(&UnicodeFileName);
+ if ( !NT_SUCCESS(Status) ) {
+ return NULL;
+ }
+ else {
+ return Handle;
+ }
+}
+
+
+VOID
+DbgkCreateThread(
+ PVOID StartAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a new thread begins to execute. If the
+ thread has an associated DebugPort, then a message is sent thru the
+ port.
+
+ If this thread is the first thread in the process, then this event
+ is translated into a CreateProcessInfo message.
+
+ If a message is sent, then while the thread is awaiting a reply,
+ all other threads in the process are suspended.
+
+Arguments:
+
+ StartAddress - Supplies the start address for the thread that is
+ starting.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PVOID Port;
+ DBGKM_APIMSG m;
+ PDBGKM_CREATE_THREAD CreateThreadArgs;
+ PDBGKM_CREATE_PROCESS CreateProcessArgs;
+ PETHREAD Thread;
+ PEPROCESS Process;
+ PDBGKM_LOAD_DLL LoadDllArgs;
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES Obja;
+ IO_STATUS_BLOCK IoStatusBlock;
+ PIMAGE_NT_HEADERS NtHeaders;
+
+ PAGED_CODE();
+
+ Process = PsGetCurrentProcess();
+
+ Port = Process->DebugPort;
+
+ if ( !Port ) {
+ return;
+ }
+
+ Thread = PsGetCurrentThread();
+
+ if ( Thread->DeadThread ) {
+ return;
+ }
+
+ //
+ // To determine if this should be turned into a create process,
+ // all threads in the process are suspended. The process list
+ // is then examined to see if the curent thread is the only thread
+ // on the list. If so, this becomes a create process message
+ //
+
+ PsLockProcess(Process,KernelMode,PsLockWaitForever);
+
+ //
+ // If we are doing a debug attach, then the create process has
+ // already occured. If this is the case, then the process has
+ // accumulated some time, so set reported to true
+ //
+
+ if ( Process->Pcb.UserTime ) {
+ Process->CreateProcessReported = TRUE;
+ }
+
+ if ( Process->CreateProcessReported == FALSE ) {
+
+ //
+ // This is a create process
+ //
+
+ Process->CreateProcessReported = TRUE;
+
+ CreateThreadArgs = &m.u.CreateProcessInfo.InitialThread;
+ CreateThreadArgs->SubSystemKey = 0;
+
+ CreateProcessArgs = &m.u.CreateProcessInfo;
+ CreateProcessArgs->SubSystemKey = 0;
+ CreateProcessArgs->FileHandle = DbgkpSectionHandleToFileHandle(
+ Process->SectionHandle
+ );
+ CreateProcessArgs->BaseOfImage = Process->SectionBaseAddress;
+
+ NtHeaders = RtlImageNtHeader(Process->SectionBaseAddress);
+ if ( NtHeaders ) {
+ CreateThreadArgs->StartAddress = (PVOID)(
+ NtHeaders->OptionalHeader.ImageBase +
+ NtHeaders->OptionalHeader.AddressOfEntryPoint);
+
+ CreateProcessArgs->DebugInfoFileOffset = NtHeaders->FileHeader.PointerToSymbolTable;
+ CreateProcessArgs->DebugInfoSize = NtHeaders->FileHeader.NumberOfSymbols;
+ }
+ else {
+ CreateThreadArgs->StartAddress = NULL;
+ CreateProcessArgs->DebugInfoFileOffset = 0;
+ CreateProcessArgs->DebugInfoSize = 0;
+ }
+
+ DBGKM_FORMAT_API_MSG(m,DbgKmCreateProcessApi,sizeof(*CreateProcessArgs));
+
+ PsUnlockProcess(Process);
+
+ DbgkpSendApiMessage(&m,Port,FALSE);
+ ZwClose(CreateProcessArgs->FileHandle);
+
+ LoadDllArgs = &m.u.LoadDll;
+ LoadDllArgs->BaseOfDll = PsSystemDllBase;
+
+ NtHeaders = RtlImageNtHeader(PsSystemDllBase);
+ if ( NtHeaders ) {
+ LoadDllArgs->DebugInfoFileOffset = NtHeaders->FileHeader.PointerToSymbolTable;
+ LoadDllArgs->DebugInfoSize = NtHeaders->FileHeader.NumberOfSymbols;
+ }
+ else {
+ LoadDllArgs->DebugInfoFileOffset = 0;
+ LoadDllArgs->DebugInfoSize = 0;
+ }
+ //
+ // Send load dll section for NT dll !
+ //
+
+ InitializeObjectAttributes(
+ &Obja,
+ &PsNtDllPathName,
+ OBJ_CASE_INSENSITIVE,
+ NULL,
+ NULL
+ );
+
+ Status = ZwOpenFile(
+ &LoadDllArgs->FileHandle,
+ (ACCESS_MASK)(GENERIC_READ | SYNCHRONIZE),
+ &Obja,
+ &IoStatusBlock,
+ FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
+ FILE_SYNCHRONOUS_IO_NONALERT
+ );
+
+ if ( NT_SUCCESS(Status) ) {
+ DBGKM_FORMAT_API_MSG(m,DbgKmLoadDllApi,sizeof(*LoadDllArgs));
+ DbgkpSendApiMessage(&m,Port,TRUE);
+ }
+ ZwClose(LoadDllArgs->FileHandle);
+
+ } else {
+
+ CreateThreadArgs = &m.u.CreateThread;
+ CreateThreadArgs->SubSystemKey = 0;
+ CreateThreadArgs->StartAddress = StartAddress;
+
+ DBGKM_FORMAT_API_MSG(m,DbgKmCreateThreadApi,sizeof(*CreateThreadArgs));
+
+ PsUnlockProcess(Process);
+
+ DbgkpSendApiMessage(&m,Port,TRUE);
+ }
+
+
+}
+
+VOID
+DbgkExitThread(
+ NTSTATUS ExitStatus
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a new thread terminates. At this
+ point, the thread will no longer execute in user-mode. No other
+ exit processing has occured.
+
+ If a message is sent, then while the thread is awaiting a reply,
+ all other threads in the process are suspended.
+
+Arguments:
+
+ ExitStatus - Supplies the ExitStatus of the exiting thread.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PVOID Port;
+ DBGKM_APIMSG m;
+ PDBGKM_EXIT_THREAD args;
+
+ PAGED_CODE();
+
+ Port = PsGetCurrentProcess()->DebugPort;
+
+ if ( !Port ) {
+ return;
+ }
+
+ if ( PsGetCurrentThread()->DeadThread ) {
+ return;
+ }
+
+ args = &m.u.ExitThread;
+ args->ExitStatus = ExitStatus;
+
+ DBGKM_FORMAT_API_MSG(m,DbgKmExitThreadApi,sizeof(*args));
+
+ DbgkpSuspendProcess(TRUE);
+
+ DbgkpSendApiMessage(&m,Port,FALSE);
+
+ DbgkpResumeProcess(TRUE);
+}
+
+VOID
+DbgkExitProcess(
+ NTSTATUS ExitStatus
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a process terminates. The address
+ space of the process is still intact, but no threads exist in
+ the process.
+
+Arguments:
+
+ ExitStatus - Supplies the ExitStatus of the exiting process.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+ PVOID Port;
+ DBGKM_APIMSG m;
+ PDBGKM_EXIT_PROCESS args;
+
+ PAGED_CODE();
+
+ Port = PsGetCurrentProcess()->DebugPort;
+
+ if ( !Port ) {
+ return;
+ }
+
+ if ( PsGetCurrentThread()->DeadThread ) {
+ return;
+ }
+
+ //
+ // this ensures that other timed lockers of the process will bail
+ // since this call is done while holding the process lock, and lock duration
+ // is controlled by debugger
+ //
+ KeQuerySystemTime(&PsGetCurrentProcess()->ExitTime);
+
+ args = &m.u.ExitProcess;
+ args->ExitStatus = ExitStatus;
+
+ DBGKM_FORMAT_API_MSG(m,DbgKmExitProcessApi,sizeof(*args));
+
+ DbgkpSendApiMessage(&m,Port,FALSE);
+
+}
+
+VOID
+DbgkMapViewOfSection(
+ IN HANDLE SectionHandle,
+ IN PVOID BaseAddress,
+ IN ULONG SectionOffset,
+ IN ULONG ViewSize
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when the current process successfully
+ maps a view of an image section. If the process has an associated
+ debug port, then a load dll message is sent.
+
+Arguments:
+
+ SectionHandle - Supplies a handle to the section mapped by the
+ process.
+
+ BaseAddress - Supplies the base address of where the section is
+ mapped in the current process address space.
+
+ SectionOffset - Supplies the offset in the section where the
+ processes mapped view begins.
+
+ ViewSize - Supplies the size of the mapped view.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PVOID Port;
+ DBGKM_APIMSG m;
+ PDBGKM_LOAD_DLL LoadDllArgs;
+ PEPROCESS Process;
+ PIMAGE_NT_HEADERS NtHeaders;
+
+ PAGED_CODE();
+
+ Process = PsGetCurrentProcess();
+
+ Port = Process->DebugPort;
+
+ if ( !Port || KeGetPreviousMode() == KernelMode ) {
+ return;
+ }
+
+ LoadDllArgs = &m.u.LoadDll;
+ LoadDllArgs->FileHandle = DbgkpSectionHandleToFileHandle(SectionHandle);
+ LoadDllArgs->BaseOfDll = BaseAddress;
+ NtHeaders = RtlImageNtHeader(BaseAddress);
+ if ( NtHeaders ) {
+ LoadDllArgs->DebugInfoFileOffset = NtHeaders->FileHeader.PointerToSymbolTable;
+ LoadDllArgs->DebugInfoSize = NtHeaders->FileHeader.NumberOfSymbols;
+ }
+ else {
+ LoadDllArgs->DebugInfoFileOffset = 0;
+ LoadDllArgs->DebugInfoSize = 0;
+ }
+ DBGKM_FORMAT_API_MSG(m,DbgKmLoadDllApi,sizeof(*LoadDllArgs));
+
+ DbgkpSendApiMessage(&m,Port,TRUE);
+ ZwClose(LoadDllArgs->FileHandle);
+
+}
+
+VOID
+DbgkUnMapViewOfSection(
+ IN PVOID BaseAddress
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when the current process successfully
+ un maps a view of an image section. If the process has an associated
+ debug port, then an "unmap view of section" message is sent.
+
+Arguments:
+
+ BaseAddress - Supplies the base address of the section being
+ unmapped.
+
+Return Value:
+
+ None.
+
+--*/
+
+{
+
+ PVOID Port;
+ DBGKM_APIMSG m;
+ PDBGKM_UNLOAD_DLL UnloadDllArgs;
+ PEPROCESS Process;
+
+ PAGED_CODE();
+
+ Process = PsGetCurrentProcess();
+
+ Port = Process->DebugPort;
+
+ if ( !Port || KeGetPreviousMode() == KernelMode ) {
+ return;
+ }
+
+ UnloadDllArgs = &m.u.UnloadDll;
+ UnloadDllArgs->BaseAddress = BaseAddress;
+
+ DBGKM_FORMAT_API_MSG(m,DbgKmUnloadDllApi,sizeof(*UnloadDllArgs));
+
+ DbgkpSendApiMessage(&m,Port,TRUE);
+
+}