314 lines
8.6 KiB
C++
314 lines
8.6 KiB
C++
|
// --------------------------------------------------------------------------
|
||
|
// 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: <none>
|
||
|
//
|
||
|
// 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: <none>
|
||
|
//
|
||
|
// Returns: <none>
|
||
|
//
|
||
|
// Purpose: Destructor for CMessageBroadcast
|
||
|
//
|
||
|
// History: 2000-11-09 vtan created
|
||
|
// --------------------------------------------------------------------------
|
||
|
|
||
|
CMessageBroadcast::~CMessageBroadcast (void)
|
||
|
|
||
|
{
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------
|
||
|
// CMessageBroadcast::EnumRequestedWindows
|
||
|
//
|
||
|
// Arguments: <none>
|
||
|
//
|
||
|
// Returns: <none>
|
||
|
//
|
||
|
// 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<LPARAM>(this)));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//---- enumerate all windows in current desktop ----
|
||
|
TopWindowCallBack(GetDesktopWindow(), reinterpret_cast<LPARAM>(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: <none>
|
||
|
//
|
||
|
// Returns: <none>
|
||
|
//
|
||
|
// 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<CMessageBroadcast*>(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<CMessageBroadcast*>(lParam)->Worker(hwnd);
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------
|
||
|
// CMessageBroadcast::Worker
|
||
|
//
|
||
|
// Arguments: <none>
|
||
|
//
|
||
|
// Returns: <none>
|
||
|
//
|
||
|
// 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);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// --------------------------------------------------------------------------
|