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.19 2003/11/17 02:12:52 hyperion 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 <win32k/userobj.h>
35 #include <include/class.h>
36 #include <include/error.h>
37 #include <include/winsta.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 RtlRosInitUnicodeStringFromLiteral(&KeyboardDeviceName
, L
"\\??\\Keyboard");
69 InitializeObjectAttributes(&KeyboardObjectAttributes
,
74 Status
= NtOpenFile(&KeyboardDeviceHandle
,
76 &KeyboardObjectAttributes
,
79 FILE_SYNCHRONOUS_IO_ALERT
);
80 if (!NT_SUCCESS(Status
))
82 DPRINT1("Win32K: Failed to open keyboard.\n");
89 * Wait to start input.
91 DbgPrint( "Input Thread Waiting for start event\n" );
92 Status
= KeWaitForSingleObject(&InputThreadsStart
,
97 DbgPrint( "Input Thread Starting...\n" );
100 * Receive and process keyboard input.
102 while (InputThreadsRunning
)
104 KEY_EVENT_RECORD KeyEvent
;
107 struct _ETHREAD
*Thread
;
111 Status
= NtReadFile (KeyboardDeviceHandle
,
117 sizeof(KEY_EVENT_RECORD
),
120 DPRINT( "KeyRaw: %s %04x\n",
121 KeyEvent
.bKeyDown
? "down" : "up",
122 KeyEvent
.wVirtualScanCode
);
124 if (Status
== STATUS_ALERTED
&& !InputThreadsRunning
)
128 if (!NT_SUCCESS(Status
))
130 DPRINT1("Win32K: Failed to read from keyboard.\n");
134 DPRINT( "Key: %s\n", KeyEvent
.bKeyDown
? "down" : "up" );
137 if (KeyEvent
.dwControlKeyState
& (LEFT_ALT_PRESSED
| RIGHT_ALT_PRESSED
))
138 fsModifiers
|= MOD_ALT
;
140 if (KeyEvent
.dwControlKeyState
& (LEFT_CTRL_PRESSED
| RIGHT_CTRL_PRESSED
))
141 fsModifiers
|= MOD_CONTROL
;
143 if (KeyEvent
.dwControlKeyState
& SHIFT_PRESSED
)
144 fsModifiers
|= MOD_SHIFT
;
146 /* FIXME: Support MOD_WIN */
148 if (GetHotKey(InputWindowStation
,
150 KeyEvent
.wVirtualKeyCode
,
155 if (KeyEvent
.bKeyDown
)
157 DPRINT("Hot key pressed (hWnd %lx, id %d)\n", hWnd
, id
);
158 MsqPostHotKeyMessage (Thread
,
161 MAKELPARAM((WORD
)fsModifiers
, (WORD
)KeyEvent
.wVirtualKeyCode
));
167 * Post a keyboard message.
169 if (KeyEvent
.bKeyDown
)
171 lParam
= KeyEvent
.wRepeatCount
|
172 ((KeyEvent
.wVirtualScanCode
<< 16) & 0x00FF0000) | 0x40000000;
174 /* Bit 24 indicates if this is an extended key */
175 if (KeyEvent
.dwControlKeyState
& ENHANCED_KEY
)
180 if (fsModifiers
& MOD_ALT
)
182 /* Context mode. 1 if ALT if pressed while the key is pressed */
186 MsqPostKeyboardMessage((fsModifiers
& MOD_ALT
) ? WM_SYSKEYDOWN
: WM_KEYDOWN
,
187 KeyEvent
.wVirtualKeyCode
,
192 lParam
= KeyEvent
.wRepeatCount
|
193 ((KeyEvent
.wVirtualScanCode
<< 16) & 0x00FF0000) | 0xC0000000;
195 /* Bit 24 indicates if this is an extended key */
196 if (KeyEvent
.dwControlKeyState
& ENHANCED_KEY
)
201 if (fsModifiers
& MOD_ALT
)
203 /* Context mode. 1 if ALT if pressed while the key is pressed */
207 MsqPostKeyboardMessage((fsModifiers
& MOD_ALT
) ? WM_SYSKEYUP
: WM_KEYUP
,
208 KeyEvent
.wVirtualKeyCode
,
212 DbgPrint( "Input Thread Stopped...\n" );
218 NtUserAcquireOrReleaseInputOwnership(BOOLEAN Release
)
220 if (Release
&& InputThreadsRunning
&& !pmPrimitiveMessageQueue
)
222 DbgPrint( "Releasing input: PM = %08x\n", pmPrimitiveMessageQueue
);
223 KeClearEvent(&InputThreadsStart
);
224 InputThreadsRunning
= FALSE
;
226 NtAlertThread(KeyboardThreadHandle
);
228 else if (!Release
&& !InputThreadsRunning
)
230 InputThreadsRunning
= TRUE
;
231 KeSetEvent(&InputThreadsStart
, IO_NO_INCREMENT
, FALSE
);
234 return(STATUS_SUCCESS
);
241 UNICODE_STRING MouseDeviceName
;
242 OBJECT_ATTRIBUTES MouseObjectAttributes
;
243 IO_STATUS_BLOCK Iosb
;
245 PFILE_OBJECT FileObject
;
246 GDI_INFORMATION GdiInfo
;
248 PIO_STACK_LOCATION StackPtr
;
250 KeInitializeEvent(&InputThreadsStart
, NotificationEvent
, FALSE
);
252 Status
= PsCreateSystemThread(&KeyboardThreadHandle
,
259 if (!NT_SUCCESS(Status
))
261 DPRINT1("Win32K: Failed to create keyboard thread.\n");
265 * Connect to the mouse class driver.
266 * Failures here don't result in a failure return, the system must be
267 * able to operate without mouse
269 RtlRosInitUnicodeStringFromLiteral(&MouseDeviceName
, L
"\\??\\MouseClass");
270 InitializeObjectAttributes(&MouseObjectAttributes
,
275 Status
= NtOpenFile(&MouseDeviceHandle
,
277 &MouseObjectAttributes
,
281 if (!NT_SUCCESS(Status
))
283 DPRINT1("Win32K: Failed to open mouse.\n");
284 return STATUS_SUCCESS
;
286 Status
= ObReferenceObjectByHandle(MouseDeviceHandle
,
287 FILE_READ_DATA
| FILE_WRITE_DATA
,
290 (PVOID
*) &FileObject
,
293 if (!NT_SUCCESS(Status
))
295 DPRINT1("Win32K: Failed to reference mouse file object.\n");
296 NtClose(MouseDeviceHandle
);
297 return STATUS_SUCCESS
;
299 KeInitializeEvent(&IoEvent
, FALSE
, NotificationEvent
);
300 GdiInfo
.CallBack
= MouseGDICallBack
;
301 Irp
= IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT
,
302 FileObject
->DeviceObject
,
311 //trigger FileObject/Event dereferencing
312 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
314 StackPtr
= IoGetNextIrpStackLocation(Irp
);
315 StackPtr
->FileObject
= FileObject
;
316 StackPtr
->DeviceObject
= FileObject
->DeviceObject
;
317 StackPtr
->Parameters
.DeviceIoControl
.InputBufferLength
= sizeof(GdiInfo
);
318 StackPtr
->Parameters
.DeviceIoControl
.OutputBufferLength
= 0;
320 Status
= IoCallDriver(FileObject
->DeviceObject
, Irp
);
321 if (Status
== STATUS_PENDING
)
323 KeWaitForSingleObject(&FileObject
->Event
, Executive
, KernelMode
, FALSE
,
325 Status
= Iosb
.Status
;
327 if (!NT_SUCCESS(Status
))
329 DPRINT1("Win32K: Failed to connect to mouse driver.\n");
330 ObDereferenceObject(&FileObject
);
331 NtClose(MouseDeviceHandle
);
332 return STATUS_SUCCESS
;
335 /* Initialize the default keyboard layout */
336 (VOID
)W32kGetDefaultKeyLayout();
338 return STATUS_SUCCESS
;
342 CleanupInputImp(VOID
)
344 return(STATUS_SUCCESS
);