[RXCE]
[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 #if defined (_M_IX86)
32 #pragma comment(linker, "/alternatename:___pfnDliNotifyHook2=___pfnDliNotifyHook2Default")
33 #pragma comment(linker, "/alternatename:___pfnDliFailureHook2=___pfnDliFailureHook2Default")
34 #elif defined (_M_IA64) || defined (_M_AMD64)
35 #pragma comment(linker, "/alternatename:__pfnDliNotifyHook2=__pfnDliNotifyHook2Default")
36 #pragma comment(linker, "/alternatename:__pfnDliFailureHook2=__pfnDliFailureHook2Default")
37 #else
38 #error Unsupported platform, please find the correct decoration for your arch!
39 #endif
40 #endif
41
42
43 /**** Helper functions to convert from RVA to address ****/
44
45 FORCEINLINE
46 unsigned
47 IndexFromPImgThunkData(PCImgThunkData pData, PCImgThunkData pBase)
48 {
49 return pData - pBase;
50 }
51
52 extern const IMAGE_DOS_HEADER __ImageBase;
53
54 FORCEINLINE
55 PVOID
56 PFromRva(RVA rva)
57 {
58 return (PVOID)(((ULONG_PTR)(rva)) + ((ULONG_PTR)&__ImageBase));
59 }
60
61
62 /**** load helper ****/
63
64 FARPROC WINAPI
65 __delayLoadHelper2(PCImgDelayDescr pidd, PImgThunkData pIATEntry)
66 {
67 DelayLoadInfo dli = {0};
68 int index;
69 PImgThunkData pIAT;
70 PImgThunkData pINT;
71 HMODULE *phMod;
72
73 pIAT = PFromRva(pidd->rvaIAT);
74 pINT = PFromRva(pidd->rvaINT);
75 phMod = PFromRva(pidd->rvaHmod);
76 index = IndexFromPImgThunkData(pIATEntry, pIAT);
77
78 dli.cb = sizeof(dli);
79 dli.pidd = pidd;
80 dli.ppfn = (FARPROC*)&pIAT[index].u1.Function;
81 dli.szDll = PFromRva(pidd->rvaDLLName);
82 dli.dlp.fImportByName = !IMAGE_SNAP_BY_ORDINAL(pINT[index].u1.Ordinal);
83 if (dli.dlp.fImportByName)
84 {
85 /* u1.AdressOfData points to a IMAGE_IMPORT_BY_NAME struct */
86 PIMAGE_IMPORT_BY_NAME piibn = PFromRva((RVA)pINT[index].u1.AddressOfData);
87 dli.dlp.szProcName = (LPCSTR)&piibn->Name;
88 }
89 else
90 {
91 dli.dlp.dwOrdinal = IMAGE_ORDINAL(pINT[index].u1.Ordinal);
92 }
93
94 if (__pfnDliNotifyHook2)
95 {
96 dli.pfnCur = __pfnDliNotifyHook2(dliStartProcessing, &dli);
97 if (dli.pfnCur)
98 {
99 pIAT[index].u1.Function = (DWORD_PTR)dli.pfnCur;
100 if (__pfnDliNotifyHook2)
101 __pfnDliNotifyHook2(dliNoteEndProcessing, &dli);
102
103 return dli.pfnCur;
104 }
105 }
106
107 dli.hmodCur = *phMod;
108
109 if (dli.hmodCur == NULL)
110 {
111 if (__pfnDliNotifyHook2)
112 dli.hmodCur = (HMODULE)__pfnDliNotifyHook2(dliNotePreLoadLibrary, &dli);
113 if (dli.hmodCur == NULL)
114 {
115 dli.hmodCur = LoadLibraryA(dli.szDll);
116 if (dli.hmodCur == NULL)
117 {
118 dli.dwLastError = GetLastError();
119 if (__pfnDliFailureHook2)
120 dli.hmodCur = (HMODULE)__pfnDliFailureHook2(dliFailLoadLib, &dli);
121
122 if (dli.hmodCur == NULL)
123 {
124 ULONG_PTR args[] = { (ULONG_PTR)&dli };
125 RaiseException(VcppException(ERROR_SEVERITY_ERROR, ERROR_MOD_NOT_FOUND), 0, 1, args);
126
127 /* If we survive the exception, we are expected to use pfnCur directly.. */
128 return dli.pfnCur;
129 }
130 }
131 }
132 *phMod = dli.hmodCur;
133 }
134
135 dli.dwLastError = ERROR_SUCCESS;
136
137 if (__pfnDliNotifyHook2)
138 dli.pfnCur = (FARPROC)__pfnDliNotifyHook2(dliNotePreGetProcAddress, &dli);
139 if (dli.pfnCur == NULL)
140 {
141 /* dli.dlp.szProcName might also contain the ordinal */
142 dli.pfnCur = GetProcAddress(dli.hmodCur, dli.dlp.szProcName);
143 if (dli.pfnCur == NULL)
144 {
145 dli.dwLastError = GetLastError();
146 if (__pfnDliFailureHook2)
147 dli.pfnCur = __pfnDliFailureHook2(dliFailGetProc, &dli);
148
149 if (dli.pfnCur == NULL)
150 {
151 ULONG_PTR args[] = { (ULONG_PTR)&dli };
152 RaiseException(VcppException(ERROR_SEVERITY_ERROR, ERROR_PROC_NOT_FOUND), 0, 1, args);
153 }
154
155 //return NULL;
156 }
157 }
158
159 pIAT[index].u1.Function = (DWORD_PTR)dli.pfnCur;
160 dli.dwLastError = ERROR_SUCCESS;
161
162 if (__pfnDliNotifyHook2)
163 __pfnDliNotifyHook2(dliNoteEndProcessing, &dli);
164
165 return dli.pfnCur;
166 }
167