现在就来依次分析函数i8042Create、i8042Cleanup、i8042Close、i8042DeviceControl、i8042InternalDeviceControl和i8042Pnp。首先分析函数i8042Create,它的实现代码如下:
#001 NTSTATUS NTAPI
#002 i8042Create(
#003 IN PDEVICE_OBJECT DeviceObject,
#004 IN PIRP Irp)
#005 {
#006 TRACE_(I8042PRT, "IRP_MJ_CREATE/n");
#007
设置IRP的状态为成功。
#008 Irp->IoStatus.Status = STATUS_SUCCESS;
返回状态信息为0。
#009 Irp->IoStatus.Information = 0;
调用函数IoCompleteRequest来设置当前IRP完成。
#010 IoCompleteRequest(Irp, IO_NO_INCREMENT);
#011 return STATUS_SUCCESS;
#012 }
函数i8042Cleanup,它的实现代码如下:
#001 NTSTATUS NTAPI
#002 i8042Cleanup(
#003 IN PDEVICE_OBJECT DeviceObject,
#004 IN PIRP Irp)
#005 {
#006 TRACE_(I8042PRT, "IRP_MJ_CLEANUP/n");
#007
设置IRP的状态为成功。
#008 Irp->IoStatus.Status = STATUS_SUCCESS;
#009 Irp->IoStatus.Information = 0;
调用函数IoCompleteRequest来设置当前IRP完成。
#010 IoCompleteRequest(Irp, IO_NO_INCREMENT);
#011 return STATUS_SUCCESS;
#012 }
函数i8042Close,它的实现代码如下:
#001 NTSTATUS NTAPI
#002 i8042Close(
#003 IN PDEVICE_OBJECT DeviceObject,
#004 IN PIRP Irp)
#005 {
#006 TRACE_(I8042PRT, "IRP_MJ_CLOSE/n");
#007
设置IRP的状态为成功。
#008 Irp->IoStatus.Status = STATUS_SUCCESS;
#009 Irp->IoStatus.Information = 0;
调用函数IoCompleteRequest来设置当前IRP完成。
#010 IoCompleteRequest(Irp, IO_NO_INCREMENT);
#011 return STATUS_SUCCESS;
#012 }
函数i8042DeviceControl,它的实现代码如下:
#001 static NTSTATUS NTAPI
#002 i8042DeviceControl(
#003 IN PDEVICE_OBJECT DeviceObject,
#004 IN PIRP Irp)
#005 {
#006 PFDO_DEVICE_EXTENSION DeviceExtension;
#007 NTSTATUS Status;
#008
#009 TRACE_(I8042PRT, "i8042DeviceControl(%p %p)/n", DeviceObject, Irp);
获取设备扩展。
#010 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
#011
根设备类型来处理。
#012 switch (DeviceExtension->Type)
#013 {
这里处理键盘类型设备。
#014 case Keyboard:
#015 return i8042KbdDeviceControl(DeviceObject, Irp);
#016 break;
#017 default:
#018 return IrpStub(DeviceObject, Irp);
#019 }
#020
#021 return Status;
#022 }
接着分析函数i8042KbdDeviceControl,它的实现代码如下:
#001 NTSTATUS NTAPI
#002 i8042KbdDeviceControl(
#003 IN PDEVICE_OBJECT DeviceObject,
#004 IN PIRP Irp)
#005 {
#006 PIO_STACK_LOCATION Stack;
#007 PI8042_KEYBOARD_EXTENSION DeviceExtension;
#008 NTSTATUS Status;
#009
获取当前IRP的栈指针。
#010 Stack = IoGetCurrentIrpStackLocation(Irp);
设置返回状态信息为0个。
#011 Irp->IoStatus.Information = 0;
获取扩展设备。
#012 DeviceExtension = (PI8042_KEYBOARD_EXTENSION)DeviceObject->DeviceExtension;
#013
根据IRP栈里的参数来获取操作码,然后根据操作码作不同的处理。
#014 switch (Stack->Parameters.DeviceIoControl.IoControlCode)
#015 {
获取系统的大写键状态。
#016 case IOCTL_GET_SYS_BUTTON_CAPS:
#017 {
#018 /* Part of GUID_DEVICE_SYS_BUTTON interface */
#019 PULONG pCaps;
#020 TRACE_(I8042PRT, "IOCTL_GET_SYS_BUTTON_CAPS/n");
#021
如果返回参数内存空间不够4个字节长,就返回非法参数。
#022 if (Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(ULONG))
#023 Status = STATUS_INVALID_PARAMETER;
#024 else
#025 {
获取系统保存参数位置。
#026 pCaps = (PULONG)Irp->AssociatedIrp.SystemBuffer;
把键盘的大写状态返回给系统。
#027 *pCaps = DeviceExtension->NewCaps;
#028 DeviceExtension->ReportedCaps = DeviceExtension->NewCaps;
设置IRP返回参数的长度为4个字节。
#029 Irp->IoStatus.Information = sizeof(ULONG);
设置返回状态为成功。
#030 Status = STATUS_SUCCESS;
#031 }
#032 break;
#033 }
获取系统按键事件。
#034 case IOCTL_GET_SYS_BUTTON_EVENT:
#035 {
#036 /* Part of GUID_DEVICE_SYS_BUTTON interface */
#037 PIRP WaitingIrp;
#038 TRACE_(I8042PRT, "IOCTL_GET_SYS_BUTTON_EVENT/n");
#039
判断是否可以返回参数,如果不可以返回,就直接返回出错。
#040 if (Stack->Parameters.DeviceIoControl.OutputBufferLength != sizeof(ULONG))
#041 Status = STATUS_INVALID_PARAMETER;
#042 else
#043 {
获取电源按键的事件。
#044 WaitingIrp = InterlockedCompareExchangePointer(
#045 &DeviceExtension->PowerIrp,
#046 Irp,
#047 NULL);
已经有一个事件的IRP在等待中,如果有就直接返回出错。
#048 /* Check if an Irp is already pending */
#049 if (WaitingIrp)
#050 {
#051 /* Unable to have a 2nd pending IRP for this IOCTL */
#052 WARN_(I8042PRT, "Unable to pend a second IRP for IOCTL_GET_SYS_BUTTON_EVENT/n");
#053 Status = STATUS_INVALID_PARAMETER;
#054 Irp->IoStatus.Status = Status;
#055 IoCompleteRequest(Irp, IO_NO_INCREMENT);
#056 }
#057 else
#058 {
如果电源的IRP已经准备好,就直接返回给系统。
#059 ULONG PowerKey;
#060 PowerKey = InterlockedExchange((PLONG)&DeviceExtension->LastPowerKey, 0);
#061 if (PowerKey != 0)
#062 {
#063 (VOID)InterlockedCompareExchangePointer(&DeviceExtension->PowerIrp, NULL, Irp);
#064 *(PULONG)Irp->AssociatedIrp.SystemBuffer = PowerKey;
#065 Status = STATUS_SUCCESS;
#066 Irp->IoStatus.Status = Status;
#067 Irp->IoStatus.Information = sizeof(ULONG);
#068 IoCompleteRequest(Irp, IO_NO_INCREMENT);
#069 }
#070 else
#071 {
#072 TRACE_(I8042PRT, "Pending IOCTL_GET_SYS_BUTTON_EVENT/n");
#073 Status = STATUS_PENDING;
#074 Irp->IoStatus.Status = Status;
#075 IoMarkIrpPending(Irp);
#076 }
#077 }
#078 return Status;
#079 }
#080 break;
#081 }
缺省是调用函数ForwardIrpAndForget把IRP前面传送。
#082 default:
#083 {
#084 ERR_(I8042PRT, "IRP_MJ_DEVICE_CONTROL / unknown ioctl code 0x%lx/n",
#085 Stack->Parameters.DeviceIoControl.IoControlCode);
#086 ASSERT(FALSE);
#087 return ForwardIrpAndForget(DeviceObject, Irp);
#088 }
#089 }
#090
#091 Irp->IoStatus.Status = Status;
#092 if (Status == STATUS_PENDING)
这里调用函数IoMarkIrpPending来标记IRP正在阻塞中。
#093 IoMarkIrpPending(Irp);
#094 else
#095 IoCompleteRequest(Irp, IO_NO_INCREMENT);
#096
#097 return Status;
#098 }
下面来分析函数i8042InternalDeviceControl的实现,代码如下:
#001 static NTSTATUS NTAPI
#002 i8042InternalDeviceControl(
#003 IN PDEVICE_OBJECT DeviceObject,
#004 IN PIRP Irp)
#005 {
#006 PFDO_DEVICE_EXTENSION DeviceExtension;
#007 ULONG ControlCode;
#008 NTSTATUS Status;
#009
#010 TRACE_(I8042PRT, "i8042InternalDeviceControl(%p %p)/n", DeviceObject, Irp);
获取设备扩展。
#011 DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
#012
根据设备扩展类型处理。
#013 switch (DeviceExtension->Type)
#014 {
不知道的类型处理。
#015 case Unknown:
#016 {
获取控制码。
#017 ControlCode = IoGetCurrentIrpStackLocation(Irp)->Parameters.DeviceIoControl.IoControlCode;
根据控制码来处理。
#018 switch (ControlCode)
#019 {
内部键盘连接处理。
#020 case IOCTL_INTERNAL_KEYBOARD_CONNECT:
进行内部的IRP处理。
#021 Status = i8042KbdInternalDeviceControl(DeviceObject, Irp);
#022 break;
内部鼠标连接处理。
#023 case IOCTL_INTERNAL_MOUSE_CONNECT:
#024 Status = i8042MouInternalDeviceControl(DeviceObject, Irp);
#025 break;
#026 default:
#027 ERR_(I8042PRT, "Unknown IO control code 0x%lx/n", ControlCode);
#028 ASSERT(FALSE);
#029 Status = STATUS_INVALID_DEVICE_REQUEST;
#030 break;
#031 }
#032 break;
#033 }
键盘处理内部IRP。
#034 case Keyboard:
#035 Status = i8042KbdInternalDeviceControl(DeviceObject, Irp);
#036 break;
鼠标处理内部IRP。
#037 case Mouse:
#038 Status = i8042MouInternalDeviceControl(DeviceObject, Irp);
#039 break;
#040 default:
#041 ERR_(I8042PRT, "Unknown FDO type %u/n", DeviceExtension->Type);
#042 ASSERT(FALSE);
#043 Status = STATUS_INTERNAL_ERROR;
#044 IoCompleteRequest(Irp, IO_NO_INCREMENT);
#045 break;
#046 }
#047
#048 return Status;
#049 }