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"
#include "dloadsup.h"

Classes

struct  InternalImgDelayDescr
 

Macros

#define WIN32_LEAN_AND_MEAN
 
#define STRICT
 
#define DLOAD_UNLOAD   1
 

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 DLOAD_UNLOAD   1
#define STRICT
#define WIN32_LEAN_AND_MEAN

Typedef Documentation

typedef const InternalImgDelayDescr* PCIIDD

Function Documentation

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

Variable Documentation

const IMAGE_DOS_HEADER __ImageBase