DXTn stride is to the next block, which is the equivalent to 4 rows
[wine] / dlls / ntdll / loader.c
1 /*
2  * Loader functions
3  *
4  * Copyright 1995, 2003 Alexandre Julliard
5  * Copyright 2002 Dmitry Timoshkov for CodeWeavers
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <assert.h>
23 #include <stdarg.h>
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winnt.h"
28 #include "winreg.h"
29 #include "winternl.h"
30
31 #include "module.h"
32 #include "file.h"
33 #include "wine/exception.h"
34 #include "excpt.h"
35 #include "wine/unicode.h"
36 #include "wine/debug.h"
37 #include "wine/server.h"
38 #include "ntdll_misc.h"
39
40 WINE_DEFAULT_DEBUG_CHANNEL(module);
41 WINE_DECLARE_DEBUG_CHANNEL(relay);
42 WINE_DECLARE_DEBUG_CHANNEL(snoop);
43 WINE_DECLARE_DEBUG_CHANNEL(loaddll);
44
45 typedef DWORD (CALLBACK *DLLENTRYPROC)(HMODULE,DWORD,LPVOID);
46
47 static int process_detaching = 0;  /* set on process detach to avoid deadlocks with thread detach */
48 static int free_lib_count;   /* recursion depth of LdrUnloadDll calls */
49
50 /* filter for page-fault exceptions */
51 static WINE_EXCEPTION_FILTER(page_fault)
52 {
53     if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
54         return EXCEPTION_EXECUTE_HANDLER;
55     return EXCEPTION_CONTINUE_SEARCH;
56 }
57
58 static const char * const reason_names[] =
59 {
60     "PROCESS_DETACH",
61     "PROCESS_ATTACH",
62     "THREAD_ATTACH",
63     "THREAD_DETACH"
64 };
65
66 static const WCHAR dllW[] = {'.','d','l','l',0};
67
68 /* internal representation of 32bit modules. per process. */
69 typedef struct _wine_modref
70 {
71     LDR_MODULE            ldr;
72     int                   nDeps;
73     struct _wine_modref **deps;
74 } WINE_MODREF;
75
76 static UINT tls_module_count;      /* number of modules with TLS directory */
77 static UINT tls_total_size;        /* total size of TLS storage */
78 static const IMAGE_TLS_DIRECTORY **tls_dirs;  /* array of TLS directories */
79
80 static CRITICAL_SECTION loader_section;
81 static CRITICAL_SECTION_DEBUG critsect_debug =
82 {
83     0, 0, &loader_section,
84     { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
85       0, 0, { 0, (DWORD)(__FILE__ ": loader_section") }
86 };
87 static CRITICAL_SECTION loader_section = { &critsect_debug, -1, 0, 0, 0, 0 };
88
89 static WINE_MODREF *cached_modref;
90 static WINE_MODREF *current_modref;
91 static NTSTATUS last_builtin_status; /* use to gather all errors in callback */
92 static const WCHAR *current_load_path;
93
94 static NTSTATUS load_dll( LPCWSTR libname, DWORD flags, WINE_MODREF** pwm );
95 static FARPROC find_named_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
96                                   DWORD exp_size, const char *name, int hint );
97
98 /* convert PE image VirtualAddress to Real Address */
99 inline static void *get_rva( HMODULE module, DWORD va )
100 {
101     return (void *)((char *)module + va);
102 }
103
104 /* check whether the file name contains a path */
105 inline static int contains_path( LPCWSTR name )
106 {
107     return ((*name && (name[1] == ':')) || strchrW(name, '/') || strchrW(name, '\\'));
108 }
109
110 /* convert from straight ASCII to Unicode without depending on the current codepage */
111 inline static void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )
112 {
113     while (len--) *dst++ = (unsigned char)*src++;
114 }
115
116 /*************************************************************************
117  *              get_modref
118  *
119  * Looks for the referenced HMODULE in the current process
120  * The loader_section must be locked while calling this function.
121  */
122 static WINE_MODREF *get_modref( HMODULE hmod )
123 {
124     PLIST_ENTRY mark, entry;
125     PLDR_MODULE mod;
126
127     if (cached_modref && cached_modref->ldr.BaseAddress == hmod) return cached_modref;
128
129     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
130     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
131     {
132         mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
133         if (mod->BaseAddress == hmod)
134             return cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
135         if (mod->BaseAddress > (void*)hmod) break;
136     }
137     return NULL;
138 }
139
140
141 /**********************************************************************
142  *          find_module
143  *
144  * Find a (loaded) win32 module depending on path
145  *     path: [in] pathname of module/library to be found
146  *
147  * The loader_section must be locked while calling this function
148  * RETURNS
149  *      the module handle if found
150  *      0 if not
151  */
152 static WINE_MODREF *find_module( LPCWSTR path )
153 {
154     WINE_MODREF *wm;
155     PLIST_ENTRY mark, entry;
156     PLDR_MODULE mod;
157     WCHAR dllname[260], *p;
158
159     /* Append .DLL to name if no extension present */
160     strcpyW( dllname, path );
161     if (!(p = strrchrW( dllname, '.')) || strchrW( p, '/' ) || strchrW( p, '\\'))
162         strcatW( dllname, dllW );
163
164     if ((wm = cached_modref) != NULL)
165     {
166         if ( !strcmpiW( dllname, wm->ldr.BaseDllName.Buffer ) ) return wm;
167         if ( !strcmpiW( dllname, wm->ldr.FullDllName.Buffer ) ) return wm;
168     }
169
170     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
171     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
172     {
173         mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
174         wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
175
176         if ( !strcmpiW( dllname, wm->ldr.BaseDllName.Buffer ) ) break;
177         if ( !strcmpiW( dllname, wm->ldr.FullDllName.Buffer ) ) break;
178     }
179     if (entry == mark) wm = NULL;
180
181     cached_modref = wm;
182     return wm;
183 }
184
185
186 /*************************************************************************
187  *              find_forwarded_export
188  *
189  * Find the final function pointer for a forwarded function.
190  * The loader_section must be locked while calling this function.
191  */
192 static FARPROC find_forwarded_export( HMODULE module, const char *forward )
193 {
194     IMAGE_EXPORT_DIRECTORY *exports;
195     DWORD exp_size;
196     WINE_MODREF *wm;
197     WCHAR mod_name[256];
198     char *end = strchr(forward, '.');
199     FARPROC proc = NULL;
200
201     if (!end) return NULL;
202     if (end - forward >= sizeof(mod_name)/sizeof(WCHAR)) return NULL;
203     ascii_to_unicode( mod_name, forward, end - forward );
204     mod_name[end - forward] = 0;
205
206     if (!(wm = find_module( mod_name )))
207     {
208         ERR("module not found for forward '%s' used by %s\n",
209             forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer) );
210         return NULL;
211     }
212     if ((exports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
213                                                  IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
214         proc = find_named_export( wm->ldr.BaseAddress, exports, exp_size, end + 1, -1 );
215
216     if (!proc)
217     {
218         ERR("function not found for forward '%s' used by %s."
219             " If you are using builtin %s, try using the native one instead.\n",
220             forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer),
221             debugstr_w(get_modref(module)->ldr.BaseDllName.Buffer) );
222     }
223     return proc;
224 }
225
226
227 /*************************************************************************
228  *              find_ordinal_export
229  *
230  * Find an exported function by ordinal.
231  * The exports base must have been subtracted from the ordinal already.
232  * The loader_section must be locked while calling this function.
233  */
234 static FARPROC find_ordinal_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
235                                     DWORD exp_size, int ordinal )
236 {
237     FARPROC proc;
238     DWORD *functions = get_rva( module, exports->AddressOfFunctions );
239
240     if (ordinal >= exports->NumberOfFunctions)
241     {
242         TRACE(" ordinal %ld out of range!\n", ordinal + exports->Base );
243         return NULL;
244     }
245     if (!functions[ordinal]) return NULL;
246
247     proc = get_rva( module, functions[ordinal] );
248
249     /* if the address falls into the export dir, it's a forward */
250     if (((char *)proc >= (char *)exports) && ((char *)proc < (char *)exports + exp_size))
251         return find_forwarded_export( module, (char *)proc );
252
253     if (TRACE_ON(snoop))
254     {
255         proc = SNOOP_GetProcAddress( module, exports, exp_size, proc, ordinal );
256     }
257     if (TRACE_ON(relay) && current_modref)
258     {
259         proc = RELAY_GetProcAddress( module, exports, exp_size, proc,
260                                      current_modref->ldr.BaseDllName.Buffer );
261     }
262     return proc;
263 }
264
265
266 /*************************************************************************
267  *              find_named_export
268  *
269  * Find an exported function by name.
270  * The loader_section must be locked while calling this function.
271  */
272 static FARPROC find_named_export( HMODULE module, IMAGE_EXPORT_DIRECTORY *exports,
273                                   DWORD exp_size, const char *name, int hint )
274 {
275     WORD *ordinals = get_rva( module, exports->AddressOfNameOrdinals );
276     DWORD *names = get_rva( module, exports->AddressOfNames );
277     int min = 0, max = exports->NumberOfNames - 1;
278
279     /* first check the hint */
280     if (hint >= 0 && hint <= max)
281     {
282         char *ename = get_rva( module, names[hint] );
283         if (!strcmp( ename, name ))
284             return find_ordinal_export( module, exports, exp_size, ordinals[hint] );
285     }
286
287     /* then do a binary search */
288     while (min <= max)
289     {
290         int res, pos = (min + max) / 2;
291         char *ename = get_rva( module, names[pos] );
292         if (!(res = strcmp( ename, name )))
293             return find_ordinal_export( module, exports, exp_size, ordinals[pos] );
294         if (res > 0) max = pos - 1;
295         else min = pos + 1;
296     }
297     return NULL;
298
299 }
300
301
302 /*************************************************************************
303  *              import_dll
304  *
305  * Import the dll specified by the given import descriptor.
306  * The loader_section must be locked while calling this function.
307  */
308 static WINE_MODREF *import_dll( HMODULE module, IMAGE_IMPORT_DESCRIPTOR *descr )
309 {
310     NTSTATUS status;
311     WINE_MODREF *wmImp;
312     HMODULE imp_mod;
313     IMAGE_EXPORT_DIRECTORY *exports;
314     DWORD exp_size;
315     IMAGE_THUNK_DATA *import_list, *thunk_list;
316     WCHAR buffer[32];
317     char *name = get_rva( module, descr->Name );
318     DWORD len = strlen(name) + 1;
319
320     if (len * sizeof(WCHAR) <= sizeof(buffer))
321     {
322         ascii_to_unicode( buffer, name, len );
323         status = load_dll( buffer, 0, &wmImp );
324     }
325     else  /* need to allocate a larger buffer */
326     {
327         WCHAR *ptr = RtlAllocateHeap( GetProcessHeap(), 0, len * sizeof(WCHAR) );
328         if (!ptr) return NULL;
329         ascii_to_unicode( ptr, name, len );
330         status = load_dll( ptr, 0, &wmImp );
331         RtlFreeHeap( GetProcessHeap(), 0, ptr );
332     }
333
334     if (status)
335     {
336         if (status == STATUS_DLL_NOT_FOUND)
337             ERR("Module (file) %s (which is needed by %s) not found\n",
338                 name, debugstr_w(current_modref->ldr.FullDllName.Buffer));
339         else
340             ERR("Loading module (file) %s (which is needed by %s) failed (error %lx).\n",
341                 name, debugstr_w(current_modref->ldr.FullDllName.Buffer), status);
342         return NULL;
343     }
344
345     imp_mod = wmImp->ldr.BaseAddress;
346     if (!(exports = RtlImageDirectoryEntryToData( imp_mod, TRUE,
347                                                   IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
348         return NULL;
349
350     thunk_list = get_rva( module, (DWORD)descr->FirstThunk );
351     if (descr->u.OriginalFirstThunk)
352         import_list = get_rva( module, (DWORD)descr->u.OriginalFirstThunk );
353     else
354         import_list = thunk_list;
355
356     while (import_list->u1.Ordinal)
357     {
358         if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))
359         {
360             int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
361
362             TRACE("--- Ordinal %s,%d\n", name, ordinal);
363             thunk_list->u1.Function = (PDWORD)find_ordinal_export( imp_mod, exports, exp_size,
364                                                                    ordinal - exports->Base );
365             if (!thunk_list->u1.Function)
366             {
367                 ERR("No implementation for %s.%d imported from %s, setting to 0xdeadbeef\n",
368                     name, ordinal, debugstr_w(current_modref->ldr.FullDllName.Buffer) );
369                 thunk_list->u1.Function = (PDWORD)0xdeadbeef;
370             }
371         }
372         else  /* import by name */
373         {
374             IMAGE_IMPORT_BY_NAME *pe_name;
375             pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );
376             TRACE("--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint);
377             thunk_list->u1.Function = (PDWORD)find_named_export( imp_mod, exports, exp_size,
378                                                                  pe_name->Name, pe_name->Hint );
379             if (!thunk_list->u1.Function)
380             {
381                 ERR("No implementation for %s.%s imported from %s, setting to 0xdeadbeef\n",
382                     name, pe_name->Name, debugstr_w(current_modref->ldr.FullDllName.Buffer) );
383                 thunk_list->u1.Function = (PDWORD)0xdeadbeef;
384             }
385         }
386         import_list++;
387         thunk_list++;
388     }
389     return wmImp;
390 }
391
392
393 /****************************************************************
394  *       fixup_imports
395  *
396  * Fixup all imports of a given module.
397  * The loader_section must be locked while calling this function.
398  */
399 static NTSTATUS fixup_imports( WINE_MODREF *wm )
400 {
401     int i, nb_imports;
402     IMAGE_IMPORT_DESCRIPTOR *imports;
403     WINE_MODREF *prev;
404     DWORD size;
405
406     if (!(imports = RtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,
407                                                   IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))
408         return STATUS_SUCCESS;
409
410     nb_imports = size / sizeof(*imports);
411     for (i = 0; i < nb_imports; i++)
412     {
413         if (!imports[i].Name)
414         {
415             nb_imports = i;
416             break;
417         }
418     }
419     if (!nb_imports) return STATUS_SUCCESS;  /* no imports */
420
421     /* Allocate module dependency list */
422     wm->nDeps = nb_imports;
423     wm->deps  = RtlAllocateHeap( ntdll_get_process_heap(), 0, nb_imports*sizeof(WINE_MODREF *) );
424
425     /* load the imported modules. They are automatically
426      * added to the modref list of the process.
427      */
428     prev = current_modref;
429     current_modref = wm;
430     for (i = 0; i < nb_imports; i++)
431     {
432         if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i] ))) break;
433     }
434     current_modref = prev;
435     if (i < nb_imports) return STATUS_DLL_NOT_FOUND;
436     return STATUS_SUCCESS;
437 }
438
439
440 /*************************************************************************
441  *              alloc_module
442  *
443  * Allocate a WINE_MODREF structure and add it to the process list
444  * The loader_section must be locked while calling this function.
445  */
446 static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )
447 {
448     WINE_MODREF *wm;
449     WCHAR *p;
450     IMAGE_NT_HEADERS *nt = RtlImageNtHeader(hModule);
451     PLIST_ENTRY entry, mark;
452     BOOLEAN linked = FALSE;
453     DWORD len;
454
455     RtlUnicodeToMultiByteSize( &len, filename, (strlenW(filename) + 1) * sizeof(WCHAR) );
456     if (!(wm = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(*wm) + len )))
457         return NULL;
458
459     wm->nDeps    = 0;
460     wm->deps     = NULL;
461
462     wm->ldr.BaseAddress   = hModule;
463     wm->ldr.EntryPoint    = (nt->OptionalHeader.AddressOfEntryPoint) ?
464                             ((char *)hModule + nt->OptionalHeader.AddressOfEntryPoint) : 0;
465     wm->ldr.SizeOfImage   = nt->OptionalHeader.SizeOfImage;
466     wm->ldr.Flags         = 0;
467     wm->ldr.LoadCount     = 0;
468     wm->ldr.TlsIndex      = -1;
469     wm->ldr.SectionHandle = NULL;
470     wm->ldr.CheckSum      = 0;
471     wm->ldr.TimeDateStamp = 0;
472
473     RtlCreateUnicodeString( &wm->ldr.FullDllName, filename );
474     if ((p = strrchrW( wm->ldr.FullDllName.Buffer, '\\' ))) p++;
475     else p = wm->ldr.FullDllName.Buffer;
476     RtlInitUnicodeString( &wm->ldr.BaseDllName, p );
477
478     /* this is a bit ugly, but we need to have app module first in LoadOrder
479      * list, But in wine, ntdll is loaded first, so by inserting DLLs at the tail
480      * and app module at the head we insure that order
481      */
482     if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
483     {
484         /* is first loaded module a DLL or an exec ? */
485         mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
486         if (mark->Flink == mark ||
487             (CONTAINING_RECORD(mark->Flink, LDR_MODULE, InLoadOrderModuleList)->Flags & LDR_IMAGE_IS_DLL))
488         {
489             InsertHeadList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
490                            &wm->ldr.InLoadOrderModuleList);
491             linked = TRUE;
492         }
493     }
494     else wm->ldr.Flags |= LDR_IMAGE_IS_DLL;
495
496     if (!linked)
497         InsertTailList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,
498                        &wm->ldr.InLoadOrderModuleList);
499
500     /* insert module in MemoryList, sorted in increasing base addresses */
501     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
502     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
503     {
504         if (CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList)->BaseAddress > wm->ldr.BaseAddress)
505             break;
506     }
507     entry->Blink->Flink = &wm->ldr.InMemoryOrderModuleList;
508     wm->ldr.InMemoryOrderModuleList.Blink = entry->Blink;
509     wm->ldr.InMemoryOrderModuleList.Flink = entry;
510     entry->Blink = &wm->ldr.InMemoryOrderModuleList;
511
512     /* wait until init is called for inserting into this list */
513     wm->ldr.InInitializationOrderModuleList.Flink = NULL;
514     wm->ldr.InInitializationOrderModuleList.Blink = NULL;
515     return wm;
516 }
517
518
519 /*************************************************************************
520  *              alloc_process_tls
521  *
522  * Allocate the process-wide structure for module TLS storage.
523  */
524 static NTSTATUS alloc_process_tls(void)
525 {
526     PLIST_ENTRY mark, entry;
527     PLDR_MODULE mod;
528     IMAGE_TLS_DIRECTORY *dir;
529     ULONG size, i;
530
531     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
532     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
533     {
534         mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
535         if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE,
536                                                   IMAGE_DIRECTORY_ENTRY_TLS, &size )))
537             continue;
538         size = (dir->EndAddressOfRawData - dir->StartAddressOfRawData) + dir->SizeOfZeroFill;
539         if (!size) continue;
540         tls_total_size += size;
541         tls_module_count++;
542     }
543     if (!tls_module_count) return STATUS_SUCCESS;
544
545     TRACE( "count %u size %u\n", tls_module_count, tls_total_size );
546
547     tls_dirs = RtlAllocateHeap( ntdll_get_process_heap(), 0, tls_module_count * sizeof(*tls_dirs) );
548     if (!tls_dirs) return STATUS_NO_MEMORY;
549
550     for (i = 0, entry = mark->Flink; entry != mark; entry = entry->Flink)
551     {
552         mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
553         if (!(dir = RtlImageDirectoryEntryToData( mod->BaseAddress, TRUE,
554                                                   IMAGE_DIRECTORY_ENTRY_TLS, &size )))
555             continue;
556         tls_dirs[i] = dir;
557         *dir->AddressOfIndex = i;
558         mod->TlsIndex = i;
559         mod->LoadCount = -1;  /* can't unload it */
560         i++;
561     }
562     return STATUS_SUCCESS;
563 }
564
565
566 /*************************************************************************
567  *              alloc_thread_tls
568  *
569  * Allocate the per-thread structure for module TLS storage.
570  */
571 static NTSTATUS alloc_thread_tls(void)
572 {
573     void **pointers;
574     char *data;
575     UINT i;
576
577     if (!tls_module_count) return STATUS_SUCCESS;
578
579     if (!(pointers = RtlAllocateHeap( ntdll_get_process_heap(), 0,
580                                       tls_module_count * sizeof(*pointers) )))
581         return STATUS_NO_MEMORY;
582
583     if (!(data = RtlAllocateHeap( ntdll_get_process_heap(), 0, tls_total_size )))
584     {
585         RtlFreeHeap( ntdll_get_process_heap(), 0, pointers );
586         return STATUS_NO_MEMORY;
587     }
588
589     for (i = 0; i < tls_module_count; i++)
590     {
591         const IMAGE_TLS_DIRECTORY *dir = tls_dirs[i];
592         ULONG size = dir->EndAddressOfRawData - dir->StartAddressOfRawData;
593
594         TRACE( "thread %04lx idx %d: %ld/%ld bytes from %p to %p\n",
595                GetCurrentThreadId(), i, size, dir->SizeOfZeroFill,
596                (void *)dir->StartAddressOfRawData, data );
597
598         pointers[i] = data;
599         memcpy( data, (void *)dir->StartAddressOfRawData, size );
600         data += size;
601         memset( data, 0, dir->SizeOfZeroFill );
602         data += dir->SizeOfZeroFill;
603     }
604     NtCurrentTeb()->ThreadLocalStoragePointer = pointers;
605     return STATUS_SUCCESS;
606 }
607
608
609 /*************************************************************************
610  *              call_tls_callbacks
611  */
612 static void call_tls_callbacks( HMODULE module, UINT reason )
613 {
614     const IMAGE_TLS_DIRECTORY *dir;
615     const PIMAGE_TLS_CALLBACK *callback;
616     ULONG dirsize;
617
618     dir = RtlImageDirectoryEntryToData( module, TRUE, IMAGE_DIRECTORY_ENTRY_TLS, &dirsize );
619     if (!dir || !dir->AddressOfCallBacks) return;
620
621     for (callback = dir->AddressOfCallBacks; *callback; callback++)
622     {
623         if (TRACE_ON(relay))
624             DPRINTF("%04lx:Call TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
625                     GetCurrentThreadId(), *callback, module, reason_names[reason] );
626         (*callback)( module, reason, NULL );
627         if (TRACE_ON(relay))
628             DPRINTF("%04lx:Ret  TLS callback (proc=%p,module=%p,reason=%s,reserved=0)\n",
629                     GetCurrentThreadId(), *callback, module, reason_names[reason] );
630     }
631 }
632
633
634 /*************************************************************************
635  *              MODULE_InitDLL
636  */
637 static BOOL MODULE_InitDLL( WINE_MODREF *wm, UINT reason, LPVOID lpReserved )
638 {
639     WCHAR mod_name[32];
640     BOOL retv = TRUE;
641     DLLENTRYPROC entry = wm->ldr.EntryPoint;
642     void *module = wm->ldr.BaseAddress;
643
644     /* Skip calls for modules loaded with special load flags */
645
646     if (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS) return TRUE;
647     if (wm->ldr.TlsIndex != -1) call_tls_callbacks( wm->ldr.BaseAddress, reason );
648     if (!entry || !(wm->ldr.Flags & LDR_IMAGE_IS_DLL)) return TRUE;
649
650     if (TRACE_ON(relay))
651     {
652         size_t len = max( wm->ldr.BaseDllName.Length, sizeof(mod_name)-sizeof(WCHAR) );
653         memcpy( mod_name, wm->ldr.BaseDllName.Buffer, len );
654         mod_name[len / sizeof(WCHAR)] = 0;
655         DPRINTF("%04lx:Call PE DLL (proc=%p,module=%p %s,reason=%s,res=%p)\n",
656                 GetCurrentThreadId(), entry, module, debugstr_w(mod_name),
657                 reason_names[reason], lpReserved );
658     }
659     else TRACE("(%p %s,%s,%p) - CALL\n", module, debugstr_w(wm->ldr.BaseDllName.Buffer),
660                reason_names[reason], lpReserved );
661
662     retv = entry( module, reason, lpReserved );
663
664     /* The state of the module list may have changed due to the call
665        to the dll. We cannot assume that this module has not been
666        deleted.  */
667     if (TRACE_ON(relay))
668         DPRINTF("%04lx:Ret  PE DLL (proc=%p,module=%p %s,reason=%s,res=%p) retval=%x\n",
669                 GetCurrentThreadId(), entry, module, debugstr_w(mod_name),
670                 reason_names[reason], lpReserved, retv );
671     else TRACE("(%p,%s,%p) - RETURN %d\n", module, reason_names[reason], lpReserved, retv );
672
673     return retv;
674 }
675
676
677 /*************************************************************************
678  *              process_attach
679  *
680  * Send the process attach notification to all DLLs the given module
681  * depends on (recursively). This is somewhat complicated due to the fact that
682  *
683  * - we have to respect the module dependencies, i.e. modules implicitly
684  *   referenced by another module have to be initialized before the module
685  *   itself can be initialized
686  *
687  * - the initialization routine of a DLL can itself call LoadLibrary,
688  *   thereby introducing a whole new set of dependencies (even involving
689  *   the 'old' modules) at any time during the whole process
690  *
691  * (Note that this routine can be recursively entered not only directly
692  *  from itself, but also via LoadLibrary from one of the called initialization
693  *  routines.)
694  *
695  * Furthermore, we need to rearrange the main WINE_MODREF list to allow
696  * the process *detach* notifications to be sent in the correct order.
697  * This must not only take into account module dependencies, but also
698  * 'hidden' dependencies created by modules calling LoadLibrary in their
699  * attach notification routine.
700  *
701  * The strategy is rather simple: we move a WINE_MODREF to the head of the
702  * list after the attach notification has returned.  This implies that the
703  * detach notifications are called in the reverse of the sequence the attach
704  * notifications *returned*.
705  *
706  * The loader_section must be locked while calling this function.
707  */
708 static NTSTATUS process_attach( WINE_MODREF *wm, LPVOID lpReserved )
709 {
710     NTSTATUS status = STATUS_SUCCESS;
711     int i;
712
713     /* prevent infinite recursion in case of cyclical dependencies */
714     if (    ( wm->ldr.Flags & LDR_LOAD_IN_PROGRESS )
715          || ( wm->ldr.Flags & LDR_PROCESS_ATTACHED ) )
716         return status;
717
718     TRACE("(%s,%p) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved );
719
720     /* Tag current MODREF to prevent recursive loop */
721     wm->ldr.Flags |= LDR_LOAD_IN_PROGRESS;
722
723     /* Recursively attach all DLLs this one depends on */
724     for ( i = 0; i < wm->nDeps; i++ )
725     {
726         if (!wm->deps[i]) continue;
727         if ((status = process_attach( wm->deps[i], lpReserved )) != STATUS_SUCCESS) break;
728     }
729
730     /* Call DLL entry point */
731     if (status == STATUS_SUCCESS)
732     {
733         WINE_MODREF *prev = current_modref;
734         current_modref = wm;
735         if (MODULE_InitDLL( wm, DLL_PROCESS_ATTACH, lpReserved ))
736             wm->ldr.Flags |= LDR_PROCESS_ATTACHED;
737         else
738             status = STATUS_DLL_INIT_FAILED;
739         current_modref = prev;
740     }
741
742     InsertTailList(&NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList, 
743                    &wm->ldr.InInitializationOrderModuleList);
744
745     /* Remove recursion flag */
746     wm->ldr.Flags &= ~LDR_LOAD_IN_PROGRESS;
747
748     TRACE("(%s,%p) - END\n", debugstr_w(wm->ldr.BaseDllName.Buffer), lpReserved );
749     return status;
750 }
751
752 /*************************************************************************
753  *              process_detach
754  *
755  * Send DLL process detach notifications.  See the comment about calling
756  * sequence at process_attach.  Unless the bForceDetach flag
757  * is set, only DLLs with zero refcount are notified.
758  */
759 static void process_detach( BOOL bForceDetach, LPVOID lpReserved )
760 {
761     PLIST_ENTRY mark, entry;
762     PLDR_MODULE mod;
763
764     RtlEnterCriticalSection( &loader_section );
765     if (bForceDetach) process_detaching = 1;
766     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
767     do
768     {
769         for (entry = mark->Blink; entry != mark; entry = entry->Blink)
770         {
771             mod = CONTAINING_RECORD(entry, LDR_MODULE, 
772                                     InInitializationOrderModuleList);
773             /* Check whether to detach this DLL */
774             if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
775                 continue;
776             if ( mod->LoadCount && !bForceDetach )
777                 continue;
778
779             /* Call detach notification */
780             mod->Flags &= ~LDR_PROCESS_ATTACHED;
781             MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr), 
782                             DLL_PROCESS_DETACH, lpReserved );
783
784             /* Restart at head of WINE_MODREF list, as entries might have
785                been added and/or removed while performing the call ... */
786             break;
787         }
788     } while (entry != mark);
789
790     RtlLeaveCriticalSection( &loader_section );
791 }
792
793 /*************************************************************************
794  *              MODULE_DllThreadAttach
795  *
796  * Send DLL thread attach notifications. These are sent in the
797  * reverse sequence of process detach notification.
798  *
799  */
800 NTSTATUS MODULE_DllThreadAttach( LPVOID lpReserved )
801 {
802     PLIST_ENTRY mark, entry;
803     PLDR_MODULE mod;
804     NTSTATUS    status;
805
806     /* don't do any attach calls if process is exiting */
807     if (process_detaching) return STATUS_SUCCESS;
808     /* FIXME: there is still a race here */
809
810     RtlEnterCriticalSection( &loader_section );
811
812     if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto done;
813
814     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
815     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
816     {
817         mod = CONTAINING_RECORD(entry, LDR_MODULE, 
818                                 InInitializationOrderModuleList);
819         if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
820             continue;
821         if ( mod->Flags & LDR_NO_DLL_CALLS )
822             continue;
823
824         MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr),
825                         DLL_THREAD_ATTACH, lpReserved );
826     }
827
828 done:
829     RtlLeaveCriticalSection( &loader_section );
830     return status;
831 }
832
833 /******************************************************************
834  *              LdrDisableThreadCalloutsForDll (NTDLL.@)
835  *
836  */
837 NTSTATUS WINAPI LdrDisableThreadCalloutsForDll(HMODULE hModule)
838 {
839     WINE_MODREF *wm;
840     NTSTATUS    ret = STATUS_SUCCESS;
841
842     RtlEnterCriticalSection( &loader_section );
843
844     wm = get_modref( hModule );
845     if (!wm || wm->ldr.TlsIndex != -1)
846         ret = STATUS_DLL_NOT_FOUND;
847     else
848         wm->ldr.Flags |= LDR_NO_DLL_CALLS;
849
850     RtlLeaveCriticalSection( &loader_section );
851
852     return ret;
853 }
854
855 /******************************************************************
856  *              LdrFindEntryForAddress (NTDLL.@)
857  *
858  * The loader_section must be locked while calling this function
859  */
860 NTSTATUS WINAPI LdrFindEntryForAddress(const void* addr, PLDR_MODULE* pmod)
861 {
862     PLIST_ENTRY mark, entry;
863     PLDR_MODULE mod;
864
865     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;
866     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
867     {
868         mod = CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList);
869         if ((const void *)mod->BaseAddress <= addr &&
870             (char *)addr < (char*)mod->BaseAddress + mod->SizeOfImage)
871         {
872             *pmod = mod;
873             return STATUS_SUCCESS;
874         }
875         if ((const void *)mod->BaseAddress > addr) break;
876     }
877     return STATUS_NO_MORE_ENTRIES;
878 }
879
880 /******************************************************************
881  *              LdrLockLoaderLock  (NTDLL.@)
882  *
883  * Note: flags are not implemented.
884  * Flag 0x01 is used to raise exceptions on errors.
885  * Flag 0x02 is used to avoid waiting on the section (does RtlTryEnterCriticalSection instead).
886  */
887 NTSTATUS WINAPI LdrLockLoaderLock( ULONG flags, ULONG *result, ULONG *magic )
888 {
889     if (flags) FIXME( "flags %lx not supported\n", flags );
890
891     if (result) *result = 1;
892     if (!magic) return STATUS_INVALID_PARAMETER_3;
893     RtlEnterCriticalSection( &loader_section );
894     *magic = GetCurrentThreadId();
895     return STATUS_SUCCESS;
896 }
897
898
899 /******************************************************************
900  *              LdrUnlockLoaderUnlock  (NTDLL.@)
901  */
902 NTSTATUS WINAPI LdrUnlockLoaderLock( ULONG flags, ULONG magic )
903 {
904     if (magic)
905     {
906         if (magic != GetCurrentThreadId()) return STATUS_INVALID_PARAMETER_2;
907         RtlLeaveCriticalSection( &loader_section );
908     }
909     return STATUS_SUCCESS;
910 }
911
912
913 /******************************************************************
914  *              LdrGetDllHandle (NTDLL.@)
915  */
916 NTSTATUS WINAPI LdrGetDllHandle(ULONG x, ULONG y, const UNICODE_STRING *name, HMODULE *base)
917 {
918     NTSTATUS status = STATUS_DLL_NOT_FOUND;
919     WCHAR dllname[MAX_PATH+4], *p;
920     UNICODE_STRING str;
921     PLIST_ENTRY mark, entry;
922     PLDR_MODULE mod;
923
924     if (x != 0 || y != 0)
925         FIXME("Unknown behavior, please report\n");
926
927     /* Append .DLL to name if no extension present */
928     if (!(p = strrchrW( name->Buffer, '.')) || strchrW( p, '/' ) || strchrW( p, '\\'))
929     {
930         if (name->Length >= MAX_PATH) return STATUS_NAME_TOO_LONG;
931         strcpyW( dllname, name->Buffer );
932         strcatW( dllname, dllW );
933         RtlInitUnicodeString( &str, dllname );
934         name = &str;
935     }
936
937     RtlEnterCriticalSection( &loader_section );
938
939     if (cached_modref)
940     {
941         if (RtlEqualUnicodeString( name, &cached_modref->ldr.FullDllName, TRUE ) ||
942             RtlEqualUnicodeString( name, &cached_modref->ldr.BaseDllName, TRUE ))
943         {
944             *base = cached_modref->ldr.BaseAddress;
945             status = STATUS_SUCCESS;
946             goto done;
947         }
948     }
949
950     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
951     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
952     {
953         mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
954
955         if (RtlEqualUnicodeString( name, &mod->FullDllName, TRUE ) ||
956             RtlEqualUnicodeString( name, &mod->BaseDllName, TRUE ))
957         {
958             cached_modref = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
959             *base = mod->BaseAddress;
960             status = STATUS_SUCCESS;
961             break;
962         }
963     }
964 done:
965     RtlLeaveCriticalSection( &loader_section );
966     TRACE("%lx %lx %s -> %p\n", x, y, debugstr_us(name), status ? NULL : *base);
967     return status;
968 }
969
970
971 /******************************************************************
972  *              LdrGetProcedureAddress  (NTDLL.@)
973  */
974 NTSTATUS WINAPI LdrGetProcedureAddress(HMODULE module, const ANSI_STRING *name,
975                                        ULONG ord, PVOID *address)
976 {
977     IMAGE_EXPORT_DIRECTORY *exports;
978     DWORD exp_size;
979     NTSTATUS ret = STATUS_PROCEDURE_NOT_FOUND;
980
981     RtlEnterCriticalSection( &loader_section );
982
983     if ((exports = RtlImageDirectoryEntryToData( module, TRUE,
984                                                  IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
985     {
986         void *proc = name ? find_named_export( module, exports, exp_size, name->Buffer, -1 )
987                           : find_ordinal_export( module, exports, exp_size, ord - exports->Base );
988         if (proc)
989         {
990             *address = proc;
991             ret = STATUS_SUCCESS;
992         }
993     }
994     else
995     {
996         /* check if the module itself is invalid to return the proper error */
997         if (!get_modref( module )) ret = STATUS_DLL_NOT_FOUND;
998     }
999
1000     RtlLeaveCriticalSection( &loader_section );
1001     return ret;
1002 }
1003
1004
1005 /***********************************************************************
1006  *           load_builtin_callback
1007  *
1008  * Load a library in memory; callback function for wine_dll_register
1009  */
1010 static void load_builtin_callback( void *module, const char *filename )
1011 {
1012     IMAGE_NT_HEADERS *nt;
1013     WINE_MODREF *wm;
1014     WCHAR *fullname, *p;
1015     DWORD len;
1016
1017     if (!module)
1018     {
1019         ERR("could not map image for %s\n", filename ? filename : "main exe" );
1020         return;
1021     }
1022     if (!(nt = RtlImageNtHeader( module )))
1023     {
1024         ERR( "bad module for %s\n", filename ? filename : "main exe" );
1025         last_builtin_status = STATUS_INVALID_IMAGE_FORMAT;
1026         return;
1027     }
1028     if (!(nt->FileHeader.Characteristics & IMAGE_FILE_DLL))
1029     {
1030         /* if we already have an executable, ignore this one */
1031         if (!NtCurrentTeb()->Peb->ImageBaseAddress)
1032             NtCurrentTeb()->Peb->ImageBaseAddress = module;
1033         return; /* don't create the modref here, will be done later on */
1034     }
1035
1036     /* create the MODREF */
1037
1038     len = GetSystemDirectoryW( NULL, 0 );
1039     if (!(fullname = RtlAllocateHeap( GetProcessHeap(), 0,
1040                                       (len + strlen(filename) + 1) * sizeof(WCHAR) )))
1041     {
1042         ERR( "can't load %s\n", filename );
1043         last_builtin_status = STATUS_NO_MEMORY;
1044         return;
1045     }
1046     p = fullname + GetSystemDirectoryW( fullname, len );
1047     *p++ = '\\';
1048     ascii_to_unicode( p, filename, strlen(filename) + 1 );
1049
1050     wm = alloc_module( module, fullname );
1051     RtlFreeHeap( GetProcessHeap(), 0, fullname );
1052     if (!wm)
1053     {
1054         ERR( "can't load %s\n", filename );
1055         last_builtin_status = STATUS_NO_MEMORY;
1056         return;
1057     }
1058     wm->ldr.Flags |= LDR_WINE_INTERNAL;
1059
1060     /* fixup imports */
1061
1062     if (fixup_imports( wm ) != STATUS_SUCCESS)
1063     {
1064         /* the module has only be inserted in the load & memory order lists */
1065         RemoveEntryList(&wm->ldr.InLoadOrderModuleList);
1066         RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);
1067         /* FIXME: free the modref */
1068         last_builtin_status = STATUS_DLL_NOT_FOUND;
1069         return;
1070     }
1071     TRACE( "loaded %s %p %p\n", filename, wm, module );
1072
1073     /* send the DLL load event */
1074
1075     SERVER_START_REQ( load_dll )
1076     {
1077         req->handle     = 0;
1078         req->base       = module;
1079         req->size       = nt->OptionalHeader.SizeOfImage;
1080         req->dbg_offset = nt->FileHeader.PointerToSymbolTable;
1081         req->dbg_size   = nt->FileHeader.NumberOfSymbols;
1082         req->name       = &wm->ldr.FullDllName.Buffer;
1083         wine_server_add_data( req, wm->ldr.FullDllName.Buffer, wm->ldr.FullDllName.Length );
1084         wine_server_call( req );
1085     }
1086     SERVER_END_REQ;
1087
1088     /* setup relay debugging entry points */
1089     if (TRACE_ON(relay)) RELAY_SetupDLL( module );
1090 }
1091
1092
1093 /******************************************************************************
1094  *      load_native_dll  (internal)
1095  */
1096 static NTSTATUS load_native_dll( LPCWSTR name, HANDLE file, DWORD flags, WINE_MODREF** pwm )
1097 {
1098     void *module;
1099     HANDLE mapping;
1100     OBJECT_ATTRIBUTES attr;
1101     LARGE_INTEGER size;
1102     IMAGE_NT_HEADERS *nt;
1103     DWORD len = 0;
1104     WINE_MODREF *wm;
1105     NTSTATUS status;
1106     UINT drive_type;
1107
1108     TRACE( "loading %s\n", debugstr_w(name) );
1109
1110     attr.Length                   = sizeof(attr);
1111     attr.RootDirectory            = 0;
1112     attr.ObjectName               = NULL;
1113     attr.Attributes               = 0;
1114     attr.SecurityDescriptor       = NULL;
1115     attr.SecurityQualityOfService = NULL;
1116     size.QuadPart = 0;
1117
1118     status = NtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,
1119                               &attr, &size, 0, SEC_IMAGE, file );
1120     if (status != STATUS_SUCCESS) return status;
1121
1122     module = NULL;
1123     status = NtMapViewOfSection( mapping, GetCurrentProcess(),
1124                                  &module, 0, 0, &size, &len, ViewShare, 0, PAGE_READONLY );
1125     NtClose( mapping );
1126     if (status != STATUS_SUCCESS) return status;
1127
1128     /* create the MODREF */
1129
1130     if (!(wm = alloc_module( module, name ))) return STATUS_NO_MEMORY;
1131
1132     /* fixup imports */
1133
1134     if (!(flags & DONT_RESOLVE_DLL_REFERENCES))
1135     {
1136         if ((status = fixup_imports(wm)) != STATUS_SUCCESS)
1137         {
1138             /* the module has only be inserted in the load & memory order lists */
1139             RemoveEntryList(&wm->ldr.InLoadOrderModuleList);
1140             RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);
1141
1142             /* FIXME: there are several more dangling references
1143              * left. Including dlls loaded by this dll before the
1144              * failed one. Unrolling is rather difficult with the
1145              * current structure and we can leave them lying
1146              * around with no problems, so we don't care.
1147              * As these might reference our wm, we don't free it.
1148              */
1149             return status;
1150         }
1151     }
1152     else wm->ldr.Flags |= LDR_DONT_RESOLVE_REFS;
1153
1154     /* send DLL load event */
1155
1156     nt = RtlImageNtHeader( module );
1157     drive_type = GetDriveTypeW( wm->ldr.FullDllName.Buffer );
1158
1159     SERVER_START_REQ( load_dll )
1160     {
1161         req->handle     = file;
1162         req->base       = module;
1163         req->size       = nt->OptionalHeader.SizeOfImage;
1164         req->dbg_offset = nt->FileHeader.PointerToSymbolTable;
1165         req->dbg_size   = nt->FileHeader.NumberOfSymbols;
1166         req->name       = &wm->ldr.FullDllName.Buffer;
1167         /* don't keep the file handle open on removable media */
1168         if (drive_type == DRIVE_REMOVABLE || drive_type == DRIVE_CDROM) req->handle = 0;
1169         wine_server_add_data( req, wm->ldr.FullDllName.Buffer, wm->ldr.FullDllName.Length );
1170         wine_server_call( req );
1171     }
1172     SERVER_END_REQ;
1173
1174     if (TRACE_ON(snoop)) SNOOP_SetupDLL( module );
1175
1176     *pwm = wm;
1177     return STATUS_SUCCESS;
1178 }
1179
1180
1181 /***********************************************************************
1182  *           load_builtin_dll
1183  */
1184 static NTSTATUS load_builtin_dll( LPCWSTR path, DWORD flags, WINE_MODREF** pwm )
1185 {
1186     char error[256], dllname[MAX_PATH];
1187     int file_exists;
1188     const WCHAR *name, *p;
1189     DWORD len, i;
1190     void *handle;
1191     WINE_MODREF *wm;
1192
1193     /* Fix the name in case we have a full path and extension */
1194     name = path;
1195     if ((p = strrchrW( name, '\\' ))) name = p + 1;
1196     if ((p = strrchrW( name, '/' ))) name = p + 1;
1197
1198     /* we don't want to depend on the current codepage here */
1199     len = strlenW( name ) + 1;
1200     if (len >= sizeof(dllname)) return STATUS_NAME_TOO_LONG;
1201     for (i = 0; i < len; i++)
1202     {
1203         if (name[i] > 127) return STATUS_DLL_NOT_FOUND;
1204         dllname[i] = (char)name[i];
1205         if (dllname[i] >= 'A' && dllname[i] <= 'Z') dllname[i] += 'a' - 'A';
1206     }
1207
1208     last_builtin_status = STATUS_SUCCESS;
1209     /* load_library will modify last_builtin_status. Note also that load_library can be
1210      * called several times, if the .so file we're loading has dependencies.
1211      * last_builtin_status will gather all the errors we may get while loading all these
1212      * libraries
1213      */
1214     if (!(handle = wine_dll_load( dllname, error, sizeof(error), &file_exists )))
1215     {
1216         if (!file_exists)
1217         {
1218             /* The file does not exist -> WARN() */
1219             WARN("cannot open .so lib for builtin %s: %s\n", debugstr_w(name), error);
1220             return STATUS_DLL_NOT_FOUND;
1221         }
1222         /* ERR() for all other errors (missing functions, ...) */
1223         ERR("failed to load .so lib for builtin %s: %s\n", debugstr_w(name), error );
1224         return STATUS_PROCEDURE_NOT_FOUND;
1225     }
1226     if (last_builtin_status != STATUS_SUCCESS) return last_builtin_status;
1227
1228     if (!(wm = find_module( path ))) wm = find_module( name );
1229     if (!wm)
1230     {
1231         ERR( "loaded .so but dll %s still not found - 16-bit dll or version conflict.\n",
1232              debugstr_w(name) );
1233         /* wine_dll_unload( handle );*/
1234         return STATUS_INVALID_IMAGE_FORMAT;
1235     }
1236     wm->ldr.SectionHandle = handle;
1237     *pwm = wm;
1238     return STATUS_SUCCESS;
1239 }
1240
1241
1242 /***********************************************************************
1243  *      load_dll  (internal)
1244  *
1245  * Load a PE style module according to the load order.
1246  * The loader_section must be locked while calling this function.
1247  */
1248 static NTSTATUS load_dll( LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )
1249 {
1250     int i;
1251     enum loadorder_type loadorder[LOADORDER_NTYPES];
1252     WCHAR *filename, *file_part;
1253     const char *filetype = "";
1254     WINE_MODREF *main_exe;
1255     HANDLE handle = INVALID_HANDLE_VALUE;
1256     NTSTATUS nts = STATUS_DLL_NOT_FOUND;
1257     const WCHAR *load_path;
1258
1259     *pwm = NULL;
1260     filename = RtlAllocateHeap ( GetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR) );
1261     if ( !filename ) return STATUS_NO_MEMORY;
1262
1263     if (!(load_path = current_load_path))
1264         load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;
1265
1266     TRACE( "looking for %s in %s\n", debugstr_w(libname), debugstr_w(load_path) );
1267
1268     if (RtlDosSearchPath_U( load_path, libname, dllW, MAX_PATH * sizeof(WCHAR), filename, &file_part ))
1269     {
1270         if ((*pwm = find_module( filename )) != NULL) goto found;
1271
1272         /* check for already loaded module in a different path */
1273         if (!contains_path( libname ))
1274         {
1275             if ((*pwm = find_module( file_part )) != NULL) goto found;
1276         }
1277         handle = CreateFileW( filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
1278     }
1279     else  /* we didn't find the file */
1280     {
1281         if (contains_path( libname ))
1282         {
1283             RtlGetFullPathName_U( libname, MAX_PATH * sizeof(WCHAR), filename, &file_part );
1284             if ((*pwm = find_module( filename )) != NULL) goto found;
1285         }
1286         else
1287         {
1288             if ((*pwm = find_module( libname )) != NULL) goto found;
1289             strcpyW( filename, libname );
1290             file_part = filename;
1291         }
1292         if (!strchrW( file_part, '.' )) strcatW( file_part, dllW );
1293     }
1294
1295     main_exe = get_modref( NtCurrentTeb()->Peb->ImageBaseAddress );
1296     MODULE_GetLoadOrderW( loadorder, main_exe->ldr.BaseDllName.Buffer, filename, TRUE);
1297
1298     for (i = 0; i < LOADORDER_NTYPES; i++)
1299     {
1300         if (loadorder[i] == LOADORDER_INVALID) break;
1301
1302         switch (loadorder[i])
1303         {
1304         case LOADORDER_DLL:
1305             TRACE("Trying native dll %s\n", debugstr_w(filename));
1306             if (handle != INVALID_HANDLE_VALUE)
1307                 nts = load_native_dll(filename, handle, flags, pwm);
1308             filetype = "native";
1309             break;
1310         case LOADORDER_BI:
1311             TRACE("Trying built-in %s\n", debugstr_w(filename));
1312             nts = load_builtin_dll(filename, flags, pwm);
1313             filetype = "builtin";
1314             break;
1315         default:
1316             nts = STATUS_INTERNAL_ERROR;
1317             break;
1318         }
1319
1320         if (nts == STATUS_SUCCESS)
1321         {
1322             /* Initialize DLL just loaded */
1323             TRACE("Loaded module %s (%s) at %p\n",
1324                   debugstr_w(filename), filetype, (*pwm)->ldr.BaseAddress);
1325             if (!TRACE_ON(module))
1326                 TRACE_(loaddll)("Loaded module %s : %s\n", debugstr_w(filename), filetype);
1327             /* Set the ldr.LoadCount here so that an attach failure will */
1328             /* decrement the dependencies through the MODULE_FreeLibrary call. */
1329             (*pwm)->ldr.LoadCount = 1;
1330             if (handle != INVALID_HANDLE_VALUE) NtClose( handle );
1331             RtlFreeHeap( GetProcessHeap(), 0, filename );
1332             return nts;
1333         }
1334         if (nts != STATUS_DLL_NOT_FOUND) break;
1335     }
1336
1337     WARN("Failed to load module %s; status=%lx\n", debugstr_w(libname), nts);
1338     if (handle != INVALID_HANDLE_VALUE) NtClose( handle );
1339     RtlFreeHeap( GetProcessHeap(), 0, filename );
1340     return nts;
1341
1342  found:
1343     if ((*pwm)->ldr.LoadCount != -1) (*pwm)->ldr.LoadCount++;
1344
1345     if (((*pwm)->ldr.Flags & LDR_DONT_RESOLVE_REFS) &&
1346         !(flags & DONT_RESOLVE_DLL_REFERENCES))
1347     {
1348         (*pwm)->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;
1349         fixup_imports( *pwm );
1350     }
1351     TRACE("Found loaded module %s for %s at %p, count=%d\n",
1352           debugstr_w((*pwm)->ldr.FullDllName.Buffer), debugstr_w(libname),
1353           (*pwm)->ldr.BaseAddress, (*pwm)->ldr.LoadCount);
1354     RtlFreeHeap( GetProcessHeap(), 0, filename );
1355     return STATUS_SUCCESS;
1356 }
1357
1358 /******************************************************************
1359  *              LdrLoadDll (NTDLL.@)
1360  */
1361 NTSTATUS WINAPI LdrLoadDll(LPCWSTR path_name, DWORD flags,
1362                            const UNICODE_STRING *libname, HMODULE* hModule)
1363 {
1364     WINE_MODREF *wm;
1365     NTSTATUS nts;
1366     const WCHAR *prev_load_path;
1367
1368     RtlEnterCriticalSection( &loader_section );
1369
1370     prev_load_path = current_load_path;
1371     current_load_path = path_name;
1372     nts = load_dll( libname->Buffer, flags, &wm );
1373     current_load_path = prev_load_path;
1374
1375     if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))
1376     {
1377         nts = process_attach( wm, NULL );
1378         if (nts != STATUS_SUCCESS)
1379         {
1380             WARN("Attach failed for module %s\n", debugstr_w(libname->Buffer));
1381             LdrUnloadDll(wm->ldr.BaseAddress);
1382             wm = NULL;
1383         }
1384     }
1385     *hModule = (wm) ? wm->ldr.BaseAddress : NULL;
1386
1387     RtlLeaveCriticalSection( &loader_section );
1388     return nts;
1389 }
1390
1391 /******************************************************************
1392  *              LdrQueryProcessModuleInformation
1393  *
1394  */
1395 NTSTATUS WINAPI LdrQueryProcessModuleInformation(PSYSTEM_MODULE_INFORMATION smi, 
1396                                                  ULONG buf_size, ULONG* req_size)
1397 {
1398     SYSTEM_MODULE*      sm = &smi->Modules[0];
1399     ULONG               size = sizeof(ULONG);
1400     NTSTATUS            nts = STATUS_SUCCESS;
1401     ANSI_STRING         str;
1402     char*               ptr;
1403     PLIST_ENTRY         mark, entry;
1404     PLDR_MODULE         mod;
1405
1406     smi->ModulesCount = 0;
1407
1408     RtlEnterCriticalSection( &loader_section );
1409     mark = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList;
1410     for (entry = mark->Flink; entry != mark; entry = entry->Flink)
1411     {
1412         mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList);
1413         size += sizeof(*sm);
1414         if (size <= buf_size)
1415         {
1416             sm->Reserved1 = 0; /* FIXME */
1417             sm->Reserved2 = 0; /* FIXME */
1418             sm->ImageBaseAddress = mod->BaseAddress;
1419             sm->ImageSize = mod->SizeOfImage;
1420             sm->Flags = mod->Flags;
1421             sm->Id = 0; /* FIXME */
1422             sm->Rank = 0; /* FIXME */
1423             sm->Unknown = 0; /* FIXME */
1424             str.Length = 0;
1425             str.MaximumLength = MAXIMUM_FILENAME_LENGTH;
1426             str.Buffer = sm->Name;
1427             RtlUnicodeStringToAnsiString(&str, &mod->FullDllName, FALSE);
1428             ptr = strrchr(sm->Name, '\\');
1429             sm->NameOffset = (ptr != NULL) ? (ptr - (char*)sm->Name + 1) : 0;
1430
1431             smi->ModulesCount++;
1432             sm++;
1433         }
1434         else nts = STATUS_INFO_LENGTH_MISMATCH;
1435     }
1436     RtlLeaveCriticalSection( &loader_section );
1437
1438     if (req_size) *req_size = size;
1439
1440     return nts;
1441 }
1442
1443 /******************************************************************
1444  *              LdrShutdownProcess (NTDLL.@)
1445  *
1446  */
1447 void WINAPI LdrShutdownProcess(void)
1448 {
1449     TRACE("()\n");
1450     process_detach( TRUE, (LPVOID)1 );
1451 }
1452
1453 /******************************************************************
1454  *              LdrShutdownThread (NTDLL.@)
1455  *
1456  */
1457 void WINAPI LdrShutdownThread(void)
1458 {
1459     PLIST_ENTRY mark, entry;
1460     PLDR_MODULE mod;
1461
1462     TRACE("()\n");
1463
1464     /* don't do any detach calls if process is exiting */
1465     if (process_detaching) return;
1466     /* FIXME: there is still a race here */
1467
1468     RtlEnterCriticalSection( &loader_section );
1469
1470     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
1471     for (entry = mark->Blink; entry != mark; entry = entry->Blink)
1472     {
1473         mod = CONTAINING_RECORD(entry, LDR_MODULE, 
1474                                 InInitializationOrderModuleList);
1475         if ( !(mod->Flags & LDR_PROCESS_ATTACHED) )
1476             continue;
1477         if ( mod->Flags & LDR_NO_DLL_CALLS )
1478             continue;
1479
1480         MODULE_InitDLL( CONTAINING_RECORD(mod, WINE_MODREF, ldr), 
1481                         DLL_THREAD_DETACH, NULL );
1482     }
1483
1484     RtlLeaveCriticalSection( &loader_section );
1485 }
1486
1487 /***********************************************************************
1488  *           MODULE_FlushModrefs
1489  *
1490  * Remove all unused modrefs and call the internal unloading routines
1491  * for the library type.
1492  *
1493  * The loader_section must be locked while calling this function.
1494  */
1495 static void MODULE_FlushModrefs(void)
1496 {
1497     PLIST_ENTRY mark, entry, prev;
1498     PLDR_MODULE mod;
1499     WINE_MODREF*wm;
1500
1501     mark = &NtCurrentTeb()->Peb->LdrData->InInitializationOrderModuleList;
1502     for (entry = mark->Blink; entry != mark; entry = prev)
1503     {
1504         mod = CONTAINING_RECORD(entry, LDR_MODULE, 
1505                                 InInitializationOrderModuleList);
1506         wm = CONTAINING_RECORD(mod, WINE_MODREF, ldr);
1507
1508         prev = entry->Blink;
1509         if (mod->LoadCount) continue;
1510
1511         RemoveEntryList(&mod->InLoadOrderModuleList);
1512         RemoveEntryList(&mod->InMemoryOrderModuleList);
1513         RemoveEntryList(&mod->InInitializationOrderModuleList);
1514
1515         TRACE(" unloading %s\n", debugstr_w(mod->FullDllName.Buffer));
1516         if (!TRACE_ON(module))
1517             TRACE_(loaddll)("Unloaded module %s : %s\n",
1518                             debugstr_w(mod->FullDllName.Buffer),
1519                             (wm->ldr.Flags & LDR_WINE_INTERNAL) ? "builtin" : "native" );
1520
1521         SERVER_START_REQ( unload_dll )
1522         {
1523             req->base = mod->BaseAddress;
1524             wine_server_call( req );
1525         }
1526         SERVER_END_REQ;
1527
1528         if (wm->ldr.Flags & LDR_WINE_INTERNAL) wine_dll_unload( wm->ldr.SectionHandle );
1529         else NtUnmapViewOfSection( GetCurrentProcess(), mod->BaseAddress );
1530         if (cached_modref == wm) cached_modref = NULL;
1531         RtlFreeUnicodeString( &mod->FullDllName );
1532         RtlFreeHeap( ntdll_get_process_heap(), 0, wm->deps );
1533         RtlFreeHeap( ntdll_get_process_heap(), 0, wm );
1534     }
1535 }
1536
1537 /***********************************************************************
1538  *           MODULE_DecRefCount
1539  *
1540  * The loader_section must be locked while calling this function.
1541  */
1542 static void MODULE_DecRefCount( WINE_MODREF *wm )
1543 {
1544     int i;
1545
1546     if ( wm->ldr.Flags & LDR_UNLOAD_IN_PROGRESS )
1547         return;
1548
1549     if ( wm->ldr.LoadCount <= 0 )
1550         return;
1551
1552     --wm->ldr.LoadCount;
1553     TRACE("(%s) ldr.LoadCount: %d\n", debugstr_w(wm->ldr.BaseDllName.Buffer), wm->ldr.LoadCount );
1554
1555     if ( wm->ldr.LoadCount == 0 )
1556     {
1557         wm->ldr.Flags |= LDR_UNLOAD_IN_PROGRESS;
1558
1559         for ( i = 0; i < wm->nDeps; i++ )
1560             if ( wm->deps[i] )
1561                 MODULE_DecRefCount( wm->deps[i] );
1562
1563         wm->ldr.Flags &= ~LDR_UNLOAD_IN_PROGRESS;
1564     }
1565 }
1566
1567 /******************************************************************
1568  *              LdrUnloadDll (NTDLL.@)
1569  *
1570  *
1571  */
1572 NTSTATUS WINAPI LdrUnloadDll( HMODULE hModule )
1573 {
1574     NTSTATUS retv = STATUS_SUCCESS;
1575
1576     TRACE("(%p)\n", hModule);
1577
1578     RtlEnterCriticalSection( &loader_section );
1579
1580     /* if we're stopping the whole process (and forcing the removal of all
1581      * DLLs) the library will be freed anyway
1582      */
1583     if (!process_detaching)
1584     {
1585         WINE_MODREF *wm;
1586
1587         free_lib_count++;
1588         if ((wm = get_modref( hModule )) != NULL)
1589         {
1590             TRACE("(%s) - START\n", debugstr_w(wm->ldr.BaseDllName.Buffer));
1591
1592             /* Recursively decrement reference counts */
1593             MODULE_DecRefCount( wm );
1594
1595             /* Call process detach notifications */
1596             if ( free_lib_count <= 1 )
1597             {
1598                 process_detach( FALSE, NULL );
1599                 MODULE_FlushModrefs();
1600             }
1601
1602             TRACE("END\n");
1603         }
1604         else
1605             retv = STATUS_DLL_NOT_FOUND;
1606
1607         free_lib_count--;
1608     }
1609
1610     RtlLeaveCriticalSection( &loader_section );
1611
1612     return retv;
1613 }
1614
1615 /***********************************************************************
1616  *           RtlImageNtHeader   (NTDLL.@)
1617  */
1618 PIMAGE_NT_HEADERS WINAPI RtlImageNtHeader(HMODULE hModule)
1619 {
1620     IMAGE_NT_HEADERS *ret;
1621
1622     __TRY
1623     {
1624         IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)hModule;
1625
1626         ret = NULL;
1627         if (dos->e_magic == IMAGE_DOS_SIGNATURE)
1628         {
1629             ret = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew);
1630             if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL;
1631         }
1632     }
1633     __EXCEPT(page_fault)
1634     {
1635         return NULL;
1636     }
1637     __ENDTRY
1638     return ret;
1639 }
1640
1641
1642 /******************************************************************
1643  *              LdrInitializeThunk (NTDLL.@)
1644  *
1645  * FIXME: the arguments are not correct, main_file is a Wine invention.
1646  */
1647 void WINAPI LdrInitializeThunk( HANDLE main_file, ULONG unknown2, ULONG unknown3, ULONG unknown4 )
1648 {
1649     NTSTATUS status;
1650     WINE_MODREF *wm;
1651     LPTHREAD_START_ROUTINE entry;
1652     PEB *peb = NtCurrentTeb()->Peb;
1653     UNICODE_STRING *main_exe_name = &peb->ProcessParameters->ImagePathName;
1654     IMAGE_NT_HEADERS *nt = RtlImageNtHeader( peb->ImageBaseAddress );
1655
1656     /* allocate the modref for the main exe */
1657     if (!(wm = alloc_module( peb->ImageBaseAddress, main_exe_name->Buffer )))
1658     {
1659         status = STATUS_NO_MEMORY;
1660         goto error;
1661     }
1662     wm->ldr.LoadCount = -1;  /* can't unload main exe */
1663     entry = wm->ldr.EntryPoint;
1664
1665     /* Install signal handlers; this cannot be done before, since we cannot
1666      * send exceptions to the debugger before the create process event that
1667      * is sent by REQ_INIT_PROCESS_DONE.
1668      * We do need the handlers in place by the time the request is over, so
1669      * we set them up here. If we segfault between here and the server call
1670      * something is very wrong... */
1671     if (!SIGNAL_Init()) exit(1);
1672
1673     /* Signal the parent process to continue */
1674     SERVER_START_REQ( init_process_done )
1675     {
1676         req->module      = peb->ImageBaseAddress;
1677         req->module_size = wm->ldr.SizeOfImage;
1678         req->entry       = entry;
1679         /* API requires a double indirection */
1680         req->name        = &main_exe_name->Buffer;
1681         req->exe_file    = main_file;
1682         req->gui         = (nt->OptionalHeader.Subsystem != IMAGE_SUBSYSTEM_WINDOWS_CUI);
1683         wine_server_add_data( req, main_exe_name->Buffer, main_exe_name->Length );
1684         wine_server_call( req );
1685         peb->BeingDebugged = reply->debugged;
1686     }
1687     SERVER_END_REQ;
1688
1689     if (main_file) NtClose( main_file ); /* we no longer need it */
1690     if (TRACE_ON(relay) || TRACE_ON(snoop)) RELAY_InitDebugLists();
1691
1692     RtlEnterCriticalSection( &loader_section );
1693
1694     if ((status = fixup_imports( wm )) != STATUS_SUCCESS) goto error;
1695     if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto error;
1696     if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error;
1697     if ((status = process_attach( wm, (LPVOID)1 )) != STATUS_SUCCESS) goto error;
1698
1699     RtlLeaveCriticalSection( &loader_section );
1700
1701     if (TRACE_ON(relay))
1702         DPRINTF( "%04lx:Starting process %s (entryproc=%p)\n", GetCurrentThreadId(),
1703                  debugstr_w(peb->ProcessParameters->ImagePathName.Buffer), entry );
1704
1705     NtCurrentTeb()->last_error = 0;  /* clear error code */
1706     if (peb->BeingDebugged) DbgBreakPoint();
1707     NtTerminateProcess( GetCurrentProcess(), entry( peb ) );
1708
1709 error:
1710     ERR( "Main exe initialization failed, status %lx\n", status );
1711     exit(1);
1712 }
1713
1714
1715 /***********************************************************************
1716  *           RtlImageDirectoryEntryToData   (NTDLL.@)
1717  */
1718 PVOID WINAPI RtlImageDirectoryEntryToData( HMODULE module, BOOL image, WORD dir, ULONG *size )
1719 {
1720     const IMAGE_NT_HEADERS *nt;
1721     DWORD addr;
1722
1723     if ((ULONG_PTR)module & 1)  /* mapped as data file */
1724     {
1725         module = (HMODULE)((ULONG_PTR)module & ~1);
1726         image = FALSE;
1727     }
1728     if (!(nt = RtlImageNtHeader( module ))) return NULL;
1729     if (dir >= nt->OptionalHeader.NumberOfRvaAndSizes) return NULL;
1730     if (!(addr = nt->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;
1731     *size = nt->OptionalHeader.DataDirectory[dir].Size;
1732     if (image || addr < nt->OptionalHeader.SizeOfHeaders) return (char *)module + addr;
1733
1734     /* not mapped as image, need to find the section containing the virtual address */
1735     return RtlImageRvaToVa( nt, module, addr, NULL );
1736 }
1737
1738
1739 /***********************************************************************
1740  *           RtlImageRvaToSection   (NTDLL.@)
1741  */
1742 PIMAGE_SECTION_HEADER WINAPI RtlImageRvaToSection( const IMAGE_NT_HEADERS *nt,
1743                                                    HMODULE module, DWORD rva )
1744 {
1745     int i;
1746     IMAGE_SECTION_HEADER *sec = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader +
1747                                                         nt->FileHeader.SizeOfOptionalHeader);
1748     for (i = 0; i < nt->FileHeader.NumberOfSections; i++, sec++)
1749     {
1750         if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
1751             return sec;
1752     }
1753     return NULL;
1754 }
1755
1756
1757 /***********************************************************************
1758  *           RtlImageRvaToVa   (NTDLL.@)
1759  */
1760 PVOID WINAPI RtlImageRvaToVa( const IMAGE_NT_HEADERS *nt, HMODULE module,
1761                               DWORD rva, IMAGE_SECTION_HEADER **section )
1762 {
1763     IMAGE_SECTION_HEADER *sec;
1764
1765     if (section && *section)  /* try this section first */
1766     {
1767         sec = *section;
1768         if ((sec->VirtualAddress <= rva) && (sec->VirtualAddress + sec->SizeOfRawData > rva))
1769             goto found;
1770     }
1771     if (!(sec = RtlImageRvaToSection( nt, module, rva ))) return NULL;
1772  found:
1773     if (section) *section = sec;
1774     return (char *)module + sec->PointerToRawData + (rva - sec->VirtualAddress);
1775 }
1776
1777
1778 /***********************************************************************
1779  *           BUILTIN32_Init
1780  *
1781  * Initialize loading callbacks and return HMODULE of main exe.
1782  * 'main' is the main exe in case it was already loaded from a PE file.
1783  *
1784  * FIXME: this should be done differently once kernel is properly separated.
1785  */
1786 HMODULE BUILTIN32_LoadExeModule( HMODULE main )
1787 {
1788     NtCurrentTeb()->Peb->ImageBaseAddress = main;
1789     last_builtin_status = STATUS_SUCCESS;
1790     wine_dll_set_callback( load_builtin_callback );
1791     if (!NtCurrentTeb()->Peb->ImageBaseAddress)
1792         MESSAGE( "No built-in EXE module loaded!  Did you create a .spec file?\n" );
1793     if (last_builtin_status != STATUS_SUCCESS)
1794         MESSAGE( "Error while processing initial modules\n");
1795     return NtCurrentTeb()->Peb->ImageBaseAddress;
1796 }