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 <stdarg.h> 22 23 #define COBJMACROS 24 25 #include "wine/debug.h" 26 #include "windef.h" 27 #include "winbase.h" 28 #include "winreg.h" 29 #include "winuser.h" 30 #ifdef __REACTOS__ 31 #include <wchar.h> 32 #include <winnls.h> 33 #endif 34 #include "shlwapi.h" 35 #include "winerror.h" 36 #include "objbase.h" 37 #include "olectl.h" 38 39 #include "msctf.h" 40 #include "msctf_internal.h" 41 42 WINE_DEFAULT_DEBUG_CHANNEL(msctf); 43 44 static const WCHAR szwLngp[] = {'L','a','n','g','u','a','g','e','P','r','o','f','i','l','e',0}; 45 static const WCHAR szwEnable[] = {'E','n','a','b','l','e',0}; 46 static const WCHAR szwTipfmt[] = {'%','s','\\','%','s',0}; 47 static const WCHAR szwFullLangfmt[] = {'%','s','\\','%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0}; 48 49 static const WCHAR szwAssemblies[] = {'A','s','s','e','m','b','l','i','e','s',0}; 50 static const WCHAR szwDefault[] = {'D','e','f','a','u','l','t',0}; 51 static const WCHAR szwProfile[] = {'P','r','o','f','i','l','e',0}; 52 static const WCHAR szwDefaultFmt[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x','\\','%','s',0}; 53 54 typedef struct tagInputProcessorProfiles { 55 ITfInputProcessorProfiles ITfInputProcessorProfiles_iface; 56 ITfSource ITfSource_iface; 57 ITfInputProcessorProfileMgr ITfInputProcessorProfileMgr_iface; 58 /* const ITfInputProcessorProfilesExVtbl *InputProcessorProfilesExVtbl; */ 59 /* const ITfInputProcessorProfileSubstituteLayoutVtbl *InputProcessorProfileSubstituteLayoutVtbl; */ 60 LONG refCount; 61 62 LANGID currentLanguage; 63 64 struct list LanguageProfileNotifySink; 65 } InputProcessorProfiles; 66 67 typedef struct tagProfilesEnumGuid { 68 IEnumGUID IEnumGUID_iface; 69 LONG refCount; 70 71 HKEY key; 72 DWORD next_index; 73 } ProfilesEnumGuid; 74 75 typedef struct tagEnumTfLanguageProfiles { 76 IEnumTfLanguageProfiles IEnumTfLanguageProfiles_iface; 77 LONG refCount; 78 79 HKEY tipkey; 80 DWORD tip_index; 81 WCHAR szwCurrentClsid[39]; 82 83 HKEY langkey; 84 DWORD lang_index; 85 86 LANGID langid; 87 ITfCategoryMgr *catmgr; 88 } EnumTfLanguageProfiles; 89 90 typedef struct { 91 IEnumTfInputProcessorProfiles IEnumTfInputProcessorProfiles_iface; 92 LONG ref; 93 } EnumTfInputProcessorProfiles; 94 95 static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut); 96 static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, EnumTfLanguageProfiles **out); 97 98 static inline EnumTfInputProcessorProfiles *impl_from_IEnumTfInputProcessorProfiles(IEnumTfInputProcessorProfiles *iface) 99 { 100 return CONTAINING_RECORD(iface, EnumTfInputProcessorProfiles, IEnumTfInputProcessorProfiles_iface); 101 } 102 103 static HRESULT WINAPI EnumTfInputProcessorProfiles_QueryInterface(IEnumTfInputProcessorProfiles *iface, 104 REFIID riid, void **ppv) 105 { 106 EnumTfInputProcessorProfiles *This = impl_from_IEnumTfInputProcessorProfiles(iface); 107 108 if(IsEqualGUID(riid, &IID_IUnknown)) { 109 TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv); 110 *ppv = &This->IEnumTfInputProcessorProfiles_iface; 111 }else if(IsEqualGUID(riid, &IID_IEnumTfInputProcessorProfiles)) { 112 TRACE("(%p)->(IID_IEnumTfInputProcessorProfiles %p)\n", This, ppv); 113 *ppv = &This->IEnumTfInputProcessorProfiles_iface; 114 }else { 115 *ppv = NULL; 116 WARN("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); 117 return E_NOINTERFACE; 118 } 119 120 IUnknown_AddRef((IUnknown*)*ppv); 121 return S_OK; 122 } 123 124 static ULONG WINAPI EnumTfInputProcessorProfiles_AddRef(IEnumTfInputProcessorProfiles *iface) 125 { 126 EnumTfInputProcessorProfiles *This = impl_from_IEnumTfInputProcessorProfiles(iface); 127 LONG ref = InterlockedIncrement(&This->ref); 128 129 TRACE("(%p) ref=%d\n", This, ref); 130 131 return ref; 132 } 133 134 static ULONG WINAPI EnumTfInputProcessorProfiles_Release(IEnumTfInputProcessorProfiles *iface) 135 { 136 EnumTfInputProcessorProfiles *This = impl_from_IEnumTfInputProcessorProfiles(iface); 137 LONG ref = InterlockedDecrement(&This->ref); 138 139 TRACE("(%p) ref=%d\n", This, ref); 140 141 if(!ref) 142 HeapFree(GetProcessHeap(), 0, This); 143 144 return ref; 145 } 146 147 static HRESULT WINAPI EnumTfInputProcessorProfiles_Clone(IEnumTfInputProcessorProfiles *iface, 148 IEnumTfInputProcessorProfiles **ret) 149 { 150 EnumTfInputProcessorProfiles *This = impl_from_IEnumTfInputProcessorProfiles(iface); 151 FIXME("(%p)->(%p)\n", This, ret); 152 return E_NOTIMPL; 153 } 154 155 static HRESULT WINAPI EnumTfInputProcessorProfiles_Next(IEnumTfInputProcessorProfiles *iface, ULONG count, 156 TF_INPUTPROCESSORPROFILE *profile, ULONG *fetch) 157 { 158 EnumTfInputProcessorProfiles *This = impl_from_IEnumTfInputProcessorProfiles(iface); 159 160 FIXME("(%p)->(%u %p %p)\n", This, count, profile, fetch); 161 162 if(fetch) 163 *fetch = 0; 164 return S_FALSE; 165 } 166 167 static HRESULT WINAPI EnumTfInputProcessorProfiles_Reset(IEnumTfInputProcessorProfiles *iface) 168 { 169 EnumTfInputProcessorProfiles *This = impl_from_IEnumTfInputProcessorProfiles(iface); 170 FIXME("(%p)\n", This); 171 return E_NOTIMPL; 172 } 173 174 static HRESULT WINAPI EnumTfInputProcessorProfiles_Skip(IEnumTfInputProcessorProfiles *iface, ULONG count) 175 { 176 EnumTfInputProcessorProfiles *This = impl_from_IEnumTfInputProcessorProfiles(iface); 177 FIXME("(%p)->(%u)\n", This, count); 178 return E_NOTIMPL; 179 } 180 181 static const IEnumTfInputProcessorProfilesVtbl EnumTfInputProcessorProfilesVtbl = { 182 EnumTfInputProcessorProfiles_QueryInterface, 183 EnumTfInputProcessorProfiles_AddRef, 184 EnumTfInputProcessorProfiles_Release, 185 EnumTfInputProcessorProfiles_Clone, 186 EnumTfInputProcessorProfiles_Next, 187 EnumTfInputProcessorProfiles_Reset, 188 EnumTfInputProcessorProfiles_Skip 189 }; 190 191 static inline InputProcessorProfiles *impl_from_ITfInputProcessorProfiles(ITfInputProcessorProfiles *iface) 192 { 193 return CONTAINING_RECORD(iface, InputProcessorProfiles, ITfInputProcessorProfiles_iface); 194 } 195 196 static inline InputProcessorProfiles *impl_from_ITfSource(ITfSource *iface) 197 { 198 return CONTAINING_RECORD(iface, InputProcessorProfiles, ITfSource_iface); 199 } 200 201 static inline ProfilesEnumGuid *impl_from_IEnumGUID(IEnumGUID *iface) 202 { 203 return CONTAINING_RECORD(iface, ProfilesEnumGuid, IEnumGUID_iface); 204 } 205 206 static inline EnumTfLanguageProfiles *impl_from_IEnumTfLanguageProfiles(IEnumTfLanguageProfiles *iface) 207 { 208 return CONTAINING_RECORD(iface, EnumTfLanguageProfiles, IEnumTfLanguageProfiles_iface); 209 } 210 211 static void InputProcessorProfiles_Destructor(InputProcessorProfiles *This) 212 { 213 TRACE("destroying %p\n", This); 214 215 free_sinks(&This->LanguageProfileNotifySink); 216 HeapFree(GetProcessHeap(),0,This); 217 } 218 219 static void add_userkey( REFCLSID rclsid, LANGID langid, 220 REFGUID guidProfile) 221 { 222 HKEY key; 223 WCHAR buf[39]; 224 WCHAR buf2[39]; 225 WCHAR fullkey[168]; 226 DWORD disposition = 0; 227 ULONG res; 228 229 TRACE("\n"); 230 231 StringFromGUID2(rclsid, buf, 39); 232 StringFromGUID2(guidProfile, buf2, 39); 233 swprintf(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2); 234 235 res = RegCreateKeyExW(HKEY_CURRENT_USER,fullkey, 0, NULL, 0, 236 KEY_READ | KEY_WRITE, NULL, &key, &disposition); 237 238 if (!res && disposition == REG_CREATED_NEW_KEY) 239 { 240 DWORD zero = 0x0; 241 RegSetValueExW(key, szwEnable, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD)); 242 } 243 244 if (!res) 245 RegCloseKey(key); 246 } 247 248 static HRESULT WINAPI InputProcessorProfiles_QueryInterface(ITfInputProcessorProfiles *iface, REFIID iid, void **ppv) 249 { 250 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 251 252 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfInputProcessorProfiles)) 253 { 254 *ppv = &This->ITfInputProcessorProfiles_iface; 255 } 256 else if (IsEqualIID(iid, &IID_ITfInputProcessorProfileMgr)) 257 { 258 *ppv = &This->ITfInputProcessorProfileMgr_iface; 259 } 260 else if (IsEqualIID(iid, &IID_ITfSource)) 261 { 262 *ppv = &This->ITfSource_iface; 263 } 264 else 265 { 266 *ppv = NULL; 267 WARN("unsupported interface: %s\n", debugstr_guid(iid)); 268 return E_NOINTERFACE; 269 } 270 271 ITfInputProcessorProfiles_AddRef(iface); 272 return S_OK; 273 } 274 275 static ULONG WINAPI InputProcessorProfiles_AddRef(ITfInputProcessorProfiles *iface) 276 { 277 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 278 return InterlockedIncrement(&This->refCount); 279 } 280 281 static ULONG WINAPI InputProcessorProfiles_Release(ITfInputProcessorProfiles *iface) 282 { 283 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 284 ULONG ret; 285 286 ret = InterlockedDecrement(&This->refCount); 287 if (ret == 0) 288 InputProcessorProfiles_Destructor(This); 289 return ret; 290 } 291 292 /***************************************************** 293 * ITfInputProcessorProfiles functions 294 *****************************************************/ 295 static HRESULT WINAPI InputProcessorProfiles_Register( 296 ITfInputProcessorProfiles *iface, REFCLSID rclsid) 297 { 298 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 299 HKEY tipkey; 300 WCHAR buf[39]; 301 WCHAR fullkey[68]; 302 303 TRACE("(%p) %s\n",This,debugstr_guid(rclsid)); 304 305 StringFromGUID2(rclsid, buf, 39); 306 swprintf(fullkey,szwTipfmt,szwSystemTIPKey,buf); 307 308 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, NULL, 0, 309 KEY_READ | KEY_WRITE, NULL, &tipkey, NULL) != ERROR_SUCCESS) 310 return E_FAIL; 311 312 RegCloseKey(tipkey); 313 314 return S_OK; 315 } 316 317 static HRESULT WINAPI InputProcessorProfiles_Unregister( 318 ITfInputProcessorProfiles *iface, REFCLSID rclsid) 319 { 320 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 321 WCHAR buf[39]; 322 WCHAR fullkey[68]; 323 324 TRACE("(%p) %s\n",This,debugstr_guid(rclsid)); 325 326 StringFromGUID2(rclsid, buf, 39); 327 swprintf(fullkey,szwTipfmt,szwSystemTIPKey,buf); 328 329 RegDeleteTreeW(HKEY_LOCAL_MACHINE, fullkey); 330 RegDeleteTreeW(HKEY_CURRENT_USER, fullkey); 331 332 return S_OK; 333 } 334 335 static HRESULT WINAPI InputProcessorProfiles_AddLanguageProfile( 336 ITfInputProcessorProfiles *iface, REFCLSID rclsid, 337 LANGID langid, REFGUID guidProfile, const WCHAR *pchDesc, 338 ULONG cchDesc, const WCHAR *pchIconFile, ULONG cchFile, 339 ULONG uIconIndex) 340 { 341 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 342 HKEY tipkey,fmtkey; 343 WCHAR buf[39]; 344 WCHAR fullkey[100]; 345 ULONG res; 346 DWORD disposition = 0; 347 348 static const WCHAR fmt2[] = {'%','s','\\','0','x','%','0','8','x','\\','%','s',0}; 349 static const WCHAR desc[] = {'D','e','s','c','r','i','p','t','i','o','n',0}; 350 static const WCHAR icnf[] = {'I','c','o','n','F','i','l','e',0}; 351 static const WCHAR icni[] = {'I','c','o','n','I','n','d','e','x',0}; 352 353 TRACE("(%p) %s %x %s %s %s %i\n",This,debugstr_guid(rclsid), langid, 354 debugstr_guid(guidProfile), debugstr_wn(pchDesc,cchDesc), 355 debugstr_wn(pchIconFile,cchFile),uIconIndex); 356 357 StringFromGUID2(rclsid, buf, 39); 358 swprintf(fullkey,szwTipfmt,szwSystemTIPKey,buf); 359 360 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,fullkey, 0, KEY_READ | KEY_WRITE, 361 &tipkey ) != ERROR_SUCCESS) 362 return E_FAIL; 363 364 StringFromGUID2(guidProfile, buf, 39); 365 swprintf(fullkey,fmt2,szwLngp,langid,buf); 366 367 res = RegCreateKeyExW(tipkey,fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE, 368 NULL, &fmtkey, &disposition); 369 370 if (!res) 371 { 372 DWORD zero = 0x0; 373 RegSetValueExW(fmtkey, desc, 0, REG_SZ, (const BYTE*)pchDesc, cchDesc * sizeof(WCHAR)); 374 RegSetValueExW(fmtkey, icnf, 0, REG_SZ, (const BYTE*)pchIconFile, cchFile * sizeof(WCHAR)); 375 RegSetValueExW(fmtkey, icni, 0, REG_DWORD, (LPBYTE)&uIconIndex, sizeof(DWORD)); 376 if (disposition == REG_CREATED_NEW_KEY) 377 RegSetValueExW(fmtkey, szwEnable, 0, REG_DWORD, (LPBYTE)&zero, sizeof(DWORD)); 378 RegCloseKey(fmtkey); 379 380 add_userkey(rclsid, langid, guidProfile); 381 } 382 RegCloseKey(tipkey); 383 384 if (!res) 385 return S_OK; 386 else 387 return E_FAIL; 388 } 389 390 static HRESULT WINAPI InputProcessorProfiles_RemoveLanguageProfile( 391 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, 392 REFGUID guidProfile) 393 { 394 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 395 FIXME("STUB:(%p)\n",This); 396 return E_NOTIMPL; 397 } 398 399 static HRESULT WINAPI InputProcessorProfiles_EnumInputProcessorInfo( 400 ITfInputProcessorProfiles *iface, IEnumGUID **ppEnum) 401 { 402 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 403 TRACE("(%p) %p\n",This,ppEnum); 404 return ProfilesEnumGuid_Constructor(ppEnum); 405 } 406 407 static HRESULT WINAPI InputProcessorProfiles_GetDefaultLanguageProfile( 408 ITfInputProcessorProfiles *iface, LANGID langid, REFGUID catid, 409 CLSID *pclsid, GUID *pguidProfile) 410 { 411 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 412 WCHAR fullkey[168]; 413 WCHAR buf[39]; 414 HKEY hkey; 415 DWORD count; 416 ULONG res; 417 418 TRACE("%p) %x %s %p %p\n",This, langid, debugstr_guid(catid),pclsid,pguidProfile); 419 420 if (!catid || !pclsid || !pguidProfile) 421 return E_INVALIDARG; 422 423 StringFromGUID2(catid, buf, 39); 424 swprintf(fullkey, szwDefaultFmt, szwSystemCTFKey, szwAssemblies, langid, buf); 425 426 if (RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, 427 &hkey ) != ERROR_SUCCESS) 428 return S_FALSE; 429 430 count = sizeof(buf); 431 res = RegQueryValueExW(hkey, szwDefault, 0, NULL, (LPBYTE)buf, &count); 432 if (res != ERROR_SUCCESS) 433 { 434 RegCloseKey(hkey); 435 return S_FALSE; 436 } 437 CLSIDFromString(buf,pclsid); 438 439 res = RegQueryValueExW(hkey, szwProfile, 0, NULL, (LPBYTE)buf, &count); 440 if (res == ERROR_SUCCESS) 441 CLSIDFromString(buf,pguidProfile); 442 443 RegCloseKey(hkey); 444 445 return S_OK; 446 } 447 448 static HRESULT WINAPI InputProcessorProfiles_SetDefaultLanguageProfile( 449 ITfInputProcessorProfiles *iface, LANGID langid, REFCLSID rclsid, 450 REFGUID guidProfiles) 451 { 452 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 453 WCHAR fullkey[168]; 454 WCHAR buf[39]; 455 HKEY hkey; 456 GUID catid; 457 HRESULT hr; 458 ITfCategoryMgr *catmgr; 459 static const GUID * tipcats[3] = { &GUID_TFCAT_TIP_KEYBOARD, 460 &GUID_TFCAT_TIP_SPEECH, 461 &GUID_TFCAT_TIP_HANDWRITING }; 462 463 TRACE("%p) %x %s %s\n",This, langid, debugstr_guid(rclsid),debugstr_guid(guidProfiles)); 464 465 if (!rclsid || !guidProfiles) 466 return E_INVALIDARG; 467 468 hr = CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr); 469 470 if (FAILED(hr)) 471 return hr; 472 473 if (ITfCategoryMgr_FindClosestCategory(catmgr, rclsid, 474 &catid, tipcats, 3) != S_OK) 475 hr = ITfCategoryMgr_FindClosestCategory(catmgr, rclsid, 476 &catid, NULL, 0); 477 ITfCategoryMgr_Release(catmgr); 478 479 if (FAILED(hr)) 480 return E_FAIL; 481 482 StringFromGUID2(&catid, buf, 39); 483 swprintf(fullkey, szwDefaultFmt, szwSystemCTFKey, szwAssemblies, langid, buf); 484 485 if (RegCreateKeyExW(HKEY_CURRENT_USER, fullkey, 0, NULL, 0, KEY_READ | KEY_WRITE, 486 NULL, &hkey, NULL ) != ERROR_SUCCESS) 487 return E_FAIL; 488 489 StringFromGUID2(rclsid, buf, 39); 490 RegSetValueExW(hkey, szwDefault, 0, REG_SZ, (LPBYTE)buf, sizeof(buf)); 491 StringFromGUID2(guidProfiles, buf, 39); 492 RegSetValueExW(hkey, szwProfile, 0, REG_SZ, (LPBYTE)buf, sizeof(buf)); 493 RegCloseKey(hkey); 494 495 return S_OK; 496 } 497 498 static HRESULT WINAPI InputProcessorProfiles_ActivateLanguageProfile( 499 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, 500 REFGUID guidProfiles) 501 { 502 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 503 HRESULT hr; 504 BOOL enabled; 505 TF_LANGUAGEPROFILE LanguageProfile; 506 507 TRACE("(%p) %s %x %s\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfiles)); 508 509 if (langid != This->currentLanguage) return E_INVALIDARG; 510 511 if (get_active_textservice(rclsid,NULL)) 512 { 513 TRACE("Already Active\n"); 514 return E_FAIL; 515 } 516 517 hr = ITfInputProcessorProfiles_IsEnabledLanguageProfile(iface, rclsid, 518 langid, guidProfiles, &enabled); 519 if (FAILED(hr) || !enabled) 520 { 521 TRACE("Not Enabled\n"); 522 return E_FAIL; 523 } 524 525 LanguageProfile.clsid = *rclsid; 526 LanguageProfile.langid = langid; 527 LanguageProfile.guidProfile = *guidProfiles; 528 LanguageProfile.fActive = TRUE; 529 530 return add_active_textservice(&LanguageProfile); 531 } 532 533 static HRESULT WINAPI InputProcessorProfiles_GetActiveLanguageProfile( 534 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID *plangid, 535 GUID *pguidProfile) 536 { 537 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 538 TF_LANGUAGEPROFILE profile; 539 540 TRACE("(%p) %s %p %p\n",This,debugstr_guid(rclsid),plangid,pguidProfile); 541 542 if (!rclsid || !plangid || !pguidProfile) 543 return E_INVALIDARG; 544 545 if (get_active_textservice(rclsid, &profile)) 546 { 547 *plangid = profile.langid; 548 *pguidProfile = profile.guidProfile; 549 return S_OK; 550 } 551 else 552 { 553 *pguidProfile = GUID_NULL; 554 return S_FALSE; 555 } 556 } 557 558 static HRESULT WINAPI InputProcessorProfiles_GetLanguageProfileDescription( 559 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, 560 REFGUID guidProfile, BSTR *pbstrProfile) 561 { 562 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 563 FIXME("STUB:(%p)\n",This); 564 return E_NOTIMPL; 565 } 566 567 static HRESULT WINAPI InputProcessorProfiles_GetCurrentLanguage( 568 ITfInputProcessorProfiles *iface, LANGID *plangid) 569 { 570 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 571 TRACE("(%p) 0x%x\n",This,This->currentLanguage); 572 573 if (!plangid) 574 return E_INVALIDARG; 575 576 *plangid = This->currentLanguage; 577 578 return S_OK; 579 } 580 581 static HRESULT WINAPI InputProcessorProfiles_ChangeCurrentLanguage( 582 ITfInputProcessorProfiles *iface, LANGID langid) 583 { 584 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 585 ITfLanguageProfileNotifySink *sink; 586 struct list *cursor; 587 BOOL accept; 588 589 FIXME("STUB:(%p)\n",This); 590 591 SINK_FOR_EACH(cursor, &This->LanguageProfileNotifySink, ITfLanguageProfileNotifySink, sink) 592 { 593 accept = TRUE; 594 ITfLanguageProfileNotifySink_OnLanguageChange(sink, langid, &accept); 595 if (!accept) 596 return E_FAIL; 597 } 598 599 /* TODO: On successful language change call OnLanguageChanged sink */ 600 return E_NOTIMPL; 601 } 602 603 static HRESULT WINAPI InputProcessorProfiles_GetLanguageList( 604 ITfInputProcessorProfiles *iface, LANGID **ppLangId, ULONG *pulCount) 605 { 606 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 607 FIXME("Semi-STUB:(%p)\n",This); 608 *ppLangId = CoTaskMemAlloc(sizeof(LANGID)); 609 **ppLangId = This->currentLanguage; 610 *pulCount = 1; 611 return S_OK; 612 } 613 614 static HRESULT WINAPI InputProcessorProfiles_EnumLanguageProfiles( 615 ITfInputProcessorProfiles *iface, LANGID langid, 616 IEnumTfLanguageProfiles **ppEnum) 617 { 618 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 619 EnumTfLanguageProfiles *profenum; 620 HRESULT hr; 621 622 TRACE("(%p) %x %p\n",This,langid,ppEnum); 623 624 if (!ppEnum) 625 return E_INVALIDARG; 626 hr = EnumTfLanguageProfiles_Constructor(langid, &profenum); 627 *ppEnum = &profenum->IEnumTfLanguageProfiles_iface; 628 629 return hr; 630 } 631 632 static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfile( 633 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, 634 REFGUID guidProfile, BOOL fEnable) 635 { 636 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 637 HKEY key; 638 WCHAR buf[39]; 639 WCHAR buf2[39]; 640 WCHAR fullkey[168]; 641 ULONG res; 642 643 TRACE("(%p) %s %x %s %i\n",This, debugstr_guid(rclsid), langid, debugstr_guid(guidProfile), fEnable); 644 645 StringFromGUID2(rclsid, buf, 39); 646 StringFromGUID2(guidProfile, buf2, 39); 647 swprintf(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2); 648 649 res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key); 650 651 if (!res) 652 { 653 RegSetValueExW(key, szwEnable, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD)); 654 RegCloseKey(key); 655 } 656 else 657 return E_FAIL; 658 659 return S_OK; 660 } 661 662 static HRESULT WINAPI InputProcessorProfiles_IsEnabledLanguageProfile( 663 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, 664 REFGUID guidProfile, BOOL *pfEnable) 665 { 666 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 667 HKEY key; 668 WCHAR buf[39]; 669 WCHAR buf2[39]; 670 WCHAR fullkey[168]; 671 ULONG res; 672 673 TRACE("(%p) %s, %i, %s, %p\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),pfEnable); 674 675 if (!pfEnable) 676 return E_INVALIDARG; 677 678 StringFromGUID2(rclsid, buf, 39); 679 StringFromGUID2(guidProfile, buf2, 39); 680 swprintf(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2); 681 682 res = RegOpenKeyExW(HKEY_CURRENT_USER, fullkey, 0, KEY_READ | KEY_WRITE, &key); 683 684 if (!res) 685 { 686 DWORD count = sizeof(DWORD); 687 res = RegQueryValueExW(key, szwEnable, 0, NULL, (LPBYTE)pfEnable, &count); 688 RegCloseKey(key); 689 } 690 691 if (res) /* Try Default */ 692 { 693 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key); 694 695 if (!res) 696 { 697 DWORD count = sizeof(DWORD); 698 res = RegQueryValueExW(key, szwEnable, 0, NULL, (LPBYTE)pfEnable, &count); 699 RegCloseKey(key); 700 } 701 } 702 703 if (!res) 704 return S_OK; 705 else 706 return E_FAIL; 707 } 708 709 static HRESULT WINAPI InputProcessorProfiles_EnableLanguageProfileByDefault( 710 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, 711 REFGUID guidProfile, BOOL fEnable) 712 { 713 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 714 HKEY key; 715 WCHAR buf[39]; 716 WCHAR buf2[39]; 717 WCHAR fullkey[168]; 718 ULONG res; 719 720 TRACE("(%p) %s %x %s %i\n",This,debugstr_guid(rclsid),langid,debugstr_guid(guidProfile),fEnable); 721 722 StringFromGUID2(rclsid, buf, 39); 723 StringFromGUID2(guidProfile, buf2, 39); 724 swprintf(fullkey,szwFullLangfmt,szwSystemTIPKey,buf,szwLngp,langid,buf2); 725 726 res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, fullkey, 0, KEY_READ | KEY_WRITE, &key); 727 728 if (!res) 729 { 730 RegSetValueExW(key, szwEnable, 0, REG_DWORD, (LPBYTE)&fEnable, sizeof(DWORD)); 731 RegCloseKey(key); 732 } 733 else 734 return E_FAIL; 735 736 return S_OK; 737 } 738 739 static HRESULT WINAPI InputProcessorProfiles_SubstituteKeyboardLayout( 740 ITfInputProcessorProfiles *iface, REFCLSID rclsid, LANGID langid, 741 REFGUID guidProfile, HKL hKL) 742 { 743 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfiles(iface); 744 FIXME("STUB:(%p)\n",This); 745 return E_NOTIMPL; 746 } 747 748 static const ITfInputProcessorProfilesVtbl InputProcessorProfilesVtbl = 749 { 750 InputProcessorProfiles_QueryInterface, 751 InputProcessorProfiles_AddRef, 752 InputProcessorProfiles_Release, 753 InputProcessorProfiles_Register, 754 InputProcessorProfiles_Unregister, 755 InputProcessorProfiles_AddLanguageProfile, 756 InputProcessorProfiles_RemoveLanguageProfile, 757 InputProcessorProfiles_EnumInputProcessorInfo, 758 InputProcessorProfiles_GetDefaultLanguageProfile, 759 InputProcessorProfiles_SetDefaultLanguageProfile, 760 InputProcessorProfiles_ActivateLanguageProfile, 761 InputProcessorProfiles_GetActiveLanguageProfile, 762 InputProcessorProfiles_GetLanguageProfileDescription, 763 InputProcessorProfiles_GetCurrentLanguage, 764 InputProcessorProfiles_ChangeCurrentLanguage, 765 InputProcessorProfiles_GetLanguageList, 766 InputProcessorProfiles_EnumLanguageProfiles, 767 InputProcessorProfiles_EnableLanguageProfile, 768 InputProcessorProfiles_IsEnabledLanguageProfile, 769 InputProcessorProfiles_EnableLanguageProfileByDefault, 770 InputProcessorProfiles_SubstituteKeyboardLayout 771 }; 772 773 static inline InputProcessorProfiles *impl_from_ITfInputProcessorProfileMgr(ITfInputProcessorProfileMgr *iface) 774 { 775 return CONTAINING_RECORD(iface, InputProcessorProfiles, ITfInputProcessorProfileMgr_iface); 776 } 777 778 static HRESULT WINAPI InputProcessorProfileMgr_QueryInterface(ITfInputProcessorProfileMgr *iface, REFIID riid, void **ppv) 779 { 780 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface); 781 return ITfInputProcessorProfiles_QueryInterface(&This->ITfInputProcessorProfiles_iface, riid, ppv); 782 } 783 784 static ULONG WINAPI InputProcessorProfileMgr_AddRef(ITfInputProcessorProfileMgr *iface) 785 { 786 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface); 787 return ITfInputProcessorProfiles_AddRef(&This->ITfInputProcessorProfiles_iface); 788 } 789 790 static ULONG WINAPI InputProcessorProfileMgr_Release(ITfInputProcessorProfileMgr *iface) 791 { 792 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface); 793 return ITfInputProcessorProfiles_Release(&This->ITfInputProcessorProfiles_iface); 794 } 795 796 static HRESULT WINAPI InputProcessorProfileMgr_ActivateProfile(ITfInputProcessorProfileMgr *iface, DWORD dwProfileType, 797 LANGID langid, REFCLSID clsid, REFGUID guidProfile, HKL hkl, DWORD dwFlags) 798 { 799 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface); 800 FIXME("(%p)->(%d %x %s %s %p %x)\n", This, dwProfileType, langid, debugstr_guid(clsid), 801 debugstr_guid(guidProfile), hkl, dwFlags); 802 return E_NOTIMPL; 803 } 804 805 static HRESULT WINAPI InputProcessorProfileMgr_DeactivateProfile(ITfInputProcessorProfileMgr *iface, DWORD dwProfileType, 806 LANGID langid, REFCLSID clsid, REFGUID guidProfile, HKL hkl, DWORD dwFlags) 807 { 808 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface); 809 FIXME("(%p)->(%d %x %s %s %p %x)\n", This, dwProfileType, langid, debugstr_guid(clsid), 810 debugstr_guid(guidProfile), hkl, dwFlags); 811 return E_NOTIMPL; 812 } 813 814 static HRESULT WINAPI InputProcessorProfileMgr_GetProfile(ITfInputProcessorProfileMgr *iface, DWORD dwProfileType, 815 LANGID langid, REFCLSID clsid, REFGUID guidProfile, HKL hkl, TF_INPUTPROCESSORPROFILE *pProfile) 816 { 817 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface); 818 FIXME("(%p)->(%d %x %s %s %p %p)\n", This, dwProfileType, langid, debugstr_guid(clsid), 819 debugstr_guid(guidProfile), hkl, pProfile); 820 return E_NOTIMPL; 821 } 822 823 static HRESULT WINAPI InputProcessorProfileMgr_EnumProfiles(ITfInputProcessorProfileMgr *iface, LANGID langid, 824 IEnumTfInputProcessorProfiles **ppEnum) 825 { 826 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface); 827 EnumTfInputProcessorProfiles *enum_profiles; 828 829 TRACE("(%p)->(%x %p)\n", This, langid, ppEnum); 830 831 enum_profiles = HeapAlloc(GetProcessHeap(), 0, sizeof(*enum_profiles)); 832 if(!enum_profiles) 833 return E_OUTOFMEMORY; 834 835 enum_profiles->IEnumTfInputProcessorProfiles_iface.lpVtbl = &EnumTfInputProcessorProfilesVtbl; 836 enum_profiles->ref = 1; 837 838 *ppEnum = &enum_profiles->IEnumTfInputProcessorProfiles_iface; 839 return S_OK; 840 } 841 842 static HRESULT WINAPI InputProcessorProfileMgr_ReleaseInputProcessor(ITfInputProcessorProfileMgr *iface, REFCLSID rclsid, 843 DWORD dwFlags) 844 { 845 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface); 846 FIXME("(%p)->(%s %x)\n", This, debugstr_guid(rclsid), dwFlags); 847 return E_NOTIMPL; 848 } 849 850 static HRESULT WINAPI InputProcessorProfileMgr_RegisterProfile(ITfInputProcessorProfileMgr *iface, REFCLSID rclsid, 851 LANGID langid, REFGUID guidProfile, const WCHAR *pchDesc, ULONG cchDesc, const WCHAR *pchIconFile, 852 ULONG cchFile, ULONG uIconIndex, HKL hklsubstitute, DWORD dwPreferredLayout, BOOL bEnabledByDefault, 853 DWORD dwFlags) 854 { 855 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface); 856 FIXME("(%p)->(%s %x %s %s %d %s %u %u %p %x %x %x)\n", This, debugstr_guid(rclsid), langid, debugstr_guid(guidProfile), 857 debugstr_w(pchDesc), cchDesc, debugstr_w(pchIconFile), cchFile, uIconIndex, hklsubstitute, dwPreferredLayout, 858 bEnabledByDefault, dwFlags); 859 return E_NOTIMPL; 860 } 861 862 static HRESULT WINAPI InputProcessorProfileMgr_UnregisterProfile(ITfInputProcessorProfileMgr *iface, REFCLSID rclsid, 863 LANGID langid, REFGUID guidProfile, DWORD dwFlags) 864 { 865 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface); 866 FIXME("(%p)->(%s %x %s %x)\n", This, debugstr_guid(rclsid), langid, debugstr_guid(guidProfile), dwFlags); 867 return E_NOTIMPL; 868 } 869 870 static HRESULT WINAPI InputProcessorProfileMgr_GetActiveProfile(ITfInputProcessorProfileMgr *iface, REFGUID catid, 871 TF_INPUTPROCESSORPROFILE *pProfile) 872 { 873 InputProcessorProfiles *This = impl_from_ITfInputProcessorProfileMgr(iface); 874 FIXME("(%p)->(%s %p)\n", This, debugstr_guid(catid), pProfile); 875 return E_NOTIMPL; 876 } 877 878 static const ITfInputProcessorProfileMgrVtbl InputProcessorProfileMgrVtbl = { 879 InputProcessorProfileMgr_QueryInterface, 880 InputProcessorProfileMgr_AddRef, 881 InputProcessorProfileMgr_Release, 882 InputProcessorProfileMgr_ActivateProfile, 883 InputProcessorProfileMgr_DeactivateProfile, 884 InputProcessorProfileMgr_GetProfile, 885 InputProcessorProfileMgr_EnumProfiles, 886 InputProcessorProfileMgr_ReleaseInputProcessor, 887 InputProcessorProfileMgr_RegisterProfile, 888 InputProcessorProfileMgr_UnregisterProfile, 889 InputProcessorProfileMgr_GetActiveProfile 890 }; 891 892 /***************************************************** 893 * ITfSource functions 894 *****************************************************/ 895 static HRESULT WINAPI IPPSource_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut) 896 { 897 InputProcessorProfiles *This = impl_from_ITfSource(iface); 898 return ITfInputProcessorProfiles_QueryInterface(&This->ITfInputProcessorProfiles_iface, iid, ppvOut); 899 } 900 901 static ULONG WINAPI IPPSource_AddRef(ITfSource *iface) 902 { 903 InputProcessorProfiles *This = impl_from_ITfSource(iface); 904 return ITfInputProcessorProfiles_AddRef(&This->ITfInputProcessorProfiles_iface); 905 } 906 907 static ULONG WINAPI IPPSource_Release(ITfSource *iface) 908 { 909 InputProcessorProfiles *This = impl_from_ITfSource(iface); 910 return ITfInputProcessorProfiles_Release(&This->ITfInputProcessorProfiles_iface); 911 } 912 913 static HRESULT WINAPI IPPSource_AdviseSink(ITfSource *iface, 914 REFIID riid, IUnknown *punk, DWORD *pdwCookie) 915 { 916 InputProcessorProfiles *This = impl_from_ITfSource(iface); 917 918 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie); 919 920 if (!riid || !punk || !pdwCookie) 921 return E_INVALIDARG; 922 923 if (IsEqualIID(riid, &IID_ITfLanguageProfileNotifySink)) 924 return advise_sink(&This->LanguageProfileNotifySink, &IID_ITfLanguageProfileNotifySink, 925 COOKIE_MAGIC_IPPSINK, punk, pdwCookie); 926 927 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid)); 928 return E_NOTIMPL; 929 } 930 931 static HRESULT WINAPI IPPSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie) 932 { 933 InputProcessorProfiles *This = impl_from_ITfSource(iface); 934 935 TRACE("(%p) %x\n",This,pdwCookie); 936 937 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_IPPSINK) 938 return E_INVALIDARG; 939 940 return unadvise_sink(pdwCookie); 941 } 942 943 static const ITfSourceVtbl InputProcessorProfilesSourceVtbl = 944 { 945 IPPSource_QueryInterface, 946 IPPSource_AddRef, 947 IPPSource_Release, 948 IPPSource_AdviseSink, 949 IPPSource_UnadviseSink, 950 }; 951 952 HRESULT InputProcessorProfiles_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) 953 { 954 InputProcessorProfiles *This; 955 if (pUnkOuter) 956 return CLASS_E_NOAGGREGATION; 957 958 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(InputProcessorProfiles)); 959 if (This == NULL) 960 return E_OUTOFMEMORY; 961 962 This->ITfInputProcessorProfiles_iface.lpVtbl= &InputProcessorProfilesVtbl; 963 This->ITfSource_iface.lpVtbl = &InputProcessorProfilesSourceVtbl; 964 This->ITfInputProcessorProfileMgr_iface.lpVtbl = &InputProcessorProfileMgrVtbl; 965 This->refCount = 1; 966 This->currentLanguage = GetUserDefaultLCID(); 967 968 list_init(&This->LanguageProfileNotifySink); 969 970 *ppOut = (IUnknown *)&This->ITfInputProcessorProfiles_iface; 971 TRACE("returning %p\n", *ppOut); 972 return S_OK; 973 } 974 975 /************************************************** 976 * IEnumGUID implementation for ITfInputProcessorProfiles::EnumInputProcessorInfo 977 **************************************************/ 978 static void ProfilesEnumGuid_Destructor(ProfilesEnumGuid *This) 979 { 980 TRACE("destroying %p\n", This); 981 RegCloseKey(This->key); 982 HeapFree(GetProcessHeap(),0,This); 983 } 984 985 static HRESULT WINAPI ProfilesEnumGuid_QueryInterface(IEnumGUID *iface, REFIID iid, LPVOID *ppvOut) 986 { 987 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface); 988 *ppvOut = NULL; 989 990 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumGUID)) 991 { 992 *ppvOut = &This->IEnumGUID_iface; 993 } 994 995 if (*ppvOut) 996 { 997 IEnumGUID_AddRef(iface); 998 return S_OK; 999 } 1000 1001 WARN("unsupported interface: %s\n", debugstr_guid(iid)); 1002 return E_NOINTERFACE; 1003 } 1004 1005 static ULONG WINAPI ProfilesEnumGuid_AddRef(IEnumGUID *iface) 1006 { 1007 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface); 1008 return InterlockedIncrement(&This->refCount); 1009 } 1010 1011 static ULONG WINAPI ProfilesEnumGuid_Release(IEnumGUID *iface) 1012 { 1013 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface); 1014 ULONG ret; 1015 1016 ret = InterlockedDecrement(&This->refCount); 1017 if (ret == 0) 1018 ProfilesEnumGuid_Destructor(This); 1019 return ret; 1020 } 1021 1022 /***************************************************** 1023 * IEnumGuid functions 1024 *****************************************************/ 1025 static HRESULT WINAPI ProfilesEnumGuid_Next( LPENUMGUID iface, 1026 ULONG celt, GUID *rgelt, ULONG *pceltFetched) 1027 { 1028 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface); 1029 ULONG fetched = 0; 1030 1031 TRACE("(%p)\n",This); 1032 1033 if (rgelt == NULL) return E_POINTER; 1034 1035 if (This->key) while (fetched < celt) 1036 { 1037 LSTATUS res; 1038 HRESULT hr; 1039 WCHAR catid[39]; 1040 DWORD cName = 39; 1041 1042 res = RegEnumKeyExW(This->key, This->next_index, catid, &cName, 1043 NULL, NULL, NULL, NULL); 1044 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break; 1045 ++(This->next_index); 1046 1047 hr = CLSIDFromString(catid, rgelt); 1048 if (FAILED(hr)) continue; 1049 1050 ++fetched; 1051 ++rgelt; 1052 } 1053 1054 if (pceltFetched) *pceltFetched = fetched; 1055 return fetched == celt ? S_OK : S_FALSE; 1056 } 1057 1058 static HRESULT WINAPI ProfilesEnumGuid_Skip( LPENUMGUID iface, ULONG celt) 1059 { 1060 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface); 1061 TRACE("(%p)\n",This); 1062 1063 This->next_index += celt; 1064 return S_OK; 1065 } 1066 1067 static HRESULT WINAPI ProfilesEnumGuid_Reset( LPENUMGUID iface) 1068 { 1069 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface); 1070 TRACE("(%p)\n",This); 1071 This->next_index = 0; 1072 return S_OK; 1073 } 1074 1075 static HRESULT WINAPI ProfilesEnumGuid_Clone( LPENUMGUID iface, 1076 IEnumGUID **ppenum) 1077 { 1078 ProfilesEnumGuid *This = impl_from_IEnumGUID(iface); 1079 HRESULT res; 1080 1081 TRACE("(%p)\n",This); 1082 1083 if (ppenum == NULL) return E_POINTER; 1084 1085 res = ProfilesEnumGuid_Constructor(ppenum); 1086 if (SUCCEEDED(res)) 1087 { 1088 ProfilesEnumGuid *new_This = impl_from_IEnumGUID(*ppenum); 1089 new_This->next_index = This->next_index; 1090 } 1091 return res; 1092 } 1093 1094 static const IEnumGUIDVtbl EnumGUIDVtbl = 1095 { 1096 ProfilesEnumGuid_QueryInterface, 1097 ProfilesEnumGuid_AddRef, 1098 ProfilesEnumGuid_Release, 1099 ProfilesEnumGuid_Next, 1100 ProfilesEnumGuid_Skip, 1101 ProfilesEnumGuid_Reset, 1102 ProfilesEnumGuid_Clone 1103 }; 1104 1105 static HRESULT ProfilesEnumGuid_Constructor(IEnumGUID **ppOut) 1106 { 1107 ProfilesEnumGuid *This; 1108 1109 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ProfilesEnumGuid)); 1110 if (This == NULL) 1111 return E_OUTOFMEMORY; 1112 1113 This->IEnumGUID_iface.lpVtbl= &EnumGUIDVtbl; 1114 This->refCount = 1; 1115 1116 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0, 1117 KEY_READ | KEY_WRITE, NULL, &This->key, NULL) != ERROR_SUCCESS) 1118 { 1119 HeapFree(GetProcessHeap(), 0, This); 1120 return E_FAIL; 1121 } 1122 1123 *ppOut = &This->IEnumGUID_iface; 1124 TRACE("returning %p\n", *ppOut); 1125 return S_OK; 1126 } 1127 1128 /************************************************** 1129 * IEnumTfLanguageProfiles implementation 1130 **************************************************/ 1131 static void EnumTfLanguageProfiles_Destructor(EnumTfLanguageProfiles *This) 1132 { 1133 TRACE("destroying %p\n", This); 1134 RegCloseKey(This->tipkey); 1135 if (This->langkey) 1136 RegCloseKey(This->langkey); 1137 ITfCategoryMgr_Release(This->catmgr); 1138 HeapFree(GetProcessHeap(),0,This); 1139 } 1140 1141 static HRESULT WINAPI EnumTfLanguageProfiles_QueryInterface(IEnumTfLanguageProfiles *iface, REFIID iid, LPVOID *ppvOut) 1142 { 1143 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface); 1144 1145 *ppvOut = NULL; 1146 1147 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfLanguageProfiles)) 1148 { 1149 *ppvOut = &This->IEnumTfLanguageProfiles_iface; 1150 } 1151 1152 if (*ppvOut) 1153 { 1154 IEnumTfLanguageProfiles_AddRef(iface); 1155 return S_OK; 1156 } 1157 1158 WARN("unsupported interface: %s\n", debugstr_guid(iid)); 1159 return E_NOINTERFACE; 1160 } 1161 1162 static ULONG WINAPI EnumTfLanguageProfiles_AddRef(IEnumTfLanguageProfiles *iface) 1163 { 1164 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface); 1165 return InterlockedIncrement(&This->refCount); 1166 } 1167 1168 static ULONG WINAPI EnumTfLanguageProfiles_Release(IEnumTfLanguageProfiles *iface) 1169 { 1170 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface); 1171 ULONG ret; 1172 1173 ret = InterlockedDecrement(&This->refCount); 1174 if (ret == 0) 1175 EnumTfLanguageProfiles_Destructor(This); 1176 return ret; 1177 } 1178 1179 /***************************************************** 1180 * IEnumGuid functions 1181 *****************************************************/ 1182 static INT next_LanguageProfile(EnumTfLanguageProfiles *This, CLSID clsid, TF_LANGUAGEPROFILE *tflp) 1183 { 1184 WCHAR fullkey[168]; 1185 ULONG res; 1186 WCHAR profileid[39]; 1187 DWORD cName = 39; 1188 GUID profile; 1189 1190 static const WCHAR fmt[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0}; 1191 1192 if (This->langkey == NULL) 1193 { 1194 swprintf(fullkey,fmt,This->szwCurrentClsid,szwLngp,This->langid); 1195 res = RegOpenKeyExW(This->tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &This->langkey); 1196 if (res) 1197 { 1198 This->langkey = NULL; 1199 return -1; 1200 } 1201 This->lang_index = 0; 1202 } 1203 res = RegEnumKeyExW(This->langkey, This->lang_index, profileid, &cName, 1204 NULL, NULL, NULL, NULL); 1205 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) 1206 { 1207 RegCloseKey(This->langkey); 1208 This->langkey = NULL; 1209 return -1; 1210 } 1211 ++(This->lang_index); 1212 1213 if (tflp) 1214 { 1215 static const GUID * tipcats[3] = { &GUID_TFCAT_TIP_KEYBOARD, 1216 &GUID_TFCAT_TIP_SPEECH, 1217 &GUID_TFCAT_TIP_HANDWRITING }; 1218 res = CLSIDFromString(profileid, &profile); 1219 if (FAILED(res)) return 0; 1220 1221 tflp->clsid = clsid; 1222 tflp->langid = This->langid; 1223 tflp->fActive = get_active_textservice(&clsid, NULL); 1224 tflp->guidProfile = profile; 1225 if (ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid, 1226 &tflp->catid, tipcats, 3) != S_OK) 1227 ITfCategoryMgr_FindClosestCategory(This->catmgr, &clsid, 1228 &tflp->catid, NULL, 0); 1229 } 1230 1231 return 1; 1232 } 1233 1234 static HRESULT WINAPI EnumTfLanguageProfiles_Next(IEnumTfLanguageProfiles *iface, 1235 ULONG ulCount, TF_LANGUAGEPROFILE *pProfile, ULONG *pcFetch) 1236 { 1237 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface); 1238 ULONG fetched = 0; 1239 1240 TRACE("(%p)\n",This); 1241 1242 if (pProfile == NULL) return E_POINTER; 1243 1244 if (This->tipkey) while (fetched < ulCount) 1245 { 1246 LSTATUS res; 1247 HRESULT hr; 1248 DWORD cName = 39; 1249 GUID clsid; 1250 1251 res = RegEnumKeyExW(This->tipkey, This->tip_index, 1252 This->szwCurrentClsid, &cName, NULL, NULL, NULL, NULL); 1253 if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) break; 1254 ++(This->tip_index); 1255 hr = CLSIDFromString(This->szwCurrentClsid, &clsid); 1256 if (FAILED(hr)) continue; 1257 1258 while ( fetched < ulCount) 1259 { 1260 INT res = next_LanguageProfile(This, clsid, pProfile); 1261 if (res == 1) 1262 { 1263 ++fetched; 1264 ++pProfile; 1265 } 1266 else if (res == -1) 1267 break; 1268 else 1269 continue; 1270 } 1271 } 1272 1273 if (pcFetch) *pcFetch = fetched; 1274 return fetched == ulCount ? S_OK : S_FALSE; 1275 } 1276 1277 static HRESULT WINAPI EnumTfLanguageProfiles_Skip( IEnumTfLanguageProfiles* iface, ULONG celt) 1278 { 1279 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface); 1280 FIXME("STUB (%p)\n",This); 1281 return E_NOTIMPL; 1282 } 1283 1284 static HRESULT WINAPI EnumTfLanguageProfiles_Reset( IEnumTfLanguageProfiles* iface) 1285 { 1286 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface); 1287 TRACE("(%p)\n",This); 1288 This->tip_index = 0; 1289 if (This->langkey) 1290 RegCloseKey(This->langkey); 1291 This->langkey = NULL; 1292 This->lang_index = 0; 1293 return S_OK; 1294 } 1295 1296 static HRESULT WINAPI EnumTfLanguageProfiles_Clone( IEnumTfLanguageProfiles *iface, 1297 IEnumTfLanguageProfiles **ppenum) 1298 { 1299 EnumTfLanguageProfiles *This = impl_from_IEnumTfLanguageProfiles(iface); 1300 EnumTfLanguageProfiles *new_This; 1301 HRESULT res; 1302 1303 TRACE("(%p)\n",This); 1304 1305 if (ppenum == NULL) return E_POINTER; 1306 1307 res = EnumTfLanguageProfiles_Constructor(This->langid, &new_This); 1308 if (SUCCEEDED(res)) 1309 { 1310 new_This->tip_index = This->tip_index; 1311 lstrcpynW(new_This->szwCurrentClsid,This->szwCurrentClsid,39); 1312 1313 if (This->langkey) 1314 { 1315 WCHAR fullkey[168]; 1316 static const WCHAR fmt[] = {'%','s','\\','%','s','\\','0','x','%','0','8','x',0}; 1317 1318 swprintf(fullkey,fmt,This->szwCurrentClsid,szwLngp,This->langid); 1319 res = RegOpenKeyExW(new_This->tipkey, fullkey, 0, KEY_READ | KEY_WRITE, &This->langkey); 1320 new_This->lang_index = This->lang_index; 1321 } 1322 *ppenum = &new_This->IEnumTfLanguageProfiles_iface; 1323 } 1324 return res; 1325 } 1326 1327 static const IEnumTfLanguageProfilesVtbl EnumTfLanguageProfilesVtbl = 1328 { 1329 EnumTfLanguageProfiles_QueryInterface, 1330 EnumTfLanguageProfiles_AddRef, 1331 EnumTfLanguageProfiles_Release, 1332 EnumTfLanguageProfiles_Clone, 1333 EnumTfLanguageProfiles_Next, 1334 EnumTfLanguageProfiles_Reset, 1335 EnumTfLanguageProfiles_Skip 1336 }; 1337 1338 static HRESULT EnumTfLanguageProfiles_Constructor(LANGID langid, EnumTfLanguageProfiles **out) 1339 { 1340 HRESULT hr; 1341 EnumTfLanguageProfiles *This; 1342 1343 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfLanguageProfiles)); 1344 if (This == NULL) 1345 return E_OUTOFMEMORY; 1346 1347 This->IEnumTfLanguageProfiles_iface.lpVtbl= &EnumTfLanguageProfilesVtbl; 1348 This->refCount = 1; 1349 This->langid = langid; 1350 1351 hr = CategoryMgr_Constructor(NULL,(IUnknown**)&This->catmgr); 1352 if (FAILED(hr)) 1353 { 1354 HeapFree(GetProcessHeap(),0,This); 1355 return hr; 1356 } 1357 1358 if (RegCreateKeyExW(HKEY_LOCAL_MACHINE, szwSystemTIPKey, 0, NULL, 0, 1359 KEY_READ | KEY_WRITE, NULL, &This->tipkey, NULL) != ERROR_SUCCESS) 1360 { 1361 HeapFree(GetProcessHeap(), 0, This); 1362 return E_FAIL; 1363 } 1364 1365 *out = This; 1366 TRACE("returning %p\n", *out); 1367 return S_OK; 1368 } 1369