summaryrefslogtreecommitdiffstats
path: root/private/ntos/dbgk
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/dbgk
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/dbgk')
-rw-r--r--private/ntos/dbgk/dbgkp.h60
-rw-r--r--private/ntos/dbgk/dbgkport.c193
-rw-r--r--private/ntos/dbgk/dbgkproc.c614
-rw-r--r--private/ntos/dbgk/dirs24
-rw-r--r--private/ntos/dbgk/mp/makefile6
-rw-r--r--private/ntos/dbgk/mp/sources29
-rw-r--r--private/ntos/dbgk/sources.inc42
-rw-r--r--private/ntos/dbgk/udbgk.c472
-rw-r--r--private/ntos/dbgk/up/makefile6
-rw-r--r--private/ntos/dbgk/up/sources27
10 files changed, 1473 insertions, 0 deletions
diff --git a/private/ntos/dbgk/dbgkp.h b/private/ntos/dbgk/dbgkp.h
new file mode 100644
index 000000000..52b511f6e
--- /dev/null
+++ b/private/ntos/dbgk/dbgkp.h
@@ -0,0 +1,60 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dbgkp.h
+
+Abstract:
+
+ This header file describes private data structures and functions
+ that make up the kernel mode portion of the Dbg subsystem.
+
+Author:
+
+ Mark Lucovsky (markl) 19-Jan-1990
+
+[Environment:]
+
+ optional-environment-info (e.g. kernel mode only...)
+
+[Notes:]
+
+ optional-notes
+
+Revision History:
+
+--*/
+
+#ifndef _DBGKP_
+#define _DBGKP_
+
+#include "ntos.h"
+#include "ntdbg.h"
+#include <zwapi.h>
+#include <string.h>
+
+NTSTATUS
+DbgkpSendApiMessage(
+ IN OUT PDBGKM_APIMSG ApiMsg,
+ IN PVOID Port,
+ IN BOOLEAN SuspendProcess
+ );
+
+VOID
+DbgkpSuspendProcess(
+ IN BOOLEAN CreateDeleteLockHeld
+ );
+
+VOID
+DbgkpResumeProcess(
+ IN BOOLEAN CreateDeleteLockHeld
+ );
+
+HANDLE
+DbgkpSectionHandleToFileHandle(
+ IN HANDLE SectionHandle
+ );
+
+#endif // _DBGKP_
diff --git a/private/ntos/dbgk/dbgkport.c b/private/ntos/dbgk/dbgkport.c
new file mode 100644
index 000000000..9541ef21a
--- /dev/null
+++ b/private/ntos/dbgk/dbgkport.c
@@ -0,0 +1,193 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dbgkport.c
+
+Abstract:
+
+ This module implements the dbg primitives to access a processes
+ DebugPort and ExceptionPort.
+
+Author:
+
+ Mark Lucovsky (markl) 19-Jan-1990
+
+Revision History:
+
+--*/
+
+#include "dbgkp.h"
+
+#ifdef ALLOC_PRAGMA
+#pragma alloc_text(PAGE, DbgkpSendApiMessage)
+#pragma alloc_text(PAGE, DbgkForwardException)
+#endif
+
+
+NTSTATUS
+DbgkpSendApiMessage(
+ IN OUT PDBGKM_APIMSG ApiMsg,
+ IN PVOID Port,
+ IN BOOLEAN SuspendProcess
+ )
+
+/*++
+
+Routine Description:
+
+ This function sends the specified API message over the specified
+ port. It is the callers responsibility to format the API message
+ prior to calling this function.
+
+ If the SuspendProcess flag is supplied, then all threads in the
+ calling process are first suspended. Upon receipt of the reply
+ message, the threads are resumed.
+
+Arguments:
+
+ ApiMsg - Supplies the API message to send.
+
+ Port - Supplies the address of a port to send the api message.
+
+ SuspendProcess - A flag that if set to true, causes all of the
+ threads in the process to be suspended prior to the call,
+ and resumed upon receipt of a reply.
+
+Return Value:
+
+ TBD
+
+--*/
+
+{
+ NTSTATUS st;
+
+ PAGED_CODE();
+
+ if ( SuspendProcess ) {
+ DbgkpSuspendProcess(FALSE);
+ }
+
+ ApiMsg->ReturnedStatus = STATUS_PENDING;
+
+ PsGetCurrentProcess()->CreateProcessReported = TRUE;
+
+ st = LpcRequestWaitReplyPort(
+ Port,
+ (PPORT_MESSAGE) ApiMsg,
+ (PPORT_MESSAGE) ApiMsg
+ );
+
+ ZwFlushInstructionCache(NtCurrentProcess(), NULL, 0);
+
+ if ( SuspendProcess ) {
+ DbgkpResumeProcess(FALSE);
+ }
+
+ return st;
+}
+
+LARGE_INTEGER DbgkpCalibrationTime;
+
+BOOLEAN
+DbgkForwardException(
+ IN PEXCEPTION_RECORD ExceptionRecord,
+ IN BOOLEAN DebugException,
+ IN BOOLEAN SecondChance
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called forward an exception to the calling process's
+ debug or subsystem exception port.
+
+Arguments:
+
+ ExceptionRecord - Supplies a pointer to an exception record.
+
+ DebugException - Supplies a boolean variable that specifies whether
+ this exception is to be forwarded to the process's
+ DebugPort(TRUE), or to its ExceptionPort(FALSE).
+
+Return Value:
+
+ TRUE - The process has a DebugPort or an ExceptionPort, and the reply
+ received from the port indicated that the exception was handled.
+
+ FALSE - The process either does not have a DebugPort or
+ ExceptionPort, or the process has a port, but the reply received
+ from the port indicated that the exception was not handled.
+
+--*/
+
+{
+ PEPROCESS Process;
+ PVOID Port;
+ DBGKM_APIMSG m;
+ PDBGKM_EXCEPTION args;
+ NTSTATUS st;
+
+ PAGED_CODE();
+
+ args = &m.u.Exception;
+
+ //
+ // Initialize the debug LPC message with default infomaation.
+ //
+
+ DBGKM_FORMAT_API_MSG(m,DbgKmExceptionApi,sizeof(*args));
+
+ //
+ // Get the address of the destination LPC port.
+ //
+
+ Process = PsGetCurrentProcess();
+ if (DebugException) {
+ Port = Process->DebugPort;
+
+ } else {
+ Port = Process->ExceptionPort;
+ m.h.u2.ZeroInit = LPC_EXCEPTION;
+ }
+
+ //
+ // If the destination LPC port address is NULL, then return FALSE.
+ //
+
+ if (Port == NULL) {
+ return FALSE;
+ }
+
+ //
+ // Fill in the remainder of the debug LPC message.
+ //
+
+ args->ExceptionRecord = *ExceptionRecord;
+ args->FirstChance = !SecondChance;
+
+ //
+ // Send the debug message to the destination LPC port.
+ //
+
+ st = DbgkpSendApiMessage(&m,Port,DebugException);
+
+ //
+ // If the send was not successful, then return a FALSE indicating that
+ // the port did not handle the exception. Otherwise, if the debug port
+ // is specified, then look at the return status in the message.
+ //
+
+ if (!NT_SUCCESS(st) ||
+ ((DebugException) &&
+ (m.ReturnedStatus == DBG_EXCEPTION_NOT_HANDLED || !NT_SUCCESS(m.ReturnedStatus)))) {
+ return FALSE;
+
+ } else {
+ return TRUE;
+ }
+}
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);
+
+}
diff --git a/private/ntos/dbgk/dirs b/private/ntos/dbgk/dirs
new file mode 100644
index 000000000..a2a38f0fd
--- /dev/null
+++ b/private/ntos/dbgk/dirs
@@ -0,0 +1,24 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=up
+
+OPTIONAL_DIRS=mp
diff --git a/private/ntos/dbgk/mp/makefile b/private/ntos/dbgk/mp/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/dbgk/mp/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/dbgk/mp/sources b/private/ntos/dbgk/mp/sources
new file mode 100644
index 000000000..dbeb18d62
--- /dev/null
+++ b/private/ntos/dbgk/mp/sources
@@ -0,0 +1,29 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+NT_UP=0
+
+TARGETPATH=..\..\mpobj
+
+!include ..\sources.inc
diff --git a/private/ntos/dbgk/sources.inc b/private/ntos/dbgk/sources.inc
new file mode 100644
index 000000000..e25cec422
--- /dev/null
+++ b/private/ntos/dbgk/sources.inc
@@ -0,0 +1,42 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=dbgk
+
+TARGETNAME=dbgk
+TARGETTYPE=LIBRARY
+
+INCLUDES=..;..\..\inc
+MIPS_OPTIONS=-nodwalign
+GPSIZE=32
+
+C_DEFINES=$(C_DEFINES) -D_NTSYSTEM_
+
+SOURCES=..\dbgkport.c \
+ ..\dbgkproc.c
+
+UMTEST=udbgk
+
+SOURCES_USED=..\sources.inc
diff --git a/private/ntos/dbgk/udbgk.c b/private/ntos/dbgk/udbgk.c
new file mode 100644
index 000000000..c4c3db876
--- /dev/null
+++ b/private/ntos/dbgk/udbgk.c
@@ -0,0 +1,472 @@
+/*++
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ udbg.c
+
+Abstract:
+
+ Usermode test for debugger
+
+Author:
+
+ Mark Lucovsky (markl) 19-Jan-1990
+
+Revision History:
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntdbg.h>
+
+HANDLE DebugPort;
+
+
+NTSTATUS
+ThreadThatExits (
+ IN PVOID ThreadParameter
+ )
+{
+ NtTerminateThread(NtCurrentThread(),(NTSTATUS) ThreadParameter );
+}
+
+ULONG
+foo(PULONG l)
+{
+ //ULONG x;
+ //x = *l;
+ //return x + 1;
+
+ return *l;
+
+}
+
+NTSTATUS
+ThreadThatExcepts (
+ IN PVOID ThreadParameter
+ )
+{
+ foo((PULONG)0x00000001);
+ NtTerminateThread(NtCurrentThread(),(NTSTATUS) ThreadParameter );
+}
+
+
+
+NTSTATUS
+ThreadThatSpins (
+ IN PVOID ThreadParameter
+ )
+{
+ for(;;);
+ NtTerminateThread(NtCurrentThread(),STATUS_SUCCESS);
+}
+
+
+UdbgTest1()
+{
+ NTSTATUS st;
+ HANDLE ExitThread, SpinThread, DebugProcess;
+ CLIENT_ID ExitClientId, SpinClientId;
+ DBGKM_APIMSG m;
+ PDBGKM_CREATE_THREAD CreateThreadArgs;
+ PDBGKM_CREATE_PROCESS CreateProcessArgs;
+ PDBGKM_EXIT_THREAD ExitThreadArgs;
+ PDBGKM_EXIT_PROCESS ExitProcessArgs;
+ ULONG Psp;
+
+ DbgPrint("UdbgTest1: (1)...\n");
+
+ //
+ // Verify that a process can be created with a debug
+ // port.
+ //
+
+ st = NtCreateProcess(
+ &DebugProcess,
+ PROCESS_ALL_ACCESS,
+ NULL,
+ NtCurrentProcess(),
+ FALSE,
+ NULL,
+ DebugPort,
+ NULL
+ );
+ ASSERT(NT_SUCCESS(st));
+
+ st = RtlCreateUserThread(
+ DebugProcess,
+ NULL,
+ TRUE,
+ 0L,
+ 0L,
+ 0L,
+ ThreadThatExits,
+ (PVOID) STATUS_ABANDONED,
+ &ExitThread,
+ &ExitClientId
+ );
+ ASSERT(NT_SUCCESS(st));
+
+ st = RtlCreateUserThread(
+ DebugProcess,
+ NULL,
+ TRUE,
+ 0L,
+ 0L,
+ 0L,
+ ThreadThatSpins,
+ NULL,
+ &SpinThread,
+ &SpinClientId
+ );
+ ASSERT(NT_SUCCESS(st));
+
+ DbgPrint("UdbgTest1: (2)...\n");
+
+ //
+ // Verify that CreateProcess Messages Arrive, and that
+ // they are correct
+ //
+
+ st = NtResumeThread(SpinThread,NULL);
+ ASSERT(NT_SUCCESS(st));
+
+ st = NtReplyWaitReceivePort(
+ DebugPort,
+ NULL,
+ NULL,
+ (PPORT_MESSAGE)&m
+ );
+ ASSERT(NT_SUCCESS(st));
+ ASSERT(m.ApiNumber == DbgKmCreateProcessApi);
+
+ CreateThreadArgs = &m.u.CreateProcess.InitialThread;
+ CreateProcessArgs = &m.u.CreateProcess;
+ ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatSpins );
+ ASSERT( CreateProcessArgs->SubSystemKey == 0);
+
+ DbgPrint("UdbgTest1: (3)...\n");
+
+ //
+ // Verify that other threads in the process are properly suspended
+ //
+
+ st = NtSuspendThread(ExitThread,&Psp);
+ ASSERT(NT_SUCCESS(st) && Psp == 2);
+
+ st = NtResumeThread(ExitThread,&Psp);
+ ASSERT(NT_SUCCESS(st) && Psp == 3);
+
+ st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
+ ASSERT(NT_SUCCESS(st));
+
+
+ DbgPrint("UdbgTest1: (4)...\n");
+
+ //
+ // Verify that CreateThread Messages Arrive, and that
+ // they are correct
+ //
+
+ st = NtResumeThread(ExitThread,&Psp);
+ ASSERT(NT_SUCCESS(st));
+
+ st = NtReplyWaitReceivePort(
+ DebugPort,
+ NULL,
+ NULL,
+ (PPORT_MESSAGE)&m
+ );
+ ASSERT(NT_SUCCESS(st));
+ ASSERT(m.ApiNumber == DbgKmCreateThreadApi);
+
+ CreateThreadArgs = &m.u.CreateThread;
+ ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatExits );
+
+ st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
+ ASSERT(NT_SUCCESS(st));
+
+ DbgPrint("UdbgTest1: (5)...\n");
+
+ //
+ // Verify that ExitThread Messages Arrive, and that
+ // they are correct
+ //
+
+ st = NtReplyWaitReceivePort(
+ DebugPort,
+ NULL,
+ NULL,
+ (PPORT_MESSAGE)&m
+ );
+ ASSERT(NT_SUCCESS(st));
+ ASSERT(m.ApiNumber == DbgKmExitThreadApi);
+
+ ExitThreadArgs = &m.u.ExitThread;
+ ASSERT( ExitThreadArgs->ExitStatus == STATUS_ABANDONED );
+
+ st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
+ ASSERT(NT_SUCCESS(st));
+
+ st = NtWaitForSingleObject(ExitThread,FALSE,NULL);
+ ASSERT(NT_SUCCESS(st));
+
+ DbgPrint("UdbgTest1: (6)...\n");
+
+ //
+ // Verify that ExitThread Messages Arrive, and that
+ // they are correct
+ //
+
+ st = NtTerminateProcess(DebugProcess,STATUS_REPARSE);
+ ASSERT(NT_SUCCESS(st));
+
+ st = NtReplyWaitReceivePort(
+ DebugPort,
+ NULL,
+ NULL,
+ (PPORT_MESSAGE)&m
+ );
+ ASSERT(NT_SUCCESS(st));
+ ASSERT(m.ApiNumber == DbgKmExitThreadApi);
+
+ ExitThreadArgs = &m.u.ExitThread;
+ ASSERT( ExitThreadArgs->ExitStatus == STATUS_REPARSE );
+
+ st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
+ ASSERT(NT_SUCCESS(st));
+
+ DbgPrint("UdbgTest1: (7)...\n");
+
+ //
+ // Verify that ExitProcess Messages Arrive, and that
+ // they are correct
+ //
+
+ st = NtReplyWaitReceivePort(
+ DebugPort,
+ NULL,
+ NULL,
+ (PPORT_MESSAGE)&m
+ );
+ ASSERT(NT_SUCCESS(st));
+ ASSERT(m.ApiNumber == DbgKmExitProcessApi);
+
+ ExitProcessArgs = &m.u.ExitProcess;
+ ASSERT( ExitProcessArgs->ExitStatus == STATUS_REPARSE );
+
+ st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
+ ASSERT(NT_SUCCESS(st));
+
+
+ st = NtWaitForSingleObject(ExitThread,FALSE,NULL);
+ ASSERT(NT_SUCCESS(st));
+
+ st = NtWaitForSingleObject(DebugProcess,FALSE,NULL);
+ ASSERT(NT_SUCCESS(st));
+
+ NtClose(ExitThread);
+ NtClose(SpinThread);
+ NtClose(DebugProcess);
+
+ DbgPrint("UdbgTest1: END OF TEST ***\n");
+
+}
+
+UdbgTest2()
+{
+ NTSTATUS st;
+ HANDLE ExceptionThread, DebugProcess;
+ DBGKM_APIMSG m;
+ PDBGKM_CREATE_THREAD CreateThreadArgs;
+ PDBGKM_CREATE_PROCESS CreateProcessArgs;
+ PDBGKM_EXIT_THREAD ExitThreadArgs;
+ PDBGKM_EXIT_PROCESS ExitProcessArgs;
+ PDBGKM_EXCEPTION ExceptionArgs;
+ ULONG Psp;
+
+ DbgPrint("UdbgTest2: (1)...\n");
+
+ //
+ // Verify that a process can be created with a debug
+ // port.
+ //
+
+ st = NtCreateProcess(
+ &DebugProcess,
+ PROCESS_ALL_ACCESS,
+ NULL,
+ NtCurrentProcess(),
+ FALSE,
+ NULL,
+ DebugPort,
+ NULL
+ );
+ ASSERT(NT_SUCCESS(st));
+
+ st = RtlCreateUserThread(
+ DebugProcess,
+ NULL,
+ TRUE,
+ 0L,
+ 0L,
+ 0L,
+ ThreadThatExcepts,
+ (PVOID) STATUS_ABANDONED,
+ &ExceptionThread,
+ NULL
+ );
+ ASSERT(NT_SUCCESS(st));
+
+ DbgPrint("UdbgTest2: (2)...\n");
+
+ //
+ // Verify that CreateThread Messages Arrive, and that
+ // they are correct
+ //
+
+ st = NtResumeThread(ExceptionThread,NULL);
+ ASSERT(NT_SUCCESS(st));
+
+ st = NtReplyWaitReceivePort(
+ DebugPort,
+ NULL,
+ NULL,
+ (PPORT_MESSAGE)&m
+ );
+ ASSERT(NT_SUCCESS(st));
+ ASSERT(m.ApiNumber == DbgKmCreateProcessApi);
+
+ CreateThreadArgs = &m.u.CreateProcess.InitialThread;
+ CreateProcessArgs = &m.u.CreateProcess;
+ ASSERT( CreateThreadArgs->SubSystemKey == 0 && CreateThreadArgs->StartAddress == (PVOID)ThreadThatExcepts );
+ ASSERT( CreateProcessArgs->SubSystemKey == 0);
+
+ st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
+ ASSERT(NT_SUCCESS(st));
+
+ DbgPrint("UdbgTest2: (3)...\n");
+
+ //
+ // Verify that First Chance Exception Messages Arrive, and that
+ // they are correct
+ //
+
+ st = NtReplyWaitReceivePort(
+ DebugPort,
+ NULL,
+ NULL,
+ (PPORT_MESSAGE)&m
+ );
+ ASSERT(NT_SUCCESS(st));
+ ASSERT(m.ApiNumber == DbgKmExceptionApi);
+
+ ExceptionArgs = &m.u.Exception;
+ ASSERT( ExceptionArgs->FirstChance == TRUE );
+
+ m.ReturnedStatus = DBG_EXCEPTION_NOT_HANDLED;
+
+ st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
+ ASSERT(NT_SUCCESS(st));
+
+ DbgPrint("UdbgTest2: (4)...\n");
+
+ //
+ // Verify that First Chance Exception Messages Arrive, and that
+ // they are correct
+ //
+
+ st = NtReplyWaitReceivePort(
+ DebugPort,
+ NULL,
+ NULL,
+ (PPORT_MESSAGE)&m
+ );
+ ASSERT(NT_SUCCESS(st));
+ ASSERT(m.ApiNumber == DbgKmExceptionApi);
+
+ ExceptionArgs = &m.u.Exception;
+ ASSERT( ExceptionArgs->FirstChance == FALSE );
+
+ m.ReturnedStatus = DBG_EXCEPTION_HANDLED;
+skip4:
+ st = NtTerminateProcess(DebugProcess,STATUS_REPARSE);
+ ASSERT(NT_SUCCESS(st));
+
+ st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
+ ASSERT(NT_SUCCESS(st));
+
+ st = NtReplyWaitReceivePort(
+ DebugPort,
+ NULL,
+ NULL,
+ (PPORT_MESSAGE)&m
+ );
+ ASSERT(NT_SUCCESS(st));
+ ASSERT(m.ApiNumber == DbgKmExitThreadApi);
+
+ ExitThreadArgs = &m.u.ExitThread;
+ ASSERT( ExitThreadArgs->ExitStatus == STATUS_REPARSE );
+
+ st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
+ ASSERT(NT_SUCCESS(st));
+
+ DbgPrint("UdbgTest2: (5)...\n");
+
+ //
+ // Verify that ExitProcess Messages Arrive, and that
+ // they are correct
+ //
+
+ st = NtReplyWaitReceivePort(
+ DebugPort,
+ NULL,
+ NULL,
+ (PPORT_MESSAGE)&m
+ );
+ ASSERT(NT_SUCCESS(st));
+ ASSERT(m.ApiNumber == DbgKmExitProcessApi);
+
+ ExitProcessArgs = &m.u.ExitProcess;
+ ASSERT( ExitProcessArgs->ExitStatus == STATUS_REPARSE );
+
+ st = NtReplyPort(DebugPort,(PPORT_MESSAGE)&m);
+ ASSERT(NT_SUCCESS(st));
+
+
+ st = NtWaitForSingleObject(ExceptionThread,FALSE,NULL);
+ ASSERT(NT_SUCCESS(st));
+
+ st = NtWaitForSingleObject(DebugProcess,FALSE,NULL);
+ ASSERT(NT_SUCCESS(st));
+
+ NtClose(ExceptionThread);
+ NtClose(DebugProcess);
+
+ DbgPrint("UdbgTest2: END OF TEST ***\n");
+}
+
+main()
+{
+ NTSTATUS st;
+ OBJECT_ATTRIBUTES Obja;
+
+ InitializeObjectAttributes(&Obja, NULL, 0, NULL, NULL);
+
+ st = NtCreatePort(
+ &DebugPort,
+ &Obja,
+ 0L,
+ 256,
+ 256 * 16
+ );
+ ASSERT(NT_SUCCESS(st));
+
+ UdbgTest2();
+ UdbgTest1();
+
+}
diff --git a/private/ntos/dbgk/up/makefile b/private/ntos/dbgk/up/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/dbgk/up/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/dbgk/up/sources b/private/ntos/dbgk/up/sources
new file mode 100644
index 000000000..6dca9c583
--- /dev/null
+++ b/private/ntos/dbgk/up/sources
@@ -0,0 +1,27 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+TARGETPATH=..\..\obj
+
+!include ..\sources.inc