reactos/dll/win32/imm32/utils.c
Katayama Hirofumi MZ 5b522667a6
[IMM32] Define Imm32HeapFree macro and use it (#3962)
- Define Imm32HeapFree macro in precomp.h and use it.
- Omit some NULL checks (for HeapFree).
CORE-11700
2021-09-19 01:52:05 +09:00

277 lines
7.4 KiB
C

/*
* PROJECT: ReactOS IMM32
* LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
* PURPOSE: Implementing IMM32 helper functions
* COPYRIGHT: Copyright 1998 Patrik Stridvall
* Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart
* Copyright 2017 James Tabor <james.tabor@reactos.org>
* Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org>
* Copyright 2020 Oleg Dubinskiy <oleg.dubinskij2013@yandex.ua>
* Copyright 2020-2021 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
*/
#include "precomp.h"
WINE_DEFAULT_DEBUG_CHANNEL(imm);
HANDLE g_hImm32Heap = NULL;
LPWSTR APIENTRY Imm32WideFromAnsi(LPCSTR pszA)
{
INT cch = lstrlenA(pszA);
LPWSTR pszW = Imm32HeapAlloc(0, (cch + 1) * sizeof(WCHAR));
if (pszW == NULL)
return NULL;
cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, pszA, cch, pszW, cch + 1);
pszW[cch] = 0;
return pszW;
}
LPSTR APIENTRY Imm32AnsiFromWide(LPCWSTR pszW)
{
INT cchW = lstrlenW(pszW);
INT cchA = (cchW + 1) * sizeof(WCHAR);
LPSTR pszA = Imm32HeapAlloc(0, cchA);
if (!pszA)
return NULL;
cchA = WideCharToMultiByte(CP_ACP, 0, pszW, cchW, pszA, cchA, NULL, NULL);
pszA[cchA] = 0;
return pszA;
}
BOOL Imm32GetSystemLibraryPath(LPWSTR pszPath, DWORD cchPath, LPCWSTR pszFileName)
{
if (!pszFileName[0] || !GetSystemDirectoryW(pszPath, cchPath))
return FALSE;
StringCchCatW(pszPath, cchPath, L"\\");
StringCchCatW(pszPath, cchPath, pszFileName);
return TRUE;
}
VOID APIENTRY LogFontAnsiToWide(const LOGFONTA *plfA, LPLOGFONTW plfW)
{
size_t cch;
RtlCopyMemory(plfW, plfA, offsetof(LOGFONTA, lfFaceName));
StringCchLengthA(plfA->lfFaceName, _countof(plfA->lfFaceName), &cch);
cch = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, plfA->lfFaceName, (INT)cch,
plfW->lfFaceName, _countof(plfW->lfFaceName));
if (cch > _countof(plfW->lfFaceName) - 1)
cch = _countof(plfW->lfFaceName) - 1;
plfW->lfFaceName[cch] = 0;
}
VOID APIENTRY LogFontWideToAnsi(const LOGFONTW *plfW, LPLOGFONTA plfA)
{
size_t cch;
RtlCopyMemory(plfA, plfW, offsetof(LOGFONTW, lfFaceName));
StringCchLengthW(plfW->lfFaceName, _countof(plfW->lfFaceName), &cch);
cch = WideCharToMultiByte(CP_ACP, 0, plfW->lfFaceName, (INT)cch,
plfA->lfFaceName, _countof(plfA->lfFaceName), NULL, NULL);
if (cch > _countof(plfA->lfFaceName) - 1)
cch = _countof(plfA->lfFaceName) - 1;
plfA->lfFaceName[cch] = 0;
}
PWND FASTCALL ValidateHwndNoErr(HWND hwnd)
{
PCLIENTINFO ClientInfo = GetWin32ClientInfo();
INT index;
PUSER_HANDLE_TABLE ht;
PUSER_HANDLE_ENTRY he;
WORD generation;
/* See if the window is cached */
if (hwnd == ClientInfo->CallbackWnd.hWnd)
return ClientInfo->CallbackWnd.pWnd;
if (!NtUserValidateHandleSecure(hwnd))
return NULL;
ht = g_SharedInfo.aheList; /* handle table */
ASSERT(ht);
/* ReactOS-Specific! */
ASSERT(g_SharedInfo.ulSharedDelta != 0);
he = (PUSER_HANDLE_ENTRY)((ULONG_PTR)ht->handles - g_SharedInfo.ulSharedDelta);
index = (LOWORD(hwnd) - FIRST_USER_HANDLE) >> 1;
if (index < 0 || index >= ht->nb_handles || he[index].type != TYPE_WINDOW)
return NULL;
generation = HIWORD(hwnd);
if (generation != he[index].generation && generation && generation != 0xFFFF)
return NULL;
return (PWND)&he[index];
}
LPVOID APIENTRY Imm32HeapAlloc(DWORD dwFlags, DWORD dwBytes)
{
if (!g_hImm32Heap)
{
g_hImm32Heap = RtlGetProcessHeap();
if (g_hImm32Heap == NULL)
return NULL;
}
return HeapAlloc(g_hImm32Heap, dwFlags, dwBytes);
}
BOOL APIENTRY
Imm32NotifyAction(HIMC hIMC, HWND hwnd, DWORD dwAction, DWORD_PTR dwIndex, DWORD_PTR dwValue,
DWORD_PTR dwCommand, DWORD_PTR dwData)
{
DWORD dwLayout;
HKL hKL;
PIMEDPI pImeDpi;
if (dwAction)
{
dwLayout = NtUserQueryInputContext(hIMC, 1);
if (dwLayout)
{
/* find keyboard layout and lock it */
hKL = GetKeyboardLayout(dwLayout);
pImeDpi = ImmLockImeDpi(hKL);
if (pImeDpi)
{
/* do notify */
pImeDpi->NotifyIME(hIMC, dwAction, dwIndex, dwValue);
ImmUnlockImeDpi(pImeDpi); /* unlock */
}
}
}
if (hwnd && dwCommand)
SendMessageW(hwnd, WM_IME_NOTIFY, dwCommand, dwData);
return TRUE;
}
DWORD APIENTRY Imm32AllocAndBuildHimcList(DWORD dwThreadId, HIMC **pphList)
{
#define INITIAL_COUNT 0x40
#define MAX_RETRY 10
NTSTATUS Status;
DWORD dwCount = INITIAL_COUNT, cRetry = 0;
HIMC *phNewList;
phNewList = Imm32HeapAlloc(0, dwCount * sizeof(HIMC));
if (phNewList == NULL)
return 0;
Status = NtUserBuildHimcList(dwThreadId, dwCount, phNewList, &dwCount);
while (Status == STATUS_BUFFER_TOO_SMALL)
{
Imm32HeapFree(phNewList);
if (cRetry++ >= MAX_RETRY)
return 0;
phNewList = Imm32HeapAlloc(0, dwCount * sizeof(HIMC));
if (phNewList == NULL)
return 0;
Status = NtUserBuildHimcList(dwThreadId, dwCount, phNewList, &dwCount);
}
if (NT_ERROR(Status) || !dwCount)
{
Imm32HeapFree(phNewList);
return 0;
}
*pphList = phNewList;
return dwCount;
#undef INITIAL_COUNT
#undef MAX_RETRY
}
/***********************************************************************
* ImmCreateIMCC(IMM32.@)
*/
HIMCC WINAPI ImmCreateIMCC(DWORD size)
{
if (size < 4)
size = 4;
return LocalAlloc(LHND, size);
}
/***********************************************************************
* ImmDestroyIMCC(IMM32.@)
*/
HIMCC WINAPI ImmDestroyIMCC(HIMCC block)
{
if (block)
return LocalFree(block);
return NULL;
}
/***********************************************************************
* ImmLockIMCC(IMM32.@)
*/
LPVOID WINAPI ImmLockIMCC(HIMCC imcc)
{
if (imcc)
return LocalLock(imcc);
return NULL;
}
/***********************************************************************
* ImmUnlockIMCC(IMM32.@)
*/
BOOL WINAPI ImmUnlockIMCC(HIMCC imcc)
{
if (imcc)
return LocalUnlock(imcc);
return FALSE;
}
/***********************************************************************
* ImmGetIMCCLockCount(IMM32.@)
*/
DWORD WINAPI ImmGetIMCCLockCount(HIMCC imcc)
{
return LocalFlags(imcc) & LMEM_LOCKCOUNT;
}
/***********************************************************************
* ImmReSizeIMCC(IMM32.@)
*/
HIMCC WINAPI ImmReSizeIMCC(HIMCC imcc, DWORD size)
{
if (!imcc)
return NULL;
return LocalReAlloc(imcc, size, LHND);
}
/***********************************************************************
* ImmGetIMCCSize(IMM32.@)
*/
DWORD WINAPI ImmGetIMCCSize(HIMCC imcc)
{
if (imcc)
return LocalSize(imcc);
return 0;
}
/***********************************************************************
* ImmGetIMCLockCount(IMM32.@)
*/
DWORD WINAPI ImmGetIMCLockCount(HIMC hIMC)
{
DWORD ret;
HIMC hClientImc;
PCLIENTIMC pClientImc;
pClientImc = ImmLockClientImc(hIMC);
if (pClientImc == NULL)
return 0;
ret = 0;
hClientImc = pClientImc->hImc;
if (hClientImc)
ret = (LocalFlags(hClientImc) & LMEM_LOCKCOUNT);
ImmUnlockClientImc(pClientImc);
return ret;
}