Use a memory mapping instead of file I/O to load 16-bit modules.
This commit is contained in:
parent
a890293f33
commit
8eb1630ce1
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue