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