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
CicProfile()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
~CicProfile()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
QueryInterface(REFIID riid,LPVOID * ppvObj)46 STDMETHODIMP CicProfile::QueryInterface(REFIID riid, LPVOID* ppvObj)
47 {
48 *ppvObj = NULL;
49 return E_NOINTERFACE;
50 }
51
52 /// @implemented
STDMETHODIMP_(ULONG)53 STDMETHODIMP_(ULONG) CicProfile::AddRef()
54 {
55 return ::InterlockedIncrement(&m_cRefs);
56 }
57
58 /// @implemented
STDMETHODIMP_(ULONG)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
ActiveLanguageProfileNotifySinkCallback(REFGUID rguid1,REFGUID rguid2,BOOL fActivated,LPVOID pUserData)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
GetCodePageA(_Out_ UINT * puCodePage)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
GetLangId(_Out_ LANGID * pLangID)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
InitProfileInstance(_Inout_ TLS * pTLS)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
GetActiveLanguageProfile(_In_ HKL hKL,_In_ REFGUID rguid,_Out_ TF_LANGUAGEPROFILE * pProfile)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
IsIME(HKL hKL)177 BOOL CicProfile::IsIME(HKL hKL)
178 {
179 return TRUE;
180 }
181