diff --git a/dlls/kernel/kernel16_private.h b/dlls/kernel/kernel16_private.h index 2f4cf012a7e..9b2ba6428d4 100644 --- a/dlls/kernel/kernel16_private.h +++ b/dlls/kernel/kernel16_private.h @@ -61,11 +61,12 @@ typedef struct _NE_MODULE WORD ne_swaparea; /* 3c Min. swap area size */ WORD ne_expver; /* 3e Expected Windows version */ /* From here, these are extra fields not present in normal Windows */ - HMODULE module32; /* 40 PE module handle for Win32 modules */ - HMODULE16 self; /* 44 Handle for this module */ - WORD self_loading_sel; /* 46 Selector used for self-loading apps. */ - LPVOID rsrc32_map; /* 48 HRSRC 16->32 map (for 32-bit modules) */ - HANDLE fd; /* 4c handle to the binary file */ + HMODULE module32; /* PE module handle for Win32 modules */ + HMODULE16 self; /* Handle for this module */ + WORD self_loading_sel; /* Selector used for self-loading apps. */ + LPVOID rsrc32_map; /* HRSRC 16->32 map (for 32-bit modules) */ + LPCVOID mapping; /* mapping of the binary file */ + SIZE_T mapping_size; /* size of the file mapping */ } NE_MODULE; typedef struct @@ -132,6 +133,14 @@ extern THHOOK *pThhook; #define NE_MODULE_NAME(pModule) \ (((OFSTRUCT *)((char*)(pModule) + (pModule)->fileinfo))->szPathName) +#define NE_GET_DATA(pModule,offset,size) \ + ((const void *)(((offset)+(size) <= pModule->mapping_size) ? \ + (const char *)pModule->mapping + (offset) : NULL)) + +#define NE_READ_DATA(pModule,buffer,offset,size) \ + (((offset)+(size) <= pModule->mapping_size) ? \ + (memcpy( buffer, (const char *)pModule->mapping + (offset), (size) ), TRUE) : FALSE) + #define CURRENT_STACK16 ((STACK16FRAME*)MapSL((SEGPTR)NtCurrentTeb()->WOW32Reserved)) #define CURRENT_DS (CURRENT_STACK16->ds) @@ -158,7 +167,6 @@ extern WORD NE_GetOrdinal( HMODULE16 hModule, const char *name ); extern FARPROC16 WINAPI NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal ); extern FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop ); extern BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset ); -extern HANDLE NE_OpenFile( NE_MODULE *pModule ); extern DWORD NE_StartTask(void); /* ne_segment.c */ diff --git a/dlls/kernel/ne_module.c b/dlls/kernel/ne_module.c index e0f8a0c0ed4..d32d5f8987c 100644 --- a/dlls/kernel/ne_module.c +++ b/dlls/kernel/ne_module.c @@ -564,46 +564,6 @@ BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset ) } -/*********************************************************************** - * NE_OpenFile - */ -HANDLE NE_OpenFile( NE_MODULE *pModule ) -{ - HANDLE handle; - char *name = NE_MODULE_NAME( pModule ); - - TRACE("(%p)\n", pModule ); - - if (pModule->fd) - { - if (!DuplicateHandle( GetCurrentProcess(), pModule->fd, - GetCurrentProcess(), &handle, 0, FALSE, - DUPLICATE_SAME_ACCESS )) handle = INVALID_HANDLE_VALUE; - } - else - { - handle = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ, - NULL, OPEN_EXISTING, 0, 0 ); - } - if (handle == INVALID_HANDLE_VALUE) - ERR( "Can't open file '%s' for module %04x\n", name, pModule->self ); - - TRACE("opened '%s' -> %p\n", name, handle); - return handle; -} - - -/* wrapper for SetFilePointer and ReadFile */ -static BOOL read_data( HANDLE handle, LONG offset, void *buffer, DWORD size ) -{ - DWORD result; - - if (SetFilePointer( handle, offset, NULL, SEEK_SET ) == INVALID_SET_FILE_POINTER) return FALSE; - if (!ReadFile( handle, buffer, size, &result, NULL )) return FALSE; - return (result == size); -} - - /*********************************************************************** * build_bundle_data * @@ -676,24 +636,39 @@ static void *build_bundle_data( NE_MODULE *pModule, void *dest, const BYTE *tabl * * Build the in-memory module from the on-disk data. */ -static HMODULE16 build_module( const IMAGE_DOS_HEADER *mz_header, const IMAGE_OS2_HEADER *ne_header, - HANDLE handle, LPCSTR path, const void *fastload, - unsigned int fastload_offset, unsigned int fastload_length ) +static HMODULE16 build_module( const void *mapping, SIZE_T mapping_size, LPCSTR path ) { + const IMAGE_DOS_HEADER *mz_header = mapping; + const IMAGE_OS2_HEADER *ne_header; + const struct ne_segment_table_entry_s *pSeg; + const void *ptr; int i; size_t size; HMODULE16 hModule; NE_MODULE *pModule; - BYTE *buffer, *pData, *ptr; + BYTE *buffer, *pData, *end; OFSTRUCT *ofs; - struct ne_segment_table_entry_s *pSeg; - /* Read a block from either the file or the fast-load area. */ -#define READ(offset,size,buffer) \ - ((fastload && ((offset) >= fastload_offset) && \ - ((offset)+(size) <= fastload_offset+fastload_length)) ? \ - (memcpy( buffer, (const char *)fastload+(offset)-fastload_offset, (size) ), TRUE) : \ - (handle && read_data( handle, (offset), (buffer), (size)))) + if (mapping_size < sizeof(*mz_header)) return ERROR_BAD_FORMAT; + if (mz_header->e_magic != IMAGE_DOS_SIGNATURE) return ERROR_BAD_FORMAT; + ne_header = (const IMAGE_OS2_HEADER *)((const char *)mapping + mz_header->e_lfanew); + if (mz_header->e_lfanew + sizeof(*ne_header) > mapping_size) return ERROR_BAD_FORMAT; + if (ne_header->ne_magic == IMAGE_NT_SIGNATURE) return 21; /* win32 exe */ + if (ne_header->ne_magic == IMAGE_OS2_SIGNATURE_LX) + { + MESSAGE("Sorry, %s is an OS/2 linear executable (LX) file!\n", path); + return 12; + } + if (ne_header->ne_magic != IMAGE_OS2_SIGNATURE) return ERROR_BAD_FORMAT; + + /* We now have a valid NE header */ + + /* check to be able to fall back to loading OS/2 programs as DOS + * FIXME: should this check be reversed in order to be less strict? + * (only fail for OS/2 ne_exetyp 0x01 here?) */ + if ((ne_header->ne_exetyp != 0x02 /* Windows */) + && (ne_header->ne_exetyp != 0x04) /* Windows 386 */) + return ERROR_BAD_FORMAT; size = sizeof(NE_MODULE) + /* segment table */ @@ -724,28 +699,23 @@ static HMODULE16 build_module( const IMAGE_DOS_HEADER *mz_header, const IMAGE_OS /* check programs for default minimal stack size */ if (!(pModule->ne_flags & NE_FFLAGS_LIBMODULE) && (pModule->ne_stack < 0x1400)) pModule->ne_stack = 0x1400; - pModule->module32 = 0; - pModule->self = hModule; - pModule->self_loading_sel = 0; + + pModule->self = hModule; + pModule->mapping = mapping; + pModule->mapping_size = mapping_size; + pData = (BYTE *)(pModule + 1); /* Clear internal Wine flags in case they are set in the EXE file */ pModule->ne_flags &= ~(NE_FFLAGS_BUILTIN | NE_FFLAGS_WIN32); - /* allocate temporary buffer for segment and entry tables */ - - if (!(buffer = HeapAlloc( GetProcessHeap(), 0, - max( ne_header->ne_cseg * sizeof(*pSeg), ne_header->ne_cbenttab ) ))) - goto failed; - /* Get the segment table */ pModule->ne_segtab = pData - (BYTE *)pModule; - if (!READ( mz_header->e_lfanew + ne_header->ne_segtab, - ne_header->ne_cseg * sizeof(struct ne_segment_table_entry_s), buffer )) + if (!(pSeg = NE_GET_DATA( pModule, mz_header->e_lfanew + ne_header->ne_segtab, + ne_header->ne_cseg * sizeof(struct ne_segment_table_entry_s) ))) goto failed; - pSeg = (struct ne_segment_table_entry_s *)buffer; for (i = ne_header->ne_cseg; i > 0; i--, pSeg++) { memcpy( pData, pSeg, sizeof(*pSeg) ); @@ -757,8 +727,8 @@ static HMODULE16 build_module( const IMAGE_DOS_HEADER *mz_header, const IMAGE_OS if (ne_header->ne_rsrctab < ne_header->ne_restab) { pModule->ne_rsrctab = pData - (BYTE *)pModule; - if (!READ( mz_header->e_lfanew + ne_header->ne_rsrctab, - ne_header->ne_restab - ne_header->ne_rsrctab, pData )) goto failed; + if (!NE_READ_DATA( pModule, pData, mz_header->e_lfanew + ne_header->ne_rsrctab, + ne_header->ne_restab - ne_header->ne_rsrctab )) goto failed; pData += ne_header->ne_restab - ne_header->ne_rsrctab; } else pModule->ne_rsrctab = 0; /* No resource table */ @@ -766,8 +736,8 @@ static HMODULE16 build_module( const IMAGE_DOS_HEADER *mz_header, const IMAGE_OS /* Get the resident names table */ pModule->ne_restab = pData - (BYTE *)pModule; - if (!READ( mz_header->e_lfanew + ne_header->ne_restab, - ne_header->ne_modtab - ne_header->ne_restab, pData )) goto failed; + if (!NE_READ_DATA( pModule, pData, mz_header->e_lfanew + ne_header->ne_restab, + ne_header->ne_modtab - ne_header->ne_restab )) goto failed; pData += ne_header->ne_modtab - ne_header->ne_restab; /* Get the module references table */ @@ -775,8 +745,8 @@ static HMODULE16 build_module( const IMAGE_DOS_HEADER *mz_header, const IMAGE_OS if (ne_header->ne_cmod > 0) { pModule->ne_modtab = pData - (BYTE *)pModule; - if (!READ( mz_header->e_lfanew + ne_header->ne_modtab, - ne_header->ne_cmod * sizeof(WORD), pData )) goto failed; + if (!NE_READ_DATA( pModule, pData, mz_header->e_lfanew + ne_header->ne_modtab, + ne_header->ne_cmod * sizeof(WORD) )) goto failed; pData += ne_header->ne_cmod * sizeof(WORD); } else pModule->ne_modtab = 0; /* No module references */ @@ -784,23 +754,21 @@ static HMODULE16 build_module( const IMAGE_DOS_HEADER *mz_header, const IMAGE_OS /* Get the imported names table */ pModule->ne_imptab = pData - (BYTE *)pModule; - if (!READ( mz_header->e_lfanew + ne_header->ne_imptab, - ne_header->ne_enttab - ne_header->ne_imptab, - pData )) goto failed; + if (!NE_READ_DATA( pModule, pData, mz_header->e_lfanew + ne_header->ne_imptab, + ne_header->ne_enttab - ne_header->ne_imptab )) goto failed; pData += ne_header->ne_enttab - ne_header->ne_imptab; /* Load entry table, convert it to the optimized version used by Windows */ pModule->ne_enttab = pData - (BYTE *)pModule; - if (!READ( mz_header->e_lfanew + ne_header->ne_enttab, - ne_header->ne_cbenttab, buffer )) goto failed; - - ptr = build_bundle_data( pModule, pData, buffer ); + if (!(ptr = NE_GET_DATA( pModule, mz_header->e_lfanew + ne_header->ne_enttab, + ne_header->ne_cbenttab ))) goto failed; + end = build_bundle_data( pModule, pData, ptr ); pData += ne_header->ne_cbenttab + sizeof(ET_BUNDLE) + 2 * (ne_header->ne_cbenttab - ne_header->ne_cmovent*6); - if (ptr > pData) + if (end > pData) { FIXME( "not enough space for entry table for %s\n", debugstr_a(path) ); goto failed; @@ -823,8 +791,8 @@ static HMODULE16 build_module( const IMAGE_DOS_HEADER *mz_header, const IMAGE_OS pModule->nrname_handle = GlobalAlloc16( 0, ne_header->ne_cbnrestab ); if (!pModule->nrname_handle) goto failed; FarSetOwner16( pModule->nrname_handle, hModule ); - ptr = GlobalLock16( pModule->nrname_handle ); - if (!read_data( handle, ne_header->ne_nrestab, ptr, ne_header->ne_cbnrestab )) + buffer = GlobalLock16( pModule->nrname_handle ); + if (!NE_READ_DATA( pModule, buffer, ne_header->ne_nrestab, ne_header->ne_cbnrestab )) { GlobalFree16( pModule->nrname_handle ); goto failed; @@ -847,92 +815,12 @@ static HMODULE16 build_module( const IMAGE_DOS_HEADER *mz_header, const IMAGE_OS } else pModule->dlls_to_init = 0; - HeapFree( GetProcessHeap(), 0, buffer ); NE_RegisterModule( pModule ); - - if (handle) - { - UINT drive_type = GetDriveTypeA( path ); - /* keep the file handle open if not on a removable media */ - if (drive_type != DRIVE_REMOVABLE && drive_type != DRIVE_CDROM) - DuplicateHandle( GetCurrentProcess(), handle, - GetCurrentProcess(), &pModule->fd, 0, FALSE, - DUPLICATE_SAME_ACCESS ); - } - return hModule; failed: - HeapFree( GetProcessHeap(), 0, buffer ); GlobalFree16( hModule ); return ERROR_BAD_FORMAT; -#undef READ -} - - -/*********************************************************************** - * NE_LoadExeHeader - */ -static HMODULE16 NE_LoadExeHeader( HANDLE handle, LPCSTR path ) -{ - IMAGE_DOS_HEADER mz_header; - IMAGE_OS2_HEADER ne_header; - HMODULE16 hModule; - char *fastload = NULL; - unsigned int fastload_offset = 0, fastload_length = 0; - - if (!read_data( handle, 0, &mz_header, sizeof(mz_header)) || - (mz_header.e_magic != IMAGE_DOS_SIGNATURE)) - return ERROR_BAD_FORMAT; - - if (!read_data( handle, mz_header.e_lfanew, &ne_header, sizeof(ne_header) )) - return ERROR_BAD_FORMAT; - - if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE16)21; /* win32 exe */ - if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) { - MESSAGE("Sorry, this is an OS/2 linear executable (LX) file!\n"); - return (HMODULE16)12; - } - if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return ERROR_BAD_FORMAT; - - /* We now have a valid NE header */ - - /* check to be able to fall back to loading OS/2 programs as DOS - * FIXME: should this check be reversed in order to be less strict? - * (only fail for OS/2 ne_exetyp 0x01 here?) */ - if ((ne_header.ne_exetyp != 0x02 /* Windows */) - && (ne_header.ne_exetyp != 0x04) /* Windows 386 */) - return ERROR_BAD_FORMAT; - - /* Read the fast-load area */ - - if (ne_header.ne_flagsothers & NE_AFLAGS_FASTLOAD) - { - fastload_offset=ne_header.ne_pretthunks << ne_header.ne_align; - fastload_length=ne_header.ne_psegrefbytes << ne_header.ne_align; - TRACE("Using fast-load area offset=%x len=%d\n", - fastload_offset, fastload_length ); - if ((fastload = HeapAlloc( GetProcessHeap(), 0, fastload_length )) != NULL) - { - if (!read_data( handle, fastload_offset, fastload, fastload_length)) - { - HeapFree( GetProcessHeap(), 0, fastload ); - WARN("Error reading fast-load area!\n"); - fastload = NULL; - } - } - } - - hModule = build_module( &mz_header, &ne_header, handle, path, - fastload, fastload_offset, fastload_length ); - HeapFree( GetProcessHeap(), 0, fastload ); - - if (hModule >= 32) - { - SNOOP16_RegisterDLL( hModule, path ); - NE_InitResourceHandler( hModule ); - } - return hModule; } @@ -992,7 +880,7 @@ static BOOL NE_LoadDLLs( NE_MODULE *pModule ) * * Load first instance of NE module from file. * - * pModule must point to a module structure prepared by NE_LoadExeHeader. + * pModule must point to a module structure prepared by build_module_data. * This routine must never be called twice on a module. * */ @@ -1042,14 +930,33 @@ static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only ) HINSTANCE16 hInstance; HFILE16 hFile; OFSTRUCT ofs; + HANDLE mapping; + void *ptr; + MEMORY_BASIC_INFORMATION info; /* Open file */ if ((hFile = OpenFile16( name, &ofs, OF_READ|OF_SHARE_DENY_WRITE )) == HFILE_ERROR16) return ERROR_FILE_NOT_FOUND; - hModule = NE_LoadExeHeader( DosFileHandleToWin32Handle(hFile), ofs.szPathName ); + mapping = CreateFileMappingW( DosFileHandleToWin32Handle(hFile), NULL, PAGE_WRITECOPY, 0, 0, NULL ); _lclose16( hFile ); - if (hModule < 32) return hModule; + if (!mapping) return ERROR_BAD_FORMAT; + + ptr = MapViewOfFile( mapping, FILE_MAP_COPY, 0, 0, 0 ); + CloseHandle( mapping ); + if (!ptr) return ERROR_BAD_FORMAT; + + VirtualQuery( ptr, &info, sizeof(info) ); + hModule = build_module( ptr, info.RegionSize, ofs.szPathName ); + + if (hModule < 32) + { + UnmapViewOfFile( ptr ); + return hModule; + } + + SNOOP16_RegisterDLL( hModule, ofs.szPathName ); + NE_InitResourceHandler( hModule ); pModule = NE_GetPtr( hModule ); @@ -1079,14 +986,12 @@ static HMODULE16 NE_DoLoadBuiltinModule( const BUILTIN16_DESCRIPTOR *descr ) SEGTABLEENTRY *pSegTable; const IMAGE_DOS_HEADER *mz_header; const IMAGE_OS2_HEADER *ne_header; - unsigned int fastload_offset, fastload_length; + SIZE_T mapping_size; mz_header = descr->module; ne_header = (const IMAGE_OS2_HEADER *)((const BYTE *)mz_header + mz_header->e_lfanew); - fastload_offset = ne_header->ne_pretthunks << ne_header->ne_align; - fastload_length = ne_header->ne_psegrefbytes << ne_header->ne_align; - hModule = build_module( mz_header, ne_header, 0, descr->file_name, - descr->module, fastload_offset, fastload_length ); + mapping_size = ne_header->ne_psegrefbytes << ne_header->ne_align; + hModule = build_module( descr->module, mapping_size, descr->file_name ); if (hModule < 32) return hModule; pModule = GlobalLock16( hModule ); pModule->ne_flags |= NE_FFLAGS_BUILTIN; @@ -1502,7 +1407,7 @@ static BOOL16 NE_FreeModule( HMODULE16 hModule, BOOL call_wep ) /* Clear magic number just in case */ pModule->ne_magic = pModule->self = 0; - if (pModule->fd) CloseHandle( pModule->fd ); + if (!(pModule->ne_flags & NE_FFLAGS_BUILTIN)) UnmapViewOfFile( (void *)pModule->mapping ); /* Remove it from the linked list */ diff --git a/dlls/kernel/ne_segment.c b/dlls/kernel/ne_segment.c index b76cf84736d..8756d127e27 100644 --- a/dlls/kernel/ne_segment.c +++ b/dlls/kernel/ne_segment.c @@ -116,162 +116,58 @@ static const char *NE_GetRelocAddrName( BYTE addr_type, int additive ) /*********************************************************************** - * NE_LoadSegment + * NE_OpenFile */ -BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum ) +static HFILE16 NE_OpenFile( NE_MODULE *pModule ) { - SEGTABLEENTRY *pSegTable, *pSeg; - HMODULE16 *pModuleTable; - WORD count, i, offset, next_offset; + char *name = NE_MODULE_NAME( pModule ); + HANDLE handle = CreateFileA( name, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, 0, 0 ); + + if (handle == INVALID_HANDLE_VALUE) + { + ERR( "Can't open file '%s' for module %04x\n", name, pModule->self ); + return HFILE_ERROR; + } + return Win32HandleToDosFileHandle( handle ); +} + + +/*********************************************************************** + * apply_relocations + * + * Apply relocations to a segment. Helper for NE_LoadSegment. + */ +static inline BOOL apply_relocations( NE_MODULE *pModule, const struct relocation_entry_s *rep, + int count, int segnum ) +{ + BYTE *func_name; + char buffer[256]; + int i, ordinal; + WORD offset, *sp; HMODULE16 module; FARPROC16 address = 0; - HANDLE hf; - DWORD res; - struct relocation_entry_s *rep, *reloc_entries; - BYTE *func_name; - int size; - char* mem; - - char buffer[256]; - int ordinal, additive; - unsigned short *sp; - - pSegTable = NE_SEG_TABLE( pModule ); - pSeg = pSegTable + segnum - 1; - - if (pSeg->flags & NE_SEGFLAGS_LOADED) - { - /* self-loader ? -> already loaded it */ - if (pModule->ne_flags & NE_FFLAGS_SELFLOAD) - return TRUE; - - /* leave, except for DGROUP, as this may be the second instance */ - if (segnum != pModule->ne_autodata) - return TRUE; - } - - if (!pSeg->filepos) return TRUE; /* No file image, just return */ - - pModuleTable = (HMODULE16 *)((char *)pModule + pModule->ne_modtab); - - hf = NE_OpenFile( pModule ); - TRACE_(module)("Loading segment %d, hSeg=%04x, flags=%04x\n", - segnum, pSeg->hSeg, pSeg->flags ); - SetFilePointer( hf, pSeg->filepos << pModule->ne_align, NULL, SEEK_SET ); - if (pSeg->size) size = pSeg->size; - else size = pSeg->minsize ? pSeg->minsize : 0x10000; - mem = GlobalLock16(pSeg->hSeg); - if (pModule->ne_flags & NE_FFLAGS_SELFLOAD && segnum > 1) - { - /* Implement self-loading segments */ - SELFLOADHEADER *selfloadheader; - void *oldstack; - HANDLE hFile32; - HFILE16 hFile16; - WORD args[3]; - DWORD ret; - - selfloadheader = MapSL( MAKESEGPTR(SEL(pSegTable->hSeg),0) ); - oldstack = NtCurrentTeb()->WOW32Reserved; - NtCurrentTeb()->WOW32Reserved = (void *)MAKESEGPTR(pModule->self_loading_sel, - 0xff00 - sizeof(STACK16FRAME)); - - TRACE_(dll)("CallLoadAppSegProc(hmodule=0x%04x,hf=%p,segnum=%d\n", - pModule->self,hf,segnum ); - DuplicateHandle( GetCurrentProcess(), hf, GetCurrentProcess(), &hFile32, - 0, FALSE, DUPLICATE_SAME_ACCESS ); - hFile16 = Win32HandleToDosFileHandle( hFile32 ); - args[2] = pModule->self; - args[1] = hFile16; - args[0] = segnum; - WOWCallback16Ex( (DWORD)selfloadheader->LoadAppSeg, WCB16_PASCAL, sizeof(args), args, &ret ); - pSeg->hSeg = LOWORD(ret); - TRACE_(dll)("Ret CallLoadAppSegProc: hSeg = 0x%04x\n", pSeg->hSeg); - _lclose16( hFile16 ); - NtCurrentTeb()->WOW32Reserved = oldstack; - } - else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED)) - ReadFile(hf, mem, size, &res, NULL); - else { - /* - The following bit of code for "iterated segments" was written without - any documentation on the format of these segments. It seems to work, - but may be missing something. If you have any doc please either send - it to me or fix the code yourself. gfm@werple.mira.net.au - */ - char* buff = HeapAlloc(GetProcessHeap(), 0, size); - char* curr = buff; - - if(buff == NULL) { - WARN_(dll)("Memory exhausted!\n"); - goto fail; - } - - ReadFile(hf, buff, size, &res, NULL); - while(curr < buff + size) { - unsigned int rept = ((short*)curr)[0]; - unsigned int len = ((short*)curr)[1]; - - curr += 2*sizeof(short); - for(; rept > 0; rept--) { - char* bytes = curr; - unsigned int byte; - for(byte = 0; byte < len; byte++) - *mem++ = *bytes++; - } - curr += len; - } - HeapFree(GetProcessHeap(), 0, buff); - } - - pSeg->flags |= NE_SEGFLAGS_LOADED; - - /* Perform exported function prolog fixups */ - NE_FixupSegmentPrologs( pModule, segnum ); - - if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA)) - goto succeed; /* No relocation data, we are done */ - - ReadFile(hf, &count, sizeof(count), &res, NULL); - if (!count) goto succeed; - - TRACE("Fixups for %.*s, segment %d, hSeg %04x\n", - *((BYTE *)pModule + pModule->ne_restab), - (char *)pModule + pModule->ne_restab + 1, - segnum, pSeg->hSeg ); - - reloc_entries = HeapAlloc(GetProcessHeap(), 0, count * sizeof(struct relocation_entry_s)); - if(reloc_entries == NULL) { - WARN("Not enough memory for relocation entries!\n"); - goto fail; - } - if (!ReadFile( hf, reloc_entries, count * sizeof(struct relocation_entry_s), &res, NULL) || - (res != count * sizeof(struct relocation_entry_s))) - { - WARN("Unable to read relocation information\n" ); - goto fail; - } + HMODULE16 *pModuleTable = (HMODULE16 *)((char *)pModule + pModule->ne_modtab); + SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule ); + SEGTABLEENTRY *pSeg = pSegTable + segnum - 1; /* * Go through the relocation table one entry at a time. */ - rep = reloc_entries; for (i = 0; i < count; i++, rep++) { - /* - * Get the target address corresponding to this entry. - */ + /* + * Get the target address corresponding to this entry. + */ - /* If additive, there is no target chain list. Instead, add source - and target */ - additive = rep->relocation_type & NE_RELFLAG_ADDITIVE; - rep->relocation_type &= 0x3; - - switch (rep->relocation_type) - { - case NE_RELTYPE_ORDINAL: + /* If additive, there is no target chain list. Instead, add source + and target */ + int additive = rep->relocation_type & NE_RELFLAG_ADDITIVE; + switch (rep->relocation_type & 3) + { + case NE_RELTYPE_ORDINAL: module = pModuleTable[rep->target1-1]; - ordinal = rep->target2; + ordinal = rep->target2; address = NE_GetEntryPoint( module, ordinal ); if (!address) { @@ -300,9 +196,9 @@ BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum ) ordinal, HIWORD(address), LOWORD(address), NE_GetRelocAddrName( rep->address_type, additive ) ); } - break; + break; - case NE_RELTYPE_NAME: + case NE_RELTYPE_NAME: module = pModuleTable[rep->target1-1]; func_name = (char *)pModule + pModule->ne_imptab + rep->target2; memcpy( buffer, func_name+1, *func_name ); @@ -321,51 +217,51 @@ BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum ) if (!address) address = (FARPROC16) 0xdeadbeef; if (TRACE_ON(fixup)) { - NE_MODULE *pTarget = NE_GetPtr( module ); + NE_MODULE *pTarget = NE_GetPtr( module ); TRACE("%d: %.*s.%s=%04x:%04x %s\n", i + 1, *((BYTE *)pTarget + pTarget->ne_restab), (char *)pTarget + pTarget->ne_restab + 1, func_name, HIWORD(address), LOWORD(address), NE_GetRelocAddrName( rep->address_type, additive ) ); } - break; + break; - case NE_RELTYPE_INTERNAL: - if ((rep->target1 & 0xff) == 0xff) - { - address = NE_GetEntryPoint( pModule->self, rep->target2 ); - } - else - { + case NE_RELTYPE_INTERNAL: + if ((rep->target1 & 0xff) == 0xff) + { + address = NE_GetEntryPoint( pModule->self, rep->target2 ); + } + else + { address = (FARPROC16)MAKESEGPTR( SEL(pSegTable[rep->target1-1].hSeg), rep->target2 ); - } + } - TRACE("%d: %04x:%04x %s\n", - i + 1, HIWORD(address), LOWORD(address), - NE_GetRelocAddrName( rep->address_type, additive ) ); - break; + TRACE("%d: %04x:%04x %s\n", + i + 1, HIWORD(address), LOWORD(address), + NE_GetRelocAddrName( rep->address_type, additive ) ); + break; - case NE_RELTYPE_OSFIXUP: - /* Relocation type 7: - * - * These appear to be used as fixups for the Windows - * floating point emulator. Let's just ignore them and - * try to use the hardware floating point. Linux should - * successfully emulate the coprocessor if it doesn't - * exist. - */ - TRACE("%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n", - i + 1, rep->relocation_type, rep->offset, - rep->target1, rep->target2, - NE_GetRelocAddrName( rep->address_type, additive ) ); - continue; - } + case NE_RELTYPE_OSFIXUP: + /* Relocation type 7: + * + * These appear to be used as fixups for the Windows + * floating point emulator. Let's just ignore them and + * try to use the hardware floating point. Linux should + * successfully emulate the coprocessor if it doesn't + * exist. + */ + TRACE("%d: TYPE %d, OFFSET %04x, TARGET %04x %04x %s\n", + i + 1, rep->relocation_type, rep->offset, + rep->target1, rep->target2, + NE_GetRelocAddrName( rep->address_type, additive ) ); + continue; + } - offset = rep->offset; + offset = rep->offset; /* Apparently, high bit of address_type is sometimes set; */ /* we ignore it for now */ - if (rep->address_type > NE_RADDR_OFFSET32) + if (rep->address_type > NE_RADDR_OFFSET32) { char module[10]; GetModuleName16( pModule->self, module, sizeof(module) ); @@ -383,17 +279,17 @@ BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum ) *(BYTE *)sp += LOBYTE((int)address); break; case NE_RADDR_OFFSET16: - *sp += LOWORD(address); + *sp += LOWORD(address); break; case NE_RADDR_POINTER32: - *sp += LOWORD(address); - *(sp+1) = HIWORD(address); + *sp += LOWORD(address); + *(sp+1) = HIWORD(address); break; case NE_RADDR_SELECTOR: - /* Borland creates additive records with offset zero. Strange, but OK */ + /* Borland creates additive records with offset zero. Strange, but OK */ if (*sp) ERR("Additive selector to %04x.Please report\n",*sp); - else + else *sp = HIWORD(address); break; default: @@ -404,6 +300,8 @@ BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum ) { do { + WORD next_offset; + sp = MapSL( MAKESEGPTR( SEL(pSeg->hSeg), offset ) ); next_offset = *sp; TRACE(" %04x:%04x\n", offset, *sp ); @@ -430,11 +328,6 @@ BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum ) } while (offset != 0xffff); } } - - HeapFree(GetProcessHeap(), 0, reloc_entries); - -succeed: - CloseHandle(hf); return TRUE; unknown: @@ -442,14 +335,125 @@ unknown: "TYPE %d, OFFSET %04x, TARGET %04x %04x\n", i + 1, rep->address_type, rep->relocation_type, rep->offset, rep->target1, rep->target2); - HeapFree(GetProcessHeap(), 0, reloc_entries); - -fail: - CloseHandle(hf); return FALSE; } +/*********************************************************************** + * NE_LoadSegment + */ +BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum ) +{ + WORD count; + DWORD pos; + const struct relocation_entry_s *rep; + int size; + SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule ); + SEGTABLEENTRY *pSeg = pSegTable + segnum - 1; + + if (pSeg->flags & NE_SEGFLAGS_LOADED) + { + /* self-loader ? -> already loaded it */ + if (pModule->ne_flags & NE_FFLAGS_SELFLOAD) + return TRUE; + + /* leave, except for DGROUP, as this may be the second instance */ + if (segnum != pModule->ne_autodata) + return TRUE; + } + + if (!pSeg->filepos) return TRUE; /* No file image, just return */ + + TRACE_(module)("Loading segment %d, hSeg=%04x, flags=%04x\n", + segnum, pSeg->hSeg, pSeg->flags ); + pos = pSeg->filepos << pModule->ne_align; + if (pSeg->size) size = pSeg->size; + else size = pSeg->minsize ? pSeg->minsize : 0x10000; + + if (pModule->ne_flags & NE_FFLAGS_SELFLOAD && segnum > 1) + { + /* Implement self-loading segments */ + SELFLOADHEADER *selfloadheader; + void *oldstack; + HFILE16 hFile16; + WORD args[3]; + DWORD ret; + + selfloadheader = MapSL( MAKESEGPTR(SEL(pSegTable->hSeg),0) ); + oldstack = NtCurrentTeb()->WOW32Reserved; + NtCurrentTeb()->WOW32Reserved = (void *)MAKESEGPTR(pModule->self_loading_sel, + 0xff00 - sizeof(STACK16FRAME)); + + hFile16 = NE_OpenFile( pModule ); + TRACE_(dll)("CallLoadAppSegProc(hmodule=0x%04x,hf=%x,segnum=%d\n", + pModule->self,hFile16,segnum ); + args[2] = pModule->self; + args[1] = hFile16; + args[0] = segnum; + WOWCallback16Ex( (DWORD)selfloadheader->LoadAppSeg, WCB16_PASCAL, sizeof(args), args, &ret ); + pSeg->hSeg = LOWORD(ret); + TRACE_(dll)("Ret CallLoadAppSegProc: hSeg = 0x%04x\n", pSeg->hSeg); + _lclose16( hFile16 ); + NtCurrentTeb()->WOW32Reserved = oldstack; + } + else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED)) + { + void *mem = GlobalLock16(pSeg->hSeg); + if (!NE_READ_DATA( pModule, mem, pos, size )) + return FALSE; + pos += size; + } + else + { + /* + The following bit of code for "iterated segments" was written without + any documentation on the format of these segments. It seems to work, + but may be missing something. + */ + const char *buff = NE_GET_DATA( pModule, pos, size ); + const char* curr = buff; + char *mem = GlobalLock16(pSeg->hSeg); + + pos += size; + if (buff == NULL) return FALSE; + + while(curr < buff + size) { + unsigned int rept = ((short*)curr)[0]; + unsigned int len = ((short*)curr)[1]; + + curr += 2*sizeof(short); + while (rept--) + { + memcpy( mem, curr, len ); + mem += len; + } + curr += len; + } + } + + pSeg->flags |= NE_SEGFLAGS_LOADED; + + /* Perform exported function prolog fixups */ + NE_FixupSegmentPrologs( pModule, segnum ); + + if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA)) + return TRUE; /* No relocation data, we are done */ + + if (!NE_READ_DATA( pModule, &count, pos, sizeof(count) ) || !count) return TRUE; + pos += sizeof(count); + + TRACE("Fixups for %.*s, segment %d, hSeg %04x\n", + *((BYTE *)pModule + pModule->ne_restab), + (char *)pModule + pModule->ne_restab + 1, + segnum, pSeg->hSeg ); + + if (!(rep = NE_GET_DATA( pModule, pos, count * sizeof(struct relocation_entry_s) ))) + return FALSE; + + return apply_relocations( pModule, rep, count, segnum ); +} + + /*********************************************************************** * NE_LoadAllSegments */ @@ -460,7 +464,6 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule ) if (pModule->ne_flags & NE_FFLAGS_SELFLOAD) { - HANDLE hf; HFILE16 hFile16; HGLOBAL16 sel; /* Handle self-loading modules */ @@ -484,8 +487,7 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule ) NtCurrentTeb()->WOW32Reserved = (void *)MAKESEGPTR(pModule->self_loading_sel, 0xff00 - sizeof(STACK16FRAME) ); - hf = NE_OpenFile(pModule); - hFile16 = Win32HandleToDosFileHandle( hf ); + hFile16 = NE_OpenFile(pModule); TRACE_(dll)("CallBootAppProc(hModule=0x%04x,hf=0x%04x)\n", pModule->self,hFile16); args[1] = pModule->self; diff --git a/dlls/kernel/resource16.c b/dlls/kernel/resource16.c index 1bf17d1b7c3..2ca2b7c2fc0 100644 --- a/dlls/kernel/resource16.c +++ b/dlls/kernel/resource16.c @@ -330,53 +330,42 @@ static NE_NAMEINFO *NE_FindResourceFromType( LPBYTE pResTab, NE_TYPEINFO *pTypeI HGLOBAL16 WINAPI NE_DefResourceHandler( HGLOBAL16 hMemObj, HMODULE16 hModule, HRSRC16 hRsrc ) { - HANDLE fd; + HGLOBAL16 handle; + WORD sizeShift; + NE_NAMEINFO* pNameInfo; NE_MODULE* pModule = NE_GetPtr( hModule ); - if (pModule && (pModule->ne_flags & NE_FFLAGS_BUILTIN)) + + if (!pModule) return 0; + + sizeShift = *(WORD *)((char *)pModule + pModule->ne_rsrctab); + pNameInfo = (NE_NAMEINFO *)((char *)pModule + hRsrc); + + if ( hMemObj ) + handle = GlobalReAlloc16( hMemObj, pNameInfo->length << sizeShift, 0 ); + else + handle = AllocResource16( hModule, hRsrc, 0 ); + + if (handle) { - HGLOBAL16 handle; - WORD sizeShift = *(WORD *)((char *)pModule + pModule->ne_rsrctab); - NE_NAMEINFO* pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc); - - if ( hMemObj ) - handle = GlobalReAlloc16( hMemObj, pNameInfo->length << sizeShift, 0 ); - else - handle = AllocResource16( hModule, hRsrc, 0 ); - - if ( handle ) + if (pModule->ne_flags & NE_FFLAGS_BUILTIN) { /* NOTE: hRsrcMap points to start of built-in resource data */ memcpy( GlobalLock16( handle ), (char *)pModule->rsrc32_map + (pNameInfo->offset << sizeShift), pNameInfo->length << sizeShift ); } - return handle; - } - if (pModule && (fd = NE_OpenFile( pModule )) != INVALID_HANDLE_VALUE) - { - HGLOBAL16 handle; - WORD sizeShift = *(WORD *)((char *)pModule + pModule->ne_rsrctab); - NE_NAMEINFO* pNameInfo = (NE_NAMEINFO*)((char*)pModule + hRsrc); - - TRACE("loading, pos=%d, len=%d\n", - (int)pNameInfo->offset << sizeShift, - (int)pNameInfo->length << sizeShift ); - if( hMemObj ) - handle = GlobalReAlloc16( hMemObj, pNameInfo->length << sizeShift, 0 ); else - handle = AllocResource16( hModule, hRsrc, 0 ); - - if( handle ) { - DWORD res; - SetFilePointer( fd, (int)pNameInfo->offset << sizeShift, NULL, SEEK_SET ); - ReadFile( fd, GlobalLock16( handle ), (int)pNameInfo->length << sizeShift, - &res, NULL ); + if (!NE_READ_DATA( pModule, GlobalLock16( handle ), + (int)pNameInfo->offset << sizeShift, + (int)pNameInfo->length << sizeShift )) + { + GlobalFree16( handle ); + handle = 0; + } } - CloseHandle(fd); - return handle; } - return (HGLOBAL16)0; + return handle; }