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)
GETADDR( DispatchMessageW, "DispatchMessageW" );
GETADDR( DispatchMessageA, "DispatchMessageA" );
GETADDR( RedrawWindow, "RedrawWindow" );
GETADDR( WaitForInputIdle, "WaitForInputIdle" );
#undef GETADDR
}
......
......@@ -103,6 +103,7 @@ typedef struct
HQUEUE16 WINAPI (*InitThreadInput16)( WORD unknown, WORD flags );
void WINAPI (*UserYield16)( void );
WORD WINAPI (*DestroyIcon32)( HGLOBAL16 handle, UINT16 flags );
DWORD WINAPI (*WaitForInputIdle)( HANDLE hProcess, DWORD dwTimeOut );
} CALLOUT_TABLE;
......
......@@ -96,6 +96,8 @@ typedef struct _PDB
struct _PDB *next; /* List reference - list of PDB's */
WORD winver; /* Windows version figured out by VERSION_GetVersion */
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;
/* Process flags */
......@@ -146,6 +148,7 @@ typedef struct _PDB
extern DWORD WINAPI GetProcessDword( DWORD dwProcessID, INT offset );
void WINAPI SetProcessDword( DWORD dwProcessID, INT offset, DWORD value );
extern DWORD WINAPI MapProcessHandle( HANDLE handle );
/* scheduler/environ.c */
extern BOOL ENV_InheritEnvironment( PDB *pdb, LPCSTR env );
......
......@@ -834,6 +834,10 @@ HINSTANCE WINAPI LoadModule( LPCSTR name, LPVOID paramBlock )
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 */
pdb = PROCESS_IdToPDB( info.dwProcessId );
tdb = pdb? (TDB *)GlobalLock16( pdb->task ) : NULL;
......@@ -1289,7 +1293,7 @@ HMODULE WINAPI GetModuleHandleW(LPCWSTR module)
/***********************************************************************
* GetModuleFileName32A (KERNEL32.235)
* GetModuleFileNameA (KERNEL32.235)
*/
DWORD WINAPI GetModuleFileNameA(
HMODULE hModule, /* [in] module handle (32bit) */
......
......@@ -313,6 +313,7 @@ static PDB *PROCESS_CreatePDB( PDB *parent, BOOL inherit )
pdb->heap = pdb->system_heap; /* will be changed later on */
pdb->next = PROCESS_First;
pdb->winver = 0xffff; /* to be determined */
pdb->main_queue = INVALID_HANDLE_VALUE16;
PROCESS_First = pdb;
return pdb;
}
......@@ -338,6 +339,7 @@ BOOL PROCESS_Init(void)
initial_pdb.priority = 8; /* Normal */
initial_pdb.flags = PDB32_WIN16_PROC;
initial_pdb.winver = 0xffff; /* to be determined */
initial_pdb.main_queue = INVALID_HANDLE_VALUE16;
/* Initialize virtual memory management */
if (!VIRTUAL_Init()) return FALSE;
......@@ -352,6 +354,14 @@ BOOL PROCESS_Init(void)
if (!(SystemHeap = HeapCreate( HEAP_GROWABLE, 0x10000, 0 ))) return FALSE;
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 */
if (!SIGNAL_Init()) return FALSE;
......@@ -485,8 +495,9 @@ void PROCESS_Start(void)
if ( Options.debug && TASK_AddTaskEntryBreakpoint )
TASK_AddTaskEntryBreakpoint( pdb->task );
/* Now call the entry point */
PROCESS_CallUserSignalProc( USIG_PROCESS_RUNNING, 0, 0 );
/* 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 );
switch ( type )
{
......
......@@ -1933,6 +1933,7 @@ DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE *pHandles,
DWORD i;
HANDLE handles[MAXIMUM_WAIT_OBJECTS];
DWORD ret;
PDB * pdb = PROCESS_Current();
HQUEUE16 hQueue = GetFastQueue16();
MESSAGEQUEUE *msgQueue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
......@@ -1968,6 +1969,7 @@ DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE *pHandles,
/*
* Check the handles in the list.
*/
SetEvent ( pdb->idle_event );
ret = WaitForMultipleObjects(nCount, pHandles, fWaitAll, 5L);
/*
......@@ -2000,9 +2002,13 @@ DWORD WINAPI MsgWaitForMultipleObjects( DWORD nCount, HANDLE *pHandles,
/* Add the thread event to the handle list */
for (i = 0; i < nCount; 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 );
if ( pdb->main_queue == hQueue ) ResetEvent ( pdb->idle_event );
ret = WaitForMultipleObjects( nCount+1, handles, fWaitAll, dwMilliseconds );
}
QUEUE_Unlock( msgQueue );
......@@ -2488,8 +2494,7 @@ DWORD WINAPI GetTickCount(void)
{
struct timeval t;
gettimeofday( &t, NULL );
/* make extremely compatible: granularity is 25 msec */
return ((t.tv_sec * 1000) + (t.tv_usec / 25000) * 25) - MSG_WineStartTicks;
return ((t.tv_sec * 1000) + (t.tv_usec / 1000)) - MSG_WineStartTicks;
}
......
......@@ -5,6 +5,7 @@
#include <string.h>
#include <signal.h>
#include <assert.h>
#include "wine/winbase16.h"
#include "wine/winuser16.h"
#include "miscemu.h"
......@@ -18,7 +19,6 @@
#include "heap.h"
#include "thread.h"
#include "process.h"
#include <assert.h>
#include "debugtools.h"
#include "spy.h"
......@@ -467,7 +467,7 @@ static HQUEUE16 QUEUE_CreateMsgQueue( BOOL16 bCreatePerQData )
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;
}
msgQueue->hEvent = ConvertToGlobalHandle( msgQueue->hEvent );
......@@ -672,14 +672,19 @@ int QUEUE_WaitBits( WORD bits, DWORD timeout )
{
MESSAGEQUEUE *queue;
DWORD curTime = 0;
HQUEUE16 hQueue;
PDB * pdb;
TRACE_(msg)("q %04x waiting for %04x\n", GetFastQueue16(), bits);
if ( THREAD_IsWin16( NtCurrentTeb() ) && (timeout != INFINITE) )
curTime = GetTickCount();
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( GetFastQueue16() ))) return 0;
hQueue = GetFastQueue16();
if (!(queue = (MESSAGEQUEUE *)QUEUE_Lock( hQueue ))) return 0;
pdb = PROCESS_Current();
for (;;)
{
if (queue->changeBits & bits)
......@@ -716,7 +721,24 @@ int QUEUE_WaitBits( WORD bits, DWORD timeout )
TRACE_(msg)("bHasWin16Lock=TRUE\n");
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 );
if ( pdb->main_queue == hQueue )
{
ResetEvent ( pdb->idle_event );
}
if ( bHasWin16Lock )
{
RestoreThunkLock( dwlc );
......@@ -724,6 +746,8 @@ int QUEUE_WaitBits( WORD bits, DWORD timeout )
}
else
{
SetEvent ( pdb->idle_event );
if ( timeout == INFINITE )
WaitEvent16( 0 ); /* win 16 thread, use WaitEvent */
else
......@@ -1395,7 +1419,7 @@ BOOL16 WINAPI SetMessageQueue16( INT16 size )
/***********************************************************************
* SetMessageQueue32 (USER32.494)
* SetMessageQueue (USER32.494)
*/
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 )
{
......@@ -1430,7 +1454,7 @@ HQUEUE16 WINAPI InitThreadInput16( WORD unknown, WORD flags )
{
WARN_(msg)("failed!\n");
return FALSE;
}
}
/* Link new queue into list */
queuePtr = (MESSAGEQUEUE *)QUEUE_Lock( hQueue );
......@@ -1496,12 +1520,54 @@ BOOL16 WINAPI GetInputState16(void)
*/
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;
}
/***********************************************************************
* GetInputState32 (USER32.244)
*/
......
......@@ -207,7 +207,9 @@ void WINAPI FinalUserInit16( void )
WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
DWORD dwFlags, HMODULE16 hModule )
{
static HANDLE win16_idle_event;
HINSTANCE16 hInst;
PDB * pdb;
/* FIXME: Proper reaction to most signals still missing. */
......@@ -234,18 +236,48 @@ WORD WINAPI UserSignalProc( UINT uCode, DWORD dwThreadOrProcessID,
break;
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_LOADED:
break;
case USIG_PROCESS_RUNNING:
pdb = PROCESS_IdToPDB ( dwThreadOrProcessID );
SetEvent ( pdb->idle_event );
break;
case USIG_PROCESS_EXIT:
break;
case USIG_PROCESS_DESTROY:
hInst = GetProcessDword( dwThreadOrProcessID, GPD_HINSTANCE16 );
USER_AppExit( hInst );
break;
case USIG_PROCESS_DESTROY:
hInst = GetProcessDword( dwThreadOrProcessID, GPD_HINSTANCE16 );
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;
default:
FIXME_(win)("(%04x, %08lx, %04lx, %04x)\n",
......
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