mirror of
https://github.com/reactos/reactos.git
synced 2025-04-27 17:10:22 +00:00
[IMM32][USER32] ImmPutImeMenuItemsIntoMappedFile (#4588)
Implement inter-process menu item retrieving. CORE-11700
This commit is contained in:
parent
fe777bb52f
commit
ffbdb7d39e
6 changed files with 307 additions and 6 deletions
|
@ -355,15 +355,191 @@ Quit:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We will transport the IME menu items by using a flat memory block via
|
||||||
|
// a file mapping object beyond the boundary of a process.
|
||||||
|
|
||||||
|
#define MAX_IMEMENU_BITMAP_BYTES 0xF00
|
||||||
|
|
||||||
|
typedef struct tagIMEMENUITEM
|
||||||
|
{
|
||||||
|
IMEMENUITEMINFOW Info;
|
||||||
|
BYTE abChecked[MAX_IMEMENU_BITMAP_BYTES];
|
||||||
|
BYTE abUnchecked[MAX_IMEMENU_BITMAP_BYTES];
|
||||||
|
BYTE abItem[MAX_IMEMENU_BITMAP_BYTES];
|
||||||
|
} IMEMENUITEM, *PIMEMENUITEM;
|
||||||
|
|
||||||
|
typedef struct tagIMEMENU
|
||||||
|
{
|
||||||
|
DWORD dwVersion;
|
||||||
|
DWORD dwFlags;
|
||||||
|
DWORD dwType;
|
||||||
|
DWORD dwItemCount;
|
||||||
|
IMEMENUITEMINFOW Parent;
|
||||||
|
IMEMENUITEM Items[ANYSIZE_ARRAY];
|
||||||
|
} IMEMENU, *PIMEMENU;
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* ImmPutImeMenuItemsIntoMappedFile (IMM32.@)
|
||||||
|
*
|
||||||
|
* Called from user32.dll to transport the IME menu items by using a
|
||||||
|
* file mapping object. This function is provided for WM_IME_SYSTEM:IMS_GETIMEMENU
|
||||||
|
* handling.
|
||||||
|
*/
|
||||||
|
LRESULT WINAPI ImmPutImeMenuItemsIntoMappedFile(HIMC hIMC)
|
||||||
|
{
|
||||||
|
LRESULT ret = FALSE;
|
||||||
|
HANDLE hMapping;
|
||||||
|
PIMEMENU pView;
|
||||||
|
LPIMEMENUITEMINFOW pParent = NULL, pItems = NULL;
|
||||||
|
DWORD i, cItems, cbItems = 0;
|
||||||
|
|
||||||
|
hMapping = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, L"ImmMenuInfo");
|
||||||
|
pView = MapViewOfFile(hMapping, FILE_MAP_ALL_ACCESS, 0, 0, 0);
|
||||||
|
if (!pView || pView->dwVersion != 1)
|
||||||
|
{
|
||||||
|
ERR("hMapping %p, pView %p\n", hMapping, pView);
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pView->Parent.cbSize > 0)
|
||||||
|
pParent = &pView->Parent;
|
||||||
|
|
||||||
|
if (pView->dwItemCount > 0)
|
||||||
|
{
|
||||||
|
cbItems = pView->dwItemCount * sizeof(IMEMENUITEMINFOW);
|
||||||
|
pItems = ImmLocalAlloc(HEAP_ZERO_MEMORY, cbItems);
|
||||||
|
if (!pItems)
|
||||||
|
{
|
||||||
|
ERR("!pItems\n");
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cItems = ImmGetImeMenuItemsW(hIMC, pView->dwFlags, pView->dwType, pParent, pItems, cbItems);
|
||||||
|
pView->dwItemCount = cItems;
|
||||||
|
if (cItems == 0)
|
||||||
|
goto Quit;
|
||||||
|
|
||||||
|
if (pItems)
|
||||||
|
{
|
||||||
|
for (i = 0; i < cItems; ++i)
|
||||||
|
{
|
||||||
|
pView->Items[i].Info = pItems[i];
|
||||||
|
|
||||||
|
// store bitmaps to bytes
|
||||||
|
if (pItems[i].hbmpChecked)
|
||||||
|
{
|
||||||
|
Imm32StoreBitmapToBytes(pItems[i].hbmpChecked, pView->Items[i].abChecked,
|
||||||
|
MAX_IMEMENU_BITMAP_BYTES);
|
||||||
|
DeleteObject(pItems[i].hbmpChecked);
|
||||||
|
}
|
||||||
|
if (pItems[i].hbmpUnchecked)
|
||||||
|
{
|
||||||
|
Imm32StoreBitmapToBytes(pItems[i].hbmpUnchecked, pView->Items[i].abUnchecked,
|
||||||
|
MAX_IMEMENU_BITMAP_BYTES);
|
||||||
|
DeleteObject(pItems[i].hbmpUnchecked);
|
||||||
|
}
|
||||||
|
if (pItems[i].hbmpItem)
|
||||||
|
{
|
||||||
|
Imm32StoreBitmapToBytes(pItems[i].hbmpItem, pView->Items[i].abItem,
|
||||||
|
MAX_IMEMENU_BITMAP_BYTES);
|
||||||
|
DeleteObject(pItems[i].hbmpItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = TRUE;
|
||||||
|
|
||||||
|
Quit:
|
||||||
|
if (pItems)
|
||||||
|
ImmLocalFree(pItems);
|
||||||
|
if (pView)
|
||||||
|
UnmapViewOfFile(pView);
|
||||||
|
if (hMapping)
|
||||||
|
CloseHandle(hMapping);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// Win: ImmGetImeMenuItemsInterProcess
|
// Win: ImmGetImeMenuItemsInterProcess
|
||||||
DWORD APIENTRY
|
DWORD APIENTRY
|
||||||
Imm32GetImeMenuItemWCrossProcess(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentMenu,
|
Imm32GetImeMenuItemWInterProcess(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentMenu,
|
||||||
LPVOID lpImeMenu, DWORD dwSize)
|
LPVOID lpImeMenu, DWORD dwSize)
|
||||||
{
|
{
|
||||||
FIXME("We have to do something\n");
|
HANDLE hMapping;
|
||||||
|
PIMEMENU pView;
|
||||||
|
DWORD i, cbView, dwItemCount, ret = 0;
|
||||||
|
HWND hImeWnd;
|
||||||
|
PIMEMENUITEM pGotItem;
|
||||||
|
LPIMEMENUITEMINFOW pSetInfo;
|
||||||
|
|
||||||
|
hImeWnd = (HWND)NtUserQueryInputContext(hIMC, QIC_DEFAULTWINDOWIME);
|
||||||
|
if (!hImeWnd || !IsWindow(hImeWnd))
|
||||||
|
{
|
||||||
|
ERR("hImeWnd %p\n", hImeWnd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dwItemCount = (lpImeMenu ? (dwSize / sizeof(IMEMENUITEMINFOW)) : 0);
|
||||||
|
cbView = sizeof(IMEMENU) + ((size_t)dwItemCount - 1) * sizeof(IMEMENUITEM);
|
||||||
|
|
||||||
|
RtlEnterCriticalSection(&gcsImeDpi);
|
||||||
|
|
||||||
|
// create a file mapping
|
||||||
|
hMapping = CreateFileMappingW(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
|
||||||
|
0, cbView, L"ImmMenuInfo");
|
||||||
|
pView = MapViewOfFile(hMapping, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 0);
|
||||||
|
if (!pView)
|
||||||
|
{
|
||||||
|
ERR("hMapping %p, pView %p\n", hMapping, pView);
|
||||||
|
goto Quit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMemory(pView, cbView);
|
||||||
|
pView->dwVersion = 1;
|
||||||
|
pView->dwFlags = dwFlags;
|
||||||
|
pView->dwType = dwType;
|
||||||
|
pView->dwItemCount = dwItemCount;
|
||||||
|
pView->Parent.cbSize = (lpImeParentMenu ? sizeof(IMEMENUITEMINFOW) : 0);
|
||||||
|
|
||||||
|
if (!SendMessageW(hImeWnd, WM_IME_SYSTEM, IMS_GETIMEMENU, (LPARAM)hIMC))
|
||||||
|
goto Quit;
|
||||||
|
|
||||||
|
ret = pView->dwItemCount;
|
||||||
|
|
||||||
|
if (!lpImeMenu)
|
||||||
|
goto Quit;
|
||||||
|
|
||||||
|
for (i = 0; i < ret; ++i)
|
||||||
|
{
|
||||||
|
pGotItem = &(pView->Items[i]);
|
||||||
|
pSetInfo = &((LPIMEMENUITEMINFOW)lpImeMenu)[i];
|
||||||
|
|
||||||
|
*pSetInfo = pGotItem->Info;
|
||||||
|
|
||||||
|
// load bitmaps from bytes
|
||||||
|
if (pSetInfo->hbmpChecked)
|
||||||
|
{
|
||||||
|
pSetInfo->hbmpChecked = Imm32LoadBitmapFromBytes(pGotItem->abChecked);
|
||||||
|
}
|
||||||
|
if (pSetInfo->hbmpUnchecked)
|
||||||
|
{
|
||||||
|
pSetInfo->hbmpUnchecked = Imm32LoadBitmapFromBytes(pGotItem->abUnchecked);
|
||||||
|
}
|
||||||
|
if (pSetInfo->hbmpItem)
|
||||||
|
{
|
||||||
|
pSetInfo->hbmpItem = Imm32LoadBitmapFromBytes(pGotItem->abItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Quit:
|
||||||
|
RtlLeaveCriticalSection(&gcsImeDpi);
|
||||||
|
if (pView)
|
||||||
|
UnmapViewOfFile(pView);
|
||||||
|
if (hMapping)
|
||||||
|
CloseHandle(hMapping);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// Win: ImmGetImeMenuItemsWorker
|
// Win: ImmGetImeMenuItemsWorker
|
||||||
DWORD APIENTRY
|
DWORD APIENTRY
|
||||||
ImmGetImeMenuItemsAW(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentMenu,
|
ImmGetImeMenuItemsAW(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentMenu,
|
||||||
|
@ -391,7 +567,7 @@ ImmGetImeMenuItemsAW(HIMC hIMC, DWORD dwFlags, DWORD dwType, LPVOID lpImeParentM
|
||||||
{
|
{
|
||||||
if (bTargetIsAnsi)
|
if (bTargetIsAnsi)
|
||||||
return 0;
|
return 0;
|
||||||
return Imm32GetImeMenuItemWCrossProcess(hIMC, dwFlags, dwType, lpImeParentMenu,
|
return Imm32GetImeMenuItemWInterProcess(hIMC, dwFlags, dwType, lpImeParentMenu,
|
||||||
lpImeMenu, dwSize);
|
lpImeMenu, dwSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,7 +81,7 @@
|
||||||
@ stdcall ImmNotifyIME(ptr long long long)
|
@ stdcall ImmNotifyIME(ptr long long long)
|
||||||
@ stub ImmPenAuxInput
|
@ stub ImmPenAuxInput
|
||||||
@ stdcall ImmProcessKey(ptr long long long long)
|
@ stdcall ImmProcessKey(ptr long long long long)
|
||||||
@ stdcall -stub ImmPutImeMenuItemsIntoMappedFile(ptr)
|
@ stdcall ImmPutImeMenuItemsIntoMappedFile(ptr)
|
||||||
@ stdcall ImmReSizeIMCC(ptr long)
|
@ stdcall ImmReSizeIMCC(ptr long)
|
||||||
@ stdcall ImmRegisterClient(ptr ptr)
|
@ stdcall ImmRegisterClient(ptr ptr)
|
||||||
@ stdcall ImmRegisterWordA(long str long str)
|
@ stdcall ImmRegisterWordA(long str long str)
|
||||||
|
|
|
@ -165,3 +165,6 @@ static inline PTHREADINFO FASTCALL Imm32CurrentPti(VOID)
|
||||||
NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
|
NtUserGetThreadState(THREADSTATE_GETTHREADINFO);
|
||||||
return NtCurrentTeb()->Win32ThreadInfo;
|
return NtCurrentTeb()->Win32ThreadInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HBITMAP Imm32LoadBitmapFromBytes(const BYTE *pb);
|
||||||
|
BOOL Imm32StoreBitmapToBytes(HBITMAP hbm, LPBYTE pbData, DWORD cbDataMax);
|
||||||
|
|
|
@ -50,6 +50,127 @@ BOOL APIENTRY Imm32IsSystemJapaneseOrKorean(VOID)
|
||||||
return (wPrimary == LANG_JAPANESE || wPrimary == LANG_KOREAN);
|
return (wPrimary == LANG_JAPANESE || wPrimary == LANG_KOREAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct tagBITMAPCOREINFO256
|
||||||
|
{
|
||||||
|
BITMAPCOREHEADER bmciHeader;
|
||||||
|
RGBTRIPLE bmciColors[256];
|
||||||
|
} BITMAPCOREINFO256, *PBITMAPCOREINFO256;
|
||||||
|
|
||||||
|
HBITMAP Imm32LoadBitmapFromBytes(const BYTE *pb)
|
||||||
|
{
|
||||||
|
HBITMAP hbm = NULL;
|
||||||
|
const BITMAPCOREINFO256 *pbmci;
|
||||||
|
LPVOID pvBits;
|
||||||
|
DWORD ib, cbBytes, cColors;
|
||||||
|
BITMAP bm;
|
||||||
|
|
||||||
|
cbBytes = *(const DWORD *)pb;
|
||||||
|
if (cbBytes == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
pb += sizeof(DWORD);
|
||||||
|
ib = sizeof(DWORD);
|
||||||
|
|
||||||
|
pbmci = (const BITMAPCOREINFO256 *)pb;
|
||||||
|
hbm = CreateDIBSection(NULL, (LPBITMAPINFO)pbmci, DIB_RGB_COLORS, &pvBits, NULL, 0);
|
||||||
|
if (!hbm || !GetObject(hbm, sizeof(BITMAP), &bm))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
switch (pbmci->bmciHeader.bcBitCount)
|
||||||
|
{
|
||||||
|
case 1: cColors = 2; break;
|
||||||
|
case 4: cColors = 16; break;
|
||||||
|
case 8: cColors = 256; break;
|
||||||
|
case 24: case 32:
|
||||||
|
cColors = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DeleteObject(hbm);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ib += sizeof(BITMAPCOREHEADER);
|
||||||
|
pb += sizeof(BITMAPCOREHEADER);
|
||||||
|
|
||||||
|
ib += cColors * sizeof(RGBTRIPLE);
|
||||||
|
pb += cColors * sizeof(RGBTRIPLE);
|
||||||
|
|
||||||
|
ib += bm.bmWidthBytes * bm.bmHeight;
|
||||||
|
if (ib > cbBytes)
|
||||||
|
{
|
||||||
|
DeleteObject(hbm);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
CopyMemory(pvBits, pb, bm.bmWidthBytes * bm.bmHeight);
|
||||||
|
|
||||||
|
return hbm;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL Imm32StoreBitmapToBytes(HBITMAP hbm, LPBYTE pbData, DWORD cbDataMax)
|
||||||
|
{
|
||||||
|
HDC hDC;
|
||||||
|
BITMAP bm;
|
||||||
|
DWORD cbBytes, cColors;
|
||||||
|
BITMAPCOREINFO256 bmci;
|
||||||
|
BOOL ret;
|
||||||
|
LPBYTE pb = pbData;
|
||||||
|
|
||||||
|
*(LPDWORD)pb = 0;
|
||||||
|
|
||||||
|
if (!GetObject(hbm, sizeof(BITMAP), &bm))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
ZeroMemory(&bmci, sizeof(bmci));
|
||||||
|
bmci.bmciHeader.bcSize = sizeof(BITMAPCOREHEADER);
|
||||||
|
bmci.bmciHeader.bcWidth = bm.bmWidth;
|
||||||
|
bmci.bmciHeader.bcHeight = bm.bmHeight;
|
||||||
|
bmci.bmciHeader.bcPlanes = 1;
|
||||||
|
bmci.bmciHeader.bcBitCount = bm.bmBitsPixel;
|
||||||
|
|
||||||
|
switch (bm.bmBitsPixel)
|
||||||
|
{
|
||||||
|
case 1: cColors = 2; break;
|
||||||
|
case 4: cColors = 16; break;
|
||||||
|
case 8: cColors = 256; break;
|
||||||
|
case 24: case 32:
|
||||||
|
cColors = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
cbBytes = sizeof(DWORD);
|
||||||
|
cbBytes += sizeof(BITMAPCOREHEADER);
|
||||||
|
cbBytes += cColors * sizeof(RGBTRIPLE);
|
||||||
|
cbBytes += bm.bmWidthBytes * bm.bmHeight;
|
||||||
|
if (cbBytes > cbDataMax)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
hDC = CreateCompatibleDC(NULL);
|
||||||
|
|
||||||
|
ret = GetDIBits(hDC, hbm, 0, bm.bmHeight, NULL, (LPBITMAPINFO)&bmci, DIB_RGB_COLORS);
|
||||||
|
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
*(LPDWORD)pb = cbBytes;
|
||||||
|
pb += sizeof(DWORD);
|
||||||
|
|
||||||
|
CopyMemory(pb, &bmci.bmciHeader, sizeof(BITMAPCOREHEADER));
|
||||||
|
pb += sizeof(BITMAPCOREHEADER);
|
||||||
|
|
||||||
|
CopyMemory(pb, &bmci.bmciColors, cColors * sizeof(RGBTRIPLE));
|
||||||
|
pb += cColors * sizeof(RGBTRIPLE);
|
||||||
|
|
||||||
|
ret = GetDIBits(hDC, hbm, 0, bm.bmHeight, pb, (LPBITMAPINFO)&bmci, DIB_RGB_COLORS);
|
||||||
|
if (!ret)
|
||||||
|
*(LPDWORD)pbData = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteDC(hDC);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// Win: IsAnsiIMC
|
// Win: IsAnsiIMC
|
||||||
BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC)
|
BOOL WINAPI Imm32IsImcAnsi(HIMC hIMC)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,6 +28,7 @@ extern "C" {
|
||||||
#define IMS_IMEACTIVATE 0x17
|
#define IMS_IMEACTIVATE 0x17
|
||||||
#define IMS_IMEDEACTIVATE 0x18
|
#define IMS_IMEDEACTIVATE 0x18
|
||||||
#define IMS_ACTIVATELAYOUT 0x19
|
#define IMS_ACTIVATELAYOUT 0x19
|
||||||
|
#define IMS_GETIMEMENU 0x1C
|
||||||
|
|
||||||
#define IMMGWL_IMC 0
|
#define IMMGWL_IMC 0
|
||||||
#define IMMGWL_PRIVATE (sizeof(LONG))
|
#define IMMGWL_PRIVATE (sizeof(LONG))
|
||||||
|
|
|
@ -678,7 +678,7 @@ static LRESULT ImeWnd_OnImeSystem(PIMEUI pimeui, WPARAM wParam, LPARAM lParam)
|
||||||
ret = IMM_FN(ImmActivateLayout)((HKL)lParam);
|
ret = IMM_FN(ImmActivateLayout)((HKL)lParam);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x1C:
|
case IMS_GETIMEMENU:
|
||||||
ret = IMM_FN(ImmPutImeMenuItemsIntoMappedFile)((HIMC)lParam);
|
ret = IMM_FN(ImmPutImeMenuItemsIntoMappedFile)((HIMC)lParam);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue