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
27 #include "wine/debug.h"
37 #include "wine/unicode.h"
38 #include "wine/list.h"
41 #include "msctf_internal.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
45 static const WCHAR szwLngp[] = {'L','a','n','g','u','a','g','e','P','r','o','f','i','l','e',0};
46 static const WCHAR szwEnabled[] = {'E','n','a','b','l','e','d',0};
47 static const WCHAR szwTipfmt[] = {'%','s','\\','%','s',0};
48 static const WCHAR szwFullLangfmt[] = {'%','s','\\','%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0};
50 typedef struct tagInputProcessorProfilesSink {
53 /* InputProcessorProfile Sinks */
55 ITfLanguageProfileNotifySink *pITfLanguageProfileNotifySink;
57 } InputProcessorProfilesSink;
59 typedef struct tagInputProcessorProfiles {
60 const ITfInputProcessorProfilesVtbl *InputProcessorProfilesVtbl;
61 const ITfSourceVtbl *SourceVtbl;
64 LANGID currentLanguage;
66 struct list LanguageProfileNotifySink;
67 } InputProcessorProfiles;
69 typedef struct tagProfilesEnumGuid {
70 const IEnumGUIDVtbl *Vtbl;
77 typedef struct tagEnumTfLanguageProfiles {
78 const IEnumTfLanguageProfilesVtbl *Vtbl;
83 WCHAR szwCurrentClsid[39];
89 ITfCategoryMgr *catmgr;
90 } EnumTfLanguageProfiles;
92 static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut);
93 static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut);
95 static inline InputProcessorProfiles *impl_from_ITfSourceVtbl(ITfSource *iface)
97 return (InputProcessorProfiles *)((char *)iface - FIELD_OFFSET(InputProcessorProfiles,SourceVtbl));
100 static void free_sink(InputProcessorProfilesSink *sink)
102 IUnknown_Release(sink->interfaces.pIUnknown);
103 HeapFree(GetProcessHeap(),0,sink);
106 static void InputProcessorProfiles_Destructor(InputProcessorProfiles *This)
108 struct list *cursor, *cursor2;
109 TRACE("destroying %p\n", This);
112 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->LanguageProfileNotifySink)
114 InputProcessorProfilesSink* sink = LIST_ENTRY(cursor,InputProcessorProfilesSink,entry);
119 HeapFree(GetProcessHeap(),0,This);
122 static void add_userkey( REFCLSID rclsid, LANGID langid,
129 DWORD disposition = 0;
134 StringFromGUID2(rclsid, buf, 39);
135 StringFromGUID2(guidProfile, buf2, 39);
136 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
138 res = RegCreateKeyExW(HKEY_CURRENT_USER,fullkey, 0, NULL, 0,
139 KEY_READ | KEY_WRITE, NULL, &key, &disposition);
141 if (!res && disposition == REG_CREATED_NEW_KEY)
144 RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
151 static HRESULT WINAPI InputProcessorProfiles_QueryInterface(ITfInputProcessorProfiles *iface, REFIID iid, LPVOID *ppvOut)
153 InputProcessorProfiles *This = (InputProcessorProfiles *)iface;
156 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfInputProcessorProfiles))
160 else if (IsEqualIID(iid, &IID_ITfSource))
162 *ppvOut = &This->SourceVtbl;
167 IUnknown_AddRef(iface);
171 WARN("unsupported interface: %s\n", debugstr_guid(iid));
172 return E_NOINTERFACE;
175 static ULONG WINAPI InputProcessorProfiles_AddRef(ITfInputProcessorProfiles *iface)
177 InputProcessorProfiles *This = (InputProcessorProfiles *)iface;
178 return InterlockedIncrement(&This->refCount);
181 static ULONG WINAPI InputProcessorProfiles_Release(ITfInputProcessorProfiles *iface)
183 InputProcessorProfiles *This = (InputProcessorProfiles *)iface;
186 ret = InterlockedDecrement(&This->refCount);
188 InputProcessorProfiles_Destructor(This);
192 /*****************************************************
193 * ITfInputProcessorProfiles functions
194 *****************************************************/
195 static HRESULT WINAPI InputProcessorProfiles_Register(
196 ITfInputProcessorProfiles *iface, REFCLSID rclsid)
198 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
203 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
205 StringFromGUID2(rclsid, buf, 39);
206 sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
208 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, NULL, 0,
209 KEY_READ | KEY_WRITE, NULL, &tipkey, NULL) != ERROR_SUCCESS)
217 static HRESULT WINAPI InputProcessorProfiles_Unregister(
218 ITfInputProcessorProfiles *iface, REFCLSID rclsid)
222 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
224 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
226 StringFromGUID2(rclsid, buf, 39);
227 sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
229 RegDeleteTreeW(HKEY_LOCAL_MACHINE, fullkey);
230 RegDeleteTreeW(HKEY_CURRENT_USER, fullkey);
235 static HRESULT WINAPI InputProcessorProfiles_AddLanguageProfile(
236 ITfInputProcessorProfiles *iface, REFCLSID rclsid,
237 LANGID langid, REFGUID guidProfile, const WCHAR *pchDesc,
238 ULONG cchDesc, const WCHAR *pchIconFile, ULONG cchFile,
245 DWORD disposition = 0;
247 static const WCHAR fmt2[] = {'%','s','\\','0','x','%','0','8','x','\\','%','s',0};
248 static const WCHAR desc[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
249 static const WCHAR icnf[] = {'I','c','o','n','F','i','l','e',0};
250 static const WCHAR icni[] = {'I','c','o','n','I','n','d','e','x',0};
252 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
254 TRACE("(%p) %s %x %s %s %s %i\n",This,debugstr_guid(rclsid), langid,
255 debugstr_guid(guidProfile), debugstr_wn(pchDesc,cchDesc),
256 debugstr_wn(pchIconFile,cchFile),uIconIndex);
258 StringFromGUID2(rclsid, buf, 39);
259 sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
261 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE,
262 &tipkey ) != ERROR_SUCCESS)
265 StringFromGUID2(guidProfile, buf, 39);
266 sprintfW(fullkey,fmt2,szwLngp,langid,buf);
268 res = RegCreateKeyExW(tipkey,fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
269 NULL, &fmtkey, &disposition);
274 RegSetValueExW(fmtkey, desc, 0, REG_SZ, (LPBYTE)pchDesc, cchDesc * sizeof(WCHAR));
275 RegSetValueExW(fmtkey, icnf, 0, REG_SZ, (LPBYTE)pchIconFile, cchFile * sizeof(WCHAR));
276 RegSetValueExW(fmtkey, icni, 0, REG_DWORD, (LPBYTE)&uIconIndex, sizeof(DWORD));
277 if (disposition == REG_CREATED_NEW_KEY)
278 RegSetValueExW(fmtkey, szwEnabled, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
281 add_userkey(rclsid, langid, guidProfile);
291 static HRESULT WINAPI InputProcessorProfiles_RemoveLanguageProfile(
292 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
295 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
296 FIXME("STUB:(%p)\n",This);
300 static HRESULT WINAPI InputProcessorProfiles_EnumInputProcessorInfo(
301 ITfInputProcessorProfiles *iface, IEnumGUID **ppEnum)
303 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
304 TRACE("(%p) %p\n",This,ppEnum);
305 return ProfilesEnumGuid_Constructor(ppEnum);
308 static HRESULT WINAPI InputProcessorProfiles_GetDefaultLanguageProfile(
309 ITfInputProcessorProfiles *iface, LANGID langid, REFGUID catid,
310 CLSID *pclsid, GUID *pguidProfile)
312 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
313 FIXME("STUB:(%p)\n",This);
317 static HRESULT WINAPI InputProcessorProfiles_SetDefaultLanguageProfile(
318 ITfInputProcessorProfiles *iface, LANGID langid, REFCLSID rclsid,
319 REFGUID guidProfiles)
321 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
322 FIXME("STUB:(%p)\n",This);
326 static HRESULT WINAPI InputProcessorProfiles_ActivateLanguageProfile(
327 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
328 REFGUID guidProfiles)
332 TF_LANGUAGEPROFILE LanguageProfile;
333 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
335 TRACE("(%p) %s %x %s\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfiles));
337 if (langid != This->currentLanguage) return E_INVALIDARG;
339 if (get_active_textservice(rclsid,NULL))
341 TRACE("Already Active\n");
345 hr = ITfInputProcessorProfiles_IsEnabledLanguageProfile(iface, rclsid,
346 langid, guidProfiles, &enabled);
347 if (FAILED(hr) || !enabled)
349 TRACE("Not Enabled\n");
353 LanguageProfile.clsid = *rclsid;
354 LanguageProfile.langid = langid;
355 LanguageProfile.guidProfile = *guidProfiles;
357 hr = add_active_textservice(&LanguageProfile);
362 static HRESULT WINAPI InputProcessorProfiles_GetActiveLanguageProfile(
363 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID *plangid,
366 TF_LANGUAGEPROFILE profile;
367 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
369 TRACE("(%p) %s %p %p\n",This,debugstr_guid(rclsid),plangid,pguidProfile);
371 if (!rclsid || !plangid || !pguidProfile)
374 if (get_active_textservice(rclsid, &profile))
376 *plangid = profile.langid;
377 *pguidProfile = profile.guidProfile;
382 *pguidProfile = GUID_NULL;
387 static HRESULT WINAPI InputProcessorProfiles_GetLanguageProfileDescription(
388 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
389 REFGUID guidProfile, BSTR *pbstrProfile)
391 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
392 FIXME("STUB:(%p)\n",This);
396 static HRESULT WINAPI InputProcessorProfiles_GetCurrentLanguage(
397 ITfInputProcessorProfiles *iface, LANGID *plangid)
399 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
400 TRACE("(%p) 0x%x\n",This,This->currentLanguage);
405 *plangid = This->currentLanguage;
410 static HRESULT WINAPI InputProcessorProfiles_ChangeCurrentLanguage(
411 ITfInputProcessorProfiles *iface, LANGID langid)
413 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
414 FIXME("STUB:(%p)\n",This);
418 static HRESULT WINAPI InputProcessorProfiles_GetLanguageList(
419 ITfInputProcessorProfiles *iface, LANGID **ppLangId, ULONG *pulCount)
421 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
422 FIXME("STUB:(%p)\n",This);
426 static HRESULT WINAPI InputProcessorProfiles_EnumLanguageProfiles(
427 ITfInputProcessorProfiles *iface, LANGID langid,
428 IEnumTfLanguageProfiles **ppEnum)
430 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
431 TRACE("(%p) %x %p\n",This,langid,ppEnum);
432 return EnumTfLanguageProfiles_Constructor(langid, ppEnum);
435 static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfile(
436 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
437 REFGUID guidProfile, BOOL fEnable)
445 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
446 TRACE("(%p) %s %x %s %i\n",This, debugstr_guid(rclsid), langid, debugstr_guid(guidProfile), fEnable);
448 StringFromGUID2(rclsid, buf, 39);
449 StringFromGUID2(guidProfile, buf2, 39);
450 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
452 res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key);
456 RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
465 static HRESULT WINAPI InputProcessorProfiles_IsEnabledLanguageProfile(
466 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
467 REFGUID guidProfile, BOOL *pfEnable)
475 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
476 TRACE("(%p) %s, %i, %s, %p\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),pfEnable);
481 StringFromGUID2(rclsid, buf, 39);
482 StringFromGUID2(guidProfile, buf2, 39);
483 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
485 res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key);
489 DWORD count = sizeof(DWORD);
490 res = RegQueryValueExW(key, szwEnabled, 0, NULL, (LPBYTE)pfEnable, &count);
494 if (res) /* Try Default */
496 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key);
500 DWORD count = sizeof(DWORD);
501 res = RegQueryValueExW(key, szwEnabled, 0, NULL, (LPBYTE)pfEnable, &count);
512 static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfileByDefault(
513 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
514 REFGUID guidProfile, BOOL fEnable)
522 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
523 TRACE("(%p) %s %x %s %i\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),fEnable);
525 StringFromGUID2(rclsid, buf, 39);
526 StringFromGUID2(guidProfile, buf2, 39);
527 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
529 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key);
533 RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
542 static HRESULT WINAPI InputProcessorProfiles_SubstituteKeyboardLayout(
543 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
544 REFGUID guidProfile, HKL hKL)
546 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
547 FIXME("STUB:(%p)\n",This);
552 static const ITfInputProcessorProfilesVtbl InputProcessorProfiles_InputProcessorProfilesVtbl =
554 InputProcessorProfiles_QueryInterface,
555 InputProcessorProfiles_AddRef,
556 InputProcessorProfiles_Release,
558 InputProcessorProfiles_Register,
559 InputProcessorProfiles_Unregister,
560 InputProcessorProfiles_AddLanguageProfile,
561 InputProcessorProfiles_RemoveLanguageProfile,
562 InputProcessorProfiles_EnumInputProcessorInfo,
563 InputProcessorProfiles_GetDefaultLanguageProfile,
564 InputProcessorProfiles_SetDefaultLanguageProfile,
565 InputProcessorProfiles_ActivateLanguageProfile,
566 InputProcessorProfiles_GetActiveLanguageProfile,
567 InputProcessorProfiles_GetLanguageProfileDescription,
568 InputProcessorProfiles_GetCurrentLanguage,
569 InputProcessorProfiles_ChangeCurrentLanguage,
570 InputProcessorProfiles_GetLanguageList,
571 InputProcessorProfiles_EnumLanguageProfiles,
572 InputProcessorProfiles_EnableLanguageProfile,
573 InputProcessorProfiles_IsEnabledLanguageProfile,
574 InputProcessorProfiles_EnableLanguageProfileByDefault,
575 InputProcessorProfiles_SubstituteKeyboardLayout
578 /*****************************************************
579 * ITfSource functions
580 *****************************************************/
581 static HRESULT WINAPI IPPSource_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
583 InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
584 return InputProcessorProfiles_QueryInterface((ITfInputProcessorProfiles *)This, iid, *ppvOut);
587 static ULONG WINAPI IPPSource_AddRef(ITfSource *iface)
589 InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
590 return InputProcessorProfiles_AddRef((ITfInputProcessorProfiles*)This);
593 static ULONG WINAPI IPPSource_Release(ITfSource *iface)
595 InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
596 return InputProcessorProfiles_Release((ITfInputProcessorProfiles *)This);
599 static WINAPI HRESULT IPPSource_AdviseSink(ITfSource *iface,
600 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
602 InputProcessorProfilesSink *ipps;
603 InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
605 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
607 if (!riid || !punk || !pdwCookie)
610 if (IsEqualIID(riid, &IID_ITfLanguageProfileNotifySink))
612 ipps = HeapAlloc(GetProcessHeap(),0,sizeof(InputProcessorProfilesSink));
614 return E_OUTOFMEMORY;
615 if (!SUCCEEDED(IUnknown_QueryInterface(punk, riid, (LPVOID*)&ipps->interfaces.pITfLanguageProfileNotifySink)))
617 HeapFree(GetProcessHeap(),0,ipps);
618 return CONNECT_E_CANNOTCONNECT;
620 list_add_head(&This->LanguageProfileNotifySink,&ipps->entry);
621 *pdwCookie = generate_Cookie(COOKIE_MAGIC_IPPSINK, ipps);
625 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
629 TRACE("cookie %x\n",*pdwCookie);
634 static WINAPI HRESULT IPPSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
636 InputProcessorProfilesSink *sink;
637 InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
639 TRACE("(%p) %x\n",This,pdwCookie);
641 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_IPPSINK)
644 sink = (InputProcessorProfilesSink*)remove_Cookie(pdwCookie);
646 return CONNECT_E_NOCONNECTION;
648 list_remove(&sink->entry);
654 static const ITfSourceVtbl InputProcessorProfiles_SourceVtbl =
656 IPPSource_QueryInterface,
660 IPPSource_AdviseSink,
661 IPPSource_UnadviseSink,
664 HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
666 InputProcessorProfiles *This;
668 return CLASS_E_NOAGGREGATION;
670 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputProcessorProfiles));
672 return E_OUTOFMEMORY;
674 This->InputProcessorProfilesVtbl= &InputProcessorProfiles_InputProcessorProfilesVtbl;
675 This->SourceVtbl = &InputProcessorProfiles_SourceVtbl;
677 This->currentLanguage = GetUserDefaultLCID();
679 list_init(&This->LanguageProfileNotifySink);
681 TRACE("returning %p\n", This);
682 *ppOut = (IUnknown *)This;
686 /**************************************************
687 * IEnumGUID implementaion for ITfInputProcessorProfiles::EnumInputProcessorInfo
688 **************************************************/
689 static void ProfilesEnumGuid_Destructor(ProfilesEnumGuid *This)
691 TRACE("destroying %p\n", This);
692 RegCloseKey(This->key);
693 HeapFree(GetProcessHeap(),0,This);
696 static HRESULT WINAPI ProfilesEnumGuid_QueryInterface(IEnumGUID *iface, REFIID iid, LPVOID *ppvOut)
698 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
701 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumGUID))
708 IUnknown_AddRef(iface);
712 WARN("unsupported interface: %s\n", debugstr_guid(iid));
713 return E_NOINTERFACE;
716 static ULONG WINAPI ProfilesEnumGuid_AddRef(IEnumGUID *iface)
718 ProfilesEnumGuid *This = (ProfilesEnumGuid*)iface;
719 return InterlockedIncrement(&This->refCount);
722 static ULONG WINAPI ProfilesEnumGuid_Release(IEnumGUID *iface)
724 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
727 ret = InterlockedDecrement(&This->refCount);
729 ProfilesEnumGuid_Destructor(This);
733 /*****************************************************
734 * IEnumGuid functions
735 *****************************************************/
736 static HRESULT WINAPI ProfilesEnumGuid_Next( LPENUMGUID iface,
737 ULONG celt, GUID *rgelt, ULONG *pceltFetched)
739 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
742 TRACE("(%p)\n",This);
744 if (rgelt == NULL) return E_POINTER;
746 if (This->key) while (fetched < celt)
753 res = RegEnumKeyExW(This->key, This->next_index, catid, &cName,
754 NULL, NULL, NULL, NULL);
755 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
756 ++(This->next_index);
758 hr = CLSIDFromString(catid, rgelt);
759 if (FAILED(hr)) continue;
765 if (pceltFetched) *pceltFetched = fetched;
766 return fetched == celt ? S_OK : S_FALSE;
769 static HRESULT WINAPI ProfilesEnumGuid_Skip( LPENUMGUID iface, ULONG celt)
771 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
772 TRACE("(%p)\n",This);
774 This->next_index += celt;
778 static HRESULT WINAPI ProfilesEnumGuid_Reset( LPENUMGUID iface)
780 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
781 TRACE("(%p)\n",This);
782 This->next_index = 0;
786 static HRESULT WINAPI ProfilesEnumGuid_Clone( LPENUMGUID iface,
789 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
792 TRACE("(%p)\n",This);
794 if (ppenum == NULL) return E_POINTER;
796 res = ProfilesEnumGuid_Constructor(ppenum);
799 ProfilesEnumGuid *new_This = (ProfilesEnumGuid *)*ppenum;
800 new_This->next_index = This->next_index;
805 static const IEnumGUIDVtbl IEnumGUID_Vtbl ={
806 ProfilesEnumGuid_QueryInterface,
807 ProfilesEnumGuid_AddRef,
808 ProfilesEnumGuid_Release,
810 ProfilesEnumGuid_Next,
811 ProfilesEnumGuid_Skip,
812 ProfilesEnumGuid_Reset,
813 ProfilesEnumGuid_Clone
816 static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut)
818 ProfilesEnumGuid *This;
820 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ProfilesEnumGuid));
822 return E_OUTOFMEMORY;
824 This->Vtbl= &IEnumGUID_Vtbl;
827 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0,
828 KEY_READ | KEY_WRITE, NULL, &This->key, NULL) != ERROR_SUCCESS)
831 TRACE("returning %p\n", This);
832 *ppOut = (IEnumGUID*)This;
836 /**************************************************
837 * IEnumTfLanguageProfiles implementaion
838 **************************************************/
839 static void EnumTfLanguageProfiles_Destructor(EnumTfLanguageProfiles *This)
841 TRACE("destroying %p\n", This);
842 RegCloseKey(This->tipkey);
844 RegCloseKey(This->langkey);
845 ITfCategoryMgr_Release(This->catmgr);
846 HeapFree(GetProcessHeap(),0,This);
849 static HRESULT WINAPI EnumTfLanguageProfiles_QueryInterface(IEnumTfLanguageProfiles *iface, REFIID iid, LPVOID *ppvOut)
851 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
854 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfLanguageProfiles))
861 IUnknown_AddRef(iface);
865 WARN("unsupported interface: %s\n", debugstr_guid(iid));
866 return E_NOINTERFACE;
869 static ULONG WINAPI EnumTfLanguageProfiles_AddRef(IEnumTfLanguageProfiles *iface)
871 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles*)iface;
872 return InterlockedIncrement(&This->refCount);
875 static ULONG WINAPI EnumTfLanguageProfiles_Release(IEnumTfLanguageProfiles *iface)
877 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
880 ret = InterlockedDecrement(&This->refCount);
882 EnumTfLanguageProfiles_Destructor(This);
886 /*****************************************************
887 * IEnumGuid functions
888 *****************************************************/
889 static INT next_LanguageProfile(EnumTfLanguageProfiles *This, CLSID clsid, TF_LANGUAGEPROFILE *tflp)
897 static const WCHAR fmt[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
899 if (This->langkey == NULL)
901 sprintfW(fullkey,fmt,This->szwCurrentClsid,szwLngp,This->langid);
902 res = RegOpenKeyExW(This->tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &This->langkey);
905 This->langkey = NULL;
908 This->lang_index = 0;
910 res = RegEnumKeyExW(This->langkey, This->lang_index, profileid, &cName,
911 NULL, NULL, NULL, NULL);
912 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
914 RegCloseKey(This->langkey);
915 This->langkey = NULL;
918 ++(This->lang_index);
922 static const GUID * tipcats[3] = { &GUID_TFCAT_TIP_KEYBOARD,
923 &GUID_TFCAT_TIP_SPEECH,
924 &GUID_TFCAT_TIP_HANDWRITING };
925 res = CLSIDFromString(profileid, &profile);
926 if (FAILED(res)) return 0;
929 tflp->langid = This->langid;
930 tflp->fActive = get_active_textservice(&clsid, NULL);
931 tflp->guidProfile = profile;
932 if (ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid,
933 &tflp->catid, tipcats, 3) != S_OK)
934 ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid,
935 &tflp->catid, NULL, 0);
941 static HRESULT WINAPI EnumTfLanguageProfiles_Next(IEnumTfLanguageProfiles *iface,
942 ULONG ulCount, TF_LANGUAGEPROFILE *pProfile, ULONG *pcFetch)
944 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
947 TRACE("(%p)\n",This);
949 if (pProfile == NULL) return E_POINTER;
951 if (This->tipkey) while (fetched < ulCount)
958 res = RegEnumKeyExW(This->tipkey, This->tip_index,
959 This->szwCurrentClsid, &cName, NULL, NULL, NULL, NULL);
960 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
962 hr = CLSIDFromString(This->szwCurrentClsid, &clsid);
963 if (FAILED(hr)) continue;
965 while ( fetched < ulCount)
967 INT res = next_LanguageProfile(This, clsid, pProfile);
980 if (pcFetch) *pcFetch = fetched;
981 return fetched == ulCount ? S_OK : S_FALSE;
984 static HRESULT WINAPI EnumTfLanguageProfiles_Skip( IEnumTfLanguageProfiles* iface, ULONG celt)
986 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
987 FIXME("STUB (%p)\n",This);
991 static HRESULT WINAPI EnumTfLanguageProfiles_Reset( IEnumTfLanguageProfiles* iface)
993 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
994 TRACE("(%p)\n",This);
997 RegCloseKey(This->langkey);
998 This->langkey = NULL;
999 This->lang_index = 0;
1003 static HRESULT WINAPI EnumTfLanguageProfiles_Clone( IEnumTfLanguageProfiles *iface,
1004 IEnumTfLanguageProfiles **ppenum)
1006 EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
1009 TRACE("(%p)\n",This);
1011 if (ppenum == NULL) return E_POINTER;
1013 res = EnumTfLanguageProfiles_Constructor(This->langid, ppenum);
1016 EnumTfLanguageProfiles *new_This = (EnumTfLanguageProfiles *)*ppenum;
1017 new_This->tip_index = This->tip_index;
1018 lstrcpynW(new_This->szwCurrentClsid,This->szwCurrentClsid,39);
1023 static const WCHAR fmt[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
1025 sprintfW(fullkey,fmt,This->szwCurrentClsid,szwLngp,This->langid);
1026 res = RegOpenKeyExW(new_This->tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &This->langkey);
1027 new_This->lang_index = This->lang_index;
1033 static const IEnumTfLanguageProfilesVtbl IEnumTfLanguageProfiles_Vtbl ={
1034 EnumTfLanguageProfiles_QueryInterface,
1035 EnumTfLanguageProfiles_AddRef,
1036 EnumTfLanguageProfiles_Release,
1038 EnumTfLanguageProfiles_Clone,
1039 EnumTfLanguageProfiles_Next,
1040 EnumTfLanguageProfiles_Reset,
1041 EnumTfLanguageProfiles_Skip
1044 static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut)
1047 EnumTfLanguageProfiles *This;
1049 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfLanguageProfiles));
1051 return E_OUTOFMEMORY;
1053 This->Vtbl= &IEnumTfLanguageProfiles_Vtbl;
1055 This->langid = langid;
1057 hr = CategoryMgr_Constructor(NULL,(IUnknown**)&This->catmgr);
1060 HeapFree(GetProcessHeap(),0,This);
1064 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0,
1065 KEY_READ | KEY_WRITE, NULL, &This->tipkey, NULL) != ERROR_SUCCESS)
1068 TRACE("returning %p\n", This);
1069 *ppOut = (IEnumTfLanguageProfiles*)This;