a89dafe2717bce41b75c4ad6b779ab98eb700a88
[reactos.git] / win32ss / user / user32 / misc / imm.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS user32.dll
4 * FILE: win32ss/user/user32/misc/imm.c
5 * PURPOSE: User32.dll Imm functions
6 * PROGRAMMER: Dmitry Chapyshev (dmitry@reactos.org)
7 * UPDATE HISTORY:
8 * 01/27/2009 Created
9 */
10
11 #include <user32.h>
12
13 #include <winnls32.h>
14
15 #include <wine/debug.h>
16 #include <strsafe.h>
17
18 WINE_DEFAULT_DEBUG_CHANNEL(user32);
19
20 #define IMM_INIT_MAGIC 0x19650412
21
22
23 Imm32ApiTable gImmApiEntries = {0};
24 HINSTANCE ghImm32 = NULL;
25 BOOL bImmInitializing = FALSE;
26 BOOL ImmApiTableZero = TRUE;
27
28 HRESULT WINAPI GetImmFileName(PWSTR lpBuffer, UINT uSize)
29 {
30 UINT length;
31 STRSAFE_LPWSTR Safe = lpBuffer;
32
33 length = GetSystemDirectoryW(lpBuffer, uSize);
34 if ( length && length < uSize )
35 {
36 StringCchCatW(Safe, uSize, L"\\");
37 return StringCchCatW(Safe, uSize, L"IMM32.DLL");
38 }
39 return StringCchCopyW(Safe, uSize, L"IMM32.DLL");
40 }
41
42 /*
43 * This function should not be implemented, it is used,
44 * if you can not load function from imm32.dll
45 */
46 BOOL WINAPI IMM_ImmIsIME(HKL hKL) { return 0; }
47 HIMC WINAPI IMM_ImmAssociateContext(HWND hwnd, HIMC himc) { return 0; }
48 BOOL WINAPI IMM_ImmReleaseContext(HWND hwnd, HIMC himc) { return 0; }
49 LRESULT WINAPI IMM_ImmEscapeAW(HKL hkl, HIMC himc, UINT uint, LPVOID lpvoid) { return 0; }
50 LONG WINAPI IMM_ImmGetCompositionStringAW(HIMC himc, DWORD dword1, LPVOID lpvoid, DWORD dword2) { return 0; }
51 BOOL WINAPI IMM_ImmGetCompositionFontA(HIMC himc, LPLOGFONTA lplf) { return 0; }
52 BOOL WINAPI IMM_ImmGetCompositionFontW(HIMC himc, LPLOGFONTW lplf) { return 0; }
53 BOOL WINAPI IMM_ImmSetCompositionFontA(HIMC himc, LPLOGFONTA lplf) { return 0; }
54 BOOL WINAPI IMM_ImmSetCompositionFontW(HIMC himc, LPLOGFONTW lplf) { return 0; }
55 BOOL WINAPI IMM_ImmSetGetCompositionWindow(HIMC himc, LPCOMPOSITIONFORM lpcf) { return 0; }
56 HIMC WINAPI IMM_ImmGetContext(HWND hwnd) { return 0; }
57 HWND WINAPI IMM_ImmGetDefaultIMEWnd(HWND hwnd) { return 0; }
58 BOOL WINAPI IMM_ImmNotifyIME(HIMC himc, DWORD dword1, DWORD dword2, DWORD dword3) { return 0; }
59 BOOL WINAPI IMM_ImmRegisterClient(PVOID ptr, HINSTANCE hMod) { return 0; }
60 UINT WINAPI IMM_ImmProcessKey(HWND hwnd, HKL hkl, UINT Vk, LPARAM lParam, DWORD HotKey) { return 0; }
61
62 /*
63 * @unimplemented
64 */
65 BOOL WINAPI IntInitializeImmEntryTable(VOID)
66 {
67 WCHAR ImmFile[MAX_PATH];
68 HMODULE imm32 = ghImm32;
69
70 if (gImmApiEntries.pImmIsIME != 0)
71 {
72 ERR("Imm Api Table Init 1\n");
73 return TRUE;
74 }
75
76 GetImmFileName(ImmFile, sizeof(ImmFile));
77 TRACE("File %ws\n",ImmFile);
78
79 if (imm32 == NULL)
80 {
81 imm32 = GetModuleHandleW(ImmFile);
82 }
83
84 if (imm32 == NULL)
85 {
86 imm32 = ghImm32 = LoadLibraryW(ImmFile);
87 if (imm32 == NULL)
88 {
89 ERR("Did not load!\n");
90 return FALSE;
91 }
92 return TRUE;
93 }
94
95 if (ImmApiTableZero)
96 {
97 ImmApiTableZero = FALSE;
98 ZeroMemory(&gImmApiEntries, sizeof(Imm32ApiTable));
99 }
100
101 gImmApiEntries.pImmIsIME = (BOOL (WINAPI*)(HKL)) GetProcAddress(imm32, "ImmIsIME");
102 if (!gImmApiEntries.pImmIsIME)
103 gImmApiEntries.pImmIsIME = IMM_ImmIsIME;
104
105 gImmApiEntries.pImmEscapeA = (LRESULT (WINAPI*)(HKL, HIMC, UINT, LPVOID)) GetProcAddress(imm32, "ImmEscapeA");
106 if (!gImmApiEntries.pImmEscapeA)
107 gImmApiEntries.pImmEscapeA = IMM_ImmEscapeAW;
108
109 gImmApiEntries.pImmEscapeW = (LRESULT (WINAPI*)(HKL, HIMC, UINT, LPVOID)) GetProcAddress(imm32, "ImmEscapeW");
110 if (!gImmApiEntries.pImmEscapeW)
111 gImmApiEntries.pImmEscapeW = IMM_ImmEscapeAW;
112
113 gImmApiEntries.pImmGetCompositionStringA = (LONG (WINAPI*)(HIMC, DWORD, LPVOID, DWORD)) GetProcAddress(imm32, "ImmGetCompositionStringA");
114 if (!gImmApiEntries.pImmGetCompositionStringA)
115 gImmApiEntries.pImmGetCompositionStringA = IMM_ImmGetCompositionStringAW;
116
117 gImmApiEntries.pImmGetCompositionStringW = (LONG (WINAPI*)(HIMC, DWORD, LPVOID, DWORD)) GetProcAddress(imm32, "ImmGetCompositionStringW");
118 if (!gImmApiEntries.pImmGetCompositionStringW)
119 gImmApiEntries.pImmGetCompositionStringW = IMM_ImmGetCompositionStringAW;
120
121 gImmApiEntries.pImmGetCompositionFontA = (BOOL (WINAPI*)(HIMC, LPLOGFONTA)) GetProcAddress(imm32, "ImmGetCompositionFontA");
122 if (!gImmApiEntries.pImmGetCompositionFontA)
123 gImmApiEntries.pImmGetCompositionFontA = IMM_ImmGetCompositionFontA;
124
125 gImmApiEntries.pImmGetCompositionFontW = (BOOL (WINAPI*)(HIMC, LPLOGFONTW)) GetProcAddress(imm32, "ImmGetCompositionFontW");
126 if (!gImmApiEntries.pImmGetCompositionFontW)
127 gImmApiEntries.pImmGetCompositionFontW = IMM_ImmGetCompositionFontW;
128
129 gImmApiEntries.pImmSetCompositionFontA = (BOOL (WINAPI*)(HIMC, LPLOGFONTA)) GetProcAddress(imm32, "ImmSetCompositionFontA");
130 if (!gImmApiEntries.pImmSetCompositionFontA)
131 gImmApiEntries.pImmSetCompositionFontA = IMM_ImmSetCompositionFontA;
132
133 gImmApiEntries.pImmSetCompositionFontW = (BOOL (WINAPI*)(HIMC, LPLOGFONTW)) GetProcAddress(imm32, "ImmSetCompositionFontW");
134 if (!gImmApiEntries.pImmSetCompositionFontW)
135 gImmApiEntries.pImmSetCompositionFontW = IMM_ImmSetCompositionFontW;
136
137 gImmApiEntries.pImmGetCompositionWindow = (BOOL (WINAPI*)(HIMC, LPCOMPOSITIONFORM)) GetProcAddress(imm32, "ImmGetCompositionWindow");
138 if (!gImmApiEntries.pImmGetCompositionWindow)
139 gImmApiEntries.pImmGetCompositionWindow = IMM_ImmSetGetCompositionWindow;
140
141 gImmApiEntries.pImmSetCompositionWindow = (BOOL (WINAPI*)(HIMC, LPCOMPOSITIONFORM)) GetProcAddress(imm32, "ImmSetCompositionWindow");
142 if (!gImmApiEntries.pImmSetCompositionWindow)
143 gImmApiEntries.pImmSetCompositionWindow = IMM_ImmSetGetCompositionWindow;
144
145 gImmApiEntries.pImmAssociateContext = (HIMC (WINAPI*)(HWND, HIMC)) GetProcAddress(imm32, "ImmAssociateContext");
146 if (!gImmApiEntries.pImmAssociateContext)
147 gImmApiEntries.pImmAssociateContext = IMM_ImmAssociateContext;
148
149 gImmApiEntries.pImmReleaseContext = (BOOL (WINAPI*)(HWND, HIMC)) GetProcAddress(imm32, "ImmReleaseContext");
150 if (!gImmApiEntries.pImmReleaseContext)
151 gImmApiEntries.pImmReleaseContext = IMM_ImmReleaseContext;
152
153 gImmApiEntries.pImmGetContext = (HIMC (WINAPI*)(HWND)) GetProcAddress(imm32, "ImmGetContext");
154 if (!gImmApiEntries.pImmGetContext)
155 gImmApiEntries.pImmGetContext = IMM_ImmGetContext;
156
157 gImmApiEntries.pImmGetDefaultIMEWnd = (HWND (WINAPI*)(HWND)) GetProcAddress(imm32, "ImmGetDefaultIMEWnd");
158 if (!gImmApiEntries.pImmGetDefaultIMEWnd)
159 gImmApiEntries.pImmGetDefaultIMEWnd = IMM_ImmGetDefaultIMEWnd;
160
161 gImmApiEntries.pImmNotifyIME = (BOOL (WINAPI*)(HIMC, DWORD, DWORD, DWORD)) GetProcAddress(imm32, "ImmNotifyIME");
162 if (!gImmApiEntries.pImmNotifyIME)
163 gImmApiEntries.pImmNotifyIME = IMM_ImmNotifyIME;
164
165 /*
166 * TODO: Load more functions from imm32.dll
167 * Function like IMPSetIMEW, IMPQueryIMEW etc. call functions
168 * from imm32.dll through pointers in the structure gImmApiEntries.
169 * I do not know whether it is necessary to initialize a table
170 * of functions to load user32 (DLL_PROCESS_ATTACH)
171 */
172
173 gImmApiEntries.pImmRegisterClient = (BOOL (WINAPI*)(PVOID, HINSTANCE)) GetProcAddress(imm32, "ImmRegisterClient");
174 if (!gImmApiEntries.pImmRegisterClient)
175 gImmApiEntries.pImmRegisterClient = IMM_ImmRegisterClient;
176
177 gImmApiEntries.pImmProcessKey = (UINT (WINAPI*)(HWND, HKL, UINT, LPARAM, DWORD)) GetProcAddress(imm32, "ImmProcessKey");
178 if (!gImmApiEntries.pImmProcessKey)
179 gImmApiEntries.pImmProcessKey = IMM_ImmProcessKey;
180
181 return TRUE;
182 }
183
184 BOOL WINAPI InitializeImmEntryTable(VOID)
185 {
186 bImmInitializing = TRUE;
187 return IntInitializeImmEntryTable();
188 }
189
190 BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
191 {
192 TRACE("(%x)\n", magic);
193
194 if (magic != IMM_INIT_MAGIC)
195 return FALSE;
196
197 if (gImmApiEntries.pImmIsIME != 0)
198 {
199 ERR("Imm Api Table Init 2\n");
200 return TRUE;
201 }
202
203 IntInitializeImmEntryTable();
204
205 if (ghImm32 == NULL && !bImmInitializing)
206 {
207 WCHAR ImmFile[MAX_PATH];
208 ERR("IMM32 not installed!\n");
209 GetImmFileName(ImmFile, sizeof(ImmFile));
210 ERR("File %ws\n",ImmFile);
211 ghImm32 = LoadLibraryW(ImmFile);
212 if (ghImm32 == NULL)
213 {
214 ERR("Did not load! 2\n");
215 return FALSE;
216 }
217 }
218 #if 0 // For real Imm32.dll testing!!!!
219 if (ghImm32 && !gImmApiEntries.pImmRegisterClient(&gSharedInfo, ghImm32))
220 {
221 ERR("Wine is stubed!\n");
222 }
223 #endif
224 return TRUE;
225 }
226
227 LRESULT WINAPI ImeWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode ) // ReactOS
228 {
229 PWND pWnd;
230 PIMEUI pimeui;
231
232 pWnd = ValidateHwnd(hwnd);
233 if (pWnd)
234 {
235 if (!pWnd->fnid)
236 {
237 if (msg != WM_NCCREATE)
238 {
239 if (unicode)
240 return DefWindowProcW(hwnd, msg, wParam, lParam);
241 return DefWindowProcA(hwnd, msg, wParam, lParam);
242 }
243 NtUserSetWindowFNID(hwnd, FNID_IME);
244 pimeui = HeapAlloc( GetProcessHeap(), 0, sizeof(IMEUI) );
245 SetWindowLongPtrW(hwnd, 0, (LONG_PTR)pimeui);
246 }
247 else
248 {
249 if (pWnd->fnid != FNID_IME)
250 {
251 ERR("Wrong window class for Ime! fnId 0x%x\n",pWnd->fnid);
252 return 0;
253 }
254 pimeui = ((PIMEWND)pWnd)->pimeui;
255 if (pimeui == NULL)
256 {
257 ERR("Window is not set to IME!\n");
258 return 0;
259 }
260 }
261 }
262
263 if (msg==WM_CREATE || msg==WM_NCCREATE)
264 return TRUE;
265
266 if (msg==WM_NCDESTROY)
267 {
268 HeapFree( GetProcessHeap(), 0, pimeui );
269 SetWindowLongPtrW(hwnd, 0, 0);
270 NtUserSetWindowFNID(hwnd, FNID_DESTROY);
271 }
272
273 if (unicode)
274 return DefWindowProcW(hwnd, msg, wParam, lParam);
275 return DefWindowProcA(hwnd, msg, wParam, lParam);
276 }
277
278 LRESULT WINAPI ImeWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
279 {
280 return ImeWndProc_common(hwnd, msg, wParam, lParam, FALSE);
281 }
282
283 LRESULT WINAPI ImeWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
284 {
285 return ImeWndProc_common(hwnd, msg, wParam, lParam, TRUE);
286 }
287
288 static const WCHAR imeW[] = {'I','M','E',0};
289
290 BOOL
291 WINAPI
292 RegisterIMEClass(VOID)
293 {
294 WNDCLASSEXW WndClass;
295 ATOM atom;
296
297 ZeroMemory(&WndClass, sizeof(WndClass));
298
299 WndClass.cbSize = sizeof(WndClass);
300 WndClass.lpszClassName = imeW;
301 WndClass.style = CS_GLOBALCLASS;
302 WndClass.lpfnWndProc = ImeWndProcW;
303 WndClass.cbWndExtra = sizeof(LONG_PTR);
304 WndClass.hCursor = LoadCursorW(NULL, IDC_ARROW);
305
306 atom = RegisterClassExWOWW( &WndClass,
307 0,
308 FNID_IME,
309 0,
310 FALSE);
311 if (atom)
312 {
313 RegisterDefaultClasses |= ICLASS_TO_MASK(ICLS_IME);
314 return TRUE;
315 }
316 ERR("Failed to register IME Class!\n");
317 return FALSE;
318 }
319
320 /*
321 * @unimplemented
322 */
323 BOOL WINAPI CliImmSetHotKey(DWORD dwID, UINT uModifiers, UINT uVirtualKey, HKL hKl)
324 {
325 UNIMPLEMENTED;
326 return FALSE;
327 }
328
329 /*
330 * @unimplemented
331 */
332 BOOL
333 WINAPI
334 IMPSetIMEW(HWND hwnd, LPIMEPROW ime)
335 {
336 UNIMPLEMENTED;
337 return FALSE;
338 }
339
340 /*
341 * @unimplemented
342 */
343 BOOL
344 WINAPI
345 IMPQueryIMEW(LPIMEPROW ime)
346 {
347 UNIMPLEMENTED;
348 return FALSE;
349 }
350
351 /*
352 * @unimplemented
353 */
354 BOOL
355 WINAPI
356 IMPGetIMEW(HWND hwnd, LPIMEPROW ime)
357 {
358 UNIMPLEMENTED;
359 return FALSE;
360 }
361
362 /*
363 * @unimplemented
364 */
365 BOOL
366 WINAPI
367 IMPSetIMEA(HWND hwnd, LPIMEPROA ime)
368 {
369 UNIMPLEMENTED;
370 return FALSE;
371 }
372
373 /*
374 * @unimplemented
375 */
376 BOOL
377 WINAPI
378 IMPQueryIMEA(LPIMEPROA ime)
379 {
380 UNIMPLEMENTED;
381 return FALSE;
382 }
383
384 /*
385 * @unimplemented
386 */
387 BOOL
388 WINAPI
389 IMPGetIMEA(HWND hwnd, LPIMEPROA ime)
390 {
391 UNIMPLEMENTED;
392 return FALSE;
393 }
394
395 /*
396 * @unimplemented
397 */
398 LRESULT
399 WINAPI
400 SendIMEMessageExW(HWND hwnd, LPARAM lparam)
401 {
402 UNIMPLEMENTED;
403 return FALSE;
404 }
405
406 /*
407 * @unimplemented
408 */
409 LRESULT
410 WINAPI
411 SendIMEMessageExA(HWND hwnd, LPARAM lparam)
412 {
413 UNIMPLEMENTED;
414 return FALSE;
415 }
416
417 /*
418 * @unimplemented
419 */
420 BOOL
421 WINAPI
422 WINNLSEnableIME(HWND hwnd, BOOL enable)
423 {
424 UNIMPLEMENTED;
425 return FALSE;
426 }
427
428 /*
429 * @unimplemented
430 */
431 BOOL
432 WINAPI
433 WINNLSGetEnableStatus(HWND hwnd)
434 {
435 UNIMPLEMENTED;
436 return FALSE;
437 }
438
439 /*
440 * @implemented
441 */
442 UINT
443 WINAPI
444 WINNLSGetIMEHotkey(HWND hwnd)
445 {
446 return FALSE;
447 }