xref: /reactos/win32ss/user/user32/misc/imm.c (revision 53221834)
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  * PROGRAMMERS:     Dmitry Chapyshev (dmitry@reactos.org)
7  *                  Katayama Hirofumi MZ (katayama.hirofumi.mz@gmail.com)
8  * UPDATE HISTORY:
9  *      01/27/2009  Created
10  */
11 
12 #include <user32.h>
13 #include <strsafe.h>
14 
15 WINE_DEFAULT_DEBUG_CHANNEL(user32);
16 
17 #define IMM_INIT_MAGIC 0x19650412
18 
19 /* Is != NULL when we have loaded the IMM ourselves */
20 HINSTANCE ghImm32 = NULL;
21 
22 BOOL bImmInitializing = FALSE;
23 
24 /* define stub functions */
25 #undef DEFINE_IMM_ENTRY
26 #define DEFINE_IMM_ENTRY(type, name, params, retval, retkind) \
27     static type WINAPI IMMSTUB_##name params { IMM_RETURN_##retkind((type)retval); }
28 #include "immtable.h"
29 
30 Imm32ApiTable gImmApiEntries = {
31 /* initialize by stubs */
32 #undef DEFINE_IMM_ENTRY
33 #define DEFINE_IMM_ENTRY(type, name, params, retval, retkind) \
34     IMMSTUB_##name,
35 #include "immtable.h"
36 };
37 
38 HRESULT
39 GetImmFileName(_Out_ LPWSTR lpBuffer,
40                _In_ size_t cchBuffer)
41 {
42     UINT length = GetSystemDirectoryW(lpBuffer, cchBuffer);
43     if (length && length < cchBuffer)
44     {
45         StringCchCatW(lpBuffer, cchBuffer, L"\\");
46         return StringCchCatW(lpBuffer, cchBuffer, L"imm32.dll");
47     }
48     return StringCchCopyW(lpBuffer, cchBuffer, L"imm32.dll");
49 }
50 
51 /*
52  * @unimplemented
53  */
54 static BOOL IntInitializeImmEntryTable(VOID)
55 {
56     WCHAR ImmFile[MAX_PATH];
57     HMODULE imm32 = ghImm32;
58 
59     /* Check whether the IMM table has already been initialized */
60     if (IMM_FN(ImmWINNLSEnableIME) != IMMSTUB_ImmWINNLSEnableIME)
61         return TRUE;
62 
63     GetImmFileName(ImmFile, _countof(ImmFile));
64     TRACE("File %S\n", ImmFile);
65 
66     /* If IMM32 is already loaded, use it without increasing reference count. */
67     if (imm32 == NULL)
68         imm32 = GetModuleHandleW(ImmFile);
69 
70     /*
71      * Loading imm32.dll will call imm32!DllMain function.
72      * imm32!DllMain calls User32InitializeImmEntryTable.
73      * Thus, if imm32.dll was loaded, the table has been loaded.
74      */
75     if (imm32 == NULL)
76     {
77         imm32 = ghImm32 = LoadLibraryW(ImmFile);
78         if (imm32 == NULL)
79         {
80             ERR("Did not load imm32.dll!\n");
81             return FALSE;
82         }
83         return TRUE;
84     }
85 
86 /* load imm procedures */
87 #undef DEFINE_IMM_ENTRY
88 #define DEFINE_IMM_ENTRY(type, name, params, retval, retkind) \
89     do { \
90         FN_##name proc = (FN_##name)GetProcAddress(imm32, #name); \
91         if (!proc) { \
92             ERR("Could not load %s\n", #name); \
93             return FALSE; \
94         } \
95         IMM_FN(name) = proc; \
96     } while (0);
97 #include "immtable.h"
98 
99     return TRUE;
100 }
101 
102 BOOL WINAPI InitializeImmEntryTable(VOID)
103 {
104     bImmInitializing = TRUE;
105     return IntInitializeImmEntryTable();
106 }
107 
108 BOOL WINAPI User32InitializeImmEntryTable(DWORD magic)
109 {
110     TRACE("Imm (%x)\n", magic);
111 
112     if (magic != IMM_INIT_MAGIC)
113         return FALSE;
114 
115     /* Check whether the IMM table has already been initialized */
116     if (IMM_FN(ImmWINNLSEnableIME) != IMMSTUB_ImmWINNLSEnableIME)
117         return TRUE;
118 
119     IntInitializeImmEntryTable();
120 
121     if (ghImm32 == NULL && !bImmInitializing)
122     {
123         WCHAR ImmFile[MAX_PATH];
124         GetImmFileName(ImmFile, _countof(ImmFile));
125         ghImm32 = LoadLibraryW(ImmFile);
126         if (ghImm32 == NULL)
127         {
128             ERR("Did not load imm32.dll!\n");
129             return FALSE;
130         }
131     }
132 
133     return IMM_FN(ImmRegisterClient)(&gSharedInfo, ghImm32);
134 }
135 
136 LRESULT WINAPI ImeWndProc_common( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam, BOOL unicode ) // ReactOS
137 {
138     PWND pWnd;
139     PIMEUI pimeui;
140 
141     pWnd = ValidateHwnd(hwnd);
142     if (pWnd)
143     {
144        if (!pWnd->fnid)
145        {
146           if (msg != WM_NCCREATE)
147           {
148              if (unicode)
149                 return DefWindowProcW(hwnd, msg, wParam, lParam);
150              return DefWindowProcA(hwnd, msg, wParam, lParam);
151           }
152           NtUserSetWindowFNID(hwnd, FNID_IME);
153           pimeui = HeapAlloc( GetProcessHeap(), 0, sizeof(IMEUI) );
154           SetWindowLongPtrW(hwnd, 0, (LONG_PTR)pimeui);
155        }
156        else
157        {
158           if (pWnd->fnid != FNID_IME)
159           {
160              ERR("Wrong window class for Ime! fnId 0x%x\n",pWnd->fnid);
161              return 0;
162           }
163           pimeui = ((PIMEWND)pWnd)->pimeui;
164           if (pimeui == NULL)
165           {
166              ERR("Window is not set to IME!\n");
167              return 0;
168           }
169        }
170     }
171 
172     if (msg==WM_CREATE || msg==WM_NCCREATE)
173         return TRUE;
174 
175     if (msg==WM_NCDESTROY)
176     {
177         HeapFree( GetProcessHeap(), 0, pimeui );
178         SetWindowLongPtrW(hwnd, 0, 0);
179         NtUserSetWindowFNID(hwnd, FNID_DESTROY);
180     }
181 
182     if (unicode)
183        return DefWindowProcW(hwnd, msg, wParam, lParam);
184     return DefWindowProcA(hwnd, msg, wParam, lParam);
185 }
186 
187 LRESULT WINAPI ImeWndProcA( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
188 {
189     return ImeWndProc_common(hwnd, msg, wParam, lParam, FALSE);
190 }
191 
192 LRESULT WINAPI ImeWndProcW( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
193 {
194     return ImeWndProc_common(hwnd, msg, wParam, lParam, TRUE);
195 }
196 
197 BOOL
198 WINAPI
199 UpdatePerUserImmEnabling(VOID)
200 {
201   BOOL Ret = NtUserCallNoParam(NOPARAM_ROUTINE_UPDATEPERUSERIMMENABLING);
202   if ( Ret )
203   {
204     if ( gpsi->dwSRVIFlags & SRVINFO_IMM32 )
205     {
206       HMODULE imm32 = GetModuleHandleW(L"imm32.dll");
207       if ( !imm32 )
208       {
209         imm32 = LoadLibraryW(L"imm32.dll");
210         if (!imm32)
211         {
212            ERR("UPUIE: Imm32 not installed!\n");
213            Ret = FALSE;
214         }
215       }
216     }
217   }
218   return Ret;
219 }
220 
221 static const WCHAR imeW[] = {'I','M','E',0};
222 
223 BOOL
224 WINAPI
225 RegisterIMEClass(VOID)
226 {
227     WNDCLASSEXW WndClass;
228     ATOM atom;
229 
230     ZeroMemory(&WndClass, sizeof(WndClass));
231 
232     WndClass.cbSize = sizeof(WndClass);
233     WndClass.lpszClassName = imeW;
234     WndClass.style = CS_GLOBALCLASS;
235     WndClass.lpfnWndProc = ImeWndProcW;
236     WndClass.cbWndExtra = sizeof(LONG_PTR);
237     WndClass.hCursor = LoadCursorW(NULL, IDC_ARROW);
238 
239     atom = RegisterClassExWOWW( &WndClass,
240                                  0,
241                                  FNID_IME,
242                                  0,
243                                  FALSE);
244     if (atom)
245     {
246        RegisterDefaultClasses |= ICLASS_TO_MASK(ICLS_IME);
247        TRACE("Register IME Class!\n");
248        return TRUE;
249     }
250     ERR("Failed to register IME Class!\n");
251     return FALSE;
252 }
253 
254 /*
255  * @unimplemented
256  */
257 BOOL WINAPI CliImmSetHotKey(DWORD dwID, UINT uModifiers, UINT uVirtualKey, HKL hKl)
258 {
259   UNIMPLEMENTED;
260   return FALSE;
261 }
262 
263 /*
264  * @implemented
265  */
266 BOOL
267 WINAPI
268 IMPSetIMEW(HWND hwnd, LPIMEPROW ime)
269 {
270     return IMM_FN(ImmIMPSetIMEW)(hwnd, ime);
271 }
272 
273 /*
274  * @implemented
275  */
276 BOOL
277 WINAPI
278 IMPQueryIMEW(LPIMEPROW ime)
279 {
280     return IMM_FN(ImmIMPQueryIMEW)(ime);
281 }
282 
283 /*
284  * @implemented
285  */
286 BOOL
287 WINAPI
288 IMPGetIMEW(HWND hwnd, LPIMEPROW ime)
289 {
290     return IMM_FN(ImmIMPGetIMEW)(hwnd, ime);
291 }
292 
293 /*
294  * @implemented
295  */
296 BOOL
297 WINAPI
298 IMPSetIMEA(HWND hwnd, LPIMEPROA ime)
299 {
300     return IMM_FN(ImmIMPSetIMEA)(hwnd, ime);
301 }
302 
303 /*
304  * @implemented
305  */
306 BOOL
307 WINAPI
308 IMPQueryIMEA(LPIMEPROA ime)
309 {
310     return IMM_FN(ImmIMPQueryIMEA)(ime);
311 }
312 
313 /*
314  * @implemented
315  */
316 BOOL
317 WINAPI
318 IMPGetIMEA(HWND hwnd, LPIMEPROA ime)
319 {
320     return IMM_FN(ImmIMPGetIMEA)(hwnd, ime);
321 }
322 
323 /*
324  * @implemented
325  */
326 LRESULT
327 WINAPI
328 SendIMEMessageExW(HWND hwnd, LPARAM lParam)
329 {
330     return IMM_FN(ImmSendIMEMessageExW)(hwnd, lParam);
331 }
332 
333 /*
334  * @implemented
335  */
336 LRESULT
337 WINAPI
338 SendIMEMessageExA(HWND hwnd, LPARAM lParam)
339 {
340     return IMM_FN(ImmSendIMEMessageExA)(hwnd, lParam);
341 }
342 
343 /*
344  * @implemented
345  */
346 BOOL
347 WINAPI
348 WINNLSEnableIME(HWND hwnd, BOOL enable)
349 {
350     return IMM_FN(ImmWINNLSEnableIME)(hwnd, enable);
351 }
352 
353 /*
354  * @implemented
355  */
356 BOOL
357 WINAPI
358 WINNLSGetEnableStatus(HWND hwnd)
359 {
360     return IMM_FN(ImmWINNLSGetEnableStatus)(hwnd);
361 }
362 
363 /*
364  * @implemented
365  */
366 UINT
367 WINAPI
368 WINNLSGetIMEHotkey(HWND hwnd)
369 {
370     return FALSE;
371 }
372