ReactOS 0.4.16-dev-1279-gc894716
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#define ROUNDUP4(n) (((n) + 3) & ~3) /* DWORD alignment */
13
16 UINT uCodePage)
17{
18 BOOL bUsedDefault;
19 DWORD dwSize, dwIndex, cbGot, cbLeft;
20 const BYTE *pbWide;
21 LPBYTE pbAnsi;
22 LPDWORD pibOffsets;
23
24 /* calculate total ansi size */
25 if (pWideCL->dwCount > 0)
26 {
27 dwSize = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
28 for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
29 {
30 pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
31 cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1, NULL, 0,
32 NULL, &bUsedDefault);
33 dwSize += cbGot;
34 }
35 }
36 else
37 {
38 dwSize = sizeof(CANDIDATELIST);
39 }
40
42 if (dwBufLen == 0)
43 return dwSize;
44 if (dwBufLen < dwSize)
45 return 0;
46
47 /* store to ansi */
48 pAnsiCL->dwSize = dwBufLen;
49 pAnsiCL->dwStyle = pWideCL->dwStyle;
50 pAnsiCL->dwCount = pWideCL->dwCount;
51 pAnsiCL->dwSelection = pWideCL->dwSelection;
52 pAnsiCL->dwPageStart = pWideCL->dwPageStart;
53 pAnsiCL->dwPageSize = pWideCL->dwPageSize;
54
55 pibOffsets = pAnsiCL->dwOffset;
56 if (pWideCL->dwCount > 0)
57 {
58 pibOffsets[0] = sizeof(CANDIDATELIST) + ((pWideCL->dwCount - 1) * sizeof(DWORD));
59 cbLeft = dwBufLen - pibOffsets[0];
60
61 for (dwIndex = 0; dwIndex < pWideCL->dwCount; ++dwIndex)
62 {
63 pbWide = (const BYTE *)pWideCL + pWideCL->dwOffset[dwIndex];
64 pbAnsi = (LPBYTE)pAnsiCL + pibOffsets[dwIndex];
65
66 /* convert to ansi */
67 cbGot = WideCharToMultiByte(uCodePage, 0, (LPCWSTR)pbWide, -1,
68 (LPSTR)pbAnsi, cbLeft, NULL, &bUsedDefault);
69 cbLeft -= cbGot;
70
71 if (dwIndex < pWideCL->dwCount - 1)
72 pibOffsets[dwIndex + 1] = pibOffsets[dwIndex] + cbGot;
73 }
74 }
75 else
76 {
77 pibOffsets[0] = sizeof(CANDIDATELIST);
78 }
79
80 return dwBufLen;
81}
82
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
151static DWORD
153 _In_ HIMC hIMC,
154 _In_ DWORD dwIndex,
157 _In_ BOOL bAnsi)
158{
159 DWORD dwSize, ret = 0;
160 UINT uCodePage;
161 LPINPUTCONTEXT pIC;
162 PCLIENTIMC pClientImc;
163 LPCANDIDATEINFO pCI;
164 LPCANDIDATELIST pCL;
165
166 pClientImc = ImmLockClientImc(hIMC);
167 if (IS_NULL_UNEXPECTEDLY(pClientImc))
168 return 0;
169
170 uCodePage = pClientImc->uCodePage;
171 pIC = ImmLockIMC(hIMC);
172 if (IS_NULL_UNEXPECTEDLY(pIC))
173 {
174 ImmUnlockClientImc(pClientImc);
175 return 0;
176 }
177
178 pCI = ImmLockIMCC(pIC->hCandInfo);
179 if (IS_NULL_UNEXPECTEDLY(pCI))
180 {
181 ImmUnlockIMC(hIMC);
182 ImmUnlockClientImc(pClientImc);
183 return 0;
184 }
185
186 if (pCI->dwSize < sizeof(CANDIDATEINFO))
187 {
188 ERR("Too small\n");
189 goto Quit;
190 }
191
192 if (pCI->dwCount <= dwIndex)
193 {
194 ERR("Out of boundary\n");
195 goto Quit;
196 }
197
198 /* get required size */
199 pCL = (LPCANDIDATELIST)((LPBYTE)pCI + pCI->dwOffset[dwIndex]);
200 if (bAnsi)
201 {
202 if (pClientImc->dwFlags & CLIENTIMC_WIDE)
203 dwSize = CandidateListAnsiToWide(pCL, NULL, 0, uCodePage);
204 else
205 dwSize = pCL->dwSize;
206 }
207 else
208 {
209 if (pClientImc->dwFlags & CLIENTIMC_WIDE)
210 dwSize = pCL->dwSize;
211 else
212 dwSize = CandidateListWideToAnsi(pCL, NULL, 0, uCodePage);
213 }
214
215 if (dwBufLen != 0 && dwSize != 0)
216 {
217 if (lpCandList == NULL || dwBufLen < dwSize)
218 goto Quit;
219
220 /* store */
221 if (bAnsi)
222 {
223 if (pClientImc->dwFlags & CLIENTIMC_WIDE)
224 CandidateListAnsiToWide(pCL, lpCandList, dwSize, uCodePage);
225 else
226 RtlCopyMemory(lpCandList, pCL, dwSize);
227 }
228 else
229 {
230 if (pClientImc->dwFlags & CLIENTIMC_WIDE)
231 RtlCopyMemory(lpCandList, pCL, dwSize);
232 else
233 CandidateListWideToAnsi(pCL, lpCandList, dwSize, uCodePage);
234 }
235 }
236
237 ret = dwSize;
238
239Quit:
241 ImmUnlockIMC(hIMC);
242 ImmUnlockClientImc(pClientImc);
243 TRACE("ret: 0x%X\n", ret);
244 return ret;
245}
246
247static DWORD
249 _In_ HIMC hIMC,
250 _Out_ LPDWORD lpdwListCount,
251 _In_ BOOL bAnsi)
252{
253 DWORD ret = 0, cbGot, dwIndex;
254 PCLIENTIMC pClientImc;
255 LPINPUTCONTEXT pIC;
256 UINT uCodePage;
257 const CANDIDATEINFO *pCI;
258 const BYTE *pb;
259 const CANDIDATELIST *pCL;
260 const DWORD *pdwOffsets;
261
262 if (IS_NULL_UNEXPECTEDLY(lpdwListCount))
263 return 0;
264
265 *lpdwListCount = 0;
266
267 pClientImc = ImmLockClientImc(hIMC);
268 if (IS_NULL_UNEXPECTEDLY(pClientImc))
269 return 0;
270
271 pIC = ImmLockIMC(hIMC);
272 if (IS_NULL_UNEXPECTEDLY(pIC))
273 {
274 ImmUnlockClientImc(pClientImc);
275 return 0;
276 }
277
278 uCodePage = pClientImc->uCodePage;
279
280 pCI = ImmLockIMCC(pIC->hCandInfo);
281 if (IS_NULL_UNEXPECTEDLY(pCI))
282 {
283 ImmUnlockIMC(hIMC);
284 ImmUnlockClientImc(pClientImc);
285 return 0;
286 }
287
288 if (pCI->dwSize < sizeof(CANDIDATEINFO))
289 {
290 ERR("Too small\n");
291 goto Quit;
292 }
293
294 *lpdwListCount = pCI->dwCount; /* the number of candidate lists */
295
296 /* calculate total size of candidate lists */
297 if (bAnsi)
298 {
299 if (pClientImc->dwFlags & CLIENTIMC_WIDE)
300 {
301 ret = ROUNDUP4(pCI->dwPrivateSize);
302 pdwOffsets = pCI->dwOffset;
303 for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
304 {
305 pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
306 pCL = (const CANDIDATELIST *)pb;
307 cbGot = CandidateListWideToAnsi(pCL, NULL, 0, uCodePage);
308 ret += cbGot;
309 }
310 }
311 else
312 {
313 ret = pCI->dwSize;
314 }
315 }
316 else
317 {
318 if (pClientImc->dwFlags & CLIENTIMC_WIDE)
319 {
320 ret = pCI->dwSize;
321 }
322 else
323 {
324 ret = ROUNDUP4(pCI->dwPrivateSize);
325 pdwOffsets = pCI->dwOffset;
326 for (dwIndex = 0; dwIndex < pCI->dwCount; ++dwIndex)
327 {
328 pb = (const BYTE *)pCI + pdwOffsets[dwIndex];
329 pCL = (const CANDIDATELIST *)pb;
330 cbGot = CandidateListAnsiToWide(pCL, NULL, 0, uCodePage);
331 ret += cbGot;
332 }
333 }
334 }
335
336Quit:
338 ImmUnlockIMC(hIMC);
339 ImmUnlockClientImc(pClientImc);
340 TRACE("ret: 0x%X\n", ret);
341 return ret;
342}
343
344/***********************************************************************
345 * ImmGetCandidateListA (IMM32.@)
346 */
349 _In_ HIMC hIMC,
350 _In_ DWORD dwIndex,
353{
354 return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, TRUE);
355}
356
357/***********************************************************************
358 * ImmGetCandidateListCountA (IMM32.@)
359 */
362 _In_ HIMC hIMC,
363 _Out_ LPDWORD lpdwListCount)
364{
365 return ImmGetCandidateListCountAW(hIMC, lpdwListCount, TRUE);
366}
367
368/***********************************************************************
369 * ImmGetCandidateListCountW (IMM32.@)
370 */
373 _In_ HIMC hIMC,
374 _Out_ LPDWORD lpdwListCount)
375{
376 return ImmGetCandidateListCountAW(hIMC, lpdwListCount, FALSE);
377}
378
379/***********************************************************************
380 * ImmGetCandidateListW (IMM32.@)
381 */
384 _In_ HIMC hIMC,
385 _In_ DWORD dwIndex,
388{
389 return ImmGetCandidateListAW(hIMC, dwIndex, lpCandList, dwBufLen, FALSE);
390}
391
392/***********************************************************************
393 * ImmGetCandidateWindow (IMM32.@)
394 */
397 _In_ HIMC hIMC,
398 _In_ DWORD dwIndex,
399 _Out_ LPCANDIDATEFORM lpCandidate)
400{
401 BOOL ret = FALSE;
402 LPINPUTCONTEXT pIC;
403 LPCANDIDATEFORM pCF;
404
405 TRACE("(%p, %lu, %p)\n", hIMC, dwIndex, lpCandidate);
406
407 if (dwIndex >= MAX_CANDIDATEFORM) /* Windows didn't check but we do for security reason */
408 {
409 ERR("Out of boundary\n");
410 return FALSE;
411 }
412
413 pIC = ImmLockIMC(hIMC);
414 if (IS_NULL_UNEXPECTEDLY(pIC))
415 return FALSE;
416
417 pCF = &pIC->cfCandForm[dwIndex];
418 if (pCF->dwIndex != IMM_INVALID_CANDFORM)
419 {
420 *lpCandidate = *pCF;
421 ret = TRUE;
422 }
423
424 ImmUnlockIMC(hIMC);
425 TRACE("ret: %d\n", ret);
426 return ret;
427}
428
429/***********************************************************************
430 * ImmSetCandidateWindow (IMM32.@)
431 */
434 _In_ HIMC hIMC,
435 _In_ LPCANDIDATEFORM lpCandidate)
436{
437 HWND hWnd;
438 LPINPUTCONTEXT pIC;
439
440 TRACE("(%p, %p)\n", hIMC, lpCandidate);
441
442 if (lpCandidate->dwIndex >= MAX_CANDIDATEFORM)
443 {
444 ERR("Out of boundary\n");
445 return FALSE;
446 }
447
448 if (IS_CROSS_THREAD_HIMC(hIMC))
449 return FALSE;
450
451 pIC = ImmLockIMC(hIMC);
452 if (IS_NULL_UNEXPECTEDLY(pIC))
453 return FALSE;
454
455 hWnd = pIC->hWnd;
456 pIC->cfCandForm[lpCandidate->dwIndex] = *lpCandidate;
457
458 ImmUnlockIMC(hIMC);
459
461 IMN_SETCANDIDATEPOS, (1 << (BYTE)lpCandidate->dwIndex));
462 return TRUE;
463}
HWND hWnd
Definition: settings.c:17
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
#define ERR(fmt,...)
Definition: precomp.h:57
DWORD CandidateListAnsiToWide(const CANDIDATELIST *pAnsiCL, LPCANDIDATELIST pWideCL, DWORD dwBufLen, UINT uCodePage)
Definition: candidate.c:84
DWORD WINAPI ImmGetCandidateListW(_In_ HIMC hIMC, _In_ DWORD dwIndex, _Out_writes_bytes_opt_(dwBufLen) LPCANDIDATELIST lpCandList, _In_ DWORD dwBufLen)
Definition: candidate.c:383
DWORD CandidateListWideToAnsi(const CANDIDATELIST *pWideCL, LPCANDIDATELIST pAnsiCL, DWORD dwBufLen, UINT uCodePage)
Definition: candidate.c:15
#define ROUNDUP4(n)
Definition: candidate.c:12
BOOL WINAPI ImmSetCandidateWindow(_In_ HIMC hIMC, _In_ LPCANDIDATEFORM lpCandidate)
Definition: candidate.c:433
BOOL WINAPI ImmGetCandidateWindow(_In_ HIMC hIMC, _In_ DWORD dwIndex, _Out_ LPCANDIDATEFORM lpCandidate)
Definition: candidate.c:396
DWORD WINAPI ImmGetCandidateListCountA(_In_ HIMC hIMC, _Out_ LPDWORD lpdwListCount)
Definition: candidate.c:361
DWORD WINAPI ImmGetCandidateListCountW(_In_ HIMC hIMC, _Out_ LPDWORD lpdwListCount)
Definition: candidate.c:372
DWORD WINAPI ImmGetCandidateListA(_In_ HIMC hIMC, _In_ DWORD dwIndex, _Out_writes_bytes_opt_(dwBufLen) LPCANDIDATELIST lpCandList, _In_ DWORD dwBufLen)
Definition: candidate.c:348
static DWORD ImmGetCandidateListCountAW(_In_ HIMC hIMC, _Out_ LPDWORD lpdwListCount, _In_ BOOL bAnsi)
Definition: candidate.c:248
static DWORD ImmGetCandidateListAW(_In_ HIMC hIMC, _In_ DWORD dwIndex, _Out_writes_bytes_opt_(dwBufLen) LPCANDIDATELIST lpCandList, _In_ DWORD dwBufLen, _In_ BOOL bAnsi)
Definition: candidate.c:152
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 WideCharToMultiByte
Definition: compat.h:111
#define MultiByteToWideChar
Definition: compat.h:110
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
PCLIENTIMC WINAPI ImmLockClientImc(_In_ HIMC hImc)
Definition: imm.c:954
VOID WINAPI ImmUnlockClientImc(_Inout_ PCLIENTIMC pClientImc)
Definition: imm.c:1001
#define CLIENTIMC_WIDE
Definition: imm32_undoc.h:169
#define IMC_SETCANDIDATEPOS
Definition: imm.h:149
struct tagCANDIDATELIST * LPCANDIDATELIST
#define IMN_SETCANDIDATEPOS
Definition: imm.h:380
BOOL WINAPI ImmUnlockIMCC(_In_ HIMCC imcc)
Definition: utils.c:615
LPINPUTCONTEXT WINAPI ImmLockIMC(_In_ HIMC hIMC)
Definition: imm.c:1079
#define NI_CONTEXTUPDATED
Definition: immdev.h:375
BOOL WINAPI ImmUnlockIMC(_In_ HIMC hIMC)
Definition: imm.c:1089
LPVOID WINAPI ImmLockIMCC(_In_ HIMCC imcc)
Definition: utils.c:604
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
unsigned int UINT
Definition: ndis.h:50
#define _Out_writes_bytes_opt_(s)
Definition: no_sal2.h:228
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#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:118
HIMCC hCandInfo
Definition: immdev.h:120
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
#define IS_CROSS_THREAD_HIMC(hIMC)
Definition: precomp.h:72
#define IMM_INVALID_CANDFORM
Definition: precomp.h:76
BOOL Imm32MakeIMENotify(_In_ HIMC hIMC, _In_ HWND hwnd, _In_ DWORD dwAction, _In_ DWORD dwIndex, _Inout_opt_ DWORD_PTR dwValue, _In_ DWORD dwCommand, _Inout_opt_ DWORD_PTR dwData)
Definition: utils.c:287
#define IS_NULL_UNEXPECTEDLY(p)
Definition: precomp.h:66
#define MAX_CANDIDATEFORM
Definition: precomp.h:78
_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:299
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