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.

501 lines
30 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. ShimHookMacro.h
  5. Abstract:
  6. Shim hooking macros for version 2
  7. Notes:
  8. None
  9. History:
  10. 10/29/2000 markder Created
  11. 12/06/2000 robkenny Converted to use namespaces
  12. 09/11/2001 mnikkel Modified DPFN and LOGN to retain LastError
  13. --*/
  14. #pragma once
  15. #ifndef _ShimHookMacro_h_
  16. #define _ShimHookMacro_h_
  17. //
  18. // These are dwReason values that the shim notification functions
  19. // can be called with.
  20. //
  21. //
  22. // This means that all the static linked DLLs have run their init routines.
  23. //
  24. #define SHIM_STATIC_DLLS_INITIALIZED 100
  25. //
  26. // This means that the current process is about to die.
  27. // This gives the shims a chance to do cleanup work while all the modules
  28. // are still loaded.
  29. //
  30. #define SHIM_PROCESS_DYING 101
  31. //
  32. // This notification is sent to notify the shims that a DLL is unloading
  33. //
  34. #define SHIM_DLL_LOADING 102
  35. extern PLDR_DATA_TABLE_ENTRY g_DllLoadingEntry;
  36. #define GETDLLLOADINGHANDLE() (g_DllLoadingEntry)
  37. //
  38. // This debug macro needs to be in this file because it needs access
  39. // to g_szModuleName which is only defined inside the namespace.
  40. //
  41. inline void DPFN(ShimLib::DEBUGLEVEL dwDetail, LPCSTR pszFmt, ...)
  42. {
  43. #if DBG
  44. // This must be the first line of this routine to preserve LastError.
  45. DWORD dwLastError = GetLastError();
  46. extern const CHAR * g_szModuleName; // created by the DECLARE_SHIM macro, inside of the shim's namespace
  47. va_list vaArgList;
  48. va_start(vaArgList, pszFmt);
  49. ShimLib::DebugPrintfList(g_szModuleName, dwDetail, pszFmt, vaArgList);
  50. va_end(vaArgList);
  51. // This must be the last line of this routine to preserve LastError.
  52. SetLastError(dwLastError);
  53. #else
  54. dwDetail;
  55. pszFmt;
  56. #endif
  57. }
  58. inline void LOGN(ShimLib::DEBUGLEVEL dwDetail, LPCSTR pszFmt, ...)
  59. {
  60. // This must be the first line of this routine to preserve LastError.
  61. DWORD dwLastError = GetLastError();
  62. extern const CHAR * g_szModuleName;
  63. if (ShimLib::g_bFileLogEnabled)
  64. {
  65. va_list vaArgList;
  66. va_start(vaArgList, pszFmt);
  67. ShimLib::ShimLogList(g_szModuleName, dwDetail, pszFmt, vaArgList);
  68. va_end(vaArgList);
  69. }
  70. #if DBG
  71. // If logging isn't enabled, dump to the debugger
  72. else
  73. {
  74. va_list vaArgList;
  75. va_start(vaArgList, pszFmt);
  76. ShimLib::DebugPrintfList(g_szModuleName, dwDetail, pszFmt, vaArgList);
  77. va_end(vaArgList);
  78. }
  79. #endif
  80. // This must be the last line of this routine to preserve LastError.
  81. SetLastError(dwLastError);
  82. }
  83. #define APIHOOK(hook) APIHook_##hook
  84. #define COMHOOK(iface, hook) COMHook_##iface##_##hook
  85. #define APIHOOK_ENUM_BEGIN enum {
  86. #define APIHOOK_ENUM_ENTRY(hook) APIHOOK_##hook##,
  87. #define APIHOOK_ENUM_ENTRY_COMSERVER(module) APIHOOK_##module##_DllGetClassObject,
  88. #define APIHOOK_ENUM_ENTRY_DIRECTX_COMSERVER() \
  89. APIHOOK_ENUM_ENTRY_COMSERVER(DDRAW) \
  90. APIHOOK_ENUM_ENTRY_COMSERVER(DSOUND) \
  91. APIHOOK_ENUM_ENTRY_COMSERVER(DPLAYX) \
  92. APIHOOK_ENUM_ENTRY_COMSERVER(DINPUT) \
  93. APIHOOK_ENUM_ENTRY(DirectDrawCreate) \
  94. APIHOOK_ENUM_ENTRY(DirectDrawCreateEx) \
  95. APIHOOK_ENUM_ENTRY(DirectSoundCreate) \
  96. APIHOOK_ENUM_ENTRY(DirectPlayCreate) \
  97. APIHOOK_ENUM_ENTRY(DirectInputCreateA) \
  98. APIHOOK_ENUM_ENTRY(DirectInputCreateW) \
  99. APIHOOK_ENUM_ENTRY(DirectInputCreateEx)
  100. #define APIHOOK_ENUM_END APIHOOK_Count };
  101. #define HOOK_BEGIN \
  102. PHOOKAPI \
  103. InitializeHooksMulti( \
  104. DWORD fdwReason, \
  105. LPSTR pszCmdLine, \
  106. DWORD* pdwHookCount \
  107. ) \
  108. { \
  109. DPFN(eDbgLevelSpew, \
  110. "[InitializeHooksMulti] fdwReason(%d) pszCmdLine(%s)\n", \
  111. fdwReason, pszCmdLine); \
  112. \
  113. if (fdwReason == DLL_PROCESS_ATTACH) { \
  114. lstrcpynA( g_szCommandLine, pszCmdLine, SHIM_COMMAND_LINE_MAX_BUFFER); \
  115. \
  116. g_pAPIHooks = \
  117. (PHOOKAPI) ShimMalloc(sizeof(HOOKAPI)*APIHOOK_Count); \
  118. if (g_pAPIHooks == NULL) { \
  119. return NULL; \
  120. } \
  121. *pdwHookCount = APIHOOK_Count; \
  122. }
  123. #define HOOK_END \
  124. if (fdwReason == DLL_PROCESS_ATTACH) { \
  125. DPFN(eDbgLevelSpew, \
  126. "[InitializeHooksMulti] pdwHookCount(%d)\n", \
  127. pdwHookCount ? *pdwHookCount : 0); \
  128. } \
  129. return g_pAPIHooks; \
  130. }
  131. #define APIHOOK_ENTRY(module, hook) \
  132. if (fdwReason == DLL_PROCESS_ATTACH) { \
  133. g_pAPIHooks[APIHOOK_##hook##].pszModule = #module; \
  134. g_pAPIHooks[APIHOOK_##hook##].pszFunctionName = #hook; \
  135. g_pAPIHooks[APIHOOK_##hook##].pfnNew = APIHOOK(hook); \
  136. }
  137. #define APIHOOK_ENTRY_NAME(module, hook, hookname) \
  138. if (fdwReason == DLL_PROCESS_ATTACH) { \
  139. g_pAPIHooks[APIHOOK_##hook##].pszModule = #module; \
  140. g_pAPIHooks[APIHOOK_##hook##].pszFunctionName = #hookname; \
  141. g_pAPIHooks[APIHOOK_##hook##].pfnNew = APIHOOK(hook); \
  142. }
  143. #define APIHOOK_ENTRY_ORD(module, hook, hookord) \
  144. if (fdwReason == DLL_PROCESS_ATTACH) { \
  145. g_pAPIHooks[APIHOOK_##hook##].pszModule = #module; \
  146. g_pAPIHooks[APIHOOK_##hook##].pszFunctionName = (char *)IntToPtr(hookord); \
  147. g_pAPIHooks[APIHOOK_##hook##].pfnNew = APIHOOK(hook); \
  148. }
  149. #define APIHOOK_ENTRY_COMSERVER(module) \
  150. if (fdwReason == DLL_PROCESS_ATTACH) { \
  151. g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pszModule = #module ".DLL"; \
  152. g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pszFunctionName = "DllGetClassObject"; \
  153. g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pfnNew = APIHOOK(module##_DllGetClassObject); \
  154. }
  155. #define APIHOOK_ENTRY_DIRECTX_COMSERVER() \
  156. if (fdwReason == DLL_PROCESS_ATTACH) { \
  157. APIHOOK_ENTRY_COMSERVER(DDRAW) \
  158. APIHOOK_ENTRY_COMSERVER(DSOUND) \
  159. APIHOOK_ENTRY_COMSERVER(DPLAYX) \
  160. APIHOOK_ENTRY_COMSERVER(DINPUT) \
  161. APIHOOK_ENTRY(DDRAW.DLL, DirectDrawCreate) \
  162. APIHOOK_ENTRY(DDRAW.DLL, DirectDrawCreateEx) \
  163. APIHOOK_ENTRY(DSOUND.DLL, DirectSoundCreate) \
  164. APIHOOK_ENTRY(DPLAYX.DLL, DirectPlayCreate) \
  165. APIHOOK_ENTRY(DINPUT.DLL, DirectInputCreateA) \
  166. APIHOOK_ENTRY(DINPUT.DLL, DirectInputCreateW) \
  167. APIHOOK_ENTRY(DINPUT.DLL, DirectInputCreateEx) \
  168. }
  169. #define COMHOOK_ENTRY(obj, iface, hook, vtblndx) \
  170. if (fdwReason == DLL_PROCESS_ATTACH) { \
  171. AddComHook(CLSID_##obj, IID_##iface, COMHOOK(iface, hook), vtblndx); \
  172. }
  173. #define DECLARE_SHIM(shim) \
  174. namespace NS_##shim \
  175. { \
  176. const CHAR * g_szModuleName = #shim; \
  177. CHAR g_szCommandLine[SHIM_COMMAND_LINE_MAX_BUFFER]; \
  178. PHOOKAPI g_pAPIHooks = NULL; \
  179. BOOL g_bSubshimUsed = FALSE; \
  180. extern PHOOKAPI InitializeHooksMulti(DWORD, LPSTR, DWORD*); \
  181. };
  182. #define MULTISHIM_BEGIN() \
  183. VOID ShimLib::InitializeHooks(DWORD) \
  184. { \
  185. g_dwShimVersion = 2; \
  186. } \
  187. PHOOKAPI ShimLib::InitializeHooksEx(DWORD fdwReason, LPWSTR pwszShim, LPSTR pszCmdLine, DWORD* pdwHookCount) \
  188. { \
  189. PHOOKAPI pAPIHooks = NULL; \
  190. g_bMultiShim = TRUE;
  191. #define MULTISHIM_ENTRY(shim) \
  192. if ((fdwReason == DLL_PROCESS_ATTACH && pwszShim != NULL && 0 == _wcsicmp( pwszShim, L#shim )) || \
  193. (fdwReason == DLL_PROCESS_DETACH && NS_##shim::g_bSubshimUsed) || \
  194. (fdwReason == SHIM_PROCESS_DYING && NS_##shim::g_bSubshimUsed) || \
  195. (fdwReason == SHIM_DLL_LOADING && NS_##shim::g_bSubshimUsed) || \
  196. (fdwReason == SHIM_STATIC_DLLS_INITIALIZED && NS_##shim::g_bSubshimUsed)) { \
  197. NS_##shim::g_bSubshimUsed = TRUE; \
  198. pAPIHooks = NS_##shim::InitializeHooksMulti( fdwReason, pszCmdLine, pdwHookCount ); \
  199. }
  200. #define MULTISHIM_END() \
  201. return pAPIHooks; \
  202. }
  203. #define MULTISHIM_NOTIFY_FUNCTION() NotifyFn
  204. #define NOTIFY_FUNCTION NotifyFn
  205. #define CALL_MULTISHIM_NOTIFY_FUNCTION() NotifyFn(fdwReason);
  206. #define CALL_NOTIFY_FUNCTION \
  207. if (FALSE == NotifyFn(fdwReason) && \
  208. fdwReason == DLL_PROCESS_ATTACH) { \
  209. *pdwHookCount = 0; \
  210. DPFN(eDbgLevelSpew, \
  211. "[InitializeHooksMulti] NotifyFn returned FALSE, fail load shim\n", \
  212. g_pAPIHooks); \
  213. return NULL; \
  214. }
  215. #define ORIGINAL_API(hook) \
  216. (*(_pfn_##hook##)(g_pAPIHooks[APIHOOK_##hook##].pfnOld))
  217. #define _ORIGINAL_API(hook, proto) \
  218. (*(_pfn_##proto##)(g_pAPIHooks[APIHOOK_##hook##].pfnOld))
  219. #define ORIGINAL_COM(iface, hook, pThis) \
  220. (*(_pfn_##iface##_##hook##)(LookupOriginalCOMFunction(*((PVOID *) pThis), COMHOOK(iface, hook), TRUE )))
  221. #define COMMAND_LINE \
  222. (g_szCommandLine)
  223. #define IMPLEMENT_COMSERVER_HOOK(module) \
  224. HRESULT \
  225. APIHOOK(##module##_DllGetClassObject)( \
  226. REFCLSID rclsid, \
  227. REFIID riid, \
  228. LPVOID * ppv \
  229. ) \
  230. { \
  231. HRESULT hrReturn = E_FAIL; \
  232. \
  233. hrReturn = _ORIGINAL_API(module##_DllGetClassObject, DllGetClassObject)( \
  234. rclsid, riid, ppv); \
  235. \
  236. if (S_OK == hrReturn) { \
  237. HookCOMInterface(rclsid, riid, ppv, TRUE); \
  238. } \
  239. \
  240. return hrReturn; \
  241. }
  242. #define IMPLEMENT_DIRECTX_COMSERVER_HOOKS() \
  243. IMPLEMENT_COMSERVER_HOOK(DDRAW) \
  244. IMPLEMENT_COMSERVER_HOOK(DSOUND) \
  245. IMPLEMENT_COMSERVER_HOOK(DPLAYX) \
  246. IMPLEMENT_COMSERVER_HOOK(DINPUT) \
  247. \
  248. HRESULT \
  249. APIHOOK(DirectDrawCreate)( \
  250. IN GUID FAR *lpGUID, \
  251. OUT LPVOID *lplpDD, \
  252. OUT IUnknown* pUnkOuter \
  253. ) \
  254. { \
  255. HRESULT hrReturn = E_FAIL; \
  256. \
  257. hrReturn = ORIGINAL_API(DirectDrawCreate)(lpGUID, lplpDD, pUnkOuter); \
  258. \
  259. if (S_OK == hrReturn) { \
  260. HookCOMInterface(CLSID_DirectDraw, IID_IDirectDraw, lplpDD, FALSE); \
  261. } \
  262. \
  263. return hrReturn; \
  264. } \
  265. \
  266. HRESULT \
  267. APIHOOK(DirectDrawCreateEx)( \
  268. GUID FAR *lpGUID, \
  269. LPVOID *lplpDD, \
  270. REFIID iid, \
  271. IUnknown* pUnkOuter \
  272. ) \
  273. { \
  274. HRESULT hrReturn = E_FAIL; \
  275. \
  276. hrReturn = ORIGINAL_API(DirectDrawCreateEx)( \
  277. lpGUID, \
  278. lplpDD, \
  279. iid, \
  280. pUnkOuter); \
  281. \
  282. if (S_OK == hrReturn) { \
  283. HookCOMInterface(CLSID_DirectDraw, iid, lplpDD, FALSE); \
  284. } \
  285. \
  286. return hrReturn; \
  287. } \
  288. \
  289. HRESULT \
  290. APIHOOK(DirectSoundCreate)( \
  291. LPCGUID lpcGuid, \
  292. LPDIRECTSOUND *ppDS, \
  293. LPUNKNOWN pUnkOuter) \
  294. { \
  295. \
  296. HRESULT hrReturn = E_FAIL; \
  297. \
  298. hrReturn = ORIGINAL_API(DirectSoundCreate)( \
  299. lpcGuid, \
  300. ppDS, \
  301. pUnkOuter); \
  302. \
  303. if (S_OK == hrReturn) { \
  304. HookCOMInterface(CLSID_DirectSound, \
  305. IID_IDirectSound, \
  306. (LPVOID*) ppDS, \
  307. FALSE); \
  308. } \
  309. \
  310. return hrReturn; \
  311. } \
  312. \
  313. HRESULT \
  314. APIHOOK(DirectPlayCreate)( \
  315. LPGUID lpGUIDSP, \
  316. LPDIRECTPLAY FAR *lplpDP, \
  317. IUnknown *lpUnk) \
  318. { \
  319. \
  320. HRESULT hrReturn = E_FAIL; \
  321. \
  322. hrReturn = ORIGINAL_API(DirectPlayCreate)( \
  323. lpGUIDSP, \
  324. lplpDP, \
  325. lpUnk); \
  326. \
  327. if (S_OK == hrReturn) { \
  328. HookCOMInterface(CLSID_DirectPlay, \
  329. IID_IDirectPlay, \
  330. (LPVOID*) lplpDP, \
  331. FALSE); \
  332. } \
  333. \
  334. return hrReturn; \
  335. } \
  336. \
  337. HRESULT \
  338. APIHOOK(DirectInputCreateA)( \
  339. HINSTANCE hinst, \
  340. DWORD dwVersion, \
  341. LPDIRECTINPUTA * lplpDirectInput, \
  342. LPUNKNOWN punkOuter) \
  343. { \
  344. \
  345. HRESULT hrReturn = E_FAIL; \
  346. \
  347. hrReturn = ORIGINAL_API(DirectInputCreateA)( \
  348. hinst, \
  349. dwVersion, \
  350. lplpDirectInput, \
  351. punkOuter); \
  352. \
  353. if (S_OK == hrReturn) { \
  354. HookCOMInterface(CLSID_DirectInput, \
  355. IID_IDirectInputA, \
  356. (LPVOID*) lplpDirectInput, \
  357. FALSE); \
  358. } \
  359. \
  360. return hrReturn; \
  361. } \
  362. \
  363. HRESULT \
  364. APIHOOK(DirectInputCreateW)( \
  365. HINSTANCE hinst, \
  366. DWORD dwVersion, \
  367. LPDIRECTINPUTW * lplpDirectInput, \
  368. LPUNKNOWN punkOuter) \
  369. { \
  370. \
  371. HRESULT hrReturn = E_FAIL; \
  372. \
  373. hrReturn = ORIGINAL_API(DirectInputCreateW)( \
  374. hinst, \
  375. dwVersion, \
  376. lplpDirectInput, \
  377. punkOuter); \
  378. \
  379. if (S_OK == hrReturn) { \
  380. HookCOMInterface(CLSID_DirectInput, \
  381. IID_IDirectInputW, \
  382. (LPVOID*) lplpDirectInput, \
  383. FALSE); \
  384. } \
  385. \
  386. return hrReturn; \
  387. } \
  388. \
  389. HRESULT \
  390. APIHOOK(DirectInputCreateEx)( \
  391. HINSTANCE hinst, \
  392. DWORD dwVersion, \
  393. REFIID riidltf, \
  394. LPVOID * ppvOut, \
  395. LPUNKNOWN punkOuter) \
  396. { \
  397. \
  398. HRESULT hrReturn = E_FAIL; \
  399. \
  400. hrReturn = ORIGINAL_API(DirectInputCreateEx)( \
  401. hinst, \
  402. dwVersion, \
  403. riidltf, \
  404. ppvOut, \
  405. punkOuter); \
  406. \
  407. if (S_OK == hrReturn) { \
  408. HookCOMInterface(CLSID_DirectInput, \
  409. riidltf, \
  410. (LPVOID*) ppvOut, \
  411. FALSE); \
  412. } \
  413. \
  414. return hrReturn; \
  415. }
  416. // Only add this hook to the list if bDeclare is TRUE
  417. // otherwise a blank entry is added.
  418. #define APIHOOK_ENTRY_OR_NOT(bDeclare, module, hook) \
  419. if (bDeclare) { \
  420. APIHOOK_ENTRY(module, hook) \
  421. }
  422. // Only add this hook to the list if bDeclare is TRUE
  423. // otherwise a blank entry is added.
  424. #define APIHOOK_ENTRY_COMSERVER_OR_NOT(bDeclare, module) \
  425. if (bDeclare) { \
  426. APIHOOK_ENTRY_COMSERVER(module) \
  427. } else { \
  428. APIHOOK_ENTRY_COMSERVER_BLANK(module) \
  429. }
  430. #define APIHOOK_ENTRY_COMSERVER_BLANK(module) \
  431. if (fdwReason == DLL_PROCESS_ATTACH) { \
  432. g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pszModule = ""; \
  433. g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pszFunctionName = ""; \
  434. g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pfnNew = NULL; \
  435. }
  436. #endif // _SHIMHOOKMACRO_H_