wine/loader/ne_image.c
Alexandre Julliard 60ce85c965 Release 980201
Sun Feb  1 13:24:54 1998  Alexandre Julliard  <julliard@lrc.epfl.ch>

	* [files/drive.c]
	Added Device= parameter to drive configuration.

	* [if1632/relay.c]
	Throw() and Catch() now use the correct CATCHBUF layout (untested).

	* [tools/build.c] [include/stackframe.h] [loader/task.c]
	Moved 16-bit stack pointer into thread database.
	Save current %fs while running 16-bit code.

Fri Jan 30 09:25:49 1998  Martin Boehme  <boehme@informatik.mu-luebeck.de>

	* [graphics/mapping.c]
	Made DPtoLP32 and LPtoDP32 respect world transforms.

	* [graphics/path.c] [graphics/painting.c] [if1632/gdi.spec]
	  [include/path.h]
	More path support.

	* [include/gdi.h] [include/windows.h] [objects/dc.c]
	  [relay/gdi32.spec]
	Support for Get/SetArcDirection and Get/SetWorldTransform

	* [windows/hook.c]
	Fixed a bug in HOOK_Map16To32Common.

Thu Jan 29 23:43:18 1998  Douglas Ridgway <ridgway@taiga.gmcl.com>

	* [graphics/metafiledrv/init.c] [objects/metafile.c]
	Documentation for metafile related API calls. Fixed a bug to avoid
	documenting it.

	* [include/windows.h]
	Declaration for LoadImage.

Thu Jan 29 21:44:45 1998  Huw D M Davies <h.davies1@physics.oxford.ac.uk>

	* [graphics/win16drv/*]
	Changes to printing code to enable use of printer fonts with the
	win3.1 postscript driver. Remember to add printer=on to [wine]
	section of wine.conf . You will also need to disable truetype
	fonts from control panel. Winword 6.0 and Write seem to be happy
	with this...

	* [include/bitmap.h]
	Fix Widthbytes for 15bpp displays.

Tue Jan 27 20:54:08 1998  Kristian Nielsen <kristian.nielsen@risoe.dk>

	* [tsx11/*] [include/ts*] [tools/make_X11wrappers]
	Implemented thread-safe X11 wrappers.

Tue Jan 27 13:54:09 1998  Constantine Sapuntzakis  <csapuntz@tma-1.lcs.mit.edu>

	* [windows/queue.c]
	Forgot to convert thdb to thread_id.

	* [misc/registry.c]
	Sped up Windows 95 registry reading. Changed code to traverse
	registry as a tree rather than read in all possible keys
	(including dead ones). 

Tue Jan 27 12:46:09 1998  Marcus Meissner <msmeissn@cip.informatik.uni-erlangen.de>

	* [loader/pe_image.c][Makefile.in][scheduler/thread.c]
	  [libtest/hello5.c]
	Don't exit() on failed to load referenced dlls.
	Fixed static tls allocation for multiple threads.
	WINELIB should now be able to load PE dlls. A sample
	winelib program, that dynamically loads a internal dll
	is included.

	* [graphics/ddraw.c][include/ddraw.h][include/d3d.h]
	Cleaned up and enhanced further. Added several DirectX5
	interface definitions and DirectSurface3 implementation.
	Stubs for D3D (NOT coming soon, just there so it fails safely).

	* [multimedia/dsound.c][include/dsound.h]
	Actually works now for a lot of cases. Some DirectX5 stuff
	added. Still lacking several features.

	* [windows/dinput.c][include/dinput.h]
	Started implementing DirectInput. Doesn't work yet, don't 
	know why.

	* [if1632/thunk.c][misc/callbacks.c]
	  [win32/kernel.c][include/callbacks.h]
	Added WOWCallback16Ex, WOWHandle32.

	* [misc/cpu.c]
	Fixed GetSystemInfo, IsProcessorFeaturePresent.

	* [multimedia/joystick.c][multimedia/time.c]
	Several fixes. Small hack to get timerevents in timeGetTime() loops.

Tue Jan 20 11:26:27 1998  Slaven Rezic  <eserte@cs.tu-berlin.de>

	* [configure.in]
	Fixed check for union semun on FreeBSD systems.

Sun Jan 18 23:05:04 1998  Karl Backström <karl_b@geocities.com>

	* [misc/ole2nls.c] [programs/progman/Sw.rc] [programs/winhelp/Sw.rc]
	  [resources/sysres_Sw.rc]
	Added/updated Swedish language support.

Sun Jan 18 18:49:01 1998  Alex Korobka <alex@trantor.pharm.sunysb.edu>

	* [misc/winsock.c] [misc/winsock_dns.c] [windows/event.c]
	  [windows/win.c] [windows/dce.c] [windows/winpos.c]
	Bug fixes.

Sun Jan 18 12:45:23 1997  Andreas Mohr <100.30936@germany.net>

	* [msdos/int25.c] [msdos/int26.c]
        Implemented "native" absolute disk read/write access.

	* [msdos/int13.c] [msdos/ioports.c]
	Enhanced GET DRIVE PARAMETERS (int13 AH=08).

	* [graphics/win16drv/prtdrv.c] [if1632/gdi.spec]
	Fixed typos, implemented dmEnumDFonts,
	Started implementation of dmRealizeObject.

	* [if1632/compobj.spec] [ole/compobj.c] [relay32/ole32.spec]
	Stubs CoCreateInstance, CoFreeUnusedLibraries, implemented
	CoFileTimeNow.

	* [if1632/kernel.spec] [include/windows.h] [memory/global.c]
	  [memory/string.c] [misc/kernel.c] [misc/Makefile.in]
	  [misc/toolhelp.c] [msdos/int21.c]
	Implemented GlobalHandleNoRIP, GetFreeMemInfo, DebugFillBuffer, 
	stubs GetSetKernelDOSProc, DiagQuery, DiagOutput, ToolHelpHook
	(Undocumented Windows).

	* [if1632/user.spec] [if1632/win32s16.spec] [misc/win32s16.c]
	Misc stubs.

	* [if1632/winaspi.spec] [misc/aspi.c]
	Implemented GetASPIDLLVersion.

	* [if1632/wprocs.spec] [msdos/int20.c] [msdos/Makefile.in]
	Added handler for Int 0x20 (terminate program, _very_ old-fashioned).

	* [misc/w32scomb.c]
	Implemented Get16DLLAddress() partially
	(big thanks to Marcus and Alexandre).

	* [relay32/Makefile.in] [relay32/builtin32.c] [relay32/dplay.spec]
	Added built-in DPLAY.DLL.

	* [relay32/winmm.spec] [multimedia/joystick.c]
	Added joySetThreshold.

	* [misc/windebug.c]
	Added WinNotify.

	* [win32/console.c]
	Stubs CreateConsoleScreenBuffer, SetConsoleActiveScreenBuffer,
	WriteConsoleOutput32A.

	* [windows/user.c]
	Stub SetEventHook.

Sat Jan 17 19:30:35 1998  Matthew Toseland  <Paul.Toseland@btinternet.com>

	* [windows/painting.c]
	Fixed broken restore-to-maximized.

Mon Jan 12 21:25:32 1998  Perceval - Marc Huguet Puig <mhp@tinet.fut.es>

	* [documentation/wine.man] [include/options.h]
	  [misc/main.c] [ole/ole2nls.c] [resources/sysres.c]
	  [resources/sysres_Ca.rc] [resources/Makefile.in]
	Added language catalan. (Afegit l'idioma català).
1998-02-01 18:33:27 +00:00

681 lines
23 KiB
C

/*
* NE modules
*
* Copyright 1993 Robert J. Amstadt
* Copyright 1995 Alexandre Julliard
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>
#include "neexe.h"
#include "windows.h"
#include "global.h"
#include "task.h"
#include "selectors.h"
#include "callback.h"
#include "file.h"
#include "module.h"
#include "stackframe.h"
#include "stddebug.h"
#include "debug.h"
#include "xmalloc.h"
/***********************************************************************
* NE_LoadSegment
*/
BOOL32 NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
{
SEGTABLEENTRY *pSegTable, *pSeg;
WORD *pModuleTable;
WORD count, i, offset;
HMODULE16 module;
FARPROC16 address;
int fd;
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;
pModuleTable = NE_MODULE_TABLE( pModule );
if (!pSeg->filepos) return TRUE; /* No file image, just return */
fd = MODULE_OpenFile( pModule->self );
dprintf_module( stddeb, "Loading segment %d, selector=%04x, flags=%04x\n",
segnum, pSeg->selector, pSeg->flags );
lseek( fd, pSeg->filepos << pModule->alignment, SEEK_SET );
if (pSeg->size) size = pSeg->size;
else if (pSeg->minsize) size = pSeg->minsize;
else size = 0x10000;
mem = GlobalLock16(pSeg->selector);
if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1)
{
/* Implement self loading segments */
SELFLOADHEADER *selfloadheader;
STACK16FRAME *stack16Top;
DWORD oldstack;
WORD oldselector, newselector;
THDB *thdb = THREAD_Current();
HFILE32 hf = FILE_DupUnixHandle( fd );
selfloadheader = (SELFLOADHEADER *)
PTR_SEG_OFF_TO_LIN(pSegTable->selector,0);
oldstack = thdb->cur_stack;
oldselector = pSeg->selector;
thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
0xff00 - sizeof(*stack16Top));
stack16Top = (STACK16FRAME *)PTR_SEG_TO_LIN(thdb->cur_stack);
stack16Top->frame32 = 0;
stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
stack16Top->entry_point = 0;
stack16Top->entry_ip = 0;
stack16Top->entry_cs = 0;
stack16Top->bp = 0;
stack16Top->ip = 0;
stack16Top->cs = 0;
newselector = Callbacks->CallLoadAppSegProc(selfloadheader->LoadAppSeg,
pModule->self, hf, segnum );
_lclose32( hf );
if (newselector != oldselector) {
/* Self loaders like creating their own selectors;
* they love asking for trouble to Wine developers
*/
if (segnum == pModule->dgroup) {
memcpy(PTR_SEG_OFF_TO_LIN(oldselector,0),
PTR_SEG_OFF_TO_LIN(newselector,0),
pSeg->minsize ? pSeg->minsize : 0x10000);
FreeSelector(newselector);
pSeg->selector = oldselector;
fprintf(stderr, "A new selector was allocated for the dgroup segment\n"
"Old selector is %d, new one is %d", oldselector, newselector);
} else {
FreeSelector(pSeg->selector);
pSeg->selector = newselector;
}
}
thdb->cur_stack = oldstack;
}
else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
read(fd, mem, 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. If you have any doco please either send
it to me or fix the code yourself. gfm@werple.mira.net.au
*/
char* buff = xmalloc(size);
char* curr = buff;
read(fd, buff, size);
while(curr < buff + size) {
unsigned int rept = *((short*) curr)++;
unsigned int len = *((short*) curr)++;
for(; rept > 0; rept--) {
char* bytes = curr;
unsigned int byte;
for(byte = 0; byte < len; byte++)
*mem++ = *bytes++;
}
curr += len;
}
free(buff);
}
pSeg->flags |= NE_SEGFLAGS_LOADED;
if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
return TRUE; /* No relocation data, we are done */
read( fd, &count, sizeof(count) );
if (!count) return TRUE;
dprintf_fixup( stddeb, "Fixups for %*.*s, segment %d, selector %04x\n",
*((BYTE *)pModule + pModule->name_table),
*((BYTE *)pModule + pModule->name_table),
(char *)pModule + pModule->name_table + 1,
segnum, pSeg->selector );
reloc_entries = (struct relocation_entry_s *)xmalloc(count * sizeof(struct relocation_entry_s));
if (read( fd, reloc_entries, count * sizeof(struct relocation_entry_s)) !=
count * sizeof(struct relocation_entry_s))
{
dprintf_fixup( stddeb, "Unable to read relocation information\n" );
return FALSE;
}
/*
* Go through the relocation table on entry at a time.
*/
rep = reloc_entries;
for (i = 0; i < count; i++, rep++)
{
/*
* 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:
module = pModuleTable[rep->target1-1];
ordinal = rep->target2;
address = MODULE_GetEntryPoint( module, ordinal );
if (!address)
{
NE_MODULE *pTarget = MODULE_GetPtr( module );
if (!pTarget)
fprintf( stderr, "Module not found: %04x, reference %d of module %*.*s\n",
module, rep->target1,
*((BYTE *)pModule + pModule->name_table),
*((BYTE *)pModule + pModule->name_table),
(char *)pModule + pModule->name_table + 1 );
else
fprintf( stderr, "Warning: no handler for %*.*s.%d, setting to 0:0\n",
*((BYTE *)pTarget + pTarget->name_table),
*((BYTE *)pTarget + pTarget->name_table),
(char *)pTarget + pTarget->name_table + 1,
ordinal );
}
if (debugging_fixup)
{
NE_MODULE *pTarget = MODULE_GetPtr( module );
fprintf( stddeb,"%d: %*.*s.%d=%04x:%04x\n", i + 1,
*((BYTE *)pTarget + pTarget->name_table),
*((BYTE *)pTarget + pTarget->name_table),
(char *)pTarget + pTarget->name_table + 1,
ordinal, HIWORD(address), LOWORD(address) );
}
break;
case NE_RELTYPE_NAME:
module = pModuleTable[rep->target1-1];
func_name = (char *)pModule + pModule->import_table + rep->target2;
memcpy( buffer, func_name+1, *func_name );
buffer[*func_name] = '\0';
func_name = buffer;
ordinal = MODULE_GetOrdinal( module, func_name );
address = MODULE_GetEntryPoint( module, ordinal );
if (!address)
{
NE_MODULE *pTarget = MODULE_GetPtr( module );
fprintf( stderr, "Warning: no handler for %.*s.%s, setting to 0:0\n",
*((BYTE *)pTarget + pTarget->name_table),
(char *)pTarget + pTarget->name_table + 1, func_name );
}
if (debugging_fixup)
{
NE_MODULE *pTarget = MODULE_GetPtr( module );
fprintf( stddeb,"%d: %.*s.%s=%04x:%04x\n", i + 1,
*((BYTE *)pTarget + pTarget->name_table),
(char *)pTarget + pTarget->name_table + 1,
func_name, HIWORD(address), LOWORD(address) );
}
break;
case NE_RELTYPE_INTERNAL:
if ((rep->target1 & 0xff) == 0xff)
{
address = MODULE_GetEntryPoint( pModule->self, rep->target2 );
}
else
{
address = (FARPROC16)PTR_SEG_OFF_TO_SEGPTR( pSegTable[rep->target1-1].selector, rep->target2 );
}
dprintf_fixup(stddeb,"%d: %04x:%04x\n",
i + 1, HIWORD(address), LOWORD(address) );
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.
*/
dprintf_fixup(stddeb,
"%d: ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
i + 1, rep->address_type, rep->relocation_type,
rep->offset);
dprintf_fixup(stddeb,"TARGET %04x %04x\n",
rep->target1, rep->target2);
continue;
default:
dprintf_fixup(stddeb,
"WARNING: %d: ADDR TYPE %d, unknown TYPE %d, OFFSET %04x, ",
i + 1, rep->address_type, rep->relocation_type,
rep->offset);
dprintf_fixup(stddeb,"TARGET %04x %04x\n",
rep->target1, rep->target2);
free(reloc_entries);
return FALSE;
}
offset = rep->offset;
/* Apparently, high bit of address_type is sometimes set; */
/* we ignore it for now */
if (rep->address_type > NE_RADDR_OFFSET32)
fprintf( stderr, "WARNING: module %s: unknown reloc addr type = 0x%02x. Please report.\n",
MODULE_GetModuleName(pModule->self), rep->address_type );
switch (rep->address_type & 0x7f)
{
case NE_RADDR_LOWBYTE:
do {
sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
dprintf_fixup(stddeb," %04x:%04x:%04x BYTE%s\n",
pSeg->selector, offset, *sp, additive ? " additive":"");
offset = *sp;
if(additive)
*(unsigned char*)sp = (unsigned char)(((int)address+offset) & 0xFF);
else
*(unsigned char*)sp = (unsigned char)((int)address & 0xFF);
}
while (offset != 0xffff && !additive);
break;
case NE_RADDR_OFFSET16:
do {
sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
dprintf_fixup(stddeb," %04x:%04x:%04x OFFSET16%s\n",
pSeg->selector, offset, *sp, additive ? " additive" : "" );
offset = *sp;
*sp = LOWORD(address);
if (additive) *sp += offset;
}
while (offset != 0xffff && !additive);
break;
case NE_RADDR_POINTER32:
do {
sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
dprintf_fixup(stddeb," %04x:%04x:%04x POINTER32%s\n",
pSeg->selector, offset, *sp, additive ? " additive" : "" );
offset = *sp;
*sp = LOWORD(address);
if (additive) *sp += offset;
*(sp+1) = HIWORD(address);
}
while (offset != 0xffff && !additive);
break;
case NE_RADDR_SELECTOR:
do {
sp = PTR_SEG_OFF_TO_LIN( pSeg->selector, offset );
dprintf_fixup(stddeb," %04x:%04x:%04x SELECTOR%s\n",
pSeg->selector, offset, *sp, additive ? " additive" : "" );
offset = *sp;
*sp = HIWORD(address);
/* Borland creates additive records with offset zero. Strange, but OK */
if(additive && offset)
fprintf(stderr,"Additive selector to %4.4x.Please report\n",offset);
}
/* FIXME: Quicken 5 has a zero offset fixup. This seems to work */
while (offset && offset != 0xffff && !additive);
break;
default:
dprintf_fixup(stddeb,
"WARNING: %d: unknown ADDR TYPE %d, TYPE %d, OFFSET %04x, ",
i + 1, rep->address_type, rep->relocation_type,
rep->offset);
dprintf_fixup(stddeb,
"TARGET %04x %04x\n", rep->target1, rep->target2);
free(reloc_entries);
return FALSE;
}
}
free(reloc_entries);
return TRUE;
}
/***********************************************************************
* NE_LoadAllSegments
*/
BOOL32 NE_LoadAllSegments( NE_MODULE *pModule )
{
int i;
if (pModule->flags & NE_FFLAGS_SELFLOAD)
{
HFILE32 hf;
/* Handle self loading modules */
SEGTABLEENTRY * pSegTable = (SEGTABLEENTRY *) NE_SEG_TABLE(pModule);
SELFLOADHEADER *selfloadheader;
STACK16FRAME *stack16Top;
THDB *thdb = THREAD_Current();
HMODULE16 hselfload = GetModuleHandle16("WPROCS");
DWORD oldstack;
WORD saved_dgroup = pSegTable[pModule->dgroup - 1].selector;
dprintf_module(stddeb, "MODULE_Load: %.*s is a self-loading module!\n",
*((BYTE*)pModule + pModule->name_table),
(char *)pModule + pModule->name_table + 1);
if (!NE_LoadSegment( pModule, 1 )) return FALSE;
selfloadheader = (SELFLOADHEADER *)
PTR_SEG_OFF_TO_LIN(pSegTable->selector, 0);
selfloadheader->EntryAddrProc = MODULE_GetEntryPoint(hselfload,27);
selfloadheader->MyAlloc = MODULE_GetEntryPoint(hselfload,28);
selfloadheader->SetOwner = MODULE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
pModule->self_loading_sel = GlobalHandleToSel(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, FALSE, FALSE, FALSE));
oldstack = thdb->cur_stack;
thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
0xff00 - sizeof(*stack16Top) );
stack16Top = (STACK16FRAME *)PTR_SEG_TO_LIN(thdb->cur_stack);
stack16Top->frame32 = 0;
stack16Top->ebp = 0;
stack16Top->ds = stack16Top->es = pModule->self_loading_sel;
stack16Top->entry_point = 0;
stack16Top->entry_ip = 0;
stack16Top->entry_cs = 0;
stack16Top->bp = 0;
stack16Top->ip = 0;
stack16Top->cs = 0;
hf = FILE_DupUnixHandle( MODULE_OpenFile( pModule->self ) );
Callbacks->CallBootAppProc(selfloadheader->BootApp, pModule->self, hf);
_lclose32(hf);
/* some BootApp procs overwrite the selector of dgroup */
pSegTable[pModule->dgroup - 1].selector = saved_dgroup;
thdb->cur_stack = oldstack;
for (i = 2; i <= pModule->seg_count; i++)
if (!NE_LoadSegment( pModule, i )) return FALSE;
}
else
{
for (i = 1; i <= pModule->seg_count; i++)
if (!NE_LoadSegment( pModule, i )) return FALSE;
}
return TRUE;
}
/***********************************************************************
* NE_LoadDLLs
*/
BOOL32 NE_LoadDLLs( NE_MODULE *pModule )
{
int i;
WORD *pModRef = (WORD *)((char *)pModule + pModule->modref_table);
WORD *pDLLs = (WORD *)GlobalLock16( pModule->dlls_to_init );
for (i = 0; i < pModule->modref_count; i++, pModRef++)
{
char buffer[256];
BYTE *pstr = (BYTE *)pModule + pModule->import_table + *pModRef;
memcpy( buffer, pstr + 1, *pstr );
strcpy( buffer + *pstr, ".dll" );
dprintf_module( stddeb, "Loading '%s'\n", buffer );
if (!(*pModRef = MODULE_FindModule( buffer )))
{
/* If the DLL is not loaded yet, load it and store */
/* its handle in the list of DLLs to initialize. */
HMODULE16 hDLL;
if ((hDLL = MODULE_Load( buffer, (LPVOID)-1, NE_FFLAGS_IMPLICIT )) == 2)
{
/* file not found */
char *p;
/* Try with prepending the path of the current module */
GetModuleFileName16( pModule->self, buffer, sizeof(buffer) );
if (!(p = strrchr( buffer, '\\' ))) p = buffer;
memcpy( p + 1, pstr + 1, *pstr );
strcpy( p + 1 + *pstr, ".dll" );
hDLL = MODULE_Load( buffer, (LPVOID)-1, NE_FFLAGS_IMPLICIT );
}
if (hDLL < 32)
{
/* FIXME: cleanup what was done */
fprintf( stderr, "Could not load '%s' required by '%.*s', error = %d\n",
buffer, *((BYTE*)pModule + pModule->name_table),
(char *)pModule + pModule->name_table + 1, hDLL );
return FALSE;
}
*pModRef = MODULE_HANDLEtoHMODULE16( hDLL );
*pDLLs++ = *pModRef;
}
else /* Increment the reference count of the DLL */
{
NE_MODULE *pOldDLL = MODULE_GetPtr( *pModRef );
if (pOldDLL) pOldDLL->count++;
}
}
return TRUE;
}
/***********************************************************************
* NE_FixupPrologs
*
* Fixup the exported functions prologs.
*/
void NE_FixupPrologs( NE_MODULE *pModule )
{
SEGTABLEENTRY *pSegTable;
WORD dgroup = 0;
WORD sel;
BYTE *p, *fixup_ptr, count;
pSegTable = NE_SEG_TABLE(pModule);
if (pModule->flags & NE_FFLAGS_SINGLEDATA)
dgroup = pSegTable[pModule->dgroup-1].selector;
dprintf_module( stddeb, "MODULE_FixupPrologs(%04x)\n", pModule->self );
p = (BYTE *)pModule + pModule->entry_table;
while (*p)
{
if (p[1] == 0) /* Unused entry */
{
p += 2; /* Skip it */
continue;
}
if (p[1] == 0xfe) /* Constant entry */
{
p += 2 + *p * 3; /* Skip it */
continue;
}
/* Now fixup the entries of this bundle */
count = *p;
sel = p[1];
p += 2;
while (count-- > 0)
{
dprintf_module( stddeb,"Flags: %04x, sel %02x ", *p, sel);
/* According to the output generated by TDUMP, the flags mean:
* 0x0001 function is exported
* 0x0002 Single data (seems to occur only in DLLs)
*/
if (sel == 0xff) { /* moveable */
dprintf_module( stddeb, "(%02x) o %04x ", p[3], *(WORD *)(p+4) );
fixup_ptr = (char *)GET_SEL_BASE(pSegTable[p[3]-1].selector) + *(WORD *)(p + 4);
} else { /* fixed */
dprintf_module( stddeb, "offset %04x ", *(WORD *)(p+1) );
fixup_ptr = (char *)GET_SEL_BASE(pSegTable[sel-1].selector) + *(WORD *)(p + 1);
}
dprintf_module( stddeb, "Signature: %02x %02x %02x,ff %x\n",
fixup_ptr[0], fixup_ptr[1], fixup_ptr[2],
pModule->flags );
if (*p & 0x0001)
{
/* Verify the signature */
if (((fixup_ptr[0] == 0x1e && fixup_ptr[1] == 0x58)
|| (fixup_ptr[0] == 0x8c && fixup_ptr[1] == 0xd8))
&& fixup_ptr[2] == 0x90)
{
if (*p & 0x0002)
{
if (pModule->flags & NE_FFLAGS_MULTIPLEDATA)
{
/* can this happen? */
fprintf( stderr, "FixupPrologs got confused\n" );
}
else if (pModule->flags & NE_FFLAGS_SINGLEDATA)
{
*fixup_ptr = 0xb8; /* MOV AX, */
*(WORD *)(fixup_ptr+1) = dgroup;
}
}
else
{
if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
fixup_ptr[0] = 0x90; /* non-library: NOPs */
fixup_ptr[1] = 0x90;
fixup_ptr[2] = 0x90;
}
}
} else {
dprintf_fixup( stddeb, "Unknown signature\n" );
}
}
else
dprintf_module( stddeb,"\n");
p += (sel == 0xff) ? 6 : 3;
}
}
}
/***********************************************************************
* NE_InitDLL
*
* Call the DLL initialization code
*/
static BOOL32 NE_InitDLL( TDB* pTask, HMODULE16 hModule )
{
NE_MODULE *pModule;
SEGTABLEENTRY *pSegTable;
CONTEXT context;
/* Registers at initialization must be:
* cx heap size
* di library instance
* ds data segment if any
* es:si command line (always 0)
*/
if (!(pModule = MODULE_GetPtr( hModule ))) return FALSE;
pSegTable = NE_SEG_TABLE( pModule );
if (!(pModule->flags & NE_FFLAGS_LIBMODULE) ||
(pModule->flags & NE_FFLAGS_WIN32)) return TRUE; /*not a library*/
/* Call USER signal handler. This is necessary to install a
* proper loader for HICON and HCURSOR resources that this DLL
* may contain. InitApp() does this for task modules. */
if (pTask && pTask->userhandler)
{
pTask->userhandler( hModule, USIG_DLL_LOAD, 0, pTask->hInstance,
pTask->hQueue );
}
if (!pModule->cs) return TRUE; /* no initialization code */
memset( &context, 0, sizeof(context) );
if (!(pModule->flags & NE_FFLAGS_SINGLEDATA))
{
if (pModule->flags & NE_FFLAGS_MULTIPLEDATA || pModule->dgroup)
{
/* Not SINGLEDATA */
fprintf(stderr, "Library is not marked SINGLEDATA\n");
exit(1);
}
else /* DATA NONE DLL */
{
DS_reg(&context) = 0;
ECX_reg(&context) = 0;
}
}
else /* DATA SINGLE DLL */
{
DS_reg(&context) = pSegTable[pModule->dgroup-1].selector;
ECX_reg(&context) = pModule->heap_size;
}
CS_reg(&context) = pSegTable[pModule->cs-1].selector;
EIP_reg(&context) = pModule->ip;
EBP_reg(&context) = OFFSETOF(THREAD_Current()->cur_stack)
+ (WORD)&((STACK16FRAME*)0)->bp;
EDI_reg(&context) = DS_reg(&context) ? DS_reg(&context) : hModule;
pModule->cs = 0; /* Don't initialize it twice */
dprintf_dll( stddeb, "Calling LibMain, cs:ip=%04lx:%04x ds=%04lx di=%04x cx=%04x\n",
CS_reg(&context), IP_reg(&context), DS_reg(&context),
DI_reg(&context), CX_reg(&context) );
Callbacks->CallRegisterShortProc( &context, 0 );
return TRUE;
}
/***********************************************************************
* NE_InitializeDLLs
*
* Recursively initialize all DLLs (according to the order in which
* they where loaded).
*/
void NE_InitializeDLLs( HMODULE16 hModule )
{
TDB* pTask = (TDB*)GlobalLock16(GetCurrentTask());
NE_MODULE *pModule;
HMODULE16 *pDLL;
if (!(pModule = MODULE_GetPtr( hModule ))) return;
if (pModule->flags & NE_FFLAGS_WIN32) return;
if (pModule->dlls_to_init)
{
HGLOBAL16 to_init = pModule->dlls_to_init;
pModule->dlls_to_init = 0;
for (pDLL = (HMODULE16 *)GlobalLock16( to_init ); *pDLL; pDLL++)
{
NE_InitializeDLLs( *pDLL );
}
GlobalFree16( to_init );
}
NE_InitDLL( pTask, hModule );
}
/***********************************************************************
* PatchCodeHandle
*
* Needed for self-loading modules.
*/
/* It does nothing */
void WINAPI PatchCodeHandle(HANDLE16 hSel)
{
fprintf(stderr,"PatchCodeHandle(%04x),stub!\n",hSel);
}