1 /* 2 * PROJECT: ReactOS msctfime.ime 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Profile of msctfime.ime 5 * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 */ 7 8 #include "msctfime.h" 9 10 WINE_DEFAULT_DEBUG_CHANNEL(msctfime); 11 12 /// @implemented 13 CicProfile::CicProfile() 14 { 15 m_dwFlags &= 0xFFFFFFF0; 16 m_cRefs = 1; 17 m_pIPProfiles = NULL; 18 m_pActiveLanguageProfileNotifySink = NULL; 19 m_LangID1 = 0; 20 m_nCodePage = CP_ACP; 21 m_LangID2 = 0; 22 m_dwUnknown1 = 0; 23 } 24 25 /// @implemented 26 CicProfile::~CicProfile() 27 { 28 if (m_pIPProfiles) 29 { 30 if (m_LangID1) 31 m_pIPProfiles->ChangeCurrentLanguage(m_LangID1); 32 33 m_pIPProfiles->Release(); 34 m_pIPProfiles = NULL; 35 } 36 37 if (m_pActiveLanguageProfileNotifySink) 38 { 39 m_pActiveLanguageProfileNotifySink->_Unadvise(); 40 m_pActiveLanguageProfileNotifySink->Release(); 41 m_pActiveLanguageProfileNotifySink = NULL; 42 } 43 } 44 45 /// @implemented 46 STDMETHODIMP CicProfile::QueryInterface(REFIID riid, LPVOID* ppvObj) 47 { 48 *ppvObj = NULL; 49 return E_NOINTERFACE; 50 } 51 52 /// @implemented 53 STDMETHODIMP_(ULONG) CicProfile::AddRef() 54 { 55 return ::InterlockedIncrement(&m_cRefs); 56 } 57 58 /// @implemented 59 STDMETHODIMP_(ULONG) CicProfile::Release() 60 { 61 if (::InterlockedDecrement(&m_cRefs) == 0) 62 { 63 delete this; 64 return 0; 65 } 66 return m_cRefs; 67 } 68 69 /// @implemented 70 INT CALLBACK 71 CicProfile::ActiveLanguageProfileNotifySinkCallback( 72 REFGUID rguid1, 73 REFGUID rguid2, 74 BOOL fActivated, 75 LPVOID pUserData) 76 { 77 CicProfile *pThis = (CicProfile *)pUserData; 78 pThis->m_dwFlags &= ~0xE; 79 return 0; 80 } 81 82 /// @implemented 83 HRESULT CicProfile::GetCodePageA(_Out_ UINT *puCodePage) 84 { 85 if (!puCodePage) 86 return E_INVALIDARG; 87 88 if (m_dwFlags & 2) 89 { 90 *puCodePage = m_nCodePage; 91 return S_OK; 92 } 93 94 *puCodePage = 0; 95 96 LANGID LangID; 97 HRESULT hr = GetLangId(&LangID); 98 if (FAILED(hr)) 99 return E_FAIL; 100 101 WCHAR szBuff[12]; 102 INT cch = ::GetLocaleInfoW(LangID, LOCALE_IDEFAULTANSICODEPAGE, szBuff, _countof(szBuff)); 103 if (cch) 104 { 105 szBuff[cch] = 0; 106 m_nCodePage = *puCodePage = wcstoul(szBuff, NULL, 10); 107 m_dwFlags |= 2; 108 } 109 110 return S_OK; 111 } 112 113 /// @implemented 114 HRESULT CicProfile::GetLangId(_Out_ LANGID *pLangID) 115 { 116 *pLangID = 0; 117 118 if (!m_pIPProfiles) 119 return E_FAIL; 120 121 if (m_dwFlags & 4) 122 { 123 *pLangID = m_LangID2; 124 return S_OK; 125 } 126 127 HRESULT hr = m_pIPProfiles->GetCurrentLanguage(pLangID); 128 if (SUCCEEDED(hr)) 129 { 130 m_dwFlags |= 4; 131 m_LangID2 = *pLangID; 132 } 133 134 return hr; 135 } 136 137 /// @implemented 138 HRESULT 139 CicProfile::InitProfileInstance(_Inout_ TLS *pTLS) 140 { 141 HRESULT hr = TF_CreateInputProcessorProfiles(&m_pIPProfiles); 142 if (FAILED(hr)) 143 return hr; 144 145 if (!m_pActiveLanguageProfileNotifySink) 146 { 147 CActiveLanguageProfileNotifySink *pSink = 148 new(cicNoThrow) CActiveLanguageProfileNotifySink( 149 CicProfile::ActiveLanguageProfileNotifySinkCallback, this); 150 if (!pSink) 151 { 152 m_pIPProfiles->Release(); 153 m_pIPProfiles = NULL; 154 return E_FAIL; 155 } 156 m_pActiveLanguageProfileNotifySink = pSink; 157 } 158 159 if (pTLS->m_pThreadMgr) 160 m_pActiveLanguageProfileNotifySink->_Advise(pTLS->m_pThreadMgr); 161 162 return hr; 163 } 164 165 /// @unimplemented 166 HRESULT 167 CicProfile::GetActiveLanguageProfile( 168 _In_ HKL hKL, 169 _In_ REFGUID rguid, 170 _Out_ TF_LANGUAGEPROFILE *pProfile) 171 { 172 return E_NOTIMPL; 173 } 174 175 /// The return value of CicProfile::IsIME is brain-damaged. 176 /// @unimplemented 177 BOOL CicProfile::IsIME(HKL hKL) 178 { 179 return TRUE; 180 } 181