00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "config.h"
00042
00043 #include <errno.h>
00044 #include <assert.h>
00045 #include <stdio.h>
00046 #include <stdlib.h>
00047 #include <string.h>
00048 #include <unistd.h>
00049 #include <sys/types.h>
00050 #include <sys/stat.h>
00051 #include <fcntl.h>
00052 #ifdef HAVE_SYS_MMAN_H
00053 #include <sys/mman.h>
00054 #endif
00055 #include "wine/windef.h"
00056 #include "wine/winbase.h"
00057 #include "wine/winerror.h"
00058 #include "wine/heap.h"
00059 #include "wine/pe_image.h"
00060 #include "wine/module.h"
00061 #include "wine/debugtools.h"
00062 #include "ext.h"
00063 #include "win32.h"
00064
00065 #define RVA(x) ((void *)((char *)load_addr+(unsigned int)(x)))
00066
00067 #define AdjustPtr(ptr,delta) ((char *)(ptr) + (delta))
00068
00069 extern void* LookupExternal(const char* library, int ordinal);
00070 extern void* LookupExternalByName(const char* library, const char* name);
00071
00072 static void dump_exports( HMODULE hModule )
00073 {
00074 char *Module;
00075 unsigned int i, j;
00076 u_short *ordinal;
00077 u_long *function,*functions;
00078 u_char **name;
00079 unsigned int load_addr = hModule;
00080
00081 DWORD rva_start = PE_HEADER(hModule)->OptionalHeader
00082 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
00083 DWORD rva_end = rva_start + PE_HEADER(hModule)->OptionalHeader
00084 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
00085 IMAGE_EXPORT_DIRECTORY *pe_exports = (IMAGE_EXPORT_DIRECTORY*)RVA(rva_start);
00086
00087 Module = (char*)RVA(pe_exports->Name);
00088 TRACE("*******EXPORT DATA*******\n");
00089 TRACE("Module name is %s, %ld functions, %ld names\n",
00090 Module, pe_exports->NumberOfFunctions, pe_exports->NumberOfNames);
00091
00092 ordinal=(u_short*) RVA(pe_exports->AddressOfNameOrdinals);
00093 functions=function=(u_long*) RVA(pe_exports->AddressOfFunctions);
00094 name=(u_char**) RVA(pe_exports->AddressOfNames);
00095
00096 TRACE(" Ord RVA Addr Name\n" );
00097 for (i=0;i<pe_exports->NumberOfFunctions;i++, function++)
00098 {
00099 if (!*function) continue;
00100 if (TRACE_ON(win32))
00101 {
00102 DPRINTF( "%4ld %08lx %p", i + pe_exports->Base, *function, RVA(*function) );
00103
00104 for (j = 0; j < pe_exports->NumberOfNames; j++)
00105 if (ordinal[j] == i)
00106 {
00107 DPRINTF( " %s", (char*)RVA(name[j]) );
00108 break;
00109 }
00110 if ((*function >= rva_start) && (*function <= rva_end))
00111 DPRINTF(" (forwarded -> %s)", (char *)RVA(*function));
00112 DPRINTF("\n");
00113 }
00114 }
00115 }
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125 FARPROC PE_FindExportedFunction(
00126 WINE_MODREF *wm,
00127 LPCSTR funcName,
00128 WIN_BOOL snoop )
00129 {
00130 u_short * ordinals;
00131 u_long * function;
00132 u_char ** name;
00133 const char *ename = NULL;
00134 int i, ordinal;
00135 PE_MODREF *pem = &(wm->binfmt.pe);
00136 IMAGE_EXPORT_DIRECTORY *exports = pem->pe_export;
00137 unsigned int load_addr = wm->module;
00138 u_long rva_start, rva_end, addr;
00139 char * forward;
00140
00141 if (HIWORD(funcName))
00142 TRACE("(%s)\n",funcName);
00143 else
00144 TRACE("(%d)\n",(int)funcName);
00145 if (!exports) {
00146
00147
00148
00149
00150 WARN("Module %08x(%s)/MODREF %p doesn't have a exports table.\n",wm->module,wm->modname,pem);
00151 return NULL;
00152 }
00153 ordinals= (u_short*) RVA(exports->AddressOfNameOrdinals);
00154 function= (u_long*) RVA(exports->AddressOfFunctions);
00155 name = (u_char **) RVA(exports->AddressOfNames);
00156 forward = NULL;
00157 rva_start = PE_HEADER(wm->module)->OptionalHeader
00158 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
00159 rva_end = rva_start + PE_HEADER(wm->module)->OptionalHeader
00160 .DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
00161
00162 if (HIWORD(funcName))
00163 {
00164
00165 int min = 0, max = exports->NumberOfNames - 1;
00166 while (min <= max)
00167 {
00168 int res, pos = (min + max) / 2;
00169 ename = (const char*) RVA(name[pos]);
00170 if (!(res = strcmp( ename, funcName )))
00171 {
00172 ordinal = ordinals[pos];
00173 goto found;
00174 }
00175 if (res > 0) max = pos - 1;
00176 else min = pos + 1;
00177 }
00178
00179 for (i = 0; i < exports->NumberOfNames; i++)
00180 {
00181 ename = (const char*) RVA(name[i]);
00182 if (!strcmp( ename, funcName ))
00183 {
00184 ERR( "%s.%s required a linear search\n", wm->modname, funcName );
00185 ordinal = ordinals[i];
00186 goto found;
00187 }
00188 }
00189 return NULL;
00190 }
00191 else
00192 {
00193 ordinal = LOWORD(funcName) - exports->Base;
00194 if (snoop && name)
00195 {
00196 for (i = 0; i < exports->NumberOfNames; i++)
00197 if (ordinals[i] == ordinal)
00198 {
00199 ename = RVA(name[i]);
00200 break;
00201 }
00202 }
00203 }
00204
00205 found:
00206 if (ordinal >= exports->NumberOfFunctions)
00207 {
00208 TRACE(" ordinal %ld out of range!\n", ordinal + exports->Base );
00209 return NULL;
00210 }
00211 addr = function[ordinal];
00212 if (!addr) return NULL;
00213 if ((addr < rva_start) || (addr >= rva_end))
00214 {
00215 FARPROC proc = RVA(addr);
00216 if (snoop)
00217 {
00218 if (!ename) ename = "@";
00219
00220 TRACE("SNOOP_GetProcAddress n/a\n");
00221
00222 }
00223 return proc;
00224 }
00225 else
00226 {
00227 WINE_MODREF *wm;
00228 char *forward = RVA(addr);
00229 char module[256];
00230 char *end = strchr(forward, '.');
00231
00232 if (!end) return NULL;
00233 if (end - forward >= sizeof(module)) return NULL;
00234 memcpy( module, forward, end - forward );
00235 module[end-forward] = 0;
00236 if (!(wm = MODULE_FindModule( module )))
00237 {
00238 ERR("module not found for forward '%s'\n", forward );
00239 return NULL;
00240 }
00241 return MODULE_GetProcAddress( wm->module, end + 1, snoop );
00242 }
00243 }
00244
00245 static DWORD fixup_imports( WINE_MODREF *wm )
00246 {
00247 IMAGE_IMPORT_DESCRIPTOR *pe_imp;
00248 PE_MODREF *pem;
00249 unsigned int load_addr = wm->module;
00250 int i,characteristics_detection=1;
00251 char *modname;
00252
00253 assert(wm->type==MODULE32_PE);
00254 pem = &(wm->binfmt.pe);
00255 if (pem->pe_export)
00256 modname = (char*) RVA(pem->pe_export->Name);
00257 else
00258 modname = "<unknown>";
00259
00260
00261 TRACE("Dumping imports list\n");
00262
00263
00264 pe_imp = pem->pe_import;
00265 if (!pe_imp) return 0;
00266
00267
00268
00269
00270
00271 for (i = 0; pe_imp->Name ; pe_imp++) {
00272 if (!i && !pe_imp->u.Characteristics)
00273 characteristics_detection = 0;
00274 if (characteristics_detection && !pe_imp->u.Characteristics)
00275 break;
00276 i++;
00277 }
00278 if (!i) return 0;
00279
00280
00281 wm->nDeps = i;
00282 wm->deps = HeapAlloc( GetProcessHeap(), 0, i*sizeof(WINE_MODREF *) );
00283
00284
00285
00286
00287
00288 for (i = 0, pe_imp = pem->pe_import; pe_imp->Name ; pe_imp++) {
00289 WINE_MODREF *wmImp;
00290 IMAGE_IMPORT_BY_NAME *pe_name;
00291 PIMAGE_THUNK_DATA import_list,thunk_list;
00292 char *name = (char *) RVA(pe_imp->Name);
00293
00294 if (characteristics_detection && !pe_imp->u.Characteristics)
00295 break;
00296
00297
00298 TRACE("Loading imports for %s.dll\n", name);
00299
00300 if (pe_imp->u.OriginalFirstThunk != 0) {
00301 TRACE("Microsoft style imports used\n");
00302 import_list =(PIMAGE_THUNK_DATA) RVA(pe_imp->u.OriginalFirstThunk);
00303 thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
00304
00305 while (import_list->u1.Ordinal) {
00306 if (IMAGE_SNAP_BY_ORDINAL(import_list->u1.Ordinal)) {
00307 int ordinal = IMAGE_ORDINAL(import_list->u1.Ordinal);
00308
00309
00310
00311 thunk_list->u1.Function=LookupExternal(name, ordinal);
00312 } else {
00313 pe_name = (PIMAGE_IMPORT_BY_NAME)RVA(import_list->u1.AddressOfData);
00314
00315 thunk_list->u1.Function=LookupExternalByName(name, pe_name->Name);
00316 }
00317 import_list++;
00318 thunk_list++;
00319 }
00320 } else {
00321 TRACE("Borland style imports used\n");
00322 thunk_list = (PIMAGE_THUNK_DATA) RVA(pe_imp->FirstThunk);
00323 while (thunk_list->u1.Ordinal) {
00324 if (IMAGE_SNAP_BY_ORDINAL(thunk_list->u1.Ordinal)) {
00325
00326 int ordinal = IMAGE_ORDINAL(thunk_list->u1.Ordinal);
00327
00328 TRACE("--- Ordinal %s.%d\n",name,ordinal);
00329 thunk_list->u1.Function=LookupExternal(
00330 name, ordinal);
00331 } else {
00332 pe_name=(PIMAGE_IMPORT_BY_NAME) RVA(thunk_list->u1.AddressOfData);
00333 TRACE("--- %s %s.%d\n",
00334 pe_name->Name,name,pe_name->Hint);
00335 thunk_list->u1.Function=LookupExternalByName(
00336 name, pe_name->Name);
00337 }
00338 thunk_list++;
00339 }
00340 }
00341 }
00342 return 0;
00343 }
00344
00345 static int calc_vma_size( HMODULE hModule )
00346 {
00347 int i,vma_size = 0;
00348 IMAGE_SECTION_HEADER *pe_seg = PE_SECTIONS(hModule);
00349
00350 TRACE("Dump of segment table\n");
00351 TRACE(" Name VSz Vaddr SzRaw Fileadr *Reloc *Lineum #Reloc #Linum Char\n");
00352 for (i = 0; i< PE_HEADER(hModule)->FileHeader.NumberOfSections; i++)
00353 {
00354 TRACE("%8s: %4.4lx %8.8lx %8.8lx %8.8lx %8.8lx %8.8lx %4.4x %4.4x %8.8lx\n",
00355 pe_seg->Name,
00356 pe_seg->Misc.VirtualSize,
00357 pe_seg->VirtualAddress,
00358 pe_seg->SizeOfRawData,
00359 pe_seg->PointerToRawData,
00360 pe_seg->PointerToRelocations,
00361 pe_seg->PointerToLinenumbers,
00362 pe_seg->NumberOfRelocations,
00363 pe_seg->NumberOfLinenumbers,
00364 pe_seg->Characteristics);
00365 vma_size=max(vma_size, pe_seg->VirtualAddress+pe_seg->SizeOfRawData);
00366 vma_size=max(vma_size, pe_seg->VirtualAddress+pe_seg->Misc.VirtualSize);
00367 pe_seg++;
00368 }
00369 return vma_size;
00370 }
00371
00372 static void do_relocations( unsigned int load_addr, IMAGE_BASE_RELOCATION *r )
00373 {
00374 int delta = load_addr - PE_HEADER(load_addr)->OptionalHeader.ImageBase;
00375 int hdelta = (delta >> 16) & 0xFFFF;
00376 int ldelta = delta & 0xFFFF;
00377
00378 if(delta == 0)
00379
00380 return;
00381 while(r->VirtualAddress)
00382 {
00383 char *page = (char*) RVA(r->VirtualAddress);
00384 int count = (r->SizeOfBlock - 8)/2;
00385 int i;
00386 TRACE_(fixup)("%x relocations for page %lx\n",
00387 count, r->VirtualAddress);
00388
00389 for(i=0;i<count;i++)
00390 {
00391 int offset = r->TypeOffset[i] & 0xFFF;
00392 int type = r->TypeOffset[i] >> 12;
00393
00394 switch(type)
00395 {
00396 case IMAGE_REL_BASED_ABSOLUTE: break;
00397 case IMAGE_REL_BASED_HIGH:
00398 *(short*)(page+offset) += hdelta;
00399 break;
00400 case IMAGE_REL_BASED_LOW:
00401 *(short*)(page+offset) += ldelta;
00402 break;
00403 case IMAGE_REL_BASED_HIGHLOW:
00404 *(int*)(page+offset) += delta;
00405
00406 break;
00407 case IMAGE_REL_BASED_HIGHADJ:
00408 FIXME("Don't know what to do with IMAGE_REL_BASED_HIGHADJ\n");
00409 break;
00410 case IMAGE_REL_BASED_MIPS_JMPADDR:
00411 FIXME("Is this a MIPS machine ???\n");
00412 break;
00413 default:
00414 FIXME("Unknown fixup type\n");
00415 break;
00416 }
00417 }
00418 r = (IMAGE_BASE_RELOCATION*)((char*)r + r->SizeOfBlock);
00419 }
00420 }
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436 HMODULE PE_LoadImage( int handle, LPCSTR filename, WORD *version )
00437 {
00438 HMODULE hModule;
00439 HANDLE mapping;
00440
00441 IMAGE_NT_HEADERS *nt;
00442 IMAGE_SECTION_HEADER *pe_sec;
00443 IMAGE_DATA_DIRECTORY *dir;
00444 BY_HANDLE_FILE_INFORMATION bhfi;
00445 int i, rawsize, lowest_va, vma_size, file_size = 0;
00446 DWORD load_addr = 0, aoep, reloc = 0;
00447
00448 int unix_handle = handle;
00449 int page_size = getpagesize();
00450
00451
00452
00453
00454 file_size=lseek(handle, 0, SEEK_END);
00455 lseek(handle, 0, SEEK_SET);
00456
00457
00458 mapping = CreateFileMappingA( handle, NULL, PAGE_READONLY | SEC_COMMIT,
00459 0, 0, NULL );
00460 if (!mapping)
00461 {
00462 WARN("CreateFileMapping error %ld\n", GetLastError() );
00463 return 0;
00464 }
00465
00466 hModule=(HMODULE)mapping;
00467
00468 if (!hModule)
00469 {
00470 WARN("MapViewOfFile error %ld\n", GetLastError() );
00471 return 0;
00472 }
00473 if ( *(WORD*)hModule !=IMAGE_DOS_SIGNATURE)
00474 {
00475 WARN("%s image doesn't have DOS signature, but 0x%04x\n", filename,*(WORD*)hModule);
00476 goto error;
00477 }
00478
00479 nt = PE_HEADER( hModule );
00480
00481
00482 if ( nt->Signature != IMAGE_NT_SIGNATURE )
00483 {
00484 WARN("%s image doesn't have PE signature, but 0x%08lx\n", filename, nt->Signature );
00485 goto error;
00486 }
00487
00488
00489 if ( nt->FileHeader.Machine != IMAGE_FILE_MACHINE_I386 )
00490 {
00491 MESSAGE("Trying to load PE image for unsupported architecture (");
00492 switch (nt->FileHeader.Machine)
00493 {
00494 case IMAGE_FILE_MACHINE_UNKNOWN: MESSAGE("Unknown"); break;
00495 case IMAGE_FILE_MACHINE_I860: MESSAGE("I860"); break;
00496 case IMAGE_FILE_MACHINE_R3000: MESSAGE("R3000"); break;
00497 case IMAGE_FILE_MACHINE_R4000: MESSAGE("R4000"); break;
00498 case IMAGE_FILE_MACHINE_R10000: MESSAGE("R10000"); break;
00499 case IMAGE_FILE_MACHINE_ALPHA: MESSAGE("Alpha"); break;
00500 case IMAGE_FILE_MACHINE_POWERPC: MESSAGE("PowerPC"); break;
00501 default: MESSAGE("Unknown-%04x", nt->FileHeader.Machine); break;
00502 }
00503 MESSAGE(")\n");
00504 goto error;
00505 }
00506
00507
00508 pe_sec = PE_SECTIONS( hModule );
00509 rawsize = 0; lowest_va = 0x10000;
00510 for (i = 0; i < nt->FileHeader.NumberOfSections; i++)
00511 {
00512 if (lowest_va > pe_sec[i].VirtualAddress)
00513 lowest_va = pe_sec[i].VirtualAddress;
00514 if (pe_sec[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
00515 continue;
00516 if (pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData > rawsize)
00517 rawsize = pe_sec[i].PointerToRawData+pe_sec[i].SizeOfRawData;
00518 }
00519
00520
00521 if ( file_size && file_size < rawsize )
00522 {
00523 ERR("PE module is too small (header: %d, filesize: %d), "
00524 "probably truncated download?\n",
00525 rawsize, file_size );
00526 goto error;
00527 }
00528
00529
00530 aoep = nt->OptionalHeader.AddressOfEntryPoint;
00531 if (aoep && (aoep < lowest_va))
00532 FIXME("VIRUS WARNING: '%s' has an invalid entrypoint (0x%08lx) "
00533 "below the first virtual address (0x%08x) "
00534 "(possibly infected by Tchernobyl/SpaceFiller virus)!\n",
00535 filename, aoep, lowest_va );
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 if ( nt->OptionalHeader.ImageBase & 0x80000000 )
00549 {
00550 HMODULE sharedMod = (HMODULE)nt->OptionalHeader.ImageBase;
00551 IMAGE_NT_HEADERS *sharedNt = (PIMAGE_NT_HEADERS)
00552 ( (LPBYTE)sharedMod + ((LPBYTE)nt - (LPBYTE)hModule) );
00553
00554
00555
00556 if ( !IsBadReadPtr( (LPBYTE)sharedMod, sizeof(IMAGE_DOS_HEADER) )
00557 && memcmp( (LPBYTE)sharedMod, (LPBYTE)hModule, sizeof(IMAGE_DOS_HEADER) ) == 0
00558 && !IsBadReadPtr( sharedNt, sizeof(IMAGE_NT_HEADERS) )
00559 && memcmp( sharedNt, nt, sizeof(IMAGE_NT_HEADERS) ) == 0 )
00560 {
00561 UnmapViewOfFile( (LPVOID)hModule );
00562 return sharedMod;
00563 }
00564 }
00565
00566
00567
00568 load_addr = nt->OptionalHeader.ImageBase;
00569 vma_size = calc_vma_size( hModule );
00570
00571 load_addr = (DWORD)VirtualAlloc( (void*)load_addr, vma_size,
00572 MEM_RESERVE | MEM_COMMIT,
00573 PAGE_EXECUTE_READWRITE );
00574 if (load_addr == 0)
00575 {
00576
00577 FIXME("We need to perform base relocations for %s\n", filename);
00578 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BASERELOC;
00579 if (dir->Size)
00580 reloc = dir->VirtualAddress;
00581 else
00582 {
00583 FIXME( "FATAL: Need to relocate %s, but no relocation records present (%s). Try to run that file directly !\n",
00584 filename,
00585 (nt->FileHeader.Characteristics&IMAGE_FILE_RELOCS_STRIPPED)?
00586 "stripped during link" : "unknown reason" );
00587 goto error;
00588 }
00589
00590
00591
00592
00593
00594 if ( nt->OptionalHeader.ImageBase & 0x80000000 )
00595 ERR( "Forced to relocate system DLL (base > 2GB). This is not good.\n" );
00596
00597 load_addr = (DWORD)VirtualAlloc( NULL, vma_size,
00598 MEM_RESERVE | MEM_COMMIT,
00599 PAGE_EXECUTE_READWRITE );
00600 if (!load_addr) {
00601 FIXME_(win32)(
00602 "FATAL: Couldn't load module %s (out of memory, %d needed)!\n", filename, vma_size);
00603 goto error;
00604 }
00605 }
00606
00607 TRACE("Load addr is %lx (base %lx), range %x\n",
00608 load_addr, nt->OptionalHeader.ImageBase, vma_size );
00609 TRACE_(segment)("Loading %s at %lx, range %x\n",
00610 filename, load_addr, vma_size );
00611
00612 #if 0
00613
00614 *(PIMAGE_DOS_HEADER)load_addr = *(PIMAGE_DOS_HEADER)hModule;
00615 *PE_HEADER( load_addr ) = *nt;
00616 memcpy( PE_SECTIONS(load_addr), PE_SECTIONS(hModule),
00617 sizeof(IMAGE_SECTION_HEADER) * nt->FileHeader.NumberOfSections );
00618
00619
00620 memcpy( load_addr, hModule, lowest_fa );
00621 #endif
00622
00623 if ((void*)FILE_dommap( handle, (void *)load_addr, 0, nt->OptionalHeader.SizeOfHeaders,
00624 0, 0, PROT_EXEC | PROT_WRITE | PROT_READ,
00625 MAP_PRIVATE | MAP_FIXED ) != (void*)load_addr)
00626 {
00627 ERR_(win32)( "Critical Error: failed to map PE header to necessary address.\n");
00628 goto error;
00629 }
00630
00631
00632 pe_sec = PE_SECTIONS( hModule );
00633 for (i = 0; i < nt->FileHeader.NumberOfSections; i++, pe_sec++)
00634 {
00635 if (!pe_sec->SizeOfRawData || !pe_sec->PointerToRawData) continue;
00636 TRACE("%s: mmaping section %s at %p off %lx size %lx/%lx\n",
00637 filename, pe_sec->Name, (void*)RVA(pe_sec->VirtualAddress),
00638 pe_sec->PointerToRawData, pe_sec->SizeOfRawData, pe_sec->Misc.VirtualSize );
00639 if ((void*)FILE_dommap( unix_handle, (void*)RVA(pe_sec->VirtualAddress),
00640 0, pe_sec->SizeOfRawData, 0, pe_sec->PointerToRawData,
00641 PROT_EXEC | PROT_WRITE | PROT_READ,
00642 MAP_PRIVATE | MAP_FIXED ) != (void*)RVA(pe_sec->VirtualAddress))
00643 {
00644
00645 ERR_(win32)( "Critical Error: failed to map PE section to necessary address.\n");
00646 goto error;
00647 }
00648 if ((pe_sec->SizeOfRawData < pe_sec->Misc.VirtualSize) &&
00649 (pe_sec->SizeOfRawData & (page_size-1)))
00650 {
00651 DWORD end = (pe_sec->SizeOfRawData & ~(page_size-1)) + page_size;
00652 if (end > pe_sec->Misc.VirtualSize) end = pe_sec->Misc.VirtualSize;
00653 TRACE("clearing %p - %p\n",
00654 RVA(pe_sec->VirtualAddress) + pe_sec->SizeOfRawData,
00655 RVA(pe_sec->VirtualAddress) + end );
00656 memset( (char*)RVA(pe_sec->VirtualAddress) + pe_sec->SizeOfRawData, 0,
00657 end - pe_sec->SizeOfRawData );
00658 }
00659 }
00660
00661
00662 if ( reloc )
00663 do_relocations( load_addr, (IMAGE_BASE_RELOCATION *)RVA(reloc) );
00664
00665
00666 *version = ( (nt->OptionalHeader.MajorSubsystemVersion & 0xff) << 8 )
00667 | (nt->OptionalHeader.MinorSubsystemVersion & 0xff);
00668
00669
00670 UnmapViewOfFile( (LPVOID)hModule );
00671 return (HMODULE)load_addr;
00672
00673 error:
00674 if (unix_handle != -1) close( unix_handle );
00675 if (load_addr)
00676 VirtualFree( (LPVOID)load_addr, 0, MEM_RELEASE );
00677 UnmapViewOfFile( (LPVOID)hModule );
00678 return 0;
00679 }
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694 WINE_MODREF *PE_CreateModule( HMODULE hModule,
00695 LPCSTR filename, DWORD flags, WIN_BOOL builtin )
00696 {
00697 DWORD load_addr = (DWORD)hModule;
00698 IMAGE_NT_HEADERS *nt = PE_HEADER(hModule);
00699 IMAGE_DATA_DIRECTORY *dir;
00700 IMAGE_IMPORT_DESCRIPTOR *pe_import = NULL;
00701 IMAGE_EXPORT_DIRECTORY *pe_export = NULL;
00702 IMAGE_RESOURCE_DIRECTORY *pe_resource = NULL;
00703 WINE_MODREF *wm;
00704 int result;
00705
00706
00707
00708
00709 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXPORT;
00710 if (dir->Size)
00711 pe_export = (PIMAGE_EXPORT_DIRECTORY)RVA(dir->VirtualAddress);
00712
00713 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IMPORT;
00714 if (dir->Size)
00715 pe_import = (PIMAGE_IMPORT_DESCRIPTOR)RVA(dir->VirtualAddress);
00716
00717 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_RESOURCE;
00718 if (dir->Size)
00719 pe_resource = (PIMAGE_RESOURCE_DIRECTORY)RVA(dir->VirtualAddress);
00720
00721 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_EXCEPTION;
00722 if (dir->Size) FIXME("Exception directory ignored\n" );
00723
00724 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_SECURITY;
00725 if (dir->Size) FIXME("Security directory ignored\n" );
00726
00727
00728
00729
00730 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DEBUG;
00731 if (dir->Size) TRACE("Debug directory ignored\n" );
00732
00733 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COPYRIGHT;
00734 if (dir->Size) FIXME("Copyright string ignored\n" );
00735
00736 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_GLOBALPTR;
00737 if (dir->Size) FIXME("Global Pointer (MIPS) ignored\n" );
00738
00739
00740
00741 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG;
00742 if (dir->Size) FIXME("Load Configuration directory ignored\n" );
00743
00744 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT;
00745 if (dir->Size) TRACE("Bound Import directory ignored\n" );
00746
00747 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_IAT;
00748 if (dir->Size) TRACE("Import Address Table directory ignored\n" );
00749
00750 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT;
00751 if (dir->Size)
00752 {
00753 TRACE("Delayed import, stub calls LoadLibrary\n" );
00754
00755
00756
00757
00758 #ifdef ImgDelayDescr
00759
00760
00761
00762 {
00763 ImgDelayDescr *pe_delay = NULL;
00764 pe_delay = (PImgDelayDescr)RVA(dir->VirtualAddress);
00765 TRACE_(delayhlp)("pe_delay->grAttrs = %08x\n", pe_delay->grAttrs);
00766 TRACE_(delayhlp)("pe_delay->szName = %s\n", pe_delay->szName);
00767 TRACE_(delayhlp)("pe_delay->phmod = %08x\n", pe_delay->phmod);
00768 TRACE_(delayhlp)("pe_delay->pIAT = %08x\n", pe_delay->pIAT);
00769 TRACE_(delayhlp)("pe_delay->pINT = %08x\n", pe_delay->pINT);
00770 TRACE_(delayhlp)("pe_delay->pBoundIAT = %08x\n", pe_delay->pBoundIAT);
00771 TRACE_(delayhlp)("pe_delay->pUnloadIAT = %08x\n", pe_delay->pUnloadIAT);
00772 TRACE_(delayhlp)("pe_delay->dwTimeStamp = %08x\n", pe_delay->dwTimeStamp);
00773 }
00774 #endif
00775 }
00776
00777 dir = nt->OptionalHeader.DataDirectory+IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR;
00778 if (dir->Size) FIXME("Unknown directory 14 ignored\n" );
00779
00780 dir = nt->OptionalHeader.DataDirectory+15;
00781 if (dir->Size) FIXME("Unknown directory 15 ignored\n" );
00782
00783
00784
00785
00786 wm = (WINE_MODREF *)HeapAlloc( GetProcessHeap(),
00787 HEAP_ZERO_MEMORY, sizeof(*wm) );
00788 wm->module = hModule;
00789
00790 if ( builtin )
00791 wm->flags |= WINE_MODREF_INTERNAL;
00792 if ( flags & DONT_RESOLVE_DLL_REFERENCES )
00793 wm->flags |= WINE_MODREF_DONT_RESOLVE_REFS;
00794 if ( flags & LOAD_LIBRARY_AS_DATAFILE )
00795 wm->flags |= WINE_MODREF_LOAD_AS_DATAFILE;
00796
00797 wm->type = MODULE32_PE;
00798 wm->binfmt.pe.pe_export = pe_export;
00799 wm->binfmt.pe.pe_import = pe_import;
00800 wm->binfmt.pe.pe_resource = pe_resource;
00801 wm->binfmt.pe.tlsindex = -1;
00802
00803 wm->filename = malloc(strlen(filename)+1);
00804 strcpy(wm->filename, filename );
00805 wm->modname = strrchr( wm->filename, '\\' );
00806 if (!wm->modname) wm->modname = wm->filename;
00807 else wm->modname++;
00808
00809 if ( pe_export )
00810 dump_exports( hModule );
00811
00812
00813
00814 if ( pe_import
00815 && !( wm->flags & WINE_MODREF_LOAD_AS_DATAFILE )
00816 && !( wm->flags & WINE_MODREF_DONT_RESOLVE_REFS )
00817 && fixup_imports( wm ) )
00818 {
00819
00820 return NULL;
00821 }
00822
00823 return wm;
00824
00825 return wm;
00826 }
00827
00828
00829
00830
00831
00832 WINE_MODREF *PE_LoadLibraryExA (LPCSTR name, DWORD flags)
00833 {
00834 HMODULE hModule32;
00835 WINE_MODREF *wm;
00836 char filename[256];
00837 int hFile;
00838 WORD version = 0;
00839
00840
00841 strncpy(filename, name, sizeof(filename));
00842 hFile=open(filename, O_RDONLY);
00843 if(hFile==-1)
00844 return NULL;
00845
00846
00847 hModule32 = PE_LoadImage( hFile, filename, &version );
00848 if (!hModule32)
00849 {
00850 SetLastError( ERROR_OUTOFMEMORY );
00851 return NULL;
00852 }
00853
00854 if ( !(wm = PE_CreateModule( hModule32, filename, flags, FALSE )) )
00855 {
00856 ERR( "can't load %s\n", filename );
00857 SetLastError( ERROR_OUTOFMEMORY );
00858 return NULL;
00859 }
00860 close(hFile);
00861
00862 return wm;
00863 }
00864
00865
00866
00867
00868
00869
00870
00871 void PE_UnloadLibrary(WINE_MODREF *wm)
00872 {
00873 TRACE(" unloading %s\n", wm->filename);
00874
00875 if (wm->filename)
00876 free(wm->filename);
00877 if (wm->short_filename)
00878 free(wm->short_filename);
00879 HeapFree( GetProcessHeap(), 0, wm->deps );
00880 VirtualFree( (LPVOID)wm->module, 0, MEM_RELEASE );
00881 HeapFree( GetProcessHeap(), 0, wm );
00882
00883 }
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906 static void __attribute__((noinline)) extend_stack_for_dll_alloca(void)
00907 {
00908 #if !defined(__FreeBSD__) && !defined(__DragonFly__)
00909 volatile int* mem=alloca(0x20000);
00910 *mem=0x1234;
00911 #endif
00912 }
00913
00914
00915
00916
00917
00918
00919 WIN_BOOL PE_InitDLL( WINE_MODREF *wm, DWORD type, LPVOID lpReserved )
00920 {
00921 WIN_BOOL retv = TRUE;
00922 assert( wm->type == MODULE32_PE );
00923
00924
00925 if ((PE_HEADER(wm->module)->FileHeader.Characteristics & IMAGE_FILE_DLL) &&
00926 (PE_HEADER(wm->module)->OptionalHeader.AddressOfEntryPoint)
00927 ) {
00928 DLLENTRYPROC entry ;
00929 entry = (void*)PE_FindExportedFunction(wm, "DllMain", 0);
00930 if(entry==NULL)
00931 entry = (void*)RVA_PTR( wm->module,OptionalHeader.AddressOfEntryPoint );
00932
00933 TRACE_(relay)("CallTo32(entryproc=%p,module=%08x,type=%ld,res=%p)\n",
00934 entry, wm->module, type, lpReserved );
00935
00936
00937 TRACE("Entering DllMain(");
00938 switch(type)
00939 {
00940 case DLL_PROCESS_DETACH:
00941 TRACE("DLL_PROCESS_DETACH) ");
00942 break;
00943 case DLL_PROCESS_ATTACH:
00944 TRACE("DLL_PROCESS_ATTACH) ");
00945 break;
00946 case DLL_THREAD_DETACH:
00947 TRACE("DLL_THREAD_DETACH) ");
00948 break;
00949 case DLL_THREAD_ATTACH:
00950 TRACE("DLL_THREAD_ATTACH) ");
00951 break;
00952 }
00953 TRACE("for %s\n", wm->filename);
00954 extend_stack_for_dll_alloca();
00955 retv = entry( wm->module, type, lpReserved );
00956 }
00957
00958 return retv;
00959 }
00960
00961 static LPVOID
00962 _fixup_address(PIMAGE_OPTIONAL_HEADER opt,int delta,LPVOID addr) {
00963 if ( ((DWORD)addr>opt->ImageBase) &&
00964 ((DWORD)addr<opt->ImageBase+opt->SizeOfImage)
00965 )
00966
00967 return (LPVOID)(((DWORD)addr)+delta);
00968 else
00969
00970 return addr;
00971 }