/**
 * This file has no copyright assigned and is placed in the Public Domain.
 * This file is part of the w64 mingw-runtime package.
 * No warranty is given; refer to the file DISCLAIMER within this package.
 */
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#include "DelayImp.h"

static inline size_t __strlen(const char *sz) {
  const char *szEnd = sz;
  while(*szEnd++)
    ;
  return szEnd - sz - 1;
}

static inline 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 inline 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;
}

inline unsigned IndexFromPImgThunkData(PCImgThunkData pitdCur,PCImgThunkData pitdBase) { return (unsigned) (pitdCur - pitdBase);}

extern "C"
const IMAGE_DOS_HEADER __ImageBase;

template <class X>
X PFromRva(RVA rva) { return X(PBYTE(&__ImageBase) + rva);}

typedef struct UnloadInfo *PUnloadInfo;
typedef struct UnloadInfo {
  PUnloadInfo puiNext;
  PCImgDelayDescr pidd;
} UnloadInfo;

inline unsigned CountOfImports(PCImgThunkData pitdBase) {
  unsigned cRet = 0;
  PCImgThunkData pitd = pitdBase;
  while(pitd->u1.Function) {
    pitd++;
    cRet++;
  }
  return cRet;
}

extern "C"
PUnloadInfo __puiHead = 0;

struct ULI : public UnloadInfo {
  ULI(PCImgDelayDescr pidd_) {
    pidd = pidd_;
    Link();
  }
  ~ULI() {
    Unlink();
  }
  void *operator new(size_t cb) { return ::LocalAlloc(LPTR,cb);}
  void operator delete(void *pv) { ::LocalFree(pv);}
  void Unlink() {
    PUnloadInfo *ppui = &__puiHead;
    while(*ppui && *ppui!=this) {
      ppui = &((*ppui)->puiNext);
    }
    if(*ppui==this) *ppui = puiNext;
  }
  void Link() {
    puiNext = __puiHead;
    __puiHead = this;
  }
};

struct InternalImgDelayDescr {
  DWORD grAttrs;
  LPCSTR szName;
  HMODULE *phmod;
  PImgThunkData pIAT;
  PCImgThunkData pINT;
  PCImgThunkData pBoundIAT;
  PCImgThunkData pUnloadIAT;
  DWORD dwTimeStamp;
};

typedef InternalImgDelayDescr *PIIDD;
typedef const InternalImgDelayDescr *PCIIDD;

static inline PIMAGE_NT_HEADERS WINAPI PinhFromImageBase(HMODULE hmod) { return PIMAGE_NT_HEADERS(PBYTE(hmod) + PIMAGE_DOS_HEADER(hmod)->e_lfanew);}
static inline void WINAPI OverlayIAT(PImgThunkData pitdDst,PCImgThunkData pitdSrc) { __memcpy(pitdDst,pitdSrc,CountOfImports(pitdDst) *sizeof IMAGE_THUNK_DATA);}
static inline DWORD WINAPI TimeStampOfImage(PIMAGE_NT_HEADERS pinh) { return pinh->FileHeader.TimeDateStamp;}
static inline bool 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

extern "C"
FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd,FARPROC *ppfnIATEntry) {
  InternalImgDelayDescr idd = {
    pidd->grAttrs,PFromRva<LPCSTR>(pidd->rvaDLLName),PFromRva<HMODULE*>(pidd->rvaHmod),PFromRva<PImgThunkData>(pidd->rvaIAT),PFromRva<PCImgThunkData>(pidd->rvaINT),PFromRva<PCImgThunkData>(pidd->rvaBoundIAT),PFromRva<PCImgThunkData>(pidd->rvaUnloadIAT),pidd->dwTimeStamp
  };
  DelayLoadInfo dli = {
    sizeof DelayLoadInfo,pidd,ppfnIATEntry,idd.szName,{ 0},0,0,0
  };

  if(0==(idd.grAttrs & dlattrRva)) {
    PDelayLoadInfo rgpdli[1] = { &dli};
    RaiseException(VcppException(ERROR_SEVERITY_ERROR,ERROR_INVALID_PARAMETER),0,1,PULONG_PTR(rgpdli));
    return 0;
  }
  HMODULE hmod = *idd.phmod;
  const unsigned iIAT = IndexFromPImgThunkData(PCImgThunkData(ppfnIATEntry),idd.pIAT);
  const unsigned iINT = iIAT;
  PCImgThunkData pitd = &(idd.pINT[iINT]);

  dli.dlp.fImportByName = !IMAGE_SNAP_BY_ORDINAL(pitd->u1.Ordinal);
  if(dli.dlp.fImportByName) dli.dlp.szProcName = LPCSTR(PFromRva<PIMAGE_IMPORT_BY_NAME>(RVA(UINT_PTR(pitd->u1.AddressOfData)))->Name);
  else dli.dlp.dwOrdinal = DWORD(IMAGE_ORDINAL(pitd->u1.Ordinal));
  FARPROC 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) new 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(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==0) {
    dli.dwLastError = ::GetLastError();
    if(__pfnDliFailureHook2) pfnRet = (*__pfnDliFailureHook2)(dliFailGetProc,&dli);
    if(pfnRet==0) {
      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;
}

extern "C"
WINBOOL WINAPI __FUnloadDelayLoadedDLL2(LPCSTR szDll) {
  WINBOOL fRet = FALSE;
  PUnloadInfo pui = __puiHead;

  for(pui = __puiHead;pui;pui = pui->puiNext) {
    LPCSTR szName = PFromRva<LPCSTR>(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 = PFromRva<HMODULE*>(pidd->rvaHmod);
    HMODULE hmod = *phmod;
    OverlayIAT(PFromRva<PImgThunkData>(pidd->rvaIAT),PFromRva<PCImgThunkData>(pidd->rvaUnloadIAT));
    ::FreeLibrary(hmod);
    *phmod = NULL;
    delete reinterpret_cast<ULI*> (pui);
    fRet = TRUE;
  }
  return fRet;
}

extern "C"
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 = PFromRva<PCImgDelayDescr>(pinh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress);
    while(pidd->rvaDLLName) {
      LPCSTR szDllCur = PFromRva<LPCSTR>(pidd->rvaDLLName);
      size_t cchDllCur = __strlen(szDllCur);
      if(cchDllCur==__strlen(szDll) && __memcmp(szDll,szDllCur,cchDllCur)==0) break;
      pidd++;
    }
    if(pidd->rvaDLLName) {
      FARPROC *ppfnIATEntry = PFromRva<FARPROC*>(pidd->rvaIAT);
      size_t cpfnIATEntries = CountOfImports(PCImgThunkData(ppfnIATEntry));
      FARPROC *ppfnIATEntryMax = ppfnIATEntry + cpfnIATEntries;
      for(;ppfnIATEntry < ppfnIATEntryMax;ppfnIATEntry++) {
	__delayLoadHelper2(pidd,ppfnIATEntry);
      }
      hrRet = S_OK;
    }
  }
  return hrRet;
}
