2 * PROJECT: ReactOS IMM32
3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
4 * PURPOSE: Implementing IMM32 helper functions
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>
15 WINE_DEFAULT_DEBUG_CHANNEL(imm
);
17 HANDLE g_hImm32Heap
= NULL
;
19 LPWSTR APIENTRY
Imm32WideFromAnsi(LPCSTR pszA
)
21 INT cch
= lstrlenA(pszA
);
22 LPWSTR pszW
= Imm32HeapAlloc(0, (cch
+ 1) * sizeof(WCHAR
));
25 cch
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, pszA
, cch
, pszW
, cch
+ 1);
30 LPSTR APIENTRY
Imm32AnsiFromWide(LPCWSTR pszW
)
32 INT cchW
= lstrlenW(pszW
);
33 INT cchA
= (cchW
+ 1) * sizeof(WCHAR
);
34 LPSTR pszA
= Imm32HeapAlloc(0, cchA
);
37 cchA
= WideCharToMultiByte(CP_ACP
, 0, pszW
, cchW
, pszA
, cchA
, NULL
, NULL
);
42 BOOL
Imm32GetSystemLibraryPath(LPWSTR pszPath
, DWORD cchPath
, LPCWSTR pszFileName
)
44 if (!pszFileName
[0] || !GetSystemDirectoryW(pszPath
, cchPath
))
46 StringCchCatW(pszPath
, cchPath
, L
"\\");
47 StringCchCatW(pszPath
, cchPath
, pszFileName
);
51 VOID APIENTRY
LogFontAnsiToWide(const LOGFONTA
*plfA
, LPLOGFONTW plfW
)
54 RtlCopyMemory(plfW
, plfA
, offsetof(LOGFONTA
, lfFaceName
));
55 StringCchLengthA(plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), &cch
);
56 cch
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, plfA
->lfFaceName
, (INT
)cch
,
57 plfW
->lfFaceName
, _countof(plfW
->lfFaceName
));
58 if (cch
> _countof(plfW
->lfFaceName
) - 1)
59 cch
= _countof(plfW
->lfFaceName
) - 1;
60 plfW
->lfFaceName
[cch
] = 0;
63 VOID APIENTRY
LogFontWideToAnsi(const LOGFONTW
*plfW
, LPLOGFONTA plfA
)
66 RtlCopyMemory(plfA
, plfW
, offsetof(LOGFONTW
, lfFaceName
));
67 StringCchLengthW(plfW
->lfFaceName
, _countof(plfW
->lfFaceName
), &cch
);
68 cch
= WideCharToMultiByte(CP_ACP
, 0, plfW
->lfFaceName
, (INT
)cch
,
69 plfA
->lfFaceName
, _countof(plfA
->lfFaceName
), NULL
, NULL
);
70 if (cch
> _countof(plfA
->lfFaceName
) - 1)
71 cch
= _countof(plfA
->lfFaceName
) - 1;
72 plfA
->lfFaceName
[cch
] = 0;
75 PWND FASTCALL
ValidateHwndNoErr(HWND hwnd
)
77 PCLIENTINFO ClientInfo
= GetWin32ClientInfo();
79 PUSER_HANDLE_TABLE ht
;
80 PUSER_HANDLE_ENTRY he
;
83 /* See if the window is cached */
84 if (hwnd
== ClientInfo
->CallbackWnd
.hWnd
)
85 return ClientInfo
->CallbackWnd
.pWnd
;
87 if (!NtUserValidateHandleSecure(hwnd
))
90 ht
= g_SharedInfo
.aheList
; /* handle table */
92 /* ReactOS-Specific! */
93 ASSERT(g_SharedInfo
.ulSharedDelta
!= 0);
94 he
= (PUSER_HANDLE_ENTRY
)((ULONG_PTR
)ht
->handles
- g_SharedInfo
.ulSharedDelta
);
96 index
= (LOWORD(hwnd
) - FIRST_USER_HANDLE
) >> 1;
97 if (index
< 0 || index
>= ht
->nb_handles
|| he
[index
].type
!= TYPE_WINDOW
)
100 generation
= HIWORD(hwnd
);
101 if (generation
!= he
[index
].generation
&& generation
&& generation
!= 0xFFFF)
104 return (PWND
)&he
[index
];
107 LPVOID APIENTRY
Imm32HeapAlloc(DWORD dwFlags
, DWORD dwBytes
)
111 g_hImm32Heap
= RtlGetProcessHeap();
112 if (g_hImm32Heap
== NULL
)
115 return HeapAlloc(g_hImm32Heap
, dwFlags
, dwBytes
);
119 Imm32NotifyAction(HIMC hIMC
, HWND hwnd
, DWORD dwAction
, DWORD_PTR dwIndex
, DWORD_PTR dwValue
,
120 DWORD_PTR dwCommand
, DWORD_PTR dwData
)
128 dwLayout
= NtUserQueryInputContext(hIMC
, 1);
131 /* find keyboard layout and lock it */
132 hKL
= GetKeyboardLayout(dwLayout
);
133 pImeDpi
= ImmLockImeDpi(hKL
);
137 pImeDpi
->NotifyIME(hIMC
, dwAction
, dwIndex
, dwValue
);
139 ImmUnlockImeDpi(pImeDpi
); /* unlock */
144 if (hwnd
&& dwCommand
)
145 SendMessageW(hwnd
, WM_IME_NOTIFY
, dwCommand
, dwData
);
150 DWORD APIENTRY
Imm32AllocAndBuildHimcList(DWORD dwThreadId
, HIMC
**pphList
)
152 #define INITIAL_COUNT 0x40
155 DWORD dwCount
= INITIAL_COUNT
, cRetry
= 0;
158 phNewList
= Imm32HeapAlloc(0, dwCount
* sizeof(HIMC
));
159 if (phNewList
== NULL
)
162 Status
= NtUserBuildHimcList(dwThreadId
, dwCount
, phNewList
, &dwCount
);
163 while (Status
== STATUS_BUFFER_TOO_SMALL
)
165 Imm32HeapFree(phNewList
);
166 if (cRetry
++ >= MAX_RETRY
)
169 phNewList
= Imm32HeapAlloc(0, dwCount
* sizeof(HIMC
));
170 if (phNewList
== NULL
)
173 Status
= NtUserBuildHimcList(dwThreadId
, dwCount
, phNewList
, &dwCount
);
176 if (NT_ERROR(Status
) || !dwCount
)
178 Imm32HeapFree(phNewList
);
182 *pphList
= phNewList
;
188 /***********************************************************************
189 * ImmCreateIMCC(IMM32.@)
191 HIMCC WINAPI
ImmCreateIMCC(DWORD size
)
195 return LocalAlloc(LHND
, size
);
198 /***********************************************************************
199 * ImmDestroyIMCC(IMM32.@)
201 HIMCC WINAPI
ImmDestroyIMCC(HIMCC block
)
204 return LocalFree(block
);
208 /***********************************************************************
209 * ImmLockIMCC(IMM32.@)
211 LPVOID WINAPI
ImmLockIMCC(HIMCC imcc
)
214 return LocalLock(imcc
);
218 /***********************************************************************
219 * ImmUnlockIMCC(IMM32.@)
221 BOOL WINAPI
ImmUnlockIMCC(HIMCC imcc
)
224 return LocalUnlock(imcc
);
228 /***********************************************************************
229 * ImmGetIMCCLockCount(IMM32.@)
231 DWORD WINAPI
ImmGetIMCCLockCount(HIMCC imcc
)
233 return LocalFlags(imcc
) & LMEM_LOCKCOUNT
;
236 /***********************************************************************
237 * ImmReSizeIMCC(IMM32.@)
239 HIMCC WINAPI
ImmReSizeIMCC(HIMCC imcc
, DWORD size
)
243 return LocalReAlloc(imcc
, size
, LHND
);
246 /***********************************************************************
247 * ImmGetIMCCSize(IMM32.@)
249 DWORD WINAPI
ImmGetIMCCSize(HIMCC imcc
)
252 return LocalSize(imcc
);
256 /***********************************************************************
257 * ImmGetIMCLockCount(IMM32.@)
259 DWORD WINAPI
ImmGetIMCLockCount(HIMC hIMC
)
263 PCLIENTIMC pClientImc
;
265 pClientImc
= ImmLockClientImc(hIMC
);
266 if (pClientImc
== NULL
)
270 hClientImc
= pClientImc
->hImc
;
272 ret
= (LocalFlags(hClientImc
) & LMEM_LOCKCOUNT
);
274 ImmUnlockClientImc(pClientImc
);