[MSCTF_WINETEST] Sync with Wine Staging 4.18. CORE-16441
authorAmine Khaldi <amine.khaldi@reactos.org>
Sat, 9 Nov 2019 21:03:01 +0000 (22:03 +0100)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sat, 9 Nov 2019 21:03:01 +0000 (22:03 +0100)
modules/rostests/winetests/msctf/inputprocessor.c

index 0d03ce3..1222085 100644 (file)
@@ -64,7 +64,8 @@ static DWORD tmSinkCookie;
 static DWORD tmSinkRefCount;
 static DWORD dmSinkCookie;
 static DWORD documentStatus;
-static DWORD key_trace_sink_cookie;
+static DWORD key_trace_sink_cookie, ui_element_sink_cookie, profile_activation_sink_cookie;
+static DWORD fake_service_onactivated_flags = 0;
 static ITfDocumentMgr *test_CurrentFocus = NULL;
 static ITfDocumentMgr *test_PrevFocus = NULL;
 static ITfDocumentMgr *test_LastCurrentFocus = FOCUS_SAVE;
@@ -85,6 +86,7 @@ static INT  test_ACP_InsertTextAtSelection = SINK_UNEXPECTED;
 static INT  test_ACP_SetSelection = SINK_UNEXPECTED;
 static INT  test_OnEndEdit = SINK_UNEXPECTED;
 
+DEFINE_GUID(CLSID_FakeService, 0xEDE1A7AD,0x66DE,0x47E0,0xB6,0x20,0x3E,0x92,0xF8,0x24,0x6B,0xF3);
 
 static inline int expected_count(int *sink)
 {
@@ -671,6 +673,115 @@ static const ITfKeyTraceEventSinkVtbl TfKeyTraceEventSinkVtbl = {
 
 static ITfKeyTraceEventSink TfKeyTraceEventSink = { &TfKeyTraceEventSinkVtbl };
 
+static HRESULT WINAPI TfUIElementSink_QueryInterface(ITfUIElementSink *iface,
+        REFIID riid, void **ppvObject)
+{
+    if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITfUIElementSink, riid)){
+        *ppvObject = iface;
+        return S_OK;
+    }
+
+    *ppvObject = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI TfUIElementSink_AddRef(ITfUIElementSink *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI TfUIElementSink_Release(ITfUIElementSink *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI TfUIElementSink_BeginUIElement(ITfUIElementSink *iface,
+        DWORD id, BOOL *show)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TfUIElementSink_UpdateUIElement(ITfUIElementSink *iface,
+        DWORD id)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static HRESULT WINAPI TfUIElementSink_EndUIElement(ITfUIElementSink *iface,
+        DWORD id)
+{
+    ok(0, "unexpected call\n");
+    return E_NOTIMPL;
+}
+
+static const ITfUIElementSinkVtbl TfUIElementSinkVtbl = {
+    TfUIElementSink_QueryInterface,
+    TfUIElementSink_AddRef,
+    TfUIElementSink_Release,
+    TfUIElementSink_BeginUIElement,
+    TfUIElementSink_UpdateUIElement,
+    TfUIElementSink_EndUIElement
+};
+
+static ITfUIElementSink TfUIElementSink = { &TfUIElementSinkVtbl };
+
+static HRESULT WINAPI ProfileActivationSink_QueryInterface(ITfInputProcessorProfileActivationSink *iface,
+        REFIID riid, void **ppvObject)
+{
+    if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITfInputProcessorProfileActivationSink, riid)){
+        *ppvObject = iface;
+        return S_OK;
+    }
+
+    *ppvObject = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ProfileActivationSink_AddRef(ITfInputProcessorProfileActivationSink *iface)
+{
+    return 2;
+}
+
+static ULONG WINAPI ProfileActivationSink_Release(ITfInputProcessorProfileActivationSink *iface)
+{
+    return 1;
+}
+
+static HRESULT WINAPI ProfileActivationSink_OnActivated(ITfInputProcessorProfileActivationSink *iface,
+    DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid,
+    REFGUID guidProfile, HKL hkl, DWORD dwFlags)
+{
+    trace("Got OnActivated: {dwProfileType %08x, langid %08x, clsid %s, catid %s, guidProfile %s, %p, dwFlags %08x}\n",
+            dwProfileType, langid, wine_dbgstr_guid(clsid),
+            wine_dbgstr_guid(catid), wine_dbgstr_guid(guidProfile), hkl, dwFlags);
+
+    ok(dwProfileType == TF_PROFILETYPE_INPUTPROCESSOR || dwProfileType == TF_PROFILETYPE_KEYBOARDLAYOUT,
+            "unexpected dwProfileType: 0x%x\n", dwProfileType);
+
+    if(dwProfileType == TF_PROFILETYPE_INPUTPROCESSOR && IsEqualGUID(&CLSID_FakeService, clsid)){
+        if(dwFlags & TF_IPSINK_FLAG_ACTIVE){
+            ok(test_ShouldActivate, "OnActivated: Activation came unexpectedly\n");
+        }
+
+        fake_service_onactivated_flags = dwFlags;
+    }
+
+    return S_OK;
+}
+
+static const ITfInputProcessorProfileActivationSinkVtbl TfInputProcessorProfileActivationSinkVtbl = {
+    ProfileActivationSink_QueryInterface,
+    ProfileActivationSink_AddRef,
+    ProfileActivationSink_Release,
+    ProfileActivationSink_OnActivated
+};
+
+static ITfInputProcessorProfileActivationSink TfInputProcessorProfileActivationSink = {
+    &TfInputProcessorProfileActivationSinkVtbl
+};
+
 static HRESULT WINAPI TfTransitoryExtensionSink_QueryInterface(ITfTransitoryExtensionSink *iface, REFIID riid, void **ppv)
 {
     if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITfTransitoryExtensionSink, riid)) {
@@ -920,7 +1031,6 @@ static HRESULT UnregisterTextService(void)
  * The tests
  */
 
-DEFINE_GUID(CLSID_FakeService, 0xEDE1A7AD,0x66DE,0x47E0,0xB6,0x20,0x3E,0x92,0xF8,0x24,0x6B,0xF3);
 DEFINE_GUID(CLSID_TF_InputProcessorProfiles, 0x33c53a50,0xf456,0x4884,0xb0,0x49,0x85,0xfd,0x64,0x3e,0xcf,0xed);
 DEFINE_GUID(CLSID_TF_CategoryMgr,         0xA4B544A1,0x438D,0x4B41,0x93,0x25,0x86,0x95,0x23,0xE2,0xD6,0xC7);
 DEFINE_GUID(GUID_TFCAT_TIP_KEYBOARD,     0x34745c63,0xb2f0,0x4784,0x8b,0x67,0x5e,0x12,0xc8,0x70,0x1a,0x31);
@@ -1128,7 +1238,7 @@ static void test_ThreadMgrAdviseSinks(void)
     tmSinkRefCount = 1;
     tmSinkCookie = 0;
     hr = ITfSource_AdviseSink(source,&IID_ITfThreadMgrEventSink, sink, &tmSinkCookie);
-    ok(hr == S_OK, "Failed to Advise Sink\n");
+    ok(hr == S_OK, "Failed to Advise ITfThreadMgrEventSink\n");
     ok(tmSinkCookie!=0,"Failed to get sink cookie\n");
 
     /* Advising the sink adds a ref, Releasing here lets the object be deleted
@@ -1138,7 +1248,15 @@ static void test_ThreadMgrAdviseSinks(void)
 
     hr = ITfSource_AdviseSink(source, &IID_ITfKeyTraceEventSink, (IUnknown*)&TfKeyTraceEventSink,
                               &key_trace_sink_cookie);
-    ok(hr == S_OK, "Failed to Advise Sink\n");
+    ok(hr == S_OK, "Failed to Advise ITfKeyTraceEventSink\n");
+
+    hr = ITfSource_AdviseSink(source, &IID_ITfUIElementSink, (IUnknown*)&TfUIElementSink,
+                              &ui_element_sink_cookie);
+    ok(hr == S_OK, "Failed to Advise ITfUIElementSink\n");
+
+    hr = ITfSource_AdviseSink(source, &IID_ITfInputProcessorProfileActivationSink, (IUnknown*)&TfInputProcessorProfileActivationSink,
+                              &profile_activation_sink_cookie);
+    ok(hr == S_OK, "Failed to Advise ITfInputProcessorProfileActivationSink\n");
 
     ITfSource_Release(source);
 }
@@ -1155,10 +1273,16 @@ static void test_ThreadMgrUnadviseSinks(void)
 
     tmSinkRefCount = 1;
     hr = ITfSource_UnadviseSink(source, tmSinkCookie);
-    ok(hr == S_OK, "Failed to unadvise Sink\n");
+    ok(hr == S_OK, "Failed to unadvise ITfThreadMgrEventSink\n");
 
     hr = ITfSource_UnadviseSink(source, key_trace_sink_cookie);
-    ok(hr == S_OK, "Failed to unadvise Sink\n");
+    ok(hr == S_OK, "Failed to unadvise ITfKeyTraceEventSink\n");
+
+    hr = ITfSource_UnadviseSink(source, ui_element_sink_cookie);
+    ok(hr == S_OK, "Failed to unadvise ITfUIElementSink\n");
+
+    hr = ITfSource_UnadviseSink(source, profile_activation_sink_cookie);
+    ok(hr == S_OK, "Failed to unadvise ITfInputProcessorProfileActivationSink\n");
 
     ITfSource_Release(source);
 }
@@ -1557,6 +1681,8 @@ static void test_startSession(void)
     ok(SUCCEEDED(hr),"Failed to Activate\n");
     ok(cid != tid,"TextService id mistakenly matches Client id\n");
 
+    todo_wine ok(fake_service_onactivated_flags & TF_IPSINK_FLAG_ACTIVE, "Expected OnActivated callback\n");
+
     test_ShouldActivate = FALSE;
     hr = ITfThreadMgr_Activate(g_tm,&cid2);
     ok(SUCCEEDED(hr),"Failed to Activate\n");
@@ -2385,6 +2511,53 @@ static void test_profile_mgr(void)
     ITfInputProcessorProfileMgr_Release(ipp_mgr);
 }
 
+static DWORD WINAPI test_MultiThreadApartment_Thread(void *param) {
+    ITfThreadMgrEx *thmgr;
+    ITfSource *source;
+    DWORD cookie;
+    HRESULT hr;
+
+    hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
+    ok(SUCCEEDED(hr), "Failed to initialize multi-threaded apartment\n");
+
+    hr = CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgrEx, (LPVOID *)&thmgr);
+    ok(SUCCEEDED(hr), "Failed to create ITfThreadMgrEx instance\n");
+
+    hr = ITfThreadMgrEx_QueryInterface(thmgr, &IID_ITfSource, (LPVOID *)&source);
+    ok(SUCCEEDED(hr), "Failed to query ITfSource interface\n");
+
+    hr = ITfSource_AdviseSink(source, &IID_ITfUIElementSink, (IUnknown*)&TfUIElementSink, &cookie);
+    ok(hr == REGDB_E_IIDNOTREG /* native */ || hr == E_NOINTERFACE /* wine */,
+       "Advise ITfUIElementSink should return marshalling failure: %08x\n", hr);
+
+    hr = ITfSource_Release(source);
+    ok(SUCCEEDED(hr), "Failed to Release source\n");
+
+    hr = ITfThreadMgrEx_Release(thmgr);
+    ok(SUCCEEDED(hr), "Failed to Release thread manager\n");
+
+    CoUninitialize();
+
+    return 0xdeadcafe;
+}
+
+static void test_MultiThreadApartment(void)
+{
+    DWORD ret;
+    HANDLE thread;
+
+    thread = CreateThread(0, 0, test_MultiThreadApartment_Thread, 0, 0, 0);
+    ok(thread != NULL, "Failed to create test thread\n");
+
+    ret = WaitForSingleObject(thread, INFINITE);
+    ok(ret == WAIT_OBJECT_0, "Failed to wait for thread completion\n");
+
+    GetExitCodeThread(thread, &ret);
+    ok(ret == 0xdeadcafe, "Thread terminated in an unexpected way\n");
+
+    CloseHandle(thread);
+}
+
 START_TEST(inputprocessor)
 {
     if (SUCCEEDED(initialize()))
@@ -2414,6 +2587,7 @@ START_TEST(inputprocessor)
         test_UnregisterCategory();
         test_Unregister();
         test_profile_mgr();
+        test_MultiThreadApartment();
 
         ITextStoreACPSink_Release(ACPSink);
         ITfDocumentMgr_Release(g_dm);