2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 /* $Id: input.c,v 1.24 2003/12/07 19:29:33 weiden Exp $
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * PURPOSE: Window classes
24 * FILE: subsys/win32k/ntuser/class.c
25 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
27 * 06-06-2001 CSH Created
30 /* INCLUDES ******************************************************************/
32 #include <ddk/ntddk.h>
33 #include <win32k/win32k.h>
34 #include <include/class.h>
35 #include <include/error.h>
36 #include <include/winsta.h>
37 #include <include/desktop.h>
38 #include <include/msgqueue.h>
39 #include <ddk/ntddmou.h>
40 #include <include/mouse.h>
41 #include <include/input.h>
42 #include <include/hotkey.h>
43 #include <rosrtl/string.h>
48 /* GLOBALS *******************************************************************/
50 static HANDLE MouseDeviceHandle
;
51 static HANDLE KeyboardThreadHandle
;
52 static CLIENT_ID KeyboardThreadId
;
53 static HANDLE KeyboardDeviceHandle
;
54 static KEVENT InputThreadsStart
;
55 static BOOLEAN InputThreadsRunning
= FALSE
;
56 PUSER_MESSAGE_QUEUE pmPrimitiveMessageQueue
= 0;
58 /* FUNCTIONS *****************************************************************/
60 VOID STDCALL_FUNC STATIC
61 KeyboardThreadMain(PVOID StartContext
)
63 UNICODE_STRING KeyboardDeviceName
;
64 OBJECT_ATTRIBUTES KeyboardObjectAttributes
;
68 PUSER_MESSAGE_QUEUE FocusQueue
;
69 struct _ETHREAD
*FocusThread
;
71 RtlRosInitUnicodeStringFromLiteral(&KeyboardDeviceName
, L
"\\??\\Keyboard");
72 InitializeObjectAttributes(&KeyboardObjectAttributes
,
77 Status
= NtOpenFile(&KeyboardDeviceHandle
,
79 &KeyboardObjectAttributes
,
82 FILE_SYNCHRONOUS_IO_ALERT
);
83 if (!NT_SUCCESS(Status
))
85 DPRINT1("Win32K: Failed to open keyboard.\n");
92 * Wait to start input.
94 DPRINT( "Input Thread Waiting for start event\n" );
95 Status
= KeWaitForSingleObject(&InputThreadsStart
,
100 DPRINT( "Input Thread Starting...\n" );
103 * Receive and process keyboard input.
105 while (InputThreadsRunning
)
107 KEY_EVENT_RECORD KeyEvent
;
110 struct _ETHREAD
*Thread
;
114 Status
= NtReadFile (KeyboardDeviceHandle
,
120 sizeof(KEY_EVENT_RECORD
),
123 DPRINT( "KeyRaw: %s %04x\n",
124 KeyEvent
.bKeyDown
? "down" : "up",
125 KeyEvent
.wVirtualScanCode
);
127 if (Status
== STATUS_ALERTED
&& !InputThreadsRunning
)
131 if (!NT_SUCCESS(Status
))
133 DPRINT1("Win32K: Failed to read from keyboard.\n");
137 DPRINT( "Key: %s\n", KeyEvent
.bKeyDown
? "down" : "up" );
140 if (KeyEvent
.dwControlKeyState
& (LEFT_ALT_PRESSED
| RIGHT_ALT_PRESSED
))
141 fsModifiers
|= MOD_ALT
;
143 if (KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
144 fsModifiers
|= MOD_CONTROL
;
146 if (KeyEvent
.dwControlKeyState
& SHIFT_PRESSED
)
147 fsModifiers
|= MOD_SHIFT
;
149 /* FIXME: Support MOD_WIN */
151 lParam
= KeyEvent
.wRepeatCount
|
152 ((KeyEvent
.wVirtualScanCode
<< 16) & 0x00FF0000) | 0x40000000;
154 /* Bit 24 indicates if this is an extended key */
155 if (KeyEvent
.dwControlKeyState
& ENHANCED_KEY
)
160 if (fsModifiers
& MOD_ALT
)
162 /* Context mode. 1 if ALT if pressed while the key is pressed */
166 if(KeyEvent
.bKeyDown
&& (fsModifiers
& MOD_ALT
))
167 msg
.message
= WM_SYSKEYDOWN
;
168 else if(KeyEvent
.bKeyDown
)
169 msg
.message
= WM_KEYDOWN
;
170 else if(fsModifiers
& MOD_ALT
)
171 msg
.message
= WM_SYSKEYUP
;
173 msg
.message
= WM_KEYUP
;
175 /* Find the target thread whose locale is in effect */
176 if (!IntGetScreenDC())
178 FocusQueue
= W32kGetPrimitiveMessageQueue();
182 FocusQueue
= IntGetFocusMessageQueue();
185 if (!FocusQueue
) continue;
187 msg
.wParam
= KeyEvent
.wVirtualKeyCode
;
189 msg
.hwnd
= FocusQueue
->FocusWindow
;
191 FocusThread
= FocusQueue
->Thread
;
193 if (FocusThread
&& FocusThread
->Win32Thread
&&
194 FocusThread
->Win32Thread
->KeyboardLayout
)
196 W32kKeyProcessMessage(&msg
,
197 FocusThread
->Win32Thread
->KeyboardLayout
);
202 if (GetHotKey(InputWindowStation
,
209 if (KeyEvent
.bKeyDown
)
211 DPRINT("Hot key pressed (hWnd %lx, id %d)\n", hWnd
, id
);
212 MsqPostHotKeyMessage (Thread
,
215 MAKELPARAM((WORD
)fsModifiers
,
222 * Post a keyboard message.
224 MsqPostKeyboardMessage(msg
.message
,msg
.wParam
,msg
.lParam
);
227 DPRINT( "Input Thread Stopped...\n" );
233 NtUserAcquireOrReleaseInputOwnership(BOOLEAN Release
)
235 if (Release
&& InputThreadsRunning
&& !pmPrimitiveMessageQueue
)
237 DPRINT( "Releasing input: PM = %08x\n", pmPrimitiveMessageQueue
);
238 KeClearEvent(&InputThreadsStart
);
239 InputThreadsRunning
= FALSE
;
241 NtAlertThread(KeyboardThreadHandle
);
243 else if (!Release
&& !InputThreadsRunning
)
245 InputThreadsRunning
= TRUE
;
246 KeSetEvent(&InputThreadsStart
, IO_NO_INCREMENT
, FALSE
);
249 return(STATUS_SUCCESS
);
256 UNICODE_STRING MouseDeviceName
;
257 OBJECT_ATTRIBUTES MouseObjectAttributes
;
258 IO_STATUS_BLOCK Iosb
;
260 PFILE_OBJECT FileObject
;
261 GDI_INFORMATION GdiInfo
;
263 PIO_STACK_LOCATION StackPtr
;
265 KeInitializeEvent(&InputThreadsStart
, NotificationEvent
, FALSE
);
267 Status
= PsCreateSystemThread(&KeyboardThreadHandle
,
274 if (!NT_SUCCESS(Status
))
276 DPRINT1("Win32K: Failed to create keyboard thread.\n");
280 * Connect to the mouse class driver.
281 * Failures here don't result in a failure return, the system must be
282 * able to operate without mouse
284 RtlRosInitUnicodeStringFromLiteral(&MouseDeviceName
, L
"\\??\\MouseClass");
285 InitializeObjectAttributes(&MouseObjectAttributes
,
290 Status
= NtOpenFile(&MouseDeviceHandle
,
292 &MouseObjectAttributes
,
296 if (!NT_SUCCESS(Status
))
298 DPRINT1("Win32K: Failed to open mouse.\n");
299 return STATUS_SUCCESS
;
301 Status
= ObReferenceObjectByHandle(MouseDeviceHandle
,
302 FILE_READ_DATA
| FILE_WRITE_DATA
,
305 (PVOID
*) &FileObject
,
308 if (!NT_SUCCESS(Status
))
310 DPRINT1("Win32K: Failed to reference mouse file object.\n");
311 NtClose(MouseDeviceHandle
);
312 return STATUS_SUCCESS
;
314 KeInitializeEvent(&IoEvent
, FALSE
, NotificationEvent
);
315 GdiInfo
.CallBack
= MouseGDICallBack
;
316 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT
,
317 FileObject
->DeviceObject
,
326 //trigger FileObject/Event dereferencing
327 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
329 StackPtr
= IoGetNextIrpStackLocation(Irp
);
330 StackPtr
->FileObject
= FileObject
;
331 StackPtr
->DeviceObject
= FileObject
->DeviceObject
;
332 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= sizeof(GdiInfo
);
333 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
= 0;
335 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
336 if (Status
== STATUS_PENDING
)
338 KeWaitForSingleObject(&FileObject
->Event
, Executive
, KernelMode
, FALSE
,
340 Status
= Iosb
.Status
;
342 if (!NT_SUCCESS(Status
))
344 DPRINT1("Win32K: Failed to connect to mouse driver.\n");
345 ObDereferenceObject(&FileObject
);
346 NtClose(MouseDeviceHandle
);
347 return STATUS_SUCCESS
;
350 /* Initialize the default keyboard layout */
351 (VOID
)W32kGetDefaultKeyLayout();
353 return STATUS_SUCCESS
;
357 CleanupInputImp(VOID
)
359 return(STATUS_SUCCESS
);