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 "msctf_internal.h"
23 static const WCHAR szwLngp
[] = {'L','a','n','g','u','a','g','e','P','r','o','f','i','l','e',0};
24 static const WCHAR szwEnable
[] = {'E','n','a','b','l','e',0};
25 static const WCHAR szwTipfmt
[] = {'%','s','\\','%','s',0};
26 static const WCHAR szwFullLangfmt
[] = {'%','s','\\','%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0};
28 static const WCHAR szwAssemblies
[] = {'A','s','s','e','m','b','l','i','e','s',0};
29 static const WCHAR szwDefault
[] = {'D','e','f','a','u','l','t',0};
30 static const WCHAR szwProfile
[] = {'P','r','o','f','i','l','e',0};
31 static const WCHAR szwDefaultFmt
[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0};
33 typedef struct tagInputProcessorProfilesSink
{
36 /* InputProcessorProfile Sinks */
38 ITfLanguageProfileNotifySink
*pITfLanguageProfileNotifySink
;
40 } InputProcessorProfilesSink
;
42 typedef struct tagInputProcessorProfiles
{
43 ITfInputProcessorProfiles ITfInputProcessorProfiles_iface
;
44 ITfSource ITfSource_iface
;
45 /* const ITfInputProcessorProfileMgrVtbl *InputProcessorProfileMgrVtbl; */
46 /* const ITfInputProcessorProfilesExVtbl *InputProcessorProfilesExVtbl; */
47 /* const ITfInputProcessorProfileSubstituteLayoutVtbl *InputProcessorProfileSubstituteLayoutVtbl; */
50 LANGID currentLanguage
;
52 struct list LanguageProfileNotifySink
;
53 } InputProcessorProfiles
;
55 typedef struct tagProfilesEnumGuid
{
56 IEnumGUID IEnumGUID_iface
;
63 typedef struct tagEnumTfLanguageProfiles
{
64 IEnumTfLanguageProfiles IEnumTfLanguageProfiles_iface
;
69 WCHAR szwCurrentClsid
[39];
75 ITfCategoryMgr
*catmgr
;
76 } EnumTfLanguageProfiles
;
78 static HRESULT
ProfilesEnumGuid_Constructor(IEnumGUID
**ppOut
);
79 static HRESULT
EnumTfLanguageProfiles_Constructor(LANGID langid
, IEnumTfLanguageProfiles
**ppOut
);
81 static inline InputProcessorProfiles
*impl_from_ITfInputProcessorProfiles(ITfInputProcessorProfiles
*iface
)
83 return CONTAINING_RECORD(iface
, InputProcessorProfiles
, ITfInputProcessorProfiles_iface
);
86 static inline InputProcessorProfiles
*impl_from_ITfSource(ITfSource
*iface
)
88 return CONTAINING_RECORD(iface
, InputProcessorProfiles
, ITfSource_iface
);
91 static inline ProfilesEnumGuid
*impl_from_IEnumGUID(IEnumGUID
*iface
)
93 return CONTAINING_RECORD(iface
, ProfilesEnumGuid
, IEnumGUID_iface
);
96 static inline EnumTfLanguageProfiles
*impl_from_IEnumTfLanguageProfiles(IEnumTfLanguageProfiles
*iface
)
98 return CONTAINING_RECORD(iface
, EnumTfLanguageProfiles
, IEnumTfLanguageProfiles_iface
);
101 static void free_sink(InputProcessorProfilesSink
*sink
)
103 IUnknown_Release(sink
->interfaces
.pIUnknown
);
104 HeapFree(GetProcessHeap(),0,sink
);
107 static void InputProcessorProfiles_Destructor(InputProcessorProfiles
*This
)
109 struct list
*cursor
, *cursor2
;
110 TRACE("destroying %p\n", This
);
113 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->LanguageProfileNotifySink
)
115 InputProcessorProfilesSink
* sink
= LIST_ENTRY(cursor
,InputProcessorProfilesSink
,entry
);
120 HeapFree(GetProcessHeap(),0,This
);
123 static void add_userkey( REFCLSID rclsid
, LANGID langid
,
130 DWORD disposition
= 0;
135 StringFromGUID2(rclsid
, buf
, 39);
136 StringFromGUID2(guidProfile
, buf2
, 39);
137 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
139 res
= RegCreateKeyExW(HKEY_CURRENT_USER
,fullkey
, 0, NULL
, 0,
140 KEY_READ
| KEY_WRITE
, NULL
, &key
, &disposition
);
142 if (!res
&& disposition
== REG_CREATED_NEW_KEY
)
145 RegSetValueExW(key
, szwEnable
, 0, REG_DWORD
, (LPBYTE
)&zero
, sizeof(DWORD
));
152 static HRESULT WINAPI
InputProcessorProfiles_QueryInterface(ITfInputProcessorProfiles
*iface
, REFIID iid
, LPVOID
*ppvOut
)
154 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
157 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfInputProcessorProfiles
))
159 *ppvOut
= &This
->ITfInputProcessorProfiles_iface
;
161 else if (IsEqualIID(iid
, &IID_ITfSource
))
163 *ppvOut
= &This
->ITfSource_iface
;
168 ITfInputProcessorProfiles_AddRef(iface
);
172 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
173 return E_NOINTERFACE
;
176 static ULONG WINAPI
InputProcessorProfiles_AddRef(ITfInputProcessorProfiles
*iface
)
178 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
179 return InterlockedIncrement(&This
->refCount
);
182 static ULONG WINAPI
InputProcessorProfiles_Release(ITfInputProcessorProfiles
*iface
)
184 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
187 ret
= InterlockedDecrement(&This
->refCount
);
189 InputProcessorProfiles_Destructor(This
);
193 /*****************************************************
194 * ITfInputProcessorProfiles functions
195 *****************************************************/
196 static HRESULT WINAPI
InputProcessorProfiles_Register(
197 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
)
199 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
204 TRACE("(%p) %s\n",This
,debugstr_guid(rclsid
));
206 StringFromGUID2(rclsid
, buf
, 39);
207 sprintfW(fullkey
,szwTipfmt
,szwSystemTIPKey
,buf
);
209 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,fullkey
, 0, NULL
, 0,
210 KEY_READ
| KEY_WRITE
, NULL
, &tipkey
, NULL
) != ERROR_SUCCESS
)
218 static HRESULT WINAPI
InputProcessorProfiles_Unregister(
219 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
)
221 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
225 TRACE("(%p) %s\n",This
,debugstr_guid(rclsid
));
227 StringFromGUID2(rclsid
, buf
, 39);
228 sprintfW(fullkey
,szwTipfmt
,szwSystemTIPKey
,buf
);
230 SHDeleteKeyW(HKEY_LOCAL_MACHINE
, fullkey
);
231 SHDeleteKeyW(HKEY_CURRENT_USER
, fullkey
);
236 static HRESULT WINAPI
InputProcessorProfiles_AddLanguageProfile(
237 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
,
238 LANGID langid
, REFGUID guidProfile
, const WCHAR
*pchDesc
,
239 ULONG cchDesc
, const WCHAR
*pchIconFile
, ULONG cchFile
,
242 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
247 DWORD disposition
= 0;
249 static const WCHAR fmt2
[] = {'%','s','\\','0','x','%','0','8','x','\\','%','s',0};
250 static const WCHAR desc
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
251 static const WCHAR icnf
[] = {'I','c','o','n','F','i','l','e',0};
252 static const WCHAR icni
[] = {'I','c','o','n','I','n','d','e','x',0};
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
, (const BYTE
*)pchDesc
, cchDesc
* sizeof(WCHAR
));
275 RegSetValueExW(fmtkey
, icnf
, 0, REG_SZ
, (const BYTE
*)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
, szwEnable
, 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
= impl_from_ITfInputProcessorProfiles(iface
);
296 FIXME("STUB:(%p)\n",This
);
300 static HRESULT WINAPI
InputProcessorProfiles_EnumInputProcessorInfo(
301 ITfInputProcessorProfiles
*iface
, IEnumGUID
**ppEnum
)
303 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(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
= impl_from_ITfInputProcessorProfiles(iface
);
319 TRACE("%p) %x %s %p %p\n",This
, langid
, debugstr_guid(catid
),pclsid
,pguidProfile
);
321 if (!catid
|| !pclsid
|| !pguidProfile
)
324 StringFromGUID2(catid
, buf
, 39);
325 sprintfW(fullkey
, szwDefaultFmt
, szwSystemCTFKey
, szwAssemblies
, langid
, buf
);
327 if (RegOpenKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, KEY_READ
| KEY_WRITE
,
328 &hkey
) != ERROR_SUCCESS
)
332 res
= RegQueryValueExW(hkey
, szwDefault
, 0, NULL
, (LPBYTE
)buf
, &count
);
333 if (res
!= ERROR_SUCCESS
)
338 CLSIDFromString(buf
,pclsid
);
340 res
= RegQueryValueExW(hkey
, szwProfile
, 0, NULL
, (LPBYTE
)buf
, &count
);
341 if (res
== ERROR_SUCCESS
)
342 CLSIDFromString(buf
,pguidProfile
);
349 static HRESULT WINAPI
InputProcessorProfiles_SetDefaultLanguageProfile(
350 ITfInputProcessorProfiles
*iface
, LANGID langid
, REFCLSID rclsid
,
351 REFGUID guidProfiles
)
353 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
359 ITfCategoryMgr
*catmgr
;
360 static const GUID
* tipcats
[3] = { &GUID_TFCAT_TIP_KEYBOARD
,
361 &GUID_TFCAT_TIP_SPEECH
,
362 &GUID_TFCAT_TIP_HANDWRITING
};
364 TRACE("%p) %x %s %s\n",This
, langid
, debugstr_guid(rclsid
),debugstr_guid(guidProfiles
));
366 if (!rclsid
|| !guidProfiles
)
369 hr
= CategoryMgr_Constructor(NULL
,(IUnknown
**)&catmgr
);
374 if (ITfCategoryMgr_FindClosestCategory(catmgr
, rclsid
,
375 &catid
, tipcats
, 3) != S_OK
)
376 hr
= ITfCategoryMgr_FindClosestCategory(catmgr
, rclsid
,
378 ITfCategoryMgr_Release(catmgr
);
383 StringFromGUID2(&catid
, buf
, 39);
384 sprintfW(fullkey
, szwDefaultFmt
, szwSystemCTFKey
, szwAssemblies
, langid
, buf
);
386 if (RegCreateKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, NULL
, 0, KEY_READ
| KEY_WRITE
,
387 NULL
, &hkey
, NULL
) != ERROR_SUCCESS
)
390 StringFromGUID2(rclsid
, buf
, 39);
391 RegSetValueExW(hkey
, szwDefault
, 0, REG_SZ
, (LPBYTE
)buf
, sizeof(buf
));
392 StringFromGUID2(guidProfiles
, buf
, 39);
393 RegSetValueExW(hkey
, szwProfile
, 0, REG_SZ
, (LPBYTE
)buf
, sizeof(buf
));
399 static HRESULT WINAPI
InputProcessorProfiles_ActivateLanguageProfile(
400 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
401 REFGUID guidProfiles
)
403 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
406 TF_LANGUAGEPROFILE LanguageProfile
;
408 TRACE("(%p) %s %x %s\n",This
,debugstr_guid(rclsid
),langid
,debugstr_guid(guidProfiles
));
410 if (langid
!= This
->currentLanguage
) return E_INVALIDARG
;
412 if (get_active_textservice(rclsid
,NULL
))
414 TRACE("Already Active\n");
418 hr
= ITfInputProcessorProfiles_IsEnabledLanguageProfile(iface
, rclsid
,
419 langid
, guidProfiles
, &enabled
);
420 if (FAILED(hr
) || !enabled
)
422 TRACE("Not Enabled\n");
426 LanguageProfile
.clsid
= *rclsid
;
427 LanguageProfile
.langid
= langid
;
428 LanguageProfile
.guidProfile
= *guidProfiles
;
430 hr
= add_active_textservice(&LanguageProfile
);
435 static HRESULT WINAPI
InputProcessorProfiles_GetActiveLanguageProfile(
436 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID
*plangid
,
439 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
440 TF_LANGUAGEPROFILE profile
;
442 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(rclsid
),plangid
,pguidProfile
);
444 if (!rclsid
|| !plangid
|| !pguidProfile
)
447 if (get_active_textservice(rclsid
, &profile
))
449 *plangid
= profile
.langid
;
450 *pguidProfile
= profile
.guidProfile
;
455 *pguidProfile
= GUID_NULL
;
460 static HRESULT WINAPI
InputProcessorProfiles_GetLanguageProfileDescription(
461 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
462 REFGUID guidProfile
, BSTR
*pbstrProfile
)
464 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
465 FIXME("STUB:(%p)\n",This
);
469 static HRESULT WINAPI
InputProcessorProfiles_GetCurrentLanguage(
470 ITfInputProcessorProfiles
*iface
, LANGID
*plangid
)
472 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
473 TRACE("(%p) 0x%x\n",This
,This
->currentLanguage
);
478 *plangid
= This
->currentLanguage
;
483 static HRESULT WINAPI
InputProcessorProfiles_ChangeCurrentLanguage(
484 ITfInputProcessorProfiles
*iface
, LANGID langid
)
486 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
490 FIXME("STUB:(%p)\n",This
);
492 LIST_FOR_EACH(cursor
, &This
->LanguageProfileNotifySink
)
494 InputProcessorProfilesSink
* sink
= LIST_ENTRY(cursor
,InputProcessorProfilesSink
,entry
);
496 ITfLanguageProfileNotifySink_OnLanguageChange(sink
->interfaces
.pITfLanguageProfileNotifySink
, langid
, &accept
);
501 /* TODO: On successful language change call OnLanguageChanged sink */
505 static HRESULT WINAPI
InputProcessorProfiles_GetLanguageList(
506 ITfInputProcessorProfiles
*iface
, LANGID
**ppLangId
, ULONG
*pulCount
)
508 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
509 FIXME("Semi-STUB:(%p)\n",This
);
510 *ppLangId
= CoTaskMemAlloc(sizeof(LANGID
));
511 **ppLangId
= This
->currentLanguage
;
516 static HRESULT WINAPI
InputProcessorProfiles_EnumLanguageProfiles(
517 ITfInputProcessorProfiles
*iface
, LANGID langid
,
518 IEnumTfLanguageProfiles
**ppEnum
)
520 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
521 TRACE("(%p) %x %p\n",This
,langid
,ppEnum
);
522 return EnumTfLanguageProfiles_Constructor(langid
, ppEnum
);
525 static HRESULT WINAPI
InputProcessorProfiles_EnableLanguageProfile(
526 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
527 REFGUID guidProfile
, BOOL fEnable
)
529 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
536 TRACE("(%p) %s %x %s %i\n",This
, debugstr_guid(rclsid
), langid
, debugstr_guid(guidProfile
), fEnable
);
538 StringFromGUID2(rclsid
, buf
, 39);
539 StringFromGUID2(guidProfile
, buf2
, 39);
540 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
542 res
= RegOpenKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
546 RegSetValueExW(key
, szwEnable
, 0, REG_DWORD
, (LPBYTE
)&fEnable
, sizeof(DWORD
));
555 static HRESULT WINAPI
InputProcessorProfiles_IsEnabledLanguageProfile(
556 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
557 REFGUID guidProfile
, BOOL
*pfEnable
)
559 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
566 TRACE("(%p) %s, %i, %s, %p\n",This
,debugstr_guid(rclsid
),langid
,debugstr_guid(guidProfile
),pfEnable
);
571 StringFromGUID2(rclsid
, buf
, 39);
572 StringFromGUID2(guidProfile
, buf2
, 39);
573 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
575 res
= RegOpenKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
579 DWORD count
= sizeof(DWORD
);
580 res
= RegQueryValueExW(key
, szwEnable
, 0, NULL
, (LPBYTE
)pfEnable
, &count
);
584 if (res
) /* Try Default */
586 res
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
590 DWORD count
= sizeof(DWORD
);
591 res
= RegQueryValueExW(key
, szwEnable
, 0, NULL
, (LPBYTE
)pfEnable
, &count
);
602 static HRESULT WINAPI
InputProcessorProfiles_EnableLanguageProfileByDefault(
603 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
604 REFGUID guidProfile
, BOOL fEnable
)
606 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
613 TRACE("(%p) %s %x %s %i\n",This
,debugstr_guid(rclsid
),langid
,debugstr_guid(guidProfile
),fEnable
);
615 StringFromGUID2(rclsid
, buf
, 39);
616 StringFromGUID2(guidProfile
, buf2
, 39);
617 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
619 res
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
623 RegSetValueExW(key
, szwEnable
, 0, REG_DWORD
, (LPBYTE
)&fEnable
, sizeof(DWORD
));
632 static HRESULT WINAPI
InputProcessorProfiles_SubstituteKeyboardLayout(
633 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
634 REFGUID guidProfile
, HKL hKL
)
636 InputProcessorProfiles
*This
= impl_from_ITfInputProcessorProfiles(iface
);
637 FIXME("STUB:(%p)\n",This
);
641 static const ITfInputProcessorProfilesVtbl InputProcessorProfilesVtbl
=
643 InputProcessorProfiles_QueryInterface
,
644 InputProcessorProfiles_AddRef
,
645 InputProcessorProfiles_Release
,
646 InputProcessorProfiles_Register
,
647 InputProcessorProfiles_Unregister
,
648 InputProcessorProfiles_AddLanguageProfile
,
649 InputProcessorProfiles_RemoveLanguageProfile
,
650 InputProcessorProfiles_EnumInputProcessorInfo
,
651 InputProcessorProfiles_GetDefaultLanguageProfile
,
652 InputProcessorProfiles_SetDefaultLanguageProfile
,
653 InputProcessorProfiles_ActivateLanguageProfile
,
654 InputProcessorProfiles_GetActiveLanguageProfile
,
655 InputProcessorProfiles_GetLanguageProfileDescription
,
656 InputProcessorProfiles_GetCurrentLanguage
,
657 InputProcessorProfiles_ChangeCurrentLanguage
,
658 InputProcessorProfiles_GetLanguageList
,
659 InputProcessorProfiles_EnumLanguageProfiles
,
660 InputProcessorProfiles_EnableLanguageProfile
,
661 InputProcessorProfiles_IsEnabledLanguageProfile
,
662 InputProcessorProfiles_EnableLanguageProfileByDefault
,
663 InputProcessorProfiles_SubstituteKeyboardLayout
666 /*****************************************************
667 * ITfSource functions
668 *****************************************************/
669 static HRESULT WINAPI
IPPSource_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
671 InputProcessorProfiles
*This
= impl_from_ITfSource(iface
);
672 return ITfInputProcessorProfiles_QueryInterface(&This
->ITfInputProcessorProfiles_iface
, iid
, ppvOut
);
675 static ULONG WINAPI
IPPSource_AddRef(ITfSource
*iface
)
677 InputProcessorProfiles
*This
= impl_from_ITfSource(iface
);
678 return ITfInputProcessorProfiles_AddRef(&This
->ITfInputProcessorProfiles_iface
);
681 static ULONG WINAPI
IPPSource_Release(ITfSource
*iface
)
683 InputProcessorProfiles
*This
= impl_from_ITfSource(iface
);
684 return ITfInputProcessorProfiles_Release(&This
->ITfInputProcessorProfiles_iface
);
687 static HRESULT WINAPI
IPPSource_AdviseSink(ITfSource
*iface
,
688 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
690 InputProcessorProfiles
*This
= impl_from_ITfSource(iface
);
691 InputProcessorProfilesSink
*ipps
;
693 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(riid
),punk
,pdwCookie
);
695 if (!riid
|| !punk
|| !pdwCookie
)
698 if (IsEqualIID(riid
, &IID_ITfLanguageProfileNotifySink
))
700 ipps
= HeapAlloc(GetProcessHeap(),0,sizeof(InputProcessorProfilesSink
));
702 return E_OUTOFMEMORY
;
703 if (FAILED(IUnknown_QueryInterface(punk
, riid
, (LPVOID
*)&ipps
->interfaces
.pITfLanguageProfileNotifySink
)))
705 HeapFree(GetProcessHeap(),0,ipps
);
706 return CONNECT_E_CANNOTCONNECT
;
708 list_add_head(&This
->LanguageProfileNotifySink
,&ipps
->entry
);
709 *pdwCookie
= generate_Cookie(COOKIE_MAGIC_IPPSINK
, ipps
);
713 FIXME("(%p) Unhandled Sink: %s\n",This
,debugstr_guid(riid
));
717 TRACE("cookie %x\n",*pdwCookie
);
722 static HRESULT WINAPI
IPPSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
724 InputProcessorProfiles
*This
= impl_from_ITfSource(iface
);
725 InputProcessorProfilesSink
*sink
;
727 TRACE("(%p) %x\n",This
,pdwCookie
);
729 if (get_Cookie_magic(pdwCookie
)!=COOKIE_MAGIC_IPPSINK
)
732 sink
= remove_Cookie(pdwCookie
);
734 return CONNECT_E_NOCONNECTION
;
736 list_remove(&sink
->entry
);
742 static const ITfSourceVtbl InputProcessorProfilesSourceVtbl
=
744 IPPSource_QueryInterface
,
747 IPPSource_AdviseSink
,
748 IPPSource_UnadviseSink
,
751 HRESULT
InputProcessorProfiles_Constructor(IUnknown
*pUnkOuter
, IUnknown
**ppOut
)
753 InputProcessorProfiles
*This
;
755 return CLASS_E_NOAGGREGATION
;
757 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(InputProcessorProfiles
));
759 return E_OUTOFMEMORY
;
761 This
->ITfInputProcessorProfiles_iface
.lpVtbl
= &InputProcessorProfilesVtbl
;
762 This
->ITfSource_iface
.lpVtbl
= &InputProcessorProfilesSourceVtbl
;
764 This
->currentLanguage
= GetUserDefaultLCID();
766 list_init(&This
->LanguageProfileNotifySink
);
768 *ppOut
= (IUnknown
*)&This
->ITfInputProcessorProfiles_iface
;
769 TRACE("returning %p\n", *ppOut
);
773 /**************************************************
774 * IEnumGUID implementation for ITfInputProcessorProfiles::EnumInputProcessorInfo
775 **************************************************/
776 static void ProfilesEnumGuid_Destructor(ProfilesEnumGuid
*This
)
778 TRACE("destroying %p\n", This
);
779 RegCloseKey(This
->key
);
780 HeapFree(GetProcessHeap(),0,This
);
783 static HRESULT WINAPI
ProfilesEnumGuid_QueryInterface(IEnumGUID
*iface
, REFIID iid
, LPVOID
*ppvOut
)
785 ProfilesEnumGuid
*This
= impl_from_IEnumGUID(iface
);
788 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_IEnumGUID
))
790 *ppvOut
= &This
->IEnumGUID_iface
;
795 IEnumGUID_AddRef(iface
);
799 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
800 return E_NOINTERFACE
;
803 static ULONG WINAPI
ProfilesEnumGuid_AddRef(IEnumGUID
*iface
)
805 ProfilesEnumGuid
*This
= impl_from_IEnumGUID(iface
);
806 return InterlockedIncrement(&This
->refCount
);
809 static ULONG WINAPI
ProfilesEnumGuid_Release(IEnumGUID
*iface
)
811 ProfilesEnumGuid
*This
= impl_from_IEnumGUID(iface
);
814 ret
= InterlockedDecrement(&This
->refCount
);
816 ProfilesEnumGuid_Destructor(This
);
820 /*****************************************************
821 * IEnumGuid functions
822 *****************************************************/
823 static HRESULT WINAPI
ProfilesEnumGuid_Next( LPENUMGUID iface
,
824 ULONG celt
, GUID
*rgelt
, ULONG
*pceltFetched
)
826 ProfilesEnumGuid
*This
= impl_from_IEnumGUID(iface
);
829 TRACE("(%p)\n",This
);
831 if (rgelt
== NULL
) return E_POINTER
;
833 if (This
->key
) while (fetched
< celt
)
840 res
= RegEnumKeyExW(This
->key
, This
->next_index
, catid
, &cName
,
841 NULL
, NULL
, NULL
, NULL
);
842 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) break;
843 ++(This
->next_index
);
845 hr
= CLSIDFromString(catid
, rgelt
);
846 if (FAILED(hr
)) continue;
852 if (pceltFetched
) *pceltFetched
= fetched
;
853 return fetched
== celt
? S_OK
: S_FALSE
;
856 static HRESULT WINAPI
ProfilesEnumGuid_Skip( LPENUMGUID iface
, ULONG celt
)
858 ProfilesEnumGuid
*This
= impl_from_IEnumGUID(iface
);
859 TRACE("(%p)\n",This
);
861 This
->next_index
+= celt
;
865 static HRESULT WINAPI
ProfilesEnumGuid_Reset( LPENUMGUID iface
)
867 ProfilesEnumGuid
*This
= impl_from_IEnumGUID(iface
);
868 TRACE("(%p)\n",This
);
869 This
->next_index
= 0;
873 static HRESULT WINAPI
ProfilesEnumGuid_Clone( LPENUMGUID iface
,
876 ProfilesEnumGuid
*This
= impl_from_IEnumGUID(iface
);
879 TRACE("(%p)\n",This
);
881 if (ppenum
== NULL
) return E_POINTER
;
883 res
= ProfilesEnumGuid_Constructor(ppenum
);
886 ProfilesEnumGuid
*new_This
= impl_from_IEnumGUID(*ppenum
);
887 new_This
->next_index
= This
->next_index
;
892 static const IEnumGUIDVtbl EnumGUIDVtbl
=
894 ProfilesEnumGuid_QueryInterface
,
895 ProfilesEnumGuid_AddRef
,
896 ProfilesEnumGuid_Release
,
897 ProfilesEnumGuid_Next
,
898 ProfilesEnumGuid_Skip
,
899 ProfilesEnumGuid_Reset
,
900 ProfilesEnumGuid_Clone
903 static HRESULT
ProfilesEnumGuid_Constructor(IEnumGUID
**ppOut
)
905 ProfilesEnumGuid
*This
;
907 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ProfilesEnumGuid
));
909 return E_OUTOFMEMORY
;
911 This
->IEnumGUID_iface
.lpVtbl
= &EnumGUIDVtbl
;
914 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, szwSystemTIPKey
, 0, NULL
, 0,
915 KEY_READ
| KEY_WRITE
, NULL
, &This
->key
, NULL
) != ERROR_SUCCESS
)
917 HeapFree(GetProcessHeap(), 0, This
);
921 *ppOut
= &This
->IEnumGUID_iface
;
922 TRACE("returning %p\n", *ppOut
);
926 /**************************************************
927 * IEnumTfLanguageProfiles implementation
928 **************************************************/
929 static void EnumTfLanguageProfiles_Destructor(EnumTfLanguageProfiles
*This
)
931 TRACE("destroying %p\n", This
);
932 RegCloseKey(This
->tipkey
);
934 RegCloseKey(This
->langkey
);
935 ITfCategoryMgr_Release(This
->catmgr
);
936 HeapFree(GetProcessHeap(),0,This
);
939 static HRESULT WINAPI
EnumTfLanguageProfiles_QueryInterface(IEnumTfLanguageProfiles
*iface
, REFIID iid
, LPVOID
*ppvOut
)
941 EnumTfLanguageProfiles
*This
= impl_from_IEnumTfLanguageProfiles(iface
);
945 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_IEnumTfLanguageProfiles
))
947 *ppvOut
= &This
->IEnumTfLanguageProfiles_iface
;
952 IEnumTfLanguageProfiles_AddRef(iface
);
956 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
957 return E_NOINTERFACE
;
960 static ULONG WINAPI
EnumTfLanguageProfiles_AddRef(IEnumTfLanguageProfiles
*iface
)
962 EnumTfLanguageProfiles
*This
= impl_from_IEnumTfLanguageProfiles(iface
);
963 return InterlockedIncrement(&This
->refCount
);
966 static ULONG WINAPI
EnumTfLanguageProfiles_Release(IEnumTfLanguageProfiles
*iface
)
968 EnumTfLanguageProfiles
*This
= impl_from_IEnumTfLanguageProfiles(iface
);
971 ret
= InterlockedDecrement(&This
->refCount
);
973 EnumTfLanguageProfiles_Destructor(This
);
977 /*****************************************************
978 * IEnumGuid functions
979 *****************************************************/
980 static INT
next_LanguageProfile(EnumTfLanguageProfiles
*This
, CLSID clsid
, TF_LANGUAGEPROFILE
*tflp
)
988 static const WCHAR fmt
[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
990 if (This
->langkey
== NULL
)
992 sprintfW(fullkey
,fmt
,This
->szwCurrentClsid
,szwLngp
,This
->langid
);
993 res
= RegOpenKeyExW(This
->tipkey
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &This
->langkey
);
996 This
->langkey
= NULL
;
999 This
->lang_index
= 0;
1001 res
= RegEnumKeyExW(This
->langkey
, This
->lang_index
, profileid
, &cName
,
1002 NULL
, NULL
, NULL
, NULL
);
1003 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
)
1005 RegCloseKey(This
->langkey
);
1006 This
->langkey
= NULL
;
1009 ++(This
->lang_index
);
1013 static const GUID
* tipcats
[3] = { &GUID_TFCAT_TIP_KEYBOARD
,
1014 &GUID_TFCAT_TIP_SPEECH
,
1015 &GUID_TFCAT_TIP_HANDWRITING
};
1016 res
= CLSIDFromString(profileid
, &profile
);
1017 if (FAILED(res
)) return 0;
1019 tflp
->clsid
= clsid
;
1020 tflp
->langid
= This
->langid
;
1021 tflp
->fActive
= get_active_textservice(&clsid
, NULL
);
1022 tflp
->guidProfile
= profile
;
1023 if (ITfCategoryMgr_FindClosestCategory(This
->catmgr
, &clsid
,
1024 &tflp
->catid
, tipcats
, 3) != S_OK
)
1025 ITfCategoryMgr_FindClosestCategory(This
->catmgr
, &clsid
,
1026 &tflp
->catid
, NULL
, 0);
1032 static HRESULT WINAPI
EnumTfLanguageProfiles_Next(IEnumTfLanguageProfiles
*iface
,
1033 ULONG ulCount
, TF_LANGUAGEPROFILE
*pProfile
, ULONG
*pcFetch
)
1035 EnumTfLanguageProfiles
*This
= impl_from_IEnumTfLanguageProfiles(iface
);
1038 TRACE("(%p)\n",This
);
1040 if (pProfile
== NULL
) return E_POINTER
;
1042 if (This
->tipkey
) while (fetched
< ulCount
)
1049 res
= RegEnumKeyExW(This
->tipkey
, This
->tip_index
,
1050 This
->szwCurrentClsid
, &cName
, NULL
, NULL
, NULL
, NULL
);
1051 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) break;
1052 ++(This
->tip_index
);
1053 hr
= CLSIDFromString(This
->szwCurrentClsid
, &clsid
);
1054 if (FAILED(hr
)) continue;
1056 while ( fetched
< ulCount
)
1058 INT res
= next_LanguageProfile(This
, clsid
, pProfile
);
1071 if (pcFetch
) *pcFetch
= fetched
;
1072 return fetched
== ulCount
? S_OK
: S_FALSE
;
1075 static HRESULT WINAPI
EnumTfLanguageProfiles_Skip( IEnumTfLanguageProfiles
* iface
, ULONG celt
)
1077 EnumTfLanguageProfiles
*This
= impl_from_IEnumTfLanguageProfiles(iface
);
1078 FIXME("STUB (%p)\n",This
);
1082 static HRESULT WINAPI
EnumTfLanguageProfiles_Reset( IEnumTfLanguageProfiles
* iface
)
1084 EnumTfLanguageProfiles
*This
= impl_from_IEnumTfLanguageProfiles(iface
);
1085 TRACE("(%p)\n",This
);
1086 This
->tip_index
= 0;
1088 RegCloseKey(This
->langkey
);
1089 This
->langkey
= NULL
;
1090 This
->lang_index
= 0;
1094 static HRESULT WINAPI
EnumTfLanguageProfiles_Clone( IEnumTfLanguageProfiles
*iface
,
1095 IEnumTfLanguageProfiles
**ppenum
)
1097 EnumTfLanguageProfiles
*This
= impl_from_IEnumTfLanguageProfiles(iface
);
1100 TRACE("(%p)\n",This
);
1102 if (ppenum
== NULL
) return E_POINTER
;
1104 res
= EnumTfLanguageProfiles_Constructor(This
->langid
, ppenum
);
1107 EnumTfLanguageProfiles
*new_This
= (EnumTfLanguageProfiles
*)*ppenum
;
1108 new_This
->tip_index
= This
->tip_index
;
1109 lstrcpynW(new_This
->szwCurrentClsid
,This
->szwCurrentClsid
,39);
1114 static const WCHAR fmt
[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
1116 sprintfW(fullkey
,fmt
,This
->szwCurrentClsid
,szwLngp
,This
->langid
);
1117 res
= RegOpenKeyExW(new_This
->tipkey
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &This
->langkey
);
1118 new_This
->lang_index
= This
->lang_index
;
1124 static const IEnumTfLanguageProfilesVtbl EnumTfLanguageProfilesVtbl
=
1126 EnumTfLanguageProfiles_QueryInterface
,
1127 EnumTfLanguageProfiles_AddRef
,
1128 EnumTfLanguageProfiles_Release
,
1129 EnumTfLanguageProfiles_Clone
,
1130 EnumTfLanguageProfiles_Next
,
1131 EnumTfLanguageProfiles_Reset
,
1132 EnumTfLanguageProfiles_Skip
1135 static HRESULT
EnumTfLanguageProfiles_Constructor(LANGID langid
, IEnumTfLanguageProfiles
**ppOut
)
1138 EnumTfLanguageProfiles
*This
;
1140 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(EnumTfLanguageProfiles
));
1142 return E_OUTOFMEMORY
;
1144 This
->IEnumTfLanguageProfiles_iface
.lpVtbl
= &EnumTfLanguageProfilesVtbl
;
1146 This
->langid
= langid
;
1148 hr
= CategoryMgr_Constructor(NULL
,(IUnknown
**)&This
->catmgr
);
1151 HeapFree(GetProcessHeap(),0,This
);
1155 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, szwSystemTIPKey
, 0, NULL
, 0,
1156 KEY_READ
| KEY_WRITE
, NULL
, &This
->tipkey
, NULL
) != ERROR_SUCCESS
)
1158 HeapFree(GetProcessHeap(), 0, This
);
1162 *ppOut
= &This
->IEnumTfLanguageProfiles_iface
;
1163 TRACE("returning %p\n", *ppOut
);