Disable dlmalloc for exe loading for now.
[wincetools.git] / loader / ntdll_loader.c
1 /* From wine1.2-1.1.42/dlls/ntdll/loader.c  */\r
2 \r
3 /*\r
4  * Loader functions\r
5  *\r
6  * Copyright 1995, 2003 Alexandre Julliard\r
7  * Copyright 2002 Dmitry Timoshkov for CodeWeavers\r
8  * Copyright 2010 g10 Code GmbH\r
9  *\r
10  * This library is free software; you can redistribute it and/or\r
11  * modify it under the terms of the GNU Lesser General Public\r
12  * License as published by the Free Software Foundation; either\r
13  * version 2.1 of the License, or (at your option) any later version.\r
14  *\r
15  * This library is distributed in the hope that it will be useful,\r
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
18  * Lesser General Public License for more details.\r
19  *\r
20  * You should have received a copy of the GNU Lesser General Public\r
21  * License along with this library; if not, write to the Free Software\r
22  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA\r
23  */\r
24 \r
25 \r
26 \r
27 #include <assert.h>\r
28 \r
29 #undef USE_DLMALLOC\r
30 #ifdef USE_DLMALLOC\r
31 #include "dlmalloc.h"\r
32 #endif\r
33 \r
34 #include "wine.h"\r
35 \r
36 PIMAGE_NT_HEADERS MyRtlImageNtHeader(HMODULE hModule)\r
37 {\r
38     IMAGE_NT_HEADERS *ret;\r
39     IMAGE_DOS_HEADER *dos = (IMAGE_DOS_HEADER *)hModule;\r
40 \r
41     ret = NULL;\r
42     if (dos->e_magic == IMAGE_DOS_SIGNATURE)\r
43     {\r
44         ret = (IMAGE_NT_HEADERS *)((char *)dos + dos->e_lfanew);\r
45         if (ret->Signature != IMAGE_NT_SIGNATURE) ret = NULL;\r
46     }\r
47     return ret;\r
48 }\r
49 \r
50 \f\r
51 /* internal representation of 32bit modules. per process. */\r
52 typedef struct _wine_modref\r
53 {\r
54     LDR_MODULE            ldr;\r
55     int                   nDeps;\r
56     struct _wine_modref **deps;\r
57 } WINE_MODREF;\r
58 \r
59 /* FIXME: cmp with himemce-map.h */\r
60 #define MAX_MODREFS 64\r
61 WINE_MODREF *modrefs[MAX_MODREFS];\r
62 int nr_modrefs;\r
63 \r
64 \r
65 static WINE_MODREF *current_modref;\r
66 \r
67 \r
68 /* convert from straight ASCII to Unicode without depending on the current codepage */\r
69 static void ascii_to_unicode( WCHAR *dst, const char *src, size_t len )\r
70 {\r
71   while (len--) *dst++ = (unsigned char)*src++;\r
72 }\r
73 \r
74 \r
75 /***********************************************************************\r
76  *           RtlImageDirectoryEntryToData   (NTDLL.@)\r
77  */\r
78 PVOID MyRtlImageDirectoryEntryToData( HMODULE module, BOOL image, WORD dir, ULONG *size )\r
79 {\r
80   const IMAGE_NT_HEADERS *nt;\r
81   DWORD addr;\r
82 \r
83   if ((ULONG_PTR)module & 1)  /* mapped as data file */\r
84     {\r
85       module = (HMODULE)((ULONG_PTR)module & ~1);\r
86       image = FALSE;\r
87     }\r
88   if (!(nt = MyRtlImageNtHeader( module ))) return NULL;\r
89   if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC)\r
90     {\r
91       const IMAGE_NT_HEADERS64 *nt64 = (const IMAGE_NT_HEADERS64 *)nt;\r
92 \r
93       if (dir >= nt64->OptionalHeader.NumberOfRvaAndSizes) return NULL;\r
94       if (!(addr = nt64->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;\r
95       *size = nt64->OptionalHeader.DataDirectory[dir].Size;\r
96       if (image || addr < nt64->OptionalHeader.SizeOfHeaders) return (char *)module + addr;\r
97     }\r
98   else if (nt->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)\r
99     {\r
100       const IMAGE_NT_HEADERS32 *nt32 = (const IMAGE_NT_HEADERS32 *)nt;\r
101 \r
102       if (dir >= nt32->OptionalHeader.NumberOfRvaAndSizes) return NULL;\r
103       if (!(addr = nt32->OptionalHeader.DataDirectory[dir].VirtualAddress)) return NULL;\r
104       *size = nt32->OptionalHeader.DataDirectory[dir].Size;\r
105       if (image || addr < nt32->OptionalHeader.SizeOfHeaders) return (char *)module + addr;\r
106     }\r
107   else return NULL;\r
108 \r
109 #if 0\r
110   /* not mapped as image, need to find the section containing the virtual address */\r
111   return RtlImageRvaToVa( nt, module, addr, NULL );\r
112 #else\r
113   return NULL;\r
114 #endif\r
115 }\r
116 \r
117 \r
118 /* convert PE image VirtualAddress to Real Address */\r
119 static void *get_rva( HMODULE module, DWORD va )\r
120 {\r
121   return (void *)((char *)module + va);\r
122 }\r
123 \r
124 \r
125 #define allocate_stub(x,y) (0xdeadbeef)\r
126 \r
127 /*************************************************************************\r
128  *              import_dll\r
129  *\r
130  * Import the dll specified by the given import descriptor.\r
131  * The loader_section must be locked while calling this function.\r
132  */\r
133 static WINE_MODREF *import_dll( HMODULE module, const IMAGE_IMPORT_DESCRIPTOR *descr, LPCWSTR load_path )\r
134 {\r
135   NTSTATUS status = STATUS_SUCCESS;\r
136   //  WINE_MODREF *wmImp;\r
137   HMODULE imp_mod;\r
138   //  const IMAGE_EXPORT_DIRECTORY *exports;\r
139   //  DWORD exp_size;\r
140   const IMAGE_THUNK_DATA *import_list;\r
141   IMAGE_THUNK_DATA *thunk_list;\r
142   WCHAR buffer[32];\r
143   const char *name = get_rva( module, descr->Name );\r
144   DWORD len = strlen(name);\r
145 #if 0\r
146   PVOID protect_base;\r
147   SIZE_T protect_size = 0;\r
148   DWORD protect_old;\r
149 #endif\r
150 #ifdef USE_DLMALLOC\r
151   int iscoredll = 0;\r
152 #endif\r
153 \r
154   thunk_list = get_rva( module, (DWORD)descr->FirstThunk );\r
155   if (descr->OriginalFirstThunk)\r
156     import_list = get_rva( module, (DWORD)descr->OriginalFirstThunk );\r
157   else\r
158     import_list = thunk_list;\r
159 \r
160   while (len && name[len-1] == ' ') len--;  /* remove trailing spaces */\r
161 \r
162 #ifdef USE_DLMALLOC\r
163   if (! _stricmp (name, "coredll.dll"))\r
164     iscoredll = 1;\r
165 #endif\r
166 \r
167   if (len * sizeof(WCHAR) < sizeof(buffer))\r
168     {\r
169 \r
170       ascii_to_unicode( buffer, name, len );\r
171       buffer[len] = 0;\r
172       //      status = load_dll( load_path, buffer, 0, &wmImp );\r
173       imp_mod = LoadLibrary (buffer);\r
174       if (imp_mod == INVALID_HANDLE_VALUE)\r
175         status = GetLastError ();\r
176     }\r
177   else  /* need to allocate a larger buffer */\r
178     {\r
179       WCHAR *ptr = malloc ((len + 1) * sizeof(WCHAR) );\r
180       if (!ptr) return NULL;\r
181       ascii_to_unicode( ptr, name, len );\r
182       ptr[len] = 0;\r
183       // status = load_dll( load_path, ptr, 0, &wmImp );\r
184       imp_mod = LoadLibrary (ptr);\r
185       if (imp_mod == INVALID_HANDLE_VALUE)\r
186         status = GetLastError ();\r
187       free (ptr);\r
188     }\r
189   if (status)\r
190     {\r
191       if (status == STATUS_DLL_NOT_FOUND)\r
192         TRACE("Library %s (which is needed by %s) not found\n",\r
193             name, current_modref->ldr.FullDllName);\r
194       else\r
195         TRACE("Loading library %s (which is needed by %s) failed (error %x).\n",\r
196             name, current_modref->ldr.FullDllName, status);\r
197       return NULL;\r
198     }\r
199 \r
200 #if 0\r
201   /* unprotect the import address table since it can be located in\r
202    * readonly section */\r
203   while (import_list[protect_size].u1.Ordinal) protect_size++;\r
204   protect_base = thunk_list;\r
205   protect_size *= sizeof(*thunk_list);\r
206   NtProtectVirtualMemory( NtCurrentProcess(), &protect_base,\r
207                           &protect_size, PAGE_WRITECOPY, &protect_old );\r
208 #endif\r
209 \r
210 #if 0\r
211   imp_mod = wmImp->ldr.BaseAddress;\r
212   exports = RtlImageDirectoryEntryToData( imp_mod, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size );\r
213 \r
214   if (!exports)\r
215     {\r
216       /* set all imported function to deadbeef */\r
217       while (import_list->u1.Ordinal)\r
218         {\r
219           if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))\r
220             {\r
221               int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);\r
222               WARN("No implementation for %s.%d", name, ordinal );\r
223               thunk_list->u1.Function = allocate_stub( name, IntToPtr(ordinal) );\r
224             }\r
225           else\r
226             {\r
227               IMAGE_IMPORT_BY_NAME *pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );\r
228               WARN("No implementation for %s.%s", name, pe_name->Name );\r
229               thunk_list->u1.Function = allocate_stub( name, (const char*)pe_name->Name );\r
230             }\r
231           WARN(" imported from %s, allocating stub %p\n",\r
232                current_modref->ldr.FullDllName,\r
233                (void *)thunk_list->u1.Function );\r
234           import_list++;\r
235           thunk_list++;\r
236         }\r
237       goto done;\r
238     }\r
239 #endif\r
240 \r
241   while (import_list->u1.Ordinal)\r
242     {\r
243       if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal))\r
244         {\r
245           int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);\r
246 \r
247           //      thunk_list->u1.Function = (ULONG_PTR)find_ordinal_export( imp_mod, exports, exp_size,\r
248           //                                                                ordinal - exports->Base, load_path );\r
249 \r
250 #ifdef USE_DLMALLOC\r
251           if (iscoredll)\r
252             {\r
253 #define COREDLL_MALLOC 1041\r
254 #define COREDLL_CALLOC 1346\r
255 #define COREDLL_FREE 1018\r
256 #define COREDLL_REALLOC 1054\r
257 \r
258               if (ordinal == COREDLL_MALLOC)\r
259                 thunk_list->u1.Function = (PWORD) dlmalloc;\r
260               else if (ordinal == COREDLL_CALLOC)\r
261                 thunk_list->u1.Function = (PWORD) dlcalloc;\r
262               else if (ordinal == COREDLL_FREE)\r
263                 thunk_list->u1.Function = (PWORD) dlfree;\r
264               else if (ordinal == COREDLL_REALLOC)\r
265                 thunk_list->u1.Function = (PWORD) dlrealloc;\r
266               else\r
267                 thunk_list->u1.Function = (PWORD)(ULONG_PTR)GetProcAddress (imp_mod, (void *) (ordinal & 0xffff));\r
268             }\r
269           else\r
270 #endif\r
271             thunk_list->u1.Function = (PDWORD)(ULONG_PTR)GetProcAddress (imp_mod, (void *) (ordinal & 0xffff));\r
272 \r
273           if (!thunk_list->u1.Function)\r
274             {\r
275               thunk_list->u1.Function = (PDWORD) allocate_stub( name, IntToPtr(ordinal) );\r
276               TRACE("No implementation for %s.%d imported from %s, setting to %p\n",\r
277                     name, ordinal, current_modref->ldr.FullDllName,\r
278                     (void *)thunk_list->u1.Function );\r
279             }\r
280           TRACE("--- Ordinal %s.%d = %p\n", name, ordinal, (void *)thunk_list->u1.Function );\r
281         }\r
282       else  /* import by name */\r
283         {\r
284           IMAGE_IMPORT_BY_NAME *pe_name;\r
285           const char *symname = (const char*)pe_name->Name;\r
286           pe_name = get_rva( module, (DWORD)import_list->u1.AddressOfData );\r
287 \r
288           //      thunk_list->u1.Function = (ULONG_PTR)find_named_export( imp_mod, exports, exp_size,\r
289           //                                                              (const char*)pe_name->Name,\r
290           //                                                              pe_name->Hint, load_path );\r
291 \r
292 #ifdef USE_DLMALLOC\r
293           if (iscoredll)\r
294             {\r
295               if (! strcmp (symname, "malloc"))\r
296                 thunk_list->u1.Function = (PWORD) dlmalloc;\r
297               else if (! strcmp (symname, "calloc"))\r
298                 thunk_list->u1.Function = (PWORD) dlcalloc;\r
299               else if (! strcmp (symname, "free"))\r
300                 thunk_list->u1.Function = (PWORD) dlfree;\r
301               else if (! strcmp (symname, "realloc"))\r
302                 thunk_list->u1.Function = (PWORD) dlrealloc;\r
303               else\r
304                 thunk_list->u1.Function = (PDWORD)(ULONG_PTR)GetProcAddressA (imp_mod, symname);\r
305             }\r
306           else\r
307 #endif\r
308             thunk_list->u1.Function = (PDWORD)(ULONG_PTR)GetProcAddressA (imp_mod, (const char*)pe_name->Name);\r
309           if (!thunk_list->u1.Function)\r
310             {\r
311               thunk_list->u1.Function = (PDWORD) allocate_stub( name, (const char*)pe_name->Name );\r
312               TRACE("No implementation for %s.%s imported from %s, setting to %p\n",\r
313                     name, pe_name->Name, current_modref->ldr.FullDllName,\r
314                     (void *)thunk_list->u1.Function );\r
315             }\r
316           TRACE("--- %s %s.%d = %p\n",\r
317                 pe_name->Name, name, pe_name->Hint, (void *)thunk_list->u1.Function);\r
318         }\r
319       import_list++;\r
320       thunk_list++;\r
321     }\r
322   // done:\r
323 #if 0\r
324   /* restore old protection of the import address table */\r
325   NtProtectVirtualMemory( NtCurrentProcess(), &protect_base, &protect_size, protect_old, NULL );\r
326   return wmImp;\r
327 #endif\r
328   return (void*)1;\r
329 }\r
330 \r
331 \r
332 \r
333 /****************************************************************\r
334  *       fixup_imports\r
335  *\r
336  * Fixup all imports of a given module.\r
337  * The loader_section must be locked while calling this function.\r
338  */\r
339 static NTSTATUS fixup_imports( WINE_MODREF *wm, LPCWSTR load_path )\r
340 {\r
341   int i, nb_imports;\r
342   const IMAGE_IMPORT_DESCRIPTOR *imports;\r
343   WINE_MODREF *prev;\r
344   DWORD size;\r
345   NTSTATUS status;\r
346   //  ULONG_PTR cookie;\r
347 \r
348   if (!(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS)) return STATUS_SUCCESS;  /* already done */\r
349   wm->ldr.Flags &= ~LDR_DONT_RESOLVE_REFS;\r
350   \r
351   if (!(imports = MyRtlImageDirectoryEntryToData( wm->ldr.BaseAddress, TRUE,\r
352                                                   IMAGE_DIRECTORY_ENTRY_IMPORT, &size )))\r
353     return STATUS_SUCCESS;\r
354   \r
355   nb_imports = 0;\r
356   while (imports[nb_imports].Name && imports[nb_imports].FirstThunk) nb_imports++;\r
357   \r
358   if (!nb_imports) return STATUS_SUCCESS;  /* no imports */\r
359   \r
360 #if 0\r
361   if (!create_module_activation_context( &wm->ldr ))\r
362     RtlActivateActivationContext( 0, wm->ldr.ActivationContext, &cookie );\r
363 #endif\r
364   \r
365 #if 0\r
366   /* Allocate module dependency list */\r
367   wm->nDeps = nb_imports;\r
368   wm->deps  = RtlAllocateHeap( GetProcessHeap(), 0, nb_imports*sizeof(WINE_MODREF *) );\r
369 #endif\r
370 \r
371   /* load the imported modules. They are automatically\r
372    * added to the modref list of the process.\r
373    */\r
374   prev = current_modref;\r
375   current_modref = wm;\r
376   status = STATUS_SUCCESS;\r
377   for (i = 0; i < nb_imports; i++)\r
378     {\r
379       //      if (!(wm->deps[i] = import_dll( wm->ldr.BaseAddress, &imports[i], load_path )))\r
380       if (! import_dll( wm->ldr.BaseAddress, &imports[i], load_path ))\r
381         status = STATUS_DLL_NOT_FOUND;\r
382     }\r
383   current_modref = prev;\r
384   //  if (wm->ldr.ActivationContext) RtlDeactivateActivationContext( 0, cookie );\r
385   return status;\r
386 }\r
387 \r
388 \r
389 static BOOL is_dll_native_subsystem( HMODULE module, const IMAGE_NT_HEADERS *nt, LPCWSTR filename )\r
390 {\r
391         return FALSE;\r
392 }\r
393 \r
394 \r
395 /*************************************************************************\r
396  *              get_modref\r
397  *\r
398  * Looks for the referenced HMODULE in the current process\r
399  * The loader_section must be locked while calling this function.\r
400  */\r
401 static WINE_MODREF *get_modref( HMODULE hmod )\r
402 {\r
403   int i;\r
404   for (i = 0; i < nr_modrefs; i++)\r
405     if (modrefs[i]->ldr.BaseAddress == hmod)\r
406       return modrefs[i];\r
407   return NULL;\r
408 }\r
409 \r
410 \r
411 \r
412 static WINE_MODREF *alloc_module( HMODULE hModule, LPCWSTR filename )\r
413 {\r
414     WINE_MODREF *wm;\r
415     const WCHAR *p;\r
416     const IMAGE_NT_HEADERS *nt = MyRtlImageNtHeader(hModule);\r
417 #if 0\r
418     PLIST_ENTRY entry, mark;\r
419 #endif\r
420 \r
421     if (!(wm = malloc (sizeof(*wm)))) return NULL;\r
422 \r
423     wm->nDeps    = 0;\r
424     wm->deps     = NULL;\r
425 \r
426     wm->ldr.BaseAddress   = hModule;\r
427     wm->ldr.EntryPoint    = NULL;\r
428     wm->ldr.SizeOfImage   = nt->OptionalHeader.SizeOfImage;\r
429     wm->ldr.Flags         = LDR_DONT_RESOLVE_REFS;\r
430     wm->ldr.LoadCount     = 1;\r
431     wm->ldr.TlsIndex      = -1;\r
432     wm->ldr.SectionHandle = NULL;\r
433     wm->ldr.CheckSum      = 0;\r
434     wm->ldr.TimeDateStamp = 0;\r
435     wm->ldr.ActivationContext = 0;\r
436 \r
437     wcscpy (wm->ldr.FullDllName, filename);\r
438     if ((p = wcsrchr( wm->ldr.FullDllName, L'\\' ))) p++;\r
439     else p = wm->ldr.FullDllName;\r
440     wcscpy (wm->ldr.BaseDllName, p );\r
441 \r
442     if ((nt->FileHeader.Characteristics & IMAGE_FILE_DLL) && !is_dll_native_subsystem( hModule, nt, p ))\r
443     {\r
444         wm->ldr.Flags |= LDR_IMAGE_IS_DLL;\r
445         if (nt->OptionalHeader.AddressOfEntryPoint)\r
446             wm->ldr.EntryPoint = (char *)hModule + nt->OptionalHeader.AddressOfEntryPoint;\r
447     }\r
448 \r
449 #if 0\r
450     InsertTailList(&NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList,\r
451                    &wm->ldr.InLoadOrderModuleList);\r
452 \r
453     /* insert module in MemoryList, sorted in increasing base addresses */\r
454     mark = &NtCurrentTeb()->Peb->LdrData->InMemoryOrderModuleList;\r
455     for (entry = mark->Flink; entry != mark; entry = entry->Flink)\r
456     {\r
457         if (CONTAINING_RECORD(entry, LDR_MODULE, InMemoryOrderModuleList)->BaseAddress > wm->ldr.BaseAddress)\r
458             break;\r
459     }\r
460     entry->Blink->Flink = &wm->ldr.InMemoryOrderModuleList;\r
461     wm->ldr.InMemoryOrderModuleList.Blink = entry->Blink;\r
462     wm->ldr.InMemoryOrderModuleList.Flink = entry;\r
463     entry->Blink = &wm->ldr.InMemoryOrderModuleList;\r
464 \r
465     /* wait until init is called for inserting into this list */\r
466     wm->ldr.InInitializationOrderModuleList.Flink = NULL;\r
467     wm->ldr.InInitializationOrderModuleList.Blink = NULL;\r
468 #endif\r
469 \r
470     modrefs[nr_modrefs++] = wm;\r
471 \r
472     return wm;\r
473 }\r
474 \r
475 \r
476 static NTSTATUS load_native_dll( LPCWSTR load_path, LPCWSTR name, HANDLE file,\r
477                                  DWORD flags, WINE_MODREF** pwm )\r
478 {\r
479   void *module;\r
480   HANDLE mapping;\r
481   LARGE_INTEGER size;\r
482   SIZE_T len = 0;\r
483   WINE_MODREF *wm;\r
484   NTSTATUS status;\r
485 \r
486   TRACE("Trying native dll %S\n", name);\r
487   \r
488   size.QuadPart = 0;\r
489   status = MyNtCreateSection( &mapping, STANDARD_RIGHTS_REQUIRED | SECTION_QUERY | SECTION_MAP_READ,\r
490                               NULL, &size, PAGE_READONLY, SEC_IMAGE, file );\r
491   if (status != STATUS_SUCCESS) return status;\r
492   \r
493   module = NULL;\r
494   status = MyNtMapViewOfSection( mapping, NtCurrentProcess(),\r
495                                  &module, 0, 0, &size, &len, ViewShare, 0, PAGE_READONLY );\r
496   CloseHandle( mapping );\r
497   if (status < 0) return status;\r
498   \r
499   /* create the MODREF */\r
500   \r
501   if (!(wm = alloc_module( module, name ))) return STATUS_NO_MEMORY;\r
502   \r
503   /* fixup imports */\r
504   \r
505   if (!(flags & DONT_RESOLVE_DLL_REFERENCES))\r
506     {\r
507 #if 1\r
508       return (STATUS_NOT_IMPLEMENTED);\r
509 #else\r
510       if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS)\r
511         {\r
512 #if 0\r
513           /* the module has only be inserted in the load & memory order lists */\r
514           RemoveEntryList(&wm->ldr.InLoadOrderModuleList);\r
515           RemoveEntryList(&wm->ldr.InMemoryOrderModuleList);\r
516           \r
517           /* FIXME: there are several more dangling references\r
518            * left. Including dlls loaded by this dll before the\r
519            * failed one. Unrolling is rather difficult with the\r
520            * current structure and we can leave them lying\r
521            * around with no problems, so we don't care.\r
522            * As these might reference our wm, we don't free it.\r
523            */\r
524 #endif\r
525           return status;\r
526         }\r
527 #endif\r
528     }\r
529   \r
530   TRACE( "Loaded %S at %p: native\n", wm->ldr.FullDllName, module );\r
531   \r
532   wm->ldr.LoadCount = 1;\r
533   *pwm = wm;\r
534   return STATUS_SUCCESS;\r
535 }\r
536 \r
537 \r
538 static NTSTATUS find_dll_file( const WCHAR *load_path, const WCHAR *libname,\r
539                                WCHAR *filename, ULONG *size, WINE_MODREF **pwm, HANDLE *handle )\r
540 {\r
541   HMODULE hnd = GetModuleHandle (NULL);\r
542   int len;\r
543   \r
544   assert (handle);\r
545   assert (*size == MAX_PATH);\r
546   \r
547   if (libname[0] == L'/' || libname[0] == L'\\')\r
548     {\r
549       wcscpy (filename, libname);\r
550     }\r
551   else\r
552     {\r
553       len = GetModuleFileName (hnd, filename, MAX_PATH);\r
554       filename[len++] = L'\\';\r
555       wcscpy (&filename[len], libname);\r
556     }\r
557   TRACE( "opening %S\n", filename);\r
558   \r
559   if (handle)\r
560     {\r
561       *handle = CreateFile( filename, GENERIC_READ, FILE_SHARE_READ, NULL,\r
562                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );\r
563       TRACE ("find_dll_file: 0x%p (0x%x)\n", *handle, GetFileSize (*handle, NULL));\r
564     }\r
565   return STATUS_SUCCESS;\r
566 }\r
567 \r
568 \r
569 static NTSTATUS load_dll( LPCWSTR load_path, LPCWSTR libname, DWORD flags, WINE_MODREF** pwm )\r
570 {\r
571     WCHAR filename[MAX_PATH];\r
572     ULONG size;\r
573     HANDLE handle = 0;\r
574     NTSTATUS nts;\r
575 \r
576     TRACE( "looking for %S in %S\n", libname, load_path ? load_path : L"default path" );\r
577 \r
578     *pwm = NULL;\r
579     size = MAX_PATH;\r
580     find_dll_file( load_path, libname, filename, &size, pwm, &handle );\r
581     \r
582     if (!handle)\r
583       nts = STATUS_DLL_NOT_FOUND;\r
584     else\r
585       nts = load_native_dll( load_path, filename, handle, flags, pwm );\r
586     \r
587     if (nts == STATUS_SUCCESS)\r
588       {\r
589         /* Initialize DLL just loaded */\r
590         TRACE("Loaded module %S at %p\n", filename, (*pwm)->ldr.BaseAddress);\r
591         if (handle)\r
592           CloseHandle( handle );\r
593         return nts;\r
594       }\r
595     \r
596     TRACE("Failed to load module %S; status=%x\n", libname, nts);\r
597     if (handle)\r
598       CloseHandle( handle );\r
599     return nts;\r
600 }\r
601 \r
602 \r
603 NTSTATUS MyLdrLoadDll(LPCWSTR path_name, DWORD flags,\r
604                       LPCWSTR libname, HMODULE* hModule)\r
605 {\r
606   WINE_MODREF *wm;\r
607   NTSTATUS nts;\r
608 \r
609   /* Support for dll path removed.  */\r
610   nts = load_dll( path_name, libname, flags, &wm );\r
611 \r
612   /* For now.  */\r
613   assert (wm->ldr.Flags & LDR_DONT_RESOLVE_REFS);\r
614 #if 0\r
615   if (nts == STATUS_SUCCESS && !(wm->ldr.Flags & LDR_DONT_RESOLVE_REFS))\r
616     {\r
617       nts = process_attach( wm, NULL );\r
618       if (nts != STATUS_SUCCESS)\r
619         {\r
620           LdrUnloadDll(wm->ldr.BaseAddress);\r
621           wm = NULL;\r
622         }\r
623     }\r
624 #endif\r
625   *hModule = (wm) ? wm->ldr.BaseAddress : NULL;\r
626 \r
627   return nts;\r
628 }\r
629 \r
630 \r
631 \r
632 /***********************************************************************\r
633  *           LdrProcessRelocationBlock  (NTDLL.@)\r
634  *\r
635  * Apply relocations to a given page of a mapped PE image.\r
636  */\r
637 IMAGE_BASE_RELOCATION * MyLdrProcessRelocationBlock( void *page, UINT count,\r
638                                                      USHORT *relocs, INT_PTR delta )\r
639 {\r
640   while (count--)\r
641     {\r
642       USHORT offset = *relocs & 0xfff;\r
643       int type = *relocs >> 12;\r
644       switch(type)\r
645         {\r
646         case IMAGE_REL_BASED_ABSOLUTE:\r
647           break;\r
648 #if 1\r
649         case IMAGE_REL_BASED_HIGH:\r
650           *(short *)((char *)page + offset) += HIWORD(delta);\r
651           break;\r
652         case IMAGE_REL_BASED_LOW:\r
653           *(short *)((char *)page + offset) += LOWORD(delta);\r
654           break;\r
655         case IMAGE_REL_BASED_HIGHLOW:\r
656           *(int *)((char *)page + offset) += delta;\r
657           break;\r
658 #else\r
659         case IMAGE_REL_BASED_DIR64:\r
660           *(INT_PTR *)((char *)page + offset) += delta;\r
661           break;\r
662 #endif\r
663         default:\r
664           TRACE("Unknown/unsupported fixup type %x.\n", type);\r
665           return NULL;\r
666         }\r
667       relocs++;\r
668     }\r
669   return (IMAGE_BASE_RELOCATION *)relocs;  /* return address of next block */\r
670 }\r
671 \r
672 \r
673 void MyLdrInitializeThunk( void *kernel_start, ULONG_PTR unknown2,\r
674                            ULONG_PTR unknown3, ULONG_PTR unknown4 )\r
675 {\r
676   static const WCHAR globalflagW[] = {'G','l','o','b','a','l','F','l','a','g',0};\r
677   NTSTATUS status;\r
678   WINE_MODREF *wm;\r
679   LPCWSTR load_path = NULL;\r
680   PEB *peb = current_peb();\r
681   IMAGE_NT_HEADERS *nt = MyRtlImageNtHeader( peb->ImageBaseAddress );\r
682   void (*_kernel_start) (void *ptr) = kernel_start;\r
683 \r
684 #if 0\r
685   if (main_exe_file) NtClose( main_exe_file );  /* at this point the main module is created */\r
686 #endif\r
687 \r
688   /* allocate the modref for the main exe (if not already done) */\r
689   wm = get_modref( peb->ImageBaseAddress );\r
690   assert( wm );\r
691   if (wm->ldr.Flags & LDR_IMAGE_IS_DLL)\r
692     {\r
693       TRACE("%S is a dll, not an executable\n", wm->ldr.FullDllName );\r
694       exit(1);\r
695     }\r
696 \r
697   //  peb->ProcessParameters->ImagePathName = wm->ldr.FullDllName;\r
698   //  version_init( wm->ldr.FullDllName );\r
699 \r
700   //  LdrQueryImageFileExecutionOptions( &peb->ProcessParameters->ImagePathName, globalflagW,\r
701   //                                 REG_DWORD, &peb->NtGlobalFlag, sizeof(peb->NtGlobalFlag), NULL );\r
702 \r
703   /* the main exe needs to be the first in the load order list */\r
704   //  RemoveEntryList( &wm->ldr.InLoadOrderModuleList );\r
705   //  InsertHeadList( &peb->LdrData->InLoadOrderModuleList, &wm->ldr.InLoadOrderModuleList );\r
706 \r
707   //  if ((status = virtual_alloc_thread_stack( NtCurrentTeb(), 0, 0 )) != STATUS_SUCCESS) goto error;\r
708   //  if ((status = server_init_process_done()) != STATUS_SUCCESS) goto error;\r
709 \r
710   //  actctx_init();\r
711   //  load_path = NtCurrentTeb()->Peb->ProcessParameters->DllPath.Buffer;\r
712   if ((status = fixup_imports( wm, load_path )) != STATUS_SUCCESS) goto error;\r
713   //  if ((status = alloc_process_tls()) != STATUS_SUCCESS) goto error;\r
714   //  if ((status = alloc_thread_tls()) != STATUS_SUCCESS) goto error;\r
715   //  heap_set_debug_flags( GetProcessHeap() );\r
716 \r
717 #if 0\r
718   /* FIXME: This may be interesting at some point.  */\r
719   status = wine_call_on_stack( attach_process_dlls, wm, NtCurrentTeb()->Tib.StackBase );\r
720   if (status != STATUS_SUCCESS) goto error;\r
721 #endif\r
722 \r
723   //  virtual_release_address_space( nt->FileHeader.Characteristics & IMAGE_FILE_LARGE_ADDRESS_AWARE );\r
724   //  virtual_clear_thread_stack();\r
725   //  wine_switch_to_stack( start_process, kernel_start, NtCurrentTeb()->Tib.StackBase );\r
726   // stack( start_process, kernel_start, NtCurrentTeb()->Tib.StackBase );\r
727   _kernel_start (peb);\r
728 \r
729  error:\r
730   TRACE( "Main exe initialization for %S failed, status %x\n",\r
731          wm->ldr.FullDllName, status);\r
732          //      peb->ProcessParameters->ImagePathName, status );\r
733   //  NtTerminateProcess( GetCurrentProcess(), status );\r
734   exit (1);\r
735 }\r