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

- Fixed MyAlloc (AKA NE_AllocateSegment).
- Implemented PatchCodeHandle16.
This commit is contained in:
Andreas Mohr 1999-04-16 08:17:17 +00:00 committed by Alexandre Julliard
parent 0a9975242a
commit dca5e56b90
5 changed files with 310 additions and 249 deletions

View file

@ -266,53 +266,33 @@ HMODULE16 BUILTIN_LoadModule( LPCSTR name, BOOL force )
LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, WORD *pOrd ) LPCSTR BUILTIN_GetEntryPoint16( WORD cs, WORD ip, WORD *pOrd )
{ {
static char buffer[80]; static char buffer[80];
WORD ordinal, i, max_offset; WORD i, max_offset;
register BYTE *p; register BYTE *p;
NE_MODULE *pModule; NE_MODULE *pModule;
ET_BUNDLE *bundle;
ET_ENTRY *entry;
if (!(pModule = NE_GetPtr( FarGetOwner16( GlobalHandle16(cs) )))) if (!(pModule = NE_GetPtr( FarGetOwner16( GlobalHandle16(cs) ))))
return NULL; return NULL;
/* Search for the ordinal */
p = (BYTE *)pModule + pModule->entry_table;
max_offset = 0; max_offset = 0;
ordinal = 1;
*pOrd = 0; *pOrd = 0;
while (*p) bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
{ entry = (ET_ENTRY *)((BYTE *)bundle+6);
switch(p[1]) do {
{ for (i = bundle->first + 1; i < bundle->last; i++)
case 0: /* unused */
ordinal += *p;
p += 2;
break;
case 1: /* code segment */
i = *p;
p += 2;
while (i-- > 0)
{ {
p++; if ((entry->offs <= ip)
if ((*(WORD *)p <= ip) && (*(WORD *)p >= max_offset)) && (entry->type == 1) /* code segment ? */
&& (entry->offs >= max_offset))
{ {
max_offset = *(WORD *)p; max_offset = entry->offs;
*pOrd = ordinal; *pOrd = i;
}
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;
} }
entry++;
} }
} while ( (bundle->next)
&& (bundle = (ET_BUNDLE *)((BYTE *)pModule+bundle->next)));
/* Search for the name in the resident names table */ /* Search for the name in the resident names table */
/* (built-in modules have no non-resident table) */ /* (built-in modules have no non-resident table) */

View file

@ -56,6 +56,20 @@ typedef struct _NE_MODULE
} 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 */ /* In-memory segment table */
typedef struct typedef struct
{ {

View file

@ -59,6 +59,8 @@ void NE_DumpModule( HMODULE16 hModule )
BYTE *pstr; BYTE *pstr;
WORD *pword; WORD *pword;
NE_MODULE *pModule; NE_MODULE *pModule;
ET_BUNDLE *bundle;
ET_ENTRY *entry;
if (!(pModule = NE_GetPtr( hModule ))) if (!(pModule = NE_GetPtr( hModule )))
{ {
@ -143,39 +145,21 @@ void NE_DumpModule( HMODULE16 hModule )
/* Dump the entry table */ /* Dump the entry table */
DUMP( "---\n" ); DUMP( "---\n" );
DUMP( "Entry table:\n" ); DUMP( "Entry table:\n" );
pstr = (char *)pModule + pModule->entry_table; bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->entry_table);
ordinal = 1; do {
while (*pstr) entry = (ET_ENTRY *)((BYTE *)bundle+6);
{ DUMP( "Bundle %d-%d: %02x\n", bundle->first, bundle->last, entry->type);
DUMP( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]); ordinal = bundle->first;
if (!pstr[1]) while (ordinal < bundle->last)
{ {
ordinal += *pstr; if (entry->type == 0xff)
pstr += 2; DUMP("%d: %02x:%04x (moveable)\n", ordinal++, entry->segnum, entry->offs);
} else
else if ((BYTE)pstr[1] == 0xff) /* moveable */ DUMP("%d: %02x:%04x (fixed)\n", ordinal++, entry->segnum, entry->offs);
{ entry++;
i = *pstr;
pstr += 2;
while (i--)
{
DUMP( "%d: %02x:%04x (moveable)\n",
ordinal++, pstr[3], *(WORD *)(pstr + 4) );
pstr += 6;
}
}
else /* fixed */
{
i = *pstr;
pstr += 2;
while (i--)
{
DUMP( "%d: %04x (fixed)\n",
ordinal++, *(WORD *)(pstr + 1) );
pstr += 3;
}
}
} }
} while ( (bundle->next)
&& (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
/* Dump the non-resident names table */ /* Dump the non-resident names table */
DUMP( "---\n" ); DUMP( "---\n" );
@ -305,43 +289,29 @@ FARPROC16 NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop ) FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop )
{ {
NE_MODULE *pModule; NE_MODULE *pModule;
WORD curOrdinal = 1; WORD sel, offset, i;
BYTE *p;
WORD sel, offset; ET_ENTRY *entry;
ET_BUNDLE *bundle;
if (!(pModule = NE_GetPtr( hModule ))) return 0; if (!(pModule = NE_GetPtr( hModule ))) return 0;
assert( !(pModule->flags & NE_FFLAGS_WIN32) ); assert( !(pModule->flags & NE_FFLAGS_WIN32) );
p = (BYTE *)pModule + pModule->entry_table; bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
while (*p && (curOrdinal + *p <= ordinal)) while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
{ {
/* Skipping this bundle */ if (!(bundle->next))
curOrdinal += *p;
switch(p[1])
{
case 0: p += 2; break; /* unused */
case 0xff: p += 2 + *p * 6; break; /* moveable */
default: p += 2 + *p * 3; break; /* fixed */
}
}
if (!*p) return 0;
switch(p[1])
{
case 0: /* unused */
return 0; return 0;
case 0xff: /* moveable */ bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
p += 2 + 6 * (ordinal - curOrdinal);
sel = p[3];
offset = *(WORD *)(p + 4);
break;
default: /* fixed */
sel = p[1];
p += 2 + 3 * (ordinal - curOrdinal);
offset = *(WORD *)(p + 1);
break;
} }
entry = (ET_ENTRY *)((BYTE *)bundle+6);
for (i=0; i < (ordinal - bundle->first - 1); i++)
entry++;
sel = entry->segnum;
offset = entry->offs;
if (sel == 0xfe) sel = 0xffff; /* constant entry */ if (sel == 0xfe) sel = 0xffff; /* constant entry */
else sel = GlobalHandleToSel16(NE_SEG_TABLE(pModule)[sel-1].hSeg); else sel = GlobalHandleToSel16(NE_SEG_TABLE(pModule)[sel-1].hSeg);
if (sel==0xffff) if (sel==0xffff)
@ -362,39 +332,26 @@ FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop )
BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset ) BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset )
{ {
NE_MODULE *pModule; NE_MODULE *pModule;
WORD curOrdinal = 1; ET_ENTRY *entry;
BYTE *p; ET_BUNDLE *bundle;
int i;
if (!(pModule = NE_GetPtr( hModule ))) return FALSE; if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
assert( !(pModule->flags & NE_FFLAGS_WIN32) ); assert( !(pModule->flags & NE_FFLAGS_WIN32) );
p = (BYTE *)pModule + pModule->entry_table; bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
while (*p && (curOrdinal + *p <= ordinal)) while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
{
/* Skipping this bundle */
curOrdinal += *p;
switch(p[1])
{ {
case 0: p += 2; break; /* unused */ bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
case 0xff: p += 2 + *p * 6; break; /* moveable */ if (!(bundle->next))
default: p += 2 + *p * 3; break; /* fixed */ return 0;
}
} }
if (!*p) return FALSE;
switch(p[1]) entry = (ET_ENTRY *)((BYTE *)bundle+6);
{ for (i=0; i < (ordinal - bundle->first - 1); i++)
case 0: /* unused */ entry++;
return FALSE;
case 0xff: /* moveable */ entry->offs = offset;
p += 2 + 6 * (ordinal - curOrdinal);
*(WORD *)(p + 4) = offset;
break;
default: /* fixed */
p += 2 + 3 * (ordinal - curOrdinal);
*(WORD *)(p + 1) = offset;
break;
}
return TRUE; return TRUE;
} }
@ -436,9 +393,11 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
int size; int size;
HMODULE16 hModule; HMODULE16 hModule;
NE_MODULE *pModule; NE_MODULE *pModule;
BYTE *pData; BYTE *pData, *pTempEntryTable;
char *buffer, *fastload = NULL; char *buffer, *fastload = NULL;
int fastload_offset = 0, fastload_length = 0; int fastload_offset = 0, fastload_length = 0;
ET_ENTRY *entry;
ET_BUNDLE *bundle, *oldbundle;
/* Read a block from either the file or the fast-load area. */ /* Read a block from either the file or the fast-load area. */
#define READ(offset,size,buffer) \ #define READ(offset,size,buffer) \
@ -480,6 +439,9 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
ne_header.entry_tab_offset - ne_header.iname_tab_offset + ne_header.entry_tab_offset - ne_header.iname_tab_offset +
/* entry table length */ /* entry table length */
ne_header.entry_tab_length + ne_header.entry_tab_length +
/* entry table extra conversion space */
sizeof(ET_BUNDLE) +
2 * (ne_header.entry_tab_length - ne_header.n_mov_entry_points*6) +
/* loaded file info */ /* loaded file info */
sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1; sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
@ -537,7 +499,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
buffer )) buffer ))
{ {
HeapFree( SystemHeap, 0, buffer ); HeapFree( SystemHeap, 0, buffer );
if (fastload) HeapFree( SystemHeap, 0, fastload ); if (fastload)
HeapFree( SystemHeap, 0, fastload );
GlobalFree16( hModule ); GlobalFree16( hModule );
return (HMODULE16)11; /* invalid exe */ return (HMODULE16)11; /* invalid exe */
} }
@ -551,7 +514,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
} }
else else
{ {
if (fastload) HeapFree( SystemHeap, 0, fastload ); if (fastload)
HeapFree( SystemHeap, 0, fastload );
GlobalFree16( hModule ); GlobalFree16( hModule );
return (HMODULE16)11; /* invalid exe */ return (HMODULE16)11; /* invalid exe */
} }
@ -576,7 +540,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
ne_header.moduleref_tab_offset - ne_header.rname_tab_offset, ne_header.moduleref_tab_offset - ne_header.rname_tab_offset,
pData )) pData ))
{ {
if (fastload) HeapFree( SystemHeap, 0, fastload ); if (fastload)
HeapFree( SystemHeap, 0, fastload );
GlobalFree16( hModule ); GlobalFree16( hModule );
return (HMODULE16)11; /* invalid exe */ return (HMODULE16)11; /* invalid exe */
} }
@ -591,7 +556,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
ne_header.n_mod_ref_tab * sizeof(WORD), ne_header.n_mod_ref_tab * sizeof(WORD),
pData )) pData ))
{ {
if (fastload) HeapFree( SystemHeap, 0, fastload ); if (fastload)
HeapFree( SystemHeap, 0, fastload );
GlobalFree16( hModule ); GlobalFree16( hModule );
return (HMODULE16)11; /* invalid exe */ return (HMODULE16)11; /* invalid exe */
} }
@ -606,24 +572,101 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
ne_header.entry_tab_offset - ne_header.iname_tab_offset, ne_header.entry_tab_offset - ne_header.iname_tab_offset,
pData )) pData ))
{ {
if (fastload) HeapFree( SystemHeap, 0, fastload ); if (fastload)
HeapFree( SystemHeap, 0, fastload );
GlobalFree16( hModule ); GlobalFree16( hModule );
return (HMODULE16)11; /* invalid exe */ return (HMODULE16)11; /* invalid exe */
} }
pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset; pData += ne_header.entry_tab_offset - ne_header.iname_tab_offset;
/* Get the entry table */ /* Load entry table, convert it to the optimized version used by Windows */
if ((pTempEntryTable = HeapAlloc( SystemHeap, 0, ne_header.entry_tab_length)) != NULL)
{
BYTE nr_entries, type, *s;
TRACE(module, "Converting entry table.\n");
pModule->entry_table = (int)pData - (int)pModule; pModule->entry_table = (int)pData - (int)pModule;
if (!READ( mz_header.e_lfanew + ne_header.entry_tab_offset, if (!READ( mz_header.e_lfanew + ne_header.entry_tab_offset,
ne_header.entry_tab_length, ne_header.entry_tab_length, pTempEntryTable ))
pData ))
{ {
if (fastload) HeapFree( SystemHeap, 0, fastload ); HeapFree( SystemHeap, 0, pTempEntryTable );
if (fastload)
HeapFree( SystemHeap, 0, fastload );
GlobalFree16( hModule ); GlobalFree16( hModule );
return (HMODULE16)11; /* invalid exe */ return (HMODULE16)11; /* invalid exe */
} }
pData += ne_header.entry_tab_length;
s = pTempEntryTable;
TRACE(module, "entry table: offs %04x, len %04x, entries %d\n", ne_header.entry_tab_offset, ne_header.entry_tab_length, *s);
bundle = (ET_BUNDLE *)pData;
TRACE(module, "first bundle: %p\n", bundle);
memset(bundle, 0, sizeof(ET_BUNDLE)); /* in case no entry table exists */
entry = (ET_ENTRY *)((BYTE *)bundle+6);
while ((nr_entries = *s++))
{
if ((type = *s++))
{
bundle->last += nr_entries;
if (type == 0xff)
while (nr_entries--)
{
entry->type = type;
entry->flags = *s++;
s += 2;
entry->segnum = *s++;
entry->offs = *(WORD *)s; s += 2;
/*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
entry++;
}
else
while (nr_entries--)
{
entry->type = type;
entry->flags = *s++;
entry->segnum = type;
entry->offs = *(WORD *)s; s += 2;
/*TRACE(module, "entry: %p, type: %d, flags: %d, segnum: %d, offs: %04x\n", entry, entry->type, entry->flags, entry->segnum, entry->offs);*/
entry++;
}
}
else
{
if (bundle->first == bundle->last)
{
bundle->first += nr_entries;
bundle->last += nr_entries;
}
else
{
oldbundle = bundle;
oldbundle->next = ((int)entry - (int)pModule);
bundle = (ET_BUNDLE *)entry;
TRACE(module, "new bundle: %p\n", bundle);
bundle->first = bundle->last =
oldbundle->last + nr_entries;
bundle->next = 0;
(BYTE *)entry += sizeof(ET_BUNDLE);
}
}
}
HeapFree( SystemHeap, 0, pTempEntryTable );
}
else
{
if (fastload)
HeapFree( SystemHeap, 0, fastload );
GlobalFree16( hModule );
return (HMODULE16)11; /* invalid exe */
}
pData += ne_header.entry_tab_length + sizeof(ET_BUNDLE) +
2 * (ne_header.entry_tab_length - ne_header.n_mov_entry_points*6);
if ((DWORD)entry > (DWORD)pData)
ERR(module, "converted entry table bigger than reserved space !!!\nentry: %p, pData: %p. Please report !\n", entry, pData);
/* Store the filename information */ /* Store the filename information */
@ -636,7 +679,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
/* Free the fast-load area */ /* Free the fast-load area */
#undef READ #undef READ
if (fastload) HeapFree( SystemHeap, 0, fastload ); if (fastload)
HeapFree( SystemHeap, 0, fastload );
/* Get the non-resident names table */ /* Get the non-resident names table */
@ -792,7 +836,7 @@ static HINSTANCE16 NE_LoadFileModule( HFILE16 hFile, OFSTRUCT *ofs,
pModule->count = 1; pModule->count = 1;
/* Call initialization rountines for all loaded DLLs. Note that /* Call initialization routines for all loaded DLLs. Note that
* when we load implicitly linked DLLs this will be done by InitTask(). * when we load implicitly linked DLLs this will be done by InitTask().
*/ */

View file

@ -88,7 +88,7 @@ BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
mem = GlobalLock16(pSeg->hSeg); mem = GlobalLock16(pSeg->hSeg);
if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1) if (pModule->flags & NE_FFLAGS_SELFLOAD && segnum > 1)
{ {
/* Implement self loading segments */ /* Implement self-loading segments */
SELFLOADHEADER *selfloadheader; SELFLOADHEADER *selfloadheader;
STACK16FRAME *stack16Top; STACK16FRAME *stack16Top;
DWORD oldstack; DWORD oldstack;
@ -396,7 +396,7 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
{ {
HFILE hf; HFILE hf;
HFILE16 hFile16; HFILE16 hFile16;
/* Handle self loading modules */ /* Handle self-loading modules */
SELFLOADHEADER *selfloadheader; SELFLOADHEADER *selfloadheader;
STACK16FRAME *stack16Top; STACK16FRAME *stack16Top;
THDB *thdb = THREAD_Current(); THDB *thdb = THREAD_Current();
@ -413,7 +413,7 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
selfloadheader->EntryAddrProc = NE_GetEntryPoint(hselfload,27); selfloadheader->EntryAddrProc = NE_GetEntryPoint(hselfload,27);
selfloadheader->MyAlloc = NE_GetEntryPoint(hselfload,28); selfloadheader->MyAlloc = NE_GetEntryPoint(hselfload,28);
selfloadheader->SetOwner = NE_GetEntryPoint(GetModuleHandle16("KERNEL"),403); 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; oldstack = thdb->cur_stack;
thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel, thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
0xff00 - sizeof(*stack16Top) ); 0xff00 - sizeof(*stack16Top) );
@ -452,19 +452,104 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
} }
/***********************************************************************
* NE_FixupSegmentPrologs
*
* Fixup exported functions prologs of one segment
*/
void NE_FixupSegmentPrologs(NE_MODULE *pModule, WORD segnum)
{
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);
if (pSegTable[segnum-1].flags & NE_SEGFLAGS_DATA)
{
pSegTable[segnum-1].flags |= NE_SEGFLAGS_LOADED;
return;
}
if (!(dgroup = SEL(pSegTable[pModule->dgroup-1].hSeg)))
return;
pSeg = PTR_SEG_OFF_TO_LIN(sel, 0);
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--)
{
/*TRACE(module, "entry: %p, entry->segnum: %d, entry->offs: %04x\n", entry, entry->segnum, entry->offs);*/
if (entry->segnum == segnum)
{
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)
{
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 */
}
if (*(WORD *)pFunc == 0xd88c)
{
if ((entry->flags & 2)) /* public data ? */
{
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 ? */
{
TRACE(module, "patch %04x:%04x -> nop, nop\n", sel, entry->offs);
*(WORD *)pFunc = 0x9090; /* nop, nop */
}
}
}
}
entry++;
}
} while ( (bundle->next)
&& (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
}
/*********************************************************************** /***********************************************************************
* PatchCodeHandle * PatchCodeHandle
* *
* Needed for self-loading modules. * Needed for self-loading modules.
*/ */
DWORD WINAPI PatchCodeHandle16(HANDLE16 hSeg)
/* It does nothing */
DWORD WINAPI PatchCodeHandle16(HANDLE16 hSel)
{ {
FIXME(module,"(%04x): stub.\n",hSel); WORD segnum;
return (DWORD)NULL; 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 * NE_FixupPrologs
@ -473,91 +558,15 @@ DWORD WINAPI PatchCodeHandle16(HANDLE16 hSel)
*/ */
void NE_FixupPrologs( NE_MODULE *pModule ) void NE_FixupPrologs( NE_MODULE *pModule )
{ {
SEGTABLEENTRY *pSegTable; WORD segnum;
WORD dgroup = 0;
WORD sel;
BYTE *p, *fixup_ptr, count;
dbg_decl_str(module, 512);
pSegTable = NE_SEG_TABLE(pModule);
if (pModule->flags & NE_FFLAGS_SINGLEDATA)
dgroup = SEL(pSegTable[pModule->dgroup-1].hSeg);
TRACE(module, "(%04x)\n", pModule->self ); TRACE(module, "(%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 */ if (pModule->flags & NE_FFLAGS_SELFLOAD)
count = *p; NE_FixupSegmentPrologs(pModule, 1);
sel = p[1]; else
p += 2; for (segnum=1; segnum <= pModule->seg_count; segnum++)
while (count-- > 0) NE_FixupSegmentPrologs(pModule, segnum);
{
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)
{
/* can this happen? */
ERR(fixup, "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 {
WARN(fixup, "Unknown signature\n" );
}
}
else
TRACE(module,"\n");
p += (sel == 0xff) ? 6 : 3;
}
}
} }
/*********************************************************************** /***********************************************************************
@ -797,23 +806,30 @@ static WORD NE_Ne2MemFlags(WORD flags)
/*********************************************************************** /***********************************************************************
* NE_AllocateSegment (WPROCS.26) * NE_AllocateSegment (WPROCS.26)
*
* MyAlloc() function for self-loading apps.
*/ */
DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem ) DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem )
{ {
WORD size = wSize << wElem; WORD size = wSize << wElem;
HANDLE16 hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size); HANDLE16 hMem = 0;
/* not data == code */ if (wSize || (wFlags & NE_SEGFLAGS_MOVEABLE))
if ( (wFlags & NE_SEGFLAGS_EXECUTEONLY) || hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size);
!(wFlags & NE_SEGFLAGS_DATA)
) { if ( ((wFlags & 0x7) != 0x1) && /* DATA */
WORD hSel = GlobalHandleToSel16(hMem); ((wFlags & 0x7) != 0x7) ) /* DATA|ALLOCATED|LOADED */
{
WORD hSel = SEL(hMem);
WORD access = SelectorAccessRights16(hSel,0,0); WORD access = SelectorAccessRights16(hSel,0,0);
access |= 2<<2; /* SEGMENT_CODE */ access |= 2<<2; /* SEGMENT_CODE */
SelectorAccessRights16(hSel,1,access); 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 ) BOOL NE_CreateSegments( NE_MODULE *pModule )
{ {
SEGTABLEENTRY *pSegment; SEGTABLEENTRY *pSegment;
int i, minsize; int i, minsize, seg_count;
assert( !(pModule->flags & NE_FFLAGS_WIN32) ); assert( !(pModule->flags & NE_FFLAGS_WIN32) );
pSegment = NE_SEG_TABLE( pModule ); 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; minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
if (i == pModule->ss) minsize += pModule->stack_size; if (i == pModule->ss) minsize += pModule->stack_size;

View file

@ -796,8 +796,10 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
NE_MODULE *pModule; NE_MODULE *pModule;
SEGTABLEENTRY *pSegment; SEGTABLEENTRY *pSegment;
OFSTRUCT *pFileInfo; OFSTRUCT *pFileInfo;
BYTE *pstr, *bundle; BYTE *pstr;
WORD *pword; WORD *pword;
ET_BUNDLE *bundle = 0;
ET_ENTRY *entry = 0;
/* Module layout: /* Module layout:
* NE_MODULE Module * NE_MODULE Module
@ -911,7 +913,6 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
/* Entry table */ /* Entry table */
pModule->entry_table = (int)pstr - (int)pModule; pModule->entry_table = (int)pstr - (int)pModule;
bundle = NULL;
odp = OrdinalDefinitions + 1; odp = OrdinalDefinitions + 1;
for (i = 1; i <= Limit; i++, odp++) for (i = 1; i <= Limit; i++, odp++)
{ {
@ -943,24 +944,25 @@ static int BuildModule16( FILE *outfile, int max_code_offset,
break; break;
} }
/* create a new bundle if necessary */ if (!bundle)
if (!bundle || (bundle[0] >= 254) || (bundle[1] != selector))
{ {
bundle = pstr; bundle = (ET_BUNDLE *)pstr;
bundle[0] = 0; bundle->first = 0;
bundle[1] = selector; pstr += sizeof(ET_BUNDLE);
pstr += 2;
} }
(*bundle)++; /* FIXME: is this really correct ?? */
if (selector != 0) entry = (ET_ENTRY *)pstr;
{ entry->type = selector;
*pstr++ = 1; entry->flags = 3; /* exported & public data */
*(WORD *)pstr = odp->offset; entry->segnum = selector;
pstr += sizeof(WORD); entry->offs = odp->offset;
} pstr += sizeof(ET_ENTRY);
} }
*pstr++ = 0; *pstr++ = 0;
bundle->last = i;
bundle->next = 0;
/* Dump the module content */ /* Dump the module content */