2 * Copyright 2002 Dmitry Timoshkov for Codeweavers
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.
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.
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
25 #include "wine/exception.h"
27 #include "wine/debug.h"
28 #include "wine/server.h"
29 #include "ntdll_misc.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
32 WINE_DECLARE_DEBUG_CHANNEL(module);
33 WINE_DECLARE_DEBUG_CHANNEL(module);
34 WINE_DECLARE_DEBUG_CHANNEL(loaddll);
36 static int free_lib_count; /* recursion depth of FreeLibrary calls */
38 /* filter for page-fault exceptions */
39 static WINE_EXCEPTION_FILTER(page_fault)
41 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
42 return EXCEPTION_EXECUTE_HANDLER;
43 return EXCEPTION_CONTINUE_SEARCH;
47 /******************************************************************
48 * LdrDisableThreadCalloutsForDll (NTDLL.@)
51 NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE hModule)
54 NTSTATUS ret = STATUS_SUCCESS;
56 RtlEnterCriticalSection( &loader_section );
58 wm = MODULE32_LookupHMODULE( hModule );
60 ret = STATUS_DLL_NOT_FOUND;
62 wm->flags |= WINE_MODREF_NO_DLL_CALLS;
64 RtlLeaveCriticalSection( &loader_section );
69 /**********************************************************************
72 * Find a (loaded) win32 module depending on path
73 * LPCSTR path: [in] pathname of module/library to be found
75 * The loader_section must be locked while calling this function
77 * the module handle if found
80 WINE_MODREF *MODULE_FindModule(LPCSTR path)
83 char dllname[260], *p;
85 /* Append .DLL to name if no extension present */
86 strcpy( dllname, path );
87 if (!(p = strrchr( dllname, '.')) || strchr( p, '/' ) || strchr( p, '\\'))
88 strcat( dllname, ".DLL" );
90 for ( wm = MODULE_modref_list; wm; wm = wm->next )
92 if ( !FILE_strcasecmp( dllname, wm->modname ) )
94 if ( !FILE_strcasecmp( dllname, wm->filename ) )
96 if ( !FILE_strcasecmp( dllname, wm->short_modname ) )
98 if ( !FILE_strcasecmp( dllname, wm->short_filename ) )
105 /******************************************************************
106 * LdrGetDllHandle (NTDLL.@)
110 NTSTATUS WINAPI LdrGetDllHandle(ULONG x, ULONG y, PUNICODE_STRING name, HMODULE *base)
114 TRACE("%08lx %08lx %s %p\n",
115 x, y, name ? debugstr_wn(name->Buffer, name->Length) : NULL, base);
117 if (x != 0 || y != 0)
118 FIXME("Unknown behavior, please report\n");
120 /* FIXME: we should store module name information as unicode */
125 RtlUnicodeStringToAnsiString( &str, name, TRUE );
127 wm = MODULE_FindModule( str.Buffer );
128 RtlFreeAnsiString( &str );
136 return STATUS_DLL_NOT_FOUND;
140 return STATUS_SUCCESS;
143 /***********************************************************************
144 * MODULE_GetProcAddress (internal)
146 FARPROC MODULE_GetProcAddress(
147 HMODULE hModule, /* [in] current module handle */
148 LPCSTR function, /* [in] function to be looked up */
155 if (HIWORD(function))
156 TRACE("(%p,%s (%d))\n",hModule,function,hint);
158 TRACE("(%p,%p)\n",hModule,function);
160 RtlEnterCriticalSection( &loader_section );
161 if ((wm = MODULE32_LookupHMODULE( hModule )))
163 retproc = wm->find_export( wm, function, hint, snoop );
165 RtlLeaveCriticalSection( &loader_section );
170 /******************************************************************
171 * LdrGetProcedureAddress (NTDLL.@)
175 NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE base, PANSI_STRING name, ULONG ord, PVOID *address)
177 WARN("%p %s %ld %p\n", base, name ? debugstr_an(name->Buffer, name->Length) : NULL, ord, address);
179 *address = MODULE_GetProcAddress( base, name ? name->Buffer : (LPSTR)ord, -1, TRUE );
181 return (*address) ? STATUS_SUCCESS : STATUS_PROCEDURE_NOT_FOUND;
185 /******************************************************************
186 * LdrShutdownProcess (NTDLL.@)
189 NTSTATUS WINAPI LdrShutdownProcess(void)
192 MODULE_DllProcessDetach( TRUE, (LPVOID)1 );
193 return STATUS_SUCCESS; /* FIXME */
196 /******************************************************************
197 * LdrShutdownThread (NTDLL.@)
200 NTSTATUS WINAPI LdrShutdownThread(void)
205 /* don't do any detach calls if process is exiting */
206 if (process_detaching) return STATUS_SUCCESS;
207 /* FIXME: there is still a race here */
209 RtlEnterCriticalSection( &loader_section );
211 for ( wm = MODULE_modref_list; wm; wm = wm->next )
213 if ( !(wm->flags & WINE_MODREF_PROCESS_ATTACHED) )
215 if ( wm->flags & WINE_MODREF_NO_DLL_CALLS )
218 MODULE_InitDLL( wm, DLL_THREAD_DETACH, NULL );
221 RtlLeaveCriticalSection( &loader_section );
222 return STATUS_SUCCESS; /* FIXME */
225 /***********************************************************************
226 * MODULE_FlushModrefs
228 * NOTE: Assumes that the process critical section is held!
230 * Remove all unused modrefs and call the internal unloading routines
231 * for the library type.
233 static void MODULE_FlushModrefs(void)
235 WINE_MODREF *wm, *next;
237 for (wm = MODULE_modref_list; wm; wm = next)
244 /* Unlink this modref from the chain */
246 wm->next->prev = wm->prev;
248 wm->prev->next = wm->next;
249 if (wm == MODULE_modref_list)
250 MODULE_modref_list = wm->next;
252 TRACE(" unloading %s\n", wm->filename);
253 if (!TRACE_ON(module))
254 TRACE_(loaddll)("Unloaded module '%s' : %s\n", wm->filename,
255 wm->dlhandle ? "builtin" : "native" );
257 SERVER_START_REQ( unload_dll )
259 req->base = (void *)wm->module;
260 wine_server_call( req );
264 if (wm->dlhandle) wine_dll_unload( wm->dlhandle );
265 else UnmapViewOfFile( (LPVOID)wm->module );
266 FreeLibrary16( wm->hDummyMod );
267 RtlFreeHeap( ntdll_get_process_heap(), 0, wm->deps );
268 RtlFreeHeap( ntdll_get_process_heap(), 0, wm );
272 /***********************************************************************
275 * NOTE: Assumes that the process critical section is held!
277 static void MODULE_DecRefCount( WINE_MODREF *wm )
281 if ( wm->flags & WINE_MODREF_MARKER )
284 if ( wm->refCount <= 0 )
288 TRACE("(%s) refCount: %d\n", wm->modname, wm->refCount );
290 if ( wm->refCount == 0 )
292 wm->flags |= WINE_MODREF_MARKER;
294 for ( i = 0; i < wm->nDeps; i++ )
296 MODULE_DecRefCount( wm->deps[i] );
298 wm->flags &= ~WINE_MODREF_MARKER;
302 /******************************************************************
303 * LdrUnloadDll (NTDLL.@)
307 NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule )
309 NTSTATUS retv = STATUS_SUCCESS;
311 TRACE("(%p)\n", hModule);
313 RtlEnterCriticalSection( &loader_section );
315 /* if we're stopping the whole process (and forcing the removal of all
316 * DLLs) the library will be freed anyway
318 if (!process_detaching)
323 if ((wm = MODULE32_LookupHMODULE( hModule )) != NULL)
325 TRACE("(%s) - START\n", wm->modname);
327 /* Recursively decrement reference counts */
328 MODULE_DecRefCount( wm );
330 /* Call process detach notifications */
331 if ( free_lib_count <= 1 )
333 MODULE_DllProcessDetach( FALSE, NULL );
334 MODULE_FlushModrefs();
340 retv = STATUS_DLL_NOT_FOUND;
345 RtlLeaveCriticalSection( &loader_section );
350 /***********************************************************************
351 * RtlImageNtHeader (NTDLL.@)
353 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
355 IMAGE_NT_HEADERS *ret;
359 IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)hModule;
362 if (dos->e_magic == IMAGE_DOS_SIGNATURE)
364 ret = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew);
365 if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL;
377 /***********************************************************************
378 * RtlImageDirectoryEntryToData (NTDLL.@)
380 PVOID WINAPI RtlImageDirectoryEntryToData( HMODULE module, BOOL image, WORD dir, ULONG *size )
382 const IMAGE_NT_HEADERS *nt;
385 if ((ULONG_PTR)module & 1) /* mapped as data file */
387 module = (HMODULE)((ULONG_PTR)module & ~1);
390 if (!(nt = RtlImageNtHeader( module ))) return NULL;
391 if (dir >= nt->OptionalHeader.NumberOfRvaAndSizes) return NULL;
392 if (!(addr = nt->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;
393 *size = nt->OptionalHeader.DataDirectory[dir].Size;
394 if (image || addr < nt->OptionalHeader.SizeOfHeaders) return (char *)module + addr;
396 /* not mapped as image, need to find the section containing the virtual address */
397 return RtlImageRvaToVa( nt, module, addr, NULL );
401 /***********************************************************************
402 * RtlImageRvaToSection (NTDLL.@)
404 PIMAGE_SECTION_HEADER WINAPI RtlImageRvaToSection( const IMAGE_NT_HEADERS *nt,
405 HMODULE module, DWORD rva )
408 IMAGE_SECTION_HEADER *sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader +
409 nt->FileHeader.SizeOfOptionalHeader);
410 for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
412 if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
419 /***********************************************************************
420 * RtlImageRvaToVa (NTDLL.@)
422 PVOID WINAPI RtlImageRvaToVa( const IMAGE_NT_HEADERS *nt, HMODULE module,
423 DWORD rva, IMAGE_SECTION_HEADER **section )
425 IMAGE_SECTION_HEADER *sec;
427 if (section && *section) /* try this section first */
430 if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
433 if (!(sec = RtlImageRvaToSection( nt, module, rva ))) return NULL;
435 if (section) *section = sec;
436 return (char *)module + sec->PointerToRawData + (rva - sec->VirtualAddress);