// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A // PARTICULAR PURPOSE. // // Copyright (c) Microsoft Corporation. All rights reserved. #include "stdafx.h" #include "COMSpy.h" #include "ComSpyCtl.h" #include "SpyCon.h" static const LPCWSTR COMSPY_REG_KEY = L"Software\\Microsoft\\COMSpy"; static const LPCWSTR REG_VALUE_LEFT = L"Left"; static const LPCWSTR REG_VALUE_TOP = L"Top"; static const LPCWSTR REG_VALUE_RIGHT = L"Right"; static const LPCWSTR REG_VALUE_BOTTOM = L"Bottom"; static const LPCWSTR REG_VALUE_SHOW_WINDOW = L"ShowWindow"; static const LPCWSTR REG_VALUE_ALWAYS_ON_TOP = L"AlwaysOnTop"; static const LPCWSTR REG_VALUE_SAVE_ON_EXIT = L"SaveOnExit"; static const LPCWSTR REG_VALUE_CONTROL_PROPERTIES = L"ControlProperties"; ///////////////////////////////////////////////////////////////////////////// // CSpyCon STDMETHODIMP CSpyCon::Run() { // Create our window RECT rcPos = { CW_USEDEFAULT, 0, 0, 0 }; CString sWindowTitle; BOOL bResult = sWindowTitle.LoadStringW(IDS_WINDOW_TITLE); _ASSERTE(bResult); HMENU hMenu = LoadMenu(_Module.GetResourceInstance(), MAKEINTRESOURCE(IDR_MENU1)); _ASSERTE(hMenu); HWND hwnd = Create(NULL, rcPos, sWindowTitle, WS_VISIBLE | WS_OVERLAPPEDWINDOW, 0, hMenu); _ASSERTE(hwnd); // Set its icon HICON hIcon = LoadIcon(_Module.GetModuleInstance(), MAKEINTRESOURCE(IDI_MAIN)); _ASSERTE(hIcon); SetIcon(hIcon, TRUE); // Create the spy control HRESULT hr = CoCreateInstance(CLSID_ComSpy, NULL, CLSCTX_INPROC, IID_PPV_ARGS(&m_spOleObject)); if (FAILED(hr)) { MessageBox(L"CoCreateInstance failed"); return hr; } _ASSERTE(m_spOleObject); m_spOleObject->SetClientSite(this); hr = m_spOleObject->QueryInterface(IID_PPV_ARGS(&m_spSpy)); _ASSERTE(SUCCEEDED(hr) && m_spSpy); // Get our window state from the registry HKEY hKey = NULL; (void)RegCreateKeyEx(HKEY_LOCAL_MACHINE, COMSPY_REG_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE, NULL, &hKey, NULL); if (hKey) { DWORD dwType; DWORD dwValue; DWORD dwSize = sizeof(dwValue); if ((ERROR_SUCCESS == RegQueryValueEx(hKey, REG_VALUE_LEFT, NULL, &dwType, (LPBYTE)&dwValue, &dwSize)) && (dwType == REG_DWORD) && (dwSize == sizeof(dwValue))) { m_wp.rcNormalPosition.left = (LONG)dwValue; } dwSize = sizeof(dwValue); if ((ERROR_SUCCESS == RegQueryValueEx(hKey, REG_VALUE_TOP, NULL, &dwType, (LPBYTE)&dwValue, &dwSize)) && (dwType == REG_DWORD) && (dwSize == sizeof(dwValue))) { m_wp.rcNormalPosition.top = (LONG)dwValue; } dwSize = sizeof(dwValue); if ((ERROR_SUCCESS == RegQueryValueEx(hKey, REG_VALUE_RIGHT, NULL, &dwType, (LPBYTE)&dwValue, &dwSize)) && (dwType == REG_DWORD) && (dwSize == sizeof(dwValue))) { m_wp.rcNormalPosition.right = (LONG)dwValue; } dwSize = sizeof(dwValue); if ((ERROR_SUCCESS == RegQueryValueEx(hKey, REG_VALUE_BOTTOM, NULL, &dwType, (LPBYTE)&dwValue, &dwSize)) && (dwType == REG_DWORD) && (dwSize == sizeof(dwValue))) { m_wp.rcNormalPosition.bottom = (LONG)dwValue; } dwSize = sizeof(dwValue); if ((ERROR_SUCCESS == RegQueryValueEx(hKey, REG_VALUE_SHOW_WINDOW, NULL, &dwType, (LPBYTE)&dwValue, &dwSize)) && (dwType == REG_DWORD) && (dwSize == sizeof(dwValue))) { m_wp.showCmd = (UINT)dwValue; } dwSize = sizeof(dwValue); if ((ERROR_SUCCESS == RegQueryValueEx(hKey, REG_VALUE_ALWAYS_ON_TOP, NULL, &dwType, (LPBYTE)&dwValue, &dwSize)) && (dwType == REG_DWORD) && (dwSize == sizeof(dwValue))) { m_bAlwaysOnTop = (dwValue != 0); } // Using OnAlwaysOnTop to handle the always on top option, which toggles the value m_bAlwaysOnTop = !m_bAlwaysOnTop; BOOL bHandledIgnored = TRUE; OnAlwaysOnTop(0,0,0,bHandledIgnored); dwSize = sizeof(dwValue); if ((ERROR_SUCCESS == RegQueryValueEx(hKey, REG_VALUE_SAVE_ON_EXIT, NULL, &dwType, (LPBYTE)&dwValue, &dwSize)) && (dwType == REG_DWORD) && (dwSize == sizeof(dwValue))) { m_bSaveOnExit = (dwValue != 0); } // Get the control properties persisted in a stream dwSize = 0; if ((ERROR_SUCCESS == RegQueryValueEx(hKey, REG_VALUE_CONTROL_PROPERTIES, NULL, &dwType, NULL, &dwSize)) && (dwType == REG_BINARY)) { HGLOBAL hGlobal = GlobalAlloc(GPTR, dwSize); if (hGlobal) { BYTE* pbValue = (BYTE*)GlobalLock(hGlobal); _ASSERTE(pbValue); LONG lResult = RegQueryValueEx(hKey, REG_VALUE_CONTROL_PROPERTIES, NULL, &dwType, pbValue, &dwSize); GlobalUnlock(hGlobal); CComPtr spStream; if ((ERROR_SUCCESS == lResult) && SUCCEEDED(CreateStreamOnHGlobal(hGlobal, TRUE, &spStream))) { CComPtr spPersist; hr = m_spSpy->QueryInterface(IID_PPV_ARGS(&spPersist)); _ASSERTE(SUCCEEDED(hr) && spPersist); // Best effort (ignore failure) (void)spPersist->Load(spStream); } else { GlobalFree(hGlobal); } } } } if (!(( m_wp.rcNormalPosition.right - m_wp.rcNormalPosition.left < 10) || (m_wp.rcNormalPosition.bottom - m_wp.rcNormalPosition.top < 10))) SetWindowPlacement(&m_wp); else ShowWindow(SW_SHOWNORMAL); GetClientRect(&rcPos); MSG msg; return m_spOleObject->DoVerb(OLEIVERB_INPLACEACTIVATE, &msg, this, 0, m_hWnd, &rcPos); } // // show the select filter dialog // LRESULT CSpyCon::OnSelectFilter(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { _ASSERTE(m_spSpy); m_spSpy->SelectApplications(); return 0; } // // the user clicks on the system menu // LRESULT CSpyCon::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { bHandled = FALSE; // always do default processing if (wParam == SC_CLOSE) OnExit(NULL, NULL, NULL, bHandled); return 0; } // // sets a glog to log to file // if the user hasn't chosen a log file, show the common dialog to allow them to select one // LRESULT CSpyCon::OnLogToFile(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { _ASSERTE(m_spSpy); BOOL bVal; m_spSpy->get_LogToFile(&bVal); bVal = !bVal; m_spSpy->put_LogToFile(bVal); return 0; } // // User wants to choose a log file -- show the common dialog // LRESULT CSpyCon::OnChooseLogFile(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { _ASSERTE(m_spSpy); CComBSTR bstrFileName; BOOL bCanceled; m_spSpy->ChooseLogFile(&bstrFileName, &bCanceled); return 0; } // // toggle the save on exit flag // LRESULT CSpyCon::OnToggleSaveOnExit(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { m_bSaveOnExit = !m_bSaveOnExit; // For most of the options, we do not save until exit or "Save Settings Now" is clicked. // If Save On Exit is disabled, however, we need to save this now. Otherwise, this // option won't be saved and will still be enabled the next time we run. if (!m_bSaveOnExit) { // Best effort (ignore failures) HKEY hKey = NULL; (void)RegCreateKeyEx(HKEY_LOCAL_MACHINE, COMSPY_REG_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL); if (hKey) { DWORD dwValue = 0; (void)RegSetValueEx(hKey, REG_VALUE_SAVE_ON_EXIT, NULL, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)); RegCloseKey(hKey); } } return 0; } // // toggle the show on screen flag // LRESULT CSpyCon::OnToggleShowOnScreen(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { _ASSERTE(m_spSpy); BOOL bVal; m_spSpy->get_ShowOnScreen(&bVal); bVal = !bVal; m_spSpy->put_ShowOnScreen(bVal); return 0; } // // update the UI in menus // LRESULT CSpyCon::OnInitMenu(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { _ASSERTE(m_spSpy); HMENU hMenu = (HMENU)wParam; CComBSTR temp = "&Log to File "; CComBSTR bstrFileName; m_spSpy->get_LogFile(&bstrFileName); if (bstrFileName.Length() > 5) temp += bstrFileName; else temp = "&Log To file..."; ModifyMenu(hMenu, ID_LOG, MF_BYCOMMAND|MF_STRING, ID_LOG, temp); BOOL bVal; m_spSpy->get_LogToFile(&bVal); CheckMenuItem(hMenu, ID_LOG, bVal ? MF_BYCOMMAND|MF_CHECKED : MF_BYCOMMAND|MF_UNCHECKED); m_spSpy->get_ShowGridLines(&bVal); CheckMenuItem(hMenu, ID_OPTIONS_GRID_LINES, bVal ? MF_BYCOMMAND|MF_CHECKED : MF_BYCOMMAND|MF_UNCHECKED); m_spSpy->get_ShowOnScreen(&bVal); CheckMenuItem(hMenu, ID_SHOW_ON_SCREEN, bVal ? MF_BYCOMMAND|MF_CHECKED : MF_BYCOMMAND|MF_UNCHECKED); CheckMenuItem(hMenu, IDM_ON_TOP, m_bAlwaysOnTop ? MF_BYCOMMAND|MF_CHECKED : MF_BYCOMMAND|MF_UNCHECKED); CheckMenuItem(hMenu, ID_SAVE_ON_EXIT, m_bSaveOnExit ? MF_BYCOMMAND|MF_CHECKED : MF_BYCOMMAND|MF_UNCHECKED); return 0; } // // show/hide gridlines in the list // // NOTE: This will only work if the user has installed IE 3.0 or greater // LRESULT CSpyCon::OnToggleGridLines(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { _ASSERTE(m_spSpy); BOOL bVal; m_spSpy->get_ShowGridLines(&bVal); bVal = !bVal; m_spSpy->put_ShowGridLines(bVal); return 0; } // // Toggle the Always on top option // LRESULT CSpyCon::OnAlwaysOnTop(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { m_bAlwaysOnTop = !m_bAlwaysOnTop; if (m_bAlwaysOnTop) SetWindowPos(HWND_TOPMOST, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE); else SetWindowPos(HWND_NOTOPMOST, 0,0,0,0, SWP_NOMOVE|SWP_NOSIZE); return 0; } // // show the standard Shell About box // LRESULT CSpyCon::OnAbout(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { _ASSERTE(m_spSpy); m_spSpy->About(); return 0; } // // pick the font to use in the list // LRESULT CSpyCon::OnChooseFont(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { _ASSERTE(m_spSpy); m_spSpy->ChooseFont(); return 0; } // // called on a WM_CLOSE & WM_SYSCOMMAND (SC_CLOSE) message. If appropriate, save settings // and then destroy the window // LRESULT CSpyCon::OnExit(WORD /*wNotifyCode*/, WORD /* wID */, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { if (m_bSaveOnExit) SaveSettings(); m_spOleObject->Close(OLECLOSE_NOSAVE); m_spOleObject.Release(); m_spSpy.Release(); DestroyWindow(); return 0; } // // save current settings to the registry // LRESULT CSpyCon::OnSaveNow(WORD /*wNotifyCode*/, WORD /* wID */, HWND /*hWndCtl*/, BOOL& /*bHandled*/) { SaveSettings(); return 0; } // // clear the list box // LRESULT CSpyCon::OnClear(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { _ASSERTE(m_spSpy); m_spSpy->ClearAllEvents(); return 0; } // // save the items in the list box to the log file // LRESULT CSpyCon::OnSave(WORD wNotifyCode, WORD wID, HWND hWndCtl, BOOL& bHandled) { _ASSERTE(m_spSpy); m_spSpy->SaveToFile(); return 0; } // // saves settings. asks the control fro a stream to save its state // HRESULT CSpyCon::SaveSettings() { _ASSERTE(m_spSpy); // Best effort (ignore failures) HKEY hKey = NULL; (void)RegCreateKeyEx(HKEY_LOCAL_MACHINE, COMSPY_REG_KEY, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, NULL); if (hKey) { DWORD dwValue = (DWORD)m_wp.rcNormalPosition.left; (void)RegSetValueEx(hKey, REG_VALUE_LEFT, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)); dwValue = (DWORD)m_wp.rcNormalPosition.top; (void)RegSetValueEx(hKey, REG_VALUE_TOP, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)); dwValue = (DWORD)m_wp.rcNormalPosition.right; (void)RegSetValueEx(hKey, REG_VALUE_RIGHT, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)); dwValue = (DWORD)m_wp.rcNormalPosition.bottom; (void)RegSetValueEx(hKey, REG_VALUE_BOTTOM, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)); dwValue = (DWORD)m_wp.showCmd; (void)RegSetValueEx(hKey, REG_VALUE_SHOW_WINDOW, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)); dwValue = m_bAlwaysOnTop ? 1 : 0; (void)RegSetValueEx(hKey, REG_VALUE_ALWAYS_ON_TOP, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)); dwValue = m_bSaveOnExit ? 1 : 0; (void)RegSetValueEx(hKey, REG_VALUE_SAVE_ON_EXIT, 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(dwValue)); CComPtr spPersist; HRESULT hr = m_spSpy->QueryInterface(IID_PPV_ARGS(&spPersist)); _ASSERTE(SUCCEEDED(hr) && spPersist); CComPtr spStream; if (SUCCEEDED(CreateStreamOnHGlobal(NULL, TRUE, &spStream))) { if (SUCCEEDED(spPersist->Save(spStream, TRUE))) { HGLOBAL hGlobal = NULL; hr = GetHGlobalFromStream(spStream, &hGlobal); _ASSERTE(SUCCEEDED(hr) && spStream); BYTE* pbValue = (BYTE *)GlobalLock(hGlobal); _ASSERTE(pbValue); DWORD dwSize = (DWORD)GlobalSize(hGlobal); (void)RegSetValueEx(hKey, REG_VALUE_CONTROL_PROPERTIES, 0, REG_BINARY, pbValue, dwSize); GlobalUnlock(hGlobal); } } RegCloseKey(hKey); } return S_OK; } LRESULT CSpyCon::OnNCDestroy(UINT /* uMsg */, WPARAM /* wParam */, LPARAM /* lParam */, BOOL& /* bHandled */) { PostQuitMessage(0); return 0; } LRESULT CSpyCon::OnErase(UINT /* uMsg */, WPARAM /* wParam */, LPARAM /* lParam */, BOOL& bHandled) { if (m_bInPlaceActive) return 0; bHandled = FALSE; return 1; } LRESULT CSpyCon::OnSize(UINT /* uMsg */, WPARAM /* wParam */, LPARAM /* lParam */, BOOL& /* bHandled */) { if (m_spOleObject && m_bInPlaceActive) { CComPtr spInPlaceObject; HRESULT hr = m_spOleObject->QueryInterface(IID_PPV_ARGS(&spInPlaceObject)); _ASSERTE(SUCCEEDED(hr) && spInPlaceObject); RECT rcClient; GetClientRect(&rcClient); spInPlaceObject->SetObjectRects(&rcClient, &rcClient); GetWindowPlacement(&m_wp); // for storing in the registry } return 0; }