From 4e951ea25bed3e8e44f930b9e3684823e04b52bf Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 8 Nov 2000 22:47:53 +0000 Subject: [PATCH] Check all Callouts function pointers for NULL before using them. Don't load USER dll if not needed by the application. --- dlls/gdi/printdrv.c | 13 ++++++++++- dlls/kernel/comm.c | 2 +- if1632/thunk.c | 9 ++++---- include/callback.h | 1 - include/task.h | 2 +- loader/dos/dosvm.c | 21 ++++++++++++------ loader/module.c | 6 +++-- loader/task.c | 54 ++++++++++++++++----------------------------- miscemu/main.c | 7 ++++++ objects/palette.c | 16 ++++++++------ scheduler/process.c | 54 +++++++++++++++------------------------------ scheduler/thread.c | 2 +- win32/except.c | 10 +++++++-- 13 files changed, 98 insertions(+), 99 deletions(-) diff --git a/dlls/gdi/printdrv.c b/dlls/gdi/printdrv.c index 8bd2dcd6056..4ecb1e92a43 100644 --- a/dlls/gdi/printdrv.c +++ b/dlls/gdi/printdrv.c @@ -617,15 +617,26 @@ INT16 WINAPI WriteSpool16(HPJOB16 hJob, LPSTR lpData, INT16 cch) return nRet; } +typedef INT WINAPI (*MSGBOX_PROC)( HWND, LPCSTR, LPCSTR, UINT ); + /********************************************************************** * WriteDialog (GDI.242) * */ INT16 WINAPI WriteDialog16(HPJOB16 hJob, LPSTR lpMsg, INT16 cchMsg) { + HMODULE mod; + MSGBOX_PROC pMessageBoxA; + INT16 ret = 0; + TRACE("%04x %04x '%s'\n", hJob, cchMsg, lpMsg); - return Callout.MessageBoxA(0, lpMsg, "Printing Error", MB_OKCANCEL); + if ((mod = GetModuleHandleA("user32.dll"))) + { + if ((pMessageBoxA = (MSGBOX_PROC)GetProcAddress( mod, "MessageBoxA" ))) + ret = pMessageBoxA(0, lpMsg, "Printing Error", MB_OKCANCEL); + } + return ret; } diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c index defa7e041a4..c6da61cd8bd 100644 --- a/dlls/kernel/comm.c +++ b/dlls/kernel/comm.c @@ -340,7 +340,7 @@ static void CALLBACK comm_notification( ULONG_PTR private ) /* send notifications, if any */ if (ptr->wnd && mask) { TRACE("notifying %04x: cid=%d, mask=%02x\n", ptr->wnd, cid, mask); - Callout.PostMessageA(ptr->wnd, WM_COMMNOTIFY, cid, mask); + if (Callout.PostMessageA) Callout.PostMessageA(ptr->wnd, WM_COMMNOTIFY, cid, mask); } } diff --git a/if1632/thunk.c b/if1632/thunk.c index 3aa43ec2adc..3a1dbcd885d 100644 --- a/if1632/thunk.c +++ b/if1632/thunk.c @@ -43,7 +43,6 @@ CALLOUT_TABLE Callout = { /* GetMessageA */ NULL, /* SendMessageA */ NULL, /* PostMessageA */ NULL, - /* PostAppMessage16 */ NULL, /* TranslateMessage */ NULL, /* DispatchMessageA */ NULL, /* RedrawWindow */ NULL, @@ -168,7 +167,7 @@ void THUNK_InitCallout(void) HMODULE hModule; NE_MODULE *pModule; - hModule = LoadLibraryA( "user32.dll" ); + hModule = GetModuleHandleA( "user32.dll" ); if ( hModule ) { #define GETADDR( name ) \ @@ -188,21 +187,21 @@ void THUNK_InitCallout(void) GETADDR( MessageBoxW ); #undef GETADDR } + else WARN("no 32-bit USER\n"); - pModule = NE_GetPtr( LoadLibrary16( "USER.EXE" ) ); + pModule = NE_GetPtr( GetModuleHandle16( "USER.EXE" ) ); if ( pModule ) { #define GETADDR( var, name, thk ) \ *(FARPROC *)&Callout.var = THUNK_GetCalloutThunk( pModule, name, \ (RELAY)THUNK_CallTo16_##thk ) - GETADDR( PostAppMessage16, "PostAppMessage", word_wwwl ); GETADDR( FinalUserInit16, "FinalUserInit", word_ ); GETADDR( InitThreadInput16, "InitThreadInput", word_ww ); GETADDR( UserYield16, "UserYield", word_ ); GETADDR( DestroyIcon32, "DestroyIcon32", word_ww ); GETADDR( UserSignalProc, "SignalProc32", word_lllw ); - #undef GETADDR } + else WARN("no 16-bit USER\n"); } diff --git a/include/callback.h b/include/callback.h index 9ba70165da3..7813e401541 100644 --- a/include/callback.h +++ b/include/callback.h @@ -31,7 +31,6 @@ typedef struct BOOL WINAPI (*GetMessageA)( MSG*, HWND, UINT, UINT ); LRESULT WINAPI (*SendMessageA)( HWND, UINT, WPARAM, LPARAM ); BOOL WINAPI (*PostMessageA)( HWND, UINT, WPARAM, LPARAM ); - BOOL16 WINAPI (*PostAppMessage16)( HTASK16, UINT16, WPARAM16, LPARAM ); BOOL WINAPI (*TranslateMessage)( const MSG *msg ); LONG WINAPI (*DispatchMessageA)( const MSG* msg ); BOOL WINAPI (*RedrawWindow)( HWND, const RECT *, HRGN, UINT ); diff --git a/include/task.h b/include/task.h index cb666eb3fb5..75cdc593c90 100644 --- a/include/task.h +++ b/include/task.h @@ -147,7 +147,7 @@ extern THHOOK *pThhook; extern BOOL TASK_Create( struct _NE_MODULE *pModule, UINT16 cmdShow, struct _TEB *teb, LPCSTR cmdline, BYTE len ); -extern void TASK_KillTask( HTASK16 hTask ); +extern void TASK_ExitTask(void); extern HTASK16 TASK_GetNextTask( HTASK16 hTask ); extern void TASK_Reschedule(void); extern void TASK_InstallTHHook( THHOOK *pNewThook ); diff --git a/loader/dos/dosvm.c b/loader/dos/dosvm.c index ba52f4a4bd1..0097f145d74 100644 --- a/loader/dos/dosvm.c +++ b/loader/dos/dosvm.c @@ -420,12 +420,15 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject ) objc=hObject?2:1; do { /* check for messages (waste time before the response check below) */ - while (Callout.PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) { - /* got a message */ - DOSVM_ProcessMessage(&msg); - /* we don't need a TranslateMessage here */ - Callout.DispatchMessageA(&msg); - got_msg = TRUE; + if (Callout.PeekMessageA) + { + while (Callout.PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) { + /* got a message */ + DOSVM_ProcessMessage(&msg); + /* we don't need a TranslateMessage here */ + Callout.DispatchMessageA(&msg); + got_msg = TRUE; + } } if (!got_msg) { /* check for console input */ @@ -448,7 +451,11 @@ void DOSVM_Wait( int read_pipe, HANDLE hObject ) break; } /* nothing yet, block while waiting for something to do */ - waitret=Callout.MsgWaitForMultipleObjects(objc,objs,FALSE,INFINITE,QS_ALLINPUT); + if (Callout.MsgWaitForMultipleObjects) + waitret = Callout.MsgWaitForMultipleObjects(objc,objs,FALSE,INFINITE,QS_ALLINPUT); + else + waitret = WaitForMultipleObjects(objc,objs,FALSE,INFINITE); + if (waitret==(DWORD)-1) { ERR_(module)("dosvm wait error=%ld\n",GetLastError()); } diff --git a/loader/module.c b/loader/module.c index e1978cf0697..ae2d2980e96 100644 --- a/loader/module.c +++ b/loader/module.c @@ -827,7 +827,8 @@ HINSTANCE WINAPI WinExec( LPCSTR lpCmdLine, UINT nCmdShow ) 0, NULL, NULL, &startup, &info )) { /* Give 30 seconds to the app to come up */ - if (Callout.WaitForInputIdle ( info.hProcess, 30000 ) == 0xFFFFFFFF) + if (Callout.WaitForInputIdle && + Callout.WaitForInputIdle( info.hProcess, 30000 ) == 0xFFFFFFFF) WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() ); hInstance = 33; /* Close off the handles */ @@ -884,7 +885,8 @@ HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock ) params->lpEnvAddress, NULL, &startup, &info )) { /* Give 30 seconds to the app to come up */ - if ( Callout.WaitForInputIdle ( info.hProcess, 30000 ) == 0xFFFFFFFF ) + if (Callout.WaitForInputIdle && + Callout.WaitForInputIdle( info.hProcess, 30000 ) == 0xFFFFFFFF ) WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() ); hInstance = 33; /* Close off the handles */ diff --git a/loader/task.c b/loader/task.c index 4db25a2700f..e6bafa09ede 100644 --- a/loader/task.c +++ b/loader/task.c @@ -379,78 +379,62 @@ static void TASK_DeleteTask( HTASK16 hTask ) /*********************************************************************** * TASK_KillTask */ -void TASK_KillTask( HTASK16 hTask ) +void TASK_ExitTask(void) { TDB *pTask; + DWORD lockCount; /* Enter the Win16Lock to protect global data structures */ SYSLEVEL_EnterWin16Lock(); - if ( !hTask ) hTask = GetCurrentTask(); - pTask = (TDB *)GlobalLock16( hTask ); + pTask = (TDB *)GlobalLock16( GetCurrentTask() ); if ( !pTask ) { SYSLEVEL_LeaveWin16Lock(); return; } - TRACE("Killing task %04x\n", hTask ); + TRACE("Killing task %04x\n", pTask->hSelf ); /* Perform USER cleanup */ - TASK_CallTaskSignalProc( USIG16_TERMINATION, hTask ); + TASK_CallTaskSignalProc( USIG16_TERMINATION, pTask->hSelf ); PROCESS_CallUserSignalProc( USIG_PROCESS_EXIT, 0 ); PROCESS_CallUserSignalProc( USIG_THREAD_EXIT, 0 ); PROCESS_CallUserSignalProc( USIG_PROCESS_DESTROY, 0 ); - if (nTaskCount <= 1) + /* 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" ); + ERR("done\n"); ExitKernel16(); } - /* FIXME: Hack! Send a message to the initial task so that - * the GetMessage wakes up and the initial task can check whether - * it is the only remaining one and terminate itself ... - * The initial task should probably install hooks or something - * to get informed about task termination :-/ - */ - Callout.PostAppMessage16( initial_task, WM_NULL, 0, 0 ); - - /* Remove the task from the list to be sure we never switch back to it */ - TASK_UnlinkTask( hTask ); if( nTaskCount ) { TDB* p = (TDB *)GlobalLock16( hFirstTask ); while( p ) { - if( p->hYieldTo == hTask ) p->hYieldTo = 0; + if( p->hYieldTo == pTask->hSelf ) p->hYieldTo = 0; p = (TDB *)GlobalLock16( p->hNext ); } } pTask->nEvents = 0; - if ( hLockedTask == hTask ) + if ( hLockedTask == pTask->hSelf ) hLockedTask = 0; - TASK_DeleteTask( hTask ); + TASK_DeleteTask( pTask->hSelf ); - /* When deleting the current task ... */ - if ( hTask == hCurrentTask ) - { - DWORD lockCount; + /* ... schedule another one ... */ + TASK_Reschedule(); - /* ... schedule another one ... */ - TASK_Reschedule(); - - /* ... and completely release the Win16Lock, just in case. */ - ReleaseThunkLock( &lockCount ); - - return; - } - - SYSLEVEL_LeaveWin16Lock(); + /* ... and completely release the Win16Lock, just in case. */ + ReleaseThunkLock( &lockCount ); } /*********************************************************************** @@ -838,7 +822,7 @@ void WINAPI Yield16(void) TDB *pCurTask = (TDB *)GlobalLock16( GetCurrentTask() ); if (pCurTask) pCurTask->hYieldTo = 0; - if (pCurTask && pCurTask->hQueue) Callout.UserYield16(); + if (pCurTask && pCurTask->hQueue && Callout.UserYield16) Callout.UserYield16(); else OldYield16(); } @@ -1148,7 +1132,7 @@ HANDLE WINAPI GetFastQueue16( void ) TEB *teb = NtCurrentTeb(); if (!teb) return 0; - if (!teb->queue) + if (!teb->queue && Callout.InitThreadInput16) Callout.InitThreadInput16( 0, THREAD_IsWin16(teb)? 4 : 5 ); if (!teb->queue) diff --git a/miscemu/main.c b/miscemu/main.c index b8bd8cdb601..da547d94148 100644 --- a/miscemu/main.c +++ b/miscemu/main.c @@ -23,6 +23,13 @@ void wine_initial_task(void) HINSTANCE16 instance; STARTUPINFOA info; + if (!LoadLibraryA( "user32.dll" )) + { + MESSAGE( "Cannot load user32.dll\n" ); + ExitProcess( GetLastError() ); + } + THUNK_InitCallout(); + GetStartupInfoA( &info ); if (!(info.dwFlags & STARTF_USESHOWWINDOW)) info.wShowWindow = SW_SHOWNORMAL; diff --git a/objects/palette.c b/objects/palette.c index 46558190e1f..3a634aa6a27 100644 --- a/objects/palette.c +++ b/objects/palette.c @@ -787,14 +787,16 @@ INT16 WINAPI UpdateColors16( HDC16 hDC ) if (!(dc = DC_GetDCPtr( hDC ))) return 0; size = dc->devCaps->sizePalette; GDI_ReleaseObj( hDC ); - hWnd = Callout.WindowFromDC( hDC ); - - /* Docs say that we have to remap current drawable pixel by pixel - * but it would take forever given the speed of XGet/PutPixel. - */ - if (hWnd && size) - Callout.RedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE ); + if (Callout.WindowFromDC) + { + hWnd = Callout.WindowFromDC( hDC ); + /* Docs say that we have to remap current drawable pixel by pixel + * but it would take forever given the speed of XGet/PutPixel. + */ + if (hWnd && size) + Callout.RedrawWindow( hWnd, NULL, 0, RDW_INVALIDATE ); + } return 0x666; } diff --git a/scheduler/process.c b/scheduler/process.c index 44a56cd1a41..f6bc48a875b 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -236,39 +236,6 @@ static BOOL process_init( char *argv[] ) } -/*********************************************************************** - * load_system_dlls - * - * Load system DLLs into the initial process (and initialize them) - */ -static int load_system_dlls(void) -{ - /* Load KERNEL */ - if (!LoadLibraryA( "KERNEL32" )) return 0; - - /* Get pointers to USER routines called by KERNEL */ - THUNK_InitCallout(); - - /* Call FinalUserInit routine */ - Callout.FinalUserInit16(); - - /* Note: The USIG_PROCESS_CREATE signal is supposed to be sent in the - * context of the parent process. Actually, the USER signal proc - * doesn't really care about that, but it *does* require that the - * startup parameters are correctly set up, so that GetProcessDword - * works. Furthermore, before calling the USER signal proc the - * 16-bit stack must be set up, which it is only after TASK_Create - * in the case of a 16-bit process. Thus, we send the signal here. - */ - PROCESS_CallUserSignalProc( USIG_PROCESS_CREATE, 0 ); - PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0 ); - PROCESS_CallUserSignalProc( USIG_PROCESS_INIT, 0 ); - PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0 ); - - return 1; -} - - /*********************************************************************** * build_command_line * @@ -361,14 +328,29 @@ static void start_process(void) goto error; wm->refCount++; - /* Load the system dlls */ - if (!load_system_dlls()) goto error; - EnterCriticalSection( ¤t_process.crit_section ); PE_InitTls(); MODULE_DllProcessAttach( current_process.exe_modref, (LPVOID)1 ); LeaveCriticalSection( ¤t_process.crit_section ); + /* Get pointers to USER routines called by KERNEL */ + THUNK_InitCallout(); + + /* Call FinalUserInit routine */ + if (Callout.FinalUserInit16) Callout.FinalUserInit16(); + + /* Note: The USIG_PROCESS_CREATE signal is supposed to be sent in the + * context of the parent process. Actually, the USER signal proc + * doesn't really care about that, but it *does* require that the + * startup parameters are correctly set up, so that GetProcessDword + * works. Furthermore, before calling the USER signal proc the + * 16-bit stack must be set up, which it is only after TASK_Create + * in the case of a 16-bit process. Thus, we send the signal here. + */ + PROCESS_CallUserSignalProc( USIG_PROCESS_CREATE, 0 ); + PROCESS_CallUserSignalProc( USIG_THREAD_INIT, 0 ); + PROCESS_CallUserSignalProc( USIG_PROCESS_INIT, 0 ); + PROCESS_CallUserSignalProc( USIG_PROCESS_LOADED, 0 ); /* Call UserSignalProc ( USIG_PROCESS_RUNNING ... ) only for non-GUI win32 apps */ if (console_app) PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0 ); diff --git a/scheduler/thread.c b/scheduler/thread.c index 9647432654a..4b0f128a719 100644 --- a/scheduler/thread.c +++ b/scheduler/thread.c @@ -374,7 +374,7 @@ void WINAPI ExitThread( DWORD code ) /* [in] Exit code for this thread */ else { MODULE_DllThreadDetach( NULL ); - if (!(NtCurrentTeb()->tibflags & TEBF_WIN32)) TASK_KillTask( 0 ); + if (!(NtCurrentTeb()->tibflags & TEBF_WIN32)) TASK_ExitTask(); SYSDEPS_ExitThread( code ); } } diff --git a/win32/except.c b/win32/except.c index ecfe9331f60..4ed10333e61 100644 --- a/win32/except.c +++ b/win32/except.c @@ -282,7 +282,10 @@ void WINAPI FatalAppExit16( UINT16 action, LPCSTR str ) void WINAPI FatalAppExitA( UINT action, LPCSTR str ) { WARN("AppExit\n"); - Callout.MessageBoxA( 0, str, NULL, MB_SYSTEMMODAL | MB_OK ); + if (Callout.MessageBoxA) + Callout.MessageBoxA( 0, str, NULL, MB_SYSTEMMODAL | MB_OK ); + else + ERR( "%s\n", debugstr_a(str) ); ExitProcess(0); } @@ -293,6 +296,9 @@ void WINAPI FatalAppExitA( UINT action, LPCSTR str ) void WINAPI FatalAppExitW( UINT action, LPCWSTR str ) { WARN("AppExit\n"); - Callout.MessageBoxW( 0, str, NULL, MB_SYSTEMMODAL | MB_OK ); + if (Callout.MessageBoxW) + Callout.MessageBoxW( 0, str, NULL, MB_SYSTEMMODAL | MB_OK ); + else + ERR( "%s\n", debugstr_w(str) ); ExitProcess(0); }