Implement delayimp lib

This library will allow to delay import from dlls, if used together with the corresponding delayimport lib for that dll. An initial patch for dlltool can be found in bug #4730.
Based on Matt Pietrek's "Under the Hood" article: http://www.microsoft.com/msj/1298/hood/hood1298.aspx and msdn documentation.

svn path=/trunk/; revision=42169
This commit is contained in:
Timo Kreuzer 2009-07-24 04:24:36 +00:00
parent 9fd89d0e43
commit ceff19824f
4 changed files with 181 additions and 0 deletions

View file

@ -0,0 +1,106 @@
#include <windows.h>
#include "delayimp.h"
inline
unsigned
IndexFromPImgThunkData(PCImgThunkData pData, PCImgThunkData pBase)
{
return pData - pBase;
}
extern const IMAGE_DOS_HEADER _image_base__;
inline PVOID
PFromRva(RVA rva)
{
return (PVOID)(((ULONG_PTR)(rva)) + ((ULONG_PTR)&_image_base__));
}
/**** load helper ****/
FARPROC WINAPI
__delayLoadHelper2(PCImgDelayDescr pidd, PImgThunkData pIATEntry)
{
DelayLoadInfo dli;
int index;
PImgThunkData pIAT;
PImgThunkData pINT;
HMODULE *phMod;
FARPROC pProc;
pIAT = PFromRva(pidd->rvaIAT);
pINT = PFromRva(pidd->rvaINT);
phMod = PFromRva(pidd->rvaHmod);
index = IndexFromPImgThunkData(pIATEntry, pIAT);
dli.cb = sizeof(dli);
dli.pidd = pidd;
dli.ppfn = (FARPROC*)pIATEntry->u1.Function;
dli.szDll = PFromRva(pidd->rvaDLLName);
dli.dlp.fImportByName = !(pINT[index].u1.Ordinal & IMAGE_ORDINAL_FLAG);
if (dli.dlp.fImportByName)
{
/* u1.AdressOfData points to a IMAGE_IMPORT_BY_NAME struct */
PIMAGE_IMPORT_BY_NAME piibn = PFromRva((RVA)pINT[index].u1.AddressOfData);
dli.dlp.szProcName = (LPCSTR)&piibn->Name;
}
else
{
dli.dlp.dwOrdinal = pINT[index].u1.Ordinal & ~IMAGE_ORDINAL_FLAG;
}
dli.hmodCur = *phMod;
dli.pfnCur = (FARPROC)pIAT[index].u1.Function;
dli.dwLastError = GetLastError();
pProc = __pfnDliNotifyHook2(dliStartProcessing, &dli);
if (pProc)
{
pIAT[index].u1.Function = (DWORD)pProc;
return pProc;
}
if (dli.hmodCur == NULL)
{
dli.hmodCur = LoadLibraryA(dli.szDll);
if (!dli.hmodCur)
{
dli.dwLastError = GetLastError();
__pfnDliFailureHook2(dliFailLoadLib, &dli);
// if (ret)
// {
// }
// FIXME: raise exception;
return NULL;
}
*phMod = dli.hmodCur;
}
/* dli.dlp.szProcName might also contain the ordinal */
pProc = GetProcAddress(dli.hmodCur, dli.dlp.szProcName);
if (!pProc)
{
dli.dwLastError = GetLastError();
__pfnDliFailureHook2(dliFailGetProc, &dli);
// FIXME: handle return value & raise exception
return NULL;
}
pIAT[index].u1.Function = (DWORD)pProc;
return pProc;
}
/*** The default hooks ***/
FARPROC WINAPI
DefaultDliNotifyHook2(unsigned dliNotify, PDelayLoadInfo pdli)
{
return NULL;
}
FARPROC WINAPI
DefaultDliFailureHook2(unsigned dliNotify, PDelayLoadInfo pdli)
{
return NULL;
}
PfnDliHook __pfnDliNotifyHook2 = DefaultDliNotifyHook2;
PfnDliHook __pfnDliFailureHook2 = DefaultDliFailureHook2;

View file

@ -0,0 +1,65 @@
#ifndef _DELAYIMP_H_
#define _DELAYIMP_H_
typedef void *RVA;
typedef IMAGE_THUNK_DATA *PImgThunkData;
typedef const IMAGE_THUNK_DATA *PCImgThunkData;
enum
{
dlattrRva
};
/* Notification codes */
enum
{
dliStartProcessing,
dliNotePreLoadLibrary,
dliNotePreGetProcAddress,
dliFailLoadLib,
dliFailGetProc,
dliNoteEndProcessing,
};
typedef struct ImgDelayDescr
{
DWORD grAttrs;
RVA rvaDLLName;
RVA rvaHmod;
RVA rvaIAT;
RVA rvaINT;
RVA rvaBoundIAT;
RVA rvaUnloadIAT;
DWORD dwTimeStamp;
} ImgDelayDescr, *PImgDelayDescr;
typedef const ImgDelayDescr *PCImgDelayDescr;
typedef struct DelayLoadProc
{
BOOL fImportByName;
union
{
LPCSTR szProcName;
DWORD dwOrdinal;
};
} DelayLoadProc;
typedef struct DelayLoadInfo
{
DWORD cb;
PCImgDelayDescr pidd;
FARPROC *ppfn;
LPCSTR szDll;
DelayLoadProc dlp;
HMODULE hmodCur;
FARPROC pfnCur;
DWORD dwLastError;
} DelayLoadInfo, *PDelayLoadInfo;
typedef FARPROC (WINAPI *PfnDliHook)(unsigned, PDelayLoadInfo);
extern PfnDliHook __pfnDliNotifyHook2;
extern PfnDliHook __pfnDliFailureHook2;
#endif /* not _DELAYIMP_H_ */

View file

@ -0,0 +1,7 @@
<?xml version="1.0"?>
<!DOCTYPE group SYSTEM "../../../tools/rbuild/project.dtd">
<group>
<module name="delayimp" type="staticlibrary" unicode="yes">
<file>delayimp.c</file>
</module>
</group>

View file

@ -5,6 +5,9 @@
<xi:include href="crt/crt.rbuild" />
<xi:include href="crt/libcntpr.rbuild" />
</directory>
<directory name="delayimp">
<xi:include href="delayimp/delayimp.rbuild" />
</directory>
<directory name="dxguid">
<xi:include href="dxguid/dxguid.rbuild" />
</directory>