mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-05 18:39:07 +00:00
Process creation sequence reorganized:
- Removed instance data segment for all but NE modules. - Check binary type in CreateProcess before loading module. - Unix process creation moved from WinExec to CreateProcess. - Bugfix: fill in thdb->teb.htask16 member correctly.
This commit is contained in:
parent
38d9ce811d
commit
6e0d38603e
|
@ -163,8 +163,10 @@ extern FARPROC16 NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal );
|
|||
extern FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop );
|
||||
extern BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset );
|
||||
extern HANDLE NE_OpenFile( NE_MODULE *pModule );
|
||||
extern HINSTANCE16 NE_LoadModule( LPCSTR name, HINSTANCE16 *hPrevInstance,
|
||||
BOOL implicit, BOOL lib_only );
|
||||
extern HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL implicit );
|
||||
extern BOOL NE_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmd_line,
|
||||
LPCSTR env, BOOL inherit, LPSTARTUPINFOA startup,
|
||||
LPPROCESS_INFORMATION info );
|
||||
|
||||
/* loader/ne/resource.c */
|
||||
extern HGLOBAL16 WINAPI NE_DefResourceHandler(HGLOBAL16,HMODULE16,HRSRC16);
|
||||
|
|
|
@ -146,9 +146,9 @@ typedef struct _THHOOK
|
|||
extern THHOOK *pThhook;
|
||||
extern void (*TASK_AddTaskEntryBreakpoint)( HTASK16 hTask );
|
||||
|
||||
extern HTASK16 TASK_Create( struct _THDB *thdb, struct _NE_MODULE *pModule,
|
||||
HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
|
||||
UINT16 cmdShow );
|
||||
extern BOOL TASK_Create( struct _THDB *thdb, struct _NE_MODULE *pModule,
|
||||
HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
|
||||
UINT16 cmdShow );
|
||||
extern void TASK_StartTask( HTASK16 hTask );
|
||||
extern void TASK_KillCurrentTask( INT16 exitCode );
|
||||
extern HTASK16 TASK_GetNextTask( HTASK16 hTask );
|
||||
|
|
654
loader/module.c
654
loader/module.c
|
@ -12,6 +12,7 @@
|
|||
#include <unistd.h>
|
||||
#include "wine/winuser16.h"
|
||||
#include "wine/winbase16.h"
|
||||
#include "windef.h"
|
||||
#include "winerror.h"
|
||||
#include "class.h"
|
||||
#include "file.h"
|
||||
|
@ -29,8 +30,6 @@
|
|||
#include "debug.h"
|
||||
#include "callback.h"
|
||||
|
||||
extern BOOL THREAD_InitDone;
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
* MODULE32_LookupHMODULE
|
||||
|
@ -208,11 +207,11 @@ HMODULE MODULE_CreateDummyModule( const OFSTRUCT *ofs, LPCSTR modName )
|
|||
pModule->count = 1;
|
||||
pModule->next = 0;
|
||||
pModule->flags = 0;
|
||||
pModule->dgroup = 1;
|
||||
pModule->dgroup = 0;
|
||||
pModule->ss = 1;
|
||||
pModule->cs = 2;
|
||||
pModule->heap_size = 0xe000;
|
||||
pModule->stack_size = 0x1000;
|
||||
pModule->heap_size = 0;
|
||||
pModule->stack_size = 0;
|
||||
pModule->seg_count = 2;
|
||||
pModule->modref_count = 0;
|
||||
pModule->nrname_size = 0;
|
||||
|
@ -226,7 +225,7 @@ HMODULE MODULE_CreateDummyModule( const OFSTRUCT *ofs, LPCSTR modName )
|
|||
((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
|
||||
|
||||
pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size);
|
||||
pModule->seg_table = pModule->dgroup_entry = (int)pSegment - (int)pModule;
|
||||
pModule->seg_table = (int)pSegment - (int)pModule;
|
||||
/* Data segment */
|
||||
pSegment->size = 0;
|
||||
pSegment->flags = NE_SEGFLAGS_DATA;
|
||||
|
@ -402,110 +401,316 @@ HMODULE MODULE_FindModule(
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* NE_CreateProcess
|
||||
/***********************************************************************
|
||||
* MODULE_GetBinaryType
|
||||
*
|
||||
* The GetBinaryType function determines whether a file is executable
|
||||
* or not and if it is it returns what type of executable it is.
|
||||
* The type of executable is a property that determines in which
|
||||
* subsystem an executable file runs under.
|
||||
*
|
||||
* Binary types returned:
|
||||
* SCS_32BIT_BINARY: A Win32 based application
|
||||
* SCS_DOS_BINARY: An MS-Dos based application
|
||||
* SCS_WOW_BINARY: A Win16 based application
|
||||
* SCS_PIF_BINARY: A PIF file that executes an MS-Dos based app
|
||||
* SCS_POSIX_BINARY: A POSIX based application ( Not implemented )
|
||||
* SCS_OS216_BINARY: A 16bit OS/2 based application ( Not implemented )
|
||||
*
|
||||
* Returns TRUE if the file is an executable in which case
|
||||
* the value pointed by lpBinaryType is set.
|
||||
* Returns FALSE if the file is not an executable or if the function fails.
|
||||
*
|
||||
* To do so it opens the file and reads in the header information
|
||||
* if the extended header information is not presend it will
|
||||
* assume that that the file is a DOS executable.
|
||||
* If the extended header information is present it will
|
||||
* determine if the file is an 16 or 32 bit Windows executable
|
||||
* by check the flags in the header.
|
||||
*
|
||||
* Note that .COM and .PIF files are only recognized by their
|
||||
* file name extension; but Windows does it the same way ...
|
||||
*/
|
||||
static HINSTANCE16 NE_CreateProcess( LPCSTR name, LPCSTR cmd_line, LPCSTR env,
|
||||
BOOL inherit, LPSTARTUPINFOA startup,
|
||||
LPPROCESS_INFORMATION info )
|
||||
static BOOL MODULE_GetBinaryType( HFILE hfile, OFSTRUCT *ofs,
|
||||
LPDWORD lpBinaryType )
|
||||
{
|
||||
HINSTANCE16 hInstance, hPrevInstance;
|
||||
NE_MODULE *pModule;
|
||||
IMAGE_DOS_HEADER mz_header;
|
||||
char magic[4], *ptr;
|
||||
|
||||
/* Load module */
|
||||
|
||||
hInstance = NE_LoadModule( name, &hPrevInstance, TRUE, FALSE );
|
||||
if (hInstance < 32) return hInstance;
|
||||
|
||||
if ( !(pModule = NE_GetPtr(hInstance))
|
||||
|| (pModule->flags & NE_FFLAGS_LIBMODULE))
|
||||
/* Seek to the start of the file and read the DOS header information.
|
||||
*/
|
||||
if ( _llseek( hfile, 0, SEEK_SET ) >= 0 &&
|
||||
_lread( hfile, &mz_header, sizeof(mz_header) ) == sizeof(mz_header) )
|
||||
{
|
||||
/* FIXME: cleanup */
|
||||
return 11;
|
||||
/* Now that we have the header check the e_magic field
|
||||
* to see if this is a dos image.
|
||||
*/
|
||||
if ( mz_header.e_magic == IMAGE_DOS_SIGNATURE )
|
||||
{
|
||||
BOOL lfanewValid = FALSE;
|
||||
/* We do have a DOS image so we will now try to seek into
|
||||
* the file by the amount indicated by the field
|
||||
* "Offset to extended header" and read in the
|
||||
* "magic" field information at that location.
|
||||
* This will tell us if there is more header information
|
||||
* to read or not.
|
||||
*/
|
||||
/* But before we do we will make sure that header
|
||||
* structure encompasses the "Offset to extended header"
|
||||
* field.
|
||||
*/
|
||||
if ( (mz_header.e_cparhdr<<4) >= sizeof(IMAGE_DOS_HEADER) )
|
||||
if ( ( mz_header.e_crlc == 0 && mz_header.e_lfarlc == 0 ) ||
|
||||
( mz_header.e_lfarlc >= sizeof(IMAGE_DOS_HEADER) ) )
|
||||
if ( mz_header.e_lfanew >= sizeof(IMAGE_DOS_HEADER) &&
|
||||
_llseek( hfile, mz_header.e_lfanew, SEEK_SET ) >= 0 &&
|
||||
_lread( hfile, magic, sizeof(magic) ) == sizeof(magic) )
|
||||
lfanewValid = TRUE;
|
||||
|
||||
if ( !lfanewValid )
|
||||
{
|
||||
/* If we cannot read this "extended header" we will
|
||||
* assume that we have a simple DOS executable.
|
||||
*/
|
||||
*lpBinaryType = SCS_DOS_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reading the magic field succeeded so
|
||||
* we will try to determine what type it is.
|
||||
*/
|
||||
if ( *(DWORD*)magic == IMAGE_NT_SIGNATURE )
|
||||
{
|
||||
/* This is an NT signature.
|
||||
*/
|
||||
*lpBinaryType = SCS_32BIT_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
else if ( *(WORD*)magic == IMAGE_OS2_SIGNATURE )
|
||||
{
|
||||
/* The IMAGE_OS2_SIGNATURE indicates that the
|
||||
* "extended header is a Windows executable (NE)
|
||||
* header. This is a bit misleading, but it is
|
||||
* documented in the SDK. ( for more details see
|
||||
* the neexe.h file )
|
||||
*/
|
||||
*lpBinaryType = SCS_WOW_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unknown extended header, so abort.
|
||||
*/
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create a task for this instance */
|
||||
/* If we get here, we don't even have a correct MZ header.
|
||||
* Try to check the file extension for known types ...
|
||||
*/
|
||||
ptr = strrchr( ofs->szPathName, '.' );
|
||||
if ( ptr && !strchr( ptr, '\\' ) && !strchr( ptr, '/' ) )
|
||||
{
|
||||
if ( !lstrcmpiA( ptr, ".COM" ) )
|
||||
{
|
||||
*lpBinaryType = SCS_DOS_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
pModule->flags |= NE_FFLAGS_GUI; /* FIXME: is this necessary? */
|
||||
if ( !lstrcmpiA( ptr, ".PIF" ) )
|
||||
{
|
||||
*lpBinaryType = SCS_PIF_BINARY;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
PROCESS_Create( pModule, cmd_line, env, hInstance,
|
||||
hPrevInstance, inherit, startup, info );
|
||||
|
||||
return hInstance;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* LoadModule16 (KERNEL.45)
|
||||
/***********************************************************************
|
||||
* GetBinaryTypeA [KERNEL32.280]
|
||||
*/
|
||||
HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock )
|
||||
BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
|
||||
{
|
||||
LOADPARAMS16 *params;
|
||||
LPSTR cmd_line, new_cmd_line;
|
||||
LPCVOID env = NULL;
|
||||
STARTUPINFOA startup;
|
||||
PROCESS_INFORMATION info;
|
||||
HINSTANCE16 hInstance, hPrevInstance;
|
||||
NE_MODULE *pModule;
|
||||
PDB *pdb;
|
||||
BOOL ret = FALSE;
|
||||
HFILE hfile;
|
||||
OFSTRUCT ofs;
|
||||
|
||||
/* Load module */
|
||||
TRACE( win32, "%s\n", lpApplicationName );
|
||||
|
||||
if (!paramBlock || (paramBlock == (LPVOID)-1))
|
||||
return LoadLibrary16( name );
|
||||
/* Sanity check.
|
||||
*/
|
||||
if ( lpApplicationName == NULL || lpBinaryType == NULL )
|
||||
return FALSE;
|
||||
|
||||
hInstance = NE_LoadModule( name, &hPrevInstance, FALSE, FALSE );
|
||||
if ( hInstance < 32 || !(pModule = NE_GetPtr(hInstance))
|
||||
|| (pModule->flags & NE_FFLAGS_LIBMODULE))
|
||||
return hInstance;
|
||||
/* Open the file indicated by lpApplicationName for reading.
|
||||
*/
|
||||
if ( (hfile = OpenFile( lpApplicationName, &ofs, OF_READ )) == HFILE_ERROR )
|
||||
return FALSE;
|
||||
|
||||
/* Create a task for this instance */
|
||||
/* Check binary type
|
||||
*/
|
||||
ret = MODULE_GetBinaryType( hfile, &ofs, lpBinaryType );
|
||||
|
||||
pModule->flags |= NE_FFLAGS_GUI; /* FIXME: is this necessary? */
|
||||
/* Close the file.
|
||||
*/
|
||||
CloseHandle( hfile );
|
||||
|
||||
params = (LOADPARAMS16 *)paramBlock;
|
||||
cmd_line = (LPSTR)PTR_SEG_TO_LIN( params->cmdLine );
|
||||
if (!cmd_line) cmd_line = "";
|
||||
else if (*cmd_line) cmd_line++; /* skip the length byte */
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!(new_cmd_line = HeapAlloc( GetProcessHeap(), 0,
|
||||
strlen(cmd_line)+strlen(name)+2 )))
|
||||
return 0;
|
||||
strcpy( new_cmd_line, name );
|
||||
strcat( new_cmd_line, " " );
|
||||
strcat( new_cmd_line, cmd_line );
|
||||
/***********************************************************************
|
||||
* GetBinaryTypeW [KERNEL32.281]
|
||||
*/
|
||||
BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
LPSTR strNew = NULL;
|
||||
|
||||
if (params->hEnvironment) env = GlobalLock16( params->hEnvironment );
|
||||
TRACE( win32, "%s\n", debugstr_w(lpApplicationName) );
|
||||
|
||||
memset( &info, '\0', sizeof(info) );
|
||||
memset( &startup, '\0', sizeof(startup) );
|
||||
startup.cb = sizeof(startup);
|
||||
if (params->showCmd)
|
||||
/* Sanity check.
|
||||
*/
|
||||
if ( lpApplicationName == NULL || lpBinaryType == NULL )
|
||||
return FALSE;
|
||||
|
||||
/* Convert the wide string to a ascii string.
|
||||
*/
|
||||
strNew = HEAP_strdupWtoA( GetProcessHeap(), 0, lpApplicationName );
|
||||
|
||||
if ( strNew != NULL )
|
||||
{
|
||||
startup.dwFlags = STARTF_USESHOWWINDOW;
|
||||
startup.wShowWindow = ((UINT16 *)PTR_SEG_TO_LIN(params->showCmd))[1];
|
||||
ret = GetBinaryTypeA( strNew, lpBinaryType );
|
||||
|
||||
/* Free the allocated string.
|
||||
*/
|
||||
HeapFree( GetProcessHeap(), 0, strNew );
|
||||
}
|
||||
|
||||
pdb = PROCESS_Create( pModule, new_cmd_line, env,
|
||||
hInstance, hPrevInstance, TRUE, &startup, &info );
|
||||
|
||||
CloseHandle( info.hThread );
|
||||
CloseHandle( info.hProcess );
|
||||
|
||||
if (params->hEnvironment) GlobalUnlock16( params->hEnvironment );
|
||||
HeapFree( GetProcessHeap(), 0, new_cmd_line );
|
||||
|
||||
/* Start task */
|
||||
|
||||
if (pdb) TASK_StartTask( pdb->task );
|
||||
|
||||
return hInstance;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* LoadModule32 (KERNEL32.499)
|
||||
* MODULE_CreateUnixProcess
|
||||
*/
|
||||
static BOOL MODULE_CreateUnixProcess( LPCSTR filename, LPCSTR lpCmdLine,
|
||||
LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInfo,
|
||||
BOOL useWine )
|
||||
{
|
||||
DOS_FULL_NAME full_name;
|
||||
const char *unixfilename = filename;
|
||||
const char *argv[256], **argptr;
|
||||
BOOL iconic = FALSE;
|
||||
|
||||
/* Get Unix file name and iconic flag */
|
||||
|
||||
if ( lpStartupInfo->dwFlags & STARTF_USESHOWWINDOW )
|
||||
if ( lpStartupInfo->wShowWindow == SW_SHOWMINIMIZED
|
||||
|| lpStartupInfo->wShowWindow == SW_SHOWMINNOACTIVE )
|
||||
iconic = TRUE;
|
||||
|
||||
if ( strchr(filename, '/')
|
||||
|| strchr(filename, ':')
|
||||
|| strchr(filename, '\\') )
|
||||
{
|
||||
if ( DOSFS_GetFullName( filename, TRUE, &full_name ) )
|
||||
unixfilename = full_name.long_name;
|
||||
}
|
||||
|
||||
if ( !unixfilename )
|
||||
{
|
||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Build argument list */
|
||||
|
||||
argptr = argv;
|
||||
if ( !useWine )
|
||||
{
|
||||
char *p = strdup(lpCmdLine);
|
||||
*argptr++ = unixfilename;
|
||||
if (iconic) *argptr++ = "-iconic";
|
||||
while (1)
|
||||
{
|
||||
while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
|
||||
if (!*p) break;
|
||||
*argptr++ = p;
|
||||
while (*p && *p != ' ' && *p != '\t') p++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*argptr++ = "wine";
|
||||
if (iconic) *argptr++ = "-iconic";
|
||||
*argptr++ = lpCmdLine;
|
||||
}
|
||||
*argptr++ = 0;
|
||||
|
||||
/* Fork and execute */
|
||||
|
||||
if ( !fork() )
|
||||
{
|
||||
/* Note: don't use Wine routines here, as this process
|
||||
has not been correctly initialized! */
|
||||
|
||||
execvp( argv[0], (char**)argv );
|
||||
|
||||
/* Failed ! */
|
||||
if ( useWine )
|
||||
fprintf( stderr, "CreateProcess: can't exec 'wine %s'\n",
|
||||
lpCmdLine );
|
||||
exit( 1 );
|
||||
}
|
||||
|
||||
/* Fake success return value */
|
||||
|
||||
memset( lpProcessInfo, '\0', sizeof( *lpProcessInfo ) );
|
||||
lpProcessInfo->hProcess = INVALID_HANDLE_VALUE;
|
||||
lpProcessInfo->hThread = INVALID_HANDLE_VALUE;
|
||||
|
||||
SetLastError( ERROR_SUCCESS );
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WinExec16 (KERNEL.166)
|
||||
*/
|
||||
HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
|
||||
{
|
||||
return WinExec( lpCmdLine, nCmdShow );
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* WinExec (KERNEL32.566)
|
||||
*/
|
||||
HINSTANCE WINAPI WinExec( LPCSTR lpCmdLine, UINT nCmdShow )
|
||||
{
|
||||
LOADPARAMS params;
|
||||
UINT16 paramCmdShow[2];
|
||||
|
||||
if (!lpCmdLine)
|
||||
return 2; /* File not found */
|
||||
|
||||
/* Set up LOADPARAMS buffer for LoadModule */
|
||||
|
||||
memset( ¶ms, '\0', sizeof(params) );
|
||||
params.lpCmdLine = (LPSTR)lpCmdLine;
|
||||
params.lpCmdShow = paramCmdShow;
|
||||
params.lpCmdShow[0] = 2;
|
||||
params.lpCmdShow[1] = nCmdShow;
|
||||
|
||||
/* Now load the executable file */
|
||||
|
||||
return LoadModule( NULL, ¶ms );
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* LoadModule (KERNEL32.499)
|
||||
*/
|
||||
HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
|
||||
{
|
||||
|
@ -521,10 +726,16 @@ HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
|
|||
startup.dwFlags = STARTF_USESHOWWINDOW;
|
||||
startup.wShowWindow = params->lpCmdShow? params->lpCmdShow[1] : 0;
|
||||
|
||||
if (!CreateProcessA( name, params->lpCmdLine,
|
||||
NULL, NULL, FALSE, 0, params->lpEnvAddress,
|
||||
NULL, &startup, &info ))
|
||||
return GetLastError(); /* guaranteed to be < 32 */
|
||||
if ( !CreateProcessA( name, params->lpCmdLine,
|
||||
NULL, NULL, FALSE, 0, params->lpEnvAddress,
|
||||
NULL, &startup, &info ) )
|
||||
{
|
||||
hInstance = GetLastError();
|
||||
if ( hInstance < 32 ) return hInstance;
|
||||
|
||||
FIXME( module, "Strange error set by CreateProcess: %d\n", hInstance );
|
||||
return 11;
|
||||
}
|
||||
|
||||
/* Get 16-bit hInstance/hTask from process */
|
||||
pdb = PROCESS_IdToPDB( info.dwProcessId );
|
||||
|
@ -539,19 +750,21 @@ HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
|
|||
}
|
||||
|
||||
/**********************************************************************
|
||||
* CreateProcess32A (KERNEL32.171)
|
||||
* CreateProcessA (KERNEL32.171)
|
||||
*/
|
||||
BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles, DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
|
||||
LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInfo )
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles, DWORD dwCreationFlags,
|
||||
LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
|
||||
LPSTARTUPINFOA lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInfo )
|
||||
{
|
||||
HINSTANCE16 hInstance;
|
||||
BOOL retv = FALSE;
|
||||
HFILE hFile;
|
||||
OFSTRUCT ofs;
|
||||
DWORD type;
|
||||
LPCSTR cmdline;
|
||||
PDB *pdb;
|
||||
char name[256];
|
||||
|
||||
/* Get name and command line */
|
||||
|
@ -667,35 +880,91 @@ BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
|
|||
FIXME(module, "(%s,...): STARTF_USEHOTKEY ignored\n", name);
|
||||
|
||||
|
||||
/* Try NE module */
|
||||
hInstance = NE_CreateProcess( name, cmdline, lpEnvironment, bInheritHandles,
|
||||
lpStartupInfo, lpProcessInfo );
|
||||
/* When in WineLib, always fork new Unix process */
|
||||
|
||||
/* Try PE module */
|
||||
if (hInstance == 21)
|
||||
hInstance = PE_CreateProcess( name, cmdline, lpEnvironment, bInheritHandles,
|
||||
lpStartupInfo, lpProcessInfo );
|
||||
if ( __winelib )
|
||||
return MODULE_CreateUnixProcess( name, cmdline,
|
||||
lpStartupInfo, lpProcessInfo, TRUE );
|
||||
|
||||
/* Try DOS module */
|
||||
if (hInstance == 11)
|
||||
hInstance = MZ_CreateProcess( name, cmdline, lpEnvironment, bInheritHandles,
|
||||
lpStartupInfo, lpProcessInfo );
|
||||
/* Check for special case: second instance of NE module */
|
||||
|
||||
if (hInstance < 32)
|
||||
lstrcpynA( ofs.szPathName, name, sizeof( ofs.szPathName ) );
|
||||
retv = NE_CreateProcess( HFILE_ERROR, &ofs, cmdline, lpEnvironment,
|
||||
bInheritHandles, lpStartupInfo, lpProcessInfo );
|
||||
|
||||
/* Load file and create process */
|
||||
|
||||
if ( !retv )
|
||||
{
|
||||
SetLastError( hInstance );
|
||||
return FALSE;
|
||||
/* Open file and determine executable type */
|
||||
|
||||
if ( (hFile = OpenFile( name, &ofs, OF_READ )) == HFILE_ERROR )
|
||||
{
|
||||
SetLastError( ERROR_FILE_NOT_FOUND );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ( !MODULE_GetBinaryType( hFile, &ofs, &type ) )
|
||||
{
|
||||
CloseHandle( hFile );
|
||||
|
||||
/* FIXME: Try Unix executable only when appropriate! */
|
||||
if ( MODULE_CreateUnixProcess( name, cmdline,
|
||||
lpStartupInfo, lpProcessInfo, FALSE ) )
|
||||
return TRUE;
|
||||
|
||||
SetLastError( ERROR_BAD_FORMAT );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/* Create process */
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case SCS_32BIT_BINARY:
|
||||
retv = PE_CreateProcess( hFile, &ofs, cmdline, lpEnvironment,
|
||||
bInheritHandles, lpStartupInfo, lpProcessInfo );
|
||||
break;
|
||||
|
||||
case SCS_DOS_BINARY:
|
||||
retv = MZ_CreateProcess( hFile, &ofs, cmdline, lpEnvironment,
|
||||
bInheritHandles, lpStartupInfo, lpProcessInfo );
|
||||
break;
|
||||
|
||||
case SCS_WOW_BINARY:
|
||||
retv = NE_CreateProcess( hFile, &ofs, cmdline, lpEnvironment,
|
||||
bInheritHandles, lpStartupInfo, lpProcessInfo );
|
||||
break;
|
||||
|
||||
case SCS_PIF_BINARY:
|
||||
case SCS_POSIX_BINARY:
|
||||
case SCS_OS216_BINARY:
|
||||
FIXME( module, "Unsupported executable type: %ld\n", type );
|
||||
/* fall through */
|
||||
|
||||
default:
|
||||
SetLastError( ERROR_BAD_FORMAT );
|
||||
retv = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
CloseHandle( hFile );
|
||||
}
|
||||
|
||||
/* Get hTask from process and start the task */
|
||||
pdb = PROCESS_IdToPDB( lpProcessInfo->dwProcessId );
|
||||
if (pdb) TASK_StartTask( pdb->task );
|
||||
|
||||
return TRUE;
|
||||
if ( retv )
|
||||
{
|
||||
PDB *pdb = PROCESS_IdToPDB( lpProcessInfo->dwProcessId );
|
||||
if (pdb) TASK_StartTask( pdb->task );
|
||||
}
|
||||
|
||||
return retv;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* CreateProcess32W (KERNEL32.172)
|
||||
* CreateProcessW (KERNEL32.172)
|
||||
* NOTES
|
||||
* lpReserved is not converted
|
||||
*/
|
||||
|
@ -897,163 +1166,6 @@ void WINAPI PrivateFreeLibrary(HINSTANCE handle)
|
|||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WinExec16 (KERNEL.166)
|
||||
*/
|
||||
HINSTANCE16 WINAPI WinExec16( LPCSTR lpCmdLine, UINT16 nCmdShow )
|
||||
{
|
||||
return WinExec( lpCmdLine, nCmdShow );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WinExec32 (KERNEL32.566)
|
||||
*/
|
||||
HINSTANCE WINAPI WinExec( LPCSTR lpCmdLine, UINT nCmdShow )
|
||||
{
|
||||
HINSTANCE handle = 2;
|
||||
char *p, filename[256];
|
||||
int spacelimit = 0, exhausted = 0;
|
||||
LOADPARAMS params;
|
||||
UINT16 paramCmdShow[2];
|
||||
|
||||
if (!lpCmdLine)
|
||||
return 2; /* File not found */
|
||||
|
||||
/* Set up LOADPARAMS32 buffer for LoadModule32 */
|
||||
|
||||
memset( ¶ms, '\0', sizeof(params) );
|
||||
params.lpCmdLine = (LPSTR)lpCmdLine;
|
||||
params.lpCmdShow = paramCmdShow;
|
||||
params.lpCmdShow[0] = 2;
|
||||
params.lpCmdShow[1] = nCmdShow;
|
||||
|
||||
|
||||
/* Keep trying to load a file by trying different filenames; e.g.,
|
||||
for the cmdline "abcd efg hij", try "abcd" with args "efg hij",
|
||||
then "abcd efg" with arg "hij", and finally "abcd efg hij" with
|
||||
no args */
|
||||
|
||||
while(!exhausted && handle == 2) {
|
||||
int spacecount = 0;
|
||||
|
||||
/* Build the filename and command-line */
|
||||
|
||||
lstrcpynA(filename, lpCmdLine,
|
||||
sizeof(filename) - 4 /* for extension */);
|
||||
|
||||
/* Keep grabbing characters until end-of-string, tab, or until the
|
||||
number of spaces is greater than the spacelimit */
|
||||
|
||||
for (p = filename; ; p++) {
|
||||
if(*p == ' ') {
|
||||
++spacecount;
|
||||
if(spacecount > spacelimit) {
|
||||
++spacelimit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(*p == '\0' || *p == '\t') {
|
||||
exhausted = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
*p = '\0';
|
||||
|
||||
/* Now load the executable file */
|
||||
|
||||
if (!__winelib)
|
||||
{
|
||||
handle = LoadModule( filename, ¶ms );
|
||||
if (handle == 2) /* file not found */
|
||||
{
|
||||
/* Check that the original file name did not have a suffix */
|
||||
p = strrchr(filename, '.');
|
||||
/* if there is a '.', check if either \ OR / follow */
|
||||
if (!p || strchr(p, '/') || strchr(p, '\\'))
|
||||
{
|
||||
p = filename + strlen(filename);
|
||||
strcpy( p, ".exe" );
|
||||
handle = LoadModule( filename, ¶ms );
|
||||
*p = '\0'; /* Remove extension */
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
handle = 2; /* file not found */
|
||||
|
||||
if (handle < 32)
|
||||
{
|
||||
/* Try to start it as a unix program */
|
||||
if (!fork())
|
||||
{
|
||||
/* Child process */
|
||||
DOS_FULL_NAME full_name;
|
||||
const char *unixfilename = NULL;
|
||||
const char *argv[256], **argptr;
|
||||
int iconic = (nCmdShow == SW_SHOWMINIMIZED ||
|
||||
nCmdShow == SW_SHOWMINNOACTIVE);
|
||||
|
||||
THREAD_InitDone = FALSE; /* we didn't init this process */
|
||||
/* get unixfilename */
|
||||
if (strchr(filename, '/') ||
|
||||
strchr(filename, ':') ||
|
||||
strchr(filename, '\\'))
|
||||
{
|
||||
if (DOSFS_GetFullName( filename, TRUE, &full_name ))
|
||||
unixfilename = full_name.long_name;
|
||||
}
|
||||
else unixfilename = filename;
|
||||
|
||||
if (unixfilename)
|
||||
{
|
||||
/* build argv */
|
||||
argptr = argv;
|
||||
if (iconic) *argptr++ = "-iconic";
|
||||
*argptr++ = unixfilename;
|
||||
p = strdup(lpCmdLine);
|
||||
while (1)
|
||||
{
|
||||
while (*p && (*p == ' ' || *p == '\t')) *p++ = '\0';
|
||||
if (!*p) break;
|
||||
*argptr++ = p;
|
||||
while (*p && *p != ' ' && *p != '\t') p++;
|
||||
}
|
||||
*argptr++ = 0;
|
||||
|
||||
/* Execute */
|
||||
execvp(argv[0], (char**)argv);
|
||||
}
|
||||
|
||||
/* Failed ! */
|
||||
|
||||
if (__winelib)
|
||||
{
|
||||
/* build argv */
|
||||
argptr = argv;
|
||||
*argptr++ = "wine";
|
||||
if (iconic) *argptr++ = "-iconic";
|
||||
*argptr++ = lpCmdLine;
|
||||
*argptr++ = 0;
|
||||
|
||||
/* Execute */
|
||||
execvp(argv[0] , (char**)argv);
|
||||
|
||||
/* Failed ! */
|
||||
MSG("WinExec: can't exec 'wine %s'\n",
|
||||
lpCmdLine);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
} /* while (!exhausted && handle < 32) */
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* WIN32_GetProcAddress16 (KERNEL32.36)
|
||||
* Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)
|
||||
|
|
|
@ -259,9 +259,6 @@ static void TASK_CallToStart(void)
|
|||
if (PE_HEADER(pModule->module32)->OptionalHeader.Subsystem==IMAGE_SUBSYSTEM_WINDOWS_CUI)
|
||||
AllocConsole();
|
||||
|
||||
if (pModule->heap_size)
|
||||
LocalInit16( pTask->hInstance, 0, pModule->heap_size );
|
||||
|
||||
MODULE_InitializeDLLs( 0, DLL_PROCESS_ATTACH, (LPVOID)-1 );
|
||||
TRACE(relay, "(entryproc=%p)\n", entry );
|
||||
|
||||
|
@ -336,8 +333,8 @@ static void TASK_CallToStart(void)
|
|||
* any real problems with that, since we operated merely on a private
|
||||
* TDB structure that is not yet linked into the task list.
|
||||
*/
|
||||
HTASK16 TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
|
||||
HINSTANCE16 hPrevInstance, UINT16 cmdShow)
|
||||
BOOL TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
|
||||
HINSTANCE16 hPrevInstance, UINT16 cmdShow)
|
||||
{
|
||||
HTASK16 hTask;
|
||||
TDB *pTask, *pInitialTask;
|
||||
|
@ -354,7 +351,7 @@ HTASK16 TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
|
|||
|
||||
hTask = GLOBAL_Alloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(TDB),
|
||||
pModule->self, FALSE, FALSE, FALSE );
|
||||
if (!hTask) return 0;
|
||||
if (!hTask) return FALSE;
|
||||
pTask = (TDB *)GlobalLock16( hTask );
|
||||
|
||||
/* Fill the task structure */
|
||||
|
@ -369,7 +366,7 @@ HTASK16 TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
|
|||
pTask->flags |= TDBF_WINOLDAP;
|
||||
|
||||
pTask->version = pModule->expected_version;
|
||||
pTask->hInstance = hInstance;
|
||||
pTask->hInstance = hInstance? hInstance : pModule->self;
|
||||
pTask->hPrevInstance = hPrevInstance;
|
||||
pTask->hModule = pModule->self;
|
||||
pTask->hParent = GetCurrentTask();
|
||||
|
@ -445,16 +442,23 @@ HTASK16 TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
|
|||
if ( pInitialTask )
|
||||
pTask->userhandler = pInitialTask->userhandler;
|
||||
|
||||
/* If we have a DGROUP/hInstance, use it for 16-bit stack */
|
||||
|
||||
if ( hInstance )
|
||||
{
|
||||
if (!(sp = pModule->sp))
|
||||
sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
|
||||
sp &= ~1; sp -= sizeof(STACK16FRAME);
|
||||
pTask->thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( hInstance, sp );
|
||||
}
|
||||
|
||||
/* Create the 16-bit stack frame */
|
||||
|
||||
if (!(sp = pModule->sp))
|
||||
sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
|
||||
sp &= ~1; sp -= 2*sizeof(STACK16FRAME);
|
||||
pTask->thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( pTask->hInstance, sp );
|
||||
pTask->thdb->cur_stack -= sizeof(STACK16FRAME);
|
||||
frame16 = (STACK16FRAME *)PTR_SEG_TO_LIN( pTask->thdb->cur_stack );
|
||||
frame16->ebp = sp + (int)&((STACK16FRAME *)0)->bp;
|
||||
frame16->ebp = OFFSETOF( pTask->thdb->cur_stack ) + (int)&((STACK16FRAME *)0)->bp;
|
||||
frame16->bp = LOWORD(frame16->ebp);
|
||||
frame16->ds = frame16->es = pTask->hInstance;
|
||||
frame16->ds = frame16->es = hInstance;
|
||||
frame16->fs = 0;
|
||||
frame16->entry_point = 0;
|
||||
frame16->entry_cs = 0;
|
||||
|
@ -474,11 +478,14 @@ HTASK16 TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
|
|||
frame32->retaddr = (DWORD)TASK_CallToStart;
|
||||
/* The remaining fields will be initialized in TASK_Reschedule */
|
||||
|
||||
|
||||
/* Enter task handle into thread and process */
|
||||
|
||||
pTask->thdb->teb.htask16 = pTask->thdb->process->task = hTask;
|
||||
|
||||
TRACE(task, "module='%s' cmdline='%s' task=%04x\n",
|
||||
name, cmd_line, hTask );
|
||||
|
||||
return hTask;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
|
|
@ -420,7 +420,6 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
|
|||
THDB *thdb = NULL;
|
||||
PDB *parent = PROCESS_Current();
|
||||
PDB *pdb = PROCESS_CreatePDB( parent, inherit );
|
||||
TDB *pTask;
|
||||
|
||||
if (!pdb) return NULL;
|
||||
info->hThread = info->hProcess = INVALID_HANDLE_VALUE;
|
||||
|
@ -452,8 +451,9 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
|
|||
size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
|
||||
else
|
||||
size = 0;
|
||||
if (!(thdb = THREAD_Create( pdb, size, FALSE, &server_thandle, &server_phandle,
|
||||
NULL, NULL ))) goto error;
|
||||
if (!(thdb = THREAD_Create( pdb, size, hInstance == 0,
|
||||
&server_thandle, &server_phandle, NULL, NULL )))
|
||||
goto error;
|
||||
if ((info->hThread = HANDLE_Alloc( parent, &thdb->header, THREAD_ALL_ACCESS,
|
||||
FALSE, server_thandle )) == INVALID_HANDLE_VALUE)
|
||||
goto error;
|
||||
|
@ -480,8 +480,8 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
|
|||
if (startup->dwFlags & STARTF_USESHOWWINDOW)
|
||||
cmdShow = startup->wShowWindow;
|
||||
|
||||
pdb->task = TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow);
|
||||
if (!pdb->task) goto error;
|
||||
if ( !TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow) )
|
||||
goto error;
|
||||
|
||||
|
||||
/* Map system DLLs into this process (from initial process) */
|
||||
|
|
|
@ -226,7 +226,7 @@ THDB *THREAD_CreateInitialThread( PDB *pdb )
|
|||
|
||||
/* Now proceed with normal initialization */
|
||||
|
||||
if (!THREAD_InitTHDB( &initial_thdb, 0, FALSE, NULL, NULL )) return NULL;
|
||||
if (!THREAD_InitTHDB( &initial_thdb, 0, TRUE, NULL, NULL )) return NULL;
|
||||
return &initial_thdb;
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,7 @@ THDB *THREAD_Create( PDB *pdb, DWORD stack_size, BOOL alloc_stack16,
|
|||
thdb->header.refcount = 1;
|
||||
thdb->process = pdb;
|
||||
thdb->teb.except = (void *)-1;
|
||||
thdb->teb.htask16 = 0; /* FIXME */
|
||||
thdb->teb.htask16 = pdb->task;
|
||||
thdb->teb.self = &thdb->teb;
|
||||
thdb->teb.flags = (pdb->flags & PDB32_WIN16_PROC)? 0 : TEBF_WIN32;
|
||||
thdb->teb.tls_ptr = thdb->tls_array;
|
||||
|
|
Loading…
Reference in a new issue