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