return ImmEnumInputContext((bProcess ? -1 : 0), Imm32SendChangeProc, 0);
}
+VOID APIENTRY Imm32RequestError(DWORD dwError)
+{
+ FIXME("()\n");
+ SetLastError(dwError);
+}
+
+DWORD APIENTRY Imm32ReconvertSize(DWORD dwSize, BOOL bAnsi, BOOL bConvert)
+{
+ DWORD dwOffset;
+ if (dwSize < sizeof(RECONVERTSTRING))
+ return 0;
+ if (!bConvert)
+ return dwSize;
+ dwOffset = dwSize - sizeof(RECONVERTSTRING);
+ if (bAnsi)
+ dwOffset /= sizeof(WCHAR);
+ else
+ dwOffset *= sizeof(WCHAR);
+ return sizeof(RECONVERTSTRING) + dwOffset;
+}
+
+DWORD APIENTRY
+Imm32ConvertReconvert(LPRECONVERTSTRING pDest, const RECONVERTSTRING *pSrc, BOOL bAnsi,
+ UINT uCodePage)
+{
+ DWORD ret = sizeof(RECONVERTSTRING), cch0, cch1, cchDest;
+
+ if ((pSrc->dwVersion != 0) || (pDest->dwVersion != 0))
+ return 0;
+
+ pDest->dwStrOffset = sizeof(RECONVERTSTRING);
+
+ /*
+ * See RECONVERTSTRING structure:
+ * https://katahiromz.web.fc2.com/colony3rd/imehackerz/en/RECONVERTSTRING.html
+ *
+ * The dwCompStrOffset and dwTargetOffset members are the relative position of dwStrOffset.
+ * dwStrLen, dwCompStrLen, and dwTargetStrLen are the TCHAR count. dwStrOffset,
+ * dwCompStrOffset, and dwTargetStrOffset are the byte offset.
+ */
+ if (bAnsi) /* Ansi <-- Wide */
+ {
+ LPCWSTR pchSrc = (LPCWSTR)((LPCSTR)pSrc + pSrc->dwStrOffset);
+ LPSTR pchDest = (LPSTR)pDest + pDest->dwStrOffset;
+
+ cchDest = WideCharToMultiByte(uCodePage, 0, pchSrc, pSrc->dwStrLen,
+ pchDest, pSrc->dwStrLen, NULL, NULL);
+
+ /* dwCompStrOffset */
+ cch1 = pSrc->dwCompStrOffset / sizeof(WCHAR);
+ cch0 = IchAnsiFromWide(cch1, pchSrc, uCodePage);
+ pDest->dwCompStrOffset = cch0 * sizeof(CHAR);
+
+ /* dwCompStrLen */
+ cch0 = IchAnsiFromWide(cch1 + pSrc->dwCompStrLen, pchSrc, uCodePage);
+ pDest->dwCompStrLen = cch0 * sizeof(CHAR) - pDest->dwCompStrOffset;
+
+ /* dwTargetStrOffset */
+ cch1 = pSrc->dwTargetStrOffset / sizeof(WCHAR);
+ cch0 = IchAnsiFromWide(cch1, pchSrc, uCodePage);
+ pDest->dwTargetStrOffset = cch0 * sizeof(CHAR);
+
+ /* dwTargetStrLen */
+ cch0 = IchAnsiFromWide(cch1 + pSrc->dwTargetStrLen, pchSrc, uCodePage);
+ pDest->dwTargetStrLen = cch0 * sizeof(CHAR) - pDest->dwTargetStrOffset;
+
+ /* dwStrLen */
+ pDest->dwStrLen = cchDest;
+ pchDest[cchDest] = 0;
+
+ ret += (cchDest + 1) * sizeof(CHAR);
+ }
+ else /* Wide <-- Ansi */
+ {
+ LPCSTR pchSrc = (LPCSTR)pSrc + pSrc->dwStrOffset;
+ LPWSTR pchDest = (LPWSTR)((LPBYTE)pDest + pDest->dwStrOffset);
+
+ cchDest = MultiByteToWideChar(uCodePage, MB_PRECOMPOSED, pchSrc, pSrc->dwStrLen,
+ pchDest, pSrc->dwStrLen);
+
+ /* dwCompStrOffset */
+ cch0 = IchWideFromAnsi(pSrc->dwCompStrOffset, pchSrc, uCodePage);
+ pDest->dwCompStrOffset = cch0 * sizeof(WCHAR);
+
+ /* dwCompStrLen */
+ cch0 = IchWideFromAnsi(pSrc->dwCompStrOffset + pSrc->dwCompStrLen, pchSrc, uCodePage);
+ pDest->dwCompStrLen = (cch0 * sizeof(WCHAR) - pDest->dwCompStrOffset) / sizeof(WCHAR);
+
+ /* dwTargetStrOffset */
+ cch0 = IchWideFromAnsi(pSrc->dwTargetStrOffset, pchSrc, uCodePage);
+ pDest->dwTargetStrOffset = cch0 * sizeof(WCHAR);
+
+ /* dwTargetStrLen */
+ cch0 = IchWideFromAnsi(pSrc->dwTargetStrOffset + pSrc->dwTargetStrLen, pchSrc, uCodePage);
+ pDest->dwTargetStrLen = (cch0 * sizeof(WCHAR) - pSrc->dwTargetStrOffset) / sizeof(WCHAR);
+
+ /* dwStrLen */
+ pDest->dwStrLen = cchDest;
+ pchDest[cchDest] = 0;
+
+ ret += (cchDest + 1) * sizeof(WCHAR);
+ }
+
+ return ret;
+}
+
+LRESULT APIENTRY
+Imm32ProcessRequest(HIMC hIMC, PWND pWnd, DWORD dwCommand, LPVOID pData, BOOL bAnsiAPI)
+{
+ HWND hWnd;
+ DWORD ret = 0, dwCharPos, cchCompStr;
+ LPVOID pCS, pTempData = pData;
+ LPRECONVERTSTRING pRS;
+ LPIMECHARPOSITION pICP;
+ PCLIENTIMC pClientImc;
+ UINT uCodePage = CP_ACP;
+ BOOL bAnsiWnd = !!(pWnd->state & WNDS_ANSIWINDOWPROC);
+ static const size_t acbData[7 * 2] =
+ {
+ /* UNICODE */
+ sizeof(COMPOSITIONFORM), sizeof(CANDIDATEFORM), sizeof(LOGFONTW),
+ sizeof(RECONVERTSTRING), sizeof(RECONVERTSTRING),
+ sizeof(IMECHARPOSITION), sizeof(RECONVERTSTRING),
+ /* ANSI */
+ sizeof(COMPOSITIONFORM), sizeof(CANDIDATEFORM), sizeof(LOGFONTA),
+ sizeof(RECONVERTSTRING), sizeof(RECONVERTSTRING),
+ sizeof(IMECHARPOSITION), sizeof(RECONVERTSTRING),
+ };
+
+ if (dwCommand == 0 || dwCommand > IMR_DOCUMENTFEED)
+ return 0; /* Out of range */
+
+ if (pData && IsBadWritePtr(pData, acbData[bAnsiAPI * 7 + dwCommand - 1]))
+ return 0; /* Invalid pointer */
+
+ /* Sanity check */
+ switch (dwCommand)
+ {
+ case IMR_RECONVERTSTRING: case IMR_DOCUMENTFEED:
+ pRS = pData;
+ if (pRS && (pRS->dwVersion != 0 || pRS->dwSize < sizeof(RECONVERTSTRING)))
+ {
+ Imm32RequestError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ break;
+
+ case IMR_CONFIRMRECONVERTSTRING:
+ pRS = pData;
+ if (!pRS || pRS->dwVersion != 0)
+ {
+ Imm32RequestError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ break;
+
+ default:
+ if (!pData)
+ {
+ Imm32RequestError(ERROR_INVALID_PARAMETER);
+ return 0;
+ }
+ break;
+ }
+
+ pClientImc = ImmLockClientImc(hIMC);
+ if (pClientImc)
+ {
+ uCodePage = pClientImc->uCodePage;
+ ImmUnlockClientImc(pClientImc);
+ }
+
+ /* Prepare */
+ switch (dwCommand)
+ {
+ case IMR_COMPOSITIONFONT:
+ if (bAnsiAPI == bAnsiWnd)
+ goto DoIt;
+ if (bAnsiWnd)
+ pTempData = Imm32HeapAlloc(0, sizeof(LOGFONTA));
+ else
+ pTempData = Imm32HeapAlloc(0, sizeof(LOGFONTW));
+ if (!pTempData)
+ return 0;
+ break;
+
+ case IMR_RECONVERTSTRING: case IMR_CONFIRMRECONVERTSTRING: case IMR_DOCUMENTFEED:
+ if (bAnsiAPI == bAnsiWnd || !pData)
+ goto DoIt;
+
+ pRS = pData;
+ ret = Imm32ReconvertSize(pRS->dwSize, FALSE, bAnsiWnd);
+ pTempData = Imm32HeapAlloc(0, ret + sizeof(WCHAR));
+ if (!pTempData)
+ return 0;
+
+ pRS = pTempData;
+ pRS->dwSize = ret;
+ pRS->dwVersion = 0;
+
+ if (dwCommand == IMR_CONFIRMRECONVERTSTRING)
+ Imm32ConvertReconvert(pData, pTempData, bAnsiWnd, uCodePage);
+ break;
+
+ case IMR_QUERYCHARPOSITION:
+ if (bAnsiAPI == bAnsiWnd)
+ goto DoIt;
+
+ pICP = pData;
+ dwCharPos = pICP->dwCharPos;
+
+ if (bAnsiAPI)
+ {
+ cchCompStr = ImmGetCompositionStringA(hIMC, GCS_COMPSTR, NULL, 0);
+ if (!cchCompStr)
+ return 0;
+
+ pCS = Imm32HeapAlloc(0, (cchCompStr + 1) * sizeof(CHAR));
+ if (!pCS)
+ return 0;
+
+ ImmGetCompositionStringA(hIMC, GCS_COMPSTR, pCS, cchCompStr);
+ pICP->dwCharPos = IchWideFromAnsi(pICP->dwCharPos, pCS, uCodePage);
+ }
+ else
+ {
+ cchCompStr = ImmGetCompositionStringW(hIMC, GCS_COMPSTR, NULL, 0);
+ if (!cchCompStr)
+ return 0;
+
+ pCS = Imm32HeapAlloc(0, (cchCompStr + 1) * sizeof(WCHAR));
+ if (!pCS)
+ return 0;
+
+ ImmGetCompositionStringW(hIMC, GCS_COMPSTR, pCS, cchCompStr);
+ pICP->dwCharPos = IchAnsiFromWide(pICP->dwCharPos, pCS, uCodePage);
+ }
+
+ Imm32HeapFree(pCS);
+ break;
+
+ default:
+ break;
+ }
+
+DoIt:
+ /* The main task */
+ hWnd = pWnd->head.h;
+ if (bAnsiWnd)
+ ret = SendMessageA(hWnd, WM_IME_REQUEST, dwCommand, (LPARAM)pTempData);
+ else
+ ret = SendMessageW(hWnd, WM_IME_REQUEST, dwCommand, (LPARAM)pTempData);
+
+ if (bAnsiAPI == bAnsiWnd)
+ goto Quit;
+
+ /* Get back to caller */
+ switch (dwCommand)
+ {
+ case IMR_COMPOSITIONFONT:
+ if (bAnsiAPI)
+ LogFontWideToAnsi(pTempData, pData);
+ else
+ LogFontAnsiToWide(pTempData, pData);
+ break;
+
+ case IMR_RECONVERTSTRING: case IMR_DOCUMENTFEED:
+ if (!ret)
+ goto Quit;
+
+ ret = Imm32ReconvertSize(ret, TRUE, bAnsiWnd);
+ if (ret < sizeof(RECONVERTSTRING) ||
+ (pTempData && !Imm32ConvertReconvert(pData, pTempData, bAnsiAPI, uCodePage)))
+ {
+ ret = 0;
+ }
+ break;
+
+ case IMR_QUERYCHARPOSITION:
+ pICP->dwCharPos = dwCharPos;
+ break;
+
+ default:
+ break;
+ }
+
+Quit:
+ if (pTempData != pData)
+ Imm32HeapFree(pTempData);
+ return ret;
+}
+
+LRESULT APIENTRY Imm32RequestMessageAW(HIMC hIMC, WPARAM wParam, LPARAM lParam, BOOL bAnsi)
+{
+ LRESULT ret = 0;
+ LPINPUTCONTEXT pIC;
+ HWND hWnd;
+ PWND pWnd = NULL;
+
+ if (!hIMC || Imm32IsCrossThreadAccess(hIMC))
+ return FALSE;
+
+ pIC = ImmLockIMC(hIMC);
+ if (!pIC)
+ return FALSE;
+
+ hWnd = pIC->hWnd;
+ if (hWnd)
+ pWnd = ValidateHwndNoErr(hWnd);
+
+ if (pWnd && pWnd->head.pti == NtCurrentTeb()->Win32ThreadInfo)
+ ret = Imm32ProcessRequest(hIMC, pWnd, (DWORD)wParam, (LPVOID)lParam, bAnsi);
+
+ ImmUnlockIMC(hIMC);
+ return ret;
+}
+
/***********************************************************************
* ImmIsUIMessageA (IMM32.@)
*/
return ret;
#undef MSG_COUNT
}
+
+/***********************************************************************
+ * ImmRequestMessageA(IMM32.@)
+ */
+LRESULT WINAPI ImmRequestMessageA(HIMC hIMC, WPARAM wParam, LPARAM lParam)
+{
+ TRACE("(%p, %p, %p)\n", hIMC, wParam, lParam);
+ return Imm32RequestMessageAW(hIMC, wParam, lParam, TRUE);
+}
+
+/***********************************************************************
+ * ImmRequestMessageW(IMM32.@)
+ */
+LRESULT WINAPI ImmRequestMessageW(HIMC hIMC, WPARAM wParam, LPARAM lParam)
+{
+ TRACE("(%p, %p, %p)\n", hIMC, wParam, lParam);
+ return Imm32RequestMessageAW(hIMC, wParam, lParam, FALSE);
+}