From 0f11de6b0d84500f34516ee3c0bd0583459170e7 Mon Sep 17 00:00:00 2001 From: Dmitry Chapyshev Date: Thu, 26 Feb 2009 11:43:42 +0000 Subject: [PATCH] - Add msctf from Wine svn path=/trunk/; revision=39769 --- reactos/boot/bootdata/packages/reactos.dff | 1 + reactos/dll/win32/msctf/categorymgr.c | 289 +++++++ reactos/dll/win32/msctf/context.c | 609 ++++++++++++++ reactos/dll/win32/msctf/documentmgr.c | 280 +++++++ reactos/dll/win32/msctf/inputprocessor.c | 885 +++++++++++++++++++++ reactos/dll/win32/msctf/msctf.c | 252 ++++++ reactos/dll/win32/msctf/msctf.rbuild | 22 + reactos/dll/win32/msctf/msctf.spec | 34 + reactos/dll/win32/msctf/msctf_internal.h | 32 + reactos/dll/win32/msctf/regsvr.c | 504 ++++++++++++ reactos/dll/win32/msctf/threadmgr.c | 309 +++++++ reactos/dll/win32/win32.rbuild | 3 + reactos/include/psdk/msctf.idl | 478 +++++++++++ reactos/include/psdk/psdk.rbuild | 2 + reactos/include/psdk/textstor.idl | 277 +++++++ reactos/lib/sdk/uuid/uuid.c | 3 + reactos/media/doc/README.WINE | 1 + 17 files changed, 3981 insertions(+) create mode 100644 reactos/dll/win32/msctf/categorymgr.c create mode 100644 reactos/dll/win32/msctf/context.c create mode 100644 reactos/dll/win32/msctf/documentmgr.c create mode 100644 reactos/dll/win32/msctf/inputprocessor.c create mode 100644 reactos/dll/win32/msctf/msctf.c create mode 100644 reactos/dll/win32/msctf/msctf.rbuild create mode 100644 reactos/dll/win32/msctf/msctf.spec create mode 100644 reactos/dll/win32/msctf/msctf_internal.h create mode 100644 reactos/dll/win32/msctf/regsvr.c create mode 100644 reactos/dll/win32/msctf/threadmgr.c create mode 100644 reactos/include/psdk/msctf.idl create mode 100644 reactos/include/psdk/textstor.idl diff --git a/reactos/boot/bootdata/packages/reactos.dff b/reactos/boot/bootdata/packages/reactos.dff index 8984bd9bc4c..2faa17c49ed 100644 --- a/reactos/boot/bootdata/packages/reactos.dff +++ b/reactos/boot/bootdata/packages/reactos.dff @@ -302,6 +302,7 @@ dll\win32\msafd\msafd.dll 1 dll\win32\mscat32\mscat32.dll 1 dll\win32\mscms\mscms.dll 1 dll\win32\mscoree\mscoree.dll 1 +dll\win32\msctf\msctf.dll 1 dll\win32\msftedit\msftedit.dll 1 dll\win32\msgina\msgina.dll 1 dll\win32\mshtml\mshtml.dll 1 diff --git a/reactos/dll/win32/msctf/categorymgr.c b/reactos/dll/win32/msctf/categorymgr.c new file mode 100644 index 00000000000..23580724286 --- /dev/null +++ b/reactos/dll/win32/msctf/categorymgr.c @@ -0,0 +1,289 @@ +/* + * ITfCategoryMgr implementation + * + * Copyright 2009 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include + +#define COBJMACROS + +#include "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winuser.h" +#include "shlwapi.h" +#include "winerror.h" +#include "objbase.h" + +#include "wine/unicode.h" + +#include "msctf.h" +#include "msctf_internal.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctf); + +typedef struct tagCategoryMgr { + const ITfCategoryMgrVtbl *CategoryMgrVtbl; + LONG refCount; +} CategoryMgr; + +static void CategoryMgr_Destructor(CategoryMgr *This) +{ + TRACE("destroying %p\n", This); + HeapFree(GetProcessHeap(),0,This); +} + +static HRESULT WINAPI CategoryMgr_QueryInterface(ITfCategoryMgr *iface, REFIID iid, LPVOID *ppvOut) +{ + CategoryMgr *This = (CategoryMgr *)iface; + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfCategoryMgr)) + { + *ppvOut = This; + } + + if (*ppvOut) + { + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("unsupported interface: %s\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI CategoryMgr_AddRef(ITfCategoryMgr *iface) +{ + CategoryMgr *This = (CategoryMgr *)iface; + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI CategoryMgr_Release(ITfCategoryMgr *iface) +{ + CategoryMgr *This = (CategoryMgr *)iface; + ULONG ret; + + ret = InterlockedDecrement(&This->refCount); + if (ret == 0) + CategoryMgr_Destructor(This); + return ret; +} + +/***************************************************** + * ITfCategoryMgr functions + *****************************************************/ + +static HRESULT WINAPI CategoryMgr_RegisterCategory ( ITfCategoryMgr *iface, + REFCLSID rclsid, REFGUID rcatid, REFGUID rguid) +{ + WCHAR fullkey[110]; + WCHAR buf[39]; + WCHAR buf2[39]; + ULONG res; + HKEY tipkey,catkey,itmkey; + CategoryMgr *This = (CategoryMgr*)iface; + + static const WCHAR ctg[] = {'C','a','t','e','g','o','r','y',0}; + static const WCHAR itm[] = {'I','t','e','m',0}; + static const WCHAR fmt[] = {'%','s','\\','%','s',0}; + static const WCHAR fmt2[] = {'%','s','\\','%','s','\\','%','s','\\','%','s',0}; + + TRACE("(%p) %s %s %s\n",This,debugstr_guid(rclsid), debugstr_guid(rcatid), debugstr_guid(rguid)); + + StringFromGUID2(rclsid, buf, 39); + sprintfW(fullkey,fmt,szwSystemTIPKey,buf); + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE, + &tipkey ) != ERROR_SUCCESS) + return E_FAIL; + + StringFromGUID2(rcatid, buf, 39); + StringFromGUID2(rguid, buf2, 39); + sprintfW(fullkey,fmt2,ctg,ctg,buf,buf2); + + res = RegCreateKeyExW(tipkey, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE, + NULL, &catkey, NULL); + RegCloseKey(catkey); + + if (!res) + { + sprintfW(fullkey,fmt2,ctg,itm,buf2,buf); + res = RegCreateKeyExW(tipkey, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE, + NULL, &itmkey, NULL); + + RegCloseKey(itmkey); + } + + RegCloseKey(tipkey); + + if (!res) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI CategoryMgr_UnregisterCategory ( ITfCategoryMgr *iface, + REFCLSID rclsid, REFGUID rcatid, REFGUID rguid) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI CategoryMgr_EnumCategoriesInItem ( ITfCategoryMgr *iface, + REFGUID rguid, IEnumGUID **ppEnum) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI CategoryMgr_EnumItemsInCategory ( ITfCategoryMgr *iface, + REFGUID rcatid, IEnumGUID **ppEnum) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI CategoryMgr_FindClosestCategory ( ITfCategoryMgr *iface, + REFGUID rguid, GUID *pcatid, const GUID **ppcatidList, ULONG ulCount) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI CategoryMgr_RegisterGUIDDescription ( + ITfCategoryMgr *iface, REFCLSID rclsid, REFGUID rguid, + const WCHAR *pchDesc, ULONG cch) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI CategoryMgr_UnregisterGUIDDescription ( + ITfCategoryMgr *iface, REFCLSID rclsid, REFGUID rguid) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI CategoryMgr_GetGUIDDescription ( ITfCategoryMgr *iface, + REFGUID rguid, BSTR *pbstrDesc) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI CategoryMgr_RegisterGUIDDWORD ( ITfCategoryMgr *iface, + REFCLSID rclsid, REFGUID rguid, DWORD dw) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI CategoryMgr_UnregisterGUIDDWORD ( ITfCategoryMgr *iface, + REFCLSID rclsid, REFGUID rguid) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI CategoryMgr_GetGUIDDWORD ( ITfCategoryMgr *iface, + REFGUID rguid, DWORD *pdw) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI CategoryMgr_RegisterGUID ( ITfCategoryMgr *iface, + REFGUID rguid, TfGuidAtom *pguidatom +) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI CategoryMgr_GetGUID ( ITfCategoryMgr *iface, + TfGuidAtom guidatom, GUID *pguid) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI CategoryMgr_IsEqualTfGuidAtom ( ITfCategoryMgr *iface, + TfGuidAtom guidatom, REFGUID rguid, BOOL *pfEqual) +{ + CategoryMgr *This = (CategoryMgr*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + + +static const ITfCategoryMgrVtbl CategoryMgr_CategoryMgrVtbl = +{ + CategoryMgr_QueryInterface, + CategoryMgr_AddRef, + CategoryMgr_Release, + + CategoryMgr_RegisterCategory, + CategoryMgr_UnregisterCategory, + CategoryMgr_EnumCategoriesInItem, + CategoryMgr_EnumItemsInCategory, + CategoryMgr_FindClosestCategory, + CategoryMgr_RegisterGUIDDescription, + CategoryMgr_UnregisterGUIDDescription, + CategoryMgr_GetGUIDDescription, + CategoryMgr_RegisterGUIDDWORD, + CategoryMgr_UnregisterGUIDDWORD, + CategoryMgr_GetGUIDDWORD, + CategoryMgr_RegisterGUID, + CategoryMgr_GetGUID, + CategoryMgr_IsEqualTfGuidAtom +}; + +HRESULT CategoryMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) +{ + CategoryMgr *This; + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CategoryMgr)); + if (This == NULL) + return E_OUTOFMEMORY; + + This->CategoryMgrVtbl= &CategoryMgr_CategoryMgrVtbl; + This->refCount = 1; + + TRACE("returning %p\n", This); + *ppOut = (IUnknown *)This; + return S_OK; +} diff --git a/reactos/dll/win32/msctf/context.c b/reactos/dll/win32/msctf/context.c new file mode 100644 index 00000000000..2fc651f101b --- /dev/null +++ b/reactos/dll/win32/msctf/context.c @@ -0,0 +1,609 @@ +/* + * ITfContext implementation + * + * Copyright 2009 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include + +#define COBJMACROS + +#include "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winuser.h" +#include "shlwapi.h" +#include "winerror.h" +#include "objbase.h" +#include "olectl.h" + +#include "wine/unicode.h" +#include "wine/list.h" + +#include "msctf.h" +#include "msctf_internal.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctf); + +typedef struct tagContextSink { + struct list entry; + union { + /* Context Sinks */ + IUnknown *pIUnknown; + /* ITfContextKeyEventSink *pITfContextKeyEventSink; */ + /* ITfEditTransactionSink *pITfEditTransactionSink; */ + /* ITfStatusSink *pITfStatusSink; */ + ITfTextEditSink *pITfTextEditSink; + /* ITfTextLayoutSink *pITfTextLayoutSink; */ + } interfaces; +} ContextSink; + +typedef struct tagContext { + const ITfContextVtbl *ContextVtbl; + const ITfSourceVtbl *SourceVtbl; + LONG refCount; + + TfClientId tidOwner; + + ITextStoreACP *pITextStoreACP; + ITfContextOwnerCompositionSink *pITfContextOwnerCompositionSink; + + ITextStoreACPSink *pITextStoreACPSink; + + /* kept as separate lists to reduce unnecessary iterations */ + struct list pContextKeyEventSink; + struct list pEditTransactionSink; + struct list pStatusSink; + struct list pTextEditSink; + struct list pTextLayoutSink; + +} Context; + + +typedef struct tagTextStoreACPSink { + const ITextStoreACPSinkVtbl *TextStoreACPSinkVtbl; + LONG refCount; + + Context *pContext; +} TextStoreACPSink; + + +static HRESULT TextStoreACPSink_Constructor(ITextStoreACPSink **ppOut, Context *pContext); + +static inline Context *impl_from_ITfSourceVtbl(ITfSource *iface) +{ + return (Context *)((char *)iface - FIELD_OFFSET(Context,SourceVtbl)); +} + +static void free_sink(ContextSink *sink) +{ + IUnknown_Release(sink->interfaces.pIUnknown); + HeapFree(GetProcessHeap(),0,sink); +} + +static void Context_Destructor(Context *This) +{ + struct list *cursor, *cursor2; + TRACE("destroying %p\n", This); + + if (This->pITextStoreACPSink) + { + ITextStoreACP_UnadviseSink(This->pITextStoreACP, (IUnknown*)This->pITextStoreACPSink); + ITextStoreACPSink_Release(This->pITextStoreACPSink); + } + + if (This->pITextStoreACP) + ITextStoreACPSink_Release(This->pITextStoreACP); + + if (This->pITfContextOwnerCompositionSink) + ITextStoreACPSink_Release(This->pITfContextOwnerCompositionSink); + + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pContextKeyEventSink) + { + ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry); + list_remove(cursor); + free_sink(sink); + } + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pEditTransactionSink) + { + ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry); + list_remove(cursor); + free_sink(sink); + } + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pStatusSink) + { + ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry); + list_remove(cursor); + free_sink(sink); + } + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pTextEditSink) + { + ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry); + list_remove(cursor); + free_sink(sink); + } + LIST_FOR_EACH_SAFE(cursor, cursor2, &This->pTextLayoutSink) + { + ContextSink* sink = LIST_ENTRY(cursor,ContextSink,entry); + list_remove(cursor); + free_sink(sink); + } + + HeapFree(GetProcessHeap(),0,This); +} + +static HRESULT WINAPI Context_QueryInterface(ITfContext *iface, REFIID iid, LPVOID *ppvOut) +{ + Context *This = (Context *)iface; + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfContext)) + { + *ppvOut = This; + } + else if (IsEqualIID(iid, &IID_ITfSource)) + { + *ppvOut = &This->SourceVtbl; + } + + if (*ppvOut) + { + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("unsupported interface: %s\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI Context_AddRef(ITfContext *iface) +{ + Context *This = (Context *)iface; + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI Context_Release(ITfContext *iface) +{ + Context *This = (Context *)iface; + ULONG ret; + + ret = InterlockedDecrement(&This->refCount); + if (ret == 0) + Context_Destructor(This); + return ret; +} + +/***************************************************** + * ITfContext functions + *****************************************************/ +static HRESULT WINAPI Context_RequestEditSession (ITfContext *iface, + TfClientId tid, ITfEditSession *pes, DWORD dwFlags, + HRESULT *phrSession) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_InWriteSession (ITfContext *iface, + TfClientId tid, + BOOL *pfWriteSession) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_GetSelection (ITfContext *iface, + TfEditCookie ec, ULONG ulIndex, ULONG ulCount, + TF_SELECTION *pSelection, ULONG *pcFetched) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_SetSelection (ITfContext *iface, + TfEditCookie ec, ULONG ulCount, const TF_SELECTION *pSelection) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_GetStart (ITfContext *iface, + TfEditCookie ec, ITfRange **ppStart) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_GetEnd (ITfContext *iface, + TfEditCookie ec, ITfRange **ppEnd) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_GetActiveView (ITfContext *iface, + ITfContextView **ppView) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_EnumViews (ITfContext *iface, + IEnumTfContextViews **ppEnum) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_GetStatus (ITfContext *iface, + TF_STATUS *pdcs) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_GetProperty (ITfContext *iface, + REFGUID guidProp, ITfProperty **ppProp) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_GetAppProperty (ITfContext *iface, + REFGUID guidProp, ITfReadOnlyProperty **ppProp) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_TrackProperties (ITfContext *iface, + const GUID **prgProp, ULONG cProp, const GUID **prgAppProp, + ULONG cAppProp, ITfReadOnlyProperty **ppProperty) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_EnumProperties (ITfContext *iface, + IEnumTfProperties **ppEnum) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_GetDocumentMgr (ITfContext *iface, + ITfDocumentMgr **ppDm) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI Context_CreateRangeBackup (ITfContext *iface, + TfEditCookie ec, ITfRange *pRange, ITfRangeBackup **ppBackup) +{ + Context *This = (Context *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static const ITfContextVtbl Context_ContextVtbl = +{ + Context_QueryInterface, + Context_AddRef, + Context_Release, + + Context_RequestEditSession, + Context_InWriteSession, + Context_GetSelection, + Context_SetSelection, + Context_GetStart, + Context_GetEnd, + Context_GetActiveView, + Context_EnumViews, + Context_GetStatus, + Context_GetProperty, + Context_GetAppProperty, + Context_TrackProperties, + Context_EnumProperties, + Context_GetDocumentMgr, + Context_CreateRangeBackup +}; + +static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut) +{ + Context *This = impl_from_ITfSourceVtbl(iface); + return Context_QueryInterface((ITfContext *)This, iid, *ppvOut); +} + +static ULONG WINAPI Source_AddRef(ITfSource *iface) +{ + Context *This = impl_from_ITfSourceVtbl(iface); + return Context_AddRef((ITfContext *)This); +} + +static ULONG WINAPI Source_Release(ITfSource *iface) +{ + Context *This = impl_from_ITfSourceVtbl(iface); + return Context_Release((ITfContext *)This); +} + +/***************************************************** + * ITfSource functions + *****************************************************/ +static WINAPI HRESULT ContextSource_AdviseSink(ITfSource *iface, + REFIID riid, IUnknown *punk, DWORD *pdwCookie) +{ + ContextSink *es; + Context *This = impl_from_ITfSourceVtbl(iface); + TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie); + + if (!riid || !punk || !pdwCookie) + return E_INVALIDARG; + + if (IsEqualIID(riid, &IID_ITfTextEditSink)) + { + es = HeapAlloc(GetProcessHeap(),0,sizeof(ContextSink)); + if (!es) + return E_OUTOFMEMORY; + if (!SUCCEEDED(IUnknown_QueryInterface(punk, riid, (LPVOID*)&es->interfaces.pITfTextEditSink))) + { + HeapFree(GetProcessHeap(),0,es); + return CONNECT_E_CANNOTCONNECT; + } + list_add_head(&This->pTextEditSink ,&es->entry); + *pdwCookie = (DWORD)es; + } + else + { + FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid)); + return E_NOTIMPL; + } + + TRACE("cookie %x\n",*pdwCookie); + return S_OK; +} + +static WINAPI HRESULT ContextSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie) +{ + ContextSink *sink = (ContextSink*)pdwCookie; + Context *This = impl_from_ITfSourceVtbl(iface); + TRACE("(%p) %x\n",This,pdwCookie); + + list_remove(&sink->entry); + free_sink(sink); + + return S_OK; +} + +static const ITfSourceVtbl Context_SourceVtbl = +{ + Source_QueryInterface, + Source_AddRef, + Source_Release, + + ContextSource_AdviseSink, + ContextSource_UnadviseSink, +}; + +HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **ppOut, TfEditCookie *pecTextStore) +{ + Context *This; + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Context)); + if (This == NULL) + return E_OUTOFMEMORY; + + TRACE("(%p) %x %p %p %p\n",This, tidOwner, punk, ppOut, pecTextStore); + + This->ContextVtbl= &Context_ContextVtbl; + This->SourceVtbl = &Context_SourceVtbl; + This->refCount = 1; + This->tidOwner = tidOwner; + + if (punk) + { + if (SUCCEEDED(IUnknown_QueryInterface(punk, &IID_ITextStoreACP, + (LPVOID*)&This->pITextStoreACP))) + { + if (SUCCEEDED(TextStoreACPSink_Constructor(&This->pITextStoreACPSink, This))) + ITextStoreACP_AdviseSink(This->pITextStoreACP, &IID_ITextStoreACPSink, + (IUnknown*)This->pITextStoreACPSink, TS_AS_ALL_SINKS); + } + + IUnknown_QueryInterface(punk, &IID_ITfContextOwnerCompositionSink, + (LPVOID*)&This->pITfContextOwnerCompositionSink); + + if (!This->pITextStoreACP && !This->pITfContextOwnerCompositionSink) + FIXME("Unhandled pUnk\n"); + } + + TRACE("returning %p\n", This); + *ppOut = (ITfContext*)This; + /* FIXME */ + *pecTextStore = 0xdeaddead; + + list_init(&This->pContextKeyEventSink); + list_init(&This->pEditTransactionSink); + list_init(&This->pStatusSink); + list_init(&This->pTextEditSink); + list_init(&This->pTextLayoutSink); + + return S_OK; +} + +/************************************************************************** + * ITextStoreACPSink + **************************************************************************/ + +static void TextStoreACPSink_Destructor(TextStoreACPSink *This) +{ + TRACE("destroying %p\n", This); + HeapFree(GetProcessHeap(),0,This); +} + +static HRESULT WINAPI TextStoreACPSink_QueryInterface(ITextStoreACPSink *iface, REFIID iid, LPVOID *ppvOut) +{ + TextStoreACPSink *This = (TextStoreACPSink *)iface; + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITextStoreACPSink)) + { + *ppvOut = This; + } + + if (*ppvOut) + { + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("unsupported interface: %s\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI TextStoreACPSink_AddRef(ITextStoreACPSink *iface) +{ + TextStoreACPSink *This = (TextStoreACPSink *)iface; + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI TextStoreACPSink_Release(ITextStoreACPSink *iface) +{ + TextStoreACPSink *This = (TextStoreACPSink *)iface; + ULONG ret; + + ret = InterlockedDecrement(&This->refCount); + if (ret == 0) + TextStoreACPSink_Destructor(This); + return ret; +} + +/***************************************************** + * ITextStoreACPSink functions + *****************************************************/ + +static HRESULT WINAPI TextStoreACPSink_OnTextChange(ITextStoreACPSink *iface, + DWORD dwFlags, const TS_TEXTCHANGE *pChange) +{ + TextStoreACPSink *This = (TextStoreACPSink *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI TextStoreACPSink_OnSelectionChange(ITextStoreACPSink *iface) +{ + TextStoreACPSink *This = (TextStoreACPSink *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI TextStoreACPSink_OnLayoutChange(ITextStoreACPSink *iface, + TsLayoutCode lcode, TsViewCookie vcView) +{ + TextStoreACPSink *This = (TextStoreACPSink *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI TextStoreACPSink_OnStatusChange(ITextStoreACPSink *iface, + DWORD dwFlags) +{ + TextStoreACPSink *This = (TextStoreACPSink *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI TextStoreACPSink_OnAttrsChange(ITextStoreACPSink *iface, + LONG acpStart, LONG acpEnd, ULONG cAttrs, const TS_ATTRID *paAttrs) +{ + TextStoreACPSink *This = (TextStoreACPSink *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI TextStoreACPSink_OnLockGranted(ITextStoreACPSink *iface, + DWORD dwLockFlags) +{ + TextStoreACPSink *This = (TextStoreACPSink *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI TextStoreACPSink_OnStartEditTransaction(ITextStoreACPSink *iface) +{ + TextStoreACPSink *This = (TextStoreACPSink *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI TextStoreACPSink_OnEndEditTransaction(ITextStoreACPSink *iface) +{ + TextStoreACPSink *This = (TextStoreACPSink *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static const ITextStoreACPSinkVtbl TextStoreACPSink_TextStoreACPSinkVtbl = +{ + TextStoreACPSink_QueryInterface, + TextStoreACPSink_AddRef, + TextStoreACPSink_Release, + + TextStoreACPSink_OnTextChange, + TextStoreACPSink_OnSelectionChange, + TextStoreACPSink_OnLayoutChange, + TextStoreACPSink_OnStatusChange, + TextStoreACPSink_OnAttrsChange, + TextStoreACPSink_OnLockGranted, + TextStoreACPSink_OnStartEditTransaction, + TextStoreACPSink_OnEndEditTransaction +}; + +static HRESULT TextStoreACPSink_Constructor(ITextStoreACPSink **ppOut, Context *pContext) +{ + TextStoreACPSink *This; + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TextStoreACPSink)); + if (This == NULL) + return E_OUTOFMEMORY; + + This->TextStoreACPSinkVtbl= &TextStoreACPSink_TextStoreACPSinkVtbl; + This->refCount = 1; + + This->pContext = pContext; + + TRACE("returning %p\n", This); + *ppOut = (ITextStoreACPSink*)This; + return S_OK; +} diff --git a/reactos/dll/win32/msctf/documentmgr.c b/reactos/dll/win32/msctf/documentmgr.c new file mode 100644 index 00000000000..c87514556ad --- /dev/null +++ b/reactos/dll/win32/msctf/documentmgr.c @@ -0,0 +1,280 @@ +/* + * ITfDocumentMgr implementation + * + * Copyright 2009 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include + +#define COBJMACROS + +#include "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winuser.h" +#include "shlwapi.h" +#include "winerror.h" +#include "objbase.h" + +#include "wine/unicode.h" + +#include "msctf.h" +#include "msctf_internal.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctf); + +typedef struct tagDocumentMgr { + const ITfDocumentMgrVtbl *DocumentMgrVtbl; + const ITfSourceVtbl *SourceVtbl; + LONG refCount; + + ITfContext* contextStack[2]; /* limit of 2 contexts */ +} DocumentMgr; + +static inline DocumentMgr *impl_from_ITfSourceVtbl(ITfSource *iface) +{ + return (DocumentMgr *)((char *)iface - FIELD_OFFSET(DocumentMgr,SourceVtbl)); +} + +static void DocumentMgr_Destructor(DocumentMgr *This) +{ + TRACE("destroying %p\n", This); + if (This->contextStack[0]) + ITfContext_Release(This->contextStack[0]); + if (This->contextStack[1]) + ITfContext_Release(This->contextStack[1]); + HeapFree(GetProcessHeap(),0,This); +} + +static HRESULT WINAPI DocumentMgr_QueryInterface(ITfDocumentMgr *iface, REFIID iid, LPVOID *ppvOut) +{ + DocumentMgr *This = (DocumentMgr *)iface; + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfDocumentMgr)) + { + *ppvOut = This; + } + else if (IsEqualIID(iid, &IID_ITfSource)) + { + *ppvOut = &This->SourceVtbl; + } + + if (*ppvOut) + { + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("unsupported interface: %s\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI DocumentMgr_AddRef(ITfDocumentMgr *iface) +{ + DocumentMgr *This = (DocumentMgr *)iface; + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI DocumentMgr_Release(ITfDocumentMgr *iface) +{ + DocumentMgr *This = (DocumentMgr *)iface; + ULONG ret; + + ret = InterlockedDecrement(&This->refCount); + if (ret == 0) + DocumentMgr_Destructor(This); + return ret; +} + +/***************************************************** + * ITfDocumentMgr functions + *****************************************************/ +static HRESULT WINAPI DocumentMgr_CreateContext(ITfDocumentMgr *iface, + TfClientId tidOwner, + DWORD dwFlags, IUnknown *punk, ITfContext **ppic, + TfEditCookie *pecTextStore) +{ + DocumentMgr *This = (DocumentMgr *)iface; + TRACE("(%p) 0x%x 0x%x %p %p %p\n",This,tidOwner,dwFlags,punk,ppic,pecTextStore); + return Context_Constructor(tidOwner, punk, ppic, pecTextStore); +} + +static HRESULT WINAPI DocumentMgr_Push(ITfDocumentMgr *iface, ITfContext *pic) +{ + DocumentMgr *This = (DocumentMgr *)iface; + ITfContext *check; + + TRACE("(%p) %p\n",This,pic); + + if (This->contextStack[1]) /* FUll */ + return TF_E_STACKFULL; + + if (!pic || FAILED(IUnknown_QueryInterface(pic,&IID_ITfContext,(LPVOID*) &check))) + return E_INVALIDARG; + + This->contextStack[1] = This->contextStack[0]; + This->contextStack[0] = check; + + return S_OK; +} + +static HRESULT WINAPI DocumentMgr_Pop(ITfDocumentMgr *iface, DWORD dwFlags) +{ + DocumentMgr *This = (DocumentMgr *)iface; + TRACE("(%p) 0x%x\n",This,dwFlags); + + if (dwFlags == TF_POPF_ALL) + { + if (This->contextStack[0]) + ITfContext_Release(This->contextStack[0]); + if (This->contextStack[1]) + ITfContext_Release(This->contextStack[1]); + This->contextStack[0] = This->contextStack[1] = NULL; + return S_OK; + } + + if (dwFlags) + return E_INVALIDARG; + + if (This->contextStack[0] == NULL) /* Cannot pop last context */ + return E_FAIL; + + ITfContext_Release(This->contextStack[0]); + This->contextStack[0] = This->contextStack[1]; + This->contextStack[1] = NULL; + + return S_OK; +} + +static HRESULT WINAPI DocumentMgr_GetTop(ITfDocumentMgr *iface, ITfContext **ppic) +{ + DocumentMgr *This = (DocumentMgr *)iface; + TRACE("(%p)\n",This); + if (!ppic) + return E_INVALIDARG; + + if (This->contextStack[0]) + ITfContext_AddRef(This->contextStack[0]); + + *ppic = This->contextStack[0]; + + return S_OK; +} + +static HRESULT WINAPI DocumentMgr_GetBase(ITfDocumentMgr *iface, ITfContext **ppic) +{ + DocumentMgr *This = (DocumentMgr *)iface; + TRACE("(%p)\n",This); + if (!ppic) + return E_INVALIDARG; + + if (This->contextStack[1]) + ITfContext_AddRef(This->contextStack[1]); + + *ppic = This->contextStack[1]; + + return S_OK; +} + +static HRESULT WINAPI DocumentMgr_EnumContexts(ITfDocumentMgr *iface, IEnumTfContexts **ppEnum) +{ + DocumentMgr *This = (DocumentMgr *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static const ITfDocumentMgrVtbl DocumentMgr_DocumentMgrVtbl = +{ + DocumentMgr_QueryInterface, + DocumentMgr_AddRef, + DocumentMgr_Release, + + DocumentMgr_CreateContext, + DocumentMgr_Push, + DocumentMgr_Pop, + DocumentMgr_GetTop, + DocumentMgr_GetBase, + DocumentMgr_EnumContexts +}; + + +static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut) +{ + DocumentMgr *This = impl_from_ITfSourceVtbl(iface); + return DocumentMgr_QueryInterface((ITfDocumentMgr*)This, iid, *ppvOut); +} + +static ULONG WINAPI Source_AddRef(ITfSource *iface) +{ + DocumentMgr *This = impl_from_ITfSourceVtbl(iface); + return DocumentMgr_AddRef((ITfDocumentMgr*)This); +} + +static ULONG WINAPI Source_Release(ITfSource *iface) +{ + DocumentMgr *This = impl_from_ITfSourceVtbl(iface); + return DocumentMgr_Release((ITfDocumentMgr*)This); +} + +/***************************************************** + * ITfSource functions + *****************************************************/ +static WINAPI HRESULT DocumentMgrSource_AdviseSink(ITfSource *iface, + REFIID riid, IUnknown *punk, DWORD *pdwCookie) +{ + DocumentMgr *This = impl_from_ITfSourceVtbl(iface); + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static WINAPI HRESULT DocumentMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie) +{ + DocumentMgr *This = impl_from_ITfSourceVtbl(iface); + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static const ITfSourceVtbl DocumentMgr_SourceVtbl = +{ + Source_QueryInterface, + Source_AddRef, + Source_Release, + + DocumentMgrSource_AdviseSink, + DocumentMgrSource_UnadviseSink, +}; + +HRESULT DocumentMgr_Constructor(ITfDocumentMgr **ppOut) +{ + DocumentMgr *This; + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DocumentMgr)); + if (This == NULL) + return E_OUTOFMEMORY; + + This->DocumentMgrVtbl= &DocumentMgr_DocumentMgrVtbl; + This->SourceVtbl = &DocumentMgr_SourceVtbl; + This->refCount = 1; + + TRACE("returning %p\n", This); + *ppOut = (ITfDocumentMgr*)This; + return S_OK; +} diff --git a/reactos/dll/win32/msctf/inputprocessor.c b/reactos/dll/win32/msctf/inputprocessor.c new file mode 100644 index 00000000000..de39af977a5 --- /dev/null +++ b/reactos/dll/win32/msctf/inputprocessor.c @@ -0,0 +1,885 @@ +/* + * ITfInputProcessorProfiles implementation + * + * Copyright 2009 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include + +#define COBJMACROS + +#include "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winuser.h" +#include "shlwapi.h" +#include "winerror.h" +#include "objbase.h" + +#include "wine/unicode.h" + +#include "msctf.h" +#include "msctf_internal.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctf); + +static const WCHAR szwLngp[] = {'L','a','n','g','u','a','g','e','P','r','o','f','i','l','e',0}; +static const WCHAR szwEnabled[] = {'E','n','a','b','l','e','d',0}; +static const WCHAR szwTipfmt[] = {'%','s','\\','%','s',0}; +static const WCHAR szwFullLangfmt[] = {'%','s','\\','%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0}; + +typedef struct tagInputProcessorProfiles { + const ITfInputProcessorProfilesVtbl *InputProcessorProfilesVtbl; + LONG refCount; + + LANGID currentLanguage; +} InputProcessorProfiles; + +typedef struct tagProfilesEnumGuid { + const IEnumGUIDVtbl *Vtbl; + LONG refCount; + + HKEY key; + DWORD next_index; +} ProfilesEnumGuid; + +typedef struct tagEnumTfLanguageProfiles { + const IEnumTfLanguageProfilesVtbl *Vtbl; + LONG refCount; + + HKEY tipkey; + DWORD tip_index; + WCHAR szwCurrentClsid[39]; + + HKEY langkey; + DWORD lang_index; + + LANGID langid; +} EnumTfLanguageProfiles; + +static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut); +static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut); + +static void InputProcessorProfiles_Destructor(InputProcessorProfiles *This) +{ + TRACE("destroying %p\n", This); + HeapFree(GetProcessHeap(),0,This); +} + +static void add_userkey( REFCLSID rclsid, LANGID langid, + REFGUID guidProfile) +{ + HKEY key; + WCHAR buf[39]; + WCHAR buf2[39]; + WCHAR fullkey[168]; + DWORD disposition = 0; + ULONG res; + + TRACE("\n"); + + StringFromGUID2(rclsid, buf, 39); + StringFromGUID2(guidProfile, buf2, 39); + sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2); + + res = RegCreateKeyExW(HKEY_CURRENT_USER,fullkey, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &key, &disposition); + + if (!res && disposition == REG_CREATED_NEW_KEY) + { + DWORD zero = 0x0; + RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD)); + } + + if (!res) + RegCloseKey(key); +} + +static HRESULT WINAPI InputProcessorProfiles_QueryInterface(ITfInputProcessorProfiles *iface, REFIID iid, LPVOID *ppvOut) +{ + InputProcessorProfiles *This = (InputProcessorProfiles *)iface; + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfInputProcessorProfiles)) + { + *ppvOut = This; + } + + if (*ppvOut) + { + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("unsupported interface: %s\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI InputProcessorProfiles_AddRef(ITfInputProcessorProfiles *iface) +{ + InputProcessorProfiles *This = (InputProcessorProfiles *)iface; + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI InputProcessorProfiles_Release(ITfInputProcessorProfiles *iface) +{ + InputProcessorProfiles *This = (InputProcessorProfiles *)iface; + ULONG ret; + + ret = InterlockedDecrement(&This->refCount); + if (ret == 0) + InputProcessorProfiles_Destructor(This); + return ret; +} + +/***************************************************** + * ITfInputProcessorProfiles functions + *****************************************************/ +static HRESULT WINAPI InputProcessorProfiles_Register( + ITfInputProcessorProfiles *iface, REFCLSID rclsid) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + HKEY tipkey; + WCHAR buf[39]; + WCHAR fullkey[68]; + + TRACE("(%p) %s\n",This,debugstr_guid(rclsid)); + + StringFromGUID2(rclsid, buf, 39); + sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf); + + if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &tipkey, NULL) != ERROR_SUCCESS) + return E_FAIL; + + RegCloseKey(tipkey); + + return S_OK; +} + +static HRESULT WINAPI InputProcessorProfiles_Unregister( + ITfInputProcessorProfiles *iface, REFCLSID rclsid) +{ + WCHAR buf[39]; + WCHAR fullkey[68]; + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + + TRACE("(%p) %s\n",This,debugstr_guid(rclsid)); + + StringFromGUID2(rclsid, buf, 39); + sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf); + + RegDeleteTreeW(HKEY_LOCAL_MACHINE, fullkey); + RegDeleteTreeW(HKEY_CURRENT_USER, fullkey); + + return S_OK; +} + +static HRESULT WINAPI InputProcessorProfiles_AddLanguageProfile( + ITfInputProcessorProfiles *iface, REFCLSID rclsid, + LANGID langid, REFGUID guidProfile, const WCHAR *pchDesc, + ULONG cchDesc, const WCHAR *pchIconFile, ULONG cchFile, + ULONG uIconIndex) +{ + HKEY tipkey,fmtkey; + WCHAR buf[39]; + WCHAR fullkey[100]; + ULONG res; + DWORD disposition = 0; + + static const WCHAR fmt2[] = {'%','s','\\','0','x','%','0','8','x','\\','%','s',0}; + static const WCHAR desc[] = {'D','e','s','c','r','i','p','t','i','o','n',0}; + static const WCHAR icnf[] = {'I','c','o','n','F','i','l','e',0}; + static const WCHAR icni[] = {'I','c','o','n','I','n','d','e','x',0}; + + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + + TRACE("(%p) %s %x %s %s %s %i\n",This,debugstr_guid(rclsid), langid, + debugstr_guid(guidProfile), debugstr_wn(pchDesc,cchDesc), + debugstr_wn(pchIconFile,cchFile),uIconIndex); + + StringFromGUID2(rclsid, buf, 39); + sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf); + + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE, + &tipkey ) != ERROR_SUCCESS) + return E_FAIL; + + StringFromGUID2(guidProfile, buf, 39); + sprintfW(fullkey,fmt2,szwLngp,langid,buf); + + res = RegCreateKeyExW(tipkey,fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE, + NULL, &fmtkey, &disposition); + + if (!res) + { + DWORD zero = 0x0; + RegSetValueExW(fmtkey, desc, 0, REG_SZ, (LPBYTE)pchDesc, cchDesc * sizeof(WCHAR)); + RegSetValueExW(fmtkey, icnf, 0, REG_SZ, (LPBYTE)pchIconFile, cchFile * sizeof(WCHAR)); + RegSetValueExW(fmtkey, icni, 0, REG_DWORD, (LPBYTE)&uIconIndex, sizeof(DWORD)); + if (disposition == REG_CREATED_NEW_KEY) + RegSetValueExW(fmtkey, szwEnabled, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD)); + RegCloseKey(fmtkey); + + add_userkey(rclsid, langid, guidProfile); + } + RegCloseKey(tipkey); + + if (!res) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI InputProcessorProfiles_RemoveLanguageProfile( + ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, + REFGUID guidProfile) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI InputProcessorProfiles_EnumInputProcessorInfo( + ITfInputProcessorProfiles *iface, IEnumGUID **ppEnum) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + TRACE("(%p) %p\n",This,ppEnum); + return ProfilesEnumGuid_Constructor(ppEnum); +} + +static HRESULT WINAPI InputProcessorProfiles_GetDefaultLanguageProfile( + ITfInputProcessorProfiles *iface, LANGID langid, REFGUID catid, + CLSID *pclsid, GUID *pguidProfile) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI InputProcessorProfiles_SetDefaultLanguageProfile( + ITfInputProcessorProfiles *iface, LANGID langid, REFCLSID rclsid, + REFGUID guidProfiles) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI InputProcessorProfiles_ActivateLanguageProfile( + ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, + REFGUID guidProfiles) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI InputProcessorProfiles_GetActiveLanguageProfile( + ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID *plangid, + GUID *pguidProfile) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI InputProcessorProfiles_GetLanguageProfileDescription( + ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, + REFGUID guidProfile, BSTR *pbstrProfile) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI InputProcessorProfiles_GetCurrentLanguage( + ITfInputProcessorProfiles *iface, LANGID *plangid) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + TRACE("(%p) 0x%x\n",This,This->currentLanguage); + + if (!plangid) + return E_INVALIDARG; + + *plangid = This->currentLanguage; + + return S_OK; +} + +static HRESULT WINAPI InputProcessorProfiles_ChangeCurrentLanguage( + ITfInputProcessorProfiles *iface, LANGID langid) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI InputProcessorProfiles_GetLanguageList( + ITfInputProcessorProfiles *iface, LANGID **ppLangId, ULONG *pulCount) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI InputProcessorProfiles_EnumLanguageProfiles( + ITfInputProcessorProfiles *iface, LANGID langid, + IEnumTfLanguageProfiles **ppEnum) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + TRACE("(%p) %x %p\n",This,langid,ppEnum); + return EnumTfLanguageProfiles_Constructor(langid, ppEnum); +} + +static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfile( + ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, + REFGUID guidProfile, BOOL fEnable) +{ + HKEY key; + WCHAR buf[39]; + WCHAR buf2[39]; + WCHAR fullkey[168]; + ULONG res; + + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + TRACE("(%p) %s %x %s %i\n",This, debugstr_guid(rclsid), langid, debugstr_guid(guidProfile), fEnable); + + StringFromGUID2(rclsid, buf, 39); + StringFromGUID2(guidProfile, buf2, 39); + sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2); + + res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key); + + if (!res) + { + RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD)); + RegCloseKey(key); + } + else + return E_FAIL; + + return S_OK; +} + +static HRESULT WINAPI InputProcessorProfiles_IsEnabledLanguageProfile( + ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, + REFGUID guidProfile, BOOL *pfEnable) +{ + HKEY key; + WCHAR buf[39]; + WCHAR buf2[39]; + WCHAR fullkey[168]; + ULONG res; + + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + TRACE("(%p) %s, %i, %s, %p\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),pfEnable); + + if (!pfEnable) + return E_INVALIDARG; + + StringFromGUID2(rclsid, buf, 39); + StringFromGUID2(guidProfile, buf2, 39); + sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2); + + res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key); + + if (!res) + { + DWORD count = sizeof(DWORD); + res = RegQueryValueExW(key, szwEnabled, 0, NULL, (LPBYTE)pfEnable, &count); + RegCloseKey(key); + } + + if (res) /* Try Default */ + { + res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key); + + if (!res) + { + DWORD count = sizeof(DWORD); + res = RegQueryValueExW(key, szwEnabled, 0, NULL, (LPBYTE)pfEnable, &count); + RegCloseKey(key); + } + } + + if (!res) + return S_OK; + else + return E_FAIL; +} + +static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfileByDefault( + ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, + REFGUID guidProfile, BOOL fEnable) +{ + HKEY key; + WCHAR buf[39]; + WCHAR buf2[39]; + WCHAR fullkey[168]; + ULONG res; + + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + TRACE("(%p) %s %x %s %i\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),fEnable); + + StringFromGUID2(rclsid, buf, 39); + StringFromGUID2(guidProfile, buf2, 39); + sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2); + + res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key); + + if (!res) + { + RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD)); + RegCloseKey(key); + } + else + return E_FAIL; + + return S_OK; +} + +static HRESULT WINAPI InputProcessorProfiles_SubstituteKeyboardLayout( + ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, + REFGUID guidProfile, HKL hKL) +{ + InputProcessorProfiles *This = (InputProcessorProfiles*)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + + +static const ITfInputProcessorProfilesVtbl InputProcessorProfiles_InputProcessorProfilesVtbl = +{ + InputProcessorProfiles_QueryInterface, + InputProcessorProfiles_AddRef, + InputProcessorProfiles_Release, + + InputProcessorProfiles_Register, + InputProcessorProfiles_Unregister, + InputProcessorProfiles_AddLanguageProfile, + InputProcessorProfiles_RemoveLanguageProfile, + InputProcessorProfiles_EnumInputProcessorInfo, + InputProcessorProfiles_GetDefaultLanguageProfile, + InputProcessorProfiles_SetDefaultLanguageProfile, + InputProcessorProfiles_ActivateLanguageProfile, + InputProcessorProfiles_GetActiveLanguageProfile, + InputProcessorProfiles_GetLanguageProfileDescription, + InputProcessorProfiles_GetCurrentLanguage, + InputProcessorProfiles_ChangeCurrentLanguage, + InputProcessorProfiles_GetLanguageList, + InputProcessorProfiles_EnumLanguageProfiles, + InputProcessorProfiles_EnableLanguageProfile, + InputProcessorProfiles_IsEnabledLanguageProfile, + InputProcessorProfiles_EnableLanguageProfileByDefault, + InputProcessorProfiles_SubstituteKeyboardLayout +}; + +HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) +{ + InputProcessorProfiles *This; + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputProcessorProfiles)); + if (This == NULL) + return E_OUTOFMEMORY; + + This->InputProcessorProfilesVtbl= &InputProcessorProfiles_InputProcessorProfilesVtbl; + This->refCount = 1; + This->currentLanguage = GetUserDefaultLCID(); + + TRACE("returning %p\n", This); + *ppOut = (IUnknown *)This; + return S_OK; +} + +/************************************************** + * IEnumGUID implementaion for ITfInputProcessorProfiles::EnumInputProcessorInfo + **************************************************/ +static void ProfilesEnumGuid_Destructor(ProfilesEnumGuid *This) +{ + TRACE("destroying %p\n", This); + RegCloseKey(This->key); + HeapFree(GetProcessHeap(),0,This); +} + +static HRESULT WINAPI ProfilesEnumGuid_QueryInterface(IEnumGUID *iface, REFIID iid, LPVOID *ppvOut) +{ + ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface; + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumGUID)) + { + *ppvOut = This; + } + + if (*ppvOut) + { + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("unsupported interface: %s\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI ProfilesEnumGuid_AddRef(IEnumGUID *iface) +{ + ProfilesEnumGuid *This = (ProfilesEnumGuid*)iface; + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI ProfilesEnumGuid_Release(IEnumGUID *iface) +{ + ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface; + ULONG ret; + + ret = InterlockedDecrement(&This->refCount); + if (ret == 0) + ProfilesEnumGuid_Destructor(This); + return ret; +} + +/***************************************************** + * IEnumGuid functions + *****************************************************/ +static HRESULT WINAPI ProfilesEnumGuid_Next( LPENUMGUID iface, + ULONG celt, GUID *rgelt, ULONG *pceltFetched) +{ + ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface; + ULONG fetched = 0; + + TRACE("(%p)\n",This); + + if (rgelt == NULL) return E_POINTER; + + if (This->key) while (fetched < celt) + { + LSTATUS res; + HRESULT hr; + WCHAR catid[39]; + DWORD cName = 39; + + res = RegEnumKeyExW(This->key, This->next_index, catid, &cName, + NULL, NULL, NULL, NULL); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break; + ++(This->next_index); + + hr = CLSIDFromString(catid, rgelt); + if (FAILED(hr)) continue; + + ++fetched; + ++rgelt; + } + + if (pceltFetched) *pceltFetched = fetched; + return fetched == celt ? S_OK : S_FALSE; +} + +static HRESULT WINAPI ProfilesEnumGuid_Skip( LPENUMGUID iface, ULONG celt) +{ + ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface; + TRACE("(%p)\n",This); + + This->next_index += celt; + return S_OK; +} + +static HRESULT WINAPI ProfilesEnumGuid_Reset( LPENUMGUID iface) +{ + ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface; + TRACE("(%p)\n",This); + This->next_index = 0; + return S_OK; +} + +static HRESULT WINAPI ProfilesEnumGuid_Clone( LPENUMGUID iface, + IEnumGUID **ppenum) +{ + ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface; + HRESULT res; + + TRACE("(%p)\n",This); + + if (ppenum == NULL) return E_POINTER; + + res = ProfilesEnumGuid_Constructor(ppenum); + if (SUCCEEDED(res)) + { + ProfilesEnumGuid *new_This = (ProfilesEnumGuid *)*ppenum; + new_This->next_index = This->next_index; + } + return res; +} + +static const IEnumGUIDVtbl IEnumGUID_Vtbl ={ + ProfilesEnumGuid_QueryInterface, + ProfilesEnumGuid_AddRef, + ProfilesEnumGuid_Release, + + ProfilesEnumGuid_Next, + ProfilesEnumGuid_Skip, + ProfilesEnumGuid_Reset, + ProfilesEnumGuid_Clone +}; + +static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut) +{ + ProfilesEnumGuid *This; + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ProfilesEnumGuid)); + if (This == NULL) + return E_OUTOFMEMORY; + + This->Vtbl= &IEnumGUID_Vtbl; + This->refCount = 1; + + if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &This->key, NULL) != ERROR_SUCCESS) + return E_FAIL; + + TRACE("returning %p\n", This); + *ppOut = (IEnumGUID*)This; + return S_OK; +} + +/************************************************** + * IEnumTfLanguageProfiles implementaion + **************************************************/ +static void EnumTfLanguageProfiles_Destructor(EnumTfLanguageProfiles *This) +{ + TRACE("destroying %p\n", This); + RegCloseKey(This->tipkey); + if (This->langkey) + RegCloseKey(This->langkey); + HeapFree(GetProcessHeap(),0,This); +} + +static HRESULT WINAPI EnumTfLanguageProfiles_QueryInterface(IEnumTfLanguageProfiles *iface, REFIID iid, LPVOID *ppvOut) +{ + EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface; + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfLanguageProfiles)) + { + *ppvOut = This; + } + + if (*ppvOut) + { + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("unsupported interface: %s\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI EnumTfLanguageProfiles_AddRef(IEnumTfLanguageProfiles *iface) +{ + EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles*)iface; + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI EnumTfLanguageProfiles_Release(IEnumTfLanguageProfiles *iface) +{ + EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface; + ULONG ret; + + ret = InterlockedDecrement(&This->refCount); + if (ret == 0) + EnumTfLanguageProfiles_Destructor(This); + return ret; +} + +/***************************************************** + * IEnumGuid functions + *****************************************************/ +static INT next_LanguageProfile(EnumTfLanguageProfiles *This, CLSID clsid, TF_LANGUAGEPROFILE *tflp) +{ + WCHAR fullkey[168]; + ULONG res; + WCHAR profileid[39]; + DWORD cName = 39; + GUID profile; + + static const WCHAR fmt[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0}; + + if (This->langkey == NULL) + { + sprintfW(fullkey,fmt,This->szwCurrentClsid,szwLngp,This->langid); + res = RegOpenKeyExW(This->tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &This->langkey); + if (res) + { + This->langkey = NULL; + return -1; + } + This->lang_index = 0; + } + res = RegEnumKeyExW(This->langkey, This->lang_index, profileid, &cName, + NULL, NULL, NULL, NULL); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) + { + RegCloseKey(This->langkey); + This->langkey = NULL; + return -1; + } + ++(This->lang_index); + + if (tflp) + { + res = CLSIDFromString(profileid, &profile); + if (FAILED(res)) return 0; + + tflp->clsid = clsid; + tflp->langid = This->langid; + /* FIXME */ + tflp->fActive = FALSE; + tflp->guidProfile = profile; + /* FIXME set catid */ + } + + return 1; +} + +static HRESULT WINAPI EnumTfLanguageProfiles_Next(IEnumTfLanguageProfiles *iface, + ULONG ulCount, TF_LANGUAGEPROFILE *pProfile, ULONG *pcFetch) +{ + EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface; + ULONG fetched = 0; + + TRACE("(%p)\n",This); + + if (pProfile == NULL) return E_POINTER; + + if (This->tipkey) while (fetched < ulCount) + { + LSTATUS res; + HRESULT hr; + DWORD cName = 39; + GUID clsid; + + res = RegEnumKeyExW(This->tipkey, This->tip_index, + This->szwCurrentClsid, &cName, NULL, NULL, NULL, NULL); + if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break; + ++(This->tip_index); + hr = CLSIDFromString(This->szwCurrentClsid, &clsid); + if (FAILED(hr)) continue; + + while ( fetched < ulCount) + { + INT res = next_LanguageProfile(This, clsid, pProfile); + if (res == 1) + { + ++fetched; + ++pProfile; + } + else if (res == -1) + break; + else + continue; + } + } + + if (pcFetch) *pcFetch = fetched; + return fetched == ulCount ? S_OK : S_FALSE; +} + +static HRESULT WINAPI EnumTfLanguageProfiles_Skip( IEnumTfLanguageProfiles* iface, ULONG celt) +{ + EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface; + FIXME("STUB (%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI EnumTfLanguageProfiles_Reset( IEnumTfLanguageProfiles* iface) +{ + EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface; + TRACE("(%p)\n",This); + This->tip_index = 0; + if (This->langkey) + RegCloseKey(This->langkey); + This->langkey = NULL; + This->lang_index = 0; + return S_OK; +} + +static HRESULT WINAPI EnumTfLanguageProfiles_Clone( IEnumTfLanguageProfiles *iface, + IEnumTfLanguageProfiles **ppenum) +{ + EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface; + HRESULT res; + + TRACE("(%p)\n",This); + + if (ppenum == NULL) return E_POINTER; + + res = EnumTfLanguageProfiles_Constructor(This->langid, ppenum); + if (SUCCEEDED(res)) + { + EnumTfLanguageProfiles *new_This = (EnumTfLanguageProfiles *)*ppenum; + new_This->tip_index = This->tip_index; + lstrcpynW(new_This->szwCurrentClsid,This->szwCurrentClsid,39); + + if (This->langkey) + { + WCHAR fullkey[168]; + static const WCHAR fmt[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0}; + + sprintfW(fullkey,fmt,This->szwCurrentClsid,szwLngp,This->langid); + res = RegOpenKeyExW(new_This->tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &This->langkey); + new_This->lang_index = This->lang_index; + } + } + return res; +} + +static const IEnumTfLanguageProfilesVtbl IEnumTfLanguageProfiles_Vtbl ={ + EnumTfLanguageProfiles_QueryInterface, + EnumTfLanguageProfiles_AddRef, + EnumTfLanguageProfiles_Release, + + EnumTfLanguageProfiles_Clone, + EnumTfLanguageProfiles_Next, + EnumTfLanguageProfiles_Reset, + EnumTfLanguageProfiles_Skip +}; + +static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut) +{ + EnumTfLanguageProfiles *This; + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfLanguageProfiles)); + if (This == NULL) + return E_OUTOFMEMORY; + + This->Vtbl= &IEnumTfLanguageProfiles_Vtbl; + This->refCount = 1; + This->langid = langid; + + if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &This->tipkey, NULL) != ERROR_SUCCESS) + return E_FAIL; + + TRACE("returning %p\n", This); + *ppOut = (IEnumTfLanguageProfiles*)This; + return S_OK; +} diff --git a/reactos/dll/win32/msctf/msctf.c b/reactos/dll/win32/msctf/msctf.c new file mode 100644 index 00000000000..1f5e35bc824 --- /dev/null +++ b/reactos/dll/win32/msctf/msctf.c @@ -0,0 +1,252 @@ +/* + * MSCTF Server DLL + * + * Copyright 2008 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include +#include + +#define COBJMACROS + +#include "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "shlwapi.h" +#include "shlguid.h" +#include "comcat.h" +#include "initguid.h" +#include "msctf.h" + +#include "msctf_internal.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctf); + +static LONG MSCTF_refCount; + +static HINSTANCE MSCTF_hinstance; + +DWORD tlsIndex = 0; + +const WCHAR szwSystemTIPKey[] = {'S','O','F','T','W','A','R','E','\\','M','i','c','r','o','s','o','f','t','\\','C','T','F','\\','T','I','P',0}; + +typedef HRESULT (*LPFNCONSTRUCTOR)(IUnknown *pUnkOuter, IUnknown **ppvOut); + +static const struct { + REFCLSID clsid; + LPFNCONSTRUCTOR ctor; +} ClassesTable[] = { + {&CLSID_TF_ThreadMgr, ThreadMgr_Constructor}, + {&CLSID_TF_InputProcessorProfiles, InputProcessorProfiles_Constructor}, + {&CLSID_TF_CategoryMgr, CategoryMgr_Constructor}, + {NULL, NULL} +}; + +typedef struct tagClassFactory +{ + const IClassFactoryVtbl *vtbl; + LONG ref; + LPFNCONSTRUCTOR ctor; +} ClassFactory; + +static void ClassFactory_Destructor(ClassFactory *This) +{ + TRACE("Destroying class factory %p\n", This); + HeapFree(GetProcessHeap(),0,This); + MSCTF_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; + } + + WARN("Unknown interface %s\n", debugstr_guid(riid)); + 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; + + TRACE("(%p, %p, %s, %p)\n", iface, punkOuter, debugstr_guid(iid), ppvOut); + 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) +{ + ClassFactory *This = (ClassFactory *)iface; + + TRACE("(%p)->(%x)\n", This, fLock); + + if(fLock) + InterlockedIncrement(&MSCTF_refCount); + else + InterlockedDecrement(&MSCTF_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; + TRACE("Created class factory %p\n", This); + MSCTF_refCount++; + return S_OK; +} + +/************************************************************************* + * MSCTF DllMain + */ +BOOL WINAPI DllMain(HINSTANCE hinst, DWORD fdwReason, LPVOID fImpLoad) +{ + TRACE("%p 0x%x %p\n", hinst, fdwReason, fImpLoad); + switch (fdwReason) + { + case DLL_WINE_PREATTACH: + return FALSE; /* prefer native version */ + case DLL_PROCESS_ATTACH: + MSCTF_hinstance = hinst; + tlsIndex = TlsAlloc(); + break; + case DLL_PROCESS_DETACH: + TlsFree(tlsIndex); + break; + } + return TRUE; +} + +/************************************************************************* + * DllCanUnloadNow (MSCTF.@) + */ +HRESULT WINAPI DllCanUnloadNow(void) +{ + return MSCTF_refCount ? S_FALSE : S_OK; +} + +/*********************************************************************** + * DllGetClassObject (MSCTF.@) + */ +HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, LPVOID *ppvOut) +{ + int i; + + *ppvOut = NULL; + if (!IsEqualIID(iid, &IID_IUnknown) && !IsEqualIID(iid, &IID_IClassFactory)) + return E_NOINTERFACE; + + for (i = 0; ClassesTable[i].clsid != NULL; i++) + if (IsEqualCLSID(ClassesTable[i].clsid, clsid)) { + return ClassFactory_Constructor(ClassesTable[i].ctor, ppvOut); + } + FIXME("CLSID %s not supported\n", debugstr_guid(clsid)); + return CLASS_E_CLASSNOTAVAILABLE; +} + +/*********************************************************************** + * TF_CreateThreadMgr (MSCTF.@) + */ +HRESULT WINAPI TF_CreateThreadMgr(ITfThreadMgr **pptim) +{ + TRACE("\n"); + return ThreadMgr_Constructor(NULL,(IUnknown**)pptim); +} + +/*********************************************************************** + * TF_GetThreadMgr (MSCTF.@) + */ +HRESULT WINAPI TF_GetThreadMgr(ITfThreadMgr **pptim) +{ + TRACE("\n"); + *pptim = (ITfThreadMgr*)TlsGetValue(tlsIndex); + + if (*pptim) + ITfThreadMgr_AddRef(*pptim); + + return S_OK; +} + +/*********************************************************************** + * SetInputScope(MSCTF.@) + */ +HRESULT WINAPI SetInputScope(HWND hwnd, INT inputscope) +{ + FIXME("STUB: %p %i\n",hwnd,inputscope); + return S_OK; +} + +/*********************************************************************** + * SetInputScopes(MSCTF.@) + */ +HRESULT WINAPI SetInputScopes(HWND hwnd, const INT *pInputScopes, + UINT cInputScopes, WCHAR **ppszPhraseList, + UINT cPhrases, WCHAR *pszRegExp, WCHAR *pszSRGS) +{ + int i; + FIXME("STUB: %p ... %s %s\n",hwnd, debugstr_w(pszRegExp), debugstr_w(pszSRGS)); + for (i = 0; i < cInputScopes; i++) + TRACE("\tScope[%i] = %i\n",i,pInputScopes[i]); + for (i = 0; i < cPhrases; i++) + TRACE("\tPhrase[%i] = %s\n",i,debugstr_w(ppszPhraseList[i])); + + return S_OK; +} diff --git a/reactos/dll/win32/msctf/msctf.rbuild b/reactos/dll/win32/msctf/msctf.rbuild new file mode 100644 index 00000000000..c2ae0483837 --- /dev/null +++ b/reactos/dll/win32/msctf/msctf.rbuild @@ -0,0 +1,22 @@ + + + + . + include/reactos/wine + + 0x600 + categorymgr.c + context.c + documentmgr.c + inputprocessor.c + msctf.c + regsvr.c + threadmgr.c + wine + uuid + ole32 + user32 + advapi32 + kernel32 + ntdll + diff --git a/reactos/dll/win32/msctf/msctf.spec b/reactos/dll/win32/msctf/msctf.spec new file mode 100644 index 00000000000..1c8bb37a1b4 --- /dev/null +++ b/reactos/dll/win32/msctf/msctf.spec @@ -0,0 +1,34 @@ +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetClassObject(ptr ptr ptr) +@ stdcall -private DllRegisterServer() +@ stdcall -private DllUnregisterServer() +@ stdcall SetInputScope(long long) +@ stub SetInputScopeXML +@ stdcall SetInputScopes(long ptr long ptr long wstr wstr) +@ stub TF_CUASAppFix +@ stub TF_CheckThreadInputIdle +@ stub TF_ClearLangBarAddIns +@ stub TF_CreateCategoryMgr +@ stub TF_CreateCicLoadMutex +@ stub TF_CreateDisplayAttributeMgr +@ stub TF_CreateInputProcessorProfiles +@ stub TF_CreateLangBarItemMgr +@ stub TF_CreateLangBarMgr +@ stdcall TF_CreateThreadMgr(ptr) +@ stub TF_DllDetachInOther +@ stub TF_GetGlobalCompartment +@ stub TF_GetInputScope +@ stub TF_GetLangIcon +@ stub TF_GetMlngHKL +@ stub TF_GetMlngIconIndex +@ stub TF_GetThreadFlags +@ stdcall TF_GetThreadMgr(ptr) +@ stub TF_InatExtractIcon +@ stub TF_InitMlngInfo +@ stub TF_InitSystem +@ stub TF_InvalidAssemblyListCache +@ stub TF_InvalidAssemblyListCacheIfExist +@ stub TF_IsCtfmonRunning +@ stub TF_IsInMarshaling +@ stub TF_MlngInfoCount +@ stub TF_RunInputCPL diff --git a/reactos/dll/win32/msctf/msctf_internal.h b/reactos/dll/win32/msctf/msctf_internal.h new file mode 100644 index 00000000000..4d83aa392bd --- /dev/null +++ b/reactos/dll/win32/msctf/msctf_internal.h @@ -0,0 +1,32 @@ +/* + * Internal header for msctf.dll + * + * Copyright 2008 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef __WINE_MSCTF_I_H +#define __WINE_MSCTF_I_H +extern DWORD tlsIndex; + +extern HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut); +extern HRESULT DocumentMgr_Constructor(ITfDocumentMgr **ppOut); +extern HRESULT Context_Constructor(TfClientId tidOwner, IUnknown *punk, ITfContext **ppOut, TfEditCookie *pecTextStore); +extern HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut); +extern HRESULT CategoryMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut); + +extern const WCHAR szwSystemTIPKey[]; +#endif /* __WINE_MSCTF_I_H */ diff --git a/reactos/dll/win32/msctf/regsvr.c b/reactos/dll/win32/msctf/regsvr.c new file mode 100644 index 00000000000..a47d984296f --- /dev/null +++ b/reactos/dll/win32/msctf/regsvr.c @@ -0,0 +1,504 @@ +/* + * self-registerable dll functions for msctf + * + * Copyright (C) 2004 Stefan Leichter + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "winuser.h" +#include "wingdi.h" +#include "winreg.h" +#include "winerror.h" + +#include "ole2.h" +#include "shlguid.h" +#include "msctf.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctf); + +/* + * Near the bottom of this file are the exported DllRegisterServer and + * DllUnregisterServer, which make all this worthwhile. + */ + +/*********************************************************************** + * interface for self-registering + */ +struct regsvr_interface +{ + IID const *iid; /* NULL for end of list */ + LPCSTR name; /* can be NULL to omit */ + IID const *base_iid; /* can be NULL to omit */ + int num_methods; /* can be <0 to omit */ + CLSID const *ps_clsid; /* can be NULL to omit */ + CLSID const *ps_clsid32; /* can be NULL to omit */ +}; + +static HRESULT register_interfaces(struct regsvr_interface const *list); +static HRESULT unregister_interfaces(struct regsvr_interface const *list); + +struct regsvr_coclass +{ + CLSID const *clsid; /* NULL for end of list */ + LPCSTR name; /* can be NULL to omit */ + LPCSTR ips; /* can be NULL to omit */ + LPCSTR ips32; /* can be NULL to omit */ + LPCSTR ips32_tmodel; /* can be NULL to omit */ + LPCSTR progid; /* can be NULL to omit */ + LPCSTR viprogid; /* can be NULL to omit */ + LPCSTR progid_extra; /* can be NULL to omit */ +}; + +static HRESULT register_coclasses(struct regsvr_coclass const *list); +static HRESULT unregister_coclasses(struct regsvr_coclass const *list); + +/*********************************************************************** + * static string constants + */ +static WCHAR const interface_keyname[10] = { + 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', 'e', 0 }; +static WCHAR const base_ifa_keyname[14] = { + 'B', 'a', 's', 'e', 'I', 'n', 't', 'e', 'r', 'f', 'a', 'c', + 'e', 0 }; +static WCHAR const num_methods_keyname[11] = { + 'N', 'u', 'm', 'M', 'e', 't', 'h', 'o', 'd', 's', 0 }; +static WCHAR const ps_clsid_keyname[15] = { + 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's', + 'i', 'd', 0 }; +static WCHAR const ps_clsid32_keyname[17] = { + 'P', 'r', 'o', 'x', 'y', 'S', 't', 'u', 'b', 'C', 'l', 's', + 'i', 'd', '3', '2', 0 }; +static WCHAR const clsid_keyname[6] = { + 'C', 'L', 'S', 'I', 'D', 0 }; +static WCHAR const curver_keyname[7] = { + 'C', 'u', 'r', 'V', 'e', 'r', 0 }; +static WCHAR const ips_keyname[13] = { + 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', + 0 }; +static WCHAR const ips32_keyname[15] = { + 'I', 'n', 'P', 'r', 'o', 'c', 'S', 'e', 'r', 'v', 'e', 'r', + '3', '2', 0 }; +static WCHAR const progid_keyname[7] = { + 'P', 'r', 'o', 'g', 'I', 'D', 0 }; +static WCHAR const viprogid_keyname[25] = { + 'V', 'e', 'r', 's', 'i', 'o', 'n', 'I', 'n', 'd', 'e', 'p', + 'e', 'n', 'd', 'e', 'n', 't', 'P', 'r', 'o', 'g', 'I', 'D', + 0 }; +static char const tmodel_valuename[] = "ThreadingModel"; + +/*********************************************************************** + * static helper functions + */ +static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid); +static LONG register_key_defvalueW(HKEY base, WCHAR const *name, + WCHAR const *value); +static LONG register_key_defvalueA(HKEY base, WCHAR const *name, + char const *value); +static LONG register_progid(WCHAR const *clsid, + char const *progid, char const *curver_progid, + char const *name, char const *extra); + +/*********************************************************************** + * register_interfaces + */ +static HRESULT register_interfaces(struct regsvr_interface const *list) +{ + LONG res = ERROR_SUCCESS; + HKEY interface_key; + + res = RegCreateKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &interface_key, NULL); + if (res != ERROR_SUCCESS) goto error_return; + + for (; res == ERROR_SUCCESS && list->iid; ++list) { + WCHAR buf[39]; + HKEY iid_key; + + StringFromGUID2(list->iid, buf, 39); + res = RegCreateKeyExW(interface_key, buf, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &iid_key, NULL); + if (res != ERROR_SUCCESS) goto error_close_interface_key; + + if (list->name) { + res = RegSetValueExA(iid_key, NULL, 0, REG_SZ, + (CONST BYTE*)(list->name), + strlen(list->name) + 1); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + if (list->base_iid) { + res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + if (0 <= list->num_methods) { + static WCHAR const fmt[3] = { '%', 'd', 0 }; + HKEY key; + + res = RegCreateKeyExW(iid_key, num_methods_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &key, NULL); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + + wsprintfW(buf, fmt, list->num_methods); + res = RegSetValueExW(key, NULL, 0, REG_SZ, + (CONST BYTE*)buf, + (lstrlenW(buf) + 1) * sizeof(WCHAR)); + RegCloseKey(key); + + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + if (list->ps_clsid) { + res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + if (list->ps_clsid32) { + res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32); + if (res != ERROR_SUCCESS) goto error_close_iid_key; + } + + error_close_iid_key: + RegCloseKey(iid_key); + } + +error_close_interface_key: + RegCloseKey(interface_key); +error_return: + return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * unregister_interfaces + */ +static HRESULT unregister_interfaces(struct regsvr_interface const *list) +{ + LONG res = ERROR_SUCCESS; + HKEY interface_key; + + res = RegOpenKeyExW(HKEY_CLASSES_ROOT, interface_keyname, 0, + KEY_READ | KEY_WRITE, &interface_key); + if (res == ERROR_FILE_NOT_FOUND) return S_OK; + if (res != ERROR_SUCCESS) goto error_return; + + for (; res == ERROR_SUCCESS && list->iid; ++list) { + WCHAR buf[39]; + + StringFromGUID2(list->iid, buf, 39); + res = RegDeleteTreeW(interface_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; + } + + RegCloseKey(interface_key); +error_return: + return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * register_coclasses + */ +static HRESULT register_coclasses(struct regsvr_coclass const *list) +{ + LONG res = ERROR_SUCCESS; + HKEY coclass_key; + + res = RegCreateKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &coclass_key, NULL); + if (res != ERROR_SUCCESS) goto error_return; + + for (; res == ERROR_SUCCESS && list->clsid; ++list) { + WCHAR buf[39]; + HKEY clsid_key; + + StringFromGUID2(list->clsid, buf, 39); + res = RegCreateKeyExW(coclass_key, buf, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &clsid_key, NULL); + if (res != ERROR_SUCCESS) goto error_close_coclass_key; + + if (list->name) { + res = RegSetValueExA(clsid_key, NULL, 0, REG_SZ, + (CONST BYTE*)(list->name), + strlen(list->name) + 1); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + if (list->ips) { + res = register_key_defvalueA(clsid_key, ips_keyname, list->ips); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + if (list->ips32) { + HKEY ips32_key; + + res = RegCreateKeyExW(clsid_key, ips32_keyname, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, + &ips32_key, NULL); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + + res = RegSetValueExA(ips32_key, NULL, 0, REG_SZ, + (CONST BYTE*)list->ips32, + lstrlenA(list->ips32) + 1); + if (res == ERROR_SUCCESS && list->ips32_tmodel) + res = RegSetValueExA(ips32_key, tmodel_valuename, 0, REG_SZ, + (CONST BYTE*)list->ips32_tmodel, + strlen(list->ips32_tmodel) + 1); + RegCloseKey(ips32_key); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + if (list->progid) { + res = register_key_defvalueA(clsid_key, progid_keyname, + list->progid); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + + res = register_progid(buf, list->progid, NULL, + list->name, list->progid_extra); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + if (list->viprogid) { + res = register_key_defvalueA(clsid_key, viprogid_keyname, + list->viprogid); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + + res = register_progid(buf, list->viprogid, list->progid, + list->name, list->progid_extra); + if (res != ERROR_SUCCESS) goto error_close_clsid_key; + } + + error_close_clsid_key: + RegCloseKey(clsid_key); + } + +error_close_coclass_key: + RegCloseKey(coclass_key); +error_return: + return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * unregister_coclasses + */ +static HRESULT unregister_coclasses(struct regsvr_coclass const *list) +{ + LONG res = ERROR_SUCCESS; + HKEY coclass_key; + + res = RegOpenKeyExW(HKEY_CLASSES_ROOT, clsid_keyname, 0, + KEY_READ | KEY_WRITE, &coclass_key); + if (res == ERROR_FILE_NOT_FOUND) return S_OK; + if (res != ERROR_SUCCESS) goto error_return; + + for (; res == ERROR_SUCCESS && list->clsid; ++list) { + WCHAR buf[39]; + + StringFromGUID2(list->clsid, buf, 39); + res = RegDeleteTreeW(coclass_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; + if (res != ERROR_SUCCESS) goto error_close_coclass_key; + + if (list->progid) { + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; + if (res != ERROR_SUCCESS) goto error_close_coclass_key; + } + + if (list->viprogid) { + res = RegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; + if (res != ERROR_SUCCESS) goto error_close_coclass_key; + } + } + +error_close_coclass_key: + RegCloseKey(coclass_key); +error_return: + return res != ERROR_SUCCESS ? HRESULT_FROM_WIN32(res) : S_OK; +} + +/*********************************************************************** + * regsvr_key_guid + */ +static LONG register_key_guid(HKEY base, WCHAR const *name, GUID const *guid) +{ + WCHAR buf[39]; + + StringFromGUID2(guid, buf, 39); + return register_key_defvalueW(base, name, buf); +} + +/*********************************************************************** + * regsvr_key_defvalueW + */ +static LONG register_key_defvalueW( + HKEY base, + WCHAR const *name, + WCHAR const *value) +{ + LONG res; + HKEY key; + + res = RegCreateKeyExW(base, name, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &key, NULL); + if (res != ERROR_SUCCESS) return res; + res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)value, + (lstrlenW(value) + 1) * sizeof(WCHAR)); + RegCloseKey(key); + return res; +} + +/*********************************************************************** + * regsvr_key_defvalueA + */ +static LONG register_key_defvalueA( + HKEY base, + WCHAR const *name, + char const *value) +{ + LONG res; + HKEY key; + + res = RegCreateKeyExW(base, name, 0, NULL, 0, + KEY_READ | KEY_WRITE, NULL, &key, NULL); + if (res != ERROR_SUCCESS) return res; + res = RegSetValueExA(key, NULL, 0, REG_SZ, (CONST BYTE*)value, + lstrlenA(value) + 1); + RegCloseKey(key); + return res; +} + +/*********************************************************************** + * regsvr_progid + */ +static LONG register_progid( + WCHAR const *clsid, + char const *progid, + char const *curver_progid, + char const *name, + char const *extra) +{ + LONG res; + HKEY progid_key; + + res = RegCreateKeyExA(HKEY_CLASSES_ROOT, progid, 0, + NULL, 0, KEY_READ | KEY_WRITE, NULL, + &progid_key, NULL); + if (res != ERROR_SUCCESS) return res; + + if (name) { + res = RegSetValueExA(progid_key, NULL, 0, REG_SZ, + (CONST BYTE*)name, strlen(name) + 1); + if (res != ERROR_SUCCESS) goto error_close_progid_key; + } + + if (clsid) { + res = register_key_defvalueW(progid_key, clsid_keyname, clsid); + if (res != ERROR_SUCCESS) goto error_close_progid_key; + } + + if (curver_progid) { + res = register_key_defvalueA(progid_key, curver_keyname, + curver_progid); + if (res != ERROR_SUCCESS) goto error_close_progid_key; + } + + if (extra) { + HKEY extra_key; + + res = RegCreateKeyExA(progid_key, extra, 0, + NULL, 0, KEY_READ | KEY_WRITE, NULL, + &extra_key, NULL); + if (res == ERROR_SUCCESS) + RegCloseKey(extra_key); + } + +error_close_progid_key: + RegCloseKey(progid_key); + return res; +} + +/*********************************************************************** + * coclass list + */ +static struct regsvr_coclass const coclass_list[] = { + { + &CLSID_TF_ThreadMgr, + "TF_ThreadMgr", + NULL, + "msctf.dll", + "Apartment" + }, + { + &CLSID_TF_InputProcessorProfiles, + "TF_InputProcessorProfiles", + NULL, + "msctf.dll", + "Apartment" + }, + { + &CLSID_TF_CategoryMgr, + "TF_CategoryMgr", + NULL, + "msctf.dll", + "Apartment" + }, + { NULL } /* list terminator */ +}; + +/*********************************************************************** + * interface list + */ + +static struct regsvr_interface const interface_list[] = { + { NULL } /* list terminator */ +}; + +/*********************************************************************** + * DllRegisterServer (HHCTRL.@) + */ +HRESULT WINAPI DllRegisterServer(void) +{ + HRESULT hr; + + TRACE("\n"); + + hr = register_coclasses(coclass_list); + if (SUCCEEDED(hr)) + hr = register_interfaces(interface_list); + return hr; +} + +/*********************************************************************** + * DllUnregisterServer (HHCTRL.@) + */ +HRESULT WINAPI DllUnregisterServer(void) +{ + HRESULT hr; + + TRACE("\n"); + + hr = unregister_coclasses(coclass_list); + if (SUCCEEDED(hr)) + hr = unregister_interfaces(interface_list); + return hr; +} diff --git a/reactos/dll/win32/msctf/threadmgr.c b/reactos/dll/win32/msctf/threadmgr.c new file mode 100644 index 00000000000..76c1fd61afd --- /dev/null +++ b/reactos/dll/win32/msctf/threadmgr.c @@ -0,0 +1,309 @@ +/* + * ITfThreadMgr implementation + * + * Copyright 2008 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" + +#include + +#define COBJMACROS + +#include "wine/debug.h" +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winuser.h" +#include "shlwapi.h" +#include "winerror.h" +#include "objbase.h" + +#include "wine/unicode.h" + +#include "msctf.h" +#include "msctf_internal.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msctf); + +typedef struct tagACLMulti { + const ITfThreadMgrVtbl *ThreadMgrVtbl; + const ITfSourceVtbl *SourceVtbl; + LONG refCount; + + ITfDocumentMgr *focus; +} ThreadMgr; + +static inline ThreadMgr *impl_from_ITfSourceVtbl(ITfSource *iface) +{ + return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceVtbl)); +} + +static void ThreadMgr_Destructor(ThreadMgr *This) +{ + TlsSetValue(tlsIndex,NULL); + TRACE("destroying %p\n", This); + if (This->focus) + ITfDocumentMgr_Release(This->focus); + HeapFree(GetProcessHeap(),0,This); +} + +static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, LPVOID *ppvOut) +{ + ThreadMgr *This = (ThreadMgr *)iface; + *ppvOut = NULL; + + if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr)) + { + *ppvOut = This; + } + else if (IsEqualIID(iid, &IID_ITfSource)) + { + *ppvOut = &This->SourceVtbl; + } + + if (*ppvOut) + { + IUnknown_AddRef(iface); + return S_OK; + } + + WARN("unsupported interface: %s\n", debugstr_guid(iid)); + return E_NOINTERFACE; +} + +static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgr *iface) +{ + ThreadMgr *This = (ThreadMgr *)iface; + return InterlockedIncrement(&This->refCount); +} + +static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface) +{ + ThreadMgr *This = (ThreadMgr *)iface; + ULONG ret; + + ret = InterlockedDecrement(&This->refCount); + if (ret == 0) + ThreadMgr_Destructor(This); + return ret; +} + +/***************************************************** + * ITfThreadMgr functions + *****************************************************/ + +static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid) +{ + ThreadMgr *This = (ThreadMgr *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface) +{ + ThreadMgr *This = (ThreadMgr *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocumentMgr +**ppdim) +{ + TRACE("(%p)\n",iface); + return DocumentMgr_Constructor(ppdim); +} + +static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs +**ppEnum) +{ + ThreadMgr *This = (ThreadMgr *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr +**ppdimFocus) +{ + ThreadMgr *This = (ThreadMgr *)iface; + TRACE("(%p)\n",This); + + if (!ppdimFocus) + return E_INVALIDARG; + + *ppdimFocus = This->focus; + + TRACE("->%p\n",This->focus); + + if (This->focus == NULL) + return S_FALSE; + + ITfDocumentMgr_AddRef(This->focus); + + return S_OK; +} + +static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *pdimFocus) +{ + ITfDocumentMgr *check; + ThreadMgr *This = (ThreadMgr *)iface; + + TRACE("(%p) %p\n",This,pdimFocus); + + if (!pdimFocus || FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check))) + return E_INVALIDARG; + + if (This->focus) + ITfDocumentMgr_Release(This->focus); + + This->focus = check; + return S_OK; +} + +static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd, +ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev) +{ + ThreadMgr *This = (ThreadMgr *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus) +{ + ThreadMgr *This = (ThreadMgr *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid, +ITfFunctionProvider **ppFuncProv) +{ + ThreadMgr *This = (ThreadMgr *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface, +IEnumTfFunctionProviders **ppEnum) +{ + ThreadMgr *This = (ThreadMgr *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface, +ITfCompartmentMgr **ppCompMgr) +{ + ThreadMgr *This = (ThreadMgr *)iface; + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl = +{ + ThreadMgr_QueryInterface, + ThreadMgr_AddRef, + ThreadMgr_Release, + + ThreadMgr_fnActivate, + ThreadMgr_fnDeactivate, + ThreadMgr_CreateDocumentMgr, + ThreadMgr_EnumDocumentMgrs, + ThreadMgr_GetFocus, + ThreadMgr_SetFocus, + ThreadMgr_AssociateFocus, + ThreadMgr_IsThreadFocus, + ThreadMgr_GetFunctionProvider, + ThreadMgr_EnumFunctionProviders, + ThreadMgr_GetGlobalCompartment +}; + + +static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut) +{ + ThreadMgr *This = impl_from_ITfSourceVtbl(iface); + return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut); +} + +static ULONG WINAPI Source_AddRef(ITfSource *iface) +{ + ThreadMgr *This = impl_from_ITfSourceVtbl(iface); + return ThreadMgr_AddRef((ITfThreadMgr*)This); +} + +static ULONG WINAPI Source_Release(ITfSource *iface) +{ + ThreadMgr *This = impl_from_ITfSourceVtbl(iface); + return ThreadMgr_Release((ITfThreadMgr *)This); +} + +/***************************************************** + * ITfSource functions + *****************************************************/ +static WINAPI HRESULT ThreadMgrSource_AdviseSink(ITfSource *iface, + REFIID riid, IUnknown *punk, DWORD *pdwCookie) +{ + ThreadMgr *This = impl_from_ITfSourceVtbl(iface); + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static WINAPI HRESULT ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie) +{ + ThreadMgr *This = impl_from_ITfSourceVtbl(iface); + FIXME("STUB:(%p)\n",This); + return E_NOTIMPL; +} + +static const ITfSourceVtbl ThreadMgr_SourceVtbl = +{ + Source_QueryInterface, + Source_AddRef, + Source_Release, + + ThreadMgrSource_AdviseSink, + ThreadMgrSource_UnadviseSink, +}; + +HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) +{ + ThreadMgr *This; + if (pUnkOuter) + return CLASS_E_NOAGGREGATION; + + /* Only 1 ThreadMgr is created per thread */ + This = TlsGetValue(tlsIndex); + if (This) + { + ThreadMgr_AddRef((ITfThreadMgr*)This); + *ppOut = (IUnknown*)This; + return S_OK; + } + + This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr)); + if (This == NULL) + return E_OUTOFMEMORY; + + This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl; + This->SourceVtbl = &ThreadMgr_SourceVtbl; + This->refCount = 1; + TlsSetValue(tlsIndex,This); + + TRACE("returning %p\n", This); + *ppOut = (IUnknown *)This; + return S_OK; +} diff --git a/reactos/dll/win32/win32.rbuild b/reactos/dll/win32/win32.rbuild index f8d4f00deb1..5bc9c676d91 100644 --- a/reactos/dll/win32/win32.rbuild +++ b/reactos/dll/win32/win32.rbuild @@ -205,6 +205,9 @@ + + + diff --git a/reactos/include/psdk/msctf.idl b/reactos/include/psdk/msctf.idl new file mode 100644 index 00000000000..6a488cb4719 --- /dev/null +++ b/reactos/include/psdk/msctf.idl @@ -0,0 +1,478 @@ +/* + * Copyright 2008 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef DO_NO_IMPORTS +import "oaidl.idl"; +import "comcat.idl"; +import "textstor.idl"; +/* import "ctfutb.idl"; */ +#endif + +/* FIXME: LANGID is defined in winnt.h and mlang.h in the platform SDK */ +cpp_quote("#ifndef _WINNT_H") +typedef WORD LANGID; +cpp_quote("#endif") + +cpp_quote("#define TF_E_STACKFULL MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, 0x0501)") +cpp_quote("EXTERN_C const CLSID CLSID_TF_ThreadMgr;") +cpp_quote("EXTERN_C const CLSID CLSID_TF_InputProcessorProfiles;") +cpp_quote("EXTERN_C const CLSID CLSID_TF_CategoryMgr;") + +/* GUIDs for Categories */ +cpp_quote("EXTERN_C const GUID GUID_TFCAT_TIP_KEYBOARD;") +cpp_quote("EXTERN_C const GUID GUID_TFCAT_TIP_SPEECH;") +cpp_quote("EXTERN_C const GUID GUID_TFCAT_TIP_HANDWRITING;") +cpp_quote("EXTERN_C const GUID GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER;") + +typedef [uuid(7213778c-7bb0-4270-b050-6189ee594e97)] DWORD TfEditCookie; +typedef [uuid(de403c21-89fd-4f85-8b87-64584d063fbc)] DWORD TfClientId; +typedef [uuid(88a9c478-f3ec-4763-8345-cd9250443f8d)] DWORD TfGuidAtom; + +interface ITfDocumentMgr; +interface ITfContext; +interface IEnumTfDocumentMgrs; +interface IEnumTfContexts; +interface ITfFunctionProvider; +interface IEnumTfFunctionProviders; +interface ITfCompartmentMgr; +interface ITfEditSession; +interface ITfRange; +interface ITfContextView; +interface IEnumTfContextViews; +interface ITfProperty; +interface ITfReadOnlyProperty; +interface IEnumTfProperties; +interface ITfRangeBackup; +interface IEnumTfLanguageProfiles; +interface ITfEditRecord; +interface ITfCompositionView; + +typedef [uuid(e1b5808d-1e46-4c19-84dc-68c5f5978cc8)] struct TF_LANGUAGEPROFILE +{ + CLSID clsid; + LANGID langid; + GUID catid; + BOOL fActive; + GUID guidProfile; +} TF_LANGUAGEPROFILE; + +[ + object, + uuid(aa80e801-2021-11d2-93e0-0060b067b86e), + pointer_default(unique) +] +interface ITfThreadMgr: IUnknown +{ + HRESULT Activate( + [out] TfClientId *ptid); + + HRESULT Deactivate(); + + HRESULT CreateDocumentMgr( + [out] ITfDocumentMgr **ppdim); + + HRESULT EnumDocumentMgrs( + [out] IEnumTfDocumentMgrs **ppEnum); + + HRESULT GetFocus( + [out] ITfDocumentMgr **ppdimFocus); + + HRESULT SetFocus( + [in] ITfDocumentMgr *pdimFocus); + + HRESULT AssociateFocus( + [in] HWND hwnd, + [in, unique] ITfDocumentMgr *pdimNew, + [out] ITfDocumentMgr **ppdimPrev); + + HRESULT IsThreadFocus( + [out] BOOL *pfThreadFocus); + + HRESULT GetFunctionProvider( + [in] REFCLSID clsid, + [out] ITfFunctionProvider **ppFuncProv); + + HRESULT EnumFunctionProviders( + [out] IEnumTfFunctionProviders **ppEnum); + + HRESULT GetGlobalCompartment( + [out] ITfCompartmentMgr **ppCompMgr); +}; + + +[ + object, + uuid(aa80e7f4-2021-11d2-93e0-0060b067b86e), + pointer_default(unique) +] +interface ITfDocumentMgr: IUnknown +{ + HRESULT CreateContext( + [in] TfClientId tidOwner, + [in] DWORD dwFlags, + [in, unique] IUnknown *punk, + [out] ITfContext **ppic, + [out] TfEditCookie *pecTextStore); + + HRESULT Push( + [in] ITfContext *pic); + + const DWORD TF_POPF_ALL = 0x0001; + + HRESULT Pop( + [in] DWORD dwFlags); + + HRESULT GetTop( + [out] ITfContext **ppic); + + HRESULT GetBase( + [out] ITfContext **ppic); + + HRESULT EnumContexts( + [out] IEnumTfContexts **ppEnum); +}; + +[ + object, + uuid(aa80e7fd-2021-11d2-93e0-0060b067b86e), + pointer_default(unique) +] +interface ITfContext : IUnknown +{ + const DWORD TF_ES_ASYNCDONTCARE = 0x0; + const DWORD TF_ES_SYNC = 0x1; + const DWORD TF_ES_READ = 0x2; + const DWORD TF_ES_READWRITE = 0x6; + const DWORD TF_ES_ASYNC = 0x8; + + HRESULT RequestEditSession( + [in] TfClientId tid, + [in] ITfEditSession *pes, + [in] DWORD dwFlags, + [out] HRESULT *phrSession); + + HRESULT InWriteSession( + [in] TfClientId tid, + [out] BOOL *pfWriteSession); + + typedef [uuid(1690be9b-d3e9-49f6-8d8b-51b905af4c43)] enum { TF_AE_NONE, TF_AE_START, TF_AE_END } TfActiveSelEnd; + + typedef [uuid(36ae42a4-6989-4bdc-b48a-6137b7bf2e42)] struct TF_SELECTIONSTYLE + { + TfActiveSelEnd ase; + BOOL fInterimChar; + } TF_SELECTIONSTYLE; + + typedef [uuid(75eb22f2-b0bf-46a8-8006-975a3b6efcf1)] struct TF_SELECTION + { + ITfRange *range; + TF_SELECTIONSTYLE style; + } TF_SELECTION; + + const ULONG TF_DEFAULT_SELECTION = TS_DEFAULT_SELECTION; + + HRESULT GetSelection( + [in] TfEditCookie ec, + [in] ULONG ulIndex, + [in] ULONG ulCount, + [out, size_is(ulCount), length_is(*pcFetched)] TF_SELECTION *pSelection, + [out] ULONG *pcFetched); + + HRESULT SetSelection( + [in] TfEditCookie ec, + [in] ULONG ulCount, + [in, size_is(ulCount)] const TF_SELECTION *pSelection); + + HRESULT GetStart( + [in] TfEditCookie ec, + [out] ITfRange **ppStart); + + HRESULT GetEnd( + [in] TfEditCookie ec, + [out] ITfRange **ppEnd); + + typedef [uuid(bc7d979a-846a-444d-afef-0a9bfa82b961)] TS_STATUS TF_STATUS; + const DWORD TF_SD_READONLY = TS_SD_READONLY; + const DWORD TF_SD_LOADING = TS_SD_LOADING; + const DWORD TF_SS_DISJOINTSEL = TS_SS_DISJOINTSEL; + const DWORD TF_SS_REGIONS = TS_SS_REGIONS; + const DWORD TF_SS_TRANSITORY = TS_SS_TRANSITORY; + + + HRESULT GetActiveView( + [out] ITfContextView **ppView); + + HRESULT EnumViews( + [out] IEnumTfContextViews **ppEnum); + + HRESULT GetStatus( + [out] TF_STATUS *pdcs); + + HRESULT GetProperty( + [in] REFGUID guidProp, + [out] ITfProperty **ppProp); + + HRESULT GetAppProperty( + [in] REFGUID guidProp, + [out] ITfReadOnlyProperty **ppProp); + + HRESULT TrackProperties( + [in, size_is(cProp)] const GUID **prgProp, + [in] ULONG cProp, + [in, size_is(cAppProp)] const GUID **prgAppProp, + [in] ULONG cAppProp, + [out] ITfReadOnlyProperty **ppProperty); + + HRESULT EnumProperties( + [out] IEnumTfProperties **ppEnum); + + HRESULT GetDocumentMgr( + [out] ITfDocumentMgr **ppDm); + + HRESULT CreateRangeBackup( + [in] TfEditCookie ec, + [in] ITfRange *pRange, + [out] ITfRangeBackup **ppBackup); + +}; + +[ + object, + uuid(4ea48a35-60ae-446f-8fd6-e6a8d82459f7), + pointer_default(unique) +] +interface ITfSource : IUnknown +{ + HRESULT AdviseSink( + [in] REFIID riid, + [in, iid_is(riid)] IUnknown *punk, + [out] DWORD *pdwCookie); + + HRESULT UnadviseSink( + [in] DWORD dwCookie); +}; + +[ + object, + local, + uuid(1F02B6C5-7842-4EE6-8A0B-9A24183A95CA), + pointer_default(unique) +] +interface ITfInputProcessorProfiles : IUnknown +{ + HRESULT Register( + [in] REFCLSID rclsid); + + HRESULT Unregister( + [in] REFCLSID rclsid); + + HRESULT AddLanguageProfile( + [in] REFCLSID rclsid, + [in] LANGID langid, + [in] REFGUID guidProfile, + [in, size_is(cchDesc)] const WCHAR *pchDesc, + [in] ULONG cchDesc, + [in, size_is(cchFile)] const WCHAR *pchIconFile, + [in] ULONG cchFile, + [in] ULONG uIconIndex); + + HRESULT RemoveLanguageProfile( + [in] REFCLSID rclsid, + [in] LANGID langid, + [in] REFGUID guidProfile); + + HRESULT EnumInputProcessorInfo( + [out] IEnumGUID **ppEnum); + + HRESULT GetDefaultLanguageProfile( + [in] LANGID langid, + [in] REFGUID catid, + [out] CLSID *pclsid, + [out] GUID *pguidProfile); + + HRESULT SetDefaultLanguageProfile( + [in] LANGID langid, + [in] REFCLSID rclsid, + [in] REFGUID guidProfiles); + + HRESULT ActivateLanguageProfile( + [in] REFCLSID rclsid, + [in] LANGID langid, + [in] REFGUID guidProfiles); + + HRESULT GetActiveLanguageProfile( + [in] REFCLSID rclsid, + [out] LANGID *plangid, + [out] GUID *pguidProfile); + + HRESULT GetLanguageProfileDescription( + [in] REFCLSID rclsid, + [in] LANGID langid, + [in] REFGUID guidProfile, + [out] BSTR *pbstrProfile); + + HRESULT GetCurrentLanguage( + [out] LANGID *plangid); + + HRESULT ChangeCurrentLanguage( + [in] LANGID langid); + + HRESULT GetLanguageList( + [out] LANGID **ppLangId, + [out] ULONG *pulCount); + + HRESULT EnumLanguageProfiles( + [in] LANGID langid, + [out] IEnumTfLanguageProfiles **ppEnum); + + HRESULT EnableLanguageProfile( + [in] REFCLSID rclsid, + [in] LANGID langid, + [in] REFGUID guidProfile, + [in] BOOL fEnable); + + HRESULT IsEnabledLanguageProfile( + [in] REFCLSID rclsid, + [in] LANGID langid, + [in] REFGUID guidProfile, + [out] BOOL *pfEnable); + + HRESULT EnableLanguageProfileByDefault( + [in] REFCLSID rclsid, + [in] LANGID langid, + [in] REFGUID guidProfile, + [in] BOOL fEnable); + + HRESULT SubstituteKeyboardLayout( + [in] REFCLSID rclsid, + [in] LANGID langid, + [in] REFGUID guidProfile, + [in] HKL hKL); +}; + +[ + object, + local, + uuid(c3acefb5-f69d-4905-938f-fcadcf4be830), + pointer_default(unique) +] +interface ITfCategoryMgr : IUnknown +{ + HRESULT RegisterCategory([in] REFCLSID rclsid, + [in] REFGUID rcatid, + [in] REFGUID rguid); + + HRESULT UnregisterCategory([in] REFCLSID rclsid, + [in] REFGUID rcatid, + [in] REFGUID rguid); + + HRESULT EnumCategoriesInItem([in] REFGUID rguid, + [out] IEnumGUID **ppEnum); + + HRESULT EnumItemsInCategory([in] REFGUID rcatid, + [out] IEnumGUID **ppEnum); + + HRESULT FindClosestCategory([in] REFGUID rguid, + [out] GUID *pcatid, + [in, size_is(ulCount)] const GUID **ppcatidList, + [in] ULONG ulCount); + + HRESULT RegisterGUIDDescription([in] REFCLSID rclsid, + [in] REFGUID rguid, + [in, size_is(cch)] const WCHAR *pchDesc, + [in] ULONG cch); + + HRESULT UnregisterGUIDDescription([in] REFCLSID rclsid, + [in] REFGUID rguid); + + HRESULT GetGUIDDescription([in] REFGUID rguid, + [out] BSTR *pbstrDesc); + + HRESULT RegisterGUIDDWORD([in] REFCLSID rclsid, + [in] REFGUID rguid, + [in] DWORD dw); + + HRESULT UnregisterGUIDDWORD([in] REFCLSID rclsid, + [in] REFGUID rguid); + + HRESULT GetGUIDDWORD([in] REFGUID rguid, + [out] DWORD *pdw); + + HRESULT RegisterGUID([in] REFGUID rguid, + [out] TfGuidAtom *pguidatom); + + HRESULT GetGUID([in] TfGuidAtom guidatom, + [out] GUID *pguid); + + HRESULT IsEqualTfGuidAtom([in] TfGuidAtom guidatom, + [in] REFGUID rguid, + [out] BOOL *pfEqual); +}; + +[ + object, + uuid(8127d409-ccd3-4683-967a-b43d5b482bf7), + pointer_default(unique) +] +interface ITfTextEditSink : IUnknown +{ + HRESULT OnEndEdit( + [in] ITfContext *pic, + [in] TfEditCookie ecReadOnly, + [in] ITfEditRecord *pEditRecord); +}; + +[ + object, + uuid(5F20AA40-B57A-4F34-96AB-3576F377CC79), + pointer_default(unique) +] +interface ITfContextOwnerCompositionSink : IUnknown +{ + HRESULT OnStartComposition( + [in] ITfCompositionView *pComposition, + [out] BOOL *pfOk); + + HRESULT OnUpdateComposition( + [in] ITfCompositionView *pComposition, + [in] ITfRange *pRangeNew); + + HRESULT OnEndComposition( + [in] ITfCompositionView *pComposition); +}; + +[ + object, + uuid(3d61bf11-ac5f-42c8-a4cb-931bcc28c744), + pointer_default(unique) +] +interface IEnumTfLanguageProfiles : IUnknown +{ + HRESULT Clone( + [out] IEnumTfLanguageProfiles **ppEnum); + + HRESULT Next( + [in] ULONG ulCount, + [out, size_is(ulCount), length_is(*pcFetch)] TF_LANGUAGEPROFILE *pProfile, + [out] ULONG *pcFetch); + + HRESULT Reset(); + + HRESULT Skip( + [in] ULONG ulCount); +}; diff --git a/reactos/include/psdk/psdk.rbuild b/reactos/include/psdk/psdk.rbuild index 9b57f3af7f8..9a626919028 100644 --- a/reactos/include/psdk/psdk.rbuild +++ b/reactos/include/psdk/psdk.rbuild @@ -21,6 +21,7 @@ indexsrv.idl mimeinfo.idl mlang.idl + msctf.idl mshtml.idl mstask.idl msxml.idl @@ -43,6 +44,7 @@ shobjidl.idl shtypes.idl strmif.idl + textstor.idl tom.idl unknwn.idl urlhist.idl diff --git a/reactos/include/psdk/textstor.idl b/reactos/include/psdk/textstor.idl new file mode 100644 index 00000000000..08ee21d793c --- /dev/null +++ b/reactos/include/psdk/textstor.idl @@ -0,0 +1,277 @@ +/* + * Copyright 2009 Aric Stewart, CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifndef DO_NO_IMPORTS +import "oaidl.idl"; +#endif + +const ULONG TS_DEFAULT_SELECTION = ~0u; + +const DWORD TS_SD_READONLY = 0x001; +const DWORD TS_SD_LOADING = 0x002; + +const DWORD TS_SS_DISJOINTSEL = 0x001; +const DWORD TS_SS_REGIONS = 0x002; +const DWORD TS_SS_TRANSITORY = 0x004; +const DWORD TS_SS_NOHIDDENTEXT = 0x008; + +const DWORD TS_AS_TEXT_CHANGE = 0x01; +const DWORD TS_AS_SEL_CHANGE = 0x02; +const DWORD TS_AS_LAYOUT_CHANGE = 0x04; +const DWORD TS_AS_ATTR_CHANGE = 0x08; +const DWORD TS_AS_STATUS_CHANGE = 0x10; + +const DWORD TS_AS_ALL_SINKS = (TS_AS_TEXT_CHANGE | TS_AS_SEL_CHANGE | TS_AS_LAYOUT_CHANGE | TS_AS_ATTR_CHANGE | TS_AS_STATUS_CHANGE); + + +typedef [uuid(05fcf85b-5e9c-4c3e-ab71-29471d4f38e7)] enum { TS_AE_NONE, TS_AE_START, TS_AE_END } TsActiveSelEnd; +typedef [uuid(033b0df0-f193-4170-b47b-141afc247878)] enum { TS_RT_PLAIN, TS_RT_HIDDEN, TS_RT_OPAQUE } TsRunType; +typedef [uuid(ef3457d9-8446-49a7-a9e6-b50d9d5f3fd9)] GUID TS_ATTRID; + +typedef [uuid(fec4f516-c503-45b1-a5fd-7a3d8ab07049)] struct TS_STATUS +{ + DWORD dwDynamicFlags; + DWORD dwStaticFlags; +} TS_STATUS; + +typedef [uuid(f3181bd6-bcf0-41d3-a81c-474b17ec38fb)] struct TS_TEXTCHANGE +{ + LONG acpStart; + LONG acpOldEnd; + LONG acpNewEnd; +} TS_TEXTCHANGE; + +typedef [uuid(7ecc3ffa-8f73-4d91-98ed-76f8ac5b1600)] struct TS_SELECTIONSTYLE +{ + TsActiveSelEnd ase; + BOOL fInterimChar; +} TS_SELECTIONSTYLE; + +typedef [uuid(c4b9c33b-8a0d-4426-bebe-d444a4701fe9)] struct TS_SELECTION_ACP +{ + LONG acpStart; + LONG acpEnd; + TS_SELECTIONSTYLE style; +} TS_SELECTION_ACP; + +typedef [uuid(a6231949-37c5-4b74-a24e-2a26c327201d)] struct TS_RUNINFO +{ + ULONG uCount; + TsRunType type; +} TS_RUNINFO; + +typedef [uuid(2cc2b33f-1174-4507-b8d9-5bc0eb37c197)] struct TS_ATTRVAL +{ + TS_ATTRID idAttr; + DWORD dwOverlapId; + VARIANT varValue; +} TS_ATTRVAL; + +typedef [uuid(7899d7c4-5f07-493c-a89a-fac8e777f476)] enum { TS_LC_CREATE, TS_LC_CHANGE, TS_LC_DESTROY } TsLayoutCode; +typedef [uuid(1faf509e-44c1-458e-950a-38a96705a62b)] DWORD TsViewCookie; + +[ + object, + uuid(22d44c94-a419-4542-a272-ae26093ececf), + pointer_default(unique) +] +interface ITextStoreACPSink : IUnknown +{ + HRESULT OnTextChange( + [in] DWORD dwFlags, + [in] const TS_TEXTCHANGE *pChange); + + HRESULT OnSelectionChange(); + + HRESULT OnLayoutChange( + [in] TsLayoutCode lcode, + [in] TsViewCookie vcView); + + HRESULT OnStatusChange( + [in] DWORD dwFlags); + + HRESULT OnAttrsChange( + [in] LONG acpStart, + [in] LONG acpEnd, + [in] ULONG cAttrs, + [in, size_is(cAttrs)] const TS_ATTRID *paAttrs); + + HRESULT OnLockGranted( + [in] DWORD dwLockFlags); + + HRESULT OnStartEditTransaction(); + + HRESULT OnEndEditTransaction(); +}; + +[ + object, + uuid(28888fe3-c2a0-483a-a3ea-8cb1ce51ff3d), + pointer_default(unique) +] +interface ITextStoreACP : IUnknown +{ + HRESULT AdviseSink( + [in] REFIID riid, + [in, iid_is(riid)] IUnknown *punk, + [in] DWORD dwMask); + + HRESULT UnadviseSink( + [in] IUnknown *punk); + + HRESULT RequestLock( + [in] DWORD dwLockFlags, + [out] HRESULT *phrSession); + + HRESULT GetStatus( + [out] TS_STATUS *pdcs); + + HRESULT QueryInsert( + [in] LONG acpTestStart, + [in] LONG acpTestEnd, + [in] ULONG cch, + [out] LONG *pacpResultStart, + [out] LONG *pacpResultEnd); + + HRESULT GetSelection( + [in] ULONG ulIndex, + [in] ULONG ulCount, + [out, size_is(ulCount), length_is(*pcFetched)] TS_SELECTION_ACP *pSelection, + [out] ULONG *pcFetched); + + HRESULT SetSelection( + [in] ULONG ulCount, + [in, size_is(ulCount)] const TS_SELECTION_ACP *pSelection); + + HRESULT GetText( + [in] LONG acpStart, + [in] LONG acpEnd, + [out, size_is(cchPlainReq), length_is(*pcchPlainRet)] WCHAR *pchPlain, + [in] ULONG cchPlainReq, + [out] ULONG *pcchPlainRet, + [out, size_is(cRunInfoReq), length_is(*pcRunInfoRet)] TS_RUNINFO *prgRunInfo, + [in] ULONG cRunInfoReq, + [out] ULONG *pcRunInfoRet, + [out] LONG *pacpNext); + + HRESULT SetText( + [in] DWORD dwFlags, + [in] LONG acpStart, + [in] LONG acpEnd, + [in, size_is(cch)] const WCHAR *pchText, + [in] ULONG cch, + [out] TS_TEXTCHANGE *pChange); + + HRESULT GetFormattedText( + [in] LONG acpStart, + [in] LONG acpEnd, + [out] IDataObject **ppDataObject); + + HRESULT GetEmbedded( + [in] LONG acpPos, + [in] REFGUID rguidService, + [in] REFIID riid, + [out, iid_is(riid)] IUnknown **ppunk); + + HRESULT QueryInsertEmbedded( + [in] const GUID *pguidService, + [in] const FORMATETC *pFormatEtc, + [out] BOOL *pfInsertable); + + HRESULT InsertEmbedded( + [in] DWORD dwFlags, + [in] LONG acpStart, + [in] LONG acpEnd, + [in] IDataObject *pDataObject, + [out] TS_TEXTCHANGE *pChange); + + + HRESULT InsertTextAtSelection( + [in] DWORD dwFlags, + [in, size_is(cch)] const WCHAR *pchText, + [in] ULONG cch, + [out] LONG *pacpStart, + [out] LONG *pacpEnd, + [out] TS_TEXTCHANGE *pChange); + + HRESULT InsertEmbeddedAtSelection( + [in] DWORD dwFlags, + [in] IDataObject *pDataObject, + [out] LONG *pacpStart, + [out] LONG *pacpEnd, + [out] TS_TEXTCHANGE *pChange); + + HRESULT RequestSupportedAttrs( + [in] DWORD dwFlags, + [in] ULONG cFilterAttrs, + [in, size_is(cFilterAttrs), unique] const TS_ATTRID *paFilterAttrs); + + HRESULT RequestAttrsAtPosition( + [in] LONG acpPos, + [in] ULONG cFilterAttrs, + [in, size_is(cFilterAttrs), unique] const TS_ATTRID *paFilterAttrs, + [in] DWORD dwFlags); + + HRESULT RequestAttrsTransitioningAtPosition( + [in] LONG acpPos, + [in] ULONG cFilterAttrs, + [in, size_is(cFilterAttrs), unique] const TS_ATTRID *paFilterAttrs, + [in] DWORD dwFlags); + + HRESULT FindNextAttrTransition( + [in] LONG acpStart, + [in] LONG acpHalt, + [in] ULONG cFilterAttrs, + [in, size_is(cFilterAttrs), unique] const TS_ATTRID *paFilterAttrs, + [in] DWORD dwFlags, + [out] LONG *pacpNext, + [out] BOOL *pfFound, + [out] LONG *plFoundOffset); + + HRESULT RetrieveRequestedAttrs( + [in] ULONG ulCount, + [out, size_is(ulCount), length_is(*pcFetched)] TS_ATTRVAL *paAttrVals, + [out] ULONG *pcFetched); + + HRESULT GetEndACP( + [out] LONG *pacp); + + HRESULT GetActiveView( + [out] TsViewCookie *pvcView); + + HRESULT GetACPFromPoint( + [in] TsViewCookie vcView, + [in] const POINT *ptScreen, + [in] DWORD dwFlags, + [out] LONG *pacp); + + HRESULT GetTextExt( + [in] TsViewCookie vcView, + [in] LONG acpStart, + [in] LONG acpEnd, + [out] RECT *prc, + [out] BOOL *pfClipped); + + HRESULT GetScreenExt( + [in] TsViewCookie vcView, + [out] RECT *prc); + + HRESULT GetWnd( + [in] TsViewCookie vcView, + [out] HWND *phwnd); +}; diff --git a/reactos/lib/sdk/uuid/uuid.c b/reactos/lib/sdk/uuid/uuid.c index 0b347c81bd4..942189b4e82 100644 --- a/reactos/lib/sdk/uuid/uuid.c +++ b/reactos/lib/sdk/uuid/uuid.c @@ -143,6 +143,9 @@ DEFINE_GUID(CLSID_StdEvent, 0x0000032b,0x0000,0x0000,0xc0,0x00,0x0 DEFINE_GUID(CLSID_ManualResetEvent, 0x0000032c,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); DEFINE_GUID(CLSID_SynchronizeContainer, 0x0000032d,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); DEFINE_GUID(CLSID_InProcFreeMarshaler, 0x0000033a,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); +DEFINE_GUID(CLSID_TF_ThreadMgr, 0x529a9e6b,0x6587,0x4f23,0xab,0x9e,0x9c,0x7d,0x68,0x3e,0x3c,0x50); +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(CLSID_ConnectionManager, 0xBA126AD1,0x2166,0x11D1,0xB1,0xD0,0x0,0x80,0x5F,0xC1,0x27,0x0E); DEFINE_GUID(CLSID_CNetCfg, 0x5B035261,0x40F9,0x11D1,0xAA,0xEC,0x00,0x80,0x5F,0xC1,0x27,0x0E); diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index dcd9ec7c334..3111864ec5e 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -69,6 +69,7 @@ reactos/dll/win32/msacm32 # Out of sync reactos/dll/win32/mscat32 # Autosync reactos/dll/win32/mscms # Autosync reactos/dll/win32/mscoree # Autosync +reactos/dll/win32/msctf # Autosync reactos/dll/win32/msftedit # Autosync reactos/dll/win32/mshtml # Autosync reactos/dll/win32/msimg32 # Autosync