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