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 Oleg Dubinskiy <oleg.dubinskij2013@yandex.ua> 10 * Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 11 */ 12 13 #include "precomp.h" 14 15 WINE_DEFAULT_DEBUG_CHANNEL(imm); 16 17 BOOL APIENTRY 18 Imm32OpenICAndCS(HIMC hIMC, LPINPUTCONTEXT *ppIC, LPCOMPOSITIONSTRING *ppCS) 19 { 20 LPINPUTCONTEXT pIC; 21 LPCOMPOSITIONSTRING pCS; 22 23 *ppIC = NULL; 24 *ppCS = NULL; 25 26 pIC = ImmLockIMC(hIMC); 27 if (!pIC) 28 return FALSE; 29 30 pCS = ImmLockIMCC(pIC->hCompStr); 31 if (!pCS) 32 { 33 ImmUnlockIMC(hIMC); 34 return FALSE; 35 } 36 37 *ppIC = pIC; 38 *ppCS = pCS; 39 return TRUE; 40 } 41 42 static inline LONG APIENTRY 43 Imm32CompStrAnsiToWide(LPCSTR psz, DWORD cb, LPWSTR lpBuf, DWORD dwBufLen, UINT uCodePage) 44 { 45 DWORD ret = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, psz, cb / sizeof(CHAR), 46 lpBuf, dwBufLen / sizeof(WCHAR)); 47 if (lpBuf && (ret + 1) * sizeof(WCHAR) <= dwBufLen) 48 lpBuf[ret] = 0; 49 return ret * sizeof(WCHAR); 50 } 51 52 static inline LONG APIENTRY 53 Imm32CompStrWideToAnsi(LPCWSTR psz, DWORD cb, LPSTR lpBuf, DWORD dwBufLen, UINT uCodePage) 54 { 55 DWORD ret = WideCharToMultiByte(uCodePage, 0, psz, cb / sizeof(WCHAR), 56 lpBuf, dwBufLen / sizeof(CHAR), NULL, NULL); 57 if (lpBuf && (ret + 1) * sizeof(CHAR) <= dwBufLen) 58 lpBuf[ret] = 0; 59 return ret * sizeof(CHAR); 60 } 61 62 static INT APIENTRY 63 Imm32CompAttrWideToAnsi(const BYTE *src, INT src_len, LPCWSTR text, 64 INT str_len, LPBYTE dst, INT dst_len, UINT uCodePage) 65 { 66 INT rc; 67 INT i, j = 0, k = 0, len; 68 69 if (!src_len) 70 return 0; 71 72 str_len /= sizeof(WCHAR); 73 rc = WideCharToMultiByte(uCodePage, 0, text, str_len, NULL, 0, NULL, NULL); 74 75 if (dst_len) 76 { 77 if (dst_len > rc) 78 dst_len = rc; 79 80 for (i = 0; i < str_len; ++i, ++k) 81 { 82 len = WideCharToMultiByte(uCodePage, 0, &text[i], 1, NULL, 0, NULL, NULL); 83 for (; len > 0; --len) 84 { 85 dst[j++] = src[k]; 86 87 if (dst_len <= j) 88 goto end; 89 } 90 } 91 end: 92 rc = j; 93 } 94 95 return rc * sizeof(BYTE); 96 } 97 98 static INT APIENTRY 99 Imm32CompAttrAnsiToWide(const BYTE *src, INT src_len, LPCSTR text, 100 INT str_len, LPBYTE dst, INT dst_len, UINT uCodePage) 101 { 102 INT rc; 103 INT i, j = 0; 104 105 if (!src_len) 106 return 0; 107 108 str_len /= sizeof(CHAR); 109 rc = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, text, str_len, NULL, 0); 110 111 if (dst_len) 112 { 113 if (dst_len > rc) 114 dst_len = rc; 115 116 for (i = 0; i < str_len; ++i) 117 { 118 if (IsDBCSLeadByteEx(uCodePage, text[i]) && text[i + 1]) 119 continue; 120 121 dst[j++] = src[i]; 122 123 if (dst_len <= j) 124 break; 125 } 126 127 rc = j; 128 } 129 130 return rc * sizeof(BYTE); 131 } 132 133 static INT APIENTRY 134 Imm32CompClauseAnsiToWide(const DWORD *source, INT slen, LPCSTR text, 135 LPDWORD target, INT tlen, UINT uCodePage) 136 { 137 INT rc, i; 138 139 if (!slen) 140 return 0; 141 142 if (tlen) 143 { 144 if (tlen > slen) 145 tlen = slen; 146 147 tlen /= sizeof(DWORD); 148 149 for (i = 0; i < tlen; ++i) 150 { 151 target[i] = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, text, source[i], NULL, 0); 152 } 153 154 rc = sizeof(DWORD) * i; 155 } 156 else 157 { 158 rc = slen; 159 } 160 161 return rc; 162 } 163 164 static INT APIENTRY 165 Imm32CompClauseWideToAnsi(const DWORD *source, INT slen, LPCWSTR text, 166 LPDWORD target, INT tlen, UINT uCodePage) 167 { 168 INT rc, i; 169 170 if (!slen) 171 return 0; 172 173 if (tlen) 174 { 175 if (tlen > slen) 176 tlen = slen; 177 178 tlen /= sizeof(DWORD); 179 180 for (i = 0; i < tlen; ++i) 181 { 182 target[i] = WideCharToMultiByte(uCodePage, 0, text, source[i], NULL, 0, NULL, NULL); 183 } 184 185 rc = sizeof(DWORD) * i; 186 } 187 else 188 { 189 rc = slen; 190 } 191 192 return rc; 193 } 194 195 #define CS_StrA(pCS, Name) ((LPCSTR)(pCS) + (pCS)->dw##Name##Offset) 196 #define CS_StrW(pCS, Name) ((LPCWSTR)CS_StrA(pCS, Name)) 197 #define CS_Attr(pCS, Name) ((const BYTE *)CS_StrA(pCS, Name)) 198 #define CS_Clause(pCS, Name) ((const DWORD *)CS_StrA(pCS, Name)) 199 #define CS_Size(pCS, Name) ((pCS)->dw##Name##Len) 200 #define CS_SizeA(pCS, Name) (CS_Size(pCS, Name) * sizeof(CHAR)) 201 #define CS_SizeW(pCS, Name) (CS_Size(pCS, Name) * sizeof(WCHAR)) 202 203 #define CS_DoStr(pCS, Name, AorW) do { \ 204 if (dwBufLen == 0) { \ 205 dwBufLen = CS_Size##AorW((pCS), Name); \ 206 } else { \ 207 if (dwBufLen > CS_Size##AorW((pCS), Name)) \ 208 dwBufLen = CS_Size##AorW((pCS), Name); \ 209 RtlCopyMemory(lpBuf, CS_Str##AorW((pCS), Name), dwBufLen); \ 210 } \ 211 } while (0) 212 213 #define CS_DoStrA(pCS, Name) CS_DoStr(pCS, Name, A) 214 #define CS_DoStrW(pCS, Name) CS_DoStr(pCS, Name, W) 215 #define CS_DoAttr CS_DoStrA 216 #define CS_DoClause CS_DoStrA 217 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("TODO:\n"); 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("TODO:\n"); 361 return IMM_ERROR_GENERAL; 362 } 363 } 364 365 return dwBufLen; 366 } 367 368 LONG APIENTRY 369 Imm32GetCompStrW(HIMC hIMC, const COMPOSITIONSTRING *pCS, DWORD dwIndex, 370 LPVOID lpBuf, DWORD dwBufLen, BOOL bAnsiClient, UINT uCodePage) 371 { 372 if (bAnsiClient) 373 { 374 switch (dwIndex) 375 { 376 case GCS_COMPREADSTR: 377 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, CompReadStr), 378 CS_SizeA(pCS, CompReadStr), 379 lpBuf, dwBufLen, uCodePage); 380 break; 381 382 case GCS_COMPREADATTR: 383 dwBufLen = Imm32CompAttrAnsiToWide(CS_Attr(pCS, CompReadAttr), 384 CS_Size(pCS, CompReadAttr), 385 CS_StrA(pCS, CompStr), CS_SizeA(pCS, CompStr), 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, CompStr), 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, CompStr), 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, CompStr), 447 lpBuf, dwBufLen, uCodePage); 448 break; 449 450 default: 451 FIXME("TODO:\n"); 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("TODO:\n"); 509 return IMM_ERROR_GENERAL; 510 } 511 } 512 513 return dwBufLen; 514 } 515 516 BOOL APIENTRY 517 Imm32SetCompositionStringAW(HIMC hIMC, DWORD dwIndex, LPVOID pComp, DWORD dwCompLen, 518 LPVOID pRead, DWORD dwReadLen, BOOL bAnsiAPI) 519 { 520 BOOL ret = FALSE, bAnsiClient; 521 LPVOID pCompNew = NULL, pReadNew = NULL; 522 DWORD dwThreadId, cbCompNew = 0, cbReadNew = 0; 523 LPINPUTCONTEXT pIC; 524 LPCOMPOSITIONSTRING pCS; 525 HKL hKL; 526 PIMEDPI pImeDpi; 527 UINT uCodePage; 528 LPRECONVERTSTRING pRS; 529 530 dwThreadId = NtUserQueryInputContext(hIMC, 1); 531 if (dwThreadId != GetCurrentThreadId()) 532 return FALSE; 533 534 hKL = GetKeyboardLayout(dwThreadId); 535 pImeDpi = ImmLockImeDpi(hKL); 536 if (!pImeDpi) 537 return FALSE; 538 539 uCodePage = pImeDpi->uCodePage; 540 bAnsiClient = !ImeDpi_IsUnicode(pImeDpi); 541 542 switch (dwIndex) 543 { 544 case SCS_SETSTR: case SCS_CHANGEATTR: case SCS_CHANGECLAUSE: 545 break; 546 547 case SCS_SETRECONVERTSTRING: case SCS_QUERYRECONVERTSTRING: 548 if (pImeDpi->ImeInfo.fdwSCSCaps & SCS_CAP_SETRECONVERTSTRING) 549 break; 550 /* FALL THROUGH */ 551 default: 552 ImmUnlockImeDpi(pImeDpi); 553 return FALSE; 554 } 555 556 if (bAnsiAPI == bAnsiClient || (!pComp && !pRead)) 557 { 558 ret = pImeDpi->ImeSetCompositionString(hIMC, dwIndex, pComp, dwCompLen, 559 pRead, dwReadLen); 560 ImmUnlockImeDpi(pImeDpi); 561 return ret; 562 } 563 564 if (!Imm32OpenICAndCS(hIMC, &pIC, &pCS)) 565 { 566 ImmUnlockImeDpi(pImeDpi); 567 return FALSE; 568 } 569 570 /* 571 * This code is really too complicated. But I cannot simplify. 572 * It converts like (pComp, dwCompLen) --> (pCompNew, cbCompNew) and 573 * (pRead, dwReadLen) --> (pReadNew, cbReadNew). 574 * (1) Check bAnsiClient, (2) Get the size, (3) Allocate a buffer for conversion, 575 * (4) Store converted data into the buffer. 576 */ 577 switch (dwIndex) 578 { 579 case SCS_SETSTR: 580 if (pComp) 581 { 582 if (bAnsiClient) 583 { 584 cbCompNew = Imm32CompStrWideToAnsi(pComp, dwCompLen, NULL, 0, uCodePage); 585 pCompNew = Imm32HeapAlloc(0, cbCompNew); 586 if (!pCompNew) 587 goto Quit; 588 589 Imm32CompStrWideToAnsi(pComp, dwCompLen, pCompNew, cbCompNew, uCodePage); 590 } 591 else 592 { 593 cbCompNew = Imm32CompStrAnsiToWide(pComp, dwCompLen, NULL, 0, uCodePage); 594 pCompNew = Imm32HeapAlloc(0, cbCompNew); 595 if (!pCompNew) 596 goto Quit; 597 598 Imm32CompStrAnsiToWide(pComp, dwCompLen, pCompNew, cbCompNew, uCodePage); 599 } 600 } 601 602 if (pRead) 603 { 604 if (bAnsiClient) 605 { 606 cbReadNew = Imm32CompStrWideToAnsi(pRead, dwReadLen, NULL, 0, uCodePage); 607 pReadNew = Imm32HeapAlloc(0, cbReadNew); 608 if (!pReadNew) 609 goto Quit; 610 611 Imm32CompStrWideToAnsi(pRead, dwReadLen, pReadNew, cbReadNew, uCodePage); 612 } 613 else 614 { 615 cbReadNew = Imm32CompStrAnsiToWide(pRead, dwReadLen, NULL, 0, uCodePage); 616 pReadNew = Imm32HeapAlloc(0, cbReadNew); 617 if (!pReadNew) 618 goto Quit; 619 620 Imm32CompStrAnsiToWide(pRead, dwReadLen, pReadNew, cbReadNew, uCodePage); 621 } 622 } 623 break; 624 625 case SCS_CHANGEATTR: 626 if (pComp) 627 { 628 if (bAnsiClient) 629 { 630 cbCompNew = Imm32CompAttrWideToAnsi(pComp, dwCompLen, 631 CS_StrW(pCS, CompStr), 632 CS_SizeW(pCS, CompStr), 633 NULL, 0, uCodePage); 634 pCompNew = Imm32HeapAlloc(0, cbCompNew); 635 if (!pCompNew) 636 goto Quit; 637 638 Imm32CompAttrWideToAnsi(pComp, dwCompLen, 639 CS_StrW(pCS, CompStr), CS_SizeW(pCS, CompStr), 640 pCompNew, cbCompNew, uCodePage); 641 } 642 else 643 { 644 cbCompNew = Imm32CompAttrAnsiToWide(pComp, dwCompLen, 645 CS_StrA(pCS, CompStr), 646 CS_SizeA(pCS, CompStr), 647 NULL, 0, uCodePage); 648 pCompNew = Imm32HeapAlloc(0, cbCompNew); 649 if (!pCompNew) 650 goto Quit; 651 652 Imm32CompAttrAnsiToWide(pComp, dwCompLen, 653 CS_StrA(pCS, CompStr), CS_SizeA(pCS, CompStr), 654 pCompNew, cbCompNew, uCodePage); 655 } 656 } 657 658 if (pRead) 659 { 660 if (bAnsiClient) 661 { 662 cbReadNew = Imm32CompAttrWideToAnsi(pRead, dwReadLen, 663 CS_StrW(pCS, CompReadStr), 664 CS_SizeW(pCS, CompReadStr), 665 NULL, 0, uCodePage); 666 pReadNew = Imm32HeapAlloc(0, cbReadNew); 667 if (!pReadNew) 668 goto Quit; 669 670 Imm32CompAttrWideToAnsi(pRead, dwReadLen, 671 CS_StrW(pCS, CompReadStr), CS_SizeW(pCS, CompReadStr), 672 pReadNew, cbReadNew, uCodePage); 673 } 674 else 675 { 676 cbReadNew = Imm32CompAttrAnsiToWide(pRead, dwReadLen, 677 CS_StrA(pCS, CompReadStr), 678 CS_SizeA(pCS, CompReadStr), 679 NULL, 0, uCodePage); 680 pReadNew = Imm32HeapAlloc(0, cbReadNew); 681 if (!pReadNew) 682 goto Quit; 683 684 Imm32CompAttrAnsiToWide(pRead, dwReadLen, 685 CS_StrA(pCS, CompReadStr), CS_SizeA(pCS, CompReadStr), 686 pReadNew, cbReadNew, uCodePage); 687 } 688 } 689 break; 690 691 case SCS_CHANGECLAUSE: 692 if (pComp) 693 { 694 if (bAnsiClient) 695 { 696 cbCompNew = Imm32CompClauseWideToAnsi(pComp, dwCompLen, CS_StrW(pCS, CompStr), 697 NULL, 0, uCodePage); 698 pCompNew = Imm32HeapAlloc(0, cbCompNew); 699 if (!pCompNew) 700 goto Quit; 701 702 Imm32CompClauseWideToAnsi(pComp, dwCompLen, CS_StrW(pCS, CompStr), 703 pCompNew, cbCompNew, uCodePage); 704 } 705 else 706 { 707 cbCompNew = Imm32CompClauseAnsiToWide(pComp, dwCompLen, CS_StrA(pCS, CompStr), 708 NULL, 0, uCodePage); 709 pCompNew = Imm32HeapAlloc(0, cbCompNew); 710 if (!pCompNew) 711 goto Quit; 712 713 Imm32CompClauseAnsiToWide(pComp, dwCompLen, CS_StrA(pCS, CompStr), 714 pCompNew, cbCompNew, uCodePage); 715 } 716 } 717 718 if (pRead) 719 { 720 if (bAnsiClient) 721 { 722 cbReadNew = Imm32CompClauseWideToAnsi(pRead, dwReadLen, CS_StrW(pCS, CompReadStr), 723 NULL, 0, uCodePage); 724 pReadNew = Imm32HeapAlloc(0, cbReadNew); 725 if (!pReadNew) 726 goto Quit; 727 728 Imm32CompClauseWideToAnsi(pRead, dwReadLen, 729 CS_StrW(pCS, CompReadStr), 730 pReadNew, cbReadNew, uCodePage); 731 } 732 else 733 { 734 cbReadNew = Imm32CompClauseAnsiToWide(pRead, dwReadLen, CS_StrA(pCS, CompReadStr), 735 NULL, 0, uCodePage); 736 pReadNew = Imm32HeapAlloc(0, cbReadNew); 737 if (!pReadNew) 738 goto Quit; 739 740 Imm32CompClauseAnsiToWide(pRead, dwReadLen, CS_StrA(pCS, CompReadStr), 741 pReadNew, cbReadNew, uCodePage); 742 } 743 } 744 break; 745 746 case SCS_SETRECONVERTSTRING: case SCS_QUERYRECONVERTSTRING: 747 { 748 if (pComp) 749 { 750 if (bAnsiClient) 751 { 752 cbCompNew = Imm32ReconvertAnsiFromWide(NULL, pComp, uCodePage); 753 pCompNew = Imm32HeapAlloc(0, cbCompNew); 754 if (!pCompNew) 755 goto Quit; 756 757 pRS = pCompNew; 758 pRS->dwSize = cbCompNew; 759 pRS->dwVersion = 0; 760 Imm32ReconvertAnsiFromWide(pRS, pComp, uCodePage); 761 } 762 else 763 { 764 cbCompNew = Imm32ReconvertWideFromAnsi(NULL, pComp, uCodePage); 765 pCompNew = Imm32HeapAlloc(0, cbCompNew); 766 if (!pCompNew) 767 goto Quit; 768 769 pRS = pCompNew; 770 pRS->dwSize = cbCompNew; 771 pRS->dwVersion = 0; 772 Imm32ReconvertWideFromAnsi(pRS, pComp, uCodePage); 773 } 774 } 775 776 if (pRead) 777 { 778 if (bAnsiClient) 779 { 780 cbReadNew = Imm32ReconvertAnsiFromWide(NULL, pRead, uCodePage); 781 pReadNew = Imm32HeapAlloc(0, cbReadNew); 782 if (!pReadNew) 783 goto Quit; 784 785 pRS = pReadNew; 786 pRS->dwSize = cbReadNew; 787 pRS->dwVersion = 0; 788 Imm32ReconvertAnsiFromWide(pRS, pRead, uCodePage); 789 } 790 else 791 { 792 cbReadNew = Imm32ReconvertWideFromAnsi(NULL, pRead, uCodePage); 793 pReadNew = Imm32HeapAlloc(0, cbReadNew); 794 if (!pReadNew) 795 goto Quit; 796 797 pRS = pReadNew; 798 pRS->dwSize = cbReadNew; 799 pRS->dwVersion = 0; 800 Imm32ReconvertWideFromAnsi(pRS, pRead, uCodePage); 801 } 802 } 803 break; 804 } 805 } 806 807 ImmUnlockIMCC(pIC->hCompStr); 808 pCS = NULL; 809 ImmUnlockIMC(hIMC); 810 pIC = NULL; 811 812 ret = pImeDpi->ImeSetCompositionString(hIMC, dwIndex, pCompNew, cbCompNew, 813 pReadNew, cbReadNew); 814 815 if (dwIndex == SCS_QUERYRECONVERTSTRING) 816 { 817 if (pComp) 818 { 819 if (bAnsiClient) 820 ret = Imm32ReconvertWideFromAnsi(pComp, pCompNew, uCodePage); 821 else 822 ret = Imm32ReconvertAnsiFromWide(pComp, pCompNew, uCodePage); 823 } 824 825 if (pRead) 826 { 827 if (bAnsiClient) 828 ret = Imm32ReconvertWideFromAnsi(pRead, pReadNew, uCodePage); 829 else 830 ret = Imm32ReconvertAnsiFromWide(pRead, pReadNew, uCodePage); 831 } 832 } 833 834 Quit: 835 if (pCS) 836 ImmUnlockIMCC(pIC->hCompStr); 837 if (pIC) 838 ImmUnlockIMC(hIMC); 839 Imm32HeapFree(pCompNew); 840 Imm32HeapFree(pReadNew); 841 ImmUnlockImeDpi(pImeDpi); 842 return ret; 843 } 844 845 /*********************************************************************** 846 * ImmGetCompositionStringA (IMM32.@) 847 */ 848 LONG WINAPI ImmGetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen) 849 { 850 LONG ret = 0; 851 LPINPUTCONTEXT pIC; 852 PCLIENTIMC pClientImc; 853 LPCOMPOSITIONSTRING pCS; 854 BOOL bAnsiClient; 855 UINT uCodePage; 856 857 TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen); 858 859 if (dwBufLen && !lpBuf) 860 return 0; 861 862 pClientImc = ImmLockClientImc(hIMC); 863 if (!pClientImc) 864 return 0; 865 866 bAnsiClient = !(pClientImc->dwFlags & CLIENTIMC_WIDE); 867 uCodePage = pClientImc->uCodePage; 868 ImmUnlockClientImc(pClientImc); 869 870 pIC = ImmLockIMC(hIMC); 871 if (!pIC) 872 return 0; 873 874 pCS = ImmLockIMCC(pIC->hCompStr); 875 if (!pCS) 876 { 877 ImmUnlockIMC(hIMC); 878 return 0; 879 } 880 881 ret = Imm32GetCompStrA(hIMC, pCS, dwIndex, lpBuf, dwBufLen, bAnsiClient, uCodePage); 882 ImmUnlockIMCC(pIC->hCompStr); 883 ImmUnlockIMC(hIMC); 884 return ret; 885 } 886 887 /*********************************************************************** 888 * ImmGetCompositionStringW (IMM32.@) 889 */ 890 LONG WINAPI ImmGetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpBuf, DWORD dwBufLen) 891 { 892 LONG ret = 0; 893 LPINPUTCONTEXT pIC; 894 PCLIENTIMC pClientImc; 895 LPCOMPOSITIONSTRING pCS; 896 BOOL bAnsiClient; 897 UINT uCodePage; 898 899 TRACE("(%p, %lu, %p, %lu)\n", hIMC, dwIndex, lpBuf, dwBufLen); 900 901 if (dwBufLen && !lpBuf) 902 return 0; 903 904 pClientImc = ImmLockClientImc(hIMC); 905 if (!pClientImc) 906 return 0; 907 908 bAnsiClient = !(pClientImc->dwFlags & CLIENTIMC_WIDE); 909 uCodePage = pClientImc->uCodePage; 910 ImmUnlockClientImc(pClientImc); 911 912 pIC = ImmLockIMC(hIMC); 913 if (!pIC) 914 return 0; 915 916 pCS = ImmLockIMCC(pIC->hCompStr); 917 if (!pCS) 918 { 919 ImmUnlockIMC(hIMC); 920 return 0; 921 } 922 923 ret = Imm32GetCompStrW(hIMC, pCS, dwIndex, lpBuf, dwBufLen, bAnsiClient, uCodePage); 924 ImmUnlockIMCC(pIC->hCompStr); 925 ImmUnlockIMC(hIMC); 926 return ret; 927 } 928 929 /*********************************************************************** 930 * ImmSetCompositionStringA (IMM32.@) 931 */ 932 BOOL WINAPI 933 ImmSetCompositionStringA(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen, 934 LPVOID lpRead, DWORD dwReadLen) 935 { 936 TRACE("(%p, %lu, %p, %lu, %p, %lu)\n", 937 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); 938 return Imm32SetCompositionStringAW(hIMC, dwIndex, lpComp, dwCompLen, 939 lpRead, dwReadLen, TRUE); 940 } 941 942 /*********************************************************************** 943 * ImmSetCompositionStringW (IMM32.@) 944 */ 945 BOOL WINAPI 946 ImmSetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen, 947 LPVOID lpRead, DWORD dwReadLen) 948 { 949 TRACE("(%p, %lu, %p, %lu, %p, %lu)\n", 950 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); 951 return Imm32SetCompositionStringAW(hIMC, dwIndex, lpComp, dwCompLen, 952 lpRead, dwReadLen, FALSE); 953 } 954