Reactos
1/*
2 * PROJECT: ReactOS delayimport Library
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Implementation of delayimport library
5 * COPYRIGHT: Copyright 2009 Timo Kreuzer <timo.kreuzer@reactos.org>
6 * Copyright 2016 Mark Jansen
7 */
8
9#include <stdarg.h>
10#include <windef.h>
11#include <winbase.h>
12#include <delayimp.h>
13
14/**** Linker magic: provide a default (NULL) pointer, but allow the user to override it ****/
15
16/* The actual items we use */
17extern PfnDliHook __pfnDliNotifyHook2;
18extern PfnDliHook __pfnDliFailureHook2;
19
20#if !defined(__GNUC__)
21/* The fallback symbols */
22PfnDliHook __pfnDliNotifyHook2Default = NULL;
23PfnDliHook __pfnDliFailureHook2Default = NULL;
24
25/* Tell the linker to use the fallback symbols */
26#if defined (_M_IX86)
27#pragma comment(linker, "/alternatename:___pfnDliNotifyHook2=___pfnDliNotifyHook2Default")
28#pragma comment(linker, "/alternatename:___pfnDliFailureHook2=___pfnDliFailureHook2Default")
29#else
30#pragma comment(linker, "/alternatename:__pfnDliNotifyHook2=__pfnDliNotifyHook2Default")
31#pragma comment(linker, "/alternatename:__pfnDliFailureHook2=__pfnDliFailureHook2Default")
32#endif
33#endif
34
35
36/**** Helper functions to convert from RVA to address ****/
37
38FORCEINLINE
39unsigned
40IndexFromPImgThunkData(PCImgThunkData pData, PCImgThunkData pBase)
41{
42 return pData - pBase;
43}
44
45extern const IMAGE_DOS_HEADER __ImageBase;
46
47FORCEINLINE
48PVOID
49PFromRva(RVA rva)
50{
51 return (PVOID)(((ULONG_PTR)(rva)) + ((ULONG_PTR)&__ImageBase));
52}
53
54
55/**** load helper ****/
56
57FARPROC WINAPI
58__delayLoadHelper2(PCImgDelayDescr pidd, PImgThunkData pIATEntry)
59{
60 DelayLoadInfo dli = {0};
61 int index;
62 PImgThunkData pIAT;
63 PImgThunkData pINT;
64 HMODULE *phMod;
65
66 pIAT = PFromRva(pidd->rvaIAT);
67 pINT = PFromRva(pidd->rvaINT);
68 phMod = PFromRva(pidd->rvaHmod);
69 index = IndexFromPImgThunkData(pIATEntry, pIAT);
70
71 dli.cb = sizeof(dli);
72 dli.pidd = pidd;
73 dli.ppfn = (FARPROC*)&pIAT[index].u1.Function;
74 dli.szDll = PFromRva(pidd->rvaDLLName);
75 dli.dlp.fImportByName = !IMAGE_SNAP_BY_ORDINAL(pINT[index].u1.Ordinal);
76 if (dli.dlp.fImportByName)
77 {
78 /* u1.AddressOfData points to a IMAGE_IMPORT_BY_NAME struct */
79 PIMAGE_IMPORT_BY_NAME piibn = PFromRva((RVA)pINT[index].u1.AddressOfData);
80 dli.dlp.szProcName = (LPCSTR)&piibn->Name;
81 }
82 else
83 {
84 dli.dlp.dwOrdinal = IMAGE_ORDINAL(pINT[index].u1.Ordinal);
85 }
86
87 if (__pfnDliNotifyHook2)
88 {
89 dli.pfnCur = __pfnDliNotifyHook2(dliStartProcessing, &dli);
90 if (dli.pfnCur)
91 {
92 pIAT[index].u1.Function = (DWORD_PTR)dli.pfnCur;
93 if (__pfnDliNotifyHook2)
94 __pfnDliNotifyHook2(dliNoteEndProcessing, &dli);
95
96 return dli.pfnCur;
97 }
98 }
99
100 dli.hmodCur = *phMod;
101
102 if (dli.hmodCur == NULL)
103 {
104 if (__pfnDliNotifyHook2)
105 dli.hmodCur = (HMODULE)__pfnDliNotifyHook2(dliNotePreLoadLibrary, &dli);
106 if (dli.hmodCur == NULL)
107 {
108 dli.hmodCur = LoadLibraryA(dli.szDll);
109 if (dli.hmodCur == NULL)
110 {
111 dli.dwLastError = GetLastError();
112 if (__pfnDliFailureHook2)
113 dli.hmodCur = (HMODULE)__pfnDliFailureHook2(dliFailLoadLib, &dli);
114
115 if (dli.hmodCur == NULL)
116 {
117 ULONG_PTR args[] = { (ULONG_PTR)&dli };
118 RaiseException(VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND), 0, 1, args);
119
120 /* If we survive the exception, we are expected to use pfnCur directly.. */
121 return dli.pfnCur;
122 }
123 }
124 }
125 *phMod = dli.hmodCur;
126 }
127
128 dli.dwLastError = ERROR_SUCCESS;
129
130 if (__pfnDliNotifyHook2)
131 dli.pfnCur = (FARPROC)__pfnDliNotifyHook2(dliNotePreGetProcAddress, &dli);
132 if (dli.pfnCur == NULL)
133 {
134 /* dli.dlp.szProcName might also contain the ordinal */
135 dli.pfnCur = GetProcAddress(dli.hmodCur, dli.dlp.szProcName);
136 if (dli.pfnCur == NULL)
137 {
138 dli.dwLastError = GetLastError();
139 if (__pfnDliFailureHook2)
140 dli.pfnCur = __pfnDliFailureHook2(dliFailGetProc, &dli);
141
142 if (dli.pfnCur == NULL)
143 {
144 ULONG_PTR args[] = { (ULONG_PTR)&dli };
145 RaiseException(VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND), 0, 1, args);
146 }
147
148 //return NULL;
149 }
150 }
151
152 pIAT[index].u1.Function = (DWORD_PTR)dli.pfnCur;
153 dli.dwLastError = ERROR_SUCCESS;
154
155 if (__pfnDliNotifyHook2)
156 __pfnDliNotifyHook2(dliNoteEndProcessing, &dli);
157
158 return dli.pfnCur;
159}
160