widl: Always check the runtimeclass interfaces presence.
[wine/zf.git] / dlls / msctf / categorymgr.c
blobf0ff896b3dd59d9b379e7c8cbdc9ba235b48ffec
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 <stdarg.h>
23 #define COBJMACROS
25 #include "wine/debug.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winuser.h"
30 #include "shlwapi.h"
31 #include "winerror.h"
32 #include "objbase.h"
35 #include "msctf.h"
36 #include "msctf_internal.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
40 typedef struct tagCategoryMgr {
41 ITfCategoryMgr ITfCategoryMgr_iface;
42 LONG refCount;
43 } CategoryMgr;
45 static inline CategoryMgr *impl_from_ITfCategoryMgr(ITfCategoryMgr *iface)
47 return CONTAINING_RECORD(iface, CategoryMgr, ITfCategoryMgr_iface);
50 static void CategoryMgr_Destructor(CategoryMgr *This)
52 TRACE("destroying %p\n", This);
53 HeapFree(GetProcessHeap(),0,This);
56 static HRESULT WINAPI CategoryMgr_QueryInterface(ITfCategoryMgr *iface, REFIID iid, LPVOID *ppvOut)
58 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
59 *ppvOut = NULL;
61 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfCategoryMgr))
63 *ppvOut = &This->ITfCategoryMgr_iface;
66 if (*ppvOut)
68 ITfCategoryMgr_AddRef(iface);
69 return S_OK;
72 WARN("unsupported interface: %s\n", debugstr_guid(iid));
73 return E_NOINTERFACE;
76 static ULONG WINAPI CategoryMgr_AddRef(ITfCategoryMgr *iface)
78 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
79 return InterlockedIncrement(&This->refCount);
82 static ULONG WINAPI CategoryMgr_Release(ITfCategoryMgr *iface)
84 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
85 ULONG ret;
87 ret = InterlockedDecrement(&This->refCount);
88 if (ret == 0)
89 CategoryMgr_Destructor(This);
90 return ret;
93 /*****************************************************
94 * ITfCategoryMgr functions
95 *****************************************************/
97 static HRESULT WINAPI CategoryMgr_RegisterCategory ( ITfCategoryMgr *iface,
98 REFCLSID rclsid, REFGUID rcatid, REFGUID rguid)
100 WCHAR fullkey[110];
101 WCHAR buf[39];
102 WCHAR buf2[39];
103 ULONG res;
104 HKEY tipkey,catkey,itmkey;
105 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
107 static const WCHAR ctg[] = {'C','a','t','e','g','o','r','y',0};
108 static const WCHAR itm[] = {'I','t','e','m',0};
109 static const WCHAR fmt[] = {'%','s','\\','%','s',0};
110 static const WCHAR fmt2[] = {'%','s','\\','%','s','\\','%','s','\\','%','s',0};
112 TRACE("(%p) %s %s %s\n",This,debugstr_guid(rclsid), debugstr_guid(rcatid), debugstr_guid(rguid));
114 StringFromGUID2(rclsid, buf, 39);
115 swprintf(fullkey,ARRAY_SIZE(fullkey),fmt,szwSystemTIPKey,buf);
117 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE,
118 &tipkey ) != ERROR_SUCCESS)
119 return E_FAIL;
121 StringFromGUID2(rcatid, buf, 39);
122 StringFromGUID2(rguid, buf2, 39);
123 swprintf(fullkey,ARRAY_SIZE(fullkey),fmt2,ctg,ctg,buf,buf2);
125 res = RegCreateKeyExW(tipkey, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
126 NULL, &catkey, NULL);
127 RegCloseKey(catkey);
129 if (!res)
131 swprintf(fullkey,ARRAY_SIZE(fullkey),fmt2,ctg,itm,buf2,buf);
132 res = RegCreateKeyExW(tipkey, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
133 NULL, &itmkey, NULL);
135 RegCloseKey(itmkey);
138 RegCloseKey(tipkey);
140 if (!res)
141 return S_OK;
142 else
143 return E_FAIL;
146 static HRESULT WINAPI CategoryMgr_UnregisterCategory ( ITfCategoryMgr *iface,
147 REFCLSID rclsid, REFGUID rcatid, REFGUID rguid)
149 WCHAR fullkey[110];
150 WCHAR buf[39];
151 WCHAR buf2[39];
152 HKEY tipkey;
153 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
155 static const WCHAR ctg[] = {'C','a','t','e','g','o','r','y',0};
156 static const WCHAR itm[] = {'I','t','e','m',0};
157 static const WCHAR fmt[] = {'%','s','\\','%','s',0};
158 static const WCHAR fmt2[] = {'%','s','\\','%','s','\\','%','s','\\','%','s',0};
160 TRACE("(%p) %s %s %s\n",This,debugstr_guid(rclsid), debugstr_guid(rcatid), debugstr_guid(rguid));
162 StringFromGUID2(rclsid, buf, 39);
163 swprintf(fullkey,ARRAY_SIZE(fullkey),fmt,szwSystemTIPKey,buf);
165 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE,
166 &tipkey ) != ERROR_SUCCESS)
167 return E_FAIL;
169 StringFromGUID2(rcatid, buf, 39);
170 StringFromGUID2(rguid, buf2, 39);
171 swprintf(fullkey,ARRAY_SIZE(fullkey),fmt2,ctg,ctg,buf,buf2);
172 RegDeleteTreeW(tipkey, fullkey);
173 swprintf(fullkey,ARRAY_SIZE(fullkey),fmt2,ctg,itm,buf2,buf);
174 RegDeleteTreeW(tipkey, fullkey);
176 RegCloseKey(tipkey);
177 return S_OK;
180 static HRESULT WINAPI CategoryMgr_EnumCategoriesInItem ( ITfCategoryMgr *iface,
181 REFGUID rguid, IEnumGUID **ppEnum)
183 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
184 FIXME("STUB:(%p)\n",This);
185 return E_NOTIMPL;
188 static HRESULT WINAPI CategoryMgr_EnumItemsInCategory ( ITfCategoryMgr *iface,
189 REFGUID rcatid, IEnumGUID **ppEnum)
191 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
192 FIXME("STUB:(%p)\n",This);
193 return E_NOTIMPL;
196 static HRESULT WINAPI CategoryMgr_FindClosestCategory ( ITfCategoryMgr *iface,
197 REFGUID rguid, GUID *pcatid, const GUID **ppcatidList, ULONG ulCount)
199 static const WCHAR fmt[] = { '%','s','\\','%','s','\\','C','a','t','e','g','o','r','y','\\','I','t','e','m','\\','%','s',0};
201 WCHAR fullkey[120];
202 WCHAR buf[39];
203 HKEY key;
204 HRESULT hr = S_FALSE;
205 INT index = 0;
206 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
208 TRACE("(%p)\n",This);
210 if (!pcatid || (ulCount && ppcatidList == NULL))
211 return E_INVALIDARG;
213 StringFromGUID2(rguid, buf, 39);
214 swprintf(fullkey,ARRAY_SIZE(fullkey),fmt,szwSystemTIPKey,buf,buf);
215 *pcatid = GUID_NULL;
217 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ, &key ) !=
218 ERROR_SUCCESS)
219 return S_FALSE;
221 while (1)
223 HRESULT hr2;
224 ULONG res;
225 GUID guid;
226 WCHAR catid[39];
227 DWORD cName;
229 cName = 39;
230 res = RegEnumKeyExW(key, index, catid, &cName, NULL, NULL, NULL, NULL);
231 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
232 index ++;
234 hr2 = CLSIDFromString(catid, &guid);
235 if (FAILED(hr2)) continue;
237 if (ulCount)
239 ULONG j;
240 BOOL found = FALSE;
241 for (j = 0; j < ulCount; j++)
242 if (IsEqualGUID(&guid, ppcatidList[j]))
244 found = TRUE;
245 *pcatid = guid;
246 hr = S_OK;
247 break;
249 if (found) break;
251 else
253 *pcatid = guid;
254 hr = S_OK;
255 break;
259 return hr;
262 static HRESULT WINAPI CategoryMgr_RegisterGUIDDescription (
263 ITfCategoryMgr *iface, REFCLSID rclsid, REFGUID rguid,
264 const WCHAR *pchDesc, ULONG cch)
266 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
267 FIXME("STUB:(%p)\n",This);
268 return E_NOTIMPL;
271 static HRESULT WINAPI CategoryMgr_UnregisterGUIDDescription (
272 ITfCategoryMgr *iface, REFCLSID rclsid, REFGUID rguid)
274 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
275 FIXME("STUB:(%p)\n",This);
276 return E_NOTIMPL;
279 static HRESULT WINAPI CategoryMgr_GetGUIDDescription ( ITfCategoryMgr *iface,
280 REFGUID rguid, BSTR *pbstrDesc)
282 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
283 FIXME("STUB:(%p)\n",This);
284 return E_NOTIMPL;
287 static HRESULT WINAPI CategoryMgr_RegisterGUIDDWORD ( ITfCategoryMgr *iface,
288 REFCLSID rclsid, REFGUID rguid, DWORD dw)
290 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
291 FIXME("STUB:(%p)\n",This);
292 return E_NOTIMPL;
295 static HRESULT WINAPI CategoryMgr_UnregisterGUIDDWORD ( ITfCategoryMgr *iface,
296 REFCLSID rclsid, REFGUID rguid)
298 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
299 FIXME("STUB:(%p)\n",This);
300 return E_NOTIMPL;
303 static HRESULT WINAPI CategoryMgr_GetGUIDDWORD ( ITfCategoryMgr *iface,
304 REFGUID rguid, DWORD *pdw)
306 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
307 FIXME("STUB:(%p)\n",This);
308 return E_NOTIMPL;
311 static HRESULT WINAPI CategoryMgr_RegisterGUID ( ITfCategoryMgr *iface,
312 REFGUID rguid, TfGuidAtom *pguidatom
315 DWORD index;
316 GUID *checkguid;
317 DWORD id;
318 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
320 TRACE("(%p) %s %p\n",This,debugstr_guid(rguid),pguidatom);
322 if (!pguidatom)
323 return E_INVALIDARG;
325 index = 0;
326 do {
327 id = enumerate_Cookie(COOKIE_MAGIC_GUIDATOM,&index);
328 if (id && IsEqualGUID(rguid,get_Cookie_data(id)))
330 *pguidatom = id;
331 return S_OK;
333 } while(id);
335 checkguid = HeapAlloc(GetProcessHeap(),0,sizeof(GUID));
336 *checkguid = *rguid;
337 id = generate_Cookie(COOKIE_MAGIC_GUIDATOM,checkguid);
339 if (!id)
341 HeapFree(GetProcessHeap(),0,checkguid);
342 return E_FAIL;
345 *pguidatom = id;
347 return S_OK;
350 static HRESULT WINAPI CategoryMgr_GetGUID ( ITfCategoryMgr *iface,
351 TfGuidAtom guidatom, GUID *pguid)
353 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
355 TRACE("(%p) %i\n",This,guidatom);
357 if (!pguid)
358 return E_INVALIDARG;
360 *pguid = GUID_NULL;
362 if (get_Cookie_magic(guidatom) == COOKIE_MAGIC_GUIDATOM)
363 *pguid = *((REFGUID)get_Cookie_data(guidatom));
365 return S_OK;
368 static HRESULT WINAPI CategoryMgr_IsEqualTfGuidAtom ( ITfCategoryMgr *iface,
369 TfGuidAtom guidatom, REFGUID rguid, BOOL *pfEqual)
371 CategoryMgr *This = impl_from_ITfCategoryMgr(iface);
373 TRACE("(%p) %i %s %p\n",This,guidatom,debugstr_guid(rguid),pfEqual);
375 if (!pfEqual)
376 return E_INVALIDARG;
378 *pfEqual = FALSE;
379 if (get_Cookie_magic(guidatom) == COOKIE_MAGIC_GUIDATOM)
381 if (IsEqualGUID(rguid,get_Cookie_data(guidatom)))
382 *pfEqual = TRUE;
385 return S_OK;
389 static const ITfCategoryMgrVtbl CategoryMgrVtbl =
391 CategoryMgr_QueryInterface,
392 CategoryMgr_AddRef,
393 CategoryMgr_Release,
394 CategoryMgr_RegisterCategory,
395 CategoryMgr_UnregisterCategory,
396 CategoryMgr_EnumCategoriesInItem,
397 CategoryMgr_EnumItemsInCategory,
398 CategoryMgr_FindClosestCategory,
399 CategoryMgr_RegisterGUIDDescription,
400 CategoryMgr_UnregisterGUIDDescription,
401 CategoryMgr_GetGUIDDescription,
402 CategoryMgr_RegisterGUIDDWORD,
403 CategoryMgr_UnregisterGUIDDWORD,
404 CategoryMgr_GetGUIDDWORD,
405 CategoryMgr_RegisterGUID,
406 CategoryMgr_GetGUID,
407 CategoryMgr_IsEqualTfGuidAtom
410 HRESULT CategoryMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
412 CategoryMgr *This;
413 if (pUnkOuter)
414 return CLASS_E_NOAGGREGATION;
416 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(CategoryMgr));
417 if (This == NULL)
418 return E_OUTOFMEMORY;
420 This->ITfCategoryMgr_iface.lpVtbl = &CategoryMgrVtbl;
421 This->refCount = 1;
423 *ppOut = (IUnknown *)&This->ITfCategoryMgr_iface;
424 TRACE("returning %p\n", *ppOut);
425 return S_OK;