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 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 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 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 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 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 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 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 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, CompStr), 293 CS_SizeW(pCS, CompStr), 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, CompStr), 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, CompStr), 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, CompStr), 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 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, CompStr), CS_SizeA(pCS, CompStr), 387 lpBuf, dwBufLen, uCodePage); 388 break; 389 390 case GCS_COMPREADCLAUSE: 391 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, CompReadClause), 392 CS_Size(pCS, CompReadClause), 393 CS_StrA(pCS, CompStr), 394 lpBuf, dwBufLen, uCodePage); 395 break; 396 397 case GCS_COMPSTR: 398 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, CompStr), 399 CS_SizeA(pCS, CompStr), 400 lpBuf, dwBufLen, uCodePage); 401 break; 402 403 case GCS_COMPATTR: 404 dwBufLen = Imm32CompAttrAnsiToWide(CS_Attr(pCS, CompAttr), 405 CS_Size(pCS, CompAttr), 406 CS_StrA(pCS, CompStr), CS_SizeA(pCS, CompStr), 407 lpBuf, dwBufLen, uCodePage); 408 break; 409 410 case GCS_COMPCLAUSE: 411 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, CompClause), 412 CS_Size(pCS, CompClause), 413 CS_StrA(pCS, CompStr), 414 lpBuf, dwBufLen, uCodePage); 415 break; 416 417 case GCS_CURSORPOS: 418 dwBufLen = IchWideFromAnsi(pCS->dwCursorPos, CS_StrA(pCS, CompStr), uCodePage); 419 break; 420 421 case GCS_DELTASTART: 422 dwBufLen = IchWideFromAnsi(pCS->dwDeltaStart, CS_StrA(pCS, CompStr), uCodePage); 423 break; 424 425 case GCS_RESULTREADSTR: 426 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, ResultReadStr), 427 CS_SizeA(pCS, ResultReadStr), 428 lpBuf, dwBufLen, uCodePage); 429 break; 430 431 case GCS_RESULTREADCLAUSE: 432 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, ResultReadClause), 433 CS_Size(pCS, ResultReadClause), 434 CS_StrA(pCS, CompStr), 435 lpBuf, dwBufLen, uCodePage); 436 break; 437 438 case GCS_RESULTSTR: 439 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, ResultStr), 440 CS_SizeA(pCS, ResultStr), 441 lpBuf, dwBufLen, uCodePage); 442 break; 443 444 case GCS_RESULTCLAUSE: 445 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, ResultClause), 446 CS_Size(pCS, ResultClause), 447 CS_StrA(pCS, CompStr), 448 lpBuf, dwBufLen, uCodePage); 449 break; 450 451 default: 452 FIXME("0x%X\n", dwIndex); 453 return IMM_ERROR_GENERAL; 454 } 455 } 456 else /* !bAnsiClient */ 457 { 458 switch (dwIndex) 459 { 460 case GCS_COMPREADSTR: 461 CS_DoStrW(pCS, CompReadStr); 462 break; 463 464 case GCS_COMPREADATTR: 465 CS_DoAttr(pCS, CompReadAttr); 466 break; 467 468 case GCS_COMPREADCLAUSE: 469 CS_DoClause(pCS, CompReadClause); 470 break; 471 472 case GCS_COMPSTR: 473 CS_DoStrW(pCS, CompStr); 474 break; 475 476 case GCS_COMPATTR: 477 CS_DoAttr(pCS, CompAttr); 478 break; 479 480 case GCS_COMPCLAUSE: 481 CS_DoClause(pCS, CompClause); 482 break; 483 484 case GCS_CURSORPOS: 485 dwBufLen = pCS->dwCursorPos; 486 break; 487 488 case GCS_DELTASTART: 489 dwBufLen = pCS->dwDeltaStart; 490 break; 491 492 case GCS_RESULTREADSTR: 493 CS_DoStrW(pCS, ResultReadStr); 494 break; 495 496 case GCS_RESULTREADCLAUSE: 497 CS_DoClause(pCS, ResultReadClause); 498 break; 499 500 case GCS_RESULTSTR: 501 CS_DoStrW(pCS, ResultStr); 502 break; 503 504 case GCS_RESULTCLAUSE: 505 CS_DoClause(pCS, ResultClause); 506 break; 507 508 default: 509 FIXME("0x%X\n", dwIndex); 510 return IMM_ERROR_GENERAL; 511 } 512 } 513 514 return dwBufLen; 515 } 516 517 // Win: ImmSetCompositionStringWorker 518 BOOL APIENTRY 519 ImmSetCompositionStringAW(HIMC hIMC, DWORD dwIndex, LPVOID pComp, DWORD dwCompLen, 520 LPVOID pRead, DWORD dwReadLen, BOOL bAnsiAPI) 521 { 522 BOOL ret = FALSE, bAnsiClient; 523 LPVOID pCompNew = NULL, pReadNew = NULL; 524 DWORD dwThreadId, cbCompNew = 0, cbReadNew = 0; 525 LPINPUTCONTEXT pIC; 526 LPCOMPOSITIONSTRING pCS; 527 HKL hKL; 528 PIMEDPI pImeDpi; 529 UINT uCodePage; 530 LPRECONVERTSTRING pRS; 531 532 dwThreadId = (DWORD)NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID); 533 if (dwThreadId != GetCurrentThreadId()) 534 { 535 ERR("Thread mismatch\n"); 536 return FALSE; 537 } 538 539 hKL = GetKeyboardLayout(dwThreadId); 540 pImeDpi = ImmLockImeDpi(hKL); 541 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 542 return FALSE; 543 544 uCodePage = pImeDpi->uCodePage; 545 bAnsiClient = !ImeDpi_IsUnicode(pImeDpi); 546 547 switch (dwIndex) 548 { 549 case SCS_SETSTR: case SCS_CHANGEATTR: case SCS_CHANGECLAUSE: 550 break; 551 552 case SCS_SETRECONVERTSTRING: case SCS_QUERYRECONVERTSTRING: 553 if (pImeDpi->ImeInfo.fdwSCSCaps & SCS_CAP_SETRECONVERTSTRING) 554 break; 555 /* FALL THROUGH */ 556 default: 557 ERR("0x%X\n", dwIndex); 558 ImmUnlockImeDpi(pImeDpi); 559 return FALSE; 560 } 561 562 if (bAnsiAPI == bAnsiClient || (!pComp && !pRead)) /* No conversion needed */ 563 { 564 ret = pImeDpi->ImeSetCompositionString(hIMC, dwIndex, pComp, dwCompLen, 565 pRead, dwReadLen); 566 ImmUnlockImeDpi(pImeDpi); 567 return ret; 568 } 569 570 if (!Imm32OpenICAndCS(hIMC, &pIC, &pCS)) 571 { 572 ImmUnlockImeDpi(pImeDpi); 573 return FALSE; 574 } 575 576 /* 577 * This code is really too complicated. But I cannot simplify. 578 * It converts like (pComp, dwCompLen) --> (pCompNew, cbCompNew) and 579 * (pRead, dwReadLen) --> (pReadNew, cbReadNew). 580 * (1) Check bAnsiClient, (2) Get the size, (3) Allocate a buffer for conversion, 581 * (4) Store converted data into the buffer. 582 */ 583 switch (dwIndex) 584 { 585 case SCS_SETSTR: 586 if (pComp) 587 { 588 if (bAnsiClient) 589 { 590 cbCompNew = Imm32CompStrWideToAnsi(pComp, dwCompLen, NULL, 0, uCodePage); 591 pCompNew = ImmLocalAlloc(0, cbCompNew); 592 if (IS_NULL_UNEXPECTEDLY(pCompNew)) 593 goto Quit; 594 595 Imm32CompStrWideToAnsi(pComp, dwCompLen, pCompNew, cbCompNew, uCodePage); 596 } 597 else 598 { 599 cbCompNew = Imm32CompStrAnsiToWide(pComp, dwCompLen, NULL, 0, uCodePage); 600 pCompNew = ImmLocalAlloc(0, cbCompNew); 601 if (IS_NULL_UNEXPECTEDLY(pCompNew)) 602 goto Quit; 603 604 Imm32CompStrAnsiToWide(pComp, dwCompLen, pCompNew, cbCompNew, uCodePage); 605 } 606 } 607 608 if (pRead) 609 { 610 if (bAnsiClient) 611 { 612 cbReadNew = Imm32CompStrWideToAnsi(pRead, dwReadLen, NULL, 0, uCodePage); 613 pReadNew = ImmLocalAlloc(0, cbReadNew); 614 if (IS_NULL_UNEXPECTEDLY(pReadNew)) 615 goto Quit; 616 617 Imm32CompStrWideToAnsi(pRead, dwReadLen, pReadNew, cbReadNew, uCodePage); 618 } 619 else 620 { 621 cbReadNew = Imm32CompStrAnsiToWide(pRead, dwReadLen, NULL, 0, uCodePage); 622 pReadNew = ImmLocalAlloc(0, cbReadNew); 623 if (IS_NULL_UNEXPECTEDLY(pReadNew)) 624 goto Quit; 625 626 Imm32CompStrAnsiToWide(pRead, dwReadLen, pReadNew, cbReadNew, uCodePage); 627 } 628 } 629 break; 630 631 case SCS_CHANGEATTR: 632 if (pComp) 633 { 634 if (bAnsiClient) 635 { 636 cbCompNew = Imm32CompAttrWideToAnsi(pComp, dwCompLen, 637 CS_StrW(pCS, CompStr), 638 CS_SizeW(pCS, CompStr), 639 NULL, 0, uCodePage); 640 pCompNew = ImmLocalAlloc(0, cbCompNew); 641 if (IS_NULL_UNEXPECTEDLY(pCompNew)) 642 goto Quit; 643 644 Imm32CompAttrWideToAnsi(pComp, dwCompLen, 645 CS_StrW(pCS, CompStr), CS_SizeW(pCS, CompStr), 646 pCompNew, cbCompNew, uCodePage); 647 } 648 else 649 { 650 cbCompNew = Imm32CompAttrAnsiToWide(pComp, dwCompLen, 651 CS_StrA(pCS, CompStr), 652 CS_SizeA(pCS, CompStr), 653 NULL, 0, uCodePage); 654 pCompNew = ImmLocalAlloc(0, cbCompNew); 655 if (IS_NULL_UNEXPECTEDLY(pCompNew)) 656 goto Quit; 657 658 Imm32CompAttrAnsiToWide(pComp, dwCompLen, 659 CS_StrA(pCS, CompStr), CS_SizeA(pCS, CompStr), 660 pCompNew, cbCompNew, uCodePage); 661 } 662 } 663 664 if (pRead) 665 { 666 if (bAnsiClient) 667 { 668 cbReadNew = Imm32CompAttrWideToAnsi(pRead, dwReadLen, 669 CS_StrW(pCS, CompReadStr), 670 CS_SizeW(pCS, CompReadStr), 671 NULL, 0, uCodePage); 672 pReadNew = ImmLocalAlloc(0, cbReadNew); 673 if (IS_NULL_UNEXPECTEDLY(pReadNew)) 674 goto Quit; 675 676 Imm32CompAttrWideToAnsi(pRead, dwReadLen, 677 CS_StrW(pCS, CompReadStr), CS_SizeW(pCS, CompReadStr), 678 pReadNew, cbReadNew, uCodePage); 679 } 680 else 681 { 682 cbReadNew = Imm32CompAttrAnsiToWide(pRead, dwReadLen, 683 CS_StrA(pCS, CompReadStr), 684 CS_SizeA(pCS, CompReadStr), 685 NULL, 0, uCodePage); 686 pReadNew = ImmLocalAlloc(0, cbReadNew); 687 if (IS_NULL_UNEXPECTEDLY(pReadNew)) 688 goto Quit; 689 690 Imm32CompAttrAnsiToWide(pRead, dwReadLen, 691 CS_StrA(pCS, CompReadStr), CS_SizeA(pCS, CompReadStr), 692 pReadNew, cbReadNew, uCodePage); 693 } 694 } 695 break; 696 697 case SCS_CHANGECLAUSE: 698 if (pComp) 699 { 700 if (bAnsiClient) 701 { 702 cbCompNew = Imm32CompClauseWideToAnsi(pComp, dwCompLen, CS_StrW(pCS, CompStr), 703 NULL, 0, uCodePage); 704 pCompNew = ImmLocalAlloc(0, cbCompNew); 705 if (IS_NULL_UNEXPECTEDLY(pCompNew)) 706 goto Quit; 707 708 Imm32CompClauseWideToAnsi(pComp, dwCompLen, CS_StrW(pCS, CompStr), 709 pCompNew, cbCompNew, uCodePage); 710 } 711 else 712 { 713 cbCompNew = Imm32CompClauseAnsiToWide(pComp, dwCompLen, CS_StrA(pCS, CompStr), 714 NULL, 0, uCodePage); 715 pCompNew = ImmLocalAlloc(0, cbCompNew); 716 if (IS_NULL_UNEXPECTEDLY(pCompNew)) 717 goto Quit; 718 719 Imm32CompClauseAnsiToWide(pComp, dwCompLen, CS_StrA(pCS, CompStr), 720 pCompNew, cbCompNew, uCodePage); 721 } 722 } 723 724 if (pRead) 725 { 726 if (bAnsiClient) 727 { 728 cbReadNew = Imm32CompClauseWideToAnsi(pRead, dwReadLen, CS_StrW(pCS, CompReadStr), 729 NULL, 0, uCodePage); 730 pReadNew = ImmLocalAlloc(0, cbReadNew); 731 if (IS_NULL_UNEXPECTEDLY(pReadNew)) 732 goto Quit; 733 734 Imm32CompClauseWideToAnsi(pRead, dwReadLen, 735 CS_StrW(pCS, CompReadStr), 736 pReadNew, cbReadNew, uCodePage); 737 } 738 else 739 { 740 cbReadNew = Imm32CompClauseAnsiToWide(pRead, dwReadLen, CS_StrA(pCS, CompReadStr), 741 NULL, 0, uCodePage); 742 pReadNew = ImmLocalAlloc(0, cbReadNew); 743 if (IS_NULL_UNEXPECTEDLY(pReadNew)) 744 goto Quit; 745 746 Imm32CompClauseAnsiToWide(pRead, dwReadLen, CS_StrA(pCS, CompReadStr), 747 pReadNew, cbReadNew, uCodePage); 748 } 749 } 750 break; 751 752 case SCS_SETRECONVERTSTRING: case SCS_QUERYRECONVERTSTRING: 753 { 754 if (pComp) 755 { 756 if (bAnsiClient) 757 { 758 cbCompNew = Imm32ReconvertAnsiFromWide(NULL, pComp, uCodePage); 759 pCompNew = ImmLocalAlloc(0, cbCompNew); 760 if (IS_NULL_UNEXPECTEDLY(pCompNew)) 761 goto Quit; 762 763 pRS = pCompNew; 764 pRS->dwSize = cbCompNew; 765 pRS->dwVersion = 0; 766 Imm32ReconvertAnsiFromWide(pRS, pComp, uCodePage); 767 } 768 else 769 { 770 cbCompNew = Imm32ReconvertWideFromAnsi(NULL, pComp, uCodePage); 771 pCompNew = ImmLocalAlloc(0, cbCompNew); 772 if (IS_NULL_UNEXPECTEDLY(pCompNew)) 773 goto Quit; 774 775 pRS = pCompNew; 776 pRS->dwSize = cbCompNew; 777 pRS->dwVersion = 0; 778 Imm32ReconvertWideFromAnsi(pRS, pComp, uCodePage); 779 } 780 } 781 782 if (pRead) 783 { 784 if (bAnsiClient) 785 { 786 cbReadNew = Imm32ReconvertAnsiFromWide(NULL, pRead, uCodePage); 787 pReadNew = ImmLocalAlloc(0, cbReadNew); 788 if (IS_NULL_UNEXPECTEDLY(pReadNew)) 789 goto Quit; 790 791 pRS = pReadNew; 792 pRS->dwSize = cbReadNew; 793 pRS->dwVersion = 0; 794 Imm32ReconvertAnsiFromWide(pRS, pRead, uCodePage); 795 } 796 else 797 { 798 cbReadNew = Imm32ReconvertWideFromAnsi(NULL, pRead, uCodePage); 799 pReadNew = ImmLocalAlloc(0, cbReadNew); 800 if (IS_NULL_UNEXPECTEDLY(pReadNew)) 801 goto Quit; 802 803 pRS = pReadNew; 804 pRS->dwSize = cbReadNew; 805 pRS->dwVersion = 0; 806 Imm32ReconvertWideFromAnsi(pRS, pRead, uCodePage); 807 } 808 } 809 break; 810 } 811 } 812 813 ImmUnlockIMCC(pIC->hCompStr); 814 pCS = NULL; 815 ImmUnlockIMC(hIMC); 816 pIC = NULL; 817 818 ret = pImeDpi->ImeSetCompositionString(hIMC, dwIndex, pCompNew, cbCompNew, 819 pReadNew, cbReadNew); 820 821 if (dwIndex == SCS_QUERYRECONVERTSTRING) 822 { 823 if (pComp) 824 { 825 if (bAnsiClient) 826 ret = Imm32ReconvertWideFromAnsi(pComp, pCompNew, uCodePage); 827 else 828 ret = Imm32ReconvertAnsiFromWide(pComp, pCompNew, uCodePage); 829 } 830 831 if (pRead) 832 { 833 if (bAnsiClient) 834 ret = Imm32ReconvertWideFromAnsi(pRead, pReadNew, uCodePage); 835 else 836 ret = Imm32ReconvertAnsiFromWide(pRead, pReadNew, uCodePage); 837 } 838 } 839 840 Quit: 841 if (pCS) 842 ImmUnlockIMCC(pIC->hCompStr); 843 if (pIC) 844 ImmUnlockIMC(hIMC); 845 ImmLocalFree(pCompNew); 846 ImmLocalFree(pReadNew); 847 ImmUnlockImeDpi(pImeDpi); 848 TRACE("ret: %d\n", ret); 849 return ret; 850 } 851 852 /*********************************************************************** 853 * ImmGetCompositionStringA (IMM32.@) 854 */ 855 LONG WINAPI ImmGetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen) 856 { 857 LONG ret = 0; 858 LPINPUTCONTEXT pIC; 859 PCLIENTIMC pClientImc; 860 LPCOMPOSITIONSTRING pCS; 861 BOOL bAnsiClient; 862 UINT uCodePage; 863 864 TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen); 865 866 if (dwBufLen && IS_NULL_UNEXPECTEDLY(lpBuf)) 867 return 0; 868 869 pClientImc = ImmLockClientImc(hIMC); 870 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 871 return 0; 872 873 bAnsiClient = !(pClientImc->dwFlags & CLIENTIMC_WIDE); 874 uCodePage = pClientImc->uCodePage; 875 ImmUnlockClientImc(pClientImc); 876 877 pIC = ImmLockIMC(hIMC); 878 if (IS_NULL_UNEXPECTEDLY(pIC)) 879 return 0; 880 881 pCS = ImmLockIMCC(pIC->hCompStr); 882 if (IS_NULL_UNEXPECTEDLY(pCS)) 883 { 884 ImmUnlockIMC(hIMC); 885 return 0; 886 } 887 888 ret = Imm32GetCompStrA(hIMC, pCS, dwIndex, lpBuf, dwBufLen, bAnsiClient, uCodePage); 889 ImmUnlockIMCC(pIC->hCompStr); 890 ImmUnlockIMC(hIMC); 891 TRACE("ret: %ld\n", ret); 892 return ret; 893 } 894 895 /*********************************************************************** 896 * ImmGetCompositionStringW (IMM32.@) 897 */ 898 LONG WINAPI ImmGetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen) 899 { 900 LONG ret = 0; 901 LPINPUTCONTEXT pIC; 902 PCLIENTIMC pClientImc; 903 LPCOMPOSITIONSTRING pCS; 904 BOOL bAnsiClient; 905 UINT uCodePage; 906 907 TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen); 908 909 if (dwBufLen && IS_NULL_UNEXPECTEDLY(lpBuf)) 910 return 0; 911 912 pClientImc = ImmLockClientImc(hIMC); 913 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 914 return 0; 915 916 bAnsiClient = !(pClientImc->dwFlags & CLIENTIMC_WIDE); 917 uCodePage = pClientImc->uCodePage; 918 ImmUnlockClientImc(pClientImc); 919 920 pIC = ImmLockIMC(hIMC); 921 if (IS_NULL_UNEXPECTEDLY(pIC)) 922 return 0; 923 924 pCS = ImmLockIMCC(pIC->hCompStr); 925 if (IS_NULL_UNEXPECTEDLY(pCS)) 926 { 927 ImmUnlockIMC(hIMC); 928 return 0; 929 } 930 931 ret = Imm32GetCompStrW(hIMC, pCS, dwIndex, lpBuf, dwBufLen, bAnsiClient, uCodePage); 932 ImmUnlockIMCC(pIC->hCompStr); 933 ImmUnlockIMC(hIMC); 934 TRACE("ret: %ld\n", ret); 935 return ret; 936 } 937 938 /*********************************************************************** 939 * ImmSetCompositionStringA (IMM32.@) 940 */ 941 BOOL WINAPI 942 ImmSetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen, 943 LPVOID lpRead, DWORD dwReadLen) 944 { 945 TRACE("(%p, %lu, %p, %lu, %p, %lu)\n", 946 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); 947 return ImmSetCompositionStringAW(hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen, TRUE); 948 } 949 950 /*********************************************************************** 951 * ImmSetCompositionStringW (IMM32.@) 952 */ 953 BOOL WINAPI 954 ImmSetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen, 955 LPVOID lpRead, DWORD dwReadLen) 956 { 957 TRACE("(%p, %lu, %p, %lu, %p, %lu)\n", 958 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); 959 return ImmSetCompositionStringAW(hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen, FALSE); 960 } 961