232 lines
6.6 KiB
C
232 lines
6.6 KiB
C
|
//
|
||
|
// DelayImp.h
|
||
|
//
|
||
|
// define structures and prototypes necessary for delay loading of imports
|
||
|
//
|
||
|
#if !defined(_delayimp_h)
|
||
|
#define _delayimp_h
|
||
|
|
||
|
#if _MSC_VER > 1000
|
||
|
#pragma once
|
||
|
#endif
|
||
|
|
||
|
#ifndef DELAYLOAD_VERSION
|
||
|
#ifdef _WIN64
|
||
|
#define DELAYLOAD_VERSION 0x200
|
||
|
#else
|
||
|
#define DELAYLOAD_VERSION 0x100
|
||
|
#endif
|
||
|
#endif
|
||
|
|
||
|
#if defined(__cplusplus)
|
||
|
#define ExternC extern "C"
|
||
|
#else
|
||
|
#define ExternC
|
||
|
#endif
|
||
|
|
||
|
typedef IMAGE_THUNK_DATA * PImgThunkData;
|
||
|
typedef const IMAGE_THUNK_DATA * PCImgThunkData;
|
||
|
typedef DWORD RVA;
|
||
|
|
||
|
typedef struct ImgDelayDescrV2 {
|
||
|
DWORD grAttrs; // attributes
|
||
|
RVA rvaDLLName; // RVA to dll name
|
||
|
RVA rvaHmod; // RVA of module handle
|
||
|
RVA rvaIAT; // RVA of the IAT
|
||
|
RVA rvaINT; // RVA of the INT
|
||
|
RVA rvaBoundIAT; // RVA of the optional bound IAT
|
||
|
RVA rvaUnloadIAT; // RVA of optional copy of original IAT
|
||
|
DWORD dwTimeStamp; // 0 if not bound,
|
||
|
// O.W. date/time stamp of DLL bound to (Old BIND)
|
||
|
} ImgDelayDescrV2, * PImgDelayDescrV2;
|
||
|
|
||
|
typedef struct ImgDelayDescrV1 {
|
||
|
DWORD grAttrs; // attributes
|
||
|
LPCSTR szName; // pointer to dll name
|
||
|
HMODULE * phmod; // address of module handle
|
||
|
PImgThunkData pIAT; // address of the IAT
|
||
|
PCImgThunkData pINT; // address of the INT
|
||
|
PCImgThunkData pBoundIAT; // address of the optional bound IAT
|
||
|
PCImgThunkData pUnloadIAT; // address of optional copy of original IAT
|
||
|
DWORD dwTimeStamp; // 0 if not bound,
|
||
|
// O.W. date/time stamp of DLL bound to (Old BIND)
|
||
|
} ImgDelayDescrV1, * PImgDelayDescrV1;
|
||
|
|
||
|
#if DELAYLOAD_VERSION >= 0x0200
|
||
|
typedef ImgDelayDescrV2 ImgDelayDescr;
|
||
|
typedef PImgDelayDescrV2 PImgDelayDescr;
|
||
|
#else
|
||
|
typedef ImgDelayDescrV1 ImgDelayDescr;
|
||
|
typedef PImgDelayDescrV1 PImgDelayDescr;
|
||
|
#endif
|
||
|
|
||
|
typedef const ImgDelayDescr * PCImgDelayDescr;
|
||
|
|
||
|
enum DLAttr { // Delay Load Attributes
|
||
|
dlattrRva = 0x1, // RVAs are used instead of pointers
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// Delay load import hook notifications
|
||
|
//
|
||
|
enum {
|
||
|
dliStartProcessing, // used to bypass or note helper only
|
||
|
dliNotePreLoadLibrary, // called just before LoadLibrary, can
|
||
|
// override w/ new HMODULE return val
|
||
|
dliNotePreGetProcAddress, // called just before GetProcAddress, can
|
||
|
// override w/ new FARPROC return value
|
||
|
dliFailLoadLib, // failed to load library, fix it by
|
||
|
// returning a valid HMODULE
|
||
|
dliFailGetProc, // failed to get proc address, fix it by
|
||
|
// returning a valid FARPROC
|
||
|
dliNoteEndProcessing, // called after all processing is done, no
|
||
|
// no bypass possible at this point except
|
||
|
// by longjmp()/throw()/RaiseException.
|
||
|
};
|
||
|
|
||
|
typedef struct DelayLoadProc {
|
||
|
BOOL fImportByName;
|
||
|
union {
|
||
|
LPCSTR szProcName;
|
||
|
DWORD dwOrdinal;
|
||
|
};
|
||
|
} DelayLoadProc;
|
||
|
|
||
|
typedef struct DelayLoadInfo {
|
||
|
DWORD cb; // size of structure
|
||
|
PCImgDelayDescr pidd; // raw form of data (everything is there)
|
||
|
FARPROC * ppfn; // points to address of function to load
|
||
|
LPCSTR szDll; // name of dll
|
||
|
DelayLoadProc dlp; // name or ordinal of procedure
|
||
|
HMODULE hmodCur; // the hInstance of the library we have loaded
|
||
|
FARPROC pfnCur; // the actual function that will be called
|
||
|
DWORD dwLastError;// error received (if an error notification)
|
||
|
} DelayLoadInfo, * PDelayLoadInfo;
|
||
|
|
||
|
typedef FARPROC (WINAPI *PfnDliHook)(
|
||
|
unsigned dliNotify,
|
||
|
PDelayLoadInfo pdli
|
||
|
);
|
||
|
|
||
|
// utility function for calculating the index of the current import
|
||
|
// for all the tables (INT, BIAT, UIAT, and IAT).
|
||
|
__inline unsigned
|
||
|
IndexFromPImgThunkData(PCImgThunkData pitdCur, PCImgThunkData pitdBase) {
|
||
|
return (unsigned)(pitdCur - pitdBase);
|
||
|
}
|
||
|
|
||
|
// C++ template utility function for converting RVAs to pointers
|
||
|
//
|
||
|
#if defined(_WIN64) && defined(_M_IA64)
|
||
|
#pragma section(".base", long, read, write)
|
||
|
ExternC
|
||
|
__declspec(allocate(".base"))
|
||
|
extern
|
||
|
IMAGE_DOS_HEADER __ImageBase;
|
||
|
#else
|
||
|
ExternC
|
||
|
extern
|
||
|
IMAGE_DOS_HEADER __ImageBase;
|
||
|
#endif
|
||
|
|
||
|
#if defined(__cplusplus)
|
||
|
template <class X>
|
||
|
X * PFromRva(RVA rva, const X *) {
|
||
|
return (X*)(PBYTE(&__ImageBase) + rva);
|
||
|
}
|
||
|
#else
|
||
|
__inline
|
||
|
void *
|
||
|
WINAPI
|
||
|
PFromRva(RVA rva, void *unused) {
|
||
|
return (PVOID)(((PBYTE)&__ImageBase) + rva);
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// Unload support
|
||
|
//
|
||
|
|
||
|
// routine definition; takes a pointer to a name to unload
|
||
|
//
|
||
|
#if DELAYLOAD_VERSION >= 0x0200
|
||
|
ExternC
|
||
|
BOOL WINAPI
|
||
|
__FUnloadDelayLoadedDLL2(LPCSTR szDll);
|
||
|
#else
|
||
|
ExternC
|
||
|
BOOL WINAPI
|
||
|
__FUnloadDelayLoadedDLL(LPCSTR szDll);
|
||
|
#endif
|
||
|
|
||
|
// structure definitions for the list of unload records
|
||
|
typedef struct UnloadInfo * PUnloadInfo;
|
||
|
typedef struct UnloadInfo {
|
||
|
PUnloadInfo puiNext;
|
||
|
PCImgDelayDescr pidd;
|
||
|
} UnloadInfo;
|
||
|
|
||
|
// the default delay load helper places the unloadinfo records in the list
|
||
|
// headed by the following pointer.
|
||
|
ExternC
|
||
|
extern
|
||
|
PUnloadInfo __puiHead;
|
||
|
|
||
|
//
|
||
|
// Exception information
|
||
|
//
|
||
|
#define FACILITY_VISUALCPP ((LONG)0x6d)
|
||
|
#define VcppException(sev,err) ((sev) | (FACILITY_VISUALCPP<<16) | err)
|
||
|
|
||
|
// utility function for calculating the count of imports given the base
|
||
|
// of the IAT. NB: this only works on a valid IAT!
|
||
|
__inline unsigned
|
||
|
CountOfImports(PCImgThunkData pitdBase) {
|
||
|
unsigned cRet = 0;
|
||
|
PCImgThunkData pitd = pitdBase;
|
||
|
while (pitd->u1.Function) {
|
||
|
pitd++;
|
||
|
cRet++;
|
||
|
}
|
||
|
return cRet;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Hook pointers
|
||
|
//
|
||
|
|
||
|
// The "notify hook" gets called for every call to the
|
||
|
// delay load helper. This allows a user to hook every call and
|
||
|
// skip the delay load helper entirely.
|
||
|
//
|
||
|
// dliNotify == {
|
||
|
// dliStartProcessing |
|
||
|
// dliPreLoadLibrary |
|
||
|
// dliPreGetProc |
|
||
|
// dliNoteEndProcessing}
|
||
|
// on this call.
|
||
|
//
|
||
|
ExternC
|
||
|
extern
|
||
|
PfnDliHook __pfnDliNotifyHook;
|
||
|
|
||
|
ExternC
|
||
|
extern
|
||
|
PfnDliHook __pfnDliNotifyHook2;
|
||
|
|
||
|
// This is the failure hook, dliNotify = {dliFailLoadLib|dliFailGetProc}
|
||
|
ExternC
|
||
|
extern
|
||
|
PfnDliHook __pfnDliFailureHook;
|
||
|
|
||
|
ExternC
|
||
|
extern
|
||
|
PfnDliHook __pfnDliFailureHook2;
|
||
|
|
||
|
#if DELAYLOAD_VERSION >= 0x0200
|
||
|
#define __pfnDliFailureHook __pfnDliFailureHook2
|
||
|
#define __pfnDliNotifyHook __pfnDliNotifyHook2
|
||
|
#endif
|
||
|
|
||
|
#endif
|