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