server: Add a helper for queuing pipe message.
[wine.git] / dlls / msctf / categorymgr.c
blobad43833d621100bbe63d13e5ad08240e451e7cdc
1 /*
2 * ITfCategoryMgr implementation
4 * Copyright 2009 Aric Stewart, CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
23 #include <stdarg.h>
25 #define COBJMACROS
27 #include "wine/debug.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "winuser.h"
32 #include "shlwapi.h"
33 #include "winerror.h"
34 #include "objbase.h"
36 #include "wine/unicode.h"
38 #include "msctf.h"
39 #include "msctf_internal.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
43 typedef struct tagCategoryMgr {
44 ITfCategoryMgr ITfCategoryMgr_iface;
45 LONG refCount;
46 } CategoryMgr;
48 static inline CategoryMgr *impl_from_ITfCategoryMgr(ITfCategoryMgr *iface)
50 return CONTAINING_RECORD(iface, CategoryMgr, ITfCategoryMgr_iface);
53 static void CategoryMgr_Destructor(CategoryMgr *This)
55 TRACE("destroying %p\n", This);
56 HeapFree(GetProcessHeap(),0,This);
59 static HRESULT WINAPI CategoryMgr_QueryInterface(ITfCategoryMgr *iface, REFIID iid, LPVOID *ppvOut)
61 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
62 *ppvOut = NULL;
64 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfCategoryMgr))
66 *ppvOut = &This->ITfCategoryMgr_iface;
69 if (*ppvOut)
71 ITfCategoryMgr_AddRef(iface);
72 return S_OK;
75 WARN("unsupported interface: %s\n", debugstr_guid(iid));
76 return E_NOINTERFACE;
79 static ULONG WINAPI CategoryMgr_AddRef(ITfCategoryMgr *iface)
81 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
82 return InterlockedIncrement(&This->refCount);
85 static ULONG WINAPI CategoryMgr_Release(ITfCategoryMgr *iface)
87 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
88 ULONG ret;
90 ret = InterlockedDecrement(&This->refCount);
91 if (ret == 0)
92 CategoryMgr_Destructor(This);
93 return ret;
96 /*****************************************************
97 * ITfCategoryMgr functions
98 *****************************************************/
100 static HRESULT WINAPI CategoryMgr_RegisterCategory ( ITfCategoryMgr *iface,
101 REFCLSID rclsid, REFGUID rcatid, REFGUID rguid)
103 WCHAR fullkey[110];
104 WCHAR buf[39];
105 WCHAR buf2[39];
106 ULONG res;
107 HKEY tipkey,catkey,itmkey;
108 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
110 static const WCHAR ctg[] = {'C','a','t','e','g','o','r','y',0};
111 static const WCHAR itm[] = {'I','t','e','m',0};
112 static const WCHAR fmt[] = {'%','s','\\','%','s',0};
113 static const WCHAR fmt2[] = {'%','s','\\','%','s','\\','%','s','\\','%','s',0};
115 TRACE("(%p) %s %s %s\n",This,debugstr_guid(rclsid), debugstr_guid(rcatid), debugstr_guid(rguid));
117 StringFromGUID2(rclsid, buf, 39);
118 sprintfW(fullkey,fmt,szwSystemTIPKey,buf);
120 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE,
121 &tipkey ) != ERROR_SUCCESS)
122 return E_FAIL;
124 StringFromGUID2(rcatid, buf, 39);
125 StringFromGUID2(rguid, buf2, 39);
126 sprintfW(fullkey,fmt2,ctg,ctg,buf,buf2);
128 res = RegCreateKeyExW(tipkey, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
129 NULL, &catkey, NULL);
130 RegCloseKey(catkey);
132 if (!res)
134 sprintfW(fullkey,fmt2,ctg,itm,buf2,buf);
135 res = RegCreateKeyExW(tipkey, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
136 NULL, &itmkey, NULL);
138 RegCloseKey(itmkey);
141 RegCloseKey(tipkey);
143 if (!res)
144 return S_OK;
145 else
146 return E_FAIL;
149 static HRESULT WINAPI CategoryMgr_UnregisterCategory ( ITfCategoryMgr *iface,
150 REFCLSID rclsid, REFGUID rcatid, REFGUID rguid)
152 WCHAR fullkey[110];
153 WCHAR buf[39];
154 WCHAR buf2[39];
155 HKEY tipkey;
156 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
158 static const WCHAR ctg[] = {'C','a','t','e','g','o','r','y',0};
159 static const WCHAR itm[] = {'I','t','e','m',0};
160 static const WCHAR fmt[] = {'%','s','\\','%','s',0};
161 static const WCHAR fmt2[] = {'%','s','\\','%','s','\\','%','s','\\','%','s',0};
163 TRACE("(%p) %s %s %s\n",This,debugstr_guid(rclsid), debugstr_guid(rcatid), debugstr_guid(rguid));
165 StringFromGUID2(rclsid, buf, 39);
166 sprintfW(fullkey,fmt,szwSystemTIPKey,buf);
168 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE,
169 &tipkey ) != ERROR_SUCCESS)
170 return E_FAIL;
172 StringFromGUID2(rcatid, buf, 39);
173 StringFromGUID2(rguid, buf2, 39);
174 sprintfW(fullkey,fmt2,ctg,ctg,buf,buf2);
176 sprintfW(fullkey,fmt2,ctg,itm,buf2,buf);
177 RegDeleteTreeW(tipkey, fullkey);
178 sprintfW(fullkey,fmt2,ctg,itm,buf2,buf);
179 RegDeleteTreeW(tipkey, fullkey);
181 RegCloseKey(tipkey);
182 return S_OK;
185 static HRESULT WINAPI CategoryMgr_EnumCategoriesInItem ( ITfCategoryMgr *iface,
186 REFGUID rguid, IEnumGUID **ppEnum)
188 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
189 FIXME("STUB:(%p)\n",This);
190 return E_NOTIMPL;
193 static HRESULT WINAPI CategoryMgr_EnumItemsInCategory ( ITfCategoryMgr *iface,
194 REFGUID rcatid, IEnumGUID **ppEnum)
196 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
197 FIXME("STUB:(%p)\n",This);
198 return E_NOTIMPL;
201 static HRESULT WINAPI CategoryMgr_FindClosestCategory ( ITfCategoryMgr *iface,
202 REFGUID rguid, GUID *pcatid, const GUID **ppcatidList, ULONG ulCount)
204 static const WCHAR fmt[] = { '%','s','\\','%','s','\\','C','a','t','e','g','o','r','y','\\','I','t','e','m','\\','%','s',0};
206 WCHAR fullkey[120];
207 WCHAR buf[39];
208 HKEY key;
209 HRESULT hr = S_FALSE;
210 INT index = 0;
211 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
213 TRACE("(%p)\n",This);
215 if (!pcatid || (ulCount && ppcatidList == NULL))
216 return E_INVALIDARG;
218 StringFromGUID2(rguid, buf, 39);
219 sprintfW(fullkey,fmt,szwSystemTIPKey,buf,buf);
220 *pcatid = GUID_NULL;
222 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ, &key ) !=
223 ERROR_SUCCESS)
224 return S_FALSE;
226 while (1)
228 HRESULT hr2;
229 ULONG res;
230 GUID guid;
231 WCHAR catid[39];
232 DWORD cName;
234 cName = 39;
235 res = RegEnumKeyExW(key, index, catid, &cName, NULL, NULL, NULL, NULL);
236 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
237 index ++;
239 hr2 = CLSIDFromString(catid, &guid);
240 if (FAILED(hr2)) continue;
242 if (ulCount)
244 ULONG j;
245 BOOL found = FALSE;
246 for (j = 0; j < ulCount; j++)
247 if (IsEqualGUID(&guid, ppcatidList[j]))
249 found = TRUE;
250 *pcatid = guid;
251 hr = S_OK;
252 break;
254 if (found) break;
256 else
258 *pcatid = guid;
259 hr = S_OK;
260 break;
264 return hr;
267 static HRESULT WINAPI CategoryMgr_RegisterGUIDDescription (
268 ITfCategoryMgr *iface, REFCLSID rclsid, REFGUID rguid,
269 const WCHAR *pchDesc, ULONG cch)
271 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
272 FIXME("STUB:(%p)\n",This);
273 return E_NOTIMPL;
276 static HRESULT WINAPI CategoryMgr_UnregisterGUIDDescription (
277 ITfCategoryMgr *iface, REFCLSID rclsid, REFGUID rguid)
279 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
280 FIXME("STUB:(%p)\n",This);
281 return E_NOTIMPL;
284 static HRESULT WINAPI CategoryMgr_GetGUIDDescription ( ITfCategoryMgr *iface,
285 REFGUID rguid, BSTR *pbstrDesc)
287 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
288 FIXME("STUB:(%p)\n",This);
289 return E_NOTIMPL;
292 static HRESULT WINAPI CategoryMgr_RegisterGUIDDWORD ( ITfCategoryMgr *iface,
293 REFCLSID rclsid, REFGUID rguid, DWORD dw)
295 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
296 FIXME("STUB:(%p)\n",This);
297 return E_NOTIMPL;
300 static HRESULT WINAPI CategoryMgr_UnregisterGUIDDWORD ( ITfCategoryMgr *iface,
301 REFCLSID rclsid, REFGUID rguid)
303 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
304 FIXME("STUB:(%p)\n",This);
305 return E_NOTIMPL;
308 static HRESULT WINAPI CategoryMgr_GetGUIDDWORD ( ITfCategoryMgr *iface,
309 REFGUID rguid, DWORD *pdw)
311 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
312 FIXME("STUB:(%p)\n",This);
313 return E_NOTIMPL;
316 static HRESULT WINAPI CategoryMgr_RegisterGUID ( ITfCategoryMgr *iface,
317 REFGUID rguid, TfGuidAtom *pguidatom
320 DWORD index;
321 GUID *checkguid;
322 DWORD id;
323 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
325 TRACE("(%p) %s %p\n",This,debugstr_guid(rguid),pguidatom);
327 if (!pguidatom)
328 return E_INVALIDARG;
330 index = 0;
331 do {
332 id = enumerate_Cookie(COOKIE_MAGIC_GUIDATOM,&index);
333 if (id && IsEqualGUID(rguid,get_Cookie_data(id)))
335 *pguidatom = id;
336 return S_OK;
338 } while(id);
340 checkguid = HeapAlloc(GetProcessHeap(),0,sizeof(GUID));
341 *checkguid = *rguid;
342 id = generate_Cookie(COOKIE_MAGIC_GUIDATOM,checkguid);
344 if (!id)
346 HeapFree(GetProcessHeap(),0,checkguid);
347 return E_FAIL;
350 *pguidatom = id;
352 return S_OK;
355 static HRESULT WINAPI CategoryMgr_GetGUID ( ITfCategoryMgr *iface,
356 TfGuidAtom guidatom, GUID *pguid)
358 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
360 TRACE("(%p) %i\n",This,guidatom);
362 if (!pguid)
363 return E_INVALIDARG;
365 *pguid = GUID_NULL;
367 if (get_Cookie_magic(guidatom) == COOKIE_MAGIC_GUIDATOM)
368 *pguid = *((REFGUID)get_Cookie_data(guidatom));
370 return S_OK;
373 static HRESULT WINAPI CategoryMgr_IsEqualTfGuidAtom ( ITfCategoryMgr *iface,
374 TfGuidAtom guidatom, REFGUID rguid, BOOL *pfEqual)
376 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
378 TRACE("(%p) %i %s %p\n",This,guidatom,debugstr_guid(rguid),pfEqual);
380 if (!pfEqual)
381 return E_INVALIDARG;
383 *pfEqual = FALSE;
384 if (get_Cookie_magic(guidatom) == COOKIE_MAGIC_GUIDATOM)
386 if (IsEqualGUID(rguid,get_Cookie_data(guidatom)))
387 *pfEqual = TRUE;
390 return S_OK;
394 static const ITfCategoryMgrVtbl CategoryMgrVtbl =
396 CategoryMgr_QueryInterface,
397 CategoryMgr_AddRef,
398 CategoryMgr_Release,
399 CategoryMgr_RegisterCategory,
400 CategoryMgr_UnregisterCategory,
401 CategoryMgr_EnumCategoriesInItem,
402 CategoryMgr_EnumItemsInCategory,
403 CategoryMgr_FindClosestCategory,
404 CategoryMgr_RegisterGUIDDescription,
405 CategoryMgr_UnregisterGUIDDescription,
406 CategoryMgr_GetGUIDDescription,
407 CategoryMgr_RegisterGUIDDWORD,
408 CategoryMgr_UnregisterGUIDDWORD,
409 CategoryMgr_GetGUIDDWORD,
410 CategoryMgr_RegisterGUID,
411 CategoryMgr_GetGUID,
412 CategoryMgr_IsEqualTfGuidAtom
415 HRESULT CategoryMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
417 CategoryMgr *This;
418 if (pUnkOuter)
419 return CLASS_E_NOAGGREGATION;
421 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CategoryMgr));
422 if (This == NULL)
423 return E_OUTOFMEMORY;
425 This->ITfCategoryMgr_iface.lpVtbl = &CategoryMgrVtbl;
426 This->refCount = 1;
428 *ppOut = (IUnknown *)&This->ITfCategoryMgr_iface;
429 TRACE("returning %p\n", *ppOut);
430 return S_OK;