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.

344 lines
9.2 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. IgnoreMessageBox.cpp
  5. Abstract:
  6. This APIHooks MessageBox and based on the passed in command line prevents the
  7. message box from being displayed. Many applications display a message box with
  8. some debugging or other extraneous comment. This is normally the result of
  9. differences between Windows 98 and Whistler.
  10. command line syntax:
  11. text,caption;text1,caption1
  12. The passed in command line is composed of a pair of one or more strings separated
  13. by semicolons. These string pairs form the text and caption that must match in order
  14. to block the display of the message box. If either the caption or text are not needed
  15. then they can be left blank. For example, "block this text,;" would prevent the message
  16. box from being displayed if the text passed to the message box was: block this text" the
  17. caption parameter would not be used. The following are some examples:
  18. "error message 1000,Error" - would not display the message box if the
  19. lpCaption parameter contained Error and
  20. the lpText parameter contained error
  21. message 1000
  22. "error message 1000," - would not display the message box if the
  23. lpText parameter contained error message 1000
  24. ",Error" - would not display any message boxes if the
  25. lpCaption parameter contained Error
  26. "message1,Error;message2,Error2 - would not display the message box if the
  27. lpText parameter contained message1 and
  28. the lpCaption parameter contained Error or
  29. the lpText parameter contained message2 and
  30. the lpCaption paramter contained Error2.
  31. The match is performed on the command line string to the current message box
  32. parameter string. The command line string can contain wildcard specification
  33. characters. This allows complex out of order matching to take place see below:
  34. ? match one character in this position
  35. * match zero or more characters in this position
  36. If the source string contains any ? * , ; \ characters, precede them with a backslash.
  37. For example, the following command line would match the indicated text and caption:
  38. Text: "Compatibility; A *very* important thing."
  39. Caption: "D:\WORD\COMPAT.DOC"
  40. Command line: "Compatibility\; A \*very\* important thing.,D:\\WORD\\COMPAT.DOC"
  41. Notes:
  42. History:
  43. 04/06/2000 philipdu Created
  44. 04/06/2000 markder Added wide-character conversion, plus Ex versions.
  45. 05/23/2001 mnikkel Added W routines so we can pick up system messagebox calls
  46. --*/
  47. #include "precomp.h"
  48. #include "CharVector.h"
  49. IMPLEMENT_SHIM_BEGIN(IgnoreMessageBox)
  50. #include "ShimHookMacro.h"
  51. APIHOOK_ENUM_BEGIN
  52. APIHOOK_ENUM_ENTRY(MessageBoxA)
  53. APIHOOK_ENUM_ENTRY(MessageBoxExA)
  54. APIHOOK_ENUM_ENTRY(MessageBoxW)
  55. APIHOOK_ENUM_ENTRY(MessageBoxExW)
  56. APIHOOK_ENUM_END
  57. class MBPair
  58. {
  59. public:
  60. CString csText;
  61. CString csCaption;
  62. };
  63. VectorT<MBPair> * g_IgnoreList = NULL;
  64. BOOL IsBlockMessage(LPCSTR szOrigText, LPCSTR szOrigCaption)
  65. {
  66. CSTRING_TRY
  67. {
  68. CString csText(szOrigText);
  69. CString csCaption(szOrigCaption);
  70. for (int i = 0; i < g_IgnoreList->Size(); ++i)
  71. {
  72. const MBPair & mbPair = g_IgnoreList->Get(i);
  73. BOOL bTextMatch = mbPair.csText.IsEmpty() || csText.PatternMatch(mbPair.csText);
  74. BOOL bTitleMatch = mbPair.csCaption.IsEmpty() || csCaption.PatternMatch(mbPair.csCaption);
  75. if (bTextMatch && bTitleMatch)
  76. {
  77. return TRUE;
  78. }
  79. }
  80. }
  81. CSTRING_CATCH
  82. {
  83. // Do Nothing
  84. }
  85. return FALSE;
  86. }
  87. BOOL IsBlockMessageW(LPWSTR szOrigText, LPWSTR szOrigCaption)
  88. {
  89. CSTRING_TRY
  90. {
  91. CString csText(szOrigText);
  92. CString csCaption(szOrigCaption);
  93. for (int i = 0; i < g_IgnoreList->Size(); ++i)
  94. {
  95. const MBPair & mbPair = g_IgnoreList->Get(i);
  96. BOOL bTextMatch = mbPair.csText.IsEmpty() || csText.PatternMatch(mbPair.csText);
  97. BOOL bTitleMatch = mbPair.csCaption.IsEmpty() || csCaption.PatternMatch(mbPair.csCaption);
  98. if (bTextMatch && bTitleMatch)
  99. {
  100. return TRUE;
  101. }
  102. }
  103. }
  104. CSTRING_CATCH
  105. {
  106. // Do Nothing
  107. }
  108. return FALSE;
  109. }
  110. int
  111. APIHOOK(MessageBoxA)(
  112. HWND hWnd, // handle to owner window
  113. LPCSTR lpText, // text in message box
  114. LPCSTR lpCaption, // message box title
  115. UINT uType // message box style
  116. )
  117. {
  118. int iReturnValue;
  119. //if this is the passed in string that we want do not
  120. //want to display then simply return to caller.
  121. if (IsBlockMessage(lpText, lpCaption))
  122. {
  123. DPFN( eDbgLevelInfo, "[IgnoreMessageBox] MessageBoxA swallowed:\n");
  124. DPFN( eDbgLevelInfo, "[IgnoreMessageBox] Caption = \"%s\"\n", lpCaption);
  125. DPFN( eDbgLevelInfo, "[IgnoreMessageBox] Text = \"%s\"\n", lpText);
  126. return MB_OK;
  127. }
  128. iReturnValue = ORIGINAL_API(MessageBoxA)(
  129. hWnd,
  130. lpText,
  131. lpCaption,
  132. uType);
  133. return iReturnValue;
  134. }
  135. int
  136. APIHOOK(MessageBoxExA)(
  137. HWND hWnd, // handle to owner window
  138. LPCSTR lpText, // text in message box
  139. LPCSTR lpCaption, // message box title
  140. UINT uType, // message box style
  141. WORD wLanguageId // language identifier
  142. )
  143. {
  144. int iReturnValue;
  145. //if this is the passed in string that we want do not
  146. //want to display then simply return to caller.
  147. if (IsBlockMessage(lpText, lpCaption))
  148. {
  149. DPFN( eDbgLevelInfo, "[IgnoreMessageBox] MessageBoxExA swallowed:\n");
  150. DPFN( eDbgLevelInfo, "[IgnoreMessageBox] Caption = \"%s\"\n", lpCaption);
  151. DPFN( eDbgLevelInfo, "[IgnoreMessageBox] Text = \"%s\"\n", lpText);
  152. return MB_OK;
  153. }
  154. iReturnValue = ORIGINAL_API(MessageBoxExA)(
  155. hWnd,
  156. lpText,
  157. lpCaption,
  158. uType,
  159. wLanguageId);
  160. return iReturnValue;
  161. }
  162. int
  163. APIHOOK(MessageBoxW)(
  164. HWND hWnd, // handle to owner window
  165. LPWSTR lpText, // text in message box
  166. LPWSTR lpCaption, // message box title
  167. UINT uType // message box style
  168. )
  169. {
  170. int iReturnValue;
  171. //if this is the passed in string that we want do not
  172. //want to display then simply return to caller.
  173. if (IsBlockMessageW(lpText, lpCaption))
  174. {
  175. DPFN( eDbgLevelInfo, "[IgnoreMessageBox] MessageBoxW swallowed:\n");
  176. DPFN( eDbgLevelInfo, "[IgnoreMessageBox] Caption = \"%S\"\n", lpCaption);
  177. DPFN( eDbgLevelInfo, "[IgnoreMessageBox] Text = \"%S\"\n", lpText);
  178. return MB_OK;
  179. }
  180. iReturnValue = ORIGINAL_API(MessageBoxW)(
  181. hWnd,
  182. lpText,
  183. lpCaption,
  184. uType);
  185. return iReturnValue;
  186. }
  187. int
  188. APIHOOK(MessageBoxExW)(
  189. HWND hWnd, // handle to owner window
  190. LPWSTR lpText, // text in message box
  191. LPWSTR lpCaption, // message box title
  192. UINT uType, // message box style
  193. WORD wLanguageId // language identifier
  194. )
  195. {
  196. int iReturnValue;
  197. //if this is the passed in string that we want do not
  198. //want to display then simply return to caller.
  199. if (IsBlockMessageW(lpText, lpCaption))
  200. {
  201. DPFN( eDbgLevelInfo, "[IgnoreMessageBox] MessageBoxExW swallowed:\n");
  202. DPFN( eDbgLevelInfo, "[IgnoreMessageBox] Caption = \"%S\"\n", lpCaption);
  203. DPFN( eDbgLevelInfo, "[IgnoreMessageBox] Text = \"%S\"\n", lpText);
  204. return MB_OK;
  205. }
  206. iReturnValue = ORIGINAL_API(MessageBoxExW)(
  207. hWnd,
  208. lpText,
  209. lpCaption,
  210. uType,
  211. wLanguageId);
  212. return iReturnValue;
  213. }
  214. BOOL
  215. ParseCommandLine(const char * cl)
  216. {
  217. CSTRING_TRY
  218. {
  219. CStringToken csCommandLine(COMMAND_LINE, ";");
  220. CString csTok;
  221. g_IgnoreList = new VectorT<MBPair>;
  222. if (!g_IgnoreList)
  223. {
  224. return FALSE;
  225. }
  226. while (csCommandLine.GetToken(csTok))
  227. {
  228. MBPair mbPair;
  229. CStringToken csMB(csTok, ",");
  230. csMB.GetToken(mbPair.csText);
  231. csMB.GetToken(mbPair.csCaption);
  232. if (!g_IgnoreList->AppendConstruct(mbPair))
  233. {
  234. return FALSE;
  235. }
  236. }
  237. }
  238. CSTRING_CATCH
  239. {
  240. // Fall through
  241. LOGN(eDbgLevelError, "[ParseCommandLine] Illegal command line");
  242. }
  243. return g_IgnoreList && g_IgnoreList->Size() > 0;
  244. }
  245. BOOL
  246. NOTIFY_FUNCTION(
  247. DWORD fdwReason
  248. )
  249. {
  250. if (fdwReason == DLL_PROCESS_ATTACH)
  251. {
  252. return ParseCommandLine(COMMAND_LINE);
  253. }
  254. return TRUE;
  255. }
  256. /*++
  257. Register hooked functions
  258. --*/
  259. HOOK_BEGIN
  260. CALL_NOTIFY_FUNCTION
  261. APIHOOK_ENTRY(USER32.DLL, MessageBoxA)
  262. APIHOOK_ENTRY(USER32.DLL, MessageBoxExA)
  263. APIHOOK_ENTRY(USER32.DLL, MessageBoxW)
  264. APIHOOK_ENTRY(USER32.DLL, MessageBoxExW)
  265. HOOK_END
  266. IMPLEMENT_SHIM_END