ole32/tests: Tests that show the consumer data object isn't a singleton.
[wine/hacks.git] / dlls / msctf / inputprocessor.c
blob7df557533602e23bfa4187c267b195cb0b6d3840
1 /*
2 * ITfInputProcessorProfiles 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 static const WCHAR szwLngp[] = {'L','a','n','g','u','a','g','e','P','r','o','f','i','l','e',0};
44 static const WCHAR szwEnabled[] = {'E','n','a','b','l','e','d',0};
45 static const WCHAR szwTipfmt[] = {'%','s','\\','%','s',0};
46 static const WCHAR szwFullLangfmt[] = {'%','s','\\','%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0};
48 typedef struct tagInputProcessorProfiles {
49 const ITfInputProcessorProfilesVtbl *InputProcessorProfilesVtbl;
50 LONG refCount;
52 LANGID currentLanguage;
53 } InputProcessorProfiles;
55 typedef struct tagProfilesEnumGuid {
56 const IEnumGUIDVtbl *Vtbl;
57 LONG refCount;
59 HKEY key;
60 DWORD next_index;
61 } ProfilesEnumGuid;
63 typedef struct tagEnumTfLanguageProfiles {
64 const IEnumTfLanguageProfilesVtbl *Vtbl;
65 LONG refCount;
67 HKEY tipkey;
68 DWORD tip_index;
69 WCHAR szwCurrentClsid[39];
71 HKEY langkey;
72 DWORD lang_index;
74 LANGID langid;
75 ITfCategoryMgr *catmgr;
76 } EnumTfLanguageProfiles;
78 static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut);
79 static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut);
81 static void InputProcessorProfiles_Destructor(InputProcessorProfiles *This)
83 TRACE("destroying %p\n", This);
84 HeapFree(GetProcessHeap(),0,This);
87 static void add_userkey( REFCLSID rclsid, LANGID langid,
88 REFGUID guidProfile)
90 HKEY key;
91 WCHAR buf[39];
92 WCHAR buf2[39];
93 WCHAR fullkey[168];
94 DWORD disposition = 0;
95 ULONG res;
97 TRACE("\n");
99 StringFromGUID2(rclsid, buf, 39);
100 StringFromGUID2(guidProfile, buf2, 39);
101 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
103 res = RegCreateKeyExW(HKEY_CURRENT_USER,fullkey, 0, NULL, 0,
104 KEY_READ | KEY_WRITE, NULL, &key, &disposition);
106 if (!res && disposition == REG_CREATED_NEW_KEY)
108 DWORD zero = 0x0;
109 RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
112 if (!res)
113 RegCloseKey(key);
116 static HRESULT WINAPI InputProcessorProfiles_QueryInterface(ITfInputProcessorProfiles *iface, REFIID iid, LPVOID *ppvOut)
118 InputProcessorProfiles *This = (InputProcessorProfiles *)iface;
119 *ppvOut = NULL;
121 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfInputProcessorProfiles))
123 *ppvOut = This;
126 if (*ppvOut)
128 IUnknown_AddRef(iface);
129 return S_OK;
132 WARN("unsupported interface: %s\n", debugstr_guid(iid));
133 return E_NOINTERFACE;
136 static ULONG WINAPI InputProcessorProfiles_AddRef(ITfInputProcessorProfiles *iface)
138 InputProcessorProfiles *This = (InputProcessorProfiles *)iface;
139 return InterlockedIncrement(&This->refCount);
142 static ULONG WINAPI InputProcessorProfiles_Release(ITfInputProcessorProfiles *iface)
144 InputProcessorProfiles *This = (InputProcessorProfiles *)iface;
145 ULONG ret;
147 ret = InterlockedDecrement(&This->refCount);
148 if (ret == 0)
149 InputProcessorProfiles_Destructor(This);
150 return ret;
153 /*****************************************************
154 * ITfInputProcessorProfiles functions
155 *****************************************************/
156 static HRESULT WINAPI InputProcessorProfiles_Register(
157 ITfInputProcessorProfiles *iface, REFCLSID rclsid)
159 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
160 HKEY tipkey;
161 WCHAR buf[39];
162 WCHAR fullkey[68];
164 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
166 StringFromGUID2(rclsid, buf, 39);
167 sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
169 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, NULL, 0,
170 KEY_READ | KEY_WRITE, NULL, &tipkey, NULL) != ERROR_SUCCESS)
171 return E_FAIL;
173 RegCloseKey(tipkey);
175 return S_OK;
178 static HRESULT WINAPI InputProcessorProfiles_Unregister(
179 ITfInputProcessorProfiles *iface, REFCLSID rclsid)
181 WCHAR buf[39];
182 WCHAR fullkey[68];
183 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
185 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
187 StringFromGUID2(rclsid, buf, 39);
188 sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
190 RegDeleteTreeW(HKEY_LOCAL_MACHINE, fullkey);
191 RegDeleteTreeW(HKEY_CURRENT_USER, fullkey);
193 return S_OK;
196 static HRESULT WINAPI InputProcessorProfiles_AddLanguageProfile(
197 ITfInputProcessorProfiles *iface, REFCLSID rclsid,
198 LANGID langid, REFGUID guidProfile, const WCHAR *pchDesc,
199 ULONG cchDesc, const WCHAR *pchIconFile, ULONG cchFile,
200 ULONG uIconIndex)
202 HKEY tipkey,fmtkey;
203 WCHAR buf[39];
204 WCHAR fullkey[100];
205 ULONG res;
206 DWORD disposition = 0;
208 static const WCHAR fmt2[] = {'%','s','\\','0','x','%','0','8','x','\\','%','s',0};
209 static const WCHAR desc[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
210 static const WCHAR icnf[] = {'I','c','o','n','F','i','l','e',0};
211 static const WCHAR icni[] = {'I','c','o','n','I','n','d','e','x',0};
213 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
215 TRACE("(%p) %s %x %s %s %s %i\n",This,debugstr_guid(rclsid), langid,
216 debugstr_guid(guidProfile), debugstr_wn(pchDesc,cchDesc),
217 debugstr_wn(pchIconFile,cchFile),uIconIndex);
219 StringFromGUID2(rclsid, buf, 39);
220 sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
222 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE,
223 &tipkey ) != ERROR_SUCCESS)
224 return E_FAIL;
226 StringFromGUID2(guidProfile, buf, 39);
227 sprintfW(fullkey,fmt2,szwLngp,langid,buf);
229 res = RegCreateKeyExW(tipkey,fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
230 NULL, &fmtkey, &disposition);
232 if (!res)
234 DWORD zero = 0x0;
235 RegSetValueExW(fmtkey, desc, 0, REG_SZ, (LPBYTE)pchDesc, cchDesc * sizeof(WCHAR));
236 RegSetValueExW(fmtkey, icnf, 0, REG_SZ, (LPBYTE)pchIconFile, cchFile * sizeof(WCHAR));
237 RegSetValueExW(fmtkey, icni, 0, REG_DWORD, (LPBYTE)&uIconIndex, sizeof(DWORD));
238 if (disposition == REG_CREATED_NEW_KEY)
239 RegSetValueExW(fmtkey, szwEnabled, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
240 RegCloseKey(fmtkey);
242 add_userkey(rclsid, langid, guidProfile);
244 RegCloseKey(tipkey);
246 if (!res)
247 return S_OK;
248 else
249 return E_FAIL;
252 static HRESULT WINAPI InputProcessorProfiles_RemoveLanguageProfile(
253 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
254 REFGUID guidProfile)
256 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
257 FIXME("STUB:(%p)\n",This);
258 return E_NOTIMPL;
261 static HRESULT WINAPI InputProcessorProfiles_EnumInputProcessorInfo(
262 ITfInputProcessorProfiles *iface, IEnumGUID **ppEnum)
264 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
265 TRACE("(%p) %p\n",This,ppEnum);
266 return ProfilesEnumGuid_Constructor(ppEnum);
269 static HRESULT WINAPI InputProcessorProfiles_GetDefaultLanguageProfile(
270 ITfInputProcessorProfiles *iface, LANGID langid, REFGUID catid,
271 CLSID *pclsid, GUID *pguidProfile)
273 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
274 FIXME("STUB:(%p)\n",This);
275 return E_NOTIMPL;
278 static HRESULT WINAPI InputProcessorProfiles_SetDefaultLanguageProfile(
279 ITfInputProcessorProfiles *iface, LANGID langid, REFCLSID rclsid,
280 REFGUID guidProfiles)
282 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
283 FIXME("STUB:(%p)\n",This);
284 return E_NOTIMPL;
287 static HRESULT WINAPI InputProcessorProfiles_ActivateLanguageProfile(
288 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
289 REFGUID guidProfiles)
291 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
292 FIXME("STUB:(%p)\n",This);
293 return E_NOTIMPL;
296 static HRESULT WINAPI InputProcessorProfiles_GetActiveLanguageProfile(
297 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID *plangid,
298 GUID *pguidProfile)
300 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
301 FIXME("STUB:(%p)\n",This);
302 return E_NOTIMPL;
305 static HRESULT WINAPI InputProcessorProfiles_GetLanguageProfileDescription(
306 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
307 REFGUID guidProfile, BSTR *pbstrProfile)
309 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
310 FIXME("STUB:(%p)\n",This);
311 return E_NOTIMPL;
314 static HRESULT WINAPI InputProcessorProfiles_GetCurrentLanguage(
315 ITfInputProcessorProfiles *iface, LANGID *plangid)
317 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
318 TRACE("(%p) 0x%x\n",This,This->currentLanguage);
320 if (!plangid)
321 return E_INVALIDARG;
323 *plangid = This->currentLanguage;
325 return S_OK;
328 static HRESULT WINAPI InputProcessorProfiles_ChangeCurrentLanguage(
329 ITfInputProcessorProfiles *iface, LANGID langid)
331 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
332 FIXME("STUB:(%p)\n",This);
333 return E_NOTIMPL;
336 static HRESULT WINAPI InputProcessorProfiles_GetLanguageList(
337 ITfInputProcessorProfiles *iface, LANGID **ppLangId, ULONG *pulCount)
339 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
340 FIXME("STUB:(%p)\n",This);
341 return E_NOTIMPL;
344 static HRESULT WINAPI InputProcessorProfiles_EnumLanguageProfiles(
345 ITfInputProcessorProfiles *iface, LANGID langid,
346 IEnumTfLanguageProfiles **ppEnum)
348 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
349 TRACE("(%p) %x %p\n",This,langid,ppEnum);
350 return EnumTfLanguageProfiles_Constructor(langid, ppEnum);
353 static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfile(
354 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
355 REFGUID guidProfile, BOOL fEnable)
357 HKEY key;
358 WCHAR buf[39];
359 WCHAR buf2[39];
360 WCHAR fullkey[168];
361 ULONG res;
363 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
364 TRACE("(%p) %s %x %s %i\n",This, debugstr_guid(rclsid), langid, debugstr_guid(guidProfile), fEnable);
366 StringFromGUID2(rclsid, buf, 39);
367 StringFromGUID2(guidProfile, buf2, 39);
368 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
370 res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key);
372 if (!res)
374 RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
375 RegCloseKey(key);
377 else
378 return E_FAIL;
380 return S_OK;
383 static HRESULT WINAPI InputProcessorProfiles_IsEnabledLanguageProfile(
384 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
385 REFGUID guidProfile, BOOL *pfEnable)
387 HKEY key;
388 WCHAR buf[39];
389 WCHAR buf2[39];
390 WCHAR fullkey[168];
391 ULONG res;
393 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
394 TRACE("(%p) %s, %i, %s, %p\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),pfEnable);
396 if (!pfEnable)
397 return E_INVALIDARG;
399 StringFromGUID2(rclsid, buf, 39);
400 StringFromGUID2(guidProfile, buf2, 39);
401 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
403 res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key);
405 if (!res)
407 DWORD count = sizeof(DWORD);
408 res = RegQueryValueExW(key, szwEnabled, 0, NULL, (LPBYTE)pfEnable, &count);
409 RegCloseKey(key);
412 if (res) /* Try Default */
414 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key);
416 if (!res)
418 DWORD count = sizeof(DWORD);
419 res = RegQueryValueExW(key, szwEnabled, 0, NULL, (LPBYTE)pfEnable, &count);
420 RegCloseKey(key);
424 if (!res)
425 return S_OK;
426 else
427 return E_FAIL;
430 static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfileByDefault(
431 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
432 REFGUID guidProfile, BOOL fEnable)
434 HKEY key;
435 WCHAR buf[39];
436 WCHAR buf2[39];
437 WCHAR fullkey[168];
438 ULONG res;
440 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
441 TRACE("(%p) %s %x %s %i\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),fEnable);
443 StringFromGUID2(rclsid, buf, 39);
444 StringFromGUID2(guidProfile, buf2, 39);
445 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
447 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key);
449 if (!res)
451 RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
452 RegCloseKey(key);
454 else
455 return E_FAIL;
457 return S_OK;
460 static HRESULT WINAPI InputProcessorProfiles_SubstituteKeyboardLayout(
461 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
462 REFGUID guidProfile, HKL hKL)
464 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
465 FIXME("STUB:(%p)\n",This);
466 return E_NOTIMPL;
470 static const ITfInputProcessorProfilesVtbl InputProcessorProfiles_InputProcessorProfilesVtbl =
472 InputProcessorProfiles_QueryInterface,
473 InputProcessorProfiles_AddRef,
474 InputProcessorProfiles_Release,
476 InputProcessorProfiles_Register,
477 InputProcessorProfiles_Unregister,
478 InputProcessorProfiles_AddLanguageProfile,
479 InputProcessorProfiles_RemoveLanguageProfile,
480 InputProcessorProfiles_EnumInputProcessorInfo,
481 InputProcessorProfiles_GetDefaultLanguageProfile,
482 InputProcessorProfiles_SetDefaultLanguageProfile,
483 InputProcessorProfiles_ActivateLanguageProfile,
484 InputProcessorProfiles_GetActiveLanguageProfile,
485 InputProcessorProfiles_GetLanguageProfileDescription,
486 InputProcessorProfiles_GetCurrentLanguage,
487 InputProcessorProfiles_ChangeCurrentLanguage,
488 InputProcessorProfiles_GetLanguageList,
489 InputProcessorProfiles_EnumLanguageProfiles,
490 InputProcessorProfiles_EnableLanguageProfile,
491 InputProcessorProfiles_IsEnabledLanguageProfile,
492 InputProcessorProfiles_EnableLanguageProfileByDefault,
493 InputProcessorProfiles_SubstituteKeyboardLayout
496 HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
498 InputProcessorProfiles *This;
499 if (pUnkOuter)
500 return CLASS_E_NOAGGREGATION;
502 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputProcessorProfiles));
503 if (This == NULL)
504 return E_OUTOFMEMORY;
506 This->InputProcessorProfilesVtbl= &InputProcessorProfiles_InputProcessorProfilesVtbl;
507 This->refCount = 1;
508 This->currentLanguage = GetUserDefaultLCID();
510 TRACE("returning %p\n", This);
511 *ppOut = (IUnknown *)This;
512 return S_OK;
515 /**************************************************
516 * IEnumGUID implementaion for ITfInputProcessorProfiles::EnumInputProcessorInfo
517 **************************************************/
518 static void ProfilesEnumGuid_Destructor(ProfilesEnumGuid *This)
520 TRACE("destroying %p\n", This);
521 RegCloseKey(This->key);
522 HeapFree(GetProcessHeap(),0,This);
525 static HRESULT WINAPI ProfilesEnumGuid_QueryInterface(IEnumGUID *iface, REFIID iid, LPVOID *ppvOut)
527 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
528 *ppvOut = NULL;
530 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumGUID))
532 *ppvOut = This;
535 if (*ppvOut)
537 IUnknown_AddRef(iface);
538 return S_OK;
541 WARN("unsupported interface: %s\n", debugstr_guid(iid));
542 return E_NOINTERFACE;
545 static ULONG WINAPI ProfilesEnumGuid_AddRef(IEnumGUID *iface)
547 ProfilesEnumGuid *This = (ProfilesEnumGuid*)iface;
548 return InterlockedIncrement(&This->refCount);
551 static ULONG WINAPI ProfilesEnumGuid_Release(IEnumGUID *iface)
553 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
554 ULONG ret;
556 ret = InterlockedDecrement(&This->refCount);
557 if (ret == 0)
558 ProfilesEnumGuid_Destructor(This);
559 return ret;
562 /*****************************************************
563 * IEnumGuid functions
564 *****************************************************/
565 static HRESULT WINAPI ProfilesEnumGuid_Next( LPENUMGUID iface,
566 ULONG celt, GUID *rgelt, ULONG *pceltFetched)
568 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
569 ULONG fetched = 0;
571 TRACE("(%p)\n",This);
573 if (rgelt == NULL) return E_POINTER;
575 if (This->key) while (fetched < celt)
577 LSTATUS res;
578 HRESULT hr;
579 WCHAR catid[39];
580 DWORD cName = 39;
582 res = RegEnumKeyExW(This->key, This->next_index, catid, &cName,
583 NULL, NULL, NULL, NULL);
584 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
585 ++(This->next_index);
587 hr = CLSIDFromString(catid, rgelt);
588 if (FAILED(hr)) continue;
590 ++fetched;
591 ++rgelt;
594 if (pceltFetched) *pceltFetched = fetched;
595 return fetched == celt ? S_OK : S_FALSE;
598 static HRESULT WINAPI ProfilesEnumGuid_Skip( LPENUMGUID iface, ULONG celt)
600 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
601 TRACE("(%p)\n",This);
603 This->next_index += celt;
604 return S_OK;
607 static HRESULT WINAPI ProfilesEnumGuid_Reset( LPENUMGUID iface)
609 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
610 TRACE("(%p)\n",This);
611 This->next_index = 0;
612 return S_OK;
615 static HRESULT WINAPI ProfilesEnumGuid_Clone( LPENUMGUID iface,
616 IEnumGUID **ppenum)
618 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
619 HRESULT res;
621 TRACE("(%p)\n",This);
623 if (ppenum == NULL) return E_POINTER;
625 res = ProfilesEnumGuid_Constructor(ppenum);
626 if (SUCCEEDED(res))
628 ProfilesEnumGuid *new_This = (ProfilesEnumGuid *)*ppenum;
629 new_This->next_index = This->next_index;
631 return res;
634 static const IEnumGUIDVtbl IEnumGUID_Vtbl ={
635 ProfilesEnumGuid_QueryInterface,
636 ProfilesEnumGuid_AddRef,
637 ProfilesEnumGuid_Release,
639 ProfilesEnumGuid_Next,
640 ProfilesEnumGuid_Skip,
641 ProfilesEnumGuid_Reset,
642 ProfilesEnumGuid_Clone
645 static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut)
647 ProfilesEnumGuid *This;
649 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ProfilesEnumGuid));
650 if (This == NULL)
651 return E_OUTOFMEMORY;
653 This->Vtbl= &IEnumGUID_Vtbl;
654 This->refCount = 1;
656 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0,
657 KEY_READ | KEY_WRITE, NULL, &This->key, NULL) != ERROR_SUCCESS)
658 return E_FAIL;
660 TRACE("returning %p\n", This);
661 *ppOut = (IEnumGUID*)This;
662 return S_OK;
665 /**************************************************
666 * IEnumTfLanguageProfiles implementaion
667 **************************************************/
668 static void EnumTfLanguageProfiles_Destructor(EnumTfLanguageProfiles *This)
670 TRACE("destroying %p\n", This);
671 RegCloseKey(This->tipkey);
672 if (This->langkey)
673 RegCloseKey(This->langkey);
674 ITfCategoryMgr_Release(This->catmgr);
675 HeapFree(GetProcessHeap(),0,This);
678 static HRESULT WINAPI EnumTfLanguageProfiles_QueryInterface(IEnumTfLanguageProfiles *iface, REFIID iid, LPVOID *ppvOut)
680 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
681 *ppvOut = NULL;
683 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfLanguageProfiles))
685 *ppvOut = This;
688 if (*ppvOut)
690 IUnknown_AddRef(iface);
691 return S_OK;
694 WARN("unsupported interface: %s\n", debugstr_guid(iid));
695 return E_NOINTERFACE;
698 static ULONG WINAPI EnumTfLanguageProfiles_AddRef(IEnumTfLanguageProfiles *iface)
700 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles*)iface;
701 return InterlockedIncrement(&This->refCount);
704 static ULONG WINAPI EnumTfLanguageProfiles_Release(IEnumTfLanguageProfiles *iface)
706 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
707 ULONG ret;
709 ret = InterlockedDecrement(&This->refCount);
710 if (ret == 0)
711 EnumTfLanguageProfiles_Destructor(This);
712 return ret;
715 /*****************************************************
716 * IEnumGuid functions
717 *****************************************************/
718 static INT next_LanguageProfile(EnumTfLanguageProfiles *This, CLSID clsid, TF_LANGUAGEPROFILE *tflp)
720 WCHAR fullkey[168];
721 ULONG res;
722 WCHAR profileid[39];
723 DWORD cName = 39;
724 GUID profile;
726 static const WCHAR fmt[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
728 if (This->langkey == NULL)
730 sprintfW(fullkey,fmt,This->szwCurrentClsid,szwLngp,This->langid);
731 res = RegOpenKeyExW(This->tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &This->langkey);
732 if (res)
734 This->langkey = NULL;
735 return -1;
737 This->lang_index = 0;
739 res = RegEnumKeyExW(This->langkey, This->lang_index, profileid, &cName,
740 NULL, NULL, NULL, NULL);
741 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
743 RegCloseKey(This->langkey);
744 This->langkey = NULL;
745 return -1;
747 ++(This->lang_index);
749 if (tflp)
751 static const GUID * tipcats[3] = { &GUID_TFCAT_TIP_KEYBOARD,
752 &GUID_TFCAT_TIP_SPEECH,
753 &GUID_TFCAT_TIP_HANDWRITING };
754 res = CLSIDFromString(profileid, &profile);
755 if (FAILED(res)) return 0;
757 tflp->clsid = clsid;
758 tflp->langid = This->langid;
759 /* FIXME */
760 tflp->fActive = FALSE;
761 tflp->guidProfile = profile;
762 if (ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid,
763 &tflp->catid, tipcats, 3) != S_OK)
764 ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid,
765 &tflp->catid, NULL, 0);
768 return 1;
771 static HRESULT WINAPI EnumTfLanguageProfiles_Next(IEnumTfLanguageProfiles *iface,
772 ULONG ulCount, TF_LANGUAGEPROFILE *pProfile, ULONG *pcFetch)
774 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
775 ULONG fetched = 0;
777 TRACE("(%p)\n",This);
779 if (pProfile == NULL) return E_POINTER;
781 if (This->tipkey) while (fetched < ulCount)
783 LSTATUS res;
784 HRESULT hr;
785 DWORD cName = 39;
786 GUID clsid;
788 res = RegEnumKeyExW(This->tipkey, This->tip_index,
789 This->szwCurrentClsid, &cName, NULL, NULL, NULL, NULL);
790 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
791 ++(This->tip_index);
792 hr = CLSIDFromString(This->szwCurrentClsid, &clsid);
793 if (FAILED(hr)) continue;
795 while ( fetched < ulCount)
797 INT res = next_LanguageProfile(This, clsid, pProfile);
798 if (res == 1)
800 ++fetched;
801 ++pProfile;
803 else if (res == -1)
804 break;
805 else
806 continue;
810 if (pcFetch) *pcFetch = fetched;
811 return fetched == ulCount ? S_OK : S_FALSE;
814 static HRESULT WINAPI EnumTfLanguageProfiles_Skip( IEnumTfLanguageProfiles* iface, ULONG celt)
816 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
817 FIXME("STUB (%p)\n",This);
818 return E_NOTIMPL;
821 static HRESULT WINAPI EnumTfLanguageProfiles_Reset( IEnumTfLanguageProfiles* iface)
823 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
824 TRACE("(%p)\n",This);
825 This->tip_index = 0;
826 if (This->langkey)
827 RegCloseKey(This->langkey);
828 This->langkey = NULL;
829 This->lang_index = 0;
830 return S_OK;
833 static HRESULT WINAPI EnumTfLanguageProfiles_Clone( IEnumTfLanguageProfiles *iface,
834 IEnumTfLanguageProfiles **ppenum)
836 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
837 HRESULT res;
839 TRACE("(%p)\n",This);
841 if (ppenum == NULL) return E_POINTER;
843 res = EnumTfLanguageProfiles_Constructor(This->langid, ppenum);
844 if (SUCCEEDED(res))
846 EnumTfLanguageProfiles *new_This = (EnumTfLanguageProfiles *)*ppenum;
847 new_This->tip_index = This->tip_index;
848 lstrcpynW(new_This->szwCurrentClsid,This->szwCurrentClsid,39);
850 if (This->langkey)
852 WCHAR fullkey[168];
853 static const WCHAR fmt[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
855 sprintfW(fullkey,fmt,This->szwCurrentClsid,szwLngp,This->langid);
856 res = RegOpenKeyExW(new_This->tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &This->langkey);
857 new_This->lang_index = This->lang_index;
860 return res;
863 static const IEnumTfLanguageProfilesVtbl IEnumTfLanguageProfiles_Vtbl ={
864 EnumTfLanguageProfiles_QueryInterface,
865 EnumTfLanguageProfiles_AddRef,
866 EnumTfLanguageProfiles_Release,
868 EnumTfLanguageProfiles_Clone,
869 EnumTfLanguageProfiles_Next,
870 EnumTfLanguageProfiles_Reset,
871 EnumTfLanguageProfiles_Skip
874 static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut)
876 HRESULT hr;
877 EnumTfLanguageProfiles *This;
879 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfLanguageProfiles));
880 if (This == NULL)
881 return E_OUTOFMEMORY;
883 This->Vtbl= &IEnumTfLanguageProfiles_Vtbl;
884 This->refCount = 1;
885 This->langid = langid;
887 hr = CategoryMgr_Constructor(NULL,(IUnknown**)&This->catmgr);
888 if (FAILED(hr))
890 HeapFree(GetProcessHeap(),0,This);
891 return hr;
894 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0,
895 KEY_READ | KEY_WRITE, NULL, &This->tipkey, NULL) != ERROR_SUCCESS)
896 return E_FAIL;
898 TRACE("returning %p\n", This);
899 *ppOut = (IEnumTfLanguageProfiles*)This;
900 return S_OK;