📄 dispatch.c
字号:
/*
* IntVideoPortWrite
*
* This is a bit of a hack. We want to take ownership of the display as late
* as possible, just before the switch to graphics mode. Win32k knows when
* this happens, we don't. So we need Win32k to inform us. This could be done
* using an IOCTL, but there's no way of knowing which IOCTL codes are unused
* in the communication between GDI driver and miniport driver. So we use
* IRP_MJ_WRITE as the signal that win32k is ready to switch to graphics mode,
* since we know for certain that there is no read/write activity going on
* between GDI and miniport drivers.
* We don't actually need the data that is passed, we just trigger on the fact
* that an IRP_MJ_WRITE was sent.
*
* Run Level
* PASSIVE_LEVEL
*/
NTSTATUS NTAPI
IntVideoPortDispatchWrite(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION piosStack = IoGetCurrentIrpStackLocation(Irp);
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
NTSTATUS nErrCode;
DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/*
* Storing the device extension pointer in a static variable is an
* ugly hack. Unfortunately, we need it in IntVideoPortResetDisplayParameters
* and InbvNotifyDisplayOwnershipLost doesn't allow us to pass a userdata
* parameter. On the bright side, the DISPLAY device is opened
* exclusively, so there can be only one device extension active at
* any point in time.
*
* FIXME: We should process all opened display devices in
* IntVideoPortResetDisplayParameters.
*/
ResetDisplayParametersDeviceExtension = DeviceExtension;
InbvNotifyDisplayOwnershipLost(IntVideoPortResetDisplayParameters);
nErrCode = STATUS_SUCCESS;
Irp->IoStatus.Information = piosStack->Parameters.Write.Length;
Irp->IoStatus.Status = nErrCode;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return nErrCode;
}
NTSTATUS NTAPI
IntVideoPortPnPStartDevice(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION Stack = IoGetCurrentIrpStackLocation(Irp);
PDRIVER_OBJECT DriverObject;
PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
PCM_RESOURCE_LIST AllocatedResources;
/*
* Get the initialization data we saved in VideoPortInitialize.
*/
DriverObject = DeviceObject->DriverObject;
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
/*
* Store some resources in the DeviceExtension.
*/
AllocatedResources = Stack->Parameters.StartDevice.AllocatedResources;
if (AllocatedResources != NULL)
{
CM_FULL_RESOURCE_DESCRIPTOR *FullList;
CM_PARTIAL_RESOURCE_DESCRIPTOR *Descriptor;
ULONG ResourceCount;
ULONG ResourceListSize;
/* Save the resource list */
ResourceCount = AllocatedResources->List[0].PartialResourceList.Count;
ResourceListSize =
FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.
PartialDescriptors[ResourceCount]);
DeviceExtension->AllocatedResources = ExAllocatePool(PagedPool, ResourceListSize);
if (DeviceExtension->AllocatedResources == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(DeviceExtension->AllocatedResources,
AllocatedResources,
ResourceListSize);
/* Get the interrupt level/vector - needed by HwFindAdapter sometimes */
for (FullList = AllocatedResources->List;
FullList < AllocatedResources->List + AllocatedResources->Count;
FullList++)
{
/* FIXME: Is this ASSERT ok for resources from the PNP manager? */
ASSERT(FullList->InterfaceType == PCIBus &&
FullList->BusNumber == DeviceExtension->SystemIoBusNumber &&
1 == FullList->PartialResourceList.Version &&
1 == FullList->PartialResourceList.Revision);
for (Descriptor = FullList->PartialResourceList.PartialDescriptors;
Descriptor < FullList->PartialResourceList.PartialDescriptors + FullList->PartialResourceList.Count;
Descriptor++)
{
if (Descriptor->Type == CmResourceTypeInterrupt)
{
DeviceExtension->InterruptLevel = Descriptor->u.Interrupt.Level;
DeviceExtension->InterruptVector = Descriptor->u.Interrupt.Vector;
if (Descriptor->ShareDisposition == CmResourceShareShared)
DeviceExtension->InterruptShared = TRUE;
else
DeviceExtension->InterruptShared = FALSE;
}
}
}
}
DPRINT("Interrupt level: 0x%x Interrupt Vector: 0x%x\n",
DeviceExtension->InterruptLevel,
DeviceExtension->InterruptVector);
/*
* Create adapter device object.
*/
return IntVideoPortFindAdapter(
DriverObject,
DriverExtension,
DeviceObject);
}
NTSTATUS
NTAPI
IntVideoPortForwardIrpAndWaitCompletionRoutine(
PDEVICE_OBJECT Fdo,
PIRP Irp,
PVOID Context)
{
PKEVENT Event = Context;
if (Irp->PendingReturned)
KeSetEvent(Event, IO_NO_INCREMENT, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS
NTAPI
IntVideoPortForwardIrpAndWait(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
KEVENT Event;
NTSTATUS Status;
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension =
(PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
KeInitializeEvent(&Event, NotificationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, IntVideoPortForwardIrpAndWaitCompletionRoutine,
&Event, TRUE, TRUE, TRUE);
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
if (Status == STATUS_PENDING)
{
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
Status = Irp->IoStatus.Status;
}
return Status;
}
NTSTATUS NTAPI
IntVideoPortDispatchPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
switch (IrpSp->MinorFunction)
{
case IRP_MN_START_DEVICE:
Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
Status = IntVideoPortPnPStartDevice(DeviceObject, Irp);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_REMOVE_DEVICE:
case IRP_MN_QUERY_REMOVE_DEVICE:
case IRP_MN_CANCEL_REMOVE_DEVICE:
case IRP_MN_SURPRISE_REMOVAL:
case IRP_MN_STOP_DEVICE:
Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
Status = STATUS_SUCCESS;
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_QUERY_STOP_DEVICE:
case IRP_MN_CANCEL_STOP_DEVICE:
Status = STATUS_SUCCESS;
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
default:
return STATUS_NOT_IMPLEMENTED;
break;
}
return Status;
}
NTSTATUS NTAPI
IntVideoPortDispatchCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
DeviceExtension = DeviceObject->DeviceExtension;
RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
IntVideoPortDispatchPower(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
return STATUS_NOT_IMPLEMENTED;
}
VOID NTAPI
IntVideoPortUnload(PDRIVER_OBJECT DriverObject)
{
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -