- implemented LdrGetProcedureAddress and made use of it for
[wine] / dlls / ntdll / loader.c
1 /*
2  * Copyright 2002 Dmitry Timoshkov for Codeweavers
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include "winbase.h"
20 #include "winnt.h"
21 #include "winternl.h"
22
23 #include "module.h"
24 #include "file.h"
25 #include "wine/exception.h"
26 #include "excpt.h"
27 #include "wine/debug.h"
28
29 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
30
31 /* filter for page-fault exceptions */
32 static WINE_EXCEPTION_FILTER(page_fault)
33 {
34     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
35         return EXCEPTION_EXECUTE_HANDLER;
36     return EXCEPTION_CONTINUE_SEARCH;
37 }
38
39
40 /******************************************************************
41  *              LdrDisableThreadCalloutsForDll (NTDLL.@)
42  *
43  */
44 NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE hModule)
45 {
46     WINE_MODREF *wm;
47     NTSTATUS    ret = STATUS_SUCCESS;
48
49     RtlEnterCriticalSection( &loader_section );
50
51     wm = MODULE32_LookupHMODULE( hModule );
52     if ( !wm )
53         ret = STATUS_DLL_NOT_FOUND;
54     else
55         wm->flags |= WINE_MODREF_NO_DLL_CALLS;
56
57     RtlLeaveCriticalSection( &loader_section );
58
59     return ret;
60 }
61
62 /**********************************************************************
63  *          MODULE_FindModule
64  *
65  * Find a (loaded) win32 module depending on path
66  *      LPCSTR path: [in] pathname of module/library to be found
67  *
68  * The loader_section must be locked while calling this function
69  * RETURNS
70  *      the module handle if found
71  *      0 if not
72  */
73 WINE_MODREF *MODULE_FindModule(LPCSTR path)
74 {
75     WINE_MODREF *wm;
76     char dllname[260], *p;
77
78     /* Append .DLL to name if no extension present */
79     strcpy( dllname, path );
80     if (!(p = strrchr( dllname, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
81             strcat( dllname, ".DLL" );
82
83     for ( wm = MODULE_modref_list; wm; wm = wm->next )
84     {
85         if ( !FILE_strcasecmp( dllname, wm->modname ) )
86             break;
87         if ( !FILE_strcasecmp( dllname, wm->filename ) )
88             break;
89         if ( !FILE_strcasecmp( dllname, wm->short_modname ) )
90             break;
91         if ( !FILE_strcasecmp( dllname, wm->short_filename ) )
92             break;
93     }
94
95     return wm;
96 }
97
98 /******************************************************************
99  *              LdrGetDllHandle (NTDLL.@)
100  *
101  *
102  */
103 NTSTATUS WINAPI LdrGetDllHandle(ULONG x, ULONG y, PUNICODE_STRING name, HMODULE *base)
104 {
105     WINE_MODREF *wm;
106
107     TRACE("%08lx %08lx %s %p\n",
108           x, y, name ? debugstr_wn(name->Buffer, name->Length) : NULL, base);
109
110     if (x != 0 || y != 0)
111         FIXME("Unknown behavior, please report\n");
112
113     /* FIXME: we should store module name information as unicode */
114     if (name)
115     {
116         STRING str;
117
118         RtlUnicodeStringToAnsiString( &str, name, TRUE );
119
120         wm = MODULE_FindModule( str.Buffer );
121         RtlFreeAnsiString( &str );
122     }
123     else
124         wm = exe_modref;
125
126     if (!wm)
127     {
128         *base = 0;
129         return STATUS_DLL_NOT_FOUND;
130     }
131
132     *base = wm->module;
133     return STATUS_SUCCESS;
134 }
135
136 /***********************************************************************
137  *           MODULE_GetProcAddress              (internal)
138  */
139 FARPROC MODULE_GetProcAddress(
140         HMODULE hModule,        /* [in] current module handle */
141         LPCSTR function,        /* [in] function to be looked up */
142         int hint,
143         BOOL snoop )
144 {
145     WINE_MODREF *wm;
146     FARPROC     retproc = 0;
147
148     if (HIWORD(function))
149         TRACE("(%p,%s (%d))\n",hModule,function,hint);
150     else
151         TRACE("(%p,%p)\n",hModule,function);
152
153     RtlEnterCriticalSection( &loader_section );
154     if ((wm = MODULE32_LookupHMODULE( hModule )))
155     {
156         retproc = wm->find_export( wm, function, hint, snoop );
157         if (!retproc) SetLastError(ERROR_PROC_NOT_FOUND);
158     }
159     RtlLeaveCriticalSection( &loader_section );
160     return retproc;
161 }
162
163
164 /******************************************************************
165  *              LdrGetProcedureAddress (NTDLL.@)
166  *
167  *
168  */
169 NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE base, PANSI_STRING name, ULONG ord, PVOID *address)
170 {
171     WARN("%p %s %ld %p\n", base, name ? debugstr_an(name->Buffer, name->Length) : NULL, ord, address);
172
173     *address = MODULE_GetProcAddress( base, name ? name->Buffer : (LPSTR)ord, -1, TRUE );
174
175     return (*address) ? STATUS_SUCCESS : STATUS_DLL_NOT_FOUND;
176 }
177
178
179 /******************************************************************
180  *              LdrShutdownProcess (NTDLL.@)
181  *
182  */
183 NTSTATUS    WINAPI  LdrShutdownProcess(void)
184 {
185     TRACE("()\n");
186     MODULE_DllProcessDetach( TRUE, (LPVOID)1 );
187     return STATUS_SUCCESS; /* FIXME */
188 }
189
190 /******************************************************************
191  *              LdrShutdownThread (NTDLL.@)
192  *
193  */
194 NTSTATUS WINAPI LdrShutdownThread(void)
195 {
196     WINE_MODREF *wm;
197     TRACE("()\n");
198
199     /* don't do any detach calls if process is exiting */
200     if (process_detaching) return STATUS_SUCCESS;
201     /* FIXME: there is still a race here */
202
203     RtlEnterCriticalSection( &loader_section );
204
205     for ( wm = MODULE_modref_list; wm; wm = wm->next )
206     {
207         if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) )
208             continue;
209         if ( wm->flags & WINE_MODREF_NO_DLL_CALLS )
210             continue;
211
212         MODULE_InitDLL( wm, DLL_THREAD_DETACH, NULL );
213     }
214
215     RtlLeaveCriticalSection( &loader_section );
216     return STATUS_SUCCESS; /* FIXME */
217 }
218
219 /***********************************************************************
220  *           RtlImageNtHeader   (NTDLL.@)
221  */
222 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
223 {
224     IMAGE_NT_HEADERS *ret;
225
226     __TRY
227     {
228         IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)hModule;
229
230         ret = NULL;
231         if (dos->e_magic == IMAGE_DOS_SIGNATURE)
232         {
233             ret = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew);
234             if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL;
235         }
236     }
237     __EXCEPT(page_fault)
238     {
239         return NULL;
240     }
241     __ENDTRY
242     return ret;
243 }
244
245
246 /***********************************************************************
247  *           RtlImageDirectoryEntryToData   (NTDLL.@)
248  */
249 PVOID WINAPI RtlImageDirectoryEntryToData( HMODULE module, BOOL image, WORD dir, ULONG *size )
250 {
251     const IMAGE_NT_HEADERS *nt;
252     DWORD addr;
253
254     if ((ULONG_PTR)module & 1)  /* mapped as data file */
255     {
256         module = (HMODULE)((ULONG_PTR)module & ~1);
257         image = FALSE;
258     }
259     if (!(nt = RtlImageNtHeader( module ))) return NULL;
260     if (dir >= nt->OptionalHeader.NumberOfRvaAndSizes) return NULL;
261     if (!(addr = nt->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;
262     *size = nt->OptionalHeader.DataDirectory[dir].Size;
263     if (image || addr < nt->OptionalHeader.SizeOfHeaders) return (char *)module + addr;
264
265     /* not mapped as image, need to find the section containing the virtual address */
266     return RtlImageRvaToVa( nt, module, addr, NULL );
267 }
268
269
270 /***********************************************************************
271  *           RtlImageRvaToSection   (NTDLL.@)
272  */
273 PIMAGE_SECTION_HEADER WINAPI RtlImageRvaToSection( const IMAGE_NT_HEADERS *nt,
274                                                    HMODULE module, DWORD rva )
275 {
276     int i;
277     IMAGE_SECTION_HEADER *sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader +
278                                                         nt->FileHeader.SizeOfOptionalHeader);
279     for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
280     {
281         if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
282             return sec;
283     }
284     return NULL;
285 }
286
287
288 /***********************************************************************
289  *           RtlImageRvaToVa   (NTDLL.@)
290  */
291 PVOID WINAPI RtlImageRvaToVa( const IMAGE_NT_HEADERS *nt, HMODULE module,
292                               DWORD rva, IMAGE_SECTION_HEADER **section )
293 {
294     IMAGE_SECTION_HEADER *sec;
295
296     if (section && *section)  /* try this section first */
297     {
298         sec = *section;
299         if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
300             goto found;
301     }
302     if (!(sec = RtlImageRvaToSection( nt, module, rva ))) return NULL;
303  found:
304     if (section) *section = sec;
305     return (char *)module + sec->PointerToRawData + (rva - sec->VirtualAddress);
306 }