VBoxMouse.cpp revision 77c694a82b69758f901218fd315d39778e859c17
2N/A * VBoxGuest -- VirtualBox Win32 guest mouse filter driver 2N/A * Based on a Microsoft DDK sample 2N/A * Copyright (C) 2006-2007 Sun Microsystems, Inc. 2N/A * This file is part of VirtualBox Open Source Edition (OSE), as 2N/A * you can redistribute it and/or modify it under the terms of the GNU 2N/A * General Public License (GPL) as published by the Free Software 2N/A * Foundation, in version 2 as it comes in the "COPYING" file of the 2N/A * VirtualBox OSE distribution. VirtualBox OSE is distributed in the 2N/A * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind. 2N/A * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa 2N/A * additional information or have any questions. 2N/A// #define LOG_ENABLED 2N/A Initialize the entry points of the driver. 2N/A // Fill in all the dispatch entry points with the pass through function 2N/A // and the explicitly fill in the functions we are going to intercept 2N/A// ExInitializeFastMutex(&vboxControlMutex); 2N/A// DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = VBoxDispatchIo; 2N/A dprintf((
"VBoxMouse::DriverEntry: Leaving DriverEntry with success\n"));
2N/A#
endif /* LOG_ENABLED */ 2N/A /* Do one time initialization. */ 2N/A /* Atomically set the flag. */ 2N/A dprintf((
"VBoxMouse::vboxDeviceAdded: Guest library initialization OK\n"));
2N/A dprintf((
"VBoxMouse::vboxDeviceAdded: Guest library initialization failed\n"));
2N/A dprintf((
"VBoxMouse::vboxDeviceAdded: looking for host mouse: Len is %d, status %x\n",
2N/A /* Check whether the device claims the IO port 0x60 or interrupt 12. */ 2N/A dprintf((
"VBoxMouse::vboxDeviceAdded: Configuration: Number of descriptors = %d\n",
2N/A dprintf((
"VBoxMouse::vboxDeviceAdded: Descriptor %d: InterfaceType %d, BusType %d, list ver %d, list rev %d, count %d\n",
2N/A dprintf((
"VBoxMouse::vboxDeviceAdded: PartialDescriptor %d: type %d, ShareDisposition %d, Flags 0x%04X, Start 0x%llx, length 0x%x\n",
2N/A /* It's the emulated 8042 PS/2 mouse/kbd device, so mark it as the Host one. 2N/A * For this device the filter will query absolute mouse coords from the host. 2N/A dprintf((
"VBoxMouse::vboxDeviceAdded: Host mouse found.\n"));
2N/A /* Save the allocated request pointer and clear the devExt. */ 2N/A // tell the VMM that from now on we can't handle absolute coordinates anymore 2N/A dprintf((
"VBoxMouse::vboxDeviceRemoved: ERROR communicating new mouse capabilities to VMMDev.\n" 2N/A dprintf((
"VBoxMouse::vboxDeviceRemoved: the request allocation has failed.\n"));
2N/A /* Set the flag to prevent reinitializing of the VBGL. */ 2N/A /* The VBGL is now in the not initialized state. */ 2N/A /* Inform host that we support absolute */ 2N/A dprintf((
"VBoxMouse::vboxInformHost: ERROR communicating new mouse capabilities to VMMDev." 2N/A /* Preallocate request for ServiceCallback */ 2N/A dprintf((
"VBoxMouse::vboxInformHost: request allocation for service callback failed\n"));
2N/A#
endif /* LOG_ENABLED */ 2N/A Generic completion routine that allows the driver to send the irp down the 2N/A stack, catch it on the way up, and do more processing at the original IRQL. 2N/A // We could switch on the major and minor functions of the IRP to perform 2N/A // different functions, but we know that Context is an event that needs Maintain a simple count of the creates and closes sent against this device dprintf((
"VBoxMouse::CreateClose: IRP_MJ_CREATE\n"));
// No Connection yet. How can we be enabled? dprintf((
"VBoxMouse::CreateClose: Not connected, returning STATUS_INVALID_DEVICE_STATE\n"));
// First time enable here // More than one create was sent down dprintf((
"VBoxMouse::CreateClose: IRP_MJ_CLOSE\n"));
// successfully closed the device, do any appropriate work here // Pass on the create and the close Passes a request on to the lower driver. If you are creating another device object (to communicate with user mode via IOCTLs), then this function must act differently based on the intended device object. If the IRP is being sent to the solitary device object, then this function should just complete the IRP (becuase there is no more stack locations below it). If the IRP is being sent to the PnP built stack, then the IRP should be passed down the stack. These changes must also be propagated to all the other IRP_MJ dispatch functions (such as create, close, cleanup, etc.) as well! dprintf((
"VBoxMouse_DispatchPassThrough\n"));
// Pass the IRP to the target 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. DeviceObject - Pointer to the device object. Irp - Pointer to the request packet. dprintf((
"VBoxMouse_InternIoCtl: %08X, fn = %d(%04X)\n",
// Connect a mouse class device driver to the port driver. // Only allow one connection. // Copy the connection parameters to the device extension. // Hook into the report chain. Everytime a mouse packet is reported to // the system, VBoxMouse_ServiceCallback will be called // Disconnect a mouse class device driver from the port driver. // Clear the connection parameters in the device extension. // devExt->UpperConnectData.ClassDeviceObject = NULL; // devExt->UpperConnectData.ClassService = NULL; // Attach this driver to the initialization and byte processing of the // i8042 (ie PS/2) mouse. This is only necessary if you want to do PS/2 // specific functions, otherwise hooking the CONNECT_DATA is sufficient // Copy the connection parameters to the device extension. // Set isr routine and context and record any values from above this driver // Store all of the other functions we might need in the future // These internal ioctls are not supported by the new PnP model. // Might want to capture this in the future. For now, then pass it down // the stack. These queries must be successful for the RIT to communicate dprintf((
"VBoxMouse_InternIoCtl: calling VBoxInformHost\n"));
This routine is the dispatch routine for plug and play irps DeviceObject - Pointer to the device object. Irp - Pointer to the request packet. dprintf((
"VBoxMouse_PnP: IRP_MN_START_DEVICE\n"));
// The device is starting. // We cannot touch the device (send it any non pnp irps) until a // start device has been passed down to the lower drivers. TRUE);
// No need for Cancel // We must now complete the IRP, since we stopped it in the // completetion routine with MORE_PROCESSING_REQUIRED. dprintf((
"VBoxMouse_PnP: IRP_MN_SURPRISE_REMOVAL\n"));
// Same as a remove device, but don't call IoDetach or IoDeleteDevice dprintf((
"VBoxMouse_PnP: IRP_MN_REMOVE_DEVICE\n"));
// Here the filter driver might modify the behavior of these IRPS // Please see PlugPlay documentation for use of these IRPs. This routine is the dispatch routine for power irps Does nothing except record the state of the device. DeviceObject - Pointer to the device object. Irp - Pointer to the request packet. i8042prt specific code, if you are writing a packet only filter driver, you DeviceObject - Our context passed during IOCTL_INTERNAL_I8042_HOOK_MOUSE CurrentInput - Current input packet being formulated by processing all the CurrentOutput - Current list of bytes being written to the mouse or the StatusByte - Byte read from I/O port 60 when the interrupt occurred DataByte - Byte read from I/O port 64 when the interrupt occurred. This value can be modified and i8042prt will use this value if ContinueProcessing is TRUE ContinueProcessing - If TRUE, i8042prt will proceed with normal processing of the interrupt. If FALSE, i8042prt will return from the interrupt after this function returns. Also, if FALSE, it is this functions responsibilityt to report the input packet via the function provided in the hook IOCTL or via queueing a DPC within this driver and calling the service callback function acquired from the connect IOCTL //dprintf(("VBoxMouse_IsrHook\n")); Called when there are mouse packets to report to the RIT. You can do anything you like to the packets. For instance: o Drop a packet altogether o Mutate the contents of a packet o Insert packets into the stream DeviceObject - Context passed during the connect IOCTL InputDataStart - First packet to be reported InputDataEnd - One past the last packet to be reported. Total number of packets is equal to InputDataEnd - InputDataStart InputDataConsumed - Set to the total number of packets consumed by the RIT (via the function pointer we replaced in the connect // dprintf(("VBoxMouse_ServiceCallback: devExt = %p, reqSC = %p\n", devExt, devExt->reqSC)); dprintf((
"VBoxMouse::VBoxMouse_ServiceCallback: ERROR querying mouse capabilities from VMMDev." // UpperConnectData must be called at DISPATCH Free all the allocated resources associated with this driver. DriverObject - Pointer to the driver object.