ReactOS 0.4.15-dev-7906-g1b85a5f
candidate.c
Go to the documentation of this file.
1/*
2 * PROJECT: ReactOS IMM32
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Implementing IMM32 candidate lists
5 * COPYRIGHT: Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
6 */
7
8#include "precomp.h"
9
11
12// Win: InternalGetCandidateListWtoA
15 UINT uCodePage)
16{
17 BOOL bUsedDefault;
18 DWORD dwSize, dwIndex, cbGot, cbLeft;
19 const BYTE *pbWide;
20 LPBYTE pbAnsi;
21 LPDWORD pibOffsets;
22
23 /* calculate total ansi size */
24 if (pWideCL->dwCount > 0)
25 {
26 dwSize = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
27 for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
28 {
29 pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
30 cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1, NULL, 0,
31 NULL, &bUsedDefault);
32 dwSize += cbGot;
33 }
34 }
35 else
36 {
37 dwSize = sizeof(CANDIDATELIST);
38 }
39
41 if (dwBufLen == 0)
42 return dwSize;
43 if (dwBufLen < dwSize)
44 return 0;
45
46 /* store to ansi */
47 pAnsiCL->dwSize = dwBufLen;
48 pAnsiCL->dwStyle = pWideCL->dwStyle;
49 pAnsiCL->dwCount = pWideCL->dwCount;
50 pAnsiCL->dwSelection = pWideCL->dwSelection;
51 pAnsiCL->dwPageStart = pWideCL->dwPageStart;
52 pAnsiCL->dwPageSize = pWideCL->dwPageSize;
53
54 pibOffsets = pAnsiCL->dwOffset;
55 if (pWideCL->dwCount > 0)
56 {
57 pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
58 cbLeft = dwBufLen - pibOffsets[0];
59
60 for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
61 {
62 pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
63 pbAnsi = (LPBYTE)pAnsiCL + pibOffsets[dwIndex];
64
65 /* convert to ansi */
66 cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1,
67 (LPSTR)pbAnsi, cbLeft, NULL, &bUsedDefault);
68 cbLeft -= cbGot;
69
70 if (dwIndex < pWideCL->dwCount - 1)
71 pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
72 }
73 }
74 else
75 {
76 pibOffsets[0] = sizeof(CANDIDATELIST);
77 }
78
79 return dwBufLen;
80}
81
82// Win: InternalGetCandidateListAtoW
85 UINT uCodePage)
86{
87 DWORD dwSize, dwIndex, cchGot, cbGot, cbLeft;
88 const BYTE *pbAnsi;
89 LPBYTE pbWide;
90 LPDWORD pibOffsets;
91
92 /* calculate total wide size */
93 if (pAnsiCL->dwCount > 0)
94 {
95 dwSize = sizeof(CANDIDATELIST) + ((pAnsiCL->dwCount - 1) * sizeof(DWORD));
96 for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
97 {
98 pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
99 cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, (LPCSTR)pbAnsi, -1, NULL, 0);
100 dwSize += cchGot * sizeof(WCHAR);
101 }
102 }
103 else
104 {
105 dwSize = sizeof(CANDIDATELIST);
106 }
107
109 if (dwBufLen == 0)
110 return dwSize;
111 if (dwBufLen < dwSize)
112 return 0;
113
114 /* store to wide */
115 pWideCL->dwSize = dwBufLen;
116 pWideCL->dwStyle = pAnsiCL->dwStyle;
117 pWideCL->dwCount = pAnsiCL->dwCount;
118 pWideCL->dwSelection = pAnsiCL->dwSelection;
119 pWideCL->dwPageStart = pAnsiCL->dwPageStart;
120 pWideCL->dwPageSize = pAnsiCL->dwPageSize;
121
122 pibOffsets = pWideCL->dwOffset;
123 if (pAnsiCL->dwCount > 0)
124 {
125 pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
126 cbLeft = dwBufLen - pibOffsets[0];
127
128 for (dwIndex = 0; dwIndex < pAnsiCL->dwCount; ++dwIndex)
129 {
130 pbAnsi = (const BYTE *)pAnsiCL + pAnsiCL->dwOffset[dwIndex];
131 pbWide = (LPBYTE)pWideCL + pibOffsets[dwIndex];
132
133 /* convert to wide */
134 cchGot = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, (LPCSTR)pbAnsi, -1,
135 (LPWSTR)pbWide, cbLeft / sizeof(WCHAR));
136 cbGot = cchGot * sizeof(WCHAR);
137 cbLeft -= cbGot;
138
139 if (dwIndex + 1 < pAnsiCL->dwCount)
140 pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
141 }
142 }
143 else
144 {
145 pibOffsets[0] = sizeof(CANDIDATELIST);
146 }
147
148 return dwBufLen;
149}
150
151// Win: ImmGetCandidateListWorker
152static DWORD APIENTRY
154 BOOL bAnsi)
155{
156 DWORD dwSize, ret = 0;
157 UINT uCodePage;
158 LPINPUTCONTEXT pIC;
159 PCLIENTIMC pClientImc;
160 LPCANDIDATEINFO pCI;
161 LPCANDIDATELIST pCL;
162
163 pClientImc = ImmLockClientImc(hIMC);
164 if (IS_NULL_UNEXPECTEDLY(pClientImc))
165 return 0;
166
167 uCodePage = pClientImc->uCodePage;
168 pIC = ImmLockIMC(hIMC);
169 if (IS_NULL_UNEXPECTEDLY(pIC))
170 {
171 ImmUnlockClientImc(pClientImc);
172 return 0;
173 }
174
175 pCI = ImmLockIMCC(pIC->hCandInfo);
176 if (IS_NULL_UNEXPECTEDLY(pCI))
177 {
178 ImmUnlockIMC(hIMC);
179 ImmUnlockClientImc(pClientImc);
180 return 0;
181 }
182
183 if (pCI->dwSize < sizeof(CANDIDATEINFO))
184 {
185 ERR("Too small\n");
186 goto Quit;
187 }
188
189 if (pCI->dwCount <= dwIndex)
190 {
191 ERR("Out of boundary\n");
192 goto Quit;
193 }
194
195 /* get required size */
196 pCL = (LPCANDIDATELIST)((LPBYTE)pCI + pCI->dwOffset[dwIndex]);
197 if (bAnsi)
198 {
199 if (pClientImc->dwFlags & CLIENTIMC_WIDE)
200 dwSize = CandidateListAnsiToWide(pCL, NULL, 0, uCodePage);
201 else
202 dwSize = pCL->dwSize;
203 }
204 else
205 {
206 if (pClientImc->dwFlags & CLIENTIMC_WIDE)
207 dwSize = pCL->dwSize;
208 else
209 dwSize = CandidateListWideToAnsi(pCL, NULL, 0, uCodePage);
210 }
211
212 if (dwBufLen != 0 && dwSize != 0)
213 {
214 if (lpCandList == NULL || dwBufLen < dwSize)
215 goto Quit;
216
217 /* store */
218 if (bAnsi)
219 {
220 if (pClientImc->dwFlags & CLIENTIMC_WIDE)
221 CandidateListAnsiToWide(pCL, lpCandList, dwSize, uCodePage);
222 else
223 RtlCopyMemory(lpCandList, pCL, dwSize);
224 }
225 else
226 {
227 if (pClientImc->dwFlags & CLIENTIMC_WIDE)
228 RtlCopyMemory(lpCandList, pCL, dwSize);
229 else
230 CandidateListWideToAnsi(pCL, lpCandList, dwSize, uCodePage);
231 }
232 }
233
234 ret = dwSize;
235
236Quit:
238 ImmUnlockIMC(hIMC);
239 ImmUnlockClientImc(pClientImc);
240 TRACE("ret: 0x%X\n", ret);
241 return ret;
242}
243
244// Win: ImmGetCandidateListCountWorker
246ImmGetCandidateListCountAW(HIMC hIMC, LPDWORD lpdwListCount, BOOL bAnsi)
247{
248 DWORD ret = 0, cbGot, dwIndex;
249 PCLIENTIMC pClientImc;
250 LPINPUTCONTEXT pIC;
251 UINT uCodePage;
252 const CANDIDATEINFO *pCI;
253 const BYTE *pb;
254 const CANDIDATELIST *pCL;
255 const DWORD *pdwOffsets;
256
257 if (IS_NULL_UNEXPECTEDLY(lpdwListCount))
258 return 0;
259
260 *lpdwListCount = 0;
261
262 pClientImc = ImmLockClientImc(hIMC);
263 if (IS_NULL_UNEXPECTEDLY(pClientImc))
264 return 0;
265
266 pIC = ImmLockIMC(hIMC);
267 if (IS_NULL_UNEXPECTEDLY(pIC))
268 {
269 ImmUnlockClientImc(pClientImc);
270 return 0;
271 }
272
273 uCodePage = pClientImc->uCodePage;
274
275 pCI = ImmLockIMCC(pIC->hCandInfo);
276 if (IS_NULL_UNEXPECTEDLY(pCI))
277 {
278 ImmUnlockIMC(hIMC);
279 ImmUnlockClientImc(pClientImc);
280 return 0;
281 }
282
283 if (pCI->dwSize < sizeof(CANDIDATEINFO))
284 {
285 ERR("Too small\n");
286 goto Quit;
287 }
288
289 *lpdwListCount = pCI->dwCount; /* the number of candidate lists */
290
291 /* calculate total size of candidate lists */
292 if (bAnsi)
293 {
294 if (pClientImc->dwFlags & CLIENTIMC_WIDE)
295 {
296 ret = ROUNDUP4(pCI->dwPrivateSize);
297 pdwOffsets = pCI->dwOffset;
298 for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
299 {
300 pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
301 pCL = (const CANDIDATELIST *)pb;
302 cbGot = CandidateListWideToAnsi(pCL, NULL, 0, uCodePage);
303 ret += cbGot;
304 }
305 }
306 else
307 {
308 ret = pCI->dwSize;
309 }
310 }
311 else
312 {
313 if (pClientImc->dwFlags & CLIENTIMC_WIDE)
314 {
315 ret = pCI->dwSize;
316 }
317 else
318 {
319 ret = ROUNDUP4(pCI->dwPrivateSize);
320 pdwOffsets = pCI->dwOffset;
321 for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
322 {
323 pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
324 pCL = (const CANDIDATELIST *)pb;
325 cbGot = CandidateListAnsiToWide(pCL, NULL, 0, uCodePage);
326 ret += cbGot;
327 }
328 }
329 }
330
331Quit:
333 ImmUnlockIMC(hIMC);
334 ImmUnlockClientImc(pClientImc);
335 TRACE("ret: 0x%X\n", ret);
336 return ret;
337}
338
339/***********************************************************************
340 * ImmGetCandidateListA (IMM32.@)
341 */
344{
345 return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, TRUE);
346}
347
348/***********************************************************************
349 * ImmGetCandidateListCountA (IMM32.@)
350 */
352{
353 return ImmGetCandidateListCountAW(hIMC, lpdwListCount, TRUE);
354}
355
356/***********************************************************************
357 * ImmGetCandidateListCountW (IMM32.@)
358 */
360{
361 return ImmGetCandidateListCountAW(hIMC, lpdwListCount, FALSE);
362}
363
364/***********************************************************************
365 * ImmGetCandidateListW (IMM32.@)
366 */
369{
370 return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, FALSE);
371}
372
373/***********************************************************************
374 * ImmGetCandidateWindow (IMM32.@)
375 */
378{
379 BOOL ret = FALSE;
380 LPINPUTCONTEXT pIC;
381 LPCANDIDATEFORM pCF;
382
383 TRACE("(%p, %lu, %p)\n", hIMC, dwIndex, lpCandidate);
384
385 if (dwIndex >= MAX_CANDIDATEFORM) /* Windows didn't check but we do for security reason */
386 {
387 ERR("Out of boundary\n");
388 return FALSE;
389 }
390
391 pIC = ImmLockIMC(hIMC);
392 if (IS_NULL_UNEXPECTEDLY(pIC))
393 return FALSE;
394
395 pCF = &pIC->cfCandForm[dwIndex];
396 if (pCF->dwIndex != IMM_INVALID_CANDFORM)
397 {
398 *lpCandidate = *pCF;
399 ret = TRUE;
400 }
401
402 ImmUnlockIMC(hIMC);
403 TRACE("ret: %d\n", ret);
404 return ret;
405}
406
407/***********************************************************************
408 * ImmSetCandidateWindow (IMM32.@)
409 */
411{
412 HWND hWnd;
413 LPINPUTCONTEXT pIC;
414
415 TRACE("(%p, %p)\n", hIMC, lpCandidate);
416
417 if (lpCandidate->dwIndex >= MAX_CANDIDATEFORM)
418 {
419 ERR("Out of boundary\n");
420 return FALSE;
421 }
422
423 if (IS_CROSS_THREAD_HIMC(hIMC))
424 return FALSE;
425
426 pIC = ImmLockIMC(hIMC);
427 if (IS_NULL_UNEXPECTEDLY(pIC))
428 return FALSE;
429
430 hWnd = pIC->hWnd;
431 pIC->cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
432
433 ImmUnlockIMC(hIMC);
434
436 IMN_SETCANDIDATEPOS, (1 << (BYTE)lpCandidate->dwIndex));
437 return TRUE;
438}
HWND hWnd
Definition: settings.c:17
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ERR(fmt,...)
Definition: debug.h:110
DWORD WINAPI ImmGetCandidateListCountA(HIMC hIMC, LPDWORD lpdwListCount)
Definition: candidate.c:351
DWORD APIENTRY CandidateListAnsiToWide(const CANDIDATELIST *pAnsiCL, LPCANDIDATELIST pWideCL, DWORD dwBufLen, UINT uCodePage)
Definition: candidate.c:84
DWORD WINAPI ImmGetCandidateListW(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen)
Definition: candidate.c:368
DWORD WINAPI ImmGetCandidateListCountW(HIMC hIMC, LPDWORD lpdwListCount)
Definition: candidate.c:359
BOOL WINAPI ImmSetCandidateWindow(HIMC hIMC, LPCANDIDATEFORM lpCandidate)
Definition: candidate.c:410
BOOL WINAPI ImmGetCandidateWindow(HIMC hIMC, DWORD dwIndex, LPCANDIDATEFORM lpCandidate)
Definition: candidate.c:377
static DWORD APIENTRY ImmGetCandidateListAW(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen, BOOL bAnsi)
Definition: candidate.c:153
DWORD APIENTRY ImmGetCandidateListCountAW(HIMC hIMC, LPDWORD lpdwListCount, BOOL bAnsi)
Definition: candidate.c:246
DWORD WINAPI ImmGetCandidateListA(HIMC hIMC, DWORD dwIndex, LPCANDIDATELIST lpCandList, DWORD dwBufLen)
Definition: candidate.c:343
DWORD APIENTRY CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, DWORD dwBufLen, UINT uCodePage)
Definition: candidate.c:14
DWORD HIMC
Definition: dimm.idl:75
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define APIENTRY
Definition: api.h:79
#define WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
BOOL WINAPI ImmUnlockIMC(HIMC hIMC)
Definition: imm.c:1066
VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc)
Definition: imm.c:983
PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc)
Definition: imm.c:937
LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC)
Definition: imm.c:1057
BOOL APIENTRY Imm32MakeIMENotify(HIMC hIMC, HWND hwnd, DWORD dwAction, DWORD_PTR dwIndex, DWORD_PTR dwValue, DWORD_PTR dwCommand, DWORD_PTR dwData)
Definition: utils.c:428
#define ROUNDUP4(n)
Definition: precomp.h:62
#define IS_CROSS_THREAD_HIMC(hIMC)
Definition: precomp.h:148
#define IMM_INVALID_CANDFORM
Definition: precomp.h:51
#define IS_NULL_UNEXPECTEDLY(p)
Definition: precomp.h:125
#define MAX_CANDIDATEFORM
Definition: precomp.h:53
BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
Definition: utils.c:1208
LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
Definition: utils.c:1198
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
#define CLIENTIMC_WIDE
Definition: imm32_undoc.h:138
#define IMC_SETCANDIDATEPOS
Definition: imm.h:149
struct tagCANDIDATELIST * LPCANDIDATELIST
#define IMN_SETCANDIDATEPOS
Definition: imm.h:380
#define NI_CONTEXTUPDATED
Definition: immdev.h:397
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
unsigned int UINT
Definition: ndis.h:50
#define DWORD
Definition: nt_native.h:44
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwSelection
Definition: dimm.idl:95
DWORD dwPageSize
Definition: dimm.idl:97
DWORD dwCount
Definition: dimm.idl:94
DWORD dwStyle
Definition: dimm.idl:93
DWORD dwPageStart
Definition: dimm.idl:96
DWORD dwOffset[1]
Definition: dimm.idl:98
CANDIDATEFORM cfCandForm[4]
Definition: immdev.h:140
HIMCC hCandInfo
Definition: immdev.h:142
DWORD dwIndex
Definition: imm.h:50
DWORD dwSize
Definition: immdev.h:31
DWORD dwPrivateSize
Definition: immdev.h:34
DWORD dwOffset[32]
Definition: immdev.h:33
DWORD dwCount
Definition: immdev.h:32
DWORD dwPageSize
Definition: imm.h:62
DWORD dwCount
Definition: imm.h:59
DWORD dwStyle
Definition: imm.h:58
DWORD dwPageStart
Definition: imm.h:61
DWORD dwOffset[ANYSIZE_ARRAY]
Definition: imm.h:63
DWORD dwSelection
Definition: imm.h:60
DWORD dwSize
Definition: imm.h:57
unsigned char * LPBYTE
Definition: typedefs.h:53
uint32_t * LPDWORD
Definition: typedefs.h:59
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
int ret
_In_ HCRYPTHASH _In_ BOOL _In_ DWORD _Inout_ DWORD _In_ DWORD dwBufLen
Definition: wincrypt.h:4246
#define WINAPI
Definition: msvc.h:6
#define MB_PRECOMPOSED
Definition: winnls.h:281
const char * LPCSTR
Definition: xmlstorage.h:183
char * LPSTR
Definition: xmlstorage.h:182
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185
unsigned char BYTE
Definition: xxhash.c:193