/*++ Copyright (c) 2000 Microsoft Corporation Module Name: output.cpp Abstract: This file contains routines and classes to handle output. Author: Jason Hartman (JasonHa) 2000-10-16 Environment: User Mode --*/ #include #include #include "debug.h" #include "output.h" #define HISTORY_LENGTH 2048 typedef struct { PDEBUG_CLIENT MonitorClient; // To be set by created thread PDEBUG_CLIENT Client; ULONG OutputMask; } MonitorThreadParams; DWORD WINAPI OutputMonitorThread(MonitorThreadParams *); HRESULT OutputMonitor::Monitor( PDEBUG_CLIENT ClientToMonitor, ULONG OutputMask ) { Client = ClientToMonitor; if (Client == NULL) return S_FALSE; Client->AddRef(); MonitorThreadParams NewThreadParams = { NULL, Client, OutputMask }; HANDLE hThread; DWORD ThreadID = 0; hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)OutputMonitorThread, &NewThreadParams, 0, &ThreadID); if (hThread) { while (NewThreadParams.MonitorClient == NULL) { DWORD ExitCode = 0; if (!GetExitCodeThread(hThread, &ExitCode)) DbgPrint("GetExitCodeThread returned error %lx.\n", GetLastError()); if (ExitCode != STILL_ACTIVE) { ThreadID = 0; break; } SleepEx(10, TRUE); } CloseHandle(hThread); } MonitorClient = NewThreadParams.MonitorClient; return (MonitorClient != NULL) ? S_OK : S_FALSE; } HRESULT OutputMonitor::GetOutputMask( PULONG OutputMask ) { HRESULT hr = S_FALSE; if (Client != NULL && MonitorClient != NULL) { hr = Client->GetOtherOutputMask(MonitorClient, OutputMask); } return hr; } HRESULT OutputMonitor::SetOutputMask( ULONG OutputMask ) { HRESULT hr = S_FALSE; if (Client != NULL && MonitorClient != NULL) { hr = Client->SetOtherOutputMask(MonitorClient, OutputMask); } return hr; } OutputMonitor::~OutputMonitor() { if (Client) { if (MonitorClient) { Client->ExitDispatch(MonitorClient); } Client->Release(); } } DWORD WINAPI OutputMonitorThread( MonitorThreadParams *Params ) { HRESULT hr = S_FALSE; PDEBUG_CLIENT MonitorClient; PrintOutputCallbacks PrintCallbacks; if (Params != NULL && Params->Client != NULL && (hr = Params->Client->CreateClient(&MonitorClient)) == S_OK) { if ((hr = MonitorClient->SetOutputMask(Params->OutputMask | DEBUG_OUTPUT_PROMPT | DEBUG_OUTPUT_PROMPT_REGISTERS | DEBUG_OUTPUT_DEBUGGEE | DEBUG_OUTPUT_DEBUGGEE_PROMPT )) == S_OK && (hr = MonitorClient->SetOutputCallbacks(&PrintCallbacks)) == S_OK) { if ((hr = MonitorClient->ConnectSession(DEBUG_CONNECT_SESSION_NO_ANNOUNCE, HISTORY_LENGTH)) != S_OK) { printf("Couldn't get debugger version/history: HRESULT 0x%lx\n", hr); } MonitorClient->SetOutputMask(Params->OutputMask); Params->MonitorClient = MonitorClient; hr = MonitorClient->DispatchCallbacks(INFINITE); } else { printf("Output callbacks setup failed, HRESULT: 0x%lx\n", hr); } MonitorClient->Release(); } DbgPrint("OutputMonitorThread calling ExitThread().\n"); ExitThread((DWORD)hr); } //---------------------------------------------------------------------------- // // Default output callbacks implementation, provides IUnknown for // static classes. // //---------------------------------------------------------------------------- STDMETHODIMP PrintOutputCallbacks::QueryInterface( THIS_ IN REFIID InterfaceId, OUT PVOID* Interface ) { *Interface = NULL; if (//(InterfaceId == IID_IUnknown) || (InterfaceId == __uuidof(IDebugOutputCallbacks))) { *Interface = (IDebugOutputCallbacks *)this; AddRef(); return S_OK; } else { return E_NOINTERFACE; } } STDMETHODIMP_(ULONG) PrintOutputCallbacks::AddRef( THIS ) { // This class is designed to be static so // there's no true refcount. return 1; } STDMETHODIMP_(ULONG) PrintOutputCallbacks::Release( THIS ) { // This class is designed to be static so // there's no true refcount. return 0; } STDMETHODIMP PrintOutputCallbacks::Output( THIS_ IN ULONG Mask, IN PCSTR Text ) { printf("%s", Text); return S_OK; } #if 0 // Stuff we probably don't need OutputMonitor::OutputMonitor( PDEBUG_CLIENT DbgClient ) { Client = DbgClient; if (Client != NULL) { Client->AddRef(); } Saved = FALSE; } HRESULT OutputMonitor::Setup( ULONG OutMask, PDEBUG_OUTPUT_CALLBACKS OutCallbacks ) { HRESULT Hr = S_FALSE; ULONG LastOutMask; PDEBUG_CLIENT f; if (Client == NULL) { return Hr; } if (!Saved) { if ((Hr = Client->GetOutputMask(&OrgOutMask)) != S_OK || (Hr = Client->GetOutputCallbacks(&OrgOutCallbacks)) != S_OK) { return Hr; } Saved = TRUE; } if ((Hr = Client->GetOutputMask(&LastOutMask)) == S_OK && (Hr = Client->SetOutputMask(OutMask)) == S_OK) { if ((Hr = Client->SetOutputCallbacks(OutCallbacks)) != S_OK) { Client->SetOutputMask(LastOutMask); } } return Hr; } HRESULT OutputMonitor::Execute( PCSTR pszCommand ) { HRESULT hr = S_FALSE; PDEBUG_CONTROL DbgControl; if (Client != NULL && (hr = Client->QueryInterface(__uuidof(IDebugControl), (void **)&DbgControl)) == S_OK) { hr = DbgControl->Execute(DEBUG_OUTCTL_THIS_CLIENT | DEBUG_OUTCTL_OVERRIDE_MASK, pszCommand, DEBUG_EXECUTE_NO_REPEAT); DbgControl->Release(); } return hr; } #endif