Use the exe name and file handle we got from the server also when

starting Win16 or DOS programs, to avoid depending on the contents of
the command-line.
This commit is contained in:
Alexandre Julliard 2001-01-06 01:55:49 +00:00
parent 2362380b64
commit 105b0f4e64
7 changed files with 148 additions and 162 deletions

View File

@ -333,33 +333,9 @@ load_error:
return FALSE;
}
BOOL WINAPI MZ_LoadImage( LPCSTR cmdline )
void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile )
{
HFILE hFile;
char *name, buffer[MAX_PATH];
LPCSTR p = strchr( cmdline, ' ' );
if (p)
{
if (!(name = HeapAlloc( GetProcessHeap(), 0, p - cmdline + 1 ))) return FALSE;
memcpy( name, cmdline, p - cmdline );
name[p - cmdline] = 0;
}
else name = (char *)cmdline;
if (!SearchPathA( NULL, name, ".exe", sizeof(buffer), buffer, NULL )) goto error;
if ((hFile = CreateFileA( buffer, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, 0, 0 )) == INVALID_HANDLE_VALUE)
goto error;
if (!MZ_DoLoadImage( hFile, buffer, NULL ))
{
CloseHandle( hFile );
goto error;
}
MZ_Launch();
error:
if (name != cmdline) HeapFree( GetProcessHeap(), 0, name );
return FALSE;
if (MZ_DoLoadImage( hFile, filename, NULL )) MZ_Launch();
}
BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )
@ -609,11 +585,10 @@ void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval )
#else /* !MZ_SUPPORTED */
BOOL WINAPI MZ_LoadImage( LPCSTR cmdline )
void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile )
{
WARN("DOS executables not supported on this platform\n");
SetLastError(ERROR_BAD_FORMAT);
return FALSE;
}
BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk )

View File

@ -7,7 +7,7 @@ import ntdll.dll
@ stdcall GetCurrent() MZ_Current
@ stdcall LoadDPMI() MZ_AllocDPMITask
@ stdcall LoadDosExe(str) MZ_LoadImage
@ stdcall LoadDosExe(str long) MZ_LoadImage
@ stdcall Exec(ptr str long ptr) MZ_Exec
@ stdcall Exit(ptr long long) MZ_Exit

View File

@ -52,7 +52,7 @@ extern CALLOUT_TABLE Callout;
typedef struct {
struct _DOSTASK* WINAPI (*Current)( void );
struct _DOSTASK* WINAPI (*LoadDPMI)( void );
BOOL WINAPI (*LoadDosExe)( LPCSTR cmdline );
void WINAPI (*LoadDosExe)( LPCSTR filename, HANDLE hFile );
BOOL WINAPI (*Exec)( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
void WINAPI (*Exit)( CONTEXT86 *context, BOOL cs_psp, WORD retval );
int WINAPI (*Enter)( CONTEXT86 *context );

View File

@ -30,7 +30,7 @@ typedef struct _DOSTASK {
#define V86_FLAG 0x00020000
extern BOOL WINAPI MZ_LoadImage( LPCSTR cmdline );
extern void WINAPI MZ_LoadImage( LPCSTR filename, HANDLE hFile );
extern BOOL WINAPI MZ_Exec( CONTEXT86 *context, LPCSTR filename, BYTE func, LPVOID paramblk );
extern void WINAPI MZ_Exit( CONTEXT86 *context, BOOL cs_psp, WORD retval );
extern LPDOSTASK WINAPI MZ_Current( void );

View File

@ -404,11 +404,8 @@ HANDLE NE_OpenFile( NE_MODULE *pModule )
/***********************************************************************
* NE_LoadExeHeader
*
* We always have to close hFile upon exit.
* Otherwise we get file sharing trouble !
*/
static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
static HMODULE16 NE_LoadExeHeader( HANDLE hFile, LPCSTR path )
{
IMAGE_DOS_HEADER mz_header;
IMAGE_OS2_HEADER ne_header;
@ -420,51 +417,31 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
int fastload_offset = 0, fastload_length = 0;
ET_ENTRY *entry;
ET_BUNDLE *bundle, *oldbundle;
HFILE16 hFile;
OFSTRUCT ofs;
/* Open file */
if ((hFile = OpenFile16( filename, &ofs, OF_READ )) == HFILE_ERROR16)
return (HMODULE16)2; /* File not found */
OFSTRUCT *ofs;
/* Read a block from either the file or the fast-load area. */
#define READ(offset,size,buffer) \
((fastload && ((offset) >= fastload_offset) && \
((offset)+(size) <= fastload_offset+fastload_length)) ? \
(memcpy( buffer, fastload+(offset)-fastload_offset, (size) ), TRUE) : \
(_llseek16( hFile, (offset), SEEK_SET), \
_hread16( hFile, (buffer), (size) ) == (size)))
(_llseek( hFile, (offset), SEEK_SET), \
_lread( hFile, (buffer), (size) ) == (size)))
_llseek16( hFile, 0, SEEK_SET );
if ((_hread16(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
_llseek( hFile, 0, SEEK_SET );
if ((_lread(hFile,&mz_header,sizeof(mz_header)) != sizeof(mz_header)) ||
(mz_header.e_magic != IMAGE_DOS_SIGNATURE))
{
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
_llseek16( hFile, mz_header.e_lfanew, SEEK_SET );
if (_hread16( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
{
_lclose16( hFile );
_llseek( hFile, mz_header.e_lfanew, SEEK_SET );
if (_lread( hFile, &ne_header, sizeof(ne_header) ) != sizeof(ne_header))
return (HMODULE16)11; /* invalid exe */
}
if (ne_header.ne_magic == IMAGE_NT_SIGNATURE)
{
_lclose16( hFile );
return (HMODULE16)21; /* win32 exe */
}
if (ne_header.ne_magic == IMAGE_NT_SIGNATURE) return (HMODULE16)21; /* win32 exe */
if (ne_header.ne_magic == IMAGE_OS2_SIGNATURE_LX) {
MESSAGE("Sorry, this is an OS/2 linear executable (LX) file !\n");
_lclose16( hFile );
return (HMODULE16)12;
}
if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE)
{
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
if (ne_header.ne_magic != IMAGE_OS2_SIGNATURE) return (HMODULE16)11; /* invalid exe */
/* We now have a valid NE header */
@ -485,14 +462,10 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
sizeof(ET_BUNDLE) +
2 * (ne_header.ne_cbenttab - ne_header.ne_cmovent*6) +
/* loaded file info */
sizeof(OFSTRUCT)-sizeof(ofs.szPathName)+strlen(ofs.szPathName)+1;
sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(path) + 1;
hModule = GlobalAlloc16( GMEM_FIXED | GMEM_ZEROINIT, size );
if (!hModule)
{
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
if (!hModule) return (HMODULE16)11; /* invalid exe */
FarSetOwner16( hModule, hModule );
pModule = (NE_MODULE *)GlobalLock16( hModule );
@ -521,8 +494,8 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
fastload_offset, fastload_length );
if ((fastload = HeapAlloc( GetProcessHeap(), 0, fastload_length )) != NULL)
{
_llseek16( hFile, fastload_offset, SEEK_SET);
if (_hread16(hFile, fastload, fastload_length) != fastload_length)
_llseek( hFile, fastload_offset, SEEK_SET);
if (_lread(hFile, fastload, fastload_length) != fastload_length)
{
HeapFree( GetProcessHeap(), 0, fastload );
WARN("Error reading fast-load area!\n");
@ -533,7 +506,7 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
/* Get the segment table */
pModule->seg_table = (int)pData - (int)pModule;
pModule->seg_table = pData - (BYTE *)pModule;
buffer = HeapAlloc( GetProcessHeap(), 0, ne_header.ne_cseg *
sizeof(struct ne_segment_table_entry_s));
if (buffer)
@ -549,7 +522,6 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
if (fastload)
HeapFree( GetProcessHeap(), 0, fastload );
GlobalFree16( hModule );
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
pSeg = (struct ne_segment_table_entry_s *)buffer;
@ -565,7 +537,6 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
if (fastload)
HeapFree( GetProcessHeap(), 0, fastload );
GlobalFree16( hModule );
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
@ -573,14 +544,11 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
if (ne_header.ne_rsrctab < ne_header.ne_restab)
{
pModule->res_table = (int)pData - (int)pModule;
pModule->res_table = pData - (BYTE *)pModule;
if (!READ(mz_header.e_lfanew + ne_header.ne_rsrctab,
ne_header.ne_restab - ne_header.ne_rsrctab,
pData ))
{
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
pData += ne_header.ne_restab - ne_header.ne_rsrctab;
NE_InitResourceHandler( hModule );
}
@ -588,7 +556,7 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
/* Get the resident names table */
pModule->name_table = (int)pData - (int)pModule;
pModule->name_table = pData - (BYTE *)pModule;
if (!READ( mz_header.e_lfanew + ne_header.ne_restab,
ne_header.ne_modtab - ne_header.ne_restab,
pData ))
@ -596,7 +564,6 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
if (fastload)
HeapFree( GetProcessHeap(), 0, fastload );
GlobalFree16( hModule );
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
pData += ne_header.ne_modtab - ne_header.ne_restab;
@ -605,7 +572,7 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
if (ne_header.ne_cmod > 0)
{
pModule->modref_table = (int)pData - (int)pModule;
pModule->modref_table = pData - (BYTE *)pModule;
if (!READ( mz_header.e_lfanew + ne_header.ne_modtab,
ne_header.ne_cmod * sizeof(WORD),
pData ))
@ -613,7 +580,6 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
if (fastload)
HeapFree( GetProcessHeap(), 0, fastload );
GlobalFree16( hModule );
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
pData += ne_header.ne_cmod * sizeof(WORD);
@ -622,7 +588,7 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
/* Get the imported names table */
pModule->import_table = (int)pData - (int)pModule;
pModule->import_table = pData - (BYTE *)pModule;
if (!READ( mz_header.e_lfanew + ne_header.ne_imptab,
ne_header.ne_enttab - ne_header.ne_imptab,
pData ))
@ -630,7 +596,6 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
if (fastload)
HeapFree( GetProcessHeap(), 0, fastload );
GlobalFree16( hModule );
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
pData += ne_header.ne_enttab - ne_header.ne_imptab;
@ -642,7 +607,7 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
BYTE nr_entries, type, *s;
TRACE("Converting entry table.\n");
pModule->entry_table = (int)pData - (int)pModule;
pModule->entry_table = pData - (BYTE *)pModule;
if (!READ( mz_header.e_lfanew + ne_header.ne_enttab,
ne_header.ne_cbenttab, pTempEntryTable ))
{
@ -650,7 +615,6 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
if (fastload)
HeapFree( GetProcessHeap(), 0, fastload );
GlobalFree16( hModule );
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
@ -716,7 +680,6 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
if (fastload)
HeapFree( GetProcessHeap(), 0, fastload );
GlobalFree16( hModule );
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
@ -728,10 +691,12 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
/* Store the filename information */
pModule->fileinfo = (int)pData - (int)pModule;
size = sizeof(OFSTRUCT)-sizeof(ofs.szPathName)+strlen(ofs.szPathName)+1;
ofs.cBytes = size - 1;
memcpy( pData, &ofs, size );
pModule->fileinfo = pData - (BYTE *)pModule;
size = sizeof(OFSTRUCT) - sizeof(ofs->szPathName) + strlen(path) + 1;
ofs = (OFSTRUCT *)pData;
ofs->cBytes = size - 1;
ofs->fFixedDisk = 1;
strcpy( ofs->szPathName, path );
pData += size;
/* Free the fast-load area */
@ -749,17 +714,15 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
if (!pModule->nrname_handle)
{
GlobalFree16( hModule );
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
buffer = GlobalLock16( pModule->nrname_handle );
_llseek16( hFile, ne_header.ne_nrestab, SEEK_SET );
if (_hread16( hFile, buffer, ne_header.ne_cbnrestab )
_llseek( hFile, ne_header.ne_nrestab, SEEK_SET );
if (_lread( hFile, buffer, ne_header.ne_cbnrestab )
!= ne_header.ne_cbnrestab)
{
GlobalFree16( pModule->nrname_handle );
GlobalFree16( hModule );
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
}
@ -776,16 +739,13 @@ static HMODULE16 NE_LoadExeHeader( LPCSTR filename )
{
if (pModule->nrname_handle) GlobalFree16( pModule->nrname_handle );
GlobalFree16( hModule );
_lclose16( hFile );
return (HMODULE16)11; /* invalid exe */
}
}
else pModule->dlls_to_init = 0;
NE_RegisterModule( pModule );
SNOOP16_RegisterDLL(pModule,ofs.szPathName);
_lclose16( hFile );
SNOOP16_RegisterDLL(pModule,path);
return hModule;
}
@ -896,8 +856,15 @@ static HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL lib_only )
NE_MODULE *pModule;
HMODULE16 hModule;
HINSTANCE16 hInstance;
HFILE16 hFile;
OFSTRUCT ofs;
hModule = NE_LoadExeHeader( name );
/* Open file */
if ((hFile = OpenFile16( name, &ofs, OF_READ )) == HFILE_ERROR16)
return (HMODULE16)2; /* File not found */
hModule = NE_LoadExeHeader( DosFileHandleToWin32Handle(hFile), ofs.szPathName );
_lclose16( hFile );
if (hModule < 32) return hModule;
pModule = NE_GetPtr( hModule );
@ -1004,23 +971,85 @@ static HINSTANCE16 MODULE_LoadModule16( LPCSTR libname, BOOL implicit, BOOL lib_
}
/**********************************************************************
* NE_CreateThread
*
* Create the thread for a 16-bit module.
*/
static HINSTANCE16 NE_CreateThread( NE_MODULE *pModule, WORD cmdShow, LPCSTR cmdline )
{
TEB *teb = NULL;
HANDLE hThread = 0;
int socket = -1;
HTASK hTask;
TDB *pTask;
HINSTANCE16 instance = 0;
SERVER_START_REQ
{
struct new_thread_request *req = server_alloc_req( sizeof(*req), 0 );
req->suspend = 0;
req->inherit = 0;
if (!server_call( REQ_NEW_THREAD ))
{
hThread = req->handle;
socket = wine_server_recv_fd( hThread, 0 );
}
}
SERVER_END_REQ;
if (!hThread) return 0;
if (!(teb = THREAD_Create( socket, 0, FALSE ))) goto error;
teb->tibflags &= ~TEBF_WIN32;
teb->startup = NE_InitProcess;
/* Create a task for this process */
if (!TASK_Create( pModule, cmdShow, teb, cmdline + 1, *cmdline )) goto error;
hTask = teb->htask16;
if (SYSDEPS_SpawnThread( teb ) == -1) goto error;
/* Post event to start the task */
PostEvent16( hTask );
/* Wait until we get the instance handle */
do
{
DirectedYield16( hTask );
if (!IsTask16( hTask )) /* thread has died */
{
DWORD exit_code;
WaitForSingleObject( hThread, INFINITE );
GetExitCodeThread( hThread, &exit_code );
CloseHandle( hThread );
return exit_code;
}
if (!(pTask = (TDB *)GlobalLock16( hTask ))) break;
instance = pTask->hInstance;
GlobalUnlock16( hTask );
} while (!instance);
return instance;
error:
/* FIXME: free TEB and task */
close( socket );
CloseHandle( hThread );
return 0; /* FIXME */
}
/**********************************************************************
* LoadModule16 (KERNEL.45)
*/
HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
{
TEB *teb = NULL;
BOOL lib_only = !paramBlock || (paramBlock == (LPVOID)-1);
LOADPARAMS16 *params;
HINSTANCE16 instance = 0;
HMODULE16 hModule;
NE_MODULE *pModule;
HTASK hTask;
TDB *pTask;
LPSTR cmdline;
WORD cmdShow;
HANDLE hThread = 0;
int socket = -1;
/* Load module */
@ -1059,65 +1088,40 @@ HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
* in the meantime), or else to a stub module which contains only header
* information.
*/
/* Create the main thread */
SERVER_START_REQ
{
struct new_thread_request *req = server_alloc_req( sizeof(*req), 0 );
req->suspend = 0;
req->inherit = 0;
if (!server_call( REQ_NEW_THREAD ))
{
hThread = req->handle;
socket = wine_server_recv_fd( hThread, 0 );
}
}
SERVER_END_REQ;
if (!hThread) return 0;
if (!(teb = THREAD_Create( socket, 0, FALSE ))) goto error;
teb->tibflags &= ~TEBF_WIN32;
teb->startup = NE_InitProcess;
/* Create a task for this process */
params = (LOADPARAMS16 *)paramBlock;
cmdShow = ((WORD *)MapSL(params->showCmd))[1];
cmdline = MapSL( params->cmdLine );
if (!TASK_Create( pModule, cmdShow, teb, cmdline + 1, *cmdline )) goto error;
hTask = teb->htask16;
if (SYSDEPS_SpawnThread( teb ) == -1) goto error;
/* Post event to start the task */
PostEvent16( hTask );
/* Wait until we get the instance handle */
do
{
DirectedYield16( hTask );
if (!IsTask16( hTask )) /* thread has died */
{
DWORD exit_code;
WaitForSingleObject( hThread, INFINITE );
GetExitCodeThread( hThread, &exit_code );
CloseHandle( hThread );
return exit_code;
return NE_CreateThread( pModule, cmdShow, cmdline );
}
if (!(pTask = (TDB *)GlobalLock16( hTask ))) break;
instance = pTask->hInstance;
GlobalUnlock16( hTask );
} while (!instance);
return instance;
error:
/* FIXME: free TEB and task */
close( socket );
CloseHandle( hThread );
return 0; /* FIXME */
/**********************************************************************
* NE_StartMain
*
* Start the main NE task.
*/
HINSTANCE16 NE_StartMain( LPCSTR name, HANDLE file )
{
STARTUPINFOA info;
HMODULE16 hModule;
NE_MODULE *pModule;
LPSTR cmdline = GetCommandLineA();
if ((hModule = NE_LoadExeHeader( file, name )) < 32) return hModule;
if (!(pModule = NE_GetPtr( hModule ))) return (HINSTANCE16)11;
if (pModule->flags & NE_FFLAGS_LIBMODULE)
{
MESSAGE( "%s is not a valid Win16 executable\n", name );
ExitProcess( ERROR_BAD_EXE_FORMAT );
}
while (*cmdline && *cmdline != ' ') cmdline++;
if (*cmdline) cmdline++;
GetStartupInfoA( &info );
if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = 1;
return NE_CreateThread( pModule, info.wShowWindow, cmdline );
}

View File

@ -14,7 +14,12 @@
#include "dosexe.h"
#include "debugtools.h"
extern void PROCESS_InitWine( int argc, char *argv[] ) WINE_NORETURN;
static char main_exe_name[MAX_PATH];
static HANDLE main_exe_file;
extern void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name,
HANDLE *win16_exe_file ) WINE_NORETURN;
extern HINSTANCE16 NE_StartMain( LPCSTR name, HANDLE file );
/***********************************************************************
* Main loop of initial task
@ -31,12 +36,12 @@ int WINAPI wine_initial_task( HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, INT
}
THUNK_InitCallout();
if ((instance = WinExec16( GetCommandLineA(), show )) < 32)
if ((instance = NE_StartMain( main_exe_name, main_exe_file )) < 32)
{
if (instance == 11) /* try DOS format */
{
if (DPMI_LoadDosSystem())
Dosvm.LoadDosExe( GetCommandLineA() );
Dosvm.LoadDosExe( main_exe_name, main_exe_file );
/* if we get back here it failed */
instance = GetLastError();
}
@ -50,6 +55,7 @@ int WINAPI wine_initial_task( HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, INT
}
ExitProcess(instance);
}
CloseHandle( main_exe_file ); /* avoid file sharing problems */
/* Start message loop for desktop window */
@ -68,6 +74,6 @@ int WINAPI wine_initial_task( HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, INT
*/
int main( int argc, char *argv[] )
{
PROCESS_InitWine( argc, argv );
PROCESS_InitWine( argc, argv, main_exe_name, &main_exe_file );
return 1; /* not reached */
}

View File

@ -437,7 +437,7 @@ void *open_winelib_app( char *argv[] )
*
* Wine initialisation: load and start the main exe file.
*/
void PROCESS_InitWine( int argc, char *argv[] )
void PROCESS_InitWine( int argc, char *argv[], LPSTR win16_exe_name, HANDLE *win16_exe_file )
{
DWORD stack_size = 0;
@ -483,8 +483,9 @@ void PROCESS_InitWine( int argc, char *argv[] )
/* it must be 16-bit or DOS format */
NtCurrentTeb()->tibflags &= ~TEBF_WIN32;
current_process.flags |= PDB32_WIN16_PROC;
strcpy( win16_exe_name, main_exe_name );
main_exe_name[0] = 0;
CloseHandle( main_exe_file );
*win16_exe_file = main_exe_file;
main_exe_file = 0;
_EnterWin16Lock();