~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/msctf/inputprocessor.c

Version: ~ [ wine-1.5.30 ] ~ [ wine-1.5.29 ] ~ [ wine-1.5.28 ] ~ [ wine-1.5.27 ] ~ [ wine-1.5.26 ] ~ [ wine-1.5.25 ] ~ [ wine-1.5.24 ] ~ [ wine-1.5.23 ] ~ [ wine-1.5.22 ] ~ [ wine-1.5.21 ] ~ [ wine-1.5.20 ] ~ [ wine-1.5.19 ] ~ [ wine-1.5.18 ] ~ [ wine-1.5.17 ] ~ [ wine-1.5.16 ] ~ [ wine-1.5.15 ] ~ [ wine-1.5.14 ] ~ [ wine-1.5.13 ] ~ [ wine-1.5.12 ] ~ [ wine-1.5.11 ] ~ [ wine-1.5.10 ] ~ [ wine-1.5.9 ] ~ [ wine-1.5.8 ] ~ [ wine-1.5.7 ] ~ [ wine-1.4.1 ] ~ [ wine-1.5.6 ] ~ [ wine-1.5.5 ] ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  *  ITfInputProcessorProfiles implementation
  3  *
  4  *  Copyright 2009 Aric Stewart, CodeWeavers
  5  *
  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.
 10  *
 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.
 15  *
 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
 19  */
 20 
 21 #include "config.h"
 22 
 23 #include <stdarg.h>
 24 
 25 #define COBJMACROS
 26 
 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"
 36 
 37 #include "wine/unicode.h"
 38 #include "wine/list.h"
 39 
 40 #include "msctf.h"
 41 #include "msctf_internal.h"
 42 
 43 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
 44 
 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','\\','','x','%','','8','x','\\','%','s',0};
 49 
 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','\\','','x','%','','8','x','\\','%','s',0};
 54 
 55 typedef struct tagInputProcessorProfilesSink {
 56     struct list         entry;
 57     union {
 58         /* InputProcessorProfile Sinks */
 59         IUnknown            *pIUnknown;
 60         ITfLanguageProfileNotifySink *pITfLanguageProfileNotifySink;
 61     } interfaces;
 62 } InputProcessorProfilesSink;
 63 
 64 typedef struct tagInputProcessorProfiles {
 65     const ITfInputProcessorProfilesVtbl *InputProcessorProfilesVtbl;
 66     const ITfSourceVtbl *SourceVtbl;
 67     /* const ITfInputProcessorProfileMgrVtbl *InputProcessorProfileMgrVtbl; */
 68     /* const ITfInputProcessorProfilesExVtbl *InputProcessorProfilesExVtbl; */
 69     /* const ITfInputProcessorProfileSubstituteLayoutVtbl *InputProcessorProfileSubstituteLayoutVtbl; */
 70     LONG refCount;
 71 
 72     LANGID  currentLanguage;
 73 
 74     struct list     LanguageProfileNotifySink;
 75 } InputProcessorProfiles;
 76 
 77 typedef struct tagProfilesEnumGuid {
 78     const IEnumGUIDVtbl *Vtbl;
 79     LONG refCount;
 80 
 81     HKEY key;
 82     DWORD next_index;
 83 } ProfilesEnumGuid;
 84 
 85 typedef struct tagEnumTfLanguageProfiles {
 86     const IEnumTfLanguageProfilesVtbl *Vtbl;
 87     LONG refCount;
 88 
 89     HKEY    tipkey;
 90     DWORD   tip_index;
 91     WCHAR   szwCurrentClsid[39];
 92 
 93     HKEY    langkey;
 94     DWORD   lang_index;
 95 
 96     LANGID  langid;
 97     ITfCategoryMgr *catmgr;
 98 } EnumTfLanguageProfiles;
 99 
100 static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut);
101 static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut);
102 
103 static inline InputProcessorProfiles *impl_from_ITfSourceVtbl(ITfSource *iface)
104 {
105     return (InputProcessorProfiles *)((char *)iface - FIELD_OFFSET(InputProcessorProfiles,SourceVtbl));
106 }
107 
108 static void free_sink(InputProcessorProfilesSink *sink)
109 {
110         IUnknown_Release(sink->interfaces.pIUnknown);
111         HeapFree(GetProcessHeap(),0,sink);
112 }
113 
114 static void InputProcessorProfiles_Destructor(InputProcessorProfiles *This)
115 {
116     struct list *cursor, *cursor2;
117     TRACE("destroying %p\n", This);
118 
119     /* free sinks */
120     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->LanguageProfileNotifySink)
121     {
122         InputProcessorProfilesSink* sink = LIST_ENTRY(cursor,InputProcessorProfilesSink,entry);
123         list_remove(cursor);
124         free_sink(sink);
125     }
126 
127     HeapFree(GetProcessHeap(),0,This);
128 }
129 
130 static void add_userkey( REFCLSID rclsid, LANGID langid,
131                                 REFGUID guidProfile)
132 {
133     HKEY key;
134     WCHAR buf[39];
135     WCHAR buf2[39];
136     WCHAR fullkey[168];
137     DWORD disposition = 0;
138     ULONG res;
139 
140     TRACE("\n");
141 
142     StringFromGUID2(rclsid, buf, 39);
143     StringFromGUID2(guidProfile, buf2, 39);
144     sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
145 
146     res = RegCreateKeyExW(HKEY_CURRENT_USER,fullkey, 0, NULL, 0,
147                    KEY_READ | KEY_WRITE, NULL, &key, &disposition);
148 
149     if (!res && disposition == REG_CREATED_NEW_KEY)
150     {
151         DWORD zero = 0x0;
152         RegSetValueExW(key, szwEnable, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD));
153     }
154 
155     if (!res)
156         RegCloseKey(key);
157 }
158 
159 static HRESULT WINAPI InputProcessorProfiles_QueryInterface(ITfInputProcessorProfiles *iface, REFIID iid, LPVOID *ppvOut)
160 {
161     InputProcessorProfiles *This = (InputProcessorProfiles *)iface;
162     *ppvOut = NULL;
163 
164     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfInputProcessorProfiles))
165     {
166         *ppvOut = This;
167     }
168     else if (IsEqualIID(iid, &IID_ITfSource))
169     {
170         *ppvOut = &This->SourceVtbl;
171     }
172 
173     if (*ppvOut)
174     {
175         IUnknown_AddRef(iface);
176         return S_OK;
177     }
178 
179     WARN("unsupported interface: %s\n", debugstr_guid(iid));
180     return E_NOINTERFACE;
181 }
182 
183 static ULONG WINAPI InputProcessorProfiles_AddRef(ITfInputProcessorProfiles *iface)
184 {
185     InputProcessorProfiles *This = (InputProcessorProfiles *)iface;
186     return InterlockedIncrement(&This->refCount);
187 }
188 
189 static ULONG WINAPI InputProcessorProfiles_Release(ITfInputProcessorProfiles *iface)
190 {
191     InputProcessorProfiles *This = (InputProcessorProfiles *)iface;
192     ULONG ret;
193 
194     ret = InterlockedDecrement(&This->refCount);
195     if (ret == 0)
196         InputProcessorProfiles_Destructor(This);
197     return ret;
198 }
199 
200 /*****************************************************
201  * ITfInputProcessorProfiles functions
202  *****************************************************/
203 static HRESULT WINAPI InputProcessorProfiles_Register(
204         ITfInputProcessorProfiles *iface, REFCLSID rclsid)
205 {
206     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
207     HKEY tipkey;
208     WCHAR buf[39];
209     WCHAR fullkey[68];
210 
211     TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
212 
213     StringFromGUID2(rclsid, buf, 39);
214     sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
215 
216     if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, NULL, 0,
217                     KEY_READ | KEY_WRITE, NULL, &tipkey, NULL) != ERROR_SUCCESS)
218         return E_FAIL;
219 
220     RegCloseKey(tipkey);
221 
222     return S_OK;
223 }
224 
225 static HRESULT WINAPI InputProcessorProfiles_Unregister(
226         ITfInputProcessorProfiles *iface, REFCLSID rclsid)
227 {
228     WCHAR buf[39];
229     WCHAR fullkey[68];
230     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
231 
232     TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
233 
234     StringFromGUID2(rclsid, buf, 39);
235     sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
236 
237     RegDeleteTreeW(HKEY_LOCAL_MACHINE, fullkey);
238     RegDeleteTreeW(HKEY_CURRENT_USER, fullkey);
239 
240     return S_OK;
241 }
242 
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,
247         ULONG uIconIndex)
248 {
249     HKEY tipkey,fmtkey;
250     WCHAR buf[39];
251     WCHAR fullkey[100];
252     ULONG res;
253     DWORD disposition = 0;
254 
255     static const WCHAR fmt2[] = {'%','s','\\','','x','%','','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};
259 
260     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
261 
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);
265 
266     StringFromGUID2(rclsid, buf, 39);
267     sprintfW(fullkey,szwTipfmt,szwSystemTIPKey,buf);
268 
269     if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE,
270                 &tipkey ) != ERROR_SUCCESS)
271         return E_FAIL;
272 
273     StringFromGUID2(guidProfile, buf, 39);
274     sprintfW(fullkey,fmt2,szwLngp,langid,buf);
275 
276     res = RegCreateKeyExW(tipkey,fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
277             NULL, &fmtkey, &disposition);
278 
279     if (!res)
280     {
281         DWORD zero = 0x0;
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));
287         RegCloseKey(fmtkey);
288 
289         add_userkey(rclsid, langid, guidProfile);
290     }
291     RegCloseKey(tipkey);
292 
293     if (!res)
294         return S_OK;
295     else
296         return E_FAIL;
297 }
298 
299 static HRESULT WINAPI InputProcessorProfiles_RemoveLanguageProfile(
300         ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
301         REFGUID guidProfile)
302 {
303     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
304     FIXME("STUB:(%p)\n",This);
305     return E_NOTIMPL;
306 }
307 
308 static HRESULT WINAPI InputProcessorProfiles_EnumInputProcessorInfo(
309         ITfInputProcessorProfiles *iface, IEnumGUID **ppEnum)
310 {
311     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
312     TRACE("(%p) %p\n",This,ppEnum);
313     return ProfilesEnumGuid_Constructor(ppEnum);
314 }
315 
316 static HRESULT WINAPI InputProcessorProfiles_GetDefaultLanguageProfile(
317         ITfInputProcessorProfiles *iface, LANGID langid, REFGUID catid,
318         CLSID *pclsid, GUID *pguidProfile)
319 {
320     WCHAR fullkey[168];
321     WCHAR buf[39];
322     HKEY hkey;
323     DWORD count;
324     ULONG res;
325     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
326 
327     TRACE("%p) %x %s %p %p\n",This, langid, debugstr_guid(catid),pclsid,pguidProfile);
328 
329     if (!catid || !pclsid || !pguidProfile)
330         return E_INVALIDARG;
331 
332     StringFromGUID2(catid, buf, 39);
333     sprintfW(fullkey, szwDefaultFmt, szwSystemCTFKey, szwAssemblies, langid, buf);
334 
335     if (RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE,
336                 &hkey ) != ERROR_SUCCESS)
337         return S_FALSE;
338 
339     count = sizeof(buf);
340     res = RegQueryValueExW(hkey, szwDefault, 0, NULL, (LPBYTE)buf, &count);
341     if (res != ERROR_SUCCESS)
342     {
343         RegCloseKey(hkey);
344         return S_FALSE;
345     }
346     CLSIDFromString(buf,pclsid);
347 
348     res = RegQueryValueExW(hkey, szwProfile, 0, NULL, (LPBYTE)buf, &count);
349     if (res == ERROR_SUCCESS)
350         CLSIDFromString(buf,pguidProfile);
351 
352     RegCloseKey(hkey);
353 
354     return S_OK;
355 }
356 
357 static HRESULT WINAPI InputProcessorProfiles_SetDefaultLanguageProfile(
358         ITfInputProcessorProfiles *iface, LANGID langid, REFCLSID rclsid,
359         REFGUID guidProfiles)
360 {
361     WCHAR fullkey[168];
362     WCHAR buf[39];
363     HKEY hkey;
364     GUID catid;
365     HRESULT hr;
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 };
371 
372     TRACE("%p) %x %s %s\n",This, langid, debugstr_guid(rclsid),debugstr_guid(guidProfiles));
373 
374     if (!rclsid || !guidProfiles)
375         return E_INVALIDARG;
376 
377     hr = CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
378 
379     if (FAILED(hr))
380         return hr;
381 
382     if (ITfCategoryMgr_FindClosestCategory(catmgr, rclsid,
383             &catid, tipcats, 3) != S_OK)
384         hr = ITfCategoryMgr_FindClosestCategory(catmgr, rclsid,
385                 &catid, NULL, 0);
386     ITfCategoryMgr_Release(catmgr);
387 
388     if (FAILED(hr))
389         return E_FAIL;
390 
391     StringFromGUID2(&catid, buf, 39);
392     sprintfW(fullkey, szwDefaultFmt, szwSystemCTFKey, szwAssemblies, langid, buf);
393 
394     if (RegCreateKeyExW(HKEY_CURRENT_USER, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE,
395                 NULL, &hkey, NULL ) != ERROR_SUCCESS)
396         return E_FAIL;
397 
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));
402     RegCloseKey(hkey);
403 
404     return S_OK;
405 }
406 
407 static HRESULT WINAPI InputProcessorProfiles_ActivateLanguageProfile(
408         ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
409         REFGUID guidProfiles)
410 {
411     HRESULT hr;
412     BOOL enabled;
413     TF_LANGUAGEPROFILE LanguageProfile;
414     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
415 
416     TRACE("(%p) %s %x %s\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfiles));
417 
418     if (langid != This->currentLanguage) return E_INVALIDARG;
419 
420     if (get_active_textservice(rclsid,NULL))
421     {
422         TRACE("Already Active\n");
423         return E_FAIL;
424     }
425 
426     hr = ITfInputProcessorProfiles_IsEnabledLanguageProfile(iface, rclsid,
427             langid, guidProfiles, &enabled);
428     if (FAILED(hr) || !enabled)
429     {
430         TRACE("Not Enabled\n");
431         return E_FAIL;
432     }
433 
434     LanguageProfile.clsid = *rclsid;
435     LanguageProfile.langid = langid;
436     LanguageProfile.guidProfile = *guidProfiles;
437 
438     hr = add_active_textservice(&LanguageProfile);
439 
440     return hr;
441 }
442 
443 static HRESULT WINAPI InputProcessorProfiles_GetActiveLanguageProfile(
444         ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID *plangid,
445         GUID *pguidProfile)
446 {
447     TF_LANGUAGEPROFILE profile;
448     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
449 
450     TRACE("(%p) %s %p %p\n",This,debugstr_guid(rclsid),plangid,pguidProfile);
451 
452     if (!rclsid || !plangid || !pguidProfile)
453         return E_INVALIDARG;
454 
455     if (get_active_textservice(rclsid, &profile))
456     {
457         *plangid = profile.langid;
458         *pguidProfile = profile.guidProfile;
459         return S_OK;
460     }
461     else
462     {
463         *pguidProfile = GUID_NULL;
464         return S_FALSE;
465     }
466 }
467 
468 static HRESULT WINAPI InputProcessorProfiles_GetLanguageProfileDescription(
469         ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
470         REFGUID guidProfile, BSTR *pbstrProfile)
471 {
472     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
473     FIXME("STUB:(%p)\n",This);
474     return E_NOTIMPL;
475 }
476 
477 static HRESULT WINAPI InputProcessorProfiles_GetCurrentLanguage(
478         ITfInputProcessorProfiles *iface, LANGID *plangid)
479 {
480     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
481     TRACE("(%p) 0x%x\n",This,This->currentLanguage);
482 
483     if (!plangid)
484         return E_INVALIDARG;
485 
486     *plangid = This->currentLanguage;
487 
488     return S_OK;
489 }
490 
491 static HRESULT WINAPI InputProcessorProfiles_ChangeCurrentLanguage(
492         ITfInputProcessorProfiles *iface, LANGID langid)
493 {
494     struct list *cursor;
495     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
496     BOOL accept;
497 
498     FIXME("STUB:(%p)\n",This);
499 
500     LIST_FOR_EACH(cursor, &This->LanguageProfileNotifySink)
501     {
502         InputProcessorProfilesSink* sink = LIST_ENTRY(cursor,InputProcessorProfilesSink,entry);
503         accept = TRUE;
504         ITfLanguageProfileNotifySink_OnLanguageChange(sink->interfaces.pITfLanguageProfileNotifySink, langid, &accept);
505         if (!accept)
506             return  E_FAIL;
507     }
508 
509     /* TODO:  On successful language change call OnLanguageChanged sink */
510     return E_NOTIMPL;
511 }
512 
513 static HRESULT WINAPI InputProcessorProfiles_GetLanguageList(
514         ITfInputProcessorProfiles *iface, LANGID **ppLangId, ULONG *pulCount)
515 {
516     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
517     FIXME("Semi-STUB:(%p)\n",This);
518     *ppLangId = CoTaskMemAlloc(sizeof(LANGID));
519     **ppLangId = This->currentLanguage;
520     *pulCount = 1;
521     return S_OK;
522 }
523 
524 static HRESULT WINAPI InputProcessorProfiles_EnumLanguageProfiles(
525         ITfInputProcessorProfiles *iface, LANGID langid,
526         IEnumTfLanguageProfiles **ppEnum)
527 {
528     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
529     TRACE("(%p) %x %p\n",This,langid,ppEnum);
530     return EnumTfLanguageProfiles_Constructor(langid, ppEnum);
531 }
532 
533 static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfile(
534         ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
535         REFGUID guidProfile, BOOL fEnable)
536 {
537     HKEY key;
538     WCHAR buf[39];
539     WCHAR buf2[39];
540     WCHAR fullkey[168];
541     ULONG res;
542 
543     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
544     TRACE("(%p) %s %x %s %i\n",This, debugstr_guid(rclsid), langid, debugstr_guid(guidProfile), fEnable);
545 
546     StringFromGUID2(rclsid, buf, 39);
547     StringFromGUID2(guidProfile, buf2, 39);
548     sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
549 
550     res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key);
551 
552     if (!res)
553     {
554         RegSetValueExW(key, szwEnable, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
555         RegCloseKey(key);
556     }
557     else
558         return E_FAIL;
559 
560     return S_OK;
561 }
562 
563 static HRESULT WINAPI InputProcessorProfiles_IsEnabledLanguageProfile(
564         ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
565         REFGUID guidProfile, BOOL *pfEnable)
566 {
567     HKEY key;
568     WCHAR buf[39];
569     WCHAR buf2[39];
570     WCHAR fullkey[168];
571     ULONG res;
572 
573     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
574     TRACE("(%p) %s, %i, %s, %p\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),pfEnable);
575 
576     if (!pfEnable)
577         return E_INVALIDARG;
578 
579     StringFromGUID2(rclsid, buf, 39);
580     StringFromGUID2(guidProfile, buf2, 39);
581     sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
582 
583     res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key);
584 
585     if (!res)
586     {
587         DWORD count = sizeof(DWORD);
588         res = RegQueryValueExW(key, szwEnable, 0, NULL, (LPBYTE)pfEnable, &count);
589         RegCloseKey(key);
590     }
591 
592     if (res)  /* Try Default */
593     {
594         res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key);
595 
596         if (!res)
597         {
598             DWORD count = sizeof(DWORD);
599             res = RegQueryValueExW(key, szwEnable, 0, NULL, (LPBYTE)pfEnable, &count);
600             RegCloseKey(key);
601         }
602     }
603 
604     if (!res)
605         return S_OK;
606     else
607         return E_FAIL;
608 }
609 
610 static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfileByDefault(
611         ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
612         REFGUID guidProfile, BOOL fEnable)
613 {
614     HKEY key;
615     WCHAR buf[39];
616     WCHAR buf2[39];
617     WCHAR fullkey[168];
618     ULONG res;
619 
620     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
621     TRACE("(%p) %s %x %s %i\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),fEnable);
622 
623     StringFromGUID2(rclsid, buf, 39);
624     StringFromGUID2(guidProfile, buf2, 39);
625     sprintfW(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2);
626 
627     res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key);
628 
629     if (!res)
630     {
631         RegSetValueExW(key, szwEnable, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD));
632         RegCloseKey(key);
633     }
634     else
635         return E_FAIL;
636 
637     return S_OK;
638 }
639 
640 static HRESULT WINAPI InputProcessorProfiles_SubstituteKeyboardLayout(
641         ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid,
642         REFGUID guidProfile, HKL hKL)
643 {
644     InputProcessorProfiles *This = (InputProcessorProfiles*)iface;
645     FIXME("STUB:(%p)\n",This);
646     return E_NOTIMPL;
647 }
648 
649 
650 static const ITfInputProcessorProfilesVtbl InputProcessorProfiles_InputProcessorProfilesVtbl =
651 {
652     InputProcessorProfiles_QueryInterface,
653     InputProcessorProfiles_AddRef,
654     InputProcessorProfiles_Release,
655 
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
674 };
675 
676 /*****************************************************
677  * ITfSource functions
678  *****************************************************/
679 static HRESULT WINAPI IPPSource_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
680 {
681     InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
682     return InputProcessorProfiles_QueryInterface((ITfInputProcessorProfiles *)This, iid, *ppvOut);
683 }
684 
685 static ULONG WINAPI IPPSource_AddRef(ITfSource *iface)
686 {
687     InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
688     return InputProcessorProfiles_AddRef((ITfInputProcessorProfiles*)This);
689 }
690 
691 static ULONG WINAPI IPPSource_Release(ITfSource *iface)
692 {
693     InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
694     return InputProcessorProfiles_Release((ITfInputProcessorProfiles *)This);
695 }
696 
697 static HRESULT WINAPI IPPSource_AdviseSink(ITfSource *iface,
698         REFIID riid, IUnknown *punk, DWORD *pdwCookie)
699 {
700     InputProcessorProfilesSink *ipps;
701     InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
702 
703     TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
704 
705     if (!riid || !punk || !pdwCookie)
706         return E_INVALIDARG;
707 
708     if (IsEqualIID(riid, &IID_ITfLanguageProfileNotifySink))
709     {
710         ipps = HeapAlloc(GetProcessHeap(),0,sizeof(InputProcessorProfilesSink));
711         if (!ipps)
712             return E_OUTOFMEMORY;
713         if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&ipps->interfaces.pITfLanguageProfileNotifySink)))
714         {
715             HeapFree(GetProcessHeap(),0,ipps);
716             return CONNECT_E_CANNOTCONNECT;
717         }
718         list_add_head(&This->LanguageProfileNotifySink,&ipps->entry);
719         *pdwCookie = generate_Cookie(COOKIE_MAGIC_IPPSINK, ipps);
720     }
721     else
722     {
723         FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
724         return E_NOTIMPL;
725     }
726 
727     TRACE("cookie %x\n",*pdwCookie);
728 
729     return S_OK;
730 }
731 
732 static HRESULT WINAPI IPPSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
733 {
734     InputProcessorProfilesSink *sink;
735     InputProcessorProfiles *This = impl_from_ITfSourceVtbl(iface);
736 
737     TRACE("(%p) %x\n",This,pdwCookie);
738 
739     if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_IPPSINK)
740         return E_INVALIDARG;
741 
742     sink = (InputProcessorProfilesSink*)remove_Cookie(pdwCookie);
743     if (!sink)
744         return CONNECT_E_NOCONNECTION;
745 
746     list_remove(&sink->entry);
747     free_sink(sink);
748 
749     return S_OK;
750 }
751 
752 static const ITfSourceVtbl InputProcessorProfiles_SourceVtbl =
753 {
754     IPPSource_QueryInterface,
755     IPPSource_AddRef,
756     IPPSource_Release,
757 
758     IPPSource_AdviseSink,
759     IPPSource_UnadviseSink,
760 };
761 
762 HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
763 {
764     InputProcessorProfiles *This;
765     if (pUnkOuter)
766         return CLASS_E_NOAGGREGATION;
767 
768     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputProcessorProfiles));
769     if (This == NULL)
770         return E_OUTOFMEMORY;
771 
772     This->InputProcessorProfilesVtbl= &InputProcessorProfiles_InputProcessorProfilesVtbl;
773     This->SourceVtbl = &InputProcessorProfiles_SourceVtbl;
774     This->refCount = 1;
775     This->currentLanguage = GetUserDefaultLCID();
776 
777     list_init(&This->LanguageProfileNotifySink);
778 
779     TRACE("returning %p\n", This);
780     *ppOut = (IUnknown *)This;
781     return S_OK;
782 }
783 
784 /**************************************************
785  * IEnumGUID implementaion for ITfInputProcessorProfiles::EnumInputProcessorInfo
786  **************************************************/
787 static void ProfilesEnumGuid_Destructor(ProfilesEnumGuid *This)
788 {
789     TRACE("destroying %p\n", This);
790     RegCloseKey(This->key);
791     HeapFree(GetProcessHeap(),0,This);
792 }
793 
794 static HRESULT WINAPI ProfilesEnumGuid_QueryInterface(IEnumGUID *iface, REFIID iid, LPVOID *ppvOut)
795 {
796     ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
797     *ppvOut = NULL;
798 
799     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumGUID))
800     {
801         *ppvOut = This;
802     }
803 
804     if (*ppvOut)
805     {
806         IUnknown_AddRef(iface);
807         return S_OK;
808     }
809 
810     WARN("unsupported interface: %s\n", debugstr_guid(iid));
811     return E_NOINTERFACE;
812 }
813 
814 static ULONG WINAPI ProfilesEnumGuid_AddRef(IEnumGUID *iface)
815 {
816     ProfilesEnumGuid *This = (ProfilesEnumGuid*)iface;
817     return InterlockedIncrement(&This->refCount);
818 }
819 
820 static ULONG WINAPI ProfilesEnumGuid_Release(IEnumGUID *iface)
821 {
822     ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
823     ULONG ret;
824 
825     ret = InterlockedDecrement(&This->refCount);
826     if (ret == 0)
827         ProfilesEnumGuid_Destructor(This);
828     return ret;
829 }
830 
831 /*****************************************************
832  * IEnumGuid functions
833  *****************************************************/
834 static HRESULT WINAPI ProfilesEnumGuid_Next( LPENUMGUID iface,
835     ULONG celt, GUID *rgelt, ULONG *pceltFetched)
836 {
837     ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
838     ULONG fetched = 0;
839 
840     TRACE("(%p)\n",This);
841 
842     if (rgelt == NULL) return E_POINTER;
843 
844     if (This->key) while (fetched < celt)
845     {
846         LSTATUS res;
847         HRESULT hr;
848         WCHAR catid[39];
849         DWORD cName = 39;
850 
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);
855 
856         hr = CLSIDFromString(catid, rgelt);
857         if (FAILED(hr)) continue;
858 
859         ++fetched;
860         ++rgelt;
861     }
862 
863     if (pceltFetched) *pceltFetched = fetched;
864     return fetched == celt ? S_OK : S_FALSE;
865 }
866 
867 static HRESULT WINAPI ProfilesEnumGuid_Skip( LPENUMGUID iface, ULONG celt)
868 {
869     ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
870     TRACE("(%p)\n",This);
871 
872     This->next_index += celt;
873     return S_OK;
874 }
875 
876 static HRESULT WINAPI ProfilesEnumGuid_Reset( LPENUMGUID iface)
877 {
878     ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
879     TRACE("(%p)\n",This);
880     This->next_index = 0;
881     return S_OK;
882 }
883 
884 static HRESULT WINAPI ProfilesEnumGuid_Clone( LPENUMGUID iface,
885     IEnumGUID **ppenum)
886 {
887     ProfilesEnumGuid *This = (ProfilesEnumGuid *)iface;
888     HRESULT res;
889 
890     TRACE("(%p)\n",This);
891 
892     if (ppenum == NULL) return E_POINTER;
893 
894     res = ProfilesEnumGuid_Constructor(ppenum);
895     if (SUCCEEDED(res))
896     {
897         ProfilesEnumGuid *new_This = (ProfilesEnumGuid *)*ppenum;
898         new_This->next_index = This->next_index;
899     }
900     return res;
901 }
902 
903 static const IEnumGUIDVtbl IEnumGUID_Vtbl ={
904     ProfilesEnumGuid_QueryInterface,
905     ProfilesEnumGuid_AddRef,
906     ProfilesEnumGuid_Release,
907 
908     ProfilesEnumGuid_Next,
909     ProfilesEnumGuid_Skip,
910     ProfilesEnumGuid_Reset,
911     ProfilesEnumGuid_Clone
912 };
913 
914 static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut)
915 {
916     ProfilesEnumGuid *This;
917 
918     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ProfilesEnumGuid));
919     if (This == NULL)
920         return E_OUTOFMEMORY;
921 
922     This->Vtbl= &IEnumGUID_Vtbl;
923     This->refCount = 1;
924 
925     if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0,
926                     KEY_READ | KEY_WRITE, NULL, &This->key, NULL) != ERROR_SUCCESS)
927         return E_FAIL;
928 
929     TRACE("returning %p\n", This);
930     *ppOut = (IEnumGUID*)This;
931     return S_OK;
932 }
933 
934 /**************************************************
935  * IEnumTfLanguageProfiles implementaion
936  **************************************************/
937 static void EnumTfLanguageProfiles_Destructor(EnumTfLanguageProfiles *This)
938 {
939     TRACE("destroying %p\n", This);
940     RegCloseKey(This->tipkey);
941     if (This->langkey)
942         RegCloseKey(This->langkey);
943     ITfCategoryMgr_Release(This->catmgr);
944     HeapFree(GetProcessHeap(),0,This);
945 }
946 
947 static HRESULT WINAPI EnumTfLanguageProfiles_QueryInterface(IEnumTfLanguageProfiles *iface, REFIID iid, LPVOID *ppvOut)
948 {
949     EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
950     *ppvOut = NULL;
951 
952     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfLanguageProfiles))
953     {
954         *ppvOut = This;
955     }
956 
957     if (*ppvOut)
958     {
959         IUnknown_AddRef(iface);
960         return S_OK;
961     }
962 
963     WARN("unsupported interface: %s\n", debugstr_guid(iid));
964     return E_NOINTERFACE;
965 }
966 
967 static ULONG WINAPI EnumTfLanguageProfiles_AddRef(IEnumTfLanguageProfiles *iface)
968 {
969     EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles*)iface;
970     return InterlockedIncrement(&This->refCount);
971 }
972 
973 static ULONG WINAPI EnumTfLanguageProfiles_Release(IEnumTfLanguageProfiles *iface)
974 {
975     EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
976     ULONG ret;
977 
978     ret = InterlockedDecrement(&This->refCount);
979     if (ret == 0)
980         EnumTfLanguageProfiles_Destructor(This);
981     return ret;
982 }
983 
984 /*****************************************************
985  * IEnumGuid functions
986  *****************************************************/
987 static INT next_LanguageProfile(EnumTfLanguageProfiles *This, CLSID clsid, TF_LANGUAGEPROFILE *tflp)
988 {
989     WCHAR fullkey[168];
990     ULONG res;
991     WCHAR profileid[39];
992     DWORD cName = 39;
993     GUID  profile;
994 
995     static const WCHAR fmt[] = {'%','s','\\','%','s','\\','','x','%','','8','x',0};
996 
997     if (This->langkey == NULL)
998     {
999         sprintfW(fullkey,fmt,This->szwCurrentClsid,szwLngp,This->langid);
1000         res = RegOpenKeyExW(This->tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &This->langkey);
1001         if (res)
1002         {
1003             This->langkey = NULL;
1004             return -1;
1005         }
1006         This->lang_index = 0;
1007     }
1008     res = RegEnumKeyExW(This->langkey, This->lang_index, profileid, &cName,
1009                 NULL, NULL, NULL, NULL);
1010     if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA)
1011     {
1012         RegCloseKey(This->langkey);
1013         This->langkey = NULL;
1014         return -1;
1015     }
1016     ++(This->lang_index);
1017 
1018     if (tflp)
1019     {
1020         static const GUID * tipcats[3] = { &GUID_TFCAT_TIP_KEYBOARD,
1021                                            &GUID_TFCAT_TIP_SPEECH,
1022                                            &GUID_TFCAT_TIP_HANDWRITING };
1023         res = CLSIDFromString(profileid, &profile);
1024         if (FAILED(res)) return 0;
1025 
1026         tflp->clsid = clsid;
1027         tflp->langid = This->langid;
1028         tflp->fActive = get_active_textservice(&clsid, NULL);
1029         tflp->guidProfile = profile;
1030         if (ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid,
1031                 &tflp->catid, tipcats, 3) != S_OK)
1032             ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid,
1033                     &tflp->catid, NULL, 0);
1034     }
1035 
1036     return 1;
1037 }
1038 
1039 static HRESULT WINAPI EnumTfLanguageProfiles_Next(IEnumTfLanguageProfiles *iface,
1040     ULONG ulCount, TF_LANGUAGEPROFILE *pProfile, ULONG *pcFetch)
1041 {
1042     EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
1043     ULONG fetched = 0;
1044 
1045     TRACE("(%p)\n",This);
1046 
1047     if (pProfile == NULL) return E_POINTER;
1048 
1049     if (This->tipkey) while (fetched < ulCount)
1050     {
1051         LSTATUS res;
1052         HRESULT hr;
1053         DWORD cName = 39;
1054         GUID clsid;
1055 
1056         res = RegEnumKeyExW(This->tipkey, This->tip_index,
1057                     This->szwCurrentClsid, &cName, NULL, NULL, NULL, NULL);
1058         if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break;
1059         ++(This->tip_index);
1060         hr = CLSIDFromString(This->szwCurrentClsid, &clsid);
1061         if (FAILED(hr)) continue;
1062 
1063         while ( fetched < ulCount)
1064         {
1065             INT res = next_LanguageProfile(This, clsid, pProfile);
1066             if (res == 1)
1067             {
1068                 ++fetched;
1069                 ++pProfile;
1070             }
1071             else if (res == -1)
1072                 break;
1073             else
1074                 continue;
1075         }
1076     }
1077 
1078     if (pcFetch) *pcFetch = fetched;
1079     return fetched == ulCount ? S_OK : S_FALSE;
1080 }
1081 
1082 static HRESULT WINAPI EnumTfLanguageProfiles_Skip( IEnumTfLanguageProfiles* iface, ULONG celt)
1083 {
1084     EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
1085     FIXME("STUB (%p)\n",This);
1086     return E_NOTIMPL;
1087 }
1088 
1089 static HRESULT WINAPI EnumTfLanguageProfiles_Reset( IEnumTfLanguageProfiles* iface)
1090 {
1091     EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
1092     TRACE("(%p)\n",This);
1093     This->tip_index = 0;
1094     if (This->langkey)
1095         RegCloseKey(This->langkey);
1096     This->langkey = NULL;
1097     This->lang_index = 0;
1098     return S_OK;
1099 }
1100 
1101 static HRESULT WINAPI EnumTfLanguageProfiles_Clone( IEnumTfLanguageProfiles *iface,
1102     IEnumTfLanguageProfiles **ppenum)
1103 {
1104     EnumTfLanguageProfiles *This = (EnumTfLanguageProfiles *)iface;
1105     HRESULT res;
1106 
1107     TRACE("(%p)\n",This);
1108 
1109     if (ppenum == NULL) return E_POINTER;
1110 
1111     res = EnumTfLanguageProfiles_Constructor(This->langid, ppenum);
1112     if (SUCCEEDED(res))
1113     {
1114         EnumTfLanguageProfiles *new_This = (EnumTfLanguageProfiles *)*ppenum;
1115         new_This->tip_index = This->tip_index;
1116         lstrcpynW(new_This->szwCurrentClsid,This->szwCurrentClsid,39);
1117 
1118         if (This->langkey)
1119         {
1120             WCHAR fullkey[168];
1121             static const WCHAR fmt[] = {'%','s','\\','%','s','\\','','x','%','','8','x',0};
1122 
1123             sprintfW(fullkey,fmt,This->szwCurrentClsid,szwLngp,This->langid);
1124             res = RegOpenKeyExW(new_This->tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &This->langkey);
1125             new_This->lang_index = This->lang_index;
1126         }
1127     }
1128     return res;
1129 }
1130 
1131 static const IEnumTfLanguageProfilesVtbl IEnumTfLanguageProfiles_Vtbl ={
1132     EnumTfLanguageProfiles_QueryInterface,
1133     EnumTfLanguageProfiles_AddRef,
1134     EnumTfLanguageProfiles_Release,
1135 
1136     EnumTfLanguageProfiles_Clone,
1137     EnumTfLanguageProfiles_Next,
1138     EnumTfLanguageProfiles_Reset,
1139     EnumTfLanguageProfiles_Skip
1140 };
1141 
1142 static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, IEnumTfLanguageProfiles **ppOut)
1143 {
1144     HRESULT hr;
1145     EnumTfLanguageProfiles *This;
1146 
1147     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfLanguageProfiles));
1148     if (This == NULL)
1149         return E_OUTOFMEMORY;
1150 
1151     This->Vtbl= &IEnumTfLanguageProfiles_Vtbl;
1152     This->refCount = 1;
1153     This->langid = langid;
1154 
1155     hr = CategoryMgr_Constructor(NULL,(IUnknown**)&This->catmgr);
1156     if (FAILED(hr))
1157     {
1158         HeapFree(GetProcessHeap(),0,This);
1159         return hr;
1160     }
1161 
1162     if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0,
1163                     KEY_READ | KEY_WRITE, NULL, &This->tipkey, NULL) != ERROR_SUCCESS)
1164         return E_FAIL;
1165 
1166     TRACE("returning %p\n", This);
1167     *ppOut = (IEnumTfLanguageProfiles*)This;
1168     return S_OK;
1169 }
1170 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.