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 #define WIN32_NO_STATUS
23 #define COM_NO_WINDOWS_H
31 #include <wine/debug.h>
35 //#include "winuser.h"
36 //#include "shlwapi.h"
37 //#include "winerror.h"
41 #include <wine/unicode.h>
42 #include <wine/list.h>
45 #include "msctf_internal.h"
47 WINE_DEFAULT_DEBUG_CHANNEL(msctf
);
49 static const WCHAR szwLngp
[] = {'L','a','n','g','u','a','g','e','P','r','o','f','i','l','e',0};
50 static const WCHAR szwEnable
[] = {'E','n','a','b','l','e',0};
51 static const WCHAR szwTipfmt
[] = {'%','s','\\','%','s',0};
52 static const WCHAR szwFullLangfmt
[] = {'%','s','\\','%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0};
54 static const WCHAR szwAssemblies
[] = {'A','s','s','e','m','b','l','i','e','s',0};
55 static const WCHAR szwDefault
[] = {'D','e','f','a','u','l','t',0};
56 static const WCHAR szwProfile
[] = {'P','r','o','f','i','l','e',0};
57 static const WCHAR szwDefaultFmt
[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0};
59 typedef struct tagInputProcessorProfilesSink
{
62 /* InputProcessorProfile Sinks */
64 ITfLanguageProfileNotifySink
*pITfLanguageProfileNotifySink
;
66 } InputProcessorProfilesSink
;
68 typedef struct tagInputProcessorProfiles
{
69 const ITfInputProcessorProfilesVtbl
*InputProcessorProfilesVtbl
;
70 const ITfSourceVtbl
*SourceVtbl
;
71 /* const ITfInputProcessorProfileMgrVtbl *InputProcessorProfileMgrVtbl; */
72 /* const ITfInputProcessorProfilesExVtbl *InputProcessorProfilesExVtbl; */
73 /* const ITfInputProcessorProfileSubstituteLayoutVtbl *InputProcessorProfileSubstituteLayoutVtbl; */
76 LANGID currentLanguage
;
78 struct list LanguageProfileNotifySink
;
79 } InputProcessorProfiles
;
81 typedef struct tagProfilesEnumGuid
{
82 const IEnumGUIDVtbl
*Vtbl
;
89 typedef struct tagEnumTfLanguageProfiles
{
90 const IEnumTfLanguageProfilesVtbl
*Vtbl
;
95 WCHAR szwCurrentClsid
[39];
101 ITfCategoryMgr
*catmgr
;
102 } EnumTfLanguageProfiles
;
104 static HRESULT
ProfilesEnumGuid_Constructor(IEnumGUID
**ppOut
);
105 static HRESULT
EnumTfLanguageProfiles_Constructor(LANGID langid
, IEnumTfLanguageProfiles
**ppOut
);
107 static inline InputProcessorProfiles
*impl_from_ITfSourceVtbl(ITfSource
*iface
)
109 return (InputProcessorProfiles
*)((char *)iface
- FIELD_OFFSET(InputProcessorProfiles
,SourceVtbl
));
112 static void free_sink(InputProcessorProfilesSink
*sink
)
114 IUnknown_Release(sink
->interfaces
.pIUnknown
);
115 HeapFree(GetProcessHeap(),0,sink
);
118 static void InputProcessorProfiles_Destructor(InputProcessorProfiles
*This
)
120 struct list
*cursor
, *cursor2
;
121 TRACE("destroying %p\n", This
);
124 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->LanguageProfileNotifySink
)
126 InputProcessorProfilesSink
* sink
= LIST_ENTRY(cursor
,InputProcessorProfilesSink
,entry
);
131 HeapFree(GetProcessHeap(),0,This
);
134 static void add_userkey( REFCLSID rclsid
, LANGID langid
,
141 DWORD disposition
= 0;
146 StringFromGUID2(rclsid
, buf
, 39);
147 StringFromGUID2(guidProfile
, buf2
, 39);
148 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
150 res
= RegCreateKeyExW(HKEY_CURRENT_USER
,fullkey
, 0, NULL
, 0,
151 KEY_READ
| KEY_WRITE
, NULL
, &key
, &disposition
);
153 if (!res
&& disposition
== REG_CREATED_NEW_KEY
)
156 RegSetValueExW(key
, szwEnable
, 0, REG_DWORD
, (LPBYTE
)&zero
, sizeof(DWORD
));
163 static HRESULT WINAPI
InputProcessorProfiles_QueryInterface(ITfInputProcessorProfiles
*iface
, REFIID iid
, LPVOID
*ppvOut
)
165 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
168 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfInputProcessorProfiles
))
172 else if (IsEqualIID(iid
, &IID_ITfSource
))
174 *ppvOut
= &This
->SourceVtbl
;
179 IUnknown_AddRef(iface
);
183 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
184 return E_NOINTERFACE
;
187 static ULONG WINAPI
InputProcessorProfiles_AddRef(ITfInputProcessorProfiles
*iface
)
189 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
190 return InterlockedIncrement(&This
->refCount
);
193 static ULONG WINAPI
InputProcessorProfiles_Release(ITfInputProcessorProfiles
*iface
)
195 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
198 ret
= InterlockedDecrement(&This
->refCount
);
200 InputProcessorProfiles_Destructor(This
);
204 /*****************************************************
205 * ITfInputProcessorProfiles functions
206 *****************************************************/
207 static HRESULT WINAPI
InputProcessorProfiles_Register(
208 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
)
210 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
215 TRACE("(%p) %s\n",This
,debugstr_guid(rclsid
));
217 StringFromGUID2(rclsid
, buf
, 39);
218 sprintfW(fullkey
,szwTipfmt
,szwSystemTIPKey
,buf
);
220 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,fullkey
, 0, NULL
, 0,
221 KEY_READ
| KEY_WRITE
, NULL
, &tipkey
, NULL
) != ERROR_SUCCESS
)
229 static HRESULT WINAPI
InputProcessorProfiles_Unregister(
230 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
)
234 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
236 TRACE("(%p) %s\n",This
,debugstr_guid(rclsid
));
238 StringFromGUID2(rclsid
, buf
, 39);
239 sprintfW(fullkey
,szwTipfmt
,szwSystemTIPKey
,buf
);
241 RegDeleteTreeW(HKEY_LOCAL_MACHINE
, fullkey
);
242 RegDeleteTreeW(HKEY_CURRENT_USER
, fullkey
);
247 static HRESULT WINAPI
InputProcessorProfiles_AddLanguageProfile(
248 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
,
249 LANGID langid
, REFGUID guidProfile
, const WCHAR
*pchDesc
,
250 ULONG cchDesc
, const WCHAR
*pchIconFile
, ULONG cchFile
,
257 DWORD disposition
= 0;
259 static const WCHAR fmt2
[] = {'%','s','\\','0','x','%','0','8','x','\\','%','s',0};
260 static const WCHAR desc
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
261 static const WCHAR icnf
[] = {'I','c','o','n','F','i','l','e',0};
262 static const WCHAR icni
[] = {'I','c','o','n','I','n','d','e','x',0};
264 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
266 TRACE("(%p) %s %x %s %s %s %i\n",This
,debugstr_guid(rclsid
), langid
,
267 debugstr_guid(guidProfile
), debugstr_wn(pchDesc
,cchDesc
),
268 debugstr_wn(pchIconFile
,cchFile
),uIconIndex
);
270 StringFromGUID2(rclsid
, buf
, 39);
271 sprintfW(fullkey
,szwTipfmt
,szwSystemTIPKey
,buf
);
273 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,fullkey
, 0, KEY_READ
| KEY_WRITE
,
274 &tipkey
) != ERROR_SUCCESS
)
277 StringFromGUID2(guidProfile
, buf
, 39);
278 sprintfW(fullkey
,fmt2
,szwLngp
,langid
,buf
);
280 res
= RegCreateKeyExW(tipkey
,fullkey
, 0, NULL
, 0, KEY_READ
| KEY_WRITE
,
281 NULL
, &fmtkey
, &disposition
);
286 RegSetValueExW(fmtkey
, desc
, 0, REG_SZ
, (const BYTE
*)pchDesc
, cchDesc
* sizeof(WCHAR
));
287 RegSetValueExW(fmtkey
, icnf
, 0, REG_SZ
, (const BYTE
*)pchIconFile
, cchFile
* sizeof(WCHAR
));
288 RegSetValueExW(fmtkey
, icni
, 0, REG_DWORD
, (LPBYTE
)&uIconIndex
, sizeof(DWORD
));
289 if (disposition
== REG_CREATED_NEW_KEY
)
290 RegSetValueExW(fmtkey
, szwEnable
, 0, REG_DWORD
, (LPBYTE
)&zero
, sizeof(DWORD
));
293 add_userkey(rclsid
, langid
, guidProfile
);
303 static HRESULT WINAPI
InputProcessorProfiles_RemoveLanguageProfile(
304 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
307 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
308 FIXME("STUB:(%p)\n",This
);
312 static HRESULT WINAPI
InputProcessorProfiles_EnumInputProcessorInfo(
313 ITfInputProcessorProfiles
*iface
, IEnumGUID
**ppEnum
)
315 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
316 TRACE("(%p) %p\n",This
,ppEnum
);
317 return ProfilesEnumGuid_Constructor(ppEnum
);
320 static HRESULT WINAPI
InputProcessorProfiles_GetDefaultLanguageProfile(
321 ITfInputProcessorProfiles
*iface
, LANGID langid
, REFGUID catid
,
322 CLSID
*pclsid
, GUID
*pguidProfile
)
329 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
331 TRACE("%p) %x %s %p %p\n",This
, langid
, debugstr_guid(catid
),pclsid
,pguidProfile
);
333 if (!catid
|| !pclsid
|| !pguidProfile
)
336 StringFromGUID2(catid
, buf
, 39);
337 sprintfW(fullkey
, szwDefaultFmt
, szwSystemCTFKey
, szwAssemblies
, langid
, buf
);
339 if (RegOpenKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, KEY_READ
| KEY_WRITE
,
340 &hkey
) != ERROR_SUCCESS
)
344 res
= RegQueryValueExW(hkey
, szwDefault
, 0, NULL
, (LPBYTE
)buf
, &count
);
345 if (res
!= ERROR_SUCCESS
)
350 CLSIDFromString(buf
,pclsid
);
352 res
= RegQueryValueExW(hkey
, szwProfile
, 0, NULL
, (LPBYTE
)buf
, &count
);
353 if (res
== ERROR_SUCCESS
)
354 CLSIDFromString(buf
,pguidProfile
);
361 static HRESULT WINAPI
InputProcessorProfiles_SetDefaultLanguageProfile(
362 ITfInputProcessorProfiles
*iface
, LANGID langid
, REFCLSID rclsid
,
363 REFGUID guidProfiles
)
370 ITfCategoryMgr
*catmgr
;
371 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
372 static const GUID
* tipcats
[3] = { &GUID_TFCAT_TIP_KEYBOARD
,
373 &GUID_TFCAT_TIP_SPEECH
,
374 &GUID_TFCAT_TIP_HANDWRITING
};
376 TRACE("%p) %x %s %s\n",This
, langid
, debugstr_guid(rclsid
),debugstr_guid(guidProfiles
));
378 if (!rclsid
|| !guidProfiles
)
381 hr
= CategoryMgr_Constructor(NULL
,(IUnknown
**)&catmgr
);
386 if (ITfCategoryMgr_FindClosestCategory(catmgr
, rclsid
,
387 &catid
, tipcats
, 3) != S_OK
)
388 hr
= ITfCategoryMgr_FindClosestCategory(catmgr
, rclsid
,
390 ITfCategoryMgr_Release(catmgr
);
395 StringFromGUID2(&catid
, buf
, 39);
396 sprintfW(fullkey
, szwDefaultFmt
, szwSystemCTFKey
, szwAssemblies
, langid
, buf
);
398 if (RegCreateKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, NULL
, 0, KEY_READ
| KEY_WRITE
,
399 NULL
, &hkey
, NULL
) != ERROR_SUCCESS
)
402 StringFromGUID2(rclsid
, buf
, 39);
403 RegSetValueExW(hkey
, szwDefault
, 0, REG_SZ
, (LPBYTE
)buf
, sizeof(buf
));
404 StringFromGUID2(guidProfiles
, buf
, 39);
405 RegSetValueExW(hkey
, szwProfile
, 0, REG_SZ
, (LPBYTE
)buf
, sizeof(buf
));
411 static HRESULT WINAPI
InputProcessorProfiles_ActivateLanguageProfile(
412 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
413 REFGUID guidProfiles
)
417 TF_LANGUAGEPROFILE LanguageProfile
;
418 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
420 TRACE("(%p) %s %x %s\n",This
,debugstr_guid(rclsid
),langid
,debugstr_guid(guidProfiles
));
422 if (langid
!= This
->currentLanguage
) return E_INVALIDARG
;
424 if (get_active_textservice(rclsid
,NULL
))
426 TRACE("Already Active\n");
430 hr
= ITfInputProcessorProfiles_IsEnabledLanguageProfile(iface
, rclsid
,
431 langid
, guidProfiles
, &enabled
);
432 if (FAILED(hr
) || !enabled
)
434 TRACE("Not Enabled\n");
438 LanguageProfile
.clsid
= *rclsid
;
439 LanguageProfile
.langid
= langid
;
440 LanguageProfile
.guidProfile
= *guidProfiles
;
442 hr
= add_active_textservice(&LanguageProfile
);
447 static HRESULT WINAPI
InputProcessorProfiles_GetActiveLanguageProfile(
448 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID
*plangid
,
451 TF_LANGUAGEPROFILE profile
;
452 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
454 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(rclsid
),plangid
,pguidProfile
);
456 if (!rclsid
|| !plangid
|| !pguidProfile
)
459 if (get_active_textservice(rclsid
, &profile
))
461 *plangid
= profile
.langid
;
462 *pguidProfile
= profile
.guidProfile
;
467 *pguidProfile
= GUID_NULL
;
472 static HRESULT WINAPI
InputProcessorProfiles_GetLanguageProfileDescription(
473 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
474 REFGUID guidProfile
, BSTR
*pbstrProfile
)
476 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
477 FIXME("STUB:(%p)\n",This
);
481 static HRESULT WINAPI
InputProcessorProfiles_GetCurrentLanguage(
482 ITfInputProcessorProfiles
*iface
, LANGID
*plangid
)
484 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
485 TRACE("(%p) 0x%x\n",This
,This
->currentLanguage
);
490 *plangid
= This
->currentLanguage
;
495 static HRESULT WINAPI
InputProcessorProfiles_ChangeCurrentLanguage(
496 ITfInputProcessorProfiles
*iface
, LANGID langid
)
499 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
502 FIXME("STUB:(%p)\n",This
);
504 LIST_FOR_EACH(cursor
, &This
->LanguageProfileNotifySink
)
506 InputProcessorProfilesSink
* sink
= LIST_ENTRY(cursor
,InputProcessorProfilesSink
,entry
);
508 ITfLanguageProfileNotifySink_OnLanguageChange(sink
->interfaces
.pITfLanguageProfileNotifySink
, langid
, &accept
);
513 /* TODO: On successful language change call OnLanguageChanged sink */
517 static HRESULT WINAPI
InputProcessorProfiles_GetLanguageList(
518 ITfInputProcessorProfiles
*iface
, LANGID
**ppLangId
, ULONG
*pulCount
)
520 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
521 FIXME("Semi-STUB:(%p)\n",This
);
522 *ppLangId
= CoTaskMemAlloc(sizeof(LANGID
));
523 **ppLangId
= This
->currentLanguage
;
528 static HRESULT WINAPI
InputProcessorProfiles_EnumLanguageProfiles(
529 ITfInputProcessorProfiles
*iface
, LANGID langid
,
530 IEnumTfLanguageProfiles
**ppEnum
)
532 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
533 TRACE("(%p) %x %p\n",This
,langid
,ppEnum
);
534 return EnumTfLanguageProfiles_Constructor(langid
, ppEnum
);
537 static HRESULT WINAPI
InputProcessorProfiles_EnableLanguageProfile(
538 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
539 REFGUID guidProfile
, BOOL fEnable
)
547 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
548 TRACE("(%p) %s %x %s %i\n",This
, debugstr_guid(rclsid
), langid
, debugstr_guid(guidProfile
), fEnable
);
550 StringFromGUID2(rclsid
, buf
, 39);
551 StringFromGUID2(guidProfile
, buf2
, 39);
552 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
554 res
= RegOpenKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
558 RegSetValueExW(key
, szwEnable
, 0, REG_DWORD
, (LPBYTE
)&fEnable
, sizeof(DWORD
));
567 static HRESULT WINAPI
InputProcessorProfiles_IsEnabledLanguageProfile(
568 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
569 REFGUID guidProfile
, BOOL
*pfEnable
)
577 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
578 TRACE("(%p) %s, %i, %s, %p\n",This
,debugstr_guid(rclsid
),langid
,debugstr_guid(guidProfile
),pfEnable
);
583 StringFromGUID2(rclsid
, buf
, 39);
584 StringFromGUID2(guidProfile
, buf2
, 39);
585 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
587 res
= RegOpenKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
591 DWORD count
= sizeof(DWORD
);
592 res
= RegQueryValueExW(key
, szwEnable
, 0, NULL
, (LPBYTE
)pfEnable
, &count
);
596 if (res
) /* Try Default */
598 res
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
602 DWORD count
= sizeof(DWORD
);
603 res
= RegQueryValueExW(key
, szwEnable
, 0, NULL
, (LPBYTE
)pfEnable
, &count
);
614 static HRESULT WINAPI
InputProcessorProfiles_EnableLanguageProfileByDefault(
615 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
616 REFGUID guidProfile
, BOOL fEnable
)
624 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
625 TRACE("(%p) %s %x %s %i\n",This
,debugstr_guid(rclsid
),langid
,debugstr_guid(guidProfile
),fEnable
);
627 StringFromGUID2(rclsid
, buf
, 39);
628 StringFromGUID2(guidProfile
, buf2
, 39);
629 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
631 res
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
635 RegSetValueExW(key
, szwEnable
, 0, REG_DWORD
, (LPBYTE
)&fEnable
, sizeof(DWORD
));
644 static HRESULT WINAPI
InputProcessorProfiles_SubstituteKeyboardLayout(
645 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
646 REFGUID guidProfile
, HKL hKL
)
648 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
649 FIXME("STUB:(%p)\n",This
);
654 static const ITfInputProcessorProfilesVtbl InputProcessorProfiles_InputProcessorProfilesVtbl
=
656 InputProcessorProfiles_QueryInterface
,
657 InputProcessorProfiles_AddRef
,
658 InputProcessorProfiles_Release
,
660 InputProcessorProfiles_Register
,
661 InputProcessorProfiles_Unregister
,
662 InputProcessorProfiles_AddLanguageProfile
,
663 InputProcessorProfiles_RemoveLanguageProfile
,
664 InputProcessorProfiles_EnumInputProcessorInfo
,
665 InputProcessorProfiles_GetDefaultLanguageProfile
,
666 InputProcessorProfiles_SetDefaultLanguageProfile
,
667 InputProcessorProfiles_ActivateLanguageProfile
,
668 InputProcessorProfiles_GetActiveLanguageProfile
,
669 InputProcessorProfiles_GetLanguageProfileDescription
,
670 InputProcessorProfiles_GetCurrentLanguage
,
671 InputProcessorProfiles_ChangeCurrentLanguage
,
672 InputProcessorProfiles_GetLanguageList
,
673 InputProcessorProfiles_EnumLanguageProfiles
,
674 InputProcessorProfiles_EnableLanguageProfile
,
675 InputProcessorProfiles_IsEnabledLanguageProfile
,
676 InputProcessorProfiles_EnableLanguageProfileByDefault
,
677 InputProcessorProfiles_SubstituteKeyboardLayout
680 /*****************************************************
681 * ITfSource functions
682 *****************************************************/
683 static HRESULT WINAPI
IPPSource_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
685 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
686 return InputProcessorProfiles_QueryInterface((ITfInputProcessorProfiles
*)This
, iid
, *ppvOut
);
689 static ULONG WINAPI
IPPSource_AddRef(ITfSource
*iface
)
691 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
692 return InputProcessorProfiles_AddRef((ITfInputProcessorProfiles
*)This
);
695 static ULONG WINAPI
IPPSource_Release(ITfSource
*iface
)
697 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
698 return InputProcessorProfiles_Release((ITfInputProcessorProfiles
*)This
);
701 static HRESULT WINAPI
IPPSource_AdviseSink(ITfSource
*iface
,
702 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
704 InputProcessorProfilesSink
*ipps
;
705 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
707 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(riid
),punk
,pdwCookie
);
709 if (!riid
|| !punk
|| !pdwCookie
)
712 if (IsEqualIID(riid
, &IID_ITfLanguageProfileNotifySink
))
714 ipps
= HeapAlloc(GetProcessHeap(),0,sizeof(InputProcessorProfilesSink
));
716 return E_OUTOFMEMORY
;
717 if (FAILED(IUnknown_QueryInterface(punk
, riid
, (LPVOID
*)&ipps
->interfaces
.pITfLanguageProfileNotifySink
)))
719 HeapFree(GetProcessHeap(),0,ipps
);
720 return CONNECT_E_CANNOTCONNECT
;
722 list_add_head(&This
->LanguageProfileNotifySink
,&ipps
->entry
);
723 *pdwCookie
= generate_Cookie(COOKIE_MAGIC_IPPSINK
, ipps
);
727 FIXME("(%p) Unhandled Sink: %s\n",This
,debugstr_guid(riid
));
731 TRACE("cookie %x\n",*pdwCookie
);
736 static HRESULT WINAPI
IPPSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
738 InputProcessorProfilesSink
*sink
;
739 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
741 TRACE("(%p) %x\n",This
,pdwCookie
);
743 if (get_Cookie_magic(pdwCookie
)!=COOKIE_MAGIC_IPPSINK
)
746 sink
= (InputProcessorProfilesSink
*)remove_Cookie(pdwCookie
);
748 return CONNECT_E_NOCONNECTION
;
750 list_remove(&sink
->entry
);
756 static const ITfSourceVtbl InputProcessorProfiles_SourceVtbl
=
758 IPPSource_QueryInterface
,
762 IPPSource_AdviseSink
,
763 IPPSource_UnadviseSink
,
766 HRESULT
InputProcessorProfiles_Constructor(IUnknown
*pUnkOuter
, IUnknown
**ppOut
)
768 InputProcessorProfiles
*This
;
770 return CLASS_E_NOAGGREGATION
;
772 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(InputProcessorProfiles
));
774 return E_OUTOFMEMORY
;
776 This
->InputProcessorProfilesVtbl
= &InputProcessorProfiles_InputProcessorProfilesVtbl
;
777 This
->SourceVtbl
= &InputProcessorProfiles_SourceVtbl
;
779 This
->currentLanguage
= GetUserDefaultLCID();
781 list_init(&This
->LanguageProfileNotifySink
);
783 TRACE("returning %p\n", This
);
784 *ppOut
= (IUnknown
*)This
;
788 /**************************************************
789 * IEnumGUID implementation for ITfInputProcessorProfiles::EnumInputProcessorInfo
790 **************************************************/
791 static void ProfilesEnumGuid_Destructor(ProfilesEnumGuid
*This
)
793 TRACE("destroying %p\n", This
);
794 RegCloseKey(This
->key
);
795 HeapFree(GetProcessHeap(),0,This
);
798 static HRESULT WINAPI
ProfilesEnumGuid_QueryInterface(IEnumGUID
*iface
, REFIID iid
, LPVOID
*ppvOut
)
800 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
803 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_IEnumGUID
))
810 IUnknown_AddRef(iface
);
814 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
815 return E_NOINTERFACE
;
818 static ULONG WINAPI
ProfilesEnumGuid_AddRef(IEnumGUID
*iface
)
820 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
821 return InterlockedIncrement(&This
->refCount
);
824 static ULONG WINAPI
ProfilesEnumGuid_Release(IEnumGUID
*iface
)
826 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
829 ret
= InterlockedDecrement(&This
->refCount
);
831 ProfilesEnumGuid_Destructor(This
);
835 /*****************************************************
836 * IEnumGuid functions
837 *****************************************************/
838 static HRESULT WINAPI
ProfilesEnumGuid_Next( LPENUMGUID iface
,
839 ULONG celt
, GUID
*rgelt
, ULONG
*pceltFetched
)
841 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
844 TRACE("(%p)\n",This
);
846 if (rgelt
== NULL
) return E_POINTER
;
848 if (This
->key
) while (fetched
< celt
)
855 res
= RegEnumKeyExW(This
->key
, This
->next_index
, catid
, &cName
,
856 NULL
, NULL
, NULL
, NULL
);
857 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) break;
858 ++(This
->next_index
);
860 hr
= CLSIDFromString(catid
, rgelt
);
861 if (FAILED(hr
)) continue;
867 if (pceltFetched
) *pceltFetched
= fetched
;
868 return fetched
== celt
? S_OK
: S_FALSE
;
871 static HRESULT WINAPI
ProfilesEnumGuid_Skip( LPENUMGUID iface
, ULONG celt
)
873 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
874 TRACE("(%p)\n",This
);
876 This
->next_index
+= celt
;
880 static HRESULT WINAPI
ProfilesEnumGuid_Reset( LPENUMGUID iface
)
882 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
883 TRACE("(%p)\n",This
);
884 This
->next_index
= 0;
888 static HRESULT WINAPI
ProfilesEnumGuid_Clone( LPENUMGUID iface
,
891 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
894 TRACE("(%p)\n",This
);
896 if (ppenum
== NULL
) return E_POINTER
;
898 res
= ProfilesEnumGuid_Constructor(ppenum
);
901 ProfilesEnumGuid
*new_This
= (ProfilesEnumGuid
*)*ppenum
;
902 new_This
->next_index
= This
->next_index
;
907 static const IEnumGUIDVtbl IEnumGUID_Vtbl
={
908 ProfilesEnumGuid_QueryInterface
,
909 ProfilesEnumGuid_AddRef
,
910 ProfilesEnumGuid_Release
,
912 ProfilesEnumGuid_Next
,
913 ProfilesEnumGuid_Skip
,
914 ProfilesEnumGuid_Reset
,
915 ProfilesEnumGuid_Clone
918 static HRESULT
ProfilesEnumGuid_Constructor(IEnumGUID
**ppOut
)
920 ProfilesEnumGuid
*This
;
922 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ProfilesEnumGuid
));
924 return E_OUTOFMEMORY
;
926 This
->Vtbl
= &IEnumGUID_Vtbl
;
929 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, szwSystemTIPKey
, 0, NULL
, 0,
930 KEY_READ
| KEY_WRITE
, NULL
, &This
->key
, NULL
) != ERROR_SUCCESS
)
932 HeapFree(GetProcessHeap(), 0, This
);
936 TRACE("returning %p\n", This
);
937 *ppOut
= (IEnumGUID
*)This
;
941 /**************************************************
942 * IEnumTfLanguageProfiles implementation
943 **************************************************/
944 static void EnumTfLanguageProfiles_Destructor(EnumTfLanguageProfiles
*This
)
946 TRACE("destroying %p\n", This
);
947 RegCloseKey(This
->tipkey
);
949 RegCloseKey(This
->langkey
);
950 ITfCategoryMgr_Release(This
->catmgr
);
951 HeapFree(GetProcessHeap(),0,This
);
954 static HRESULT WINAPI
EnumTfLanguageProfiles_QueryInterface(IEnumTfLanguageProfiles
*iface
, REFIID iid
, LPVOID
*ppvOut
)
956 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
959 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_IEnumTfLanguageProfiles
))
966 IUnknown_AddRef(iface
);
970 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
971 return E_NOINTERFACE
;
974 static ULONG WINAPI
EnumTfLanguageProfiles_AddRef(IEnumTfLanguageProfiles
*iface
)
976 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
977 return InterlockedIncrement(&This
->refCount
);
980 static ULONG WINAPI
EnumTfLanguageProfiles_Release(IEnumTfLanguageProfiles
*iface
)
982 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
985 ret
= InterlockedDecrement(&This
->refCount
);
987 EnumTfLanguageProfiles_Destructor(This
);
991 /*****************************************************
992 * IEnumGuid functions
993 *****************************************************/
994 static INT
next_LanguageProfile(EnumTfLanguageProfiles
*This
, CLSID clsid
, TF_LANGUAGEPROFILE
*tflp
)
1002 static const WCHAR fmt
[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
1004 if (This
->langkey
== NULL
)
1006 sprintfW(fullkey
,fmt
,This
->szwCurrentClsid
,szwLngp
,This
->langid
);
1007 res
= RegOpenKeyExW(This
->tipkey
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &This
->langkey
);
1010 This
->langkey
= NULL
;
1013 This
->lang_index
= 0;
1015 res
= RegEnumKeyExW(This
->langkey
, This
->lang_index
, profileid
, &cName
,
1016 NULL
, NULL
, NULL
, NULL
);
1017 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
)
1019 RegCloseKey(This
->langkey
);
1020 This
->langkey
= NULL
;
1023 ++(This
->lang_index
);
1027 static const GUID
* tipcats
[3] = { &GUID_TFCAT_TIP_KEYBOARD
,
1028 &GUID_TFCAT_TIP_SPEECH
,
1029 &GUID_TFCAT_TIP_HANDWRITING
};
1030 res
= CLSIDFromString(profileid
, &profile
);
1031 if (FAILED(res
)) return 0;
1033 tflp
->clsid
= clsid
;
1034 tflp
->langid
= This
->langid
;
1035 tflp
->fActive
= get_active_textservice(&clsid
, NULL
);
1036 tflp
->guidProfile
= profile
;
1037 if (ITfCategoryMgr_FindClosestCategory(This
->catmgr
, &clsid
,
1038 &tflp
->catid
, tipcats
, 3) != S_OK
)
1039 ITfCategoryMgr_FindClosestCategory(This
->catmgr
, &clsid
,
1040 &tflp
->catid
, NULL
, 0);
1046 static HRESULT WINAPI
EnumTfLanguageProfiles_Next(IEnumTfLanguageProfiles
*iface
,
1047 ULONG ulCount
, TF_LANGUAGEPROFILE
*pProfile
, ULONG
*pcFetch
)
1049 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
1052 TRACE("(%p)\n",This
);
1054 if (pProfile
== NULL
) return E_POINTER
;
1056 if (This
->tipkey
) while (fetched
< ulCount
)
1063 res
= RegEnumKeyExW(This
->tipkey
, This
->tip_index
,
1064 This
->szwCurrentClsid
, &cName
, NULL
, NULL
, NULL
, NULL
);
1065 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) break;
1066 ++(This
->tip_index
);
1067 hr
= CLSIDFromString(This
->szwCurrentClsid
, &clsid
);
1068 if (FAILED(hr
)) continue;
1070 while ( fetched
< ulCount
)
1072 INT res
= next_LanguageProfile(This
, clsid
, pProfile
);
1085 if (pcFetch
) *pcFetch
= fetched
;
1086 return fetched
== ulCount
? S_OK
: S_FALSE
;
1089 static HRESULT WINAPI
EnumTfLanguageProfiles_Skip( IEnumTfLanguageProfiles
* iface
, ULONG celt
)
1091 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
1092 FIXME("STUB (%p)\n",This
);
1096 static HRESULT WINAPI
EnumTfLanguageProfiles_Reset( IEnumTfLanguageProfiles
* iface
)
1098 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
1099 TRACE("(%p)\n",This
);
1100 This
->tip_index
= 0;
1102 RegCloseKey(This
->langkey
);
1103 This
->langkey
= NULL
;
1104 This
->lang_index
= 0;
1108 static HRESULT WINAPI
EnumTfLanguageProfiles_Clone( IEnumTfLanguageProfiles
*iface
,
1109 IEnumTfLanguageProfiles
**ppenum
)
1111 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
1114 TRACE("(%p)\n",This
);
1116 if (ppenum
== NULL
) return E_POINTER
;
1118 res
= EnumTfLanguageProfiles_Constructor(This
->langid
, ppenum
);
1121 EnumTfLanguageProfiles
*new_This
= (EnumTfLanguageProfiles
*)*ppenum
;
1122 new_This
->tip_index
= This
->tip_index
;
1123 lstrcpynW(new_This
->szwCurrentClsid
,This
->szwCurrentClsid
,39);
1128 static const WCHAR fmt
[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
1130 sprintfW(fullkey
,fmt
,This
->szwCurrentClsid
,szwLngp
,This
->langid
);
1131 res
= RegOpenKeyExW(new_This
->tipkey
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &This
->langkey
);
1132 new_This
->lang_index
= This
->lang_index
;
1138 static const IEnumTfLanguageProfilesVtbl IEnumTfLanguageProfiles_Vtbl
={
1139 EnumTfLanguageProfiles_QueryInterface
,
1140 EnumTfLanguageProfiles_AddRef
,
1141 EnumTfLanguageProfiles_Release
,
1143 EnumTfLanguageProfiles_Clone
,
1144 EnumTfLanguageProfiles_Next
,
1145 EnumTfLanguageProfiles_Reset
,
1146 EnumTfLanguageProfiles_Skip
1149 static HRESULT
EnumTfLanguageProfiles_Constructor(LANGID langid
, IEnumTfLanguageProfiles
**ppOut
)
1152 EnumTfLanguageProfiles
*This
;
1154 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(EnumTfLanguageProfiles
));
1156 return E_OUTOFMEMORY
;
1158 This
->Vtbl
= &IEnumTfLanguageProfiles_Vtbl
;
1160 This
->langid
= langid
;
1162 hr
= CategoryMgr_Constructor(NULL
,(IUnknown
**)&This
->catmgr
);
1165 HeapFree(GetProcessHeap(),0,This
);
1169 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, szwSystemTIPKey
, 0, NULL
, 0,
1170 KEY_READ
| KEY_WRITE
, NULL
, &This
->tipkey
, NULL
) != ERROR_SUCCESS
)
1172 HeapFree(GetProcessHeap(), 0, This
);
1176 TRACE("returning %p\n", This
);
1177 *ppOut
= (IEnumTfLanguageProfiles
*)This
;