summaryrefslogtreecommitdiffstats
path: root/private/sm/server/dbgssapi.c
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/sm/server/dbgssapi.c
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/sm/server/dbgssapi.c')
-rw-r--r--private/sm/server/dbgssapi.c704
1 files changed, 704 insertions, 0 deletions
diff --git a/private/sm/server/dbgssapi.c b/private/sm/server/dbgssapi.c
new file mode 100644
index 000000000..16f3b695e
--- /dev/null
+++ b/private/sm/server/dbgssapi.c
@@ -0,0 +1,704 @@
+/*++
+
+Copyright (c) 1989 - 1993 Microsoft Corporation
+
+Module Name:
+
+ dbgssapi.c
+
+Abstract:
+
+ This module implements the DbgSs APIs
+
+Author:
+
+ Mark Lucovsky (markl) 22-Jan-1990
+
+Revision History:
+
+--*/
+
+#include "smsrvp.h"
+
+NTSTATUS
+DbgpSsException (
+ IN PDBGP_SUBSYSTEM Subsystem,
+ IN OUT PDBGSS_APIMSG ApiMsg
+ )
+/*++
+
+Routine Description:
+
+ This function is called when a subsystem wants to
+ report that an exception has occured.
+
+Arguments:
+
+ Subsystem - Supplies the address of the subsystem making the call
+
+ ApiMsg - Supplies the DbgSs API message that contains the information
+ needed to complete this call.
+
+Return Value:
+
+ DBG_REPLY_LATER - Successful receipt of message. A reply will be
+ generated when a continue is received from Ui.
+
+ + TBD
+
+--*/
+
+{
+ PDBGP_APP_THREAD AppThread;
+ NTSTATUS ExceptionCode;
+
+ //
+ // Locate AppThread
+ //
+
+ AppThread = DbgpIsAppInHashTable(&ApiMsg->AppClientId);
+
+ if ( !AppThread ) {
+ return STATUS_INVALID_CID;
+ }
+
+ AppThread->Subsystem = Subsystem;
+
+ RtlEnterCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+
+ //
+ // Verify that the thread is DbgIdle (i.e. we are expecting a state change)
+ //
+
+ if ( AppThread->CurrentState != DbgIdle ) {
+ RtlLeaveCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+ return DBG_APP_NOT_IDLE;
+ }
+
+ ExceptionCode = ApiMsg->u.Exception.ExceptionRecord.ExceptionCode;
+
+ if ( ExceptionCode == STATUS_BREAKPOINT ) {
+ AppThread->CurrentState = DbgBreakpointStateChange;
+ } else if ( ExceptionCode == STATUS_SINGLE_STEP ) {
+ AppThread->CurrentState = DbgSingleStepStateChange;
+ } else {
+ AppThread->CurrentState = DbgExceptionStateChange;
+ }
+
+ AppThread->ContinueState = AppThread->CurrentState;
+ AppThread->LastSsApiMsg = *ApiMsg;
+
+ NtReleaseSemaphore(
+ AppThread->UserInterface->StateChangeSemaphore,
+ 1,
+ NULL
+ );
+
+ RtlLeaveCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+
+ return DBG_REPLY_LATER;
+}
+
+NTSTATUS
+DbgpSsCreateThread (
+ IN PDBGP_SUBSYSTEM Subsystem,
+ IN OUT PDBGSS_APIMSG ApiMsg
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a subsystem wants to
+ report that a thread has been created.
+
+Arguments:
+
+ Subsystem - Supplies the address of the subsystem making the call
+
+ ApiMsg - Supplies the DbgSs API message that contains the information
+ needed to complete this call.
+
+Return Value:
+
+ DBG_REPLY_LATER - Successful receipt of message. A reply will be
+ generated when a continue is received from Ui.
+
+ STATUS_INVALID_CID - Process that this thread is part of could not
+ be located.
+
+ + TBD
+
+--*/
+
+{
+ PDBGP_APP_PROCESS AppProcess;
+ PDBGP_APP_THREAD AppThread;
+ NTSTATUS st;
+ OBJECT_ATTRIBUTES Obja;
+
+ //
+ // Locate AppProcess this thread is a part of
+ //
+
+ RtlEnterCriticalSection(&DbgpHashTableLock);
+
+ AppProcess = DbgpIsAppProcessInHashTable(&ApiMsg->AppClientId);
+
+ if ( !AppProcess ) {
+ RtlLeaveCriticalSection(&DbgpHashTableLock);
+ return STATUS_INVALID_CID;
+ }
+
+ //
+ // Now look to see if a thread whose ClientId matches
+ // the new threads ClientId exists in the APP table.
+ // This check is not really necessary, its really just
+ // a question of trust of DbgSs APIs.
+ //
+
+ AppThread = DbgpIsAppInHashTable(&ApiMsg->AppClientId);
+
+ if ( AppThread ) {
+ RtlLeaveCriticalSection(&DbgpHashTableLock);
+ return STATUS_INVALID_CID;
+ }
+
+
+ //
+ // Allocate an initialize and application thread structure.
+ // Link this into its process and into the application
+ // hash table
+ //
+
+ AppThread = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( DBG_TAG ), sizeof(DBGP_APP_THREAD));
+
+ if ( !AppThread ) {
+ RtlLeaveCriticalSection(&DbgpHashTableLock);
+ return STATUS_NO_MEMORY;
+ }
+
+ AppThread->Subsystem = Subsystem;
+
+ AppThread->CurrentState = DbgCreateThreadStateChange;
+ AppThread->ContinueState = DbgCreateThreadStateChange;
+ AppThread->AppProcess = AppProcess;
+ AppThread->UserInterface = AppProcess->UserInterface;
+ AppThread->AppClientId = ApiMsg->AppClientId;
+ AppThread->LastSsApiMsg = *ApiMsg;
+
+ //
+ // Get a local handle to the thread.
+ //
+
+ InitializeObjectAttributes(&Obja, NULL, 0, NULL, NULL);
+ st = NtOpenThread(
+ &AppThread->HandleToThread,
+ DBGP_OPEN_APP_THREAD_ACCESS,
+ &Obja,
+ &AppThread->AppClientId
+ );
+
+ if ( !NT_SUCCESS(st) ) {
+ AppThread->HandleToThread = NULL;
+ }
+
+
+ //
+ // Insert thread on its process app list
+ //
+
+ RtlEnterCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+
+ InsertTailList(
+ &AppProcess->AppThreadListHead,
+ &AppThread->AppLinks
+ );
+
+ //
+ // Insert thread in app hash table
+ //
+
+ InsertTailList(
+ &DbgpAppThreadHashTable[DBGP_THREAD_CLIENT_ID_TO_INDEX(&AppThread->AppClientId)],
+ &AppThread->HashTableLinks
+ );
+ NtReleaseSemaphore(
+ AppThread->UserInterface->StateChangeSemaphore,
+ 1,
+ NULL
+ );
+
+ RtlLeaveCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+
+ RtlLeaveCriticalSection(&DbgpHashTableLock);
+
+
+ return DBG_REPLY_LATER;
+
+}
+
+NTSTATUS
+DbgpSsCreateProcess (
+ IN PDBGP_SUBSYSTEM Subsystem,
+ IN OUT PDBGSS_APIMSG ApiMsg
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a subsystem wants to
+ report that a new process has been created.
+
+Arguments:
+
+ Subsystem - Supplies the address of the subsystem making the call
+
+ ApiMsg - Supplies the DbgSs API message that contains the information
+ needed to complete this call.
+
+Return Value:
+
+ DBG_REPLY_LATER - Successful receipt of message. A reply will be
+ generated when a continue is received from Ui.
+
+ STATUS_INVALID_CID - An invalid ClientId was specified for the
+ DebugUiClientId.
+
+ + TBD
+
+--*/
+
+{
+ PDBGP_USER_INTERFACE UserInterface;
+ PDBGP_APP_PROCESS AppProcess;
+ PDBGP_APP_THREAD AppThread;
+ PDBGSS_CREATE_PROCESS args;
+ NTSTATUS st;
+ OBJECT_ATTRIBUTES Obja;
+
+ args = &ApiMsg->u.CreateProcessInfo;
+
+ //
+ // Locate user interface specified by DebugUiClientId
+ //
+
+ RtlEnterCriticalSection(&DbgpHashTableLock);
+
+ UserInterface = DbgpIsUiInHashTable(&args->DebugUiClientId);
+
+ if ( !UserInterface ) {
+ RtlLeaveCriticalSection(&DbgpHashTableLock);
+ return STATUS_INVALID_CID;
+ }
+
+ //
+ // Now look to see if a thread whose ClientId matches
+ // the new threads ClientId exists in the APP tables.
+ // This check is not really necessary, its really just
+ // a question of trust of DbgSs APIs.
+ //
+
+ AppThread = DbgpIsAppInHashTable(&ApiMsg->AppClientId);
+
+ if ( AppThread ) {
+ RtlLeaveCriticalSection(&DbgpHashTableLock);
+ return STATUS_INVALID_CID;
+ }
+
+
+ //
+ // Allocate an initialize and application thread and process structure.
+ // Link these into the user interface and into the application
+ // hash table
+ //
+
+ AppProcess = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( DBG_TAG ), sizeof(DBGP_APP_PROCESS));
+
+ if ( !AppProcess ) {
+ RtlLeaveCriticalSection(&DbgpHashTableLock);
+ return STATUS_NO_MEMORY;
+ }
+
+ AppThread = RtlAllocateHeap(RtlProcessHeap(), MAKE_TAG( DBG_TAG ), sizeof(DBGP_APP_THREAD));
+
+ if ( !AppThread ) {
+ RtlFreeHeap(RtlProcessHeap(),0,AppProcess);
+ RtlLeaveCriticalSection(&DbgpHashTableLock);
+ return STATUS_NO_MEMORY;
+
+ }
+ AppThread->Subsystem = Subsystem;
+
+ AppThread->CurrentState = DbgCreateProcessStateChange;
+ AppThread->CurrentState = DbgCreateProcessStateChange;
+ AppThread->AppProcess = AppProcess;
+ AppThread->UserInterface = UserInterface;
+ AppThread->AppClientId = ApiMsg->AppClientId;
+ AppThread->LastSsApiMsg = *ApiMsg;
+
+ AppProcess->AppClientId.UniqueProcess = ApiMsg->AppClientId.UniqueProcess;
+ AppProcess->AppClientId.UniqueThread = NULL;
+ AppProcess->UserInterface = UserInterface;
+ InitializeListHead(&AppProcess->AppThreadListHead);
+
+ InsertTailList(
+ &AppProcess->AppThreadListHead,
+ &AppThread->AppLinks
+ );
+
+
+ //
+ // Get a local handle to the thread.
+ //
+
+ InitializeObjectAttributes(&Obja, NULL, 0, NULL, NULL);
+ st = NtOpenThread(
+ &AppThread->HandleToThread,
+ DBGP_OPEN_APP_THREAD_ACCESS,
+ &Obja,
+ &AppThread->AppClientId
+ );
+
+ if ( !NT_SUCCESS(st) ) {
+ AppThread->HandleToThread = NULL;
+ }
+
+ //
+ // Get a local handle to the process.
+ //
+
+ InitializeObjectAttributes(&Obja, NULL, 0, NULL, NULL);
+ st = NtOpenProcess(
+ &AppProcess->DbgSrvHandleToProcess,
+ DBGP_OPEN_APP_PROCESS_ACCESS,
+ &Obja,
+ &AppThread->AppClientId
+ );
+
+ if ( !NT_SUCCESS(st) ) {
+ AppProcess->DbgSrvHandleToProcess = NULL;
+ }
+
+ //
+ // Insert process on its user interfaces app list
+ //
+
+ RtlEnterCriticalSection(&UserInterface->UserInterfaceLock);
+
+ InsertTailList(
+ &UserInterface->AppProcessListHead,
+ &AppProcess->AppLinks
+ );
+
+ //
+ // Insert process in app hash table
+ //
+
+ InsertTailList(
+ &DbgpAppProcessHashTable[DBGP_PROCESS_CLIENT_ID_TO_INDEX(&AppThread->AppClientId)],
+ &AppProcess->HashTableLinks
+ );
+
+ //
+ // Insert thread in app hash table
+ //
+
+ InsertTailList(
+ &DbgpAppThreadHashTable[DBGP_THREAD_CLIENT_ID_TO_INDEX(&AppThread->AppClientId)],
+ &AppThread->HashTableLinks
+ );
+
+ NtReleaseSemaphore(
+ UserInterface->StateChangeSemaphore,
+ 1,
+ NULL
+ );
+
+ RtlLeaveCriticalSection(&UserInterface->UserInterfaceLock);
+
+ RtlLeaveCriticalSection(&DbgpHashTableLock);
+
+
+ return DBG_REPLY_LATER;
+
+}
+
+NTSTATUS
+DbgpSsExitThread (
+ IN PDBGP_SUBSYSTEM Subsystem,
+ IN OUT PDBGSS_APIMSG ApiMsg
+ )
+
+/*++
+
+Routine Description:
+
+ This function is called when a subsystem wants to
+ report that a thread is exiting.
+
+Arguments:
+
+ Subsystem - Supplies the address of the subsystem making the call
+
+ ApiMsg - Supplies the DbgSs API message that contains the information
+ needed to complete this call.
+
+Return Value:
+
+ DBG_REPLY_LATER - Successful receipt of message. A reply will be
+ generated when a continue is received from Ui.
+
+ + TBD
+
+--*/
+
+{
+ PDBGP_APP_THREAD AppThread;
+
+ //
+ // Locate AppThread
+ //
+
+ AppThread = DbgpIsAppInHashTable(&ApiMsg->AppClientId);
+
+ if ( !AppThread ) {
+ return STATUS_INVALID_CID;
+ }
+
+ AppThread->Subsystem = Subsystem;
+
+ RtlEnterCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+
+ //
+ // Verify that the thread is DbgIdle (i.e. we are expecting a state change)
+ //
+
+ if ( AppThread->CurrentState != DbgIdle ) {
+ DbgPrint("Not Idle\n");
+ RtlLeaveCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+ return DBG_APP_NOT_IDLE;
+ }
+
+ AppThread->CurrentState = DbgExitThreadStateChange;
+ AppThread->ContinueState = DbgExitThreadStateChange;
+ AppThread->LastSsApiMsg = *ApiMsg;
+
+ NtReleaseSemaphore(
+ AppThread->UserInterface->StateChangeSemaphore,
+ 1,
+ NULL
+ );
+
+ RtlLeaveCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+
+ return DBG_REPLY_LATER;
+}
+
+NTSTATUS
+DbgpSsExitProcess (
+ IN PDBGP_SUBSYSTEM Subsystem,
+ IN OUT PDBGSS_APIMSG ApiMsg
+ )
+/*++
+
+Routine Description:
+
+ This function is called when a subsystem wants to
+ report that a process is exiting.
+
+Arguments:
+
+ Subsystem - Supplies the address of the subsystem making the call
+
+ ApiMsg - Supplies the DbgSs API message that contains the information
+ needed to complete this call.
+
+Return Value:
+
+ DBG_REPLY_LATER - Successful receipt of message. A reply will be
+ generated when a continue is received from Ui.
+
+ + TBD
+
+--*/
+
+{
+ PDBGP_APP_THREAD AppThread;
+
+ //
+ // Locate AppThread
+ //
+
+ AppThread = DbgpIsAppInHashTable(&ApiMsg->AppClientId);
+
+ if ( !AppThread ) {
+ return STATUS_INVALID_CID;
+ }
+
+ AppThread->Subsystem = Subsystem;
+
+ RtlEnterCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+
+ //
+ // Verify that the thread is DbgIdle (i.e. we are expecting a state change)
+ //
+
+ if ( AppThread->CurrentState != DbgIdle ) {
+ RtlLeaveCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+ return DBG_APP_NOT_IDLE;
+ }
+
+ AppThread->CurrentState = DbgExitProcessStateChange;
+ AppThread->ContinueState = DbgExitProcessStateChange;
+ AppThread->LastSsApiMsg = *ApiMsg;
+
+ NtReleaseSemaphore(
+ AppThread->UserInterface->StateChangeSemaphore,
+ 1,
+ NULL
+ );
+
+ RtlLeaveCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+
+ return DBG_REPLY_LATER;
+}
+
+NTSTATUS
+DbgpSsLoadDll (
+ IN PDBGP_SUBSYSTEM Subsystem,
+ IN OUT PDBGSS_APIMSG ApiMsg
+ )
+/*++
+
+Routine Description:
+
+ This function is called when a subsystem wants to
+ report that a process has loaded a Dll.
+
+Arguments:
+
+ Subsystem - Supplies the address of the subsystem making the call
+
+ ApiMsg - Supplies the DbgSs API message that contains the information
+ needed to complete this call.
+
+Return Value:
+
+ DBG_REPLY_LATER - Successful receipt of message. A reply will be
+ generated when a continue is received from Ui.
+
+ + TBD
+
+--*/
+
+{
+ PDBGP_APP_THREAD AppThread;
+
+ //
+ // Locate AppThread
+ //
+
+ AppThread = DbgpIsAppInHashTable(&ApiMsg->AppClientId);
+
+ if ( !AppThread ) {
+ return STATUS_INVALID_CID;
+ }
+
+ AppThread->Subsystem = Subsystem;
+
+ RtlEnterCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+
+ //
+ // Verify that the thread is DbgIdle (i.e. we are expecting a state change)
+ //
+
+ if ( AppThread->CurrentState != DbgIdle ) {
+ RtlLeaveCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+ return DBG_APP_NOT_IDLE;
+ }
+
+ AppThread->CurrentState = DbgLoadDllStateChange;
+ AppThread->ContinueState = AppThread->CurrentState;
+ AppThread->LastSsApiMsg = *ApiMsg;
+
+ NtReleaseSemaphore(
+ AppThread->UserInterface->StateChangeSemaphore,
+ 1,
+ NULL
+ );
+
+ RtlLeaveCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+
+ return DBG_REPLY_LATER;
+}
+
+NTSTATUS
+DbgpSsUnloadDll (
+ IN PDBGP_SUBSYSTEM Subsystem,
+ IN OUT PDBGSS_APIMSG ApiMsg
+ )
+/*++
+
+Routine Description:
+
+ This function is called when a subsystem wants to
+ report that a process has unloaded a dll.
+
+Arguments:
+
+ Subsystem - Supplies the address of the subsystem making the call
+
+ ApiMsg - Supplies the DbgSs API message that contains the information
+ needed to complete this call.
+
+Return Value:
+
+ DBG_REPLY_LATER - Successful receipt of message. A reply will be
+ generated when a continue is received from Ui.
+
+ + TBD
+
+--*/
+
+{
+ PDBGP_APP_THREAD AppThread;
+
+ //
+ // Locate AppThread
+ //
+
+ AppThread = DbgpIsAppInHashTable(&ApiMsg->AppClientId);
+
+ if ( !AppThread ) {
+ return STATUS_INVALID_CID;
+ }
+
+ AppThread->Subsystem = Subsystem;
+
+ RtlEnterCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+
+ //
+ // Verify that the thread is DbgIdle (i.e. we are expecting a state change)
+ //
+
+ if ( AppThread->CurrentState != DbgIdle ) {
+ RtlLeaveCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+ return DBG_APP_NOT_IDLE;
+ }
+
+ AppThread->CurrentState = DbgUnloadDllStateChange;
+ AppThread->ContinueState = AppThread->CurrentState;
+ AppThread->LastSsApiMsg = *ApiMsg;
+
+ NtReleaseSemaphore(
+ AppThread->UserInterface->StateChangeSemaphore,
+ 1,
+ NULL
+ );
+
+ RtlLeaveCriticalSection(&AppThread->UserInterface->UserInterfaceLock);
+
+ return DBG_REPLY_LATER;
+}