xref: /reactos/sdk/lib/delayimp/delayimp.c (revision 84ccccab)
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 
166