Robert Shearman : ole32:
Improve CoRegisterMessageFilter and add tests for it.
Alexandre Julliard
julliard at wine.codeweavers.com
Mon Jul 17 07:00:13 CDT 2006
Module: wine
Branch: refs/heads/master
Commit: fac6bedda9e78f8cd4e015f8afcf551b52adb411
URL: http://source.winehq.org/git/?p=wine.git;a=commit;h=fac6bedda9e78f8cd4e015f8afcf551b52adb411
Author: Robert Shearman <rob at codeweavers.com>
Date: Fri Jul 14 17:13:58 2006 +0100
ole32: Improve CoRegisterMessageFilter and add tests for it.
---
dlls/ole32/compobj.c | 44 +++++++++++++++-
dlls/ole32/tests/compobj.c | 119 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 160 insertions(+), 3 deletions(-)
diff --git a/dlls/ole32/compobj.c b/dlls/ole32/compobj.c
index db0fcbe..c89d8ce 100644
--- a/dlls/ole32/compobj.c
+++ b/dlls/ole32/compobj.c
@@ -2410,15 +2410,53 @@ DWORD WINAPI CoGetCurrentProcess(void)
* 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)
{
- FIXME("stub\n");
- if (lplpMessageFilter) {
- *lplpMessageFilter = NULL;
+ 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->multi_threaded)
+ {
+ ERR("can't set message filter in MTA\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);
+
+ if (lpMessageFilter)
+ FIXME("message filter has been registered, but will not be used\n");
+
return S_OK;
}
diff --git a/dlls/ole32/tests/compobj.c b/dlls/ole32/tests/compobj.c
index 9164be8..19a6faa 100644
--- a/dlls/ole32/tests/compobj.c
+++ b/dlls/ole32/tests/compobj.c
@@ -29,6 +29,9 @@ #include "shlguid.h"
#include "wine/test.h"
+/* functions that are not present on all versions of Windows */
+HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
+
#define ok_ole_success(hr, func) ok(hr == S_OK, func " failed with error 0x%08lx\n", hr)
static const CLSID CLSID_non_existent = { 0x12345678, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
@@ -142,12 +145,128 @@ static void test_ole_menu(void)
DestroyWindow(hwndFrame);
}
+
+static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
+{
+ if (ppvObj == NULL) return E_POINTER;
+
+ if (IsEqualGUID(riid, &IID_IUnknown) ||
+ IsEqualGUID(riid, &IID_IClassFactory))
+ {
+ *ppvObj = (LPVOID)iface;
+ IMessageFilter_AddRef(iface);
+ return S_OK;
+ }
+
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
+{
+ return 2; /* non-heap object */
+}
+
+static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
+{
+ return 1; /* non-heap object */
+}
+
+static DWORD WINAPI MessageFilter_HandleInComingCall(
+ IMessageFilter *iface,
+ DWORD dwCallType,
+ HTASK threadIDCaller,
+ DWORD dwTickCount,
+ LPINTERFACEINFO lpInterfaceInfo)
+{
+ trace("HandleInComingCall\n");
+ return SERVERCALL_ISHANDLED;
+}
+
+static DWORD WINAPI MessageFilter_RetryRejectedCall(
+ IMessageFilter *iface,
+ HTASK threadIDCallee,
+ DWORD dwTickCount,
+ DWORD dwRejectType)
+{
+ trace("RetryRejectedCall\n");
+ return 0;
+}
+
+static DWORD WINAPI MessageFilter_MessagePending(
+ IMessageFilter *iface,
+ HTASK threadIDCallee,
+ DWORD dwTickCount,
+ DWORD dwPendingType)
+{
+ trace("MessagePending\n");
+ return PENDINGMSG_WAITNOPROCESS;
+}
+
+static const IMessageFilterVtbl MessageFilter_Vtbl =
+{
+ MessageFilter_QueryInterface,
+ MessageFilter_AddRef,
+ MessageFilter_Release,
+ MessageFilter_HandleInComingCall,
+ MessageFilter_RetryRejectedCall,
+ MessageFilter_MessagePending
+};
+
+static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
+
+static void test_CoRegisterMessageFilter(void)
+{
+ HRESULT hr;
+ IMessageFilter *prev_filter;
+
+#if 0 /* crashes without an apartment! */
+ hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
+#endif
+
+ pCoInitializeEx(NULL, COINIT_MULTITHREADED);
+ prev_filter = (IMessageFilter *)0xdeadbeef;
+ hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
+ ok(hr == CO_E_NOT_SUPPORTED,
+ "CoRegisterMessageFilter should have failed with CO_E_NOT_SUPPORTED instead of 0x%08lx\n",
+ hr);
+ ok(prev_filter == (IMessageFilter *)0xdeadbeef,
+ "prev_filter should have been set to %p\n", prev_filter);
+ CoUninitialize();
+
+ pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+
+ hr = CoRegisterMessageFilter(NULL, NULL);
+ ok_ole_success(hr, "CoRegisterMessageFilter");
+
+ prev_filter = (IMessageFilter *)0xdeadbeef;
+ hr = CoRegisterMessageFilter(NULL, &prev_filter);
+ ok_ole_success(hr, "CoRegisterMessageFilter");
+ ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
+
+ hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
+ ok_ole_success(hr, "CoRegisterMessageFilter");
+ ok(prev_filter == NULL, "prev_filter should have been set to NULL instead of %p\n", prev_filter);
+
+ hr = CoRegisterMessageFilter(NULL, NULL);
+ ok_ole_success(hr, "CoRegisterMessageFilter");
+
+ CoUninitialize();
+}
+
START_TEST(compobj)
{
+ HMODULE hOle32 = GetModuleHandle("ole32");
+ if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx")))
+ {
+ trace("You need DCOM95 installed to run this test\n");
+ return;
+ }
+
test_ProgIDFromCLSID();
test_CLSIDFromProgID();
test_CLSIDFromString();
test_CoCreateInstance();
test_ole_menu();
test_CoGetClassObject();
+ test_CoRegisterMessageFilter();
}
More information about the wine-cvs
mailing list