243 lines
6.5 KiB
C
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);
|
|
}
|