STLdoc
STLdocumentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Classes | Macros | Typedefs | Functions | Variables
delayhlp.cpp File Reference
#include <windows.h>
#include "DelayImp.h"

Classes

struct  InternalImgDelayDescr
 

Macros

#define WIN32_LEAN_AND_MEAN
 
#define STRICT
 

Typedefs

typedef InternalImgDelayDescrPIIDD
 
typedef const InternalImgDelayDescrPCIIDD
 

Functions

static size_t __strlen (const char *sz)
 
static int __memcmp (const void *pv1, const void *pv2, size_t cb)
 
static void__memcpy (void *pvDst, const void *pvSrc, size_t cb)
 
unsigned IndexFromPImgThunkData (PCImgThunkData pitdCur, PCImgThunkData pitdBase)
 
template<class X >
PFromRva (RVA rva)
 
unsigned CountOfImports (PCImgThunkData pitdBase)
 
static PIMAGE_NT_HEADERS WINAPI PinhFromImageBase (HMODULE hmod)
 
static void WINAPI OverlayIAT (PImgThunkData pitdDst, PCImgThunkData pitdSrc)
 
static DWORD WINAPI TimeStampOfImage (PIMAGE_NT_HEADERS pinh)
 
static bool WINAPI FLoadedAtPreferredAddress (PIMAGE_NT_HEADERS pinh, HMODULE hmod)
 
static PCImgDelayDescr PiddFromDllName (LPCSTR szDll)
 
FARPROC WINAPI __delayLoadHelper2 (PCImgDelayDescr pidd, FARPROC *ppfnIATEntry)
 
BOOL WINAPI __FUnloadDelayLoadedDLL2 (LPCSTR szDll)
 
HRESULT WINAPI __HrLoadAllImportsForDll (LPCSTR szDll)
 

Variables

const IMAGE_DOS_HEADER __ImageBase
 

Macro Definition Documentation

#define STRICT
#define WIN32_LEAN_AND_MEAN

Typedef Documentation

typedef const InternalImgDelayDescr* PCIIDD

Function Documentation

FARPROC WINAPI __delayLoadHelper2 ( PCImgDelayDescr  pidd,
FARPROC *  ppfnIATEntry 
)
210  {
211 
212  // Set up some data we use for the hook procs but also useful for
213  // our own use
214  //
215  InternalImgDelayDescr idd = {
216  pidd->grAttrs,
217  PFromRva<LPCSTR>(pidd->rvaDLLName),
218  PFromRva<HMODULE*>(pidd->rvaHmod),
219  PFromRva<PImgThunkData>(pidd->rvaIAT),
220  PFromRva<PCImgThunkData>(pidd->rvaINT),
221  PFromRva<PCImgThunkData>(pidd->rvaBoundIAT),
222  PFromRva<PCImgThunkData>(pidd->rvaUnloadIAT),
223  pidd->dwTimeStamp
224  };
225 
226  DelayLoadInfo dli = {
227  sizeof DelayLoadInfo,
228  pidd,
229  ppfnIATEntry,
230  idd.szName,
231  { 0 },
232  0,
233  0,
234  0
235  };
236 
237  if (0 == (idd.grAttrs & dlattrRva)) {
238  PDelayLoadInfo rgpdli[1] = { &dli };
239 
240  RaiseException(
241  VcppException(ERROR_SEVERITY_ERROR, ERROR_INVALID_PARAMETER),
242  0,
243  1,
244  PULONG_PTR(rgpdli)
245  );
246  return 0;
247  }
248 
249  HMODULE hmod = *idd.phmod;
250 
251  // Calculate the index for the IAT entry in the import address table
252  // N.B. The INT entries are ordered the same as the IAT entries so
253  // the calculation can be done on the IAT side.
254  //
255  const unsigned iIAT = IndexFromPImgThunkData(PCImgThunkData(ppfnIATEntry), idd.pIAT);
256  const unsigned iINT = iIAT;
257 
258  PCImgThunkData pitd = &(idd.pINT[iINT]);
259 
260  dli.dlp.fImportByName = !IMAGE_SNAP_BY_ORDINAL(pitd->u1.Ordinal);
261 
262  if (dli.dlp.fImportByName) {
263  dli.dlp.szProcName = LPCSTR(PFromRva<PIMAGE_IMPORT_BY_NAME>(RVA(UINT_PTR(pitd->u1.AddressOfData)))->Name);
264  }
265  else {
266  dli.dlp.dwOrdinal = DWORD(IMAGE_ORDINAL(pitd->u1.Ordinal));
267  }
268 
269  // Call the initial hook. If it exists and returns a function pointer,
270  // abort the rest of the processing and just return it for the call.
271  //
272  FARPROC pfnRet = NULL;
273 
274  if (__pfnDliNotifyHook2) {
275  pfnRet = ((*__pfnDliNotifyHook2)(dliStartProcessing, &dli));
276 
277  if (pfnRet != NULL) {
278  goto HookBypass;
279  }
280  }
281 
282  // Check to see if we need to try to load the library.
283  //
284  if (hmod == 0) {
285  if (__pfnDliNotifyHook2) {
286  hmod = HMODULE(((*__pfnDliNotifyHook2)(dliNotePreLoadLibrary, &dli)));
287  }
288  if (hmod == 0) {
289  hmod = ::LoadLibraryEx(dli.szDll, NULL, 0);
290  }
291  if (hmod == 0) {
292  dli.dwLastError = ::GetLastError();
293  if (__pfnDliFailureHook2) {
294  // when the hook is called on LoadLibrary failure, it will
295  // return 0 for failure and an hmod for the lib if it fixed
296  // the problem.
297  //
298  hmod = HMODULE((*__pfnDliFailureHook2)(dliFailLoadLib, &dli));
299  }
300 
301  if (hmod == 0) {
302  PDelayLoadInfo rgpdli[1] = { &dli };
303 
304  RaiseException(
305  VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND),
306  0,
307  1,
308  PULONG_PTR(rgpdli)
309  );
310 
311  // If we get to here, we blindly assume that the handler of the exception
312  // has magically fixed everything up and left the function pointer in
313  // dli.pfnCur.
314  //
315  return dli.pfnCur;
316  }
317  }
318 
319  // Store the library handle. If it is already there, we infer
320  // that another thread got there first, and we need to do a
321  // FreeLibrary() to reduce the refcount
322  //
323  HMODULE hmodT = HMODULE(InterlockedExchangePointer((PVOID *) idd.phmod, PVOID(hmod)));
324  if (hmodT == hmod) {
325  ::FreeLibrary(hmod);
326  }
327  }
328 
329  // Go for the procedure now.
330  //
331  dli.hmodCur = hmod;
332  if (__pfnDliNotifyHook2) {
333  pfnRet = (*__pfnDliNotifyHook2)(dliNotePreGetProcAddress, &dli);
334  }
335  if (pfnRet == 0) {
336  if (pidd->rvaBoundIAT && pidd->dwTimeStamp) {
337  // bound imports exist...check the timestamp from the target image
338  //
339  PIMAGE_NT_HEADERS pinh(PinhFromImageBase(hmod));
340 
341  if (pinh->Signature == IMAGE_NT_SIGNATURE &&
342  TimeStampOfImage(pinh) == idd.dwTimeStamp &&
343  FLoadedAtPreferredAddress(pinh, hmod)) {
344 
345  // Everything is good to go, if we have a decent address
346  // in the bound IAT!
347  //
348  pfnRet = FARPROC(UINT_PTR(idd.pBoundIAT[iIAT].u1.Function));
349  if (pfnRet != 0) {
350  goto SetEntryHookBypass;
351  }
352  }
353  }
354 
355  pfnRet = ::GetProcAddress(hmod, dli.dlp.szProcName);
356  }
357 
358  if (pfnRet == 0) {
359  dli.dwLastError = ::GetLastError();
360  if (__pfnDliFailureHook2) {
361  // when the hook is called on GetProcAddress failure, it will
362  // return 0 on failure and a valid proc address on success
363  //
364  pfnRet = (*__pfnDliFailureHook2)(dliFailGetProc, &dli);
365  }
366  if (pfnRet == 0) {
367  PDelayLoadInfo rgpdli[1] = { &dli };
368 
369  RaiseException(
370  VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND),
371  0,
372  1,
373  PULONG_PTR(rgpdli)
374  );
375 
376  // If we get to here, we blindly assume that the handler of the exception
377  // has magically fixed everything up and left the function pointer in
378  // dli.pfnCur.
379  //
380  pfnRet = dli.pfnCur;
381  }
382  }
383 
384 SetEntryHookBypass:
385  *ppfnIATEntry = pfnRet;
386 
387 HookBypass:
388  if (__pfnDliNotifyHook2) {
389  dli.dwLastError = 0;
390  dli.hmodCur = hmod;
391  dli.pfnCur = pfnRet;
392  (*__pfnDliNotifyHook2)(dliNoteEndProcessing, &dli);
393  }
394  return pfnRet;
395  }
Definition: delayimp.h:70
RVA rvaUnloadIAT
Definition: delayimp.h:29
FARPROC pfnCur
Definition: delayimp.h:77
static DWORD WINAPI TimeStampOfImage(PIMAGE_NT_HEADERS pinh)
Definition: delayhlp.cpp:145
Definition: delayimp.h:55
RVA rvaHmod
Definition: delayimp.h:25
LPCSTR szName
Definition: delayhlp.cpp:118
Definition: delayimp.h:37
Definition: delayimp.h:53
Definition: delayimp.h:46
BOOL fImportByName
Definition: delayimp.h:63
RVA rvaDLLName
Definition: delayimp.h:24
PCImgThunkData pINT
Definition: delayhlp.cpp:121
#define NULL
Definition: crtdbg.h:30
RVA rvaIAT
Definition: delayimp.h:26
static PIMAGE_NT_HEADERS WINAPI PinhFromImageBase(HMODULE hmod)
Definition: delayhlp.cpp:133
DWORD dwTimeStamp
Definition: delayimp.h:30
LPCSTR szProcName
Definition: delayimp.h:65
DelayLoadProc dlp
Definition: delayimp.h:75
DWORD dwLastError
Definition: delayimp.h:78
HMODULE hmodCur
Definition: delayimp.h:76
struct DelayLoadInfo DelayLoadInfo
DWORD grAttrs
Definition: delayimp.h:23
HMODULE * phmod
Definition: delayhlp.cpp:119
DWORD RVA
Definition: delayimp.h:20
unsigned long DWORD
Definition: concrt.h:57
LPCSTR szDll
Definition: delayimp.h:74
ExternC PfnDliHook __pfnDliFailureHook2
Definition: delayimp.h:130
DWORD dwOrdinal
Definition: delayimp.h:66
Definition: delayhlp.cpp:116
PCImgThunkData pBoundIAT
Definition: delayhlp.cpp:122
PImgThunkData pIAT
Definition: delayhlp.cpp:120
DWORD grAttrs
Definition: delayhlp.cpp:117
const IMAGE_THUNK_DATA * PCImgThunkData
Definition: delayimp.h:19
static bool WINAPI FLoadedAtPreferredAddress(PIMAGE_NT_HEADERS pinh, HMODULE hmod)
Definition: delayhlp.cpp:151
#define VcppException(sev, err)
Definition: delayimp.h:108
DWORD dwTimeStamp
Definition: delayhlp.cpp:124
unsigned IndexFromPImgThunkData(PCImgThunkData pitdCur, PCImgThunkData pitdBase)
Definition: delayhlp.cpp:79
ExternC PfnDliHook __pfnDliNotifyHook2
Definition: delayimp.h:126
Definition: delayimp.h:57
Definition: delayimp.h:49
RVA rvaBoundIAT
Definition: delayimp.h:28
Definition: delayimp.h:51
RVA rvaINT
Definition: delayimp.h:27
BOOL WINAPI __FUnloadDelayLoadedDLL2 ( LPCSTR  szDll)
399  {
400  BOOL fRet = FALSE;
401  PCImgDelayDescr pidd = PiddFromDllName(szDll);
402 
403  if ((pidd != NULL) &&
404  (pidd->rvaUnloadIAT != 0)) {
405  HMODULE * phmod = PFromRva<HMODULE*>(pidd->rvaHmod);
406  HMODULE hmod = *phmod;
407  if (hmod != NULL) {
408  OverlayIAT(
409  PFromRva<PImgThunkData>(pidd->rvaIAT),
410  PFromRva<PCImgThunkData>(pidd->rvaUnloadIAT)
411  );
412  ::FreeLibrary(hmod);
413  *phmod = NULL;
414  fRet = TRUE;
415  }
416 
417  }
418  return fRet;
419  }
RVA rvaUnloadIAT
Definition: delayimp.h:29
RVA rvaHmod
Definition: delayimp.h:25
#define NULL
Definition: crtdbg.h:30
RVA rvaIAT
Definition: delayimp.h:26
static PCImgDelayDescr PiddFromDllName(LPCSTR szDll)
Definition: delayhlp.cpp:157
static void WINAPI OverlayIAT(PImgThunkData pitdDst, PCImgThunkData pitdSrc)
Definition: delayhlp.cpp:139
Definition: delayimp.h:22
HRESULT WINAPI __HrLoadAllImportsForDll ( LPCSTR  szDll)
423  {
424  HRESULT hrRet = HRESULT_FROM_WIN32(ERROR_MOD_NOT_FOUND);
425  PCImgDelayDescr pidd = PiddFromDllName(szDll);
426 
427  if (pidd != NULL) {
428  // Found a matching DLL name, now process it.
429  //
430  // Set up the internal structure
431  //
432  FARPROC * ppfnIATEntry = PFromRva<FARPROC*>(pidd->rvaIAT);
433  size_t cpfnIATEntries = CountOfImports(PCImgThunkData(ppfnIATEntry));
434  FARPROC * ppfnIATEntryMax = ppfnIATEntry + cpfnIATEntries;
435 
436  for (;ppfnIATEntry < ppfnIATEntryMax; ppfnIATEntry++) {
437  __delayLoadHelper2(pidd, ppfnIATEntry);
438  }
439 
440  // Done, indicate some semblance of success
441  //
442  hrRet = S_OK;
443  }
444  return hrRet;
445  }
#define S_OK
Definition: comutil.h:62
#define NULL
Definition: crtdbg.h:30
RVA rvaIAT
Definition: delayimp.h:26
static PCImgDelayDescr PiddFromDllName(LPCSTR szDll)
Definition: delayhlp.cpp:157
Definition: delayimp.h:22
unsigned CountOfImports(PCImgThunkData pitdBase)
Definition: delayhlp.cpp:103
const IMAGE_THUNK_DATA * PCImgThunkData
Definition: delayimp.h:19
FARPROC WINAPI __delayLoadHelper2(PCImgDelayDescr pidd, FARPROC *ppfnIATEntry)
Definition: delayhlp.cpp:207
static int __memcmp ( const void pv1,
const void pv2,
size_t  cb 
)
inlinestatic
45  {
46  if (!cb) {
47  return 0;
48  }
49 
50  while ( --cb && *(char *)pv1 == *(char *)pv2 ) {
51  pv1 = (char *)pv1 + 1;
52  pv2 = (char *)pv2 + 1;
53  }
54 
55  return *((unsigned char *)pv1) - *((unsigned char *)pv2);
56  }
static void* __memcpy ( void pvDst,
const void pvSrc,
size_t  cb 
)
inlinestatic
59  {
60 
61  void * pvRet = pvDst;
62 
63  //
64  // copy from lower addresses to higher addresses
65  //
66  while (cb--) {
67  *(char *)pvDst = *(char *)pvSrc;
68  pvDst = (char *)pvDst + 1;
69  pvSrc = (char *)pvSrc + 1;
70  }
71 
72  return pvRet;
73  }
static size_t __strlen ( const char *  sz)
inlinestatic
34  {
35  const char *szEnd = sz;
36 
37  while( *szEnd++ ) {
38  ;
39  }
40 
41  return szEnd - sz - 1;
42  }
unsigned CountOfImports ( PCImgThunkData  pitdBase)
inline
103  {
104  unsigned cRet = 0;
105  PCImgThunkData pitd = pitdBase;
106  while (pitd->u1.Function) {
107  pitd++;
108  cRet++;
109  }
110  return cRet;
111  }
const IMAGE_THUNK_DATA * PCImgThunkData
Definition: delayimp.h:19
static bool WINAPI FLoadedAtPreferredAddress ( PIMAGE_NT_HEADERS  pinh,
HMODULE  hmod 
)
inlinestatic
151  {
152  return UINT_PTR(hmod) == pinh->OptionalHeader.ImageBase;
153  }
unsigned IndexFromPImgThunkData ( PCImgThunkData  pitdCur,
PCImgThunkData  pitdBase 
)
inline
79  {
80  return (unsigned) (pitdCur - pitdBase);
81  }
static void WINAPI OverlayIAT ( PImgThunkData  pitdDst,
PCImgThunkData  pitdSrc 
)
inlinestatic
139  {
140  __memcpy(pitdDst, pitdSrc, CountOfImports(pitdDst) * sizeof IMAGE_THUNK_DATA);
141  }
static void * __memcpy(void *pvDst, const void *pvSrc, size_t cb)
Definition: delayhlp.cpp:59
unsigned CountOfImports(PCImgThunkData pitdBase)
Definition: delayhlp.cpp:103
template<class X >
X PFromRva ( RVA  rva)
96  {
97  return X(PBYTE(&__ImageBase) + rva);
98  }
const IMAGE_DOS_HEADER __ImageBase
Definition: delayhlp.cpp:92
static PCImgDelayDescr PiddFromDllName ( LPCSTR  szDll)
static
157  {
158  PCImgDelayDescr piddRet = NULL;
159  PIMAGE_NT_HEADERS pinh = PinhFromImageBase(HMODULE(&__ImageBase));
160 
161  // Scan the Delay load IAT/INT for the dll in question
162  //
163  if (pinh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].Size != 0) {
164  PCImgDelayDescr pidd = PFromRva<PCImgDelayDescr>(
165  pinh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT].VirtualAddress
166  );
167 
168  // Check all of the dlls listed up to the NULL one.
169  //
170  while (pidd->rvaDLLName != 0) {
171  // Check to see if it is the DLL we want
172  // Intentionally case sensitive to avoid complication of using the CRT
173  // for those that don't use the CRT...the user can replace this with
174  // a variant of a case insenstive comparison routine.
175  //
176  LPCSTR szDllCur = PFromRva<LPCSTR>(pidd->rvaDLLName);
177  size_t cchDllCur = __strlen(szDllCur);
178  if (cchDllCur == __strlen(szDll) && __memcmp(szDll, szDllCur, cchDllCur) == 0) {
179  piddRet = pidd;
180  break;
181  }
182 
183  pidd++;
184  }
185  }
186  return piddRet;
187  }
RVA rvaDLLName
Definition: delayimp.h:24
#define NULL
Definition: crtdbg.h:30
static size_t __strlen(const char *sz)
Definition: delayhlp.cpp:34
static PIMAGE_NT_HEADERS WINAPI PinhFromImageBase(HMODULE hmod)
Definition: delayhlp.cpp:133
static int __memcmp(const void *pv1, const void *pv2, size_t cb)
Definition: delayhlp.cpp:45
const IMAGE_DOS_HEADER __ImageBase
Definition: delayhlp.cpp:92
Definition: delayimp.h:22
static PIMAGE_NT_HEADERS WINAPI PinhFromImageBase ( HMODULE  hmod)
inlinestatic
133  {
134  return PIMAGE_NT_HEADERS(PBYTE(hmod) + PIMAGE_DOS_HEADER(hmod)->e_lfanew);
135  }
static DWORD WINAPI TimeStampOfImage ( PIMAGE_NT_HEADERS  pinh)
inlinestatic
145  {
146  return pinh->FileHeader.TimeDateStamp;
147  }

Variable Documentation

const IMAGE_DOS_HEADER __ImageBase