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à).
680 lines
23 KiB
C
680 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);
|
|
}
|