Commit c75d0e16 authored by Ulrich Weigand's avatar Ulrich Weigand Committed by Alexandre Julliard

Implemented new Wine startup sequence, separating startup into

KERNEL/USER/GDI related parts, allowing native replacement. Implemented initial 'kernel' task.
parent ddea38d7
......@@ -93,9 +93,9 @@ extern const WIN16_DESCRIPTOR WPROCS_Descriptor;
static BUILTIN16_DLL BuiltinDLLs[] =
{
{ &KERNEL_Descriptor, DLL_FLAG_ALWAYS_USED },
{ &USER_Descriptor, DLL_FLAG_ALWAYS_USED },
{ &GDI_Descriptor, DLL_FLAG_ALWAYS_USED },
{ &KERNEL_Descriptor, 0 },
{ &USER_Descriptor, 0 },
{ &GDI_Descriptor, 0 },
{ &SYSTEM_Descriptor, DLL_FLAG_ALWAYS_USED },
{ &DISPLAY_Descriptor, DLL_FLAG_ALWAYS_USED },
{ &WPROCS_Descriptor, DLL_FLAG_ALWAYS_USED },
......@@ -202,10 +202,8 @@ static HMODULE16 BUILTIN_DoLoadModule16( const WIN16_DESCRIPTOR *descr )
BOOL32 BUILTIN_Init(void)
{
BUILTIN16_DLL *dll;
NE_MODULE *pModule;
WORD vector;
HMODULE16 hModule;
WORD cs, ds;
fnBUILTIN_LoadModule = BUILTIN_LoadModule;
......@@ -215,48 +213,6 @@ BOOL32 BUILTIN_Init(void)
if (!BUILTIN_DoLoadModule16( dll->descr )) return FALSE;
}
/* Set the USER and GDI heap selectors */
pModule = NE_GetPtr( GetModuleHandle16( "USER" ));
USER_HeapSel = pModule ? GlobalHandleToSel((NE_SEG_TABLE( pModule ) + pModule->dgroup - 1)->hSeg) : 0;
pModule = NE_GetPtr( GetModuleHandle16( "GDI" ));
GDI_HeapSel = pModule ? GlobalHandleToSel((NE_SEG_TABLE( pModule ) + pModule->dgroup - 1)->hSeg) : 0;
/* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
hModule = GetModuleHandle16( "KERNEL" );
NE_SetEntryPoint( hModule, 178, GetWinFlags() );
/* Initialize KERNEL.454/455 (__FLATCS/__FLATDS) */
GET_CS(cs); GET_DS(ds);
NE_SetEntryPoint( hModule, 454, cs );
NE_SetEntryPoint( hModule, 455, ds );
/* Initialize KERNEL.THHOOK */
TASK_InstallTHHook((THHOOK *)PTR_SEG_TO_LIN(
(SEGPTR)NE_GetEntryPoint( hModule, 332 )));
/* Initialize the real-mode selector entry points */
#define SET_ENTRY_POINT( num, addr ) \
NE_SetEntryPoint( hModule, (num), GLOBAL_CreateBlock( GMEM_FIXED, \
DOSMEM_MapDosToLinear(addr), 0x10000, hModule, \
FALSE, FALSE, FALSE, NULL ))
SET_ENTRY_POINT( 183, 0x00000 ); /* KERNEL.183: __0000H */
SET_ENTRY_POINT( 174, 0xa0000 ); /* KERNEL.174: __A000H */
SET_ENTRY_POINT( 181, 0xb0000 ); /* KERNEL.181: __B000H */
SET_ENTRY_POINT( 182, 0xb8000 ); /* KERNEL.182: __B800H */
SET_ENTRY_POINT( 195, 0xc0000 ); /* KERNEL.195: __C000H */
SET_ENTRY_POINT( 179, 0xd0000 ); /* KERNEL.179: __D000H */
SET_ENTRY_POINT( 190, 0xe0000 ); /* KERNEL.190: __E000H */
SET_ENTRY_POINT( 173, 0xf0000 ); /* KERNEL.173: __ROMBIOS */
SET_ENTRY_POINT( 194, 0xf0000 ); /* KERNEL.194: __F000H */
NE_SetEntryPoint( hModule, 193, DOSMEM_BiosSeg ); /* KERNEL.193: __0040H */
#undef SET_ENTRY_POINT
/* Set interrupt vectors from entry points in WPROCS.DLL */
hModule = GetModuleHandle16( "WPROCS" );
......
......@@ -5,10 +5,10 @@
#ifndef __WINE_MAIN_H
#define __WINE_MAIN_H
extern BOOL32 MAIN_KernelInit(void);
extern void MAIN_Usage(char*);
extern BOOL32 MAIN_UserInit(void);
extern BOOL32 MAIN_MainInit(void);
extern BOOL32 MAIN_WineInit( int *argc, char *argv[] );
extern HINSTANCE32 MAIN_WinelibInit( int *argc, char *argv[] );
extern int MAIN_GetLanguageID(char*lang, char*country, char*charset, char*dialect);
extern BOOL32 RELAY_Init(void);
......
......@@ -32,19 +32,22 @@
#include "spy.h"
#include "tweak.h"
#include "user.h"
#include "global.h"
#include "dce.h"
#include "shell.h"
#include "winproc.h"
#include "syslevel.h"
#include "thread.h"
#include "task.h"
#include "debug.h"
int __winelib = 1; /* Winelib run-time flag */
/***********************************************************************
* Kernel initialisation routine
* Main initialisation routine
*/
BOOL32 MAIN_KernelInit(void)
BOOL32 MAIN_MainInit(void)
{
/* Initialize syslevel handling */
SYSLEVEL_Init();
......@@ -73,43 +76,133 @@ BOOL32 MAIN_KernelInit(void)
/* Initialize IO-port permissions */
IO_port_init();
/* registry initialisation */
SHELL_LoadRegistry();
return TRUE;
}
/***********************************************************************
* KERNEL initialisation routine
*/
BOOL32 WINAPI MAIN_KernelInit(HINSTANCE32 hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
static BOOL32 initDone = FALSE;
NE_MODULE *pModule;
HMODULE16 hModule;
if ( initDone ) return TRUE;
initDone = TRUE;
/* Create and switch to initial task */
pModule = NE_GetPtr( GetModuleHandle16( "KERNEL32" ) );
if ( pModule )
{
THDB *thdb = THREAD_Current();
HINSTANCE16 hInstance = NE_CreateInstance( pModule, NULL, TRUE );
thdb->process->task = TASK_Create( thdb, pModule, hInstance, 0, FALSE );
TASK_StartTask( thdb->process->task );
}
/* Initialize special KERNEL entry points */
hModule = GetModuleHandle16( "KERNEL" );
if ( hModule )
{
WORD cs, ds;
/* Initialize KERNEL.178 (__WINFLAGS) with the correct flags value */
NE_SetEntryPoint( hModule, 178, GetWinFlags() );
/* Initialize KERNEL.454/455 (__FLATCS/__FLATDS) */
GET_CS(cs); GET_DS(ds);
NE_SetEntryPoint( hModule, 454, cs );
NE_SetEntryPoint( hModule, 455, ds );
/* Initialize KERNEL.THHOOK */
TASK_InstallTHHook((THHOOK *)PTR_SEG_TO_LIN(
(SEGPTR)NE_GetEntryPoint( hModule, 332 )));
/* Initialize the real-mode selector entry points */
#define SET_ENTRY_POINT( num, addr ) \
NE_SetEntryPoint( hModule, (num), GLOBAL_CreateBlock( GMEM_FIXED, \
DOSMEM_MapDosToLinear(addr), 0x10000, hModule, \
FALSE, FALSE, FALSE, NULL ))
SET_ENTRY_POINT( 183, 0x00000 ); /* KERNEL.183: __0000H */
SET_ENTRY_POINT( 174, 0xa0000 ); /* KERNEL.174: __A000H */
SET_ENTRY_POINT( 181, 0xb0000 ); /* KERNEL.181: __B000H */
SET_ENTRY_POINT( 182, 0xb8000 ); /* KERNEL.182: __B800H */
SET_ENTRY_POINT( 195, 0xc0000 ); /* KERNEL.195: __C000H */
SET_ENTRY_POINT( 179, 0xd0000 ); /* KERNEL.179: __D000H */
SET_ENTRY_POINT( 190, 0xe0000 ); /* KERNEL.190: __E000H */
SET_ENTRY_POINT( 173, 0xf0000 ); /* KERNEL.173: __ROMBIOS */
SET_ENTRY_POINT( 194, 0xf0000 ); /* KERNEL.194: __F000H */
NE_SetEntryPoint( hModule, 193, DOSMEM_BiosSeg ); /* KERNEL.193: __0040H */
#undef SET_ENTRY_POINT
}
return TRUE;
}
/***********************************************************************
* USER (and GDI) initialisation routine
* GDI initialisation routine
*/
BOOL32 MAIN_UserInit(void)
BOOL32 WINAPI MAIN_GdiInit(HINSTANCE32 hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
int queueSize;
NE_MODULE *pModule;
if ( GDI_HeapSel ) return TRUE;
/* Create USER and GDI heap */
if (!USER_HeapSel)
/* Create GDI heap */
pModule = NE_GetPtr( GetModuleHandle16( "GDI" ) );
if ( pModule )
{
USER_HeapSel = GlobalAlloc16( GMEM_FIXED, 0x10000 );
LocalInit( USER_HeapSel, 0, 0xffff );
GDI_HeapSel = GlobalHandleToSel( (NE_SEG_TABLE( pModule ) +
pModule->dgroup - 1)->hSeg );
}
if (!GDI_HeapSel)
else
{
GDI_HeapSel = GlobalAlloc16( GMEM_FIXED, GDI_HEAP_SIZE );
GDI_HeapSel = GlobalAlloc16( GMEM_FIXED, GDI_HEAP_SIZE );
LocalInit( GDI_HeapSel, 0, GDI_HEAP_SIZE-1 );
}
/* GDI initialisation */
return GDI_Init();
}
/***********************************************************************
* USER initialisation routine
*/
BOOL32 WINAPI MAIN_UserInit(HINSTANCE32 hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
NE_MODULE *pModule;
int queueSize;
if ( USER_HeapSel ) return TRUE;
/* Create USER heap */
pModule = NE_GetPtr( GetModuleHandle16( "USER" ) );
if ( pModule )
{
USER_HeapSel = GlobalHandleToSel( (NE_SEG_TABLE( pModule ) +
pModule->dgroup - 1)->hSeg );
}
else
{
USER_HeapSel = GlobalAlloc16( GMEM_FIXED, 0x10000 );
LocalInit( USER_HeapSel, 0, 0xffff );
}
/* Initialize Wine tweaks */
if (!TWEAK_Init()) return FALSE;
/* Initialize OEM Bitmaps */
if (!OBM_Init()) return FALSE;
/* registry initialisation */
SHELL_LoadRegistry();
/* Global atom table initialisation */
if (!ATOM_Init()) return FALSE;
/* GDI initialisation */
if (!GDI_Init()) return FALSE;
if (!ATOM_Init( USER_HeapSel )) return FALSE;
/* Initialize system colors and metrics*/
SYSMETRICS_Init();
......@@ -152,6 +245,13 @@ BOOL32 MAIN_UserInit(void)
/* Set double click time */
SetDoubleClickTime32( GetProfileInt32A("windows","DoubleClickSpeed",452) );
/* Create task message queue for the initial task */
if ( GetCurrentTask() )
{
queueSize = GetProfileInt32A( "windows", "DefaultQueueSize", 8 );
if (!SetMessageQueue32( queueSize )) return FALSE;
}
return TRUE;
}
......@@ -159,19 +259,50 @@ BOOL32 MAIN_UserInit(void)
/***********************************************************************
* Winelib initialisation routine
*/
BOOL32 MAIN_WinelibInit( int *argc, char *argv[] )
HINSTANCE32 MAIN_WinelibInit( int *argc, char *argv[] )
{
WINE_MODREF *wm;
NE_MODULE *pModule;
OFSTRUCT ofs;
HMODULE16 hModule;
HINSTANCE16 hInstance;
/* Create the initial process */
if (!PROCESS_Init()) return FALSE;
if (!PROCESS_Init()) return 0;
/* Parse command line arguments */
MAIN_WineInit( argc, argv );
/* Initialize the kernel */
if (!MAIN_KernelInit()) return FALSE;
/* Main initialization */
if (!MAIN_MainInit()) return 0;
/* Initialize all the USER stuff */
if (!MAIN_UserInit()) return FALSE;
/* Initialize KERNEL */
if (!MAIN_KernelInit(0, 0, NULL)) return 0;
return TRUE;
/* Initialize GDI */
if (!MAIN_GdiInit(0, 0, NULL)) return 0;
/* Initialize USER */
if (!MAIN_UserInit(0, 0, NULL)) return 0;
/* Create and switch to initial task */
if (!(wm = ELF_CreateDummyModule( argv[0], argv[0], PROCESS_Current() )))
return 0;
PROCESS_Current()->exe_modref = wm;
strcpy( ofs.szPathName, wm->modname );
if ((hModule = MODULE_CreateDummyModule( &ofs )) < 32) return 0;
pModule = (NE_MODULE *)GlobalLock16( hModule );
pModule->flags = NE_FFLAGS_WIN32;
pModule->module32 = wm->module;
hInstance = NE_CreateInstance( pModule, NULL, TRUE );
PROCESS_Current()->task = TASK_Create( THREAD_Current(), pModule, hInstance, 0, FALSE );
TASK_StartTask( PROCESS_Current()->task );
InitApp( hInstance );
return wm->module;
}
......@@ -425,9 +425,8 @@ HTASK16 TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
if (!(sp = pModule->sp))
sp = pSegTable[pModule->ss-1].minsize + pModule->stack_size;
sp &= ~1;
sp &= ~1; sp -= 2*sizeof(STACK16FRAME);
pTask->thdb->cur_stack = PTR_SEG_OFF_TO_SEGPTR( pTask->hInstance, sp );
pTask->thdb->cur_stack -= 2*sizeof(STACK16FRAME);
frame16 = (STACK16FRAME *)PTR_SEG_TO_LIN( pTask->thdb->cur_stack );
frame16->ebp = sp + (int)&((STACK16FRAME *)0)->bp;
frame16->bp = LOWORD(frame16->ebp);
......@@ -451,9 +450,6 @@ HTASK16 TASK_Create( THDB *thdb, NE_MODULE *pModule, HINSTANCE16 hInstance,
frame32->retaddr = (DWORD)TASK_CallToStart;
/* The remaining fields will be initialized in TASK_Reschedule */
if (!THREAD_Current()->cur_stack)
THREAD_Current()->cur_stack = pTask->thdb->cur_stack;
TRACE(task, "module='%s' cmdline='%s' task=%04x\n",
name, cmd_line, hTask );
......@@ -483,11 +479,10 @@ void TASK_StartTask( HTASK16 hTask )
we simply Yield(). If we are 32-bit however, we need to signal
the main process somehow (NOT YET IMPLEMENTED!) */
if ( GetCurrentTask() )
if ( THREAD_IsWin16( THREAD_Current() ) )
Yield16();
else
FIXME(task, "Don't know how to start 16-bit task from 32-bit thread. Move the mouse!\n");
if ( THREAD_IsWin16( THREAD_Current() ) )
OldYield();
else
FIXME(task, "Don't know how to start 16-bit task from 32-bit thread. Move the mouse!\n");
}
......@@ -584,7 +579,7 @@ void TASK_KillCurrentTask( INT16 exitCode )
TASK_DeleteTask( hTaskToKill );
}
if (nTaskCount <= 1)
if (nTaskCount <= 2) /* FIXME */
{
TRACE(task, "this is the last task, exiting\n" );
USER_ExitWindows();
......@@ -630,6 +625,34 @@ void TASK_Reschedule(void)
HTASK16 hTask = 0;
STACK16FRAME *newframe16;
/* Get the initial task up and running */
if (!hCurrentTask && GetCurrentTask())
{
/* We need to remove one pair of stackframes (exept for Winelib) */
STACK16FRAME *oldframe16 = CURRENT_STACK16;
STACK32FRAME *oldframe32 = oldframe16->frame32;
STACK16FRAME *newframe16 = PTR_SEG_TO_LIN( oldframe32->frame16 );
STACK32FRAME *newframe32 = newframe16->frame32;
if (newframe32)
{
newframe16->entry_ip = oldframe16->entry_ip;
newframe16->entry_cs = oldframe16->entry_cs;
newframe16->ip = oldframe16->ip;
newframe16->cs = oldframe16->cs;
newframe32->ebp = oldframe32->ebp;
newframe32->restore_addr = oldframe32->restore_addr;
newframe32->codeselector = oldframe32->codeselector;
newframe32->retaddr = oldframe32->retaddr; /* don't call TASK_CallToStart */
THREAD_Current()->cur_stack = oldframe32->frame16;
}
hCurrentTask = GetCurrentTask();
pNewTask = (TDB *)GlobalLock16( hCurrentTask );
pNewTask->ss_sp = pNewTask->thdb->cur_stack;
return;
}
/* NOTE: As we are entered from 16-bit code, we hold the Win16Lock.
We hang onto it thoughout most of this routine, so that accesses
to global variables (most notably the task list) are protected. */
......@@ -1229,6 +1252,13 @@ HANDLE32 WINAPI GetFastQueue( void )
if (!thdb) return 0;
if (!(thdb->teb.queue))
{
HMODULE16 hModule = GetModuleHandle16( "USER" );
FARPROC16 proc = WIN32_GetProcAddress16( hModule, "InitThreadInput" );
Callbacks->CallBootAppProc( proc, 0, 4 ); /* FIXME! */
}
if (!(thdb->teb.queue))
FIXME( task, "(): should initialize thread-local queue, expect failure!\n" );
return (HANDLE32)thdb->teb.queue;
......
......@@ -3,6 +3,7 @@
*
*/
#include <assert.h>
#include "callback.h"
#include "debug.h"
#include "debugger.h"
......@@ -13,6 +14,7 @@
#include "process.h"
#include "win16drv.h"
#include "psdrv.h"
#include "thread.h"
#include "windows.h"
......@@ -21,13 +23,13 @@
*/
BOOL32 MAIN_EmulatorInit(void)
{
/* Initialize the kernel */
if (!MAIN_KernelInit()) return FALSE;
/* Main initialization */
if (!MAIN_MainInit()) return FALSE;
/* Initialize relay code */
if (!RELAY_Init()) return FALSE;
/* Initialize signal handling */
/* Initialize signal handling */
if (!SIGNAL_InitEmulator()) return FALSE;
/* Create the Win16 printer driver */
......@@ -36,8 +38,46 @@ BOOL32 MAIN_EmulatorInit(void)
/* Create the Postscript printer driver (FIXME: should be in Winelib) */
if (!PSDRV_Init()) return FALSE;
/* Initialize all the USER stuff */
return MAIN_UserInit();
/* Load system DLLs into the initial process (and initialize them) */
if (!LoadLibrary16( "KERNEL" )) return FALSE; /* always built-in */
if (!LoadLibrary32A( "KERNEL32" )) return FALSE; /* always built-in */
if (!LoadLibrary16( "GDI.EXE" )) return FALSE;
if (!LoadLibrary32A( "GDI32.DLL" )) return FALSE;
if (!LoadLibrary16( "USER.EXE" )) return FALSE;
if (!LoadLibrary32A( "USER32.DLL" )) return FALSE;
return TRUE;
}
/***********************************************************************
* Main loop of initial task
*/
void MAIN_EmulatorRun( void )
{
BOOL32 (*WINAPI pGetMessage)(MSG32* lpmsg,HWND32 hwnd,UINT32 min,UINT32 max);
BOOL32 (*WINAPI pTranslateMessage)( const MSG32* msg );
LONG (*WINAPI pDispatchMessage)( const MSG32* msg );
MSG32 msg;
HMODULE32 hModule = GetModuleHandle32A( "USER32" );
pGetMessage = GetProcAddress32( hModule, "GetMessageA" );
pTranslateMessage = GetProcAddress32( hModule, "TranslateMessage" );
pDispatchMessage = GetProcAddress32( hModule, "DispatchMessageA" );
assert( pGetMessage );
assert( pTranslateMessage );
assert( pDispatchMessage );
while ( GetNumTasks() > 1 && pGetMessage( &msg, 0, 0, 0 ) )
{
pTranslateMessage( &msg );
pDispatchMessage( &msg );
}
ExitProcess( 0 );
}
......@@ -131,8 +171,10 @@ int main( int argc, char *argv[] )
if (Options.debug) DEBUG_AddModuleBreakpoints();
ctx_debug_call = ctx_debug;
#if 0 /* FIXME!! */
IF1632_CallLargeStack = (int (*)(int (*func)(), void *arg))CALL32_Init();
Yield16(); /* Start the first task */
#endif
MAIN_EmulatorRun();
MSG("WinMain: Should never happen: returned from Yield16()\n" );
return 0;
}
name gdi32
type win32
init MAIN_GdiInit
0 stub AbortDoc
1 stdcall AbortPath(long) AbortPath32
......
name kernel32
type win32
init MAIN_KernelInit
# Functions exported by the Win95 kernel32.dll
# (these need to have these exact ordinals, for some win95 dlls
......
name user32
type win32
init MAIN_UserInit
1 stub ActivateKeyboardLayout
2 stdcall AdjustWindowRect(ptr long long) AdjustWindowRect32
......
......@@ -254,7 +254,7 @@ BOOL32 PROCESS_Init(void)
/* Create the initial process and thread structures */
if (!(pdb = PROCESS_CreatePDB( NULL ))) return FALSE;
if (!(thdb = THREAD_Create( pdb, 0, TRUE, NULL, NULL, NULL, NULL ))) return FALSE;
if (!(thdb = THREAD_Create( pdb, 0, FALSE, NULL, NULL, NULL, NULL ))) return FALSE;
thdb->unix_pid = getpid();
PROCESS_InitialProcessID = PDB_TO_PROCESS_ID(pdb);
......@@ -346,6 +346,12 @@ PDB32 *PROCESS_Create( NE_MODULE *pModule, LPCSTR cmd_line, LPCSTR env,
pdb->task = TASK_Create( thdb, pModule, hInstance, hPrevInstance, cmdShow);
if (!pdb->task) goto error;
/* Map system DLLs into this process (from initial process) */
/* FIXME: this is a hack */
pdb->modref_list = PROCESS_Initial()->modref_list;
return pdb;
error:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment