~ubuntu-branches/ubuntu/maverick/vlc/maverick

« back to all changes in this revision

Viewing changes to loader/pe_image.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler
  • Date: 2008-09-17 21:56:14 UTC
  • mfrom: (1.1.17 upstream)
  • Revision ID: james.westby@ubuntu.com-20080917215614-tj0vx8xzd57e52t8
Tags: 0.9.2-1ubuntu1
* New Upstream Release, exception granted by
    - dktrkranz, norsetto, Hobbsee (via irc). LP: #270404

Changes done in ubuntu:

* add libxul-dev to build-depends
* make sure that vlc is build against libxul in configure. This doesn't
  change anything in the package, but makes it more robust if building
  in an 'unclean' chroot or when modifying the package.
* debian/control: make Vcs-* fields point to the motumedia branch
* add libx264-dev and libass-dev to build-depends
  LP: #210354, #199870
* actually enable libass support by passing --enable-libass to configure
* enable libdca: add libdca-dev to build depends and --enable-libdca
* install the x264 plugin.

Changes already in the pkg-multimedia branch in debian:

* don't install usr/share/vlc/mozilla in debian/mozilla-plugin-vlc.install  
* new upstream .desktop file now registers flash video mimetype LP: #261567
* add Xb-Npp-Applications to mozilla-plugin-vlc
* remove duplicate entries in debian/vlc-nox.install

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * $Id: 13465a77cc168906e0e96136f34cdce06fa82d2d $
3
 
 *
4
 
 *  Copyright   1994    Eric Youndale & Erik Bos
5
 
 *  Copyright   1995    Martin von Löwis
6
 
 *  Copyright   1996-98 Marcus Meissner
7
 
 *
8
 
 *      based on Eric Youndale's pe-test and:
9
 
 *
10
 
 *      ftp.microsoft.com:/pub/developer/MSDN/CD8/PEFILE.ZIP
11
 
 * make that:
12
 
 *      ftp.microsoft.com:/developr/MSDN/OctCD/PEFILE.ZIP
13
 
 *
14
 
 * Modified for use with MPlayer, detailed CVS changelog at
15
 
 * http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
16
 
 *
17
 
 * File now distributed as part of VLC media player with no modifications.
18
 
 *
19
 
 * This program is free software; you can redistribute it and/or modify
20
 
 * it under the terms of the GNU General Public License as published by
21
 
 * the Free Software Foundation; either version 2 of the License, or
22
 
 * (at your option) any later version.
23
 
 *
24
 
 * This program is distributed in the hope that it will be useful,
25
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
27
 
 * GNU General Public License for more details.
28
 
 *
29
 
 * You should have received a copy of the GNU General Public License
30
 
 * along with this program; if not, write to the Free Software
31
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
32
 
 */
33
 
/* Notes:
34
 
 * Before you start changing something in this file be aware of the following:
35
 
 *
36
 
 * - There are several functions called recursively. In a very subtle and 
37
 
 *   obscure way. DLLs can reference each other recursively etc.
38
 
 * - If you want to enhance, speed up or clean up something in here, think
39
 
 *   twice WHY it is implemented in that strange way. There is usually a reason.
40
 
 *   Though sometimes it might just be lazyness ;)
41
 
 * - In PE_MapImage, right before fixup_imports() all external and internal 
42
 
 *   state MUST be correct since this function can be called with the SAME image
43
 
 *   AGAIN. (Thats recursion for you.) That means MODREF.module and
44
 
 *   NE_MODULE.module32.
45
 
 * - Sometimes, we can't use Linux mmap() to mmap() the images directly.
46
 
 *
47
 
 *   The problem is, that there is not direct 1:1 mapping from a diskimage and
48
 
 *   a memoryimage. The headers at the start are mapped linear, but the sections
49
 
 *   are not. Older x86 pe binaries are 512 byte aligned in file and 4096 byte
50
 
 *   aligned in memory. Linux likes them 4096 byte aligned in memory (due to
51
 
 *   x86 pagesize, this cannot be fixed without a rather large kernel rewrite)
52
 
 *   and 'blocksize' file-aligned (offsets). Since we have 512/1024/2048 (CDROM)
53
 
 *   and other byte blocksizes, we can't always do this.  We *can* do this for
54
 
 *   newer pe binaries produced by MSVC 5 and later, since they are also aligned
55
 
 *   to 4096 byte boundaries on disk.
56
 
 */
57
 
#include "config.h"
58
 
 
59
 
#include <errno.h>
60
 
#include <assert.h>
61
 
#include <stdio.h>
62
 
#include <stdlib.h>
63
 
#include <string.h>
64
 
#include <unistd.h>
65
 
#include <sys/types.h>
66
 
#include <sys/stat.h>
67
 
#include <fcntl.h>
68
 
#ifdef HAVE_SYS_MMAN_H
69
 
#include <sys/mman.h>
70
 
#endif
71
 
#include "wine/windef.h"
72
 
#include "wine/winbase.h"
73
 
#include "wine/winerror.h"
74
 
#include "wine/heap.h"
75
 
#include "wine/pe_image.h"
76
 
#include "wine/module.h"
77
 
#include "wine/debugtools.h"
78
 
#include "ext.h"
79
 
#include "win32.h"
80
 
 
81
 
#define RVA(x) ((void *)((char *)load_addr+(unsigned int)(x)))
82
 
 
83
 
#define AdjustPtr(ptr,delta) ((char *)(ptr) + (delta))
84
 
 
85
 
extern void* LookupExternal(const char* library, int ordinal);
86
 
extern void* LookupExternalByName(const char* library, const char* name);
87
 
 
88
 
static void dump_exports( HMODULE hModule )
89
 
90
 
  char          *Module;
91
 
  unsigned int i, j;
92
 
  u_short       *ordinal;
93
 
  u_long        *function,*functions;
94
 
  u_char        **name;
95
 
  unsigned int load_addr = hModule;
96
 
 
97
 
  DWORD rva_start = PE_HEADER(hModule)->OptionalHeader
98
 
                   .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
99
 
  DWORD rva_end = rva_start + PE_HEADER(hModule)->OptionalHeader
100
 
                   .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
101
 
  IMAGE_EXPORT_DIRECTORY *pe_exports = (IMAGE_EXPORT_DIRECTORY*)RVA(rva_start);
102
 
 
103
 
  Module = (char*)RVA(pe_exports->Name);
104
 
  TRACE("*******EXPORT DATA*******\n");
105
 
  TRACE("Module name is %s, %ld functions, %ld names\n", 
106
 
        Module, pe_exports->NumberOfFunctions, pe_exports->NumberOfNames);
107
 
 
108
 
  ordinal=(u_short*) RVA(pe_exports->AddressOfNameOrdinals);
109
 
  functions=function=(u_long*) RVA(pe_exports->AddressOfFunctions);
110
 
  name=(u_char**) RVA(pe_exports->AddressOfNames);
111
 
 
112
 
  TRACE(" Ord    RVA     Addr   Name\n" );
113
 
  for (i=0;i<pe_exports->NumberOfFunctions;i++, function++)
114
 
  {
115
 
      if (!*function) continue;  
116
 
      if (TRACE_ON(win32))
117
 
      {
118
 
        DPRINTF( "%4ld %08lx %p", i + pe_exports->Base, *function, RVA(*function) );
119
 
        
120
 
        for (j = 0; j < pe_exports->NumberOfNames; j++)
121
 
          if (ordinal[j] == i)
122
 
          {
123
 
              DPRINTF( "  %s", (char*)RVA(name[j]) );
124
 
              break;
125
 
          }
126
 
        if ((*function >= rva_start) && (*function <= rva_end))
127
 
          DPRINTF(" (forwarded -> %s)", (char *)RVA(*function));
128
 
        DPRINTF("\n");
129
 
      }
130
 
  }
131
 
}
132
 
 
133
 
/* Look up the specified function or ordinal in the exportlist:
134
 
 * If it is a string:
135
 
 *      - look up the name in the Name list. 
136
 
 *      - look up the ordinal with that index.
137
 
 *      - use the ordinal as offset into the functionlist
138
 
 * If it is a ordinal:
139
 
 *      - use ordinal-pe_export->Base as offset into the functionlist
140
 
 */
141
 
FARPROC PE_FindExportedFunction( 
142
 
        WINE_MODREF *wm,        
143
 
        LPCSTR funcName,        
144
 
        WIN_BOOL snoop )
145
 
{
146
 
        u_short                         * ordinals;
147
 
        u_long                          * function;
148
 
        u_char                          ** name;
149
 
        const char *ename = NULL;
150
 
        int                             i, ordinal;
151
 
        PE_MODREF                       *pem = &(wm->binfmt.pe);
152
 
        IMAGE_EXPORT_DIRECTORY          *exports = pem->pe_export;
153
 
        unsigned int                    load_addr = wm->module;
154
 
        u_long                          rva_start, rva_end, addr;
155
 
        char                            * forward;
156
 
 
157
 
        if (HIWORD(funcName))
158
 
                TRACE("(%s)\n",funcName);
159
 
        else
160
 
                TRACE("(%d)\n",(int)funcName);
161
 
        if (!exports) {
162
 
                /* Not a fatal problem, some apps do
163
 
                 * GetProcAddress(0,"RegisterPenApp") which triggers this
164
 
                 * case.
165
 
                 */
166
 
                WARN("Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem);
167
 
                return NULL;
168
 
        }
169
 
        ordinals= (u_short*)  RVA(exports->AddressOfNameOrdinals);
170
 
        function= (u_long*)   RVA(exports->AddressOfFunctions);
171
 
        name    = (u_char **) RVA(exports->AddressOfNames);
172
 
        forward = NULL;
173
 
        rva_start = PE_HEADER(wm->module)->OptionalHeader
174
 
                .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
175
 
        rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader
176
 
                .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
177
 
 
178
 
        if (HIWORD(funcName))
179
 
        {
180
 
            
181
 
            int min = 0, max = exports->NumberOfNames - 1;
182
 
            while (min <= max)
183
 
            {
184
 
                int res, pos = (min + max) / 2;
185
 
                ename = (const char*) RVA(name[pos]);
186
 
                if (!(res = strcmp( ename, funcName )))
187
 
                {
188
 
                    ordinal = ordinals[pos];
189
 
                    goto found;
190
 
                }
191
 
                if (res > 0) max = pos - 1;
192
 
                else min = pos + 1;
193
 
            }
194
 
            
195
 
            for (i = 0; i < exports->NumberOfNames; i++)
196
 
            {
197
 
                ename = (const char*) RVA(name[i]);
198
 
                if (!strcmp( ename, funcName ))
199
 
                {
200
 
                    ERR( "%s.%s required a linear search\n", wm->modname, funcName );
201
 
                    ordinal = ordinals[i];
202
 
                    goto found;
203
 
                }
204
 
            }
205
 
            return NULL;
206
 
        }
207
 
        else  
208
 
        {
209
 
            ordinal = LOWORD(funcName) - exports->Base;
210
 
            if (snoop && name)  
211
 
            {
212
 
                for (i = 0; i < exports->NumberOfNames; i++)
213
 
                    if (ordinals[i] == ordinal)
214
 
                    {
215
 
                        ename = RVA(name[i]);
216
 
                        break;
217
 
                    }
218
 
            }
219
 
        }
220
 
 
221
 
 found:
222
 
        if (ordinal >= exports->NumberOfFunctions)
223
 
        {
224
 
            TRACE("     ordinal %ld out of range!\n", ordinal + exports->Base );
225
 
            return NULL;
226
 
        }
227
 
        addr = function[ordinal];
228
 
        if (!addr) return NULL;
229
 
        if ((addr < rva_start) || (addr >= rva_end))
230
 
        {
231
 
            FARPROC proc = RVA(addr);
232
 
            if (snoop)
233
 
            {
234
 
                if (!ename) ename = "@";
235
 
//                proc = SNOOP_GetProcAddress(wm->module,ename,ordinal,proc);
236
 
                TRACE("SNOOP_GetProcAddress n/a\n");
237
 
                
238
 
            }
239
 
            return proc;
240
 
        }
241
 
        else  
242
 
        {
243
 
                WINE_MODREF *wm;
244
 
                char *forward = RVA(addr);
245
 
                char module[256];
246
 
                char *end = strchr(forward, '.');
247
 
 
248
 
                if (!end) return NULL;
249
 
                if (end - forward >= sizeof(module)) return NULL;
250
 
                memcpy( module, forward, end - forward );
251
 
                module[end-forward] = 0;
252
 
                if (!(wm = MODULE_FindModule( module )))
253
 
                {
254
 
                    ERR("module not found for forward '%s'\n", forward );
255
 
                    return NULL;
256
 
                }
257
 
                return MODULE_GetProcAddress( wm->module, end + 1, snoop );
258
 
        }
259
 
}
260
 
 
261
 
static DWORD fixup_imports( WINE_MODREF *wm )
262
 
{
263
 
    IMAGE_IMPORT_DESCRIPTOR     *pe_imp;
264
 
    PE_MODREF                   *pem;
265
 
    unsigned int load_addr      = wm->module;
266
 
    int                         i,characteristics_detection=1;
267
 
    char                        *modname;
268
 
    
269
 
    assert(wm->type==MODULE32_PE);
270
 
    pem = &(wm->binfmt.pe);
271
 
    if (pem->pe_export)
272
 
        modname = (char*) RVA(pem->pe_export->Name);
273
 
    else
274
 
        modname = "<unknown>";
275
 
 
276
 
    
277
 
    TRACE("Dumping imports list\n");
278
 
 
279
 
    
280
 
    pe_imp = pem->pe_import;
281
 
    if (!pe_imp) return 0;
282
 
 
283
 
    /* We assume that we have at least one import with !0 characteristics and
284
 
     * detect broken imports with all characteristsics 0 (notably Borland) and
285
 
     * switch the detection off for them.
286
 
     */
287
 
    for (i = 0; pe_imp->Name ; pe_imp++) {
288
 
        if (!i && !pe_imp->u.Characteristics)
289
 
                characteristics_detection = 0;
290
 
        if (characteristics_detection && !pe_imp->u.Characteristics)
291
 
                break;
292
 
        i++;
293
 
    }
294
 
    if (!i) return 0;  
295
 
 
296
 
    
297
 
    wm->nDeps = i;
298
 
    wm->deps  = HeapAlloc( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) );
299
 
 
300
 
    /* load the imported modules. They are automatically 
301
 
     * added to the modref list of the process.
302
 
     */
303
 
 
304
 
    for (i = 0, pe_imp = pem->pe_import; pe_imp->Name ; pe_imp++) {
305
 
        WINE_MODREF             *wmImp;
306
 
        IMAGE_IMPORT_BY_NAME    *pe_name;
307
 
        PIMAGE_THUNK_DATA       import_list,thunk_list;
308
 
        char                    *name = (char *) RVA(pe_imp->Name);
309
 
 
310
 
        if (characteristics_detection && !pe_imp->u.Characteristics)
311
 
                break;
312
 
 
313
 
//#warning FIXME: here we should fill imports
314
 
        TRACE("Loading imports for %s.dll\n", name);
315
 
    
316
 
        if (pe_imp->u.OriginalFirstThunk != 0) { 
317
 
            TRACE("Microsoft style imports used\n");
318
 
            import_list =(PIMAGE_THUNK_DATA) RVA(pe_imp->u.OriginalFirstThunk);
319
 
            thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
320
 
 
321
 
            while (import_list->u1.Ordinal) {
322
 
                if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) {
323
 
                    int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
324
 
 
325
 
//                  TRACE("--- Ordinal %s,%d\n", name, ordinal);
326
 
                    
327
 
                    thunk_list->u1.Function=LookupExternal(name, ordinal);
328
 
                } else {                
329
 
                    pe_name = (PIMAGE_IMPORT_BY_NAME)RVA(import_list->u1.AddressOfData);
330
 
//                  TRACE("--- %s %s.%d\n", pe_name->Name, name, pe_name->Hint);
331
 
                    thunk_list->u1.Function=LookupExternalByName(name, pe_name->Name);
332
 
                }
333
 
                import_list++;
334
 
                thunk_list++;
335
 
            }
336
 
        } else {        
337
 
            TRACE("Borland style imports used\n");
338
 
            thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
339
 
            while (thunk_list->u1.Ordinal) {
340
 
                if (IMAGE_SNAP_BY_ORDINAL(thunk_list->u1.Ordinal)) {
341
 
                    
342
 
                    int ordinal = IMAGE_ORDINAL(thunk_list->u1.Ordinal);
343
 
 
344
 
                    TRACE("--- Ordinal %s.%d\n",name,ordinal);
345
 
                    thunk_list->u1.Function=LookupExternal(
346
 
                      name, ordinal);
347
 
                } else {
348
 
                    pe_name=(PIMAGE_IMPORT_BY_NAME) RVA(thunk_list->u1.AddressOfData);
349
 
                    TRACE("--- %s %s.%d\n",
350
 
                                  pe_name->Name,name,pe_name->Hint);
351
 
                    thunk_list->u1.Function=LookupExternalByName(
352
 
                      name, pe_name->Name);
353
 
                }
354
 
                thunk_list++;
355
 
            }
356
 
        }
357
 
    }
358
 
    return 0;
359
 
}
360
 
 
361
 
static int calc_vma_size( HMODULE hModule )
362
 
{
363
 
    int i,vma_size = 0;
364
 
    IMAGE_SECTION_HEADER *pe_seg = PE_SECTIONS(hModule);
365
 
 
366
 
    TRACE("Dump of segment table\n");
367
 
    TRACE("   Name    VSz  Vaddr     SzRaw   Fileadr  *Reloc *Lineum #Reloc #Linum Char\n");
368
 
    for (i = 0; i< PE_HEADER(hModule)->FileHeader.NumberOfSections; i++)
369
 
    {
370
 
        TRACE("%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n", 
371
 
                      pe_seg->Name, 
372
 
                      pe_seg->Misc.VirtualSize,
373
 
                      pe_seg->VirtualAddress,
374
 
                      pe_seg->SizeOfRawData,
375
 
                      pe_seg->PointerToRawData,
376
 
                      pe_seg->PointerToRelocations,
377
 
                      pe_seg->PointerToLinenumbers,
378
 
                      pe_seg->NumberOfRelocations,
379
 
                      pe_seg->NumberOfLinenumbers,
380
 
                      pe_seg->Characteristics);
381
 
        vma_size=max(vma_size, pe_seg->VirtualAddress+pe_seg->SizeOfRawData);
382
 
        vma_size=max(vma_size, pe_seg->VirtualAddress+pe_seg->Misc.VirtualSize);
383
 
        pe_seg++;
384
 
    }
385
 
    return vma_size;
386
 
}
387
 
 
388
 
static void do_relocations( unsigned int load_addr, IMAGE_BASE_RELOCATION *r )
389
 
{
390
 
    int delta = load_addr - PE_HEADER(load_addr)->OptionalHeader.ImageBase;
391
 
    int hdelta = (delta >> 16) & 0xFFFF;
392
 
    int ldelta = delta & 0xFFFF;
393
 
 
394
 
        if(delta == 0)
395
 
                
396
 
                return;
397
 
        while(r->VirtualAddress)
398
 
        {
399
 
                char *page = (char*) RVA(r->VirtualAddress);
400
 
                int count = (r->SizeOfBlock - 8)/2;
401
 
                int i;
402
 
                TRACE_(fixup)("%x relocations for page %lx\n",
403
 
                        count, r->VirtualAddress);
404
 
                
405
 
                for(i=0;i<count;i++)
406
 
                {
407
 
                        int offset = r->TypeOffset[i] & 0xFFF;
408
 
                        int type = r->TypeOffset[i] >> 12;
409
 
//                      TRACE_(fixup)("patching %x type %x\n", offset, type);
410
 
                        switch(type)
411
 
                        {
412
 
                        case IMAGE_REL_BASED_ABSOLUTE: break;
413
 
                        case IMAGE_REL_BASED_HIGH:
414
 
                                *(short*)(page+offset) += hdelta;
415
 
                                break;
416
 
                        case IMAGE_REL_BASED_LOW:
417
 
                                *(short*)(page+offset) += ldelta;
418
 
                                break;
419
 
                        case IMAGE_REL_BASED_HIGHLOW:
420
 
                                *(int*)(page+offset) += delta;
421
 
                                
422
 
                                break;
423
 
                        case IMAGE_REL_BASED_HIGHADJ:
424
 
                                FIXME("Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n");
425
 
                                break;
426
 
                        case IMAGE_REL_BASED_MIPS_JMPADDR:
427
 
                                FIXME("Is this a MIPS machine ???\n");
428
 
                                break;
429
 
                        default:
430
 
                                FIXME("Unknown fixup type\n");
431
 
                                break;
432
 
                        }
433
 
                }
434
 
                r = (IMAGE_BASE_RELOCATION*)((char*)r + r->SizeOfBlock);
435
 
        }
436
 
}
437
 
                
438
 
 
439
 
        
440
 
        
441
 
 
442
 
/**********************************************************************
443
 
 *                      PE_LoadImage
444
 
 * Load one PE format DLL/EXE into memory
445
 
 * 
446
 
 * Unluckily we can't just mmap the sections where we want them, for 
447
 
 * (at least) Linux does only support offsets which are page-aligned.
448
 
 *
449
 
 * BUT we have to map the whole image anyway, for Win32 programs sometimes
450
 
 * want to access them. (HMODULE32 point to the start of it)
451
 
 */
452
 
HMODULE PE_LoadImage( int handle, LPCSTR filename, WORD *version )
453
 
{
454
 
    HMODULE     hModule;
455
 
    HANDLE      mapping;
456
 
 
457
 
    IMAGE_NT_HEADERS *nt;
458
 
    IMAGE_SECTION_HEADER *pe_sec;
459
 
    IMAGE_DATA_DIRECTORY *dir;
460
 
    BY_HANDLE_FILE_INFORMATION bhfi;
461
 
    int i, rawsize, lowest_va, vma_size, file_size = 0;
462
 
    DWORD load_addr = 0, aoep, reloc = 0;
463
 
//    struct get_read_fd_request *req = get_req_buffer();
464
 
    int unix_handle = handle;
465
 
    int page_size = getpagesize();
466
 
 
467
 
    
468
 
//    if ( GetFileInformationByHandle( hFile, &bhfi ) ) 
469
 
//      file_size = bhfi.nFileSizeLow; 
470
 
    file_size=lseek(handle, 0, SEEK_END);
471
 
    lseek(handle, 0, SEEK_SET);
472
 
 
473
 
//#warning fix CreateFileMappingA
474
 
    mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY | SEC_COMMIT,
475
 
                                    0, 0, NULL );
476
 
    if (!mapping)
477
 
    {
478
 
        WARN("CreateFileMapping error %ld\n", GetLastError() );
479
 
        return 0;
480
 
    }
481
 
//    hModule = (HMODULE)MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
482
 
    hModule=(HMODULE)mapping;
483
 
//    CloseHandle( mapping );
484
 
    if (!hModule)
485
 
    {
486
 
        WARN("MapViewOfFile error %ld\n", GetLastError() );
487
 
        return 0;
488
 
    }
489
 
    if ( *(WORD*)hModule !=IMAGE_DOS_SIGNATURE)
490
 
    {
491
 
        WARN("%s image doesn't have DOS signature, but 0x%04x\n", filename,*(WORD*)hModule);
492
 
        goto error;
493
 
    }
494
 
 
495
 
    nt = PE_HEADER( hModule );
496
 
 
497
 
    
498
 
    if ( nt->Signature != IMAGE_NT_SIGNATURE )
499
 
    {
500
 
        WARN("%s image doesn't have PE signature, but 0x%08lx\n", filename, nt->Signature );
501
 
        goto error;
502
 
    }
503
 
 
504
 
    
505
 
    if ( nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386 )
506
 
    {
507
 
        MESSAGE("Trying to load PE image for unsupported architecture (");
508
 
        switch (nt->FileHeader.Machine)
509
 
        {
510
 
        case IMAGE_FILE_MACHINE_UNKNOWN: MESSAGE("Unknown"); break;
511
 
        case IMAGE_FILE_MACHINE_I860:    MESSAGE("I860"); break;
512
 
        case IMAGE_FILE_MACHINE_R3000:   MESSAGE("R3000"); break;
513
 
        case IMAGE_FILE_MACHINE_R4000:   MESSAGE("R4000"); break;
514
 
        case IMAGE_FILE_MACHINE_R10000:  MESSAGE("R10000"); break;
515
 
        case IMAGE_FILE_MACHINE_ALPHA:   MESSAGE("Alpha"); break;
516
 
        case IMAGE_FILE_MACHINE_POWERPC: MESSAGE("PowerPC"); break;
517
 
        default: MESSAGE("Unknown-%04x", nt->FileHeader.Machine); break;
518
 
        }
519
 
        MESSAGE(")\n");
520
 
        goto error;
521
 
    }
522
 
 
523
 
    
524
 
    pe_sec = PE_SECTIONS( hModule );
525
 
    rawsize = 0; lowest_va = 0x10000;
526
 
    for (i = 0; i < nt->FileHeader.NumberOfSections; i++) 
527
 
    {
528
 
        if (lowest_va > pe_sec[i].VirtualAddress)
529
 
           lowest_va = pe_sec[i].VirtualAddress;
530
 
        if (pe_sec[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
531
 
            continue;
532
 
        if (pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData > rawsize)
533
 
            rawsize = pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData;
534
 
    }
535
 
 
536
 
    
537
 
    if ( file_size && file_size < rawsize )
538
 
    {
539
 
        ERR("PE module is too small (header: %d, filesize: %d), "
540
 
                    "probably truncated download?\n", 
541
 
                    rawsize, file_size );
542
 
        goto error;
543
 
    }
544
 
 
545
 
    
546
 
    aoep = nt->OptionalHeader.AddressOfEntryPoint;
547
 
    if (aoep && (aoep < lowest_va))
548
 
        FIXME("VIRUS WARNING: '%s' has an invalid entrypoint (0x%08lx) "
549
 
                      "below the first virtual address (0x%08x) "
550
 
                      "(possibly infected by Tchernobyl/SpaceFiller virus)!\n",
551
 
                       filename, aoep, lowest_va );
552
 
 
553
 
 
554
 
    /* FIXME:  Hack!  While we don't really support shared sections yet,
555
 
     *         this checks for those special cases where the whole DLL
556
 
     *         consists only of shared sections and is mapped into the
557
 
     *         shared address space > 2GB.  In this case, we assume that
558
 
     *         the module got mapped at its base address. Thus we simply
559
 
     *         check whether the module has actually been mapped there
560
 
     *         and use it, if so.  This is needed to get Win95 USER32.DLL
561
 
     *         to work (until we support shared sections properly).
562
 
     */
563
 
 
564
 
    if ( nt->OptionalHeader.ImageBase & 0x80000000 )
565
 
    {
566
 
        HMODULE sharedMod = (HMODULE)nt->OptionalHeader.ImageBase; 
567
 
        IMAGE_NT_HEADERS *sharedNt = (PIMAGE_NT_HEADERS)
568
 
               ( (LPBYTE)sharedMod + ((LPBYTE)nt - (LPBYTE)hModule) );
569
 
 
570
 
        /* Well, this check is not really comprehensive, 
571
 
           but should be good enough for now ... */
572
 
        if (    !IsBadReadPtr( (LPBYTE)sharedMod, sizeof(IMAGE_DOS_HEADER) )
573
 
             && memcmp( (LPBYTE)sharedMod, (LPBYTE)hModule, sizeof(IMAGE_DOS_HEADER) ) == 0
574
 
             && !IsBadReadPtr( sharedNt, sizeof(IMAGE_NT_HEADERS) )
575
 
             && memcmp( sharedNt, nt, sizeof(IMAGE_NT_HEADERS) ) == 0 )
576
 
        {
577
 
            UnmapViewOfFile( (LPVOID)hModule );
578
 
            return sharedMod;
579
 
        }
580
 
    }
581
 
 
582
 
 
583
 
    
584
 
    load_addr = nt->OptionalHeader.ImageBase;
585
 
    vma_size = calc_vma_size( hModule );
586
 
 
587
 
    load_addr = (DWORD)VirtualAlloc( (void*)load_addr, vma_size,
588
 
                                     MEM_RESERVE | MEM_COMMIT,
589
 
                                     PAGE_EXECUTE_READWRITE );
590
 
    if (load_addr == 0) 
591
 
    {
592
 
        
593
 
        FIXME("We need to perform base relocations for %s\n", filename);
594
 
        dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BASERELOC;
595
 
        if (dir->Size)
596
 
            reloc = dir->VirtualAddress;
597
 
        else 
598
 
        {
599
 
            FIXME( "FATAL: Need to relocate %s, but no relocation records present (%s). Try to run that file directly !\n",
600
 
                   filename,
601
 
                   (nt->FileHeader.Characteristics&IMAGE_FILE_RELOCS_STRIPPED)?
602
 
                   "stripped during link" : "unknown reason" );
603
 
            goto error;
604
 
        }
605
 
 
606
 
        /* FIXME: If we need to relocate a system DLL (base > 2GB) we should
607
 
         *        really make sure that the *new* base address is also > 2GB.
608
 
         *        Some DLLs really check the MSB of the module handle :-/
609
 
         */
610
 
        if ( nt->OptionalHeader.ImageBase & 0x80000000 )
611
 
            ERR( "Forced to relocate system DLL (base > 2GB). This is not good.\n" );
612
 
 
613
 
        load_addr = (DWORD)VirtualAlloc( NULL, vma_size,
614
 
                                         MEM_RESERVE | MEM_COMMIT,
615
 
                                         PAGE_EXECUTE_READWRITE );
616
 
        if (!load_addr) {
617
 
            FIXME_(win32)(
618
 
                   "FATAL: Couldn't load module %s (out of memory, %d needed)!\n", filename, vma_size);
619
 
            goto error;
620
 
        }
621
 
    }
622
 
 
623
 
    TRACE("Load addr is %lx (base %lx), range %x\n",
624
 
          load_addr, nt->OptionalHeader.ImageBase, vma_size );
625
 
    TRACE_(segment)("Loading %s at %lx, range %x\n",
626
 
                    filename, load_addr, vma_size );
627
 
 
628
 
#if 0
629
 
    
630
 
    *(PIMAGE_DOS_HEADER)load_addr = *(PIMAGE_DOS_HEADER)hModule;
631
 
    *PE_HEADER( load_addr ) = *nt;
632
 
    memcpy( PE_SECTIONS(load_addr), PE_SECTIONS(hModule),
633
 
            sizeof(IMAGE_SECTION_HEADER) * nt->FileHeader.NumberOfSections );
634
 
 
635
 
    
636
 
    memcpy( load_addr, hModule, lowest_fa );
637
 
#endif
638
 
 
639
 
    if ((void*)FILE_dommap( handle, (void *)load_addr, 0, nt->OptionalHeader.SizeOfHeaders,
640
 
                     0, 0, PROT_EXEC | PROT_WRITE | PROT_READ,
641
 
                     MAP_PRIVATE | MAP_FIXED ) != (void*)load_addr)
642
 
    {
643
 
        ERR_(win32)( "Critical Error: failed to map PE header to necessary address.\n");        
644
 
        goto error;
645
 
    }
646
 
 
647
 
    
648
 
    pe_sec = PE_SECTIONS( hModule );
649
 
    for (i = 0; i < nt->FileHeader.NumberOfSections; i++, pe_sec++)
650
 
    {
651
 
        if (!pe_sec->SizeOfRawData || !pe_sec->PointerToRawData) continue;
652
 
        TRACE("%s: mmaping section %s at %p off %lx size %lx/%lx\n",
653
 
              filename, pe_sec->Name, (void*)RVA(pe_sec->VirtualAddress),
654
 
              pe_sec->PointerToRawData, pe_sec->SizeOfRawData, pe_sec->Misc.VirtualSize );
655
 
        if ((void*)FILE_dommap( unix_handle, (void*)RVA(pe_sec->VirtualAddress),
656
 
                         0, pe_sec->SizeOfRawData, 0, pe_sec->PointerToRawData,
657
 
                         PROT_EXEC | PROT_WRITE | PROT_READ,
658
 
                         MAP_PRIVATE | MAP_FIXED ) != (void*)RVA(pe_sec->VirtualAddress))
659
 
        {
660
 
            
661
 
            ERR_(win32)( "Critical Error: failed to map PE section to necessary address.\n");
662
 
            goto error;
663
 
        }
664
 
        if ((pe_sec->SizeOfRawData < pe_sec->Misc.VirtualSize) &&
665
 
            (pe_sec->SizeOfRawData & (page_size-1)))
666
 
        {
667
 
            DWORD end = (pe_sec->SizeOfRawData & ~(page_size-1)) + page_size;
668
 
            if (end > pe_sec->Misc.VirtualSize) end = pe_sec->Misc.VirtualSize;
669
 
            TRACE("clearing %p - %p\n",
670
 
                  RVA(pe_sec->VirtualAddress) + pe_sec->SizeOfRawData,
671
 
                  RVA(pe_sec->VirtualAddress) + end );
672
 
            memset( (char*)RVA(pe_sec->VirtualAddress) + pe_sec->SizeOfRawData, 0,
673
 
                    end - pe_sec->SizeOfRawData );
674
 
        }
675
 
    }
676
 
 
677
 
    
678
 
    if ( reloc )
679
 
        do_relocations( load_addr, (IMAGE_BASE_RELOCATION *)RVA(reloc) );
680
 
 
681
 
    
682
 
    *version =   ( (nt->OptionalHeader.MajorSubsystemVersion & 0xff) << 8 )
683
 
               |   (nt->OptionalHeader.MinorSubsystemVersion & 0xff);
684
 
 
685
 
    
686
 
    UnmapViewOfFile( (LPVOID)hModule );
687
 
    return (HMODULE)load_addr;
688
 
 
689
 
error:
690
 
    if (unix_handle != -1) close( unix_handle );
691
 
    if (load_addr) 
692
 
    VirtualFree( (LPVOID)load_addr, 0, MEM_RELEASE );
693
 
    UnmapViewOfFile( (LPVOID)hModule );
694
 
    return 0;
695
 
}
696
 
 
697
 
/**********************************************************************
698
 
 *                 PE_CreateModule
699
 
 *
700
 
 * Create WINE_MODREF structure for loaded HMODULE32, link it into
701
 
 * process modref_list, and fixup all imports.
702
 
 *
703
 
 * Note: hModule must point to a correctly allocated PE image,
704
 
 *       with base relocations applied; the 16-bit dummy module
705
 
 *       associated to hModule must already exist.
706
 
 *
707
 
 * Note: This routine must always be called in the context of the
708
 
 *       process that is to own the module to be created.
709
 
 */
710
 
WINE_MODREF *PE_CreateModule( HMODULE hModule, 
711
 
                              LPCSTR filename, DWORD flags, WIN_BOOL builtin )
712
 
{
713
 
    DWORD load_addr = (DWORD)hModule;  
714
 
    IMAGE_NT_HEADERS *nt = PE_HEADER(hModule);
715
 
    IMAGE_DATA_DIRECTORY *dir;
716
 
    IMAGE_IMPORT_DESCRIPTOR *pe_import = NULL;
717
 
    IMAGE_EXPORT_DIRECTORY *pe_export = NULL;
718
 
    IMAGE_RESOURCE_DIRECTORY *pe_resource = NULL;
719
 
    WINE_MODREF *wm;
720
 
    int result;
721
 
 
722
 
 
723
 
    
724
 
 
725
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT;
726
 
    if (dir->Size)
727
 
        pe_export = (PIMAGE_EXPORT_DIRECTORY)RVA(dir->VirtualAddress);
728
 
 
729
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT;
730
 
    if (dir->Size)
731
 
        pe_import = (PIMAGE_IMPORT_DESCRIPTOR)RVA(dir->VirtualAddress);
732
 
 
733
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_RESOURCE;
734
 
    if (dir->Size)
735
 
        pe_resource = (PIMAGE_RESOURCE_DIRECTORY)RVA(dir->VirtualAddress);
736
 
 
737
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXCEPTION;
738
 
    if (dir->Size) FIXME("Exception directory ignored\n" );
739
 
 
740
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_SECURITY;
741
 
    if (dir->Size) FIXME("Security directory ignored\n" );
742
 
 
743
 
    
744
 
    
745
 
 
746
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DEBUG;
747
 
    if (dir->Size) TRACE("Debug directory ignored\n" );
748
 
 
749
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COPYRIGHT;
750
 
    if (dir->Size) FIXME("Copyright string ignored\n" );
751
 
 
752
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_GLOBALPTR;
753
 
    if (dir->Size) FIXME("Global Pointer (MIPS) ignored\n" );
754
 
 
755
 
    
756
 
 
757
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG;
758
 
    if (dir->Size) FIXME("Load Configuration directory ignored\n" );
759
 
 
760
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT;
761
 
    if (dir->Size) TRACE("Bound Import directory ignored\n" );
762
 
 
763
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IAT;
764
 
    if (dir->Size) TRACE("Import Address Table directory ignored\n" );
765
 
 
766
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT;
767
 
    if (dir->Size)
768
 
    {
769
 
                TRACE("Delayed import, stub calls LoadLibrary\n" );
770
 
                /*
771
 
                 * Nothing to do here.
772
 
                 */
773
 
 
774
 
#ifdef ImgDelayDescr
775
 
                /*
776
 
                 * This code is useful to observe what the heck is going on.
777
 
                 */
778
 
                {
779
 
                ImgDelayDescr *pe_delay = NULL;
780
 
        pe_delay = (PImgDelayDescr)RVA(dir->VirtualAddress);
781
 
        TRACE_(delayhlp)("pe_delay->grAttrs = %08x\n", pe_delay->grAttrs);
782
 
        TRACE_(delayhlp)("pe_delay->szName = %s\n", pe_delay->szName);
783
 
        TRACE_(delayhlp)("pe_delay->phmod = %08x\n", pe_delay->phmod);
784
 
        TRACE_(delayhlp)("pe_delay->pIAT = %08x\n", pe_delay->pIAT);
785
 
        TRACE_(delayhlp)("pe_delay->pINT = %08x\n", pe_delay->pINT);
786
 
        TRACE_(delayhlp)("pe_delay->pBoundIAT = %08x\n", pe_delay->pBoundIAT);
787
 
        TRACE_(delayhlp)("pe_delay->pUnloadIAT = %08x\n", pe_delay->pUnloadIAT);
788
 
        TRACE_(delayhlp)("pe_delay->dwTimeStamp = %08x\n", pe_delay->dwTimeStamp);
789
 
        }
790
 
#endif 
791
 
        }
792
 
 
793
 
    dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR;
794
 
    if (dir->Size) FIXME("Unknown directory 14 ignored\n" );
795
 
 
796
 
    dir = nt->OptionalHeader.DataDirectory+15;
797
 
    if (dir->Size) FIXME("Unknown directory 15 ignored\n" );
798
 
 
799
 
 
800
 
    
801
 
 
802
 
    wm = (WINE_MODREF *)HeapAlloc( GetProcessHeap(), 
803
 
                                   HEAP_ZERO_MEMORY, sizeof(*wm) );
804
 
    wm->module = hModule;
805
 
 
806
 
    if ( builtin ) 
807
 
        wm->flags |= WINE_MODREF_INTERNAL;
808
 
    if ( flags & DONT_RESOLVE_DLL_REFERENCES )
809
 
        wm->flags |= WINE_MODREF_DONT_RESOLVE_REFS;
810
 
    if ( flags & LOAD_LIBRARY_AS_DATAFILE )
811
 
        wm->flags |= WINE_MODREF_LOAD_AS_DATAFILE;
812
 
 
813
 
    wm->type = MODULE32_PE;
814
 
    wm->binfmt.pe.pe_export = pe_export;
815
 
    wm->binfmt.pe.pe_import = pe_import;
816
 
    wm->binfmt.pe.pe_resource = pe_resource;
817
 
    wm->binfmt.pe.tlsindex = -1;
818
 
 
819
 
    wm->filename = malloc(strlen(filename)+1);
820
 
    strcpy(wm->filename, filename );
821
 
    wm->modname = strrchr( wm->filename, '\\' );
822
 
    if (!wm->modname) wm->modname = wm->filename;
823
 
    else wm->modname++;
824
 
 
825
 
    if ( pe_export )
826
 
        dump_exports( hModule );
827
 
 
828
 
    /* Fixup Imports */
829
 
 
830
 
    if (    pe_import
831
 
         && !( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE )
832
 
         && !( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS ) 
833
 
         && fixup_imports( wm ) ) 
834
 
    {
835
 
        /* remove entry from modref chain */
836
 
         return NULL;
837
 
    }
838
 
 
839
 
    return wm;
840
 
 
841
 
    return wm;
842
 
}
843
 
 
844
 
/******************************************************************************
845
 
 * The PE Library Loader frontend. 
846
 
 * FIXME: handle the flags.
847
 
 */
848
 
WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags)
849
 
{
850
 
        HMODULE         hModule32;
851
 
        WINE_MODREF     *wm;
852
 
        char            filename[256];
853
 
        int hFile;
854
 
        WORD            version = 0;
855
 
 
856
 
        
857
 
        strncpy(filename, name, sizeof(filename));      
858
 
        hFile=open(filename, O_RDONLY);
859
 
        if(hFile==-1)
860
 
            return NULL;
861
 
        
862
 
        
863
 
        hModule32 = PE_LoadImage( hFile, filename, &version );
864
 
        if (!hModule32)
865
 
        {
866
 
                SetLastError( ERROR_OUTOFMEMORY );      
867
 
                return NULL;
868
 
        }
869
 
 
870
 
        if ( !(wm = PE_CreateModule( hModule32, filename, flags, FALSE )) )
871
 
        {
872
 
                ERR( "can't load %s\n", filename );
873
 
                SetLastError( ERROR_OUTOFMEMORY );
874
 
                return NULL;
875
 
        }
876
 
        close(hFile);
877
 
        //printf("^^^^^^^^^^^^^^^^Alloc VM1  %p\n", wm);
878
 
        return wm;
879
 
}
880
 
 
881
 
 
882
 
/*****************************************************************************
883
 
 *      PE_UnloadLibrary
884
 
 *
885
 
 * Unload the library unmapping the image and freeing the modref structure.
886
 
 */
887
 
void PE_UnloadLibrary(WINE_MODREF *wm)
888
 
{
889
 
    TRACE(" unloading %s\n", wm->filename);
890
 
 
891
 
    if (wm->filename)
892
 
        free(wm->filename);
893
 
    if (wm->short_filename)
894
 
        free(wm->short_filename);
895
 
    HeapFree( GetProcessHeap(), 0, wm->deps );
896
 
    VirtualFree( (LPVOID)wm->module, 0, MEM_RELEASE );
897
 
    HeapFree( GetProcessHeap(), 0, wm );
898
 
    //printf("^^^^^^^^^^^^^^^^Free VM1  %p\n", wm);
899
 
}
900
 
 
901
 
/*****************************************************************************
902
 
 * Load the PE main .EXE. All other loading is done by PE_LoadLibraryExA
903
 
 * FIXME: this function should use PE_LoadLibraryExA, but currently can't
904
 
 * due to the PROCESS_Create stuff.
905
 
 */
906
 
 
907
 
 
908
 
/*
909
 
 * This is a dirty hack.
910
 
 * The win32 DLLs contain an alloca routine, that first probes the soon
911
 
 * to be allocated new memory *below* the current stack pointer in 4KByte
912
 
 * increments.  After the mem probing below the current %esp,  the stack
913
 
 * pointer is finally decremented to make room for the "alloca"ed memory.
914
 
 * Maybe the probing code is intended to extend the stack on a windows box.
915
 
 * Anyway, the linux kernel does *not* extend the stack by simply accessing
916
 
 * memory below %esp;  it segfaults.
917
 
 * The extend_stack_for_dll_alloca() routine just preallocates a big chunk
918
 
 * of memory on the stack, for use by the DLLs alloca routine.
919
 
 * Added the noinline attribute as e.g. gcc 3.2.2 inlines this function
920
 
 * in a way that breaks it.
921
 
 */
922
 
static void __attribute__((noinline)) extend_stack_for_dll_alloca(void)
923
 
{
924
 
#if !defined(__FreeBSD__) && !defined(__DragonFly__)
925
 
    volatile int* mem=alloca(0x20000);
926
 
    *mem=0x1234;
927
 
#endif
928
 
}
929
 
 
930
 
/* Called if the library is loaded or freed.
931
 
 * NOTE: if a thread attaches a DLL, the current thread will only do
932
 
 * DLL_PROCESS_ATTACH. Only new created threads do DLL_THREAD_ATTACH
933
 
 * (SDK)
934
 
 */
935
 
WIN_BOOL PE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
936
 
{
937
 
    WIN_BOOL retv = TRUE;
938
 
    assert( wm->type == MODULE32_PE );
939
 
 
940
 
    
941
 
    if ((PE_HEADER(wm->module)->FileHeader.Characteristics & IMAGE_FILE_DLL) &&
942
 
        (PE_HEADER(wm->module)->OptionalHeader.AddressOfEntryPoint)
943
 
    ) {
944
 
        DLLENTRYPROC entry ;
945
 
        entry = (void*)PE_FindExportedFunction(wm, "DllMain", 0);
946
 
        if(entry==NULL)
947
 
            entry = (void*)RVA_PTR( wm->module,OptionalHeader.AddressOfEntryPoint );
948
 
        
949
 
        TRACE_(relay)("CallTo32(entryproc=%p,module=%08x,type=%ld,res=%p)\n",
950
 
                       entry, wm->module, type, lpReserved );
951
 
        
952
 
        
953
 
        TRACE("Entering DllMain(");
954
 
        switch(type)
955
 
        {
956
 
            case DLL_PROCESS_DETACH:
957
 
                TRACE("DLL_PROCESS_DETACH) ");
958
 
                break;
959
 
            case DLL_PROCESS_ATTACH:
960
 
                TRACE("DLL_PROCESS_ATTACH) ");
961
 
                break;
962
 
            case DLL_THREAD_DETACH:
963
 
                TRACE("DLL_THREAD_DETACH) ");
964
 
                break;
965
 
            case DLL_THREAD_ATTACH:
966
 
                TRACE("DLL_THREAD_ATTACH) ");
967
 
                break;
968
 
        }       
969
 
        TRACE("for %s\n", wm->filename);
970
 
        extend_stack_for_dll_alloca();
971
 
        retv = entry( wm->module, type, lpReserved );
972
 
    }
973
 
 
974
 
    return retv;
975
 
}
976
 
 
977
 
static LPVOID
978
 
_fixup_address(PIMAGE_OPTIONAL_HEADER opt,int delta,LPVOID addr) {
979
 
        if (    ((DWORD)addr>opt->ImageBase) &&
980
 
                ((DWORD)addr<opt->ImageBase+opt->SizeOfImage)
981
 
        )
982
 
                
983
 
                return (LPVOID)(((DWORD)addr)+delta);
984
 
        else
985
 
                
986
 
                return addr;
987
 
}