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.

254 lines
4.4 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. IgnoreHungAppPaint.cpp
  5. Abstract:
  6. Setup the hollow brush to prevent user from trashing peoples windows.
  7. Notes:
  8. This is a general purpose shim.
  9. History:
  10. 12/04/2000 linstev Created
  11. --*/
  12. #include "precomp.h"
  13. #include "LegalStr.h"
  14. IMPLEMENT_SHIM_BEGIN(IgnoreHungAppPaint)
  15. #include "ShimHookMacro.h"
  16. APIHOOK_ENUM_BEGIN
  17. APIHOOK_ENUM_ENTRY(RegisterClassA)
  18. APIHOOK_ENUM_ENTRY(RegisterClassW)
  19. APIHOOK_ENUM_ENTRY(RegisterClassExA)
  20. APIHOOK_ENUM_ENTRY(RegisterClassExW)
  21. APIHOOK_ENUM_END
  22. struct HUNGCLASS
  23. {
  24. char szClass[MAX_PATH];
  25. HUNGCLASS *next;
  26. };
  27. HUNGCLASS *g_lHungList = NULL;
  28. BOOL g_bAll = FALSE;
  29. /*++
  30. Check if a class needs a hollow brush.
  31. --*/
  32. BOOL
  33. IsHungClassA(LPCSTR szClass)
  34. {
  35. BOOL bRet = FALSE;
  36. if (szClass)
  37. {
  38. HUNGCLASS *h = g_lHungList;
  39. while (h)
  40. {
  41. if (_stricmp(szClass, h->szClass) == 0)
  42. {
  43. LOGN(eDbgLevelWarning, "Matched hung class: forcing HOLLOW_BRUSH");
  44. bRet = TRUE;
  45. break;
  46. }
  47. h = h->next;
  48. }
  49. }
  50. return bRet;
  51. }
  52. /*++
  53. Check if a class needs a hollow brush.
  54. --*/
  55. BOOL
  56. IsHungClassW(LPCWSTR wszClass)
  57. {
  58. CHAR szClass[MAX_PATH];
  59. WideCharToMultiByte(
  60. CP_ACP,
  61. 0,
  62. (LPWSTR) wszClass,
  63. MAX_PATH,
  64. (LPSTR) szClass,
  65. MAX_PATH,
  66. 0,
  67. 0);
  68. return IsHungClassA(szClass);
  69. }
  70. /*++
  71. Hook all possible calls that can initialize or change a window's
  72. WindowProc (or DialogProc)
  73. --*/
  74. ATOM
  75. APIHOOK(RegisterClassA)(
  76. WNDCLASSA *lpWndClass
  77. )
  78. {
  79. if (lpWndClass && (g_bAll || IsHungClassA(lpWndClass->lpszClassName)))
  80. {
  81. lpWndClass->hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
  82. }
  83. return ORIGINAL_API(RegisterClassA)(lpWndClass);
  84. }
  85. ATOM
  86. APIHOOK(RegisterClassW)(
  87. WNDCLASSW *lpWndClass
  88. )
  89. {
  90. if (lpWndClass && IsHungClassW(lpWndClass->lpszClassName))
  91. {
  92. lpWndClass->hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
  93. }
  94. return ORIGINAL_API(RegisterClassW)(lpWndClass);
  95. }
  96. ATOM
  97. APIHOOK(RegisterClassExA)(
  98. WNDCLASSEXA *lpWndClass
  99. )
  100. {
  101. if (lpWndClass && IsHungClassA(lpWndClass->lpszClassName))
  102. {
  103. lpWndClass->hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
  104. }
  105. return ORIGINAL_API(RegisterClassExA)(lpWndClass);
  106. }
  107. ATOM
  108. APIHOOK(RegisterClassExW)(
  109. WNDCLASSEXW *lpWndClass
  110. )
  111. {
  112. if (lpWndClass && IsHungClassW(lpWndClass->lpszClassName))
  113. {
  114. lpWndClass->hbrBackground = (HBRUSH) GetStockObject(HOLLOW_BRUSH);
  115. }
  116. return ORIGINAL_API(RegisterClassExW)(lpWndClass);
  117. }
  118. /*++
  119. Parse the command line for fixes:
  120. CLASS1; CLASS2; CLASS3 ...
  121. --*/
  122. VOID
  123. ParseCommandLineA(
  124. LPCSTR lpCommandLine
  125. )
  126. {
  127. // Add all the defaults if no command line is specified
  128. if (!lpCommandLine || (lpCommandLine[0] == '\0'))
  129. {
  130. g_bAll = TRUE;
  131. DPFN(eDbgLevelInfo, "All classes will use HOLLOW_BRUSH");
  132. return;
  133. }
  134. char seps[] = " ,\t;";
  135. char *token = NULL;
  136. // Since strtok modifies the string, we need to copy it
  137. LPSTR szCommandLine = (LPSTR) malloc(strlen(lpCommandLine) + 1);
  138. if (!szCommandLine) goto Exit;
  139. strcpy(szCommandLine, lpCommandLine);
  140. //
  141. // Run the string, looking for fix names
  142. //
  143. token = _strtok(szCommandLine, seps);
  144. while (token)
  145. {
  146. HUNGCLASS *h;
  147. h = (HUNGCLASS *) malloc(sizeof(HUNGCLASS));
  148. if (h)
  149. {
  150. h->next = g_lHungList;
  151. g_lHungList = h;
  152. strncpy(h->szClass, token, MAX_PATH);
  153. DPFN(eDbgLevelInfo, "Adding %s", token);
  154. }
  155. else
  156. {
  157. DPFN(eDbgLevelError, "Out of memory");
  158. }
  159. // Get the next token
  160. token = _strtok(NULL, seps);
  161. }
  162. Exit:
  163. if (szCommandLine)
  164. {
  165. free(szCommandLine);
  166. }
  167. }
  168. /*++
  169. Register hooked functions
  170. --*/
  171. BOOL
  172. NOTIFY_FUNCTION(
  173. DWORD fdwReason
  174. )
  175. {
  176. if (fdwReason == DLL_PROCESS_ATTACH) {
  177. ParseCommandLineA(COMMAND_LINE);
  178. }
  179. return TRUE;
  180. }
  181. HOOK_BEGIN
  182. CALL_NOTIFY_FUNCTION
  183. APIHOOK_ENTRY(USER32.DLL, RegisterClassA)
  184. APIHOOK_ENTRY(USER32.DLL, RegisterClassW);
  185. APIHOOK_ENTRY(USER32.DLL, RegisterClassExA);
  186. APIHOOK_ENTRY(USER32.DLL, RegisterClassExW);
  187. HOOK_END
  188. IMPLEMENT_SHIM_END