|
|
// Spewview: remote debug spew monitor
//
// Copyright (c) 2000 Microsoft Corp.
//
// Main dialog window
//
// 16 Mar 2000 sburns
#include "headers.hxx"
#include "MainDialog.hpp"
#include "SpewDialog.hpp"
#include "resource.h"
static const DWORD _help_map[] = { IDC_CLIENT_NAME, NO_HELP, IDC_APP_NAME, NO_HELP, IDC_GET_FLAGS, NO_HELP, IDC_SET_FLAGS, NO_HELP, IDC_VIEW_SPEW, NO_HELP, IDC_FLAGS_GROUP, NO_HELP, IDC_OUTPUT_TO_FILE, NO_HELP, IDC_OUTPUT_TO_DEBUGGER, NO_HELP, IDC_OUTPUT_TO_SPEWVIEW, NO_HELP, IDC_OUTPUT_LOGS, NO_HELP, IDC_OUTPUT_HEADER, NO_HELP, IDC_OUTPUT_ERRORS, NO_HELP, IDC_OUTPUT_CTORS, NO_HELP, IDC_OUTPUT_ADDREFS, NO_HELP, IDC_OUTPUT_FUNCCALLS, NO_HELP, IDC_OUTPUT_TIME_OF_DAY, NO_HELP, IDC_OUTPUT_RUN_TIME, NO_HELP, IDC_OUTPUT_SCOPE_EXIT, NO_HELP, IDC_FLAGS, NO_HELP, IDC_STATUS, NO_HELP, 0, 0 };
static const DWORD ID_TO_FLAGMAP[] = { IDC_OUTPUT_TO_FILE, Burnslib::Log::OUTPUT_TO_FILE, IDC_OUTPUT_TO_DEBUGGER, Burnslib::Log::OUTPUT_TO_DEBUGGER, IDC_OUTPUT_TO_SPEWVIEW, Burnslib::Log::OUTPUT_TO_SPEWVIEW, IDC_OUTPUT_LOGS, Burnslib::Log::OUTPUT_LOGS, IDC_OUTPUT_HEADER, Burnslib::Log::OUTPUT_HEADER, IDC_OUTPUT_ERRORS, Burnslib::Log::OUTPUT_ERRORS, IDC_OUTPUT_CTORS, Burnslib::Log::OUTPUT_CTORS, IDC_OUTPUT_ADDREFS, Burnslib::Log::OUTPUT_ADDREFS, IDC_OUTPUT_FUNCCALLS, Burnslib::Log::OUTPUT_FUNCCALLS, IDC_OUTPUT_TIME_OF_DAY, Burnslib::Log::OUTPUT_TIME_OF_DAY, IDC_OUTPUT_RUN_TIME, Burnslib::Log::OUTPUT_RUN_TIME, IDC_OUTPUT_SCOPE_EXIT, Burnslib::Log::OUTPUT_SCOPE_EXIT, 0, 0 };
MainDialog::MainDialog() : Dialog(IDD_MAIN, _help_map), spewviewer(0), setFlagsOnStart(false) { LOG_CTOR(MainDialog); }
MainDialog::~MainDialog() { LOG_DTOR(MainDialog);
SaveUiHistory();
delete spewviewer; spewviewer = 0; }
void MainDialog::SetStatusText(const String& text) { LOG_FUNCTION2(MainDialog::SetStatusText, text);
Win::SetDlgItemText(hwnd, IDC_STATUS, text); }
void MainDialog::EnableControls() { LOG_FUNCTION(MainDialog::EnableControls);
String c = Win::GetTrimmedDlgItemText(hwnd, IDC_CLIENT_NAME); String a = Win::GetTrimmedDlgItemText(hwnd, IDC_APP_NAME);
bool enableButtons = !Win::GetTrimmedDlgItemText(hwnd, IDC_CLIENT_NAME).empty() && !Win::GetTrimmedDlgItemText(hwnd, IDC_APP_NAME).empty();
Win::EnableWindow(Win::GetDlgItem(hwnd, IDC_GET_FLAGS), enableButtons); Win::EnableWindow(Win::GetDlgItem(hwnd, IDC_SET_FLAGS), enableButtons); Win::EnableWindow(Win::GetDlgItem(hwnd, IDC_VIEW_SPEW), enableButtons); Win::EnableWindow(Win::GetDlgItem(hwnd, IDC_FLAGS_GROUP), enableButtons);
for (int i = 0; ID_TO_FLAGMAP[i]; i += 2) { Win::EnableWindow( Win::GetDlgItem(hwnd, ID_TO_FLAGMAP[i]), enableButtons); } }
void MainDialog::AddToUiHistory(const String& clientName, const String& appName) { LOG_FUNCTION(MainDialog::AddToUiHistory); ASSERT(!clientName.empty()); ASSERT(!appName.empty());
push_back_unique(clientNameHistory, clientName); push_back_unique(appNameHistory, appName);
lastClientNameUsed = clientName; lastAppNameUsed = appName; }
// Caller must call Win::RegCloseKey(remoteHKLM)
HRESULT MainDialog::ConnectToClientRegistry( HKEY& remoteHKLM, String& clientName, String& appName) { LOG_FUNCTION(MainDialog::ConnectToClientRegistry); ASSERT(!remoteHKLM);
remoteHKLM = 0; clientName = Win::GetTrimmedDlgItemText(hwnd, IDC_CLIENT_NAME); appName = Win::GetTrimmedDlgItemText(hwnd, IDC_APP_NAME);
if (clientName.empty() or appName.empty()) { popup.Error( hwnd, L"You need to specify a client machine and application"); return E_INVALIDARG; }
HRESULT hr = S_OK; do { SetStatusText( String::format( L"Attempting to attach to machine %1", clientName.c_str()));
Computer comp(clientName);
hr = comp.Refresh(); if (FAILED(hr)) { String msg = String::format( L"Can't attach to client machine %1", clientName.c_str()); SetStatusText(msg);
popup.Error(hwnd, hr, msg); break; }
// connect to the client machine's registry
hr = Win::RegConnectRegistry( comp.IsLocal() ? String() : L"\\\\" + comp.GetNetbiosName(), HKEY_LOCAL_MACHINE, remoteHKLM); if (FAILED(hr)) { String msg = String::format( L"Can't connect to registry of client machine %1", clientName.c_str());
SetStatusText(msg);
popup.Error(hwnd, hr, msg); break; } } while (0);
#ifdef DBG
if (SUCCEEDED(hr)) { ASSERT(remoteHKLM); } #endif
return hr; }
DWORD CollectFlags(HWND dialogParent) { LOG_FUNCTION(CollectFlags); ASSERT(Win::IsWindow(dialogParent));
DWORD outputFlags = 0;
for (int i = 0; ID_TO_FLAGMAP[i]; i += 2) { if (Win::IsDlgButtonChecked(dialogParent, ID_TO_FLAGMAP[i])) { outputFlags |= ID_TO_FLAGMAP[i + 1]; } }
return outputFlags; }
void UpdateFlagsEdit(HWND dialogParent) { LOG_FUNCTION(UpdateFlagsEdit); ASSERT(Win::IsWindow(dialogParent));
DWORD flags = CollectFlags(dialogParent);
Win::SetDlgItemText( dialogParent, IDC_FLAGS, String::format(L"%1!08X!", flags)); }
// Set the logging options
//
// remoteHKLM - already opened registry handle. Not closed by this
// function.
HRESULT SetLoggingOptions( HWND dialogParent, HKEY remoteHKLM, const String& clientName, const String& appName) { LOG_FUNCTION(SetLoggingOptions); ASSERT(Win::IsWindow(dialogParent)); ASSERT(remoteHKLM); ASSERT(!clientName.empty()); ASSERT(!appName.empty());
HRESULT hr = S_OK;
do { String logKey = String(REG_ADMIN_RUNTIME_OPTIONS) + appName; RegistryKey key; hr = key.Create(remoteHKLM, logKey); if (FAILED(hr)) { popup.Error( dialogParent, hr, String::format( L"Can't create logging registry key %1 on client machine %2", logKey.c_str(), clientName.c_str())); break; }
DWORD outputFlags = CollectFlags(dialogParent);
hr = key.SetValue(L"LogFlags", outputFlags); if (FAILED(hr)) { popup.Error( dialogParent, hr, String::format( L"Can't set logging registry value on client machine %1", clientName.c_str())); break; } } while (0);
return hr; }
HRESULT MainDialog::SetFlags() { LOG_FUNCTION(MainDialog::SetFlags);
HRESULT hr = S_OK; HKEY remoteHKLM = 0; String clientName; String appName;
do { hr = ConnectToClientRegistry(remoteHKLM, clientName, appName);
// if that failed, the connect function will have griped to the user
// already, so just bail out here
BREAK_ON_FAILED_HRESULT(hr);
hr = SetLoggingOptions(hwnd, remoteHKLM, clientName, appName);
// ditto about griping here
BREAK_ON_FAILED_HRESULT(hr); } while (0); Win::RegCloseKey(remoteHKLM);
if (SUCCEEDED(hr)) { // Since we could successfully perform the operation, save the
// client name and app name in the ui history
AddToUiHistory(clientName, appName); }
return hr; }
void MainDialog::OnSetFlagsButton() { LOG_FUNCTION(MainDialog::OnSetFlagsButton);
if (SUCCEEDED(SetFlags())) { // refresh the flags
HRESULT hr = GetFlags(); ASSERT(SUCCEEDED(hr));
SetStatusText(L"Flags set successfully."); } }
void MainDialog::OnGetFlagsButton() { LOG_FUNCTION(MainDialog::OnGetFlagsButton);
if (SUCCEEDED(GetFlags())) { SetStatusText(L"Flags read successfully."); } }
void MainDialog::UpdateCheckboxen(DWORD flags) { LOG_FUNCTION(MainDialog::UpdateCheckboxen); for (int i = 0; ID_TO_FLAGMAP[i]; i += 2) { Win::CheckDlgButton( hwnd, ID_TO_FLAGMAP[i], (flags & ID_TO_FLAGMAP[i + 1]) ? BST_CHECKED : BST_UNCHECKED); } }
void MainDialog::ResetFlagsDisplay() { LOG_FUNCTION(MainDialog::ResetFlagsDisplay);
Win::SetDlgItemText(hwnd, IDC_FLAGS, L""); Win::UpdateWindow(Win::GetDlgItem(hwnd, IDC_FLAGS));
// clear all the checkboxes
UpdateCheckboxen(0); }
HRESULT MainDialog::GetFlags() { LOG_FUNCTION(MainDialog::GetFlags);
HRESULT hr = S_OK; HKEY remoteHKLM = 0; String clientName; String appName;
Win::WaitCursor wait;
do { ResetFlagsDisplay();
hr = ConnectToClientRegistry(remoteHKLM, clientName, appName);
// if that failed, the connect function will have griped to the user
// already, so just bail out here
BREAK_ON_FAILED_HRESULT(hr);
// Set the logging options
String logKey = String(REG_ADMIN_RUNTIME_OPTIONS) + appName; RegistryKey key; hr = key.Open(remoteHKLM, logKey); if (FAILED(hr)) { String msg = String::format( L"Can't open logging registry key %1 on client machine %2", logKey.c_str(), clientName.c_str()); SetStatusText(msg); popup.Error(hwnd, hr, msg); break; }
DWORD outputFlags = 0; hr = key.GetValue(L"LogFlags", outputFlags); if (FAILED(hr)) { String msg = String::format( L"Can't get logging registry value on client machine %1", clientName.c_str()); SetStatusText(msg); popup.Error(hwnd, hr, msg); break; }
// here, we've got the flags, so update the checkboxen
UpdateCheckboxen(outputFlags); UpdateFlagsEdit(hwnd); } while (0);
Win::RegCloseKey(remoteHKLM);
if (SUCCEEDED(hr)) { // Since we could successfully perform the operation, save the
// client name and app name in the ui history
AddToUiHistory(clientName, appName); }
return hr; }
HRESULT MainDialog::SetClientConfiguration() { LOG_FUNCTION(MainDialog::SetClientConfiguration);
HRESULT hr = S_OK; HKEY remoteHKLM = 0; String clientName; String appName;
Win::WaitCursor wait;
do { hr = ConnectToClientRegistry(remoteHKLM, clientName, appName);
// if that failed, the connect function will have griped to the user
// already, so just bail out here
BREAK_ON_FAILED_HRESULT(hr);
// create the spewview key with the name of the server (this machine)
RegistryKey key;
hr = key.Create( remoteHKLM, SPEWVIEW_KEY_NAME + appName, REG_OPTION_VOLATILE); if (FAILED(hr)) { popup.Error( hwnd, hr, String::format( L"Can't create spewview registry key on client machine %1", clientName.c_str())); break; }
hr = key.SetValue( L"Server", Win::GetComputerNameEx(ComputerNameNetBIOS)); if (FAILED(hr)) { popup.Error( hwnd, hr, String::format( L"Can't set spewview server registry value on client machine %1", clientName.c_str())); break; }
if (setFlagsOnStart) { hr = SetLoggingOptions(hwnd, remoteHKLM, clientName, appName);
// if that failed, the function will have griped to the user already,
// so just bail out here
BREAK_ON_FAILED_HRESULT(hr); } } while (0);
Win::RegCloseKey(remoteHKLM);
if (SUCCEEDED(hr)) { // Since we could successfully perform the operation, save the
// client name and app name in the ui history
AddToUiHistory(clientName, appName); }
return hr; }
void MainDialog::OnStartButton() { LOG_FUNCTION(MainDialog::OnStartButton);
HRESULT hr = S_OK; do { if (spewviewer) { popup.Error( hwnd, L"Spew Viewing has already commenced."); break; } String clientName = Win::GetTrimmedDlgItemText(hwnd, IDC_CLIENT_NAME); String appName = Win::GetTrimmedDlgItemText(hwnd, IDC_APP_NAME);
if (clientName.empty() or appName.empty()) { popup.Error( hwnd, L"You need to specify a client machine and application"); break; }
if (!setFlagsOnStart) { GetFlags(); }
// configure the client
hr = SetClientConfiguration();
// if that call failed, it will have griped at the user.
BREAK_ON_FAILED_HRESULT(hr);
// deleted either in dtor or in WM_KILL_SPEWVIEWER handler
spewviewer = new SpewDialog(clientName, appName); spewviewer->ModelessExecute(hwnd); } while (0); }
bool MainDialog::OnCommand( HWND windowFrom, unsigned controlIDFrom, unsigned code) { // LOG_FUNCTION(MainDialog::OnCommand);
switch (controlIDFrom) { case IDC_VIEW_SPEW: { if (code == BN_CLICKED) { OnStartButton(); return true; } break; } case IDC_GET_FLAGS: { if (code == BN_CLICKED) { OnGetFlagsButton(); return true; } break; } case IDC_SET_FLAGS: { if (code == BN_CLICKED) { OnSetFlagsButton(); return true; } break; } case IDCANCEL: { if (code == BN_CLICKED) { // kill the spew window...
Win::EndDialog(hwnd, 0); return true; } break; } case IDC_CLIENT_NAME: case IDC_APP_NAME: { if (code == CBN_EDITCHANGE) { EnableControls(); } if (code == CBN_CLOSEUP) { // move the list box selection into the combo box edit control
Win::SetWindowText( windowFrom, Win::ComboBox_GetCurText(windowFrom));
EnableControls(); } break; } case IDC_OUTPUT_TO_FILE: case IDC_OUTPUT_TO_DEBUGGER: case IDC_OUTPUT_TO_SPEWVIEW: case IDC_OUTPUT_LOGS: case IDC_OUTPUT_HEADER: case IDC_OUTPUT_ERRORS: case IDC_OUTPUT_CTORS: case IDC_OUTPUT_ADDREFS: case IDC_OUTPUT_FUNCCALLS: case IDC_OUTPUT_TIME_OF_DAY: case IDC_OUTPUT_RUN_TIME: case IDC_OUTPUT_SCOPE_EXIT: { if (code == BN_CLICKED) { UpdateFlagsEdit(hwnd); setFlagsOnStart = true; } break; } case IDC_FLAGS: { switch (code) { case EN_CHANGE: { setFlagsOnStart = true;
// update the display
String text = Win::GetWindowText(windowFrom); DWORD flags = 0; text.convert(flags, 16);
UpdateCheckboxen(flags); break; } case EN_UPDATE: { } default: { // do nothing
break; } break; } } default: { // do nothing
} }
return false; }
void AddLastUsedNameToCombo( HWND combo, const StringList& historyList, const String& lastNameUsed) { typedef std::binder1st<String::EqualIgnoreCase> FindIfPredicate;
if (!lastNameUsed.empty()) { if ( std::find_if( historyList.begin(), historyList.end(), FindIfPredicate(String::EqualIgnoreCase(), lastNameUsed)) == historyList.end() ) { // last name used not present in history list, so add it
Win::ComboBox_AddString(combo, lastNameUsed); }
Win::ComboBox_SelectString(combo, lastNameUsed); } }
void MainDialog::OnInit() { LOG_FUNCTION(MainDialog::OnInit);
LoadUiHistory();
// Load the client and app name combo boxes with the historical values
HWND clientCombo = Win::GetDlgItem(hwnd, IDC_CLIENT_NAME);
Win::ComboBox_AddStrings( clientCombo, clientNameHistory.begin(), clientNameHistory.end());
HWND appCombo = Win::GetDlgItem(hwnd, IDC_APP_NAME);
Win::ComboBox_AddStrings( appCombo, appNameHistory.begin(), appNameHistory.end());
AddLastUsedNameToCombo(clientCombo, clientNameHistory, lastClientNameUsed); AddLastUsedNameToCombo(appCombo, appNameHistory, lastAppNameUsed);
// Limit to number of hex digits in a DWORD
Win::Edit_LimitText(Win::GetDlgItem(hwnd, IDC_FLAGS), 8);
SetStatusText(L""); ResetFlagsDisplay(); EnableControls(); }
void MainDialog::LoadUiHistory() { LOG_FUNCTION(MainDialog::LoadUiHistory);
HRESULT hr = S_OK;
do { RegistryKey key;
hr = key.Open(HKEY_LOCAL_MACHINE, SPEWVIEW_KEY_NAME); BREAK_ON_FAILED_HRESULT(hr);
hr = key.GetValue( L"ClientNameHistory", std::back_inserter(clientNameHistory)); LOG_HRESULT(hr);
// don't break on failure, try to read the app name history too.
hr = key.GetValue( L"AppNameHistory", std::back_inserter(appNameHistory)); LOG_HRESULT(hr);
// don't break on failure, try to read the last names used, too.
hr = key.GetValue(L"LastClientNameUsed", lastClientNameUsed); LOG_HRESULT(hr);
hr = key.GetValue(L"LastAppNameUsed", lastAppNameUsed); LOG_HRESULT(hr); } while (0); }
void MainDialog::SaveUiHistory() { LOG_FUNCTION(MainDialog::SaveUiHistory);
HRESULT hr = S_OK;
do { RegistryKey key;
hr = key.Create(HKEY_LOCAL_MACHINE, SPEWVIEW_KEY_NAME); BREAK_ON_FAILED_HRESULT(hr);
hr = key.SetValue( L"ClientNameHistory", clientNameHistory.begin(), clientNameHistory.end()); LOG_HRESULT(hr);
// don't break on failure, try to write the app name history too.
hr = key.SetValue( L"AppNameHistory", appNameHistory.begin(), appNameHistory.end()); LOG_HRESULT(hr);
// don't break on failure, try to write the last names used, too.
hr = key.SetValue(L"LastClientNameUsed", lastClientNameUsed); LOG_HRESULT(hr);
hr = key.SetValue(L"LastAppNameUsed", lastAppNameUsed); LOG_HRESULT(hr); } while (0); }
bool MainDialog::OnMessage( UINT message, WPARAM /* wparam */ , LPARAM /* lparam */ ) { switch (message) { case WM_KILL_SPEWVIEWER: { delete spewviewer; spewviewer = 0;
return true; } default: { // do nothing
break; } }
return false; }
|