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