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.

375 lines
9.7 KiB

  1. /*
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. SMSDeadlock.cpp
  5. Abstract:
  6. SMS experiences a deadlock due to its loading a module that tries to take
  7. MFC42's AfxResourceLock during DllMain when the LoaderLock is held.
  8. MFC42's established locking-order is FIRST take the AfxResourceLock, and
  9. SECONDLY take the loader lock.
  10. This shim tries to right the order of lock-taking by taking the
  11. AfxResourceLock prior to allowing LoadLibrary and FreeLibrary calls.
  12. Thus the order of lock acquisition is righted.
  13. DLL's for which LoadLibrary takes the Afx lock are specified on the
  14. command line and separated by semi-colons. A blank command line indicates
  15. that ALL modules should take the lock.
  16. NOTE: Every module in a process (including system) should be shimmed by
  17. this shim. The dlls specified in the command line are the TARGETS of
  18. LoadLibrary for which we should take the AfxResource lock. To actually
  19. make that switch no matter who calls LoadLibrary, we must shim all
  20. modules.
  21. History:
  22. 09/26/2002 astritz Created
  23. */
  24. #include "precomp.h"
  25. IMPLEMENT_SHIM_BEGIN(SMSDeadlock)
  26. #include "ShimHookMacro.h"
  27. typedef void (AFXAPI * _pfn_AfxLockGlobals)(int nLockType);
  28. typedef void (AFXAPI * _pfn_AfxUnlockGlobals)(int nLockType);
  29. _pfn_AfxLockGlobals g_pfnAfxLockGlobals = NULL;
  30. _pfn_AfxUnlockGlobals g_pfnAfxUnlockGlobals = NULL;
  31. CString * g_csLockLib = NULL;
  32. int g_csLockLibCount = NULL;
  33. APIHOOK_ENUM_BEGIN
  34. APIHOOK_ENUM_ENTRY(LoadLibraryA)
  35. APIHOOK_ENUM_ENTRY(LoadLibraryExA)
  36. APIHOOK_ENUM_ENTRY(LoadLibraryW)
  37. APIHOOK_ENUM_ENTRY(LoadLibraryExW)
  38. APIHOOK_ENUM_ENTRY(FreeLibrary)
  39. APIHOOK_ENUM_END
  40. /*++
  41. This function parses the COMMAND_LINE for the libraries you wish to ignore.
  42. --*/
  43. BOOL
  44. ParseCommandLine(
  45. LPCSTR lpszCommandLine
  46. )
  47. {
  48. CSTRING_TRY
  49. {
  50. DPF(g_szModuleName, eDbgLevelInfo, "[ParseCommandLine] CommandLine(%s)\n", lpszCommandLine);
  51. CString csCl(lpszCommandLine);
  52. CStringParser csParser(csCl, L";");
  53. g_csLockLibCount = csParser.GetCount();
  54. g_csLockLib = csParser.ReleaseArgv();
  55. return TRUE;
  56. }
  57. CSTRING_CATCH
  58. {
  59. // Do nothing.
  60. }
  61. return FALSE;
  62. }
  63. HINSTANCE
  64. APIHOOK(LoadLibraryA)(
  65. LPCSTR lpLibFileName
  66. )
  67. {
  68. HINSTANCE hRet;
  69. BOOL bTakeLock = FALSE;
  70. if( g_pfnAfxLockGlobals && g_pfnAfxUnlockGlobals ) {
  71. if( g_csLockLibCount == 0 ) {
  72. bTakeLock = TRUE;
  73. } else {
  74. CSTRING_TRY
  75. {
  76. CString csFilePath(lpLibFileName);
  77. CString csFileName;
  78. csFilePath.GetLastPathComponent(csFileName);
  79. for (int i = 0; i < g_csLockLibCount; i++)
  80. {
  81. if (g_csLockLib[i].CompareNoCase(csFileName) == 0)
  82. {
  83. LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryA] Caught attempt loading %ls, taking AfxResourceLock.", g_csLockLib[i].Get());
  84. bTakeLock = TRUE;
  85. break;
  86. }
  87. }
  88. }
  89. CSTRING_CATCH
  90. {
  91. // Do Nothing
  92. }
  93. }
  94. }
  95. if( bTakeLock ) {
  96. (*g_pfnAfxLockGlobals)(0);
  97. }
  98. hRet = ORIGINAL_API(LoadLibraryA)(lpLibFileName);
  99. if( bTakeLock ) {
  100. (*g_pfnAfxUnlockGlobals)(0);
  101. }
  102. return hRet;
  103. }
  104. HINSTANCE
  105. APIHOOK(LoadLibraryW)(
  106. LPCWSTR lpLibFileName
  107. )
  108. {
  109. HINSTANCE hRet;
  110. BOOL bTakeLock = FALSE;
  111. if( g_pfnAfxLockGlobals && g_pfnAfxUnlockGlobals ) {
  112. if( g_csLockLibCount == 0 ) {
  113. bTakeLock = TRUE;
  114. } else {
  115. CSTRING_TRY
  116. {
  117. CString csFilePath(lpLibFileName);
  118. CString csFileName;
  119. csFilePath.GetLastPathComponent(csFileName);
  120. for (int i = 0; i < g_csLockLibCount; i++)
  121. {
  122. if (g_csLockLib[i].CompareNoCase(csFileName) == 0)
  123. {
  124. LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryW] Caught attempt loading %ls, taking AfxResourceLock.", g_csLockLib[i].Get());
  125. bTakeLock = TRUE;
  126. break;
  127. }
  128. }
  129. }
  130. CSTRING_CATCH
  131. {
  132. // Do Nothing
  133. }
  134. }
  135. }
  136. if( bTakeLock ) {
  137. (*g_pfnAfxLockGlobals)(0);
  138. }
  139. hRet = ORIGINAL_API(LoadLibraryW)(lpLibFileName);
  140. if( bTakeLock ) {
  141. (*g_pfnAfxUnlockGlobals)(0);
  142. }
  143. return hRet;
  144. }
  145. HINSTANCE
  146. APIHOOK(LoadLibraryExA)(
  147. LPCSTR lpLibFileName,
  148. HANDLE hFile,
  149. DWORD dwFlags
  150. )
  151. {
  152. HINSTANCE hRet;
  153. BOOL bTakeLock = FALSE;
  154. if( g_pfnAfxLockGlobals && g_pfnAfxUnlockGlobals ) {
  155. if( g_csLockLibCount == 0 ) {
  156. bTakeLock = TRUE;
  157. } else {
  158. CSTRING_TRY
  159. {
  160. CString csFilePath(lpLibFileName);
  161. CString csFileName;
  162. csFilePath.GetLastPathComponent(csFileName);
  163. for (int i = 0; i < g_csLockLibCount; i++)
  164. {
  165. if (g_csLockLib[i].CompareNoCase(csFileName) == 0)
  166. {
  167. LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryExA] Caught attempt loading %ls, taking AfxResourceLock.", g_csLockLib[i].Get());
  168. bTakeLock = TRUE;
  169. break;
  170. }
  171. }
  172. }
  173. CSTRING_CATCH
  174. {
  175. // Do Nothing
  176. }
  177. }
  178. }
  179. if( bTakeLock ) {
  180. (*g_pfnAfxLockGlobals)(0);
  181. }
  182. hRet = ORIGINAL_API(LoadLibraryExA)(lpLibFileName, hFile, dwFlags);
  183. if( bTakeLock ) {
  184. (*g_pfnAfxUnlockGlobals)(0);
  185. }
  186. return hRet;
  187. }
  188. HINSTANCE
  189. APIHOOK(LoadLibraryExW)(
  190. LPCWSTR lpLibFileName,
  191. HANDLE hFile,
  192. DWORD dwFlags
  193. )
  194. {
  195. HINSTANCE hRet;
  196. BOOL bTakeLock = FALSE;
  197. if( g_pfnAfxLockGlobals && g_pfnAfxUnlockGlobals ) {
  198. if( g_csLockLibCount == 0 ) {
  199. bTakeLock = TRUE;
  200. } else {
  201. CSTRING_TRY
  202. {
  203. CString csFilePath(lpLibFileName);
  204. CString csFileName;
  205. csFilePath.GetLastPathComponent(csFileName);
  206. for (int i = 0; i < g_csLockLibCount; i++)
  207. {
  208. if (g_csLockLib[i].CompareNoCase(csFileName) == 0)
  209. {
  210. LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryExW] Caught attempt loading %ls, taking AfxResourceLock.", g_csLockLib[i].Get());
  211. bTakeLock = TRUE;
  212. break;
  213. }
  214. }
  215. }
  216. CSTRING_CATCH
  217. {
  218. // Do Nothing
  219. }
  220. }
  221. }
  222. if( bTakeLock ) {
  223. (*g_pfnAfxLockGlobals)(0);
  224. }
  225. hRet = ORIGINAL_API(LoadLibraryExW)(lpLibFileName, hFile, dwFlags);
  226. if( bTakeLock ) {
  227. (*g_pfnAfxUnlockGlobals)(0);
  228. }
  229. return hRet;
  230. }
  231. BOOL
  232. APIHOOK(FreeLibrary)(
  233. HMODULE hModule
  234. )
  235. {
  236. BOOL bTakeLock = FALSE;
  237. BOOL bRet;
  238. if( g_pfnAfxLockGlobals && g_pfnAfxUnlockGlobals ) {
  239. if( g_csLockLibCount == 0 ) {
  240. bTakeLock = TRUE;
  241. } else {
  242. WCHAR wszModule[MAX_PATH];
  243. if( GetModuleFileNameW(hModule, wszModule, MAX_PATH) ) {
  244. CSTRING_TRY
  245. {
  246. CString csFilePath(wszModule);
  247. CString csFileName;
  248. csFilePath.GetLastPathComponent(csFileName);
  249. for (int i = 0; i < g_csLockLibCount; i++)
  250. {
  251. if (g_csLockLib[i].CompareNoCase(csFileName) == 0)
  252. {
  253. LOG(g_szModuleName,eDbgLevelError, "[FreeLibrary] Caught attempt freeing %ls, taking AfxResourceLock.", g_csLockLib[i].Get());
  254. bTakeLock = TRUE;
  255. break;
  256. }
  257. }
  258. }
  259. CSTRING_CATCH
  260. {
  261. // Do Nothing
  262. }
  263. }
  264. }
  265. }
  266. if( bTakeLock ) {
  267. (*g_pfnAfxLockGlobals)(0);
  268. }
  269. bRet = ORIGINAL_API(FreeLibrary)(hModule);
  270. if( bTakeLock ) {
  271. (*g_pfnAfxUnlockGlobals)(0);
  272. }
  273. return bRet;
  274. }
  275. /*++
  276. Register hooked functions
  277. --*/
  278. BOOL
  279. NOTIFY_FUNCTION(
  280. DWORD fdwReason
  281. )
  282. {
  283. if( fdwReason == DLL_PROCESS_ATTACH )
  284. {
  285. ParseCommandLine(COMMAND_LINE);
  286. }
  287. else if( fdwReason == SHIM_STATIC_DLLS_INITIALIZED )
  288. {
  289. HMODULE hMod = LoadLibraryW(L"MFC42.DLL");
  290. if( NULL != hMod )
  291. {
  292. g_pfnAfxLockGlobals = (_pfn_AfxLockGlobals)GetProcAddress(hMod, (LPCSTR)1196);
  293. g_pfnAfxUnlockGlobals = (_pfn_AfxUnlockGlobals)GetProcAddress(hMod, (LPCSTR)1569);
  294. }
  295. }
  296. return TRUE;
  297. }
  298. HOOK_BEGIN
  299. CALL_NOTIFY_FUNCTION
  300. APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryA)
  301. APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryExA)
  302. APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryW)
  303. APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryExW)
  304. APIHOOK_ENTRY(KERNEL32.DLL, FreeLibrary)
  305. HOOK_END
  306. IMPLEMENT_SHIM_END