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