Misc. user fixes.
[reactos.git] / reactos / subsys / win32k / ntuser / input.c
1 /* $Id: input.c,v 1.3 2002/09/17 23:43:28 dwelch Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * PURPOSE: Window classes
6 * FILE: subsys/win32k/ntuser/class.c
7 * PROGRAMER: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * REVISION HISTORY:
9 * 06-06-2001 CSH Created
10 */
11
12 /* INCLUDES ******************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <win32k/win32k.h>
16 #include <win32k/userobj.h>
17 #include <include/class.h>
18 #include <include/error.h>
19 #include <include/winsta.h>
20 #include <include/msgqueue.h>
21 #include "../../drivers/input/include/mouse.h"
22
23 #define NDEBUG
24 #include <debug.h>
25
26 /* GLOBALS *******************************************************************/
27
28 static HANDLE MouseDeviceHandle;
29 static HANDLE KeyboardThreadHandle;
30 static CLIENT_ID KeyboardThreadId;
31 static HANDLE KeyboardDeviceHandle;
32 static KEVENT InputThreadsStart;
33 static BOOLEAN InputThreadsRunning = FALSE;
34
35 VOID MouseGDICallBack(PMOUSE_INPUT_DATA Data, ULONG InputCount);
36
37 /* FUNCTIONS *****************************************************************/
38
39 NTSTATUS STDCALL STATIC
40 KeyboardThreadMain(PVOID StartContext)
41 {
42 UNICODE_STRING KeyboardDeviceName;
43 OBJECT_ATTRIBUTES KeyboardObjectAttributes;
44 IO_STATUS_BLOCK Iosb;
45 NTSTATUS Status;
46
47 RtlInitUnicodeStringFromLiteral(&KeyboardDeviceName, L"\\??\\Keyboard");
48 InitializeObjectAttributes(&KeyboardObjectAttributes,
49 &KeyboardDeviceName,
50 0,
51 NULL,
52 NULL);
53 Status = NtOpenFile(&KeyboardDeviceHandle,
54 FILE_ALL_ACCESS,
55 &KeyboardObjectAttributes,
56 &Iosb,
57 0,
58 0);
59 if (!NT_SUCCESS(Status))
60 {
61 DbgPrint("W32K: Failed to open keyboard.\n");
62 return(Status);
63 }
64
65 for (;;)
66 {
67 /*
68 * Wait to start input.
69 */
70 Status = KeWaitForSingleObject(&InputThreadsStart,
71 0,
72 UserMode,
73 TRUE,
74 NULL);
75 /*
76 * Receive and process keyboard input.
77 */
78 while (InputThreadsRunning)
79 {
80 KEY_EVENT_RECORD KeyEvent;
81 LPARAM lParam;
82
83 Status = NtReadFile (KeyboardDeviceHandle,
84 NULL,
85 NULL,
86 NULL,
87 &Iosb,
88 &KeyEvent,
89 sizeof(KEY_EVENT_RECORD),
90 NULL,
91 NULL);
92 if (Status == STATUS_ALERTED && !InputThreadsRunning)
93 {
94 break;
95 }
96 if (!NT_SUCCESS(Status))
97 {
98 DbgPrint("W32K: Failed to read from keyboard.\n");
99 return(Status);
100 }
101
102 /*
103 * Post a keyboard message.
104 */
105 if (KeyEvent.bKeyDown)
106 {
107 /* FIXME: Bit 24 indicates if this is an extended key. */
108 lParam = KeyEvent.wRepeatCount |
109 ((KeyEvent.wVirtualScanCode << 16) & 0x00FF0000) | 0x40000000;
110 MsqPostKeyboardMessage(WM_KEYDOWN, KeyEvent.wVirtualKeyCode,
111 lParam);
112 }
113 else
114 {
115 /* FIXME: Bit 24 indicates if this is an extended key. */
116 lParam = KeyEvent.wRepeatCount |
117 ((KeyEvent.wVirtualScanCode << 16) & 0x00FF0000) | 0xC0000000;
118 MsqPostKeyboardMessage(WM_KEYUP, KeyEvent.wVirtualKeyCode,
119 lParam);
120 }
121 }
122 }
123 }
124
125 NTSTATUS STDCALL
126 NtUserAcquireOrReleaseInputOwnership(BOOLEAN Release)
127 {
128 if (Release && InputThreadsRunning)
129 {
130 KeClearEvent(&InputThreadsStart);
131 InputThreadsRunning = FALSE;
132 NtAlertThread(KeyboardThreadHandle);
133 }
134 else if (!Release && !InputThreadsRunning)
135 {
136 InputThreadsRunning = TRUE;
137 KeSetEvent(&InputThreadsStart, IO_NO_INCREMENT, FALSE);
138 }
139 return(STATUS_SUCCESS);
140 }
141
142 NTSTATUS
143 InitInputImpl(VOID)
144 {
145 NTSTATUS Status;
146 UNICODE_STRING MouseDeviceName;
147 OBJECT_ATTRIBUTES MouseObjectAttributes;
148 IO_STATUS_BLOCK Iosb;
149 PIRP Irp;
150 PFILE_OBJECT FileObject;
151 GDI_INFORMATION GdiInfo;
152 KEVENT IoEvent;
153 PIO_STACK_LOCATION StackPtr;
154
155 KeInitializeEvent(&InputThreadsStart, NotificationEvent, FALSE);
156
157 Status = PsCreateSystemThread(&KeyboardThreadHandle,
158 THREAD_ALL_ACCESS,
159 NULL,
160 NULL,
161 &KeyboardThreadId,
162 KeyboardThreadMain,
163 NULL);
164 if (!NT_SUCCESS(Status))
165 {
166 DbgPrint("W32K: Failed to create keyboard thread.\n");
167 NtClose(KeyboardThreadHandle);
168 }
169
170 /*
171 * Connect to the mouse class driver.
172 */
173 RtlInitUnicodeStringFromLiteral(&MouseDeviceName, L"\\??\\MouseClass");
174 InitializeObjectAttributes(&MouseObjectAttributes,
175 &MouseDeviceName,
176 0,
177 NULL,
178 NULL);
179 Status = NtOpenFile(&MouseDeviceHandle,
180 FILE_ALL_ACCESS,
181 &MouseObjectAttributes,
182 &Iosb,
183 0,
184 0);
185 if (!NT_SUCCESS(Status))
186 {
187 DbgPrint("W32K: Failed to open mouse.\n");
188 return(Status);
189 }
190 Status = ObReferenceObjectByHandle(MouseDeviceHandle,
191 FILE_READ_DATA | FILE_WRITE_DATA,
192 IoFileObjectType,
193 KernelMode,
194 (PVOID *) &FileObject,
195 NULL);
196
197 if (!NT_SUCCESS(Status))
198 {
199 DbgPrint("W32K: Failed to reference mouse file object.\n");
200 return(Status);
201 }
202 KeInitializeEvent(&IoEvent, FALSE, NotificationEvent);
203 GdiInfo.CallBack = MouseGDICallBack;
204 Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
205 FileObject->DeviceObject,
206 &GdiInfo,
207 sizeof(GdiInfo),
208 NULL,
209 0,
210 TRUE,
211 &FileObject->Event,
212 &Iosb);
213 StackPtr = IoGetNextIrpStackLocation(Irp);
214 StackPtr->FileObject = FileObject;
215 StackPtr->DeviceObject = FileObject->DeviceObject;
216 StackPtr->Parameters.DeviceIoControl.InputBufferLength = sizeof(GdiInfo);
217 StackPtr->Parameters.DeviceIoControl.OutputBufferLength = 0;
218
219 Status = IoCallDriver(FileObject->DeviceObject, Irp);
220 if (Status == STATUS_PENDING)
221 {
222 KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, FALSE,
223 NULL);
224 Status = Iosb.Status;
225 }
226 if (!NT_SUCCESS(Status))
227 {
228 DbgPrint("W32K: Failed to connect to mouse driver.\n");
229 return(Status);
230 }
231
232 return(STATUS_SUCCESS);
233 }
234
235 NTSTATUS
236 CleanupInputImp(VOID)
237 {
238 return(STATUS_SUCCESS);
239 }
240
241 /* EOF */