1 /*
2 * PROJECT: ReactOS IMM32
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Implementing composition strings of IMM32
5 * COPYRIGHT: Copyright 1998 Patrik Stridvall
6 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
7 * Copyright 2017 James Tabor <james.tabor@reactos.org>
8 * Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
9 * Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
10 */
11
12 #include "precomp.h"
13
14 WINE_DEFAULT_DEBUG_CHANNEL(imm);
15
16 BOOL APIENTRY
Imm32OpenICAndCS(HIMC hIMC,LPINPUTCONTEXT * ppIC,LPCOMPOSITIONSTRING * ppCS)17 Imm32OpenICAndCS(HIMC hIMC, LPINPUTCONTEXT *ppIC, LPCOMPOSITIONSTRING *ppCS)
18 {
19 LPINPUTCONTEXT pIC;
20 LPCOMPOSITIONSTRING pCS;
21
22 *ppIC = NULL;
23 *ppCS = NULL;
24
25 pIC = ImmLockIMC(hIMC);
26 if (IS_NULL_UNEXPECTEDLY(pIC))
27 return FALSE;
28
29 pCS = ImmLockIMCC(pIC->hCompStr);
30 if (IS_NULL_UNEXPECTEDLY(pCS))
31 {
32 ImmUnlockIMC(hIMC);
33 return FALSE;
34 }
35
36 *ppIC = pIC;
37 *ppCS = pCS;
38 return TRUE;
39 }
40
41 static inline LONG APIENTRY
Imm32CompStrAnsiToWide(LPCSTR psz,DWORD cb,LPWSTR lpBuf,DWORD dwBufLen,UINT uCodePage)42 Imm32CompStrAnsiToWide(LPCSTR psz, DWORD cb, LPWSTR lpBuf, DWORD dwBufLen, UINT uCodePage)
43 {
44 DWORD ret = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, psz, cb / sizeof(CHAR),
45 lpBuf, dwBufLen / sizeof(WCHAR));
46 if (lpBuf && (ret + 1) * sizeof(WCHAR) <= dwBufLen)
47 lpBuf[ret] = 0;
48 return ret * sizeof(WCHAR);
49 }
50
51 static inline LONG APIENTRY
Imm32CompStrWideToAnsi(LPCWSTR psz,DWORD cb,LPSTR lpBuf,DWORD dwBufLen,UINT uCodePage)52 Imm32CompStrWideToAnsi(LPCWSTR psz, DWORD cb, LPSTR lpBuf, DWORD dwBufLen, UINT uCodePage)
53 {
54 DWORD ret = WideCharToMultiByte(uCodePage, 0, psz, cb / sizeof(WCHAR),
55 lpBuf, dwBufLen / sizeof(CHAR), NULL, NULL);
56 if (lpBuf && (ret + 1) * sizeof(CHAR) <= dwBufLen)
57 lpBuf[ret] = 0;
58 return ret * sizeof(CHAR);
59 }
60
61 static INT APIENTRY
Imm32CompAttrWideToAnsi(const BYTE * src,INT src_len,LPCWSTR text,INT str_len,LPBYTE dst,INT dst_len,UINT uCodePage)62 Imm32CompAttrWideToAnsi(const BYTE *src, INT src_len, LPCWSTR text,
63 INT str_len, LPBYTE dst, INT dst_len, UINT uCodePage)
64 {
65 INT rc;
66 INT i, j = 0, k = 0, len;
67
68 if (!src_len)
69 return 0;
70
71 str_len /= sizeof(WCHAR);
72 rc = WideCharToMultiByte(uCodePage, 0, text, str_len, NULL, 0, NULL, NULL);
73
74 if (dst_len)
75 {
76 if (dst_len > rc)
77 dst_len = rc;
78
79 for (i = 0; i < str_len; ++i, ++k)
80 {
81 len = WideCharToMultiByte(uCodePage, 0, &text[i], 1, NULL, 0, NULL, NULL);
82 for (; len > 0; --len)
83 {
84 dst[j++] = src[k];
85
86 if (dst_len <= j)
87 goto end;
88 }
89 }
90 end:
91 rc = j;
92 }
93
94 return rc * sizeof(BYTE);
95 }
96
97 static INT APIENTRY
Imm32CompAttrAnsiToWide(const BYTE * src,INT src_len,LPCSTR text,INT str_len,LPBYTE dst,INT dst_len,UINT uCodePage)98 Imm32CompAttrAnsiToWide(const BYTE *src, INT src_len, LPCSTR text,
99 INT str_len, LPBYTE dst, INT dst_len, UINT uCodePage)
100 {
101 INT rc;
102 INT i, j = 0;
103
104 if (!src_len)
105 return 0;
106
107 str_len /= sizeof(CHAR);
108 rc = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, text, str_len, NULL, 0);
109
110 if (dst_len)
111 {
112 if (dst_len > rc)
113 dst_len = rc;
114
115 for (i = 0; i < str_len; ++i)
116 {
117 if (IsDBCSLeadByteEx(uCodePage, text[i]) && text[i + 1])
118 continue;
119
120 dst[j++] = src[i];
121
122 if (dst_len <= j)
123 break;
124 }
125
126 rc = j;
127 }
128
129 return rc * sizeof(BYTE);
130 }
131
132 static INT APIENTRY
Imm32CompClauseAnsiToWide(const DWORD * source,INT slen,LPCSTR text,LPDWORD target,INT tlen,UINT uCodePage)133 Imm32CompClauseAnsiToWide(const DWORD *source, INT slen, LPCSTR text,
134 LPDWORD target, INT tlen, UINT uCodePage)
135 {
136 INT rc, i;
137
138 if (!slen)
139 return 0;
140
141 if (tlen)
142 {
143 if (tlen > slen)
144 tlen = slen;
145
146 tlen /= sizeof(DWORD);
147
148 for (i = 0; i < tlen; ++i)
149 {
150 target[i] = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, text, source[i], NULL, 0);
151 }
152
153 rc = sizeof(DWORD) * i;
154 }
155 else
156 {
157 rc = slen;
158 }
159
160 return rc;
161 }
162
163 static INT APIENTRY
Imm32CompClauseWideToAnsi(const DWORD * source,INT slen,LPCWSTR text,LPDWORD target,INT tlen,UINT uCodePage)164 Imm32CompClauseWideToAnsi(const DWORD *source, INT slen, LPCWSTR text,
165 LPDWORD target, INT tlen, UINT uCodePage)
166 {
167 INT rc, i;
168
169 if (!slen)
170 return 0;
171
172 if (tlen)
173 {
174 if (tlen > slen)
175 tlen = slen;
176
177 tlen /= sizeof(DWORD);
178
179 for (i = 0; i < tlen; ++i)
180 {
181 target[i] = WideCharToMultiByte(uCodePage, 0, text, source[i], NULL, 0, NULL, NULL);
182 }
183
184 rc = sizeof(DWORD) * i;
185 }
186 else
187 {
188 rc = slen;
189 }
190
191 return rc;
192 }
193
194 #define CS_StrA(pCS, Name) ((LPCSTR)(pCS) + (pCS)->dw##Name##Offset)
195 #define CS_StrW(pCS, Name) ((LPCWSTR)CS_StrA(pCS, Name))
196 #define CS_Attr(pCS, Name) ((const BYTE *)CS_StrA(pCS, Name))
197 #define CS_Clause(pCS, Name) ((const DWORD *)CS_StrA(pCS, Name))
198 #define CS_Size(pCS, Name) ((pCS)->dw##Name##Len)
199 #define CS_SizeA(pCS, Name) (CS_Size(pCS, Name) * sizeof(CHAR))
200 #define CS_SizeW(pCS, Name) (CS_Size(pCS, Name) * sizeof(WCHAR))
201
202 #define CS_DoStr(pCS, Name, AorW) do { \
203 if (dwBufLen == 0) { \
204 dwBufLen = CS_Size##AorW((pCS), Name); \
205 } else { \
206 if (dwBufLen > CS_Size##AorW((pCS), Name)) \
207 dwBufLen = CS_Size##AorW((pCS), Name); \
208 RtlCopyMemory(lpBuf, CS_Str##AorW((pCS), Name), dwBufLen); \
209 } \
210 } while (0)
211
212 #define CS_DoStrA(pCS, Name) CS_DoStr(pCS, Name, A)
213 #define CS_DoStrW(pCS, Name) CS_DoStr(pCS, Name, W)
214 #define CS_DoAttr CS_DoStrA
215 #define CS_DoClause CS_DoStrA
216
217 // Win: InternalGetCompositionStringA
218 LONG APIENTRY
Imm32GetCompStrA(HIMC hIMC,const COMPOSITIONSTRING * pCS,DWORD dwIndex,LPVOID lpBuf,DWORD dwBufLen,BOOL bAnsiClient,UINT uCodePage)219 Imm32GetCompStrA(HIMC hIMC, const COMPOSITIONSTRING *pCS, DWORD dwIndex,
220 LPVOID lpBuf, DWORD dwBufLen, BOOL bAnsiClient, UINT uCodePage)
221 {
222 if (bAnsiClient)
223 {
224 switch (dwIndex)
225 {
226 case GCS_COMPREADSTR:
227 CS_DoStrA(pCS, CompReadStr);
228 break;
229
230 case GCS_COMPREADATTR:
231 CS_DoAttr(pCS, CompReadAttr);
232 break;
233
234 case GCS_COMPREADCLAUSE:
235 CS_DoClause(pCS, CompReadClause);
236 break;
237
238 case GCS_COMPSTR:
239 CS_DoStrA(pCS, CompStr);
240 break;
241
242 case GCS_COMPATTR:
243 CS_DoAttr(pCS, CompAttr);
244 break;
245
246 case GCS_COMPCLAUSE:
247 CS_DoClause(pCS, CompClause);
248 break;
249
250 case GCS_CURSORPOS:
251 dwBufLen = pCS->dwCursorPos;
252 break;
253
254 case GCS_DELTASTART:
255 dwBufLen = pCS->dwDeltaStart;
256 break;
257
258 case GCS_RESULTREADSTR:
259 CS_DoStrA(pCS, ResultReadStr);
260 break;
261
262 case GCS_RESULTREADCLAUSE:
263 CS_DoClause(pCS, ResultReadClause);
264 break;
265
266 case GCS_RESULTSTR:
267 CS_DoStrA(pCS, ResultStr);
268 break;
269
270 case GCS_RESULTCLAUSE:
271 CS_DoClause(pCS, ResultClause);
272 break;
273
274 default:
275 FIXME("0x%X\n", dwIndex);
276 return IMM_ERROR_GENERAL;
277 }
278 }
279 else /* !bAnsiClient */
280 {
281 switch (dwIndex)
282 {
283 case GCS_COMPREADSTR:
284 dwBufLen = Imm32CompStrWideToAnsi(CS_StrW(pCS, CompReadStr),
285 CS_SizeW(pCS, CompReadStr),
286 lpBuf, dwBufLen, uCodePage);
287 break;
288
289 case GCS_COMPREADATTR:
290 dwBufLen = Imm32CompAttrWideToAnsi(CS_Attr(pCS, CompReadAttr),
291 CS_Size(pCS, CompReadAttr),
292 CS_StrW(pCS, CompReadStr),
293 CS_SizeW(pCS, CompReadStr),
294 lpBuf, dwBufLen, uCodePage);
295 break;
296
297 case GCS_COMPREADCLAUSE:
298 dwBufLen = Imm32CompClauseWideToAnsi(CS_Clause(pCS, CompReadClause),
299 CS_Size(pCS, CompReadClause),
300 CS_StrW(pCS, CompReadStr),
301 lpBuf, dwBufLen, uCodePage);
302 break;
303
304 case GCS_COMPSTR:
305 dwBufLen = Imm32CompStrWideToAnsi(CS_StrW(pCS, CompStr),
306 CS_SizeW(pCS, CompStr),
307 lpBuf, dwBufLen, uCodePage);
308 break;
309
310 case GCS_COMPATTR:
311 dwBufLen = Imm32CompAttrWideToAnsi(CS_Attr(pCS, CompAttr),
312 CS_Size(pCS, CompAttr),
313 CS_StrW(pCS, CompStr),
314 CS_SizeW(pCS, CompStr),
315 lpBuf, dwBufLen, uCodePage);
316 break;
317
318 case GCS_COMPCLAUSE:
319 dwBufLen = Imm32CompClauseWideToAnsi(CS_Clause(pCS, CompClause),
320 CS_Size(pCS, CompClause),
321 CS_StrW(pCS, CompStr),
322 lpBuf, dwBufLen, uCodePage);
323 break;
324
325 case GCS_CURSORPOS:
326 dwBufLen = IchAnsiFromWide(pCS->dwCursorPos, CS_StrW(pCS, CompStr), uCodePage);
327 break;
328
329 case GCS_DELTASTART:
330 dwBufLen = IchAnsiFromWide(pCS->dwDeltaStart, CS_StrW(pCS, CompStr), uCodePage);
331 break;
332
333 case GCS_RESULTREADSTR:
334 dwBufLen = Imm32CompStrWideToAnsi(CS_StrW(pCS, ResultReadStr),
335 CS_SizeW(pCS, ResultReadStr),
336 lpBuf, dwBufLen, uCodePage);
337 break;
338
339 case GCS_RESULTREADCLAUSE:
340 dwBufLen = Imm32CompClauseWideToAnsi(CS_Clause(pCS, ResultReadClause),
341 CS_Size(pCS, ResultReadClause),
342 CS_StrW(pCS, ResultReadStr),
343 lpBuf, dwBufLen, uCodePage);
344 break;
345
346 case GCS_RESULTSTR:
347 dwBufLen = Imm32CompStrWideToAnsi(CS_StrW(pCS, ResultStr),
348 CS_SizeW(pCS, ResultStr),
349 lpBuf, dwBufLen, uCodePage);
350 break;
351
352 case GCS_RESULTCLAUSE:
353 dwBufLen = Imm32CompClauseWideToAnsi(CS_Clause(pCS, ResultClause),
354 CS_Size(pCS, ResultClause),
355 CS_StrW(pCS, ResultStr),
356 lpBuf, dwBufLen, uCodePage);
357 break;
358
359 default:
360 FIXME("0x%X\n", dwIndex);
361 return IMM_ERROR_GENERAL;
362 }
363 }
364
365 return dwBufLen;
366 }
367
368 // Win: InternalGetCompositionStringW
369 LONG APIENTRY
Imm32GetCompStrW(HIMC hIMC,const COMPOSITIONSTRING * pCS,DWORD dwIndex,LPVOID lpBuf,DWORD dwBufLen,BOOL bAnsiClient,UINT uCodePage)370 Imm32GetCompStrW(HIMC hIMC, const COMPOSITIONSTRING *pCS, DWORD dwIndex,
371 LPVOID lpBuf, DWORD dwBufLen, BOOL bAnsiClient, UINT uCodePage)
372 {
373 if (bAnsiClient)
374 {
375 switch (dwIndex)
376 {
377 case GCS_COMPREADSTR:
378 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, CompReadStr),
379 CS_SizeA(pCS, CompReadStr),
380 lpBuf, dwBufLen, uCodePage);
381 break;
382
383 case GCS_COMPREADATTR:
384 dwBufLen = Imm32CompAttrAnsiToWide(CS_Attr(pCS, CompReadAttr),
385 CS_Size(pCS, CompReadAttr),
386 CS_StrA(pCS, CompReadStr),
387 CS_SizeA(pCS, CompReadStr),
388 lpBuf, dwBufLen, uCodePage);
389 break;
390
391 case GCS_COMPREADCLAUSE:
392 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, CompReadClause),
393 CS_Size(pCS, CompReadClause),
394 CS_StrA(pCS, CompReadStr),
395 lpBuf, dwBufLen, uCodePage);
396 break;
397
398 case GCS_COMPSTR:
399 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, CompStr),
400 CS_SizeA(pCS, CompStr),
401 lpBuf, dwBufLen, uCodePage);
402 break;
403
404 case GCS_COMPATTR:
405 dwBufLen = Imm32CompAttrAnsiToWide(CS_Attr(pCS, CompAttr),
406 CS_Size(pCS, CompAttr),
407 CS_StrA(pCS, CompStr), CS_SizeA(pCS, CompStr),
408 lpBuf, dwBufLen, uCodePage);
409 break;
410
411 case GCS_COMPCLAUSE:
412 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, CompClause),
413 CS_Size(pCS, CompClause),
414 CS_StrA(pCS, CompStr),
415 lpBuf, dwBufLen, uCodePage);
416 break;
417
418 case GCS_CURSORPOS:
419 dwBufLen = IchWideFromAnsi(pCS->dwCursorPos, CS_StrA(pCS, CompStr), uCodePage);
420 break;
421
422 case GCS_DELTASTART:
423 dwBufLen = IchWideFromAnsi(pCS->dwDeltaStart, CS_StrA(pCS, CompStr), uCodePage);
424 break;
425
426 case GCS_RESULTREADSTR:
427 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, ResultReadStr),
428 CS_SizeA(pCS, ResultReadStr),
429 lpBuf, dwBufLen, uCodePage);
430 break;
431
432 case GCS_RESULTREADCLAUSE:
433 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, ResultReadClause),
434 CS_Size(pCS, ResultReadClause),
435 CS_StrA(pCS, ResultReadStr),
436 lpBuf, dwBufLen, uCodePage);
437 break;
438
439 case GCS_RESULTSTR:
440 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, ResultStr),
441 CS_SizeA(pCS, ResultStr),
442 lpBuf, dwBufLen, uCodePage);
443 break;
444
445 case GCS_RESULTCLAUSE:
446 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, ResultClause),
447 CS_Size(pCS, ResultClause),
448 CS_StrA(pCS, ResultStr),
449 lpBuf, dwBufLen, uCodePage);
450 break;
451
452 default:
453 FIXME("0x%X\n", dwIndex);
454 return IMM_ERROR_GENERAL;
455 }
456 }
457 else /* !bAnsiClient */
458 {
459 switch (dwIndex)
460 {
461 case GCS_COMPREADSTR:
462 CS_DoStrW(pCS, CompReadStr);
463 break;
464
465 case GCS_COMPREADATTR:
466 CS_DoAttr(pCS, CompReadAttr);
467 break;
468
469 case GCS_COMPREADCLAUSE:
470 CS_DoClause(pCS, CompReadClause);
471 break;
472
473 case GCS_COMPSTR:
474 CS_DoStrW(pCS, CompStr);
475 break;
476
477 case GCS_COMPATTR:
478 CS_DoAttr(pCS, CompAttr);
479 break;
480
481 case GCS_COMPCLAUSE:
482 CS_DoClause(pCS, CompClause);
483 break;
484
485 case GCS_CURSORPOS:
486 dwBufLen = pCS->dwCursorPos;
487 break;
488
489 case GCS_DELTASTART:
490 dwBufLen = pCS->dwDeltaStart;
491 break;
492
493 case GCS_RESULTREADSTR:
494 CS_DoStrW(pCS, ResultReadStr);
495 break;
496
497 case GCS_RESULTREADCLAUSE:
498 CS_DoClause(pCS, ResultReadClause);
499 break;
500
501 case GCS_RESULTSTR:
502 CS_DoStrW(pCS, ResultStr);
503 break;
504
505 case GCS_RESULTCLAUSE:
506 CS_DoClause(pCS, ResultClause);
507 break;
508
509 default:
510 FIXME("0x%X\n", dwIndex);
511 return IMM_ERROR_GENERAL;
512 }
513 }
514
515 return dwBufLen;
516 }
517
518 // Win: ImmSetCompositionStringWorker
519 BOOL APIENTRY
ImmSetCompositionStringAW(HIMC hIMC,DWORD dwIndex,LPVOID pComp,DWORD dwCompLen,LPVOID pRead,DWORD dwReadLen,BOOL bAnsiAPI)520 ImmSetCompositionStringAW(HIMC hIMC, DWORD dwIndex, LPVOID pComp, DWORD dwCompLen,
521 LPVOID pRead, DWORD dwReadLen, BOOL bAnsiAPI)
522 {
523 BOOL ret = FALSE, bAnsiClient;
524 LPVOID pCompNew = NULL, pReadNew = NULL;
525 DWORD dwThreadId, cbCompNew = 0, cbReadNew = 0;
526 LPINPUTCONTEXT pIC;
527 LPCOMPOSITIONSTRING pCS;
528 HKL hKL;
529 PIMEDPI pImeDpi;
530 UINT uCodePage;
531 LPRECONVERTSTRING pRS;
532
533 dwThreadId = (DWORD)NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID);
534 if (dwThreadId != GetCurrentThreadId())
535 {
536 ERR("Thread mismatch\n");
537 return FALSE;
538 }
539
540 hKL = GetKeyboardLayout(dwThreadId);
541 pImeDpi = ImmLockImeDpi(hKL);
542 if (IS_NULL_UNEXPECTEDLY(pImeDpi))
543 return FALSE;
544
545 uCodePage = pImeDpi->uCodePage;
546 bAnsiClient = !ImeDpi_IsUnicode(pImeDpi);
547
548 switch (dwIndex)
549 {
550 case SCS_SETSTR: case SCS_CHANGEATTR: case SCS_CHANGECLAUSE:
551 break;
552
553 case SCS_SETRECONVERTSTRING: case SCS_QUERYRECONVERTSTRING:
554 if (pImeDpi->ImeInfo.fdwSCSCaps & SCS_CAP_SETRECONVERTSTRING)
555 break;
556 /* FALL THROUGH */
557 default:
558 ERR("0x%X\n", dwIndex);
559 ImmUnlockImeDpi(pImeDpi);
560 return FALSE;
561 }
562
563 if (bAnsiAPI == bAnsiClient || (!pComp && !pRead)) /* No conversion needed */
564 {
565 ret = pImeDpi->ImeSetCompositionString(hIMC, dwIndex, pComp, dwCompLen,
566 pRead, dwReadLen);
567 ImmUnlockImeDpi(pImeDpi);
568 return ret;
569 }
570
571 if (!Imm32OpenICAndCS(hIMC, &pIC, &pCS))
572 {
573 ImmUnlockImeDpi(pImeDpi);
574 return FALSE;
575 }
576
577 /*
578 * This code is really too complicated. But I cannot simplify.
579 * It converts like (pComp, dwCompLen) --> (pCompNew, cbCompNew) and
580 * (pRead, dwReadLen) --> (pReadNew, cbReadNew).
581 * (1) Check bAnsiClient, (2) Get the size, (3) Allocate a buffer for conversion,
582 * (4) Store converted data into the buffer.
583 */
584 switch (dwIndex)
585 {
586 case SCS_SETSTR:
587 if (pComp)
588 {
589 if (bAnsiClient)
590 {
591 cbCompNew = Imm32CompStrWideToAnsi(pComp, dwCompLen, NULL, 0, uCodePage);
592 pCompNew = ImmLocalAlloc(0, cbCompNew);
593 if (IS_NULL_UNEXPECTEDLY(pCompNew))
594 goto Quit;
595
596 Imm32CompStrWideToAnsi(pComp, dwCompLen, pCompNew, cbCompNew, uCodePage);
597 }
598 else
599 {
600 cbCompNew = Imm32CompStrAnsiToWide(pComp, dwCompLen, NULL, 0, uCodePage);
601 pCompNew = ImmLocalAlloc(0, cbCompNew);
602 if (IS_NULL_UNEXPECTEDLY(pCompNew))
603 goto Quit;
604
605 Imm32CompStrAnsiToWide(pComp, dwCompLen, pCompNew, cbCompNew, uCodePage);
606 }
607 }
608
609 if (pRead)
610 {
611 if (bAnsiClient)
612 {
613 cbReadNew = Imm32CompStrWideToAnsi(pRead, dwReadLen, NULL, 0, uCodePage);
614 pReadNew = ImmLocalAlloc(0, cbReadNew);
615 if (IS_NULL_UNEXPECTEDLY(pReadNew))
616 goto Quit;
617
618 Imm32CompStrWideToAnsi(pRead, dwReadLen, pReadNew, cbReadNew, uCodePage);
619 }
620 else
621 {
622 cbReadNew = Imm32CompStrAnsiToWide(pRead, dwReadLen, NULL, 0, uCodePage);
623 pReadNew = ImmLocalAlloc(0, cbReadNew);
624 if (IS_NULL_UNEXPECTEDLY(pReadNew))
625 goto Quit;
626
627 Imm32CompStrAnsiToWide(pRead, dwReadLen, pReadNew, cbReadNew, uCodePage);
628 }
629 }
630 break;
631
632 case SCS_CHANGEATTR:
633 if (pComp)
634 {
635 if (bAnsiClient)
636 {
637 cbCompNew = Imm32CompAttrWideToAnsi(pComp, dwCompLen,
638 CS_StrW(pCS, CompStr),
639 CS_SizeW(pCS, CompStr),
640 NULL, 0, uCodePage);
641 pCompNew = ImmLocalAlloc(0, cbCompNew);
642 if (IS_NULL_UNEXPECTEDLY(pCompNew))
643 goto Quit;
644
645 Imm32CompAttrWideToAnsi(pComp, dwCompLen,
646 CS_StrW(pCS, CompStr), CS_SizeW(pCS, CompStr),
647 pCompNew, cbCompNew, uCodePage);
648 }
649 else
650 {
651 cbCompNew = Imm32CompAttrAnsiToWide(pComp, dwCompLen,
652 CS_StrA(pCS, CompStr),
653 CS_SizeA(pCS, CompStr),
654 NULL, 0, uCodePage);
655 pCompNew = ImmLocalAlloc(0, cbCompNew);
656 if (IS_NULL_UNEXPECTEDLY(pCompNew))
657 goto Quit;
658
659 Imm32CompAttrAnsiToWide(pComp, dwCompLen,
660 CS_StrA(pCS, CompStr), CS_SizeA(pCS, CompStr),
661 pCompNew, cbCompNew, uCodePage);
662 }
663 }
664
665 if (pRead)
666 {
667 if (bAnsiClient)
668 {
669 cbReadNew = Imm32CompAttrWideToAnsi(pRead, dwReadLen,
670 CS_StrW(pCS, CompReadStr),
671 CS_SizeW(pCS, CompReadStr),
672 NULL, 0, uCodePage);
673 pReadNew = ImmLocalAlloc(0, cbReadNew);
674 if (IS_NULL_UNEXPECTEDLY(pReadNew))
675 goto Quit;
676
677 Imm32CompAttrWideToAnsi(pRead, dwReadLen,
678 CS_StrW(pCS, CompReadStr), CS_SizeW(pCS, CompReadStr),
679 pReadNew, cbReadNew, uCodePage);
680 }
681 else
682 {
683 cbReadNew = Imm32CompAttrAnsiToWide(pRead, dwReadLen,
684 CS_StrA(pCS, CompReadStr),
685 CS_SizeA(pCS, CompReadStr),
686 NULL, 0, uCodePage);
687 pReadNew = ImmLocalAlloc(0, cbReadNew);
688 if (IS_NULL_UNEXPECTEDLY(pReadNew))
689 goto Quit;
690
691 Imm32CompAttrAnsiToWide(pRead, dwReadLen,
692 CS_StrA(pCS, CompReadStr), CS_SizeA(pCS, CompReadStr),
693 pReadNew, cbReadNew, uCodePage);
694 }
695 }
696 break;
697
698 case SCS_CHANGECLAUSE:
699 if (pComp)
700 {
701 if (bAnsiClient)
702 {
703 cbCompNew = Imm32CompClauseWideToAnsi(pComp, dwCompLen, CS_StrW(pCS, CompStr),
704 NULL, 0, uCodePage);
705 pCompNew = ImmLocalAlloc(0, cbCompNew);
706 if (IS_NULL_UNEXPECTEDLY(pCompNew))
707 goto Quit;
708
709 Imm32CompClauseWideToAnsi(pComp, dwCompLen, CS_StrW(pCS, CompStr),
710 pCompNew, cbCompNew, uCodePage);
711 }
712 else
713 {
714 cbCompNew = Imm32CompClauseAnsiToWide(pComp, dwCompLen, CS_StrA(pCS, CompStr),
715 NULL, 0, uCodePage);
716 pCompNew = ImmLocalAlloc(0, cbCompNew);
717 if (IS_NULL_UNEXPECTEDLY(pCompNew))
718 goto Quit;
719
720 Imm32CompClauseAnsiToWide(pComp, dwCompLen, CS_StrA(pCS, CompStr),
721 pCompNew, cbCompNew, uCodePage);
722 }
723 }
724
725 if (pRead)
726 {
727 if (bAnsiClient)
728 {
729 cbReadNew = Imm32CompClauseWideToAnsi(pRead, dwReadLen, CS_StrW(pCS, CompReadStr),
730 NULL, 0, uCodePage);
731 pReadNew = ImmLocalAlloc(0, cbReadNew);
732 if (IS_NULL_UNEXPECTEDLY(pReadNew))
733 goto Quit;
734
735 Imm32CompClauseWideToAnsi(pRead, dwReadLen,
736 CS_StrW(pCS, CompReadStr),
737 pReadNew, cbReadNew, uCodePage);
738 }
739 else
740 {
741 cbReadNew = Imm32CompClauseAnsiToWide(pRead, dwReadLen, CS_StrA(pCS, CompReadStr),
742 NULL, 0, uCodePage);
743 pReadNew = ImmLocalAlloc(0, cbReadNew);
744 if (IS_NULL_UNEXPECTEDLY(pReadNew))
745 goto Quit;
746
747 Imm32CompClauseAnsiToWide(pRead, dwReadLen, CS_StrA(pCS, CompReadStr),
748 pReadNew, cbReadNew, uCodePage);
749 }
750 }
751 break;
752
753 case SCS_SETRECONVERTSTRING: case SCS_QUERYRECONVERTSTRING:
754 {
755 if (pComp)
756 {
757 if (bAnsiClient)
758 {
759 cbCompNew = Imm32ReconvertAnsiFromWide(NULL, pComp, uCodePage);
760 pCompNew = ImmLocalAlloc(0, cbCompNew);
761 if (IS_NULL_UNEXPECTEDLY(pCompNew))
762 goto Quit;
763
764 pRS = pCompNew;
765 pRS->dwSize = cbCompNew;
766 pRS->dwVersion = 0;
767 Imm32ReconvertAnsiFromWide(pRS, pComp, uCodePage);
768 }
769 else
770 {
771 cbCompNew = Imm32ReconvertWideFromAnsi(NULL, pComp, uCodePage);
772 pCompNew = ImmLocalAlloc(0, cbCompNew);
773 if (IS_NULL_UNEXPECTEDLY(pCompNew))
774 goto Quit;
775
776 pRS = pCompNew;
777 pRS->dwSize = cbCompNew;
778 pRS->dwVersion = 0;
779 Imm32ReconvertWideFromAnsi(pRS, pComp, uCodePage);
780 }
781 }
782
783 if (pRead)
784 {
785 if (bAnsiClient)
786 {
787 cbReadNew = Imm32ReconvertAnsiFromWide(NULL, pRead, uCodePage);
788 pReadNew = ImmLocalAlloc(0, cbReadNew);
789 if (IS_NULL_UNEXPECTEDLY(pReadNew))
790 goto Quit;
791
792 pRS = pReadNew;
793 pRS->dwSize = cbReadNew;
794 pRS->dwVersion = 0;
795 Imm32ReconvertAnsiFromWide(pRS, pRead, uCodePage);
796 }
797 else
798 {
799 cbReadNew = Imm32ReconvertWideFromAnsi(NULL, pRead, uCodePage);
800 pReadNew = ImmLocalAlloc(0, cbReadNew);
801 if (IS_NULL_UNEXPECTEDLY(pReadNew))
802 goto Quit;
803
804 pRS = pReadNew;
805 pRS->dwSize = cbReadNew;
806 pRS->dwVersion = 0;
807 Imm32ReconvertWideFromAnsi(pRS, pRead, uCodePage);
808 }
809 }
810 break;
811 }
812 }
813
814 ImmUnlockIMCC(pIC->hCompStr);
815 pCS = NULL;
816 ImmUnlockIMC(hIMC);
817 pIC = NULL;
818
819 ret = pImeDpi->ImeSetCompositionString(hIMC, dwIndex, pCompNew, cbCompNew,
820 pReadNew, cbReadNew);
821
822 if (dwIndex == SCS_QUERYRECONVERTSTRING)
823 {
824 if (pComp)
825 {
826 if (bAnsiClient)
827 ret = Imm32ReconvertWideFromAnsi(pComp, pCompNew, uCodePage);
828 else
829 ret = Imm32ReconvertAnsiFromWide(pComp, pCompNew, uCodePage);
830 }
831
832 if (pRead)
833 {
834 if (bAnsiClient)
835 ret = Imm32ReconvertWideFromAnsi(pRead, pReadNew, uCodePage);
836 else
837 ret = Imm32ReconvertAnsiFromWide(pRead, pReadNew, uCodePage);
838 }
839 }
840
841 Quit:
842 if (pCS)
843 ImmUnlockIMCC(pIC->hCompStr);
844 if (pIC)
845 ImmUnlockIMC(hIMC);
846 ImmLocalFree(pCompNew);
847 ImmLocalFree(pReadNew);
848 ImmUnlockImeDpi(pImeDpi);
849 TRACE("ret: %d\n", ret);
850 return ret;
851 }
852
853 /***********************************************************************
854 * ImmGetCompositionStringA (IMM32.@)
855 */
ImmGetCompositionStringA(HIMC hIMC,DWORD dwIndex,LPVOID lpBuf,DWORD dwBufLen)856 LONG WINAPI ImmGetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
857 {
858 LONG ret = 0;
859 LPINPUTCONTEXT pIC;
860 PCLIENTIMC pClientImc;
861 LPCOMPOSITIONSTRING pCS;
862 BOOL bAnsiClient;
863 UINT uCodePage;
864
865 TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
866
867 if (dwBufLen && IS_NULL_UNEXPECTEDLY(lpBuf))
868 return 0;
869
870 pClientImc = ImmLockClientImc(hIMC);
871 if (IS_NULL_UNEXPECTEDLY(pClientImc))
872 return 0;
873
874 bAnsiClient = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
875 uCodePage = pClientImc->uCodePage;
876 ImmUnlockClientImc(pClientImc);
877
878 pIC = ImmLockIMC(hIMC);
879 if (IS_NULL_UNEXPECTEDLY(pIC))
880 return 0;
881
882 pCS = ImmLockIMCC(pIC->hCompStr);
883 if (IS_NULL_UNEXPECTEDLY(pCS))
884 {
885 ImmUnlockIMC(hIMC);
886 return 0;
887 }
888
889 ret = Imm32GetCompStrA(hIMC, pCS, dwIndex, lpBuf, dwBufLen, bAnsiClient, uCodePage);
890 ImmUnlockIMCC(pIC->hCompStr);
891 ImmUnlockIMC(hIMC);
892 TRACE("ret: %ld\n", ret);
893 return ret;
894 }
895
896 /***********************************************************************
897 * ImmGetCompositionStringW (IMM32.@)
898 */
ImmGetCompositionStringW(HIMC hIMC,DWORD dwIndex,LPVOID lpBuf,DWORD dwBufLen)899 LONG WINAPI ImmGetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen)
900 {
901 LONG ret = 0;
902 LPINPUTCONTEXT pIC;
903 PCLIENTIMC pClientImc;
904 LPCOMPOSITIONSTRING pCS;
905 BOOL bAnsiClient;
906 UINT uCodePage;
907
908 TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
909
910 if (dwBufLen && IS_NULL_UNEXPECTEDLY(lpBuf))
911 return 0;
912
913 pClientImc = ImmLockClientImc(hIMC);
914 if (IS_NULL_UNEXPECTEDLY(pClientImc))
915 return 0;
916
917 bAnsiClient = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
918 uCodePage = pClientImc->uCodePage;
919 ImmUnlockClientImc(pClientImc);
920
921 pIC = ImmLockIMC(hIMC);
922 if (IS_NULL_UNEXPECTEDLY(pIC))
923 return 0;
924
925 pCS = ImmLockIMCC(pIC->hCompStr);
926 if (IS_NULL_UNEXPECTEDLY(pCS))
927 {
928 ImmUnlockIMC(hIMC);
929 return 0;
930 }
931
932 ret = Imm32GetCompStrW(hIMC, pCS, dwIndex, lpBuf, dwBufLen, bAnsiClient, uCodePage);
933 ImmUnlockIMCC(pIC->hCompStr);
934 ImmUnlockIMC(hIMC);
935 TRACE("ret: %ld\n", ret);
936 return ret;
937 }
938
939 /***********************************************************************
940 * ImmSetCompositionStringA (IMM32.@)
941 */
942 BOOL WINAPI
ImmSetCompositionStringA(HIMC hIMC,DWORD dwIndex,LPVOID lpComp,DWORD dwCompLen,LPVOID lpRead,DWORD dwReadLen)943 ImmSetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen,
944 LPVOID lpRead, DWORD dwReadLen)
945 {
946 TRACE("(%p, %lu, %p, %lu, %p, %lu)\n",
947 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
948 return ImmSetCompositionStringAW(hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen, TRUE);
949 }
950
951 /***********************************************************************
952 * ImmSetCompositionStringW (IMM32.@)
953 */
954 BOOL WINAPI
ImmSetCompositionStringW(HIMC hIMC,DWORD dwIndex,LPVOID lpComp,DWORD dwCompLen,LPVOID lpRead,DWORD dwReadLen)955 ImmSetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen,
956 LPVOID lpRead, DWORD dwReadLen)
957 {
958 TRACE("(%p, %lu, %p, %lu, %p, %lu)\n",
959 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
960 return ImmSetCompositionStringAW(hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen, FALSE);
961 }
962