update for HEAD-2003091401
[reactos.git] / 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$
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
42 #define NDEBUG
43 #include <debug.h>
44
45 /* GLOBALS *******************************************************************/
46
47 static HANDLE MouseDeviceHandle;
48 static HANDLE KeyboardThreadHandle;
49 static CLIENT_ID KeyboardThreadId;
50 static HANDLE KeyboardDeviceHandle;
51 static KEVENT InputThreadsStart;
52 static BOOLEAN InputThreadsRunning = FALSE;
53
54 /* FUNCTIONS *****************************************************************/
55
56 VOID STDCALL_FUNC STATIC
57 KeyboardThreadMain(PVOID StartContext)
58 {
59   UNICODE_STRING KeyboardDeviceName;
60   OBJECT_ATTRIBUTES KeyboardObjectAttributes;
61   IO_STATUS_BLOCK Iosb;
62   NTSTATUS Status;
63
64   RtlInitUnicodeStringFromLiteral(&KeyboardDeviceName, L"\\??\\Keyboard");
65   InitializeObjectAttributes(&KeyboardObjectAttributes,
66                              &KeyboardDeviceName,
67                              0,
68                              NULL,
69                              NULL);
70   Status = NtOpenFile(&KeyboardDeviceHandle,
71                       FILE_ALL_ACCESS,
72                       &KeyboardObjectAttributes,
73                       &Iosb,
74                       0,
75                       FILE_SYNCHRONOUS_IO_ALERT);
76   if (!NT_SUCCESS(Status))
77     {
78       DbgPrint("Win32K: Failed to open keyboard.\n");
79       return; //(Status);
80     }
81
82   for (;;)
83     {
84       /*
85        * Wait to start input.
86        */
87       Status = KeWaitForSingleObject(&InputThreadsStart,
88                                      0,
89                                      UserMode,
90                                      TRUE,
91                                      NULL);
92
93       /*
94        * Receive and process keyboard input.
95        */
96       while (InputThreadsRunning)
97         {
98           KEY_EVENT_RECORD KeyEvent;
99           LPARAM lParam;
100     BOOLEAN SysKey;
101           
102           Status = NtReadFile (KeyboardDeviceHandle, 
103                                NULL,
104                                NULL,
105                                NULL,
106                                &Iosb,
107                                &KeyEvent,
108                                sizeof(KEY_EVENT_RECORD),
109                                NULL,
110                                NULL);
111     DbgPrint( "KeyRaw: %s %04x\n",
112               KeyEvent.bKeyDown ? "down" : "up",
113               KeyEvent.wVirtualScanCode );
114
115           if (Status == STATUS_ALERTED && !InputThreadsRunning)
116             {
117               break;
118             }
119           if (!NT_SUCCESS(Status))
120             {
121               DbgPrint("Win32K: Failed to read from keyboard.\n");
122               return; //(Status);
123             }
124           
125     SysKey = KeyEvent.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED);
126         DbgPrint( "Key: %s\n", KeyEvent.bKeyDown ? "down" : "up" );
127
128           /*
129            * Post a keyboard message.
130            */
131           if (KeyEvent.bKeyDown)
132             {
133               lParam = KeyEvent.wRepeatCount | 
134                       ((KeyEvent.wVirtualScanCode << 16) & 0x00FF0000) | 0x40000000;
135
136               /* Bit 24 indicates if this is an extended key */
137         if (KeyEvent.dwControlKeyState & ENHANCED_KEY)
138           {
139             lParam |= (1 << 24);
140           }
141
142         if (SysKey)
143           {
144             lParam |= (1 << 29);  /* Context mode. 1 if ALT if pressed while the key is pressed */
145           }
146
147               MsqPostKeyboardMessage(SysKey ? WM_SYSKEYDOWN : WM_KEYDOWN, KeyEvent.wVirtualKeyCode, 
148                                      lParam);
149             }
150           else
151             {
152               lParam = KeyEvent.wRepeatCount | 
153                       ((KeyEvent.wVirtualScanCode << 16) & 0x00FF0000) | 0xC0000000;
154
155               /* Bit 24 indicates if this is an extended key */
156         if (KeyEvent.dwControlKeyState & ENHANCED_KEY)
157           {
158             lParam |= (1 << 24);
159           }
160
161         if (SysKey)
162           {
163             lParam |= (1 << 29);  /* Context mode. 1 if ALT if pressed while the key is pressed */
164           }
165               MsqPostKeyboardMessage(SysKey ? WM_SYSKEYUP : WM_KEYUP, KeyEvent.wVirtualKeyCode, 
166                                      lParam);
167             }
168         }
169     }
170 }
171
172 NTSTATUS STDCALL
173 NtUserAcquireOrReleaseInputOwnership(BOOLEAN Release)
174 {
175   if (Release && InputThreadsRunning)
176     {
177       KeClearEvent(&InputThreadsStart);
178       InputThreadsRunning = FALSE;
179       NtAlertThread(KeyboardThreadHandle);
180     }
181   else if (!Release && !InputThreadsRunning)
182     {
183       InputThreadsRunning = TRUE;
184       KeSetEvent(&InputThreadsStart, IO_NO_INCREMENT, FALSE);
185     }
186   return(STATUS_SUCCESS);
187 }
188
189 NTSTATUS FASTCALL
190 InitInputImpl(VOID)
191 {
192   NTSTATUS Status;
193   UNICODE_STRING MouseDeviceName;
194   OBJECT_ATTRIBUTES MouseObjectAttributes;
195   IO_STATUS_BLOCK Iosb;
196   PIRP Irp;
197   PFILE_OBJECT FileObject;
198   GDI_INFORMATION GdiInfo;
199   KEVENT IoEvent;
200   PIO_STACK_LOCATION StackPtr;
201
202   KeInitializeEvent(&InputThreadsStart, NotificationEvent, FALSE);
203
204   Status = PsCreateSystemThread(&KeyboardThreadHandle,
205                                 THREAD_ALL_ACCESS,
206                                 NULL,
207                                 NULL,
208                                 &KeyboardThreadId,
209                                 KeyboardThreadMain,
210                                 NULL);
211   if (!NT_SUCCESS(Status))
212     {
213       DbgPrint("Win32K: Failed to create keyboard thread.\n");
214     }
215
216   /*
217    * Connect to the mouse class driver.
218    */  
219   RtlInitUnicodeStringFromLiteral(&MouseDeviceName, L"\\??\\MouseClass");
220   InitializeObjectAttributes(&MouseObjectAttributes,
221                              &MouseDeviceName,
222                              0,
223                              NULL,
224                              NULL);
225   Status = NtOpenFile(&MouseDeviceHandle,
226                       FILE_ALL_ACCESS,
227                       &MouseObjectAttributes,
228                       &Iosb,
229                       0,
230                       0);
231   if (!NT_SUCCESS(Status))
232     {
233       DbgPrint("Win32K: Failed to open mouse.\n");
234       return(Status);
235     }
236   Status = ObReferenceObjectByHandle(MouseDeviceHandle,
237                                      FILE_READ_DATA | FILE_WRITE_DATA,
238                                      IoFileObjectType,
239                                      KernelMode,
240                                      (PVOID *) &FileObject,
241                                      NULL);
242    
243    if (!NT_SUCCESS(Status))
244      {
245        DbgPrint("Win32K: Failed to reference mouse file object.\n");
246        return(Status);
247      }
248    KeInitializeEvent(&IoEvent, FALSE, NotificationEvent);
249    GdiInfo.CallBack = MouseGDICallBack;
250    Irp = IoBuildDeviceIoControlRequest(IOCTL_INTERNAL_MOUSE_CONNECT,
251                                        FileObject->DeviceObject,
252                                        &GdiInfo,
253                                        sizeof(GdiInfo),
254                                        NULL,
255                                        0,
256                                        TRUE,
257                                        &FileObject->Event,
258                                        &Iosb);
259
260    //trigger FileObject/Event dereferencing
261    Irp->Tail.Overlay.OriginalFileObject = FileObject;
262
263    StackPtr = IoGetNextIrpStackLocation(Irp);
264    StackPtr->FileObject = FileObject;
265    StackPtr->DeviceObject = FileObject->DeviceObject;
266    StackPtr->Parameters.DeviceIoControl.InputBufferLength = sizeof(GdiInfo);
267    StackPtr->Parameters.DeviceIoControl.OutputBufferLength = 0;
268
269    Status = IoCallDriver(FileObject->DeviceObject, Irp);
270    if (Status == STATUS_PENDING)
271      {
272        KeWaitForSingleObject(&FileObject->Event, Executive, KernelMode, FALSE,
273                              NULL);
274        Status = Iosb.Status;
275      }
276    if (!NT_SUCCESS(Status))
277      {
278        DbgPrint("Win32K: Failed to connect to mouse driver.\n");
279        return(Status);
280      }
281    
282    return(STATUS_SUCCESS);
283 }
284
285 NTSTATUS FASTCALL
286 CleanupInputImp(VOID)
287 {
288   return(STATUS_SUCCESS);
289 }
290
291 BOOL
292 STDCALL
293 NtUserDragDetect(
294   HWND hWnd,
295   LONG x,
296   LONG y)
297 {
298   UNIMPLEMENTED
299   return 0;
300 }
301
302
303 /* EOF */