Added stubs for AccessCheckByType, AddAuditAccessAce,
[wine] / dlls / ntdll / loader.c
1 /*
2  * Loader functions
3  *
4  * Copyright 1995, 2003 Alexandre Julliard
5  * Copyright 2002 Dmitry Timoshkov for CodeWeavers
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include <assert.h>
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnt.h"
28 #include "winreg.h"
29 #include "winternl.h"
30
31 #include "module.h"
32 #include "file.h"
33 #include "wine/exception.h"
34 #include "excpt.h"
35 #include "wine/unicode.h"
36 #include "wine/debug.h"
37 #include "wine/server.h"
38 #include "ntdll_misc.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(module);
41 WINE_DECLARE_DEBUG_CHANNEL(relay);
42 WINE_DECLARE_DEBUG_CHANNEL(snoop);
43 WINE_DECLARE_DEBUG_CHANNEL(loaddll);
44
45 typedef DWORD (CALLBACK *DLLENTRYPROC)(HMODULE,DWORD,LPVOID);
46
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 */
49
50 /* filter for page-fault exceptions */
51 static WINE_EXCEPTION_FILTER(page_fault)
52 {
53     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
54         return EXCEPTION_EXECUTE_HANDLER;
55     return EXCEPTION_CONTINUE_SEARCH;
56 }
57
58 static const char * const reason_names[] =
59 {
60     "PROCESS_DETACH",
61     "PROCESS_ATTACH",
62     "THREAD_ATTACH",
63     "THREAD_DETACH"
64 };
65
66 static const WCHAR dllW[] = {'.','d','l','l',0};
67
68 /* internal representation of 32bit modules. per process. */
69 typedef struct _wine_modref
70 {
71     LDR_MODULE            ldr;
72     int                   nDeps;
73     struct _wine_modref **deps;
74 } WINE_MODREF;
75
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
79 {
80     const WCHAR *load_path;
81     NTSTATUS     status;
82     WINE_MODREF *wm;
83 };
84
85 static struct builtin_load_info default_load_info;
86 static struct builtin_load_info *builtin_load_info = &default_load_info;
87
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 */
91
92 static UNICODE_STRING system_dir;  /* system directory */
93
94 static CRITICAL_SECTION loader_section;
95 static CRITICAL_SECTION_DEBUG critsect_debug =
96 {
97     0, 0, &loader_section,
98     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
99       0, 0, { 0, (DWORD)(__FILE__ ": loader_section") }
100 };
101 static CRITICAL_SECTION loader_section = { &critsect_debug, -1, 0, 0, 0, 0 };
102
103 static WINE_MODREF *cached_modref;
104 static WINE_MODREF *current_modref;
105
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 );
109
110 /* convert PE image VirtualAddress to Real Address */
111 inline static void *get_rva( HMODULE module, DWORD va )
112 {
113     return (void *)((char *)module + va);
114 }
115
116 /* check whether the file name contains a path */
117 inline static int contains_path( LPCWSTR name )
118 {
119     return ((*name && (name[1] == ':')) || strchrW(name, '/') || strchrW(name, '\\'));
120 }
121
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 )
124 {
125     while (len--) *dst++ = (unsigned char)*src++;
126 }
127
128 /*************************************************************************
129  *              get_modref
130  *
131  * Looks for the referenced HMODULE in the current process
132  * The loader_section must be locked while calling this function.
133  */
134 static WINE_MODREF *get_modref( HMODULE hmod )
135 {
136     PLIST_ENTRY mark, entry;
137     PLDR_MODULE mod;
138
139     if (cached_modref && cached_modref->ldr.BaseAddress == hmod) return cached_modref;
140
141     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
142     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
143     {
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;
148     }
149     return NULL;
150 }
151
152
153 /**********************************************************************
154  *          find_basename_module
155  *
156  * Find a module from its base name.
157  * The loader_section must be locked while calling this function
158  */
159 static WINE_MODREF *find_basename_module( LPCWSTR name )
160 {
161     PLIST_ENTRY mark, entry;
162
163     if (cached_modref && !strcmpiW( name, cached_modref->ldr.BaseDllName.Buffer ))
164         return cached_modref;
165
166     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
167     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
168     {
169         LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
170         if (!strcmpiW( name, mod->BaseDllName.Buffer ))
171         {
172             cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
173             return cached_modref;
174         }
175     }
176     return NULL;
177 }
178
179
180 /**********************************************************************
181  *          find_fullname_module
182  *
183  * Find a module from its full path name.
184  * The loader_section must be locked while calling this function
185  */
186 static WINE_MODREF *find_fullname_module( LPCWSTR name )
187 {
188     PLIST_ENTRY mark, entry;
189
190     if (cached_modref && !strcmpiW( name, cached_modref->ldr.FullDllName.Buffer ))
191         return cached_modref;
192
193     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
194     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
195     {
196         LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
197         if (!strcmpiW( name, mod->FullDllName.Buffer ))
198         {
199             cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
200             return cached_modref;
201         }
202     }
203     return NULL;
204 }
205
206
207 /*************************************************************************
208  *              find_forwarded_export
209  *
210  * Find the final function pointer for a forwarded function.
211  * The loader_section must be locked while calling this function.
212  */
213 static FARPROC find_forwarded_export( HMODULE module, const char *forward )
214 {
215     IMAGE_EXPORT_DIRECTORY *exports;
216     DWORD exp_size;
217     WINE_MODREF *wm;
218     WCHAR mod_name[32];
219     char *end = strchr(forward, '.');
220     FARPROC proc = NULL;
221
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) );
226
227     if (!(wm = find_basename_module( mod_name )))
228     {
229         ERR("module not found for forward '%s' used by %s\n",
230             forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer) );
231         return NULL;
232     }
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 );
236
237     if (!proc)
238     {
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) );
243     }
244     return proc;
245 }
246
247
248 /*************************************************************************
249  *              find_ordinal_export
250  *
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.
254  */
255 static FARPROC find_ordinal_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
256                                     DWORD exp_size, int ordinal )
257 {
258     FARPROC proc;
259     DWORD *functions = get_rva( module, exports->AddressOfFunctions );
260
261     if (ordinal >= exports->NumberOfFunctions)
262     {
263         TRACE(" ordinal %ld out of range!\n", ordinal + exports->Base );
264         return NULL;
265     }
266     if (!functions[ordinal]) return NULL;
267
268     proc = get_rva( module, functions[ordinal] );
269
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 );
273
274     if (TRACE_ON(snoop))
275     {
276         proc = SNOOP_GetProcAddress( module, exports, exp_size, proc, ordinal );
277     }
278     if (TRACE_ON(relay) && current_modref)
279     {
280         proc = RELAY_GetProcAddress( module, exports, exp_size, proc,
281                                      current_modref->ldr.BaseDllName.Buffer );
282     }
283     return proc;
284 }
285
286
287 /*************************************************************************
288  *              find_named_export
289  *
290  * Find an exported function by name.
291  * The loader_section must be locked while calling this function.
292  */
293 static FARPROC find_named_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
294                                   DWORD exp_size, const char *name, int hint )
295 {
296     WORD *ordinals = get_rva( module, exports->AddressOfNameOrdinals );
297     DWORD *names = get_rva( module, exports->AddressOfNames );
298     int min = 0, max = exports->NumberOfNames - 1;
299
300     /* first check the hint */
301     if (hint >= 0 && hint <= max)
302     {
303         char *ename = get_rva( module, names[hint] );
304         if (!strcmp( ename, name ))
305             return find_ordinal_export( module, exports, exp_size, ordinals[hint] );
306     }
307
308     /* then do a binary search */
309     while (min <= max)
310     {
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;
316         else min = pos + 1;
317     }
318     return NULL;
319
320 }
321
322
323 /*************************************************************************
324  *              import_dll
325  *
326  * Import the dll specified by the given import descriptor.
327  * The loader_section must be locked while calling this function.
328  */
329 static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr, LPCWSTR load_path )
330 {
331     NTSTATUS status;
332     WINE_MODREF *wmImp;
333     HMODULE imp_mod;
334     IMAGE_EXPORT_DIRECTORY *exports;
335     DWORD exp_size;
336     IMAGE_THUNK_DATA *import_list, *thunk_list;
337     WCHAR buffer[32];
338     char *name = get_rva( module, descr->Name );
339     DWORD len = strlen(name) + 1;
340
341     thunk_list = get_rva( module, (DWORD)descr->FirstThunk );
342     if (descr->u.OriginalFirstThunk)
343         import_list = get_rva( module, (DWORD)descr->u.OriginalFirstThunk );
344     else
345         import_list = thunk_list;
346
347     if (len * sizeof(WCHAR) <= sizeof(buffer))
348     {
349         ascii_to_unicode( buffer, name, len );
350         status = load_dll( load_path, buffer, 0, &wmImp );
351     }
352     else  /* need to allocate a larger buffer */
353     {
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 );
359     }
360
361     if (status)
362     {
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));
366         else
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);
369         imp_mod = NULL;
370         exports = NULL;
371     }
372     else
373     {
374         imp_mod = wmImp->ldr.BaseAddress;
375         exports = RtlImageDirectoryEntryToData( imp_mod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );
376     }
377
378     if (!exports)
379     {
380         /* set all imported function to deadbeef */
381         while (import_list->u1.Ordinal)
382         {
383             if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
384             {
385                 ERR("No implementation for %s.%ld", name, IMAGE_ORDINAL(import_list->u1.Ordinal));
386             }
387             else
388             {
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 );
391             }
392             ERR(" imported from %s, setting to 0xdeadbeef\n",
393                 debugstr_w(current_modref->ldr.FullDllName.Buffer) );
394             thunk_list->u1.Function = (PDWORD)0xdeadbeef;
395
396             import_list++;
397             thunk_list++;
398         }
399         return wmImp;
400     }
401
402     while (import_list->u1.Ordinal)
403     {
404         if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
405         {
406             int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
407
408             thunk_list->u1.Function = (PDWORD)find_ordinal_export( imp_mod, exports, exp_size,
409                                                                    ordinal - exports->Base );
410             if (!thunk_list->u1.Function)
411             {
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;
415             }
416             TRACE("--- Ordinal %s.%d = %p\n", name, ordinal, thunk_list->u1.Function );
417         }
418         else  /* import by name */
419         {
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)
425             {
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;
429             }
430             TRACE("--- %s %s.%d = %p\n", pe_name->Name, name, pe_name->Hint, thunk_list->u1.Function);
431         }
432         import_list++;
433         thunk_list++;
434     }
435     return wmImp;
436 }
437
438
439 /****************************************************************
440  *       fixup_imports
441  *
442  * Fixup all imports of a given module.
443  * The loader_section must be locked while calling this function.
444  */
445 static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path )
446 {
447     int i, nb_imports;
448     IMAGE_IMPORT_DESCRIPTOR *imports;
449     WINE_MODREF *prev;
450     DWORD size;
451     NTSTATUS status;
452
453     if (!(imports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
454                                                   IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))
455         return STATUS_SUCCESS;
456
457     nb_imports = size / sizeof(*imports);
458     for (i = 0; i < nb_imports; i++)
459     {
460         if (!imports[i].Name)
461         {
462             nb_imports = i;
463             break;
464         }
465     }
466     if (!nb_imports) return STATUS_SUCCESS;  /* no imports */
467
468     /* Allocate module dependency list */
469     wm->nDeps = nb_imports;
470     wm->deps  = RtlAllocateHeap( ntdll_get_process_heap(), 0, nb_imports*sizeof(WINE_MODREF *) );
471
472     /* load the imported modules. They are automatically
473      * added to the modref list of the process.
474      */
475     prev = current_modref;
476     current_modref = wm;
477     status = STATUS_SUCCESS;
478     for (i = 0; i < nb_imports; i++)
479     {
480         if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i], load_path )))
481             status = STATUS_DLL_NOT_FOUND;
482     }
483     current_modref = prev;
484     return status;
485 }
486
487
488 /*************************************************************************
489  *              alloc_module
490  *
491  * Allocate a WINE_MODREF structure and add it to the process list
492  * The loader_section must be locked while calling this function.
493  */
494 static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
495 {
496     WINE_MODREF *wm;
497     WCHAR *p;
498     IMAGE_NT_HEADERS *nt = RtlImageNtHeader(hModule);
499     PLIST_ENTRY entry, mark;
500     BOOLEAN linked = FALSE;
501     DWORD len;
502
503     RtlUnicodeToMultiByteSize( &len, filename, (strlenW(filename) + 1) * sizeof(WCHAR) );
504     if (!(wm = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*wm) + len )))
505         return NULL;
506
507     wm->nDeps    = 0;
508     wm->deps     = NULL;
509
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;
514     wm->ldr.Flags         = 0;
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;
520
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 );
525
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
529      */
530     if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
531     {
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))
536         {
537             InsertHeadList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
538                            &wm->ldr.InLoadOrderModuleList);
539             linked = TRUE;
540         }
541     }
542     else wm->ldr.Flags |= LDR_IMAGE_IS_DLL;
543
544     if (!linked)
545         InsertTailList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
546                        &wm->ldr.InLoadOrderModuleList);
547
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)
551     {
552         if (CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList)->BaseAddress > wm->ldr.BaseAddress)
553             break;
554     }
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;
559
560     /* wait until init is called for inserting into this list */
561     wm->ldr.InInitializationOrderModuleList.Flink = NULL;
562     wm->ldr.InInitializationOrderModuleList.Blink = NULL;
563     return wm;
564 }
565
566
567 /*************************************************************************
568  *              alloc_process_tls
569  *
570  * Allocate the process-wide structure for module TLS storage.
571  */
572 static NTSTATUS alloc_process_tls(void)
573 {
574     PLIST_ENTRY mark, entry;
575     PLDR_MODULE mod;
576     IMAGE_TLS_DIRECTORY *dir;
577     ULONG size, i;
578
579     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
580     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
581     {
582         mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
583         if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE,
584                                                   IMAGE_DIRECTORY_ENTRY_TLS, &size )))
585             continue;
586         size = (dir->EndAddressOfRawData - dir->StartAddressOfRawData) + dir->SizeOfZeroFill;
587         if (!size) continue;
588         tls_total_size += size;
589         tls_module_count++;
590     }
591     if (!tls_module_count) return STATUS_SUCCESS;
592
593     TRACE( "count %u size %u\n", tls_module_count, tls_total_size );
594
595     tls_dirs = RtlAllocateHeap( ntdll_get_process_heap(), 0, tls_module_count * sizeof(*tls_dirs) );
596     if (!tls_dirs) return STATUS_NO_MEMORY;
597
598     for (i = 0, entry = mark->Flink; entry != mark; entry = entry->Flink)
599     {
600         mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
601         if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE,
602                                                   IMAGE_DIRECTORY_ENTRY_TLS, &size )))
603             continue;
604         tls_dirs[i] = dir;
605         *dir->AddressOfIndex = i;
606         mod->TlsIndex = i;
607         mod->LoadCount = -1;  /* can't unload it */
608         i++;
609     }
610     return STATUS_SUCCESS;
611 }
612
613
614 /*************************************************************************
615  *              alloc_thread_tls
616  *
617  * Allocate the per-thread structure for module TLS storage.
618  */
619 static NTSTATUS alloc_thread_tls(void)
620 {
621     void **pointers;
622     char *data;
623     UINT i;
624
625     if (!tls_module_count) return STATUS_SUCCESS;
626
627     if (!(pointers = RtlAllocateHeap( ntdll_get_process_heap(), 0,
628                                       tls_module_count * sizeof(*pointers) )))
629         return STATUS_NO_MEMORY;
630
631     if (!(data = RtlAllocateHeap( ntdll_get_process_heap(), 0, tls_total_size )))
632     {
633         RtlFreeHeap( ntdll_get_process_heap(), 0, pointers );
634         return STATUS_NO_MEMORY;
635     }
636
637     for (i = 0; i < tls_module_count; i++)
638     {
639         const IMAGE_TLS_DIRECTORY *dir = tls_dirs[i];
640         ULONG size = dir->EndAddressOfRawData - dir->StartAddressOfRawData;
641
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 );
645
646         pointers[i] = data;
647         memcpy( data, (void *)dir->StartAddressOfRawData, size );
648         data += size;
649         memset( data, 0, dir->SizeOfZeroFill );
650         data += dir->SizeOfZeroFill;
651     }
652     NtCurrentTeb()->ThreadLocalStoragePointer = pointers;
653     return STATUS_SUCCESS;
654 }
655
656
657 /*************************************************************************
658  *              call_tls_callbacks
659  */
660 static void call_tls_callbacks( HMODULE module, UINT reason )
661 {
662     const IMAGE_TLS_DIRECTORY *dir;
663     const PIMAGE_TLS_CALLBACK *callback;
664     ULONG dirsize;
665
666     dir = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &dirsize );
667     if (!dir || !dir->AddressOfCallBacks) return;
668
669     for (callback = dir->AddressOfCallBacks; *callback; callback++)
670     {
671         if (TRACE_ON(relay))
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 );
675         if (TRACE_ON(relay))
676             DPRINTF("%04lx:Ret  TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
677                     GetCurrentThreadId(), *callback, module, reason_names[reason] );
678     }
679 }
680
681
682 /*************************************************************************
683  *              MODULE_InitDLL
684  */
685 static BOOL MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved )
686 {
687     WCHAR mod_name[32];
688     BOOL retv = TRUE;
689     DLLENTRYPROC entry = wm->ldr.EntryPoint;
690     void *module = wm->ldr.BaseAddress;
691
692     /* Skip calls for modules loaded with special load flags */
693
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;
697
698     if (TRACE_ON(relay))
699     {
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 );
706     }
707     else TRACE("(%p %s,%s,%p) - CALL\n", module, debugstr_w(wm->ldr.BaseDllName.Buffer),
708                reason_names[reason], lpReserved );
709
710     retv = entry( module, reason, lpReserved );
711
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
714        deleted.  */
715     if (TRACE_ON(relay))
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 );
720
721     return retv;
722 }
723
724
725 /*************************************************************************
726  *              process_attach
727  *
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
730  *
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
734  *
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
738  *
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
741  *  routines.)
742  *
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.
748  *
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*.
753  *
754  * The loader_section must be locked while calling this function.
755  */
756 static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved )
757 {
758     NTSTATUS status = STATUS_SUCCESS;
759     int i;
760
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 ) )
764         return status;
765
766     TRACE("(%s,%p) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved );
767
768     /* Tag current MODREF to prevent recursive loop */
769     wm->ldr.Flags |= LDR_LOAD_IN_PROGRESS;
770
771     /* Recursively attach all DLLs this one depends on */
772     for ( i = 0; i < wm->nDeps; i++ )
773     {
774         if (!wm->deps[i]) continue;
775         if ((status = process_attach( wm->deps[i], lpReserved )) != STATUS_SUCCESS) break;
776     }
777
778     /* Call DLL entry point */
779     if (status == STATUS_SUCCESS)
780     {
781         WINE_MODREF *prev = current_modref;
782         current_modref = wm;
783         if (MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved ))
784             wm->ldr.Flags |= LDR_PROCESS_ATTACHED;
785         else
786             status = STATUS_DLL_INIT_FAILED;
787         current_modref = prev;
788     }
789
790     InsertTailList(&NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList, 
791                    &wm->ldr.InInitializationOrderModuleList);
792
793     /* Remove recursion flag */
794     wm->ldr.Flags &= ~LDR_LOAD_IN_PROGRESS;
795
796     TRACE("(%s,%p) - END\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved );
797     return status;
798 }
799
800 /*************************************************************************
801  *              process_detach
802  *
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.
806  */
807 static void process_detach( BOOL bForceDetach, LPVOID lpReserved )
808 {
809     PLIST_ENTRY mark, entry;
810     PLDR_MODULE mod;
811
812     RtlEnterCriticalSection( &loader_section );
813     if (bForceDetach) process_detaching = 1;
814     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
815     do
816     {
817         for (entry = mark->Blink; entry != mark; entry = entry->Blink)
818         {
819             mod = CONTAINING_RECORD(entry, LDR_MODULE, 
820                                     InInitializationOrderModuleList);
821             /* Check whether to detach this DLL */
822             if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
823                 continue;
824             if ( mod->LoadCount && !bForceDetach )
825                 continue;
826
827             /* Call detach notification */
828             mod->Flags &= ~LDR_PROCESS_ATTACHED;
829             MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr), 
830                             DLL_PROCESS_DETACH, lpReserved );
831
832             /* Restart at head of WINE_MODREF list, as entries might have
833                been added and/or removed while performing the call ... */
834             break;
835         }
836     } while (entry != mark);
837
838     RtlLeaveCriticalSection( &loader_section );
839 }
840
841 /*************************************************************************
842  *              MODULE_DllThreadAttach
843  *
844  * Send DLL thread attach notifications. These are sent in the
845  * reverse sequence of process detach notification.
846  *
847  */
848 NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved )
849 {
850     PLIST_ENTRY mark, entry;
851     PLDR_MODULE mod;
852     NTSTATUS    status;
853
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 */
857
858     RtlEnterCriticalSection( &loader_section );
859
860     if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto done;
861
862     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
863     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
864     {
865         mod = CONTAINING_RECORD(entry, LDR_MODULE, 
866                                 InInitializationOrderModuleList);
867         if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
868             continue;
869         if ( mod->Flags & LDR_NO_DLL_CALLS )
870             continue;
871
872         MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr),
873                         DLL_THREAD_ATTACH, lpReserved );
874     }
875
876 done:
877     RtlLeaveCriticalSection( &loader_section );
878     return status;
879 }
880
881 /******************************************************************
882  *              LdrDisableThreadCalloutsForDll (NTDLL.@)
883  *
884  */
885 NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE hModule)
886 {
887     WINE_MODREF *wm;
888     NTSTATUS    ret = STATUS_SUCCESS;
889
890     RtlEnterCriticalSection( &loader_section );
891
892     wm = get_modref( hModule );
893     if (!wm || wm->ldr.TlsIndex != -1)
894         ret = STATUS_DLL_NOT_FOUND;
895     else
896         wm->ldr.Flags |= LDR_NO_DLL_CALLS;
897
898     RtlLeaveCriticalSection( &loader_section );
899
900     return ret;
901 }
902
903 /******************************************************************
904  *              LdrFindEntryForAddress (NTDLL.@)
905  *
906  * The loader_section must be locked while calling this function
907  */
908 NTSTATUS WINAPI LdrFindEntryForAddress(const void* addr, PLDR_MODULE* pmod)
909 {
910     PLIST_ENTRY mark, entry;
911     PLDR_MODULE mod;
912
913     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
914     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
915     {
916         mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
917         if ((const void *)mod->BaseAddress <= addr &&
918             (char *)addr < (char*)mod->BaseAddress + mod->SizeOfImage)
919         {
920             *pmod = mod;
921             return STATUS_SUCCESS;
922         }
923         if ((const void *)mod->BaseAddress > addr) break;
924     }
925     return STATUS_NO_MORE_ENTRIES;
926 }
927
928 /******************************************************************
929  *              LdrLockLoaderLock  (NTDLL.@)
930  *
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).
934  */
935 NTSTATUS WINAPI LdrLockLoaderLock( ULONG flags, ULONG *result, ULONG *magic )
936 {
937     if (flags) FIXME( "flags %lx not supported\n", flags );
938
939     if (result) *result = 1;
940     if (!magic) return STATUS_INVALID_PARAMETER_3;
941     RtlEnterCriticalSection( &loader_section );
942     *magic = GetCurrentThreadId();
943     return STATUS_SUCCESS;
944 }
945
946
947 /******************************************************************
948  *              LdrUnlockLoaderUnlock  (NTDLL.@)
949  */
950 NTSTATUS WINAPI LdrUnlockLoaderLock( ULONG flags, ULONG magic )
951 {
952     if (magic)
953     {
954         if (magic != GetCurrentThreadId()) return STATUS_INVALID_PARAMETER_2;
955         RtlLeaveCriticalSection( &loader_section );
956     }
957     return STATUS_SUCCESS;
958 }
959
960
961 /******************************************************************
962  *              LdrGetDllHandle (NTDLL.@)
963  */
964 NTSTATUS WINAPI LdrGetDllHandle(ULONG x, ULONG y, const UNICODE_STRING *name, HMODULE *base)
965 {
966     NTSTATUS status = STATUS_DLL_NOT_FOUND;
967     WCHAR dllname[MAX_PATH+4], *p;
968     UNICODE_STRING str;
969     PLIST_ENTRY mark, entry;
970     PLDR_MODULE mod;
971
972     if (x != 0 || y != 0)
973         FIXME("Unknown behavior, please report\n");
974
975     /* Append .DLL to name if no extension present */
976     if (!(p = strrchrW( name->Buffer, '.')) || strchrW( p, '/' ) || strchrW( p, '\\'))
977     {
978         if (name->Length >= MAX_PATH) return STATUS_NAME_TOO_LONG;
979         strcpyW( dllname, name->Buffer );
980         strcatW( dllname, dllW );
981         RtlInitUnicodeString( &str, dllname );
982         name = &str;
983     }
984
985     RtlEnterCriticalSection( &loader_section );
986
987     if (cached_modref)
988     {
989         if (RtlEqualUnicodeString( name, &cached_modref->ldr.FullDllName, TRUE ) ||
990             RtlEqualUnicodeString( name, &cached_modref->ldr.BaseDllName, TRUE ))
991         {
992             *base = cached_modref->ldr.BaseAddress;
993             status = STATUS_SUCCESS;
994             goto done;
995         }
996     }
997
998     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
999     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1000     {
1001         mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
1002
1003         if (RtlEqualUnicodeString( name, &mod->FullDllName, TRUE ) ||
1004             RtlEqualUnicodeString( name, &mod->BaseDllName, TRUE ))
1005         {
1006             cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
1007             *base = mod->BaseAddress;
1008             status = STATUS_SUCCESS;
1009             break;
1010         }
1011     }
1012 done:
1013     RtlLeaveCriticalSection( &loader_section );
1014     TRACE("%lx %lx %s -> %p\n", x, y, debugstr_us(name), status ? NULL : *base);
1015     return status;
1016 }
1017
1018
1019 /******************************************************************
1020  *              LdrGetProcedureAddress  (NTDLL.@)
1021  */
1022 NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name,
1023                                        ULONG ord, PVOID *address)
1024 {
1025     IMAGE_EXPORT_DIRECTORY *exports;
1026     DWORD exp_size;
1027     NTSTATUS ret = STATUS_PROCEDURE_NOT_FOUND;
1028
1029     RtlEnterCriticalSection( &loader_section );
1030
1031     if ((exports = RtlImageDirectoryEntryToData( module, TRUE,
1032                                                  IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
1033     {
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 );
1036         if (proc)
1037         {
1038             *address = proc;
1039             ret = STATUS_SUCCESS;
1040         }
1041     }
1042     else
1043     {
1044         /* check if the module itself is invalid to return the proper error */
1045         if (!get_modref( module )) ret = STATUS_DLL_NOT_FOUND;
1046     }
1047
1048     RtlLeaveCriticalSection( &loader_section );
1049     return ret;
1050 }
1051
1052
1053 /***********************************************************************
1054  *           load_builtin_callback
1055  *
1056  * Load a library in memory; callback function for wine_dll_register
1057  */
1058 static void load_builtin_callback( void *module, const char *filename )
1059 {
1060     static const WCHAR emptyW[1];
1061     void *addr;
1062     IMAGE_NT_HEADERS *nt;
1063     WINE_MODREF *wm;
1064     WCHAR *fullname, *p;
1065     const WCHAR *load_path;
1066
1067     if (!module)
1068     {
1069         ERR("could not map image for %s\n", filename ? filename : "main exe" );
1070         return;
1071     }
1072     if (!(nt = RtlImageNtHeader( module )))
1073     {
1074         ERR( "bad module for %s\n", filename ? filename : "main exe" );
1075         builtin_load_info->status = STATUS_INVALID_IMAGE_FORMAT;
1076         return;
1077     }
1078     if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
1079     {
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 */
1084     }
1085
1086     /* create the MODREF */
1087
1088     if (!(fullname = RtlAllocateHeap( GetProcessHeap(), 0,
1089                                       system_dir.MaximumLength + (strlen(filename) + 1) * sizeof(WCHAR) )))
1090     {
1091         ERR( "can't load %s\n", filename );
1092         builtin_load_info->status = STATUS_NO_MEMORY;
1093         return;
1094     }
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 );
1099
1100     wm = alloc_module( module, fullname );
1101     RtlFreeHeap( GetProcessHeap(), 0, fullname );
1102     if (!wm)
1103     {
1104         ERR( "can't load %s\n", filename );
1105         builtin_load_info->status = STATUS_NO_MEMORY;
1106         return;
1107     }
1108     wm->ldr.Flags |= LDR_WINE_INTERNAL;
1109     NtAllocateVirtualMemory( GetCurrentProcess(), &addr, module, &nt->OptionalHeader.SizeOfImage,
1110                              MEM_SYSTEM | MEM_IMAGE, PAGE_EXECUTE_WRITECOPY );
1111
1112     /* fixup imports */
1113
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)
1118     {
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;
1124         return;
1125     }
1126     builtin_load_info->wm = wm;
1127     TRACE( "loaded %s %p %p\n", filename, wm, module );
1128
1129     /* send the DLL load event */
1130
1131     SERVER_START_REQ( load_dll )
1132     {
1133         req->handle     = 0;
1134         req->base       = module;
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 );
1141     }
1142     SERVER_END_REQ;
1143
1144     /* setup relay debugging entry points */
1145     if (TRACE_ON(relay)) RELAY_SetupDLL( module );
1146 }
1147
1148
1149 /******************************************************************************
1150  *      load_native_dll  (internal)
1151  */
1152 static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
1153                                  DWORD flags, WINE_MODREF** pwm )
1154 {
1155     void *module;
1156     HANDLE mapping;
1157     OBJECT_ATTRIBUTES attr;
1158     LARGE_INTEGER size;
1159     IMAGE_NT_HEADERS *nt;
1160     DWORD len = 0;
1161     WINE_MODREF *wm;
1162     NTSTATUS status;
1163
1164     TRACE( "loading %s\n", debugstr_w(name) );
1165
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;
1172     size.QuadPart = 0;
1173
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;
1177
1178     module = NULL;
1179     status = NtMapViewOfSection( mapping, GetCurrentProcess(),
1180                                  &module, 0, 0, &size, &len, ViewShare, 0, PAGE_READONLY );
1181     NtClose( mapping );
1182     if (status != STATUS_SUCCESS) return status;
1183
1184     /* create the MODREF */
1185
1186     if (!(wm = alloc_module( module, name ))) return STATUS_NO_MEMORY;
1187
1188     /* fixup imports */
1189
1190     if (!(flags & DONT_RESOLVE_DLL_REFERENCES))
1191     {
1192         if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS)
1193         {
1194             /* the module has only be inserted in the load & memory order lists */
1195             RemoveEntryList(&wm->ldr.InLoadOrderModuleList);
1196             RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);
1197
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.
1204              */
1205             return status;
1206         }
1207     }
1208     else wm->ldr.Flags |= LDR_DONT_RESOLVE_REFS;
1209
1210     /* send DLL load event */
1211
1212     nt = RtlImageNtHeader( module );
1213
1214     SERVER_START_REQ( load_dll )
1215     {
1216         req->handle     = file;
1217         req->base       = module;
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 );
1224     }
1225     SERVER_END_REQ;
1226
1227     if (TRACE_ON(snoop)) SNOOP_SetupDLL( module );
1228
1229     *pwm = wm;
1230     return STATUS_SUCCESS;
1231 }
1232
1233
1234 /***********************************************************************
1235  *           load_builtin_dll
1236  */
1237 static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, DWORD flags, WINE_MODREF** pwm )
1238 {
1239     char error[256], dllname[MAX_PATH];
1240     int file_exists;
1241     const WCHAR *name, *p;
1242     DWORD len, i;
1243     void *handle;
1244     struct builtin_load_info info, *prev_info;
1245
1246     /* Fix the name in case we have a full path and extension */
1247     name = path;
1248     if ((p = strrchrW( name, '\\' ))) name = p + 1;
1249     if ((p = strrchrW( name, '/' ))) name = p + 1;
1250
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++)
1255     {
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';
1259     }
1260
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
1264      * libraries
1265      */
1266     info.load_path = load_path;
1267     info.status    = STATUS_SUCCESS;
1268     info.wm        = NULL;
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;
1273
1274     if (!handle)
1275     {
1276         if (!file_exists)
1277         {
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;
1281         }
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;
1285     }
1286     if (info.status != STATUS_SUCCESS) return info.status;
1287
1288     if (!info.wm)
1289     {
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;
1294     }
1295
1296     info.wm->ldr.SectionHandle = handle;
1297     if (strcmpiW( info.wm->ldr.BaseDllName.Buffer, name ))
1298     {
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;
1303     }
1304     *pwm = info.wm;
1305     return STATUS_SUCCESS;
1306 }
1307
1308
1309 /***********************************************************************
1310  *      find_dll_file
1311  *
1312  * Find the file (or already loaded module) for a given dll name.
1313  */
1314 static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
1315                                WCHAR *filename, ULONG *size, WINE_MODREF **pwm, HANDLE *handle )
1316 {
1317     WCHAR *file_part, *ext;
1318     ULONG len;
1319
1320     if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH)
1321     {
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, '\\'))
1325         {
1326             WCHAR *dllname;
1327
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 );
1335         }
1336         else len = RtlDosSearchPath_U( load_path, libname, NULL, *size, filename, &file_part );
1337
1338         if (len)
1339         {
1340             if (len >= *size)
1341             {
1342                 *size = len + sizeof(WCHAR);
1343                 return STATUS_BUFFER_TOO_SMALL;
1344             }
1345             if ((*pwm = find_fullname_module( filename )) != NULL) return STATUS_SUCCESS;
1346
1347             /* check for already loaded module in a different path */
1348             if (!contains_path( libname ))
1349             {
1350                 if ((*pwm = find_basename_module( file_part )) != NULL) return STATUS_SUCCESS;
1351             }
1352             *handle = pCreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1353             return STATUS_SUCCESS;
1354         }
1355
1356         /* not found */
1357
1358         if (!contains_path( libname ))
1359         {
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, '.' ))
1366             {
1367                 len += sizeof(dllW) - sizeof(WCHAR);
1368                 if (len >= *size) goto overflow;
1369                 strcatW( filename, dllW );
1370             }
1371             *pwm = find_basename_module( filename );
1372             return STATUS_SUCCESS;
1373         }
1374     }
1375
1376     /* absolute path name, or relative path name but not found above */
1377
1378     len = RtlGetFullPathName_U( libname, *size, filename, &file_part );
1379     if (len >= *size) goto overflow;
1380     if (file_part && !strchrW( file_part, '.' ))
1381     {
1382         len += sizeof(dllW) - sizeof(WCHAR);
1383         if (len >= *size) goto overflow;
1384         strcatW( file_part, dllW );
1385     }
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;
1389
1390 overflow:
1391     *size = len + sizeof(WCHAR);
1392     return STATUS_BUFFER_TOO_SMALL;
1393 }
1394
1395
1396 /***********************************************************************
1397  *      load_dll  (internal)
1398  *
1399  * Load a PE style module according to the load order.
1400  * The loader_section must be locked while calling this function.
1401  */
1402 static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
1403 {
1404     int i;
1405     enum loadorder_type loadorder[LOADORDER_NTYPES];
1406     WCHAR buffer[32];
1407     WCHAR *filename;
1408     ULONG size;
1409     const char *filetype = "";
1410     WINE_MODREF *main_exe;
1411     HANDLE handle = INVALID_HANDLE_VALUE;
1412     NTSTATUS nts;
1413
1414     TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
1415
1416     filename = buffer;
1417     size = sizeof(buffer);
1418     for (;;)
1419     {
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;
1426     }
1427
1428     if (*pwm)  /* found already loaded module */
1429     {
1430         if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
1431
1432         if (((*pwm)->ldr.Flags & LDR_DONT_RESOLVE_REFS) &&
1433             !(flags & DONT_RESOLVE_DLL_REFERENCES))
1434         {
1435             (*pwm)->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;
1436             fixup_imports( *pwm, load_path );
1437         }
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;
1443     }
1444
1445     main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
1446     MODULE_GetLoadOrderW( loadorder, main_exe->ldr.BaseDllName.Buffer, filename, TRUE);
1447
1448     nts = STATUS_DLL_NOT_FOUND;
1449     for (i = 0; i < LOADORDER_NTYPES; i++)
1450     {
1451         if (loadorder[i] == LOADORDER_INVALID) break;
1452
1453         switch (loadorder[i])
1454         {
1455         case LOADORDER_DLL:
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";
1460             break;
1461         case LOADORDER_BI:
1462             TRACE("Trying built-in %s\n", debugstr_w(filename));
1463             nts = load_builtin_dll( load_path, filename, flags, pwm );
1464             filetype = "builtin";
1465             break;
1466         default:
1467             nts = STATUS_INTERNAL_ERROR;
1468             break;
1469         }
1470
1471         if (nts == STATUS_SUCCESS)
1472         {
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 );
1483             return nts;
1484         }
1485         if (nts != STATUS_DLL_NOT_FOUND) break;
1486     }
1487
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 );
1491     return nts;
1492 }
1493
1494 /******************************************************************
1495  *              LdrLoadDll (NTDLL.@)
1496  */
1497 NTSTATUS WINAPI LdrLoadDll(LPCWSTR path_name, DWORD flags,
1498                            const UNICODE_STRING *libname, HMODULE* hModule)
1499 {
1500     WINE_MODREF *wm;
1501     NTSTATUS nts;
1502
1503     RtlEnterCriticalSection( &loader_section );
1504
1505     if (!path_name) path_name = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
1506     nts = load_dll( path_name, libname->Buffer, flags, &wm );
1507
1508     if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
1509     {
1510         nts = process_attach( wm, NULL );
1511         if (nts != STATUS_SUCCESS)
1512         {
1513             WARN("Attach failed for module %s\n", debugstr_w(libname->Buffer));
1514             LdrUnloadDll(wm->ldr.BaseAddress);
1515             wm = NULL;
1516         }
1517     }
1518     *hModule = (wm) ? wm->ldr.BaseAddress : NULL;
1519
1520     RtlLeaveCriticalSection( &loader_section );
1521     return nts;
1522 }
1523
1524 /******************************************************************
1525  *              LdrQueryProcessModuleInformation
1526  *
1527  */
1528 NTSTATUS WINAPI LdrQueryProcessModuleInformation(PSYSTEM_MODULE_INFORMATION smi, 
1529                                                  ULONG buf_size, ULONG* req_size)
1530 {
1531     SYSTEM_MODULE*      sm = &smi->Modules[0];
1532     ULONG               size = sizeof(ULONG);
1533     NTSTATUS            nts = STATUS_SUCCESS;
1534     ANSI_STRING         str;
1535     char*               ptr;
1536     PLIST_ENTRY         mark, entry;
1537     PLDR_MODULE         mod;
1538
1539     smi->ModulesCount = 0;
1540
1541     RtlEnterCriticalSection( &loader_section );
1542     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
1543     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1544     {
1545         mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
1546         size += sizeof(*sm);
1547         if (size <= buf_size)
1548         {
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 */
1557             str.Length = 0;
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;
1563
1564             smi->ModulesCount++;
1565             sm++;
1566         }
1567         else nts = STATUS_INFO_LENGTH_MISMATCH;
1568     }
1569     RtlLeaveCriticalSection( &loader_section );
1570
1571     if (req_size) *req_size = size;
1572
1573     return nts;
1574 }
1575
1576 /******************************************************************
1577  *              LdrShutdownProcess (NTDLL.@)
1578  *
1579  */
1580 void WINAPI LdrShutdownProcess(void)
1581 {
1582     TRACE("()\n");
1583     process_detach( TRUE, (LPVOID)1 );
1584 }
1585
1586 /******************************************************************
1587  *              LdrShutdownThread (NTDLL.@)
1588  *
1589  */
1590 void WINAPI LdrShutdownThread(void)
1591 {
1592     PLIST_ENTRY mark, entry;
1593     PLDR_MODULE mod;
1594
1595     TRACE("()\n");
1596
1597     /* don't do any detach calls if process is exiting */
1598     if (process_detaching) return;
1599     /* FIXME: there is still a race here */
1600
1601     RtlEnterCriticalSection( &loader_section );
1602
1603     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
1604     for (entry = mark->Blink; entry != mark; entry = entry->Blink)
1605     {
1606         mod = CONTAINING_RECORD(entry, LDR_MODULE, 
1607                                 InInitializationOrderModuleList);
1608         if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
1609             continue;
1610         if ( mod->Flags & LDR_NO_DLL_CALLS )
1611             continue;
1612
1613         MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr), 
1614                         DLL_THREAD_DETACH, NULL );
1615     }
1616
1617     RtlLeaveCriticalSection( &loader_section );
1618 }
1619
1620 /***********************************************************************
1621  *           MODULE_FlushModrefs
1622  *
1623  * Remove all unused modrefs and call the internal unloading routines
1624  * for the library type.
1625  *
1626  * The loader_section must be locked while calling this function.
1627  */
1628 static void MODULE_FlushModrefs(void)
1629 {
1630     PLIST_ENTRY mark, entry, prev;
1631     PLDR_MODULE mod;
1632     WINE_MODREF*wm;
1633
1634     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
1635     for (entry = mark->Blink; entry != mark; entry = prev)
1636     {
1637         mod = CONTAINING_RECORD(entry, LDR_MODULE, 
1638                                 InInitializationOrderModuleList);
1639         wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
1640
1641         prev = entry->Blink;
1642         if (mod->LoadCount) continue;
1643
1644         RemoveEntryList(&mod->InLoadOrderModuleList);
1645         RemoveEntryList(&mod->InMemoryOrderModuleList);
1646         RemoveEntryList(&mod->InInitializationOrderModuleList);
1647
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" );
1653
1654         SERVER_START_REQ( unload_dll )
1655         {
1656             req->base = mod->BaseAddress;
1657             wine_server_call( req );
1658         }
1659         SERVER_END_REQ;
1660
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 );
1667     }
1668 }
1669
1670 /***********************************************************************
1671  *           MODULE_DecRefCount
1672  *
1673  * The loader_section must be locked while calling this function.
1674  */
1675 static void MODULE_DecRefCount( WINE_MODREF *wm )
1676 {
1677     int i;
1678
1679     if ( wm->ldr.Flags & LDR_UNLOAD_IN_PROGRESS )
1680         return;
1681
1682     if ( wm->ldr.LoadCount <= 0 )
1683         return;
1684
1685     --wm->ldr.LoadCount;
1686     TRACE("(%s) ldr.LoadCount: %d\n", debugstr_w(wm->ldr.BaseDllName.Buffer), wm->ldr.LoadCount );
1687
1688     if ( wm->ldr.LoadCount == 0 )
1689     {
1690         wm->ldr.Flags |= LDR_UNLOAD_IN_PROGRESS;
1691
1692         for ( i = 0; i < wm->nDeps; i++ )
1693             if ( wm->deps[i] )
1694                 MODULE_DecRefCount( wm->deps[i] );
1695
1696         wm->ldr.Flags &= ~LDR_UNLOAD_IN_PROGRESS;
1697     }
1698 }
1699
1700 /******************************************************************
1701  *              LdrUnloadDll (NTDLL.@)
1702  *
1703  *
1704  */
1705 NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule )
1706 {
1707     NTSTATUS retv = STATUS_SUCCESS;
1708
1709     TRACE("(%p)\n", hModule);
1710
1711     RtlEnterCriticalSection( &loader_section );
1712
1713     /* if we're stopping the whole process (and forcing the removal of all
1714      * DLLs) the library will be freed anyway
1715      */
1716     if (!process_detaching)
1717     {
1718         WINE_MODREF *wm;
1719
1720         free_lib_count++;
1721         if ((wm = get_modref( hModule )) != NULL)
1722         {
1723             TRACE("(%s) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer));
1724
1725             /* Recursively decrement reference counts */
1726             MODULE_DecRefCount( wm );
1727
1728             /* Call process detach notifications */
1729             if ( free_lib_count <= 1 )
1730             {
1731                 process_detach( FALSE, NULL );
1732                 MODULE_FlushModrefs();
1733             }
1734
1735             TRACE("END\n");
1736         }
1737         else
1738             retv = STATUS_DLL_NOT_FOUND;
1739
1740         free_lib_count--;
1741     }
1742
1743     RtlLeaveCriticalSection( &loader_section );
1744
1745     return retv;
1746 }
1747
1748 /***********************************************************************
1749  *           RtlImageNtHeader   (NTDLL.@)
1750  */
1751 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
1752 {
1753     IMAGE_NT_HEADERS *ret;
1754
1755     __TRY
1756     {
1757         IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)hModule;
1758
1759         ret = NULL;
1760         if (dos->e_magic == IMAGE_DOS_SIGNATURE)
1761         {
1762             ret = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew);
1763             if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL;
1764         }
1765     }
1766     __EXCEPT(page_fault)
1767     {
1768         return NULL;
1769     }
1770     __ENDTRY
1771     return ret;
1772 }
1773
1774
1775 /******************************************************************
1776  *              LdrInitializeThunk (NTDLL.@)
1777  *
1778  * FIXME: the arguments are not correct, main_file and CreateFileW_ptr are Wine inventions.
1779  */
1780 void WINAPI LdrInitializeThunk( HANDLE main_file, void *CreateFileW_ptr, ULONG unknown3, ULONG unknown4 )
1781 {
1782     NTSTATUS status;
1783     WINE_MODREF *wm;
1784     LPCWSTR load_path;
1785     PEB *peb = NtCurrentTeb()->Peb;
1786     UNICODE_STRING *main_exe_name = &peb->ProcessParameters->ImagePathName;
1787     IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress );
1788
1789     pCreateFileW = CreateFileW_ptr;
1790     if (!MODULE_GetSystemDirectory( &system_dir ))
1791     {
1792         ERR( "Couldn't get system dir\n");
1793         exit(1);
1794     }
1795
1796     /* allocate the modref for the main exe */
1797     if (!(wm = alloc_module( peb->ImageBaseAddress, main_exe_name->Buffer )))
1798     {
1799         status = STATUS_NO_MEMORY;
1800         goto error;
1801     }
1802     wm->ldr.LoadCount = -1;  /* can't unload main exe */
1803
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);
1811
1812     /* Signal the parent process to continue */
1813     SERVER_START_REQ( init_process_done )
1814     {
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 );
1824     }
1825     SERVER_END_REQ;
1826
1827     if (main_file) NtClose( main_file ); /* we no longer need it */
1828
1829     if (TRACE_ON(relay) || TRACE_ON(snoop))
1830     {
1831         RELAY_InitDebugLists();
1832
1833         if (TRACE_ON(relay))  /* setup relay for already loaded dlls */
1834         {
1835             LIST_ENTRY *entry, *mark = &peb->LdrData->InLoadOrderModuleList;
1836             for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1837             {
1838                 LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
1839                 if (mod->Flags & LDR_WINE_INTERNAL) RELAY_SetupDLL( mod->BaseAddress );
1840             }
1841         }
1842     }
1843
1844     RtlEnterCriticalSection( &loader_section );
1845
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;
1851
1852     RtlLeaveCriticalSection( &loader_section );
1853     return;
1854
1855 error:
1856     ERR( "Main exe initialization failed, status %lx\n", status );
1857     exit(1);
1858 }
1859
1860
1861 /***********************************************************************
1862  *           RtlImageDirectoryEntryToData   (NTDLL.@)
1863  */
1864 PVOID WINAPI RtlImageDirectoryEntryToData( HMODULE module, BOOL image, WORD dir, ULONG *size )
1865 {
1866     const IMAGE_NT_HEADERS *nt;
1867     DWORD addr;
1868
1869     if ((ULONG_PTR)module & 1)  /* mapped as data file */
1870     {
1871         module = (HMODULE)((ULONG_PTR)module & ~1);
1872         image = FALSE;
1873     }
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;
1879
1880     /* not mapped as image, need to find the section containing the virtual address */
1881     return RtlImageRvaToVa( nt, module, addr, NULL );
1882 }
1883
1884
1885 /***********************************************************************
1886  *           RtlImageRvaToSection   (NTDLL.@)
1887  */
1888 PIMAGE_SECTION_HEADER WINAPI RtlImageRvaToSection( const IMAGE_NT_HEADERS *nt,
1889                                                    HMODULE module, DWORD rva )
1890 {
1891     int i;
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++)
1895     {
1896         if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
1897             return sec;
1898     }
1899     return NULL;
1900 }
1901
1902
1903 /***********************************************************************
1904  *           RtlImageRvaToVa   (NTDLL.@)
1905  */
1906 PVOID WINAPI RtlImageRvaToVa( const IMAGE_NT_HEADERS *nt, HMODULE module,
1907                               DWORD rva, IMAGE_SECTION_HEADER **section )
1908 {
1909     IMAGE_SECTION_HEADER *sec;
1910
1911     if (section && *section)  /* try this section first */
1912     {
1913         sec = *section;
1914         if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
1915             goto found;
1916     }
1917     if (!(sec = RtlImageRvaToSection( nt, module, rva ))) return NULL;
1918  found:
1919     if (section) *section = sec;
1920     return (char *)module + sec->PointerToRawData + (rva - sec->VirtualAddress);
1921 }
1922
1923
1924 /***********************************************************************
1925  *           __wine_process_init
1926  */
1927 void __wine_process_init( int argc, char *argv[] )
1928 {
1929     static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
1930
1931     WINE_MODREF *wm;
1932     NTSTATUS status;
1933     ANSI_STRING func_name;
1934     void (* DECLSPEC_NORETURN init_func)();
1935
1936     thread_init();
1937
1938     /* setup the load callback and create ntdll modref */
1939     wine_dll_set_callback( load_builtin_callback );
1940
1941     if ((status = load_builtin_dll( NULL, kernel32W, 0, &wm )) != STATUS_SUCCESS)
1942     {
1943         MESSAGE( "wine: could not load kernel32.dll, status %lx\n", status );
1944         exit(1);
1945     }
1946     RtlInitAnsiString( &func_name, "__wine_kernel_init" );
1947     if ((status = LdrGetProcedureAddress( wm->ldr.BaseAddress, &func_name,
1948                                           0, (void **)&init_func )) != STATUS_SUCCESS)
1949     {
1950         MESSAGE( "wine: could not find __wine_kernel_init in kernel32.dll, status %lx\n", status );
1951         exit(1);
1952     }
1953     init_func();
1954 }