// -------------------------------------------------------------------------- // Module Name: MessageBroadcast.cpp // // Copyright (c) 2000, Microsoft Corporation // // Class to manager sending or posting messages to windows to tell them that // things have changed. // // History: 2000-11-11 vtan created (split from services.cpp) // -------------------------------------------------------------------------- #include "stdafx.h" #include "MessageBroadcast.h" #include "Services.h" #include "ThemeSection.h" #include "Loader.h" #define TBOOL(x) ((BOOL)(x)) #define TW32(x) ((DWORD)(x)) #define THR(x) ((HRESULT)(x)) #define goto !!DO NOT USE GOTO!! - DO NOT REMOVE THIS ON PAIN OF DEATH // -------------------------------------------------------------------------- // CMessageBroadcast::CMessageBroadcast // // Arguments: fAllDesktops - if TRUE, all accessible desktops will be enum-ed // // Returns: // // Purpose: Constructor for CMessageBroadcast // // History: 2000-11-09 vtan created // -------------------------------------------------------------------------- CMessageBroadcast::CMessageBroadcast (BOOL fAllDesktops) : _hwnd(NULL), _dwProcessID(0), _fExclude(FALSE) { ZeroMemory(&_msg, sizeof(_msg)); _eMsgType = MT_SIMPLE; // default (set in each request function) _fAllDesktops = fAllDesktops; } // -------------------------------------------------------------------------- // CMessageBroadcast::~CMessageBroadcast // // Arguments: // // Returns: // // Purpose: Destructor for CMessageBroadcast // // History: 2000-11-09 vtan created // -------------------------------------------------------------------------- CMessageBroadcast::~CMessageBroadcast (void) { } // -------------------------------------------------------------------------- // CMessageBroadcast::EnumRequestedWindows // // Arguments: // // Returns: // // Purpose: Enumerate all windows in all desktops or just on current desktop // // History: 2000-12-20 rfernand created // -------------------------------------------------------------------------- void CMessageBroadcast::EnumRequestedWindows (void) { if (_fAllDesktops) { //---- enumerate all desktops in current session/station ---- TBOOL(EnumDesktops(GetProcessWindowStation(), DesktopCallBack, reinterpret_cast(this))); } else { //---- enumerate all windows in current desktop ---- TopWindowCallBack(GetDesktopWindow(), reinterpret_cast(this)); } } // -------------------------------------------------------------------------- void CMessageBroadcast::PostSimpleMsg(UINT msg, WPARAM wParam, LPARAM lParam) { _eMsgType = MT_SIMPLE; _msg.message = msg; _msg.wParam = wParam; _msg.lParam = lParam; EnumRequestedWindows(); } // -------------------------------------------------------------------------- void CMessageBroadcast::PostAllThreadsMsg(UINT msg, WPARAM wParam, LPARAM lParam) { //---- post the msg to a window on each unique processid/threadid ---- _ThreadsProcessed.RemoveAll(); // will track unique processid/threadid we have posted to _eMsgType = MT_ALLTHREADS; _msg.message = msg; _msg.wParam = wParam; _msg.lParam = lParam; EnumRequestedWindows(); } // -------------------------------------------------------------------------- // CMessageBroadcast::PostFilteredMsg // // Arguments: // // Returns: // // Purpose: Builds a message and stores conditions for the enumerator to // make a decision on whether a message needs to be posted. Then // enumerate all the windows (and children). // // History: 2000-11-09 vtan created // -------------------------------------------------------------------------- void CMessageBroadcast::PostFilteredMsg(UINT msg, WPARAM wParam, LPARAM lParam, HWND hwndTarget, BOOL fProcess, BOOL fExclude) { _eMsgType = MT_FILTERED; //---- set up the message ---- _msg.message = msg; _msg.wParam = wParam; _msg.lParam = lParam; _hwnd = hwndTarget; if (fProcess) { _dwProcessID = GetCurrentProcessId(); } else { _dwProcessID = 0; } _fExclude = (fExclude != NULL); //---- enumerate all desktops in current session/station ---- EnumRequestedWindows(); } // -------------------------------------------------------------------------- // CMessageBroadcast::DesktopCallBack // // Arguments: See the platform SDK under EnumDesktops. // // Returns: BOOL // // Purpose: enum all windows for specified desktop // // History: 2000-12-13 rfernand created // -------------------------------------------------------------------------- BOOL CALLBACK CMessageBroadcast::DesktopCallBack(LPTSTR lpszDesktop, LPARAM lParam) { HDESK hDesk = OpenDesktop(lpszDesktop, 0, FALSE, DESKTOP_READOBJECTS | DESKTOP_ENUMERATE); if (hDesk) { Log(LOG_TMCHANGEMSG, L"CMessageBroadcast: Desktop Opened: %s", lpszDesktop); //---- enum windows on desktop ---- TBOOL(EnumDesktopWindows(hDesk, TopWindowCallBack, lParam)); CloseDesktop(hDesk); } return TRUE; // EnumDesktopWindows() returns unreliable errors } // -------------------------------------------------------------------------- // CMessageBroadcast::TopWindowCallBack // // Arguments: hwnd, lParam // // Returns: TRUE (keep enumerating) // // Purpose: call "Worker" for hwnd and all of its (nested) children // // History: 2000-12-13 rfernand created // -------------------------------------------------------------------------- BOOL CALLBACK CMessageBroadcast::TopWindowCallBack (HWND hwnd, LPARAM lParam) { //---- process top level window ---- reinterpret_cast(lParam)->Worker(hwnd); //---- process all children windows ---- TBOOL(EnumChildWindows(hwnd, ChildWindowCallBack, lParam)); return TRUE; } // -------------------------------------------------------------------------- // CMessageBroadcast::ChildWindowCallBack // // Arguments: hwnd, lParam // // Returns: TRUE (keep enumerating) // // Purpose: call "Worker" for hwnd // // History: 2000-12-13 rfernand created // -------------------------------------------------------------------------- BOOL CALLBACK CMessageBroadcast::ChildWindowCallBack (HWND hwnd, LPARAM lParam) { //---- process top level window ---- reinterpret_cast(lParam)->Worker(hwnd); return TRUE; } // -------------------------------------------------------------------------- // CMessageBroadcast::Worker // // Arguments: // // Returns: // // Purpose: Performs validation on whether the HWND should get the built // message. // // History: 2000-11-09 vtan created // -------------------------------------------------------------------------- void CMessageBroadcast::Worker (HWND hwnd) { if (_eMsgType == MT_SIMPLE) { TBOOL(PostMessage(hwnd, _msg.message, _msg.wParam, _msg.lParam)); } else if (_eMsgType == MT_ALLTHREADS) { DWORD dwThreadId = GetWindowThreadProcessId(hwnd, NULL); BOOL fSendIt = TRUE; //---- is this a new thread? ---- for (int i=0; i < _ThreadsProcessed.m_nSize; i++) { if (_ThreadsProcessed[i] == dwThreadId) { fSendIt = FALSE; break; } } if (fSendIt) { TBOOL(PostMessage(hwnd, _msg.message, _msg.wParam, _msg.lParam)); _ThreadsProcessed.Add(dwThreadId); } } else // MT_FILTERED { bool fMatch; fMatch = true; if (_dwProcessID != 0) { fMatch = (IsWindowProcess(hwnd, _dwProcessID) != FALSE); if (_fExclude) { fMatch = !fMatch; } } if (fMatch) { if (_hwnd != NULL) { fMatch = ((_hwnd == hwnd) || IsChild(_hwnd, hwnd)); if (_fExclude) { fMatch = !fMatch; } } if (fMatch) { TBOOL(PostMessage(hwnd, _msg.message, _msg.wParam, _msg.lParam)); //Log(LOG_TMCHANGE, L"Worker: just POSTED msg=0x%x to hwnd=0x%x", // _msg.message, hwnd); } } } } // --------------------------------------------------------------------------