mirror of
https://github.com/UzixLS/KernelEx.git
synced 2025-07-19 07:21:20 +03:00
import KernelEx-4.5-RC5
This commit is contained in:
164
apilibs/kexbasen/ole32/CoWaitForMultipleHandles.c
Executable file
164
apilibs/kexbasen/ole32/CoWaitForMultipleHandles.c
Executable file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* KernelEx
|
||||
* Copyright 2010, Tihiy
|
||||
*
|
||||
* Copyright 1995 Martin von Loewis
|
||||
* Copyright 1998 Justin Bradford
|
||||
* Copyright 1999 Francis Beaudet
|
||||
* Copyright 1999 Sylvain St-Germain
|
||||
* Copyright 2002 Marcus Meissner
|
||||
* Copyright 2004 Mike Hearn
|
||||
* Copyright 2005-2006 Robert Shearman (for CodeWeavers)
|
||||
*
|
||||
* This file is part of KernelEx source code.
|
||||
*
|
||||
* KernelEx is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published
|
||||
* by the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* KernelEx is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Make; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#define COBJMACROS
|
||||
#define CINTERFACE
|
||||
#include <windows.h>
|
||||
#include "kexcoresdk.h"
|
||||
|
||||
#define COFLAGS_APARTMENTTHREADED 0x80
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DWORD Unknown; //+0x00
|
||||
DWORD dwCOMFlags; //+0x04
|
||||
BYTE filler[0x40]; //+0x08
|
||||
IMessageFilter *filter; //+0x48
|
||||
} APARTMENT, *PAPARTMENT;
|
||||
|
||||
|
||||
static PAPARTMENT COM_CurrentApt()
|
||||
{
|
||||
DWORD** ppdwTlsIndex = (DWORD**)
|
||||
( (DWORD)kexGetProcAddress(GetModuleHandle("OLE32.DLL"),"CoGetState")+2 );
|
||||
return (PAPARTMENT)TlsGetValue(**ppdwTlsIndex);
|
||||
}
|
||||
|
||||
BOOL CALLBACK FindCOMWindow( HWND hwnd, LPARAM lParam )
|
||||
{
|
||||
char wndname[200];
|
||||
if ( GetWindowTextA(hwnd,wndname,200) && strcmp(wndname,"OleMainThreadWndName") == 0
|
||||
&& (HINSTANCE)GetWindowLongA(hwnd,GWL_HINSTANCE) == GetModuleHandle("OLE32.DLL") )
|
||||
{
|
||||
*(PHANDLE)lParam = hwnd;
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* processes COM messages, returns FALSE if thread quits */
|
||||
static BOOL COM_PumpMessages()
|
||||
{
|
||||
HWND comWindow = NULL;
|
||||
EnumThreadWindows(GetCurrentThreadId(),FindCOMWindow,(LPARAM)&comWindow);
|
||||
MSG msg;
|
||||
BOOL haveMsgs =
|
||||
PeekMessageA(&msg, comWindow, WM_USER, WM_APP - 1, PM_REMOVE|PM_NOYIELD) ||
|
||||
/* next retrieve other messages necessary for the app to remain responsive */
|
||||
PeekMessageA(&msg, NULL, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE|PM_NOYIELD) ||
|
||||
PeekMessageA(&msg, NULL, 0, 0, PM_QS_PAINT|PM_QS_SENDMESSAGE|PM_REMOVE|PM_NOYIELD);
|
||||
if (haveMsgs)
|
||||
{
|
||||
DispatchMessage(&msg);
|
||||
if (msg.message == WM_QUIT) //resend
|
||||
{
|
||||
PostQuitMessage(msg.wParam);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* MAKE_EXPORT CoWaitForMultipleHandles_new=CoWaitForMultipleHandles */
|
||||
HRESULT WINAPI CoWaitForMultipleHandles_new(
|
||||
DWORD dwFlags,
|
||||
DWORD dwTimeout,
|
||||
ULONG cHandles,
|
||||
LPHANDLE pHandles,
|
||||
LPDWORD lpdwindex
|
||||
)
|
||||
{
|
||||
if (!pHandles || !lpdwindex)
|
||||
return E_INVALIDARG;
|
||||
|
||||
HRESULT hr = S_OK;
|
||||
DWORD start_time = GetTickCount();
|
||||
PAPARTMENT apt = COM_CurrentApt();
|
||||
BOOL message_loop = apt && (apt->dwCOMFlags & COFLAGS_APARTMENTTHREADED);
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
DWORD now = GetTickCount();
|
||||
DWORD res;
|
||||
if (now - start_time > dwTimeout)
|
||||
{
|
||||
hr = RPC_S_CALLPENDING;
|
||||
break;
|
||||
}
|
||||
if (message_loop)
|
||||
{
|
||||
DWORD wait_flags = ((dwFlags & COWAIT_WAITALL) ? MWMO_WAITALL : 0) |
|
||||
((dwFlags & COWAIT_ALERTABLE ) ? MWMO_ALERTABLE : 0);
|
||||
|
||||
res = MsgWaitForMultipleObjectsEx(cHandles,pHandles,
|
||||
(dwTimeout == INFINITE) ? INFINITE : start_time + dwTimeout - now,
|
||||
QS_ALLINPUT,wait_flags);
|
||||
|
||||
if (res == WAIT_OBJECT_0 + cHandles) /* messages available */
|
||||
{
|
||||
if (apt->filter) /* call message filter */
|
||||
{
|
||||
//don't know htask or pendingtype :(
|
||||
DWORD handled = IMessageFilter_MessagePending(apt->filter,0,
|
||||
now-start_time,PENDINGTYPE_TOPLEVEL);
|
||||
if (handled == PENDINGMSG_CANCELCALL)
|
||||
hr = RPC_E_CALL_CANCELED;
|
||||
}
|
||||
message_loop = COM_PumpMessages();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
res = WaitForMultipleObjectsEx(cHandles,pHandles,
|
||||
(dwFlags & COWAIT_WAITALL) ? TRUE : FALSE,
|
||||
(dwTimeout == INFINITE) ? INFINITE : start_time + dwTimeout - now,
|
||||
(dwFlags & COWAIT_ALERTABLE) ? TRUE : FALSE);
|
||||
|
||||
}
|
||||
if (res < WAIT_OBJECT_0 + cHandles)
|
||||
{
|
||||
/* handle signaled, store index */
|
||||
*lpdwindex = (res - WAIT_OBJECT_0);
|
||||
break;
|
||||
}
|
||||
else if (res == WAIT_TIMEOUT)
|
||||
{
|
||||
hr = RPC_S_CALLPENDING;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
hr = E_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return hr;
|
||||
}
|
Reference in New Issue
Block a user