wined3d: Always store the palette index in the alpha component.
[wine/multimedia.git] / dlls / msctf / inputprocessor.c
blobf1595f89e552581b8035f9220b7752285238a2c8
1 /*
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 "config.h"
23 #include <stdarg.h>
25 #define COBJMACROS
27 #include "wine/debug.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "winuser.h"
32 #include "shlwapi.h"
33 #include "winerror.h"
34 #include "objbase.h"
35 #include "olectl.h"
37 #include "wine/unicode.h"
38 #include "wine/list.h"
40 #include "msctf.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 {
56 struct list entry;
57 union {
58 /* InputProcessorProfile Sinks */
59 IUnknown *pIUnknown;
60 ITfLanguageProfileNotifySink *pITfLanguageProfileNotifySink;
61 } interfaces;
62 } InputProcessorProfilesSink;
64 typedef struct tagInputProcessorProfiles {
65 ITfInputProcessorProfiles ITfInputProcessorProfiles_iface;
66 ITfSource ITfSource_iface;
67 ITfInputProcessorProfileMgr ITfInputProcessorProfileMgr_iface;
68 /* const ITfInputProcessorProfilesExVtbl *InputProcessorProfilesExVtbl; */
69 /* const ITfInputProcessorProfileSubstituteLayoutVtbl *InputProcessorProfileSubstituteLayoutVtbl; */
70 LONG refCount;
72 LANGID currentLanguage;
74 struct list LanguageProfileNotifySink;
75 } InputProcessorProfiles;
77 typedef struct tagProfilesEnumGuid {
78 IEnumGUID IEnumGUID_iface;
79 LONG refCount;
81 HKEY key;
82 DWORD next_index;
83 } ProfilesEnumGuid;
85 typedef struct tagEnumTfLanguageProfiles {
86 IEnumTfLanguageProfiles IEnumTfLanguageProfiles_iface;
87 LONG refCount;
89 HKEY tipkey;
90 DWORD tip_index;
91 WCHAR szwCurrentClsid[39];
93 HKEY langkey;
94 DWORD lang_index;
96 LANGID langid;
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_ITfInputProcessorProfiles(ITfInputProcessorProfiles *iface)
105 return CONTAINING_RECORD(iface, InputProcessorProfiles, ITfInputProcessorProfiles_iface);
108 static inline InputProcessorProfiles *impl_from_ITfSource(ITfSource *iface)
110 return CONTAINING_RECORD(iface, InputProcessorProfiles, ITfSource_iface);
113 static inline ProfilesEnumGuid *impl_from_IEnumGUID(IEnumGUID *iface)
115 return CONTAINING_RECORD(iface, ProfilesEnumGuid, IEnumGUID_iface);
118 static inline EnumTfLanguageProfiles *impl_from_IEnumTfLanguageProfiles(IEnumTfLanguageProfiles *iface)
120 return CONTAINING_RECORD(iface, EnumTfLanguageProfiles, IEnumTfLanguageProfiles_iface);
123 static void free_sink(InputProcessorProfilesSink *sink)
125 IUnknown_Release(sink->interfaces.pIUnknown);
126 HeapFree(GetProcessHeap(),0,sink);
129 static void InputProcessorProfiles_Destructor(InputProcessorProfiles *This)
131 struct list *cursor, *cursor2;
132 TRACE("destroying %p\n", This);
134 /* free sinks */
135 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->LanguageProfileNotifySink)
137 InputProcessorProfilesSink* sink = LIST_ENTRY(cursor,InputProcessorProfilesSink,entry);
138 list_remove(cursor);
139 free_sink(sink);
142 HeapFree(GetProcessHeap(),0,This);
145 static void add_userkey( REFCLSID rclsid, LANGID langid,
146 REFGUID guidProfile)
148 HKEY key;
149 WCHAR buf[39];
150 WCHAR buf2[39];
151 WCHAR fullkey[168];
152 DWORD disposition = 0;
153 ULONG res;
155 TRACE("\n");
157 StringFromGUID2(rclsid, buf, 39);
158 StringFromGUID2(guidProfile, buf2, 39);
159 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
161 res = RegCreateKeyExW(HKEY_CURRENT_USER,fullkey, 0, NULL, 0,
162 KEY_READ | KEY_WRITE, NULL, &key, &disposition);
164 if (!res && disposition == REG_CREATED_NEW_KEY)
166 DWORD zero = 0x0;
167 RegSetValueExW(key, szwEnable, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
170 if (!res)
171 RegCloseKey(key);
174 static HRESULT WINAPI InputProcessorProfiles_QueryInterface(ITfInputProcessorProfiles *iface, REFIID iid, void **ppv)
176 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
178 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfInputProcessorProfiles))
180 *ppv = &This->ITfInputProcessorProfiles_iface;
182 else if (IsEqualIID(iid, &IID_ITfInputProcessorProfileMgr))
184 *ppv = &This->ITfInputProcessorProfileMgr_iface;
186 else if (IsEqualIID(iid, &IID_ITfSource))
188 *ppv = &This->ITfSource_iface;
190 else
192 *ppv = NULL;
193 WARN("unsupported interface: %s\n", debugstr_guid(iid));
194 return E_NOINTERFACE;
197 ITfInputProcessorProfiles_AddRef(iface);
198 return S_OK;
201 static ULONG WINAPI InputProcessorProfiles_AddRef(ITfInputProcessorProfiles *iface)
203 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
204 return InterlockedIncrement(&This->refCount);
207 static ULONG WINAPI InputProcessorProfiles_Release(ITfInputProcessorProfiles *iface)
209 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
210 ULONG ret;
212 ret = InterlockedDecrement(&This->refCount);
213 if (ret == 0)
214 InputProcessorProfiles_Destructor(This);
215 return ret;
218 /*****************************************************
219 * ITfInputProcessorProfiles functions
220 *****************************************************/
221 static HRESULT WINAPI InputProcessorProfiles_Register(
222 ITfInputProcessorProfiles *iface, REFCLSID rclsid)
224 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
225 HKEY tipkey;
226 WCHAR buf[39];
227 WCHAR fullkey[68];
229 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
231 StringFromGUID2(rclsid, buf, 39);
232 sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
234 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, NULL, 0,
235 KEY_READ | KEY_WRITE, NULL, &tipkey, NULL) != ERROR_SUCCESS)
236 return E_FAIL;
238 RegCloseKey(tipkey);
240 return S_OK;
243 static HRESULT WINAPI InputProcessorProfiles_Unregister(
244 ITfInputProcessorProfiles *iface, REFCLSID rclsid)
246 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
247 WCHAR buf[39];
248 WCHAR fullkey[68];
250 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
252 StringFromGUID2(rclsid, buf, 39);
253 sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
255 RegDeleteTreeW(HKEY_LOCAL_MACHINE, fullkey);
256 RegDeleteTreeW(HKEY_CURRENT_USER, fullkey);
258 return S_OK;
261 static HRESULT WINAPI InputProcessorProfiles_AddLanguageProfile(
262 ITfInputProcessorProfiles *iface, REFCLSID rclsid,
263 LANGID langid, REFGUID guidProfile, const WCHAR *pchDesc,
264 ULONG cchDesc, const WCHAR *pchIconFile, ULONG cchFile,
265 ULONG uIconIndex)
267 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
268 HKEY tipkey,fmtkey;
269 WCHAR buf[39];
270 WCHAR fullkey[100];
271 ULONG res;
272 DWORD disposition = 0;
274 static const WCHAR fmt2[] = {'%','s','\\','0','x','%','0','8','x','\\','%','s',0};
275 static const WCHAR desc[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
276 static const WCHAR icnf[] = {'I','c','o','n','F','i','l','e',0};
277 static const WCHAR icni[] = {'I','c','o','n','I','n','d','e','x',0};
279 TRACE("(%p) %s %x %s %s %s %i\n",This,debugstr_guid(rclsid), langid,
280 debugstr_guid(guidProfile), debugstr_wn(pchDesc,cchDesc),
281 debugstr_wn(pchIconFile,cchFile),uIconIndex);
283 StringFromGUID2(rclsid, buf, 39);
284 sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
286 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE,
287 &tipkey ) != ERROR_SUCCESS)
288 return E_FAIL;
290 StringFromGUID2(guidProfile, buf, 39);
291 sprintfW(fullkey,fmt2,szwLngp,langid,buf);
293 res = RegCreateKeyExW(tipkey,fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
294 NULL, &fmtkey, &disposition);
296 if (!res)
298 DWORD zero = 0x0;
299 RegSetValueExW(fmtkey, desc, 0, REG_SZ, (const BYTE*)pchDesc, cchDesc * sizeof(WCHAR));
300 RegSetValueExW(fmtkey, icnf, 0, REG_SZ, (const BYTE*)pchIconFile, cchFile * sizeof(WCHAR));
301 RegSetValueExW(fmtkey, icni, 0, REG_DWORD, (LPBYTE)&uIconIndex, sizeof(DWORD));
302 if (disposition == REG_CREATED_NEW_KEY)
303 RegSetValueExW(fmtkey, szwEnable, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
304 RegCloseKey(fmtkey);
306 add_userkey(rclsid, langid, guidProfile);
308 RegCloseKey(tipkey);
310 if (!res)
311 return S_OK;
312 else
313 return E_FAIL;
316 static HRESULT WINAPI InputProcessorProfiles_RemoveLanguageProfile(
317 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
318 REFGUID guidProfile)
320 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
321 FIXME("STUB:(%p)\n",This);
322 return E_NOTIMPL;
325 static HRESULT WINAPI InputProcessorProfiles_EnumInputProcessorInfo(
326 ITfInputProcessorProfiles *iface, IEnumGUID **ppEnum)
328 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
329 TRACE("(%p) %p\n",This,ppEnum);
330 return ProfilesEnumGuid_Constructor(ppEnum);
333 static HRESULT WINAPI InputProcessorProfiles_GetDefaultLanguageProfile(
334 ITfInputProcessorProfiles *iface, LANGID langid, REFGUID catid,
335 CLSID *pclsid, GUID *pguidProfile)
337 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
338 WCHAR fullkey[168];
339 WCHAR buf[39];
340 HKEY hkey;
341 DWORD count;
342 ULONG res;
344 TRACE("%p) %x %s %p %p\n",This, langid, debugstr_guid(catid),pclsid,pguidProfile);
346 if (!catid || !pclsid || !pguidProfile)
347 return E_INVALIDARG;
349 StringFromGUID2(catid, buf, 39);
350 sprintfW(fullkey, szwDefaultFmt, szwSystemCTFKey, szwAssemblies, langid, buf);
352 if (RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE,
353 &hkey ) != ERROR_SUCCESS)
354 return S_FALSE;
356 count = sizeof(buf);
357 res = RegQueryValueExW(hkey, szwDefault, 0, NULL, (LPBYTE)buf, &count);
358 if (res != ERROR_SUCCESS)
360 RegCloseKey(hkey);
361 return S_FALSE;
363 CLSIDFromString(buf,pclsid);
365 res = RegQueryValueExW(hkey, szwProfile, 0, NULL, (LPBYTE)buf, &count);
366 if (res == ERROR_SUCCESS)
367 CLSIDFromString(buf,pguidProfile);
369 RegCloseKey(hkey);
371 return S_OK;
374 static HRESULT WINAPI InputProcessorProfiles_SetDefaultLanguageProfile(
375 ITfInputProcessorProfiles *iface, LANGID langid, REFCLSID rclsid,
376 REFGUID guidProfiles)
378 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
379 WCHAR fullkey[168];
380 WCHAR buf[39];
381 HKEY hkey;
382 GUID catid;
383 HRESULT hr;
384 ITfCategoryMgr *catmgr;
385 static const GUID * tipcats[3] = { &GUID_TFCAT_TIP_KEYBOARD,
386 &GUID_TFCAT_TIP_SPEECH,
387 &GUID_TFCAT_TIP_HANDWRITING };
389 TRACE("%p) %x %s %s\n",This, langid, debugstr_guid(rclsid),debugstr_guid(guidProfiles));
391 if (!rclsid || !guidProfiles)
392 return E_INVALIDARG;
394 hr = CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
396 if (FAILED(hr))
397 return hr;
399 if (ITfCategoryMgr_FindClosestCategory(catmgr, rclsid,
400 &catid, tipcats, 3) != S_OK)
401 hr = ITfCategoryMgr_FindClosestCategory(catmgr, rclsid,
402 &catid, NULL, 0);
403 ITfCategoryMgr_Release(catmgr);
405 if (FAILED(hr))
406 return E_FAIL;
408 StringFromGUID2(&catid, buf, 39);
409 sprintfW(fullkey, szwDefaultFmt, szwSystemCTFKey, szwAssemblies, langid, buf);
411 if (RegCreateKeyExW(HKEY_CURRENT_USER, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
412 NULL, &hkey, NULL ) != ERROR_SUCCESS)
413 return E_FAIL;
415 StringFromGUID2(rclsid, buf, 39);
416 RegSetValueExW(hkey, szwDefault, 0, REG_SZ, (LPBYTE)buf, sizeof(buf));
417 StringFromGUID2(guidProfiles, buf, 39);
418 RegSetValueExW(hkey, szwProfile, 0, REG_SZ, (LPBYTE)buf, sizeof(buf));
419 RegCloseKey(hkey);
421 return S_OK;
424 static HRESULT WINAPI InputProcessorProfiles_ActivateLanguageProfile(
425 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
426 REFGUID guidProfiles)
428 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
429 HRESULT hr;
430 BOOL enabled;
431 TF_LANGUAGEPROFILE LanguageProfile;
433 TRACE("(%p) %s %x %s\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfiles));
435 if (langid != This->currentLanguage) return E_INVALIDARG;
437 if (get_active_textservice(rclsid,NULL))
439 TRACE("Already Active\n");
440 return E_FAIL;
443 hr = ITfInputProcessorProfiles_IsEnabledLanguageProfile(iface, rclsid,
444 langid, guidProfiles, &enabled);
445 if (FAILED(hr) || !enabled)
447 TRACE("Not Enabled\n");
448 return E_FAIL;
451 LanguageProfile.clsid = *rclsid;
452 LanguageProfile.langid = langid;
453 LanguageProfile.guidProfile = *guidProfiles;
455 hr = add_active_textservice(&LanguageProfile);
457 return hr;
460 static HRESULT WINAPI InputProcessorProfiles_GetActiveLanguageProfile(
461 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID *plangid,
462 GUID *pguidProfile)
464 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
465 TF_LANGUAGEPROFILE profile;
467 TRACE("(%p) %s %p %p\n",This,debugstr_guid(rclsid),plangid,pguidProfile);
469 if (!rclsid || !plangid || !pguidProfile)
470 return E_INVALIDARG;
472 if (get_active_textservice(rclsid, &profile))
474 *plangid = profile.langid;
475 *pguidProfile = profile.guidProfile;
476 return S_OK;
478 else
480 *pguidProfile = GUID_NULL;
481 return S_FALSE;
485 static HRESULT WINAPI InputProcessorProfiles_GetLanguageProfileDescription(
486 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
487 REFGUID guidProfile, BSTR *pbstrProfile)
489 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
490 FIXME("STUB:(%p)\n",This);
491 return E_NOTIMPL;
494 static HRESULT WINAPI InputProcessorProfiles_GetCurrentLanguage(
495 ITfInputProcessorProfiles *iface, LANGID *plangid)
497 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
498 TRACE("(%p) 0x%x\n",This,This->currentLanguage);
500 if (!plangid)
501 return E_INVALIDARG;
503 *plangid = This->currentLanguage;
505 return S_OK;
508 static HRESULT WINAPI InputProcessorProfiles_ChangeCurrentLanguage(
509 ITfInputProcessorProfiles *iface, LANGID langid)
511 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
512 struct list *cursor;
513 BOOL accept;
515 FIXME("STUB:(%p)\n",This);
517 LIST_FOR_EACH(cursor, &This->LanguageProfileNotifySink)
519 InputProcessorProfilesSink* sink = LIST_ENTRY(cursor,InputProcessorProfilesSink,entry);
520 accept = TRUE;
521 ITfLanguageProfileNotifySink_OnLanguageChange(sink->interfaces.pITfLanguageProfileNotifySink, langid, &accept);
522 if (!accept)
523 return E_FAIL;
526 /* TODO: On successful language change call OnLanguageChanged sink */
527 return E_NOTIMPL;
530 static HRESULT WINAPI InputProcessorProfiles_GetLanguageList(
531 ITfInputProcessorProfiles *iface, LANGID **ppLangId, ULONG *pulCount)
533 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
534 FIXME("Semi-STUB:(%p)\n",This);
535 *ppLangId = CoTaskMemAlloc(sizeof(LANGID));
536 **ppLangId = This->currentLanguage;
537 *pulCount = 1;
538 return S_OK;
541 static HRESULT WINAPI InputProcessorProfiles_EnumLanguageProfiles(
542 ITfInputProcessorProfiles *iface, LANGID langid,
543 IEnumTfLanguageProfiles **ppEnum)
545 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
546 TRACE("(%p) %x %p\n",This,langid,ppEnum);
547 return EnumTfLanguageProfiles_Constructor(langid, ppEnum);
550 static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfile(
551 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
552 REFGUID guidProfile, BOOL fEnable)
554 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
555 HKEY key;
556 WCHAR buf[39];
557 WCHAR buf2[39];
558 WCHAR fullkey[168];
559 ULONG res;
561 TRACE("(%p) %s %x %s %i\n",This, debugstr_guid(rclsid), langid, debugstr_guid(guidProfile), fEnable);
563 StringFromGUID2(rclsid, buf, 39);
564 StringFromGUID2(guidProfile, buf2, 39);
565 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
567 res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key);
569 if (!res)
571 RegSetValueExW(key, szwEnable, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
572 RegCloseKey(key);
574 else
575 return E_FAIL;
577 return S_OK;
580 static HRESULT WINAPI InputProcessorProfiles_IsEnabledLanguageProfile(
581 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
582 REFGUID guidProfile, BOOL *pfEnable)
584 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
585 HKEY key;
586 WCHAR buf[39];
587 WCHAR buf2[39];
588 WCHAR fullkey[168];
589 ULONG res;
591 TRACE("(%p) %s, %i, %s, %p\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),pfEnable);
593 if (!pfEnable)
594 return E_INVALIDARG;
596 StringFromGUID2(rclsid, buf, 39);
597 StringFromGUID2(guidProfile, buf2, 39);
598 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
600 res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key);
602 if (!res)
604 DWORD count = sizeof(DWORD);
605 res = RegQueryValueExW(key, szwEnable, 0, NULL, (LPBYTE)pfEnable, &count);
606 RegCloseKey(key);
609 if (res) /* Try Default */
611 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key);
613 if (!res)
615 DWORD count = sizeof(DWORD);
616 res = RegQueryValueExW(key, szwEnable, 0, NULL, (LPBYTE)pfEnable, &count);
617 RegCloseKey(key);
621 if (!res)
622 return S_OK;
623 else
624 return E_FAIL;
627 static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfileByDefault(
628 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
629 REFGUID guidProfile, BOOL fEnable)
631 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
632 HKEY key;
633 WCHAR buf[39];
634 WCHAR buf2[39];
635 WCHAR fullkey[168];
636 ULONG res;
638 TRACE("(%p) %s %x %s %i\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),fEnable);
640 StringFromGUID2(rclsid, buf, 39);
641 StringFromGUID2(guidProfile, buf2, 39);
642 sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
644 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key);
646 if (!res)
648 RegSetValueExW(key, szwEnable, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
649 RegCloseKey(key);
651 else
652 return E_FAIL;
654 return S_OK;
657 static HRESULT WINAPI InputProcessorProfiles_SubstituteKeyboardLayout(
658 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
659 REFGUID guidProfile, HKL hKL)
661 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface);
662 FIXME("STUB:(%p)\n",This);
663 return E_NOTIMPL;
666 static const ITfInputProcessorProfilesVtbl InputProcessorProfilesVtbl =
668 InputProcessorProfiles_QueryInterface,
669 InputProcessorProfiles_AddRef,
670 InputProcessorProfiles_Release,
671 InputProcessorProfiles_Register,
672 InputProcessorProfiles_Unregister,
673 InputProcessorProfiles_AddLanguageProfile,
674 InputProcessorProfiles_RemoveLanguageProfile,
675 InputProcessorProfiles_EnumInputProcessorInfo,
676 InputProcessorProfiles_GetDefaultLanguageProfile,
677 InputProcessorProfiles_SetDefaultLanguageProfile,
678 InputProcessorProfiles_ActivateLanguageProfile,
679 InputProcessorProfiles_GetActiveLanguageProfile,
680 InputProcessorProfiles_GetLanguageProfileDescription,
681 InputProcessorProfiles_GetCurrentLanguage,
682 InputProcessorProfiles_ChangeCurrentLanguage,
683 InputProcessorProfiles_GetLanguageList,
684 InputProcessorProfiles_EnumLanguageProfiles,
685 InputProcessorProfiles_EnableLanguageProfile,
686 InputProcessorProfiles_IsEnabledLanguageProfile,
687 InputProcessorProfiles_EnableLanguageProfileByDefault,
688 InputProcessorProfiles_SubstituteKeyboardLayout
691 static inline InputProcessorProfiles *impl_from_ITfInputProcessorProfileMgr(ITfInputProcessorProfileMgr *iface)
693 return CONTAINING_RECORD(iface, InputProcessorProfiles, ITfInputProcessorProfileMgr_iface);
696 static HRESULT WINAPI InputProcessorProfileMgr_QueryInterface(ITfInputProcessorProfileMgr *iface, REFIID riid, void **ppv)
698 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface);
699 return ITfInputProcessorProfiles_QueryInterface(&This->ITfInputProcessorProfiles_iface, riid, ppv);
702 static ULONG WINAPI InputProcessorProfileMgr_AddRef(ITfInputProcessorProfileMgr *iface)
704 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface);
705 return ITfInputProcessorProfiles_AddRef(&This->ITfInputProcessorProfiles_iface);
708 static ULONG WINAPI InputProcessorProfileMgr_Release(ITfInputProcessorProfileMgr *iface)
710 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface);
711 return ITfInputProcessorProfiles_Release(&This->ITfInputProcessorProfiles_iface);
714 static HRESULT WINAPI InputProcessorProfileMgr_ActivateProfile(ITfInputProcessorProfileMgr *iface, DWORD dwProfileType,
715 LANGID langid, REFCLSID clsid, REFGUID guidProfile, HKL hkl, DWORD dwFlags)
717 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface);
718 FIXME("(%p)->(%d %x %s %s %p %x)\n", This, dwProfileType, langid, debugstr_guid(clsid),
719 debugstr_guid(guidProfile), hkl, dwFlags);
720 return E_NOTIMPL;
723 static HRESULT WINAPI InputProcessorProfileMgr_DeactivateProfile(ITfInputProcessorProfileMgr *iface, DWORD dwProfileType,
724 LANGID langid, REFCLSID clsid, REFGUID guidProfile, HKL hkl, DWORD dwFlags)
726 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface);
727 FIXME("(%p)->(%d %x %s %s %p %x)\n", This, dwProfileType, langid, debugstr_guid(clsid),
728 debugstr_guid(guidProfile), hkl, dwFlags);
729 return E_NOTIMPL;
732 static HRESULT WINAPI InputProcessorProfileMgr_GetProfile(ITfInputProcessorProfileMgr *iface, DWORD dwProfileType,
733 LANGID langid, REFCLSID clsid, REFGUID guidProfile, HKL hkl, TF_INPUTPROCESSORPROFILE *pProfile)
735 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface);
736 FIXME("(%p)->(%d %x %s %s %p %p)\n", This, dwProfileType, langid, debugstr_guid(clsid),
737 debugstr_guid(guidProfile), hkl, pProfile);
738 return E_NOTIMPL;
741 static HRESULT WINAPI InputProcessorProfileMgr_EnumProfiles(ITfInputProcessorProfileMgr *iface, LANGID langid,
742 IEnumTfInputProcessorProfiles **ppEnum)
744 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface);
745 FIXME("(%p)->(%x %p)\n", This, langid, ppEnum);
746 return E_NOTIMPL;
749 static HRESULT WINAPI InputProcessorProfileMgr_ReleaseInputProcessor(ITfInputProcessorProfileMgr *iface, REFCLSID rclsid,
750 DWORD dwFlags)
752 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface);
753 FIXME("(%p)->(%s %x)\n", This, debugstr_guid(rclsid), dwFlags);
754 return E_NOTIMPL;
757 static HRESULT WINAPI InputProcessorProfileMgr_RegisterProfile(ITfInputProcessorProfileMgr *iface, REFCLSID rclsid,
758 LANGID langid, REFGUID guidProfile, const WCHAR *pchDesc, ULONG cchDesc, const WCHAR *pchIconFile,
759 ULONG cchFile, ULONG uIconIndex, HKL hklsubstitute, DWORD dwPreferredLayout, BOOL bEnabledByDefault,
760 DWORD dwFlags)
762 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface);
763 FIXME("(%p)->(%s %x %s %s %d %s %u %u %p %x %x %x)\n", This, debugstr_guid(rclsid), langid, debugstr_guid(guidProfile),
764 debugstr_w(pchDesc), cchDesc, debugstr_w(pchIconFile), cchFile, uIconIndex, hklsubstitute, dwPreferredLayout,
765 bEnabledByDefault, dwFlags);
766 return E_NOTIMPL;
769 static HRESULT WINAPI InputProcessorProfileMgr_UnregisterProfile(ITfInputProcessorProfileMgr *iface, REFCLSID rclsid,
770 LANGID langid, REFGUID guidProfile, DWORD dwFlags)
772 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface);
773 FIXME("(%p)->(%s %x %s %x)\n", This, debugstr_guid(rclsid), langid, debugstr_guid(guidProfile), dwFlags);
774 return E_NOTIMPL;
777 static HRESULT WINAPI InputProcessorProfileMgr_GetActiveProfile(ITfInputProcessorProfileMgr *iface, REFGUID catid,
778 TF_INPUTPROCESSORPROFILE *pProfile)
780 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface);
781 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(catid), pProfile);
782 return E_NOTIMPL;
785 static const ITfInputProcessorProfileMgrVtbl InputProcessorProfileMgrVtbl = {
786 InputProcessorProfileMgr_QueryInterface,
787 InputProcessorProfileMgr_AddRef,
788 InputProcessorProfileMgr_Release,
789 InputProcessorProfileMgr_ActivateProfile,
790 InputProcessorProfileMgr_DeactivateProfile,
791 InputProcessorProfileMgr_GetProfile,
792 InputProcessorProfileMgr_EnumProfiles,
793 InputProcessorProfileMgr_ReleaseInputProcessor,
794 InputProcessorProfileMgr_RegisterProfile,
795 InputProcessorProfileMgr_UnregisterProfile,
796 InputProcessorProfileMgr_GetActiveProfile
799 /*****************************************************
800 * ITfSource functions
801 *****************************************************/
802 static HRESULT WINAPI IPPSource_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
804 InputProcessorProfiles *This = impl_from_ITfSource(iface);
805 return ITfInputProcessorProfiles_QueryInterface(&This->ITfInputProcessorProfiles_iface, iid, ppvOut);
808 static ULONG WINAPI IPPSource_AddRef(ITfSource *iface)
810 InputProcessorProfiles *This = impl_from_ITfSource(iface);
811 return ITfInputProcessorProfiles_AddRef(&This->ITfInputProcessorProfiles_iface);
814 static ULONG WINAPI IPPSource_Release(ITfSource *iface)
816 InputProcessorProfiles *This = impl_from_ITfSource(iface);
817 return ITfInputProcessorProfiles_Release(&This->ITfInputProcessorProfiles_iface);
820 static HRESULT WINAPI IPPSource_AdviseSink(ITfSource *iface,
821 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
823 InputProcessorProfiles *This = impl_from_ITfSource(iface);
824 InputProcessorProfilesSink *ipps;
826 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
828 if (!riid || !punk || !pdwCookie)
829 return E_INVALIDARG;
831 if (IsEqualIID(riid, &IID_ITfLanguageProfileNotifySink))
833 ipps = HeapAlloc(GetProcessHeap(),0,sizeof(InputProcessorProfilesSink));
834 if (!ipps)
835 return E_OUTOFMEMORY;
836 if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&ipps->interfaces.pITfLanguageProfileNotifySink)))
838 HeapFree(GetProcessHeap(),0,ipps);
839 return CONNECT_E_CANNOTCONNECT;
841 list_add_head(&This->LanguageProfileNotifySink,&ipps->entry);
842 *pdwCookie = generate_Cookie(COOKIE_MAGIC_IPPSINK, ipps);
844 else
846 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
847 return E_NOTIMPL;
850 TRACE("cookie %x\n",*pdwCookie);
852 return S_OK;
855 static HRESULT WINAPI IPPSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
857 InputProcessorProfiles *This = impl_from_ITfSource(iface);
858 InputProcessorProfilesSink *sink;
860 TRACE("(%p) %x\n",This,pdwCookie);
862 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_IPPSINK)
863 return E_INVALIDARG;
865 sink = remove_Cookie(pdwCookie);
866 if (!sink)
867 return CONNECT_E_NOCONNECTION;
869 list_remove(&sink->entry);
870 free_sink(sink);
872 return S_OK;
875 static const ITfSourceVtbl InputProcessorProfilesSourceVtbl =
877 IPPSource_QueryInterface,
878 IPPSource_AddRef,
879 IPPSource_Release,
880 IPPSource_AdviseSink,
881 IPPSource_UnadviseSink,
884 HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
886 InputProcessorProfiles *This;
887 if (pUnkOuter)
888 return CLASS_E_NOAGGREGATION;
890 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputProcessorProfiles));
891 if (This == NULL)
892 return E_OUTOFMEMORY;
894 This->ITfInputProcessorProfiles_iface.lpVtbl= &InputProcessorProfilesVtbl;
895 This->ITfSource_iface.lpVtbl = &InputProcessorProfilesSourceVtbl;
896 This->ITfInputProcessorProfileMgr_iface.lpVtbl = &InputProcessorProfileMgrVtbl;
897 This->refCount = 1;
898 This->currentLanguage = GetUserDefaultLCID();
900 list_init(&This->LanguageProfileNotifySink);
902 *ppOut = (IUnknown *)&This->ITfInputProcessorProfiles_iface;
903 TRACE("returning %p\n", *ppOut);
904 return S_OK;
907 /**************************************************
908 * IEnumGUID implementation for ITfInputProcessorProfiles::EnumInputProcessorInfo
909 **************************************************/
910 static void ProfilesEnumGuid_Destructor(ProfilesEnumGuid *This)
912 TRACE("destroying %p\n", This);
913 RegCloseKey(This->key);
914 HeapFree(GetProcessHeap(),0,This);
917 static HRESULT WINAPI ProfilesEnumGuid_QueryInterface(IEnumGUID *iface, REFIID iid, LPVOID *ppvOut)
919 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface);
920 *ppvOut = NULL;
922 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumGUID))
924 *ppvOut = &This->IEnumGUID_iface;
927 if (*ppvOut)
929 IEnumGUID_AddRef(iface);
930 return S_OK;
933 WARN("unsupported interface: %s\n", debugstr_guid(iid));
934 return E_NOINTERFACE;
937 static ULONG WINAPI ProfilesEnumGuid_AddRef(IEnumGUID *iface)
939 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface);
940 return InterlockedIncrement(&This->refCount);
943 static ULONG WINAPI ProfilesEnumGuid_Release(IEnumGUID *iface)
945 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface);
946 ULONG ret;
948 ret = InterlockedDecrement(&This->refCount);
949 if (ret == 0)
950 ProfilesEnumGuid_Destructor(This);
951 return ret;
954 /*****************************************************
955 * IEnumGuid functions
956 *****************************************************/
957 static HRESULT WINAPI ProfilesEnumGuid_Next( LPENUMGUID iface,
958 ULONG celt, GUID *rgelt, ULONG *pceltFetched)
960 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface);
961 ULONG fetched = 0;
963 TRACE("(%p)\n",This);
965 if (rgelt == NULL) return E_POINTER;
967 if (This->key) while (fetched < celt)
969 LSTATUS res;
970 HRESULT hr;
971 WCHAR catid[39];
972 DWORD cName = 39;
974 res = RegEnumKeyExW(This->key, This->next_index, catid, &cName,
975 NULL, NULL, NULL, NULL);
976 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
977 ++(This->next_index);
979 hr = CLSIDFromString(catid, rgelt);
980 if (FAILED(hr)) continue;
982 ++fetched;
983 ++rgelt;
986 if (pceltFetched) *pceltFetched = fetched;
987 return fetched == celt ? S_OK : S_FALSE;
990 static HRESULT WINAPI ProfilesEnumGuid_Skip( LPENUMGUID iface, ULONG celt)
992 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface);
993 TRACE("(%p)\n",This);
995 This->next_index += celt;
996 return S_OK;
999 static HRESULT WINAPI ProfilesEnumGuid_Reset( LPENUMGUID iface)
1001 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface);
1002 TRACE("(%p)\n",This);
1003 This->next_index = 0;
1004 return S_OK;
1007 static HRESULT WINAPI ProfilesEnumGuid_Clone( LPENUMGUID iface,
1008 IEnumGUID **ppenum)
1010 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface);
1011 HRESULT res;
1013 TRACE("(%p)\n",This);
1015 if (ppenum == NULL) return E_POINTER;
1017 res = ProfilesEnumGuid_Constructor(ppenum);
1018 if (SUCCEEDED(res))
1020 ProfilesEnumGuid *new_This = impl_from_IEnumGUID(*ppenum);
1021 new_This->next_index = This->next_index;
1023 return res;
1026 static const IEnumGUIDVtbl EnumGUIDVtbl =
1028 ProfilesEnumGuid_QueryInterface,
1029 ProfilesEnumGuid_AddRef,
1030 ProfilesEnumGuid_Release,
1031 ProfilesEnumGuid_Next,
1032 ProfilesEnumGuid_Skip,
1033 ProfilesEnumGuid_Reset,
1034 ProfilesEnumGuid_Clone
1037 static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut)
1039 ProfilesEnumGuid *This;
1041 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ProfilesEnumGuid));
1042 if (This == NULL)
1043 return E_OUTOFMEMORY;
1045 This->IEnumGUID_iface.lpVtbl= &EnumGUIDVtbl;
1046 This->refCount = 1;
1048 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0,
1049 KEY_READ | KEY_WRITE, NULL, &This->key, NULL) != ERROR_SUCCESS)
1051 HeapFree(GetProcessHeap(), 0, This);
1052 return E_FAIL;
1055 *ppOut = &This->IEnumGUID_iface;
1056 TRACE("returning %p\n", *ppOut);
1057 return S_OK;
1060 /**************************************************
1061 * IEnumTfLanguageProfiles implementation
1062 **************************************************/
1063 static void EnumTfLanguageProfiles_Destructor(EnumTfLanguageProfiles *This)
1065 TRACE("destroying %p\n", This);
1066 RegCloseKey(This->tipkey);
1067 if (This->langkey)
1068 RegCloseKey(This->langkey);
1069 ITfCategoryMgr_Release(This->catmgr);
1070 HeapFree(GetProcessHeap(),0,This);
1073 static HRESULT WINAPI EnumTfLanguageProfiles_QueryInterface(IEnumTfLanguageProfiles *iface, REFIID iid, LPVOID *ppvOut)
1075 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface);
1077 *ppvOut = NULL;
1079 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfLanguageProfiles))
1081 *ppvOut = &This->IEnumTfLanguageProfiles_iface;
1084 if (*ppvOut)
1086 IEnumTfLanguageProfiles_AddRef(iface);
1087 return S_OK;
1090 WARN("unsupported interface: %s\n", debugstr_guid(iid));
1091 return E_NOINTERFACE;
1094 static ULONG WINAPI EnumTfLanguageProfiles_AddRef(IEnumTfLanguageProfiles *iface)
1096 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface);
1097 return InterlockedIncrement(&This->refCount);
1100 static ULONG WINAPI EnumTfLanguageProfiles_Release(IEnumTfLanguageProfiles *iface)
1102 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface);
1103 ULONG ret;
1105 ret = InterlockedDecrement(&This->refCount);
1106 if (ret == 0)
1107 EnumTfLanguageProfiles_Destructor(This);
1108 return ret;
1111 /*****************************************************
1112 * IEnumGuid functions
1113 *****************************************************/
1114 static INT next_LanguageProfile(EnumTfLanguageProfiles *This, CLSID clsid, TF_LANGUAGEPROFILE *tflp)
1116 WCHAR fullkey[168];
1117 ULONG res;
1118 WCHAR profileid[39];
1119 DWORD cName = 39;
1120 GUID profile;
1122 static const WCHAR fmt[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
1124 if (This->langkey == NULL)
1126 sprintfW(fullkey,fmt,This->szwCurrentClsid,szwLngp,This->langid);
1127 res = RegOpenKeyExW(This->tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &This->langkey);
1128 if (res)
1130 This->langkey = NULL;
1131 return -1;
1133 This->lang_index = 0;
1135 res = RegEnumKeyExW(This->langkey, This->lang_index, profileid, &cName,
1136 NULL, NULL, NULL, NULL);
1137 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
1139 RegCloseKey(This->langkey);
1140 This->langkey = NULL;
1141 return -1;
1143 ++(This->lang_index);
1145 if (tflp)
1147 static const GUID * tipcats[3] = { &GUID_TFCAT_TIP_KEYBOARD,
1148 &GUID_TFCAT_TIP_SPEECH,
1149 &GUID_TFCAT_TIP_HANDWRITING };
1150 res = CLSIDFromString(profileid, &profile);
1151 if (FAILED(res)) return 0;
1153 tflp->clsid = clsid;
1154 tflp->langid = This->langid;
1155 tflp->fActive = get_active_textservice(&clsid, NULL);
1156 tflp->guidProfile = profile;
1157 if (ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid,
1158 &tflp->catid, tipcats, 3) != S_OK)
1159 ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid,
1160 &tflp->catid, NULL, 0);
1163 return 1;
1166 static HRESULT WINAPI EnumTfLanguageProfiles_Next(IEnumTfLanguageProfiles *iface,
1167 ULONG ulCount, TF_LANGUAGEPROFILE *pProfile, ULONG *pcFetch)
1169 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface);
1170 ULONG fetched = 0;
1172 TRACE("(%p)\n",This);
1174 if (pProfile == NULL) return E_POINTER;
1176 if (This->tipkey) while (fetched < ulCount)
1178 LSTATUS res;
1179 HRESULT hr;
1180 DWORD cName = 39;
1181 GUID clsid;
1183 res = RegEnumKeyExW(This->tipkey, This->tip_index,
1184 This->szwCurrentClsid, &cName, NULL, NULL, NULL, NULL);
1185 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
1186 ++(This->tip_index);
1187 hr = CLSIDFromString(This->szwCurrentClsid, &clsid);
1188 if (FAILED(hr)) continue;
1190 while ( fetched < ulCount)
1192 INT res = next_LanguageProfile(This, clsid, pProfile);
1193 if (res == 1)
1195 ++fetched;
1196 ++pProfile;
1198 else if (res == -1)
1199 break;
1200 else
1201 continue;
1205 if (pcFetch) *pcFetch = fetched;
1206 return fetched == ulCount ? S_OK : S_FALSE;
1209 static HRESULT WINAPI EnumTfLanguageProfiles_Skip( IEnumTfLanguageProfiles* iface, ULONG celt)
1211 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface);
1212 FIXME("STUB (%p)\n",This);
1213 return E_NOTIMPL;
1216 static HRESULT WINAPI EnumTfLanguageProfiles_Reset( IEnumTfLanguageProfiles* iface)
1218 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface);
1219 TRACE("(%p)\n",This);
1220 This->tip_index = 0;
1221 if (This->langkey)
1222 RegCloseKey(This->langkey);
1223 This->langkey = NULL;
1224 This->lang_index = 0;
1225 return S_OK;
1228 static HRESULT WINAPI EnumTfLanguageProfiles_Clone( IEnumTfLanguageProfiles *iface,
1229 IEnumTfLanguageProfiles **ppenum)
1231 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface);
1232 HRESULT res;
1234 TRACE("(%p)\n",This);
1236 if (ppenum == NULL) return E_POINTER;
1238 res = EnumTfLanguageProfiles_Constructor(This->langid, ppenum);
1239 if (SUCCEEDED(res))
1241 EnumTfLanguageProfiles *new_This = (EnumTfLanguageProfiles *)*ppenum;
1242 new_This->tip_index = This->tip_index;
1243 lstrcpynW(new_This->szwCurrentClsid,This->szwCurrentClsid,39);
1245 if (This->langkey)
1247 WCHAR fullkey[168];
1248 static const WCHAR fmt[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0};
1250 sprintfW(fullkey,fmt,This->szwCurrentClsid,szwLngp,This->langid);
1251 res = RegOpenKeyExW(new_This->tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &This->langkey);
1252 new_This->lang_index = This->lang_index;
1255 return res;
1258 static const IEnumTfLanguageProfilesVtbl EnumTfLanguageProfilesVtbl =
1260 EnumTfLanguageProfiles_QueryInterface,
1261 EnumTfLanguageProfiles_AddRef,
1262 EnumTfLanguageProfiles_Release,
1263 EnumTfLanguageProfiles_Clone,
1264 EnumTfLanguageProfiles_Next,
1265 EnumTfLanguageProfiles_Reset,
1266 EnumTfLanguageProfiles_Skip
1269 static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut)
1271 HRESULT hr;
1272 EnumTfLanguageProfiles *This;
1274 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfLanguageProfiles));
1275 if (This == NULL)
1276 return E_OUTOFMEMORY;
1278 This->IEnumTfLanguageProfiles_iface.lpVtbl= &EnumTfLanguageProfilesVtbl;
1279 This->refCount = 1;
1280 This->langid = langid;
1282 hr = CategoryMgr_Constructor(NULL,(IUnknown**)&This->catmgr);
1283 if (FAILED(hr))
1285 HeapFree(GetProcessHeap(),0,This);
1286 return hr;
1289 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0,
1290 KEY_READ | KEY_WRITE, NULL, &This->tipkey, NULL) != ERROR_SUCCESS)
1292 HeapFree(GetProcessHeap(), 0, This);
1293 return E_FAIL;
1296 *ppOut = &This->IEnumTfLanguageProfiles_iface;
1297 TRACE("returning %p\n", *ppOut);
1298 return S_OK;