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 szwEnable
[] = {'E','n','a','b','l','e',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 static const WCHAR szwAssemblies
[] = {'A','s','s','e','m','b','l','i','e','s',0};
51 static const WCHAR szwDefault
[] = {'D','e','f','a','u','l','t',0};
52 static const WCHAR szwProfile
[] = {'P','r','o','f','i','l','e',0};
53 static const WCHAR szwDefaultFmt
[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0};
55 typedef struct tagInputProcessorProfilesSink
{
58 /* InputProcessorProfile Sinks */
60 ITfLanguageProfileNotifySink
*pITfLanguageProfileNotifySink
;
62 } InputProcessorProfilesSink
;
64 typedef struct tagInputProcessorProfiles
{
65 const ITfInputProcessorProfilesVtbl
*InputProcessorProfilesVtbl
;
66 const ITfSourceVtbl
*SourceVtbl
;
67 /* const ITfInputProcessorProfileMgrVtbl *InputProcessorProfileMgrVtbl; */
68 /* const ITfInputProcessorProfilesExVtbl *InputProcessorProfilesExVtbl; */
69 /* const ITfInputProcessorProfileSubstituteLayoutVtbl *InputProcessorProfileSubstituteLayoutVtbl; */
72 LANGID currentLanguage
;
74 struct list LanguageProfileNotifySink
;
75 } InputProcessorProfiles
;
77 typedef struct tagProfilesEnumGuid
{
78 const IEnumGUIDVtbl
*Vtbl
;
85 typedef struct tagEnumTfLanguageProfiles
{
86 const IEnumTfLanguageProfilesVtbl
*Vtbl
;
91 WCHAR szwCurrentClsid
[39];
97 ITfCategoryMgr
*catmgr
;
98 } EnumTfLanguageProfiles
;
100 static HRESULT
ProfilesEnumGuid_Constructor(IEnumGUID
**ppOut
);
101 static HRESULT
EnumTfLanguageProfiles_Constructor(LANGID langid
, IEnumTfLanguageProfiles
**ppOut
);
103 static inline InputProcessorProfiles
*impl_from_ITfSourceVtbl(ITfSource
*iface
)
105 return (InputProcessorProfiles
*)((char *)iface
- FIELD_OFFSET(InputProcessorProfiles
,SourceVtbl
));
108 static void free_sink(InputProcessorProfilesSink
*sink
)
110 IUnknown_Release(sink
->interfaces
.pIUnknown
);
111 HeapFree(GetProcessHeap(),0,sink
);
114 static void InputProcessorProfiles_Destructor(InputProcessorProfiles
*This
)
116 struct list
*cursor
, *cursor2
;
117 TRACE("destroying %p\n", This
);
120 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->LanguageProfileNotifySink
)
122 InputProcessorProfilesSink
* sink
= LIST_ENTRY(cursor
,InputProcessorProfilesSink
,entry
);
127 HeapFree(GetProcessHeap(),0,This
);
130 static void add_userkey( REFCLSID rclsid
, LANGID langid
,
137 DWORD disposition
= 0;
142 StringFromGUID2(rclsid
, buf
, 39);
143 StringFromGUID2(guidProfile
, buf2
, 39);
144 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
146 res
= RegCreateKeyExW(HKEY_CURRENT_USER
,fullkey
, 0, NULL
, 0,
147 KEY_READ
| KEY_WRITE
, NULL
, &key
, &disposition
);
149 if (!res
&& disposition
== REG_CREATED_NEW_KEY
)
152 RegSetValueExW(key
, szwEnable
, 0, REG_DWORD
, (LPBYTE
)&zero
, sizeof(DWORD
));
159 static HRESULT WINAPI
InputProcessorProfiles_QueryInterface(ITfInputProcessorProfiles
*iface
, REFIID iid
, LPVOID
*ppvOut
)
161 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
164 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfInputProcessorProfiles
))
168 else if (IsEqualIID(iid
, &IID_ITfSource
))
170 *ppvOut
= &This
->SourceVtbl
;
175 ITfInputProcessorProfiles_AddRef(iface
);
179 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
180 return E_NOINTERFACE
;
183 static ULONG WINAPI
InputProcessorProfiles_AddRef(ITfInputProcessorProfiles
*iface
)
185 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
186 return InterlockedIncrement(&This
->refCount
);
189 static ULONG WINAPI
InputProcessorProfiles_Release(ITfInputProcessorProfiles
*iface
)
191 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
194 ret
= InterlockedDecrement(&This
->refCount
);
196 InputProcessorProfiles_Destructor(This
);
200 /*****************************************************
201 * ITfInputProcessorProfiles functions
202 *****************************************************/
203 static HRESULT WINAPI
InputProcessorProfiles_Register(
204 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
)
206 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
211 TRACE("(%p) %s\n",This
,debugstr_guid(rclsid
));
213 StringFromGUID2(rclsid
, buf
, 39);
214 sprintfW(fullkey
,szwTipfmt
,szwSystemTIPKey
,buf
);
216 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,fullkey
, 0, NULL
, 0,
217 KEY_READ
| KEY_WRITE
, NULL
, &tipkey
, NULL
) != ERROR_SUCCESS
)
225 static HRESULT WINAPI
InputProcessorProfiles_Unregister(
226 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
)
230 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
232 TRACE("(%p) %s\n",This
,debugstr_guid(rclsid
));
234 StringFromGUID2(rclsid
, buf
, 39);
235 sprintfW(fullkey
,szwTipfmt
,szwSystemTIPKey
,buf
);
237 RegDeleteTreeW(HKEY_LOCAL_MACHINE
, fullkey
);
238 RegDeleteTreeW(HKEY_CURRENT_USER
, fullkey
);
243 static HRESULT WINAPI
InputProcessorProfiles_AddLanguageProfile(
244 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
,
245 LANGID langid
, REFGUID guidProfile
, const WCHAR
*pchDesc
,
246 ULONG cchDesc
, const WCHAR
*pchIconFile
, ULONG cchFile
,
253 DWORD disposition
= 0;
255 static const WCHAR fmt2
[] = {'%','s','\\','0','x','%','0','8','x','\\','%','s',0};
256 static const WCHAR desc
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
257 static const WCHAR icnf
[] = {'I','c','o','n','F','i','l','e',0};
258 static const WCHAR icni
[] = {'I','c','o','n','I','n','d','e','x',0};
260 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
262 TRACE("(%p) %s %x %s %s %s %i\n",This
,debugstr_guid(rclsid
), langid
,
263 debugstr_guid(guidProfile
), debugstr_wn(pchDesc
,cchDesc
),
264 debugstr_wn(pchIconFile
,cchFile
),uIconIndex
);
266 StringFromGUID2(rclsid
, buf
, 39);
267 sprintfW(fullkey
,szwTipfmt
,szwSystemTIPKey
,buf
);
269 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,fullkey
, 0, KEY_READ
| KEY_WRITE
,
270 &tipkey
) != ERROR_SUCCESS
)
273 StringFromGUID2(guidProfile
, buf
, 39);
274 sprintfW(fullkey
,fmt2
,szwLngp
,langid
,buf
);
276 res
= RegCreateKeyExW(tipkey
,fullkey
, 0, NULL
, 0, KEY_READ
| KEY_WRITE
,
277 NULL
, &fmtkey
, &disposition
);
282 RegSetValueExW(fmtkey
, desc
, 0, REG_SZ
, (const BYTE
*)pchDesc
, cchDesc
* sizeof(WCHAR
));
283 RegSetValueExW(fmtkey
, icnf
, 0, REG_SZ
, (const BYTE
*)pchIconFile
, cchFile
* sizeof(WCHAR
));
284 RegSetValueExW(fmtkey
, icni
, 0, REG_DWORD
, (LPBYTE
)&uIconIndex
, sizeof(DWORD
));
285 if (disposition
== REG_CREATED_NEW_KEY
)
286 RegSetValueExW(fmtkey
, szwEnable
, 0, REG_DWORD
, (LPBYTE
)&zero
, sizeof(DWORD
));
289 add_userkey(rclsid
, langid
, guidProfile
);
299 static HRESULT WINAPI
InputProcessorProfiles_RemoveLanguageProfile(
300 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
303 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
304 FIXME("STUB:(%p)\n",This
);
308 static HRESULT WINAPI
InputProcessorProfiles_EnumInputProcessorInfo(
309 ITfInputProcessorProfiles
*iface
, IEnumGUID
**ppEnum
)
311 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
312 TRACE("(%p) %p\n",This
,ppEnum
);
313 return ProfilesEnumGuid_Constructor(ppEnum
);
316 static HRESULT WINAPI
InputProcessorProfiles_GetDefaultLanguageProfile(
317 ITfInputProcessorProfiles
*iface
, LANGID langid
, REFGUID catid
,
318 CLSID
*pclsid
, GUID
*pguidProfile
)
325 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
327 TRACE("%p) %x %s %p %p\n",This
, langid
, debugstr_guid(catid
),pclsid
,pguidProfile
);
329 if (!catid
|| !pclsid
|| !pguidProfile
)
332 StringFromGUID2(catid
, buf
, 39);
333 sprintfW(fullkey
, szwDefaultFmt
, szwSystemCTFKey
, szwAssemblies
, langid
, buf
);
335 if (RegOpenKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, KEY_READ
| KEY_WRITE
,
336 &hkey
) != ERROR_SUCCESS
)
340 res
= RegQueryValueExW(hkey
, szwDefault
, 0, NULL
, (LPBYTE
)buf
, &count
);
341 if (res
!= ERROR_SUCCESS
)
346 CLSIDFromString(buf
,pclsid
);
348 res
= RegQueryValueExW(hkey
, szwProfile
, 0, NULL
, (LPBYTE
)buf
, &count
);
349 if (res
== ERROR_SUCCESS
)
350 CLSIDFromString(buf
,pguidProfile
);
357 static HRESULT WINAPI
InputProcessorProfiles_SetDefaultLanguageProfile(
358 ITfInputProcessorProfiles
*iface
, LANGID langid
, REFCLSID rclsid
,
359 REFGUID guidProfiles
)
366 ITfCategoryMgr
*catmgr
;
367 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
368 static const GUID
* tipcats
[3] = { &GUID_TFCAT_TIP_KEYBOARD
,
369 &GUID_TFCAT_TIP_SPEECH
,
370 &GUID_TFCAT_TIP_HANDWRITING
};
372 TRACE("%p) %x %s %s\n",This
, langid
, debugstr_guid(rclsid
),debugstr_guid(guidProfiles
));
374 if (!rclsid
|| !guidProfiles
)
377 hr
= CategoryMgr_Constructor(NULL
,(IUnknown
**)&catmgr
);
382 if (ITfCategoryMgr_FindClosestCategory(catmgr
, rclsid
,
383 &catid
, tipcats
, 3) != S_OK
)
384 hr
= ITfCategoryMgr_FindClosestCategory(catmgr
, rclsid
,
386 ITfCategoryMgr_Release(catmgr
);
391 StringFromGUID2(&catid
, buf
, 39);
392 sprintfW(fullkey
, szwDefaultFmt
, szwSystemCTFKey
, szwAssemblies
, langid
, buf
);
394 if (RegCreateKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, NULL
, 0, KEY_READ
| KEY_WRITE
,
395 NULL
, &hkey
, NULL
) != ERROR_SUCCESS
)
398 StringFromGUID2(rclsid
, buf
, 39);
399 RegSetValueExW(hkey
, szwDefault
, 0, REG_SZ
, (LPBYTE
)buf
, sizeof(buf
));
400 StringFromGUID2(guidProfiles
, buf
, 39);
401 RegSetValueExW(hkey
, szwProfile
, 0, REG_SZ
, (LPBYTE
)buf
, sizeof(buf
));
407 static HRESULT WINAPI
InputProcessorProfiles_ActivateLanguageProfile(
408 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
409 REFGUID guidProfiles
)
413 TF_LANGUAGEPROFILE LanguageProfile
;
414 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
416 TRACE("(%p) %s %x %s\n",This
,debugstr_guid(rclsid
),langid
,debugstr_guid(guidProfiles
));
418 if (langid
!= This
->currentLanguage
) return E_INVALIDARG
;
420 if (get_active_textservice(rclsid
,NULL
))
422 TRACE("Already Active\n");
426 hr
= ITfInputProcessorProfiles_IsEnabledLanguageProfile(iface
, rclsid
,
427 langid
, guidProfiles
, &enabled
);
428 if (FAILED(hr
) || !enabled
)
430 TRACE("Not Enabled\n");
434 LanguageProfile
.clsid
= *rclsid
;
435 LanguageProfile
.langid
= langid
;
436 LanguageProfile
.guidProfile
= *guidProfiles
;
438 hr
= add_active_textservice(&LanguageProfile
);
443 static HRESULT WINAPI
InputProcessorProfiles_GetActiveLanguageProfile(
444 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID
*plangid
,
447 TF_LANGUAGEPROFILE profile
;
448 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
450 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(rclsid
),plangid
,pguidProfile
);
452 if (!rclsid
|| !plangid
|| !pguidProfile
)
455 if (get_active_textservice(rclsid
, &profile
))
457 *plangid
= profile
.langid
;
458 *pguidProfile
= profile
.guidProfile
;
463 *pguidProfile
= GUID_NULL
;
468 static HRESULT WINAPI
InputProcessorProfiles_GetLanguageProfileDescription(
469 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
470 REFGUID guidProfile
, BSTR
*pbstrProfile
)
472 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
473 FIXME("STUB:(%p)\n",This
);
477 static HRESULT WINAPI
InputProcessorProfiles_GetCurrentLanguage(
478 ITfInputProcessorProfiles
*iface
, LANGID
*plangid
)
480 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
481 TRACE("(%p) 0x%x\n",This
,This
->currentLanguage
);
486 *plangid
= This
->currentLanguage
;
491 static HRESULT WINAPI
InputProcessorProfiles_ChangeCurrentLanguage(
492 ITfInputProcessorProfiles
*iface
, LANGID langid
)
495 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
498 FIXME("STUB:(%p)\n",This
);
500 LIST_FOR_EACH(cursor
, &This
->LanguageProfileNotifySink
)
502 InputProcessorProfilesSink
* sink
= LIST_ENTRY(cursor
,InputProcessorProfilesSink
,entry
);
504 ITfLanguageProfileNotifySink_OnLanguageChange(sink
->interfaces
.pITfLanguageProfileNotifySink
, langid
, &accept
);
509 /* TODO: On successful language change call OnLanguageChanged sink */
513 static HRESULT WINAPI
InputProcessorProfiles_GetLanguageList(
514 ITfInputProcessorProfiles
*iface
, LANGID
**ppLangId
, ULONG
*pulCount
)
516 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
517 FIXME("Semi-STUB:(%p)\n",This
);
518 *ppLangId
= CoTaskMemAlloc(sizeof(LANGID
));
519 **ppLangId
= This
->currentLanguage
;
524 static HRESULT WINAPI
InputProcessorProfiles_EnumLanguageProfiles(
525 ITfInputProcessorProfiles
*iface
, LANGID langid
,
526 IEnumTfLanguageProfiles
**ppEnum
)
528 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
529 TRACE("(%p) %x %p\n",This
,langid
,ppEnum
);
530 return EnumTfLanguageProfiles_Constructor(langid
, ppEnum
);
533 static HRESULT WINAPI
InputProcessorProfiles_EnableLanguageProfile(
534 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
535 REFGUID guidProfile
, BOOL fEnable
)
543 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
544 TRACE("(%p) %s %x %s %i\n",This
, debugstr_guid(rclsid
), langid
, debugstr_guid(guidProfile
), fEnable
);
546 StringFromGUID2(rclsid
, buf
, 39);
547 StringFromGUID2(guidProfile
, buf2
, 39);
548 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
550 res
= RegOpenKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
554 RegSetValueExW(key
, szwEnable
, 0, REG_DWORD
, (LPBYTE
)&fEnable
, sizeof(DWORD
));
563 static HRESULT WINAPI
InputProcessorProfiles_IsEnabledLanguageProfile(
564 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
565 REFGUID guidProfile
, BOOL
*pfEnable
)
573 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
574 TRACE("(%p) %s, %i, %s, %p\n",This
,debugstr_guid(rclsid
),langid
,debugstr_guid(guidProfile
),pfEnable
);
579 StringFromGUID2(rclsid
, buf
, 39);
580 StringFromGUID2(guidProfile
, buf2
, 39);
581 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
583 res
= RegOpenKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
587 DWORD count
= sizeof(DWORD
);
588 res
= RegQueryValueExW(key
, szwEnable
, 0, NULL
, (LPBYTE
)pfEnable
, &count
);
592 if (res
) /* Try Default */
594 res
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
598 DWORD count
= sizeof(DWORD
);
599 res
= RegQueryValueExW(key
, szwEnable
, 0, NULL
, (LPBYTE
)pfEnable
, &count
);
610 static HRESULT WINAPI
InputProcessorProfiles_EnableLanguageProfileByDefault(
611 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
612 REFGUID guidProfile
, BOOL fEnable
)
620 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
621 TRACE("(%p) %s %x %s %i\n",This
,debugstr_guid(rclsid
),langid
,debugstr_guid(guidProfile
),fEnable
);
623 StringFromGUID2(rclsid
, buf
, 39);
624 StringFromGUID2(guidProfile
, buf2
, 39);
625 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
627 res
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
631 RegSetValueExW(key
, szwEnable
, 0, REG_DWORD
, (LPBYTE
)&fEnable
, sizeof(DWORD
));
640 static HRESULT WINAPI
InputProcessorProfiles_SubstituteKeyboardLayout(
641 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
642 REFGUID guidProfile
, HKL hKL
)
644 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
645 FIXME("STUB:(%p)\n",This
);
650 static const ITfInputProcessorProfilesVtbl InputProcessorProfiles_InputProcessorProfilesVtbl
=
652 InputProcessorProfiles_QueryInterface
,
653 InputProcessorProfiles_AddRef
,
654 InputProcessorProfiles_Release
,
656 InputProcessorProfiles_Register
,
657 InputProcessorProfiles_Unregister
,
658 InputProcessorProfiles_AddLanguageProfile
,
659 InputProcessorProfiles_RemoveLanguageProfile
,
660 InputProcessorProfiles_EnumInputProcessorInfo
,
661 InputProcessorProfiles_GetDefaultLanguageProfile
,
662 InputProcessorProfiles_SetDefaultLanguageProfile
,
663 InputProcessorProfiles_ActivateLanguageProfile
,
664 InputProcessorProfiles_GetActiveLanguageProfile
,
665 InputProcessorProfiles_GetLanguageProfileDescription
,
666 InputProcessorProfiles_GetCurrentLanguage
,
667 InputProcessorProfiles_ChangeCurrentLanguage
,
668 InputProcessorProfiles_GetLanguageList
,
669 InputProcessorProfiles_EnumLanguageProfiles
,
670 InputProcessorProfiles_EnableLanguageProfile
,
671 InputProcessorProfiles_IsEnabledLanguageProfile
,
672 InputProcessorProfiles_EnableLanguageProfileByDefault
,
673 InputProcessorProfiles_SubstituteKeyboardLayout
676 /*****************************************************
677 * ITfSource functions
678 *****************************************************/
679 static HRESULT WINAPI
IPPSource_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
681 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
682 return InputProcessorProfiles_QueryInterface((ITfInputProcessorProfiles
*)This
, iid
, *ppvOut
);
685 static ULONG WINAPI
IPPSource_AddRef(ITfSource
*iface
)
687 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
688 return InputProcessorProfiles_AddRef((ITfInputProcessorProfiles
*)This
);
691 static ULONG WINAPI
IPPSource_Release(ITfSource
*iface
)
693 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
694 return InputProcessorProfiles_Release((ITfInputProcessorProfiles
*)This
);
697 static HRESULT WINAPI
IPPSource_AdviseSink(ITfSource
*iface
,
698 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
700 InputProcessorProfilesSink
*ipps
;
701 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
703 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(riid
),punk
,pdwCookie
);
705 if (!riid
|| !punk
|| !pdwCookie
)
708 if (IsEqualIID(riid
, &IID_ITfLanguageProfileNotifySink
))
710 ipps
= HeapAlloc(GetProcessHeap(),0,sizeof(InputProcessorProfilesSink
));
712 return E_OUTOFMEMORY
;
713 if (FAILED(IUnknown_QueryInterface(punk
, riid
, (LPVOID
*)&ipps
->interfaces
.pITfLanguageProfileNotifySink
)))
715 HeapFree(GetProcessHeap(),0,ipps
);
716 return CONNECT_E_CANNOTCONNECT
;
718 list_add_head(&This
->LanguageProfileNotifySink
,&ipps
->entry
);
719 *pdwCookie
= generate_Cookie(COOKIE_MAGIC_IPPSINK
, ipps
);
723 FIXME("(%p) Unhandled Sink: %s\n",This
,debugstr_guid(riid
));
727 TRACE("cookie %x\n",*pdwCookie
);
732 static HRESULT WINAPI
IPPSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
734 InputProcessorProfilesSink
*sink
;
735 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
737 TRACE("(%p) %x\n",This
,pdwCookie
);
739 if (get_Cookie_magic(pdwCookie
)!=COOKIE_MAGIC_IPPSINK
)
742 sink
= (InputProcessorProfilesSink
*)remove_Cookie(pdwCookie
);
744 return CONNECT_E_NOCONNECTION
;
746 list_remove(&sink
->entry
);
752 static const ITfSourceVtbl InputProcessorProfiles_SourceVtbl
=
754 IPPSource_QueryInterface
,
758 IPPSource_AdviseSink
,
759 IPPSource_UnadviseSink
,
762 HRESULT
InputProcessorProfiles_Constructor(IUnknown
*pUnkOuter
, IUnknown
**ppOut
)
764 InputProcessorProfiles
*This
;
766 return CLASS_E_NOAGGREGATION
;
768 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(InputProcessorProfiles
));
770 return E_OUTOFMEMORY
;
772 This
->InputProcessorProfilesVtbl
= &InputProcessorProfiles_InputProcessorProfilesVtbl
;
773 This
->SourceVtbl
= &InputProcessorProfiles_SourceVtbl
;
775 This
->currentLanguage
= GetUserDefaultLCID();
777 list_init(&This
->LanguageProfileNotifySink
);
779 TRACE("returning %p\n", This
);
780 *ppOut
= (IUnknown
*)This
;
784 /**************************************************
785 * IEnumGUID implementation for ITfInputProcessorProfiles::EnumInputProcessorInfo
786 **************************************************/
787 static void ProfilesEnumGuid_Destructor(ProfilesEnumGuid
*This
)
789 TRACE("destroying %p\n", This
);
790 RegCloseKey(This
->key
);
791 HeapFree(GetProcessHeap(),0,This
);
794 static HRESULT WINAPI
ProfilesEnumGuid_QueryInterface(IEnumGUID
*iface
, REFIID iid
, LPVOID
*ppvOut
)
796 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
799 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_IEnumGUID
))
806 IEnumGUID_AddRef(iface
);
810 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
811 return E_NOINTERFACE
;
814 static ULONG WINAPI
ProfilesEnumGuid_AddRef(IEnumGUID
*iface
)
816 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
817 return InterlockedIncrement(&This
->refCount
);
820 static ULONG WINAPI
ProfilesEnumGuid_Release(IEnumGUID
*iface
)
822 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
825 ret
= InterlockedDecrement(&This
->refCount
);
827 ProfilesEnumGuid_Destructor(This
);
831 /*****************************************************
832 * IEnumGuid functions
833 *****************************************************/
834 static HRESULT WINAPI
ProfilesEnumGuid_Next( LPENUMGUID iface
,
835 ULONG celt
, GUID
*rgelt
, ULONG
*pceltFetched
)
837 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
840 TRACE("(%p)\n",This
);
842 if (rgelt
== NULL
) return E_POINTER
;
844 if (This
->key
) while (fetched
< celt
)
851 res
= RegEnumKeyExW(This
->key
, This
->next_index
, catid
, &cName
,
852 NULL
, NULL
, NULL
, NULL
);
853 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) break;
854 ++(This
->next_index
);
856 hr
= CLSIDFromString(catid
, rgelt
);
857 if (FAILED(hr
)) continue;
863 if (pceltFetched
) *pceltFetched
= fetched
;
864 return fetched
== celt
? S_OK
: S_FALSE
;
867 static HRESULT WINAPI
ProfilesEnumGuid_Skip( LPENUMGUID iface
, ULONG celt
)
869 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
870 TRACE("(%p)\n",This
);
872 This
->next_index
+= celt
;
876 static HRESULT WINAPI
ProfilesEnumGuid_Reset( LPENUMGUID iface
)
878 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
879 TRACE("(%p)\n",This
);
880 This
->next_index
= 0;
884 static HRESULT WINAPI
ProfilesEnumGuid_Clone( LPENUMGUID iface
,
887 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
890 TRACE("(%p)\n",This
);
892 if (ppenum
== NULL
) return E_POINTER
;
894 res
= ProfilesEnumGuid_Constructor(ppenum
);
897 ProfilesEnumGuid
*new_This
= (ProfilesEnumGuid
*)*ppenum
;
898 new_This
->next_index
= This
->next_index
;
903 static const IEnumGUIDVtbl IEnumGUID_Vtbl
={
904 ProfilesEnumGuid_QueryInterface
,
905 ProfilesEnumGuid_AddRef
,
906 ProfilesEnumGuid_Release
,
908 ProfilesEnumGuid_Next
,
909 ProfilesEnumGuid_Skip
,
910 ProfilesEnumGuid_Reset
,
911 ProfilesEnumGuid_Clone
914 static HRESULT
ProfilesEnumGuid_Constructor(IEnumGUID
**ppOut
)
916 ProfilesEnumGuid
*This
;
918 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ProfilesEnumGuid
));
920 return E_OUTOFMEMORY
;
922 This
->Vtbl
= &IEnumGUID_Vtbl
;
925 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, szwSystemTIPKey
, 0, NULL
, 0,
926 KEY_READ
| KEY_WRITE
, NULL
, &This
->key
, NULL
) != ERROR_SUCCESS
)
928 HeapFree(GetProcessHeap(), 0, This
);
932 TRACE("returning %p\n", This
);
933 *ppOut
= (IEnumGUID
*)This
;
937 /**************************************************
938 * IEnumTfLanguageProfiles implementation
939 **************************************************/
940 static void EnumTfLanguageProfiles_Destructor(EnumTfLanguageProfiles
*This
)
942 TRACE("destroying %p\n", This
);
943 RegCloseKey(This
->tipkey
);
945 RegCloseKey(This
->langkey
);
946 ITfCategoryMgr_Release(This
->catmgr
);
947 HeapFree(GetProcessHeap(),0,This
);
950 static HRESULT WINAPI
EnumTfLanguageProfiles_QueryInterface(IEnumTfLanguageProfiles
*iface
, REFIID iid
, LPVOID
*ppvOut
)
952 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
955 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_IEnumTfLanguageProfiles
))
962 IEnumTfLanguageProfiles_AddRef(iface
);
966 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
967 return E_NOINTERFACE
;
970 static ULONG WINAPI
EnumTfLanguageProfiles_AddRef(IEnumTfLanguageProfiles
*iface
)
972 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
973 return InterlockedIncrement(&This
->refCount
);
976 static ULONG WINAPI
EnumTfLanguageProfiles_Release(IEnumTfLanguageProfiles
*iface
)
978 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
981 ret
= InterlockedDecrement(&This
->refCount
);
983 EnumTfLanguageProfiles_Destructor(This
);
987 /*****************************************************
988 * IEnumGuid functions
989 *****************************************************/
990 static INT
next_LanguageProfile(EnumTfLanguageProfiles
*This
, CLSID clsid
, TF_LANGUAGEPROFILE
*tflp
)
998 static const WCHAR fmt
[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
1000 if (This
->langkey
== NULL
)
1002 sprintfW(fullkey
,fmt
,This
->szwCurrentClsid
,szwLngp
,This
->langid
);
1003 res
= RegOpenKeyExW(This
->tipkey
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &This
->langkey
);
1006 This
->langkey
= NULL
;
1009 This
->lang_index
= 0;
1011 res
= RegEnumKeyExW(This
->langkey
, This
->lang_index
, profileid
, &cName
,
1012 NULL
, NULL
, NULL
, NULL
);
1013 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
)
1015 RegCloseKey(This
->langkey
);
1016 This
->langkey
= NULL
;
1019 ++(This
->lang_index
);
1023 static const GUID
* tipcats
[3] = { &GUID_TFCAT_TIP_KEYBOARD
,
1024 &GUID_TFCAT_TIP_SPEECH
,
1025 &GUID_TFCAT_TIP_HANDWRITING
};
1026 res
= CLSIDFromString(profileid
, &profile
);
1027 if (FAILED(res
)) return 0;
1029 tflp
->clsid
= clsid
;
1030 tflp
->langid
= This
->langid
;
1031 tflp
->fActive
= get_active_textservice(&clsid
, NULL
);
1032 tflp
->guidProfile
= profile
;
1033 if (ITfCategoryMgr_FindClosestCategory(This
->catmgr
, &clsid
,
1034 &tflp
->catid
, tipcats
, 3) != S_OK
)
1035 ITfCategoryMgr_FindClosestCategory(This
->catmgr
, &clsid
,
1036 &tflp
->catid
, NULL
, 0);
1042 static HRESULT WINAPI
EnumTfLanguageProfiles_Next(IEnumTfLanguageProfiles
*iface
,
1043 ULONG ulCount
, TF_LANGUAGEPROFILE
*pProfile
, ULONG
*pcFetch
)
1045 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
1048 TRACE("(%p)\n",This
);
1050 if (pProfile
== NULL
) return E_POINTER
;
1052 if (This
->tipkey
) while (fetched
< ulCount
)
1059 res
= RegEnumKeyExW(This
->tipkey
, This
->tip_index
,
1060 This
->szwCurrentClsid
, &cName
, NULL
, NULL
, NULL
, NULL
);
1061 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) break;
1062 ++(This
->tip_index
);
1063 hr
= CLSIDFromString(This
->szwCurrentClsid
, &clsid
);
1064 if (FAILED(hr
)) continue;
1066 while ( fetched
< ulCount
)
1068 INT res
= next_LanguageProfile(This
, clsid
, pProfile
);
1081 if (pcFetch
) *pcFetch
= fetched
;
1082 return fetched
== ulCount
? S_OK
: S_FALSE
;
1085 static HRESULT WINAPI
EnumTfLanguageProfiles_Skip( IEnumTfLanguageProfiles
* iface
, ULONG celt
)
1087 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
1088 FIXME("STUB (%p)\n",This
);
1092 static HRESULT WINAPI
EnumTfLanguageProfiles_Reset( IEnumTfLanguageProfiles
* iface
)
1094 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
1095 TRACE("(%p)\n",This
);
1096 This
->tip_index
= 0;
1098 RegCloseKey(This
->langkey
);
1099 This
->langkey
= NULL
;
1100 This
->lang_index
= 0;
1104 static HRESULT WINAPI
EnumTfLanguageProfiles_Clone( IEnumTfLanguageProfiles
*iface
,
1105 IEnumTfLanguageProfiles
**ppenum
)
1107 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
1110 TRACE("(%p)\n",This
);
1112 if (ppenum
== NULL
) return E_POINTER
;
1114 res
= EnumTfLanguageProfiles_Constructor(This
->langid
, ppenum
);
1117 EnumTfLanguageProfiles
*new_This
= (EnumTfLanguageProfiles
*)*ppenum
;
1118 new_This
->tip_index
= This
->tip_index
;
1119 lstrcpynW(new_This
->szwCurrentClsid
,This
->szwCurrentClsid
,39);
1124 static const WCHAR fmt
[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
1126 sprintfW(fullkey
,fmt
,This
->szwCurrentClsid
,szwLngp
,This
->langid
);
1127 res
= RegOpenKeyExW(new_This
->tipkey
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &This
->langkey
);
1128 new_This
->lang_index
= This
->lang_index
;
1134 static const IEnumTfLanguageProfilesVtbl IEnumTfLanguageProfiles_Vtbl
={
1135 EnumTfLanguageProfiles_QueryInterface
,
1136 EnumTfLanguageProfiles_AddRef
,
1137 EnumTfLanguageProfiles_Release
,
1139 EnumTfLanguageProfiles_Clone
,
1140 EnumTfLanguageProfiles_Next
,
1141 EnumTfLanguageProfiles_Reset
,
1142 EnumTfLanguageProfiles_Skip
1145 static HRESULT
EnumTfLanguageProfiles_Constructor(LANGID langid
, IEnumTfLanguageProfiles
**ppOut
)
1148 EnumTfLanguageProfiles
*This
;
1150 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(EnumTfLanguageProfiles
));
1152 return E_OUTOFMEMORY
;
1154 This
->Vtbl
= &IEnumTfLanguageProfiles_Vtbl
;
1156 This
->langid
= langid
;
1158 hr
= CategoryMgr_Constructor(NULL
,(IUnknown
**)&This
->catmgr
);
1161 HeapFree(GetProcessHeap(),0,This
);
1165 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, szwSystemTIPKey
, 0, NULL
, 0,
1166 KEY_READ
| KEY_WRITE
, NULL
, &This
->tipkey
, NULL
) != ERROR_SUCCESS
)
1168 HeapFree(GetProcessHeap(), 0, This
);
1172 TRACE("returning %p\n", This
);
1173 *ppOut
= (IEnumTfLanguageProfiles
*)This
;