Reactos
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
14WINE_DEFAULT_DEBUG_CHANNEL(imm);
15
16BOOL
17Imm32OpenICAndCS(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
41static inline LONG
42Imm32CompStrAnsiToWide(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] = UNICODE_NULL;
48 return ret * sizeof(WCHAR);
49}
50
51static inline LONG
52Imm32CompStrWideToAnsi(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] = ANSI_NULL;
58 return ret * sizeof(CHAR);
59}
60
61static INT
62Imm32CompAttrWideToAnsi(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 }
90end:
91 rc = j;
92 }
93
94 return rc * sizeof(BYTE);
95}
96
97static INT
98Imm32CompAttrAnsiToWide(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
132static INT
133Imm32CompClauseAnsiToWide(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
163static INT
164Imm32CompClauseWideToAnsi(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
217static LONG
218Imm32GetCompStrA(HIMC hIMC, const COMPOSITIONSTRING *pCS, DWORD dwIndex,
219 LPVOID lpBuf, DWORD dwBufLen, BOOL bAnsiClient, UINT uCodePage)
220{
221 if (bAnsiClient)
222 {
223 switch (dwIndex)
224 {
225 case GCS_COMPREADSTR:
226 CS_DoStrA(pCS, CompReadStr);
227 break;
228
229 case GCS_COMPREADATTR:
230 CS_DoAttr(pCS, CompReadAttr);
231 break;
232
233 case GCS_COMPREADCLAUSE:
234 CS_DoClause(pCS, CompReadClause);
235 break;
236
237 case GCS_COMPSTR:
238 CS_DoStrA(pCS, CompStr);
239 break;
240
241 case GCS_COMPATTR:
242 CS_DoAttr(pCS, CompAttr);
243 break;
244
245 case GCS_COMPCLAUSE:
246 CS_DoClause(pCS, CompClause);
247 break;
248
249 case GCS_CURSORPOS:
250 dwBufLen = pCS->dwCursorPos;
251 break;
252
253 case GCS_DELTASTART:
254 dwBufLen = pCS->dwDeltaStart;
255 break;
256
257 case GCS_RESULTREADSTR:
258 CS_DoStrA(pCS, ResultReadStr);
259 break;
260
261 case GCS_RESULTREADCLAUSE:
262 CS_DoClause(pCS, ResultReadClause);
263 break;
264
265 case GCS_RESULTSTR:
266 CS_DoStrA(pCS, ResultStr);
267 break;
268
269 case GCS_RESULTCLAUSE:
270 CS_DoClause(pCS, ResultClause);
271 break;
272
273 default:
274 FIXME("0x%X\n", dwIndex);
275 return IMM_ERROR_GENERAL;
276 }
277 }
278 else /* !bAnsiClient */
279 {
280 switch (dwIndex)
281 {
282 case GCS_COMPREADSTR:
283 dwBufLen = Imm32CompStrWideToAnsi(CS_StrW(pCS, CompReadStr),
284 CS_SizeW(pCS, CompReadStr),
285 lpBuf, dwBufLen, uCodePage);
286 break;
287
288 case GCS_COMPREADATTR:
289 dwBufLen = Imm32CompAttrWideToAnsi(CS_Attr(pCS, CompReadAttr),
290 CS_Size(pCS, CompReadAttr),
291 CS_StrW(pCS, CompReadStr),
292 CS_SizeW(pCS, CompReadStr),
293 lpBuf, dwBufLen, uCodePage);
294 break;
295
296 case GCS_COMPREADCLAUSE:
297 dwBufLen = Imm32CompClauseWideToAnsi(CS_Clause(pCS, CompReadClause),
298 CS_Size(pCS, CompReadClause),
299 CS_StrW(pCS, CompReadStr),
300 lpBuf, dwBufLen, uCodePage);
301 break;
302
303 case GCS_COMPSTR:
304 dwBufLen = Imm32CompStrWideToAnsi(CS_StrW(pCS, CompStr),
305 CS_SizeW(pCS, CompStr),
306 lpBuf, dwBufLen, uCodePage);
307 break;
308
309 case GCS_COMPATTR:
310 dwBufLen = Imm32CompAttrWideToAnsi(CS_Attr(pCS, CompAttr),
311 CS_Size(pCS, CompAttr),
312 CS_StrW(pCS, CompStr),
313 CS_SizeW(pCS, CompStr),
314 lpBuf, dwBufLen, uCodePage);
315 break;
316
317 case GCS_COMPCLAUSE:
318 dwBufLen = Imm32CompClauseWideToAnsi(CS_Clause(pCS, CompClause),
319 CS_Size(pCS, CompClause),
320 CS_StrW(pCS, CompStr),
321 lpBuf, dwBufLen, uCodePage);
322 break;
323
324 case GCS_CURSORPOS:
325 dwBufLen = IchAnsiFromWide(pCS->dwCursorPos, CS_StrW(pCS, CompStr), uCodePage);
326 break;
327
328 case GCS_DELTASTART:
329 dwBufLen = IchAnsiFromWide(pCS->dwDeltaStart, CS_StrW(pCS, CompStr), uCodePage);
330 break;
331
332 case GCS_RESULTREADSTR:
333 dwBufLen = Imm32CompStrWideToAnsi(CS_StrW(pCS, ResultReadStr),
334 CS_SizeW(pCS, ResultReadStr),
335 lpBuf, dwBufLen, uCodePage);
336 break;
337
338 case GCS_RESULTREADCLAUSE:
339 dwBufLen = Imm32CompClauseWideToAnsi(CS_Clause(pCS, ResultReadClause),
340 CS_Size(pCS, ResultReadClause),
341 CS_StrW(pCS, ResultReadStr),
342 lpBuf, dwBufLen, uCodePage);
343 break;
344
345 case GCS_RESULTSTR:
346 dwBufLen = Imm32CompStrWideToAnsi(CS_StrW(pCS, ResultStr),
347 CS_SizeW(pCS, ResultStr),
348 lpBuf, dwBufLen, uCodePage);
349 break;
350
351 case GCS_RESULTCLAUSE:
352 dwBufLen = Imm32CompClauseWideToAnsi(CS_Clause(pCS, ResultClause),
353 CS_Size(pCS, ResultClause),
354 CS_StrW(pCS, ResultStr),
355 lpBuf, dwBufLen, uCodePage);
356 break;
357
358 default:
359 FIXME("0x%X\n", dwIndex);
360 return IMM_ERROR_GENERAL;
361 }
362 }
363
364 return dwBufLen;
365}
366
367static LONG
368Imm32GetCompStrW(HIMC hIMC, const COMPOSITIONSTRING *pCS, DWORD dwIndex,
369 LPVOID lpBuf, DWORD dwBufLen, BOOL bAnsiClient, UINT uCodePage)
370{
371 if (bAnsiClient)
372 {
373 switch (dwIndex)
374 {
375 case GCS_COMPREADSTR:
376 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, CompReadStr),
377 CS_SizeA(pCS, CompReadStr),
378 lpBuf, dwBufLen, uCodePage);
379 break;
380
381 case GCS_COMPREADATTR:
382 dwBufLen = Imm32CompAttrAnsiToWide(CS_Attr(pCS, CompReadAttr),
383 CS_Size(pCS, CompReadAttr),
384 CS_StrA(pCS, CompReadStr),
385 CS_SizeA(pCS, CompReadStr),
386 lpBuf, dwBufLen, uCodePage);
387 break;
388
389 case GCS_COMPREADCLAUSE:
390 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, CompReadClause),
391 CS_Size(pCS, CompReadClause),
392 CS_StrA(pCS, CompReadStr),
393 lpBuf, dwBufLen, uCodePage);
394 break;
395
396 case GCS_COMPSTR:
397 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, CompStr),
398 CS_SizeA(pCS, CompStr),
399 lpBuf, dwBufLen, uCodePage);
400 break;
401
402 case GCS_COMPATTR:
403 dwBufLen = Imm32CompAttrAnsiToWide(CS_Attr(pCS, CompAttr),
404 CS_Size(pCS, CompAttr),
405 CS_StrA(pCS, CompStr), CS_SizeA(pCS, CompStr),
406 lpBuf, dwBufLen, uCodePage);
407 break;
408
409 case GCS_COMPCLAUSE:
410 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, CompClause),
411 CS_Size(pCS, CompClause),
412 CS_StrA(pCS, CompStr),
413 lpBuf, dwBufLen, uCodePage);
414 break;
415
416 case GCS_CURSORPOS:
417 dwBufLen = IchWideFromAnsi(pCS->dwCursorPos, CS_StrA(pCS, CompStr), uCodePage);
418 break;
419
420 case GCS_DELTASTART:
421 dwBufLen = IchWideFromAnsi(pCS->dwDeltaStart, CS_StrA(pCS, CompStr), uCodePage);
422 break;
423
424 case GCS_RESULTREADSTR:
425 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, ResultReadStr),
426 CS_SizeA(pCS, ResultReadStr),
427 lpBuf, dwBufLen, uCodePage);
428 break;
429
430 case GCS_RESULTREADCLAUSE:
431 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, ResultReadClause),
432 CS_Size(pCS, ResultReadClause),
433 CS_StrA(pCS, ResultReadStr),
434 lpBuf, dwBufLen, uCodePage);
435 break;
436
437 case GCS_RESULTSTR:
438 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, ResultStr),
439 CS_SizeA(pCS, ResultStr),
440 lpBuf, dwBufLen, uCodePage);
441 break;
442
443 case GCS_RESULTCLAUSE:
444 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, ResultClause),
445 CS_Size(pCS, ResultClause),
446 CS_StrA(pCS, ResultStr),
447 lpBuf, dwBufLen, uCodePage);
448 break;
449
450 default:
451 FIXME("0x%X\n", dwIndex);
452 return IMM_ERROR_GENERAL;
453 }
454 }
455 else /* !bAnsiClient */
456 {
457 switch (dwIndex)
458 {
459 case GCS_COMPREADSTR:
460 CS_DoStrW(pCS, CompReadStr);
461 break;
462
463 case GCS_COMPREADATTR:
464 CS_DoAttr(pCS, CompReadAttr);
465 break;
466
467 case GCS_COMPREADCLAUSE:
468 CS_DoClause(pCS, CompReadClause);
469 break;
470
471 case GCS_COMPSTR:
472 CS_DoStrW(pCS, CompStr);
473 break;
474
475 case GCS_COMPATTR:
476 CS_DoAttr(pCS, CompAttr);
477 break;
478
479 case GCS_COMPCLAUSE:
480 CS_DoClause(pCS, CompClause);
481 break;
482
483 case GCS_CURSORPOS:
484 dwBufLen = pCS->dwCursorPos;
485 break;
486
487 case GCS_DELTASTART:
488 dwBufLen = pCS->dwDeltaStart;
489 break;
490
491 case GCS_RESULTREADSTR:
492 CS_DoStrW(pCS, ResultReadStr);
493 break;
494
495 case GCS_RESULTREADCLAUSE:
496 CS_DoClause(pCS, ResultReadClause);
497 break;
498
499 case GCS_RESULTSTR:
500 CS_DoStrW(pCS, ResultStr);
501 break;
502
503 case GCS_RESULTCLAUSE:
504 CS_DoClause(pCS, ResultClause);
505 break;
506
507 default:
508 FIXME("0x%X\n", dwIndex);
509 return IMM_ERROR_GENERAL;
510 }
511 }
512
513 return dwBufLen;
514}
515
516static BOOL
517ImmSetCompositionStringAW(
518 _In_ HIMC hIMC,
519 _In_ DWORD dwIndex,
520 _Inout_updates_bytes_opt_(dwCompLen) LPVOID pComp,
521 _In_ DWORD dwCompLen,
522 _Inout_updates_bytes_opt_(dwReadLen) LPVOID pRead,
523 _In_ DWORD dwReadLen,
524 _In_ BOOL bAnsiAPI)
525{
526 BOOL ret = FALSE, bAnsiClient;
527 LPVOID pCompNew = NULL, pReadNew = NULL;
528 DWORD dwThreadId, cbCompNew = 0, cbReadNew = 0;
529 LPINPUTCONTEXT pIC;
530 LPCOMPOSITIONSTRING pCS;
531 HKL hKL;
532 PIMEDPI pImeDpi;
533 UINT uCodePage;
534 LPRECONVERTSTRING pRS;
535
536 dwThreadId = (DWORD)NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID);
537 if (dwThreadId != GetCurrentThreadId())
538 {
539 ERR("Thread mismatch\n");
540 return FALSE;
541 }
542
543 hKL = GetKeyboardLayout(dwThreadId);
544 pImeDpi = ImmLockImeDpi(hKL);
545 if (IS_NULL_UNEXPECTEDLY(pImeDpi))
546 return FALSE;
547
548 uCodePage = pImeDpi->uCodePage;
549 bAnsiClient = !ImeDpi_IsUnicode(pImeDpi);
550
551 switch (dwIndex)
552 {
553 case SCS_SETSTR: case SCS_CHANGEATTR: case SCS_CHANGECLAUSE:
554 break;
555
556 case SCS_SETRECONVERTSTRING: case SCS_QUERYRECONVERTSTRING:
557 if (pImeDpi->ImeInfo.fdwSCSCaps & SCS_CAP_SETRECONVERTSTRING)
558 break;
559 /* FALL THROUGH */
560 default:
561 ERR("0x%X\n", dwIndex);
562 ImmUnlockImeDpi(pImeDpi);
563 return FALSE;
564 }
565
566 if (bAnsiAPI == bAnsiClient || (!pComp && !pRead)) /* No conversion needed */
567 {
568 ret = pImeDpi->ImeSetCompositionString(hIMC, dwIndex, pComp, dwCompLen,
569 pRead, dwReadLen);
570 ImmUnlockImeDpi(pImeDpi);
571 return ret;
572 }
573
574 if (!Imm32OpenICAndCS(hIMC, &pIC, &pCS))
575 {
576 ImmUnlockImeDpi(pImeDpi);
577 return FALSE;
578 }
579
580 /*
581 * This code is really too complicated. But I cannot simplify.
582 * It converts like (pComp, dwCompLen) --> (pCompNew, cbCompNew) and
583 * (pRead, dwReadLen) --> (pReadNew, cbReadNew).
584 * (1) Check bAnsiClient, (2) Get the size, (3) Allocate a buffer for conversion,
585 * (4) Store converted data into the buffer.
586 */
587 switch (dwIndex)
588 {
589 case SCS_SETSTR:
590 if (pComp)
591 {
592 if (bAnsiClient)
593 {
594 cbCompNew = Imm32CompStrWideToAnsi(pComp, dwCompLen, NULL, 0, uCodePage);
595 pCompNew = ImmLocalAlloc(0, cbCompNew);
596 if (IS_NULL_UNEXPECTEDLY(pCompNew))
597 goto Quit;
598
599 Imm32CompStrWideToAnsi(pComp, dwCompLen, pCompNew, cbCompNew, uCodePage);
600 }
601 else
602 {
603 cbCompNew = Imm32CompStrAnsiToWide(pComp, dwCompLen, NULL, 0, uCodePage);
604 pCompNew = ImmLocalAlloc(0, cbCompNew);
605 if (IS_NULL_UNEXPECTEDLY(pCompNew))
606 goto Quit;
607
608 Imm32CompStrAnsiToWide(pComp, dwCompLen, pCompNew, cbCompNew, uCodePage);
609 }
610 }
611
612 if (pRead)
613 {
614 if (bAnsiClient)
615 {
616 cbReadNew = Imm32CompStrWideToAnsi(pRead, dwReadLen, NULL, 0, uCodePage);
617 pReadNew = ImmLocalAlloc(0, cbReadNew);
618 if (IS_NULL_UNEXPECTEDLY(pReadNew))
619 goto Quit;
620
621 Imm32CompStrWideToAnsi(pRead, dwReadLen, pReadNew, cbReadNew, uCodePage);
622 }
623 else
624 {
625 cbReadNew = Imm32CompStrAnsiToWide(pRead, dwReadLen, NULL, 0, uCodePage);
626 pReadNew = ImmLocalAlloc(0, cbReadNew);
627 if (IS_NULL_UNEXPECTEDLY(pReadNew))
628 goto Quit;
629
630 Imm32CompStrAnsiToWide(pRead, dwReadLen, pReadNew, cbReadNew, uCodePage);
631 }
632 }
633 break;
634
635 case SCS_CHANGEATTR:
636 if (pComp)
637 {
638 if (bAnsiClient)
639 {
640 cbCompNew = Imm32CompAttrWideToAnsi(pComp, dwCompLen,
641 CS_StrW(pCS, CompStr),
642 CS_SizeW(pCS, CompStr),
643 NULL, 0, uCodePage);
644 pCompNew = ImmLocalAlloc(0, cbCompNew);
645 if (IS_NULL_UNEXPECTEDLY(pCompNew))
646 goto Quit;
647
648 Imm32CompAttrWideToAnsi(pComp, dwCompLen,
649 CS_StrW(pCS, CompStr), CS_SizeW(pCS, CompStr),
650 pCompNew, cbCompNew, uCodePage);
651 }
652 else
653 {
654 cbCompNew = Imm32CompAttrAnsiToWide(pComp, dwCompLen,
655 CS_StrA(pCS, CompStr),
656 CS_SizeA(pCS, CompStr),
657 NULL, 0, uCodePage);
658 pCompNew = ImmLocalAlloc(0, cbCompNew);
659 if (IS_NULL_UNEXPECTEDLY(pCompNew))
660 goto Quit;
661
662 Imm32CompAttrAnsiToWide(pComp, dwCompLen,
663 CS_StrA(pCS, CompStr), CS_SizeA(pCS, CompStr),
664 pCompNew, cbCompNew, uCodePage);
665 }
666 }
667
668 if (pRead)
669 {
670 if (bAnsiClient)
671 {
672 cbReadNew = Imm32CompAttrWideToAnsi(pRead, dwReadLen,
673 CS_StrW(pCS, CompReadStr),
674 CS_SizeW(pCS, CompReadStr),
675 NULL, 0, uCodePage);
676 pReadNew = ImmLocalAlloc(0, cbReadNew);
677 if (IS_NULL_UNEXPECTEDLY(pReadNew))
678 goto Quit;
679
680 Imm32CompAttrWideToAnsi(pRead, dwReadLen,
681 CS_StrW(pCS, CompReadStr), CS_SizeW(pCS, CompReadStr),
682 pReadNew, cbReadNew, uCodePage);
683 }
684 else
685 {
686 cbReadNew = Imm32CompAttrAnsiToWide(pRead, dwReadLen,
687 CS_StrA(pCS, CompReadStr),
688 CS_SizeA(pCS, CompReadStr),
689 NULL, 0, uCodePage);
690 pReadNew = ImmLocalAlloc(0, cbReadNew);
691 if (IS_NULL_UNEXPECTEDLY(pReadNew))
692 goto Quit;
693
694 Imm32CompAttrAnsiToWide(pRead, dwReadLen,
695 CS_StrA(pCS, CompReadStr), CS_SizeA(pCS, CompReadStr),
696 pReadNew, cbReadNew, uCodePage);
697 }
698 }
699 break;
700
701 case SCS_CHANGECLAUSE:
702 if (pComp)
703 {
704 if (bAnsiClient)
705 {
706 cbCompNew = Imm32CompClauseWideToAnsi(pComp, dwCompLen, CS_StrW(pCS, CompStr),
707 NULL, 0, uCodePage);
708 pCompNew = ImmLocalAlloc(0, cbCompNew);
709 if (IS_NULL_UNEXPECTEDLY(pCompNew))
710 goto Quit;
711
712 Imm32CompClauseWideToAnsi(pComp, dwCompLen, CS_StrW(pCS, CompStr),
713 pCompNew, cbCompNew, uCodePage);
714 }
715 else
716 {
717 cbCompNew = Imm32CompClauseAnsiToWide(pComp, dwCompLen, CS_StrA(pCS, CompStr),
718 NULL, 0, uCodePage);
719 pCompNew = ImmLocalAlloc(0, cbCompNew);
720 if (IS_NULL_UNEXPECTEDLY(pCompNew))
721 goto Quit;
722
723 Imm32CompClauseAnsiToWide(pComp, dwCompLen, CS_StrA(pCS, CompStr),
724 pCompNew, cbCompNew, uCodePage);
725 }
726 }
727
728 if (pRead)
729 {
730 if (bAnsiClient)
731 {
732 cbReadNew = Imm32CompClauseWideToAnsi(pRead, dwReadLen, CS_StrW(pCS, CompReadStr),
733 NULL, 0, uCodePage);
734 pReadNew = ImmLocalAlloc(0, cbReadNew);
735 if (IS_NULL_UNEXPECTEDLY(pReadNew))
736 goto Quit;
737
738 Imm32CompClauseWideToAnsi(pRead, dwReadLen,
739 CS_StrW(pCS, CompReadStr),
740 pReadNew, cbReadNew, uCodePage);
741 }
742 else
743 {
744 cbReadNew = Imm32CompClauseAnsiToWide(pRead, dwReadLen, CS_StrA(pCS, CompReadStr),
745 NULL, 0, uCodePage);
746 pReadNew = ImmLocalAlloc(0, cbReadNew);
747 if (IS_NULL_UNEXPECTEDLY(pReadNew))
748 goto Quit;
749
750 Imm32CompClauseAnsiToWide(pRead, dwReadLen, CS_StrA(pCS, CompReadStr),
751 pReadNew, cbReadNew, uCodePage);
752 }
753 }
754 break;
755
756 case SCS_SETRECONVERTSTRING: case SCS_QUERYRECONVERTSTRING:
757 {
758 if (pComp)
759 {
760 if (bAnsiClient)
761 {
762 cbCompNew = Imm32ReconvertAnsiFromWide(NULL, pComp, uCodePage);
763 pCompNew = ImmLocalAlloc(0, cbCompNew);
764 if (IS_NULL_UNEXPECTEDLY(pCompNew))
765 goto Quit;
766
767 pRS = pCompNew;
768 pRS->dwSize = cbCompNew;
769 pRS->dwVersion = 0;
770 Imm32ReconvertAnsiFromWide(pRS, pComp, uCodePage);
771 }
772 else
773 {
774 cbCompNew = Imm32ReconvertWideFromAnsi(NULL, pComp, uCodePage);
775 pCompNew = ImmLocalAlloc(0, cbCompNew);
776 if (IS_NULL_UNEXPECTEDLY(pCompNew))
777 goto Quit;
778
779 pRS = pCompNew;
780 pRS->dwSize = cbCompNew;
781 pRS->dwVersion = 0;
782 Imm32ReconvertWideFromAnsi(pRS, pComp, uCodePage);
783 }
784 }
785
786 if (pRead)
787 {
788 if (bAnsiClient)
789 {
790 cbReadNew = Imm32ReconvertAnsiFromWide(NULL, pRead, uCodePage);
791 pReadNew = ImmLocalAlloc(0, cbReadNew);
792 if (IS_NULL_UNEXPECTEDLY(pReadNew))
793 goto Quit;
794
795 pRS = pReadNew;
796 pRS->dwSize = cbReadNew;
797 pRS->dwVersion = 0;
798 Imm32ReconvertAnsiFromWide(pRS, pRead, uCodePage);
799 }
800 else
801 {
802 cbReadNew = Imm32ReconvertWideFromAnsi(NULL, pRead, uCodePage);
803 pReadNew = ImmLocalAlloc(0, cbReadNew);
804 if (IS_NULL_UNEXPECTEDLY(pReadNew))
805 goto Quit;
806
807 pRS = pReadNew;
808 pRS->dwSize = cbReadNew;
809 pRS->dwVersion = 0;
810 Imm32ReconvertWideFromAnsi(pRS, pRead, uCodePage);
811 }
812 }
813 break;
814 }
815 }
816
817 ImmUnlockIMCC(pIC->hCompStr);
818 pCS = NULL;
819 ImmUnlockIMC(hIMC);
820 pIC = NULL;
821
822 ret = pImeDpi->ImeSetCompositionString(hIMC, dwIndex, pCompNew, cbCompNew,
823 pReadNew, cbReadNew);
824
825 if (dwIndex == SCS_QUERYRECONVERTSTRING)
826 {
827 if (pComp)
828 {
829 if (bAnsiClient)
830 ret = Imm32ReconvertWideFromAnsi(pComp, pCompNew, uCodePage);
831 else
832 ret = Imm32ReconvertAnsiFromWide(pComp, pCompNew, uCodePage);
833 }
834
835 if (pRead)
836 {
837 if (bAnsiClient)
838 ret = Imm32ReconvertWideFromAnsi(pRead, pReadNew, uCodePage);
839 else
840 ret = Imm32ReconvertAnsiFromWide(pRead, pReadNew, uCodePage);
841 }
842 }
843
844Quit:
845 if (pCS)
846 ImmUnlockIMCC(pIC->hCompStr);
847 if (pIC)
848 ImmUnlockIMC(hIMC);
849 ImmLocalFree(pCompNew);
850 ImmLocalFree(pReadNew);
851 ImmUnlockImeDpi(pImeDpi);
852 TRACE("ret: %d\n", ret);
853 return ret;
854}
855
856/***********************************************************************
857 * ImmGetCompositionStringA (IMM32.@)
858 */
859LONG WINAPI
860ImmGetCompositionStringA(
861 _In_ HIMC hIMC,
862 _In_ DWORD dwIndex,
863 _Out_writes_bytes_opt_(dwBufLen) LPVOID lpBuf,
864 _In_ DWORD dwBufLen)
865{
866 LONG ret = 0;
867 LPINPUTCONTEXT pIC;
868 PCLIENTIMC pClientImc;
869 LPCOMPOSITIONSTRING pCS;
870 BOOL bAnsiClient;
871 UINT uCodePage;
872
873 TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
874
875 if (dwBufLen && IS_NULL_UNEXPECTEDLY(lpBuf))
876 return 0;
877
878 pClientImc = ImmLockClientImc(hIMC);
879 if (IS_NULL_UNEXPECTEDLY(pClientImc))
880 return 0;
881
882 bAnsiClient = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
883 uCodePage = pClientImc->uCodePage;
884 ImmUnlockClientImc(pClientImc);
885
886 pIC = ImmLockIMC(hIMC);
887 if (IS_NULL_UNEXPECTEDLY(pIC))
888 return 0;
889
890 pCS = ImmLockIMCC(pIC->hCompStr);
891 if (IS_NULL_UNEXPECTEDLY(pCS))
892 {
893 ImmUnlockIMC(hIMC);
894 return 0;
895 }
896
897 ret = Imm32GetCompStrA(hIMC, pCS, dwIndex, lpBuf, dwBufLen, bAnsiClient, uCodePage);
898 ImmUnlockIMCC(pIC->hCompStr);
899 ImmUnlockIMC(hIMC);
900 TRACE("ret: %ld\n", ret);
901 return ret;
902}
903
904/***********************************************************************
905 * ImmGetCompositionStringW (IMM32.@)
906 */
907LONG WINAPI
908ImmGetCompositionStringW(
909 _In_ HIMC hIMC,
910 _In_ DWORD dwIndex,
911 _Out_writes_bytes_opt_(dwBufLen) LPVOID lpBuf,
912 _In_ DWORD dwBufLen)
913{
914 LONG ret = 0;
915 LPINPUTCONTEXT pIC;
916 PCLIENTIMC pClientImc;
917 LPCOMPOSITIONSTRING pCS;
918 BOOL bAnsiClient;
919 UINT uCodePage;
920
921 TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen);
922
923 if (dwBufLen && IS_NULL_UNEXPECTEDLY(lpBuf))
924 return 0;
925
926 pClientImc = ImmLockClientImc(hIMC);
927 if (IS_NULL_UNEXPECTEDLY(pClientImc))
928 return 0;
929
930 bAnsiClient = !(pClientImc->dwFlags & CLIENTIMC_WIDE);
931 uCodePage = pClientImc->uCodePage;
932 ImmUnlockClientImc(pClientImc);
933
934 pIC = ImmLockIMC(hIMC);
935 if (IS_NULL_UNEXPECTEDLY(pIC))
936 return 0;
937
938 pCS = ImmLockIMCC(pIC->hCompStr);
939 if (IS_NULL_UNEXPECTEDLY(pCS))
940 {
941 ImmUnlockIMC(hIMC);
942 return 0;
943 }
944
945 ret = Imm32GetCompStrW(hIMC, pCS, dwIndex, lpBuf, dwBufLen, bAnsiClient, uCodePage);
946 ImmUnlockIMCC(pIC->hCompStr);
947 ImmUnlockIMC(hIMC);
948 TRACE("ret: %ld\n", ret);
949 return ret;
950}
951
952/***********************************************************************
953 * ImmSetCompositionStringA (IMM32.@)
954 */
955BOOL WINAPI
956ImmSetCompositionStringA(
957 _In_ HIMC hIMC,
958 _In_ DWORD dwIndex,
959 _Inout_updates_bytes_opt_(dwCompLen) LPVOID lpComp,
960 _In_ DWORD dwCompLen,
961 _Inout_updates_bytes_opt_(dwReadLen) LPVOID lpRead,
962 _In_ DWORD dwReadLen)
963{
964 TRACE("(%p, %lu, %p, %lu, %p, %lu)\n",
965 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
966 return ImmSetCompositionStringAW(hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen, TRUE);
967}
968
969/***********************************************************************
970 * ImmSetCompositionStringW (IMM32.@)
971 */
972BOOL WINAPI
973ImmSetCompositionStringW(
974 _In_ HIMC hIMC,
975 _In_ DWORD dwIndex,
976 _Inout_updates_bytes_opt_(dwCompLen) LPVOID lpComp,
977 _In_ DWORD dwCompLen,
978 _Inout_updates_bytes_opt_(dwReadLen) LPVOID lpRead,
979 _In_ DWORD dwReadLen)
980{
981 TRACE("(%p, %lu, %p, %lu, %p, %lu)\n",
982 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen);
983 return ImmSetCompositionStringAW(hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen, FALSE);
984}