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/user3…
==============================================================================
--- 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/winen…
==============================================================================
--- 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/winen…
==============================================================================
--- 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/winen…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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__(a)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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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/win3…
==============================================================================
--- 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