From 35fd9fbbace044ed72418cd3352a7ffc9daf5430 Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Wed, 14 Aug 2019 08:39:26 +0200 Subject: [PATCH] Move eap::monitor_ui to Module.h/cpp Signed-off-by: Simon Rozman --- lib/EAPBase_UI/include/EAP_UI.h | 97 ---------------- lib/EAPBase_UI/include/Module.h | 89 ++++++++++++++ lib/EAPBase_UI/src/EAP_UI.cpp | 198 -------------------------------- lib/EAPBase_UI/src/Module.cpp | 195 +++++++++++++++++++++++++++++++ 4 files changed, 284 insertions(+), 295 deletions(-) diff --git a/lib/EAPBase_UI/include/EAP_UI.h b/lib/EAPBase_UI/include/EAP_UI.h index d0464e4..f167d46 100644 --- a/lib/EAPBase_UI/include/EAP_UI.h +++ b/lib/EAPBase_UI/include/EAP_UI.h @@ -106,11 +106,6 @@ inline void wxInitializeConfig(); /// @} -namespace eap -{ - class monitor_ui; -} - #pragma once #include // Fixes `CreateDialog` name collision @@ -1137,95 +1132,3 @@ inline void wxInitializeConfig() wxConfigBase *cfgPrev = wxConfigBase::Set(new wxConfig(wxT(PRODUCT_NAME_STR), wxT(VENDOR_NAME_STR))); if (cfgPrev) wxDELETE(cfgPrev); } - - -namespace eap -{ - /// \addtogroup EAPBaseGUI - /// @{ - - /// - /// Base class to enable single instance of the same dialog (master) return result to multiple threads (slaves) - /// - class monitor_ui - { - public: - /// - /// Constructs a UI monitor - /// - monitor_ui(_In_ HINSTANCE module, _In_ const GUID &guid); - - /// - /// Destructs the UI monitor - /// - virtual ~monitor_ui(); - - /// - /// Sets pop-up window handle - /// - /// \param[in] hwnd Handle of window to set as a new pop-up - /// - void set_popup(_In_ HWND hwnd); - - /// - /// Notifies all slaves waiting for this master and send them result data - /// - /// \param[in] data Pointer to result data - /// \param[in] size \p data size in bytes - /// - void release_slaves(_In_bytecount_(size) const void *data, _In_ size_t size) const; - - /// - /// Returns true if this is a master - /// - inline bool is_master() const - { - return m_is_master; - } - - /// - /// Returns true if this is a slave - /// - inline bool is_slave() const - { - return !is_master(); - } - - /// - /// Returns the data master send - /// - inline const std::vector& master_data() const - { - return m_data; - } - - protected: - /// \cond internal - - virtual LRESULT winproc( - _In_ UINT msg, - _In_ WPARAM wparam, - _In_ LPARAM lparam); - - static LRESULT CALLBACK winproc( - _In_ HWND hwnd, - _In_ UINT msg, - _In_ WPARAM wparam, - _In_ LPARAM lparam); - - /// \endcond - - protected: - bool m_is_master; ///< Is this monitor master? - HWND m_hwnd; ///< Message window handle - std::list m_slaves; ///< List of slaves to notify on finish - volatile HWND m_hwnd_popup; ///< Pop-up window handle - std::vector m_data; ///< Data master sent - - // Custom window messages - static const UINT s_msg_attach; ///< Slave sends this message to attach to master - static const UINT s_msg_finish; ///< Master sends this message to slaves to notify them it has finished (wparam has size, lparam has data) - }; - - /// @} -} diff --git a/lib/EAPBase_UI/include/Module.h b/lib/EAPBase_UI/include/Module.h index c5539b3..b25cd32 100644 --- a/lib/EAPBase_UI/include/Module.h +++ b/lib/EAPBase_UI/include/Module.h @@ -21,6 +21,7 @@ namespace eap { class peer_ui; + class monitor_ui; } #pragma once @@ -148,4 +149,92 @@ namespace eap }; /// @} + + /// \addtogroup EAPBaseGUI + /// @{ + + /// + /// Base class to enable single instance of the same dialog (master) return result to multiple threads (slaves) + /// + class monitor_ui + { + public: + /// + /// Constructs a UI monitor + /// + monitor_ui(_In_ HINSTANCE module, _In_ const GUID &guid); + + /// + /// Destructs the UI monitor + /// + virtual ~monitor_ui(); + + /// + /// Sets pop-up window handle + /// + /// \param[in] hwnd Handle of window to set as a new pop-up + /// + void set_popup(_In_ HWND hwnd); + + /// + /// Notifies all slaves waiting for this master and send them result data + /// + /// \param[in] data Pointer to result data + /// \param[in] size \p data size in bytes + /// + void release_slaves(_In_bytecount_(size) const void *data, _In_ size_t size) const; + + /// + /// Returns true if this is a master + /// + inline bool is_master() const + { + return m_is_master; + } + + /// + /// Returns true if this is a slave + /// + inline bool is_slave() const + { + return !is_master(); + } + + /// + /// Returns the data master send + /// + inline const std::vector& master_data() const + { + return m_data; + } + + protected: + /// \cond internal + + virtual LRESULT winproc( + _In_ UINT msg, + _In_ WPARAM wparam, + _In_ LPARAM lparam); + + static LRESULT CALLBACK winproc( + _In_ HWND hwnd, + _In_ UINT msg, + _In_ WPARAM wparam, + _In_ LPARAM lparam); + + /// \endcond + + protected: + bool m_is_master; ///< Is this monitor master? + HWND m_hwnd; ///< Message window handle + std::list m_slaves; ///< List of slaves to notify on finish + volatile HWND m_hwnd_popup; ///< Pop-up window handle + std::vector m_data; ///< Data master sent + + // Custom window messages + static const UINT s_msg_attach; ///< Slave sends this message to attach to master + static const UINT s_msg_finish; ///< Master sends this message to slaves to notify them it has finished (wparam has size, lparam has data) + }; + + /// @} } diff --git a/lib/EAPBase_UI/src/EAP_UI.cpp b/lib/EAPBase_UI/src/EAP_UI.cpp index 8b3564d..e11e19c 100644 --- a/lib/EAPBase_UI/src/EAP_UI.cpp +++ b/lib/EAPBase_UI/src/EAP_UI.cpp @@ -467,201 +467,3 @@ void wxEAPProviderSelectDialog::OnProvSelect(wxCommandEvent& event) event.Skip(); } /// \endcond - - -using namespace std; -using namespace winstd; - -////////////////////////////////////////////////////////////////////// -// eap::monitor_ui -////////////////////////////////////////////////////////////////////// - -eap::monitor_ui::monitor_ui(_In_ HINSTANCE module, _In_ const GUID &guid) : - m_hwnd_popup(NULL) -{ - // Verify if the monitor is already running. - const WNDCLASSEX wnd_class_desc_master = { - sizeof(WNDCLASSEX), // cbSize - 0, // style - winproc, // lpfnWndProc - 0, // cbClsExtra - 0, // cbWndExtra - module, // hInstance - NULL, // hIcon - NULL, // hCursor - NULL, // hbrBackground - NULL, // lpszMenuName - _T(__FUNCTION__), // lpszClassName - NULL // hIconSm - }; - ATOM wnd_class = RegisterClassEx(&wnd_class_desc_master); - if (!wnd_class) - throw win_runtime_error(__FUNCTION__ " Error registering master monitor window class."); - tstring_guid guid_str(guid); - HWND hwnd_master = FindWindowEx(HWND_MESSAGE, NULL, reinterpret_cast(wnd_class), guid_str.c_str()); - if (hwnd_master) { - // Another monitor is already running. - m_is_master = false; - - // Register slave windows class slightly different, not to include slaves in FindWindowEx(). - const WNDCLASSEX wnd_class_desc_slave = { - sizeof(WNDCLASSEX), // cbSize - 0, // style - winproc, // lpfnWndProc - 0, // cbClsExtra - 0, // cbWndExtra - module, // hInstance - NULL, // hIcon - NULL, // hCursor - NULL, // hbrBackground - NULL, // lpszMenuName - _T(__FUNCTION__) _T("-Slave"), // lpszClassName - NULL // hIconSm - }; - wnd_class = RegisterClassEx(&wnd_class_desc_slave); - if (!wnd_class) - throw win_runtime_error(__FUNCTION__ " Error registering slave monitor window class."); - } else { - // This is a fresh monitor. - m_is_master = true; - } - - m_hwnd = CreateWindowEx( - 0, // dwExStyle - reinterpret_cast(wnd_class), // lpClassName - guid_str.c_str(), // lpWindowName - 0, // dwStyle - 0, // x - 0, // y - 0, // nWidth - 0, // nHeight - HWND_MESSAGE, // hWndParent - NULL, // hMenu - module, // hInstance - this); // lpParam - - if (!m_is_master) { - // Notify master we are waiting him. - SendMessage(hwnd_master, s_msg_attach, 0, (LPARAM)m_hwnd); - - // Slaves must pump message queue until finished. - MSG msg; - while (GetMessage(&msg, NULL, 0, 0) > 0) { - TranslateMessage(&msg); - DispatchMessage(&msg); - } - } -} - - -eap::monitor_ui::~monitor_ui() -{ - if (m_hwnd) - DestroyWindow(m_hwnd); -} - - -void eap::monitor_ui::set_popup(_In_ HWND hwnd) -{ - m_hwnd_popup = hwnd; -} - - -void eap::monitor_ui::release_slaves(_In_bytecount_(size) const void *data, _In_ size_t size) const -{ - assert(!size || data); - - for (auto slave = m_slaves.cbegin(), slave_end = m_slaves.cend(); slave != slave_end; ++slave) { - // Get slave's PID. - DWORD pid_slave; - GetWindowThreadProcessId(*slave, &pid_slave); - - // Get slave's process handle. - process proc_slave; - if (!proc_slave.open(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, 0, pid_slave)) - continue; - - // Allocate memory in slave's virtual memory space and save data to it. - vmemory mem_slave; - if (!mem_slave.alloc(proc_slave, NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)) - continue; - if (!WriteProcessMemory(proc_slave, mem_slave, data, size, NULL)) - continue; - - // Notify slave. Use SendMessage(), not PostMessage(), as memory will get cleaned up. - SendMessage(*slave, s_msg_finish, (WPARAM)size, (LPARAM)(LPVOID)mem_slave); - } -} - - -/// \cond internal - -LRESULT eap::monitor_ui::winproc( - _In_ UINT msg, - _In_ WPARAM wparam, - _In_ LPARAM lparam) -{ - UNREFERENCED_PARAMETER(wparam); - - if (msg == s_msg_attach) { - // Attach a new slave. - assert(m_is_master); - m_slaves.push_back((HWND)lparam); - - HWND hwnd_popup = m_hwnd_popup; - if (hwnd_popup) { - // Bring pop-up window up. - if (::IsIconic(hwnd_popup)) - ::SendMessage(hwnd_popup, WM_SYSCOMMAND, SC_RESTORE, 0); - ::SetActiveWindow(hwnd_popup); - ::SetForegroundWindow(hwnd_popup); - } - - return TRUE; - } else if (msg == s_msg_finish) { - // Master finished. - assert(!m_is_master); - m_data.assign(reinterpret_cast(lparam), reinterpret_cast(lparam) + wparam); - - // Finish slave too. - DestroyWindow(m_hwnd); - return TRUE; - } else if (msg == WM_DESTROY) { - // Stop the message pump. - PostQuitMessage(0); - return 0; - } - - return DefWindowProc(m_hwnd, msg, wparam, lparam); -} - - -LRESULT CALLBACK eap::monitor_ui::winproc( - _In_ HWND hwnd, - _In_ UINT msg, - _In_ WPARAM wparam, - _In_ LPARAM lparam) -{ - if (msg == WM_CREATE) { - // Set window's user data to "this" pointer. - const CREATESTRUCT *cs = (CREATESTRUCT*)lparam; - SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)cs->lpCreateParams); - - // Forward to our handler. - return ((eap::monitor_ui*)cs->lpCreateParams)->winproc(msg, wparam, lparam); - } else { - // Get "this" pointer from window's user data. - eap::monitor_ui *_this = (eap::monitor_ui*)GetWindowLongPtr(hwnd, GWLP_USERDATA); - if (_this) { - // Forward to our handler. - return _this->winproc(msg, wparam, lparam); - } else - return DefWindowProc(hwnd, msg, wparam, lparam); - } -} - -/// \endcond - - -const UINT eap::monitor_ui::s_msg_attach = RegisterWindowMessage(_T(PRODUCT_NAME_STR) _T("-Attach")); -const UINT eap::monitor_ui::s_msg_finish = RegisterWindowMessage(_T(PRODUCT_NAME_STR) _T("-Finish")); diff --git a/lib/EAPBase_UI/src/Module.cpp b/lib/EAPBase_UI/src/Module.cpp index 42c989f..25a6905 100644 --- a/lib/EAPBase_UI/src/Module.cpp +++ b/lib/EAPBase_UI/src/Module.cpp @@ -30,3 +30,198 @@ using namespace winstd; eap::peer_ui::peer_ui(_In_ eap_type_t eap_method) : module(eap_method) { } + + +////////////////////////////////////////////////////////////////////// +// eap::monitor_ui +////////////////////////////////////////////////////////////////////// + +eap::monitor_ui::monitor_ui(_In_ HINSTANCE module, _In_ const GUID &guid) : + m_hwnd_popup(NULL) +{ + // Verify if the monitor is already running. + const WNDCLASSEX wnd_class_desc_master = { + sizeof(WNDCLASSEX), // cbSize + 0, // style + winproc, // lpfnWndProc + 0, // cbClsExtra + 0, // cbWndExtra + module, // hInstance + NULL, // hIcon + NULL, // hCursor + NULL, // hbrBackground + NULL, // lpszMenuName + _T(__FUNCTION__), // lpszClassName + NULL // hIconSm + }; + ATOM wnd_class = RegisterClassEx(&wnd_class_desc_master); + if (!wnd_class) + throw win_runtime_error(__FUNCTION__ " Error registering master monitor window class."); + tstring_guid guid_str(guid); + HWND hwnd_master = FindWindowEx(HWND_MESSAGE, NULL, reinterpret_cast(wnd_class), guid_str.c_str()); + if (hwnd_master) { + // Another monitor is already running. + m_is_master = false; + + // Register slave windows class slightly different, not to include slaves in FindWindowEx(). + const WNDCLASSEX wnd_class_desc_slave = { + sizeof(WNDCLASSEX), // cbSize + 0, // style + winproc, // lpfnWndProc + 0, // cbClsExtra + 0, // cbWndExtra + module, // hInstance + NULL, // hIcon + NULL, // hCursor + NULL, // hbrBackground + NULL, // lpszMenuName + _T(__FUNCTION__) _T("-Slave"), // lpszClassName + NULL // hIconSm + }; + wnd_class = RegisterClassEx(&wnd_class_desc_slave); + if (!wnd_class) + throw win_runtime_error(__FUNCTION__ " Error registering slave monitor window class."); + } else { + // This is a fresh monitor. + m_is_master = true; + } + + m_hwnd = CreateWindowEx( + 0, // dwExStyle + reinterpret_cast(wnd_class), // lpClassName + guid_str.c_str(), // lpWindowName + 0, // dwStyle + 0, // x + 0, // y + 0, // nWidth + 0, // nHeight + HWND_MESSAGE, // hWndParent + NULL, // hMenu + module, // hInstance + this); // lpParam + + if (!m_is_master) { + // Notify master we are waiting him. + SendMessage(hwnd_master, s_msg_attach, 0, (LPARAM)m_hwnd); + + // Slaves must pump message queue until finished. + MSG msg; + while (GetMessage(&msg, NULL, 0, 0) > 0) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + } +} + + +eap::monitor_ui::~monitor_ui() +{ + if (m_hwnd) + DestroyWindow(m_hwnd); +} + + +void eap::monitor_ui::set_popup(_In_ HWND hwnd) +{ + m_hwnd_popup = hwnd; +} + + +void eap::monitor_ui::release_slaves(_In_bytecount_(size) const void *data, _In_ size_t size) const +{ + assert(!size || data); + + for (auto slave = m_slaves.cbegin(), slave_end = m_slaves.cend(); slave != slave_end; ++slave) { + // Get slave's PID. + DWORD pid_slave; + GetWindowThreadProcessId(*slave, &pid_slave); + + // Get slave's process handle. + process proc_slave; + if (!proc_slave.open(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, 0, pid_slave)) + continue; + + // Allocate memory in slave's virtual memory space and save data to it. + vmemory mem_slave; + if (!mem_slave.alloc(proc_slave, NULL, size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)) + continue; + if (!WriteProcessMemory(proc_slave, mem_slave, data, size, NULL)) + continue; + + // Notify slave. Use SendMessage(), not PostMessage(), as memory will get cleaned up. + SendMessage(*slave, s_msg_finish, (WPARAM)size, (LPARAM)(LPVOID)mem_slave); + } +} + + +/// \cond internal + +LRESULT eap::monitor_ui::winproc( + _In_ UINT msg, + _In_ WPARAM wparam, + _In_ LPARAM lparam) +{ + UNREFERENCED_PARAMETER(wparam); + + if (msg == s_msg_attach) { + // Attach a new slave. + assert(m_is_master); + m_slaves.push_back((HWND)lparam); + + HWND hwnd_popup = m_hwnd_popup; + if (hwnd_popup) { + // Bring pop-up window up. + if (::IsIconic(hwnd_popup)) + ::SendMessage(hwnd_popup, WM_SYSCOMMAND, SC_RESTORE, 0); + ::SetActiveWindow(hwnd_popup); + ::SetForegroundWindow(hwnd_popup); + } + + return TRUE; + } else if (msg == s_msg_finish) { + // Master finished. + assert(!m_is_master); + m_data.assign(reinterpret_cast(lparam), reinterpret_cast(lparam) + wparam); + + // Finish slave too. + DestroyWindow(m_hwnd); + return TRUE; + } else if (msg == WM_DESTROY) { + // Stop the message pump. + PostQuitMessage(0); + return 0; + } + + return DefWindowProc(m_hwnd, msg, wparam, lparam); +} + + +LRESULT CALLBACK eap::monitor_ui::winproc( + _In_ HWND hwnd, + _In_ UINT msg, + _In_ WPARAM wparam, + _In_ LPARAM lparam) +{ + if (msg == WM_CREATE) { + // Set window's user data to "this" pointer. + const CREATESTRUCT *cs = (CREATESTRUCT*)lparam; + SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)cs->lpCreateParams); + + // Forward to our handler. + return ((eap::monitor_ui*)cs->lpCreateParams)->winproc(msg, wparam, lparam); + } else { + // Get "this" pointer from window's user data. + eap::monitor_ui *_this = (eap::monitor_ui*)GetWindowLongPtr(hwnd, GWLP_USERDATA); + if (_this) { + // Forward to our handler. + return _this->winproc(msg, wparam, lparam); + } else + return DefWindowProc(hwnd, msg, wparam, lparam); + } +} + +/// \endcond + + +const UINT eap::monitor_ui::s_msg_attach = RegisterWindowMessage(_T(PRODUCT_NAME_STR) _T("-Attach")); +const UINT eap::monitor_ui::s_msg_finish = RegisterWindowMessage(_T(PRODUCT_NAME_STR) _T("-Finish"));