Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

313 lines
8.6 KiB

  1. // --------------------------------------------------------------------------
  2. // Module Name: MessageBroadcast.cpp
  3. //
  4. // Copyright (c) 2000, Microsoft Corporation
  5. //
  6. // Class to manager sending or posting messages to windows to tell them that
  7. // things have changed.
  8. //
  9. // History: 2000-11-11 vtan created (split from services.cpp)
  10. // --------------------------------------------------------------------------
  11. #include "stdafx.h"
  12. #include "MessageBroadcast.h"
  13. #include "Services.h"
  14. #include "ThemeSection.h"
  15. #include "Loader.h"
  16. #define TBOOL(x) ((BOOL)(x))
  17. #define TW32(x) ((DWORD)(x))
  18. #define THR(x) ((HRESULT)(x))
  19. #define goto !!DO NOT USE GOTO!! - DO NOT REMOVE THIS ON PAIN OF DEATH
  20. // --------------------------------------------------------------------------
  21. // CMessageBroadcast::CMessageBroadcast
  22. //
  23. // Arguments: fAllDesktops - if TRUE, all accessible desktops will be enum-ed
  24. //
  25. // Returns: <none>
  26. //
  27. // Purpose: Constructor for CMessageBroadcast
  28. //
  29. // History: 2000-11-09 vtan created
  30. // --------------------------------------------------------------------------
  31. CMessageBroadcast::CMessageBroadcast (BOOL fAllDesktops) :
  32. _hwnd(NULL),
  33. _dwProcessID(0),
  34. _fExclude(FALSE)
  35. {
  36. ZeroMemory(&_msg, sizeof(_msg));
  37. _eMsgType = MT_SIMPLE; // default (set in each request function)
  38. _fAllDesktops = fAllDesktops;
  39. }
  40. // --------------------------------------------------------------------------
  41. // CMessageBroadcast::~CMessageBroadcast
  42. //
  43. // Arguments: <none>
  44. //
  45. // Returns: <none>
  46. //
  47. // Purpose: Destructor for CMessageBroadcast
  48. //
  49. // History: 2000-11-09 vtan created
  50. // --------------------------------------------------------------------------
  51. CMessageBroadcast::~CMessageBroadcast (void)
  52. {
  53. }
  54. // --------------------------------------------------------------------------
  55. // CMessageBroadcast::EnumRequestedWindows
  56. //
  57. // Arguments: <none>
  58. //
  59. // Returns: <none>
  60. //
  61. // Purpose: Enumerate all windows in all desktops or just on current desktop
  62. //
  63. // History: 2000-12-20 rfernand created
  64. // --------------------------------------------------------------------------
  65. void CMessageBroadcast::EnumRequestedWindows (void)
  66. {
  67. if (_fAllDesktops)
  68. {
  69. //---- enumerate all desktops in current session/station ----
  70. TBOOL(EnumDesktops(GetProcessWindowStation(), DesktopCallBack, reinterpret_cast<LPARAM>(this)));
  71. }
  72. else
  73. {
  74. //---- enumerate all windows in current desktop ----
  75. TopWindowCallBack(GetDesktopWindow(), reinterpret_cast<LPARAM>(this));
  76. }
  77. }
  78. // --------------------------------------------------------------------------
  79. void CMessageBroadcast::PostSimpleMsg(UINT msg, WPARAM wParam, LPARAM lParam)
  80. {
  81. _eMsgType = MT_SIMPLE;
  82. _msg.message = msg;
  83. _msg.wParam = wParam;
  84. _msg.lParam = lParam;
  85. EnumRequestedWindows();
  86. }
  87. // --------------------------------------------------------------------------
  88. void CMessageBroadcast::PostAllThreadsMsg(UINT msg, WPARAM wParam, LPARAM lParam)
  89. {
  90. //---- post the msg to a window on each unique processid/threadid ----
  91. _ThreadsProcessed.RemoveAll(); // will track unique processid/threadid we have posted to
  92. _eMsgType = MT_ALLTHREADS;
  93. _msg.message = msg;
  94. _msg.wParam = wParam;
  95. _msg.lParam = lParam;
  96. EnumRequestedWindows();
  97. }
  98. // --------------------------------------------------------------------------
  99. // CMessageBroadcast::PostFilteredMsg
  100. //
  101. // Arguments: <none>
  102. //
  103. // Returns: <none>
  104. //
  105. // Purpose: Builds a message and stores conditions for the enumerator to
  106. // make a decision on whether a message needs to be posted. Then
  107. // enumerate all the windows (and children).
  108. //
  109. // History: 2000-11-09 vtan created
  110. // --------------------------------------------------------------------------
  111. void CMessageBroadcast::PostFilteredMsg(UINT msg, WPARAM wParam, LPARAM lParam,
  112. HWND hwndTarget, BOOL fProcess, BOOL fExclude)
  113. {
  114. _eMsgType = MT_FILTERED;
  115. //---- set up the message ----
  116. _msg.message = msg;
  117. _msg.wParam = wParam;
  118. _msg.lParam = lParam;
  119. _hwnd = hwndTarget;
  120. if (fProcess)
  121. {
  122. _dwProcessID = GetCurrentProcessId();
  123. }
  124. else
  125. {
  126. _dwProcessID = 0;
  127. }
  128. _fExclude = (fExclude != NULL);
  129. //---- enumerate all desktops in current session/station ----
  130. EnumRequestedWindows();
  131. }
  132. // --------------------------------------------------------------------------
  133. // CMessageBroadcast::DesktopCallBack
  134. //
  135. // Arguments: See the platform SDK under EnumDesktops.
  136. //
  137. // Returns: BOOL
  138. //
  139. // Purpose: enum all windows for specified desktop
  140. //
  141. // History: 2000-12-13 rfernand created
  142. // --------------------------------------------------------------------------
  143. BOOL CALLBACK CMessageBroadcast::DesktopCallBack(LPTSTR lpszDesktop, LPARAM lParam)
  144. {
  145. HDESK hDesk = OpenDesktop(lpszDesktop, 0, FALSE, DESKTOP_READOBJECTS | DESKTOP_ENUMERATE);
  146. if (hDesk)
  147. {
  148. Log(LOG_TMCHANGEMSG, L"CMessageBroadcast: Desktop Opened: %s", lpszDesktop);
  149. //---- enum windows on desktop ----
  150. TBOOL(EnumDesktopWindows(hDesk, TopWindowCallBack, lParam));
  151. CloseDesktop(hDesk);
  152. }
  153. return TRUE; // EnumDesktopWindows() returns unreliable errors
  154. }
  155. // --------------------------------------------------------------------------
  156. // CMessageBroadcast::TopWindowCallBack
  157. //
  158. // Arguments: hwnd, lParam
  159. //
  160. // Returns: TRUE (keep enumerating)
  161. //
  162. // Purpose: call "Worker" for hwnd and all of its (nested) children
  163. //
  164. // History: 2000-12-13 rfernand created
  165. // --------------------------------------------------------------------------
  166. BOOL CALLBACK CMessageBroadcast::TopWindowCallBack (HWND hwnd, LPARAM lParam)
  167. {
  168. //---- process top level window ----
  169. reinterpret_cast<CMessageBroadcast*>(lParam)->Worker(hwnd);
  170. //---- process all children windows ----
  171. TBOOL(EnumChildWindows(hwnd, ChildWindowCallBack, lParam));
  172. return TRUE;
  173. }
  174. // --------------------------------------------------------------------------
  175. // CMessageBroadcast::ChildWindowCallBack
  176. //
  177. // Arguments: hwnd, lParam
  178. //
  179. // Returns: TRUE (keep enumerating)
  180. //
  181. // Purpose: call "Worker" for hwnd
  182. //
  183. // History: 2000-12-13 rfernand created
  184. // --------------------------------------------------------------------------
  185. BOOL CALLBACK CMessageBroadcast::ChildWindowCallBack (HWND hwnd, LPARAM lParam)
  186. {
  187. //---- process top level window ----
  188. reinterpret_cast<CMessageBroadcast*>(lParam)->Worker(hwnd);
  189. return TRUE;
  190. }
  191. // --------------------------------------------------------------------------
  192. // CMessageBroadcast::Worker
  193. //
  194. // Arguments: <none>
  195. //
  196. // Returns: <none>
  197. //
  198. // Purpose: Performs validation on whether the HWND should get the built
  199. // message.
  200. //
  201. // History: 2000-11-09 vtan created
  202. // --------------------------------------------------------------------------
  203. void CMessageBroadcast::Worker (HWND hwnd)
  204. {
  205. if (_eMsgType == MT_SIMPLE)
  206. {
  207. TBOOL(PostMessage(hwnd, _msg.message, _msg.wParam, _msg.lParam));
  208. }
  209. else if (_eMsgType == MT_ALLTHREADS)
  210. {
  211. DWORD dwThreadId = GetWindowThreadProcessId(hwnd, NULL);
  212. BOOL fSendIt = TRUE;
  213. //---- is this a new thread? ----
  214. for (int i=0; i < _ThreadsProcessed.m_nSize; i++)
  215. {
  216. if (_ThreadsProcessed[i] == dwThreadId)
  217. {
  218. fSendIt = FALSE;
  219. break;
  220. }
  221. }
  222. if (fSendIt)
  223. {
  224. TBOOL(PostMessage(hwnd, _msg.message, _msg.wParam, _msg.lParam));
  225. _ThreadsProcessed.Add(dwThreadId);
  226. }
  227. }
  228. else // MT_FILTERED
  229. {
  230. bool fMatch;
  231. fMatch = true;
  232. if (_dwProcessID != 0)
  233. {
  234. fMatch = (IsWindowProcess(hwnd, _dwProcessID) != FALSE);
  235. if (_fExclude)
  236. {
  237. fMatch = !fMatch;
  238. }
  239. }
  240. if (fMatch)
  241. {
  242. if (_hwnd != NULL)
  243. {
  244. fMatch = ((_hwnd == hwnd) || IsChild(_hwnd, hwnd));
  245. if (_fExclude)
  246. {
  247. fMatch = !fMatch;
  248. }
  249. }
  250. if (fMatch)
  251. {
  252. TBOOL(PostMessage(hwnd, _msg.message, _msg.wParam, _msg.lParam));
  253. //Log(LOG_TMCHANGE, L"Worker: just POSTED msg=0x%x to hwnd=0x%x",
  254. // _msg.message, hwnd);
  255. }
  256. }
  257. }
  258. }
  259. // --------------------------------------------------------------------------