mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-02 12:03:45 +00:00
Implemented WaitForInputIdle.
This commit is contained in:
parent
f1f68312e7
commit
6619f5a71a
8 changed files with 142 additions and 19 deletions
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue