- Implemented proper ("real", compressed) Win16 entry tables.
- Fixed MyAlloc (AKA NE_AllocateSegment). - Implemented PatchCodeHandle16.
This commit is contained in:
parent
0a9975242a
commit
dca5e56b90
|
@ -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) */
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue