NT4/private/sm/server/dbguisup.c
2020-09-30 17:12:29 +02:00

243 lines
6.5 KiB
C

/*++
Copyright (c) 1989 Microsoft Corporation
Module Name:
dbguisup.c
Abstract:
This module implements support routines for User Interfaces
Author:
Mark Lucovsky (markl) 23-Jan-1990
Revision History:
--*/
#include "smsrvp.h"
PDBGP_USER_INTERFACE
DbgpIsUiInHashTable(
IN PCLIENT_ID DebugUiClientId
)
/*++
Routine Description:
This routine scans the user interface hash table looking
for a user interface that matches the specified client id.
If a matching user interface is found, then its address is
returned.
Arguments:
DebugUiClientId - Supplies the address of ClientId of the user
interface to locate.
Return Value:
NULL - No user interface with a matching ClientId could be located.
NON-NULL - Returns the address of the user interface that matches
the specified ClientId.
--*/
{
ULONG Index;
PLIST_ENTRY Head, Next;
PDBGP_USER_INTERFACE UserInterface;
RtlEnterCriticalSection(&DbgpHashTableLock);
Index = DBGP_PROCESS_CLIENT_ID_TO_INDEX(DebugUiClientId);
Head = &DbgpUiHashTable[Index];
Next = Head->Flink;
while ( Next != Head ) {
UserInterface = CONTAINING_RECORD(Next,DBGP_USER_INTERFACE,HashTableLinks);
if ( DBGP_CLIENT_IDS_EQUAL(
&UserInterface->DebugUiClientId,
DebugUiClientId
)) {
RtlLeaveCriticalSection(&DbgpHashTableLock);
return UserInterface;
}
Next = Next->Flink;
}
RtlLeaveCriticalSection(&DbgpHashTableLock);
return NULL;
}
VOID
DbgpUiHasTerminated(
IN PCLIENT_ID DebugUiClientId
)
/*++
Routine Description:
This routine processes client died messages from a user interface.
Its purpose is to cleanup all control blocks/data structures associated
with a user-interface.
Arguments:
DebugUiClientId - Supplies the client id of the terminated Ui.
Return Value:
None.
--*/
{
PLIST_ENTRY HeadProcess, NextProcess;
PLIST_ENTRY HeadThread, NextThread;
PDBGP_APP_THREAD AppThread;
PDBGP_APP_PROCESS AppProcess;
NTSTATUS st;
PDBGP_USER_INTERFACE UserInterface;
DBGSRV_APIMSG ContinueMsg;
HANDLE NullPort;
HANDLE Thread;
OBJECT_ATTRIBUTES ThreadObja;
KERNEL_USER_TIMES Times;
InitializeObjectAttributes(&ThreadObja, NULL, 0, NULL, NULL);
NullPort = NULL;
RtlEnterCriticalSection(&DbgpHashTableLock);
UserInterface = DbgpIsUiInHashTable(DebugUiClientId);
if ( !UserInterface ) {
RtlLeaveCriticalSection(&DbgpHashTableLock);
return;
}
//
// User interface was located, so take it out of the list.
//
RemoveEntryList(&UserInterface->HashTableLinks);
RtlLeaveCriticalSection(&DbgpHashTableLock);
//
// Now process each thread and process owned by the user-interface
//
HeadProcess = &UserInterface->AppProcessListHead;
NextProcess = HeadProcess->Flink;
while ( NextProcess != HeadProcess ) {
//
// For each process managed by the user interface,
// scan its thread list
//
AppProcess = CONTAINING_RECORD(NextProcess,DBGP_APP_PROCESS,AppLinks);
NtSetInformationProcess(
AppProcess->DbgSrvHandleToProcess,
ProcessDebugPort,
&NullPort,
sizeof(HANDLE)
);
HeadThread = &AppProcess->AppThreadListHead;
NextThread = HeadThread->Flink;
while ( NextThread != HeadThread ) {
AppThread = CONTAINING_RECORD(NextThread,DBGP_APP_THREAD,AppLinks);
//
// Terminate the thread if not already dead
//
st = NtOpenThread(
&Thread,
THREAD_TERMINATE | THREAD_QUERY_INFORMATION,
&ThreadObja,
&AppThread->AppClientId
);
if ( NT_SUCCESS(st) ) {
//
// check exit time
//
st = NtQueryInformationThread(
Thread,
ThreadTimes,
(PVOID) &Times,
sizeof(Times),
NULL
);
if ( NT_SUCCESS(st) ) {
if ( Times.ExitTime.LowPart == 0 &&
Times.ExitTime.HighPart == 0 ) {
NtTerminateThread(Thread,DBG_TERMINATE_PROCESS);
}
}
NtClose(Thread);
}
if ( AppThread->CurrentState == DbgReplyPending ) {
AppThread->CurrentState = DbgIdle;
DBGSRV_FORMAT_API_MSG(ContinueMsg,DbgSrvContinueApi,0L,AppThread->LastSsApiMsg.ContinueKey);
ContinueMsg.ReturnedStatus = DBG_CONTINUE;
st = NtRequestPort(
AppThread->Subsystem->CommunicationPort,
(PPORT_MESSAGE)&ContinueMsg
);
ASSERT(NT_SUCCESS(st));
}
else {
if ( DBGP_REPORTING_STATE_CHANGE(AppThread) ) {
AppThread->ContinueState = AppThread->CurrentState;
AppThread->CurrentState = DbgIdle;
DBGSRV_FORMAT_API_MSG(ContinueMsg,DbgSrvContinueApi,0L,AppThread->LastSsApiMsg.ContinueKey);
ContinueMsg.ReturnedStatus = DBG_CONTINUE;
st = NtRequestPort(
AppThread->Subsystem->CommunicationPort,
(PPORT_MESSAGE)&ContinueMsg
);
}
}
if ( AppThread->HandleToThread &&
!AppThread->HandleToThread & 1 ) {
NtClose(AppThread->HandleToThread);
}
NextThread = NextThread->Flink;
RemoveEntryList(&AppThread->AppLinks);
RemoveEntryList(&AppThread->HashTableLinks);
RtlFreeHeap(RtlProcessHeap(), 0,AppThread);
}
NtClose(AppProcess->DbgSrvHandleToProcess);
NextProcess = NextProcess->Flink;
RemoveEntryList(&AppProcess->HashTableLinks);
RemoveEntryList(&AppProcess->AppLinks);
RtlFreeHeap(RtlProcessHeap(), 0,AppProcess);
}
NtClose(UserInterface->CommunicationPort);
NtClose(UserInterface->DebugUiProcess);
NtClose(UserInterface->StateChangeSemaphore);
RtlDeleteCriticalSection(&UserInterface->UserInterfaceLock);
RtlFreeHeap(RtlProcessHeap(), 0,UserInterface);
}