reactos/rosapps/sysutils/utils/pice/module/patch.c

236 lines
6.7 KiB
C

/*++
Copyright (c) 1998-2001 Klaus P. Gerlicher
Module Name:
patch.c
Abstract:
hooking of kernel internal keyboard interrupt handler
Environment:
Kernel mode only
Author:
Klaus P. Gerlicher
Reactos Port: Eugene Ingerman
Revision History:
10-Jul-1999: created
15-Nov-2000: general cleanup of source files
12/1/2001 reactos port
Copyright notice:
This file may be distributed under the terms of the GNU Public License.
--*/
////////////////////////////////////////////////////
// INCLUDES
////
#include "remods.h"
#include "precomp.h"
//#include <asm/system.h>
#include <ntddkbd.h>
#include <ntdd8042.h>
#include <rosrtl/string.h>
////////////////////////////////////////////////////
// GLOBALS
////
static PUCHAR pPatchAddress;
static ULONG ulOldOffset = 0;
static ULONG ulKeyPatchFlags;
void (*old_handle_scancode)(UCHAR,int);
char tempPatch[256];
UCHAR ucBreakKey = 'd'; // key that will break into debugger in combination with CTRL
////////////////////////////////////////////////////
// FUNCTIONS
////
//***********************************************************************************
// PiceKbdIsr - keyboard isr hook routine.
// IsrContext - context that we passed to keyboard driver in internal iocontrol
// pCurrentInput, pCurrentOutput - not implemented yet
// StatusByte - keyboard status register
// pByte - pointer to the byte read from keyboard data port. can be changed.
// pContinueProcessing - should keyboard driver continue processing this byte.
//***********************************************************************************
BOOLEAN PiceKbdIsr (
PVOID IsrContext,
PKEYBOARD_INPUT_DATA pCurrentInput,
POUTPUT_PACKET pCurrentOutput,
UCHAR StatusByte,
PUCHAR pByte,
PBOOLEAN pContinueProcessing,
PKEYBOARD_SCAN_STATE pScanState
)
{
static BOOLEAN bControl = FALSE;
BOOLEAN bForward=TRUE; // should we let keyboard driver process this keystroke
BOOLEAN isDown=!(*pByte & 0x80);
UCHAR ucKey = *pByte & 0x7f;
ENTER_FUNC();
// BUG?? should protect with spinlock since bControl is static.
DPRINT((0,"PiceKbdIsr(pByte: %x, val: %x,%u)\n",pByte,*pByte,isDown));
DPRINT((0,"PiceKbdIsr(1): bControl = %u bForward = %u bEnterNow = %u\n",bControl,bForward,bEnterNow));
if(isDown)
{
DPRINT((0,"bControl: %x, ucKey: %x, breakkey: %x\n", bControl, ucKey, AsciiToScan(ucBreakKey)));
// CTRL pressed
if(ucKey==0x1d)
{
bControl=TRUE;
}
else if(bControl==TRUE && ucKey==AsciiToScan(ucBreakKey)) // CTRL-D
{
// fake a CTRL-D release call
bEnterNow=TRUE;
bControl=FALSE;
// simulate an initial break
__asm__("\n\t \
pushfl\n\t \
pushl %cs\n\t \
pushl $returnpoint\n\t \
pushl $" STR(REASON_CTRLF) "\n\t \
jmp NewInt31Handler\n\t \
returnpoint:");
*pByte = 0x1d | 0x80 | 0x7f;
bForward=TRUE;
}
else if((ucKey == 66|| ucKey == 68) && bStepping)
{
bForward=FALSE;
}
}
else
{
// CTRL released
if(ucKey==0x1d)
{
bControl=FALSE;
}
else if((ucKey == 66|| ucKey == 68) && bStepping)
{
bForward=FALSE;
}
}
*pContinueProcessing = bForward;
DPRINT((5,"*pContinueProcessing: %d\n", *pContinueProcessing));
LEAVE_FUNC();
return TRUE;
}
//***********************************************************************************
// PiceSendIoctl - send internal_io_control to the driver
// Target - Device Object that receives control request
// Ioctl - request
// InputBuffer - Type3Buffer will be pointing here
// InputBufferLength - length of inputbuffer
//***********************************************************************************
NTSTATUS PiceSendIoctl(PDEVICE_OBJECT Target, ULONG Ioctl,
PVOID InputBuffer, ULONG InputBufferLength)
{
KEVENT event;
NTSTATUS status = STATUS_SUCCESS;
IO_STATUS_BLOCK iosb;
PIRP irp;
KeInitializeEvent(&event,
NotificationEvent,
FALSE
);
if (NULL == (irp = IoBuildDeviceIoControlRequest(Ioctl,
Target,
InputBuffer,
InputBufferLength,
0,
0,
TRUE,
&event,
&iosb))) {
DPRINT((0,"PiceSendIoctl: STATUS_INSUFFICIENT_RESOURCES\n"));
return STATUS_INSUFFICIENT_RESOURCES;
}
status = IoCallDriver(Target, irp);
if (STATUS_PENDING == status) {
status = KeWaitForSingleObject(&event,
Executive,
KernelMode,
FALSE,
NULL);
ASSERT(STATUS_SUCCESS == status);
status = iosb.Status;
}
DPRINT((0,"PiceSendIoctl: status: %d\n",NT_SUCCESS(status)));
return status;
}
//**************************************************
// PatchKeyboardDriver - set keyboard driver hook.
// We use interface supported by standard keyboard drivers.
//**************************************************
BOOLEAN PatchKeyboardDriver(void)
{
PINTERNAL_I8042_HOOK_KEYBOARD phkData;
//When we have i8042 driver this should be changed!!!!!!!
UNICODE_STRING DevName = ROS_STRING_INITIALIZER(L"\\Device\\Keyboard");
PDEVICE_OBJECT kbdDevice = NULL;
PFILE_OBJECT FO = NULL;
NTSTATUS status;
ENTER_FUNC();
//Get pointer to keyboard device
if( !NT_SUCCESS( status = IoGetDeviceObjectPointer( &DevName, FILE_READ_ACCESS, &FO, &kbdDevice ) ) )
{
DPRINT((0,"PatchKeyboardDriver: IoGetDeviceObjectPointer status: %x\n", status));
return FALSE;
}
phkData = ExAllocatePool( PagedPool, sizeof( INTERNAL_I8042_HOOK_KEYBOARD ) );
RtlZeroMemory( phkData, sizeof( INTERNAL_I8042_HOOK_KEYBOARD ) );
phkData->IsrRoutine = (PI8042_KEYBOARD_ISR) PiceKbdIsr;
phkData->Context = (PVOID) NULL; //DeviceObject;
//call keyboard device internal io control to hook keyboard input stream
status = PiceSendIoctl( kbdDevice, IOCTL_INTERNAL_I8042_HOOK_KEYBOARD,
phkData, sizeof( INTERNAL_I8042_HOOK_KEYBOARD ) );
DPRINT((0,"PatchKeyboardDriver: PiceSendIoctl status: %x\n", status));
ObDereferenceObject(FO);
ExFreePool(phkData);
LEAVE_FUNC();
return NT_SUCCESS(status);
}
void RestoreKeyboardDriver(void)
{
ENTER_FUNC();
DbgPrint("RestoreKeyboardDriver: Not Implemented yet!!!\n");
LEAVE_FUNC();
}