Commit 6619f5a7 authored by Peter Ganten's avatar Peter Ganten Committed by Alexandre Julliard

Implemented WaitForInputIdle.

parent f1f68312
...@@ -375,6 +375,7 @@ void THUNK_InitCallout(void) ...@@ -375,6 +375,7 @@ void THUNK_InitCallout(void)
GETADDR( DispatchMessageW, "DispatchMessageW" ); GETADDR( DispatchMessageW, "DispatchMessageW" );
GETADDR( DispatchMessageA, "DispatchMessageA" ); GETADDR( DispatchMessageA, "DispatchMessageA" );
GETADDR( RedrawWindow, "RedrawWindow" ); GETADDR( RedrawWindow, "RedrawWindow" );
GETADDR( WaitForInputIdle, "WaitForInputIdle" );
#undef GETADDR #undef GETADDR
} }
......
...@@ -103,6 +103,7 @@ typedef struct ...@@ -103,6 +103,7 @@ typedef struct
HQUEUE16 WINAPI (*InitThreadInput16)( WORD unknown, WORD flags ); HQUEUE16 WINAPI (*InitThreadInput16)( WORD unknown, WORD flags );
void WINAPI (*UserYield16)( void ); void WINAPI (*UserYield16)( void );
WORD WINAPI (*DestroyIcon32)( HGLOBAL16 handle, UINT16 flags ); WORD WINAPI (*DestroyIcon32)( HGLOBAL16 handle, UINT16 flags );
DWORD WINAPI (*WaitForInputIdle)( HANDLE hProcess, DWORD dwTimeOut );
} CALLOUT_TABLE; } CALLOUT_TABLE;
......
...@@ -96,6 +96,8 @@ typedef struct _PDB ...@@ -96,6 +96,8 @@ typedef struct _PDB
struct _PDB *next; /* List reference - list of PDB's */ struct _PDB *next; /* List reference - list of PDB's */
WORD winver; /* Windows version figured out by VERSION_GetVersion */ WORD winver; /* Windows version figured out by VERSION_GetVersion */
struct _SERVICETABLE *service_table; /* Service table for service thread */ struct _SERVICETABLE *service_table; /* Service table for service thread */
HANDLE idle_event; /* event to signal, when the process is idle */
HANDLE16 main_queue; /* main message queue of the process */
} PDB; } PDB;
/* Process flags */ /* Process flags */
...@@ -146,6 +148,7 @@ typedef struct _PDB ...@@ -146,6 +148,7 @@ typedef struct _PDB
extern DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset ); extern DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset );
void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value ); void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value );
extern DWORD WINAPI MapProcessHandle( HANDLE handle );
/* scheduler/environ.c */ /* scheduler/environ.c */
extern BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env ); extern BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env );
......
...@@ -834,6 +834,10 @@ HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock ) ...@@ -834,6 +834,10 @@ HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
return 11; return 11;
} }
/* Give 30 seconds to the app to come up */
if ( Callout.WaitForInputIdle ( info.hProcess, 30000 ) == 0xFFFFFFFF )
WARN("WaitForInputIdle failed: Error %ld\n", GetLastError() );
/* Get 16-bit hInstance/hTask from process */ /* Get 16-bit hInstance/hTask from process */
pdb = PROCESS_IdToPDB( info.dwProcessId ); pdb = PROCESS_IdToPDB( info.dwProcessId );
tdb = pdb? (TDB *)GlobalLock16( pdb->task ) : NULL; tdb = pdb? (TDB *)GlobalLock16( pdb->task ) : NULL;
...@@ -1289,7 +1293,7 @@ HMODULE WINAPI GetModuleHandleW(LPCWSTR module) ...@@ -1289,7 +1293,7 @@ HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
/*********************************************************************** /***********************************************************************
* GetModuleFileName32A (KERNEL32.235) * GetModuleFileNameA (KERNEL32.235)
*/ */
DWORD WINAPI GetModuleFileNameA( DWORD WINAPI GetModuleFileNameA(
HMODULE hModule, /* [in] module handle (32bit) */ HMODULE hModule, /* [in] module handle (32bit) */
......
...@@ -313,6 +313,7 @@ static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit ) ...@@ -313,6 +313,7 @@ static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit )
pdb->heap = pdb->system_heap; /* will be changed later on */ pdb->heap = pdb->system_heap; /* will be changed later on */
pdb->next = PROCESS_First; pdb->next = PROCESS_First;
pdb->winver = 0xffff; /* to be determined */ pdb->winver = 0xffff; /* to be determined */
pdb->main_queue = INVALID_HANDLE_VALUE16;
PROCESS_First = pdb; PROCESS_First = pdb;
return pdb; return pdb;
} }
...@@ -338,6 +339,7 @@ BOOL PROCESS_Init(void) ...@@ -338,6 +339,7 @@ BOOL PROCESS_Init(void)
initial_pdb.priority = 8; /* Normal */ initial_pdb.priority = 8; /* Normal */
initial_pdb.flags = PDB32_WIN16_PROC; initial_pdb.flags = PDB32_WIN16_PROC;
initial_pdb.winver = 0xffff; /* to be determined */ initial_pdb.winver = 0xffff; /* to be determined */
initial_pdb.main_queue = INVALID_HANDLE_VALUE16;
/* Initialize virtual memory management */ /* Initialize virtual memory management */
if (!VIRTUAL_Init()) return FALSE; if (!VIRTUAL_Init()) return FALSE;
...@@ -352,6 +354,14 @@ BOOL PROCESS_Init(void) ...@@ -352,6 +354,14 @@ BOOL PROCESS_Init(void)
if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE; if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
initial_pdb.system_heap = initial_pdb.heap = SystemHeap; initial_pdb.system_heap = initial_pdb.heap = SystemHeap;
/* Create the idle event for the initial process
FIXME 1: Shouldn't we call UserSignalProc for the initial process too?
FIXME 2: It seems to me that the initial pdb becomes never freed, so I don't now
where to release the idle event for the initial process.
*/
initial_pdb.idle_event = CreateEventA ( NULL, TRUE, FALSE, NULL );
initial_pdb.idle_event = ConvertToGlobalHandle ( initial_pdb.idle_event );
/* Initialize signal handling */ /* Initialize signal handling */
if (!SIGNAL_Init()) return FALSE; if (!SIGNAL_Init()) return FALSE;
...@@ -485,7 +495,8 @@ void PROCESS_Start(void) ...@@ -485,7 +495,8 @@ void PROCESS_Start(void)
if ( Options.debug && TASK_AddTaskEntryBreakpoint ) if ( Options.debug && TASK_AddTaskEntryBreakpoint )
TASK_AddTaskEntryBreakpoint( pdb->task ); TASK_AddTaskEntryBreakpoint( pdb->task );
/* Now call the entry point */ /* Call UserSignalProc ( USIG_PROCESS_RUNNING ... ) only for non-GUI win32 apps */
if ( type != PROC_WIN16 && (pdb->flags & PDB32_CONSOLE_PROC))
PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0, 0 ); PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0, 0 );
switch ( type ) switch ( type )
......
...@@ -1933,6 +1933,7 @@ DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE *pHandles, ...@@ -1933,6 +1933,7 @@ DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE *pHandles,
DWORD i; DWORD i;
HANDLE handles[MAXIMUM_WAIT_OBJECTS]; HANDLE handles[MAXIMUM_WAIT_OBJECTS];
DWORD ret; DWORD ret;
PDB * pdb = PROCESS_Current();
HQUEUE16 hQueue = GetFastQueue16(); HQUEUE16 hQueue = GetFastQueue16();
MESSAGEQUEUE *msgQueue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue ); MESSAGEQUEUE *msgQueue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
...@@ -1968,6 +1969,7 @@ DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE *pHandles, ...@@ -1968,6 +1969,7 @@ DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE *pHandles,
/* /*
* Check the handles in the list. * Check the handles in the list.
*/ */
SetEvent ( pdb->idle_event );
ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, 5L); ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, 5L);
/* /*
...@@ -2002,7 +2004,11 @@ DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE *pHandles, ...@@ -2002,7 +2004,11 @@ DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE *pHandles,
handles[i] = pHandles[i]; handles[i] = pHandles[i];
handles[nCount] = msgQueue->hEvent; handles[nCount] = msgQueue->hEvent;
if ( pdb->main_queue == INVALID_HANDLE_VALUE16 ) pdb->main_queue = hQueue;
if ( pdb->main_queue == hQueue ) SetEvent ( pdb->idle_event );
ret = WaitForMultipleObjects( nCount+1, handles, fWaitAll, dwMilliseconds ); ret = WaitForMultipleObjects( nCount+1, handles, fWaitAll, dwMilliseconds );
if ( pdb->main_queue == hQueue ) ResetEvent ( pdb->idle_event );
} }
QUEUE_Unlock( msgQueue ); QUEUE_Unlock( msgQueue );
...@@ -2488,8 +2494,7 @@ DWORD WINAPI GetTickCount(void) ...@@ -2488,8 +2494,7 @@ DWORD WINAPI GetTickCount(void)
{ {
struct timeval t; struct timeval t;
gettimeofday( &t, NULL ); gettimeofday( &t, NULL );
/* make extremely compatible: granularity is 25 msec */ return ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - MSG_WineStartTicks;
return ((t.tv_sec * 1000) + (t.tv_usec / 25000) * 25) - MSG_WineStartTicks;
} }
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include <string.h> #include <string.h>
#include <signal.h> #include <signal.h>
#include <assert.h>
#include "wine/winbase16.h" #include "wine/winbase16.h"
#include "wine/winuser16.h" #include "wine/winuser16.h"
#include "miscemu.h" #include "miscemu.h"
...@@ -18,7 +19,6 @@ ...@@ -18,7 +19,6 @@
#include "heap.h" #include "heap.h"
#include "thread.h" #include "thread.h"
#include "process.h" #include "process.h"
#include <assert.h>
#include "debugtools.h" #include "debugtools.h"
#include "spy.h" #include "spy.h"
...@@ -467,7 +467,7 @@ static HQUEUE16 QUEUE_CreateMsgQueue( BOOL16 bCreatePerQData ) ...@@ -467,7 +467,7 @@ static HQUEUE16 QUEUE_CreateMsgQueue( BOOL16 bCreatePerQData )
if (msgQueue->hEvent == 0) if (msgQueue->hEvent == 0)
{ {
WARN_(msg)("CreateEvent32A is not able to create an event object"); WARN_(msg)("CreateEventA is not able to create an event object");
return 0; return 0;
} }
msgQueue->hEvent = ConvertToGlobalHandle( msgQueue->hEvent ); msgQueue->hEvent = ConvertToGlobalHandle( msgQueue->hEvent );
...@@ -672,13 +672,18 @@ int QUEUE_WaitBits( WORD bits, DWORD timeout ) ...@@ -672,13 +672,18 @@ int QUEUE_WaitBits( WORD bits, DWORD timeout )
{ {
MESSAGEQUEUE *queue; MESSAGEQUEUE *queue;
DWORD curTime = 0; DWORD curTime = 0;
HQUEUE16 hQueue;
PDB * pdb;
TRACE_(msg)("q %04x waiting for %04x\n", GetFastQueue16(), bits); TRACE_(msg)("q %04x waiting for %04x\n", GetFastQueue16(), bits);
if ( THREAD_IsWin16( NtCurrentTeb() ) && (timeout != INFINITE) ) if ( THREAD_IsWin16( NtCurrentTeb() ) && (timeout != INFINITE) )
curTime = GetTickCount(); curTime = GetTickCount();
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0; hQueue = GetFastQueue16();
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue ))) return 0;
pdb = PROCESS_Current();
for (;;) for (;;)
{ {
...@@ -716,7 +721,24 @@ int QUEUE_WaitBits( WORD bits, DWORD timeout ) ...@@ -716,7 +721,24 @@ int QUEUE_WaitBits( WORD bits, DWORD timeout )
TRACE_(msg)("bHasWin16Lock=TRUE\n"); TRACE_(msg)("bHasWin16Lock=TRUE\n");
ReleaseThunkLock( &dwlc ); ReleaseThunkLock( &dwlc );
} }
if ( pdb->main_queue == INVALID_HANDLE_VALUE16 )
{
pdb->main_queue = hQueue;
}
if ( pdb->main_queue == hQueue )
{
SetEvent ( pdb->idle_event );
}
WaitForSingleObject( queue->hEvent, timeout ); WaitForSingleObject( queue->hEvent, timeout );
if ( pdb->main_queue == hQueue )
{
ResetEvent ( pdb->idle_event );
}
if ( bHasWin16Lock ) if ( bHasWin16Lock )
{ {
RestoreThunkLock( dwlc ); RestoreThunkLock( dwlc );
...@@ -724,6 +746,8 @@ int QUEUE_WaitBits( WORD bits, DWORD timeout ) ...@@ -724,6 +746,8 @@ int QUEUE_WaitBits( WORD bits, DWORD timeout )
} }
else else
{ {
SetEvent ( pdb->idle_event );
if ( timeout == INFINITE ) if ( timeout == INFINITE )
WaitEvent16( 0 ); /* win 16 thread, use WaitEvent */ WaitEvent16( 0 ); /* win 16 thread, use WaitEvent */
else else
...@@ -1395,7 +1419,7 @@ BOOL16 WINAPI SetMessageQueue16( INT16 size ) ...@@ -1395,7 +1419,7 @@ BOOL16 WINAPI SetMessageQueue16( INT16 size )
/*********************************************************************** /***********************************************************************
* SetMessageQueue32 (USER32.494) * SetMessageQueue (USER32.494)
*/ */
BOOL WINAPI SetMessageQueue( INT size ) BOOL WINAPI SetMessageQueue( INT size )
{ {
...@@ -1409,7 +1433,7 @@ BOOL WINAPI SetMessageQueue( INT size ) ...@@ -1409,7 +1433,7 @@ BOOL WINAPI SetMessageQueue( INT size )
} }
/*********************************************************************** /***********************************************************************
* InitThreadInput (USER.409) * InitThreadInput16 (USER.409)
*/ */
HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags ) HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
{ {
...@@ -1496,12 +1520,54 @@ BOOL16 WINAPI GetInputState16(void) ...@@ -1496,12 +1520,54 @@ BOOL16 WINAPI GetInputState16(void)
*/ */
DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut) DWORD WINAPI WaitForInputIdle (HANDLE hProcess, DWORD dwTimeOut)
{ {
FIXME_(msg)("(hProcess=%d, dwTimeOut=%ld): stub\n", hProcess, dwTimeOut); PDB * pdb;
DWORD cur_time, ret, pid = MapProcessHandle ( hProcess );
/* Check whether the calling process is a command line application */
if (!THREAD_IsWin16(NtCurrentTeb() ) &&
(PROCESS_Current()->flags & PDB32_CONSOLE_PROC))
{
TRACE_(msg)("not a win32 GUI application!\n" );
return 0;
}
pdb = PROCESS_IdToPDB( pid );
/* check whether we are waiting for a win32 process or the win16 subsystem */
if ( pdb->flags & PDB32_WIN16_PROC ) {
if ( THREAD_IsWin16(NtCurrentTeb()) ) return 0;
}
else { /* target is win32 */
if ( pdb->flags & PDB32_CONSOLE_PROC ) return 0;
if ( GetFastQueue16() == pdb->main_queue ) return 0;
}
cur_time = GetTickCount();
TRACE_(msg)("waiting for %x\n", pdb->idle_event );
while ( dwTimeOut > GetTickCount() - cur_time || dwTimeOut == INFINITE ) {
ret = MsgWaitForMultipleObjects ( 1, &pdb->idle_event, FALSE, dwTimeOut, QS_SENDMESSAGE );
if ( ret == ( WAIT_OBJECT_0 + 1 )) {
MESSAGEQUEUE * queue;
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0xFFFFFFFF;
QUEUE_ReceiveMessage ( queue );
QUEUE_Unlock ( queue );
continue;
}
if ( ret == WAIT_TIMEOUT || ret == 0xFFFFFFFF ) {
TRACE_(msg)("timeout or error\n");
return ret;
}
else {
TRACE_(msg)("finished\n");
return 0;
}
}
return WAIT_TIMEOUT; return WAIT_TIMEOUT;
} }
/*********************************************************************** /***********************************************************************
* GetInputState32 (USER32.244) * GetInputState32 (USER32.244)
*/ */
......
...@@ -207,7 +207,9 @@ void WINAPI FinalUserInit16( void ) ...@@ -207,7 +207,9 @@ void WINAPI FinalUserInit16( void )
WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID, WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
DWORD dwFlags, HMODULE16 hModule ) DWORD dwFlags, HMODULE16 hModule )
{ {
static HANDLE win16_idle_event;
HINSTANCE16 hInst; HINSTANCE16 hInst;
PDB * pdb;
/* FIXME: Proper reaction to most signals still missing. */ /* FIXME: Proper reaction to most signals still missing. */
...@@ -234,9 +236,33 @@ WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID, ...@@ -234,9 +236,33 @@ WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
break; break;
case USIG_PROCESS_CREATE: case USIG_PROCESS_CREATE:
pdb = PROCESS_IdToPDB( dwThreadOrProcessID );
/* Create the idle event for the process. We have just one idle_event for all
win16 processes, while each win32 process has its own */
if ( pdb->flags & PDB32_WIN16_PROC )
{
if (!win16_idle_event)
{
win16_idle_event = CreateEventA ( NULL, TRUE, FALSE, NULL );
win16_idle_event = ConvertToGlobalHandle ( win16_idle_event );
}
pdb->idle_event = win16_idle_event;
}
else { /* win32 process */
pdb->idle_event = CreateEventA ( NULL, TRUE, FALSE, NULL );
pdb->idle_event = ConvertToGlobalHandle ( pdb->idle_event );
TRACE_(win)("created win32 idle event: %x\n", pdb->idle_event );
}
break;
case USIG_PROCESS_INIT: case USIG_PROCESS_INIT:
case USIG_PROCESS_LOADED: case USIG_PROCESS_LOADED:
break;
case USIG_PROCESS_RUNNING: case USIG_PROCESS_RUNNING:
pdb = PROCESS_IdToPDB ( dwThreadOrProcessID );
SetEvent ( pdb->idle_event );
break; break;
case USIG_PROCESS_EXIT: case USIG_PROCESS_EXIT:
...@@ -245,6 +271,12 @@ WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID, ...@@ -245,6 +271,12 @@ WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
case USIG_PROCESS_DESTROY: case USIG_PROCESS_DESTROY:
hInst = GetProcessDword( dwThreadOrProcessID, GPD_HINSTANCE16 ); hInst = GetProcessDword( dwThreadOrProcessID, GPD_HINSTANCE16 );
USER_AppExit( hInst ); USER_AppExit( hInst );
pdb = PROCESS_IdToPDB( dwThreadOrProcessID );
if ( ! (pdb->flags & PDB32_WIN16_PROC) ) {
TRACE_(win)("destroying win32 idle event: %x\n", pdb->idle_event );
CloseHandle ( pdb->idle_event );
}
break; break;
default: default:
......
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