虚拟鼠标驱动的实现
好久以前的东西了,发出来给感兴趣的朋友参考一下。
虚拟鼠标驱动就是通过驱动虚拟一个mouse,然后通过上层应用程序控制其发码,可以模拟硬件级的发码。
下面来看一下代码,主要的函数如下:
NTSTATUS
DriverEntry (
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
/*++
Routine Description:
Initialize the entry points of the driver.
--*/
{
ULONG i;
NTSTATUS status = STATUS_SUCCESS;
UNICODE_STRING deviceLinkUnicodeString;
UNICODE_STRING deviceNameUnicodeString;
RtlInitUnicodeString(&deviceNameUnicodeString, L"//Device//VMouse");
UNREFERENCED_PARAMETER (RegistryPath);
status = IoCreateDevice(DriverObject, 0,
&deviceNameUnicodeString,FILE_DEVICE_UNKNOWN,
0, FALSE, &g_DeviceObject);
if (!NT_SUCCESS(status))
{
return status;
}
RtlInitUnicodeString(&deviceLinkUnicodeString, L"//DosDevices//VMouse");
status = IoCreateSymbolicLink(&deviceLinkUnicodeString, &deviceNameUnicodeString);
if (!NT_SUCCESS(status))
{
if (g_DeviceObject)
{
IoDeleteDevice(g_DeviceObject);
return status;
}
}
g_DeviceObject->Flags |= DO_BUFFERED_IO|DO_POWER_PAGABLE;
g_DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
//
// Fill in all the dispatch entry points with the pass through function
// and the explicitly fill in the functions we are going to intercept
//
// for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
// DriverObject->MajorFunction[i] = MouFilter_DispatchPassThrough;
// }
DriverObject->MajorFunction [IRP_MJ_CREATE] =
DriverObject->MajorFunction [IRP_MJ_CLOSE] = MouFilter_CreateClose;
DriverObject->MajorFunction [IRP_MJ_PNP] = MouFilter_PnP;
DriverObject->MajorFunction [IRP_MJ_POWER] = MouFilter_Power;
DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL] =
MouFilter_InternIoCtl;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL ] = DeviceControl;
//
// If you are planning on using this function, you must create another
// device object to send the requests to. Please see the considerations
// comments for MouFilter_DispatchPassThrough for implementation details.
//
// DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL];
DriverObject->DriverUnload = MouFilter_Unload;
DriverObject->DriverExtension->AddDevice = MouFilter_AddDevice;
return STATUS_SUCCESS;
}
虚拟鼠标最主要的就是下面的部分,告诉OS你的设备属性:
NTSTATUS
MouFilter_InternIoCtl(
__in PDEVICE_OBJECT DeviceObject,
__in PIRP Irp
)
/*++
Routine Description:
This routine is the dispatch routine for internal device control requests.
There are two specific control codes that are of interest:
IOCTL_INTERNAL_MOUSE_CONNECT:
Store the old context and function pointer and replace it with our own.
This makes life much simpler than intercepting IRPs sent by the RIT and
modifying them on the way back up.
IOCTL_INTERNAL_I8042_HOOK_MOUSE:
Add in the necessary function pointers and context values so that we can
alter how the ps/2 MOUSE is initialized.
NOTE: Handling IOCTL_INTERNAL_I8042_HOOK_MOUSE is *NOT* necessary if
all you want to do is filter MOUSE_INPUT_DATAs. You can remove
the handling code and all related device extension fields and
functions to conserve space.
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the request packet.
Return Value:
Status is returned.
--*/
{
/*省略*/
case IOCTL_MOUSE_QUERY_ATTRIBUTES:
if(irpStack->Parameters.DeviceIoControl.InputBufferLength>=sizeof(MOUSE_UNIT_ID_PARAMETER))
{
}
if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <sizeof(MOUSE_ATTRIBUTES))
{
Irp->IoStatus.Status = STATUS_BUFFER_TOO_SMALL;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return status;
}
else
{
PMOUSE_ATTRIBUTES pka = (PMOUSE_ATTRIBUTES) Irp->AssociatedIrp.SystemBuffer ;
pka->MouseIdentifier=WHEELMOUSE_HID_HARDWARE;
pka->NumberOfButtons=3;
pka->SampleRate=100;
pka->InputDataQueueLength=256;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof(MOUSE_ATTRIBUTES);
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return status;
break;
}
break;
}
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver( devExt->TopOfStack, Irp);
}
和上层通信模拟按键
NTSTATUS DeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
PIO_STACK_LOCATION IrpStack = IoGetCurrentIrpStackLocation(Irp);
NTSTATUS status = STATUS_INVALID_DEVICE_REQUEST;
//ULONG OutputLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
PDEVICE_EXTENSION DevExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
if(g_DeviceObject != DeviceObject)
{
IrpStack = IoGetCurrentIrpStackLocation(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver( DevExt->TopOfStack, Irp);
}
switch( IrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_SENDBUTTON:
{
int i;
ULONG nSend = 0;
MOUSE_INPUT_DATA Data[10];
PVMOUSEBUFF Buffer = (PVMOUSEBUFF)Irp->AssociatedIrp.SystemBuffer;
ULONG InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
if( (Buffer==0) || (InputLength < sizeof(VMOUSEBUFF)) || (Buffer->nCount > 10) )
{
status = STATUS_INVALID_PARAMETER;
break;
}
RtlZeroMemory(Data,sizeof(MOUSE_INPUT_DATA)*10);
for(i =0 ; i< Buffer->nCount ; i++)
{
if (Buffer->nBtns[i].Pressed==1)// key down
{
Data[i].ButtonFlags = MouseFlag[Buffer->nBtns[i].ButtonNo-1].dwDn;
}
else if( !Buffer->nBtns[i].Pressed )//key up
{
Data[i].ButtonFlags= MouseFlag[Buffer->nBtns[i].ButtonNo-1].dwUp;
}
Data[i].UnitId = UnitId ;
}
SeviceCallback(MouseDev,Data,&Data[i],&nSend);
status = STATUS_SUCCESS;
break;
}
default:
status = STATUS_INVALID_DEVICE_REQUEST;
}
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return status;
}