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.

292 lines
7.4 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. IgnoreLoadLibrary.cpp
  5. Abstract:
  6. This shim allows the user to specified a list of libraries it tries to ignore and
  7. optionally the return values of the LoadLibrary call. Some apps try to load libraries
  8. they don't use but expect the LoadLibrary call to succeed.
  9. Use ; as the delimeter of the item and optionally use : to specify the return value.
  10. If you don't specify a return value we'll make the return value NULL.
  11. Eg:
  12. video_3dfx.dll;video_3dfx
  13. helper32.dll:1234;helper.dll
  14. Notes:
  15. This is a general purpose shim.
  16. History:
  17. 04/13/2000 a-jamd Created
  18. 10/11/2000 maonis Added support for specifying return values and renamed it from
  19. FailLoadLibrary to IgnoreLoadLibrary.
  20. 11/16/2000 linstev Added SetErrorMode emulation
  21. --*/
  22. #include "precomp.h"
  23. IMPLEMENT_SHIM_BEGIN(IgnoreLoadLibrary)
  24. #include "ShimHookMacro.h"
  25. // Globals are zero initialized by default. see c++ spec 3.6.2.
  26. CString * g_csIgnoreLib;
  27. int g_csIgnoreLibCount;
  28. DWORD * g_rgReturnValues;
  29. APIHOOK_ENUM_BEGIN
  30. APIHOOK_ENUM_ENTRY(LoadLibraryA)
  31. APIHOOK_ENUM_ENTRY(LoadLibraryExA)
  32. APIHOOK_ENUM_ENTRY(LoadLibraryW)
  33. APIHOOK_ENUM_ENTRY(LoadLibraryExW)
  34. APIHOOK_ENUM_END
  35. /*++
  36. This function parses the COMMAND_LINE for the libraries you wish to ignore.
  37. --*/
  38. BOOL ParseCommandLine(LPCSTR lpszCommandLine)
  39. {
  40. CSTRING_TRY
  41. {
  42. DPF(g_szModuleName, eDbgLevelInfo, "[ParseCommandLine] CommandLine(%s)\n", lpszCommandLine);
  43. CString csCl(lpszCommandLine);
  44. CStringParser csParser(csCl, L" ;");
  45. g_csIgnoreLibCount = csParser.GetCount();
  46. g_csIgnoreLib = csParser.ReleaseArgv();
  47. g_rgReturnValues = (DWORD *)malloc(sizeof(*g_rgReturnValues) * g_csIgnoreLibCount);
  48. if (g_csIgnoreLibCount && !g_rgReturnValues)
  49. {
  50. return FALSE;
  51. }
  52. // Iterate over all strings looking for a return value
  53. for (int i = 0; i < g_csIgnoreLibCount; ++i)
  54. {
  55. CStringToken csIgnore(g_csIgnoreLib[i], L":");
  56. CString csLib;
  57. CString csValue;
  58. csIgnore.GetToken(csLib);
  59. csIgnore.GetToken(csValue);
  60. if (!csValue.IsEmpty())
  61. {
  62. WCHAR *unused;
  63. g_csIgnoreLib[i] = csLib;
  64. g_rgReturnValues[i] = wcstol(csValue, &unused, 10);
  65. }
  66. DPF(g_szModuleName, eDbgLevelInfo, "[ParseCommandLine] library (%S) return value(%d)\n", g_csIgnoreLib[i].Get(), g_rgReturnValues[i]);
  67. }
  68. return TRUE;
  69. }
  70. CSTRING_CATCH
  71. {
  72. // Do nothing.
  73. }
  74. return FALSE;
  75. }
  76. /*++
  77. These stub functions break into LoadLibrary and check to see if lpLibFileName equals
  78. one of the specified dll's. If so return the specified return value. If not call LoadLibrary on it.
  79. --*/
  80. HINSTANCE
  81. APIHOOK(LoadLibraryA)(LPCSTR lpLibFileName)
  82. {
  83. CSTRING_TRY
  84. {
  85. CString csFilePath(lpLibFileName);
  86. CString csFileName;
  87. csFilePath.GetLastPathComponent(csFileName);
  88. for (int i = 0; i < g_csIgnoreLibCount; i++)
  89. {
  90. if (g_csIgnoreLib[i].CompareNoCase(csFileName) == 0)
  91. {
  92. LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryA] Caught attempt loading %s, return %d\n", g_csIgnoreLib[i].Get(), g_rgReturnValues[i]);
  93. return (HINSTANCE) g_rgReturnValues[i];
  94. }
  95. }
  96. }
  97. CSTRING_CATCH
  98. {
  99. // Do Nothing
  100. }
  101. DPF(g_szModuleName, eDbgLevelSpew, "LoadLibraryA Allow(%s)", lpLibFileName);
  102. UINT uLastMode;
  103. HINSTANCE hRet;
  104. uLastMode = SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  105. hRet = ORIGINAL_API(LoadLibraryA)(lpLibFileName);
  106. SetErrorMode(uLastMode);
  107. return hRet;
  108. }
  109. HINSTANCE
  110. APIHOOK(LoadLibraryExA)(
  111. LPCSTR lpLibFileName,
  112. HANDLE hFile,
  113. DWORD dwFlags
  114. )
  115. {
  116. CSTRING_TRY
  117. {
  118. CString csFilePath(lpLibFileName);
  119. CString csFileName;
  120. csFilePath.GetLastPathComponent(csFileName);
  121. for (int i = 0; i < g_csIgnoreLibCount; i++)
  122. {
  123. if (g_csIgnoreLib[i].CompareNoCase(csFileName) == 0)
  124. {
  125. LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryExA] Caught attempt loading %s, return %d\n", g_csIgnoreLib[i].Get(), g_rgReturnValues[i]);
  126. return (HINSTANCE) g_rgReturnValues[i];
  127. }
  128. }
  129. }
  130. CSTRING_CATCH
  131. {
  132. // Do Nothing
  133. }
  134. DPF(g_szModuleName, eDbgLevelSpew, "LoadLibraryExA Allow(%s)", lpLibFileName);
  135. UINT uLastMode;
  136. HINSTANCE hRet;
  137. uLastMode = SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  138. hRet = ORIGINAL_API(LoadLibraryExA)(lpLibFileName, hFile, dwFlags);
  139. SetErrorMode(uLastMode);
  140. return hRet;
  141. }
  142. HINSTANCE
  143. APIHOOK(LoadLibraryW)(LPCWSTR lpLibFileName)
  144. {
  145. CSTRING_TRY
  146. {
  147. CString csFilePath(lpLibFileName);
  148. CString csFileName;
  149. csFilePath.GetLastPathComponent(csFileName);
  150. for (int i = 0; i < g_csIgnoreLibCount; i++)
  151. {
  152. if (g_csIgnoreLib[i].CompareNoCase(csFileName) == 0)
  153. {
  154. LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryW] Caught attempt loading %s, return %d\n", g_csIgnoreLib[i].Get(), g_rgReturnValues[i]);
  155. return (HINSTANCE) g_rgReturnValues[i];
  156. }
  157. }
  158. }
  159. CSTRING_CATCH
  160. {
  161. // Do Nothing
  162. }
  163. DPF(g_szModuleName, eDbgLevelSpew,"LoadLibraryW Allow(%S)", lpLibFileName);
  164. UINT uLastMode;
  165. HINSTANCE hRet;
  166. uLastMode = SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  167. hRet = ORIGINAL_API(LoadLibraryW)(lpLibFileName);
  168. SetErrorMode(uLastMode);
  169. return hRet;
  170. }
  171. HINSTANCE
  172. APIHOOK(LoadLibraryExW)(
  173. LPCWSTR lpLibFileName,
  174. HANDLE hFile,
  175. DWORD dwFlags
  176. )
  177. {
  178. CSTRING_TRY
  179. {
  180. CString csFilePath(lpLibFileName);
  181. CString csFileName;
  182. csFilePath.GetLastPathComponent(csFileName);
  183. for (int i = 0; i < g_csIgnoreLibCount; i++)
  184. {
  185. if (g_csIgnoreLib[i].CompareNoCase(csFileName) == 0)
  186. {
  187. LOG(g_szModuleName,eDbgLevelError, "[LoadLibraryExW] Caught attempt loading %s, return %d\n", g_csIgnoreLib[i].Get(), g_rgReturnValues[i]);
  188. return (HINSTANCE) g_rgReturnValues[i];
  189. }
  190. }
  191. }
  192. CSTRING_CATCH
  193. {
  194. // Do Nothing
  195. }
  196. DPF(g_szModuleName, eDbgLevelSpew,"APIHook_LoadLibraryExW Allow(%S)", lpLibFileName);
  197. UINT uLastMode;
  198. HINSTANCE hRet;
  199. uLastMode = SetErrorMode(SEM_NOGPFAULTERRORBOX | SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
  200. hRet = ORIGINAL_API(LoadLibraryExW)(lpLibFileName, hFile, dwFlags);
  201. SetErrorMode(uLastMode);
  202. return hRet;
  203. }
  204. /*++
  205. Register hooked functions
  206. --*/
  207. BOOL
  208. NOTIFY_FUNCTION(
  209. DWORD fdwReason)
  210. {
  211. if (fdwReason == DLL_PROCESS_ATTACH)
  212. {
  213. ParseCommandLine(COMMAND_LINE);
  214. }
  215. return TRUE;
  216. }
  217. HOOK_BEGIN
  218. CALL_NOTIFY_FUNCTION
  219. APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryA)
  220. APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryExA)
  221. APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryW)
  222. APIHOOK_ENTRY(KERNEL32.DLL, LoadLibraryExW)
  223. HOOK_END
  224. IMPLEMENT_SHIM_END