|
|
/*++
Copyright (c) 2000-2001 Microsoft Corporation
Module Name:
ShimHookMacro.h
Abstract:
Shim hooking macros for version 2
Notes:
None
History:
10/29/2000 markder Created 12/06/2000 robkenny Converted to use namespaces 09/11/2001 mnikkel Modified DPFN and LOGN to retain LastError
--*/
#pragma once
#ifndef _ShimHookMacro_h_
#define _ShimHookMacro_h_
//
// These are dwReason values that the shim notification functions
// can be called with.
//
//
// This means that all the static linked DLLs have run their init routines.
//
#define SHIM_STATIC_DLLS_INITIALIZED 100
//
// This means that the current process is about to die.
// This gives the shims a chance to do cleanup work while all the modules
// are still loaded.
//
#define SHIM_PROCESS_DYING 101
//
// This notification is sent to notify the shims that a DLL is unloading
//
#define SHIM_DLL_LOADING 102
extern PLDR_DATA_TABLE_ENTRY g_DllLoadingEntry; #define GETDLLLOADINGHANDLE() (g_DllLoadingEntry)
//
// This debug macro needs to be in this file because it needs access
// to g_szModuleName which is only defined inside the namespace.
//
inline void DPFN(ShimLib::DEBUGLEVEL dwDetail, LPCSTR pszFmt, ...) { #if DBG
// This must be the first line of this routine to preserve LastError.
DWORD dwLastError = GetLastError();
extern const CHAR * g_szModuleName; // created by the DECLARE_SHIM macro, inside of the shim's namespace
va_list vaArgList; va_start(vaArgList, pszFmt);
ShimLib::DebugPrintfList(g_szModuleName, dwDetail, pszFmt, vaArgList);
va_end(vaArgList); // This must be the last line of this routine to preserve LastError.
SetLastError(dwLastError); #else
dwDetail; pszFmt; #endif
}
inline void LOGN(ShimLib::DEBUGLEVEL dwDetail, LPCSTR pszFmt, ...) { // This must be the first line of this routine to preserve LastError.
DWORD dwLastError = GetLastError();
extern const CHAR * g_szModuleName;
if (ShimLib::g_bFileLogEnabled) { va_list vaArgList; va_start(vaArgList, pszFmt);
ShimLib::ShimLogList(g_szModuleName, dwDetail, pszFmt, vaArgList);
va_end(vaArgList); } #if DBG
// If logging isn't enabled, dump to the debugger
else { va_list vaArgList; va_start(vaArgList, pszFmt);
ShimLib::DebugPrintfList(g_szModuleName, dwDetail, pszFmt, vaArgList);
va_end(vaArgList); } #endif
// This must be the last line of this routine to preserve LastError.
SetLastError(dwLastError); }
#define APIHOOK(hook) APIHook_##hook
#define COMHOOK(iface, hook) COMHook_##iface##_##hook
#define APIHOOK_ENUM_BEGIN enum {
#define APIHOOK_ENUM_ENTRY(hook) APIHOOK_##hook##,
#define APIHOOK_ENUM_ENTRY_COMSERVER(module) APIHOOK_##module##_DllGetClassObject,
#define APIHOOK_ENUM_ENTRY_DIRECTX_COMSERVER() \
APIHOOK_ENUM_ENTRY_COMSERVER(DDRAW) \ APIHOOK_ENUM_ENTRY_COMSERVER(DSOUND) \ APIHOOK_ENUM_ENTRY_COMSERVER(DPLAYX) \ APIHOOK_ENUM_ENTRY_COMSERVER(DINPUT) \ APIHOOK_ENUM_ENTRY(DirectDrawCreate) \ APIHOOK_ENUM_ENTRY(DirectDrawCreateEx) \ APIHOOK_ENUM_ENTRY(DirectSoundCreate) \ APIHOOK_ENUM_ENTRY(DirectPlayCreate) \ APIHOOK_ENUM_ENTRY(DirectInputCreateA) \ APIHOOK_ENUM_ENTRY(DirectInputCreateW) \ APIHOOK_ENUM_ENTRY(DirectInputCreateEx)
#define APIHOOK_ENUM_END APIHOOK_Count };
#define HOOK_BEGIN \
PHOOKAPI \ InitializeHooksMulti( \ DWORD fdwReason, \ LPSTR pszCmdLine, \ DWORD* pdwHookCount \ ) \ { \ DPFN(eDbgLevelSpew, \ "[InitializeHooksMulti] fdwReason(%d) pszCmdLine(%s)\n", \ fdwReason, pszCmdLine); \ \ if (fdwReason == DLL_PROCESS_ATTACH) { \ g_szCommandLine = StringDuplicateA(pszCmdLine); \ if (pszCmdLine != NULL && g_szCommandLine == NULL) { \ return NULL; \ } \ \ g_pAPIHooks = \ (PHOOKAPI) ShimMalloc(sizeof(HOOKAPI)*APIHOOK_Count); \ if (g_pAPIHooks == NULL) { \ return NULL; \ } \ *pdwHookCount = APIHOOK_Count; \ }
#define HOOK_END \
if (fdwReason == DLL_PROCESS_ATTACH) { \ DPFN(eDbgLevelSpew, \ "[InitializeHooksMulti] pdwHookCount(%d)\n", \ pdwHookCount ? *pdwHookCount : 0); \ } \ return g_pAPIHooks; \ }
#define APIHOOK_ENTRY(module, hook) \
if (fdwReason == DLL_PROCESS_ATTACH) { \ g_pAPIHooks[APIHOOK_##hook##].pszModule = #module; \ g_pAPIHooks[APIHOOK_##hook##].pszFunctionName = #hook; \ g_pAPIHooks[APIHOOK_##hook##].pfnNew = APIHOOK(hook); \ }
#define APIHOOK_ENTRY_NAME(module, hook, hookname) \
if (fdwReason == DLL_PROCESS_ATTACH) { \ g_pAPIHooks[APIHOOK_##hook##].pszModule = #module; \ g_pAPIHooks[APIHOOK_##hook##].pszFunctionName = #hookname; \ g_pAPIHooks[APIHOOK_##hook##].pfnNew = APIHOOK(hook); \ }
#define APIHOOK_ENTRY_ORD(module, hook, hookord) \
if (fdwReason == DLL_PROCESS_ATTACH) { \ g_pAPIHooks[APIHOOK_##hook##].pszModule = #module; \ g_pAPIHooks[APIHOOK_##hook##].pszFunctionName = (char *)IntToPtr(hookord); \ g_pAPIHooks[APIHOOK_##hook##].pfnNew = APIHOOK(hook); \ }
#define APIHOOK_ENTRY_COMSERVER(module) \
if (fdwReason == DLL_PROCESS_ATTACH) { \ g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pszModule = #module ".DLL"; \ g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pszFunctionName = "DllGetClassObject"; \ g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pfnNew = APIHOOK(module##_DllGetClassObject); \ }
#define APIHOOK_ENTRY_DIRECTX_COMSERVER() \
if (fdwReason == DLL_PROCESS_ATTACH) { \ APIHOOK_ENTRY_COMSERVER(DDRAW) \ APIHOOK_ENTRY_COMSERVER(DSOUND) \ APIHOOK_ENTRY_COMSERVER(DPLAYX) \ APIHOOK_ENTRY_COMSERVER(DINPUT) \ APIHOOK_ENTRY(DDRAW.DLL, DirectDrawCreate) \ APIHOOK_ENTRY(DDRAW.DLL, DirectDrawCreateEx) \ APIHOOK_ENTRY(DSOUND.DLL, DirectSoundCreate) \ APIHOOK_ENTRY(DPLAYX.DLL, DirectPlayCreate) \ APIHOOK_ENTRY(DINPUT.DLL, DirectInputCreateA) \ APIHOOK_ENTRY(DINPUT.DLL, DirectInputCreateW) \ APIHOOK_ENTRY(DINPUT.DLL, DirectInputCreateEx) \ }
#define COMHOOK_ENTRY(obj, iface, hook, vtblndx) \
if (fdwReason == DLL_PROCESS_ATTACH) { \ AddComHook(CLSID_##obj, IID_##iface, COMHOOK(iface, hook), vtblndx); \ }
#define DECLARE_SHIM(shim) \
namespace NS_##shim \ { \ const CHAR * g_szModuleName = #shim; \ CHAR * g_szCommandLine = ""; \ PHOOKAPI g_pAPIHooks = NULL; \ BOOL g_bSubshimUsed = FALSE; \ extern PHOOKAPI InitializeHooksMulti(DWORD, LPSTR, DWORD*); \ };
#define MULTISHIM_BEGIN() \
VOID ShimLib::InitializeHooks(DWORD) \ { \ g_dwShimVersion = 2; \ } \ PHOOKAPI ShimLib::InitializeHooksEx(DWORD fdwReason, LPWSTR pwszShim, LPSTR pszCmdLine, DWORD* pdwHookCount) \ { \ PHOOKAPI pAPIHooks = NULL; \ g_bMultiShim = TRUE;
#define MULTISHIM_ENTRY(shim) \
if ((fdwReason == DLL_PROCESS_ATTACH && pwszShim != NULL && 0 == _wcsicmp( pwszShim, L#shim )) || \ (fdwReason == DLL_PROCESS_DETACH && NS_##shim::g_bSubshimUsed) || \ (fdwReason == SHIM_PROCESS_DYING && NS_##shim::g_bSubshimUsed) || \ (fdwReason == SHIM_DLL_LOADING && NS_##shim::g_bSubshimUsed) || \ (fdwReason == SHIM_STATIC_DLLS_INITIALIZED && NS_##shim::g_bSubshimUsed)) { \ NS_##shim::g_bSubshimUsed = TRUE; \ pAPIHooks = NS_##shim::InitializeHooksMulti( fdwReason, pszCmdLine, pdwHookCount ); \ }
#define MULTISHIM_END() \
return pAPIHooks; \ }
#define MULTISHIM_NOTIFY_FUNCTION() NotifyFn
#define NOTIFY_FUNCTION NotifyFn
#define CALL_MULTISHIM_NOTIFY_FUNCTION() NotifyFn(fdwReason);
#define CALL_NOTIFY_FUNCTION \
if (FALSE == NotifyFn(fdwReason) && \ fdwReason == DLL_PROCESS_ATTACH) { \ *pdwHookCount = 0; \ DPFN(eDbgLevelSpew, \ "[InitializeHooksMulti] NotifyFn returned FALSE, fail load shim\n", \ g_pAPIHooks); \ return NULL; \ }
#define ORIGINAL_API(hook) \
(*(_pfn_##hook##)(g_pAPIHooks[APIHOOK_##hook##].pfnOld))
#define _ORIGINAL_API(hook, proto) \
(*(_pfn_##proto##)(g_pAPIHooks[APIHOOK_##hook##].pfnOld))
#define ORIGINAL_COM(iface, hook, pThis) \
(*(_pfn_##iface##_##hook##)(LookupOriginalCOMFunction(*((PVOID *) pThis), COMHOOK(iface, hook), TRUE )))
#define COMMAND_LINE \
(g_szCommandLine)
#define IMPLEMENT_COMSERVER_HOOK(module) \
HRESULT \ APIHOOK(##module##_DllGetClassObject)( \ REFCLSID rclsid, \ REFIID riid, \ LPVOID * ppv \ ) \ { \ HRESULT hrReturn = E_FAIL; \ \ hrReturn = _ORIGINAL_API(module##_DllGetClassObject, DllGetClassObject)( \ rclsid, riid, ppv); \ \ if (S_OK == hrReturn) { \ HookCOMInterface(rclsid, riid, ppv, TRUE); \ } \ \ return hrReturn; \ }
#define IMPLEMENT_DIRECTX_COMSERVER_HOOKS() \
IMPLEMENT_COMSERVER_HOOK(DDRAW) \ IMPLEMENT_COMSERVER_HOOK(DSOUND) \ IMPLEMENT_COMSERVER_HOOK(DPLAYX) \ IMPLEMENT_COMSERVER_HOOK(DINPUT) \ \ HRESULT \ APIHOOK(DirectDrawCreate)( \ IN GUID FAR *lpGUID, \ OUT LPVOID *lplpDD, \ OUT IUnknown* pUnkOuter \ ) \ { \ HRESULT hrReturn = E_FAIL; \ \ hrReturn = ORIGINAL_API(DirectDrawCreate)(lpGUID, lplpDD, pUnkOuter); \ \ if (S_OK == hrReturn) { \ HookCOMInterface(CLSID_DirectDraw, IID_IDirectDraw, lplpDD, FALSE); \ } \ \ return hrReturn; \ } \ \ HRESULT \ APIHOOK(DirectDrawCreateEx)( \ GUID FAR *lpGUID, \ LPVOID *lplpDD, \ REFIID iid, \ IUnknown* pUnkOuter \ ) \ { \ HRESULT hrReturn = E_FAIL; \ \ hrReturn = ORIGINAL_API(DirectDrawCreateEx)( \ lpGUID, \ lplpDD, \ iid, \ pUnkOuter); \ \ if (S_OK == hrReturn) { \ HookCOMInterface(CLSID_DirectDraw, iid, lplpDD, FALSE); \ } \ \ return hrReturn; \ } \ \ HRESULT \ APIHOOK(DirectSoundCreate)( \ LPCGUID lpcGuid, \ LPDIRECTSOUND *ppDS, \ LPUNKNOWN pUnkOuter) \ { \ \ HRESULT hrReturn = E_FAIL; \ \ hrReturn = ORIGINAL_API(DirectSoundCreate)( \ lpcGuid, \ ppDS, \ pUnkOuter); \ \ if (S_OK == hrReturn) { \ HookCOMInterface(CLSID_DirectSound, \ IID_IDirectSound, \ (LPVOID*) ppDS, \ FALSE); \ } \ \ return hrReturn; \ } \ \ HRESULT \ APIHOOK(DirectPlayCreate)( \ LPGUID lpGUIDSP, \ LPDIRECTPLAY FAR *lplpDP, \ IUnknown *lpUnk) \ { \ \ HRESULT hrReturn = E_FAIL; \ \ hrReturn = ORIGINAL_API(DirectPlayCreate)( \ lpGUIDSP, \ lplpDP, \ lpUnk); \ \ if (S_OK == hrReturn) { \ HookCOMInterface(CLSID_DirectPlay, \ IID_IDirectPlay, \ (LPVOID*) lplpDP, \ FALSE); \ } \ \ return hrReturn; \ } \ \ HRESULT \ APIHOOK(DirectInputCreateA)( \ HINSTANCE hinst, \ DWORD dwVersion, \ LPDIRECTINPUTA * lplpDirectInput, \ LPUNKNOWN punkOuter) \ { \ \ HRESULT hrReturn = E_FAIL; \ \ hrReturn = ORIGINAL_API(DirectInputCreateA)( \ hinst, \ dwVersion, \ lplpDirectInput, \ punkOuter); \ \ if (S_OK == hrReturn) { \ HookCOMInterface(CLSID_DirectInput, \ IID_IDirectInputA, \ (LPVOID*) lplpDirectInput, \ FALSE); \ } \ \ return hrReturn; \ } \ \ HRESULT \ APIHOOK(DirectInputCreateW)( \ HINSTANCE hinst, \ DWORD dwVersion, \ LPDIRECTINPUTW * lplpDirectInput, \ LPUNKNOWN punkOuter) \ { \ \ HRESULT hrReturn = E_FAIL; \ \ hrReturn = ORIGINAL_API(DirectInputCreateW)( \ hinst, \ dwVersion, \ lplpDirectInput, \ punkOuter); \ \ if (S_OK == hrReturn) { \ HookCOMInterface(CLSID_DirectInput, \ IID_IDirectInputW, \ (LPVOID*) lplpDirectInput, \ FALSE); \ } \ \ return hrReturn; \ } \ \ HRESULT \ APIHOOK(DirectInputCreateEx)( \ HINSTANCE hinst, \ DWORD dwVersion, \ REFIID riidltf, \ LPVOID * ppvOut, \ LPUNKNOWN punkOuter) \ { \ \ HRESULT hrReturn = E_FAIL; \ \ hrReturn = ORIGINAL_API(DirectInputCreateEx)( \ hinst, \ dwVersion, \ riidltf, \ ppvOut, \ punkOuter); \ \ if (S_OK == hrReturn) { \ HookCOMInterface(CLSID_DirectInput, \ riidltf, \ (LPVOID*) ppvOut, \ FALSE); \ } \ \ return hrReturn; \ }
// Only add this hook to the list if bDeclare is TRUE
// otherwise a blank entry is added.
#define APIHOOK_ENTRY_OR_NOT(bDeclare, module, hook) \
if (bDeclare) { \ APIHOOK_ENTRY(module, hook) \ }
// Only add this hook to the list if bDeclare is TRUE
// otherwise a blank entry is added.
#define APIHOOK_ENTRY_COMSERVER_OR_NOT(bDeclare, module) \
if (bDeclare) { \ APIHOOK_ENTRY_COMSERVER(module) \ } else { \ APIHOOK_ENTRY_COMSERVER_BLANK(module) \ }
#define APIHOOK_ENTRY_COMSERVER_BLANK(module) \
if (fdwReason == DLL_PROCESS_ATTACH) { \ g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pszModule = ""; \ g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pszFunctionName = ""; \ g_pAPIHooks[APIHOOK_##module##_DllGetClassObject].pfnNew = NULL; \ }
#endif // _SHIMHOOKMACRO_H_
|