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, 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 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 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 */ 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 */ 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 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 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