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