:pserver:cvsanon@mok.lvcm.com:/CVS/ReactOS reactos
[reactos.git] / apps / utils / pice / module / patch.c
1 /*++
2
3 Copyright (c) 1998-2001 Klaus P. Gerlicher
4
5 Module Name:
6
7     patch.c
8
9 Abstract:
10
11     hooking of kernel internal keyboard interrupt handler
12
13 Environment:
14
15     Kernel mode only
16
17 Author:
18
19     Klaus P. Gerlicher
20         Reactos Port: Eugene Ingerman
21
22 Revision History:
23
24     10-Jul-1999:        created
25     15-Nov-2000:    general cleanup of source files
26         12/1/2001               reactos port
27
28 Copyright notice:
29
30   This file may be distributed under the terms of the GNU Public License.
31
32 --*/
33
34 ////////////////////////////////////////////////////
35 // INCLUDES
36 ////
37 #include "remods.h"
38 #include "precomp.h"
39
40 //#include <asm/system.h>
41
42 #include <ddk/ntddkbd.h>
43 #include <ddk/ntdd8042.h>
44
45 ////////////////////////////////////////////////////
46 // GLOBALS
47 ////
48
49 static PUCHAR pPatchAddress;
50 static ULONG ulOldOffset = 0;
51 static ULONG ulKeyPatchFlags;
52
53 void (*old_handle_scancode)(UCHAR,int);
54 char tempPatch[256];
55 UCHAR ucBreakKey = 'd'; // key that will break into debugger in combination with CTRL
56
57 ////////////////////////////////////////////////////
58 // FUNCTIONS
59 ////
60
61 //***********************************************************************************
62 //      PiceKbdIsr - keyboard isr hook routine.
63 //      IsrContext - context that we passed to keyboard driver in  internal iocontrol
64 //      pCurrentInput, pCurrentOutput - not implemented yet
65 //      StatusByte -  keyboard status register
66 //      pByte - pointer to the byte read from keyboard data port. can be changed.
67 //      pContinueProcessing - should keyboard driver continue processing this byte.
68 //***********************************************************************************
69 BOOLEAN PiceKbdIsr (
70     PVOID                   IsrContext,
71     PKEYBOARD_INPUT_DATA    pCurrentInput,
72     POUTPUT_PACKET          pCurrentOutput,
73     UCHAR                   StatusByte,
74     PUCHAR                  pByte,
75     PBOOLEAN                pContinueProcessing,
76     PKEYBOARD_SCAN_STATE    pScanState
77     )
78 {
79         static BOOLEAN bControl = FALSE;
80         BOOLEAN bForward=TRUE;              // should we let keyboard driver process this keystroke
81         BOOLEAN isDown=!(*pByte & 0x80);
82         UCHAR ucKey = *pByte & 0x7f;
83
84     ENTER_FUNC();
85
86         // BUG?? should protect with spinlock since bControl is static.
87     DPRINT((0,"PiceKbdIsr(pByte: %x, val: %x,%u)\n",pByte,*pByte,isDown));
88     DPRINT((0,"PiceKbdIsr(1): bControl = %u bForward = %u bEnterNow = %u\n",bControl,bForward,bEnterNow));
89
90         if(isDown)
91         {
92                 DPRINT((0,"bControl: %x, ucKey: %x, breakkey: %x\n", bControl, ucKey, AsciiToScan(ucBreakKey)));
93                 // CTRL pressed
94                 if(ucKey==0x1d)
95                 {
96                         bControl=TRUE;
97                 }
98                 else if(bControl==TRUE && ucKey==AsciiToScan(ucBreakKey)) // CTRL-D
99                 {
100             // fake a CTRL-D release call
101             bEnterNow=TRUE;
102                         bControl=FALSE;
103         // simulate an initial break
104         __asm__("\n\t \
105             pushfl\n\t \
106             pushl %cs\n\t \
107             pushl $returnpoint\n\t \
108             pushl $" STR(REASON_CTRLF) "\n\t \
109             jmp NewInt31Handler\n\t \
110                         returnpoint:");
111                         *pByte =  0x1d | 0x80 | 0x7f;
112                         bForward=TRUE;
113                 }
114         else if((ucKey == 66|| ucKey == 68) && bStepping)
115         {
116                         bForward=FALSE;
117         }
118
119         }
120         else
121         {
122         // CTRL released
123                 if(ucKey==0x1d)
124                 {
125                         bControl=FALSE;
126                 }
127         else if((ucKey == 66|| ucKey == 68) && bStepping)
128         {
129                         bForward=FALSE;
130         }
131     }
132         *pContinueProcessing = bForward;
133         DPRINT((5,"*pContinueProcessing: %d\n", *pContinueProcessing));
134     LEAVE_FUNC();
135         return TRUE;
136 }
137
138 //***********************************************************************************
139 //      PiceSendIoctl - send internal_io_control to the driver
140 //      Target - Device Object that receives control request
141 //      Ioctl - request
142 //      InputBuffer - Type3Buffer will be pointing here
143 //      InputBufferLength - length of inputbuffer
144 //***********************************************************************************
145 NTSTATUS PiceSendIoctl(PDEVICE_OBJECT Target, ULONG Ioctl,
146                                         PVOID InputBuffer, ULONG InputBufferLength)
147 {
148     KEVENT          event;
149     NTSTATUS        status = STATUS_SUCCESS;
150     IO_STATUS_BLOCK iosb;
151     PIRP            irp;
152
153     KeInitializeEvent(&event,
154                       NotificationEvent,
155                       FALSE
156                       );
157
158     if (NULL == (irp = IoBuildDeviceIoControlRequest(Ioctl,
159                                                      Target,
160                                                      InputBuffer,
161                                                      InputBufferLength,
162                                                      0,
163                                                      0,
164                                                      TRUE,
165                                                      &event,
166                                                      &iosb))) {
167                 DPRINT((0,"PiceSendIoctl: STATUS_INSUFFICIENT_RESOURCES\n"));
168         return STATUS_INSUFFICIENT_RESOURCES;
169     }
170
171     status = IoCallDriver(Target, irp);
172
173     if (STATUS_PENDING == status) {
174
175                 status = KeWaitForSingleObject(&event,
176                                        Executive,
177                                        KernelMode,
178                                        FALSE,
179                                        NULL);
180
181         ASSERT(STATUS_SUCCESS == status);
182         status = iosb.Status;
183     }
184         DPRINT((0,"PiceSendIoctl: status: %d\n",NT_SUCCESS(status)));
185     return status;
186 }
187
188 //**************************************************
189 // PatchKeyboardDriver - set keyboard driver hook.
190 // We use interface supported by standard keyboard drivers.
191 //**************************************************
192 BOOLEAN PatchKeyboardDriver(void)
193 {
194         PINTERNAL_I8042_HOOK_KEYBOARD phkData;
195         //When we have i8042 driver this should be changed!!!!!!!
196     UNICODE_STRING DevName = UNICODE_STRING_INITIALIZER(L"\\Device\\Keyboard");
197         PDEVICE_OBJECT kbdDevice = NULL;
198         PFILE_OBJECT FO = NULL;
199         NTSTATUS status;
200
201         ENTER_FUNC();
202
203         //Get pointer to keyboard device
204     if( !NT_SUCCESS( status = IoGetDeviceObjectPointer( &DevName, FILE_READ_ACCESS, &FO, &kbdDevice ) ) )
205         {
206                 DPRINT((0,"PatchKeyboardDriver: IoGetDeviceObjectPointer status: %x\n", status));
207                 return FALSE;
208         }
209         phkData = ExAllocatePool( PagedPool, sizeof( INTERNAL_I8042_HOOK_KEYBOARD ) );
210         RtlZeroMemory( phkData, sizeof( INTERNAL_I8042_HOOK_KEYBOARD ) );
211
212         phkData->IsrRoutine = (PI8042_KEYBOARD_ISR) PiceKbdIsr;
213         phkData->Context = (PVOID) NULL; //DeviceObject;
214
215         //call keyboard device internal io control to hook keyboard input stream
216         status = PiceSendIoctl( kbdDevice, IOCTL_INTERNAL_I8042_HOOK_KEYBOARD,
217                         phkData, sizeof( INTERNAL_I8042_HOOK_KEYBOARD ) );
218         DPRINT((0,"PatchKeyboardDriver: PiceSendIoctl status: %x\n", status));
219
220
221         ObDereferenceObject(FO);
222         ExFreePool(phkData);
223
224         LEAVE_FUNC();
225
226     return NT_SUCCESS(status);
227 }
228
229 void RestoreKeyboardDriver(void)
230 {
231     ENTER_FUNC();
232     DbgPrint("RestoreKeyboardDriver: Not Implemented yet!!!\n");
233         LEAVE_FUNC();
234 }