diff --git a/include/module.h b/include/module.h index 51160e26e21..9f52cb197d9 100644 --- a/include/module.h +++ b/include/module.h @@ -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); diff --git a/include/task.h b/include/task.h index af64809a01f..906e03cd9e0 100644 --- a/include/task.h +++ b/include/task.h @@ -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 ); diff --git a/loader/module.c b/loader/module.c index a771e6f269a..9156e99ec53 100644 --- a/loader/module.c +++ b/loader/module.c @@ -12,6 +12,7 @@ #include #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) diff --git a/loader/task.c b/loader/task.c index 6f90cd74a9b..c17d513056b 100644 --- a/loader/task.c +++ b/loader/task.c @@ -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; } /*********************************************************************** diff --git a/scheduler/process.c b/scheduler/process.c index ef903bd5e3d..32609230e9c 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -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) */ diff --git a/scheduler/thread.c b/scheduler/thread.c index 67963333b7f..0f0a0b10c3c 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -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;