Simplified hInstance creation/handling.

Fixes problems with self-loaders creating DGROUP themselves.
This commit is contained in:
Ulrich Weigand 1999-11-21 00:50:30 +00:00 committed by Alexandre Julliard
parent f64e0d7e37
commit 61206bd8a0
3 changed files with 75 additions and 134 deletions

View File

@ -222,11 +222,10 @@ extern NE_NAMEINFO *NE_FindResourceFromType( LPBYTE pResTab, NE_TYPEINFO *pTypeI
/* loader/ne/segment.c */ /* loader/ne/segment.c */
extern BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum ); extern BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum );
extern BOOL NE_LoadAllSegments( NE_MODULE *pModule ); extern BOOL NE_LoadAllSegments( NE_MODULE *pModule );
extern void NE_FixupPrologs( NE_MODULE *pModule ); extern BOOL NE_CreateSegment( NE_MODULE *pModule, int segnum );
extern BOOL NE_CreateAllSegments( NE_MODULE *pModule );
extern HINSTANCE16 NE_GetInstance( NE_MODULE *pModule );
extern void NE_InitializeDLLs( HMODULE16 hModule ); extern void NE_InitializeDLLs( HMODULE16 hModule );
extern BOOL NE_CreateSegments( NE_MODULE *pModule );
extern HINSTANCE16 NE_CreateInstance( NE_MODULE *pModule, HINSTANCE16 *prev,
BOOL lib_only );
/* loader/ne/convert.c */ /* loader/ne/convert.c */
HGLOBAL16 NE_LoadPEResource( NE_MODULE *pModule, WORD type, LPVOID bits, DWORD size ); HGLOBAL16 NE_LoadPEResource( NE_MODULE *pModule, WORD type, LPVOID bits, DWORD size );

View File

@ -799,12 +799,9 @@ static BOOL NE_LoadDLLs( NE_MODULE *pModule )
*/ */
static HINSTANCE16 NE_DoLoadModule( NE_MODULE *pModule ) static HINSTANCE16 NE_DoLoadModule( NE_MODULE *pModule )
{ {
HINSTANCE16 hInstance;
/* Allocate the segments for this module */ /* Allocate the segments for this module */
if (!NE_CreateSegments( pModule ) || if (!NE_CreateAllSegments( pModule ))
!(hInstance = NE_CreateInstance( pModule, NULL, FALSE )))
return 8; /* Insufficient memory */ return 8; /* Insufficient memory */
/* Load the referenced DLLs */ /* Load the referenced DLLs */
@ -816,16 +813,12 @@ static HINSTANCE16 NE_DoLoadModule( NE_MODULE *pModule )
NE_LoadAllSegments( pModule ); NE_LoadAllSegments( pModule );
/* Fixup the functions prologs */
NE_FixupPrologs( pModule );
/* Make sure the usage count is 1 on the first loading of */ /* Make sure the usage count is 1 on the first loading of */
/* the module, even if it contains circular DLL references */ /* the module, even if it contains circular DLL references */
pModule->count = 1; pModule->count = 1;
return hInstance; return NE_GetInstance( pModule );
} }
/********************************************************************** /**********************************************************************
@ -1002,11 +995,6 @@ HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
/* Increment refcount */ /* Increment refcount */
pModule->count++; pModule->count++;
/* If library module, we just retrieve the instance handle */
if ( ( pModule->flags & NE_FFLAGS_LIBMODULE ) || lib_only )
return NE_CreateInstance( pModule, NULL, TRUE );
} }
else else
{ {
@ -1017,13 +1005,12 @@ HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
if ( !(pModule = NE_GetPtr( hModule )) ) if ( !(pModule = NE_GetPtr( hModule )) )
return (HINSTANCE16)11; return (HINSTANCE16)11;
/* If library module, we're finished */
if ( ( pModule->flags & NE_FFLAGS_LIBMODULE ) || lib_only )
return hModule;
} }
/* If library module, we just retrieve the instance handle */
if ( ( pModule->flags & NE_FFLAGS_LIBMODULE ) || lib_only )
return NE_GetInstance( pModule );
/* /*
* At this point, we need to create a new process. * At this point, we need to create a new process.
@ -1177,9 +1164,13 @@ BOOL NE_InitProcess( NE_MODULE *pModule )
/* Second instance of an already loaded NE module */ /* Second instance of an already loaded NE module */
/* Note that the refcount was already incremented by the parent */ /* Note that the refcount was already incremented by the parent */
hInstance = NE_CreateInstance( pModule, &hPrevInstance, FALSE ); hPrevInstance = NE_GetInstance( pModule );
if ( hInstance != hPrevInstance ) /* not a library */
NE_LoadSegment( pModule, pModule->dgroup ); if ( pModule->dgroup )
if ( NE_CreateSegment( pModule, pModule->dgroup ) )
NE_LoadSegment( pModule, pModule->dgroup );
hInstance = NE_GetInstance( pModule );
} }
else else
{ {

View File

@ -36,6 +36,8 @@ DECLARE_DEBUG_CHANNEL(segment)
#define SEL(x) ((x)|1) #define SEL(x) ((x)|1)
static void NE_FixupSegmentPrologs(NE_MODULE *pModule, WORD segnum);
/*********************************************************************** /***********************************************************************
* NE_GetRelocAddrName * NE_GetRelocAddrName
*/ */
@ -97,14 +99,12 @@ BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
/* Implement self-loading segments */ /* Implement self-loading segments */
SELFLOADHEADER *selfloadheader; SELFLOADHEADER *selfloadheader;
DWORD oldstack; DWORD oldstack;
WORD old_hSeg, new_hSeg;
HFILE hFile32; HFILE hFile32;
HFILE16 hFile16; HFILE16 hFile16;
selfloadheader = (SELFLOADHEADER *) selfloadheader = (SELFLOADHEADER *)
PTR_SEG_OFF_TO_LIN(SEL(pSegTable->hSeg),0); PTR_SEG_OFF_TO_LIN(SEL(pSegTable->hSeg),0);
oldstack = NtCurrentTeb()->cur_stack; oldstack = NtCurrentTeb()->cur_stack;
old_hSeg = pSeg->hSeg;
NtCurrentTeb()->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel, NtCurrentTeb()->cur_stack = PTR_SEG_OFF_TO_SEGPTR(pModule->self_loading_sel,
0xff00 - sizeof(STACK16FRAME)); 0xff00 - sizeof(STACK16FRAME));
@ -113,29 +113,11 @@ BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
DuplicateHandle( GetCurrentProcess(), hf, GetCurrentProcess(), &hFile32, DuplicateHandle( GetCurrentProcess(), hf, GetCurrentProcess(), &hFile32,
0, FALSE, DUPLICATE_SAME_ACCESS ); 0, FALSE, DUPLICATE_SAME_ACCESS );
hFile16 = FILE_AllocDosHandle( hFile32 ); hFile16 = FILE_AllocDosHandle( hFile32 );
new_hSeg = Callbacks->CallLoadAppSegProc(selfloadheader->LoadAppSeg, pSeg->hSeg = Callbacks->CallLoadAppSegProc( selfloadheader->LoadAppSeg,
pModule->self, hFile16, pModule->self, hFile16,
segnum ); segnum );
TRACE_(dll)("Ret CallLoadAppSegProc: hSeg = 0x%04x\n",new_hSeg); TRACE_(dll)("Ret CallLoadAppSegProc: hSeg = 0x%04x\n", pSeg->hSeg);
_lclose16( hFile16 ); _lclose16( hFile16 );
if (SEL(new_hSeg) != SEL(old_hSeg)) {
/* Self loaders like creating their own selectors;
* they love asking for trouble to Wine developers
*/
if (segnum == pModule->dgroup) {
memcpy(PTR_SEG_OFF_TO_LIN(SEL(old_hSeg),0),
PTR_SEG_OFF_TO_LIN(SEL(new_hSeg),0),
pSeg->minsize ? pSeg->minsize : 0x10000);
FreeSelector16(SEL(new_hSeg));
pSeg->hSeg = old_hSeg;
TRACE_(module)("New hSeg allocated for dgroup segment:Old=%d,New=%d\n",
old_hSeg, new_hSeg);
} else {
FreeSelector16(SEL(pSeg->hSeg));
pSeg->hSeg = new_hSeg;
}
}
NtCurrentTeb()->cur_stack = oldstack; NtCurrentTeb()->cur_stack = oldstack;
} }
else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED)) else if (!(pSeg->flags & NE_SEGFLAGS_ITERATED))
@ -165,6 +147,10 @@ BOOL NE_LoadSegment( NE_MODULE *pModule, WORD segnum )
} }
pSeg->flags |= NE_SEGFLAGS_LOADED; pSeg->flags |= NE_SEGFLAGS_LOADED;
/* Perform exported function prolog fixups */
NE_FixupSegmentPrologs( pModule, segnum );
if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA)) if (!(pSeg->flags & NE_SEGFLAGS_RELOC_DATA))
return TRUE; /* No relocation data, we are done */ return TRUE; /* No relocation data, we are done */
@ -396,7 +382,6 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
SELFLOADHEADER *selfloadheader; SELFLOADHEADER *selfloadheader;
HMODULE16 hselfload = GetModuleHandle16("WPROCS"); HMODULE16 hselfload = GetModuleHandle16("WPROCS");
DWORD oldstack; DWORD oldstack;
WORD saved_hSeg = pSegTable[pModule->dgroup - 1].hSeg;
TRACE_(module)("%.*s is a self-loading module!\n", TRACE_(module)("%.*s is a self-loading module!\n",
*((BYTE*)pModule + pModule->name_table), *((BYTE*)pModule + pModule->name_table),
@ -420,8 +405,6 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
Callbacks->CallBootAppProc(selfloadheader->BootApp, pModule->self,hFile16); Callbacks->CallBootAppProc(selfloadheader->BootApp, pModule->self,hFile16);
TRACE_(dll)("Return from CallBootAppProc\n"); TRACE_(dll)("Return from CallBootAppProc\n");
_lclose16(hf); _lclose16(hf);
/* some BootApp procs overwrite the segment handle of dgroup */
pSegTable[pModule->dgroup - 1].hSeg = saved_hSeg;
NtCurrentTeb()->cur_stack = oldstack; NtCurrentTeb()->cur_stack = oldstack;
for (i = 2; i <= pModule->seg_count; i++) for (i = 2; i <= pModule->seg_count; i++)
@ -441,7 +424,7 @@ BOOL NE_LoadAllSegments( NE_MODULE *pModule )
* *
* Fixup exported functions prologs of one segment * Fixup exported functions prologs of one segment
*/ */
void NE_FixupSegmentPrologs(NE_MODULE *pModule, WORD segnum) static void NE_FixupSegmentPrologs(NE_MODULE *pModule, WORD segnum)
{ {
SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule ); SEGTABLEENTRY *pSegTable = NE_SEG_TABLE( pModule );
ET_BUNDLE *bundle; ET_BUNDLE *bundle;
@ -537,23 +520,6 @@ DWORD WINAPI PatchCodeHandle16(HANDLE16 hSeg)
return MAKELONG(hSeg, sel); 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);
}
/*********************************************************************** /***********************************************************************
* NE_GetDLLInitParams * NE_GetDLLInitParams
@ -746,49 +712,6 @@ static WORD NE_Ne2MemFlags(WORD flags)
return memflags; return memflags;
} }
/***********************************************************************
* NE_CreateInstance
*
* If lib_only is TRUE, handle the module like a library even if it is a .EXE
*/
HINSTANCE16 NE_CreateInstance( NE_MODULE *pModule, HINSTANCE16 *prev,
BOOL lib_only )
{
SEGTABLEENTRY *pSegment;
int minsize;
HINSTANCE16 hNewSeg;
if (pModule->dgroup == 0)
{
if (prev) *prev = pModule->self;
return pModule->self;
}
pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
if (prev) *prev = SEL(pSegment->hSeg);
/* if it's a library, create a new instance only the first time */
if (pSegment->hSeg)
{
if (pModule->flags & NE_FFLAGS_LIBMODULE) return SEL(pSegment->hSeg);
if (lib_only) return SEL(pSegment->hSeg);
}
minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
if (pModule->ss == pModule->dgroup) minsize += pModule->stack_size;
minsize += pModule->heap_size;
hNewSeg = GLOBAL_Alloc( NE_Ne2MemFlags(pSegment->flags), minsize,
pModule->self, FALSE, FALSE, FALSE );
if (!hNewSeg) return 0;
pSegment->hSeg = hNewSeg;
pSegment->flags |= NE_SEGFLAGS_ALLOCATED;
/* a HINSTANCE is the selector of the DSEG */
return (HINSTANCE16)SEL(hNewSeg);
}
/*********************************************************************** /***********************************************************************
* NE_AllocateSegment (WPROCS.26) * NE_AllocateSegment (WPROCS.26)
* *
@ -817,37 +740,65 @@ DWORD WINAPI NE_AllocateSegment( WORD wFlags, WORD wSize, WORD wElem )
return MAKELONG( 0, hMem ); return MAKELONG( 0, hMem );
} }
/***********************************************************************
* NE_GetInstance
*/
HINSTANCE16 NE_GetInstance( NE_MODULE *pModule )
{
if ( !pModule->dgroup )
return pModule->self;
else
{
SEGTABLEENTRY *pSegment;
pSegment = NE_SEG_TABLE( pModule ) + pModule->dgroup - 1;
return SEL(pSegment->hSeg);
}
}
/*********************************************************************** /***********************************************************************
* NE_CreateSegments * NE_CreateSegment
*/ */
BOOL NE_CreateSegments( NE_MODULE *pModule ) BOOL NE_CreateSegment( NE_MODULE *pModule, int segnum )
{ {
SEGTABLEENTRY *pSegment; SEGTABLEENTRY *pSegment = NE_SEG_TABLE( pModule ) + segnum - 1;
int i, minsize, seg_count; int minsize;
assert( !(pModule->flags & NE_FFLAGS_WIN32) ); assert( !(pModule->flags & NE_FFLAGS_WIN32) );
pSegment = NE_SEG_TABLE( pModule ); if ( segnum < 1 || segnum > pModule->seg_count )
return FALSE;
if (pModule->flags & NE_FFLAGS_SELFLOAD) if ( (pModule->flags & NE_FFLAGS_SELFLOAD) && segnum != 1 )
seg_count = 1; return TRUE; /* selfloader allocates segment itself */
else
seg_count = pModule->seg_count; if ( (pSegment->flags & NE_SEGFLAGS_ALLOCATED) && segnum != pModule->dgroup )
for (i = 1; i <= seg_count; i++, pSegment++) return TRUE; /* all but DGROUP only allocated once */
{
minsize = pSegment->minsize ? pSegment->minsize : 0x10000; minsize = pSegment->minsize ? pSegment->minsize : 0x10000;
if (i == pModule->ss) minsize += pModule->stack_size; if ( segnum == pModule->ss ) minsize += pModule->stack_size;
/* The DGROUP is allocated by NE_CreateInstance */ if ( segnum == pModule->dgroup ) minsize += pModule->heap_size;
if (i == pModule->dgroup) continue;
pSegment->hSeg = GLOBAL_Alloc( NE_Ne2MemFlags(pSegment->flags), pSegment->hSeg = GLOBAL_Alloc( NE_Ne2MemFlags(pSegment->flags),
minsize, pModule->self, minsize, pModule->self,
!(pSegment->flags & NE_SEGFLAGS_DATA), !(pSegment->flags & NE_SEGFLAGS_DATA),
(pSegment->flags & NE_SEGFLAGS_32BIT) != 0, (pSegment->flags & NE_SEGFLAGS_32BIT) != 0,
FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ ); FALSE /*pSegment->flags & NE_SEGFLAGS_READONLY*/ );
if (!pSegment->hSeg) return FALSE; if (!pSegment->hSeg) return FALSE;
pSegment->flags |= NE_SEGFLAGS_ALLOCATED;
} pSegment->flags |= NE_SEGFLAGS_ALLOCATED;
return TRUE;
}
/***********************************************************************
* NE_CreateAllSegments
*/
BOOL NE_CreateAllSegments( NE_MODULE *pModule )
{
int i;
for ( i = 1; i <= pModule->seg_count; i++ )
if ( !NE_CreateSegment( pModule, i ) )
return FALSE;
pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table + pModule->dgroup_entry = pModule->dgroup ? pModule->seg_table +
(pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0; (pModule->dgroup - 1) * sizeof(SEGTABLEENTRY) : 0;