Moved and renamed some ReactOS specific macros
[reactos.git] / reactos / subsys / win32k / ntuser / input.c
1 /*
2 * ReactOS W32 Subsystem
3 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 ReactOS Team
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id: input.c,v 1.19 2003/11/17 02:12:52 hyperion Exp $
20 *
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)
26 * REVISION HISTORY:
27 * 06-06-2001 CSH Created
28 */
29
30 /* INCLUDES ******************************************************************/
31
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>
44
45 #define NDEBUG
46 #include <debug.h>
47
48 /* GLOBALS *******************************************************************/
49
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;
57
58 /* FUNCTIONS *****************************************************************/
59
60 VOID STDCALL_FUNC STATIC
61 KeyboardThreadMain(PVOID StartContext)
62 {
63 UNICODE_STRING KeyboardDeviceName;
64 OBJECT_ATTRIBUTES KeyboardObjectAttributes;
65 IO_STATUS_BLOCK Iosb;
66 NTSTATUS Status;
67
68 RtlRosInitUnicodeStringFromLiteral(&KeyboardDeviceName, L"\\??\\Keyboard");
69 InitializeObjectAttributes(&KeyboardObjectAttributes,
70 &KeyboardDeviceName,
71 0,
72 NULL,
73 NULL);
74 Status = NtOpenFile(&KeyboardDeviceHandle,
75 FILE_ALL_ACCESS,
76 &KeyboardObjectAttributes,
77 &Iosb,
78 0,
79 FILE_SYNCHRONOUS_IO_ALERT);
80 if (!NT_SUCCESS(Status))
81 {
82 DPRINT1("Win32K: Failed to open keyboard.\n");
83 return; //(Status);
84 }
85
86 for (;;)
87 {
88 /*
89 * Wait to start input.
90 */
91 DbgPrint( "Input Thread Waiting for start event\n" );
92 Status = KeWaitForSingleObject(&InputThreadsStart,
93 0,
94 UserMode,
95 TRUE,
96 NULL);
97 DbgPrint( "Input Thread Starting...\n" );
98
99 /*
100 * Receive and process keyboard input.
101 */
102 while (InputThreadsRunning)
103 {
104 KEY_EVENT_RECORD KeyEvent;
105 LPARAM lParam = 0;
106 UINT fsModifiers;
107 struct _ETHREAD *Thread;
108 HWND hWnd;
109 int id;
110
111 Status = NtReadFile (KeyboardDeviceHandle,
112 NULL,
113 NULL,
114 NULL,
115 &Iosb,
116 &KeyEvent,
117 sizeof(KEY_EVENT_RECORD),
118 NULL,
119 NULL);
120 DPRINT( "KeyRaw: %s %04x\n",
121 KeyEvent.bKeyDown ? "down" : "up",
122 KeyEvent.wVirtualScanCode );
123
124 if (Status == STATUS_ALERTED && !InputThreadsRunning)
125 {
126 break;
127 }
128 if (!NT_SUCCESS(Status))
129 {
130 DPRINT1("Win32K: Failed to read from keyboard.\n");
131 return; //(Status);
132 }
133
134 DPRINT( "Key: %s\n", KeyEvent.bKeyDown ? "down" : "up" );
135
136 fsModifiers = 0;
137 if (KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED))
138 fsModifiers |= MOD_ALT;
139
140 if (KeyEvent.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED))
141 fsModifiers |= MOD_CONTROL;
142
143 if (KeyEvent.dwControlKeyState & SHIFT_PRESSED)
144 fsModifiers |= MOD_SHIFT;
145
146 /* FIXME: Support MOD_WIN */
147
148 if (GetHotKey(InputWindowStation,
149 fsModifiers,
150 KeyEvent.wVirtualKeyCode,
151 &Thread,
152 &hWnd,
153 &id))
154 {
155 if (KeyEvent.bKeyDown)
156 {
157 DPRINT("Hot key pressed (hWnd %lx, id %d)\n", hWnd, id);
158 MsqPostHotKeyMessage (Thread,
159 hWnd,
160 (WPARAM)id,
161 MAKELPARAM((WORD)fsModifiers, (WORD)KeyEvent.wVirtualKeyCode));
162 }
163 }
164 else
165
166 /*
167 * Post a keyboard message.
168 */
169 if (KeyEvent.bKeyDown)
170 {
171 lParam = KeyEvent.wRepeatCount |
172 ((KeyEvent.wVirtualScanCode << 16) & 0x00FF0000) | 0x40000000;
173
174 /* Bit 24 indicates if this is an extended key */
175 if (KeyEvent.dwControlKeyState & ENHANCED_KEY)
176 {
177 lParam |= (1 << 24);
178 }
179
180 if (fsModifiers & MOD_ALT)
181 {
182 /* Context mode. 1 if ALT if pressed while the key is pressed */
183 lParam |= (1 << 29);
184 }
185
186 MsqPostKeyboardMessage((fsModifiers & MOD_ALT) ? WM_SYSKEYDOWN : WM_KEYDOWN,
187 KeyEvent.wVirtualKeyCode,
188 lParam);
189 }
190 else
191 {
192 lParam = KeyEvent.wRepeatCount |
193 ((KeyEvent.wVirtualScanCode << 16) & 0x00FF0000) | 0xC0000000;
194
195 /* Bit 24 indicates if this is an extended key */
196 if (KeyEvent.dwControlKeyState & ENHANCED_KEY)
197 {
198 lParam |= (1 << 24);
199 }
200
201 if (fsModifiers & MOD_ALT)
202 {
203 /* Context mode. 1 if ALT if pressed while the key is pressed */
204 lParam |= (1 << 29);
205 }
206
207 MsqPostKeyboardMessage((fsModifiers & MOD_ALT) ? WM_SYSKEYUP : WM_KEYUP,
208 KeyEvent.wVirtualKeyCode,
209 lParam);
210 }
211 }
212 DbgPrint( "Input Thread Stopped...\n" );
213 }
214 }
215
216
217 NTSTATUS STDCALL
218 NtUserAcquireOrReleaseInputOwnership(BOOLEAN Release)
219 {
220 if (Release && InputThreadsRunning && !pmPrimitiveMessageQueue)
221 {
222 DbgPrint( "Releasing input: PM = %08x\n", pmPrimitiveMessageQueue );
223 KeClearEvent(&InputThreadsStart);
224 InputThreadsRunning = FALSE;
225
226 NtAlertThread(KeyboardThreadHandle);
227 }
228 else if (!Release && !InputThreadsRunning)
229 {
230 InputThreadsRunning = TRUE;
231 KeSetEvent(&InputThreadsStart, IO_NO_INCREMENT, FALSE);
232 }
233
234 return(STATUS_SUCCESS);
235 }
236
237 NTSTATUS FASTCALL
238 InitInputImpl(VOID)
239 {
240 NTSTATUS Status;
241 UNICODE_STRING MouseDeviceName;
242 OBJECT_ATTRIBUTES MouseObjectAttributes;
243 IO_STATUS_BLOCK Iosb;
244 PIRP Irp;
245 PFILE_OBJECT FileObject;
246 GDI_INFORMATION GdiInfo;
247 KEVENT IoEvent;
248 PIO_STACK_LOCATION StackPtr;
249
250 KeInitializeEvent(&InputThreadsStart, NotificationEvent, FALSE);
251
252 Status = PsCreateSystemThread(&KeyboardThreadHandle,
253 THREAD_ALL_ACCESS,
254 NULL,
255 NULL,
256 &KeyboardThreadId,
257 KeyboardThreadMain,
258 NULL);
259 if (!NT_SUCCESS(Status))
260 {
261 DPRINT1("Win32K: Failed to create keyboard thread.\n");
262 }
263
264 /*
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
268 */
269 RtlRosInitUnicodeStringFromLiteral(&MouseDeviceName, L"\\??\\MouseClass");
270 InitializeObjectAttributes(&MouseObjectAttributes,
271 &MouseDeviceName,
272 0,
273 NULL,
274 NULL);
275 Status = NtOpenFile(&MouseDeviceHandle,
276 FILE_ALL_ACCESS,
277 &MouseObjectAttributes,
278 &Iosb,
279 0,
280 0);
281 if (!NT_SUCCESS(Status))
282 {
283 DPRINT1("Win32K: Failed to open mouse.\n");
284 return STATUS_SUCCESS;
285 }
286 Status = ObReferenceObjectByHandle(MouseDeviceHandle,
287 FILE_READ_DATA | FILE_WRITE_DATA,
288 IoFileObjectType,
289 KernelMode,
290 (PVOID *) &FileObject,
291 NULL);
292
293 if (!NT_SUCCESS(Status))
294 {
295 DPRINT1("Win32K: Failed to reference mouse file object.\n");
296 NtClose(MouseDeviceHandle);
297 return STATUS_SUCCESS;
298 }
299 KeInitializeEvent(&IoEvent, FALSE, NotificationEvent);
300 GdiInfo.CallBack = MouseGDICallBack;
301 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
302 FileObject->DeviceObject,
303 &GdiInfo,
304 sizeof(GdiInfo),
305 NULL,
306 0,
307 TRUE,
308 &FileObject->Event,
309 &Iosb);
310
311 //trigger FileObject/Event dereferencing
312 Irp->Tail.Overlay.OriginalFileObject = FileObject;
313
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;
319
320 Status = IoCallDriver(FileObject->DeviceObject, Irp);
321 if (Status == STATUS_PENDING)
322 {
323 KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, FALSE,
324 NULL);
325 Status = Iosb.Status;
326 }
327 if (!NT_SUCCESS(Status))
328 {
329 DPRINT1("Win32K: Failed to connect to mouse driver.\n");
330 ObDereferenceObject(&FileObject);
331 NtClose(MouseDeviceHandle);
332 return STATUS_SUCCESS;
333 }
334
335 /* Initialize the default keyboard layout */
336 (VOID)W32kGetDefaultKeyLayout();
337
338 return STATUS_SUCCESS;
339 }
340
341 NTSTATUS FASTCALL
342 CleanupInputImp(VOID)
343 {
344 return(STATUS_SUCCESS);
345 }
346
347 BOOL
348 STDCALL
349 NtUserDragDetect(
350 HWND hWnd,
351 LONG x,
352 LONG y)
353 {
354 UNIMPLEMENTED
355 return 0;
356 }
357
358 /* EOF */