Leaked source code of windows server 2003
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.

333 lines
7.1 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. ClueFinders3rdGrade.cpp
  5. Abstract:
  6. This shim simulates the behaviour of Win9x wrt static controls and
  7. Get/SetWindowText. Basically, Win9x stored the resource id for a static
  8. control in it's name. On NT, this isn't stored.
  9. We used to set a low-level window hook that catches the CreateWindow calls,
  10. but gave up because it kept regressing and it would be too expensive for
  11. the layer.
  12. Notes:
  13. This is an app specific shim.
  14. History:
  15. 06/19/2000 linstev Created
  16. 11/17/2000 linstev Made app specific
  17. --*/
  18. #include "precomp.h"
  19. IMPLEMENT_SHIM_BEGIN(ClueFinders3rdGrade)
  20. #include "ShimHookMacro.h"
  21. APIHOOK_ENUM_BEGIN
  22. APIHOOK_ENUM_ENTRY(GetWindowTextA)
  23. APIHOOK_ENUM_ENTRY(SetWindowTextA)
  24. APIHOOK_ENUM_ENTRY(CreateDialogIndirectParamA)
  25. APIHOOK_ENUM_END
  26. typedef HMODULE (*_pfn_GetModuleHandleA)(LPCSTR lpModuleName);
  27. //
  28. // List of static handles
  29. //
  30. struct HWNDITEM
  31. {
  32. HWND hWnd;
  33. DWORD dwRsrcId;
  34. HWNDITEM *next;
  35. };
  36. HWNDITEM *g_hWndList = NULL;
  37. //
  38. // Handle to use for CallNextHook
  39. //
  40. HHOOK g_hHookCbt = 0;
  41. //
  42. // Critical section for list access
  43. //
  44. CRITICAL_SECTION g_csList;
  45. /*++
  46. Search the window list for a resource id if GetWindowTextA fails.
  47. --*/
  48. int
  49. APIHOOK(GetWindowTextA)(
  50. HWND hWnd,
  51. LPSTR lpString,
  52. int nMaxCount
  53. )
  54. {
  55. int iRet = ORIGINAL_API(GetWindowTextA)(
  56. hWnd,
  57. lpString,
  58. nMaxCount);
  59. if (iRet == 0) {
  60. //
  61. // Check for Resource Id
  62. //
  63. EnterCriticalSection(&g_csList);
  64. HWNDITEM *hitem = g_hWndList;
  65. while (hitem) {
  66. if (hitem->hWnd == hWnd) {
  67. //
  68. // Copy the resource id into the buffer
  69. //
  70. if ((hitem->dwRsrcId != (DWORD)-1) && (nMaxCount >= 3)) {
  71. MoveMemory(lpString, (LPBYTE) &hitem->dwRsrcId + 1, 3);
  72. iRet = 2;
  73. DPFN( eDbgLevelError, "Returning ResourceId: %08lx for HWND=%08lx", *(LPDWORD)lpString, hWnd);
  74. }
  75. break;
  76. }
  77. hitem = hitem->next;
  78. }
  79. LeaveCriticalSection(&g_csList);
  80. }
  81. return iRet;
  82. }
  83. /*++
  84. Hook SetWindowText so the list is kept in sync.
  85. --*/
  86. BOOL
  87. APIHOOK(SetWindowTextA)(
  88. HWND hWnd,
  89. LPCSTR lpString
  90. )
  91. {
  92. //
  93. // Set the text for this window if it's in our list
  94. //
  95. EnterCriticalSection(&g_csList);
  96. HWNDITEM *hitem = g_hWndList;
  97. while (hitem) {
  98. if (hitem->hWnd == hWnd) {
  99. if (lpString && (*(LPBYTE) lpString == 0xFF)) {
  100. hitem->dwRsrcId = *(LPDWORD) lpString;
  101. }
  102. break;
  103. }
  104. hitem = hitem->next;
  105. }
  106. LeaveCriticalSection(&g_csList);
  107. return ORIGINAL_API(SetWindowTextA)(hWnd, lpString);
  108. }
  109. /*++
  110. Hook to find CreateWindow calls and get the attached resource id.
  111. --*/
  112. LRESULT
  113. CALLBACK
  114. CBTProcW(
  115. int nCode,
  116. WPARAM wParam,
  117. LPARAM lParam
  118. )
  119. {
  120. HWND hWnd = (HWND) wParam;
  121. LPCBT_CREATEWNDW pCbtWnd;
  122. switch (nCode) {
  123. case HCBT_CREATEWND:
  124. //
  125. // Add to our list of windows if it's a static - or we don't know
  126. //
  127. pCbtWnd = (LPCBT_CREATEWNDW) lParam;
  128. if (pCbtWnd && pCbtWnd->lpcs && pCbtWnd->lpcs->lpszClass &&
  129. (IsBadReadPtr(pCbtWnd->lpcs->lpszClass, 4) ||
  130. (_wcsicmp(pCbtWnd->lpcs->lpszClass, L"static") == 0))) {
  131. HWNDITEM *hitem = (HWNDITEM *) malloc(sizeof(HWNDITEM));
  132. if (hitem) {
  133. hitem->hWnd = hWnd;
  134. //
  135. // Check for a resource id in the name
  136. //
  137. if (pCbtWnd->lpcs->lpszName &&
  138. (*(LPBYTE) pCbtWnd->lpcs->lpszName == 0xFF)) {
  139. hitem->dwRsrcId = *(LPDWORD) pCbtWnd->lpcs->lpszName;
  140. } else {
  141. hitem->dwRsrcId = (DWORD)-1;
  142. }
  143. //
  144. // Update our list
  145. //
  146. EnterCriticalSection(&g_csList);
  147. hitem->next = g_hWndList;
  148. g_hWndList = hitem;
  149. LeaveCriticalSection(&g_csList);
  150. DPFN( eDbgLevelError, "CreateWindow HWND=%08lx, ResourceId=%08lx", hitem->hWnd, hitem->dwRsrcId);
  151. } else {
  152. DPFN( eDbgLevelError, "Failed to allocate list item");
  153. }
  154. }
  155. break;
  156. case HCBT_DESTROYWND:
  157. //
  158. // Remove the window from our list
  159. //
  160. EnterCriticalSection(&g_csList);
  161. HWNDITEM *hitem = g_hWndList, *hprev = NULL;
  162. while (hitem) {
  163. if (hitem->hWnd == hWnd) {
  164. if (hprev) {
  165. hprev->next = hitem->next;
  166. } else {
  167. g_hWndList = hitem->next;
  168. }
  169. free(hitem);
  170. DPFN( eDbgLevelError, "DestroyWindow %08lx", hWnd);
  171. break;
  172. }
  173. hprev = hitem;
  174. hitem = hitem->next;
  175. }
  176. LeaveCriticalSection(&g_csList);
  177. break;
  178. }
  179. return CallNextHookEx(g_hHookCbt, nCode, wParam, lParam);
  180. }
  181. /*++
  182. Hook CreateDialog which is where the problem occurs
  183. --*/
  184. HWND
  185. APIHOOK(CreateDialogIndirectParamA)(
  186. HINSTANCE hInstance,
  187. LPCDLGTEMPLATE lpTemplate,
  188. HWND hWndParent,
  189. DLGPROC lpDialogFunc,
  190. LPARAM lParamInit
  191. )
  192. {
  193. if (!g_hHookCbt) {
  194. g_hHookCbt = SetWindowsHookExW(WH_CBT, CBTProcW, GetModuleHandleW(0), 0);
  195. DPFN( eDbgLevelInfo, "[CreateDialogIndirectParamA] Hook added");
  196. }
  197. HWND hRet = ORIGINAL_API(CreateDialogIndirectParamA)(
  198. hInstance,
  199. lpTemplate,
  200. hWndParent,
  201. lpDialogFunc,
  202. lParamInit);
  203. if (g_hHookCbt) {
  204. UnhookWindowsHookEx(g_hHookCbt);
  205. g_hHookCbt = 0;
  206. }
  207. return hRet;
  208. }
  209. /*++
  210. Register hooked functions
  211. --*/
  212. BOOL
  213. NOTIFY_FUNCTION(
  214. DWORD fdwReason)
  215. {
  216. if (fdwReason == DLL_PROCESS_ATTACH) {
  217. //
  218. // Initialize our critical section here
  219. //
  220. if (!InitializeCriticalSectionAndSpinCount(&g_csList, 0x80000000))
  221. {
  222. return FALSE;
  223. }
  224. } else if (fdwReason == DLL_PROCESS_DETACH) {
  225. //
  226. // Clear the hook
  227. //
  228. if (g_hHookCbt) {
  229. UnhookWindowsHookEx(g_hHookCbt);
  230. }
  231. }
  232. return TRUE;
  233. }
  234. HOOK_BEGIN
  235. CALL_NOTIFY_FUNCTION
  236. APIHOOK_ENTRY(USER32.DLL, GetWindowTextA)
  237. APIHOOK_ENTRY(USER32.DLL, SetWindowTextA)
  238. APIHOOK_ENTRY(USER32.DLL, CreateDialogIndirectParamA)
  239. HOOK_END
  240. IMPLEMENT_SHIM_END