:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / subsys / win32k / ntuser / input.c
1 /* $Id$
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                       FILE_SYNCHRONOUS_IO_ALERT);
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     }
168
169   /*
170    * Connect to the mouse class driver.
171    */  
172   RtlInitUnicodeStringFromLiteral(&MouseDeviceName, L"\\??\\MouseClass");
173   InitializeObjectAttributes(&MouseObjectAttributes,
174                              &MouseDeviceName,
175                              0,
176                              NULL,
177                              NULL);
178   Status = NtOpenFile(&MouseDeviceHandle,
179                       FILE_ALL_ACCESS,
180                       &MouseObjectAttributes,
181                       &Iosb,
182                       0,
183                       0);
184   if (!NT_SUCCESS(Status))
185     {
186       DbgPrint("W32K: Failed to open mouse.\n");
187       return(Status);
188     }
189   Status = ObReferenceObjectByHandle(MouseDeviceHandle,
190                                      FILE_READ_DATA | FILE_WRITE_DATA,
191                                      IoFileObjectType,
192                                      KernelMode,
193                                      (PVOID *) &FileObject,
194                                      NULL);
195    
196    if (!NT_SUCCESS(Status))
197      {
198        DbgPrint("W32K: Failed to reference mouse file object.\n");
199        return(Status);
200      }
201    KeInitializeEvent(&IoEvent, FALSE, NotificationEvent);
202    GdiInfo.CallBack = MouseGDICallBack;
203    Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
204                                        FileObject->DeviceObject,
205                                        &GdiInfo,
206                                        sizeof(GdiInfo),
207                                        NULL,
208                                        0,
209                                        TRUE,
210                                        &FileObject->Event,
211                                        &Iosb);
212    StackPtr = IoGetNextIrpStackLocation(Irp);
213    StackPtr->FileObject = FileObject;
214    StackPtr->DeviceObject = FileObject->DeviceObject;
215    StackPtr->Parameters.DeviceIoControl.InputBufferLength = sizeof(GdiInfo);
216    StackPtr->Parameters.DeviceIoControl.OutputBufferLength = 0;
217
218    Status = IoCallDriver(FileObject->DeviceObject, Irp);
219    if (Status == STATUS_PENDING)
220      {
221        KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, FALSE,
222                              NULL);
223        Status = Iosb.Status;
224      }
225    if (!NT_SUCCESS(Status))
226      {
227        DbgPrint("W32K: Failed to connect to mouse driver.\n");
228        return(Status);
229      }
230    
231    return(STATUS_SUCCESS);
232 }
233
234 NTSTATUS
235 CleanupInputImp(VOID)
236 {
237   return(STATUS_SUCCESS);
238 }
239
240 /* EOF */