wined3d: Move shader generation into the shader backend.
[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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #include "config.h"
23 #include "wine/port.h"
24
25 #include <assert.h>
26 #include <stdarg.h>
27
28 #define NONAMELESSUNION
29 #define NONAMELESSSTRUCT
30
31 #include "ntstatus.h"
32 #define WIN32_NO_STATUS
33 #include "windef.h"
34 #include "winnt.h"
35 #include "winternl.h"
36
37 #include "wine/exception.h"
38 #include "wine/library.h"
39 #include "wine/pthread.h"
40 #include "wine/unicode.h"
41 #include "wine/debug.h"
42 #include "wine/server.h"
43 #include "ntdll_misc.h"
44 #include "ddk/wdm.h"
45
46 WINE_DEFAULT_DEBUG_CHANNEL(module);
47 WINE_DECLARE_DEBUG_CHANNEL(relay);
48 WINE_DECLARE_DEBUG_CHANNEL(snoop);
49 WINE_DECLARE_DEBUG_CHANNEL(loaddll);
50 WINE_DECLARE_DEBUG_CHANNEL(imports);
51
52 /* we don't want to include winuser.h */
53 #define RT_MANIFEST                         ((ULONG_PTR)24)
54 #define ISOLATIONAWARE_MANIFEST_RESOURCE_ID ((ULONG_PTR)2)
55
56 extern struct wine_pthread_functions pthread_functions;
57
58 typedef DWORD (CALLBACK *DLLENTRYPROC)(HMODULE,DWORD,LPVOID);
59
60 static int process_detaching = 0;  /* set on process detach to avoid deadlocks with thread detach */
61 static int free_lib_count;   /* recursion depth of LdrUnloadDll calls */
62
63 static const char * const reason_names[] =
64 {
65     "PROCESS_DETACH",
66     "PROCESS_ATTACH",
67     "THREAD_ATTACH",
68     "THREAD_DETACH",
69     NULL, NULL, NULL, NULL,
70     "WINE_PREATTACH"
71 };
72
73 static const WCHAR dllW[] = {'.','d','l','l',0};
74
75 /* internal representation of 32bit modules. per process. */
76 typedef struct _wine_modref
77 {
78     LDR_MODULE            ldr;
79     int                   nDeps;
80     struct _wine_modref **deps;
81 } WINE_MODREF;
82
83 /* info about the current builtin dll load */
84 /* used to keep track of things across the register_dll constructor call */
85 struct builtin_load_info
86 {
87     const WCHAR *load_path;
88     const WCHAR *filename;
89     NTSTATUS     status;
90     WINE_MODREF *wm;
91 };
92
93 static struct builtin_load_info default_load_info;
94 static struct builtin_load_info *builtin_load_info = &default_load_info;
95
96 static HANDLE main_exe_file;
97 static UINT tls_module_count;      /* number of modules with TLS directory */
98 static UINT tls_total_size;        /* total size of TLS storage */
99 static const IMAGE_TLS_DIRECTORY **tls_dirs;  /* array of TLS directories */
100
101 UNICODE_STRING windows_dir = { 0, 0, NULL };  /* windows directory */
102 UNICODE_STRING system_dir = { 0, 0, NULL };  /* system directory */
103
104 static RTL_CRITICAL_SECTION loader_section;
105 static RTL_CRITICAL_SECTION_DEBUG critsect_debug =
106 {
107     0, 0, &loader_section,
108     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
109       0, 0, { (DWORD_PTR)(__FILE__ ": loader_section") }
110 };
111 static RTL_CRITICAL_SECTION loader_section = { &critsect_debug, -1, 0, 0, 0, 0 };
112
113 static WINE_MODREF *cached_modref;
114 static WINE_MODREF *current_modref;
115 static WINE_MODREF *last_failed_modref;
116
117 static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm );
118 static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved );
119 static FARPROC find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
120                                   DWORD exp_size, const char *name, int hint, LPCWSTR load_path );
121
122 /* convert PE image VirtualAddress to Real Address */
123 static inline void *get_rva( HMODULE module, DWORD va )
124 {
125     return (void *)((char *)module + va);
126 }
127
128 /* check whether the file name contains a path */
129 static inline int contains_path( LPCWSTR name )
130 {
131     return ((*name && (name[1] == ':')) || strchrW(name, '/') || strchrW(name, '\\'));
132 }
133
134 /* convert from straight ASCII to Unicode without depending on the current codepage */
135 static inline void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )
136 {
137     while (len--) *dst++ = (unsigned char)*src++;
138 }
139
140
141 /*************************************************************************
142  *              call_dll_entry_point
143  *
144  * Some brain-damaged dlls (ir32_32.dll for instance) modify ebx in
145  * their entry point, so we need a small asm wrapper.
146  */
147 #ifdef __i386__
148 extern BOOL call_dll_entry_point( DLLENTRYPROC proc, void *module, UINT reason, void *reserved );
149 __ASM_GLOBAL_FUNC(call_dll_entry_point,
150                   "pushl %ebp\n\t"
151                   "movl %esp,%ebp\n\t"
152                   "pushl %ebx\n\t"
153                   "subl $8,%esp\n\t"
154                   "pushl 20(%ebp)\n\t"
155                   "pushl 16(%ebp)\n\t"
156                   "pushl 12(%ebp)\n\t"
157                   "movl 8(%ebp),%eax\n\t"
158                   "call *%eax\n\t"
159                   "leal -4(%ebp),%esp\n\t"
160                   "popl %ebx\n\t"
161                   "popl %ebp\n\t"
162                   "ret" )
163 #else /* __i386__ */
164 static inline BOOL call_dll_entry_point( DLLENTRYPROC proc, void *module,
165                                          UINT reason, void *reserved )
166 {
167     return proc( module, reason, reserved );
168 }
169 #endif /* __i386__ */
170
171
172 #ifdef __i386__
173 /*************************************************************************
174  *              stub_entry_point
175  *
176  * Entry point for stub functions.
177  */
178 static void stub_entry_point( const char *dll, const char *name, ... )
179 {
180     EXCEPTION_RECORD rec;
181
182     rec.ExceptionCode           = EXCEPTION_WINE_STUB;
183     rec.ExceptionFlags          = EH_NONCONTINUABLE;
184     rec.ExceptionRecord         = NULL;
185 #ifdef __GNUC__
186     rec.ExceptionAddress        = __builtin_return_address(0);
187 #else
188     rec.ExceptionAddress        = *((void **)&dll - 1);
189 #endif
190     rec.NumberParameters        = 2;
191     rec.ExceptionInformation[0] = (ULONG_PTR)dll;
192     rec.ExceptionInformation[1] = (ULONG_PTR)name;
193     for (;;) RtlRaiseException( &rec );
194 }
195
196
197 #include "pshpack1.h"
198 struct stub
199 {
200     BYTE        popl_eax;   /* popl %eax */
201     BYTE        pushl1;     /* pushl $name */
202     const char *name;
203     BYTE        pushl2;     /* pushl $dll */
204     const char *dll;
205     BYTE        pushl_eax;  /* pushl %eax */
206     BYTE        jmp;        /* jmp stub_entry_point */
207     DWORD       entry;
208 };
209 #include "poppack.h"
210
211 /*************************************************************************
212  *              allocate_stub
213  *
214  * Allocate a stub entry point.
215  */
216 static ULONG_PTR allocate_stub( const char *dll, const char *name )
217 {
218 #define MAX_SIZE 65536
219     static struct stub *stubs;
220     static unsigned int nb_stubs;
221     struct stub *stub;
222
223     if (nb_stubs >= MAX_SIZE / sizeof(*stub)) return 0xdeadbeef;
224
225     if (!stubs)
226     {
227         SIZE_T size = MAX_SIZE;
228         if (NtAllocateVirtualMemory( NtCurrentProcess(), (void **)&stubs, 0, &size,
229                                      MEM_COMMIT, PAGE_EXECUTE_WRITECOPY ) != STATUS_SUCCESS)
230             return 0xdeadbeef;
231     }
232     stub = &stubs[nb_stubs++];
233     stub->popl_eax  = 0x58;  /* popl %eax */
234     stub->pushl1    = 0x68;  /* pushl $name */
235     stub->name      = name;
236     stub->pushl2    = 0x68;  /* pushl $dll */
237     stub->dll       = dll;
238     stub->pushl_eax = 0x50;  /* pushl %eax */
239     stub->jmp       = 0xe9;  /* jmp stub_entry_point */
240     stub->entry     = (BYTE *)stub_entry_point - (BYTE *)(&stub->entry + 1);
241     return (ULONG_PTR)stub;
242 }
243
244 #else  /* __i386__ */
245 static inline ULONG_PTR allocate_stub( const char *dll, const char *name ) { return 0xdeadbeef; }
246 #endif  /* __i386__ */
247
248
249 /*************************************************************************
250  *              get_modref
251  *
252  * Looks for the referenced HMODULE in the current process
253  * The loader_section must be locked while calling this function.
254  */
255 static WINE_MODREF *get_modref( HMODULE hmod )
256 {
257     PLIST_ENTRY mark, entry;
258     PLDR_MODULE mod;
259
260     if (cached_modref && cached_modref->ldr.BaseAddress == hmod) return cached_modref;
261
262     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
263     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
264     {
265         mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
266         if (mod->BaseAddress == hmod)
267             return cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
268         if (mod->BaseAddress > (void*)hmod) break;
269     }
270     return NULL;
271 }
272
273
274 /**********************************************************************
275  *          find_basename_module
276  *
277  * Find a module from its base name.
278  * The loader_section must be locked while calling this function
279  */
280 static WINE_MODREF *find_basename_module( LPCWSTR name )
281 {
282     PLIST_ENTRY mark, entry;
283
284     if (cached_modref && !strcmpiW( name, cached_modref->ldr.BaseDllName.Buffer ))
285         return cached_modref;
286
287     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
288     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
289     {
290         LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
291         if (!strcmpiW( name, mod->BaseDllName.Buffer ))
292         {
293             cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
294             return cached_modref;
295         }
296     }
297     return NULL;
298 }
299
300
301 /**********************************************************************
302  *          find_fullname_module
303  *
304  * Find a module from its full path name.
305  * The loader_section must be locked while calling this function
306  */
307 static WINE_MODREF *find_fullname_module( LPCWSTR name )
308 {
309     PLIST_ENTRY mark, entry;
310
311     if (cached_modref && !strcmpiW( name, cached_modref->ldr.FullDllName.Buffer ))
312         return cached_modref;
313
314     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
315     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
316     {
317         LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
318         if (!strcmpiW( name, mod->FullDllName.Buffer ))
319         {
320             cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
321             return cached_modref;
322         }
323     }
324     return NULL;
325 }
326
327
328 /*************************************************************************
329  *              find_forwarded_export
330  *
331  * Find the final function pointer for a forwarded function.
332  * The loader_section must be locked while calling this function.
333  */
334 static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWSTR load_path )
335 {
336     const IMAGE_EXPORT_DIRECTORY *exports;
337     DWORD exp_size;
338     WINE_MODREF *wm;
339     WCHAR mod_name[32];
340     const char *end = strrchr(forward, '.');
341     FARPROC proc = NULL;
342
343     if (!end) return NULL;
344     if ((end - forward) * sizeof(WCHAR) >= sizeof(mod_name)) return NULL;
345     ascii_to_unicode( mod_name, forward, end - forward );
346     mod_name[end - forward] = 0;
347     if (!strchrW( mod_name, '.' ))
348     {
349         if ((end - forward) * sizeof(WCHAR) >= sizeof(mod_name) - sizeof(dllW)) return NULL;
350         memcpy( mod_name + (end - forward), dllW, sizeof(dllW) );
351     }
352
353     if (!(wm = find_basename_module( mod_name )))
354     {
355         TRACE( "delay loading %s for '%s'\n", debugstr_w(mod_name), forward );
356         if (load_dll( load_path, mod_name, 0, &wm ) == STATUS_SUCCESS &&
357             !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
358         {
359             if (process_attach( wm, NULL ) != STATUS_SUCCESS)
360             {
361                 LdrUnloadDll( wm->ldr.BaseAddress );
362                 wm = NULL;
363             }
364         }
365
366         if (!wm)
367         {
368             ERR( "module not found for forward '%s' used by %s\n",
369                  forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer) );
370             return NULL;
371         }
372     }
373     if ((exports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
374                                                  IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
375         proc = find_named_export( wm->ldr.BaseAddress, exports, exp_size, end + 1, -1, load_path );
376
377     if (!proc)
378     {
379         ERR("function not found for forward '%s' used by %s."
380             " If you are using builtin %s, try using the native one instead.\n",
381             forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer),
382             debugstr_w(get_modref(module)->ldr.BaseDllName.Buffer) );
383     }
384     return proc;
385 }
386
387
388 /*************************************************************************
389  *              find_ordinal_export
390  *
391  * Find an exported function by ordinal.
392  * The exports base must have been subtracted from the ordinal already.
393  * The loader_section must be locked while calling this function.
394  */
395 static FARPROC find_ordinal_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
396                                     DWORD exp_size, DWORD ordinal, LPCWSTR load_path )
397 {
398     FARPROC proc;
399     const DWORD *functions = get_rva( module, exports->AddressOfFunctions );
400
401     if (ordinal >= exports->NumberOfFunctions)
402     {
403         TRACE(" ordinal %d out of range!\n", ordinal + exports->Base );
404         return NULL;
405     }
406     if (!functions[ordinal]) return NULL;
407
408     proc = get_rva( module, functions[ordinal] );
409
410     /* if the address falls into the export dir, it's a forward */
411     if (((const char *)proc >= (const char *)exports) && 
412         ((const char *)proc < (const char *)exports + exp_size))
413         return find_forwarded_export( module, (const char *)proc, load_path );
414
415     if (TRACE_ON(snoop))
416     {
417         const WCHAR *user = current_modref ? current_modref->ldr.BaseDllName.Buffer : NULL;
418         proc = SNOOP_GetProcAddress( module, exports, exp_size, proc, ordinal, user );
419     }
420     if (TRACE_ON(relay))
421     {
422         const WCHAR *user = current_modref ? current_modref->ldr.BaseDllName.Buffer : NULL;
423         proc = RELAY_GetProcAddress( module, exports, exp_size, proc, ordinal, user );
424     }
425     return proc;
426 }
427
428
429 /*************************************************************************
430  *              find_named_export
431  *
432  * Find an exported function by name.
433  * The loader_section must be locked while calling this function.
434  */
435 static FARPROC find_named_export( HMODULE module, const IMAGE_EXPORT_DIRECTORY *exports,
436                                   DWORD exp_size, const char *name, int hint, LPCWSTR load_path )
437 {
438     const WORD *ordinals = get_rva( module, exports->AddressOfNameOrdinals );
439     const DWORD *names = get_rva( module, exports->AddressOfNames );
440     int min = 0, max = exports->NumberOfNames - 1;
441
442     /* first check the hint */
443     if (hint >= 0 && hint <= max)
444     {
445         char *ename = get_rva( module, names[hint] );
446         if (!strcmp( ename, name ))
447             return find_ordinal_export( module, exports, exp_size, ordinals[hint], load_path );
448     }
449
450     /* then do a binary search */
451     while (min <= max)
452     {
453         int res, pos = (min + max) / 2;
454         char *ename = get_rva( module, names[pos] );
455         if (!(res = strcmp( ename, name )))
456             return find_ordinal_export( module, exports, exp_size, ordinals[pos], load_path );
457         if (res > 0) max = pos - 1;
458         else min = pos + 1;
459     }
460     return NULL;
461
462 }
463
464
465 /*************************************************************************
466  *              import_dll
467  *
468  * Import the dll specified by the given import descriptor.
469  * The loader_section must be locked while calling this function.
470  */
471 static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LPCWSTR load_path )
472 {
473     NTSTATUS status;
474     WINE_MODREF *wmImp;
475     HMODULE imp_mod;
476     const IMAGE_EXPORT_DIRECTORY *exports;
477     DWORD exp_size;
478     const IMAGE_THUNK_DATA *import_list;
479     IMAGE_THUNK_DATA *thunk_list;
480     WCHAR buffer[32];
481     const char *name = get_rva( module, descr->Name );
482     DWORD len = strlen(name);
483     PVOID protect_base;
484     SIZE_T protect_size = 0;
485     DWORD protect_old;
486
487     thunk_list = get_rva( module, (DWORD)descr->FirstThunk );
488     if (descr->u.OriginalFirstThunk)
489         import_list = get_rva( module, (DWORD)descr->u.OriginalFirstThunk );
490     else
491         import_list = thunk_list;
492
493     while (len && name[len-1] == ' ') len--;  /* remove trailing spaces */
494
495     if (len * sizeof(WCHAR) < sizeof(buffer))
496     {
497         ascii_to_unicode( buffer, name, len );
498         buffer[len] = 0;
499         status = load_dll( load_path, buffer, 0, &wmImp );
500     }
501     else  /* need to allocate a larger buffer */
502     {
503         WCHAR *ptr = RtlAllocateHeap( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) );
504         if (!ptr) return NULL;
505         ascii_to_unicode( ptr, name, len );
506         ptr[len] = 0;
507         status = load_dll( load_path, ptr, 0, &wmImp );
508         RtlFreeHeap( GetProcessHeap(), 0, ptr );
509     }
510
511     if (status)
512     {
513         if (status == STATUS_DLL_NOT_FOUND)
514             ERR("Library %s (which is needed by %s) not found\n",
515                 name, debugstr_w(current_modref->ldr.FullDllName.Buffer));
516         else
517             ERR("Loading library %s (which is needed by %s) failed (error %x).\n",
518                 name, debugstr_w(current_modref->ldr.FullDllName.Buffer), status);
519         return NULL;
520     }
521
522     /* unprotect the import address table since it can be located in
523      * readonly section */
524     while (import_list[protect_size].u1.Ordinal) protect_size++;
525     protect_base = thunk_list;
526     protect_size *= sizeof(*thunk_list);
527     NtProtectVirtualMemory( NtCurrentProcess(), &protect_base,
528                             &protect_size, PAGE_WRITECOPY, &protect_old );
529
530     imp_mod = wmImp->ldr.BaseAddress;
531     exports = RtlImageDirectoryEntryToData( imp_mod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );
532
533     if (!exports)
534     {
535         /* set all imported function to deadbeef */
536         while (import_list->u1.Ordinal)
537         {
538             if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
539             {
540                 int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
541                 WARN("No implementation for %s.%d", name, ordinal );
542                 thunk_list->u1.Function = allocate_stub( name, IntToPtr(ordinal) );
543             }
544             else
545             {
546                 IMAGE_IMPORT_BY_NAME *pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );
547                 WARN("No implementation for %s.%s", name, pe_name->Name );
548                 thunk_list->u1.Function = allocate_stub( name, (const char*)pe_name->Name );
549             }
550             WARN(" imported from %s, allocating stub %p\n",
551                  debugstr_w(current_modref->ldr.FullDllName.Buffer),
552                  (void *)thunk_list->u1.Function );
553             import_list++;
554             thunk_list++;
555         }
556         goto done;
557     }
558
559     while (import_list->u1.Ordinal)
560     {
561         if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
562         {
563             int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
564
565             thunk_list->u1.Function = (ULONG_PTR)find_ordinal_export( imp_mod, exports, exp_size,
566                                                                       ordinal - exports->Base, load_path );
567             if (!thunk_list->u1.Function)
568             {
569                 thunk_list->u1.Function = allocate_stub( name, IntToPtr(ordinal) );
570                 WARN("No implementation for %s.%d imported from %s, setting to %p\n",
571                      name, ordinal, debugstr_w(current_modref->ldr.FullDllName.Buffer),
572                      (void *)thunk_list->u1.Function );
573             }
574             TRACE_(imports)("--- Ordinal %s.%d = %p\n", name, ordinal, (void *)thunk_list->u1.Function );
575         }
576         else  /* import by name */
577         {
578             IMAGE_IMPORT_BY_NAME *pe_name;
579             pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );
580             thunk_list->u1.Function = (ULONG_PTR)find_named_export( imp_mod, exports, exp_size,
581                                                                     (const char*)pe_name->Name,
582                                                                     pe_name->Hint, load_path );
583             if (!thunk_list->u1.Function)
584             {
585                 thunk_list->u1.Function = allocate_stub( name, (const char*)pe_name->Name );
586                 WARN("No implementation for %s.%s imported from %s, setting to %p\n",
587                      name, pe_name->Name, debugstr_w(current_modref->ldr.FullDllName.Buffer),
588                      (void *)thunk_list->u1.Function );
589             }
590             TRACE_(imports)("--- %s %s.%d = %p\n",
591                             pe_name->Name, name, pe_name->Hint, (void *)thunk_list->u1.Function);
592         }
593         import_list++;
594         thunk_list++;
595     }
596
597 done:
598     /* restore old protection of the import address table */
599     NtProtectVirtualMemory( NtCurrentProcess(), &protect_base, &protect_size, protect_old, NULL );
600     return wmImp;
601 }
602
603
604 /***********************************************************************
605  *           create_module_activation_context
606  */
607 static NTSTATUS create_module_activation_context( LDR_MODULE *module )
608 {
609     NTSTATUS status;
610     LDR_RESOURCE_INFO info;
611     const IMAGE_RESOURCE_DATA_ENTRY *entry;
612
613     info.Type = RT_MANIFEST;
614     info.Name = ISOLATIONAWARE_MANIFEST_RESOURCE_ID;
615     info.Language = 0;
616     if (!(status = LdrFindResource_U( module->BaseAddress, &info, 3, &entry )))
617     {
618         ACTCTXW ctx;
619         ctx.cbSize   = sizeof(ctx);
620         ctx.lpSource = NULL;
621         ctx.dwFlags  = ACTCTX_FLAG_RESOURCE_NAME_VALID | ACTCTX_FLAG_HMODULE_VALID;
622         ctx.hModule  = module->BaseAddress;
623         ctx.lpResourceName = (LPCWSTR)ISOLATIONAWARE_MANIFEST_RESOURCE_ID;
624         status = RtlCreateActivationContext( &module->ActivationContext, &ctx );
625     }
626     return status;
627 }
628
629
630 /****************************************************************
631  *       fixup_imports
632  *
633  * Fixup all imports of a given module.
634  * The loader_section must be locked while calling this function.
635  */
636 static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path )
637 {
638     int i, nb_imports;
639     const IMAGE_IMPORT_DESCRIPTOR *imports;
640     WINE_MODREF *prev;
641     DWORD size;
642     NTSTATUS status;
643     ULONG_PTR cookie;
644
645     if (!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) return STATUS_SUCCESS;  /* already done */
646     wm->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;
647
648     if (!(imports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
649                                                   IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))
650         return STATUS_SUCCESS;
651
652     nb_imports = 0;
653     while (imports[nb_imports].Name && imports[nb_imports].FirstThunk) nb_imports++;
654
655     if (!nb_imports) return STATUS_SUCCESS;  /* no imports */
656
657     if (!create_module_activation_context( &wm->ldr ))
658         RtlActivateActivationContext( 0, wm->ldr.ActivationContext, &cookie );
659
660     /* Allocate module dependency list */
661     wm->nDeps = nb_imports;
662     wm->deps  = RtlAllocateHeap( GetProcessHeap(), 0, nb_imports*sizeof(WINE_MODREF *) );
663
664     /* load the imported modules. They are automatically
665      * added to the modref list of the process.
666      */
667     prev = current_modref;
668     current_modref = wm;
669     status = STATUS_SUCCESS;
670     for (i = 0; i < nb_imports; i++)
671     {
672         if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i], load_path )))
673             status = STATUS_DLL_NOT_FOUND;
674     }
675     current_modref = prev;
676     if (wm->ldr.ActivationContext) RtlDeactivateActivationContext( 0, cookie );
677     return status;
678 }
679
680
681 /*************************************************************************
682  *              alloc_module
683  *
684  * Allocate a WINE_MODREF structure and add it to the process list
685  * The loader_section must be locked while calling this function.
686  */
687 static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
688 {
689     WINE_MODREF *wm;
690     const WCHAR *p;
691     const IMAGE_NT_HEADERS *nt = RtlImageNtHeader(hModule);
692     PLIST_ENTRY entry, mark;
693
694     if (!(wm = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*wm) ))) return NULL;
695
696     wm->nDeps    = 0;
697     wm->deps     = NULL;
698
699     wm->ldr.BaseAddress   = hModule;
700     wm->ldr.EntryPoint    = NULL;
701     wm->ldr.SizeOfImage   = nt->OptionalHeader.SizeOfImage;
702     wm->ldr.Flags         = LDR_DONT_RESOLVE_REFS;
703     wm->ldr.LoadCount     = 1;
704     wm->ldr.TlsIndex      = -1;
705     wm->ldr.SectionHandle = NULL;
706     wm->ldr.CheckSum      = 0;
707     wm->ldr.TimeDateStamp = 0;
708     wm->ldr.ActivationContext = 0;
709
710     RtlCreateUnicodeString( &wm->ldr.FullDllName, filename );
711     if ((p = strrchrW( wm->ldr.FullDllName.Buffer, '\\' ))) p++;
712     else p = wm->ldr.FullDllName.Buffer;
713     RtlInitUnicodeString( &wm->ldr.BaseDllName, p );
714
715     if (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)
716     {
717         wm->ldr.Flags |= LDR_IMAGE_IS_DLL;
718         if (nt->OptionalHeader.AddressOfEntryPoint)
719             wm->ldr.EntryPoint = (char *)hModule + nt->OptionalHeader.AddressOfEntryPoint;
720     }
721
722     InsertTailList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
723                    &wm->ldr.InLoadOrderModuleList);
724
725     /* insert module in MemoryList, sorted in increasing base addresses */
726     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
727     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
728     {
729         if (CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList)->BaseAddress > wm->ldr.BaseAddress)
730             break;
731     }
732     entry->Blink->Flink = &wm->ldr.InMemoryOrderModuleList;
733     wm->ldr.InMemoryOrderModuleList.Blink = entry->Blink;
734     wm->ldr.InMemoryOrderModuleList.Flink = entry;
735     entry->Blink = &wm->ldr.InMemoryOrderModuleList;
736
737     /* wait until init is called for inserting into this list */
738     wm->ldr.InInitializationOrderModuleList.Flink = NULL;
739     wm->ldr.InInitializationOrderModuleList.Blink = NULL;
740
741     if (!(nt->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NX_COMPAT))
742     {
743         WARN( "disabling no-exec because of %s\n", debugstr_w(wm->ldr.BaseDllName.Buffer) );
744         VIRTUAL_SetForceExec( TRUE );
745     }
746     return wm;
747 }
748
749
750 /*************************************************************************
751  *              alloc_process_tls
752  *
753  * Allocate the process-wide structure for module TLS storage.
754  */
755 static NTSTATUS alloc_process_tls(void)
756 {
757     PLIST_ENTRY mark, entry;
758     PLDR_MODULE mod;
759     const IMAGE_TLS_DIRECTORY *dir;
760     ULONG size, i;
761
762     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
763     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
764     {
765         mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
766         if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE,
767                                                   IMAGE_DIRECTORY_ENTRY_TLS, &size )))
768             continue;
769         size = (dir->EndAddressOfRawData - dir->StartAddressOfRawData) + dir->SizeOfZeroFill;
770         if (!size) continue;
771         tls_total_size += size;
772         tls_module_count++;
773     }
774     if (!tls_module_count) return STATUS_SUCCESS;
775
776     TRACE( "count %u size %u\n", tls_module_count, tls_total_size );
777
778     tls_dirs = RtlAllocateHeap( GetProcessHeap(), 0, tls_module_count * sizeof(*tls_dirs) );
779     if (!tls_dirs) return STATUS_NO_MEMORY;
780
781     for (i = 0, entry = mark->Flink; entry != mark; entry = entry->Flink)
782     {
783         mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
784         if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE,
785                                                   IMAGE_DIRECTORY_ENTRY_TLS, &size )))
786             continue;
787         tls_dirs[i] = dir;
788         *(DWORD *)dir->AddressOfIndex = i;
789         mod->TlsIndex = i;
790         mod->LoadCount = -1;  /* can't unload it */
791         i++;
792     }
793     return STATUS_SUCCESS;
794 }
795
796
797 /*************************************************************************
798  *              alloc_thread_tls
799  *
800  * Allocate the per-thread structure for module TLS storage.
801  */
802 static NTSTATUS alloc_thread_tls(void)
803 {
804     void **pointers;
805     char *data;
806     UINT i;
807
808     if (!tls_module_count) return STATUS_SUCCESS;
809
810     if (!(pointers = RtlAllocateHeap( GetProcessHeap(), 0,
811                                       tls_module_count * sizeof(*pointers) )))
812         return STATUS_NO_MEMORY;
813
814     if (!(data = RtlAllocateHeap( GetProcessHeap(), 0, tls_total_size )))
815     {
816         RtlFreeHeap( GetProcessHeap(), 0, pointers );
817         return STATUS_NO_MEMORY;
818     }
819
820     for (i = 0; i < tls_module_count; i++)
821     {
822         const IMAGE_TLS_DIRECTORY *dir = tls_dirs[i];
823         ULONG size = dir->EndAddressOfRawData - dir->StartAddressOfRawData;
824
825         TRACE( "thread %04x idx %d: %d/%d bytes from %p to %p\n",
826                GetCurrentThreadId(), i, size, dir->SizeOfZeroFill,
827                (void *)dir->StartAddressOfRawData, data );
828
829         pointers[i] = data;
830         memcpy( data, (void *)dir->StartAddressOfRawData, size );
831         data += size;
832         memset( data, 0, dir->SizeOfZeroFill );
833         data += dir->SizeOfZeroFill;
834     }
835     NtCurrentTeb()->ThreadLocalStoragePointer = pointers;
836     return STATUS_SUCCESS;
837 }
838
839
840 /*************************************************************************
841  *              call_tls_callbacks
842  */
843 static void call_tls_callbacks( HMODULE module, UINT reason )
844 {
845     const IMAGE_TLS_DIRECTORY *dir;
846     const PIMAGE_TLS_CALLBACK *callback;
847     ULONG dirsize;
848
849     dir = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &dirsize );
850     if (!dir || !dir->AddressOfCallBacks) return;
851
852     for (callback = (const PIMAGE_TLS_CALLBACK *)dir->AddressOfCallBacks; *callback; callback++)
853     {
854         if (TRACE_ON(relay))
855             DPRINTF("%04x:Call TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
856                     GetCurrentThreadId(), *callback, module, reason_names[reason] );
857         __TRY
858         {
859             (*callback)( module, reason, NULL );
860         }
861         __EXCEPT_ALL
862         {
863             if (TRACE_ON(relay))
864                 DPRINTF("%04x:exception in TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
865                         GetCurrentThreadId(), callback, module, reason_names[reason] );
866             return;
867         }
868         __ENDTRY
869         if (TRACE_ON(relay))
870             DPRINTF("%04x:Ret  TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
871                     GetCurrentThreadId(), *callback, module, reason_names[reason] );
872     }
873 }
874
875
876 /*************************************************************************
877  *              MODULE_InitDLL
878  */
879 static NTSTATUS MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved )
880 {
881     WCHAR mod_name[32];
882     NTSTATUS status = STATUS_SUCCESS;
883     DLLENTRYPROC entry = wm->ldr.EntryPoint;
884     void *module = wm->ldr.BaseAddress;
885     BOOL retv = TRUE;
886
887     /* Skip calls for modules loaded with special load flags */
888
889     if (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS) return STATUS_SUCCESS;
890     if (wm->ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.BaseAddress, reason );
891     if (!entry) return STATUS_SUCCESS;
892
893     if (TRACE_ON(relay))
894     {
895         size_t len = min( wm->ldr.BaseDllName.Length, sizeof(mod_name)-sizeof(WCHAR) );
896         memcpy( mod_name, wm->ldr.BaseDllName.Buffer, len );
897         mod_name[len / sizeof(WCHAR)] = 0;
898         DPRINTF("%04x:Call PE DLL (proc=%p,module=%p %s,reason=%s,res=%p)\n",
899                 GetCurrentThreadId(), entry, module, debugstr_w(mod_name),
900                 reason_names[reason], lpReserved );
901     }
902     else TRACE("(%p %s,%s,%p) - CALL\n", module, debugstr_w(wm->ldr.BaseDllName.Buffer),
903                reason_names[reason], lpReserved );
904
905     __TRY
906     {
907         retv = call_dll_entry_point( entry, module, reason, lpReserved );
908         if (!retv)
909             status = STATUS_DLL_INIT_FAILED;
910     }
911     __EXCEPT_ALL
912     {
913         if (TRACE_ON(relay))
914             DPRINTF("%04x:exception in PE entry point (proc=%p,module=%p,reason=%s,res=%p)\n",
915                     GetCurrentThreadId(), entry, module, reason_names[reason], lpReserved );
916         status = GetExceptionCode();
917     }
918     __ENDTRY
919
920     /* The state of the module list may have changed due to the call
921        to the dll. We cannot assume that this module has not been
922        deleted.  */
923     if (TRACE_ON(relay))
924         DPRINTF("%04x:Ret  PE DLL (proc=%p,module=%p %s,reason=%s,res=%p) retval=%x\n",
925                 GetCurrentThreadId(), entry, module, debugstr_w(mod_name),
926                 reason_names[reason], lpReserved, retv );
927     else TRACE("(%p,%s,%p) - RETURN %d\n", module, reason_names[reason], lpReserved, retv );
928
929     return status;
930 }
931
932
933 /*************************************************************************
934  *              process_attach
935  *
936  * Send the process attach notification to all DLLs the given module
937  * depends on (recursively). This is somewhat complicated due to the fact that
938  *
939  * - we have to respect the module dependencies, i.e. modules implicitly
940  *   referenced by another module have to be initialized before the module
941  *   itself can be initialized
942  *
943  * - the initialization routine of a DLL can itself call LoadLibrary,
944  *   thereby introducing a whole new set of dependencies (even involving
945  *   the 'old' modules) at any time during the whole process
946  *
947  * (Note that this routine can be recursively entered not only directly
948  *  from itself, but also via LoadLibrary from one of the called initialization
949  *  routines.)
950  *
951  * Furthermore, we need to rearrange the main WINE_MODREF list to allow
952  * the process *detach* notifications to be sent in the correct order.
953  * This must not only take into account module dependencies, but also
954  * 'hidden' dependencies created by modules calling LoadLibrary in their
955  * attach notification routine.
956  *
957  * The strategy is rather simple: we move a WINE_MODREF to the head of the
958  * list after the attach notification has returned.  This implies that the
959  * detach notifications are called in the reverse of the sequence the attach
960  * notifications *returned*.
961  *
962  * The loader_section must be locked while calling this function.
963  */
964 static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved )
965 {
966     NTSTATUS status = STATUS_SUCCESS;
967     ULONG_PTR cookie;
968     int i;
969
970     if (process_detaching) return status;
971
972     /* prevent infinite recursion in case of cyclical dependencies */
973     if (    ( wm->ldr.Flags & LDR_LOAD_IN_PROGRESS )
974          || ( wm->ldr.Flags & LDR_PROCESS_ATTACHED ) )
975         return status;
976
977     TRACE("(%s,%p) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved );
978
979     /* Tag current MODREF to prevent recursive loop */
980     wm->ldr.Flags |= LDR_LOAD_IN_PROGRESS;
981     if (lpReserved) wm->ldr.LoadCount = -1;  /* pin it if imported by the main exe */
982     if (wm->ldr.ActivationContext) RtlActivateActivationContext( 0, wm->ldr.ActivationContext, &cookie );
983
984     /* Recursively attach all DLLs this one depends on */
985     for ( i = 0; i < wm->nDeps; i++ )
986     {
987         if (!wm->deps[i]) continue;
988         if ((status = process_attach( wm->deps[i], lpReserved )) != STATUS_SUCCESS) break;
989     }
990
991     /* Call DLL entry point */
992     if (status == STATUS_SUCCESS)
993     {
994         WINE_MODREF *prev = current_modref;
995         current_modref = wm;
996         status = MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved );
997         if (status == STATUS_SUCCESS)
998             wm->ldr.Flags |= LDR_PROCESS_ATTACHED;
999         else
1000         {
1001             /* point to the name so LdrInitializeThunk can print it */
1002             last_failed_modref = wm;
1003             WARN("Initialization of %s failed\n", debugstr_w(wm->ldr.BaseDllName.Buffer));
1004         }
1005         current_modref = prev;
1006     }
1007
1008     if (!wm->ldr.InInitializationOrderModuleList.Flink)
1009         InsertTailList(&NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList,
1010                        &wm->ldr.InInitializationOrderModuleList);
1011
1012     if (wm->ldr.ActivationContext) RtlDeactivateActivationContext( 0, cookie );
1013     /* Remove recursion flag */
1014     wm->ldr.Flags &= ~LDR_LOAD_IN_PROGRESS;
1015
1016     TRACE("(%s,%p) - END\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved );
1017     return status;
1018 }
1019
1020
1021 /**********************************************************************
1022  *          attach_implicitly_loaded_dlls
1023  *
1024  * Attach to the (builtin) dlls that have been implicitly loaded because
1025  * of a dependency at the Unix level, but not imported at the Win32 level.
1026  */
1027 static void attach_implicitly_loaded_dlls( LPVOID reserved )
1028 {
1029     for (;;)
1030     {
1031         PLIST_ENTRY mark, entry;
1032
1033         mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
1034         for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1035         {
1036             LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
1037
1038             if (mod->Flags & (LDR_LOAD_IN_PROGRESS | LDR_PROCESS_ATTACHED)) continue;
1039             TRACE( "found implicitly loaded %s, attaching to it\n",
1040                    debugstr_w(mod->BaseDllName.Buffer));
1041             process_attach( CONTAINING_RECORD(mod, WINE_MODREF, ldr), reserved );
1042             break;  /* restart the search from the start */
1043         }
1044         if (entry == mark) break;  /* nothing found */
1045     }
1046 }
1047
1048
1049 /*************************************************************************
1050  *              process_detach
1051  *
1052  * Send DLL process detach notifications.  See the comment about calling
1053  * sequence at process_attach.  Unless the bForceDetach flag
1054  * is set, only DLLs with zero refcount are notified.
1055  */
1056 static void process_detach( BOOL bForceDetach, LPVOID lpReserved )
1057 {
1058     PLIST_ENTRY mark, entry;
1059     PLDR_MODULE mod;
1060
1061     RtlEnterCriticalSection( &loader_section );
1062     if (bForceDetach) process_detaching = 1;
1063     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
1064     do
1065     {
1066         for (entry = mark->Blink; entry != mark; entry = entry->Blink)
1067         {
1068             mod = CONTAINING_RECORD(entry, LDR_MODULE, 
1069                                     InInitializationOrderModuleList);
1070             /* Check whether to detach this DLL */
1071             if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
1072                 continue;
1073             if ( mod->LoadCount && !bForceDetach )
1074                 continue;
1075
1076             /* Call detach notification */
1077             mod->Flags &= ~LDR_PROCESS_ATTACHED;
1078             MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr), 
1079                             DLL_PROCESS_DETACH, lpReserved );
1080
1081             /* Restart at head of WINE_MODREF list, as entries might have
1082                been added and/or removed while performing the call ... */
1083             break;
1084         }
1085     } while (entry != mark);
1086
1087     RtlLeaveCriticalSection( &loader_section );
1088 }
1089
1090 /*************************************************************************
1091  *              MODULE_DllThreadAttach
1092  *
1093  * Send DLL thread attach notifications. These are sent in the
1094  * reverse sequence of process detach notification.
1095  *
1096  */
1097 NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved )
1098 {
1099     PLIST_ENTRY mark, entry;
1100     PLDR_MODULE mod;
1101     NTSTATUS    status;
1102
1103     /* don't do any attach calls if process is exiting */
1104     if (process_detaching) return STATUS_SUCCESS;
1105     /* FIXME: there is still a race here */
1106
1107     RtlEnterCriticalSection( &loader_section );
1108
1109     if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto done;
1110
1111     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
1112     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1113     {
1114         mod = CONTAINING_RECORD(entry, LDR_MODULE, 
1115                                 InInitializationOrderModuleList);
1116         if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
1117             continue;
1118         if ( mod->Flags & LDR_NO_DLL_CALLS )
1119             continue;
1120
1121         MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr),
1122                         DLL_THREAD_ATTACH, lpReserved );
1123     }
1124
1125 done:
1126     RtlLeaveCriticalSection( &loader_section );
1127     return status;
1128 }
1129
1130 /******************************************************************
1131  *              LdrDisableThreadCalloutsForDll (NTDLL.@)
1132  *
1133  */
1134 NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE hModule)
1135 {
1136     WINE_MODREF *wm;
1137     NTSTATUS    ret = STATUS_SUCCESS;
1138
1139     RtlEnterCriticalSection( &loader_section );
1140
1141     wm = get_modref( hModule );
1142     if (!wm || wm->ldr.TlsIndex != -1)
1143         ret = STATUS_DLL_NOT_FOUND;
1144     else
1145         wm->ldr.Flags |= LDR_NO_DLL_CALLS;
1146
1147     RtlLeaveCriticalSection( &loader_section );
1148
1149     return ret;
1150 }
1151
1152 /******************************************************************
1153  *              LdrFindEntryForAddress (NTDLL.@)
1154  *
1155  * The loader_section must be locked while calling this function
1156  */
1157 NTSTATUS WINAPI LdrFindEntryForAddress(const void* addr, PLDR_MODULE* pmod)
1158 {
1159     PLIST_ENTRY mark, entry;
1160     PLDR_MODULE mod;
1161
1162     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
1163     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1164     {
1165         mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
1166         if ((const void *)mod->BaseAddress <= addr &&
1167             (const char *)addr < (char*)mod->BaseAddress + mod->SizeOfImage)
1168         {
1169             *pmod = mod;
1170             return STATUS_SUCCESS;
1171         }
1172         if ((const void *)mod->BaseAddress > addr) break;
1173     }
1174     return STATUS_NO_MORE_ENTRIES;
1175 }
1176
1177 /******************************************************************
1178  *              LdrLockLoaderLock  (NTDLL.@)
1179  *
1180  * Note: flags are not implemented.
1181  * Flag 0x01 is used to raise exceptions on errors.
1182  * Flag 0x02 is used to avoid waiting on the section (does RtlTryEnterCriticalSection instead).
1183  */
1184 NTSTATUS WINAPI LdrLockLoaderLock( ULONG flags, ULONG *result, ULONG *magic )
1185 {
1186     if (flags) FIXME( "flags %x not supported\n", flags );
1187
1188     if (result) *result = 1;
1189     if (!magic) return STATUS_INVALID_PARAMETER_3;
1190     RtlEnterCriticalSection( &loader_section );
1191     *magic = GetCurrentThreadId();
1192     return STATUS_SUCCESS;
1193 }
1194
1195
1196 /******************************************************************
1197  *              LdrUnlockLoaderUnlock  (NTDLL.@)
1198  */
1199 NTSTATUS WINAPI LdrUnlockLoaderLock( ULONG flags, ULONG magic )
1200 {
1201     if (magic)
1202     {
1203         if (magic != GetCurrentThreadId()) return STATUS_INVALID_PARAMETER_2;
1204         RtlLeaveCriticalSection( &loader_section );
1205     }
1206     return STATUS_SUCCESS;
1207 }
1208
1209
1210 /******************************************************************
1211  *              LdrGetProcedureAddress  (NTDLL.@)
1212  */
1213 NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name,
1214                                        ULONG ord, PVOID *address)
1215 {
1216     IMAGE_EXPORT_DIRECTORY *exports;
1217     DWORD exp_size;
1218     NTSTATUS ret = STATUS_PROCEDURE_NOT_FOUND;
1219
1220     RtlEnterCriticalSection( &loader_section );
1221
1222     /* check if the module itself is invalid to return the proper error */
1223     if (!get_modref( module )) ret = STATUS_DLL_NOT_FOUND;
1224     else if ((exports = RtlImageDirectoryEntryToData( module, TRUE,
1225                                                       IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
1226     {
1227         LPCWSTR load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
1228         void *proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1, load_path )
1229                           : find_ordinal_export( module, exports, exp_size, ord - exports->Base, load_path );
1230         if (proc)
1231         {
1232             *address = proc;
1233             ret = STATUS_SUCCESS;
1234         }
1235     }
1236
1237     RtlLeaveCriticalSection( &loader_section );
1238     return ret;
1239 }
1240
1241
1242 /***********************************************************************
1243  *           is_fake_dll
1244  *
1245  * Check if a loaded native dll is a Wine fake dll.
1246  */
1247 static BOOL is_fake_dll( HANDLE handle )
1248 {
1249     static const char fakedll_signature[] = "Wine placeholder DLL";
1250     char buffer[sizeof(IMAGE_DOS_HEADER) + sizeof(fakedll_signature)];
1251     const IMAGE_DOS_HEADER *dos = (const IMAGE_DOS_HEADER *)buffer;
1252     IO_STATUS_BLOCK io;
1253     LARGE_INTEGER offset;
1254
1255     offset.QuadPart = 0;
1256     if (NtReadFile( handle, 0, NULL, 0, &io, buffer, sizeof(buffer), &offset, NULL )) return FALSE;
1257     if (io.Information < sizeof(buffer)) return FALSE;
1258     if (dos->e_magic != IMAGE_DOS_SIGNATURE) return FALSE;
1259     if (dos->e_lfanew >= sizeof(*dos) + sizeof(fakedll_signature) &&
1260         !memcmp( dos + 1, fakedll_signature, sizeof(fakedll_signature) )) return TRUE;
1261     return FALSE;
1262 }
1263
1264
1265 /***********************************************************************
1266  *           get_builtin_fullname
1267  *
1268  * Build the full pathname for a builtin dll.
1269  */
1270 static WCHAR *get_builtin_fullname( const WCHAR *path, const char *filename )
1271 {
1272     static const WCHAR soW[] = {'.','s','o',0};
1273     WCHAR *p, *fullname;
1274     size_t i, len = strlen(filename);
1275
1276     /* check if path can correspond to the dll we have */
1277     if (path && (p = strrchrW( path, '\\' )))
1278     {
1279         p++;
1280         for (i = 0; i < len; i++)
1281             if (tolowerW(p[i]) != tolowerW( (WCHAR)filename[i]) ) break;
1282         if (i == len && (!p[len] || !strcmpiW( p + len, soW )))
1283         {
1284             /* the filename matches, use path as the full path */
1285             len += p - path;
1286             if ((fullname = RtlAllocateHeap( GetProcessHeap(), 0, (len + 1) * sizeof(WCHAR) )))
1287             {
1288                 memcpy( fullname, path, len * sizeof(WCHAR) );
1289                 fullname[len] = 0;
1290             }
1291             return fullname;
1292         }
1293     }
1294
1295     if ((fullname = RtlAllocateHeap( GetProcessHeap(), 0,
1296                                      system_dir.MaximumLength + (len + 1) * sizeof(WCHAR) )))
1297     {
1298         memcpy( fullname, system_dir.Buffer, system_dir.Length );
1299         p = fullname + system_dir.Length / sizeof(WCHAR);
1300         if (p > fullname && p[-1] != '\\') *p++ = '\\';
1301         ascii_to_unicode( p, filename, len + 1 );
1302     }
1303     return fullname;
1304 }
1305
1306
1307 /***********************************************************************
1308  *           load_builtin_callback
1309  *
1310  * Load a library in memory; callback function for wine_dll_register
1311  */
1312 static void load_builtin_callback( void *module, const char *filename )
1313 {
1314     static const WCHAR emptyW[1];
1315     void *addr;
1316     IMAGE_NT_HEADERS *nt;
1317     WINE_MODREF *wm;
1318     WCHAR *fullname;
1319     const WCHAR *load_path;
1320     SIZE_T size;
1321
1322     if (!module)
1323     {
1324         ERR("could not map image for %s\n", filename ? filename : "main exe" );
1325         return;
1326     }
1327     if (!(nt = RtlImageNtHeader( module )))
1328     {
1329         ERR( "bad module for %s\n", filename ? filename : "main exe" );
1330         builtin_load_info->status = STATUS_INVALID_IMAGE_FORMAT;
1331         return;
1332     }
1333     addr = module;
1334     size = nt->OptionalHeader.SizeOfImage;
1335     NtAllocateVirtualMemory( NtCurrentProcess(), &addr, 0, &size,
1336                              MEM_SYSTEM | MEM_IMAGE, PAGE_EXECUTE_WRITECOPY );
1337     /* create the MODREF */
1338
1339     if (!(fullname = get_builtin_fullname( builtin_load_info->filename, filename )))
1340     {
1341         ERR( "can't load %s\n", filename );
1342         builtin_load_info->status = STATUS_NO_MEMORY;
1343         return;
1344     }
1345
1346     wm = alloc_module( module, fullname );
1347     RtlFreeHeap( GetProcessHeap(), 0, fullname );
1348     if (!wm)
1349     {
1350         ERR( "can't load %s\n", filename );
1351         builtin_load_info->status = STATUS_NO_MEMORY;
1352         return;
1353     }
1354     wm->ldr.Flags |= LDR_WINE_INTERNAL;
1355
1356     if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL) &&
1357         !NtCurrentTeb()->Peb->ImageBaseAddress)  /* if we already have an executable, ignore this one */
1358     {
1359         NtCurrentTeb()->Peb->ImageBaseAddress = module;
1360     }
1361     else
1362     {
1363         /* fixup imports */
1364
1365         load_path = builtin_load_info->load_path;
1366         if (!load_path) load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
1367         if (!load_path) load_path = emptyW;
1368         if (fixup_imports( wm, load_path ) != STATUS_SUCCESS)
1369         {
1370             /* the module has only be inserted in the load & memory order lists */
1371             RemoveEntryList(&wm->ldr.InLoadOrderModuleList);
1372             RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);
1373             /* FIXME: free the modref */
1374             builtin_load_info->status = STATUS_DLL_NOT_FOUND;
1375             return;
1376         }
1377     }
1378
1379     builtin_load_info->wm = wm;
1380     TRACE( "loaded %s %p %p\n", filename, wm, module );
1381
1382     /* send the DLL load event */
1383
1384     SERVER_START_REQ( load_dll )
1385     {
1386         req->handle     = 0;
1387         req->base       = module;
1388         req->size       = nt->OptionalHeader.SizeOfImage;
1389         req->dbg_offset = nt->FileHeader.PointerToSymbolTable;
1390         req->dbg_size   = nt->FileHeader.NumberOfSymbols;
1391         req->name       = &wm->ldr.FullDllName.Buffer;
1392         wine_server_add_data( req, wm->ldr.FullDllName.Buffer, wm->ldr.FullDllName.Length );
1393         wine_server_call( req );
1394     }
1395     SERVER_END_REQ;
1396
1397     /* setup relay debugging entry points */
1398     if (TRACE_ON(relay)) RELAY_SetupDLL( module );
1399 }
1400
1401
1402 /******************************************************************************
1403  *      load_native_dll  (internal)
1404  */
1405 static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,
1406                                  DWORD flags, WINE_MODREF** pwm )
1407 {
1408     void *module;
1409     HANDLE mapping;
1410     OBJECT_ATTRIBUTES attr;
1411     LARGE_INTEGER size;
1412     IMAGE_NT_HEADERS *nt;
1413     SIZE_T len = 0;
1414     WINE_MODREF *wm;
1415     NTSTATUS status;
1416
1417     TRACE("Trying native dll %s\n", debugstr_w(name));
1418
1419     attr.Length                   = sizeof(attr);
1420     attr.RootDirectory            = 0;
1421     attr.ObjectName               = NULL;
1422     attr.Attributes               = 0;
1423     attr.SecurityDescriptor       = NULL;
1424     attr.SecurityQualityOfService = NULL;
1425     size.QuadPart = 0;
1426
1427     status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1428                               &attr, &size, 0, SEC_IMAGE, file );
1429     if (status != STATUS_SUCCESS) return status;
1430
1431     module = NULL;
1432     status = NtMapViewOfSection( mapping, NtCurrentProcess(),
1433                                  &module, 0, 0, &size, &len, ViewShare, 0, PAGE_READONLY );
1434     NtClose( mapping );
1435     if (status != STATUS_SUCCESS) return status;
1436
1437     /* create the MODREF */
1438
1439     if (!(wm = alloc_module( module, name ))) return STATUS_NO_MEMORY;
1440
1441     /* fixup imports */
1442
1443     if (!(flags & DONT_RESOLVE_DLL_REFERENCES))
1444     {
1445         if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS)
1446         {
1447             /* the module has only be inserted in the load & memory order lists */
1448             RemoveEntryList(&wm->ldr.InLoadOrderModuleList);
1449             RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);
1450
1451             /* FIXME: there are several more dangling references
1452              * left. Including dlls loaded by this dll before the
1453              * failed one. Unrolling is rather difficult with the
1454              * current structure and we can leave them lying
1455              * around with no problems, so we don't care.
1456              * As these might reference our wm, we don't free it.
1457              */
1458             return status;
1459         }
1460     }
1461
1462     /* send DLL load event */
1463
1464     nt = RtlImageNtHeader( module );
1465
1466     SERVER_START_REQ( load_dll )
1467     {
1468         req->handle     = file;
1469         req->base       = module;
1470         req->size       = nt->OptionalHeader.SizeOfImage;
1471         req->dbg_offset = nt->FileHeader.PointerToSymbolTable;
1472         req->dbg_size   = nt->FileHeader.NumberOfSymbols;
1473         req->name       = &wm->ldr.FullDllName.Buffer;
1474         wine_server_add_data( req, wm->ldr.FullDllName.Buffer, wm->ldr.FullDllName.Length );
1475         wine_server_call( req );
1476     }
1477     SERVER_END_REQ;
1478
1479     if ((wm->ldr.Flags & LDR_IMAGE_IS_DLL) && TRACE_ON(snoop)) SNOOP_SetupDLL( module );
1480
1481     TRACE_(loaddll)( "Loaded %s at %p: native\n", debugstr_w(wm->ldr.FullDllName.Buffer), module );
1482
1483     wm->ldr.LoadCount = 1;
1484     *pwm = wm;
1485     return STATUS_SUCCESS;
1486 }
1487
1488
1489 /***********************************************************************
1490  *           load_builtin_dll
1491  */
1492 static NTSTATUS load_builtin_dll( LPCWSTR load_path, LPCWSTR path, HANDLE file,
1493                                   DWORD flags, WINE_MODREF** pwm )
1494 {
1495     char error[256], dllname[MAX_PATH];
1496     const WCHAR *name, *p;
1497     DWORD len, i;
1498     void *handle = NULL;
1499     struct builtin_load_info info, *prev_info;
1500
1501     /* Fix the name in case we have a full path and extension */
1502     name = path;
1503     if ((p = strrchrW( name, '\\' ))) name = p + 1;
1504     if ((p = strrchrW( name, '/' ))) name = p + 1;
1505
1506     /* load_library will modify info.status. Note also that load_library can be
1507      * called several times, if the .so file we're loading has dependencies.
1508      * info.status will gather all the errors we may get while loading all these
1509      * libraries
1510      */
1511     info.load_path = load_path;
1512     info.filename  = NULL;
1513     info.status    = STATUS_SUCCESS;
1514     info.wm        = NULL;
1515
1516     if (file)  /* we have a real file, try to load it */
1517     {
1518         UNICODE_STRING nt_name;
1519         ANSI_STRING unix_name;
1520
1521         TRACE("Trying built-in %s\n", debugstr_w(path));
1522
1523         if (!RtlDosPathNameToNtPathName_U( path, &nt_name, NULL, NULL ))
1524             return STATUS_DLL_NOT_FOUND;
1525
1526         if (wine_nt_to_unix_file_name( &nt_name, &unix_name, FILE_OPEN, FALSE ))
1527         {
1528             RtlFreeUnicodeString( &nt_name );
1529             return STATUS_DLL_NOT_FOUND;
1530         }
1531         prev_info = builtin_load_info;
1532         info.filename = nt_name.Buffer + 4;  /* skip \??\ */
1533         builtin_load_info = &info;
1534         handle = wine_dlopen( unix_name.Buffer, RTLD_NOW, error, sizeof(error) );
1535         builtin_load_info = prev_info;
1536         RtlFreeUnicodeString( &nt_name );
1537         RtlFreeHeap( GetProcessHeap(), 0, unix_name.Buffer );
1538         if (!handle)
1539         {
1540             WARN( "failed to load .so lib for builtin %s: %s\n", debugstr_w(path), error );
1541             return STATUS_INVALID_IMAGE_FORMAT;
1542         }
1543     }
1544     else
1545     {
1546         int file_exists;
1547
1548         TRACE("Trying built-in %s\n", debugstr_w(name));
1549
1550         /* we don't want to depend on the current codepage here */
1551         len = strlenW( name ) + 1;
1552         if (len >= sizeof(dllname)) return STATUS_NAME_TOO_LONG;
1553         for (i = 0; i < len; i++)
1554         {
1555             if (name[i] > 127) return STATUS_DLL_NOT_FOUND;
1556             dllname[i] = (char)name[i];
1557             if (dllname[i] >= 'A' && dllname[i] <= 'Z') dllname[i] += 'a' - 'A';
1558         }
1559
1560         prev_info = builtin_load_info;
1561         builtin_load_info = &info;
1562         handle = wine_dll_load( dllname, error, sizeof(error), &file_exists );
1563         builtin_load_info = prev_info;
1564         if (!handle)
1565         {
1566             if (!file_exists)
1567             {
1568                 /* The file does not exist -> WARN() */
1569                 WARN("cannot open .so lib for builtin %s: %s\n", debugstr_w(name), error);
1570                 return STATUS_DLL_NOT_FOUND;
1571             }
1572             /* ERR() for all other errors (missing functions, ...) */
1573             ERR("failed to load .so lib for builtin %s: %s\n", debugstr_w(name), error );
1574             return STATUS_PROCEDURE_NOT_FOUND;
1575         }
1576     }
1577
1578     if (info.status != STATUS_SUCCESS)
1579     {
1580         wine_dll_unload( handle );
1581         return info.status;
1582     }
1583
1584     if (!info.wm)
1585     {
1586         PLIST_ENTRY mark, entry;
1587
1588         /* The constructor wasn't called, this means the .so is already
1589          * loaded under a different name. Try to find the wm for it. */
1590
1591         mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
1592         for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1593         {
1594             LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
1595             if (mod->Flags & LDR_WINE_INTERNAL && mod->SectionHandle == handle)
1596             {
1597                 info.wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
1598                 TRACE( "Found %s at %p for builtin %s\n",
1599                        debugstr_w(info.wm->ldr.FullDllName.Buffer), info.wm->ldr.BaseAddress, debugstr_w(path) );
1600                 break;
1601             }
1602         }
1603         wine_dll_unload( handle );  /* release the libdl refcount */
1604         if (!info.wm) return STATUS_INVALID_IMAGE_FORMAT;
1605         if (info.wm->ldr.LoadCount != -1) info.wm->ldr.LoadCount++;
1606     }
1607     else
1608     {
1609         TRACE_(loaddll)( "Loaded %s at %p: builtin\n", debugstr_w(info.wm->ldr.FullDllName.Buffer), info.wm->ldr.BaseAddress );
1610         info.wm->ldr.LoadCount = 1;
1611         info.wm->ldr.SectionHandle = handle;
1612     }
1613
1614     *pwm = info.wm;
1615     return STATUS_SUCCESS;
1616 }
1617
1618
1619 /***********************************************************************
1620  *      find_actctx_dll
1621  *
1622  * Find the full path (if any) of the dll from the activation context.
1623  */
1624 static NTSTATUS find_actctx_dll( LPCWSTR libname, LPWSTR *fullname )
1625 {
1626     static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s','\\'};
1627     static const WCHAR dotManifestW[] = {'.','m','a','n','i','f','e','s','t',0};
1628
1629     ACTIVATION_CONTEXT_ASSEMBLY_DETAILED_INFORMATION *info;
1630     ACTCTX_SECTION_KEYED_DATA data;
1631     UNICODE_STRING nameW;
1632     NTSTATUS status;
1633     SIZE_T needed, size = 1024;
1634     WCHAR *p;
1635
1636     RtlInitUnicodeString( &nameW, libname );
1637     data.cbSize = sizeof(data);
1638     status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, NULL,
1639                                                     ACTIVATION_CONTEXT_SECTION_DLL_REDIRECTION,
1640                                                     &nameW, &data );
1641     if (status != STATUS_SUCCESS) return status;
1642
1643     for (;;)
1644     {
1645         if (!(info = RtlAllocateHeap( GetProcessHeap(), 0, size )))
1646         {
1647             status = STATUS_NO_MEMORY;
1648             goto done;
1649         }
1650         status = RtlQueryInformationActivationContext( 0, data.hActCtx, &data.ulAssemblyRosterIndex,
1651                                                        AssemblyDetailedInformationInActivationContext,
1652                                                        info, size, &needed );
1653         if (status == STATUS_SUCCESS) break;
1654         if (status != STATUS_BUFFER_TOO_SMALL) goto done;
1655         RtlFreeHeap( GetProcessHeap(), 0, info );
1656         size = needed;
1657         /* restart with larger buffer */
1658     }
1659
1660     if ((p = strrchrW( info->lpAssemblyManifestPath, '\\' )))
1661     {
1662         DWORD dirlen = info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
1663
1664         p++;
1665         if (strncmpiW( p, info->lpAssemblyDirectoryName, dirlen ) || strcmpiW( p + dirlen, dotManifestW ))
1666         {
1667             /* manifest name does not match directory name, so it's not a global
1668              * windows/winsxs manifest; use the manifest directory name instead */
1669             dirlen = p - info->lpAssemblyManifestPath;
1670             needed = (dirlen + 1) * sizeof(WCHAR) + nameW.Length;
1671             if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed )))
1672             {
1673                 status = STATUS_NO_MEMORY;
1674                 goto done;
1675             }
1676             memcpy( p, info->lpAssemblyManifestPath, dirlen * sizeof(WCHAR) );
1677             p += dirlen;
1678             strcpyW( p, libname );
1679             goto done;
1680         }
1681     }
1682
1683     needed = (windows_dir.Length + sizeof(winsxsW) + info->ulAssemblyDirectoryNameLength +
1684               nameW.Length + 2*sizeof(WCHAR));
1685
1686     if (!(*fullname = p = RtlAllocateHeap( GetProcessHeap(), 0, needed )))
1687     {
1688         status = STATUS_NO_MEMORY;
1689         goto done;
1690     }
1691     memcpy( p, windows_dir.Buffer, windows_dir.Length );
1692     p += windows_dir.Length / sizeof(WCHAR);
1693     memcpy( p, winsxsW, sizeof(winsxsW) );
1694     p += sizeof(winsxsW) / sizeof(WCHAR);
1695     memcpy( p, info->lpAssemblyDirectoryName, info->ulAssemblyDirectoryNameLength );
1696     p += info->ulAssemblyDirectoryNameLength / sizeof(WCHAR);
1697     *p++ = '\\';
1698     strcpyW( p, libname );
1699 done:
1700     RtlFreeHeap( GetProcessHeap(), 0, info );
1701     RtlReleaseActivationContext( data.hActCtx );
1702     return status;
1703 }
1704
1705
1706 /***********************************************************************
1707  *      find_dll_file
1708  *
1709  * Find the file (or already loaded module) for a given dll name.
1710  */
1711 static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,
1712                                WCHAR *filename, ULONG *size, WINE_MODREF **pwm, HANDLE *handle )
1713 {
1714     OBJECT_ATTRIBUTES attr;
1715     IO_STATUS_BLOCK io;
1716     UNICODE_STRING nt_name;
1717     WCHAR *file_part, *ext, *dllname;
1718     ULONG len;
1719
1720     /* first append .dll if needed */
1721
1722     dllname = NULL;
1723     if (!(ext = strrchrW( libname, '.')) || strchrW( ext, '/' ) || strchrW( ext, '\\'))
1724     {
1725         if (!(dllname = RtlAllocateHeap( GetProcessHeap(), 0,
1726                                          (strlenW(libname) * sizeof(WCHAR)) + sizeof(dllW) )))
1727             return STATUS_NO_MEMORY;
1728         strcpyW( dllname, libname );
1729         strcatW( dllname, dllW );
1730         libname = dllname;
1731     }
1732
1733     nt_name.Buffer = NULL;
1734
1735     if (!contains_path( libname ))
1736     {
1737         NTSTATUS status;
1738         WCHAR *fullname = NULL;
1739
1740         if ((*pwm = find_basename_module( libname )) != NULL) goto found;
1741
1742         status = find_actctx_dll( libname, &fullname );
1743         if (status == STATUS_SUCCESS)
1744         {
1745             TRACE ("found %s for %s\n", debugstr_w(fullname), debugstr_w(libname) );
1746             RtlFreeHeap( GetProcessHeap(), 0, dllname );
1747             libname = dllname = fullname;
1748         }
1749         else if (status != STATUS_SXS_KEY_NOT_FOUND)
1750         {
1751             RtlFreeHeap( GetProcessHeap(), 0, dllname );
1752             return status;
1753         }
1754     }
1755
1756     if (RtlDetermineDosPathNameType_U( libname ) == RELATIVE_PATH)
1757     {
1758         /* we need to search for it */
1759         len = RtlDosSearchPath_U( load_path, libname, NULL, *size, filename, &file_part );
1760         if (len)
1761         {
1762             if (len >= *size) goto overflow;
1763             if ((*pwm = find_fullname_module( filename )) || !handle) goto found;
1764
1765             if (!RtlDosPathNameToNtPathName_U( filename, &nt_name, NULL, NULL ))
1766             {
1767                 RtlFreeHeap( GetProcessHeap(), 0, dllname );
1768                 return STATUS_NO_MEMORY;
1769             }
1770             attr.Length = sizeof(attr);
1771             attr.RootDirectory = 0;
1772             attr.Attributes = OBJ_CASE_INSENSITIVE;
1773             attr.ObjectName = &nt_name;
1774             attr.SecurityDescriptor = NULL;
1775             attr.SecurityQualityOfService = NULL;
1776             if (NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ|FILE_SHARE_DELETE, 0 )) *handle = 0;
1777             goto found;
1778         }
1779
1780         /* not found */
1781
1782         if (!contains_path( libname ))
1783         {
1784             /* if libname doesn't contain a path at all, we simply return the name as is,
1785              * to be loaded as builtin */
1786             len = strlenW(libname) * sizeof(WCHAR);
1787             if (len >= *size) goto overflow;
1788             strcpyW( filename, libname );
1789             goto found;
1790         }
1791     }
1792
1793     /* absolute path name, or relative path name but not found above */
1794
1795     if (!RtlDosPathNameToNtPathName_U( libname, &nt_name, &file_part, NULL ))
1796     {
1797         RtlFreeHeap( GetProcessHeap(), 0, dllname );
1798         return STATUS_NO_MEMORY;
1799     }
1800     len = nt_name.Length - 4*sizeof(WCHAR);  /* for \??\ prefix */
1801     if (len >= *size) goto overflow;
1802     memcpy( filename, nt_name.Buffer + 4, len + sizeof(WCHAR) );
1803     if (!(*pwm = find_fullname_module( filename )) && handle)
1804     {
1805         attr.Length = sizeof(attr);
1806         attr.RootDirectory = 0;
1807         attr.Attributes = OBJ_CASE_INSENSITIVE;
1808         attr.ObjectName = &nt_name;
1809         attr.SecurityDescriptor = NULL;
1810         attr.SecurityQualityOfService = NULL;
1811         if (NtOpenFile( handle, GENERIC_READ, &attr, &io, FILE_SHARE_READ|FILE_SHARE_DELETE, 0 )) *handle = 0;
1812     }
1813 found:
1814     RtlFreeUnicodeString( &nt_name );
1815     RtlFreeHeap( GetProcessHeap(), 0, dllname );
1816     return STATUS_SUCCESS;
1817
1818 overflow:
1819     RtlFreeUnicodeString( &nt_name );
1820     RtlFreeHeap( GetProcessHeap(), 0, dllname );
1821     *size = len + sizeof(WCHAR);
1822     return STATUS_BUFFER_TOO_SMALL;
1823 }
1824
1825
1826 /***********************************************************************
1827  *      load_dll  (internal)
1828  *
1829  * Load a PE style module according to the load order.
1830  * The loader_section must be locked while calling this function.
1831  */
1832 static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
1833 {
1834     enum loadorder loadorder;
1835     WCHAR buffer[32];
1836     WCHAR *filename;
1837     ULONG size;
1838     WINE_MODREF *main_exe;
1839     HANDLE handle = 0;
1840     NTSTATUS nts;
1841
1842     TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
1843
1844     *pwm = NULL;
1845     filename = buffer;
1846     size = sizeof(buffer);
1847     for (;;)
1848     {
1849         nts = find_dll_file( load_path, libname, filename, &size, pwm, &handle );
1850         if (nts == STATUS_SUCCESS) break;
1851         if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
1852         if (nts != STATUS_BUFFER_TOO_SMALL) return nts;
1853         /* grow the buffer and retry */
1854         if (!(filename = RtlAllocateHeap( GetProcessHeap(), 0, size ))) return STATUS_NO_MEMORY;
1855     }
1856
1857     if (*pwm)  /* found already loaded module */
1858     {
1859         if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
1860
1861         if (!(flags & DONT_RESOLVE_DLL_REFERENCES)) fixup_imports( *pwm, load_path );
1862
1863         TRACE("Found %s for %s at %p, count=%d\n",
1864               debugstr_w((*pwm)->ldr.FullDllName.Buffer), debugstr_w(libname),
1865               (*pwm)->ldr.BaseAddress, (*pwm)->ldr.LoadCount);
1866         if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
1867         return STATUS_SUCCESS;
1868     }
1869
1870     main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
1871     loadorder = get_load_order( main_exe ? main_exe->ldr.BaseDllName.Buffer : NULL, filename );
1872
1873     if (handle && is_fake_dll( handle ))
1874     {
1875         TRACE( "%s is a fake Wine dll\n", debugstr_w(filename) );
1876         NtClose( handle );
1877         handle = 0;
1878     }
1879
1880     switch(loadorder)
1881     {
1882     case LO_INVALID:
1883         nts = STATUS_NO_MEMORY;
1884         break;
1885     case LO_DISABLED:
1886         nts = STATUS_DLL_NOT_FOUND;
1887         break;
1888     case LO_NATIVE:
1889     case LO_NATIVE_BUILTIN:
1890         if (!handle) nts = STATUS_DLL_NOT_FOUND;
1891         else
1892         {
1893             nts = load_native_dll( load_path, filename, handle, flags, pwm );
1894             if (nts == STATUS_INVALID_FILE_FOR_SECTION)
1895                 /* not in PE format, maybe it's a builtin */
1896                 nts = load_builtin_dll( load_path, filename, handle, flags, pwm );
1897         }
1898         if (nts == STATUS_DLL_NOT_FOUND && loadorder == LO_NATIVE_BUILTIN)
1899             nts = load_builtin_dll( load_path, filename, 0, flags, pwm );
1900         break;
1901     case LO_BUILTIN:
1902     case LO_BUILTIN_NATIVE:
1903     case LO_DEFAULT:  /* default is builtin,native */
1904         nts = load_builtin_dll( load_path, filename, handle, flags, pwm );
1905         if (!handle) break;  /* nothing else we can try */
1906         /* file is not a builtin library, try without using the specified file */
1907         if (nts != STATUS_SUCCESS)
1908             nts = load_builtin_dll( load_path, filename, 0, flags, pwm );
1909         if (nts == STATUS_SUCCESS && loadorder == LO_DEFAULT &&
1910             (MODULE_InitDLL( *pwm, DLL_WINE_PREATTACH, NULL ) != STATUS_SUCCESS))
1911         {
1912             /* stub-only dll, try native */
1913             TRACE( "%s pre-attach returned FALSE, preferring native\n", debugstr_w(filename) );
1914             LdrUnloadDll( (*pwm)->ldr.BaseAddress );
1915             nts = STATUS_DLL_NOT_FOUND;
1916         }
1917         if (nts == STATUS_DLL_NOT_FOUND && loadorder != LO_BUILTIN)
1918             nts = load_native_dll( load_path, filename, handle, flags, pwm );
1919         break;
1920     }
1921
1922     if (nts == STATUS_SUCCESS)
1923     {
1924         /* Initialize DLL just loaded */
1925         TRACE("Loaded module %s (%s) at %p\n", debugstr_w(filename),
1926               ((*pwm)->ldr.Flags & LDR_WINE_INTERNAL) ? "builtin" : "native",
1927               (*pwm)->ldr.BaseAddress);
1928         if (handle) NtClose( handle );
1929         if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
1930         return nts;
1931     }
1932
1933     WARN("Failed to load module %s; status=%x\n", debugstr_w(libname), nts);
1934     if (handle) NtClose( handle );
1935     if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
1936     return nts;
1937 }
1938
1939 /******************************************************************
1940  *              LdrLoadDll (NTDLL.@)
1941  */
1942 NTSTATUS WINAPI LdrLoadDll(LPCWSTR path_name, DWORD flags,
1943                            const UNICODE_STRING *libname, HMODULE* hModule)
1944 {
1945     WINE_MODREF *wm;
1946     NTSTATUS nts;
1947
1948     RtlEnterCriticalSection( &loader_section );
1949
1950     if (!path_name) path_name = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
1951     nts = load_dll( path_name, libname->Buffer, flags, &wm );
1952
1953     if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
1954     {
1955         nts = process_attach( wm, NULL );
1956         if (nts != STATUS_SUCCESS)
1957         {
1958             LdrUnloadDll(wm->ldr.BaseAddress);
1959             wm = NULL;
1960         }
1961     }
1962     *hModule = (wm) ? wm->ldr.BaseAddress : NULL;
1963
1964     RtlLeaveCriticalSection( &loader_section );
1965     return nts;
1966 }
1967
1968
1969 /******************************************************************
1970  *              LdrGetDllHandle (NTDLL.@)
1971  */
1972 NTSTATUS WINAPI LdrGetDllHandle( LPCWSTR load_path, ULONG flags, const UNICODE_STRING *name, HMODULE *base )
1973 {
1974     NTSTATUS status;
1975     WCHAR buffer[128];
1976     WCHAR *filename;
1977     ULONG size;
1978     WINE_MODREF *wm;
1979
1980     RtlEnterCriticalSection( &loader_section );
1981
1982     if (!load_path) load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
1983
1984     filename = buffer;
1985     size = sizeof(buffer);
1986     for (;;)
1987     {
1988         status = find_dll_file( load_path, name->Buffer, filename, &size, &wm, NULL );
1989         if (filename != buffer) RtlFreeHeap( GetProcessHeap(), 0, filename );
1990         if (status != STATUS_BUFFER_TOO_SMALL) break;
1991         /* grow the buffer and retry */
1992         if (!(filename = RtlAllocateHeap( GetProcessHeap(), 0, size )))
1993         {
1994             status = STATUS_NO_MEMORY;
1995             break;
1996         }
1997     }
1998
1999     if (status == STATUS_SUCCESS)
2000     {
2001         if (wm) *base = wm->ldr.BaseAddress;
2002         else status = STATUS_DLL_NOT_FOUND;
2003     }
2004
2005     RtlLeaveCriticalSection( &loader_section );
2006     TRACE( "%s -> %p (load path %s)\n", debugstr_us(name), status ? NULL : *base, debugstr_w(load_path) );
2007     return status;
2008 }
2009
2010
2011 /******************************************************************
2012  *              LdrAddRefDll (NTDLL.@)
2013  */
2014 NTSTATUS WINAPI LdrAddRefDll( ULONG flags, HMODULE module )
2015 {
2016     NTSTATUS ret = STATUS_SUCCESS;
2017     WINE_MODREF *wm;
2018
2019     if (flags) FIXME( "%p flags %x not implemented\n", module, flags );
2020
2021     RtlEnterCriticalSection( &loader_section );
2022
2023     if ((wm = get_modref( module )))
2024     {
2025         if (wm->ldr.LoadCount != -1) wm->ldr.LoadCount++;
2026         TRACE( "(%s) ldr.LoadCount: %d\n", debugstr_w(wm->ldr.BaseDllName.Buffer), wm->ldr.LoadCount );
2027     }
2028     else ret = STATUS_INVALID_PARAMETER;
2029
2030     RtlLeaveCriticalSection( &loader_section );
2031     return ret;
2032 }
2033
2034
2035 /******************************************************************
2036  *              LdrQueryProcessModuleInformation
2037  *
2038  */
2039 NTSTATUS WINAPI LdrQueryProcessModuleInformation(PSYSTEM_MODULE_INFORMATION smi, 
2040                                                  ULONG buf_size, ULONG* req_size)
2041 {
2042     SYSTEM_MODULE*      sm = &smi->Modules[0];
2043     ULONG               size = sizeof(ULONG);
2044     NTSTATUS            nts = STATUS_SUCCESS;
2045     ANSI_STRING         str;
2046     char*               ptr;
2047     PLIST_ENTRY         mark, entry;
2048     PLDR_MODULE         mod;
2049     WORD id = 0;
2050
2051     smi->ModulesCount = 0;
2052
2053     RtlEnterCriticalSection( &loader_section );
2054     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
2055     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
2056     {
2057         mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
2058         size += sizeof(*sm);
2059         if (size <= buf_size)
2060         {
2061             sm->Reserved1 = 0; /* FIXME */
2062             sm->Reserved2 = 0; /* FIXME */
2063             sm->ImageBaseAddress = mod->BaseAddress;
2064             sm->ImageSize = mod->SizeOfImage;
2065             sm->Flags = mod->Flags;
2066             sm->Id = id++;
2067             sm->Rank = 0; /* FIXME */
2068             sm->Unknown = 0; /* FIXME */
2069             str.Length = 0;
2070             str.MaximumLength = MAXIMUM_FILENAME_LENGTH;
2071             str.Buffer = (char*)sm->Name;
2072             RtlUnicodeStringToAnsiString(&str, &mod->FullDllName, FALSE);
2073             ptr = strrchr(str.Buffer, '\\');
2074             sm->NameOffset = (ptr != NULL) ? (ptr - str.Buffer + 1) : 0;
2075
2076             smi->ModulesCount++;
2077             sm++;
2078         }
2079         else nts = STATUS_INFO_LENGTH_MISMATCH;
2080     }
2081     RtlLeaveCriticalSection( &loader_section );
2082
2083     if (req_size) *req_size = size;
2084
2085     return nts;
2086 }
2087
2088
2089 /******************************************************************
2090  *              RtlDllShutdownInProgress  (NTDLL.@)
2091  */
2092 BOOLEAN WINAPI RtlDllShutdownInProgress(void)
2093 {
2094     return process_detaching;
2095 }
2096
2097
2098 /******************************************************************
2099  *              LdrShutdownProcess (NTDLL.@)
2100  *
2101  */
2102 void WINAPI LdrShutdownProcess(void)
2103 {
2104     TRACE("()\n");
2105     process_detach( TRUE, (LPVOID)1 );
2106 }
2107
2108 /******************************************************************
2109  *              LdrShutdownThread (NTDLL.@)
2110  *
2111  */
2112 void WINAPI LdrShutdownThread(void)
2113 {
2114     PLIST_ENTRY mark, entry;
2115     PLDR_MODULE mod;
2116
2117     TRACE("()\n");
2118
2119     /* don't do any detach calls if process is exiting */
2120     if (process_detaching) return;
2121     /* FIXME: there is still a race here */
2122
2123     RtlEnterCriticalSection( &loader_section );
2124
2125     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
2126     for (entry = mark->Blink; entry != mark; entry = entry->Blink)
2127     {
2128         mod = CONTAINING_RECORD(entry, LDR_MODULE, 
2129                                 InInitializationOrderModuleList);
2130         if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
2131             continue;
2132         if ( mod->Flags & LDR_NO_DLL_CALLS )
2133             continue;
2134
2135         MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr), 
2136                         DLL_THREAD_DETACH, NULL );
2137     }
2138
2139     RtlLeaveCriticalSection( &loader_section );
2140     RtlFreeHeap( GetProcessHeap(), 0, NtCurrentTeb()->ThreadLocalStoragePointer );
2141 }
2142
2143
2144 /***********************************************************************
2145  *           free_modref
2146  *
2147  */
2148 static void free_modref( WINE_MODREF *wm )
2149 {
2150     RemoveEntryList(&wm->ldr.InLoadOrderModuleList);
2151     RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);
2152     if (wm->ldr.InInitializationOrderModuleList.Flink)
2153         RemoveEntryList(&wm->ldr.InInitializationOrderModuleList);
2154
2155     TRACE(" unloading %s\n", debugstr_w(wm->ldr.FullDllName.Buffer));
2156     if (!TRACE_ON(module))
2157         TRACE_(loaddll)("Unloaded module %s : %s\n",
2158                         debugstr_w(wm->ldr.FullDllName.Buffer),
2159                         (wm->ldr.Flags & LDR_WINE_INTERNAL) ? "builtin" : "native" );
2160
2161     SERVER_START_REQ( unload_dll )
2162     {
2163         req->base = wm->ldr.BaseAddress;
2164         wine_server_call( req );
2165     }
2166     SERVER_END_REQ;
2167
2168     RtlReleaseActivationContext( wm->ldr.ActivationContext );
2169     NtUnmapViewOfSection( NtCurrentProcess(), wm->ldr.BaseAddress );
2170     if (wm->ldr.Flags & LDR_WINE_INTERNAL) wine_dll_unload( wm->ldr.SectionHandle );
2171     if (cached_modref == wm) cached_modref = NULL;
2172     RtlFreeUnicodeString( &wm->ldr.FullDllName );
2173     RtlFreeHeap( GetProcessHeap(), 0, wm->deps );
2174     RtlFreeHeap( GetProcessHeap(), 0, wm );
2175 }
2176
2177 /***********************************************************************
2178  *           MODULE_FlushModrefs
2179  *
2180  * Remove all unused modrefs and call the internal unloading routines
2181  * for the library type.
2182  *
2183  * The loader_section must be locked while calling this function.
2184  */
2185 static void MODULE_FlushModrefs(void)
2186 {
2187     PLIST_ENTRY mark, entry, prev;
2188     PLDR_MODULE mod;
2189     WINE_MODREF*wm;
2190
2191     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
2192     for (entry = mark->Blink; entry != mark; entry = prev)
2193     {
2194         mod = CONTAINING_RECORD(entry, LDR_MODULE, InInitializationOrderModuleList);
2195         wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
2196         prev = entry->Blink;
2197         if (!mod->LoadCount) free_modref( wm );
2198     }
2199
2200     /* check load order list too for modules that haven't been initialized yet */
2201     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
2202     for (entry = mark->Blink; entry != mark; entry = prev)
2203     {
2204         mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
2205         wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
2206         prev = entry->Blink;
2207         if (!mod->LoadCount) free_modref( wm );
2208     }
2209 }
2210
2211 /***********************************************************************
2212  *           MODULE_DecRefCount
2213  *
2214  * The loader_section must be locked while calling this function.
2215  */
2216 static void MODULE_DecRefCount( WINE_MODREF *wm )
2217 {
2218     int i;
2219
2220     if ( wm->ldr.Flags & LDR_UNLOAD_IN_PROGRESS )
2221         return;
2222
2223     if ( wm->ldr.LoadCount <= 0 )
2224         return;
2225
2226     --wm->ldr.LoadCount;
2227     TRACE("(%s) ldr.LoadCount: %d\n", debugstr_w(wm->ldr.BaseDllName.Buffer), wm->ldr.LoadCount );
2228
2229     if ( wm->ldr.LoadCount == 0 )
2230     {
2231         wm->ldr.Flags |= LDR_UNLOAD_IN_PROGRESS;
2232
2233         for ( i = 0; i < wm->nDeps; i++ )
2234             if ( wm->deps[i] )
2235                 MODULE_DecRefCount( wm->deps[i] );
2236
2237         wm->ldr.Flags &= ~LDR_UNLOAD_IN_PROGRESS;
2238     }
2239 }
2240
2241 /******************************************************************
2242  *              LdrUnloadDll (NTDLL.@)
2243  *
2244  *
2245  */
2246 NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule )
2247 {
2248     NTSTATUS retv = STATUS_SUCCESS;
2249
2250     TRACE("(%p)\n", hModule);
2251
2252     RtlEnterCriticalSection( &loader_section );
2253
2254     /* if we're stopping the whole process (and forcing the removal of all
2255      * DLLs) the library will be freed anyway
2256      */
2257     if (!process_detaching)
2258     {
2259         WINE_MODREF *wm;
2260
2261         free_lib_count++;
2262         if ((wm = get_modref( hModule )) != NULL)
2263         {
2264             TRACE("(%s) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer));
2265
2266             /* Recursively decrement reference counts */
2267             MODULE_DecRefCount( wm );
2268
2269             /* Call process detach notifications */
2270             if ( free_lib_count <= 1 )
2271             {
2272                 process_detach( FALSE, NULL );
2273                 MODULE_FlushModrefs();
2274             }
2275
2276             TRACE("END\n");
2277         }
2278         else
2279             retv = STATUS_DLL_NOT_FOUND;
2280
2281         free_lib_count--;
2282     }
2283
2284     RtlLeaveCriticalSection( &loader_section );
2285
2286     return retv;
2287 }
2288
2289 /***********************************************************************
2290  *           RtlImageNtHeader   (NTDLL.@)
2291  */
2292 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
2293 {
2294     IMAGE_NT_HEADERS *ret;
2295
2296     __TRY
2297     {
2298         IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)hModule;
2299
2300         ret = NULL;
2301         if (dos->e_magic == IMAGE_DOS_SIGNATURE)
2302         {
2303             ret = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew);
2304             if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL;
2305         }
2306     }
2307     __EXCEPT_PAGE_FAULT
2308     {
2309         return NULL;
2310     }
2311     __ENDTRY
2312     return ret;
2313 }
2314
2315
2316 /******************************************************************
2317  *              LdrInitializeThunk (NTDLL.@)
2318  *
2319  */
2320 void WINAPI LdrInitializeThunk( ULONG unknown1, ULONG unknown2, ULONG unknown3, ULONG unknown4 )
2321 {
2322     NTSTATUS status;
2323     WINE_MODREF *wm;
2324     LPCWSTR load_path;
2325     PEB *peb = NtCurrentTeb()->Peb;
2326     IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress );
2327
2328     if (main_exe_file) NtClose( main_exe_file );  /* at this point the main module is created */
2329
2330     /* allocate the modref for the main exe (if not already done) */
2331     wm = get_modref( peb->ImageBaseAddress );
2332     assert( wm );
2333     if (wm->ldr.Flags & LDR_IMAGE_IS_DLL)
2334     {
2335         ERR("%s is a dll, not an executable\n", debugstr_w(wm->ldr.FullDllName.Buffer) );
2336         exit(1);
2337     }
2338
2339     peb->LoaderLock = &loader_section;
2340     peb->ProcessParameters->ImagePathName = wm->ldr.FullDllName;
2341     version_init( wm->ldr.FullDllName.Buffer );
2342
2343     /* the main exe needs to be the first in the load order list */
2344     RemoveEntryList( &wm->ldr.InLoadOrderModuleList );
2345     InsertHeadList( &peb->LdrData->InLoadOrderModuleList, &wm->ldr.InLoadOrderModuleList );
2346
2347     status = server_init_process_done();
2348     if (status != STATUS_SUCCESS) goto error;
2349
2350     actctx_init();
2351     load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
2352     if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS) goto error;
2353     if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto error;
2354     if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error;
2355
2356     pthread_functions.sigprocmask( SIG_UNBLOCK, &server_block_set, NULL );
2357
2358     RtlEnterCriticalSection( &loader_section );
2359
2360     if ((status = process_attach( wm, (LPVOID)1 )) != STATUS_SUCCESS)
2361     {
2362         if (last_failed_modref)
2363             ERR( "%s failed to initialize, aborting\n", debugstr_w(last_failed_modref->ldr.BaseDllName.Buffer) + 1 );
2364         goto error;
2365     }
2366     attach_implicitly_loaded_dlls( (LPVOID)1 );
2367
2368     RtlLeaveCriticalSection( &loader_section );
2369
2370     if (nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE) VIRTUAL_UseLargeAddressSpace();
2371     return;
2372
2373 error:
2374     ERR( "Main exe initialization for %s failed, status %x\n",
2375          debugstr_w(peb->ProcessParameters->ImagePathName.Buffer), status );
2376     NtTerminateProcess( GetCurrentProcess(), status );
2377 }
2378
2379
2380 /***********************************************************************
2381  *           RtlImageDirectoryEntryToData   (NTDLL.@)
2382  */
2383 PVOID WINAPI RtlImageDirectoryEntryToData( HMODULE module, BOOL image, WORD dir, ULONG *size )
2384 {
2385     const IMAGE_NT_HEADERS *nt;
2386     DWORD addr;
2387
2388     if ((ULONG_PTR)module & 1)  /* mapped as data file */
2389     {
2390         module = (HMODULE)((ULONG_PTR)module & ~1);
2391         image = FALSE;
2392     }
2393     if (!(nt = RtlImageNtHeader( module ))) return NULL;
2394     if (dir >= nt->OptionalHeader.NumberOfRvaAndSizes) return NULL;
2395     if (!(addr = nt->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;
2396     *size = nt->OptionalHeader.DataDirectory[dir].Size;
2397     if (image || addr < nt->OptionalHeader.SizeOfHeaders) return (char *)module + addr;
2398
2399     /* not mapped as image, need to find the section containing the virtual address */
2400     return RtlImageRvaToVa( nt, module, addr, NULL );
2401 }
2402
2403
2404 /***********************************************************************
2405  *           RtlImageRvaToSection   (NTDLL.@)
2406  */
2407 PIMAGE_SECTION_HEADER WINAPI RtlImageRvaToSection( const IMAGE_NT_HEADERS *nt,
2408                                                    HMODULE module, DWORD rva )
2409 {
2410     int i;
2411     const IMAGE_SECTION_HEADER *sec;
2412
2413     sec = (const IMAGE_SECTION_HEADER*)((const char*)&nt->OptionalHeader +
2414                                         nt->FileHeader.SizeOfOptionalHeader);
2415     for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
2416     {
2417         if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
2418             return (PIMAGE_SECTION_HEADER)sec;
2419     }
2420     return NULL;
2421 }
2422
2423
2424 /***********************************************************************
2425  *           RtlImageRvaToVa   (NTDLL.@)
2426  */
2427 PVOID WINAPI RtlImageRvaToVa( const IMAGE_NT_HEADERS *nt, HMODULE module,
2428                               DWORD rva, IMAGE_SECTION_HEADER **section )
2429 {
2430     IMAGE_SECTION_HEADER *sec;
2431
2432     if (section && *section)  /* try this section first */
2433     {
2434         sec = *section;
2435         if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
2436             goto found;
2437     }
2438     if (!(sec = RtlImageRvaToSection( nt, module, rva ))) return NULL;
2439  found:
2440     if (section) *section = sec;
2441     return (char *)module + sec->PointerToRawData + (rva - sec->VirtualAddress);
2442 }
2443
2444
2445 /***********************************************************************
2446  *           RtlPcToFileHeader   (NTDLL.@)
2447  */
2448 PVOID WINAPI RtlPcToFileHeader( PVOID pc, PVOID *address )
2449 {
2450     LDR_MODULE *module;
2451     PVOID ret = NULL;
2452
2453     RtlEnterCriticalSection( &loader_section );
2454     if (!LdrFindEntryForAddress( pc, &module )) ret = module->BaseAddress;
2455     RtlLeaveCriticalSection( &loader_section );
2456     *address = ret;
2457     return ret;
2458 }
2459
2460
2461 /***********************************************************************
2462  *           NtLoadDriver   (NTDLL.@)
2463  *           ZwLoadDriver   (NTDLL.@)
2464  */
2465 NTSTATUS WINAPI NtLoadDriver( const UNICODE_STRING *DriverServiceName )
2466 {
2467     FIXME("(%p), stub!\n",DriverServiceName);
2468     return STATUS_NOT_IMPLEMENTED;
2469 }
2470
2471
2472 /***********************************************************************
2473  *           NtUnloadDriver   (NTDLL.@)
2474  *           ZwUnloadDriver   (NTDLL.@)
2475  */
2476 NTSTATUS WINAPI NtUnloadDriver( const UNICODE_STRING *DriverServiceName )
2477 {
2478     FIXME("(%p), stub!\n",DriverServiceName);
2479     return STATUS_NOT_IMPLEMENTED;
2480 }
2481
2482
2483 /******************************************************************
2484  *              DllMain   (NTDLL.@)
2485  */
2486 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved )
2487 {
2488     if (reason == DLL_PROCESS_ATTACH) LdrDisableThreadCalloutsForDll( inst );
2489     return TRUE;
2490 }
2491
2492
2493 /******************************************************************
2494  *              __wine_init_windows_dir   (NTDLL.@)
2495  *
2496  * Windows and system dir initialization once kernel32 has been loaded.
2497  */
2498 void __wine_init_windows_dir( const WCHAR *windir, const WCHAR *sysdir )
2499 {
2500     PLIST_ENTRY mark, entry;
2501     LPWSTR buffer, p;
2502
2503     RtlCreateUnicodeString( &windows_dir, windir );
2504     RtlCreateUnicodeString( &system_dir, sysdir );
2505     strcpyW( user_shared_data->NtSystemRoot, windir );
2506
2507     /* prepend the system dir to the name of the already created modules */
2508     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
2509     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
2510     {
2511         LDR_MODULE *mod = CONTAINING_RECORD( entry, LDR_MODULE, InLoadOrderModuleList );
2512
2513         assert( mod->Flags & LDR_WINE_INTERNAL );
2514
2515         buffer = RtlAllocateHeap( GetProcessHeap(), 0,
2516                                   system_dir.Length + mod->FullDllName.Length + 2*sizeof(WCHAR) );
2517         if (!buffer) continue;
2518         strcpyW( buffer, system_dir.Buffer );
2519         p = buffer + strlenW( buffer );
2520         if (p > buffer && p[-1] != '\\') *p++ = '\\';
2521         strcpyW( p, mod->FullDllName.Buffer );
2522         RtlInitUnicodeString( &mod->FullDllName, buffer );
2523         RtlInitUnicodeString( &mod->BaseDllName, p );
2524     }
2525 }
2526
2527
2528 /***********************************************************************
2529  *           __wine_process_init
2530  */
2531 void __wine_process_init(void)
2532 {
2533     static const WCHAR kernel32W[] = {'k','e','r','n','e','l','3','2','.','d','l','l',0};
2534
2535     WINE_MODREF *wm;
2536     NTSTATUS status;
2537     ANSI_STRING func_name;
2538     void (* DECLSPEC_NORETURN init_func)(void);
2539     extern mode_t FILE_umask;
2540
2541     main_exe_file = thread_init();
2542
2543     /* retrieve current umask */
2544     FILE_umask = umask(0777);
2545     umask( FILE_umask );
2546
2547     /* setup the load callback and create ntdll modref */
2548     wine_dll_set_callback( load_builtin_callback );
2549
2550     if ((status = load_builtin_dll( NULL, kernel32W, 0, 0, &wm )) != STATUS_SUCCESS)
2551     {
2552         MESSAGE( "wine: could not load kernel32.dll, status %x\n", status );
2553         exit(1);
2554     }
2555     RtlInitAnsiString( &func_name, "UnhandledExceptionFilter" );
2556     LdrGetProcedureAddress( wm->ldr.BaseAddress, &func_name, 0, (void **)&unhandled_exception_filter );
2557
2558     RtlInitAnsiString( &func_name, "__wine_kernel_init" );
2559     if ((status = LdrGetProcedureAddress( wm->ldr.BaseAddress, &func_name,
2560                                           0, (void **)&init_func )) != STATUS_SUCCESS)
2561     {
2562         MESSAGE( "wine: could not find __wine_kernel_init in kernel32.dll, status %x\n", status );
2563         exit(1);
2564     }
2565     init_func();
2566 }