Commit dca5e56b authored by Andreas Mohr's avatar Andreas Mohr Committed by Alexandre Julliard

- Implemented proper ("real", compressed) Win16 entry tables.

- Fixed MyAlloc (AKA NE_AllocateSegment). - Implemented PatchCodeHandle16.
parent 0a997524
......@@ -266,53 +266,33 @@ HMODULE16 BUILTIN_LoadModule( LPCSTR name, BOOL force )
LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, WORD *pOrd )
{
static char buffer[80];
WORD ordinal, i, max_offset;
WORD i, max_offset;
register BYTE *p;
NE_MODULE *pModule;
ET_BUNDLE *bundle;
ET_ENTRY *entry;
if (!(pModule = NE_GetPtr( FarGetOwner16( GlobalHandle16(cs) ))))
return NULL;
/* Search for the ordinal */
p = (BYTE *)pModule + pModule->entry_table;
max_offset = 0;
ordinal = 1;
*pOrd = 0;
while (*p)
{
switch(p[1])
{
case 0: /* unused */
ordinal += *p;
p += 2;
break;
case 1: /* code segment */
i = *p;
p += 2;
while (i-- > 0)
bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
entry = (ET_ENTRY *)((BYTE *)bundle+6);
do {
for (i = bundle->first + 1; i < bundle->last; i++)
{
p++;
if ((*(WORD *)p <= ip) && (*(WORD *)p >= max_offset))
if ((entry->offs <= ip)
&& (entry->type == 1) /* code segment ? */
&& (entry->offs >= max_offset))
{
max_offset = *(WORD *)p;
*pOrd = ordinal;
}
p += 2;
ordinal++;
}
break;
case 0xff: /* moveable (should not happen in built-in modules) */
TRACE( relay, "Built-in module has moveable entry\n" );
ordinal += *p;
p += 2 + *p * 6;
break;
default: /* other segment */
ordinal += *p;
p += 2 + *p * 3;
break;
max_offset = entry->offs;
*pOrd = i;
}
entry++;
}
} while ( (bundle->next)
&& (bundle = (ET_BUNDLE *)((BYTE *)pModule+bundle->next)));
/* Search for the name in the resident names table */
/* (built-in modules have no non-resident table) */
......
......@@ -56,6 +56,20 @@ typedef struct _NE_MODULE
} NE_MODULE;
typedef struct {
BYTE type;
BYTE flags;
BYTE segnum;
WORD offs WINE_PACKED;
} ET_ENTRY;
typedef struct {
WORD first; /* ordinal */
WORD last; /* ordinal */
WORD next; /* bundle */
} ET_BUNDLE;
/* In-memory segment table */
typedef struct
{
......
......@@ -88,7 +88,7 @@ BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
mem = GlobalLock16(pSeg->hSeg);
if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1)
{
/* Implement self loading segments */
/* Implement self-loading segments */
SELFLOADHEADER *selfloadheader;
STACK16FRAME *stack16Top;
DWORD oldstack;
......@@ -396,7 +396,7 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
{
HFILE hf;
HFILE16 hFile16;
/* Handle self loading modules */
/* Handle self-loading modules */
SELFLOADHEADER *selfloadheader;
STACK16FRAME *stack16Top;
THDB *thdb = THREAD_Current();
......@@ -413,7 +413,7 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
selfloadheader->EntryAddrProc = NE_GetEntryPoint(hselfload,27);
selfloadheader->MyAlloc = NE_GetEntryPoint(hselfload,28);
selfloadheader->SetOwner = NE_GetEntryPoint(GetModuleHandle16("KERNEL"),403);
pModule->self_loading_sel = GlobalHandleToSel16(GLOBAL_Alloc(GMEM_ZEROINIT, 0xFF00, pModule->self, FALSE, FALSE, FALSE));
pModule->self_loading_sel = SEL(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) );
......@@ -453,111 +453,120 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
/***********************************************************************
* PatchCodeHandle
* NE_FixupSegmentPrologs
*
* Needed for self-loading modules.
* Fixup exported functions prologs of one segment
*/
/* It does nothing */
DWORD WINAPI PatchCodeHandle16(HANDLE16 hSel)
void NE_FixupSegmentPrologs(NE_MODULE *pModule, WORD segnum)
{
FIXME(module,"(%04x): stub.\n",hSel);
return (DWORD)NULL;
}
SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
ET_BUNDLE *bundle;
ET_ENTRY *entry;
WORD dgroup, num_entries, sel = SEL(pSegTable[segnum-1].hSeg);
BYTE *pSeg, *pFunc;
TRACE(module, "(%d);\n", segnum);
/***********************************************************************
* NE_FixupPrologs
*
* Fixup the exported functions prologs.
*/
void NE_FixupPrologs( NE_MODULE *pModule )
if (pSegTable[segnum-1].flags & NE_SEGFLAGS_DATA)
{
SEGTABLEENTRY *pSegTable;
WORD dgroup = 0;
WORD sel;
BYTE *p, *fixup_ptr, count;
dbg_decl_str(module, 512);
pSegTable[segnum-1].flags |= NE_SEGFLAGS_LOADED;
return;
}
if (!(dgroup = SEL(pSegTable[pModule->dgroup-1].hSeg)))
return;
pSegTable = NE_SEG_TABLE(pModule);
if (pModule->flags & NE_FFLAGS_SINGLEDATA)
dgroup = SEL(pSegTable[pModule->dgroup-1].hSeg);
pSeg = PTR_SEG_OFF_TO_LIN(sel, 0);
TRACE(module, "(%04x)\n", pModule->self );
p = (BYTE *)pModule + pModule->entry_table;
while (*p)
bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->entry_table);
do {
TRACE(module, "num_entries: %d, bundle: %p, next: %04x, pSeg: %p\n", bundle->last - bundle->first, bundle, bundle->next, pSeg);
if (!(num_entries = bundle->last - bundle->first))
return;
entry = (ET_ENTRY *)((BYTE *)bundle+6);
while (num_entries--)
{
if (p[1] == 0) /* Unused entry */
/*TRACE(module, "entry: %p, entry->segnum: %d, entry->offs: %04x\n", entry, entry->segnum, entry->offs);*/
if (entry->segnum == segnum)
{
p += 2; /* Skip it */
continue;
}
if (p[1] == 0xfe) /* Constant entry */
pFunc = ((BYTE *)pSeg+entry->offs);
TRACE(module, "pFunc: %p, *(DWORD *)pFunc: %08lx, num_entries: %d\n", pFunc, *(DWORD *)pFunc, num_entries);
if (*(pFunc+2) == 0x90)
{
p += 2 + *p * 3; /* Skip it */
continue;
if (*(WORD *)pFunc == 0x581e) /* push ds, pop ax */
{
TRACE(module, "patch %04x:%04x -> mov ax, ds\n", sel, entry->offs);
*(WORD *)pFunc = 0xd88c; /* mov ax, ds */
}
/* Now fixup the entries of this bundle */
count = *p;
sel = p[1];
p += 2;
while (count-- > 0)
{
dbg_reset_str(module);
dsprintf(module,"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 */
dsprintf(module, "(%02x) o %04x", p[3], *(WORD *)(p+4) );
fixup_ptr = (char *)GET_SEL_BASE(SEL(pSegTable[p[3]-1].hSeg)) + *(WORD *)(p + 4);
} else { /* fixed */
dsprintf(module, "offset %04x", *(WORD *)(p+1) );
fixup_ptr = (char *)GET_SEL_BASE(SEL(pSegTable[sel-1].hSeg)) +
*(WORD *)(p + 1);
}
TRACE(module, "%s Signature: %02x %02x %02x,ff %x\n",
dbg_str(module), 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)
if (*(WORD *)pFunc == 0xd88c)
{
/* can this happen? */
ERR(fixup, "FixupPrologs got confused\n" );
}
else if (pModule->flags & NE_FFLAGS_SINGLEDATA)
if ((entry->flags & 2)) /* public data ? */
{
*fixup_ptr = 0xb8; /* MOV AX, */
*(WORD *)(fixup_ptr+1) = dgroup;
}
TRACE(module, "patch %04x:%04x -> mov ax, dgroup [%04x]\n", sel, entry->offs, dgroup);
*pFunc = 0xb8; /* mov ax, */
*(WORD *)(pFunc+1) = dgroup;
}
else
if ((pModule->flags & NE_FFLAGS_MULTIPLEDATA)
&& (entry->flags & 1)) /* exported ? */
{
if (pModule->flags & NE_FFLAGS_MULTIPLEDATA) {
fixup_ptr[0] = 0x90; /* non-library: NOPs */
fixup_ptr[1] = 0x90;
fixup_ptr[2] = 0x90;
TRACE(module, "patch %04x:%04x -> nop, nop\n", sel, entry->offs);
*(WORD *)pFunc = 0x9090; /* nop, nop */
}
}
} else {
WARN(fixup, "Unknown signature\n" );
}
}
else
TRACE(module,"\n");
p += (sel == 0xff) ? 6 : 3;
entry++;
}
} while ( (bundle->next)
&& (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
}
/***********************************************************************
* PatchCodeHandle
*
* Needed for self-loading modules.
*/
DWORD WINAPI PatchCodeHandle16(HANDLE16 hSeg)
{
WORD segnum;
WORD sel = SEL(hSeg);
NE_MODULE *pModule = NE_GetPtr(FarGetOwner16(sel));
SEGTABLEENTRY *pSegTable = NE_SEG_TABLE(pModule);
TRACE(module, "(%04x);\n", hSeg);
/* find the segment number of the module that belongs to hSeg */
for (segnum = 1; segnum <= pModule->seg_count; segnum++)
{
if (SEL(pSegTable[segnum-1].hSeg) == sel)
{
NE_FixupSegmentPrologs(pModule, segnum);
break;
}
}
return MAKELONG(hSeg, sel);
}
/***********************************************************************
* NE_FixupPrologs
*
* Fixup the exported functions prologs.
*/
void NE_FixupPrologs( NE_MODULE *pModule )
{
WORD segnum;
TRACE(module, "(%04x)\n", pModule->self );
if (pModule->flags & NE_FFLAGS_SELFLOAD)
NE_FixupSegmentPrologs(pModule, 1);
else
for (segnum=1; segnum <= pModule->seg_count; segnum++)
NE_FixupSegmentPrologs(pModule, segnum);
}
/***********************************************************************
......@@ -797,23 +806,30 @@ static WORD NE_Ne2MemFlags(WORD flags)
/***********************************************************************
* NE_AllocateSegment (WPROCS.26)
*
* MyAlloc() function for self-loading apps.
*/
DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem )
{
WORD size = wSize << wElem;
HANDLE16 hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size);
HANDLE16 hMem = 0;
if (wSize || (wFlags & NE_SEGFLAGS_MOVEABLE))
hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size);
/* not data == code */
if ( (wFlags & NE_SEGFLAGS_EXECUTEONLY) ||
!(wFlags & NE_SEGFLAGS_DATA)
) {
WORD hSel = GlobalHandleToSel16(hMem);
if ( ((wFlags & 0x7) != 0x1) && /* DATA */
((wFlags & 0x7) != 0x7) ) /* DATA|ALLOCATED|LOADED */
{
WORD hSel = SEL(hMem);
WORD access = SelectorAccessRights16(hSel,0,0);
access |= 2<<2; /* SEGMENT_CODE */
SelectorAccessRights16(hSel,1,access);
}
return MAKELONG( hMem, GlobalHandleToSel16(hMem) );
if (size)
return MAKELONG( hMem, SEL(hMem) );
else
return MAKELONG( 0, hMem );
}
......@@ -823,12 +839,17 @@ DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem )
BOOL NE_CreateSegments( NE_MODULE *pModule )
{
SEGTABLEENTRY *pSegment;
int i, minsize;
int i, minsize, seg_count;
assert( !(pModule->flags & NE_FFLAGS_WIN32) );
pSegment = NE_SEG_TABLE( pModule );
for (i = 1; i <= pModule->seg_count; i++, pSegment++)
if (pModule->flags & NE_FFLAGS_SELFLOAD)
seg_count = 1;
else
seg_count = pModule->seg_count;
for (i = 1; i <= seg_count; i++, pSegment++)
{
minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
if (i == pModule->ss) minsize += pModule->stack_size;
......
......@@ -796,8 +796,10 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
NE_MODULE *pModule;
SEGTABLEENTRY *pSegment;
OFSTRUCT *pFileInfo;
BYTE *pstr, *bundle;
BYTE *pstr;
WORD *pword;
ET_BUNDLE *bundle = 0;
ET_ENTRY *entry = 0;
/* Module layout:
* NE_MODULE Module
......@@ -911,7 +913,6 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
/* Entry table */
pModule->entry_table = (int)pstr - (int)pModule;
bundle = NULL;
odp = OrdinalDefinitions + 1;
for (i = 1; i <= Limit; i++, odp++)
{
......@@ -943,24 +944,25 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
break;
}
/* create a new bundle if necessary */
if (!bundle || (bundle[0] >= 254) || (bundle[1] != selector))
if (!bundle)
{
bundle = pstr;
bundle[0] = 0;
bundle[1] = selector;
pstr += 2;
bundle = (ET_BUNDLE *)pstr;
bundle->first = 0;
pstr += sizeof(ET_BUNDLE);
}
(*bundle)++;
if (selector != 0)
{
*pstr++ = 1;
*(WORD *)pstr = odp->offset;
pstr += sizeof(WORD);
}
/* FIXME: is this really correct ?? */
entry = (ET_ENTRY *)pstr;
entry->type = selector;
entry->flags = 3; /* exported & public data */
entry->segnum = selector;
entry->offs = odp->offset;
pstr += sizeof(ET_ENTRY);
}
*pstr++ = 0;
bundle->last = i;
bundle->next = 0;
/* Dump the module content */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment