Remove extra #include directives from winspool.h.
[wine] / loader / pe_image.c
1 /*
2  *  Copyright   1994    Eric Youndale & Erik Bos
3  *  Copyright   1995    Martin von Löwis
4  *  Copyright   1996-98 Marcus Meissner
5  *
6  *      based on Eric Youndale's pe-test and:
7  *      ftp.microsoft.com:/developr/MSDN/OctCD/PEFILE.ZIP
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2.1 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 /* Notes:
24  * Before you start changing something in this file be aware of the following:
25  *
26  * - There are several functions called recursively. In a very subtle and
27  *   obscure way. DLLs can reference each other recursively etc.
28  * - If you want to enhance, speed up or clean up something in here, think
29  *   twice WHY it is implemented in that strange way. There is usually a reason.
30  *   Though sometimes it might just be lazyness ;)
31  * - In PE_MapImage, right before PE_fixup_imports() all external and internal
32  *   state MUST be correct since this function can be called with the SAME image
33  *   AGAIN. (Thats recursion for you.) That means MODREF.module and
34  *   NE_MODULE.module32.
35  */
36
37 #include "config.h"
38
39 #include <sys/types.h>
40 #ifdef HAVE_SYS_MMAN_H
41 #include <sys/mman.h>
42 #endif
43 #include <string.h>
44 #include "wine/winbase16.h"
45 #include "winerror.h"
46 #include "snoop.h"
47 #include "wine/server.h"
48 #include "wine/debug.h"
49
50 WINE_DEFAULT_DEBUG_CHANNEL(win32);
51 WINE_DECLARE_DEBUG_CHANNEL(module);
52 WINE_DECLARE_DEBUG_CHANNEL(relay);
53
54
55 /* convert PE image VirtualAddress to Real Address */
56 inline static void *get_rva( HMODULE module, DWORD va )
57 {
58     return (void *)((char *)module + va);
59 }
60
61 #define AdjustPtr(ptr,delta) ((char *)(ptr) + (delta))
62
63 void dump_exports( HMODULE hModule )
64 {
65   char          *Module;
66   int           i, j;
67   WORD          *ordinal;
68   DWORD         *function,*functions;
69   DWORD *name;
70   IMAGE_EXPORT_DIRECTORY *pe_exports;
71   DWORD rva_start, size;
72
73   pe_exports = RtlImageDirectoryEntryToData( hModule, TRUE, IMAGE_DIRECTORY_ENTRY_EXPORT, &size );
74   rva_start = (char *)pe_exports - (char *)hModule;
75
76   Module = get_rva(hModule, pe_exports->Name);
77   DPRINTF("*******EXPORT DATA*******\n");
78   DPRINTF("Module name is %s, %ld functions, %ld names\n",
79           Module, pe_exports->NumberOfFunctions, pe_exports->NumberOfNames);
80
81   ordinal = get_rva(hModule, pe_exports->AddressOfNameOrdinals);
82   functions = function = get_rva(hModule, pe_exports->AddressOfFunctions);
83   name = get_rva(hModule, pe_exports->AddressOfNames);
84
85   DPRINTF(" Ord    RVA     Addr   Name\n" );
86   for (i=0;i<pe_exports->NumberOfFunctions;i++, function++)
87   {
88       if (!*function) continue;  /* No such function */
89       DPRINTF( "%4ld %08lx %p", i + pe_exports->Base, *function, get_rva(hModule, *function) );
90       /* Check if we have a name for it */
91       for (j = 0; j < pe_exports->NumberOfNames; j++)
92           if (ordinal[j] == i)
93           {
94               DPRINTF( "  %s", (char*)get_rva(hModule, name[j]) );
95               break;
96           }
97       if ((*function >= rva_start) && (*function <= rva_start + size))
98           DPRINTF(" (forwarded -> %s)", (char *)get_rva(hModule, *function));
99       DPRINTF("\n");
100   }
101 }
102
103 /* Look up the specified function or ordinal in the export list:
104  * If it is a string:
105  *      - look up the name in the name list.
106  *      - look up the ordinal with that index.
107  *      - use the ordinal as offset into the functionlist
108  * If it is an ordinal:
109  *      - use ordinal-pe_export->Base as offset into the function list
110  */
111 static FARPROC PE_FindExportedFunction(
112         WINE_MODREF *wm,        /* [in] WINE modreference */
113         LPCSTR funcName,        /* [in] function name */
114         int hint,
115         BOOL snoop )
116 {
117         WORD                            * ordinals;
118         DWORD                           * function;
119         int                             i, ordinal;
120         DWORD                           rva_start, addr;
121         char                            * forward;
122         DWORD *name;
123         char *ename = NULL;
124         FARPROC proc;
125         IMAGE_EXPORT_DIRECTORY *exports;
126         DWORD exp_size;
127
128         if (!(exports = RtlImageDirectoryEntryToData( wm->module, TRUE,
129                                                       IMAGE_DIRECTORY_ENTRY_EXPORT, &exp_size )))
130             return NULL;
131
132         if (HIWORD(funcName)) TRACE("(%s)\n",funcName);
133         else TRACE("(%d)\n",LOWORD(funcName));
134
135         ordinals= get_rva(wm->module, exports->AddressOfNameOrdinals);
136         function= get_rva(wm->module, exports->AddressOfFunctions);
137         name    = get_rva(wm->module, exports->AddressOfNames);
138         forward = NULL;
139         rva_start = (char *)exports - (char *)wm->module;
140
141         if (HIWORD(funcName))
142         {
143             int min = 0, max = exports->NumberOfNames - 1;
144
145             /* first check the hint */
146             if (hint >= 0 && hint <= max)
147             {
148                 ename = get_rva(wm->module, name[hint]);
149                 if (!strcmp( ename, funcName ))
150                 {
151                     ordinal = ordinals[hint];
152                     goto found;
153                 }
154             }
155
156             /* then do a binary search */
157             while (min <= max)
158             {
159                 int res, pos = (min + max) / 2;
160                 ename = get_rva(wm->module, name[pos]);
161                 if (!(res = strcmp( ename, funcName )))
162                 {
163                     ordinal = ordinals[pos];
164                     goto found;
165                 }
166                 if (res > 0) max = pos - 1;
167                 else min = pos + 1;
168             }
169             return NULL;
170         }
171         else  /* find by ordinal */
172         {
173             ordinal = LOWORD(funcName) - exports->Base;
174             if (snoop && name)  /* need to find a name for it */
175             {
176                 for (i = 0; i < exports->NumberOfNames; i++)
177                     if (ordinals[i] == ordinal)
178                     {
179                         ename = get_rva(wm->module, name[i]);
180                         break;
181                     }
182             }
183         }
184
185  found:
186         if (ordinal >= exports->NumberOfFunctions)
187         {
188             TRACE("     ordinal %ld out of range!\n", ordinal + exports->Base );
189             return NULL;
190         }
191         addr = function[ordinal];
192         if (!addr) return NULL;
193
194         proc = get_rva(wm->module, addr);
195         if (((char *)proc < (char *)exports) || ((char *)proc >= (char *)exports + exp_size))
196         {
197             if (snoop)
198             {
199                 if (!ename) ename = "@";
200                 proc = SNOOP_GetProcAddress(wm->module,ename,ordinal,proc);
201             }
202             return proc;
203         }
204         else  /* forward entry point */
205         {
206                 WINE_MODREF *wm_fw;
207                 char *forward = (char *)proc;
208                 char module[256];
209                 char *end = strchr(forward, '.');
210
211                 if (!end) return NULL;
212                 if (end - forward >= sizeof(module)) return NULL;
213                 memcpy( module, forward, end - forward );
214                 module[end-forward] = 0;
215                 if (!(wm_fw = MODULE_FindModule( module )))
216                 {
217                     ERR("module not found for forward '%s' used by '%s'\n", forward, wm->modname );
218                     return NULL;
219                 }
220                 if (!(proc = MODULE_GetProcAddress( wm_fw->module, end + 1, -1, snoop )))
221                     ERR("function not found for forward '%s' used by '%s'. If you are using builtin '%s', try using the native one instead.\n", forward, wm->modname, wm->modname );
222                 return proc;
223         }
224 }
225
226 /****************************************************************
227  *      PE_fixup_imports
228  */
229 DWORD PE_fixup_imports( WINE_MODREF *wm )
230 {
231     int i,characteristics_detection=1;
232     IMAGE_IMPORT_DESCRIPTOR *imports, *pe_imp;
233     DWORD size;
234
235     imports = RtlImageDirectoryEntryToData( wm->module, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &size );
236
237     /* first, count the number of imported non-internal modules */
238     pe_imp = imports;
239     if (!pe_imp) return 0;
240
241     /* OK, now dump the import list */
242     TRACE("Dumping imports list\n");
243
244     /* We assume that we have at least one import with !0 characteristics and
245      * detect broken imports with all characteristics 0 (notably Borland) and
246      * switch the detection off for them.
247      */
248     for (i = 0; pe_imp->Name ; pe_imp++) {
249         if (!i && !pe_imp->u.Characteristics)
250                 characteristics_detection = 0;
251         if (characteristics_detection && !pe_imp->u.Characteristics)
252                 break;
253         i++;
254     }
255     if (!i) return 0;  /* no imports */
256
257     /* Allocate module dependency list */
258     wm->nDeps = i;
259     wm->deps  = HeapAlloc( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) );
260
261     /* load the imported modules. They are automatically
262      * added to the modref list of the process.
263      */
264
265     for (i = 0, pe_imp = imports; pe_imp->Name ; pe_imp++) {
266         WINE_MODREF             *wmImp;
267         IMAGE_IMPORT_BY_NAME    *pe_name;
268         PIMAGE_THUNK_DATA       import_list,thunk_list;
269         char                    *name = get_rva(wm->module, pe_imp->Name);
270
271         if (characteristics_detection && !pe_imp->u.Characteristics)
272                 break;
273
274         wmImp = MODULE_LoadLibraryExA( name, 0, 0 );
275         if (!wmImp) {
276             ERR_(module)("Module (file) %s (which is needed by %s) not found\n", name, wm->filename);
277             return 1;
278         }
279         wm->deps[i++] = wmImp;
280
281         /* FIXME: forwarder entries ... */
282
283         if (pe_imp->u.OriginalFirstThunk != 0) { /* original MS style */
284             TRACE("Microsoft style imports used\n");
285             import_list = get_rva(wm->module, (DWORD)pe_imp->u.OriginalFirstThunk);
286             thunk_list = get_rva(wm->module, (DWORD)pe_imp->FirstThunk);
287
288             while (import_list->u1.Ordinal) {
289                 if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) {
290                     int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
291
292                     TRACE("--- Ordinal %s,%d\n", name, ordinal);
293                     thunk_list->u1.Function=(PDWORD)MODULE_GetProcAddress(
294                         wmImp->module, (LPCSTR)ordinal, -1, TRUE
295                     );
296                     if (!thunk_list->u1.Function) {
297                         ERR("No implementation for %s.%d imported from %s, setting to 0xdeadbeef\n",
298                                 name, ordinal, wm->filename );
299                         thunk_list->u1.Function = (PDWORD)0xdeadbeef;
300                     }
301                 } else {                /* import by name */
302                     pe_name = get_rva(wm->module, (DWORD)import_list->u1.AddressOfData);
303                     TRACE("--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint);
304                     thunk_list->u1.Function=(PDWORD)MODULE_GetProcAddress(
305                         wmImp->module, pe_name->Name, pe_name->Hint, TRUE
306                     );
307                     if (!thunk_list->u1.Function) {
308                         ERR("No implementation for %s.%d(%s) imported from %s, setting to 0xdeadbeef\n",
309                                 name,pe_name->Hint,pe_name->Name,wm->filename);
310                         thunk_list->u1.Function = (PDWORD)0xdeadbeef;
311                     }
312                 }
313                 import_list++;
314                 thunk_list++;
315             }
316         } else {        /* Borland style */
317             TRACE("Borland style imports used\n");
318             thunk_list = get_rva(wm->module, (DWORD)pe_imp->FirstThunk);
319             while (thunk_list->u1.Ordinal) {
320                 if (IMAGE_SNAP_BY_ORDINAL(thunk_list->u1.Ordinal)) {
321                     /* not sure about this branch, but it seems to work */
322                     int ordinal = IMAGE_ORDINAL(thunk_list->u1.Ordinal);
323
324                     TRACE("--- Ordinal %s.%d\n",name,ordinal);
325                     thunk_list->u1.Function=(PDWORD)MODULE_GetProcAddress(
326                         wmImp->module, (LPCSTR) ordinal, -1, TRUE
327                     );
328                     if (!thunk_list->u1.Function) {
329                         ERR("No implementation for %s.%d imported from %s, setting to 0xdeadbeef\n",
330                                 name,ordinal, wm->filename);
331                         thunk_list->u1.Function = (PDWORD)0xdeadbeef;
332                     }
333                 } else {
334                     pe_name=get_rva(wm->module, (DWORD)thunk_list->u1.AddressOfData);
335                     TRACE("--- %s %s.%d\n",
336                                   pe_name->Name,name,pe_name->Hint);
337                     thunk_list->u1.Function=(PDWORD)MODULE_GetProcAddress(
338                         wmImp->module, pe_name->Name, pe_name->Hint, TRUE
339                     );
340                     if (!thunk_list->u1.Function) {
341                         ERR("No implementation for %s.%d(%s) imported from %s, setting to 0xdeadbeef\n",
342                                 name, pe_name->Hint, pe_name->Name, wm->filename);
343                         thunk_list->u1.Function = (PDWORD)0xdeadbeef;
344                     }
345                 }
346                 thunk_list++;
347             }
348         }
349     }
350     return 0;
351 }
352
353 /**********************************************************************
354  *                      PE_LoadImage
355  * Load one PE format DLL/EXE into memory
356  *
357  * Unluckily we can't just mmap the sections where we want them, for
358  * (at least) Linux does only support offsets which are page-aligned.
359  *
360  * BUT we have to map the whole image anyway, for Win32 programs sometimes
361  * want to access them. (HMODULE points to the start of it)
362  */
363 HMODULE PE_LoadImage( HANDLE hFile, LPCSTR filename, DWORD flags )
364 {
365     IMAGE_NT_HEADERS *nt;
366     HMODULE hModule;
367     HANDLE mapping;
368     void *base;
369
370     TRACE_(module)( "loading %s\n", filename );
371
372     mapping = CreateFileMappingA( hFile, NULL, SEC_IMAGE, 0, 0, NULL );
373     if (!mapping) return 0;
374     base = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
375     CloseHandle( mapping );
376     if (!base) return 0;
377
378     /* virus check */
379
380     hModule = (HMODULE)base;
381     nt = RtlImageNtHeader( hModule );
382
383     if (nt->OptionalHeader.AddressOfEntryPoint)
384     {
385         if (!RtlImageRvaToSection( nt, hModule, nt->OptionalHeader.AddressOfEntryPoint ))
386             MESSAGE("VIRUS WARNING: PE module has an invalid entrypoint (0x%08lx) "
387                     "outside all sections (possibly infected by Tchernobyl/SpaceFiller virus)!\n",
388                     nt->OptionalHeader.AddressOfEntryPoint );
389     }
390
391     return hModule;
392 }
393
394 /**********************************************************************
395  *                 PE_CreateModule
396  *
397  * Create WINE_MODREF structure for loaded HMODULE, link it into
398  * process modref_list, and fixup all imports.
399  *
400  * Note: hModule must point to a correctly allocated PE image,
401  *       with base relocations applied; the 16-bit dummy module
402  *       associated to hModule must already exist.
403  *
404  * Note: This routine must always be called in the context of the
405  *       process that is to own the module to be created.
406  *
407  * Note: Assumes that the process critical section is held
408  */
409 WINE_MODREF *PE_CreateModule( HMODULE hModule, LPCSTR filename, DWORD flags,
410                               HANDLE hFile, BOOL builtin )
411 {
412     IMAGE_NT_HEADERS *nt;
413     IMAGE_DATA_DIRECTORY *dir;
414     IMAGE_EXPORT_DIRECTORY *pe_export = NULL;
415     WINE_MODREF *wm;
416     HMODULE16 hModule16;
417
418     /* Retrieve DataDirectory entries */
419
420     nt = RtlImageNtHeader(hModule);
421     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT;
422     if (dir->Size) pe_export = get_rva(hModule, dir->VirtualAddress);
423
424     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXCEPTION;
425     if (dir->Size) FIXME("Exception directory ignored\n" );
426
427     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_SECURITY;
428     if (dir->Size) FIXME("Security directory ignored\n" );
429
430     /* IMAGE_DIRECTORY_ENTRY_BASERELOC handled in PE_LoadImage */
431     /* IMAGE_DIRECTORY_ENTRY_DEBUG handled by debugger */
432
433     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_GLOBALPTR;
434     if (dir->Size) FIXME("Global Pointer (MIPS) ignored\n" );
435
436     /* IMAGE_DIRECTORY_ENTRY_TLS handled in PE_TlsInit */
437
438     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG;
439     if (dir->Size) FIXME("Load Configuration directory ignored\n" );
440
441     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT;
442     if (dir->Size) TRACE("Bound Import directory ignored\n" );
443
444     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IAT;
445     if (dir->Size) TRACE("Import Address Table directory ignored\n" );
446
447     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT;
448     if (dir->Size)
449     {
450         TRACE("Delayed import, stub calls LoadLibrary\n" );
451         /*
452          * Nothing to do here.
453          */
454
455 #ifdef ImgDelayDescr
456         /*
457          * This code is useful to observe what the heck is going on.
458          */
459         {
460             ImgDelayDescr *pe_delay = NULL;
461             pe_delay = get_rva(hModule, dir->VirtualAddress);
462             TRACE("pe_delay->grAttrs = %08x\n", pe_delay->grAttrs);
463             TRACE("pe_delay->szName = %s\n", pe_delay->szName);
464             TRACE("pe_delay->phmod = %08x\n", pe_delay->phmod);
465             TRACE("pe_delay->pIAT = %08x\n", pe_delay->pIAT);
466             TRACE("pe_delay->pINT = %08x\n", pe_delay->pINT);
467             TRACE("pe_delay->pBoundIAT = %08x\n", pe_delay->pBoundIAT);
468             TRACE("pe_delay->pUnloadIAT = %08x\n", pe_delay->pUnloadIAT);
469             TRACE("pe_delay->dwTimeStamp = %08x\n", pe_delay->dwTimeStamp);
470         }
471 #endif /* ImgDelayDescr */
472     }
473
474     dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR;
475     if (dir->Size) FIXME("Unknown directory 14 ignored\n" );
476
477     dir = nt->OptionalHeader.DataDirectory+15;
478     if (dir->Size) FIXME("Unknown directory 15 ignored\n" );
479
480     /* Create 16-bit dummy module */
481
482     if ((hModule16 = MODULE_CreateDummyModule( filename, hModule )) < 32)
483     {
484         SetLastError( (DWORD)hModule16 );       /* This should give the correct error */
485         return NULL;
486     }
487
488     /* Allocate and fill WINE_MODREF */
489
490     if (!(wm = MODULE_AllocModRef( hModule, filename )))
491     {
492         FreeLibrary16( hModule16 );
493         return NULL;
494     }
495     wm->hDummyMod = hModule16;
496
497     if ( builtin )
498     {
499         NE_MODULE *pModule = (NE_MODULE *)GlobalLock16( hModule16 );
500         pModule->flags |= NE_FFLAGS_BUILTIN;
501         wm->flags |= WINE_MODREF_INTERNAL;
502     }
503     else if ( flags & DONT_RESOLVE_DLL_REFERENCES )
504         wm->flags |= WINE_MODREF_DONT_RESOLVE_REFS;
505
506     wm->find_export = PE_FindExportedFunction;
507
508     /* Dump Exports */
509
510     if (pe_export && TRACE_ON(win32))
511         dump_exports( hModule );
512
513     /* Fixup Imports */
514
515     if (!(wm->flags & WINE_MODREF_DONT_RESOLVE_REFS) &&
516         PE_fixup_imports( wm ))
517     {
518         /* remove entry from modref chain */
519
520         if ( !wm->prev )
521             MODULE_modref_list = wm->next;
522         else
523             wm->prev->next = wm->next;
524
525         if ( wm->next ) wm->next->prev = wm->prev;
526         wm->next = wm->prev = NULL;
527
528         /* FIXME: there are several more dangling references
529          * left. Including dlls loaded by this dll before the
530          * failed one. Unrolling is rather difficult with the
531          * current structure and we can leave them lying
532          * around with no problems, so we don't care.
533          * As these might reference our wm, we don't free it.
534          */
535          return NULL;
536     }
537
538     if (!builtin && pe_export)
539         SNOOP_RegisterDLL( hModule, wm->modname, pe_export->Base, pe_export->NumberOfFunctions );
540
541     /* Send DLL load event */
542     /* we don't need to send a dll event for the main exe */
543
544     if (nt->FileHeader.Characteristics & IMAGE_FILE_DLL)
545     {
546         if (hFile)
547         {
548             UINT drive_type = GetDriveTypeA( wm->short_filename );
549             /* don't keep the file handle open on removable media */
550             if (drive_type == DRIVE_REMOVABLE || drive_type == DRIVE_CDROM) hFile = 0;
551         }
552         SERVER_START_REQ( load_dll )
553         {
554             req->handle     = hFile;
555             req->base       = (void *)hModule;
556             req->size       = nt->OptionalHeader.SizeOfImage;
557             req->dbg_offset = nt->FileHeader.PointerToSymbolTable;
558             req->dbg_size   = nt->FileHeader.NumberOfSymbols;
559             req->name       = &wm->filename;
560             wine_server_add_data( req, wm->filename, strlen(wm->filename) );
561             wine_server_call( req );
562         }
563         SERVER_END_REQ;
564     }
565
566     return wm;
567 }
568
569 /******************************************************************************
570  * The PE Library Loader frontend.
571  * FIXME: handle the flags.
572  */
573 WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags)
574 {
575         HMODULE         hModule32;
576         WINE_MODREF     *wm;
577         HANDLE          hFile;
578
579         hFile = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ,
580                              NULL, OPEN_EXISTING, 0, 0 );
581         if ( hFile == INVALID_HANDLE_VALUE ) return NULL;
582
583         /* Load PE module */
584         hModule32 = PE_LoadImage( hFile, name, flags );
585         if (!hModule32)
586         {
587                 CloseHandle( hFile );
588                 return NULL;
589         }
590
591         /* Create 32-bit MODREF */
592         if ( !(wm = PE_CreateModule( hModule32, name, flags, hFile, FALSE )) )
593         {
594                 ERR( "can't load %s\n", name );
595                 CloseHandle( hFile );
596                 SetLastError( ERROR_OUTOFMEMORY );
597                 return NULL;
598         }
599
600         CloseHandle( hFile );
601         return wm;
602 }
603
604
605 /* Called if the library is loaded or freed.
606  * NOTE: if a thread attaches a DLL, the current thread will only do
607  * DLL_PROCESS_ATTACH. Only newly created threads do DLL_THREAD_ATTACH
608  * (SDK)
609  */
610 typedef DWORD (CALLBACK *DLLENTRYPROC)(HMODULE,DWORD,LPVOID);
611
612 BOOL PE_InitDLL( HMODULE module, DWORD type, LPVOID lpReserved )
613 {
614     BOOL retv = TRUE;
615     IMAGE_NT_HEADERS *nt = RtlImageNtHeader(module);
616
617     /* Is this a library? And has it got an entrypoint? */
618     if (nt && (nt->FileHeader.Characteristics & IMAGE_FILE_DLL) &&
619         (nt->OptionalHeader.AddressOfEntryPoint))
620     {
621         DLLENTRYPROC entry = (void*)((char*)module + nt->OptionalHeader.AddressOfEntryPoint);
622         if (TRACE_ON(relay))
623             DPRINTF("%08lx:Call PE DLL (proc=%p,module=%p,type=%ld,res=%p)\n",
624                     GetCurrentThreadId(), entry, module, type, lpReserved );
625         retv = entry( module, type, lpReserved );
626         if (TRACE_ON(relay))
627             DPRINTF("%08lx:Ret  PE DLL (proc=%p,module=%p,type=%ld,res=%p) retval=%x\n",
628                     GetCurrentThreadId(), entry, module, type, lpReserved, retv );
629     }
630
631     return retv;
632 }
633
634 /************************************************************************
635  *      PE_InitTls                      (internal)
636  *
637  * If included, initialises the thread local storages of modules.
638  * Pointers in those structs are not RVAs but real pointers which have been
639  * relocated by do_relocations() already.
640  */
641 static LPVOID
642 _fixup_address(PIMAGE_OPTIONAL_HEADER opt,int delta,LPVOID addr) {
643         if (    ((DWORD)addr>opt->ImageBase) &&
644                 ((DWORD)addr<opt->ImageBase+opt->SizeOfImage)
645         )
646                 /* the address has not been relocated! */
647                 return (LPVOID)(((DWORD)addr)+delta);
648         else
649                 /* the address has been relocated already */
650                 return addr;
651 }
652 void PE_InitTls( void )
653 {
654         WINE_MODREF             *wm;
655         IMAGE_NT_HEADERS        *peh;
656         DWORD                   size,datasize,dirsize;
657         LPVOID                  mem;
658         PIMAGE_TLS_DIRECTORY    pdir;
659         int delta;
660
661         for (wm = MODULE_modref_list;wm;wm=wm->next) {
662                 peh = RtlImageNtHeader(wm->module);
663                 pdir = RtlImageDirectoryEntryToData( wm->module, TRUE,
664                                                      IMAGE_DIRECTORY_ENTRY_TLS, &dirsize );
665                 if (!pdir) continue;
666                 delta = (char *)wm->module - (char *)peh->OptionalHeader.ImageBase;
667
668                 if ( wm->tlsindex == -1 ) {
669                         LPDWORD xaddr;
670                         wm->tlsindex = TlsAlloc();
671                         xaddr = _fixup_address(&(peh->OptionalHeader),delta,
672                                         pdir->AddressOfIndex
673                         );
674                         *xaddr=wm->tlsindex;
675                 }
676                 datasize= pdir->EndAddressOfRawData-pdir->StartAddressOfRawData;
677                 size    = datasize + pdir->SizeOfZeroFill;
678                 mem=VirtualAlloc(0,size,MEM_RESERVE|MEM_COMMIT,PAGE_READWRITE);
679                 memcpy(mem,_fixup_address(&(peh->OptionalHeader),delta,(LPVOID)pdir->StartAddressOfRawData),datasize);
680                 if (pdir->AddressOfCallBacks) {
681                      PIMAGE_TLS_CALLBACK *cbs;
682
683                      cbs = _fixup_address(&(peh->OptionalHeader),delta,pdir->AddressOfCallBacks);
684                      if (*cbs)
685                        FIXME("TLS Callbacks aren't going to be called\n");
686                 }
687
688                 TlsSetValue( wm->tlsindex, mem );
689         }
690 }