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:
Ulrich Weigand 1999-02-28 11:14:32 +00:00 committed by Alexandre Julliard
parent 38d9ce811d
commit 6e0d38603e
6 changed files with 419 additions and 298 deletions

View file

@ -163,8 +163,10 @@ extern FARPROC16 NE_GetEntryPoint( HMODULE16 hModule, WORD ordinal );
extern FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop ); extern FARPROC16 NE_GetEntryPointEx( HMODULE16 hModule, WORD ordinal, BOOL16 snoop );
extern BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset ); extern BOOL16 NE_SetEntryPoint( HMODULE16 hModule, WORD ordinal, WORD offset );
extern HANDLE NE_OpenFile( NE_MODULE *pModule ); extern HANDLE NE_OpenFile( NE_MODULE *pModule );
extern HINSTANCE16 NE_LoadModule( LPCSTR name, HINSTANCE16 *hPrevInstance, extern HINSTANCE16 NE_LoadModule( LPCSTR name, BOOL implicit );
BOOL implicit, BOOL lib_only ); extern BOOL NE_CreateProcess( HFILE hFile, OFSTRUCT *ofs, LPCSTR cmd_line,
LPCSTR env, BOOL inherit, LPSTARTUPINFOA startup,
LPPROCESS_INFORMATION info );
/* loader/ne/resource.c */ /* loader/ne/resource.c */
extern HGLOBAL16 WINAPI NE_DefResourceHandler(HGLOBAL16,HMODULE16,HRSRC16); extern HGLOBAL16 WINAPI NE_DefResourceHandler(HGLOBAL16,HMODULE16,HRSRC16);

View file

@ -146,9 +146,9 @@ typedef struct _THHOOK
extern THHOOK *pThhook; extern THHOOK *pThhook;
extern void (*TASK_AddTaskEntryBreakpoint)( HTASK16 hTask ); extern void (*TASK_AddTaskEntryBreakpoint)( HTASK16 hTask );
extern HTASK16 TASK_Create( struct _THDB *thdb, struct _NE_MODULE *pModule, extern BOOL TASK_Create( struct _THDB *thdb, struct _NE_MODULE *pModule,
HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance, HINSTANCE16 hInstance, HINSTANCE16 hPrevInstance,
UINT16 cmdShow ); UINT16 cmdShow );
extern void TASK_StartTask( HTASK16 hTask ); extern void TASK_StartTask( HTASK16 hTask );
extern void TASK_KillCurrentTask( INT16 exitCode ); extern void TASK_KillCurrentTask( INT16 exitCode );
extern HTASK16 TASK_GetNextTask( HTASK16 hTask ); extern HTASK16 TASK_GetNextTask( HTASK16 hTask );

View file

@ -12,6 +12,7 @@
#include <unistd.h> #include <unistd.h>
#include "wine/winuser16.h" #include "wine/winuser16.h"
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "windef.h"
#include "winerror.h" #include "winerror.h"
#include "class.h" #include "class.h"
#include "file.h" #include "file.h"
@ -29,8 +30,6 @@
#include "debug.h" #include "debug.h"
#include "callback.h" #include "callback.h"
extern BOOL THREAD_InitDone;
/************************************************************************* /*************************************************************************
* MODULE32_LookupHMODULE * MODULE32_LookupHMODULE
@ -208,11 +207,11 @@ HMODULE MODULE_CreateDummyModule( const OFSTRUCT *ofs, LPCSTR modName )
pModule->count = 1; pModule->count = 1;
pModule->next = 0; pModule->next = 0;
pModule->flags = 0; pModule->flags = 0;
pModule->dgroup = 1; pModule->dgroup = 0;
pModule->ss = 1; pModule->ss = 1;
pModule->cs = 2; pModule->cs = 2;
pModule->heap_size = 0xe000; pModule->heap_size = 0;
pModule->stack_size = 0x1000; pModule->stack_size = 0;
pModule->seg_count = 2; pModule->seg_count = 2;
pModule->modref_count = 0; pModule->modref_count = 0;
pModule->nrname_size = 0; pModule->nrname_size = 0;
@ -226,7 +225,7 @@ HMODULE MODULE_CreateDummyModule( const OFSTRUCT *ofs, LPCSTR modName )
((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1; ((OFSTRUCT *)(pModule+1))->cBytes = of_size - 1;
pSegment = (SEGTABLEENTRY*)((char*)(pModule + 1) + of_size); 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 */ /* Data segment */
pSegment->size = 0; pSegment->size = 0;
pSegment->flags = NE_SEGFLAGS_DATA; pSegment->flags = NE_SEGFLAGS_DATA;
@ -402,110 +401,316 @@ HMODULE MODULE_FindModule(
return 0; return 0;
} }
/***********************************************************************
* MODULE_GetBinaryType
/********************************************************************** *
* NE_CreateProcess * 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, static BOOL MODULE_GetBinaryType( HFILE hfile, OFSTRUCT *ofs,
BOOL inherit, LPSTARTUPINFOA startup, LPDWORD lpBinaryType )
LPPROCESS_INFORMATION info )
{ {
HINSTANCE16 hInstance, hPrevInstance; IMAGE_DOS_HEADER mz_header;
NE_MODULE *pModule; char magic[4], *ptr;
/* Load module */ /* Seek to the start of the file and read the DOS header information.
*/
hInstance = NE_LoadModule( name, &hPrevInstance, TRUE, FALSE ); if ( _llseek( hfile, 0, SEEK_SET ) >= 0 &&
if (hInstance < 32) return hInstance; _lread( hfile, &mz_header, sizeof(mz_header) ) == sizeof(mz_header) )
if ( !(pModule = NE_GetPtr(hInstance))
|| (pModule->flags & NE_FFLAGS_LIBMODULE))
{ {
/* FIXME: cleanup */ /* Now that we have the header check the e_magic field
return 11; * 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, return FALSE;
hPrevInstance, inherit, startup, info );
return hInstance;
} }
/***********************************************************************
/********************************************************************** * GetBinaryTypeA [KERNEL32.280]
* LoadModule16 (KERNEL.45)
*/ */
HINSTANCE16 WINAPI LoadModule16( LPCSTR name, LPVOID paramBlock ) BOOL WINAPI GetBinaryTypeA( LPCSTR lpApplicationName, LPDWORD lpBinaryType )
{ {
LOADPARAMS16 *params; BOOL ret = FALSE;
LPSTR cmd_line, new_cmd_line; HFILE hfile;
LPCVOID env = NULL; OFSTRUCT ofs;
STARTUPINFOA startup;
PROCESS_INFORMATION info;
HINSTANCE16 hInstance, hPrevInstance;
NE_MODULE *pModule;
PDB *pdb;
/* Load module */ TRACE( win32, "%s\n", lpApplicationName );
if (!paramBlock || (paramBlock == (LPVOID)-1)) /* Sanity check.
return LoadLibrary16( name ); */
if ( lpApplicationName == NULL || lpBinaryType == NULL )
return FALSE;
hInstance = NE_LoadModule( name, &hPrevInstance, FALSE, FALSE ); /* Open the file indicated by lpApplicationName for reading.
if ( hInstance < 32 || !(pModule = NE_GetPtr(hInstance)) */
|| (pModule->flags & NE_FFLAGS_LIBMODULE)) if ( (hfile = OpenFile( lpApplicationName, &ofs, OF_READ )) == HFILE_ERROR )
return hInstance; 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; return ret;
cmd_line = (LPSTR)PTR_SEG_TO_LIN( params->cmdLine ); }
if (!cmd_line) cmd_line = "";
else if (*cmd_line) cmd_line++; /* skip the length byte */
if (!(new_cmd_line = HeapAlloc( GetProcessHeap(), 0, /***********************************************************************
strlen(cmd_line)+strlen(name)+2 ))) * GetBinaryTypeW [KERNEL32.281]
return 0; */
strcpy( new_cmd_line, name ); BOOL WINAPI GetBinaryTypeW( LPCWSTR lpApplicationName, LPDWORD lpBinaryType )
strcat( new_cmd_line, " " ); {
strcat( new_cmd_line, cmd_line ); 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) ); /* Sanity check.
memset( &startup, '\0', sizeof(startup) ); */
startup.cb = sizeof(startup); if ( lpApplicationName == NULL || lpBinaryType == NULL )
if (params->showCmd) return FALSE;
/* Convert the wide string to a ascii string.
*/
strNew = HEAP_strdupWtoA( GetProcessHeap(), 0, lpApplicationName );
if ( strNew != NULL )
{ {
startup.dwFlags = STARTF_USESHOWWINDOW; ret = GetBinaryTypeA( strNew, lpBinaryType );
startup.wShowWindow = ((UINT16 *)PTR_SEG_TO_LIN(params->showCmd))[1];
/* Free the allocated string.
*/
HeapFree( GetProcessHeap(), 0, strNew );
} }
pdb = PROCESS_Create( pModule, new_cmd_line, env, return ret;
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;
} }
/********************************************************************** /**********************************************************************
* 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( &params, '\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, &params );
}
/**********************************************************************
* LoadModule (KERNEL32.499)
*/ */
HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock ) HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
{ {
@ -521,10 +726,16 @@ HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
startup.dwFlags = STARTF_USESHOWWINDOW; startup.dwFlags = STARTF_USESHOWWINDOW;
startup.wShowWindow = params->lpCmdShow? params->lpCmdShow[1] : 0; startup.wShowWindow = params->lpCmdShow? params->lpCmdShow[1] : 0;
if (!CreateProcessA( name, params->lpCmdLine, if ( !CreateProcessA( name, params->lpCmdLine,
NULL, NULL, FALSE, 0, params->lpEnvAddress, NULL, NULL, FALSE, 0, params->lpEnvAddress,
NULL, &startup, &info )) NULL, &startup, &info ) )
return GetLastError(); /* guaranteed to be < 32 */ {
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 */ /* Get 16-bit hInstance/hTask from process */
pdb = PROCESS_IdToPDB( info.dwProcessId ); 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, BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles, DWORD dwCreationFlags, BOOL bInheritHandles, DWORD dwCreationFlags,
LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo, LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInfo ) LPPROCESS_INFORMATION lpProcessInfo )
{ {
HINSTANCE16 hInstance; BOOL retv = FALSE;
HFILE hFile;
OFSTRUCT ofs;
DWORD type;
LPCSTR cmdline; LPCSTR cmdline;
PDB *pdb;
char name[256]; char name[256];
/* Get name and command line */ /* Get name and command line */
@ -667,35 +880,91 @@ BOOL WINAPI CreateProcessA( LPCSTR lpApplicationName, LPSTR lpCommandLine,
FIXME(module, "(%s,...): STARTF_USEHOTKEY ignored\n", name); FIXME(module, "(%s,...): STARTF_USEHOTKEY ignored\n", name);
/* Try NE module */ /* When in WineLib, always fork new Unix process */
hInstance = NE_CreateProcess( name, cmdline, lpEnvironment, bInheritHandles,
lpStartupInfo, lpProcessInfo );
/* Try PE module */ if ( __winelib )
if (hInstance == 21) return MODULE_CreateUnixProcess( name, cmdline,
hInstance = PE_CreateProcess( name, cmdline, lpEnvironment, bInheritHandles, lpStartupInfo, lpProcessInfo, TRUE );
lpStartupInfo, lpProcessInfo );
/* Try DOS module */ /* Check for special case: second instance of NE module */
if (hInstance == 11)
hInstance = MZ_CreateProcess( name, cmdline, lpEnvironment, bInheritHandles,
lpStartupInfo, lpProcessInfo );
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 ); /* Open file and determine executable type */
return FALSE;
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 */ /* 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 * NOTES
* lpReserved is not converted * 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( &params, '\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, &params );
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, &params );
*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) * WIN32_GetProcAddress16 (KERNEL32.36)
* Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func) * Get procaddress in 16bit module from win32... (kernel32 undoc. ordinal func)

View file

@ -259,9 +259,6 @@ static void TASK_CallToStart(void)
if (PE_HEADER(pModule->module32)->OptionalHeader.Subsystem==IMAGE_SUBSYSTEM_WINDOWS_CUI) if (PE_HEADER(pModule->module32)->OptionalHeader.Subsystem==IMAGE_SUBSYSTEM_WINDOWS_CUI)
AllocConsole(); AllocConsole();
if (pModule->heap_size)
LocalInit16( pTask->hInstance, 0, pModule->heap_size );
MODULE_InitializeDLLs( 0, DLL_PROCESS_ATTACH, (LPVOID)-1 ); MODULE_InitializeDLLs( 0, DLL_PROCESS_ATTACH, (LPVOID)-1 );
TRACE(relay, "(entryproc=%p)\n", entry ); 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 * any real problems with that, since we operated merely on a private
* TDB structure that is not yet linked into the task list. * TDB structure that is not yet linked into the task list.
*/ */
HTASK16 TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance, BOOL TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
HINSTANCE16 hPrevInstance, UINT16 cmdShow) HINSTANCE16 hPrevInstance, UINT16 cmdShow)
{ {
HTASK16 hTask; HTASK16 hTask;
TDB *pTask, *pInitialTask; 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), hTask = GLOBAL_Alloc( GMEM_FIXED | GMEM_ZEROINIT, sizeof(TDB),
pModule->self, FALSE, FALSE, FALSE ); pModule->self, FALSE, FALSE, FALSE );
if (!hTask) return 0; if (!hTask) return FALSE;
pTask = (TDB *)GlobalLock16( hTask ); pTask = (TDB *)GlobalLock16( hTask );
/* Fill the task structure */ /* Fill the task structure */
@ -369,7 +366,7 @@ HTASK16 TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
pTask->flags |= TDBF_WINOLDAP; pTask->flags |= TDBF_WINOLDAP;
pTask->version = pModule->expected_version; pTask->version = pModule->expected_version;
pTask->hInstance = hInstance; pTask->hInstance = hInstance? hInstance : pModule->self;
pTask->hPrevInstance = hPrevInstance; pTask->hPrevInstance = hPrevInstance;
pTask->hModule = pModule->self; pTask->hModule = pModule->self;
pTask->hParent = GetCurrentTask(); pTask->hParent = GetCurrentTask();
@ -445,16 +442,23 @@ HTASK16 TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
if ( pInitialTask ) if ( pInitialTask )
pTask->userhandler = pInitialTask->userhandler; 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 */ /* Create the 16-bit stack frame */
if (!(sp = pModule->sp)) pTask->thdb->cur_stack -= sizeof(STACK16FRAME);
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 );
frame16 = (STACK16FRAME *)PTR_SEG_TO_LIN( pTask->thdb->cur_stack ); 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->bp = LOWORD(frame16->ebp);
frame16->ds = frame16->es = pTask->hInstance; frame16->ds = frame16->es = hInstance;
frame16->fs = 0; frame16->fs = 0;
frame16->entry_point = 0; frame16->entry_point = 0;
frame16->entry_cs = 0; frame16->entry_cs = 0;
@ -474,11 +478,14 @@ HTASK16 TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
frame32->retaddr = (DWORD)TASK_CallToStart; frame32->retaddr = (DWORD)TASK_CallToStart;
/* The remaining fields will be initialized in TASK_Reschedule */ /* 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", TRACE(task, "module='%s' cmdline='%s' task=%04x\n",
name, cmd_line, hTask ); name, cmd_line, hTask );
return hTask; return TRUE;
} }
/*********************************************************************** /***********************************************************************

View file

@ -420,7 +420,6 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
THDB *thdb = NULL; THDB *thdb = NULL;
PDB *parent = PROCESS_Current(); PDB *parent = PROCESS_Current();
PDB *pdb = PROCESS_CreatePDB( parent, inherit ); PDB *pdb = PROCESS_CreatePDB( parent, inherit );
TDB *pTask;
if (!pdb) return NULL; if (!pdb) return NULL;
info->hThread = info->hProcess = INVALID_HANDLE_VALUE; 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; size = PE_HEADER(pModule->module32)->OptionalHeader.SizeOfStackReserve;
else else
size = 0; size = 0;
if (!(thdb = THREAD_Create( pdb, size, FALSE, &server_thandle, &server_phandle, if (!(thdb = THREAD_Create( pdb, size, hInstance == 0,
NULL, NULL ))) goto error; &server_thandle, &server_phandle, NULL, NULL )))
goto error;
if ((info->hThread = HANDLE_Alloc( parent, &thdb->header, THREAD_ALL_ACCESS, if ((info->hThread = HANDLE_Alloc( parent, &thdb->header, THREAD_ALL_ACCESS,
FALSE, server_thandle )) == INVALID_HANDLE_VALUE) FALSE, server_thandle )) == INVALID_HANDLE_VALUE)
goto error; goto error;
@ -480,8 +480,8 @@ PDB *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
if (startup->dwFlags & STARTF_USESHOWWINDOW) if (startup->dwFlags & STARTF_USESHOWWINDOW)
cmdShow = startup->wShowWindow; cmdShow = startup->wShowWindow;
pdb->task = TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow); if ( !TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow) )
if (!pdb->task) goto error; goto error;
/* Map system DLLs into this process (from initial process) */ /* Map system DLLs into this process (from initial process) */

View file

@ -226,7 +226,7 @@ THDB *THREAD_CreateInitialThread( PDB *pdb )
/* Now proceed with normal initialization */ /* 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; return &initial_thdb;
} }
@ -244,7 +244,7 @@ THDB *THREAD_Create( PDB *pdb, DWORD stack_size, BOOL alloc_stack16,
thdb->header.refcount = 1; thdb->header.refcount = 1;
thdb->process = pdb; thdb->process = pdb;
thdb->teb.except = (void *)-1; thdb->teb.except = (void *)-1;
thdb->teb.htask16 = 0; /* FIXME */ thdb->teb.htask16 = pdb->task;
thdb->teb.self = &thdb->teb; thdb->teb.self = &thdb->teb;
thdb->teb.flags = (pdb->flags & PDB32_WIN16_PROC)? 0 : TEBF_WIN32; thdb->teb.flags = (pdb->flags & PDB32_WIN16_PROC)? 0 : TEBF_WIN32;
thdb->teb.tls_ptr = thdb->tls_array; thdb->teb.tls_ptr = thdb->tls_array;