4 * Copyright 1995, 2003 Alexandre Julliard
5 * Copyright 2002 Dmitry Timoshkov for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
33 #include "wine/exception.h"
35 #include "wine/unicode.h"
36 #include "wine/debug.h"
37 #include "wine/server.h"
38 #include "ntdll_misc.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(module);
41 WINE_DECLARE_DEBUG_CHANNEL(relay);
42 WINE_DECLARE_DEBUG_CHANNEL(snoop);
43 WINE_DECLARE_DEBUG_CHANNEL(loaddll);
45 typedef DWORD (CALLBACK *DLLENTRYPROC)(HMODULE,DWORD,LPVOID);
47 static int process_detaching = 0; /* set on process detach to avoid deadlocks with thread detach */
48 static int free_lib_count; /* recursion depth of LdrUnloadDll calls */
50 /* filter for page-fault exceptions */
51 static WINE_EXCEPTION_FILTER(page_fault)
53 if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
54 return EXCEPTION_EXECUTE_HANDLER;
55 return EXCEPTION_CONTINUE_SEARCH;
58 static const char * const reason_names[] =
66 static const WCHAR dllW[] = {'.','d','l','l',0};
68 /* internal representation of 32bit modules. per process. */
69 typedef struct _wine_modref
73 struct _wine_modref **deps;
76 /* info about the current builtin dll load */
77 /* used to keep track of things across the register_dll constructor call */
78 struct builtin_load_info
80 const WCHAR *load_path;
85 static struct builtin_load_info default_load_info;
86 static struct builtin_load_info *builtin_load_info = &default_load_info;
88 static UINT tls_module_count; /* number of modules with TLS directory */
89 static UINT tls_total_size; /* total size of TLS storage */
90 static const IMAGE_TLS_DIRECTORY **tls_dirs; /* array of TLS directories */
92 static UNICODE_STRING system_dir; /* system directory */
94 static CRITICAL_SECTION loader_section;
95 static CRITICAL_SECTION_DEBUG critsect_debug =
97 0, 0, &loader_section,
98 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
99 0, 0, { 0, (DWORD)(__FILE__ ": loader_section") }
101 static CRITICAL_SECTION loader_section = { &critsect_debug, -1, 0, 0, 0, 0 };
103 static WINE_MODREF *cached_modref;
104 static WINE_MODREF *current_modref;
106 static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm );
107 static FARPROC find_named_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
108 DWORD exp_size, const char *name, int hint );
110 /* convert PE image VirtualAddress to Real Address */
111 inline static void *get_rva( HMODULE module, DWORD va )
113 return (void *)((char *)module + va);
116 /* check whether the file name contains a path */
117 inline static int contains_path( LPCWSTR name )
119 return ((*name && (name[1] == ':')) || strchrW(name, '/') || strchrW(name, '\\'));
122 /* convert from straight ASCII to Unicode without depending on the current codepage */
123 inline static void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )
125 while (len--) *dst++ = (unsigned char)*src++;
128 /*************************************************************************
131 * Looks for the referenced HMODULE in the current process
132 * The loader_section must be locked while calling this function.
134 static WINE_MODREF *get_modref( HMODULE hmod )
136 PLIST_ENTRY mark, entry;
139 if (cached_modref && cached_modref->ldr.BaseAddress == hmod) return cached_modref;
141 mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
142 for (entry = mark->Flink; entry != mark; entry = entry->Flink)
144 mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
145 if (mod->BaseAddress == hmod)
146 return cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
147 if (mod->BaseAddress > (void*)hmod) break;
153 /**********************************************************************
154 * find_basename_module
156 * Find a module from its base name.
157 * The loader_section must be locked while calling this function
159 static WINE_MODREF *find_basename_module( LPCWSTR name )
161 PLIST_ENTRY mark, entry;
163 if (cached_modref && !strcmpiW( name, cached_modref->ldr.BaseDllName.Buffer ))
164 return cached_modref;
166 mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
167 for (entry = mark->Flink; entry != mark; entry = entry->Flink)
169 LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
170 if (!strcmpiW( name, mod->BaseDllName.Buffer ))
172 cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
173 return cached_modref;
180 /**********************************************************************
181 * find_fullname_module
183 * Find a module from its full path name.
184 * The loader_section must be locked while calling this function
186 static WINE_MODREF *find_fullname_module( LPCWSTR name )
188 PLIST_ENTRY mark, entry;
190 if (cached_modref && !strcmpiW( name, cached_modref->ldr.FullDllName.Buffer ))
191 return cached_modref;
193 mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
194 for (entry = mark->Flink; entry != mark; entry = entry->Flink)
196 LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
197 if (!strcmpiW( name, mod->FullDllName.Buffer ))
199 cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
200 return cached_modref;
207 /*************************************************************************
208 * find_forwarded_export
210 * Find the final function pointer for a forwarded function.
211 * The loader_section must be locked while calling this function.
213 static FARPROC find_forwarded_export( HMODULE module, const char *forward )
215 IMAGE_EXPORT_DIRECTORY *exports;
219 char *end = strchr(forward, '.');
222 if (!end) return NULL;
223 if ((end - forward) * sizeof(WCHAR) >= sizeof(mod_name) - sizeof(dllW)) return NULL;
224 ascii_to_unicode( mod_name, forward, end - forward );
225 memcpy( mod_name + (end - forward), dllW, sizeof(dllW) );
227 if (!(wm = find_basename_module( mod_name )))
229 ERR("module not found for forward '%s' used by %s\n",
230 forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer) );
233 if ((exports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
234 IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
235 proc = find_named_export( wm->ldr.BaseAddress, exports, exp_size, end + 1, -1 );
239 ERR("function not found for forward '%s' used by %s."
240 " If you are using builtin %s, try using the native one instead.\n",
241 forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer),
242 debugstr_w(get_modref(module)->ldr.BaseDllName.Buffer) );
248 /*************************************************************************
249 * find_ordinal_export
251 * Find an exported function by ordinal.
252 * The exports base must have been subtracted from the ordinal already.
253 * The loader_section must be locked while calling this function.
255 static FARPROC find_ordinal_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
256 DWORD exp_size, int ordinal )
259 DWORD *functions = get_rva( module, exports->AddressOfFunctions );
261 if (ordinal >= exports->NumberOfFunctions)
263 TRACE(" ordinal %ld out of range!\n", ordinal + exports->Base );
266 if (!functions[ordinal]) return NULL;
268 proc = get_rva( module, functions[ordinal] );
270 /* if the address falls into the export dir, it's a forward */
271 if (((char *)proc >= (char *)exports) && ((char *)proc < (char *)exports + exp_size))
272 return find_forwarded_export( module, (char *)proc );
276 proc = SNOOP_GetProcAddress( module, exports, exp_size, proc, ordinal );
278 if (TRACE_ON(relay) && current_modref)
280 proc = RELAY_GetProcAddress( module, exports, exp_size, proc,
281 current_modref->ldr.BaseDllName.Buffer );
287 /*************************************************************************
290 * Find an exported function by name.
291 * The loader_section must be locked while calling this function.
293 static FARPROC find_named_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
294 DWORD exp_size, const char *name, int hint )
296 WORD *ordinals = get_rva( module, exports->AddressOfNameOrdinals );
297 DWORD *names = get_rva( module, exports->AddressOfNames );
298 int min = 0, max = exports->NumberOfNames - 1;
300 /* first check the hint */
301 if (hint >= 0 && hint <= max)
303 char *ename = get_rva( module, names[hint] );
304 if (!strcmp( ename, name ))
305 return find_ordinal_export( module, exports, exp_size, ordinals[hint] );
308 /* then do a binary search */
311 int res, pos = (min + max) / 2;
312 char *ename = get_rva( module, names[pos] );
313 if (!(res = strcmp( ename, name )))
314 return find_ordinal_export( module, exports, exp_size, ordinals[pos] );
315 if (res > 0) max = pos - 1;
323 /*************************************************************************
326 * Import the dll specified by the given import descriptor.
327 * The loader_section must be locked while calling this function.
329 static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr, LPCWSTR load_path )
334 IMAGE_EXPORT_DIRECTORY *exports;
336 IMAGE_THUNK_DATA *import_list, *thunk_list;
338 char *name = get_rva( module, descr->Name );
339 DWORD len = strlen(name) + 1;
341 thunk_list = get_rva( module, (DWORD)descr->FirstThunk );
342 if (descr->u.OriginalFirstThunk)
343 import_list = get_rva( module, (DWORD)descr->u.OriginalFirstThunk );
345 import_list = thunk_list;
347 if (len * sizeof(WCHAR) <= sizeof(buffer))
349 ascii_to_unicode( buffer, name, len );
350 status = load_dll( load_path, buffer, 0, &wmImp );
352 else /* need to allocate a larger buffer */
354 WCHAR *ptr = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) );
355 if (!ptr) return NULL;
356 ascii_to_unicode( ptr, name, len );
357 status = load_dll( load_path, ptr, 0, &wmImp );
358 RtlFreeHeap( GetProcessHeap(), 0, ptr );
363 if (status == STATUS_DLL_NOT_FOUND)
364 ERR("Module (file) %s (which is needed by %s) not found\n",
365 name, debugstr_w(current_modref->ldr.FullDllName.Buffer));
367 ERR("Loading module (file) %s (which is needed by %s) failed (error %lx).\n",
368 name, debugstr_w(current_modref->ldr.FullDllName.Buffer), status);
374 imp_mod = wmImp->ldr.BaseAddress;
375 exports = RtlImageDirectoryEntryToData( imp_mod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );
380 /* set all imported function to deadbeef */
381 while (import_list->u1.Ordinal)
383 if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
385 ERR("No implementation for %s.%ld", name, IMAGE_ORDINAL(import_list->u1.Ordinal));
389 IMAGE_IMPORT_BY_NAME *pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );
390 ERR("No implementation for %s.%s", name, pe_name->Name );
392 ERR(" imported from %s, setting to 0xdeadbeef\n",
393 debugstr_w(current_modref->ldr.FullDllName.Buffer) );
394 thunk_list->u1.Function = (PDWORD)0xdeadbeef;
402 while (import_list->u1.Ordinal)
404 if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
406 int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
408 thunk_list->u1.Function = (PDWORD)find_ordinal_export( imp_mod, exports, exp_size,
409 ordinal - exports->Base );
410 if (!thunk_list->u1.Function)
412 ERR("No implementation for %s.%d imported from %s, setting to 0xdeadbeef\n",
413 name, ordinal, debugstr_w(current_modref->ldr.FullDllName.Buffer) );
414 thunk_list->u1.Function = (PDWORD)0xdeadbeef;
416 TRACE("--- Ordinal %s.%d = %p\n", name, ordinal, thunk_list->u1.Function );
418 else /* import by name */
420 IMAGE_IMPORT_BY_NAME *pe_name;
421 pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );
422 thunk_list->u1.Function = (PDWORD)find_named_export( imp_mod, exports, exp_size,
423 pe_name->Name, pe_name->Hint );
424 if (!thunk_list->u1.Function)
426 ERR("No implementation for %s.%s imported from %s, setting to 0xdeadbeef\n",
427 name, pe_name->Name, debugstr_w(current_modref->ldr.FullDllName.Buffer) );
428 thunk_list->u1.Function = (PDWORD)0xdeadbeef;
430 TRACE("--- %s %s.%d = %p\n", pe_name->Name, name, pe_name->Hint, thunk_list->u1.Function);
439 /****************************************************************
442 * Fixup all imports of a given module.
443 * The loader_section must be locked while calling this function.
445 static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path )
448 IMAGE_IMPORT_DESCRIPTOR *imports;
453 if (!(imports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
454 IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))
455 return STATUS_SUCCESS;
457 nb_imports = size / sizeof(*imports);
458 for (i = 0; i < nb_imports; i++)
460 if (!imports[i].Name)
466 if (!nb_imports) return STATUS_SUCCESS; /* no imports */
468 /* Allocate module dependency list */
469 wm->nDeps = nb_imports;
470 wm->deps = RtlAllocateHeap( ntdll_get_process_heap(), 0, nb_imports*sizeof(WINE_MODREF *) );
472 /* load the imported modules. They are automatically
473 * added to the modref list of the process.
475 prev = current_modref;
477 status = STATUS_SUCCESS;
478 for (i = 0; i < nb_imports; i++)
480 if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i], load_path )))
481 status = STATUS_DLL_NOT_FOUND;
483 current_modref = prev;
488 /*************************************************************************
491 * Allocate a WINE_MODREF structure and add it to the process list
492 * The loader_section must be locked while calling this function.
494 static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
498 IMAGE_NT_HEADERS *nt = RtlImageNtHeader(hModule);
499 PLIST_ENTRY entry, mark;
500 BOOLEAN linked = FALSE;
503 RtlUnicodeToMultiByteSize( &len, filename, (strlenW(filename) + 1) * sizeof(WCHAR) );
504 if (!(wm = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*wm) + len )))
510 wm->ldr.BaseAddress = hModule;
511 wm->ldr.EntryPoint = (nt->OptionalHeader.AddressOfEntryPoint) ?
512 ((char *)hModule + nt->OptionalHeader.AddressOfEntryPoint) : 0;
513 wm->ldr.SizeOfImage = nt->OptionalHeader.SizeOfImage;
515 wm->ldr.LoadCount = 0;
516 wm->ldr.TlsIndex = -1;
517 wm->ldr.SectionHandle = NULL;
518 wm->ldr.CheckSum = 0;
519 wm->ldr.TimeDateStamp = 0;
521 RtlCreateUnicodeString( &wm->ldr.FullDllName, filename );
522 if ((p = strrchrW( wm->ldr.FullDllName.Buffer, '\\' ))) p++;
523 else p = wm->ldr.FullDllName.Buffer;
524 RtlInitUnicodeString( &wm->ldr.BaseDllName, p );
526 /* this is a bit ugly, but we need to have app module first in LoadOrder
527 * list, But in wine, ntdll is loaded first, so by inserting DLLs at the tail
528 * and app module at the head we insure that order
530 if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
532 /* is first loaded module a DLL or an exec ? */
533 mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
534 if (mark->Flink == mark ||
535 (CONTAINING_RECORD(mark->Flink, LDR_MODULE, InLoadOrderModuleList)->Flags & LDR_IMAGE_IS_DLL))
537 InsertHeadList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
538 &wm->ldr.InLoadOrderModuleList);
542 else wm->ldr.Flags |= LDR_IMAGE_IS_DLL;
545 InsertTailList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
546 &wm->ldr.InLoadOrderModuleList);
548 /* insert module in MemoryList, sorted in increasing base addresses */
549 mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
550 for (entry = mark->Flink; entry != mark; entry = entry->Flink)
552 if (CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList)->BaseAddress > wm->ldr.BaseAddress)
555 entry->Blink->Flink = &wm->ldr.InMemoryOrderModuleList;
556 wm->ldr.InMemoryOrderModuleList.Blink = entry->Blink;
557 wm->ldr.InMemoryOrderModuleList.Flink = entry;
558 entry->Blink = &wm->ldr.InMemoryOrderModuleList;
560 /* wait until init is called for inserting into this list */
561 wm->ldr.InInitializationOrderModuleList.Flink = NULL;
562 wm->ldr.InInitializationOrderModuleList.Blink = NULL;
567 /*************************************************************************
570 * Allocate the process-wide structure for module TLS storage.
572 static NTSTATUS alloc_process_tls(void)
574 PLIST_ENTRY mark, entry;
576 IMAGE_TLS_DIRECTORY *dir;
579 mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
580 for (entry = mark->Flink; entry != mark; entry = entry->Flink)
582 mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
583 if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE,
584 IMAGE_DIRECTORY_ENTRY_TLS, &size )))
586 size = (dir->EndAddressOfRawData - dir->StartAddressOfRawData) + dir->SizeOfZeroFill;
588 tls_total_size += size;
591 if (!tls_module_count) return STATUS_SUCCESS;
593 TRACE( "count %u size %u\n", tls_module_count, tls_total_size );
595 tls_dirs = RtlAllocateHeap( ntdll_get_process_heap(), 0, tls_module_count * sizeof(*tls_dirs) );
596 if (!tls_dirs) return STATUS_NO_MEMORY;
598 for (i = 0, entry = mark->Flink; entry != mark; entry = entry->Flink)
600 mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
601 if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE,
602 IMAGE_DIRECTORY_ENTRY_TLS, &size )))
605 *dir->AddressOfIndex = i;
607 mod->LoadCount = -1; /* can't unload it */
610 return STATUS_SUCCESS;
614 /*************************************************************************
617 * Allocate the per-thread structure for module TLS storage.
619 static NTSTATUS alloc_thread_tls(void)
625 if (!tls_module_count) return STATUS_SUCCESS;
627 if (!(pointers = RtlAllocateHeap( ntdll_get_process_heap(), 0,
628 tls_module_count * sizeof(*pointers) )))
629 return STATUS_NO_MEMORY;
631 if (!(data = RtlAllocateHeap( ntdll_get_process_heap(), 0, tls_total_size )))
633 RtlFreeHeap( ntdll_get_process_heap(), 0, pointers );
634 return STATUS_NO_MEMORY;
637 for (i = 0; i < tls_module_count; i++)
639 const IMAGE_TLS_DIRECTORY *dir = tls_dirs[i];
640 ULONG size = dir->EndAddressOfRawData - dir->StartAddressOfRawData;
642 TRACE( "thread %04lx idx %d: %ld/%ld bytes from %p to %p\n",
643 GetCurrentThreadId(), i, size, dir->SizeOfZeroFill,
644 (void *)dir->StartAddressOfRawData, data );
647 memcpy( data, (void *)dir->StartAddressOfRawData, size );
649 memset( data, 0, dir->SizeOfZeroFill );
650 data += dir->SizeOfZeroFill;
652 NtCurrentTeb()->ThreadLocalStoragePointer = pointers;
653 return STATUS_SUCCESS;
657 /*************************************************************************
660 static void call_tls_callbacks( HMODULE module, UINT reason )
662 const IMAGE_TLS_DIRECTORY *dir;
663 const PIMAGE_TLS_CALLBACK *callback;
666 dir = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &dirsize );
667 if (!dir || !dir->AddressOfCallBacks) return;
669 for (callback = dir->AddressOfCallBacks; *callback; callback++)
672 DPRINTF("%04lx:Call TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
673 GetCurrentThreadId(), *callback, module, reason_names[reason] );
674 (*callback)( module, reason, NULL );
676 DPRINTF("%04lx:Ret TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
677 GetCurrentThreadId(), *callback, module, reason_names[reason] );
682 /*************************************************************************
685 static BOOL MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved )
689 DLLENTRYPROC entry = wm->ldr.EntryPoint;
690 void *module = wm->ldr.BaseAddress;
692 /* Skip calls for modules loaded with special load flags */
694 if (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS) return TRUE;
695 if (wm->ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.BaseAddress, reason );
696 if (!entry || !(wm->ldr.Flags & LDR_IMAGE_IS_DLL)) return TRUE;
700 size_t len = min( wm->ldr.BaseDllName.Length, sizeof(mod_name)-sizeof(WCHAR) );
701 memcpy( mod_name, wm->ldr.BaseDllName.Buffer, len );
702 mod_name[len / sizeof(WCHAR)] = 0;
703 DPRINTF("%04lx:Call PE DLL (proc=%p,module=%p %s,reason=%s,res=%p)\n",
704 GetCurrentThreadId(), entry, module, debugstr_w(mod_name),
705 reason_names[reason], lpReserved );
707 else TRACE("(%p %s,%s,%p) - CALL\n", module, debugstr_w(wm->ldr.BaseDllName.Buffer),
708 reason_names[reason], lpReserved );
710 retv = entry( module, reason, lpReserved );
712 /* The state of the module list may have changed due to the call
713 to the dll. We cannot assume that this module has not been
716 DPRINTF("%04lx:Ret PE DLL (proc=%p,module=%p %s,reason=%s,res=%p) retval=%x\n",
717 GetCurrentThreadId(), entry, module, debugstr_w(mod_name),
718 reason_names[reason], lpReserved, retv );
719 else TRACE("(%p,%s,%p) - RETURN %d\n", module, reason_names[reason], lpReserved, retv );
725 /*************************************************************************
728 * Send the process attach notification to all DLLs the given module
729 * depends on (recursively). This is somewhat complicated due to the fact that
731 * - we have to respect the module dependencies, i.e. modules implicitly
732 * referenced by another module have to be initialized before the module
733 * itself can be initialized
735 * - the initialization routine of a DLL can itself call LoadLibrary,
736 * thereby introducing a whole new set of dependencies (even involving
737 * the 'old' modules) at any time during the whole process
739 * (Note that this routine can be recursively entered not only directly
740 * from itself, but also via LoadLibrary from one of the called initialization
743 * Furthermore, we need to rearrange the main WINE_MODREF list to allow
744 * the process *detach* notifications to be sent in the correct order.
745 * This must not only take into account module dependencies, but also
746 * 'hidden' dependencies created by modules calling LoadLibrary in their
747 * attach notification routine.
749 * The strategy is rather simple: we move a WINE_MODREF to the head of the
750 * list after the attach notification has returned. This implies that the
751 * detach notifications are called in the reverse of the sequence the attach
752 * notifications *returned*.
754 * The loader_section must be locked while calling this function.
756 static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved )
758 NTSTATUS status = STATUS_SUCCESS;
761 /* prevent infinite recursion in case of cyclical dependencies */
762 if ( ( wm->ldr.Flags & LDR_LOAD_IN_PROGRESS )
763 || ( wm->ldr.Flags & LDR_PROCESS_ATTACHED ) )
766 TRACE("(%s,%p) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved );
768 /* Tag current MODREF to prevent recursive loop */
769 wm->ldr.Flags |= LDR_LOAD_IN_PROGRESS;
771 /* Recursively attach all DLLs this one depends on */
772 for ( i = 0; i < wm->nDeps; i++ )
774 if (!wm->deps[i]) continue;
775 if ((status = process_attach( wm->deps[i], lpReserved )) != STATUS_SUCCESS) break;
778 /* Call DLL entry point */
779 if (status == STATUS_SUCCESS)
781 WINE_MODREF *prev = current_modref;
783 if (MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved ))
784 wm->ldr.Flags |= LDR_PROCESS_ATTACHED;
786 status = STATUS_DLL_INIT_FAILED;
787 current_modref = prev;
790 InsertTailList(&NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList,
791 &wm->ldr.InInitializationOrderModuleList);
793 /* Remove recursion flag */
794 wm->ldr.Flags &= ~LDR_LOAD_IN_PROGRESS;
796 TRACE("(%s,%p) - END\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved );
800 /*************************************************************************
803 * Send DLL process detach notifications. See the comment about calling
804 * sequence at process_attach. Unless the bForceDetach flag
805 * is set, only DLLs with zero refcount are notified.
807 static void process_detach( BOOL bForceDetach, LPVOID lpReserved )
809 PLIST_ENTRY mark, entry;
812 RtlEnterCriticalSection( &loader_section );
813 if (bForceDetach) process_detaching = 1;
814 mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
817 for (entry = mark->Blink; entry != mark; entry = entry->Blink)
819 mod = CONTAINING_RECORD(entry, LDR_MODULE,
820 InInitializationOrderModuleList);
821 /* Check whether to detach this DLL */
822 if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
824 if ( mod->LoadCount && !bForceDetach )
827 /* Call detach notification */
828 mod->Flags &= ~LDR_PROCESS_ATTACHED;
829 MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr),
830 DLL_PROCESS_DETACH, lpReserved );
832 /* Restart at head of WINE_MODREF list, as entries might have
833 been added and/or removed while performing the call ... */
836 } while (entry != mark);
838 RtlLeaveCriticalSection( &loader_section );
841 /*************************************************************************
842 * MODULE_DllThreadAttach
844 * Send DLL thread attach notifications. These are sent in the
845 * reverse sequence of process detach notification.
848 NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved )
850 PLIST_ENTRY mark, entry;
854 /* don't do any attach calls if process is exiting */
855 if (process_detaching) return STATUS_SUCCESS;
856 /* FIXME: there is still a race here */
858 RtlEnterCriticalSection( &loader_section );
860 if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto done;
862 mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
863 for (entry = mark->Flink; entry != mark; entry = entry->Flink)
865 mod = CONTAINING_RECORD(entry, LDR_MODULE,
866 InInitializationOrderModuleList);
867 if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
869 if ( mod->Flags & LDR_NO_DLL_CALLS )
872 MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr),
873 DLL_THREAD_ATTACH, lpReserved );
877 RtlLeaveCriticalSection( &loader_section );
881 /******************************************************************
882 * LdrDisableThreadCalloutsForDll (NTDLL.@)
885 NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE hModule)
888 NTSTATUS ret = STATUS_SUCCESS;
890 RtlEnterCriticalSection( &loader_section );
892 wm = get_modref( hModule );
893 if (!wm || wm->ldr.TlsIndex != -1)
894 ret = STATUS_DLL_NOT_FOUND;
896 wm->ldr.Flags |= LDR_NO_DLL_CALLS;
898 RtlLeaveCriticalSection( &loader_section );
903 /******************************************************************
904 * LdrFindEntryForAddress (NTDLL.@)
906 * The loader_section must be locked while calling this function
908 NTSTATUS WINAPI LdrFindEntryForAddress(const void* addr, PLDR_MODULE* pmod)
910 PLIST_ENTRY mark, entry;
913 mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
914 for (entry = mark->Flink; entry != mark; entry = entry->Flink)
916 mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
917 if ((const void *)mod->BaseAddress <= addr &&
918 (char *)addr < (char*)mod->BaseAddress + mod->SizeOfImage)
921 return STATUS_SUCCESS;
923 if ((const void *)mod->BaseAddress > addr) break;
925 return STATUS_NO_MORE_ENTRIES;
928 /******************************************************************
929 * LdrLockLoaderLock (NTDLL.@)
931 * Note: flags are not implemented.
932 * Flag 0x01 is used to raise exceptions on errors.
933 * Flag 0x02 is used to avoid waiting on the section (does RtlTryEnterCriticalSection instead).
935 NTSTATUS WINAPI LdrLockLoaderLock( ULONG flags, ULONG *result, ULONG *magic )
937 if (flags) FIXME( "flags %lx not supported\n", flags );
939 if (result) *result = 1;
940 if (!magic) return STATUS_INVALID_PARAMETER_3;
941 RtlEnterCriticalSection( &loader_section );
942 *magic = GetCurrentThreadId();
943 return STATUS_SUCCESS;
947 /******************************************************************
948 * LdrUnlockLoaderUnlock (NTDLL.@)
950 NTSTATUS WINAPI LdrUnlockLoaderLock( ULONG flags, ULONG magic )
954 if (magic != GetCurrentThreadId()) return STATUS_INVALID_PARAMETER_2;
955 RtlLeaveCriticalSection( &loader_section );
957 return STATUS_SUCCESS;
961 /******************************************************************
962 * LdrGetDllHandle (NTDLL.@)
964 NTSTATUS WINAPI LdrGetDllHandle(ULONG x, ULONG y, const UNICODE_STRING *name, HMODULE *base)
966 NTSTATUS status = STATUS_DLL_NOT_FOUND;
967 WCHAR dllname[MAX_PATH+4], *p;
969 PLIST_ENTRY mark, entry;
972 if (x != 0 || y != 0)
973 FIXME("Unknown behavior, please report\n");
975 /* Append .DLL to name if no extension present */
976 if (!(p = strrchrW( name->Buffer, '.')) || strchrW( p, '/' ) || strchrW( p, '\\'))
978 if (name->Length >= MAX_PATH) return STATUS_NAME_TOO_LONG;
979 strcpyW( dllname, name->Buffer );
980 strcatW( dllname, dllW );
981 RtlInitUnicodeString( &str, dllname );
985 RtlEnterCriticalSection( &loader_section );
989 if (RtlEqualUnicodeString( name, &cached_modref->ldr.FullDllName, TRUE ) ||
990 RtlEqualUnicodeString( name, &cached_modref->ldr.BaseDllName, TRUE ))
992 *base = cached_modref->ldr.BaseAddress;
993 status = STATUS_SUCCESS;
998 mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
999 for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1001 mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
1003 if (RtlEqualUnicodeString( name, &mod->FullDllName, TRUE ) ||
1004 RtlEqualUnicodeString( name, &mod->BaseDllName, TRUE ))
1006 cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
1007 *base = mod->BaseAddress;
1008 status = STATUS_SUCCESS;
1013 RtlLeaveCriticalSection( &loader_section );
1014 TRACE("%lx %lx %s -> %p\n", x, y, debugstr_us(name), status ? NULL : *base);
1019 /******************************************************************
1020 * LdrGetProcedureAddress (NTDLL.@)
1022 NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name,
1023 ULONG ord, PVOID *address)
1025 IMAGE_EXPORT_DIRECTORY *exports;
1027 NTSTATUS ret = STATUS_PROCEDURE_NOT_FOUND;
1029 RtlEnterCriticalSection( &loader_section );
1031 if ((exports = RtlImageDirectoryEntryToData( module, TRUE,
1032 IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
1034 void *proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1 )
1035 : find_ordinal_export( module, exports, exp_size, ord - exports->Base );
1039 ret = STATUS_SUCCESS;
1044 /* check if the module itself is invalid to return the proper error */
1045 if (!get_modref( module )) ret = STATUS_DLL_NOT_FOUND;
1048 RtlLeaveCriticalSection( &loader_section );
1053 /***********************************************************************
1054 * load_builtin_callback
1056 * Load a library in memory; callback function for wine_dll_register
1058 static void load_builtin_callback( void *module, const char *filename )
1060 static const WCHAR emptyW[1];
1062 IMAGE_NT_HEADERS *nt;
1064 WCHAR *fullname, *p;
1065 const WCHAR *load_path;
1069 ERR("could not map image for %s\n", filename ? filename : "main exe" );
1072 if (!(nt = RtlImageNtHeader( module )))
1074 ERR( "bad module for %s\n", filename ? filename : "main exe" );
1075 builtin_load_info->status = STATUS_INVALID_IMAGE_FORMAT;
1078 if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
1080 /* if we already have an executable, ignore this one */
1081 if (!NtCurrentTeb()->Peb->ImageBaseAddress)
1082 NtCurrentTeb()->Peb->ImageBaseAddress = module;
1083 return; /* don't create the modref here, will be done later on */
1086 /* create the MODREF */
1088 if (!(fullname = RtlAllocateHeap( GetProcessHeap(), 0,
1089 system_dir.MaximumLength + (strlen(filename) + 1) * sizeof(WCHAR) )))
1091 ERR( "can't load %s\n", filename );
1092 builtin_load_info->status = STATUS_NO_MEMORY;
1095 memcpy( fullname, system_dir.Buffer, system_dir.Length );
1096 p = fullname + system_dir.Length / sizeof(WCHAR);
1097 if (p > fullname && p[-1] != '\\') *p++ = '\\';
1098 ascii_to_unicode( p, filename, strlen(filename) + 1 );
1100 wm = alloc_module( module, fullname );
1101 RtlFreeHeap( GetProcessHeap(), 0, fullname );
1104 ERR( "can't load %s\n", filename );
1105 builtin_load_info->status = STATUS_NO_MEMORY;
1108 wm->ldr.Flags |= LDR_WINE_INTERNAL;
1109 NtAllocateVirtualMemory( GetCurrentProcess(), &addr, module, &nt->OptionalHeader.SizeOfImage,
1110 MEM_SYSTEM | MEM_IMAGE, PAGE_EXECUTE_WRITECOPY );
1114 load_path = builtin_load_info->load_path;
1115 if (!load_path) load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
1116 if (!load_path) load_path = emptyW;
1117 if (fixup_imports( wm, load_path ) != STATUS_SUCCESS)
1119 /* the module has only be inserted in the load & memory order lists */
1120 RemoveEntryList(&wm->ldr.InLoadOrderModuleList);
1121 RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);
1122 /* FIXME: free the modref */
1123 builtin_load_info->status = STATUS_DLL_NOT_FOUND;
1126 builtin_load_info->wm = wm;
1127 TRACE( "loaded %s %p %p\n", filename, wm, module );
1129 /* send the DLL load event */
1131 SERVER_START_REQ( load_dll )
1135 req->size = nt->OptionalHeader.SizeOfImage;
1136 req->dbg_offset = nt->FileHeader.PointerToSymbolTable;
1137 req->dbg_size = nt->FileHeader.NumberOfSymbols;
1138 req->name = &wm->ldr.FullDllName.Buffer;
1139 wine_server_add_data( req, wm->ldr.FullDllName.Buffer, wm->ldr.FullDllName.Length );
1140 wine_server_call( req );
1144 /* setup relay debugging entry points */
1145 if (TRACE_ON(relay)) RELAY_SetupDLL( module );
1149 /******************************************************************************
1150 * load_native_dll (internal)
1152 static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
1153 DWORD flags, WINE_MODREF** pwm )
1157 OBJECT_ATTRIBUTES attr;
1159 IMAGE_NT_HEADERS *nt;
1164 TRACE( "loading %s\n", debugstr_w(name) );
1166 attr.Length = sizeof(attr);
1167 attr.RootDirectory = 0;
1168 attr.ObjectName = NULL;
1169 attr.Attributes = 0;
1170 attr.SecurityDescriptor = NULL;
1171 attr.SecurityQualityOfService = NULL;
1174 status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1175 &attr, &size, 0, SEC_IMAGE, file );
1176 if (status != STATUS_SUCCESS) return status;
1179 status = NtMapViewOfSection( mapping, GetCurrentProcess(),
1180 &module, 0, 0, &size, &len, ViewShare, 0, PAGE_READONLY );
1182 if (status != STATUS_SUCCESS) return status;
1184 /* create the MODREF */
1186 if (!(wm = alloc_module( module, name ))) return STATUS_NO_MEMORY;
1190 if (!(flags & DONT_RESOLVE_DLL_REFERENCES))
1192 if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS)
1194 /* the module has only be inserted in the load & memory order lists */
1195 RemoveEntryList(&wm->ldr.InLoadOrderModuleList);
1196 RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);
1198 /* FIXME: there are several more dangling references
1199 * left. Including dlls loaded by this dll before the
1200 * failed one. Unrolling is rather difficult with the
1201 * current structure and we can leave them lying
1202 * around with no problems, so we don't care.
1203 * As these might reference our wm, we don't free it.
1208 else wm->ldr.Flags |= LDR_DONT_RESOLVE_REFS;
1210 /* send DLL load event */
1212 nt = RtlImageNtHeader( module );
1214 SERVER_START_REQ( load_dll )
1218 req->size = nt->OptionalHeader.SizeOfImage;
1219 req->dbg_offset = nt->FileHeader.PointerToSymbolTable;
1220 req->dbg_size = nt->FileHeader.NumberOfSymbols;
1221 req->name = &wm->ldr.FullDllName.Buffer;
1222 wine_server_add_data( req, wm->ldr.FullDllName.Buffer, wm->ldr.FullDllName.Length );
1223 wine_server_call( req );
1227 if (TRACE_ON(snoop)) SNOOP_SetupDLL( module );
1230 return STATUS_SUCCESS;
1234 /***********************************************************************
1237 static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, DWORD flags, WINE_MODREF** pwm )
1239 char error[256], dllname[MAX_PATH];
1241 const WCHAR *name, *p;
1244 struct builtin_load_info info, *prev_info;
1246 /* Fix the name in case we have a full path and extension */
1248 if ((p = strrchrW( name, '\\' ))) name = p + 1;
1249 if ((p = strrchrW( name, '/' ))) name = p + 1;
1251 /* we don't want to depend on the current codepage here */
1252 len = strlenW( name ) + 1;
1253 if (len >= sizeof(dllname)) return STATUS_NAME_TOO_LONG;
1254 for (i = 0; i < len; i++)
1256 if (name[i] > 127) return STATUS_DLL_NOT_FOUND;
1257 dllname[i] = (char)name[i];
1258 if (dllname[i] >= 'A' && dllname[i] <= 'Z') dllname[i] += 'a' - 'A';
1261 /* load_library will modify info.status. Note also that load_library can be
1262 * called several times, if the .so file we're loading has dependencies.
1263 * info.status will gather all the errors we may get while loading all these
1266 info.load_path = load_path;
1267 info.status = STATUS_SUCCESS;
1269 prev_info = builtin_load_info;
1270 builtin_load_info = &info;
1271 handle = wine_dll_load( dllname, error, sizeof(error), &file_exists );
1272 builtin_load_info = prev_info;
1278 /* The file does not exist -> WARN() */
1279 WARN("cannot open .so lib for builtin %s: %s\n", debugstr_w(name), error);
1280 return STATUS_DLL_NOT_FOUND;
1282 /* ERR() for all other errors (missing functions, ...) */
1283 ERR("failed to load .so lib for builtin %s: %s\n", debugstr_w(name), error );
1284 return STATUS_PROCEDURE_NOT_FOUND;
1286 if (info.status != STATUS_SUCCESS) return info.status;
1290 /* The constructor wasn't called, this means the .so is already
1291 * loaded under a different name. We can't support multiple names
1292 * for the same module, so return an error. */
1293 return STATUS_INVALID_IMAGE_FORMAT;
1296 info.wm->ldr.SectionHandle = handle;
1297 if (strcmpiW( info.wm->ldr.BaseDllName.Buffer, name ))
1299 ERR( "loaded .so for %s but got %s instead - probably 16-bit dll\n",
1300 debugstr_w(name), debugstr_w(info.wm->ldr.BaseDllName.Buffer) );
1301 /* wine_dll_unload( handle );*/
1302 return STATUS_INVALID_IMAGE_FORMAT;
1305 return STATUS_SUCCESS;
1309 /***********************************************************************
1312 * Find the file (or already loaded module) for a given dll name.
1314 static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
1315 WCHAR *filename, ULONG *size, WINE_MODREF **pwm, HANDLE *handle )
1317 WCHAR *file_part, *ext;
1320 if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH)
1322 /* we need to search for it */
1323 /* but first append .dll because RtlDosSearchPath extension handling is broken */
1324 if (!(ext = strrchrW( libname, '.')) || strchrW( ext, '/' ) || strchrW( ext, '\\'))
1328 if (!(dllname = RtlAllocateHeap( GetProcessHeap(), 0,
1329 (strlenW(libname) * sizeof(WCHAR)) + sizeof(dllW) )))
1330 return STATUS_NO_MEMORY;
1331 strcpyW( dllname, libname );
1332 strcatW( dllname, dllW );
1333 len = RtlDosSearchPath_U( load_path, dllname, NULL, *size, filename, &file_part );
1334 RtlFreeHeap( GetProcessHeap(), 0, dllname );
1336 else len = RtlDosSearchPath_U( load_path, libname, NULL, *size, filename, &file_part );
1342 *size = len + sizeof(WCHAR);
1343 return STATUS_BUFFER_TOO_SMALL;
1345 if ((*pwm = find_fullname_module( filename )) != NULL) return STATUS_SUCCESS;
1347 /* check for already loaded module in a different path */
1348 if (!contains_path( libname ))
1350 if ((*pwm = find_basename_module( file_part )) != NULL) return STATUS_SUCCESS;
1352 *handle = pCreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1353 return STATUS_SUCCESS;
1358 if (!contains_path( libname ))
1360 /* if libname doesn't contain a path at all, we simply return the name as is,
1361 * to be loaded as builtin */
1362 len = strlenW(libname) * sizeof(WCHAR);
1363 if (len >= *size) goto overflow;
1364 strcpyW( filename, libname );
1365 if (!strchrW( filename, '.' ))
1367 len += sizeof(dllW) - sizeof(WCHAR);
1368 if (len >= *size) goto overflow;
1369 strcatW( filename, dllW );
1371 *pwm = find_basename_module( filename );
1372 return STATUS_SUCCESS;
1376 /* absolute path name, or relative path name but not found above */
1378 len = RtlGetFullPathName_U( libname, *size, filename, &file_part );
1379 if (len >= *size) goto overflow;
1380 if (file_part && !strchrW( file_part, '.' ))
1382 len += sizeof(dllW) - sizeof(WCHAR);
1383 if (len >= *size) goto overflow;
1384 strcatW( file_part, dllW );
1386 if ((*pwm = find_fullname_module( filename )) != NULL) return STATUS_SUCCESS;
1387 *handle = pCreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1388 return STATUS_SUCCESS;
1391 *size = len + sizeof(WCHAR);
1392 return STATUS_BUFFER_TOO_SMALL;
1396 /***********************************************************************
1397 * load_dll (internal)
1399 * Load a PE style module according to the load order.
1400 * The loader_section must be locked while calling this function.
1402 static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
1405 enum loadorder_type loadorder[LOADORDER_NTYPES];
1409 const char *filetype = "";
1410 WINE_MODREF *main_exe;
1411 HANDLE handle = INVALID_HANDLE_VALUE;
1414 TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
1417 size = sizeof(buffer);
1420 nts = find_dll_file( load_path, libname, filename, &size, pwm, &handle );
1421 if (nts == STATUS_SUCCESS) break;
1422 if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
1423 if (nts != STATUS_BUFFER_TOO_SMALL) return nts;
1424 /* grow the buffer and retry */
1425 if (!(filename = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return STATUS_NO_MEMORY;
1428 if (*pwm) /* found already loaded module */
1430 if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
1432 if (((*pwm)->ldr.Flags & LDR_DONT_RESOLVE_REFS) &&
1433 !(flags & DONT_RESOLVE_DLL_REFERENCES))
1435 (*pwm)->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;
1436 fixup_imports( *pwm, load_path );
1438 TRACE("Found loaded module %s for %s at %p, count=%d\n",
1439 debugstr_w((*pwm)->ldr.FullDllName.Buffer), debugstr_w(libname),
1440 (*pwm)->ldr.BaseAddress, (*pwm)->ldr.LoadCount);
1441 if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
1442 return STATUS_SUCCESS;
1445 main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
1446 MODULE_GetLoadOrderW( loadorder, main_exe->ldr.BaseDllName.Buffer, filename, TRUE);
1448 nts = STATUS_DLL_NOT_FOUND;
1449 for (i = 0; i < LOADORDER_NTYPES; i++)
1451 if (loadorder[i] == LOADORDER_INVALID) break;
1453 switch (loadorder[i])
1456 TRACE("Trying native dll %s\n", debugstr_w(filename));
1457 if (handle == INVALID_HANDLE_VALUE) continue; /* it cannot possibly be loaded */
1458 nts = load_native_dll( load_path, filename, handle, flags, pwm );
1459 filetype = "native";
1462 TRACE("Trying built-in %s\n", debugstr_w(filename));
1463 nts = load_builtin_dll( load_path, filename, flags, pwm );
1464 filetype = "builtin";
1467 nts = STATUS_INTERNAL_ERROR;
1471 if (nts == STATUS_SUCCESS)
1473 /* Initialize DLL just loaded */
1474 TRACE("Loaded module %s (%s) at %p\n",
1475 debugstr_w(filename), filetype, (*pwm)->ldr.BaseAddress);
1476 if (!TRACE_ON(module))
1477 TRACE_(loaddll)("Loaded module %s : %s\n", debugstr_w(filename), filetype);
1478 /* Set the ldr.LoadCount here so that an attach failure will */
1479 /* decrement the dependencies through the MODULE_FreeLibrary call. */
1480 (*pwm)->ldr.LoadCount = 1;
1481 if (handle != INVALID_HANDLE_VALUE) NtClose( handle );
1482 if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
1485 if (nts != STATUS_DLL_NOT_FOUND) break;
1488 WARN("Failed to load module %s; status=%lx\n", debugstr_w(libname), nts);
1489 if (handle != INVALID_HANDLE_VALUE) NtClose( handle );
1490 if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
1494 /******************************************************************
1495 * LdrLoadDll (NTDLL.@)
1497 NTSTATUS WINAPI LdrLoadDll(LPCWSTR path_name, DWORD flags,
1498 const UNICODE_STRING *libname, HMODULE* hModule)
1503 RtlEnterCriticalSection( &loader_section );
1505 if (!path_name) path_name = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
1506 nts = load_dll( path_name, libname->Buffer, flags, &wm );
1508 if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
1510 nts = process_attach( wm, NULL );
1511 if (nts != STATUS_SUCCESS)
1513 WARN("Attach failed for module %s\n", debugstr_w(libname->Buffer));
1514 LdrUnloadDll(wm->ldr.BaseAddress);
1518 *hModule = (wm) ? wm->ldr.BaseAddress : NULL;
1520 RtlLeaveCriticalSection( &loader_section );
1524 /******************************************************************
1525 * LdrQueryProcessModuleInformation
1528 NTSTATUS WINAPI LdrQueryProcessModuleInformation(PSYSTEM_MODULE_INFORMATION smi,
1529 ULONG buf_size, ULONG* req_size)
1531 SYSTEM_MODULE* sm = &smi->Modules[0];
1532 ULONG size = sizeof(ULONG);
1533 NTSTATUS nts = STATUS_SUCCESS;
1536 PLIST_ENTRY mark, entry;
1539 smi->ModulesCount = 0;
1541 RtlEnterCriticalSection( &loader_section );
1542 mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
1543 for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1545 mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
1546 size += sizeof(*sm);
1547 if (size <= buf_size)
1549 sm->Reserved1 = 0; /* FIXME */
1550 sm->Reserved2 = 0; /* FIXME */
1551 sm->ImageBaseAddress = mod->BaseAddress;
1552 sm->ImageSize = mod->SizeOfImage;
1553 sm->Flags = mod->Flags;
1554 sm->Id = 0; /* FIXME */
1555 sm->Rank = 0; /* FIXME */
1556 sm->Unknown = 0; /* FIXME */
1558 str.MaximumLength = MAXIMUM_FILENAME_LENGTH;
1559 str.Buffer = sm->Name;
1560 RtlUnicodeStringToAnsiString(&str, &mod->FullDllName, FALSE);
1561 ptr = strrchr(sm->Name, '\\');
1562 sm->NameOffset = (ptr != NULL) ? (ptr - (char*)sm->Name + 1) : 0;
1564 smi->ModulesCount++;
1567 else nts = STATUS_INFO_LENGTH_MISMATCH;
1569 RtlLeaveCriticalSection( &loader_section );
1571 if (req_size) *req_size = size;
1576 /******************************************************************
1577 * LdrShutdownProcess (NTDLL.@)
1580 void WINAPI LdrShutdownProcess(void)
1583 process_detach( TRUE, (LPVOID)1 );
1586 /******************************************************************
1587 * LdrShutdownThread (NTDLL.@)
1590 void WINAPI LdrShutdownThread(void)
1592 PLIST_ENTRY mark, entry;
1597 /* don't do any detach calls if process is exiting */
1598 if (process_detaching) return;
1599 /* FIXME: there is still a race here */
1601 RtlEnterCriticalSection( &loader_section );
1603 mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
1604 for (entry = mark->Blink; entry != mark; entry = entry->Blink)
1606 mod = CONTAINING_RECORD(entry, LDR_MODULE,
1607 InInitializationOrderModuleList);
1608 if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
1610 if ( mod->Flags & LDR_NO_DLL_CALLS )
1613 MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr),
1614 DLL_THREAD_DETACH, NULL );
1617 RtlLeaveCriticalSection( &loader_section );
1620 /***********************************************************************
1621 * MODULE_FlushModrefs
1623 * Remove all unused modrefs and call the internal unloading routines
1624 * for the library type.
1626 * The loader_section must be locked while calling this function.
1628 static void MODULE_FlushModrefs(void)
1630 PLIST_ENTRY mark, entry, prev;
1634 mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
1635 for (entry = mark->Blink; entry != mark; entry = prev)
1637 mod = CONTAINING_RECORD(entry, LDR_MODULE,
1638 InInitializationOrderModuleList);
1639 wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
1641 prev = entry->Blink;
1642 if (mod->LoadCount) continue;
1644 RemoveEntryList(&mod->InLoadOrderModuleList);
1645 RemoveEntryList(&mod->InMemoryOrderModuleList);
1646 RemoveEntryList(&mod->InInitializationOrderModuleList);
1648 TRACE(" unloading %s\n", debugstr_w(mod->FullDllName.Buffer));
1649 if (!TRACE_ON(module))
1650 TRACE_(loaddll)("Unloaded module %s : %s\n",
1651 debugstr_w(mod->FullDllName.Buffer),
1652 (wm->ldr.Flags & LDR_WINE_INTERNAL) ? "builtin" : "native" );
1654 SERVER_START_REQ( unload_dll )
1656 req->base = mod->BaseAddress;
1657 wine_server_call( req );
1661 if (wm->ldr.Flags & LDR_WINE_INTERNAL) wine_dll_unload( wm->ldr.SectionHandle );
1662 NtUnmapViewOfSection( GetCurrentProcess(), mod->BaseAddress );
1663 if (cached_modref == wm) cached_modref = NULL;
1664 RtlFreeUnicodeString( &mod->FullDllName );
1665 RtlFreeHeap( ntdll_get_process_heap(), 0, wm->deps );
1666 RtlFreeHeap( ntdll_get_process_heap(), 0, wm );
1670 /***********************************************************************
1671 * MODULE_DecRefCount
1673 * The loader_section must be locked while calling this function.
1675 static void MODULE_DecRefCount( WINE_MODREF *wm )
1679 if ( wm->ldr.Flags & LDR_UNLOAD_IN_PROGRESS )
1682 if ( wm->ldr.LoadCount <= 0 )
1685 --wm->ldr.LoadCount;
1686 TRACE("(%s) ldr.LoadCount: %d\n", debugstr_w(wm->ldr.BaseDllName.Buffer), wm->ldr.LoadCount );
1688 if ( wm->ldr.LoadCount == 0 )
1690 wm->ldr.Flags |= LDR_UNLOAD_IN_PROGRESS;
1692 for ( i = 0; i < wm->nDeps; i++ )
1694 MODULE_DecRefCount( wm->deps[i] );
1696 wm->ldr.Flags &= ~LDR_UNLOAD_IN_PROGRESS;
1700 /******************************************************************
1701 * LdrUnloadDll (NTDLL.@)
1705 NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule )
1707 NTSTATUS retv = STATUS_SUCCESS;
1709 TRACE("(%p)\n", hModule);
1711 RtlEnterCriticalSection( &loader_section );
1713 /* if we're stopping the whole process (and forcing the removal of all
1714 * DLLs) the library will be freed anyway
1716 if (!process_detaching)
1721 if ((wm = get_modref( hModule )) != NULL)
1723 TRACE("(%s) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer));
1725 /* Recursively decrement reference counts */
1726 MODULE_DecRefCount( wm );
1728 /* Call process detach notifications */
1729 if ( free_lib_count <= 1 )
1731 process_detach( FALSE, NULL );
1732 MODULE_FlushModrefs();
1738 retv = STATUS_DLL_NOT_FOUND;
1743 RtlLeaveCriticalSection( &loader_section );
1748 /***********************************************************************
1749 * RtlImageNtHeader (NTDLL.@)
1751 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
1753 IMAGE_NT_HEADERS *ret;
1757 IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)hModule;
1760 if (dos->e_magic == IMAGE_DOS_SIGNATURE)
1762 ret = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew);
1763 if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL;
1766 __EXCEPT(page_fault)
1775 /******************************************************************
1776 * LdrInitializeThunk (NTDLL.@)
1778 * FIXME: the arguments are not correct, main_file and CreateFileW_ptr are Wine inventions.
1780 void WINAPI LdrInitializeThunk( HANDLE main_file, void *CreateFileW_ptr, ULONG unknown3, ULONG unknown4 )
1785 PEB *peb = NtCurrentTeb()->Peb;
1786 UNICODE_STRING *main_exe_name = &peb->ProcessParameters->ImagePathName;
1787 IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress );
1789 pCreateFileW = CreateFileW_ptr;
1790 if (!MODULE_GetSystemDirectory( &system_dir ))
1792 ERR( "Couldn't get system dir\n");
1796 /* allocate the modref for the main exe */
1797 if (!(wm = alloc_module( peb->ImageBaseAddress, main_exe_name->Buffer )))
1799 status = STATUS_NO_MEMORY;
1802 wm->ldr.LoadCount = -1; /* can't unload main exe */
1804 /* Install signal handlers; this cannot be done before, since we cannot
1805 * send exceptions to the debugger before the create process event that
1806 * is sent by REQ_INIT_PROCESS_DONE.
1807 * We do need the handlers in place by the time the request is over, so
1808 * we set them up here. If we segfault between here and the server call
1809 * something is very wrong... */
1810 if (!SIGNAL_Init()) exit(1);
1812 /* Signal the parent process to continue */
1813 SERVER_START_REQ( init_process_done )
1815 req->module = peb->ImageBaseAddress;
1816 req->module_size = wm->ldr.SizeOfImage;
1817 req->entry = wm->ldr.EntryPoint;
1818 /* API requires a double indirection */
1819 req->name = &main_exe_name->Buffer;
1820 req->exe_file = main_file;
1821 req->gui = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI);
1822 wine_server_add_data( req, main_exe_name->Buffer, main_exe_name->Length );
1823 wine_server_call( req );
1827 if (main_file) NtClose( main_file ); /* we no longer need it */
1829 if (TRACE_ON(relay) || TRACE_ON(snoop))
1831 RELAY_InitDebugLists();
1833 if (TRACE_ON(relay)) /* setup relay for already loaded dlls */
1835 LIST_ENTRY *entry, *mark = &peb->LdrData->InLoadOrderModuleList;
1836 for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1838 LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
1839 if (mod->Flags & LDR_WINE_INTERNAL) RELAY_SetupDLL( mod->BaseAddress );
1844 RtlEnterCriticalSection( &loader_section );
1846 load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
1847 if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS) goto error;
1848 if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto error;
1849 if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error;
1850 if ((status = process_attach( wm, (LPVOID)1 )) != STATUS_SUCCESS) goto error;
1852 RtlLeaveCriticalSection( &loader_section );
1856 ERR( "Main exe initialization failed, status %lx\n", status );
1861 /***********************************************************************
1862 * RtlImageDirectoryEntryToData (NTDLL.@)
1864 PVOID WINAPI RtlImageDirectoryEntryToData( HMODULE module, BOOL image, WORD dir, ULONG *size )
1866 const IMAGE_NT_HEADERS *nt;
1869 if ((ULONG_PTR)module & 1) /* mapped as data file */
1871 module = (HMODULE)((ULONG_PTR)module & ~1);
1874 if (!(nt = RtlImageNtHeader( module ))) return NULL;
1875 if (dir >= nt->OptionalHeader.NumberOfRvaAndSizes) return NULL;
1876 if (!(addr = nt->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;
1877 *size = nt->OptionalHeader.DataDirectory[dir].Size;
1878 if (image || addr < nt->OptionalHeader.SizeOfHeaders) return (char *)module + addr;
1880 /* not mapped as image, need to find the section containing the virtual address */
1881 return RtlImageRvaToVa( nt, module, addr, NULL );
1885 /***********************************************************************
1886 * RtlImageRvaToSection (NTDLL.@)
1888 PIMAGE_SECTION_HEADER WINAPI RtlImageRvaToSection( const IMAGE_NT_HEADERS *nt,
1889 HMODULE module, DWORD rva )
1892 IMAGE_SECTION_HEADER *sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader +
1893 nt->FileHeader.SizeOfOptionalHeader);
1894 for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
1896 if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
1903 /***********************************************************************
1904 * RtlImageRvaToVa (NTDLL.@)
1906 PVOID WINAPI RtlImageRvaToVa( const IMAGE_NT_HEADERS *nt, HMODULE module,
1907 DWORD rva, IMAGE_SECTION_HEADER **section )
1909 IMAGE_SECTION_HEADER *sec;
1911 if (section && *section) /* try this section first */
1914 if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
1917 if (!(sec = RtlImageRvaToSection( nt, module, rva ))) return NULL;
1919 if (section) *section = sec;
1920 return (char *)module + sec->PointerToRawData + (rva - sec->VirtualAddress);
1924 /***********************************************************************
1925 * __wine_process_init
1927 void __wine_process_init( int argc, char *argv[] )
1929 static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
1933 ANSI_STRING func_name;
1934 void (* DECLSPEC_NORETURN init_func)();
1938 /* setup the load callback and create ntdll modref */
1939 wine_dll_set_callback( load_builtin_callback );
1941 if ((status = load_builtin_dll( NULL, kernel32W, 0, &wm )) != STATUS_SUCCESS)
1943 MESSAGE( "wine: could not load kernel32.dll, status %lx\n", status );
1946 RtlInitAnsiString( &func_name, "__wine_kernel_init" );
1947 if ((status = LdrGetProcedureAddress( wm->ldr.BaseAddress, &func_name,
1948 0, (void **)&init_func )) != STATUS_SUCCESS)
1950 MESSAGE( "wine: could not find __wine_kernel_init in kernel32.dll, status %lx\n", status );