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 (!pIC) 27 return FALSE; 28 29 pCS = ImmLockIMCC(pIC->hCompStr); 30 if (!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 LONG APIENTRY 218 Imm32GetCompStrA(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("TODO:\n"); 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, CompStr), 292 CS_SizeW(pCS, CompStr), 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, CompStr), 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, CompStr), 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, CompStr), 355 lpBuf, dwBufLen, uCodePage); 356 break; 357 358 default: 359 FIXME("TODO:\n"); 360 return IMM_ERROR_GENERAL; 361 } 362 } 363 364 return dwBufLen; 365 } 366 367 LONG APIENTRY 368 Imm32GetCompStrW(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, CompStr), CS_SizeA(pCS, CompStr), 385 lpBuf, dwBufLen, uCodePage); 386 break; 387 388 case GCS_COMPREADCLAUSE: 389 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, CompReadClause), 390 CS_Size(pCS, CompReadClause), 391 CS_StrA(pCS, CompStr), 392 lpBuf, dwBufLen, uCodePage); 393 break; 394 395 case GCS_COMPSTR: 396 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, CompStr), 397 CS_SizeA(pCS, CompStr), 398 lpBuf, dwBufLen, uCodePage); 399 break; 400 401 case GCS_COMPATTR: 402 dwBufLen = Imm32CompAttrAnsiToWide(CS_Attr(pCS, CompAttr), 403 CS_Size(pCS, CompAttr), 404 CS_StrA(pCS, CompStr), CS_SizeA(pCS, CompStr), 405 lpBuf, dwBufLen, uCodePage); 406 break; 407 408 case GCS_COMPCLAUSE: 409 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, CompClause), 410 CS_Size(pCS, CompClause), 411 CS_StrA(pCS, CompStr), 412 lpBuf, dwBufLen, uCodePage); 413 break; 414 415 case GCS_CURSORPOS: 416 dwBufLen = IchWideFromAnsi(pCS->dwCursorPos, CS_StrA(pCS, CompStr), uCodePage); 417 break; 418 419 case GCS_DELTASTART: 420 dwBufLen = IchWideFromAnsi(pCS->dwDeltaStart, CS_StrA(pCS, CompStr), uCodePage); 421 break; 422 423 case GCS_RESULTREADSTR: 424 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, ResultReadStr), 425 CS_SizeA(pCS, ResultReadStr), 426 lpBuf, dwBufLen, uCodePage); 427 break; 428 429 case GCS_RESULTREADCLAUSE: 430 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, ResultReadClause), 431 CS_Size(pCS, ResultReadClause), 432 CS_StrA(pCS, CompStr), 433 lpBuf, dwBufLen, uCodePage); 434 break; 435 436 case GCS_RESULTSTR: 437 dwBufLen = Imm32CompStrAnsiToWide(CS_StrA(pCS, ResultStr), 438 CS_SizeA(pCS, ResultStr), 439 lpBuf, dwBufLen, uCodePage); 440 break; 441 442 case GCS_RESULTCLAUSE: 443 dwBufLen = Imm32CompClauseAnsiToWide(CS_Clause(pCS, ResultClause), 444 CS_Size(pCS, ResultClause), 445 CS_StrA(pCS, CompStr), 446 lpBuf, dwBufLen, uCodePage); 447 break; 448 449 default: 450 FIXME("TODO:\n"); 451 return IMM_ERROR_GENERAL; 452 } 453 } 454 else /* !bAnsiClient */ 455 { 456 switch (dwIndex) 457 { 458 case GCS_COMPREADSTR: 459 CS_DoStrW(pCS, CompReadStr); 460 break; 461 462 case GCS_COMPREADATTR: 463 CS_DoAttr(pCS, CompReadAttr); 464 break; 465 466 case GCS_COMPREADCLAUSE: 467 CS_DoClause(pCS, CompReadClause); 468 break; 469 470 case GCS_COMPSTR: 471 CS_DoStrW(pCS, CompStr); 472 break; 473 474 case GCS_COMPATTR: 475 CS_DoAttr(pCS, CompAttr); 476 break; 477 478 case GCS_COMPCLAUSE: 479 CS_DoClause(pCS, CompClause); 480 break; 481 482 case GCS_CURSORPOS: 483 dwBufLen = pCS->dwCursorPos; 484 break; 485 486 case GCS_DELTASTART: 487 dwBufLen = pCS->dwDeltaStart; 488 break; 489 490 case GCS_RESULTREADSTR: 491 CS_DoStrW(pCS, ResultReadStr); 492 break; 493 494 case GCS_RESULTREADCLAUSE: 495 CS_DoClause(pCS, ResultReadClause); 496 break; 497 498 case GCS_RESULTSTR: 499 CS_DoStrW(pCS, ResultStr); 500 break; 501 502 case GCS_RESULTCLAUSE: 503 CS_DoClause(pCS, ResultClause); 504 break; 505 506 default: 507 FIXME("TODO:\n"); 508 return IMM_ERROR_GENERAL; 509 } 510 } 511 512 return dwBufLen; 513 } 514 515 // Win: ImmSetCompositionStringWorker 516 BOOL APIENTRY 517 ImmSetCompositionStringAW(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 = (DWORD)NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID); 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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 = ImmLocalAlloc(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 ImmLocalFree(pCompNew); 840 ImmLocalFree(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 ImmSetCompositionStringAW(hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen, TRUE); 939 } 940 941 /*********************************************************************** 942 * ImmSetCompositionStringW (IMM32.@) 943 */ 944 BOOL WINAPI 945 ImmSetCompositionStringW(HIMC hIMC, DWORD dwIndex, LPVOID lpComp, DWORD dwCompLen, 946 LPVOID lpRead, DWORD dwReadLen) 947 { 948 TRACE("(%p, %lu, %p, %lu, %p, %lu)\n", 949 hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen); 950 return ImmSetCompositionStringAW(hIMC, dwIndex, lpComp, dwCompLen, lpRead, dwReadLen, FALSE); 951 } 952