Aric Stewart : msctf/tests: Add framework for a TextService for testing.

Alexandre Julliard julliard at winehq.org
Tue Apr 14 16:00:01 CDT 2009


Module: wine
Branch: master
Commit: afe5dba276526f27ef40981046effffca1c99a7a
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=afe5dba276526f27ef40981046effffca1c99a7a

Author: Aric Stewart <aric at codeweavers.com>
Date:   Fri Apr 10 07:55:45 2009 -0500

msctf/tests: Add framework for a TextService for testing.

---

 dlls/msctf/tests/inputprocessor.c |  215 ++++++++++++++++++++++++++++++++++++-
 1 files changed, 213 insertions(+), 2 deletions(-)

diff --git a/dlls/msctf/tests/inputprocessor.c b/dlls/msctf/tests/inputprocessor.c
index 20991e4..13b81c7 100644
--- a/dlls/msctf/tests/inputprocessor.c
+++ b/dlls/msctf/tests/inputprocessor.c
@@ -23,15 +23,19 @@
 #define COBJMACROS
 #include "wine/test.h"
 #include "winuser.h"
+#include "initguid.h"
 #include "shlwapi.h"
 #include "shlguid.h"
 #include "comcat.h"
-#include "initguid.h"
 #include "msctf.h"
 
 static ITfInputProcessorProfiles* g_ipp;
 static LANGID gLangid;
-static ITfCategoryMgr * g_cm;
+static ITfCategoryMgr * g_cm = NULL;
+static ITfThreadMgr* g_tm = NULL;
+
+HRESULT RegisterTextService(REFCLSID rclsid);
+HRESULT UnregisterTextService();
 
 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);
@@ -41,6 +45,7 @@ DEFINE_GUID(GUID_TFCAT_TIP_SPEECH,       0xB5A73CD1,0x8355,0x426B,0xA1,0x61,0x25
 DEFINE_GUID(GUID_TFCAT_TIP_HANDWRITING,  0x246ecb87,0xc2f2,0x4abe,0x90,0x5b,0xc8,0xb3,0x8a,0xdd,0x2c,0x43);
 DEFINE_GUID (GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER,  0x046B8C80,0x1647,0x40F7,0x9B,0x21,0xB9,0x3B,0x81,0xAA,0xBC,0x1B);
 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+DEFINE_GUID(CLSID_TF_ThreadMgr,           0x529a9e6b,0x6587,0x4f23,0xab,0x9e,0x9c,0x7d,0x68,0x3e,0x3c,0x50);
 
 
 static HRESULT initialize(void)
@@ -52,6 +57,9 @@ static HRESULT initialize(void)
     if (SUCCEEDED(hr))
         hr = CoCreateInstance (&CLSID_TF_CategoryMgr, NULL,
           CLSCTX_INPROC_SERVER, &IID_ITfCategoryMgr, (void**)&g_cm);
+    if (SUCCEEDED(hr))
+        hr = CoCreateInstance (&CLSID_TF_ThreadMgr, NULL,
+          CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, (void**)&g_tm);
     return hr;
 }
 
@@ -61,6 +69,8 @@ static void cleanup(void)
         ITfInputProcessorProfiles_Release(g_ipp);
     if (g_cm)
         ITfCategoryMgr_Release(g_cm);
+    if (g_tm)
+        ITfThreadMgr_Release(g_tm);
     CoUninitialize();
 }
 
@@ -71,6 +81,8 @@ static void test_Register(void)
     static const WCHAR szDesc[] = {'F','a','k','e',' ','W','i','n','e',' ','S','e','r','v','i','c','e',0};
     static const WCHAR szFile[] = {'F','a','k','e',' ','W','i','n','e',' ','S','e','r','v','i','c','e',' ','F','i','l','e',0};
 
+    hr = RegisterTextService(&CLSID_FakeService);
+    ok(SUCCEEDED(hr),"Unable to register COM for TextService\n");
     hr = ITfInputProcessorProfiles_Register(g_ipp, &CLSID_FakeService);
     ok(SUCCEEDED(hr),"Unable to register text service(%x)\n",hr);
     hr = ITfInputProcessorProfiles_AddLanguageProfile(g_ipp, &CLSID_FakeService, gLangid, &CLSID_FakeService, szDesc, sizeof(szDesc)/sizeof(WCHAR), szFile, sizeof(szFile)/sizeof(WCHAR), 1);
@@ -82,6 +94,7 @@ static void test_Unregister(void)
     HRESULT hr;
     hr = ITfInputProcessorProfiles_Unregister(g_ipp, &CLSID_FakeService);
     ok(SUCCEEDED(hr),"Unable to unregister text service(%x)\n",hr);
+    UnregisterTextService();
 }
 
 static void test_EnumInputProcessorInfo(void)
@@ -200,3 +213,201 @@ START_TEST(inputprocessor)
         skip("Unable to create InputProcessor\n");
     cleanup();
 }
+
+
+
+/********************************************************************************************
+ * Stub text service for testing
+ ********************************************************************************************/
+
+static LONG TS_refCount;
+static IClassFactory *cf;
+static DWORD regid;
+
+typedef HRESULT (*LPFNCONSTRUCTOR)(IUnknown *pUnkOuter, IUnknown **ppvOut);
+
+typedef struct tagClassFactory
+{
+    const IClassFactoryVtbl *vtbl;
+    LONG   ref;
+    LPFNCONSTRUCTOR ctor;
+} ClassFactory;
+
+typedef struct tagTextService
+{
+    const ITfTextInputProcessorVtbl *TextInputProcessorVtbl;
+    LONG refCount;
+} TextService;
+
+static void ClassFactory_Destructor(ClassFactory *This)
+{
+    HeapFree(GetProcessHeap(),0,This);
+    TS_refCount--;
+}
+
+static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppvOut)
+{
+    *ppvOut = NULL;
+    if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown))
+    {
+        IClassFactory_AddRef(iface);
+        *ppvOut = iface;
+        return S_OK;
+    }
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface)
+{
+    ClassFactory *This = (ClassFactory *)iface;
+    return InterlockedIncrement(&This->ref);
+}
+
+static ULONG WINAPI ClassFactory_Release(IClassFactory *iface)
+{
+    ClassFactory *This = (ClassFactory *)iface;
+    ULONG ret = InterlockedDecrement(&This->ref);
+
+    if (ret == 0)
+        ClassFactory_Destructor(This);
+    return ret;
+}
+
+static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *punkOuter, REFIID iid, LPVOID *ppvOut)
+{
+    ClassFactory *This = (ClassFactory *)iface;
+    HRESULT ret;
+    IUnknown *obj;
+
+    ret = This->ctor(punkOuter, &obj);
+    if (FAILED(ret))
+        return ret;
+    ret = IUnknown_QueryInterface(obj, iid, ppvOut);
+    IUnknown_Release(obj);
+    return ret;
+}
+
+static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock)
+{
+    if(fLock)
+        InterlockedIncrement(&TS_refCount);
+    else
+        InterlockedDecrement(&TS_refCount);
+
+    return S_OK;
+}
+
+static const IClassFactoryVtbl ClassFactoryVtbl = {
+    /* IUnknown */
+    ClassFactory_QueryInterface,
+    ClassFactory_AddRef,
+    ClassFactory_Release,
+
+    /* IClassFactory*/
+    ClassFactory_CreateInstance,
+    ClassFactory_LockServer
+};
+
+static HRESULT ClassFactory_Constructor(LPFNCONSTRUCTOR ctor, LPVOID *ppvOut)
+{
+    ClassFactory *This = HeapAlloc(GetProcessHeap(),0,sizeof(ClassFactory));
+    This->vtbl = &ClassFactoryVtbl;
+    This->ref = 1;
+    This->ctor = ctor;
+    *ppvOut = (LPVOID)This;
+    TS_refCount++;
+    return S_OK;
+}
+
+static void TextService_Destructor(TextService *This)
+{
+    HeapFree(GetProcessHeap(),0,This);
+}
+
+static HRESULT WINAPI TextService_QueryInterface(ITfTextInputProcessor *iface, REFIID iid, LPVOID *ppvOut)
+{
+    TextService *This = (TextService *)iface;
+    *ppvOut = NULL;
+
+    if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfTextInputProcessor))
+    {
+        *ppvOut = This;
+    }
+
+    if (*ppvOut)
+    {
+        IUnknown_AddRef(iface);
+        return S_OK;
+    }
+
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI TextService_AddRef(ITfTextInputProcessor *iface)
+{
+    TextService *This = (TextService *)iface;
+    return InterlockedIncrement(&This->refCount);
+}
+
+static ULONG WINAPI TextService_Release(ITfTextInputProcessor *iface)
+{
+    TextService *This = (TextService *)iface;
+    ULONG ret;
+
+    ret = InterlockedDecrement(&This->refCount);
+    if (ret == 0)
+        TextService_Destructor(This);
+    return ret;
+}
+
+static HRESULT WINAPI TextService_Activate(ITfTextInputProcessor *iface,
+        ITfThreadMgr *ptim, TfClientId id)
+{
+    trace("TextService_Activate\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI TextService_Deactivate(ITfTextInputProcessor *iface)
+{
+    trace("TextService_Deactivate\n");
+    return S_OK;
+}
+
+static const ITfTextInputProcessorVtbl TextService_TextInputProcessorVtbl=
+{
+    TextService_QueryInterface,
+    TextService_AddRef,
+    TextService_Release,
+
+    TextService_Activate,
+    TextService_Deactivate
+};
+
+HRESULT TextService_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
+{
+    TextService *This;
+    if (pUnkOuter)
+        return CLASS_E_NOAGGREGATION;
+
+    This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TextService));
+    if (This == NULL)
+        return E_OUTOFMEMORY;
+
+    This->TextInputProcessorVtbl= &TextService_TextInputProcessorVtbl;
+    This->refCount = 1;
+
+    *ppOut = (IUnknown *)This;
+    return S_OK;
+}
+
+HRESULT RegisterTextService(REFCLSID rclsid)
+{
+    ClassFactory_Constructor( TextService_Constructor ,(LPVOID*)&cf);
+    return CoRegisterClassObject(rclsid, (IUnknown*) cf, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &regid);
+}
+
+HRESULT UnregisterTextService()
+{
+    return CoRevokeClassObject(regid);
+}




More information about the wine-cvs mailing list