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.

504 lines
31 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. g_szCommandLine = StringDuplicateA(pszCmdLine); \
  115. if (pszCmdLine != NULL && g_szCommandLine == NULL) { \
  116. return NULL; \
  117. } \
  118. \
  119. g_pAPIHooks = \
  120. (PHOOKAPI) ShimMalloc(sizeof(HOOKAPI)*APIHOOK_Count); \
  121. if (g_pAPIHooks == NULL) { \
  122. return NULL; \
  123. } \
  124. *pdwHookCount = APIHOOK_Count; \
  125. }
  126. #define HOOK_END \
  127. if (fdwReason == DLL_PROCESS_ATTACH) { \
  128. DPFN(eDbgLevelSpew, \
  129. "[InitializeHooksMulti] pdwHookCount(%d)\n", \
  130. pdwHookCount ? *pdwHookCount : 0); \
  131. } \
  132. return g_pAPIHooks; \
  133. }
  134. #define APIHOOK_ENTRY(module, hook) \
  135. if (fdwReason == DLL_PROCESS_ATTACH) { \
  136. g_pAPIHooks[APIHOOK_##hook##].pszModule = #module; \
  137. g_pAPIHooks[APIHOOK_##hook##].pszFunctionName = #hook; \
  138. g_pAPIHooks[APIHOOK_##hook##].pfnNew = APIHOOK(hook); \
  139. }
  140. #define APIHOOK_ENTRY_NAME(module, hook, hookname) \
  141. if (fdwReason == DLL_PROCESS_ATTACH) { \
  142. g_pAPIHooks[APIHOOK_##hook##].pszModule = #module; \
  143. g_pAPIHooks[APIHOOK_##hook##].pszFunctionName = #hookname; \
  144. g_pAPIHooks[APIHOOK_##hook##].pfnNew = APIHOOK(hook); \
  145. }
  146. #define APIHOOK_ENTRY_ORD(module, hook, hookord) \
  147. if (fdwReason == DLL_PROCESS_ATTACH) { \
  148. g_pAPIHooks[APIHOOK_##hook##].pszModule = #module; \
  149. g_pAPIHooks[APIHOOK_##hook##].pszFunctionName = (char *)IntToPtr(hookord); \
  150. g_pAPIHooks[APIHOOK_##hook##].pfnNew = APIHOOK(hook); \
  151. }
  152. #define APIHOOK_ENTRY_COMSERVER(module) \
  153. if (fdwReason == DLL_PROCESS_ATTACH) { \
  154. g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pszModule = #module ".DLL"; \
  155. g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pszFunctionName = "DllGetClassObject"; \
  156. g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pfnNew = APIHOOK(module##_DllGetClassObject); \
  157. }
  158. #define APIHOOK_ENTRY_DIRECTX_COMSERVER() \
  159. if (fdwReason == DLL_PROCESS_ATTACH) { \
  160. APIHOOK_ENTRY_COMSERVER(DDRAW) \
  161. APIHOOK_ENTRY_COMSERVER(DSOUND) \
  162. APIHOOK_ENTRY_COMSERVER(DPLAYX) \
  163. APIHOOK_ENTRY_COMSERVER(DINPUT) \
  164. APIHOOK_ENTRY(DDRAW.DLL, DirectDrawCreate) \
  165. APIHOOK_ENTRY(DDRAW.DLL, DirectDrawCreateEx) \
  166. APIHOOK_ENTRY(DSOUND.DLL, DirectSoundCreate) \
  167. APIHOOK_ENTRY(DPLAYX.DLL, DirectPlayCreate) \
  168. APIHOOK_ENTRY(DINPUT.DLL, DirectInputCreateA) \
  169. APIHOOK_ENTRY(DINPUT.DLL, DirectInputCreateW) \
  170. APIHOOK_ENTRY(DINPUT.DLL, DirectInputCreateEx) \
  171. }
  172. #define COMHOOK_ENTRY(obj, iface, hook, vtblndx) \
  173. if (fdwReason == DLL_PROCESS_ATTACH) { \
  174. AddComHook(CLSID_##obj, IID_##iface, COMHOOK(iface, hook), vtblndx); \
  175. }
  176. #define DECLARE_SHIM(shim) \
  177. namespace NS_##shim \
  178. { \
  179. const CHAR * g_szModuleName = #shim; \
  180. CHAR * g_szCommandLine = ""; \
  181. PHOOKAPI g_pAPIHooks = NULL; \
  182. BOOL g_bSubshimUsed = FALSE; \
  183. extern PHOOKAPI InitializeHooksMulti(DWORD, LPSTR, DWORD*); \
  184. };
  185. #define MULTISHIM_BEGIN() \
  186. VOID ShimLib::InitializeHooks(DWORD) \
  187. { \
  188. g_dwShimVersion = 2; \
  189. } \
  190. PHOOKAPI ShimLib::InitializeHooksEx(DWORD fdwReason, LPWSTR pwszShim, LPSTR pszCmdLine, DWORD* pdwHookCount) \
  191. { \
  192. PHOOKAPI pAPIHooks = NULL; \
  193. g_bMultiShim = TRUE;
  194. #define MULTISHIM_ENTRY(shim) \
  195. if ((fdwReason == DLL_PROCESS_ATTACH && pwszShim != NULL && 0 == _wcsicmp( pwszShim, L#shim )) || \
  196. (fdwReason == DLL_PROCESS_DETACH && NS_##shim::g_bSubshimUsed) || \
  197. (fdwReason == SHIM_PROCESS_DYING && NS_##shim::g_bSubshimUsed) || \
  198. (fdwReason == SHIM_DLL_LOADING && NS_##shim::g_bSubshimUsed) || \
  199. (fdwReason == SHIM_STATIC_DLLS_INITIALIZED && NS_##shim::g_bSubshimUsed)) { \
  200. NS_##shim::g_bSubshimUsed = TRUE; \
  201. pAPIHooks = NS_##shim::InitializeHooksMulti( fdwReason, pszCmdLine, pdwHookCount ); \
  202. }
  203. #define MULTISHIM_END() \
  204. return pAPIHooks; \
  205. }
  206. #define MULTISHIM_NOTIFY_FUNCTION() NotifyFn
  207. #define NOTIFY_FUNCTION NotifyFn
  208. #define CALL_MULTISHIM_NOTIFY_FUNCTION() NotifyFn(fdwReason);
  209. #define CALL_NOTIFY_FUNCTION \
  210. if (FALSE == NotifyFn(fdwReason) && \
  211. fdwReason == DLL_PROCESS_ATTACH) { \
  212. *pdwHookCount = 0; \
  213. DPFN(eDbgLevelSpew, \
  214. "[InitializeHooksMulti] NotifyFn returned FALSE, fail load shim\n", \
  215. g_pAPIHooks); \
  216. return NULL; \
  217. }
  218. #define ORIGINAL_API(hook) \
  219. (*(_pfn_##hook##)(g_pAPIHooks[APIHOOK_##hook##].pfnOld))
  220. #define _ORIGINAL_API(hook, proto) \
  221. (*(_pfn_##proto##)(g_pAPIHooks[APIHOOK_##hook##].pfnOld))
  222. #define ORIGINAL_COM(iface, hook, pThis) \
  223. (*(_pfn_##iface##_##hook##)(LookupOriginalCOMFunction(*((PVOID *) pThis), COMHOOK(iface, hook), TRUE )))
  224. #define COMMAND_LINE \
  225. (g_szCommandLine)
  226. #define IMPLEMENT_COMSERVER_HOOK(module) \
  227. HRESULT \
  228. APIHOOK(##module##_DllGetClassObject)( \
  229. REFCLSID rclsid, \
  230. REFIID riid, \
  231. LPVOID * ppv \
  232. ) \
  233. { \
  234. HRESULT hrReturn = E_FAIL; \
  235. \
  236. hrReturn = _ORIGINAL_API(module##_DllGetClassObject, DllGetClassObject)( \
  237. rclsid, riid, ppv); \
  238. \
  239. if (S_OK == hrReturn) { \
  240. HookCOMInterface(rclsid, riid, ppv, TRUE); \
  241. } \
  242. \
  243. return hrReturn; \
  244. }
  245. #define IMPLEMENT_DIRECTX_COMSERVER_HOOKS() \
  246. IMPLEMENT_COMSERVER_HOOK(DDRAW) \
  247. IMPLEMENT_COMSERVER_HOOK(DSOUND) \
  248. IMPLEMENT_COMSERVER_HOOK(DPLAYX) \
  249. IMPLEMENT_COMSERVER_HOOK(DINPUT) \
  250. \
  251. HRESULT \
  252. APIHOOK(DirectDrawCreate)( \
  253. IN GUID FAR *lpGUID, \
  254. OUT LPVOID *lplpDD, \
  255. OUT IUnknown* pUnkOuter \
  256. ) \
  257. { \
  258. HRESULT hrReturn = E_FAIL; \
  259. \
  260. hrReturn = ORIGINAL_API(DirectDrawCreate)(lpGUID, lplpDD, pUnkOuter); \
  261. \
  262. if (S_OK == hrReturn) { \
  263. HookCOMInterface(CLSID_DirectDraw, IID_IDirectDraw, lplpDD, FALSE); \
  264. } \
  265. \
  266. return hrReturn; \
  267. } \
  268. \
  269. HRESULT \
  270. APIHOOK(DirectDrawCreateEx)( \
  271. GUID FAR *lpGUID, \
  272. LPVOID *lplpDD, \
  273. REFIID iid, \
  274. IUnknown* pUnkOuter \
  275. ) \
  276. { \
  277. HRESULT hrReturn = E_FAIL; \
  278. \
  279. hrReturn = ORIGINAL_API(DirectDrawCreateEx)( \
  280. lpGUID, \
  281. lplpDD, \
  282. iid, \
  283. pUnkOuter); \
  284. \
  285. if (S_OK == hrReturn) { \
  286. HookCOMInterface(CLSID_DirectDraw, iid, lplpDD, FALSE); \
  287. } \
  288. \
  289. return hrReturn; \
  290. } \
  291. \
  292. HRESULT \
  293. APIHOOK(DirectSoundCreate)( \
  294. LPCGUID lpcGuid, \
  295. LPDIRECTSOUND *ppDS, \
  296. LPUNKNOWN pUnkOuter) \
  297. { \
  298. \
  299. HRESULT hrReturn = E_FAIL; \
  300. \
  301. hrReturn = ORIGINAL_API(DirectSoundCreate)( \
  302. lpcGuid, \
  303. ppDS, \
  304. pUnkOuter); \
  305. \
  306. if (S_OK == hrReturn) { \
  307. HookCOMInterface(CLSID_DirectSound, \
  308. IID_IDirectSound, \
  309. (LPVOID*) ppDS, \
  310. FALSE); \
  311. } \
  312. \
  313. return hrReturn; \
  314. } \
  315. \
  316. HRESULT \
  317. APIHOOK(DirectPlayCreate)( \
  318. LPGUID lpGUIDSP, \
  319. LPDIRECTPLAY FAR *lplpDP, \
  320. IUnknown *lpUnk) \
  321. { \
  322. \
  323. HRESULT hrReturn = E_FAIL; \
  324. \
  325. hrReturn = ORIGINAL_API(DirectPlayCreate)( \
  326. lpGUIDSP, \
  327. lplpDP, \
  328. lpUnk); \
  329. \
  330. if (S_OK == hrReturn) { \
  331. HookCOMInterface(CLSID_DirectPlay, \
  332. IID_IDirectPlay, \
  333. (LPVOID*) lplpDP, \
  334. FALSE); \
  335. } \
  336. \
  337. return hrReturn; \
  338. } \
  339. \
  340. HRESULT \
  341. APIHOOK(DirectInputCreateA)( \
  342. HINSTANCE hinst, \
  343. DWORD dwVersion, \
  344. LPDIRECTINPUTA * lplpDirectInput, \
  345. LPUNKNOWN punkOuter) \
  346. { \
  347. \
  348. HRESULT hrReturn = E_FAIL; \
  349. \
  350. hrReturn = ORIGINAL_API(DirectInputCreateA)( \
  351. hinst, \
  352. dwVersion, \
  353. lplpDirectInput, \
  354. punkOuter); \
  355. \
  356. if (S_OK == hrReturn) { \
  357. HookCOMInterface(CLSID_DirectInput, \
  358. IID_IDirectInputA, \
  359. (LPVOID*) lplpDirectInput, \
  360. FALSE); \
  361. } \
  362. \
  363. return hrReturn; \
  364. } \
  365. \
  366. HRESULT \
  367. APIHOOK(DirectInputCreateW)( \
  368. HINSTANCE hinst, \
  369. DWORD dwVersion, \
  370. LPDIRECTINPUTW * lplpDirectInput, \
  371. LPUNKNOWN punkOuter) \
  372. { \
  373. \
  374. HRESULT hrReturn = E_FAIL; \
  375. \
  376. hrReturn = ORIGINAL_API(DirectInputCreateW)( \
  377. hinst, \
  378. dwVersion, \
  379. lplpDirectInput, \
  380. punkOuter); \
  381. \
  382. if (S_OK == hrReturn) { \
  383. HookCOMInterface(CLSID_DirectInput, \
  384. IID_IDirectInputW, \
  385. (LPVOID*) lplpDirectInput, \
  386. FALSE); \
  387. } \
  388. \
  389. return hrReturn; \
  390. } \
  391. \
  392. HRESULT \
  393. APIHOOK(DirectInputCreateEx)( \
  394. HINSTANCE hinst, \
  395. DWORD dwVersion, \
  396. REFIID riidltf, \
  397. LPVOID * ppvOut, \
  398. LPUNKNOWN punkOuter) \
  399. { \
  400. \
  401. HRESULT hrReturn = E_FAIL; \
  402. \
  403. hrReturn = ORIGINAL_API(DirectInputCreateEx)( \
  404. hinst, \
  405. dwVersion, \
  406. riidltf, \
  407. ppvOut, \
  408. punkOuter); \
  409. \
  410. if (S_OK == hrReturn) { \
  411. HookCOMInterface(CLSID_DirectInput, \
  412. riidltf, \
  413. (LPVOID*) ppvOut, \
  414. FALSE); \
  415. } \
  416. \
  417. return hrReturn; \
  418. }
  419. // Only add this hook to the list if bDeclare is TRUE
  420. // otherwise a blank entry is added.
  421. #define APIHOOK_ENTRY_OR_NOT(bDeclare, module, hook) \
  422. if (bDeclare) { \
  423. APIHOOK_ENTRY(module, hook) \
  424. }
  425. // Only add this hook to the list if bDeclare is TRUE
  426. // otherwise a blank entry is added.
  427. #define APIHOOK_ENTRY_COMSERVER_OR_NOT(bDeclare, module) \
  428. if (bDeclare) { \
  429. APIHOOK_ENTRY_COMSERVER(module) \
  430. } else { \
  431. APIHOOK_ENTRY_COMSERVER_BLANK(module) \
  432. }
  433. #define APIHOOK_ENTRY_COMSERVER_BLANK(module) \
  434. if (fdwReason == DLL_PROCESS_ATTACH) { \
  435. g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pszModule = ""; \
  436. g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pszFunctionName = ""; \
  437. g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pfnNew = NULL; \
  438. }
  439. #endif // _SHIMHOOKMACRO_H_