f439a78e9ff6566d926b596e5659b95fd97a536f
[reactos.git] / reactos / 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 #pragma comment(linker, "/alternatename:___pfnDliNotifyHook2=___pfnDliNotifyHook2Default")
32 #pragma comment(linker, "/alternatename:___pfnDliFailureHook2=___pfnDliFailureHook2Default")
33 #endif
34
35
36 /**** Helper functions to convert from RVA to address ****/
37
38 FORCEINLINE
39 unsigned
40 IndexFromPImgThunkData(PCImgThunkData pData, PCImgThunkData pBase)
41 {
42 return pData - pBase;
43 }
44
45 extern const IMAGE_DOS_HEADER __ImageBase;
46
47 FORCEINLINE
48 PVOID
49 PFromRva(RVA rva)
50 {
51 return (PVOID)(((ULONG_PTR)(rva)) + ((ULONG_PTR)&__ImageBase));
52 }
53
54
55 /**** load helper ****/
56
57 FARPROC 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.AdressOfData 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