1 /* 2 * ReactOS kernel 3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 */ 19 /* 20 * PROJECT: ReactOS user32.dll 21 * FILE: win32ss/user/user32/windows/input.c 22 * PURPOSE: Input 23 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 24 * UPDATE HISTORY: 25 * 09-05-2001 CSH Created 26 */ 27 28 /* INCLUDES ******************************************************************/ 29 30 #include <user32.h> 31 32 #include <strsafe.h> 33 34 #include <wine/debug.h> 35 WINE_DEFAULT_DEBUG_CHANNEL(user32); 36 37 /* GLOBALS *******************************************************************/ 38 39 40 41 /* FUNCTIONS *****************************************************************/ 42 43 44 /* 45 * @implemented 46 */ 47 BOOL 48 WINAPI 49 DragDetect( 50 HWND hWnd, 51 POINT pt) 52 { 53 return NtUserDragDetect(hWnd, pt); 54 #if 0 55 MSG msg; 56 RECT rect; 57 POINT tmp; 58 ULONG dx = GetSystemMetrics(SM_CXDRAG); 59 ULONG dy = GetSystemMetrics(SM_CYDRAG); 60 61 rect.left = pt.x - dx; 62 rect.right = pt.x + dx; 63 rect.top = pt.y - dy; 64 rect.bottom = pt.y + dy; 65 66 SetCapture(hWnd); 67 68 for (;;) 69 { 70 while ( 71 PeekMessageW(&msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) || 72 PeekMessageW(&msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) 73 ) 74 { 75 if (msg.message == WM_LBUTTONUP) 76 { 77 ReleaseCapture(); 78 return FALSE; 79 } 80 if (msg.message == WM_MOUSEMOVE) 81 { 82 tmp.x = LOWORD(msg.lParam); 83 tmp.y = HIWORD(msg.lParam); 84 if (!PtInRect(&rect, tmp)) 85 { 86 ReleaseCapture(); 87 return TRUE; 88 } 89 } 90 if (msg.message == WM_KEYDOWN) 91 { 92 if (msg.wParam == VK_ESCAPE) 93 { 94 ReleaseCapture(); 95 return TRUE; 96 } 97 } 98 } 99 WaitMessage(); 100 } 101 return 0; 102 #endif 103 } 104 105 /* 106 * @implemented 107 */ 108 BOOL WINAPI 109 EnableWindow(HWND hWnd, BOOL bEnable) 110 { 111 return NtUserxEnableWindow(hWnd, bEnable); 112 } 113 114 /* 115 * @implemented 116 */ 117 SHORT 118 WINAPI 119 DECLSPEC_HOTPATCH 120 GetAsyncKeyState(int vKey) 121 { 122 if (vKey < 0 || vKey > 256) 123 return 0; 124 return (SHORT)NtUserGetAsyncKeyState((DWORD)vKey); 125 } 126 127 128 /* 129 * @implemented 130 */ 131 HKL WINAPI 132 GetKeyboardLayout(DWORD idThread) 133 { 134 return NtUserxGetKeyboardLayout(idThread); 135 } 136 137 138 /* 139 * @implemented 140 */ 141 UINT WINAPI 142 GetKBCodePage(VOID) 143 { 144 return GetOEMCP(); 145 } 146 147 148 /* 149 * @implemented 150 */ 151 int WINAPI 152 GetKeyNameTextA(LONG lParam, 153 LPSTR lpString, 154 int nSize) 155 { 156 LPWSTR pwszBuf; 157 UINT cchBuf = 0; 158 int iRet = 0; 159 BOOL defChar = FALSE; 160 161 pwszBuf = HeapAlloc(GetProcessHeap(), 0, nSize * sizeof(WCHAR)); 162 if (!pwszBuf) 163 return 0; 164 165 cchBuf = NtUserGetKeyNameText(lParam, pwszBuf, nSize); 166 167 iRet = WideCharToMultiByte(CP_ACP, 0, 168 pwszBuf, cchBuf, 169 lpString, nSize, ".", &defChar); // FIXME: do we need defChar? 170 lpString[iRet] = 0; 171 HeapFree(GetProcessHeap(), 0, pwszBuf); 172 173 return iRet; 174 } 175 176 /* 177 * @implemented 178 */ 179 int WINAPI 180 GetKeyNameTextW(LONG lParam, 181 LPWSTR lpString, 182 int nSize) 183 { 184 return NtUserGetKeyNameText(lParam, lpString, nSize); 185 } 186 187 /* 188 * @implemented 189 */ 190 SHORT 191 WINAPI 192 DECLSPEC_HOTPATCH 193 GetKeyState(int nVirtKey) 194 { 195 return (SHORT)NtUserGetKeyState((DWORD)nVirtKey); 196 } 197 198 /* 199 * @implemented 200 */ 201 BOOL WINAPI 202 GetKeyboardLayoutNameA(LPSTR pwszKLID) 203 { 204 WCHAR buf[KL_NAMELENGTH]; 205 206 if (!GetKeyboardLayoutNameW(buf)) 207 return FALSE; 208 209 if (!WideCharToMultiByte(CP_ACP, 0, buf, -1, pwszKLID, KL_NAMELENGTH, NULL, NULL)) 210 return FALSE; 211 212 return TRUE; 213 } 214 215 /* 216 * @implemented 217 */ 218 BOOL WINAPI 219 GetKeyboardLayoutNameW(LPWSTR pwszKLID) 220 { 221 return NtUserGetKeyboardLayoutName(pwszKLID); 222 } 223 224 /* 225 * @implemented 226 */ 227 int WINAPI 228 GetKeyboardType(int nTypeFlag) 229 { 230 return NtUserxGetKeyboardType(nTypeFlag); 231 } 232 233 /* 234 * @implemented 235 */ 236 BOOL WINAPI 237 GetLastInputInfo(PLASTINPUTINFO plii) 238 { 239 TRACE("%p\n", plii); 240 241 if (plii->cbSize != sizeof (*plii)) 242 { 243 SetLastError(ERROR_INVALID_PARAMETER); 244 return FALSE; 245 } 246 247 plii->dwTime = gpsi->dwLastRITEventTickCount; 248 return TRUE; 249 } 250 251 /* 252 * @implemented 253 */ 254 HKL WINAPI 255 LoadKeyboardLayoutA(LPCSTR pszKLID, 256 UINT Flags) 257 { 258 WCHAR wszKLID[16]; 259 260 if (!MultiByteToWideChar(CP_ACP, 0, pszKLID, -1, 261 wszKLID, sizeof(wszKLID)/sizeof(wszKLID[0]))) 262 { 263 return FALSE; 264 } 265 266 return LoadKeyboardLayoutW(wszKLID, Flags); 267 } 268 269 /* 270 * @implemented 271 */ 272 HKL WINAPI 273 LoadKeyboardLayoutW(LPCWSTR pwszKLID, 274 UINT Flags) 275 { 276 DWORD dwhkl, dwType, dwSize; 277 UNICODE_STRING ustrKbdName; 278 UNICODE_STRING ustrKLID; 279 WCHAR wszRegKey[256] = L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\"; 280 WCHAR wszLayoutId[10], wszNewKLID[10]; 281 HKEY hKey; 282 283 /* LOWORD of dwhkl is Locale Identifier */ 284 dwhkl = LOWORD(wcstoul(pwszKLID, NULL, 16)); 285 286 if (Flags & KLF_SUBSTITUTE_OK) 287 { 288 /* Check substitutes key */ 289 if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Substitutes", 0, 290 KEY_READ, &hKey) == ERROR_SUCCESS) 291 { 292 dwSize = sizeof(wszNewKLID); 293 if (RegQueryValueExW(hKey, pwszKLID, NULL, &dwType, (LPBYTE)wszNewKLID, &dwSize) == ERROR_SUCCESS) 294 { 295 /* Use new KLID value */ 296 pwszKLID = wszNewKLID; 297 } 298 299 /* Close the key now */ 300 RegCloseKey(hKey); 301 } 302 } 303 304 /* Append KLID at the end of registry key */ 305 StringCbCatW(wszRegKey, sizeof(wszRegKey), pwszKLID); 306 307 /* Open layout registry key for read */ 308 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegKey, 0, 309 KEY_READ, &hKey) == ERROR_SUCCESS) 310 { 311 dwSize = sizeof(wszLayoutId); 312 if (RegQueryValueExW(hKey, L"Layout Id", NULL, &dwType, (LPBYTE)wszLayoutId, &dwSize) == ERROR_SUCCESS) 313 { 314 /* If Layout Id is specified, use this value | f000 as HIWORD */ 315 /* FIXME: Microsoft Office expects this value to be something specific 316 * for Japanese and Korean Windows with an IME the value is 0xe001 317 * We should probably check to see if an IME exists and if so then 318 * set this word properly. 319 */ 320 dwhkl |= (0xf000 | wcstol(wszLayoutId, NULL, 16)) << 16; 321 } 322 323 /* Close the key now */ 324 RegCloseKey(hKey); 325 } 326 else 327 { 328 ERR("Could not find keyboard layout %S.\n", pwszKLID); 329 return NULL; 330 } 331 332 /* If Layout Id is not given HIWORD == LOWORD (for dwhkl) */ 333 if (!HIWORD(dwhkl)) 334 dwhkl |= dwhkl << 16; 335 336 ZeroMemory(&ustrKbdName, sizeof(ustrKbdName)); 337 RtlInitUnicodeString(&ustrKLID, pwszKLID); 338 return NtUserLoadKeyboardLayoutEx(NULL, 0, &ustrKbdName, 339 NULL, &ustrKLID, 340 dwhkl, Flags); 341 } 342 343 /* 344 * @implemented 345 */ 346 UINT WINAPI 347 MapVirtualKeyA(UINT uCode, 348 UINT uMapType) 349 { 350 return MapVirtualKeyExA(uCode, uMapType, GetKeyboardLayout(0)); 351 } 352 353 /* 354 * @implemented 355 */ 356 UINT WINAPI 357 MapVirtualKeyExA(UINT uCode, 358 UINT uMapType, 359 HKL dwhkl) 360 { 361 return MapVirtualKeyExW(uCode, uMapType, dwhkl); 362 } 363 364 365 /* 366 * @implemented 367 */ 368 UINT WINAPI 369 MapVirtualKeyExW(UINT uCode, 370 UINT uMapType, 371 HKL dwhkl) 372 { 373 return NtUserMapVirtualKeyEx(uCode, uMapType, 0, dwhkl); 374 } 375 376 377 /* 378 * @implemented 379 */ 380 UINT WINAPI 381 MapVirtualKeyW(UINT uCode, 382 UINT uMapType) 383 { 384 return MapVirtualKeyExW(uCode, uMapType, GetKeyboardLayout(0)); 385 } 386 387 388 /* 389 * @implemented 390 */ 391 DWORD WINAPI 392 OemKeyScan(WORD wOemChar) 393 { 394 WCHAR p; 395 SHORT Vk; 396 UINT Scan; 397 398 MultiByteToWideChar(CP_OEMCP, 0, (PCSTR)&wOemChar, 1, &p, 1); 399 Vk = VkKeyScanW(p); 400 Scan = MapVirtualKeyW((Vk & 0x00ff), 0); 401 if (!Scan) return -1; 402 /* 403 Page 450-1, MS W2k SuperBible by SAMS. Return, low word has the 404 scan code and high word has the shift state. 405 */ 406 return ((Vk & 0xff00) << 8) | Scan; 407 } 408 409 410 /* 411 * @implemented 412 */ 413 BOOL WINAPI 414 SetDoubleClickTime(UINT uInterval) 415 { 416 return (BOOL)NtUserSystemParametersInfo(SPI_SETDOUBLECLICKTIME, 417 uInterval, 418 NULL, 419 0); 420 } 421 422 423 /* 424 * @implemented 425 */ 426 BOOL 427 WINAPI 428 SwapMouseButton( 429 BOOL fSwap) 430 { 431 return NtUserxSwapMouseButton(fSwap); 432 } 433 434 435 /* 436 * @implemented 437 */ 438 int WINAPI 439 ToAscii(UINT uVirtKey, 440 UINT uScanCode, 441 CONST BYTE *lpKeyState, 442 LPWORD lpChar, 443 UINT uFlags) 444 { 445 return ToAsciiEx(uVirtKey, uScanCode, lpKeyState, lpChar, uFlags, 0); 446 } 447 448 449 /* 450 * @implemented 451 */ 452 int WINAPI 453 ToAsciiEx(UINT uVirtKey, 454 UINT uScanCode, 455 CONST BYTE *lpKeyState, 456 LPWORD lpChar, 457 UINT uFlags, 458 HKL dwhkl) 459 { 460 WCHAR UniChars[2]; 461 int Ret, CharCount; 462 463 Ret = ToUnicodeEx(uVirtKey, uScanCode, lpKeyState, UniChars, 2, uFlags, dwhkl); 464 CharCount = (Ret < 0 ? 1 : Ret); 465 WideCharToMultiByte(CP_ACP, 0, UniChars, CharCount, (LPSTR)lpChar, 2, NULL, NULL); 466 467 return Ret; 468 } 469 470 471 /* 472 * @implemented 473 */ 474 int WINAPI 475 ToUnicode(UINT wVirtKey, 476 UINT wScanCode, 477 CONST BYTE *lpKeyState, 478 LPWSTR pwszBuff, 479 int cchBuff, 480 UINT wFlags) 481 { 482 return ToUnicodeEx(wVirtKey, wScanCode, lpKeyState, pwszBuff, cchBuff, 483 wFlags, 0); 484 } 485 486 487 /* 488 * @implemented 489 */ 490 int WINAPI 491 ToUnicodeEx(UINT wVirtKey, 492 UINT wScanCode, 493 CONST BYTE *lpKeyState, 494 LPWSTR pwszBuff, 495 int cchBuff, 496 UINT wFlags, 497 HKL dwhkl) 498 { 499 return NtUserToUnicodeEx(wVirtKey, wScanCode, (PBYTE)lpKeyState, pwszBuff, cchBuff, 500 wFlags, dwhkl); 501 } 502 503 504 505 /* 506 * @implemented 507 */ 508 SHORT WINAPI 509 VkKeyScanA(CHAR ch) 510 { 511 WCHAR wChar; 512 513 if (IsDBCSLeadByte(ch)) 514 return -1; 515 516 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1); 517 return VkKeyScanW(wChar); 518 } 519 520 521 /* 522 * @implemented 523 */ 524 SHORT WINAPI 525 VkKeyScanExA(CHAR ch, 526 HKL dwhkl) 527 { 528 WCHAR wChar; 529 530 if (IsDBCSLeadByte(ch)) 531 return -1; 532 533 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1); 534 return VkKeyScanExW(wChar, dwhkl); 535 } 536 537 538 /* 539 * @implemented 540 */ 541 SHORT WINAPI 542 VkKeyScanExW(WCHAR ch, 543 HKL dwhkl) 544 { 545 return (SHORT)NtUserVkKeyScanEx(ch, dwhkl, TRUE); 546 } 547 548 549 /* 550 * @implemented 551 */ 552 SHORT WINAPI 553 VkKeyScanW(WCHAR ch) 554 { 555 return (SHORT)NtUserVkKeyScanEx(ch, 0, FALSE); 556 } 557 558 559 /* 560 * @implemented 561 */ 562 VOID 563 WINAPI 564 keybd_event( 565 BYTE bVk, 566 BYTE bScan, 567 DWORD dwFlags, 568 ULONG_PTR dwExtraInfo) 569 { 570 INPUT Input; 571 572 Input.type = INPUT_KEYBOARD; 573 Input.ki.wVk = bVk; 574 Input.ki.wScan = bScan; 575 Input.ki.dwFlags = dwFlags; 576 Input.ki.time = 0; 577 Input.ki.dwExtraInfo = dwExtraInfo; 578 579 NtUserSendInput(1, &Input, sizeof(INPUT)); 580 } 581 582 583 /* 584 * @implemented 585 */ 586 VOID 587 WINAPI 588 mouse_event( 589 DWORD dwFlags, 590 DWORD dx, 591 DWORD dy, 592 DWORD dwData, 593 ULONG_PTR dwExtraInfo) 594 { 595 INPUT Input; 596 597 Input.type = INPUT_MOUSE; 598 Input.mi.dx = dx; 599 Input.mi.dy = dy; 600 Input.mi.mouseData = dwData; 601 Input.mi.dwFlags = dwFlags; 602 Input.mi.time = 0; 603 Input.mi.dwExtraInfo = dwExtraInfo; 604 605 NtUserSendInput(1, &Input, sizeof(INPUT)); 606 } 607 608 /* EOF */ 609