mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-05 17:19:33 +00:00
- 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 )
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -59,6 +59,8 @@ void NE_DumpModule( HMODULE16 hModule )
|
|||
BYTE *pstr;
|
||||
WORD *pword;
|
||||
NE_MODULE *pModule;
|
||||
ET_BUNDLE *bundle;
|
||||
ET_ENTRY *entry;
|
||||
|
||||
if (!(pModule = NE_GetPtr( hModule )))
|
||||
{
|
||||
|
@ -143,39 +145,21 @@ void NE_DumpModule( HMODULE16 hModule )
|
|||
/* Dump the entry table */
|
||||
DUMP( "---\n" );
|
||||
DUMP( "Entry table:\n" );
|
||||
pstr = (char *)pModule + pModule->entry_table;
|
||||
ordinal = 1;
|
||||
while (*pstr)
|
||||
{
|
||||
DUMP( "Bundle %d-%d: %02x\n", ordinal, ordinal + *pstr - 1, pstr[1]);
|
||||
if (!pstr[1])
|
||||
bundle = (ET_BUNDLE *)((BYTE *)pModule+pModule->entry_table);
|
||||
do {
|
||||
entry = (ET_ENTRY *)((BYTE *)bundle+6);
|
||||
DUMP( "Bundle %d-%d: %02x\n", bundle->first, bundle->last, entry->type);
|
||||
ordinal = bundle->first;
|
||||
while (ordinal < bundle->last)
|
||||
{
|
||||
ordinal += *pstr;
|
||||
pstr += 2;
|
||||
}
|
||||
else if ((BYTE)pstr[1] == 0xff) /* moveable */
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (entry->type == 0xff)
|
||||
DUMP("%d: %02x:%04x (moveable)\n", ordinal++, entry->segnum, entry->offs);
|
||||
else
|
||||
DUMP("%d: %02x:%04x (fixed)\n", ordinal++, entry->segnum, entry->offs);
|
||||
entry++;
|
||||
}
|
||||
} while ( (bundle->next)
|
||||
&& (bundle = ((ET_BUNDLE *)((BYTE *)pModule + bundle->next))) );
|
||||
|
||||
/* Dump the non-resident names table */
|
||||
DUMP( "---\n" );
|
||||
|
@ -305,43 +289,29 @@ FARPROC16 NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal )
|
|||
FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop )
|
||||
{
|
||||
NE_MODULE *pModule;
|
||||
WORD curOrdinal = 1;
|
||||
BYTE *p;
|
||||
WORD sel, offset;
|
||||
WORD sel, offset, i;
|
||||
|
||||
ET_ENTRY *entry;
|
||||
ET_BUNDLE *bundle;
|
||||
|
||||
if (!(pModule = NE_GetPtr( hModule ))) return 0;
|
||||
assert( !(pModule->flags & NE_FFLAGS_WIN32) );
|
||||
|
||||
p = (BYTE *)pModule + pModule->entry_table;
|
||||
while (*p && (curOrdinal + *p <= ordinal))
|
||||
bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
|
||||
while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
|
||||
{
|
||||
/* Skipping this bundle */
|
||||
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 */
|
||||
if (!(bundle->next))
|
||||
return 0;
|
||||
case 0xff: /* moveable */
|
||||
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;
|
||||
bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
|
||||
}
|
||||
|
||||
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 */
|
||||
else sel = GlobalHandleToSel16(NE_SEG_TABLE(pModule)[sel-1].hSeg);
|
||||
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 )
|
||||
{
|
||||
NE_MODULE *pModule;
|
||||
WORD curOrdinal = 1;
|
||||
BYTE *p;
|
||||
ET_ENTRY *entry;
|
||||
ET_BUNDLE *bundle;
|
||||
int i;
|
||||
|
||||
if (!(pModule = NE_GetPtr( hModule ))) return FALSE;
|
||||
assert( !(pModule->flags & NE_FFLAGS_WIN32) );
|
||||
|
||||
p = (BYTE *)pModule + pModule->entry_table;
|
||||
while (*p && (curOrdinal + *p <= ordinal))
|
||||
{
|
||||
/* Skipping this bundle */
|
||||
curOrdinal += *p;
|
||||
switch(p[1])
|
||||
bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
|
||||
while ((ordinal < bundle->first + 1) || (ordinal > bundle->last))
|
||||
{
|
||||
case 0: p += 2; break; /* unused */
|
||||
case 0xff: p += 2 + *p * 6; break; /* moveable */
|
||||
default: p += 2 + *p * 3; break; /* fixed */
|
||||
}
|
||||
bundle = (ET_BUNDLE *)((BYTE *)pModule + bundle->next);
|
||||
if (!(bundle->next))
|
||||
return 0;
|
||||
}
|
||||
if (!*p) return FALSE;
|
||||
|
||||
switch(p[1])
|
||||
{
|
||||
case 0: /* unused */
|
||||
return FALSE;
|
||||
case 0xff: /* moveable */
|
||||
p += 2 + 6 * (ordinal - curOrdinal);
|
||||
*(WORD *)(p + 4) = offset;
|
||||
break;
|
||||
default: /* fixed */
|
||||
p += 2 + 3 * (ordinal - curOrdinal);
|
||||
*(WORD *)(p + 1) = offset;
|
||||
break;
|
||||
}
|
||||
entry = (ET_ENTRY *)((BYTE *)bundle+6);
|
||||
for (i=0; i < (ordinal - bundle->first - 1); i++)
|
||||
entry++;
|
||||
|
||||
entry->offs = offset;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -436,9 +393,11 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
|
|||
int size;
|
||||
HMODULE16 hModule;
|
||||
NE_MODULE *pModule;
|
||||
BYTE *pData;
|
||||
BYTE *pData, *pTempEntryTable;
|
||||
char *buffer, *fastload = NULL;
|
||||
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. */
|
||||
#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 +
|
||||
/* entry table 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 */
|
||||
sizeof(OFSTRUCT)-sizeof(ofs->szPathName)+strlen(ofs->szPathName)+1;
|
||||
|
||||
|
@ -537,7 +499,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
|
|||
buffer ))
|
||||
{
|
||||
HeapFree( SystemHeap, 0, buffer );
|
||||
if (fastload) HeapFree( SystemHeap, 0, fastload );
|
||||
if (fastload)
|
||||
HeapFree( SystemHeap, 0, fastload );
|
||||
GlobalFree16( hModule );
|
||||
return (HMODULE16)11; /* invalid exe */
|
||||
}
|
||||
|
@ -551,7 +514,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
|
|||
}
|
||||
else
|
||||
{
|
||||
if (fastload) HeapFree( SystemHeap, 0, fastload );
|
||||
if (fastload)
|
||||
HeapFree( SystemHeap, 0, fastload );
|
||||
GlobalFree16( hModule );
|
||||
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,
|
||||
pData ))
|
||||
{
|
||||
if (fastload) HeapFree( SystemHeap, 0, fastload );
|
||||
if (fastload)
|
||||
HeapFree( SystemHeap, 0, fastload );
|
||||
GlobalFree16( hModule );
|
||||
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),
|
||||
pData ))
|
||||
{
|
||||
if (fastload) HeapFree( SystemHeap, 0, fastload );
|
||||
if (fastload)
|
||||
HeapFree( SystemHeap, 0, fastload );
|
||||
GlobalFree16( hModule );
|
||||
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,
|
||||
pData ))
|
||||
{
|
||||
if (fastload) HeapFree( SystemHeap, 0, fastload );
|
||||
if (fastload)
|
||||
HeapFree( SystemHeap, 0, fastload );
|
||||
GlobalFree16( hModule );
|
||||
return (HMODULE16)11; /* invalid exe */
|
||||
}
|
||||
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;
|
||||
if (!READ( mz_header.e_lfanew + ne_header.entry_tab_offset,
|
||||
ne_header.entry_tab_length,
|
||||
pData ))
|
||||
ne_header.entry_tab_length, pTempEntryTable ))
|
||||
{
|
||||
if (fastload) HeapFree( SystemHeap, 0, fastload );
|
||||
HeapFree( SystemHeap, 0, pTempEntryTable );
|
||||
if (fastload)
|
||||
HeapFree( SystemHeap, 0, fastload );
|
||||
GlobalFree16( hModule );
|
||||
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 */
|
||||
|
||||
|
@ -636,7 +679,8 @@ static HMODULE16 NE_LoadExeHeader( HFILE16 hFile, OFSTRUCT *ofs )
|
|||
/* Free the fast-load area */
|
||||
|
||||
#undef READ
|
||||
if (fastload) HeapFree( SystemHeap, 0, fastload );
|
||||
if (fastload)
|
||||
HeapFree( SystemHeap, 0, fastload );
|
||||
|
||||
/* Get the non-resident names table */
|
||||
|
||||
|
@ -792,7 +836,7 @@ static HINSTANCE16 NE_LoadFileModule( HFILE16 hFile, OFSTRUCT *ofs,
|
|||
|
||||
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().
|
||||
*/
|
||||
|
||||
|
|
|
@ -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) );
|
||||
|
@ -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
|
||||
*
|
||||
* Needed for self-loading modules.
|
||||
*/
|
||||
|
||||
/* It does nothing */
|
||||
DWORD WINAPI PatchCodeHandle16(HANDLE16 hSel)
|
||||
DWORD WINAPI PatchCodeHandle16(HANDLE16 hSeg)
|
||||
{
|
||||
FIXME(module,"(%04x): stub.\n",hSel);
|
||||
return (DWORD)NULL;
|
||||
}
|
||||
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
|
||||
|
@ -473,91 +558,15 @@ DWORD WINAPI PatchCodeHandle16(HANDLE16 hSel)
|
|||
*/
|
||||
void NE_FixupPrologs( NE_MODULE *pModule )
|
||||
{
|
||||
SEGTABLEENTRY *pSegTable;
|
||||
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);
|
||||
WORD segnum;
|
||||
|
||||
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 */
|
||||
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)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
/* not data == code */
|
||||
if ( (wFlags & NE_SEGFLAGS_EXECUTEONLY) ||
|
||||
!(wFlags & NE_SEGFLAGS_DATA)
|
||||
) {
|
||||
WORD hSel = GlobalHandleToSel16(hMem);
|
||||
if (wSize || (wFlags & NE_SEGFLAGS_MOVEABLE))
|
||||
hMem = GlobalAlloc16( NE_Ne2MemFlags(wFlags), size);
|
||||
|
||||
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 */
|
||||
|
||||
|
|
Loading…
Reference in a new issue