Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 19 +++++++++++++++++++ dlls/combase/combase.spec | 2 +- dlls/ole32/compobj.c | 29 ----------------------------- dlls/ole32/ole32.spec | 2 +- 4 files changed, 21 insertions(+), 31 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index cceb36a5931..c4a7f719129 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -1387,3 +1387,22 @@ void WINAPI DECLSPEC_HOTPATCH CoFreeUnusedLibraries(void) { CoFreeUnusedLibrariesEx(INFINITE, 0); } + +/*********************************************************************** + * CoGetCallContext (combase.@) + */ +HRESULT WINAPI CoGetCallContext(REFIID riid, void **obj) +{ + struct tlsdata *tlsdata; + HRESULT hr; + + TRACE("%s, %p\n", debugstr_guid(riid), obj); + + if (FAILED(hr = com_get_tlsdata(&tlsdata))) + return hr; + + if (!tlsdata->call_state) + return RPC_E_CALL_COMPLETE; + + return IUnknown_QueryInterface(tlsdata->call_state, riid, obj); +} diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 8a91088ca4e..8293c9de259 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -97,7 +97,7 @@ @ stdcall CoGetActivationState(int128 long ptr) @ stub CoGetApartmentID @ stdcall CoGetApartmentType(ptr ptr) ole32.CoGetApartmentType -@ stdcall CoGetCallContext(ptr ptr) ole32.CoGetCallContext +@ stdcall CoGetCallContext(ptr ptr) @ stdcall CoGetCallState(long ptr) @ stdcall CoGetCallerTID(ptr) ole32.CoGetCallerTID @ stub CoGetCancelObject diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 350508ac9a3..2dc2d417e07 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -3458,35 +3458,6 @@ HRESULT WINAPI CoAllowSetForegroundWindow(IUnknown *pUnk, void *pvReserved) return S_OK; }
-/*********************************************************************** - * CoGetCallContext [OLE32.@] - * - * Gets the context of the currently executing server call in the current - * thread. - * - * PARAMS - * riid [I] Context interface to return. - * ppv [O] Pointer to memory that will receive the context on return. - * - * RETURNS - * Success: S_OK. - * Failure: HRESULT code. - */ -HRESULT WINAPI CoGetCallContext(REFIID riid, void **ppv) -{ - struct oletls *info = COM_CurrentInfo(); - - TRACE("(%s, %p)\n", debugstr_guid(riid), ppv); - - if (!info) - return E_OUTOFMEMORY; - - if (!info->call_state) - return RPC_E_CALL_COMPLETE; - - return IUnknown_QueryInterface(info->call_state, riid, ppv); -} - /*********************************************************************** * CoSwitchCallContext [OLE32.@] * diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index f21f6429ca5..43237550195 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -27,7 +27,7 @@ @ stdcall CoFreeUnusedLibrariesEx(long long) @ stdcall CoGetActivationState(int128 long ptr) combase.CoGetActivationState @ stdcall CoGetApartmentType(ptr ptr) -@ stdcall CoGetCallContext(ptr ptr) +@ stdcall CoGetCallContext(ptr ptr) combase.CoGetCallContext @ stdcall CoGetCallState(long ptr) combase.CoGetCallState @ stdcall CoGetCallerTID(ptr) @ stdcall CoGetClassObject(ptr long ptr ptr ptr)
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 20 ++++++++++++++++++++ dlls/combase/combase.spec | 2 +- dlls/ole32/compobj.c | 29 ----------------------------- dlls/ole32/ole32.spec | 2 +- 4 files changed, 22 insertions(+), 31 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index c4a7f719129..52a159d7fe2 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -1406,3 +1406,23 @@ HRESULT WINAPI CoGetCallContext(REFIID riid, void **obj)
return IUnknown_QueryInterface(tlsdata->call_state, riid, obj); } + +/*********************************************************************** + * CoSwitchCallContext (combase.@) + */ +HRESULT WINAPI CoSwitchCallContext(IUnknown *context, IUnknown **old_context) +{ + struct tlsdata *tlsdata; + HRESULT hr; + + TRACE("%p, %p\n", context, old_context); + + if (FAILED(hr = com_get_tlsdata(&tlsdata))) + return hr; + + /* Reference counts are not touched. */ + *old_context = tlsdata->call_state; + tlsdata->call_state = context; + + return S_OK; +} diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 8293c9de259..55ba999a37d 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -158,7 +158,7 @@ @ stdcall CoSetErrorInfo(long ptr) SetErrorInfo @ stdcall CoSetProxyBlanket(ptr long long ptr long long ptr long) @ stdcall CoSuspendClassObjects() ole32.CoSuspendClassObjects -@ stdcall CoSwitchCallContext(ptr ptr) ole32.CoSwitchCallContext +@ stdcall CoSwitchCallContext(ptr ptr) @ stdcall CoTaskMemAlloc(long) @ stdcall CoTaskMemFree(ptr) @ stdcall CoTaskMemRealloc(ptr long) diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 2dc2d417e07..4e7cd3c6672 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -3458,35 +3458,6 @@ HRESULT WINAPI CoAllowSetForegroundWindow(IUnknown *pUnk, void *pvReserved) return S_OK; }
-/*********************************************************************** - * CoSwitchCallContext [OLE32.@] - * - * Switches the context of the currently executing server call in the current - * thread. - * - * PARAMS - * pObject [I] Pointer to new context object - * ppOldObject [O] Pointer to memory that will receive old context object pointer - * - * RETURNS - * Success: S_OK. - * Failure: HRESULT code. - */ -HRESULT WINAPI CoSwitchCallContext(IUnknown *pObject, IUnknown **ppOldObject) -{ - struct oletls *info = COM_CurrentInfo(); - - TRACE("(%p, %p)\n", pObject, ppOldObject); - - if (!info) - return E_OUTOFMEMORY; - - *ppOldObject = info->call_state; - info->call_state = pObject; /* CoSwitchCallContext does not addref nor release objects */ - - return S_OK; -} - static BOOL COM_PeekMessage(struct apartment *apt, MSG *msg) { /* first try to retrieve messages for incoming COM calls to the apartment window */ diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index 43237550195..b64b5114093 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -82,7 +82,7 @@ @ stdcall CoSetProxyBlanket(ptr long long ptr long long ptr long) combase.CoSetProxyBlanket @ stdcall CoSetState(ptr) @ stdcall CoSuspendClassObjects() -@ stdcall CoSwitchCallContext(ptr ptr) +@ stdcall CoSwitchCallContext(ptr ptr) combase.CoSwitchCallContext @ stdcall CoTaskMemAlloc(long) combase.CoTaskMemAlloc @ stdcall CoTaskMemFree(ptr) combase.CoTaskMemFree @ stdcall CoTaskMemRealloc(ptr long) combase.CoTaskMemRealloc
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 95 ++++++++++++++++++++++++++++++++ dlls/combase/combase.spec | 4 +- dlls/ole32/compobj.c | 110 -------------------------------------- dlls/ole32/ole32.spec | 4 +- 4 files changed, 99 insertions(+), 114 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 52a159d7fe2..114ea89e05e 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -65,6 +65,26 @@ struct progidredirect_data ULONG clsid_offset; };
+struct init_spy +{ + struct list entry; + IInitializeSpy *spy; + unsigned int id; +}; + +static struct init_spy *get_spy_entry(struct tlsdata *tlsdata, unsigned int id) +{ + struct init_spy *spy; + + LIST_FOR_EACH_ENTRY(spy, &tlsdata->spies, struct init_spy, entry) + { + if (id == spy->id && spy->spy) + return spy; + } + + return NULL; +} + static NTSTATUS create_key(HKEY *retkey, ACCESS_MASK access, OBJECT_ATTRIBUTES *attr) { NTSTATUS status = NtCreateKey((HANDLE *)retkey, access, attr, 0, NULL, 0, NULL); @@ -1426,3 +1446,78 @@ HRESULT WINAPI CoSwitchCallContext(IUnknown *context, IUnknown **old_context)
return S_OK; } + +/****************************************************************************** + * CoRegisterInitializeSpy (combase.@) + */ +HRESULT WINAPI CoRegisterInitializeSpy(IInitializeSpy *spy, ULARGE_INTEGER *cookie) +{ + struct tlsdata *tlsdata; + struct init_spy *entry; + unsigned int id; + HRESULT hr; + + TRACE("%p, %p\n", spy, cookie); + + if (!spy || !cookie) + return E_INVALIDARG; + + if (FAILED(hr = com_get_tlsdata(&tlsdata))) + return hr; + + hr = IInitializeSpy_QueryInterface(spy, &IID_IInitializeSpy, (void **)&spy); + if (FAILED(hr)) + return hr; + + entry = heap_alloc(sizeof(*entry)); + if (!entry) + { + IInitializeSpy_Release(spy); + return E_OUTOFMEMORY; + } + + entry->spy = spy; + + id = 0; + while (get_spy_entry(tlsdata, id) != NULL) + { + id++; + } + + entry->id = id; + list_add_head(&tlsdata->spies, &entry->entry); + + cookie->u.HighPart = GetCurrentThreadId(); + cookie->u.LowPart = entry->id; + + return S_OK; +} + +/****************************************************************************** + * CoRevokeInitializeSpy (combase.@) + */ +HRESULT WINAPI CoRevokeInitializeSpy(ULARGE_INTEGER cookie) +{ + struct tlsdata *tlsdata; + struct init_spy *spy; + HRESULT hr; + + TRACE("%s\n", wine_dbgstr_longlong(cookie.QuadPart)); + + if (cookie.u.HighPart != GetCurrentThreadId()) + return E_INVALIDARG; + + if (FAILED(hr = com_get_tlsdata(&tlsdata))) + return hr; + + if (!(spy = get_spy_entry(tlsdata, cookie.u.LowPart))) return E_INVALIDARG; + + IInitializeSpy_Release(spy->spy); + spy->spy = NULL; + if (!tlsdata->spies_lock) + { + list_remove(&spy->entry); + heap_free(spy); + } + return S_OK; +} diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 55ba999a37d..08426810784 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -140,7 +140,7 @@ @ stub CoReactivateObject @ stub CoRegisterActivationFilter @ stdcall CoRegisterClassObject(ptr ptr long long ptr) ole32.CoRegisterClassObject -@ stdcall CoRegisterInitializeSpy(ptr ptr) ole32.CoRegisterInitializeSpy +@ stdcall CoRegisterInitializeSpy(ptr ptr) @ stdcall CoRegisterMallocSpy(ptr) @ stdcall CoRegisterMessageFilter(ptr ptr) ole32.CoRegisterMessageFilter @ stdcall CoRegisterPSClsid(ptr ptr) ole32.CoRegisterPSClsid @@ -152,7 +152,7 @@ @ stub CoRetireServer @ stdcall CoRevertToSelf() @ stdcall CoRevokeClassObject(long) ole32.CoRevokeClassObject -@ stdcall CoRevokeInitializeSpy(int64) ole32.CoRevokeInitializeSpy +@ stdcall CoRevokeInitializeSpy(int64) @ stdcall CoRevokeMallocSpy() @ stub CoSetCancelObject @ stdcall CoSetErrorInfo(long ptr) SetErrorInfo diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 4e7cd3c6672..2a5e9f573ab 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -1775,19 +1775,6 @@ DWORD WINAPI CoBuildVersion(void) return (rmm<<16)+rup; }
-static struct init_spy *get_spy_entry(struct oletls *info, unsigned int id) -{ - struct init_spy *spy; - - LIST_FOR_EACH_ENTRY(spy, &info->spies, struct init_spy, entry) - { - if (id == spy->id && spy->spy) - return spy; - } - - return NULL; -} - /* * When locked, don't modify list (unless we add a new head), so that it's * safe to iterate it. Freeing of list entries is delayed and done on unlock. @@ -1811,103 +1798,6 @@ static void unlock_init_spies(struct oletls *info) } }
-/****************************************************************************** - * CoRegisterInitializeSpy [OLE32.@] - * - * Add a Spy that watches CoInitializeEx calls - * - * PARAMS - * spy [I] Pointer to IUnknown interface that will be QueryInterface'd. - * cookie [II] cookie receiver - * - * RETURNS - * Success: S_OK if not already initialized, S_FALSE otherwise. - * Failure: HRESULT code. - * - * SEE ALSO - * CoInitializeEx - */ -HRESULT WINAPI CoRegisterInitializeSpy(IInitializeSpy *spy, ULARGE_INTEGER *cookie) -{ - struct oletls *info = COM_CurrentInfo(); - struct init_spy *entry; - unsigned int id; - HRESULT hr; - - TRACE("(%p, %p)\n", spy, cookie); - - if (!spy || !cookie || !info) - { - if (!info) - WARN("Could not allocate tls\n"); - return E_INVALIDARG; - } - - hr = IInitializeSpy_QueryInterface(spy, &IID_IInitializeSpy, (void **)&spy); - if (FAILED(hr)) - return hr; - - entry = heap_alloc(sizeof(*entry)); - if (!entry) - { - IInitializeSpy_Release(spy); - return E_OUTOFMEMORY; - } - - entry->spy = spy; - - id = 0; - while (get_spy_entry(info, id) != NULL) - { - id++; - } - - entry->id = id; - list_add_head(&info->spies, &entry->entry); - - cookie->HighPart = GetCurrentThreadId(); - cookie->LowPart = entry->id; - - return S_OK; -} - -/****************************************************************************** - * CoRevokeInitializeSpy [OLE32.@] - * - * Remove a spy that previously watched CoInitializeEx calls - * - * PARAMS - * cookie [I] The cookie obtained from a previous CoRegisterInitializeSpy call - * - * RETURNS - * Success: S_OK if a spy is removed - * Failure: E_INVALIDARG - * - * SEE ALSO - * CoInitializeEx - */ -HRESULT WINAPI CoRevokeInitializeSpy(ULARGE_INTEGER cookie) -{ - struct oletls *info = COM_CurrentInfo(); - struct init_spy *spy; - - TRACE("(%s)\n", wine_dbgstr_longlong(cookie.QuadPart)); - - if (!info || cookie.HighPart != GetCurrentThreadId()) - return E_INVALIDARG; - - if (!(spy = get_spy_entry(info, cookie.LowPart))) return E_INVALIDARG; - - IInitializeSpy_Release(spy->spy); - spy->spy = NULL; - if (!info->spies_lock) - { - list_remove(&spy->entry); - heap_free(spy); - } - return S_OK; -} - HRESULT enter_apartment( struct oletls *info, DWORD model ) { HRESULT hr = S_OK; diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index b64b5114093..a4837bd6ff0 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -66,7 +66,7 @@ @ stub CoQueryReleaseObject @ stdcall CoRegisterChannelHook(ptr ptr) @ stdcall CoRegisterClassObject(ptr ptr long long ptr) -@ stdcall CoRegisterInitializeSpy(ptr ptr) +@ stdcall CoRegisterInitializeSpy(ptr ptr) combase.CoRegisterInitializeSpy @ stdcall CoRegisterMallocSpy(ptr) combase.CoRegisterMallocSpy @ stdcall CoRegisterMessageFilter(ptr ptr) @ stdcall CoRegisterPSClsid(ptr ptr) @@ -77,7 +77,7 @@ @ stdcall CoResumeClassObjects() @ stdcall CoRevertToSelf() combase.CoRevertToSelf @ stdcall CoRevokeClassObject(long) -@ stdcall CoRevokeInitializeSpy(int64) +@ stdcall CoRevokeInitializeSpy(int64) combase.CoRevokeInitializeSpy @ stdcall CoRevokeMallocSpy() combase.CoRevokeMallocSpy @ stdcall CoSetProxyBlanket(ptr long long ptr long long ptr long) combase.CoSetProxyBlanket @ stdcall CoSetState(ptr)
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 163 ++++++++++++++++++++++++++++++ dlls/combase/combase.spec | 2 +- dlls/combase/combase_private.h | 40 +++++++- dlls/combase/marshal.c | 3 +- dlls/ole32/compobj.c | 179 --------------------------------- dlls/ole32/ole32.spec | 2 +- 6 files changed, 206 insertions(+), 183 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 114ea89e05e..88dc7aa7b19 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -25,6 +25,7 @@ #define USE_COM_CONTEXT_DEF #include "objbase.h" #include "oleauto.h" +#include "dde.h" #include "winternl.h"
#include "combase_private.h" @@ -1521,3 +1522,165 @@ HRESULT WINAPI CoRevokeInitializeSpy(ULARGE_INTEGER cookie) } return S_OK; } + +static BOOL com_peek_message(struct apartment *apt, MSG *msg) +{ + /* First try to retrieve messages for incoming COM calls to the apartment window */ + return (apt->win && PeekMessageW(msg, apt->win, 0, 0, PM_REMOVE | PM_NOYIELD)) || + /* Next retrieve other messages necessary for the app to remain responsive */ + PeekMessageW(msg, NULL, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE | PM_NOYIELD) || + PeekMessageW(msg, NULL, 0, 0, PM_QS_PAINT | PM_QS_SENDMESSAGE | PM_REMOVE | PM_NOYIELD); +} + +/*********************************************************************** + * CoWaitForMultipleHandles (combase.@) + */ +HRESULT WINAPI CoWaitForMultipleHandles(DWORD flags, DWORD timeout, ULONG handle_count, HANDLE *handles, + DWORD *index) +{ + BOOL check_apc = !!(flags & COWAIT_ALERTABLE), post_quit = FALSE, message_loop; + DWORD start_time, wait_flags = 0; + struct tlsdata *tlsdata; + struct apartment *apt; + UINT exit_code; + HRESULT hr; + + TRACE("%#x, %#x, %u, %p, %p\n", flags, timeout, handle_count, handles, index); + + if (!index) + return E_INVALIDARG; + + *index = 0; + + if (!handles) + return E_INVALIDARG; + + if (!handle_count) + return RPC_E_NO_SYNC; + + if (FAILED(hr = com_get_tlsdata(&tlsdata))) + return hr; + + apt = com_get_current_apt(); + message_loop = apt && !apt->multi_threaded; + + if (flags & COWAIT_WAITALL) + wait_flags |= MWMO_WAITALL; + if (flags & COWAIT_ALERTABLE) + wait_flags |= MWMO_ALERTABLE; + + start_time = GetTickCount(); + + while (TRUE) + { + DWORD now = GetTickCount(), res; + + if (now - start_time > timeout) + { + hr = RPC_S_CALLPENDING; + break; + } + + if (message_loop) + { + TRACE("waiting for rpc completion or window message\n"); + + res = WAIT_TIMEOUT; + + if (check_apc) + { + res = WaitForMultipleObjectsEx(handle_count, handles, !!(flags & COWAIT_WAITALL), 0, TRUE); + check_apc = FALSE; + } + + if (res == WAIT_TIMEOUT) + res = MsgWaitForMultipleObjectsEx(handle_count, handles, + timeout == INFINITE ? INFINITE : start_time + timeout - now, + QS_SENDMESSAGE | QS_ALLPOSTMESSAGE | QS_PAINT, wait_flags); + + if (res == WAIT_OBJECT_0 + handle_count) /* messages available */ + { + int msg_count = 0; + MSG msg; + + /* call message filter */ + + if (apt->filter) + { + PENDINGTYPE pendingtype = tlsdata->pending_call_count_server ? PENDINGTYPE_NESTED : PENDINGTYPE_TOPLEVEL; + DWORD be_handled = IMessageFilter_MessagePending(apt->filter, 0 /* FIXME */, now - start_time, pendingtype); + + TRACE("IMessageFilter_MessagePending returned %d\n", be_handled); + + switch (be_handled) + { + case PENDINGMSG_CANCELCALL: + WARN("call canceled\n"); + hr = RPC_E_CALL_CANCELED; + break; + case PENDINGMSG_WAITNOPROCESS: + case PENDINGMSG_WAITDEFPROCESS: + default: + /* FIXME: MSDN is very vague about the difference + * between WAITNOPROCESS and WAITDEFPROCESS - there + * appears to be none, so it is possibly a left-over + * from the 16-bit world. */ + break; + } + } + + if (!apt->win) + { + /* If window is NULL on apartment, peek at messages so that it will not trigger + * MsgWaitForMultipleObjects next time. */ + PeekMessageW(NULL, NULL, 0, 0, PM_QS_POSTMESSAGE | PM_NOREMOVE | PM_NOYIELD); + } + + /* Some apps (e.g. Visio 2010) don't handle WM_PAINT properly and loop forever, + * so after processing 100 messages we go back to checking the wait handles */ + while (msg_count++ < 100 && com_peek_message(apt, &msg)) + { + if (msg.message == WM_QUIT) + { + TRACE("Received WM_QUIT message\n"); + post_quit = TRUE; + exit_code = msg.wParam; + } + else + { + TRACE("Received message whilst waiting for RPC: 0x%04x\n", msg.message); + TranslateMessage(&msg); + DispatchMessageW(&msg); + } + } + continue; + } + } + else + { + TRACE("Waiting for rpc completion\n"); + + res = WaitForMultipleObjectsEx(handle_count, handles, !!(flags & COWAIT_WAITALL), + (timeout == INFINITE) ? INFINITE : start_time + timeout - now, !!(flags & COWAIT_ALERTABLE)); + } + + switch (res) + { + case WAIT_TIMEOUT: + hr = RPC_S_CALLPENDING; + break; + case WAIT_FAILED: + hr = HRESULT_FROM_WIN32(GetLastError()); + break; + default: + *index = res; + break; + } + break; + } + if (post_quit) PostQuitMessage(exit_code); + + TRACE("-- 0x%08x\n", hr); + + return hr; +} diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 08426810784..7fd1e964cd3 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -170,7 +170,7 @@ @ stub CoVrfCheckThreadState @ stub CoVrfGetThreadState @ stub CoVrfReleaseThreadState -@ stdcall CoWaitForMultipleHandles(long long long ptr ptr) ole32.CoWaitForMultipleHandles +@ stdcall CoWaitForMultipleHandles(long long long ptr ptr) @ stub CoWaitForMultipleObjects @ stdcall CreateErrorInfo(ptr) @ stdcall CreateStreamOnHGlobal(ptr long ptr) ole32.CreateStreamOnHGlobal diff --git a/dlls/combase/combase_private.h b/dlls/combase/combase_private.h index bae57e89487..28a98fd5803 100644 --- a/dlls/combase/combase_private.h +++ b/dlls/combase/combase_private.h @@ -15,10 +15,41 @@ */
#include "winternl.h" +#include "wine/orpc.h"
#include "wine/list.h"
-struct apartment; +struct apartment +{ + struct list entry; + + LONG refs; /* refcount of the apartment (LOCK) */ + BOOL multi_threaded; /* multi-threaded or single-threaded apartment? (RO) */ + DWORD tid; /* thread id (RO) */ + OXID oxid; /* object exporter ID (RO) */ + LONG ipidc; /* interface pointer ID counter, starts at 1 (LOCK) */ + CRITICAL_SECTION cs; /* thread safety */ + struct list proxies; /* imported objects (CS cs) */ + struct list stubmgrs; /* stub managers for exported objects (CS cs) */ + BOOL remunk_exported; /* has the IRemUnknown interface for this apartment been created yet? (CS cs) */ + LONG remoting_started; /* has the RPC system been started for this apartment? (LOCK) */ + struct list loaded_dlls; /* list of dlls loaded by this apartment (CS cs) */ + DWORD host_apt_tid; /* thread ID of apartment hosting objects of differing threading model (CS cs) */ + HWND host_apt_hwnd; /* handle to apartment window of host apartment (CS cs) */ + struct local_server *local_server; /* A marshallable object exposing local servers (CS cs) */ + BOOL being_destroyed; /* is currently being destroyed */ + + /* FIXME: OIDs should be given out by RPCSS */ + OID oidc; /* object ID counter, starts at 1, zero is invalid OID (CS cs) */ + + /* STA-only fields */ + HWND win; /* message window (LOCK) */ + IMessageFilter *filter; /* message filter (CS cs) */ + BOOL main; /* is this a main-threaded-apartment? (RO) */ + + /* MTA-only */ + struct list usage_cookies; /* Used for refcount control with CoIncrementMTAUsage()/CoDecrementMTAUsage(). */ +};
/* this is what is stored in TEB->ReservedForOle */ struct tlsdata @@ -50,3 +81,10 @@ static inline HRESULT com_get_tlsdata(struct tlsdata **data) *data = NtCurrentTeb()->ReservedForOle; return *data ? S_OK : InternalTlsAllocData(data); } + +static inline struct apartment* com_get_current_apt(void) +{ + struct tlsdata *tlsdata = NULL; + com_get_tlsdata(&tlsdata); + return tlsdata->apt; +} diff --git a/dlls/combase/marshal.c b/dlls/combase/marshal.c index 9a88be72368..db5089f013e 100644 --- a/dlls/combase/marshal.c +++ b/dlls/combase/marshal.c @@ -22,9 +22,10 @@ #define COBJMACROS #include "objbase.h"
+#include "combase_private.h" + #include "wine/debug.h" #include "wine/heap.h" -#include "wine/orpc.h"
WINE_DEFAULT_DEBUG_CHANNEL(ole);
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 2a5e9f573ab..574a7b33055 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -3348,185 +3348,6 @@ HRESULT WINAPI CoAllowSetForegroundWindow(IUnknown *pUnk, void *pvReserved) return S_OK; }
-static BOOL COM_PeekMessage(struct apartment *apt, MSG *msg) -{ - /* first try to retrieve messages for incoming COM calls to the apartment window */ - return (apt->win && PeekMessageW(msg, apt->win, 0, 0, PM_REMOVE|PM_NOYIELD)) || - /* next retrieve other messages necessary for the app to remain responsive */ - PeekMessageW(msg, NULL, WM_DDE_FIRST, WM_DDE_LAST, PM_REMOVE|PM_NOYIELD) || - PeekMessageW(msg, NULL, 0, 0, PM_QS_PAINT|PM_QS_SENDMESSAGE|PM_REMOVE|PM_NOYIELD); -} - -/*********************************************************************** - * CoWaitForMultipleHandles [OLE32.@] - * - * Waits for one or more handles to become signaled. - * - * PARAMS - * dwFlags [I] Flags. See notes. - * dwTimeout [I] Timeout in milliseconds. - * cHandles [I] Number of handles pointed to by pHandles. - * pHandles [I] Handles to wait for. - * lpdwindex [O] Index of handle that was signaled. - * - * RETURNS - * Success: S_OK. - * Failure: RPC_S_CALLPENDING on timeout. - * - * NOTES - * - * The dwFlags parameter can be zero or more of the following: - *| COWAIT_WAITALL - Wait for all of the handles to become signaled. - *| COWAIT_ALERTABLE - Allows a queued APC to run during the wait. - * - * SEE ALSO - * MsgWaitForMultipleObjects, WaitForMultipleObjects. - */ -HRESULT WINAPI CoWaitForMultipleHandles(DWORD dwFlags, DWORD dwTimeout, - ULONG cHandles, LPHANDLE pHandles, LPDWORD lpdwindex) -{ - HRESULT hr = S_OK; - DWORD start_time = GetTickCount(); - APARTMENT *apt = COM_CurrentApt(); - BOOL message_loop = apt && !apt->multi_threaded; - BOOL check_apc = (dwFlags & COWAIT_ALERTABLE) != 0; - BOOL post_quit = FALSE; - UINT exit_code; - - TRACE("(0x%08x, 0x%08x, %d, %p, %p)\n", dwFlags, dwTimeout, cHandles, - pHandles, lpdwindex); - - if (!lpdwindex) - return E_INVALIDARG; - - *lpdwindex = 0; - - if (!pHandles) - return E_INVALIDARG; - - if (!cHandles) - return RPC_E_NO_SYNC; - - 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); - - TRACE("waiting for rpc completion or window message\n"); - - res = WAIT_TIMEOUT; - - if (check_apc) - { - res = WaitForMultipleObjectsEx(cHandles, pHandles, - (dwFlags & COWAIT_WAITALL) != 0, 0, TRUE); - check_apc = FALSE; - } - - if (res == WAIT_TIMEOUT) - res = MsgWaitForMultipleObjectsEx(cHandles, pHandles, - (dwTimeout == INFINITE) ? INFINITE : start_time + dwTimeout - now, - QS_SENDMESSAGE | QS_ALLPOSTMESSAGE | QS_PAINT, wait_flags); - - if (res == WAIT_OBJECT_0 + cHandles) /* messages available */ - { - MSG msg; - int count = 0; - - /* call message filter */ - - if (COM_CurrentApt()->filter) - { - PENDINGTYPE pendingtype = - COM_CurrentInfo()->pending_call_count_server ? - PENDINGTYPE_NESTED : PENDINGTYPE_TOPLEVEL; - DWORD be_handled = IMessageFilter_MessagePending( - COM_CurrentApt()->filter, 0 /* FIXME */, - now - start_time, pendingtype); - TRACE("IMessageFilter_MessagePending returned %d\n", be_handled); - switch (be_handled) - { - case PENDINGMSG_CANCELCALL: - WARN("call canceled\n"); - hr = RPC_E_CALL_CANCELED; - break; - case PENDINGMSG_WAITNOPROCESS: - case PENDINGMSG_WAITDEFPROCESS: - default: - /* FIXME: MSDN is very vague about the difference - * between WAITNOPROCESS and WAITDEFPROCESS - there - * appears to be none, so it is possibly a left-over - * from the 16-bit world. */ - break; - } - } - - if (!apt->win) - { - /* If window is NULL on apartment, peek at messages so that it will not trigger - * MsgWaitForMultipleObjects next time. */ - PeekMessageW(NULL, NULL, 0, 0, PM_QS_POSTMESSAGE | PM_NOREMOVE | PM_NOYIELD); - } - /* some apps (e.g. Visio 2010) don't handle WM_PAINT properly and loop forever, - * so after processing 100 messages we go back to checking the wait handles */ - while (count++ < 100 && COM_PeekMessage(apt, &msg)) - { - if (msg.message == WM_QUIT) - { - TRACE("received WM_QUIT message\n"); - post_quit = TRUE; - exit_code = msg.wParam; - } - else - { - TRACE("received message whilst waiting for RPC: 0x%04x\n", msg.message); - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - } - continue; - } - } - else - { - TRACE("waiting for rpc completion\n"); - - res = WaitForMultipleObjectsEx(cHandles, pHandles, (dwFlags & COWAIT_WAITALL) != 0, - (dwTimeout == INFINITE) ? INFINITE : start_time + dwTimeout - now, - (dwFlags & COWAIT_ALERTABLE) != 0); - } - - switch (res) - { - case WAIT_TIMEOUT: - hr = RPC_S_CALLPENDING; - break; - case WAIT_FAILED: - hr = HRESULT_FROM_WIN32( GetLastError() ); - break; - default: - *lpdwindex = res; - break; - } - break; - } - if (post_quit) PostQuitMessage(exit_code); - TRACE("-- 0x%08x\n", hr); - return hr; -} - - /*********************************************************************** * CoGetObject [OLE32.@] * diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index a4837bd6ff0..afb0e104075 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -91,7 +91,7 @@ @ stub CoUnloadingWOW @ stdcall CoUnmarshalHresult(ptr ptr) combase.CoUnmarshalHresult @ stdcall CoUnmarshalInterface(ptr ptr ptr) -@ stdcall CoWaitForMultipleHandles(long long long ptr ptr) +@ stdcall CoWaitForMultipleHandles(long long long ptr ptr) combase.CoWaitForMultipleHandles @ stdcall CreateAntiMoniker(ptr) @ stdcall CreateBindCtx(long ptr) @ stdcall CreateClassMoniker(ptr ptr)
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=77319
Your paranoid android.
=== debiant (32 bit Chinese:China report) ===
ole32: clipboard.c:1159: Test failed: got 800401d0 clipboard.c:1175: Test failed: got 800401d0 clipboard.c:1182: Test failed: data objects match clipboard.c:1185: Test failed: Failed to clear clipboard, hr 0x800401d0. clipboard.c:1190: Test failed: data objects match clipboard.c:1191: Test failed: data objects match clipboard.c:1201: Test failed: got 800401d0 clipboard.c:1213: Test failed: got 800401d0 clipboard.c:1214: Test failed: GetData not called clipboard.c:1217: Test failed: 1 1 clipboard.c:1223: Test failed: got 800401d0 clipboard.c:1224: Test failed: GetData not called clipboard.c:1228: Test failed: 1 clipboard.c:1239: Test failed: got 800401d0 clipboard.c:1250: Test failed: got 800401d0 clipboard.c:1256: Test failed: got 800401d0 clipboard.c:1257: Test failed: GetData not called clipboard.c:1263: Test failed: 1 1 clipboard.c:1266: Test failed: Failed to clear clipboard, hr 0x800401d0. clipboard.c:1269: Test failed: 1 clipboard.c:1281: Test failed: Failed to clear clipboard, hr 0x800401d0. clipboard.c:1283: Test failed: 1 1 clipboard.c:1287: Test failed: 1
Signed-off-by: Huw Davies huw@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- dlls/combase/combase.c | 37 ++++++++++++++++++++++++ dlls/combase/combase.spec | 2 +- dlls/ole32/compobj.c | 59 --------------------------------------- dlls/ole32/ole32.spec | 2 +- 4 files changed, 39 insertions(+), 61 deletions(-)
diff --git a/dlls/combase/combase.c b/dlls/combase/combase.c index 88dc7aa7b19..96c6a9bb817 100644 --- a/dlls/combase/combase.c +++ b/dlls/combase/combase.c @@ -1684,3 +1684,40 @@ HRESULT WINAPI CoWaitForMultipleHandles(DWORD flags, DWORD timeout, ULONG handle
return hr; } + +/****************************************************************************** + * CoRegisterMessageFilter (combase.@) + */ +HRESULT WINAPI CoRegisterMessageFilter(IMessageFilter *filter, IMessageFilter **ret_filter) +{ + IMessageFilter *old_filter; + struct apartment *apt; + + TRACE("%p, %p\n", filter, ret_filter); + + apt = com_get_current_apt(); + + /* Can't set a message filter in a multi-threaded apartment */ + if (!apt || apt->multi_threaded) + { + WARN("Can't set message filter in MTA or uninitialized apt\n"); + return CO_E_NOT_SUPPORTED; + } + + if (filter) + IMessageFilter_AddRef(filter); + + EnterCriticalSection(&apt->cs); + + old_filter = apt->filter; + apt->filter = filter; + + LeaveCriticalSection(&apt->cs); + + if (ret_filter) + *ret_filter = old_filter; + else if (old_filter) + IMessageFilter_Release(old_filter); + + return S_OK; +} diff --git a/dlls/combase/combase.spec b/dlls/combase/combase.spec index 7fd1e964cd3..bb7eaf69f9d 100644 --- a/dlls/combase/combase.spec +++ b/dlls/combase/combase.spec @@ -142,7 +142,7 @@ @ stdcall CoRegisterClassObject(ptr ptr long long ptr) ole32.CoRegisterClassObject @ stdcall CoRegisterInitializeSpy(ptr ptr) @ stdcall CoRegisterMallocSpy(ptr) -@ stdcall CoRegisterMessageFilter(ptr ptr) ole32.CoRegisterMessageFilter +@ stdcall CoRegisterMessageFilter(ptr ptr) @ stdcall CoRegisterPSClsid(ptr ptr) ole32.CoRegisterPSClsid @ stdcall CoRegisterSurrogate(ptr) ole32.CoRegisterSurrogate @ stdcall CoRegisterSurrogateEx(ptr ptr) ole32.CoRegisterSurrogateEx diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c index 574a7b33055..f02cdb8b53f 100644 --- a/dlls/ole32/compobj.c +++ b/dlls/ole32/compobj.c @@ -3146,65 +3146,6 @@ HRESULT WINAPI CoGetCurrentLogicalThreadId(GUID *id) return S_OK; }
-/****************************************************************************** - * CoRegisterMessageFilter [OLE32.@] - * - * Registers a message filter. - * - * PARAMS - * lpMessageFilter [I] Pointer to interface. - * lplpMessageFilter [O] Indirect pointer to prior instance if non-NULL. - * - * RETURNS - * Success: S_OK. - * Failure: HRESULT code. - * - * NOTES - * Both lpMessageFilter and lplpMessageFilter are optional. Passing in a NULL - * lpMessageFilter removes the message filter. - * - * If lplpMessageFilter is not NULL the previous message filter will be - * returned in the memory pointer to this parameter and the caller is - * responsible for releasing the object. - * - * The current thread be in an apartment otherwise the function will crash. - */ -HRESULT WINAPI CoRegisterMessageFilter( - LPMESSAGEFILTER lpMessageFilter, - LPMESSAGEFILTER *lplpMessageFilter) -{ - struct apartment *apt; - IMessageFilter *lpOldMessageFilter; - - TRACE("(%p, %p)\n", lpMessageFilter, lplpMessageFilter); - - apt = COM_CurrentApt(); - - /* can't set a message filter in a multi-threaded apartment */ - if (!apt || apt->multi_threaded) - { - WARN("can't set message filter in MTA or uninitialized apt\n"); - return CO_E_NOT_SUPPORTED; - } - - if (lpMessageFilter) - IMessageFilter_AddRef(lpMessageFilter); - - EnterCriticalSection(&apt->cs); - - lpOldMessageFilter = apt->filter; - apt->filter = lpMessageFilter; - - LeaveCriticalSection(&apt->cs); - - if (lplpMessageFilter) - *lplpMessageFilter = lpOldMessageFilter; - else if (lpOldMessageFilter) - IMessageFilter_Release(lpOldMessageFilter); - - return S_OK; -} - /*********************************************************************** * CoIsOle1Class [OLE32.@] * diff --git a/dlls/ole32/ole32.spec b/dlls/ole32/ole32.spec index afb0e104075..ed5a958ce3c 100644 --- a/dlls/ole32/ole32.spec +++ b/dlls/ole32/ole32.spec @@ -68,7 +68,7 @@ @ stdcall CoRegisterClassObject(ptr ptr long long ptr) @ stdcall CoRegisterInitializeSpy(ptr ptr) combase.CoRegisterInitializeSpy @ stdcall CoRegisterMallocSpy(ptr) combase.CoRegisterMallocSpy -@ stdcall CoRegisterMessageFilter(ptr ptr) +@ stdcall CoRegisterMessageFilter(ptr ptr) combase.CoRegisterMessageFilter @ stdcall CoRegisterPSClsid(ptr ptr) @ stdcall CoRegisterSurrogate(ptr) @ stdcall CoRegisterSurrogateEx(ptr ptr)
Signed-off-by: Huw Davies huw@codeweavers.com
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=77316
Your paranoid android.
=== debiant (32 bit Chinese:China report) ===
ole32: clipboard.c:984: Test failed: failed to flush clipboard, hr = 0x800401d0 clipboard.c:988: Test failed: did not expect current clipboard to be data2, hr = 0x00000000 clipboard.c:993: Test failed: OpenClipboard failed clipboard.c:995: Test failed: got 00000000 clipboard.c:997: Test failed: got fixed block 00000000 / 00000000 clipboard.c:999: Test failed: CloseClipboard failed clipboard.c:864: Test failed: didn't find cf_dataobject clipboard.c:865: Test failed: didn't find cf_ole_priv_data clipboard.c:1004: Test failed: Failed to clear clipboard, hr = 0x800401d0 clipboard.c:1013: Test failed: failed to set clipboard to complex data, hr = 0x800401d0 clipboard.c:882: Test failed: IDataObject_GetData failed with error 0x800401d0 clipboard.c:887: Test failed: IDataObject_GetData failed with error 0x800401d0 clipboard.c:892: Test failed: IDataObject_GetData failed with error 0x800401d0 clipboard.c:897: Test failed: IDataObject_GetData failed with error 0x800401d0 clipboard.c:900: Test failed: DataObjectImpl_GetData called 5 times instead of 0 times clipboard.c:864: Test failed: didn't find cf_dataobject clipboard.c:865: Test failed: didn't find cf_ole_priv_data clipboard.c:626: Test failed: got 800401d0 clipboard.c:1019: Test failed: failed to clear clipboard, hr = 0x800401d0. clipboard.c:626: Test failed: got 800401d0 clipboard.c:1027: Test failed: expected data2 ref=0, got 4
=== debiant (64 bit WoW report) ===
ole32: clipboard.c:1250: Test failed: got 800401d0 clipboard.c:1256: Test failed: got 800401d0 clipboard.c:1257: Test failed: GetData not called clipboard.c:1261: Test failed: 5 clipboard.c:1263: Test failed: 1 1 clipboard.c:1266: Test failed: Failed to clear clipboard, hr 0x800401d0. clipboard.c:1269: Test failed: 1 clipboard.c:1278: Test failed: 5 clipboard.c:1281: Test failed: Failed to clear clipboard, hr 0x800401d0. clipboard.c:1283: Test failed: 5 5