2 * ITfInputProcessorProfiles implementation
4 * Copyright 2009 Aric Stewart, CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/debug.h"
37 #include "wine/unicode.h"
38 #include "wine/list.h"
41 #include "msctf_internal.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(msctf
);
45 static const WCHAR szwLngp
[] = {'L','a','n','g','u','a','g','e','P','r','o','f','i','l','e',0};
46 static const WCHAR szwEnabled
[] = {'E','n','a','b','l','e','d',0};
47 static const WCHAR szwTipfmt
[] = {'%','s','\\','%','s',0};
48 static const WCHAR szwFullLangfmt
[] = {'%','s','\\','%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0};
50 typedef struct tagInputProcessorProfilesSink
{
53 /* InputProcessorProfile Sinks */
55 ITfLanguageProfileNotifySink
*pITfLanguageProfileNotifySink
;
57 } InputProcessorProfilesSink
;
59 typedef struct tagInputProcessorProfiles
{
60 const ITfInputProcessorProfilesVtbl
*InputProcessorProfilesVtbl
;
61 const ITfSourceVtbl
*SourceVtbl
;
62 /* const ITfInputProcessorProfileMgrVtbl *InputProcessorProfileMgrVtbl; */
63 /* const ITfInputProcessorProfilesExVtbl *InputProcessorProfilesExVtbl; */
64 /* const ITfInputProcessorProfileSubstituteLayoutVtbl *InputProcessorProfileSubstituteLayoutVtbl; */
67 LANGID currentLanguage
;
69 struct list LanguageProfileNotifySink
;
70 } InputProcessorProfiles
;
72 typedef struct tagProfilesEnumGuid
{
73 const IEnumGUIDVtbl
*Vtbl
;
80 typedef struct tagEnumTfLanguageProfiles
{
81 const IEnumTfLanguageProfilesVtbl
*Vtbl
;
86 WCHAR szwCurrentClsid
[39];
92 ITfCategoryMgr
*catmgr
;
93 } EnumTfLanguageProfiles
;
95 static HRESULT
ProfilesEnumGuid_Constructor(IEnumGUID
**ppOut
);
96 static HRESULT
EnumTfLanguageProfiles_Constructor(LANGID langid
, IEnumTfLanguageProfiles
**ppOut
);
98 static inline InputProcessorProfiles
*impl_from_ITfSourceVtbl(ITfSource
*iface
)
100 return (InputProcessorProfiles
*)((char *)iface
- FIELD_OFFSET(InputProcessorProfiles
,SourceVtbl
));
103 static void free_sink(InputProcessorProfilesSink
*sink
)
105 IUnknown_Release(sink
->interfaces
.pIUnknown
);
106 HeapFree(GetProcessHeap(),0,sink
);
109 static void InputProcessorProfiles_Destructor(InputProcessorProfiles
*This
)
111 struct list
*cursor
, *cursor2
;
112 TRACE("destroying %p\n", This
);
115 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->LanguageProfileNotifySink
)
117 InputProcessorProfilesSink
* sink
= LIST_ENTRY(cursor
,InputProcessorProfilesSink
,entry
);
122 HeapFree(GetProcessHeap(),0,This
);
125 static void add_userkey( REFCLSID rclsid
, LANGID langid
,
132 DWORD disposition
= 0;
137 StringFromGUID2(rclsid
, buf
, 39);
138 StringFromGUID2(guidProfile
, buf2
, 39);
139 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
141 res
= RegCreateKeyExW(HKEY_CURRENT_USER
,fullkey
, 0, NULL
, 0,
142 KEY_READ
| KEY_WRITE
, NULL
, &key
, &disposition
);
144 if (!res
&& disposition
== REG_CREATED_NEW_KEY
)
147 RegSetValueExW(key
, szwEnabled
, 0, REG_DWORD
, (LPBYTE
)&zero
, sizeof(DWORD
));
154 static HRESULT WINAPI
InputProcessorProfiles_QueryInterface(ITfInputProcessorProfiles
*iface
, REFIID iid
, LPVOID
*ppvOut
)
156 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
159 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfInputProcessorProfiles
))
163 else if (IsEqualIID(iid
, &IID_ITfSource
))
165 *ppvOut
= &This
->SourceVtbl
;
170 IUnknown_AddRef(iface
);
174 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
175 return E_NOINTERFACE
;
178 static ULONG WINAPI
InputProcessorProfiles_AddRef(ITfInputProcessorProfiles
*iface
)
180 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
181 return InterlockedIncrement(&This
->refCount
);
184 static ULONG WINAPI
InputProcessorProfiles_Release(ITfInputProcessorProfiles
*iface
)
186 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
189 ret
= InterlockedDecrement(&This
->refCount
);
191 InputProcessorProfiles_Destructor(This
);
195 /*****************************************************
196 * ITfInputProcessorProfiles functions
197 *****************************************************/
198 static HRESULT WINAPI
InputProcessorProfiles_Register(
199 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
)
201 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
206 TRACE("(%p) %s\n",This
,debugstr_guid(rclsid
));
208 StringFromGUID2(rclsid
, buf
, 39);
209 sprintfW(fullkey
,szwTipfmt
,szwSystemTIPKey
,buf
);
211 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
,fullkey
, 0, NULL
, 0,
212 KEY_READ
| KEY_WRITE
, NULL
, &tipkey
, NULL
) != ERROR_SUCCESS
)
220 static HRESULT WINAPI
InputProcessorProfiles_Unregister(
221 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
)
225 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
227 TRACE("(%p) %s\n",This
,debugstr_guid(rclsid
));
229 StringFromGUID2(rclsid
, buf
, 39);
230 sprintfW(fullkey
,szwTipfmt
,szwSystemTIPKey
,buf
);
232 RegDeleteTreeW(HKEY_LOCAL_MACHINE
, fullkey
);
233 RegDeleteTreeW(HKEY_CURRENT_USER
, fullkey
);
238 static HRESULT WINAPI
InputProcessorProfiles_AddLanguageProfile(
239 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
,
240 LANGID langid
, REFGUID guidProfile
, const WCHAR
*pchDesc
,
241 ULONG cchDesc
, const WCHAR
*pchIconFile
, ULONG cchFile
,
248 DWORD disposition
= 0;
250 static const WCHAR fmt2
[] = {'%','s','\\','0','x','%','0','8','x','\\','%','s',0};
251 static const WCHAR desc
[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
252 static const WCHAR icnf
[] = {'I','c','o','n','F','i','l','e',0};
253 static const WCHAR icni
[] = {'I','c','o','n','I','n','d','e','x',0};
255 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
257 TRACE("(%p) %s %x %s %s %s %i\n",This
,debugstr_guid(rclsid
), langid
,
258 debugstr_guid(guidProfile
), debugstr_wn(pchDesc
,cchDesc
),
259 debugstr_wn(pchIconFile
,cchFile
),uIconIndex
);
261 StringFromGUID2(rclsid
, buf
, 39);
262 sprintfW(fullkey
,szwTipfmt
,szwSystemTIPKey
,buf
);
264 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE
,fullkey
, 0, KEY_READ
| KEY_WRITE
,
265 &tipkey
) != ERROR_SUCCESS
)
268 StringFromGUID2(guidProfile
, buf
, 39);
269 sprintfW(fullkey
,fmt2
,szwLngp
,langid
,buf
);
271 res
= RegCreateKeyExW(tipkey
,fullkey
, 0, NULL
, 0, KEY_READ
| KEY_WRITE
,
272 NULL
, &fmtkey
, &disposition
);
277 RegSetValueExW(fmtkey
, desc
, 0, REG_SZ
, (LPBYTE
)pchDesc
, cchDesc
* sizeof(WCHAR
));
278 RegSetValueExW(fmtkey
, icnf
, 0, REG_SZ
, (LPBYTE
)pchIconFile
, cchFile
* sizeof(WCHAR
));
279 RegSetValueExW(fmtkey
, icni
, 0, REG_DWORD
, (LPBYTE
)&uIconIndex
, sizeof(DWORD
));
280 if (disposition
== REG_CREATED_NEW_KEY
)
281 RegSetValueExW(fmtkey
, szwEnabled
, 0, REG_DWORD
, (LPBYTE
)&zero
, sizeof(DWORD
));
284 add_userkey(rclsid
, langid
, guidProfile
);
294 static HRESULT WINAPI
InputProcessorProfiles_RemoveLanguageProfile(
295 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
298 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
299 FIXME("STUB:(%p)\n",This
);
303 static HRESULT WINAPI
InputProcessorProfiles_EnumInputProcessorInfo(
304 ITfInputProcessorProfiles
*iface
, IEnumGUID
**ppEnum
)
306 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
307 TRACE("(%p) %p\n",This
,ppEnum
);
308 return ProfilesEnumGuid_Constructor(ppEnum
);
311 static HRESULT WINAPI
InputProcessorProfiles_GetDefaultLanguageProfile(
312 ITfInputProcessorProfiles
*iface
, LANGID langid
, REFGUID catid
,
313 CLSID
*pclsid
, GUID
*pguidProfile
)
315 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
316 FIXME("STUB:(%p)\n",This
);
320 static HRESULT WINAPI
InputProcessorProfiles_SetDefaultLanguageProfile(
321 ITfInputProcessorProfiles
*iface
, LANGID langid
, REFCLSID rclsid
,
322 REFGUID guidProfiles
)
324 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
325 FIXME("STUB:(%p)\n",This
);
329 static HRESULT WINAPI
InputProcessorProfiles_ActivateLanguageProfile(
330 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
331 REFGUID guidProfiles
)
335 TF_LANGUAGEPROFILE LanguageProfile
;
336 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
338 TRACE("(%p) %s %x %s\n",This
,debugstr_guid(rclsid
),langid
,debugstr_guid(guidProfiles
));
340 if (langid
!= This
->currentLanguage
) return E_INVALIDARG
;
342 if (get_active_textservice(rclsid
,NULL
))
344 TRACE("Already Active\n");
348 hr
= ITfInputProcessorProfiles_IsEnabledLanguageProfile(iface
, rclsid
,
349 langid
, guidProfiles
, &enabled
);
350 if (FAILED(hr
) || !enabled
)
352 TRACE("Not Enabled\n");
356 LanguageProfile
.clsid
= *rclsid
;
357 LanguageProfile
.langid
= langid
;
358 LanguageProfile
.guidProfile
= *guidProfiles
;
360 hr
= add_active_textservice(&LanguageProfile
);
365 static HRESULT WINAPI
InputProcessorProfiles_GetActiveLanguageProfile(
366 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID
*plangid
,
369 TF_LANGUAGEPROFILE profile
;
370 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
372 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(rclsid
),plangid
,pguidProfile
);
374 if (!rclsid
|| !plangid
|| !pguidProfile
)
377 if (get_active_textservice(rclsid
, &profile
))
379 *plangid
= profile
.langid
;
380 *pguidProfile
= profile
.guidProfile
;
385 *pguidProfile
= GUID_NULL
;
390 static HRESULT WINAPI
InputProcessorProfiles_GetLanguageProfileDescription(
391 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
392 REFGUID guidProfile
, BSTR
*pbstrProfile
)
394 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
395 FIXME("STUB:(%p)\n",This
);
399 static HRESULT WINAPI
InputProcessorProfiles_GetCurrentLanguage(
400 ITfInputProcessorProfiles
*iface
, LANGID
*plangid
)
402 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
403 TRACE("(%p) 0x%x\n",This
,This
->currentLanguage
);
408 *plangid
= This
->currentLanguage
;
413 static HRESULT WINAPI
InputProcessorProfiles_ChangeCurrentLanguage(
414 ITfInputProcessorProfiles
*iface
, LANGID langid
)
416 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
417 FIXME("STUB:(%p)\n",This
);
421 static HRESULT WINAPI
InputProcessorProfiles_GetLanguageList(
422 ITfInputProcessorProfiles
*iface
, LANGID
**ppLangId
, ULONG
*pulCount
)
424 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
425 FIXME("STUB:(%p)\n",This
);
429 static HRESULT WINAPI
InputProcessorProfiles_EnumLanguageProfiles(
430 ITfInputProcessorProfiles
*iface
, LANGID langid
,
431 IEnumTfLanguageProfiles
**ppEnum
)
433 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
434 TRACE("(%p) %x %p\n",This
,langid
,ppEnum
);
435 return EnumTfLanguageProfiles_Constructor(langid
, ppEnum
);
438 static HRESULT WINAPI
InputProcessorProfiles_EnableLanguageProfile(
439 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
440 REFGUID guidProfile
, BOOL fEnable
)
448 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
449 TRACE("(%p) %s %x %s %i\n",This
, debugstr_guid(rclsid
), langid
, debugstr_guid(guidProfile
), fEnable
);
451 StringFromGUID2(rclsid
, buf
, 39);
452 StringFromGUID2(guidProfile
, buf2
, 39);
453 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
455 res
= RegOpenKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
459 RegSetValueExW(key
, szwEnabled
, 0, REG_DWORD
, (LPBYTE
)&fEnable
, sizeof(DWORD
));
468 static HRESULT WINAPI
InputProcessorProfiles_IsEnabledLanguageProfile(
469 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
470 REFGUID guidProfile
, BOOL
*pfEnable
)
478 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
479 TRACE("(%p) %s, %i, %s, %p\n",This
,debugstr_guid(rclsid
),langid
,debugstr_guid(guidProfile
),pfEnable
);
484 StringFromGUID2(rclsid
, buf
, 39);
485 StringFromGUID2(guidProfile
, buf2
, 39);
486 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
488 res
= RegOpenKeyExW(HKEY_CURRENT_USER
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
492 DWORD count
= sizeof(DWORD
);
493 res
= RegQueryValueExW(key
, szwEnabled
, 0, NULL
, (LPBYTE
)pfEnable
, &count
);
497 if (res
) /* Try Default */
499 res
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
503 DWORD count
= sizeof(DWORD
);
504 res
= RegQueryValueExW(key
, szwEnabled
, 0, NULL
, (LPBYTE
)pfEnable
, &count
);
515 static HRESULT WINAPI
InputProcessorProfiles_EnableLanguageProfileByDefault(
516 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
517 REFGUID guidProfile
, BOOL fEnable
)
525 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
526 TRACE("(%p) %s %x %s %i\n",This
,debugstr_guid(rclsid
),langid
,debugstr_guid(guidProfile
),fEnable
);
528 StringFromGUID2(rclsid
, buf
, 39);
529 StringFromGUID2(guidProfile
, buf2
, 39);
530 sprintfW(fullkey
,szwFullLangfmt
,szwSystemTIPKey
,buf
,szwLngp
,langid
,buf2
);
532 res
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &key
);
536 RegSetValueExW(key
, szwEnabled
, 0, REG_DWORD
, (LPBYTE
)&fEnable
, sizeof(DWORD
));
545 static HRESULT WINAPI
InputProcessorProfiles_SubstituteKeyboardLayout(
546 ITfInputProcessorProfiles
*iface
, REFCLSID rclsid
, LANGID langid
,
547 REFGUID guidProfile
, HKL hKL
)
549 InputProcessorProfiles
*This
= (InputProcessorProfiles
*)iface
;
550 FIXME("STUB:(%p)\n",This
);
555 static const ITfInputProcessorProfilesVtbl InputProcessorProfiles_InputProcessorProfilesVtbl
=
557 InputProcessorProfiles_QueryInterface
,
558 InputProcessorProfiles_AddRef
,
559 InputProcessorProfiles_Release
,
561 InputProcessorProfiles_Register
,
562 InputProcessorProfiles_Unregister
,
563 InputProcessorProfiles_AddLanguageProfile
,
564 InputProcessorProfiles_RemoveLanguageProfile
,
565 InputProcessorProfiles_EnumInputProcessorInfo
,
566 InputProcessorProfiles_GetDefaultLanguageProfile
,
567 InputProcessorProfiles_SetDefaultLanguageProfile
,
568 InputProcessorProfiles_ActivateLanguageProfile
,
569 InputProcessorProfiles_GetActiveLanguageProfile
,
570 InputProcessorProfiles_GetLanguageProfileDescription
,
571 InputProcessorProfiles_GetCurrentLanguage
,
572 InputProcessorProfiles_ChangeCurrentLanguage
,
573 InputProcessorProfiles_GetLanguageList
,
574 InputProcessorProfiles_EnumLanguageProfiles
,
575 InputProcessorProfiles_EnableLanguageProfile
,
576 InputProcessorProfiles_IsEnabledLanguageProfile
,
577 InputProcessorProfiles_EnableLanguageProfileByDefault
,
578 InputProcessorProfiles_SubstituteKeyboardLayout
581 /*****************************************************
582 * ITfSource functions
583 *****************************************************/
584 static HRESULT WINAPI
IPPSource_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
586 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
587 return InputProcessorProfiles_QueryInterface((ITfInputProcessorProfiles
*)This
, iid
, *ppvOut
);
590 static ULONG WINAPI
IPPSource_AddRef(ITfSource
*iface
)
592 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
593 return InputProcessorProfiles_AddRef((ITfInputProcessorProfiles
*)This
);
596 static ULONG WINAPI
IPPSource_Release(ITfSource
*iface
)
598 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
599 return InputProcessorProfiles_Release((ITfInputProcessorProfiles
*)This
);
602 static WINAPI HRESULT
IPPSource_AdviseSink(ITfSource
*iface
,
603 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
605 InputProcessorProfilesSink
*ipps
;
606 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
608 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(riid
),punk
,pdwCookie
);
610 if (!riid
|| !punk
|| !pdwCookie
)
613 if (IsEqualIID(riid
, &IID_ITfLanguageProfileNotifySink
))
615 ipps
= HeapAlloc(GetProcessHeap(),0,sizeof(InputProcessorProfilesSink
));
617 return E_OUTOFMEMORY
;
618 if (FAILED(IUnknown_QueryInterface(punk
, riid
, (LPVOID
*)&ipps
->interfaces
.pITfLanguageProfileNotifySink
)))
620 HeapFree(GetProcessHeap(),0,ipps
);
621 return CONNECT_E_CANNOTCONNECT
;
623 list_add_head(&This
->LanguageProfileNotifySink
,&ipps
->entry
);
624 *pdwCookie
= generate_Cookie(COOKIE_MAGIC_IPPSINK
, ipps
);
628 FIXME("(%p) Unhandled Sink: %s\n",This
,debugstr_guid(riid
));
632 TRACE("cookie %x\n",*pdwCookie
);
637 static WINAPI HRESULT
IPPSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
639 InputProcessorProfilesSink
*sink
;
640 InputProcessorProfiles
*This
= impl_from_ITfSourceVtbl(iface
);
642 TRACE("(%p) %x\n",This
,pdwCookie
);
644 if (get_Cookie_magic(pdwCookie
)!=COOKIE_MAGIC_IPPSINK
)
647 sink
= (InputProcessorProfilesSink
*)remove_Cookie(pdwCookie
);
649 return CONNECT_E_NOCONNECTION
;
651 list_remove(&sink
->entry
);
657 static const ITfSourceVtbl InputProcessorProfiles_SourceVtbl
=
659 IPPSource_QueryInterface
,
663 IPPSource_AdviseSink
,
664 IPPSource_UnadviseSink
,
667 HRESULT
InputProcessorProfiles_Constructor(IUnknown
*pUnkOuter
, IUnknown
**ppOut
)
669 InputProcessorProfiles
*This
;
671 return CLASS_E_NOAGGREGATION
;
673 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(InputProcessorProfiles
));
675 return E_OUTOFMEMORY
;
677 This
->InputProcessorProfilesVtbl
= &InputProcessorProfiles_InputProcessorProfilesVtbl
;
678 This
->SourceVtbl
= &InputProcessorProfiles_SourceVtbl
;
680 This
->currentLanguage
= GetUserDefaultLCID();
682 list_init(&This
->LanguageProfileNotifySink
);
684 TRACE("returning %p\n", This
);
685 *ppOut
= (IUnknown
*)This
;
689 /**************************************************
690 * IEnumGUID implementaion for ITfInputProcessorProfiles::EnumInputProcessorInfo
691 **************************************************/
692 static void ProfilesEnumGuid_Destructor(ProfilesEnumGuid
*This
)
694 TRACE("destroying %p\n", This
);
695 RegCloseKey(This
->key
);
696 HeapFree(GetProcessHeap(),0,This
);
699 static HRESULT WINAPI
ProfilesEnumGuid_QueryInterface(IEnumGUID
*iface
, REFIID iid
, LPVOID
*ppvOut
)
701 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
704 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_IEnumGUID
))
711 IUnknown_AddRef(iface
);
715 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
716 return E_NOINTERFACE
;
719 static ULONG WINAPI
ProfilesEnumGuid_AddRef(IEnumGUID
*iface
)
721 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
722 return InterlockedIncrement(&This
->refCount
);
725 static ULONG WINAPI
ProfilesEnumGuid_Release(IEnumGUID
*iface
)
727 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
730 ret
= InterlockedDecrement(&This
->refCount
);
732 ProfilesEnumGuid_Destructor(This
);
736 /*****************************************************
737 * IEnumGuid functions
738 *****************************************************/
739 static HRESULT WINAPI
ProfilesEnumGuid_Next( LPENUMGUID iface
,
740 ULONG celt
, GUID
*rgelt
, ULONG
*pceltFetched
)
742 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
745 TRACE("(%p)\n",This
);
747 if (rgelt
== NULL
) return E_POINTER
;
749 if (This
->key
) while (fetched
< celt
)
756 res
= RegEnumKeyExW(This
->key
, This
->next_index
, catid
, &cName
,
757 NULL
, NULL
, NULL
, NULL
);
758 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) break;
759 ++(This
->next_index
);
761 hr
= CLSIDFromString(catid
, rgelt
);
762 if (FAILED(hr
)) continue;
768 if (pceltFetched
) *pceltFetched
= fetched
;
769 return fetched
== celt
? S_OK
: S_FALSE
;
772 static HRESULT WINAPI
ProfilesEnumGuid_Skip( LPENUMGUID iface
, ULONG celt
)
774 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
775 TRACE("(%p)\n",This
);
777 This
->next_index
+= celt
;
781 static HRESULT WINAPI
ProfilesEnumGuid_Reset( LPENUMGUID iface
)
783 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
784 TRACE("(%p)\n",This
);
785 This
->next_index
= 0;
789 static HRESULT WINAPI
ProfilesEnumGuid_Clone( LPENUMGUID iface
,
792 ProfilesEnumGuid
*This
= (ProfilesEnumGuid
*)iface
;
795 TRACE("(%p)\n",This
);
797 if (ppenum
== NULL
) return E_POINTER
;
799 res
= ProfilesEnumGuid_Constructor(ppenum
);
802 ProfilesEnumGuid
*new_This
= (ProfilesEnumGuid
*)*ppenum
;
803 new_This
->next_index
= This
->next_index
;
808 static const IEnumGUIDVtbl IEnumGUID_Vtbl
={
809 ProfilesEnumGuid_QueryInterface
,
810 ProfilesEnumGuid_AddRef
,
811 ProfilesEnumGuid_Release
,
813 ProfilesEnumGuid_Next
,
814 ProfilesEnumGuid_Skip
,
815 ProfilesEnumGuid_Reset
,
816 ProfilesEnumGuid_Clone
819 static HRESULT
ProfilesEnumGuid_Constructor(IEnumGUID
**ppOut
)
821 ProfilesEnumGuid
*This
;
823 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ProfilesEnumGuid
));
825 return E_OUTOFMEMORY
;
827 This
->Vtbl
= &IEnumGUID_Vtbl
;
830 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, szwSystemTIPKey
, 0, NULL
, 0,
831 KEY_READ
| KEY_WRITE
, NULL
, &This
->key
, NULL
) != ERROR_SUCCESS
)
834 TRACE("returning %p\n", This
);
835 *ppOut
= (IEnumGUID
*)This
;
839 /**************************************************
840 * IEnumTfLanguageProfiles implementaion
841 **************************************************/
842 static void EnumTfLanguageProfiles_Destructor(EnumTfLanguageProfiles
*This
)
844 TRACE("destroying %p\n", This
);
845 RegCloseKey(This
->tipkey
);
847 RegCloseKey(This
->langkey
);
848 ITfCategoryMgr_Release(This
->catmgr
);
849 HeapFree(GetProcessHeap(),0,This
);
852 static HRESULT WINAPI
EnumTfLanguageProfiles_QueryInterface(IEnumTfLanguageProfiles
*iface
, REFIID iid
, LPVOID
*ppvOut
)
854 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
857 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_IEnumTfLanguageProfiles
))
864 IUnknown_AddRef(iface
);
868 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
869 return E_NOINTERFACE
;
872 static ULONG WINAPI
EnumTfLanguageProfiles_AddRef(IEnumTfLanguageProfiles
*iface
)
874 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
875 return InterlockedIncrement(&This
->refCount
);
878 static ULONG WINAPI
EnumTfLanguageProfiles_Release(IEnumTfLanguageProfiles
*iface
)
880 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
883 ret
= InterlockedDecrement(&This
->refCount
);
885 EnumTfLanguageProfiles_Destructor(This
);
889 /*****************************************************
890 * IEnumGuid functions
891 *****************************************************/
892 static INT
next_LanguageProfile(EnumTfLanguageProfiles
*This
, CLSID clsid
, TF_LANGUAGEPROFILE
*tflp
)
900 static const WCHAR fmt
[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
902 if (This
->langkey
== NULL
)
904 sprintfW(fullkey
,fmt
,This
->szwCurrentClsid
,szwLngp
,This
->langid
);
905 res
= RegOpenKeyExW(This
->tipkey
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &This
->langkey
);
908 This
->langkey
= NULL
;
911 This
->lang_index
= 0;
913 res
= RegEnumKeyExW(This
->langkey
, This
->lang_index
, profileid
, &cName
,
914 NULL
, NULL
, NULL
, NULL
);
915 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
)
917 RegCloseKey(This
->langkey
);
918 This
->langkey
= NULL
;
921 ++(This
->lang_index
);
925 static const GUID
* tipcats
[3] = { &GUID_TFCAT_TIP_KEYBOARD
,
926 &GUID_TFCAT_TIP_SPEECH
,
927 &GUID_TFCAT_TIP_HANDWRITING
};
928 res
= CLSIDFromString(profileid
, &profile
);
929 if (FAILED(res
)) return 0;
932 tflp
->langid
= This
->langid
;
933 tflp
->fActive
= get_active_textservice(&clsid
, NULL
);
934 tflp
->guidProfile
= profile
;
935 if (ITfCategoryMgr_FindClosestCategory(This
->catmgr
, &clsid
,
936 &tflp
->catid
, tipcats
, 3) != S_OK
)
937 ITfCategoryMgr_FindClosestCategory(This
->catmgr
, &clsid
,
938 &tflp
->catid
, NULL
, 0);
944 static HRESULT WINAPI
EnumTfLanguageProfiles_Next(IEnumTfLanguageProfiles
*iface
,
945 ULONG ulCount
, TF_LANGUAGEPROFILE
*pProfile
, ULONG
*pcFetch
)
947 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
950 TRACE("(%p)\n",This
);
952 if (pProfile
== NULL
) return E_POINTER
;
954 if (This
->tipkey
) while (fetched
< ulCount
)
961 res
= RegEnumKeyExW(This
->tipkey
, This
->tip_index
,
962 This
->szwCurrentClsid
, &cName
, NULL
, NULL
, NULL
, NULL
);
963 if (res
!= ERROR_SUCCESS
&& res
!= ERROR_MORE_DATA
) break;
965 hr
= CLSIDFromString(This
->szwCurrentClsid
, &clsid
);
966 if (FAILED(hr
)) continue;
968 while ( fetched
< ulCount
)
970 INT res
= next_LanguageProfile(This
, clsid
, pProfile
);
983 if (pcFetch
) *pcFetch
= fetched
;
984 return fetched
== ulCount
? S_OK
: S_FALSE
;
987 static HRESULT WINAPI
EnumTfLanguageProfiles_Skip( IEnumTfLanguageProfiles
* iface
, ULONG celt
)
989 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
990 FIXME("STUB (%p)\n",This
);
994 static HRESULT WINAPI
EnumTfLanguageProfiles_Reset( IEnumTfLanguageProfiles
* iface
)
996 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
997 TRACE("(%p)\n",This
);
1000 RegCloseKey(This
->langkey
);
1001 This
->langkey
= NULL
;
1002 This
->lang_index
= 0;
1006 static HRESULT WINAPI
EnumTfLanguageProfiles_Clone( IEnumTfLanguageProfiles
*iface
,
1007 IEnumTfLanguageProfiles
**ppenum
)
1009 EnumTfLanguageProfiles
*This
= (EnumTfLanguageProfiles
*)iface
;
1012 TRACE("(%p)\n",This
);
1014 if (ppenum
== NULL
) return E_POINTER
;
1016 res
= EnumTfLanguageProfiles_Constructor(This
->langid
, ppenum
);
1019 EnumTfLanguageProfiles
*new_This
= (EnumTfLanguageProfiles
*)*ppenum
;
1020 new_This
->tip_index
= This
->tip_index
;
1021 lstrcpynW(new_This
->szwCurrentClsid
,This
->szwCurrentClsid
,39);
1026 static const WCHAR fmt
[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
1028 sprintfW(fullkey
,fmt
,This
->szwCurrentClsid
,szwLngp
,This
->langid
);
1029 res
= RegOpenKeyExW(new_This
->tipkey
, fullkey
, 0, KEY_READ
| KEY_WRITE
, &This
->langkey
);
1030 new_This
->lang_index
= This
->lang_index
;
1036 static const IEnumTfLanguageProfilesVtbl IEnumTfLanguageProfiles_Vtbl
={
1037 EnumTfLanguageProfiles_QueryInterface
,
1038 EnumTfLanguageProfiles_AddRef
,
1039 EnumTfLanguageProfiles_Release
,
1041 EnumTfLanguageProfiles_Clone
,
1042 EnumTfLanguageProfiles_Next
,
1043 EnumTfLanguageProfiles_Reset
,
1044 EnumTfLanguageProfiles_Skip
1047 static HRESULT
EnumTfLanguageProfiles_Constructor(LANGID langid
, IEnumTfLanguageProfiles
**ppOut
)
1050 EnumTfLanguageProfiles
*This
;
1052 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(EnumTfLanguageProfiles
));
1054 return E_OUTOFMEMORY
;
1056 This
->Vtbl
= &IEnumTfLanguageProfiles_Vtbl
;
1058 This
->langid
= langid
;
1060 hr
= CategoryMgr_Constructor(NULL
,(IUnknown
**)&This
->catmgr
);
1063 HeapFree(GetProcessHeap(),0,This
);
1067 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE
, szwSystemTIPKey
, 0, NULL
, 0,
1068 KEY_READ
| KEY_WRITE
, NULL
, &This
->tipkey
, NULL
) != ERROR_SUCCESS
)
1071 TRACE("returning %p\n", This
);
1072 *ppOut
= (IEnumTfLanguageProfiles
*)This
;