/************************************************************************** * WINHELP entry point * * FIXME: should go into winhlp32.exe, but we don't support 16-bit modules in executables yet. */ void WINAPI WINHELP_EntryPoint( CONTEXT86 *context ) { static const WCHAR winhlp32W[] = {'\\','w','i','n','h','l','p','3','2','.','e','x','e',0}; PDB16 *psp; INT len, total; WCHAR *cmdline, *p; PROCESS_INFORMATION info; STARTUPINFOW startup; DWORD count, exit_code = 1; InitTask16( context ); TRACE( "(ds=%x es=%x fs=%x gs=%x, bx=%04x cx=%04x di=%04x si=%x)\n", context->SegDs, context->SegEs, context->SegFs, context->SegGs, context->Ebx, context->Ecx, context->Edi, context->Esi ); psp = GlobalLock16( context->SegEs ); len = MultiByteToWideChar( CP_ACP, 0, (char *)psp->cmdLine + 1, psp->cmdLine[0], NULL, 0 ); total = (GetSystemDirectoryW( NULL, 0 ) + len + 1) * sizeof(WCHAR) + sizeof(winhlp32W); cmdline = HeapAlloc( GetProcessHeap(), 0, total ); GetSystemDirectoryW( cmdline, total ); lstrcatW( cmdline, winhlp32W ); p = cmdline + lstrlenW(cmdline); if (len) { *p++ = ' '; MultiByteToWideChar( CP_ACP, 0, (char *)psp->cmdLine + 1, psp->cmdLine[0], p, len ); p[len] = 0; } memset( &startup, 0, sizeof(startup) ); startup.cb = sizeof(startup); if (CreateProcessW( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info )) { /* Give 10 seconds to the app to come up */ if (wait_input_idle( info.hProcess, 10000 ) == WAIT_FAILED) WARN("WaitForInputIdle failed: Error %d\n", GetLastError() ); ReleaseThunkLock( &count ); WaitForSingleObject( info.hProcess, INFINITE ); GetExitCodeProcess( info.hProcess, &exit_code ); CloseHandle( info.hThread ); CloseHandle( info.hProcess ); } else ReleaseThunkLock( &count ); HeapFree( GetProcessHeap(), 0, cmdline ); ExitThread( exit_code ); }
/*********************************************************************** * WIN32_OldYield (KERNEL.447) */ void WINAPI WIN32_OldYield16(void) { DWORD count; ReleaseThunkLock(&count); RestoreThunkLock(count); }
/*********************************************************************** * WaitEvent (KERNEL.30) */ BOOL16 WINAPI WaitEvent16( HTASK16 hTask ) { TDB *pTask; if (!hTask) hTask = GetCurrentTask(); pTask = TASK_GetPtr( hTask ); if (pTask->flags & TDBF_WIN32) { FIXME("called for Win32 thread (%04x)!\n", GetCurrentThreadId()); return TRUE; } if (pTask->nEvents > 0) { pTask->nEvents--; return FALSE; } if (pTask->teb == NtCurrentTeb()) { DWORD lockCount; NtResetEvent( pTask->hEvent, NULL ); ReleaseThunkLock( &lockCount ); SYSLEVEL_CheckNotLevel( 1 ); WaitForSingleObject( pTask->hEvent, INFINITE ); RestoreThunkLock( lockCount ); if (pTask->nEvents > 0) pTask->nEvents--; } else FIXME("for other task %04x cur=%04x\n",pTask->hSelf,GetCurrentTask()); return TRUE; }
/********************************************************************** * DOSVM_Exit */ void DOSVM_Exit( WORD retval ) { DWORD count; ReleaseThunkLock( &count ); ExitThread( retval ); }
/********************************************************************** * WOW_CallProc32W */ static DWORD WOW_CallProc32W16( FARPROC proc32, DWORD nrofargs, DWORD *args ) { DWORD ret; DWORD mutex_count; ReleaseThunkLock( &mutex_count ); /* * FIXME: If ( nrofargs & CPEX_DEST_CDECL ) != 0, we should call a * 32-bit CDECL routine ... */ if (!proc32) ret = 0; else switch (nrofargs) { case 0: ret = proc32(); break; case 1: ret = proc32(args[0]); break; case 2: ret = proc32(args[0],args[1]); break; case 3: ret = proc32(args[0],args[1],args[2]); break; case 4: ret = proc32(args[0],args[1],args[2],args[3]); break; case 5: ret = proc32(args[0],args[1],args[2],args[3],args[4]); break; case 6: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5]); break; case 7: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6]); break; case 8: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]); break; case 9: ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]); break; case 10:ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]); break; case 11:ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]); break; case 12:ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]); break; case 13:ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]); break; case 14:ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]); break; case 15:ret = proc32(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]); break; default: /* FIXME: should go up to 32 arguments */ ERR("Unsupported number of arguments %ld, please report.\n",nrofargs); ret = 0; break; } RestoreThunkLock( mutex_count ); TRACE("returns %08lx\n",ret); return ret; }
/*********************************************************************** * VWin32_EventWait (KERNEL.450) */ VOID WINAPI VWin32_EventWait(HANDLE event) { DWORD mutex_count; ReleaseThunkLock( &mutex_count ); WaitForSingleObject( event, INFINITE ); RestoreThunkLock( mutex_count ); }
/*********************************************************************** * WaitForSingleObject (KERNEL.460) */ DWORD WINAPI WaitForSingleObject16( HANDLE handle, DWORD timeout ) { DWORD retval, mutex_count; ReleaseThunkLock( &mutex_count ); retval = WaitForSingleObject( handle, timeout ); RestoreThunkLock( mutex_count ); return retval; }
/*********************************************************************** * FreeLibrary32W (KERNEL.514) */ DWORD WINAPI FreeLibrary32W16( DWORD hLibModule ) { BOOL retv; DWORD mutex_count; ReleaseThunkLock( &mutex_count ); retv = FreeLibrary( (HMODULE)hLibModule ); RestoreThunkLock( mutex_count ); return (DWORD)retv; }
/************************************************************************** * WINOLDAP entry point */ void WINAPI WINOLDAP_EntryPoint( CONTEXT86 *context ) { PDB16 *psp; INT len; LPSTR cmdline; PROCESS_INFORMATION info; STARTUPINFOA startup; DWORD count, exit_code = 1; InitTask16( context ); TRACE( "(ds=%x es=%x fs=%x gs=%x, bx=%04x cx=%04x di=%04x si=%x)\n", context->SegDs, context->SegEs, context->SegFs, context->SegGs, context->Ebx, context->Ecx, context->Edi, context->Esi ); psp = GlobalLock16( context->SegEs ); len = psp->cmdLine[0]; cmdline = HeapAlloc( GetProcessHeap(), 0, len + 1 ); memcpy( cmdline, psp->cmdLine + 1, len ); cmdline[len] = 0; memset( &startup, 0, sizeof(startup) ); startup.cb = sizeof(startup); if (CreateProcessA( NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &info )) { /* Give 10 seconds to the app to come up */ if (wait_input_idle( info.hProcess, 10000 ) == WAIT_FAILED) WARN("WaitForInputIdle failed: Error %d\n", GetLastError() ); ReleaseThunkLock( &count ); WaitForSingleObject( info.hProcess, INFINITE ); GetExitCodeProcess( info.hProcess, &exit_code ); CloseHandle( info.hThread ); CloseHandle( info.hProcess ); } else ReleaseThunkLock( &count ); HeapFree( GetProcessHeap(), 0, cmdline ); ExitThread( exit_code ); }
/*********************************************************************** * WaitForMultipleObjectsEx (KERNEL.495) */ DWORD WINAPI WaitForMultipleObjectsEx16( DWORD count, const HANDLE *handles, BOOL wait_all, DWORD timeout, BOOL alertable ) { DWORD retval, mutex_count; ReleaseThunkLock( &mutex_count ); retval = WaitForMultipleObjectsEx( count, handles, wait_all, timeout, alertable ); RestoreThunkLock( mutex_count ); return retval; }
/*********************************************************************** * TASK_ExitTask */ void TASK_ExitTask(void) { WIN16_SUBSYSTEM_TIB *tib; TDB *pTask; DWORD lockCount; /* Enter the Win16Lock to protect global data structures */ _EnterWin16Lock(); pTask = TASK_GetCurrent(); if ( !pTask ) { _LeaveWin16Lock(); return; } TRACE("Killing task %04x\n", pTask->hSelf ); /* Perform USER cleanup */ TASK_CallTaskSignalProc( USIG16_TERMINATION, pTask->hSelf ); /* Remove the task from the list to be sure we never switch back to it */ TASK_UnlinkTask( pTask->hSelf ); if (!nTaskCount || (nTaskCount == 1 && hFirstTask == initial_task)) { TRACE("this is the last task, exiting\n" ); ExitKernel16(); } pTask->nEvents = 0; if ( hLockedTask == pTask->hSelf ) hLockedTask = 0; TASK_DeleteTask( pTask->hSelf ); if ((tib = NtCurrentTeb()->Tib.SubSystemTib)) { free_win16_tib( tib ); NtCurrentTeb()->Tib.SubSystemTib = NULL; } /* ... and completely release the Win16Lock, just in case. */ ReleaseThunkLock( &lockCount ); }
/*********************************************************************** * LoadLibraryEx32W (KERNEL.513) */ DWORD WINAPI LoadLibraryEx32W16( LPCSTR lpszLibFile, DWORD hFile, DWORD dwFlags ) { HMODULE hModule; DWORD mutex_count; OFSTRUCT ofs; const char *p; if (!lpszLibFile) { SetLastError(ERROR_INVALID_PARAMETER); return 0; } /* if the file cannot be found, call LoadLibraryExA anyway, since it might be a builtin module. This case is handled in MODULE_LoadLibraryExA */ if ((p = strrchr( lpszLibFile, '.' )) && !strchr( p, '\\' )) /* got an extension */ { if (OpenFile16( lpszLibFile, &ofs, OF_EXIST ) != HFILE_ERROR16) lpszLibFile = ofs.szPathName; } else { char buffer[MAX_PATH+4]; strcpy( buffer, lpszLibFile ); strcat( buffer, ".dll" ); if (OpenFile16( buffer, &ofs, OF_EXIST ) != HFILE_ERROR16) lpszLibFile = ofs.szPathName; } ReleaseThunkLock( &mutex_count ); hModule = LoadLibraryExA( lpszLibFile, (HANDLE)hFile, dwFlags ); RestoreThunkLock( mutex_count ); return (DWORD)hModule; }
/*********************************************************************** * main */ int main( int argc, char *argv[] ) { DWORD count; HINSTANCE16 instance; LOADPARAMS16 params; WORD showCmd[2]; char buffer[MAX_PATH]; STARTUPINFOA info; char *cmdline, *appname, **first_arg; char *p; if (!argv[1]) usage(); if (!strcmp( argv[1], "--app-name" )) { if (!(appname = argv[2])) usage(); first_arg = argv + 3; } else { if (!SearchPathA( NULL, argv[1], ".exe", sizeof(buffer), buffer, NULL )) { WINE_MESSAGE( "winevdm: unable to exec '%s': file not found\n", argv[1] ); ExitProcess(1); } appname = buffer; first_arg = argv + 1; } if (*first_arg) first_arg++; /* skip program name */ cmdline = build_command_line( first_arg ); if (WINE_TRACE_ON(winevdm)) { int i; WINE_TRACE( "GetCommandLine = '%s'\n", GetCommandLineA() ); WINE_TRACE( "appname = '%s'\n", appname ); WINE_TRACE( "cmdline = '%.*s'\n", cmdline[0], cmdline+1 ); for (i = 0; argv[i]; i++) WINE_TRACE( "argv[%d]: '%s'\n", i, argv[i] ); } GetStartupInfoA( &info ); showCmd[0] = 2; showCmd[1] = (info.dwFlags & STARTF_USESHOWWINDOW) ? info.wShowWindow : SW_SHOWNORMAL; params.hEnvironment = 0; params.cmdLine = MapLS( cmdline ); params.showCmd = MapLS( showCmd ); params.reserved = 0; RestoreThunkLock(1); /* grab the Win16 lock */ /* some programs assume mmsystem is always present */ LoadLibrary16( "gdi.exe" ); LoadLibrary16( "user.exe" ); LoadLibrary16( "mmsystem.dll" ); if ((instance = LoadModule16( appname, ¶ms )) < 32) { if (instance == 11) { /* first see if it is a .pif file */ if( ( p = strrchr( appname, '.' )) && !strcasecmp( p, ".pif")) pif_cmd( appname, cmdline + 1); else { /* try DOS format */ /* loader expects arguments to be regular C strings */ start_dos_exe( appname, cmdline + 1 ); } /* if we get back here it failed */ instance = GetLastError(); } WINE_MESSAGE( "winevdm: can't exec '%s': ", appname ); switch (instance) { case 2: WINE_MESSAGE("file not found\n" ); break; case 11: WINE_MESSAGE("invalid program file\n" ); break; default: WINE_MESSAGE("error=%d\n", instance ); break; } ExitProcess(instance); } /* wait forever; the process will be killed when the last task exits */ ReleaseThunkLock( &count ); Sleep( INFINITE ); return 0; }
/*********************************************************************** * ExitProcess (KERNEL.466) */ void WINAPI ExitProcess16( WORD status ) { DWORD count; ReleaseThunkLock( &count ); ExitProcess( status ); }