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