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"
36 #include "wine/unicode.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;
52 LANGID currentLanguage;
53 } InputProcessorProfiles;
55 typedef struct tagProfilesEnumGuid {
56 const IEnumGUIDVtbl *Vtbl;
63 static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut);
65 static void InputProcessorProfiles_Destructor(InputProcessorProfiles *This)
67 TRACE("destroying %p\n", This);
68 HeapFree(GetProcessHeap(),0,This);
71 static void add_userkey( REFCLSID rclsid, LANGID langid,
78 DWORD disposition = 0;
83 StringFromGUID2(rclsid, buf, 39);
84 StringFromGUID2(guidProfile, buf2, 39);
85 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
87 res = RegCreateKeyExW(HKEY_CURRENT_USER,fullkey, 0, NULL, 0,
88 KEY_READ | KEY_WRITE, NULL, &key, &disposition);
90 if (!res && disposition == REG_CREATED_NEW_KEY)
93 RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
100 static HRESULT WINAPI InputProcessorProfiles_QueryInterface(ITfInputProcessorProfiles *iface, REFIID iid, LPVOID *ppvOut)
102 InputProcessorProfiles *This = (InputProcessorProfiles *)iface;
105 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfInputProcessorProfiles))
112 IUnknown_AddRef(iface);
116 WARN("unsupported interface: %s\n", debugstr_guid(iid));
117 return E_NOINTERFACE;
120 static ULONG WINAPI InputProcessorProfiles_AddRef(ITfInputProcessorProfiles *iface)
122 InputProcessorProfiles *This = (InputProcessorProfiles *)iface;
123 return InterlockedIncrement(&This->refCount);
126 static ULONG WINAPI InputProcessorProfiles_Release(ITfInputProcessorProfiles *iface)
128 InputProcessorProfiles *This = (InputProcessorProfiles *)iface;
131 ret = InterlockedDecrement(&This->refCount);
133 InputProcessorProfiles_Destructor(This);
137 /*****************************************************
138 * ITfInputProcessorProfiles functions
139 *****************************************************/
140 static HRESULT WINAPI InputProcessorProfiles_Register(
141 ITfInputProcessorProfiles *iface, REFCLSID rclsid)
143 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
148 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
150 StringFromGUID2(rclsid, buf, 39);
151 sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
153 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, NULL, 0,
154 KEY_READ | KEY_WRITE, NULL, &tipkey, NULL) != ERROR_SUCCESS)
162 static HRESULT WINAPI InputProcessorProfiles_Unregister(
163 ITfInputProcessorProfiles *iface, REFCLSID rclsid)
167 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
169 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
171 StringFromGUID2(rclsid, buf, 39);
172 sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
174 RegDeleteTreeW(HKEY_LOCAL_MACHINE, fullkey);
175 RegDeleteTreeW(HKEY_CURRENT_USER, fullkey);
180 static HRESULT WINAPI InputProcessorProfiles_AddLanguageProfile(
181 ITfInputProcessorProfiles *iface, REFCLSID rclsid,
182 LANGID langid, REFGUID guidProfile, const WCHAR *pchDesc,
183 ULONG cchDesc, const WCHAR *pchIconFile, ULONG cchFile,
190 DWORD disposition = 0;
192 static const WCHAR fmt2[] = {'%','s','\\','0','x','%','0','8','x','\\','%','s',0};
193 static const WCHAR desc[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
194 static const WCHAR icnf[] = {'I','c','o','n','F','i','l','e',0};
195 static const WCHAR icni[] = {'I','c','o','n','I','n','d','e','x',0};
197 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
199 TRACE("(%p) %s %x %s %s %s %i\n",This,debugstr_guid(rclsid), langid,
200 debugstr_guid(guidProfile), debugstr_wn(pchDesc,cchDesc),
201 debugstr_wn(pchIconFile,cchFile),uIconIndex);
203 StringFromGUID2(rclsid, buf, 39);
204 sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
206 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE,
207 &tipkey ) != ERROR_SUCCESS)
210 StringFromGUID2(guidProfile, buf, 39);
211 sprintfW(fullkey,fmt2,szwLngp,langid,buf);
213 res = RegCreateKeyExW(tipkey,fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
214 NULL, &fmtkey, &disposition);
219 RegSetValueExW(fmtkey, desc, 0, REG_SZ, (LPBYTE)pchDesc, cchDesc * sizeof(WCHAR));
220 RegSetValueExW(fmtkey, icnf, 0, REG_SZ, (LPBYTE)pchIconFile, cchFile * sizeof(WCHAR));
221 RegSetValueExW(fmtkey, icni, 0, REG_DWORD, (LPBYTE)&uIconIndex, sizeof(DWORD));
222 if (disposition == REG_CREATED_NEW_KEY)
223 RegSetValueExW(fmtkey, szwEnabled, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
226 add_userkey(rclsid, langid, guidProfile);
236 static HRESULT WINAPI InputProcessorProfiles_RemoveLanguageProfile(
237 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
240 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
241 FIXME("STUB:(%p)\n",This);
245 static HRESULT WINAPI InputProcessorProfiles_EnumInputProcessorInfo(
246 ITfInputProcessorProfiles *iface, IEnumGUID **ppEnum)
248 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
249 TRACE("(%p) %p\n",This,ppEnum);
250 return ProfilesEnumGuid_Constructor(ppEnum);
253 static HRESULT WINAPI InputProcessorProfiles_GetDefaultLanguageProfile(
254 ITfInputProcessorProfiles *iface, LANGID langid, REFGUID catid,
255 CLSID *pclsid, GUID *pguidProfile)
257 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
258 FIXME("STUB:(%p)\n",This);
262 static HRESULT WINAPI InputProcessorProfiles_SetDefaultLanguageProfile(
263 ITfInputProcessorProfiles *iface, LANGID langid, REFCLSID rclsid,
264 REFGUID guidProfiles)
266 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
267 FIXME("STUB:(%p)\n",This);
271 static HRESULT WINAPI InputProcessorProfiles_ActivateLanguageProfile(
272 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
273 REFGUID guidProfiles)
275 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
276 FIXME("STUB:(%p)\n",This);
280 static HRESULT WINAPI InputProcessorProfiles_GetActiveLanguageProfile(
281 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID *plangid,
284 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
285 FIXME("STUB:(%p)\n",This);
289 static HRESULT WINAPI InputProcessorProfiles_GetLanguageProfileDescription(
290 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
291 REFGUID guidProfile, BSTR *pbstrProfile)
293 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
294 FIXME("STUB:(%p)\n",This);
298 static HRESULT WINAPI InputProcessorProfiles_GetCurrentLanguage(
299 ITfInputProcessorProfiles *iface, LANGID *plangid)
301 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
302 TRACE("(%p) 0x%x\n",This,This->currentLanguage);
307 *plangid = This->currentLanguage;
312 static HRESULT WINAPI InputProcessorProfiles_ChangeCurrentLanguage(
313 ITfInputProcessorProfiles *iface, LANGID langid)
315 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
316 FIXME("STUB:(%p)\n",This);
320 static HRESULT WINAPI InputProcessorProfiles_GetLanguageList(
321 ITfInputProcessorProfiles *iface, LANGID **ppLangId, ULONG *pulCount)
323 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
324 FIXME("STUB:(%p)\n",This);
328 static HRESULT WINAPI InputProcessorProfiles_EnumLanguageProfiles(
329 ITfInputProcessorProfiles *iface, LANGID langid,
330 IEnumTfLanguageProfiles **ppEnum)
332 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
333 FIXME("STUB:(%p)\n",This);
337 static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfile(
338 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
339 REFGUID guidProfile, BOOL fEnable)
347 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
348 TRACE("(%p) %s %x %s %i\n",This, debugstr_guid(rclsid), langid, debugstr_guid(guidProfile), fEnable);
350 StringFromGUID2(rclsid, buf, 39);
351 StringFromGUID2(guidProfile, buf2, 39);
352 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
354 res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key);
358 RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
367 static HRESULT WINAPI InputProcessorProfiles_IsEnabledLanguageProfile(
368 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
369 REFGUID guidProfile, BOOL *pfEnable)
377 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
378 TRACE("(%p) %s, %i, %s, %p\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),pfEnable);
383 StringFromGUID2(rclsid, buf, 39);
384 StringFromGUID2(guidProfile, buf2, 39);
385 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
387 res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key);
391 DWORD count = sizeof(DWORD);
392 res = RegQueryValueExW(key, szwEnabled, 0, NULL, (LPBYTE)pfEnable, &count);
396 if (res) /* Try Default */
398 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key);
402 DWORD count = sizeof(DWORD);
403 res = RegQueryValueExW(key, szwEnabled, 0, NULL, (LPBYTE)pfEnable, &count);
414 static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfileByDefault(
415 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
416 REFGUID guidProfile, BOOL fEnable)
424 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
425 TRACE("(%p) %s %x %s %i\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),fEnable);
427 StringFromGUID2(rclsid, buf, 39);
428 StringFromGUID2(guidProfile, buf2, 39);
429 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
431 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key);
435 RegSetValueExW(key, szwEnabled, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
444 static HRESULT WINAPI InputProcessorProfiles_SubstituteKeyboardLayout(
445 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
446 REFGUID guidProfile, HKL hKL)
448 InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
449 FIXME("STUB:(%p)\n",This);
454 static const ITfInputProcessorProfilesVtbl InputProcessorProfiles_InputProcessorProfilesVtbl =
456 InputProcessorProfiles_QueryInterface,
457 InputProcessorProfiles_AddRef,
458 InputProcessorProfiles_Release,
460 InputProcessorProfiles_Register,
461 InputProcessorProfiles_Unregister,
462 InputProcessorProfiles_AddLanguageProfile,
463 InputProcessorProfiles_RemoveLanguageProfile,
464 InputProcessorProfiles_EnumInputProcessorInfo,
465 InputProcessorProfiles_GetDefaultLanguageProfile,
466 InputProcessorProfiles_SetDefaultLanguageProfile,
467 InputProcessorProfiles_ActivateLanguageProfile,
468 InputProcessorProfiles_GetActiveLanguageProfile,
469 InputProcessorProfiles_GetLanguageProfileDescription,
470 InputProcessorProfiles_GetCurrentLanguage,
471 InputProcessorProfiles_ChangeCurrentLanguage,
472 InputProcessorProfiles_GetLanguageList,
473 InputProcessorProfiles_EnumLanguageProfiles,
474 InputProcessorProfiles_EnableLanguageProfile,
475 InputProcessorProfiles_IsEnabledLanguageProfile,
476 InputProcessorProfiles_EnableLanguageProfileByDefault,
477 InputProcessorProfiles_SubstituteKeyboardLayout
480 HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
482 InputProcessorProfiles *This;
484 return CLASS_E_NOAGGREGATION;
486 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputProcessorProfiles));
488 return E_OUTOFMEMORY;
490 This->InputProcessorProfilesVtbl= &InputProcessorProfiles_InputProcessorProfilesVtbl;
492 This->currentLanguage = GetUserDefaultLCID();
494 TRACE("returning %p\n", This);
495 *ppOut = (IUnknown *)This;
499 /**************************************************
500 * IEnumGUID implementaion for ITfInputProcessorProfiles::EnumInputProcessorInfo
501 **************************************************/
502 static void ProfilesEnumGuid_Destructor(ProfilesEnumGuid *This)
504 TRACE("destroying %p\n", This);
505 RegCloseKey(This->key);
506 HeapFree(GetProcessHeap(),0,This);
509 static HRESULT WINAPI ProfilesEnumGuid_QueryInterface(IEnumGUID *iface, REFIID iid, LPVOID *ppvOut)
511 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
514 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumGUID))
521 IUnknown_AddRef(iface);
525 WARN("unsupported interface: %s\n", debugstr_guid(iid));
526 return E_NOINTERFACE;
529 static ULONG WINAPI ProfilesEnumGuid_AddRef(IEnumGUID *iface)
531 ProfilesEnumGuid *This = (ProfilesEnumGuid*)iface;
532 return InterlockedIncrement(&This->refCount);
535 static ULONG WINAPI ProfilesEnumGuid_Release(IEnumGUID *iface)
537 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
540 ret = InterlockedDecrement(&This->refCount);
542 ProfilesEnumGuid_Destructor(This);
546 /*****************************************************
547 * IEnumGuid functions
548 *****************************************************/
549 static HRESULT WINAPI ProfilesEnumGuid_Next( LPENUMGUID iface,
550 ULONG celt, GUID *rgelt, ULONG *pceltFetched)
552 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
555 TRACE("(%p)\n",This);
557 if (rgelt == NULL) return E_POINTER;
559 if (This->key) while (fetched < celt)
566 res = RegEnumKeyExW(This->key, This->next_index, catid, &cName,
567 NULL, NULL, NULL, NULL);
568 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
569 ++(This->next_index);
571 hr = CLSIDFromString(catid, rgelt);
572 if (FAILED(hr)) continue;
578 if (pceltFetched) *pceltFetched = fetched;
579 return fetched == celt ? S_OK : S_FALSE;
582 static HRESULT WINAPI ProfilesEnumGuid_Skip( LPENUMGUID iface, ULONG celt)
584 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
585 TRACE("(%p)\n",This);
587 This->next_index += celt;
591 static HRESULT WINAPI ProfilesEnumGuid_Reset( LPENUMGUID iface)
593 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
594 TRACE("(%p)\n",This);
595 This->next_index = 0;
599 static HRESULT WINAPI ProfilesEnumGuid_Clone( LPENUMGUID iface,
602 ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
605 TRACE("(%p)\n",This);
607 if (ppenum == NULL) return E_POINTER;
609 res = ProfilesEnumGuid_Constructor(ppenum);
612 ProfilesEnumGuid *new_This = (ProfilesEnumGuid *)*ppenum;
613 new_This->next_index = This->next_index;
618 static const IEnumGUIDVtbl IEnumGUID_Vtbl ={
619 ProfilesEnumGuid_QueryInterface,
620 ProfilesEnumGuid_AddRef,
621 ProfilesEnumGuid_Release,
623 ProfilesEnumGuid_Next,
624 ProfilesEnumGuid_Skip,
625 ProfilesEnumGuid_Reset,
626 ProfilesEnumGuid_Clone
629 static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut)
631 ProfilesEnumGuid *This;
633 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ProfilesEnumGuid));
635 return E_OUTOFMEMORY;
637 This->Vtbl= &IEnumGUID_Vtbl;
640 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0,
641 KEY_READ | KEY_WRITE, NULL, &This->key, NULL) != ERROR_SUCCESS)
644 TRACE("returning %p\n", This);
645 *ppOut = (IEnumGUID*)This;