Author: fireball Date: Wed Aug 5 20:10:41 2009 New Revision: 42409
URL: http://svn.reactos.org/svn/reactos?rev=42409&view=rev Log: Giannis Adamopoulos - Implement initial keyboard input support. - Bring EngLoadImage from trunk.
Added: branches/arwinss/reactos/subsystems/win32/win32k/include/keyboard.h (with props) branches/arwinss/reactos/subsystems/win32/win32k/main/kbdlayout.c (contents, props changed) - copied, changed from r42406, trunk/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c branches/arwinss/reactos/subsystems/win32/win32k/main/keyboard.c - copied, changed from r42406, trunk/reactos/subsystems/win32/win32k/ntuser/keyboard.c Modified: branches/arwinss/reactos/dll/win32/user32/legacy.c branches/arwinss/reactos/dll/win32/winent.drv/mouse.c branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c branches/arwinss/reactos/dll/win32/winent.drv/winent.h branches/arwinss/reactos/include/reactos/win32k/rosuser.h branches/arwinss/reactos/subsystems/win32/csrss/win32csr/input.c branches/arwinss/reactos/subsystems/win32/win32k/eng/engfile.c branches/arwinss/reactos/subsystems/win32/win32k/include/tags.h branches/arwinss/reactos/subsystems/win32/win32k/include/win32.h branches/arwinss/reactos/subsystems/win32/win32k/include/win32kp.h branches/arwinss/reactos/subsystems/win32/win32k/main/init.c branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db branches/arwinss/reactos/subsystems/win32/win32k/win32k.rbuild branches/arwinss/reactos/subsystems/win32/win32k/wine/main.c
Modified: branches/arwinss/reactos/dll/win32/user32/legacy.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/user32... ============================================================================== --- branches/arwinss/reactos/dll/win32/user32/legacy.c [iso-8859-1] (original) +++ branches/arwinss/reactos/dll/win32/user32/legacy.c [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -8,10 +8,10 @@ #include "winerror.h" #include "wine/winbase16.h" #include "wine/winuser16.h" +#include "wine/debug.h"
-#include "win32k/rosuser.h" - -#include "wine/debug.h" +VOID NTAPI +RosUserConnectCsrss();
WINE_DEFAULT_DEBUG_CHANNEL(userlegacy);
Modified: branches/arwinss/reactos/dll/win32/winent.drv/mouse.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/winent... ============================================================================== --- branches/arwinss/reactos/dll/win32/winent.drv/mouse.c [iso-8859-1] (original) +++ branches/arwinss/reactos/dll/win32/winent.drv/mouse.c [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -66,25 +66,13 @@ MOUSEEVENTF_XUP };
-BYTE key_state_table[256]; - -/*********************************************************************** - * clip_point_to_rect - * - * Clip point to the provided rectangle - */ -static inline void clip_point_to_rect( LPCRECT rect, LPPOINT pt ) -{ - if (pt->x < rect->left) pt->x = rect->left; - else if (pt->x >= rect->right) pt->x = rect->right - 1; - if (pt->y < rect->top) pt->y = rect->top; - else if (pt->y >= rect->bottom) pt->y = rect->bottom - 1; -} +static BYTE TrackSysKey = 0; /* determine whether ALT key up will cause a WM_SYSKEYUP + or a WM_KEYUP message */
/*********************************************************************** * get_key_state */ -static WORD get_key_state(void) +static WORD get_key_state(BYTE* key_state_table) { WORD ret = 0;
@@ -111,7 +99,8 @@ * queue_raw_mouse_message */ static void queue_raw_mouse_message( UINT message, HWND hwnd, DWORD x, DWORD y, - DWORD data, DWORD time, DWORD extra_info, UINT injected_flags ) + DWORD data, DWORD time, DWORD extra_info, UINT injected_flags, + BYTE* key_state_table) { MSLLHOOKSTRUCT hook;
@@ -129,7 +118,7 @@ req->id = (injected_flags & LLMHF_INJECTED) ? 0 : GetCurrentThreadId(); req->win = wine_server_user_handle( hwnd ); req->msg = message; - req->wparam = MAKEWPARAM( get_key_state(), data ); + req->wparam = MAKEWPARAM( get_key_state(key_state_table), data ); req->lparam = 0; req->x = x; req->y = y; @@ -143,13 +132,16 @@
/*********************************************************************** - * X11DRV_send_mouse_input - */ -void RosDrv_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y, + * NTDRV_SendMouseInput + */ +void NTDRV_SendMouseInput( HWND hwnd, DWORD flags, DWORD x, DWORD y, DWORD data, DWORD time, DWORD extra_info, UINT injected_flags ) { POINT pt; - POINT cursor_pos; + POINT cursor_pos; + BYTE key_state_table[256]; + + RosUserGetAsyncKeyboardState(key_state_table);
if (flags & MOUSEEVENTF_MOVE && flags & MOUSEEVENTF_ABSOLUTE) { @@ -200,73 +192,187 @@ if (flags & MOUSEEVENTF_MOVE) { queue_raw_mouse_message( WM_MOUSEMOVE, hwnd, pt.x, pt.y, data, time, - extra_info, injected_flags ); + extra_info, injected_flags, key_state_table ); RosDrv_SetCursorPos(pt.x, pt.y); - //if ((injected_flags & LLMHF_INJECTED) && - // ((flags & MOUSEEVENTF_ABSOLUTE) || x || y)) /* we have to actually move the cursor */ - //{ - // X11DRV_SetCursorPos( pt.x, pt.y ); - //} - //else - //{ - // wine_tsx11_lock(); - // clip_point_to_rect( &cursor_clip, &pt); - // cursor_pos = pt; - // wine_tsx11_unlock(); - //} } if (flags & MOUSEEVENTF_LEFTDOWN) { key_state_table[VK_LBUTTON] |= 0xc0; queue_raw_mouse_message( GetSystemMetrics(SM_SWAPBUTTON) ? WM_RBUTTONDOWN : WM_LBUTTONDOWN, - hwnd, pt.x, pt.y, data, time, extra_info, injected_flags ); + hwnd, pt.x, pt.y, data, time, extra_info, injected_flags, key_state_table ); } if (flags & MOUSEEVENTF_LEFTUP) { key_state_table[VK_LBUTTON] &= ~0x80; queue_raw_mouse_message( GetSystemMetrics(SM_SWAPBUTTON) ? WM_RBUTTONUP : WM_LBUTTONUP, - hwnd, pt.x, pt.y, data, time, extra_info, injected_flags ); + hwnd, pt.x, pt.y, data, time, extra_info, injected_flags, key_state_table ); } if (flags & MOUSEEVENTF_RIGHTDOWN) { key_state_table[VK_RBUTTON] |= 0xc0; queue_raw_mouse_message( GetSystemMetrics(SM_SWAPBUTTON) ? WM_LBUTTONDOWN : WM_RBUTTONDOWN, - hwnd, pt.x, pt.y, data, time, extra_info, injected_flags ); + hwnd, pt.x, pt.y, data, time, extra_info, injected_flags, key_state_table ); } if (flags & MOUSEEVENTF_RIGHTUP) { key_state_table[VK_RBUTTON] &= ~0x80; queue_raw_mouse_message( GetSystemMetrics(SM_SWAPBUTTON) ? WM_LBUTTONUP : WM_RBUTTONUP, - hwnd, pt.x, pt.y, data, time, extra_info, injected_flags ); + hwnd, pt.x, pt.y, data, time, extra_info, injected_flags, key_state_table ); } if (flags & MOUSEEVENTF_MIDDLEDOWN) { key_state_table[VK_MBUTTON] |= 0xc0; queue_raw_mouse_message( WM_MBUTTONDOWN, hwnd, pt.x, pt.y, data, time, - extra_info, injected_flags ); + extra_info, injected_flags, key_state_table ); } if (flags & MOUSEEVENTF_MIDDLEUP) { key_state_table[VK_MBUTTON] &= ~0x80; queue_raw_mouse_message( WM_MBUTTONUP, hwnd, pt.x, pt.y, data, time, - extra_info, injected_flags ); + extra_info, injected_flags, key_state_table ); } if (flags & MOUSEEVENTF_WHEEL) { queue_raw_mouse_message( WM_MOUSEWHEEL, hwnd, pt.x, pt.y, data, time, - extra_info, injected_flags ); + extra_info, injected_flags, key_state_table ); } if (flags & MOUSEEVENTF_XDOWN) { key_state_table[VK_XBUTTON1 + data - 1] |= 0xc0; queue_raw_mouse_message( WM_XBUTTONDOWN, hwnd, pt.x, pt.y, data, time, - extra_info, injected_flags ); + extra_info, injected_flags, key_state_table ); } if (flags & MOUSEEVENTF_XUP) { key_state_table[VK_XBUTTON1 + data - 1] &= ~0x80; queue_raw_mouse_message( WM_XBUTTONUP, hwnd, pt.x, pt.y, data, time, - extra_info, injected_flags ); - } + extra_info, injected_flags, key_state_table ); + } + + RosUserSetAsyncKeyboardState(key_state_table); }
+ +/*********************************************************************** + * NTDRV_SendKeyboardInput + */ +void NTDRV_SendKeyboardInput( WORD wVk, WORD wScan, DWORD event_flags, DWORD time, + DWORD dwExtraInfo, UINT injected_flags ) +{ + UINT message; + KBDLLHOOKSTRUCT hook; + WORD flags, wVkStripped, wVkL, wVkR, vk_hook = wVk; + BYTE key_state_table[256]; + POINT cursor_pos; + + RosUserGetAsyncKeyboardState(key_state_table); + + wVk = LOBYTE(wVk); + flags = LOBYTE(wScan); + + if (event_flags & KEYEVENTF_EXTENDEDKEY) flags |= KF_EXTENDED; + /* FIXME: set KF_DLGMODE and KF_MENUMODE when needed */ + + /* strip left/right for menu, control, shift */ + switch (wVk) + { + case VK_MENU: + case VK_LMENU: + case VK_RMENU: + wVk = (event_flags & KEYEVENTF_EXTENDEDKEY) ? VK_RMENU : VK_LMENU; + wVkStripped = VK_MENU; + wVkL = VK_LMENU; + wVkR = VK_RMENU; + break; + case VK_CONTROL: + case VK_LCONTROL: + case VK_RCONTROL: + wVk = (event_flags & KEYEVENTF_EXTENDEDKEY) ? VK_RCONTROL : VK_LCONTROL; + wVkStripped = VK_CONTROL; + wVkL = VK_LCONTROL; + wVkR = VK_RCONTROL; + break; + case VK_SHIFT: + case VK_LSHIFT: + case VK_RSHIFT: + wVk = (event_flags & KEYEVENTF_EXTENDEDKEY) ? VK_RSHIFT : VK_LSHIFT; + wVkStripped = VK_SHIFT; + wVkL = VK_LSHIFT; + wVkR = VK_RSHIFT; + break; + default: + wVkStripped = wVkL = wVkR = wVk; + } + + if (event_flags & KEYEVENTF_KEYUP) + { + message = WM_KEYUP; + if ((key_state_table[VK_MENU] & 0x80) && + ((wVkStripped == VK_MENU) || (wVkStripped == VK_CONTROL) + || !(key_state_table[VK_CONTROL] & 0x80))) + { + if( TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */ + (wVkStripped != VK_MENU)) /* <ALT>-down...<something else>-up */ + message = WM_SYSKEYUP; + TrackSysKey = 0; + } + flags |= KF_REPEAT | KF_UP; + } + else + { + message = WM_KEYDOWN; + if ((key_state_table[VK_MENU] & 0x80 || wVkStripped == VK_MENU) && + !(key_state_table[VK_CONTROL] & 0x80 || wVkStripped == VK_CONTROL)) + { + message = WM_SYSKEYDOWN; + TrackSysKey = wVkStripped; + } + if (key_state_table[wVk] & 0x80) flags |= KF_REPEAT; + } + + TRACE("KEY: wParam=%04x, lParam=%08lx, InputKeyState=%x\n", + wVk, MAKELPARAM( 1, flags ), key_state_table[wVk] ); + + /* Hook gets whatever key was sent. */ + hook.vkCode = vk_hook; + hook.scanCode = wScan; + hook.flags = (flags >> 8) | injected_flags; + hook.time = time; + hook.dwExtraInfo = dwExtraInfo; + if (HOOK_CallHooks( WH_KEYBOARD_LL, HC_ACTION, message, (LPARAM)&hook, TRUE )) return; + + if (event_flags & KEYEVENTF_KEYUP) + { + key_state_table[wVk] &= ~0x80; + key_state_table[wVkStripped] = key_state_table[wVkL] | key_state_table[wVkR]; + } + else + { + if (!(key_state_table[wVk] & 0x80)) key_state_table[wVk] ^= 0x01; + key_state_table[wVk] |= 0xc0; + key_state_table[wVkStripped] = key_state_table[wVkL] | key_state_table[wVkR]; + } + + if (key_state_table[VK_MENU] & 0x80) flags |= KF_ALTDOWN; + + if (wVkStripped == VK_SHIFT) flags &= ~KF_EXTENDED; + + GetCursorPos(&cursor_pos); + + SERVER_START_REQ( send_hardware_message ) + { + req->id = (injected_flags & LLKHF_INJECTED) ? 0 : GetCurrentThreadId(); + req->win = 0; + req->msg = message; + req->wparam = wVk; + req->lparam = MAKELPARAM( 1 /* repeat count */, flags ); + req->x = cursor_pos.x; + req->y = cursor_pos.y; + req->time = time; + req->info = dwExtraInfo; + wine_server_call( req ); + } + SERVER_END_REQ; + + RosUserSetAsyncKeyboardState(key_state_table); +}
Modified: branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/winent... ============================================================================== --- branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c [iso-8859-1] (original) +++ branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -83,8 +83,7 @@
HKL CDECL RosDrv_ActivateKeyboardLayout( HKL layout, UINT flags ) { - UNIMPLEMENTED; - return 0; + return RosUserActivateKeyboardLayout(layout, flags); }
void CDECL RosDrv_Beep(void) @@ -94,38 +93,33 @@
SHORT CDECL RosDrv_GetAsyncKeyState( INT key ) { - UNIMPLEMENTED; - return 0; + return RosUserGetAsyncKeyState( key ); }
INT CDECL RosDrv_GetKeyNameText( LONG lparam, LPWSTR buffer, INT size ) { - UNIMPLEMENTED; - return 0; + return RosUserGetKeyNameText(lparam, buffer, size); }
HKL CDECL RosDrv_GetKeyboardLayout( DWORD layout ) { - UNIMPLEMENTED; - return 0; + return RosUserGetKeyboardLayout(layout); }
BOOL CDECL RosDrv_GetKeyboardLayoutName( LPWSTR name ) { - UNIMPLEMENTED; - return FALSE; + return RosUserGetKeyboardLayoutName(name); }
HKL CDECL RosDrv_LoadKeyboardLayout( LPCWSTR name, UINT flags ) { - UNIMPLEMENTED; - return 0; + return RosUserLoadKeyboardLayoutEx( NULL, 0, NULL, NULL, NULL, + wcstoul(name, NULL, 16), flags); }
UINT CDECL RosDrv_MapVirtualKeyEx( UINT code, UINT type, HKL layout ) { - UNIMPLEMENTED; - return 0; + return RosUserMapVirtualKeyEx(code, type, 0, layout); }
UINT CDECL RosDrv_SendInput( UINT count, LPINPUT inputs, int size ) @@ -137,12 +131,13 @@ switch(inputs->type) { case INPUT_MOUSE: - RosDrv_send_mouse_input( 0, inputs->mi.dwFlags, inputs->mi.dx, inputs->mi.dy, + NTDRV_SendMouseInput( 0, inputs->mi.dwFlags, inputs->mi.dx, inputs->mi.dy, inputs->mi.mouseData, inputs->mi.time, inputs->mi.dwExtraInfo, LLMHF_INJECTED ); break; case INPUT_KEYBOARD: - FIXME( "INPUT_KEYBOARD not supported\n" ); + NTDRV_SendKeyboardInput( inputs->ki.wVk, inputs->ki.wScan, inputs->ki.dwFlags, + inputs->ki.time, inputs->ki.dwExtraInfo, LLKHF_INJECTED ); break; case INPUT_HARDWARE: FIXME( "INPUT_HARDWARE not supported\n" ); @@ -155,20 +150,17 @@ INT CDECL RosDrv_ToUnicodeEx( UINT virt, UINT scan, const BYTE *state, LPWSTR str, int size, UINT flags, HKL layout ) { - UNIMPLEMENTED; - return 0; + return RosUserToUnicodeEx(virt, scan, state, str, size, flags, layout); }
BOOL CDECL RosDrv_UnloadKeyboardLayout( HKL layout ) { - UNIMPLEMENTED; - return 0; + return RosUserUnloadKeyboardLayout(layout); }
SHORT CDECL RosDrv_VkKeyScanEx( WCHAR ch, HKL layout ) { - UNIMPLEMENTED; - return -1; + return RosUserVkKeyScanEx(ch, layout, TRUE); }
/***********************************************************************
Modified: branches/arwinss/reactos/dll/win32/winent.drv/winent.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/winent... ============================================================================== --- branches/arwinss/reactos/dll/win32/winent.drv/winent.h [iso-8859-1] (original) +++ branches/arwinss/reactos/dll/win32/winent.drv/winent.h [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -38,8 +38,11 @@ const RECT *lprect, LPCWSTR wstr, UINT count, const INT *lpDx );
-void RosDrv_send_mouse_input( HWND hwnd, DWORD flags, DWORD x, DWORD y, +void NTDRV_SendMouseInput( HWND hwnd, DWORD flags, DWORD x, DWORD y, DWORD data, DWORD time, DWORD extra_info, UINT injected_flags ); + +void NTDRV_SendKeyboardInput( WORD wVk, WORD wScan, DWORD event_flags, DWORD time, + DWORD dwExtraInfo, UINT injected_flags );
BOOL CDECL RosDrv_SetCursorPos( INT x, INT y );
Modified: branches/arwinss/reactos/include/reactos/win32k/rosuser.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/include/reactos/... ============================================================================== --- branches/arwinss/reactos/include/reactos/win32k/rosuser.h [iso-8859-1] (original) +++ branches/arwinss/reactos/include/reactos/win32k/rosuser.h [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -62,6 +62,77 @@ IN HMONITOR hMonitor, OUT LPMONITORINFO pMonitorInfo);
+HKL +APIENTRY +RosUserGetKeyboardLayout( + DWORD dwThreadId); + +BOOL +APIENTRY +RosUserGetKeyboardLayoutName( + LPWSTR lpszName); + +HKL +APIENTRY +RosUserLoadKeyboardLayoutEx( + IN HANDLE Handle, + IN DWORD offTable, + IN PUNICODE_STRING puszKeyboardName, + IN HKL hKL, + IN PUNICODE_STRING puszKLID, + IN DWORD dwKLID, + IN UINT Flags); + +HKL +APIENTRY +RosUserActivateKeyboardLayout( + HKL hKl, + ULONG Flags); + +BOOL +APIENTRY +RosUserUnloadKeyboardLayout( + HKL hKl); + +DWORD +APIENTRY +RosUserVkKeyScanEx( + WCHAR wChar, + HKL hKeyboardLayout, + BOOL UsehKL ); + +DWORD +APIENTRY +RosUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize ); + +int +APIENTRY +RosUserToUnicodeEx( + UINT wVirtKey, + UINT wScanCode, + PBYTE lpKeyState, + LPWSTR pwszBuff, + int cchBuff, + UINT wFlags, + HKL dwhkl ); + +UINT +APIENTRY +RosUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl ); + +SHORT +APIENTRY +RosUserGetAsyncKeyState( + INT key); + +BOOL +APIENTRY +RosUserSetAsyncKeyboardState(BYTE key_state_table[]); + +BOOL +APIENTRY +RosUserGetAsyncKeyboardState(BYTE key_state_table[]); + VOID NTAPI RosUserConnectCsrss();
Modified: branches/arwinss/reactos/subsystems/win32/csrss/win32csr/input.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/csrss/win32csr/input.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/csrss/win32csr/input.c [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -177,12 +177,195 @@ } }
+/* Sends the keyboard commands to turn on/off the lights. + */ +static NTSTATUS APIENTRY +IntKeyboardUpdateLeds(HANDLE KeyboardDeviceHandle, + PKEYBOARD_INPUT_DATA KeyInput, + PKEYBOARD_INDICATOR_TRANSLATION IndicatorTrans) +{ + NTSTATUS Status; + UINT Count; + static KEYBOARD_INDICATOR_PARAMETERS Indicators; + IO_STATUS_BLOCK Block; + + if (!IndicatorTrans) + return STATUS_NOT_SUPPORTED; + + if (KeyInput->Flags & (KEY_E0 | KEY_E1 | KEY_BREAK)) + return STATUS_SUCCESS; + + for (Count = 0; Count < IndicatorTrans->NumberOfIndicatorKeys; Count++) + { + if (KeyInput->MakeCode == IndicatorTrans->IndicatorList[Count].MakeCode) + { + Indicators.LedFlags ^= + IndicatorTrans->IndicatorList[Count].IndicatorFlags; + + /* Update the lights on the hardware */ + + Status = NtDeviceIoControlFile(KeyboardDeviceHandle, + NULL, + NULL, + NULL, + &Block, + IOCTL_KEYBOARD_SET_INDICATORS, + &Indicators, sizeof(Indicators), + NULL, 0); + + return Status; + } + } + + return STATUS_SUCCESS; +} + +/* Asks the keyboard driver to send a small table that shows which + * lights should connect with which scancodes + */ +static NTSTATUS APIENTRY +IntKeyboardGetIndicatorTrans(HANDLE KeyboardDeviceHandle, + PKEYBOARD_INDICATOR_TRANSLATION *IndicatorTrans) +{ + NTSTATUS Status; + DWORD Size = 0; + IO_STATUS_BLOCK Block; + PKEYBOARD_INDICATOR_TRANSLATION Ret; + + Size = sizeof(KEYBOARD_INDICATOR_TRANSLATION); + + Ret = HeapAlloc(Win32CsrApiHeap, 0, Size); + + while (Ret) + { + Status = NtDeviceIoControlFile(KeyboardDeviceHandle, + NULL, + NULL, + NULL, + &Block, + IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION, + NULL, + 0, + Ret, Size); + + if (Status != STATUS_BUFFER_TOO_SMALL) + break; + + HeapFree(Win32CsrApiHeap, 0, Ret); + + Size += sizeof(KEYBOARD_INDICATOR_TRANSLATION); + + Ret = HeapAlloc(Win32CsrApiHeap, 0, Size); + } + + if (!Ret) + return STATUS_INSUFFICIENT_RESOURCES; + + if (Status != STATUS_SUCCESS) + { + HeapFree(Win32CsrApiHeap, 0, Ret); + return Status; + } + + *IndicatorTrans = Ret; + return Status; +} + +DWORD WINAPI KeyboardInputThread(LPVOID lpParameter) +{ + UNICODE_STRING KeyboardDeviceName = RTL_CONSTANT_STRING(L"\Device\KeyboardClass0"); + OBJECT_ATTRIBUTES KeyboardObjectAttributes; + IO_STATUS_BLOCK Iosb; + HANDLE KeyboardDeviceHandle; + NTSTATUS Status; + PKEYBOARD_INDICATOR_TRANSLATION IndicatorTrans = NULL; + + InitializeObjectAttributes(&KeyboardObjectAttributes, + &KeyboardDeviceName, + 0, + NULL, + NULL); + + do + { + Sleep(1000); + Status = NtOpenFile(&KeyboardDeviceHandle, + FILE_ALL_ACCESS, + &KeyboardObjectAttributes, + &Iosb, + 0, + FILE_SYNCHRONOUS_IO_ALERT); + } while (!NT_SUCCESS(Status)); + + IntKeyboardGetIndicatorTrans(KeyboardDeviceHandle, + &IndicatorTrans); + while(1) + { + KEYBOARD_INPUT_DATA KeyInput; + DWORD flags; + + Status = NtReadFile(KeyboardDeviceHandle, + NULL, + NULL, + NULL, + &Iosb, + &KeyInput, + sizeof(KEYBOARD_INPUT_DATA), + NULL, + NULL); + + if(Status == STATUS_ALERTED) + { + break; + } + if(Status == STATUS_PENDING) + { + NtWaitForSingleObject(KeyboardDeviceHandle, FALSE, NULL); + Status = Iosb.Status; + } + if(!NT_SUCCESS(Status)) + { + DPRINT1("Win32K: Failed to read from mouse.\n"); + return Status; + } + + DPRINT("KeyRaw: %s %04x\n", + (KeyInput.Flags & KEY_BREAK) ? "up" : "down", + KeyInput.MakeCode ); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Win32K: Failed to read from keyboard.\n"); + return Status; + } + + IntKeyboardUpdateLeds(KeyboardDeviceHandle, + &KeyInput, + IndicatorTrans); + + flags = 0; + + if (KeyInput.Flags & KEY_E0) + flags |= KEYEVENTF_EXTENDEDKEY; + + if (KeyInput.Flags & KEY_BREAK) + flags |= KEYEVENTF_KEYUP; + + keybd_event(MapVirtualKey(KeyInput.MakeCode & 0xff, MAPVK_VSC_TO_VK), KeyInput.MakeCode & 0xff, flags , 0); + } + + return Status; +} +
void CsrInitInputSupport() { - HANDLE MouseThreadHandle; + HANDLE MouseThreadHandle, KeyboardThreadHandle;
ClipCursor(NULL);
MouseThreadHandle = CreateThread(NULL, 0, MouseInputThread, NULL, 0,NULL); -} + KeyboardThreadHandle = CreateThread(NULL, 0, KeyboardInputThread, NULL, 0,NULL); +} + +/* EOF */
Modified: branches/arwinss/reactos/subsystems/win32/win32k/eng/engfile.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/eng/engfile.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/eng/engfile.c [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -3,7 +3,7 @@ * LICENSE: GPL - See COPYING in the top level directory * FILE: subsystems/win32/win32k/eng/engfile.c * PURPOSE: File Support Routines - * PROGRAMMERS: Stefan Ginsberg (stefan__100__@hotmail.com) + * PROGRAMMERS: */
/* INCLUDES ******************************************************************/ @@ -12,6 +12,15 @@ #define NDEBUG #include <debug.h>
+typedef struct _DRIVERS +{ + LIST_ENTRY ListEntry; + HANDLE ImageHandle; + UNICODE_STRING DriverName; +}DRIVERS, *PDRIVERS; + +extern LIST_ENTRY GlobalDriverListHead; + /* PUBLIC FUNCTIONS **********************************************************/
BOOL @@ -19,7 +28,7 @@ EngDeleteFile(IN PWSTR pwszFileName) { UNIMPLEMENTED; - return FALSE; + return FALSE; }
NTSTATUS @@ -64,12 +73,55 @@ return FALSE; }
+ +/* + * @implemented + */ HANDLE APIENTRY -EngLoadImage(IN PWSTR pwszDriver) -{ - UNIMPLEMENTED; - return NULL; +EngLoadImage (LPWSTR DriverName) +{ + HANDLE hImageHandle = NULL; + SYSTEM_GDI_DRIVER_INFORMATION GdiDriverInfo; + NTSTATUS Status; + + RtlInitUnicodeString(&GdiDriverInfo.DriverName, DriverName); + if( !IsListEmpty(&GlobalDriverListHead) ) + { + PLIST_ENTRY CurrentEntry = GlobalDriverListHead.Flink; + PDRIVERS Current; + /* probably the driver was already loaded, let's try to find it out */ + while( CurrentEntry != &GlobalDriverListHead ) + { + Current = CONTAINING_RECORD(CurrentEntry, DRIVERS, ListEntry); + if( Current && (0 == RtlCompareUnicodeString(&GdiDriverInfo.DriverName, &Current->DriverName, FALSE)) ) { + hImageHandle = Current->ImageHandle; + break; + } + CurrentEntry = CurrentEntry->Flink; + }; + } + + if( !hImageHandle ) + { + /* the driver was not loaded before, so let's do that */ + Status = ZwSetSystemInformation(SystemLoadGdiDriverInformation, &GdiDriverInfo, sizeof(SYSTEM_GDI_DRIVER_INFORMATION)); + if (!NT_SUCCESS(Status)) { + DPRINT1("ZwSetSystemInformation failed with Status 0x%lx\n", Status); + } + else { + hImageHandle = (HANDLE)GdiDriverInfo.ImageAddress; + PDRIVERS DriverInfo = ExAllocatePool(PagedPool, sizeof(DRIVERS)); + DriverInfo->DriverName.MaximumLength = GdiDriverInfo.DriverName.MaximumLength; + DriverInfo->DriverName.Length = GdiDriverInfo.DriverName.Length; + DriverInfo->DriverName.Buffer = ExAllocatePool(PagedPool, GdiDriverInfo.DriverName.MaximumLength); + RtlCopyUnicodeString(&DriverInfo->DriverName, &GdiDriverInfo.DriverName); + DriverInfo->ImageHandle = hImageHandle; + InsertHeadList(&GlobalDriverListHead, &DriverInfo->ListEntry); + } + } + + return hImageHandle; }
HANDLE @@ -98,9 +150,44 @@
VOID APIENTRY -EngUnloadImage(IN HANDLE hModule) -{ - UNIMPLEMENTED; +EngUnloadImage ( IN HANDLE hModule ) +{ + NTSTATUS Status; + + DPRINT("hModule 0x%x\n", hModule); + + Status = ZwSetSystemInformation(SystemUnloadGdiDriverInformation, + &hModule, sizeof(HANDLE)); + + if(!NT_SUCCESS(Status)) + { + DPRINT1("ZwSetSystemInformation failed with status 0x%08X\n", + Status); + } + else + { + /* remove from the list */ + if( !IsListEmpty(&GlobalDriverListHead) ) + { + PLIST_ENTRY CurrentEntry = GlobalDriverListHead.Flink; + PDRIVERS Current; + /* probably the driver was already loaded, let's try to find it out */ + while( CurrentEntry != &GlobalDriverListHead ) + { + Current = CONTAINING_RECORD(CurrentEntry, DRIVERS, ListEntry); + + if( Current ) { + if(Current->ImageHandle == hModule) { + ExFreePool(Current->DriverName.Buffer); + RemoveEntryList(&Current->ListEntry); + ExFreePool(Current); + break; + } + } + CurrentEntry = CurrentEntry->Flink; + }; + } + } }
PVOID
Added: branches/arwinss/reactos/subsystems/win32/win32k/include/keyboard.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/include/keyboard.h (added) +++ branches/arwinss/reactos/subsystems/win32/win32k/include/keyboard.h [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -1,0 +1,26 @@ +#ifndef _WIN32K_KBD_H +#define _WIN32K_KBD_H + +#include <internal/kbd.h> + +typedef struct _KBL +{ + LIST_ENTRY List; + DWORD Flags; + WCHAR Name[KL_NAMELENGTH]; // used w GetKeyboardLayoutName same as wszKLID. + struct _KBDTABLES* KBTables; // KBDTABLES in ntoskrnl/include/internal/kbd.h + HANDLE hModule; + ULONG RefCount; + HKL hkl; + DWORD klid; // Low word - language id. High word - device id. +} KBL, *PKBL; + +#define KBL_UNLOAD 1 +#define KBL_PRELOAD 2 +#define KBL_RESET 4 + +BOOL UserInitDefaultKeyboardLayout(); +PKBL UserGetDefaultKeyBoardLayout(VOID); +PKBL UserHklToKbl(HKL hKl); + +#endif /* _WIN32K_KBD_H */
Propchange: branches/arwinss/reactos/subsystems/win32/win32k/include/keyboard.h ------------------------------------------------------------------------------ svn:eol-style = native
Modified: branches/arwinss/reactos/subsystems/win32/win32k/include/tags.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/include/tags.h [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/include/tags.h [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -11,6 +11,7 @@ #define TAG_DRIVER TAG('G', 'D', 'R', 'V') /* video drivers */ #define TAG_GDIHNDTBLE TAG('G', 'D', 'I', 'H') /* gdi handle table */ #define TAG_GSEM TAG('G', 's', 'e', 'm') /* Gdi Semaphore */ +#define TAG_STRING TAG('S', 'T', 'R', ' ') #define TAG_SURFOBJ TAG('S', 'R', 'F', 'O') /* surface object */ #define TAG_PALETTE TAG('G', 'l', 'a', '8') #define TAG_RTLREGISTRY TAG('R', 'q', 'r', 'v') /* RTL registry */
Modified: branches/arwinss/reactos/subsystems/win32/win32k/include/win32.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/include/win32.h [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/include/win32.h [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -34,6 +34,7 @@ struct msg_queue *queue; /* message queue */ obj_handle_t desktop; /* desktop handle */ int desktop_users; /* number of objects using the thread desktop */ + struct _KBL* KeyboardLayout; } THREADINFO, *PTHREADINFO;
#include <poppack.h>
Modified: branches/arwinss/reactos/subsystems/win32/win32k/include/win32kp.h URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/include/win32kp.h [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/include/win32kp.h [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -27,6 +27,7 @@ /* CSR interaction */ #include <csr.h>
+#include <keyboard.h> #include <win32.h> #include <heap.h> #include <tags.h>
Modified: branches/arwinss/reactos/subsystems/win32/win32k/main/init.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/main/init.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/main/init.c [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -30,6 +30,7 @@ PSECTION_OBJECT GlobalUserHeapSection = NULL; PGDI_HANDLE_TABLE GdiHandleTable = NULL; PSECTION_OBJECT GdiTableSection = NULL; +LIST_ENTRY GlobalDriverListHead;
/* PRIVATE FUNCTIONS *********************************************************/
@@ -143,6 +144,7 @@ Win32Thread->process = Win32Process; Win32Thread->peThread = Thread; Win32Thread->desktop = Win32Process->desktop; + Win32Thread->KeyboardLayout = UserGetDefaultKeyBoardLayout(); } else { @@ -321,6 +323,9 @@ /* Register them */ PsEstablishWin32Callouts(&CalloutData);
+ /* Initialize a list of loaded drivers in Win32 subsystem */ + InitializeListHead(&GlobalDriverListHead); + /* Initialize user implementation */ UserInitialize();
Copied: branches/arwinss/reactos/subsystems/win32/win32k/main/kbdlayout.c (from r42406, trunk/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c) URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/kbdlayout.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/main/kbdlayout.c [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -1,691 +1,640 @@ - -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: subsystems/win32/win32k/ntuser/kbdlayout.c - * PURPOSE: Keyboard layout management - * COPYRIGHT: Copyright 2007 Saveliy Tretiakov - * Copyright 2008 Colin Finck - * - */ - - -/* INCLUDES ******************************************************************/ - -#include <w32k.h> - -#define NDEBUG -#include <debug.h> - -PKBL KBLList = NULL; // Keyboard layout list. - -typedef PVOID (*KbdLayerDescriptor)(VOID); -NTSTATUS APIENTRY LdrGetProcedureAddress(PVOID module, - PANSI_STRING import_name, - DWORD flags, - PVOID *func_addr); - - - -/* PRIVATE FUNCTIONS ******************************************************/ - - -/* - * Utility function to read a value from the registry more easily. - * - * IN PUNICODE_STRING KeyName -> Name of key to open - * IN PUNICODE_STRING ValueName -> Name of value to open - * OUT PUNICODE_STRING ReturnedValue -> String contained in registry - * - * Returns NTSTATUS - */ - -static NTSTATUS APIENTRY ReadRegistryValue( PUNICODE_STRING KeyName, - PUNICODE_STRING ValueName, - PUNICODE_STRING ReturnedValue ) -{ - NTSTATUS Status; - HANDLE KeyHandle; - OBJECT_ATTRIBUTES KeyAttributes; - PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo; - ULONG Length = 0; - ULONG ResLength = 0; - PWCHAR ReturnBuffer; - - InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE, - NULL, NULL); - Status = ZwOpenKey(&KeyHandle, KEY_READ, &KeyAttributes); - if( !NT_SUCCESS(Status) ) - { - return Status; - } - - Status = ZwQueryValueKey(KeyHandle, ValueName, KeyValuePartialInformation, - 0, - 0, - &ResLength); - - if( Status != STATUS_BUFFER_TOO_SMALL ) - { - NtClose(KeyHandle); - return Status; - } - - ResLength += sizeof( *KeyValuePartialInfo ); - KeyValuePartialInfo = - ExAllocatePoolWithTag(PagedPool, ResLength, TAG_STRING); - Length = ResLength; - - if( !KeyValuePartialInfo ) - { - NtClose(KeyHandle); - return STATUS_NO_MEMORY; - } - - Status = ZwQueryValueKey(KeyHandle, - ValueName, - KeyValuePartialInformation, - (PVOID)KeyValuePartialInfo, - Length, - &ResLength); - - if( !NT_SUCCESS(Status) ) - { - NtClose(KeyHandle); - ExFreePoolWithTag(KeyValuePartialInfo, TAG_STRING); - return Status; - } - - /* At this point, KeyValuePartialInfo->Data contains the key data */ - ReturnBuffer = ExAllocatePoolWithTag(PagedPool, - KeyValuePartialInfo->DataLength, - TAG_STRING); - - if(!ReturnBuffer) - { - NtClose(KeyHandle); - ExFreePoolWithTag(KeyValuePartialInfo, TAG_STRING); - return STATUS_NO_MEMORY; - } - - RtlCopyMemory(ReturnBuffer, - KeyValuePartialInfo->Data, - KeyValuePartialInfo->DataLength); - RtlInitUnicodeString(ReturnedValue, ReturnBuffer); - - ExFreePoolWithTag(KeyValuePartialInfo, TAG_STRING); - NtClose(KeyHandle); - - return Status; -} - -static BOOL UserLoadKbdDll(WCHAR *wsKLID, - HANDLE *phModule, - PKBDTABLES *pKbdTables) -{ - NTSTATUS Status; - KbdLayerDescriptor layerDescGetFn; - ANSI_STRING kbdProcedureName; - UNICODE_STRING LayoutKeyName; - UNICODE_STRING LayoutValueName; - UNICODE_STRING LayoutFile; - UNICODE_STRING FullLayoutPath; - UNICODE_STRING klid; - WCHAR LayoutPathBuffer[MAX_PATH] = L"\SystemRoot\System32\"; - WCHAR KeyNameBuffer[MAX_PATH] = L"\REGISTRY\Machine\SYSTEM\" - L"CurrentControlSet\Control\Keyboard Layouts\"; - - RtlInitUnicodeString(&klid, wsKLID); - RtlInitUnicodeString(&LayoutValueName,L"Layout File"); - RtlInitUnicodeString(&LayoutKeyName, KeyNameBuffer); - LayoutKeyName.MaximumLength = sizeof(KeyNameBuffer); - - RtlAppendUnicodeStringToString(&LayoutKeyName, &klid); - Status = ReadRegistryValue(&LayoutKeyName, &LayoutValueName, &LayoutFile); - - if(!NT_SUCCESS(Status)) - { - DPRINT("Can't get layout filename for %wZ. (%08lx)\n", klid, Status); - return FALSE; - } - - DPRINT("Read registry and got %wZ\n", &LayoutFile); - RtlInitUnicodeString(&FullLayoutPath, LayoutPathBuffer); - FullLayoutPath.MaximumLength = sizeof(LayoutPathBuffer); - RtlAppendUnicodeStringToString(&FullLayoutPath, &LayoutFile); - DPRINT("Loading Keyboard DLL %wZ\n", &FullLayoutPath); - ExFreePoolWithTag(LayoutFile.Buffer, TAG_STRING); - - *phModule = EngLoadImage(FullLayoutPath.Buffer); - - if(*phModule) - { - DPRINT("Loaded %wZ\n", &FullLayoutPath); - - RtlInitAnsiString( &kbdProcedureName, "KbdLayerDescriptor" ); - LdrGetProcedureAddress((PVOID)*phModule, - &kbdProcedureName, - 0, - (PVOID*)&layerDescGetFn); - - if(layerDescGetFn) - { - *pKbdTables = layerDescGetFn(); - } - else - { - DPRINT1("Error: %wZ has no KbdLayerDescriptor()\n", &FullLayoutPath); - } - - if(!layerDescGetFn || !*pKbdTables) - { - DPRINT1("Failed to load the keyboard layout.\n"); - EngUnloadImage(*phModule); - return FALSE; - } - } - else - { - DPRINT1("Failed to load dll %wZ\n", &FullLayoutPath); - return FALSE; - } - - return TRUE; -} - -static PKBL UserLoadDllAndCreateKbl(DWORD LocaleId) -{ - PKBL NewKbl; - ULONG hKl; - LANGID langid; - - NewKbl = ExAllocatePool(PagedPool, sizeof(KBL)); - - if(!NewKbl) - { - DPRINT1("%s: Can't allocate memory!\n", __FUNCTION__); - return NULL; - } - - swprintf(NewKbl->Name, L"%08lx", LocaleId); - - if(!UserLoadKbdDll(NewKbl->Name, &NewKbl->hModule, &NewKbl->KBTables)) - { - DPRINT("%s: failed to load %x dll!\n", __FUNCTION__, LocaleId); - ExFreePool(NewKbl); - return NULL; - } - - /* Microsoft Office expects this value to be something specific - * for Japanese and Korean Windows with an IME the value is 0xe001 - * We should probably check to see if an IME exists and if so then - * set this word properly. - */ - langid = PRIMARYLANGID(LANGIDFROMLCID(LocaleId)); - hKl = LocaleId; - - if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN) - hKl |= 0xe001 << 16; /* FIXME */ - else hKl |= hKl << 16; - - NewKbl->hkl = (HKL) hKl; - NewKbl->klid = LocaleId; - NewKbl->Flags = 0; - NewKbl->RefCount = 0; - - return NewKbl; -} - -BOOL UserInitDefaultKeyboardLayout() -{ - LCID LocaleId; - NTSTATUS Status; - - Status = ZwQueryDefaultLocale(FALSE, &LocaleId); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Could not get default locale (%08lx).\n", Status); - } - else - { - DPRINT("DefaultLocale = %08lx\n", LocaleId); - } - - if(!NT_SUCCESS(Status) || !(KBLList = UserLoadDllAndCreateKbl(LocaleId))) - { - DPRINT1("Trying to load US Keyboard Layout.\n"); - LocaleId = 0x409; - - if(!(KBLList = UserLoadDllAndCreateKbl(LocaleId))) - { - DPRINT1("Failed to load any Keyboard Layout\n"); - return FALSE; - } - } - - KBLList->Flags |= KBL_PRELOAD; - - InitializeListHead(&KBLList->List); - return TRUE; -} - -PKBL W32kGetDefaultKeyLayout(VOID) -{ - const WCHAR szKeyboardLayoutPath[] = L"\Keyboard Layout\Preload"; - const WCHAR szDefaultUserPath[] = L"\REGISTRY\USER\.DEFAULT"; - - HANDLE KeyHandle; - LCID LayoutLocaleId = 0; - NTSTATUS Status; - OBJECT_ATTRIBUTES KeyAttributes; - PKBL pKbl; - UNICODE_STRING CurrentUserPath; - UNICODE_STRING FullKeyboardLayoutPath; - UNICODE_STRING LayoutValueName; - UNICODE_STRING LayoutLocaleIdString; - WCHAR wszBuffer[MAX_PATH]; - - // Get the path to HKEY_CURRENT_USER - Status = RtlFormatCurrentUserKeyPath(&CurrentUserPath); - - if( NT_SUCCESS(Status) ) - { - // FIXME: Is this 100% correct? - // We're called very early, so HKEY_CURRENT_USER might not be available yet. Check this first. - InitializeObjectAttributes(&KeyAttributes, &CurrentUserPath, OBJ_CASE_INSENSITIVE, NULL, NULL); - Status = ZwOpenKey(&KeyHandle, KEY_READ, &KeyAttributes); - - if(Status == STATUS_OBJECT_NAME_NOT_FOUND) - { - // It is not available, so read it from HKEY_USERS.DEFAULT - RtlCopyMemory(wszBuffer, szDefaultUserPath, sizeof(szDefaultUserPath)); - } - else - { - // The path is available - ZwClose(KeyHandle); - RtlCopyMemory(wszBuffer, CurrentUserPath.Buffer, CurrentUserPath.MaximumLength); - } - - // Build the full path - RtlInitUnicodeString(&FullKeyboardLayoutPath, wszBuffer); - FullKeyboardLayoutPath.MaximumLength = MAX_PATH; - - Status = RtlAppendUnicodeToString(&FullKeyboardLayoutPath, szKeyboardLayoutPath); - - if( NT_SUCCESS(Status) ) - { - // Return the first keyboard layout listed there - RtlInitUnicodeString(&LayoutValueName, L"1"); - - Status = ReadRegistryValue(&FullKeyboardLayoutPath, &LayoutValueName, &LayoutLocaleIdString); - - if( NT_SUCCESS(Status) ) - { - RtlUnicodeStringToInteger(&LayoutLocaleIdString, 16, &LayoutLocaleId); - ExFreePoolWithTag(LayoutLocaleIdString.Buffer, TAG_STRING); - } - else - DPRINT1("ReadRegistryValue failed! (%08lx).\n", Status); - } - else - DPRINT1("RtlAppendUnicodeToString failed! (%08lx)\n", Status); - - RtlFreeUnicodeString(&CurrentUserPath); - } - else - DPRINT1("RtlFormatCurrentUserKeyPath failed! (%08lx)\n", Status); - - if(!LayoutLocaleId) - { - // This block is only reached in case of a failure, so use DPRINT1 here - DPRINT1("Assuming default locale for the keyboard layout (0x409 - US)\n"); - LayoutLocaleId = 0x409; - } - - pKbl = KBLList; - do - { - if(pKbl->klid == LayoutLocaleId) - { - return pKbl; - } - - pKbl = (PKBL) pKbl->List.Flink; - } while(pKbl != KBLList); - - DPRINT("Loading new default keyboard layout.\n"); - pKbl = UserLoadDllAndCreateKbl(LayoutLocaleId); - - if(!pKbl) - { - DPRINT("Failed to load %x!!! Returning any availableKL.\n", LayoutLocaleId); - return KBLList; - } - - InsertTailList(&KBLList->List, &pKbl->List); - return pKbl; -} - -PKBL UserHklToKbl(HKL hKl) -{ - PKBL pKbl = KBLList; - do - { - if(pKbl->hkl == hKl) return pKbl; - pKbl = (PKBL) pKbl->List.Flink; - } while(pKbl != KBLList); - - return NULL; -} - -BOOL UserUnloadKbl(PKBL pKbl) -{ - /* According to msdn, UnloadKeyboardLayout can fail - if the keyboard layout identifier was preloaded. */ - - if(pKbl->Flags & KBL_PRELOAD) - { - DPRINT1("Attempted to unload preloaded keyboard layout.\n"); - return FALSE; - } - - if(pKbl->RefCount > 0) - { - /* Layout is used by other threads. - Mark it as unloaded and don't do anything else. */ - pKbl->Flags |= KBL_UNLOAD; - } - else - { - //Unload the layout - EngUnloadImage(pKbl->hModule); - RemoveEntryList(&pKbl->List); - ExFreePool(pKbl); - } - - return TRUE; -} - -static PKBL co_UserActivateKbl(PTHREADINFO w32Thread, PKBL pKbl, UINT Flags) -{ - PKBL Prev; - - Prev = w32Thread->KeyboardLayout; - Prev->RefCount--; - w32Thread->KeyboardLayout = pKbl; - pKbl->RefCount++; - - if(Flags & KLF_SETFORPROCESS) - { - //FIXME - - } - - if(Prev->Flags & KBL_UNLOAD && Prev->RefCount == 0) - { - UserUnloadKbl(Prev); - } - - // Send WM_INPUTLANGCHANGE to thread's focus window - co_IntSendMessage(w32Thread->MessageQueue->FocusWindow, - WM_INPUTLANGCHANGE, - 0, // FIXME: put charset here (what is this?) - (LPARAM)pKbl->hkl); //klid - - return Prev; -} - -/* EXPORTS *******************************************************************/ - -HKL FASTCALL -UserGetKeyboardLayout( - DWORD dwThreadId) -{ - NTSTATUS Status; - PETHREAD Thread; - PTHREADINFO W32Thread; - HKL Ret; - - if(!dwThreadId) - { - W32Thread = PsGetCurrentThreadWin32Thread(); - return W32Thread->KeyboardLayout->hkl; - } - - Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread); - if(!NT_SUCCESS(Status)) - { - SetLastWin32Error(ERROR_INVALID_PARAMETER); - return NULL; - } - - W32Thread = PsGetThreadWin32Thread(Thread); - Ret = W32Thread->KeyboardLayout->hkl; - ObDereferenceObject(Thread); - return Ret; -} - -UINT -APIENTRY -NtUserGetKeyboardLayoutList( - INT nItems, - HKL* pHklBuff) -{ - UINT Ret = 0; - PKBL pKbl; - - UserEnterShared(); - pKbl = KBLList; - - if(nItems == 0) - { - do - { - Ret++; - pKbl = (PKBL) pKbl->List.Flink; - } while(pKbl != KBLList); - } - else - { - _SEH2_TRY - { - ProbeForWrite(pHklBuff, nItems*sizeof(HKL), 4); - - while(Ret < nItems) - { - if(!(pKbl->Flags & KBL_UNLOAD)) - { - pHklBuff[Ret] = pKbl->hkl; - Ret++; - pKbl = (PKBL) pKbl->List.Flink; - if(pKbl == KBLList) break; - } - } - - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - SetLastNtError(_SEH2_GetExceptionCode()); - Ret = 0; - } - _SEH2_END; - } - - UserLeave(); - return Ret; -} - -BOOL -APIENTRY -NtUserGetKeyboardLayoutName( - LPWSTR lpszName) -{ - BOOL ret = FALSE; - PKBL pKbl; - PTHREADINFO pti; - - UserEnterShared(); - - _SEH2_TRY - { - ProbeForWrite(lpszName, KL_NAMELENGTH*sizeof(WCHAR), 1); - pti = PsGetCurrentThreadWin32Thread(); - pKbl = pti->KeyboardLayout; - RtlCopyMemory(lpszName, pKbl->Name, KL_NAMELENGTH*sizeof(WCHAR)); - ret = TRUE; - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - SetLastNtError(_SEH2_GetExceptionCode()); - ret = FALSE; - } - _SEH2_END; - - UserLeave(); - return ret; -} - - -HKL -APIENTRY -NtUserLoadKeyboardLayoutEx( - IN HANDLE Handle, - IN DWORD offTable, - IN PUNICODE_STRING puszKeyboardName, - IN HKL hKL, - IN PUNICODE_STRING puszKLID, - IN DWORD dwKLID, - IN UINT Flags) -{ - HKL Ret = NULL; - PKBL pKbl = NULL, Cur; - - UserEnterExclusive(); - - //Let's see if layout was already loaded. - Cur = KBLList; - do - { - if(Cur->klid == dwKLID) - { - pKbl = Cur; - pKbl->Flags &= ~KBL_UNLOAD; - break; - } - - Cur = (PKBL) Cur->List.Flink; - } while(Cur != KBLList); - - //It wasn't, so load it. - if(!pKbl) - { - pKbl = UserLoadDllAndCreateKbl(dwKLID); - - if(!pKbl) - { - goto the_end; - } - - InsertTailList(&KBLList->List, &pKbl->List); - } - - if(Flags & KLF_REORDER) KBLList = pKbl; - - if(Flags & KLF_ACTIVATE) - { - co_UserActivateKbl(PsGetCurrentThreadWin32Thread(), pKbl, Flags); - } - - Ret = pKbl->hkl; - - //FIXME: KLF_NOTELLSHELL - // KLF_REPLACELANG - // KLF_SUBSTITUTE_OK - -the_end: - UserLeave(); - return Ret; -} - -HKL -APIENTRY -NtUserActivateKeyboardLayout( - HKL hKl, - ULONG Flags) -{ - PKBL pKbl; - HKL Ret = NULL; - PTHREADINFO pWThread; - - UserEnterExclusive(); - - pWThread = PsGetCurrentThreadWin32Thread(); - - if(pWThread->KeyboardLayout->hkl == hKl) - { - Ret = hKl; - goto the_end; - } - - if(hKl == (HKL)HKL_NEXT) - { - pKbl = (PKBL)pWThread->KeyboardLayout->List.Flink; - } - else if(hKl == (HKL)HKL_PREV) - { - pKbl = (PKBL)pWThread->KeyboardLayout->List.Blink; - } - else pKbl = UserHklToKbl(hKl); - - //FIXME: KLF_RESET, KLF_SHIFTLOCK - - if(pKbl) - { - if(Flags & KLF_REORDER) - KBLList = pKbl; - - if(pKbl == pWThread->KeyboardLayout) - { - Ret = pKbl->hkl; - } - else - { - pKbl = co_UserActivateKbl(pWThread, pKbl, Flags); - Ret = pKbl->hkl; - } - } - else - { - DPRINT1("%s: Invalid HKL %x!\n", __FUNCTION__, hKl); - } - -the_end: - UserLeave(); - return Ret; -} - -BOOL -APIENTRY -NtUserUnloadKeyboardLayout( - HKL hKl) -{ - PKBL pKbl; - BOOL Ret = FALSE; - - UserEnterExclusive(); - - if((pKbl = UserHklToKbl(hKl))) - { - Ret = UserUnloadKbl(pKbl); - } - else - { - DPRINT1("%s: Invalid HKL %x!\n", __FUNCTION__, hKl); - } - - UserLeave(); - return Ret; -} - -/* EOF */ + +/* + * PROJECT: ReactOS Kernel + * LICENSE: GPL - See COPYING in the top level directory + * FILE: subsystems/win32/win32k/ntuser/kbdlayout.c + * PURPOSE: Keyboard layout management + * COPYRIGHT: Copyright 2007 Saveliy Tretiakov + * Copyright 2008 Colin Finck + * + */ + + +/* INCLUDES ******************************************************************/ + +#include <win32k.h> +#define NDEBUG +#include <debug.h> + +PKBL KBLList = NULL; // Keyboard layout list. + +typedef PVOID (*KbdLayerDescriptor)(VOID); +NTSTATUS APIENTRY LdrGetProcedureAddress(PVOID module, + PANSI_STRING import_name, + DWORD flags, + PVOID *func_addr); + + + +/* PRIVATE FUNCTIONS ******************************************************/ + + +/* + * Utility function to read a value from the registry more easily. + * + * IN PUNICODE_STRING KeyName -> Name of key to open + * IN PUNICODE_STRING ValueName -> Name of value to open + * OUT PUNICODE_STRING ReturnedValue -> String contained in registry + * + * Returns NTSTATUS + */ + +static NTSTATUS APIENTRY ReadRegistryValue( PUNICODE_STRING KeyName, + PUNICODE_STRING ValueName, + PUNICODE_STRING ReturnedValue ) +{ + NTSTATUS Status; + HANDLE KeyHandle; + OBJECT_ATTRIBUTES KeyAttributes; + PKEY_VALUE_PARTIAL_INFORMATION KeyValuePartialInfo; + ULONG Length = 0; + ULONG ResLength = 0; + PWCHAR ReturnBuffer; + + InitializeObjectAttributes(&KeyAttributes, KeyName, OBJ_CASE_INSENSITIVE, + NULL, NULL); + Status = ZwOpenKey(&KeyHandle, KEY_READ, &KeyAttributes); + if( !NT_SUCCESS(Status) ) + { + return Status; + } + + Status = ZwQueryValueKey(KeyHandle, ValueName, KeyValuePartialInformation, + 0, + 0, + &ResLength); + + if( Status != STATUS_BUFFER_TOO_SMALL ) + { + NtClose(KeyHandle); + return Status; + } + + ResLength += sizeof( *KeyValuePartialInfo ); + KeyValuePartialInfo = + ExAllocatePoolWithTag(PagedPool, ResLength, TAG_STRING); + Length = ResLength; + + if( !KeyValuePartialInfo ) + { + NtClose(KeyHandle); + return STATUS_NO_MEMORY; + } + + Status = ZwQueryValueKey(KeyHandle, + ValueName, + KeyValuePartialInformation, + (PVOID)KeyValuePartialInfo, + Length, + &ResLength); + + if( !NT_SUCCESS(Status) ) + { + NtClose(KeyHandle); + ExFreePoolWithTag(KeyValuePartialInfo, TAG_STRING); + return Status; + } + + /* At this point, KeyValuePartialInfo->Data contains the key data */ + ReturnBuffer = ExAllocatePoolWithTag(PagedPool, + KeyValuePartialInfo->DataLength, + TAG_STRING); + + if(!ReturnBuffer) + { + NtClose(KeyHandle); + ExFreePoolWithTag(KeyValuePartialInfo, TAG_STRING); + return STATUS_NO_MEMORY; + } + + RtlCopyMemory(ReturnBuffer, + KeyValuePartialInfo->Data, + KeyValuePartialInfo->DataLength); + RtlInitUnicodeString(ReturnedValue, ReturnBuffer); + + ExFreePoolWithTag(KeyValuePartialInfo, TAG_STRING); + NtClose(KeyHandle); + + return Status; +} + +static BOOL UserLoadKbdDll(WCHAR *wsKLID, + HANDLE *phModule, + PKBDTABLES *pKbdTables) +{ + NTSTATUS Status; + KbdLayerDescriptor layerDescGetFn; + ANSI_STRING kbdProcedureName; + UNICODE_STRING LayoutKeyName; + UNICODE_STRING LayoutValueName; + UNICODE_STRING LayoutFile; + UNICODE_STRING FullLayoutPath; + UNICODE_STRING klid; + WCHAR LayoutPathBuffer[MAX_PATH] = L"\SystemRoot\System32\"; + WCHAR KeyNameBuffer[MAX_PATH] = L"\REGISTRY\Machine\SYSTEM\" + L"CurrentControlSet\Control\Keyboard Layouts\"; + + RtlInitUnicodeString(&klid, wsKLID); + RtlInitUnicodeString(&LayoutValueName,L"Layout File"); + RtlInitUnicodeString(&LayoutKeyName, KeyNameBuffer); + LayoutKeyName.MaximumLength = sizeof(KeyNameBuffer); + + RtlAppendUnicodeStringToString(&LayoutKeyName, &klid); + Status = ReadRegistryValue(&LayoutKeyName, &LayoutValueName, &LayoutFile); + + if(!NT_SUCCESS(Status)) + { + DPRINT("Can't get layout filename for %wZ. (%08lx)\n", klid, Status); + return FALSE; + } + + DPRINT("Read registry and got %wZ\n", &LayoutFile); + RtlInitUnicodeString(&FullLayoutPath, LayoutPathBuffer); + FullLayoutPath.MaximumLength = sizeof(LayoutPathBuffer); + RtlAppendUnicodeStringToString(&FullLayoutPath, &LayoutFile); + DPRINT("Loading Keyboard DLL %wZ\n", &FullLayoutPath); + ExFreePoolWithTag(LayoutFile.Buffer, TAG_STRING); + + *phModule = EngLoadImage(FullLayoutPath.Buffer); + + if(*phModule) + { + DPRINT("Loaded %wZ\n", &FullLayoutPath); + + RtlInitAnsiString( &kbdProcedureName, "KbdLayerDescriptor" ); + LdrGetProcedureAddress((PVOID)*phModule, + &kbdProcedureName, + 0, + (PVOID*)&layerDescGetFn); + + if(layerDescGetFn) + { + *pKbdTables = layerDescGetFn(); + } + else + { + DPRINT1("Error: %wZ has no KbdLayerDescriptor()\n", &FullLayoutPath); + } + + if(!layerDescGetFn || !*pKbdTables) + { + DPRINT1("Failed to load the keyboard layout.\n"); + EngUnloadImage(*phModule); + return FALSE; + } + } + else + { + DPRINT1("Failed to load dll %wZ\n", &FullLayoutPath); + return FALSE; + } + + return TRUE; +} + +static PKBL UserLoadDllAndCreateKbl(DWORD LocaleId) +{ + PKBL NewKbl; + ULONG hKl; + LANGID langid; + + NewKbl = ExAllocatePool(PagedPool, sizeof(KBL)); + + if(!NewKbl) + { + DPRINT1("%s: Can't allocate memory!\n", __FUNCTION__); + return NULL; + } + + swprintf(NewKbl->Name, L"%08lx", LocaleId); + + if(!UserLoadKbdDll(NewKbl->Name, &NewKbl->hModule, &NewKbl->KBTables)) + { + DPRINT("%s: failed to load %x dll!\n", __FUNCTION__, LocaleId); + ExFreePool(NewKbl); + return NULL; + } + + /* Microsoft Office expects this value to be something specific + * for Japanese and Korean Windows with an IME the value is 0xe001 + * We should probably check to see if an IME exists and if so then + * set this word properly. + */ + langid = PRIMARYLANGID(LANGIDFROMLCID(LocaleId)); + hKl = LocaleId; + + if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN) + hKl |= 0xe001 << 16; /* FIXME */ + else hKl |= hKl << 16; + + NewKbl->hkl = (HKL) hKl; + NewKbl->klid = LocaleId; + NewKbl->Flags = 0; + NewKbl->RefCount = 0; + + return NewKbl; +} + +BOOL UserInitDefaultKeyboardLayout() +{ + LCID LocaleId; + NTSTATUS Status; + + Status = ZwQueryDefaultLocale(FALSE, &LocaleId); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Could not get default locale (%08lx).\n", Status); + } + else + { + DPRINT("DefaultLocale = %08lx\n", LocaleId); + } + + if(!NT_SUCCESS(Status) || !(KBLList = UserLoadDllAndCreateKbl(LocaleId))) + { + DPRINT1("Trying to load US Keyboard Layout.\n"); + LocaleId = 0x409; + + if(!(KBLList = UserLoadDllAndCreateKbl(LocaleId))) + { + DPRINT1("Failed to load any Keyboard Layout\n"); + return FALSE; + } + } + + KBLList->Flags |= KBL_PRELOAD; + + InitializeListHead(&KBLList->List); + return TRUE; +} + +PKBL UserGetDefaultKeyBoardLayout(VOID) +{ + const WCHAR szKeyboardLayoutPath[] = L"\Keyboard Layout\Preload"; + const WCHAR szDefaultUserPath[] = L"\REGISTRY\USER\.DEFAULT"; + + HANDLE KeyHandle; + LCID LayoutLocaleId = 0; + NTSTATUS Status; + OBJECT_ATTRIBUTES KeyAttributes; + PKBL pKbl; + UNICODE_STRING CurrentUserPath; + UNICODE_STRING FullKeyboardLayoutPath; + UNICODE_STRING LayoutValueName; + UNICODE_STRING LayoutLocaleIdString; + WCHAR wszBuffer[MAX_PATH]; + + // Get the path to HKEY_CURRENT_USER + Status = RtlFormatCurrentUserKeyPath(&CurrentUserPath); + + if( NT_SUCCESS(Status) ) + { + // FIXME: Is this 100% correct? + // We're called very early, so HKEY_CURRENT_USER might not be available yet. Check this first. + InitializeObjectAttributes(&KeyAttributes, &CurrentUserPath, OBJ_CASE_INSENSITIVE, NULL, NULL); + Status = ZwOpenKey(&KeyHandle, KEY_READ, &KeyAttributes); + + if(Status == STATUS_OBJECT_NAME_NOT_FOUND) + { + // It is not available, so read it from HKEY_USERS.DEFAULT + RtlCopyMemory(wszBuffer, szDefaultUserPath, sizeof(szDefaultUserPath)); + } + else + { + // The path is available + ZwClose(KeyHandle); + RtlCopyMemory(wszBuffer, CurrentUserPath.Buffer, CurrentUserPath.MaximumLength); + } + + // Build the full path + RtlInitUnicodeString(&FullKeyboardLayoutPath, wszBuffer); + FullKeyboardLayoutPath.MaximumLength = MAX_PATH; + + Status = RtlAppendUnicodeToString(&FullKeyboardLayoutPath, szKeyboardLayoutPath); + + if( NT_SUCCESS(Status) ) + { + // Return the first keyboard layout listed there + RtlInitUnicodeString(&LayoutValueName, L"1"); + + Status = ReadRegistryValue(&FullKeyboardLayoutPath, &LayoutValueName, &LayoutLocaleIdString); + + if( NT_SUCCESS(Status) ) + { + RtlUnicodeStringToInteger(&LayoutLocaleIdString, 16, &LayoutLocaleId); + ExFreePoolWithTag(LayoutLocaleIdString.Buffer, TAG_STRING); + } + else + DPRINT1("ReadRegistryValue failed! (%08lx).\n", Status); + } + else + DPRINT1("RtlAppendUnicodeToString failed! (%08lx)\n", Status); + + RtlFreeUnicodeString(&CurrentUserPath); + } + else + DPRINT1("RtlFormatCurrentUserKeyPath failed! (%08lx)\n", Status); + + if(!LayoutLocaleId) + { + // This block is only reached in case of a failure, so use DPRINT1 here + DPRINT1("Assuming default locale for the keyboard layout (0x409 - US)\n"); + LayoutLocaleId = 0x409; + } + + pKbl = KBLList; + do + { + if(pKbl->klid == LayoutLocaleId) + { + return pKbl; + } + + pKbl = (PKBL) pKbl->List.Flink; + } while(pKbl != KBLList); + + DPRINT("Loading new default keyboard layout.\n"); + pKbl = UserLoadDllAndCreateKbl(LayoutLocaleId); + + if(!pKbl) + { + DPRINT("Failed to load %x!!! Returning any availableKL.\n", LayoutLocaleId); + return KBLList; + } + + InsertTailList(&KBLList->List, &pKbl->List); + return pKbl; +} + +PKBL UserHklToKbl(HKL hKl) +{ + PKBL pKbl = KBLList; + do + { + if(pKbl->hkl == hKl) return pKbl; + pKbl = (PKBL) pKbl->List.Flink; + } while(pKbl != KBLList); + + return NULL; +} + +BOOL UserUnloadKbl(PKBL pKbl) +{ + /* According to msdn, UnloadKeyboardLayout can fail + if the keyboard layout identifier was preloaded. */ + + if(pKbl->Flags & KBL_PRELOAD) + { + DPRINT1("Attempted to unload preloaded keyboard layout.\n"); + return FALSE; + } + + if(pKbl->RefCount > 0) + { + /* Layout is used by other threads. + Mark it as unloaded and don't do anything else. */ + pKbl->Flags |= KBL_UNLOAD; + } + else + { + //Unload the layout + EngUnloadImage(pKbl->hModule); + RemoveEntryList(&pKbl->List); + ExFreePool(pKbl); + } + + return TRUE; +} + +static PKBL UserActivateKbl(PTHREADINFO w32Thread, PKBL pKbl, UINT Flags) +{ + PKBL Prev; + + Prev = w32Thread->KeyboardLayout; + Prev->RefCount--; + w32Thread->KeyboardLayout = pKbl; + pKbl->RefCount++; + + if(Flags & KLF_SETFORPROCESS) + { + //FIXME + + } + + if(Prev->Flags & KBL_UNLOAD && Prev->RefCount == 0) + { + UserUnloadKbl(Prev); + } + + //// Send WM_INPUTLANGCHANGE to thread's focus window + //co_IntSendMessage(w32Thread->MessageQueue->FocusWindow, + // WM_INPUTLANGCHANGE, + // 0, // FIXME: put charset here (what is this?) + // (LPARAM)pKbl->hkl); //klid + + return Prev; +} + +/* EXPORTS *******************************************************************/ + +HKL APIENTRY +RosUserGetKeyboardLayout( + DWORD dwThreadId) +{ + NTSTATUS Status; + PETHREAD Thread; + PTHREADINFO W32Thread; + HKL Ret; + + if(!dwThreadId) + { + W32Thread = PsGetCurrentThreadWin32Thread(); + return W32Thread->KeyboardLayout->hkl; + } + + Status = PsLookupThreadByThreadId((HANDLE)dwThreadId, &Thread); + if(!NT_SUCCESS(Status)) + { + SetLastWin32Error(ERROR_INVALID_PARAMETER); + return NULL; + } + + W32Thread = PsGetThreadWin32Thread(Thread); + Ret = W32Thread->KeyboardLayout->hkl; + ObDereferenceObject(Thread); + return Ret; +} + +BOOL +APIENTRY +RosUserGetKeyboardLayoutName( + LPWSTR lpszName) +{ + BOOL ret = FALSE; + PKBL pKbl; + PTHREADINFO pti; + + //UserEnterShared(); + + _SEH2_TRY + { + ProbeForWrite(lpszName, KL_NAMELENGTH*sizeof(WCHAR), 1); + pti = PsGetCurrentThreadWin32Thread(); + pKbl = pti->KeyboardLayout; + RtlCopyMemory(lpszName, pKbl->Name, KL_NAMELENGTH*sizeof(WCHAR)); + ret = TRUE; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + SetLastNtError(_SEH2_GetExceptionCode()); + ret = FALSE; + } + _SEH2_END; + + //UserLeave(); + return ret; +} + + +HKL +APIENTRY +RosUserLoadKeyboardLayoutEx( + IN HANDLE Handle, + IN DWORD offTable, + IN PUNICODE_STRING puszKeyboardName, + IN HKL hKL, + IN PUNICODE_STRING puszKLID, + IN DWORD dwKLID, + IN UINT Flags) +{ + HKL Ret = NULL; + PKBL pKbl = NULL, Cur; + + UserEnterExclusive(); + + //Let's see if layout was already loaded. + Cur = KBLList; + do + { + if(Cur->klid == dwKLID) + { + pKbl = Cur; + pKbl->Flags &= ~KBL_UNLOAD; + break; + } + + Cur = (PKBL) Cur->List.Flink; + } while(Cur != KBLList); + + //It wasn't, so load it. + if(!pKbl) + { + pKbl = UserLoadDllAndCreateKbl(dwKLID); + + if(!pKbl) + { + goto the_end; + } + + InsertTailList(&KBLList->List, &pKbl->List); + } + + if(Flags & KLF_REORDER) KBLList = pKbl; + + if(Flags & KLF_ACTIVATE) + { + UserActivateKbl(PsGetCurrentThreadWin32Thread(), pKbl, Flags); + } + + Ret = pKbl->hkl; + + //FIXME: KLF_NOTELLSHELL + // KLF_REPLACELANG + // KLF_SUBSTITUTE_OK + +the_end: + UserLeave(); + return Ret; +} + +HKL +APIENTRY +RosUserActivateKeyboardLayout( + HKL hKl, + ULONG Flags) +{ + PKBL pKbl; + HKL Ret = NULL; + PTHREADINFO pWThread; + + UserEnterExclusive(); + + pWThread = PsGetCurrentThreadWin32Thread(); + + if(pWThread->KeyboardLayout->hkl == hKl) + { + Ret = hKl; + goto the_end; + } + + if(hKl == (HKL)HKL_NEXT) + { + pKbl = (PKBL)pWThread->KeyboardLayout->List.Flink; + } + else if(hKl == (HKL)HKL_PREV) + { + pKbl = (PKBL)pWThread->KeyboardLayout->List.Blink; + } + else pKbl = UserHklToKbl(hKl); + + //FIXME: KLF_RESET, KLF_SHIFTLOCK + + if(pKbl) + { + if(Flags & KLF_REORDER) + KBLList = pKbl; + + if(pKbl == pWThread->KeyboardLayout) + { + Ret = pKbl->hkl; + } + else + { + pKbl = UserActivateKbl(pWThread, pKbl, Flags); + Ret = pKbl->hkl; + } + } + else + { + DPRINT1("%s: Invalid HKL %x!\n", __FUNCTION__, hKl); + } + +the_end: + UserLeave(); + return Ret; +} + +BOOL +APIENTRY +RosUserUnloadKeyboardLayout( + HKL hKl) +{ + PKBL pKbl; + BOOL Ret = FALSE; + + UserEnterExclusive(); + + if((pKbl = UserHklToKbl(hKl))) + { + Ret = UserUnloadKbl(pKbl); + } + else + { + DPRINT1("%s: Invalid HKL %x!\n", __FUNCTION__, hKl); + } + + UserLeave(); + return Ret; +} + +/* EOF */
Propchange: branches/arwinss/reactos/subsystems/win32/win32k/main/kbdlayout.c ------------------------------------------------------------------------------ svn:eol-style = native
Copied: branches/arwinss/reactos/subsystems/win32/win32k/main/keyboard.c (from r42406, trunk/reactos/subsystems/win32/win32k/ntuser/keyboard.c) URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- trunk/reactos/subsystems/win32/win32k/ntuser/keyboard.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/main/keyboard.c [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -28,8 +28,7 @@
/* INCLUDES ******************************************************************/
-#include <w32k.h> - +#include <win32k.h> #define NDEBUG #include <debug.h>
@@ -38,33 +37,13 @@ #define CAPITAL_BIT 0x80000000 #define NUMLOCK_BIT 0x40000000 #define MOD_BITS_MASK 0x3fffffff -#define MOD_KCTRL 0x02 /* Key States */ -#define KS_DOWN_MASK 0xc0 -#define KS_DOWN_BIT 0x80 -#define KS_LOCK_BIT 0x01 -/* lParam bits */ -#define LP_EXT_BIT (1<<24) -/* From kbdxx.c -- Key changes with numlock */ -#define KNUMP 0x400 +#define KEY_DOWN_BIT 0x80 +#define KEY_LOCK_BIT 0x01
BYTE gQueueKeyStateTable[256];
- - -/* FUNCTIONS *****************************************************************/ - -/* Initialization -- Right now, just zero the key state and init the lock */ -NTSTATUS FASTCALL InitKeyboardImpl(VOID) -{ - RtlZeroMemory(&gQueueKeyStateTable,0x100); - return STATUS_SUCCESS; -} - -/*** Statics used by TranslateMessage ***/ - -/*** Shift state code was out of hand, sorry. --- arty */
static UINT DontDistinguishShifts( UINT ret ) { @@ -77,69 +56,6 @@ return ret; }
-static VOID APIENTRY SetKeyState(DWORD key, DWORD vk, DWORD ext, BOOL down) -{ - ASSERT(vk <= 0xff); - - /* Special handling for toggles like numpad and caps lock */ - if (vk == VK_CAPITAL || vk == VK_NUMLOCK) - { - if (down) - gQueueKeyStateTable[vk] ^= KS_LOCK_BIT; - } - - if (ext && vk == VK_LSHIFT) - vk = VK_RSHIFT; - if (ext && vk == VK_LCONTROL) - vk = VK_RCONTROL; - if (ext && vk == VK_LMENU) - vk = VK_RMENU; - - if (down) - gQueueKeyStateTable[vk] |= KS_DOWN_BIT; - else - gQueueKeyStateTable[vk] &= ~KS_DOWN_MASK; - - if (vk == VK_LSHIFT || vk == VK_RSHIFT) - { - if ((gQueueKeyStateTable[VK_LSHIFT] & KS_DOWN_BIT) || - (gQueueKeyStateTable[VK_RSHIFT] & KS_DOWN_BIT)) - { - gQueueKeyStateTable[VK_SHIFT] |= KS_DOWN_BIT; - } - else - { - gQueueKeyStateTable[VK_SHIFT] &= ~KS_DOWN_MASK; - } - } - - if (vk == VK_LCONTROL || vk == VK_RCONTROL) - { - if ((gQueueKeyStateTable[VK_LCONTROL] & KS_DOWN_BIT) || - (gQueueKeyStateTable[VK_RCONTROL] & KS_DOWN_BIT)) - { - gQueueKeyStateTable[VK_CONTROL] |= KS_DOWN_BIT; - } - else - { - gQueueKeyStateTable[VK_CONTROL] &= ~KS_DOWN_MASK; - } - } - - if (vk == VK_LMENU || vk == VK_RMENU) - { - if ((gQueueKeyStateTable[VK_LMENU] & KS_DOWN_BIT) || - (gQueueKeyStateTable[VK_RMENU] & KS_DOWN_BIT)) - { - gQueueKeyStateTable[VK_MENU] |= KS_DOWN_BIT; - } - else - { - gQueueKeyStateTable[VK_MENU] &= ~KS_DOWN_MASK; - } - } -} - VOID DumpKeyState( PBYTE KeyState ) { int i; @@ -193,39 +109,39 @@ /* DumpKeyState( KeyState ); */
if (KeysSet( pkKT, KeyState, VK_LSHIFT, VK_RSHIFT ) & - KS_DOWN_BIT) + KEY_DOWN_BIT) ModBits |= GetShiftBit( pkKT, VK_SHIFT );
if (KeysSet( pkKT, KeyState, VK_SHIFT, 0 ) & - KS_DOWN_BIT) + KEY_DOWN_BIT) ModBits |= GetShiftBit( pkKT, VK_SHIFT );
if (KeysSet( pkKT, KeyState, VK_LCONTROL, VK_RCONTROL ) & - KS_DOWN_BIT ) + KEY_DOWN_BIT ) ModBits |= GetShiftBit( pkKT, VK_CONTROL );
if (KeysSet( pkKT, KeyState, VK_CONTROL, 0 ) & - KS_DOWN_BIT ) + KEY_DOWN_BIT ) ModBits |= GetShiftBit( pkKT, VK_CONTROL );
if (KeysSet( pkKT, KeyState, VK_LMENU, VK_RMENU ) & - KS_DOWN_BIT ) + KEY_DOWN_BIT ) ModBits |= GetShiftBit( pkKT, VK_MENU );
/* Handle Alt+Gr */ if (pkKT->fLocalFlags & 0x1) if (KeysSet( pkKT, KeyState, VK_RMENU, 0 ) & - KS_DOWN_BIT) + KEY_DOWN_BIT) ModBits |= GetShiftBit( pkKT, VK_CONTROL );
/* Deal with VK_CAPITAL */ - if (KeysSet( pkKT, KeyState, VK_CAPITAL, 0 ) & KS_LOCK_BIT) + if (KeysSet( pkKT, KeyState, VK_CAPITAL, 0 ) & KEY_LOCK_BIT) { ModBits |= CAPITAL_BIT; }
/* Deal with VK_NUMLOCK */ - if (KeysSet( pkKT, KeyState, VK_NUMLOCK, 0 ) & KS_LOCK_BIT) + if (KeysSet( pkKT, KeyState, VK_NUMLOCK, 0 ) & KEY_LOCK_BIT) { ModBits |= NUMLOCK_BIT; } @@ -347,209 +263,35 @@ return 0; }
- -DWORD FASTCALL UserGetKeyState(DWORD key) +DWORD FASTCALL UserGetAsyncKeyState(DWORD key) { DWORD ret = 0;
if( key < 0x100 ) { - ret = ((DWORD)(gQueueKeyStateTable[key] & KS_DOWN_BIT) << 8 ) | - (gQueueKeyStateTable[key] & KS_LOCK_BIT); + ret = ((DWORD)(gQueueKeyStateTable[key] & KEY_DOWN_BIT) << 8 ) | + (gQueueKeyStateTable[key] & KEY_LOCK_BIT); }
return ret; } +
SHORT APIENTRY -NtUserGetKeyState( +RosUserGetAsyncKeyState( INT key) { - DECLARE_RETURN(DWORD); - - DPRINT("Enter NtUserGetKeyState\n"); + SHORT ret; + UserEnterExclusive();
- RETURN(UserGetKeyState(key)); - -CLEANUP: - DPRINT("Leave NtUserGetKeyState, ret=%i\n",_ret_); + ret = (SHORT)UserGetAsyncKeyState(key); + UserLeave(); - END_CLEANUP; -} - - - -DWORD FASTCALL UserGetAsyncKeyState(DWORD key) -{ - DWORD ret = 0; - - if( key < 0x100 ) - { - ret = ((DWORD)(gQueueKeyStateTable[key] & KS_DOWN_BIT) << 8 ) | - (gQueueKeyStateTable[key] & KS_LOCK_BIT); - }
return ret; -} - - - -SHORT -APIENTRY -NtUserGetAsyncKeyState( - INT key) -{ - DECLARE_RETURN(SHORT); - - DPRINT("Enter NtUserGetAsyncKeyState\n"); - UserEnterExclusive(); - - RETURN((SHORT)UserGetAsyncKeyState(key)); - -CLEANUP: - DPRINT("Leave NtUserGetAsyncKeyState, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} - - - -BOOL FASTCALL -IntTranslateKbdMessage(LPMSG lpMsg, - HKL dwhkl) -{ - PTHREADINFO pti; - static INT dead_char = 0; - LONG UState = 0; - WCHAR wp[2] = { 0 }; - MSG NewMsg = { 0 }; - PKBDTABLES keyLayout; - BOOL Result = FALSE; - DWORD ScanCode = 0; - - pti = PsGetCurrentThreadWin32Thread(); - keyLayout = pti->KeyboardLayout->KBTables; - if( !keyLayout ) - return FALSE; - - if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN) - return FALSE; - - ScanCode = (lpMsg->lParam >> 16) & 0xff; - - /* All messages have to contain the cursor point. */ - IntGetCursorLocation(pti->Desktop->WindowStation, - &NewMsg.pt); - - UState = ToUnicodeInner(lpMsg->wParam, HIWORD(lpMsg->lParam) & 0xff, - gQueueKeyStateTable, wp, 2, 0, - keyLayout ); - - if (UState == 1) - { - NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR; - if (dead_char) - { - ULONG i; - WCHAR first, second; - DPRINT("PREVIOUS DEAD CHAR: %c\n", dead_char); - - for( i = 0; keyLayout->pDeadKey[i].dwBoth; i++ ) - { - first = keyLayout->pDeadKey[i].dwBoth >> 16; - second = keyLayout->pDeadKey[i].dwBoth; - if (first == dead_char && second == wp[0]) - { - wp[0] = keyLayout->pDeadKey[i].wchComposed; - dead_char = 0; - break; - } - } - - DPRINT("FINAL CHAR: %c\n", wp[0]); - } - - if (dead_char) - { - NewMsg.hwnd = lpMsg->hwnd; - NewMsg.wParam = dead_char; - NewMsg.lParam = lpMsg->lParam; - dead_char = 0; - MsqPostMessage(pti->MessageQueue, &NewMsg, FALSE, QS_KEY); - } - - NewMsg.hwnd = lpMsg->hwnd; - NewMsg.wParam = wp[0]; - NewMsg.lParam = lpMsg->lParam; - DPRINT( "CHAR='%c' %04x %08x\n", wp[0], wp[0], lpMsg->lParam ); - MsqPostMessage(pti->MessageQueue, &NewMsg, FALSE, QS_KEY); - Result = TRUE; - } - else if (UState == -1) - { - NewMsg.message = - (lpMsg->message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR; - NewMsg.hwnd = lpMsg->hwnd; - NewMsg.wParam = wp[0]; - NewMsg.lParam = lpMsg->lParam; - dead_char = wp[0]; - MsqPostMessage(pti->MessageQueue, &NewMsg, FALSE, QS_KEY); - Result = TRUE; - } - - return Result; -} - -DWORD -APIENTRY -NtUserGetKeyboardState( - LPBYTE lpKeyState) -{ - BOOL Result = TRUE; - DECLARE_RETURN(DWORD); - - DPRINT("Enter NtUserGetKeyboardState\n"); - UserEnterShared(); - - if (lpKeyState) - { - if(!NT_SUCCESS(MmCopyToCaller(lpKeyState, gQueueKeyStateTable, 256))) - Result = FALSE; - } - - RETURN(Result); - -CLEANUP: - DPRINT("Leave NtUserGetKeyboardState, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} - -BOOL -APIENTRY -NtUserSetKeyboardState(LPBYTE lpKeyState) -{ - BOOL Result = TRUE; - DECLARE_RETURN(DWORD); - - DPRINT("Enter NtUserSetKeyboardState\n"); - UserEnterExclusive(); - - if (lpKeyState) - { - if(! NT_SUCCESS(MmCopyFromCaller(gQueueKeyStateTable, lpKeyState, 256))) - Result = FALSE; - } - - RETURN(Result); - -CLEANUP: - DPRINT("Leave NtUserSetKeyboardState, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; }
static UINT VkToScan( UINT Code, BOOL ExtCode, PKBDTABLES pkKT ) @@ -664,33 +406,31 @@
UINT APIENTRY -NtUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl ) +RosUserMapVirtualKeyEx( UINT Code, UINT Type, DWORD keyboardId, HKL dwhkl ) { PTHREADINFO pti; PKBDTABLES keyLayout; - DECLARE_RETURN(UINT); - - DPRINT("Enter NtUserMapVirtualKeyEx\n"); + UINT ret = 0; + UserEnterExclusive();
pti = PsGetCurrentThreadWin32Thread(); keyLayout = pti ? pti->KeyboardLayout->KBTables : 0;
- if( !keyLayout ) - RETURN(0); - - RETURN(IntMapVirtualKeyEx( Code, Type, keyLayout )); - -CLEANUP: - DPRINT("Leave NtUserMapVirtualKeyEx, ret=%i\n",_ret_); + if( keyLayout ) + { + ret = IntMapVirtualKeyEx( Code, Type, keyLayout ); + } + UserLeave(); - END_CLEANUP; + + return ret; }
int APIENTRY -NtUserToUnicodeEx( +RosUserToUnicodeEx( UINT wVirtKey, UINT wScanCode, PBYTE lpKeyState, @@ -703,28 +443,35 @@ BYTE KeyStateBuf[0x100]; PWCHAR OutPwszBuff = 0; int ret = 0; - DECLARE_RETURN(int); - - DPRINT("Enter NtUserSetKeyboardState\n"); - UserEnterShared();//faxme: this syscall doesnt seem to need any locking... - - - if( !NT_SUCCESS(MmCopyFromCaller(KeyStateBuf, - lpKeyState, - sizeof(KeyStateBuf))) ) - { - DPRINT1( "Couldn't copy key state from caller.\n" ); - RETURN(0); - } + + //UserEnterShared(); + + NTSTATUS Status = STATUS_SUCCESS; + + _SEH2_TRY + { + ProbeForRead(lpKeyState,sizeof(KeyStateBuf),1); + RtlCopyMemory(KeyStateBuf,lpKeyState,sizeof(KeyStateBuf)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + if( !NT_SUCCESS(Status)) + { + goto cleanup; + }
/* Virtual code is correct and key is pressed currently? */ - if (wVirtKey < 0x100 && KeyStateBuf[wVirtKey] & KS_DOWN_BIT) + if (wVirtKey < 0x100 && KeyStateBuf[wVirtKey] & KEY_DOWN_BIT) { OutPwszBuff = ExAllocatePoolWithTag(NonPagedPool,sizeof(WCHAR) * cchBuff, TAG_STRING); if( !OutPwszBuff ) { DPRINT1( "ExAllocatePool(%d) failed\n", sizeof(WCHAR) * cchBuff); - RETURN(0); + goto cleanup; } RtlZeroMemory( OutPwszBuff, sizeof( WCHAR ) * cchBuff );
@@ -737,33 +484,39 @@ wFlags, pti ? pti->KeyboardLayout->KBTables : 0 );
- MmCopyToCaller(pwszBuff,OutPwszBuff,sizeof(WCHAR)*cchBuff); + _SEH2_TRY + { + ProbeForWrite(pwszBuff,sizeof(WCHAR)*cchBuff,1); + RtlCopyMemory(pwszBuff,OutPwszBuff,sizeof(WCHAR)*cchBuff); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + ExFreePoolWithTag(OutPwszBuff, TAG_STRING); } - else - ret = 0; - - RETURN(ret); - -CLEANUP: - DPRINT("Leave NtUserSetKeyboardState, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} - -static int W32kSimpleToupper( int ch ) -{ - if( ch >= 'a' && ch <= 'z' ) - ch = ch - 'a' + 'A'; - return ch; -} + +cleanup: + //UserLeave(); + return ret; +} + +//static int W32kSimpleToupper( int ch ) +//{ +// if( ch >= 'a' && ch <= 'z' ) +// ch = ch - 'a' + 'A'; +// return ch; +//}
DWORD APIENTRY -NtUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize ) +RosUserGetKeyNameText( LONG lParam, LPWSTR lpString, int nSize ) { PTHREADINFO pti; - int i; + //int i; DWORD ret = 0; UINT CareVk = 0; UINT VkCode = 0; @@ -771,16 +524,14 @@ BOOL ExtKey = lParam & (1<<24) ? TRUE : FALSE; PKBDTABLES keyLayout; VSC_LPWSTR *KeyNames; - DECLARE_RETURN(DWORD); - - DPRINT("Enter NtUserGetKeyNameText\n"); - UserEnterShared(); + + //UserEnterShared();
pti = PsGetCurrentThreadWin32Thread(); keyLayout = pti ? pti->KeyboardLayout->KBTables : 0;
if( !keyLayout || nSize < 1 ) - RETURN(0); + goto cleanup;
if( lParam & (1<<25) ) { @@ -807,190 +558,43 @@ else KeyNames = keyLayout->pKeyNames;
- for( i = 0; KeyNames[i].pwsz; i++ ) - { - if( KeyNames[i].vsc == ScanCode ) - { - UINT StrLen = wcslen(KeyNames[i].pwsz); - UINT StrMax = StrLen > (nSize - 1) ? (nSize - 1) : StrLen; - WCHAR null_wc = 0; - if( NT_SUCCESS( MmCopyToCaller( lpString, - KeyNames[i].pwsz, - StrMax * sizeof(WCHAR) ) ) && - NT_SUCCESS( MmCopyToCaller( lpString + StrMax, - &null_wc, - sizeof( WCHAR ) ) ) ) - { - ret = StrMax; - break; - } - } - } - - if( ret == 0 ) - { - WCHAR UCName[2]; - - UCName[0] = W32kSimpleToupper(IntMapVirtualKeyEx( VkCode, 2, keyLayout )); - UCName[1] = 0; - ret = 1; - - if( !NT_SUCCESS(MmCopyToCaller( lpString, UCName, 2 * sizeof(WCHAR) )) ) - RETURN(0); - } - - RETURN(ret); - -CLEANUP: - DPRINT("Leave NtUserGetKeyNameText, ret=%i\n",_ret_); - UserLeave(); - END_CLEANUP; -} - -/* - * Filter this message according to the current key layout, setting wParam - * appropriately. - */ - -VOID FASTCALL -W32kKeyProcessMessage(LPMSG Msg, - PKBDTABLES KeyboardLayout, - BYTE Prefix) -{ - DWORD ScanCode = 0, ModifierBits = 0; - DWORD i = 0; - DWORD BaseMapping = 0; - DWORD RawVk = 0; - static WORD NumpadConversion[][2] = - { { VK_DELETE, VK_DECIMAL }, - { VK_INSERT, VK_NUMPAD0 }, - { VK_END, VK_NUMPAD1 }, - { VK_DOWN, VK_NUMPAD2 }, - { VK_NEXT, VK_NUMPAD3 }, - { VK_LEFT, VK_NUMPAD4 }, - { VK_CLEAR, VK_NUMPAD5 }, - { VK_RIGHT, VK_NUMPAD6 }, - { VK_HOME, VK_NUMPAD7 }, - { VK_UP, VK_NUMPAD8 }, - { VK_PRIOR, VK_NUMPAD9 }, - { 0,0 } }; - PVSC_VK VscVkTable = NULL; - - if( !KeyboardLayout || !Msg || - (Msg->message != WM_KEYDOWN && Msg->message != WM_SYSKEYDOWN && - Msg->message != WM_KEYUP && Msg->message != WM_SYSKEYUP) ) - { - return; - } - - /* arty -- handle numpad -- On real windows, the actual key produced - * by the messaging layer is different based on the state of numlock. */ - ModifierBits = ModBits(KeyboardLayout,gQueueKeyStateTable); - - /* Get the raw scan code, so we can look up whether the key is a numpad - * key - * - * Shift and the LP_EXT_BIT cancel. */ - ScanCode = (Msg->lParam >> 16) & 0xff; - BaseMapping = Msg->wParam = - IntMapVirtualKeyEx( ScanCode, 1, KeyboardLayout ); - if( Prefix == 0 ) - { - if( ScanCode >= KeyboardLayout->bMaxVSCtoVK ) - RawVk = 0xff; - else - RawVk = KeyboardLayout->pusVSCtoVK[ScanCode]; - } - else - { - if( Prefix == 0xE0 ) - { - /* ignore shift codes */ - if( ScanCode == 0x2A || ScanCode == 0x36 ) - { - return; - } - VscVkTable = KeyboardLayout->pVSCtoVK_E0; - } - else if( Prefix == 0xE1 ) - { - VscVkTable = KeyboardLayout->pVSCtoVK_E1; - } - - RawVk = 0xff; - while (VscVkTable->Vsc) - { - if( VscVkTable->Vsc == ScanCode ) - { - RawVk = VscVkTable->Vk; - } - VscVkTable++; - } - } - - if ((ModifierBits & NUMLOCK_BIT) && - !(ModifierBits & GetShiftBit(KeyboardLayout, VK_SHIFT)) && - (RawVk & KNUMP) && - !(Msg->lParam & LP_EXT_BIT)) - { - /* The key in question is a numpad key. Search for a translation. */ - for (i = 0; NumpadConversion[i][0]; i++) - { - if ((BaseMapping & 0xff) == NumpadConversion[i][0]) /* RawVk? */ - { - Msg->wParam = NumpadConversion[i][1]; - break; - } - } - } - - DPRINT("Key: [%04x -> %04x]\n", BaseMapping, Msg->wParam); - - /* Now that we have the VK, we can set the keymap appropriately - * This is a better place for this code, as it's guaranteed to be - * run, unlike translate message. */ - if (Msg->message == WM_KEYDOWN || Msg->message == WM_SYSKEYDOWN) - { - SetKeyState( ScanCode, Msg->wParam, Msg->lParam & LP_EXT_BIT, - TRUE ); /* Strike key */ - } - else if (Msg->message == WM_KEYUP || Msg->message == WM_SYSKEYUP) - { - SetKeyState( ScanCode, Msg->wParam, Msg->lParam & LP_EXT_BIT, - FALSE ); /* Release key */ - } - - /* We need to unset SYSKEYDOWN if the ALT key is an ALT+Gr */ - if( gQueueKeyStateTable[VK_RMENU] & KS_DOWN_BIT ) - { - if( Msg->message == WM_SYSKEYDOWN ) - Msg->message = WM_KEYDOWN; - else - Msg->message = WM_KEYUP; - } - -} - - - -DWORD FASTCALL -UserGetKeyboardType( - DWORD TypeFlag) -{ - switch(TypeFlag) - { - case 0: /* Keyboard type */ - return 4; /* AT-101 */ - case 1: /* Keyboard Subtype */ - return 0; /* There are no defined subtypes */ - case 2: /* Number of F-keys */ - return 12; /* We're doing an 101 for now, so return 12 F-keys */ - default: - DPRINT1("Unknown type!\n"); - return 0; /* The book says 0 here, so 0 */ - } -} - + //FIXME! + //for( i = 0; KeyNames[i].pwsz; i++ ) + //{ + // if( KeyNames[i].vsc == ScanCode ) + // { + // UINT StrLen = wcslen(KeyNames[i].pwsz); + // UINT StrMax = StrLen > (nSize - 1) ? (nSize - 1) : StrLen; + // WCHAR null_wc = 0; + // if( NT_SUCCESS( MmCopyToCaller( lpString, + // KeyNames[i].pwsz, + // StrMax * sizeof(WCHAR) ) ) && + // NT_SUCCESS( MmCopyToCaller( lpString + StrMax, + // &null_wc, + // sizeof( WCHAR ) ) ) ) + // { + // ret = StrMax; + // break; + // } + // } + //} + + //if( ret == 0 ) + //{ + // WCHAR UCName[2]; + + // UCName[0] = W32kSimpleToupper(IntMapVirtualKeyEx( VkCode, 2, keyLayout )); + // UCName[1] = 0; + // ret = 1; + + // if( !NT_SUCCESS(MmCopyToCaller( lpString, UCName, 2 * sizeof(WCHAR) )) ) + // ret = 0; + //} + +cleanup: + //UserLeave(); + return ret; +}
/* Based on TryToTranslateChar, instead of processing VirtualKey match, @@ -998,7 +602,7 @@ */ DWORD APIENTRY -NtUserVkKeyScanEx( +RosUserVkKeyScanEx( WCHAR wChar, HKL hKeyboardLayout, BOOL UsehKL ) // TRUE from KeyboardLayout, FALSE from pkbl = (THREADINFO)->KeyboardLayout @@ -1011,8 +615,7 @@ PKBL pkbl = NULL; DWORD CapsMod = 0, CapsState = 0, Ret = -1;
- DPRINT("NtUserVkKeyScanEx() wChar %d, KbdLayout 0x%p\n", wChar, hKeyboardLayout); - UserEnterShared(); + //UserEnterShared();
if (UsehKL) { @@ -1055,9 +658,49 @@ } } Exit: - UserLeave(); + //UserLeave(); return Ret; }
+BOOL +APIENTRY +RosUserSetAsyncKeyboardState(BYTE key_state_table[]) +{ + NTSTATUS Status = STATUS_SUCCESS; + + _SEH2_TRY + { + ProbeForRead(key_state_table,sizeof(gQueueKeyStateTable),1); + RtlCopyMemory(gQueueKeyStateTable,key_state_table,sizeof(gQueueKeyStateTable)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + return NT_SUCCESS(Status); +} + +BOOL +APIENTRY +RosUserGetAsyncKeyboardState(BYTE key_state_table[]) +{ + NTSTATUS Status = STATUS_SUCCESS; + + _SEH2_TRY + { + ProbeForWrite(key_state_table,sizeof(gQueueKeyStateTable),1); + RtlCopyMemory(key_state_table,gQueueKeyStateTable,sizeof(gQueueKeyStateTable)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + Status = _SEH2_GetExceptionCode(); + } + _SEH2_END; + + return NT_SUCCESS(Status); +} +
/* EOF */
Modified: branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/w32ksvc.db [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -67,4 +67,16 @@ RosUserClipCursor 1 RosUserSetCursor 1 RosUserEnumDisplayMonitors 3 -RosUserGetMonitorInfo 2 +RosUserGetMonitorInfo 2 +RosUserGetKeyboardLayout 1 +RosUserGetKeyboardLayoutName 1 +RosUserLoadKeyboardLayoutEx 7 +RosUserActivateKeyboardLayout 2 +RosUserUnloadKeyboardLayout 1 +RosUserSetAsyncKeyboardState 1 +RosUserGetAsyncKeyboardState 1 +RosUserVkKeyScanEx 3 +RosUserGetKeyNameText 3 +RosUserToUnicodeEx 7 +RosUserMapVirtualKeyEx 4 +RosUserGetAsyncKeyState 1
Modified: branches/arwinss/reactos/subsystems/win32/win32k/win32k.rbuild URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/win32k.rbuild [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/win32k.rbuild [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -114,6 +114,8 @@ <file>usrheap.c</file> <file>cursor.c</file> <file>monitor.c</file> + <file>kbdlayout.c</file> + <file>keyboard.c</file> </directory> <directory name="wine"> <file>atom.c</file>
Modified: branches/arwinss/reactos/subsystems/win32/win32k/wine/main.c URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win32... ============================================================================== --- branches/arwinss/reactos/subsystems/win32/win32k/wine/main.c [iso-8859-1] (original) +++ branches/arwinss/reactos/subsystems/win32/win32k/wine/main.c [iso-8859-1] Wed Aug 5 20:10:41 2009 @@ -60,6 +60,12 @@ { DPRINT1("Failure initializing USER resource!\n"); } + + /* Initialize the default keyboard layout */ + if(!UserInitDefaultKeyboardLayout()) + { + DPRINT1("Failed to initialize default keyboard layout!\n"); + } }
UINT