Commit 4e951ea2 authored by Alexandre Julliard's avatar Alexandre Julliard

Check all Callouts function pointers for NULL before using them.

Don't load USER dll if not needed by the application.
parent d3576a9f
......@@ -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;
}
......
......@@ -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);
}
}
......
......@@ -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");
}
......@@ -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 );
......
......@@ -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 );
......
......@@ -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());
}
......
......@@ -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 */
......
......@@ -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 );
/* When deleting the current task ... */
if ( hTask == hCurrentTask )
{
DWORD lockCount;
TASK_DeleteTask( pTask->hSelf );
/* ... schedule another one ... */
TASK_Reschedule();
/* ... and completely release the Win16Lock, just in case. */
ReleaseThunkLock( &lockCount );
return;
}
/* ... schedule another one ... */
TASK_Reschedule();
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)
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -237,39 +237,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
*
* Build the command line of a process from the argv array.
......@@ -361,14 +328,29 @@ static void start_process(void)
goto error;
wm->refCount++;
/* Load the system dlls */
if (!load_system_dlls()) goto error;
EnterCriticalSection( &current_process.crit_section );
PE_InitTls();
MODULE_DllProcessAttach( current_process.exe_modref, (LPVOID)1 );
LeaveCriticalSection( &current_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 );
......
......@@ -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 );
}
}
......
......@@ -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);
}
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