2bb93784c6
zig can now cross compile hello.c targeting windows
280 lines
8.3 KiB
C
280 lines
8.3 KiB
C
/**
|
|
* This file has no copyright assigned and is placed in the Public Domain.
|
|
* This file is part of the mingw-w64 runtime package.
|
|
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
|
|
*
|
|
* This file is derived from Microsoft implementation file delayhlp.cpp, which
|
|
* is free for users to modify and derive.
|
|
*/
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <windows.h>
|
|
#include <delayimp.h>
|
|
|
|
static size_t __strlen(const char *sz)
|
|
{
|
|
const char *szEnd = sz;
|
|
while(*szEnd++ != 0)
|
|
;
|
|
return szEnd - sz - 1;
|
|
}
|
|
|
|
static int __memcmp(const void *pv1,const void *pv2,size_t cb)
|
|
{
|
|
if(!cb)
|
|
return 0;
|
|
while(--cb && *(char *)pv1 == *(char *)pv2) {
|
|
pv1 = ((char *)pv1) + 1;
|
|
pv2 = ((char *)pv2) + 1;
|
|
}
|
|
return *((unsigned char *)pv1) - *((unsigned char *)pv2);
|
|
}
|
|
|
|
static void *__memcpy(void *pvDst,const void *pvSrc,size_t cb)
|
|
{
|
|
void *pvRet = pvDst;
|
|
while(cb--) {
|
|
*(char *)pvDst = *(char *)pvSrc;
|
|
pvDst = ((char *)pvDst) + 1;
|
|
pvSrc = ((char *)pvSrc) + 1;
|
|
}
|
|
return pvRet;
|
|
}
|
|
|
|
static unsigned IndexFromPImgThunkData(PCImgThunkData pitdCur,PCImgThunkData pitdBase)
|
|
{
|
|
return (unsigned) (pitdCur - pitdBase);
|
|
}
|
|
|
|
#define __ImageBase __MINGW_LSYMBOL(_image_base__)
|
|
extern IMAGE_DOS_HEADER __ImageBase;
|
|
|
|
#define PtrFromRVA(RVA) (((PBYTE)&__ImageBase) + (RVA))
|
|
|
|
typedef struct UnloadInfo *PUnloadInfo;
|
|
typedef struct UnloadInfo {
|
|
PUnloadInfo puiNext;
|
|
PCImgDelayDescr pidd;
|
|
} UnloadInfo;
|
|
|
|
static unsigned CountOfImports(PCImgThunkData pitdBase)
|
|
{
|
|
unsigned cRet = 0;
|
|
PCImgThunkData pitd = pitdBase;
|
|
while(pitd->u1.Function) {
|
|
pitd++;
|
|
cRet++;
|
|
}
|
|
return cRet;
|
|
}
|
|
|
|
PUnloadInfo __puiHead = 0;
|
|
|
|
static UnloadInfo *add_ULI(PCImgDelayDescr pidd_)
|
|
{
|
|
UnloadInfo *ret = (UnloadInfo *) LocalAlloc(LPTR,sizeof(UnloadInfo));
|
|
ret->pidd = pidd_;
|
|
ret->puiNext = __puiHead;
|
|
__puiHead = ret;
|
|
return ret;
|
|
}
|
|
|
|
static void del_ULI(UnloadInfo *p)
|
|
{
|
|
if (p) {
|
|
PUnloadInfo *ppui = &__puiHead;
|
|
while(*ppui && *ppui!=p) {
|
|
ppui = &((*ppui)->puiNext);
|
|
}
|
|
if(*ppui==p) *ppui = p->puiNext;
|
|
LocalFree((void *)p);
|
|
}
|
|
}
|
|
|
|
typedef struct InternalImgDelayDescr {
|
|
DWORD grAttrs;
|
|
LPCSTR szName;
|
|
HMODULE *phmod;
|
|
PImgThunkData pIAT;
|
|
PCImgThunkData pINT;
|
|
PCImgThunkData pBoundIAT;
|
|
PCImgThunkData pUnloadIAT;
|
|
DWORD dwTimeStamp;
|
|
} InternalImgDelayDescr;
|
|
|
|
typedef InternalImgDelayDescr *PIIDD;
|
|
typedef const InternalImgDelayDescr *PCIIDD;
|
|
|
|
static PIMAGE_NT_HEADERS WINAPI PinhFromImageBase(HMODULE hmod)
|
|
{
|
|
return (PIMAGE_NT_HEADERS) (((PBYTE)(hmod)) + ((PIMAGE_DOS_HEADER)(hmod))->e_lfanew);
|
|
}
|
|
|
|
static void WINAPI OverlayIAT(PImgThunkData pitdDst,PCImgThunkData pitdSrc)
|
|
{
|
|
__memcpy(pitdDst,pitdSrc,CountOfImports(pitdDst) * sizeof(IMAGE_THUNK_DATA));
|
|
}
|
|
|
|
static DWORD WINAPI TimeStampOfImage(PIMAGE_NT_HEADERS pinh)
|
|
{
|
|
return pinh->FileHeader.TimeDateStamp;
|
|
}
|
|
|
|
static int WINAPI FLoadedAtPreferredAddress(PIMAGE_NT_HEADERS pinh,HMODULE hmod)
|
|
{
|
|
return ((UINT_PTR)(hmod)) == pinh->OptionalHeader.ImageBase;
|
|
}
|
|
|
|
#if(defined(_X86_) && !defined(__x86_64))
|
|
#undef InterlockedExchangePointer
|
|
#define InterlockedExchangePointer(Target,Value) (PVOID)(LONG_PTR)InterlockedExchange((PLONG)(Target),(LONG)(LONG_PTR)(Value))
|
|
/*typedef unsigned long *PULONG_PTR;*/
|
|
#endif
|
|
|
|
FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd,FARPROC *ppfnIATEntry);
|
|
|
|
FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd,FARPROC *ppfnIATEntry)
|
|
{
|
|
InternalImgDelayDescr idd = {
|
|
pidd->grAttrs,(LPCTSTR) PtrFromRVA(pidd->rvaDLLName),(HMODULE *) PtrFromRVA(pidd->rvaHmod),
|
|
(PImgThunkData) PtrFromRVA(pidd->rvaIAT), (PCImgThunkData) PtrFromRVA(pidd->rvaINT),
|
|
(PCImgThunkData) PtrFromRVA(pidd->rvaBoundIAT), (PCImgThunkData) PtrFromRVA(pidd->rvaUnloadIAT),
|
|
pidd->dwTimeStamp};
|
|
DelayLoadInfo dli = {
|
|
sizeof(DelayLoadInfo),pidd,ppfnIATEntry,idd.szName,{ 0, { NULL } },0,0,0
|
|
};
|
|
HMODULE hmod;
|
|
unsigned iIAT, iINT;
|
|
PCImgThunkData pitd;
|
|
FARPROC pfnRet;
|
|
|
|
if(!(idd.grAttrs & dlattrRva)) {
|
|
PDelayLoadInfo rgpdli[1] = { &dli};
|
|
RaiseException(VcppException(ERROR_SEVERITY_ERROR,ERROR_INVALID_PARAMETER),0,1,(PULONG_PTR)(rgpdli));
|
|
return 0;
|
|
}
|
|
hmod = *idd.phmod;
|
|
iIAT = IndexFromPImgThunkData((PCImgThunkData)(ppfnIATEntry),idd.pIAT);
|
|
iINT = iIAT;
|
|
pitd = &(idd.pINT[iINT]);
|
|
|
|
dli.dlp.fImportByName = !IMAGE_SNAP_BY_ORDINAL(pitd->u1.Ordinal);
|
|
if(dli.dlp.fImportByName)
|
|
dli.dlp.szProcName =
|
|
(LPCSTR)
|
|
(
|
|
((PIMAGE_IMPORT_BY_NAME) PtrFromRVA(
|
|
(RVA)((UINT_PTR)(pitd->u1.AddressOfData))
|
|
)
|
|
)->Name
|
|
);
|
|
else dli.dlp.dwOrdinal = (DWORD)(IMAGE_ORDINAL(pitd->u1.Ordinal));
|
|
pfnRet = NULL;
|
|
if(__pfnDliNotifyHook2) {
|
|
pfnRet = ((*__pfnDliNotifyHook2)(dliStartProcessing,&dli));
|
|
if(pfnRet!=NULL) goto HookBypass;
|
|
}
|
|
if(hmod==0) {
|
|
if(__pfnDliNotifyHook2)
|
|
hmod = (HMODULE) (((*__pfnDliNotifyHook2)(dliNotePreLoadLibrary,&dli)));
|
|
if(hmod==0) hmod = LoadLibrary(dli.szDll);
|
|
if(hmod==0) {
|
|
dli.dwLastError = GetLastError();
|
|
if(__pfnDliFailureHook2)
|
|
hmod = (HMODULE) ((*__pfnDliFailureHook2)(dliFailLoadLib,&dli));
|
|
if(hmod==0) {
|
|
PDelayLoadInfo rgpdli[1] = { &dli};
|
|
RaiseException(VcppException(ERROR_SEVERITY_ERROR,ERROR_MOD_NOT_FOUND),0,1,(PULONG_PTR)(rgpdli));
|
|
return dli.pfnCur;
|
|
}
|
|
}
|
|
HMODULE hmodT = (HMODULE)(InterlockedExchangePointer((PVOID *) idd.phmod,(PVOID)(hmod)));
|
|
if(hmodT!=hmod) {
|
|
if(pidd->rvaUnloadIAT) add_ULI(pidd);
|
|
} else FreeLibrary(hmod);
|
|
}
|
|
dli.hmodCur = hmod;
|
|
if(__pfnDliNotifyHook2) pfnRet = (*__pfnDliNotifyHook2)(dliNotePreGetProcAddress,&dli);
|
|
if(pfnRet==0) {
|
|
if(pidd->rvaBoundIAT && pidd->dwTimeStamp) {
|
|
PIMAGE_NT_HEADERS pinh = (PIMAGE_NT_HEADERS) (PinhFromImageBase(hmod));
|
|
if(pinh->Signature==IMAGE_NT_SIGNATURE &&
|
|
TimeStampOfImage(pinh)==idd.dwTimeStamp &&
|
|
FLoadedAtPreferredAddress(pinh,hmod)) {
|
|
pfnRet = (FARPROC) ((UINT_PTR)(idd.pBoundIAT[iIAT].u1.Function));
|
|
if(pfnRet!=0) goto SetEntryHookBypass;
|
|
}
|
|
}
|
|
pfnRet = GetProcAddress(hmod,dli.dlp.szProcName);
|
|
}
|
|
if(!pfnRet) {
|
|
dli.dwLastError = GetLastError();
|
|
if(__pfnDliFailureHook2) pfnRet = (*__pfnDliFailureHook2)(dliFailGetProc,&dli);
|
|
if(!pfnRet) {
|
|
PDelayLoadInfo rgpdli[1] = { &dli};
|
|
RaiseException(VcppException(ERROR_SEVERITY_ERROR,ERROR_PROC_NOT_FOUND),0,1,(PULONG_PTR)(rgpdli));
|
|
pfnRet = dli.pfnCur;
|
|
}
|
|
}
|
|
SetEntryHookBypass:
|
|
*ppfnIATEntry = pfnRet;
|
|
HookBypass:
|
|
if(__pfnDliNotifyHook2) {
|
|
dli.dwLastError = 0;
|
|
dli.hmodCur = hmod;
|
|
dli.pfnCur = pfnRet;
|
|
(*__pfnDliNotifyHook2)(dliNoteEndProcessing,&dli);
|
|
}
|
|
return pfnRet;
|
|
}
|
|
|
|
WINBOOL WINAPI __FUnloadDelayLoadedDLL2(LPCSTR szDll)
|
|
{
|
|
WINBOOL fRet = FALSE;
|
|
PUnloadInfo pui = __puiHead;
|
|
|
|
for(pui = __puiHead;pui;pui = pui->puiNext) {
|
|
LPCSTR szName = (LPCTSTR) PtrFromRVA(pui->pidd->rvaDLLName);
|
|
size_t cbName = __strlen(szName);
|
|
if(cbName==__strlen(szDll) && __memcmp(szDll,szName,cbName)==0) break;
|
|
}
|
|
if(pui && pui->pidd->rvaUnloadIAT) {
|
|
PCImgDelayDescr pidd = pui->pidd;
|
|
HMODULE *phmod = (HMODULE *) PtrFromRVA(pidd->rvaHmod);
|
|
HMODULE hmod = *phmod;
|
|
OverlayIAT((PImgThunkData) PtrFromRVA(pidd->rvaIAT), (PCImgThunkData) PtrFromRVA(pidd->rvaUnloadIAT));
|
|
FreeLibrary(hmod);
|
|
*phmod = NULL;
|
|
del_ULI((UnloadInfo *) pui);
|
|
fRet = TRUE;
|
|
}
|
|
return fRet;
|
|
}
|
|
|
|
HRESULT WINAPI __HrLoadAllImportsForDll(LPCSTR szDll)
|
|
{
|
|
HRESULT hrRet = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
|
|
PIMAGE_NT_HEADERS pinh = PinhFromImageBase((HMODULE) (&__ImageBase));
|
|
if(pinh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size) {
|
|
PCImgDelayDescr pidd;
|
|
pidd = (PCImgDelayDescr) PtrFromRVA(pinh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress);
|
|
while(pidd->rvaDLLName) {
|
|
LPCSTR szDllCur = (LPCSTR) PtrFromRVA(pidd->rvaDLLName);
|
|
size_t cchDllCur = __strlen(szDllCur);
|
|
if(cchDllCur==__strlen(szDll) && __memcmp(szDll,szDllCur,cchDllCur)==0) break;
|
|
pidd++;
|
|
}
|
|
if(pidd->rvaDLLName) {
|
|
FARPROC *ppfnIATEntry = (FARPROC *) PtrFromRVA(pidd->rvaIAT);
|
|
size_t cpfnIATEntries = CountOfImports((PCImgThunkData) (ppfnIATEntry));
|
|
FARPROC *ppfnIATEntryMax = ppfnIATEntry + cpfnIATEntries;
|
|
for(;ppfnIATEntry < ppfnIATEntryMax;ppfnIATEntry++) {
|
|
__delayLoadHelper2(pidd,ppfnIATEntry);
|
|
}
|
|
hrRet = S_OK;
|
|
}
|
|
}
|
|
return hrRet;
|
|
}
|