Reactos
at master 984 lines 33 kB view raw
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}