reactos/win32ss/drivers/videoprt/dispatch.c

889 lines
33 KiB
C

/*
* VideoPort driver
*
* Copyright (C) 2002, 2003, 2004 ReactOS Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "videoprt.h"
#include <ndk/inbvfuncs.h>
#include <ndk/psfuncs.h>
#define NDEBUG
#include <debug.h>
/* GLOBAL VARIABLES ***********************************************************/
PVIDEO_PORT_DEVICE_EXTENSION ResetDisplayParametersDeviceExtension = NULL;
PVIDEO_WIN32K_CALLOUT Win32kCallout;
/* PRIVATE FUNCTIONS **********************************************************/
/*
* Reset display to blue screen
*/
BOOLEAN
NTAPI
IntVideoPortResetDisplayParameters(ULONG Columns, ULONG Rows)
{
PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
if (ResetDisplayParametersDeviceExtension == NULL)
return FALSE;
DriverExtension = ResetDisplayParametersDeviceExtension->DriverExtension;
if (DriverExtension->InitializationData.HwResetHw != NULL)
{
if (DriverExtension->InitializationData.HwResetHw(
&ResetDisplayParametersDeviceExtension->MiniPortDeviceExtension,
Columns, Rows))
{
ResetDisplayParametersDeviceExtension = NULL;
return TRUE;
}
}
ResetDisplayParametersDeviceExtension = NULL;
return FALSE;
}
NTSTATUS
NTAPI
IntVideoPortAddDevice(
IN PDRIVER_OBJECT DriverObject,
IN PDEVICE_OBJECT PhysicalDeviceObject)
{
PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status;
/* Get the initialization data we saved in VideoPortInitialize. */
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
/* Create adapter device object. */
Status = IntVideoPortCreateAdapterDeviceObject(DriverObject,
DriverExtension,
PhysicalDeviceObject,
&DeviceObject);
if (NT_SUCCESS(Status))
VideoPortDeviceNumber++;
return Status;
}
/*
* IntVideoPortDispatchOpen
*
* Answer requests for Open calls.
*
* Run Level
* PASSIVE_LEVEL
*/
NTSTATUS
NTAPI
IntVideoPortDispatchOpen(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
TRACE_(VIDEOPRT, "IntVideoPortDispatchOpen\n");
if (CsrssInitialized == FALSE)
{
/*
* We know the first open call will be from the CSRSS process
* to let us know its handle.
*/
INFO_(VIDEOPRT, "Referencing CSRSS\n");
Csrss = (PKPROCESS)PsGetCurrentProcess();
INFO_(VIDEOPRT, "Csrss %p\n", Csrss);
IntInitializeVideoAddressSpace();
CsrssInitialized = TRUE;
}
DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DriverExtension = DeviceExtension->DriverExtension;
if (DriverExtension->InitializationData.HwInitialize(&DeviceExtension->MiniPortDeviceExtension))
{
Irp->IoStatus.Status = STATUS_SUCCESS;
InterlockedIncrement((PLONG)&DeviceExtension->DeviceOpened);
}
else
{
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
}
Irp->IoStatus.Information = FILE_OPENED;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
/*
* IntVideoPortDispatchClose
*
* Answer requests for Close calls.
*
* Run Level
* PASSIVE_LEVEL
*/
NTSTATUS
NTAPI
IntVideoPortDispatchClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
TRACE_(VIDEOPRT, "IntVideoPortDispatchClose\n");
DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
if ((DeviceExtension->DeviceOpened >= 1) &&
(InterlockedDecrement((PLONG)&DeviceExtension->DeviceOpened) == 0))
{
ResetDisplayParametersDeviceExtension = NULL;
InbvNotifyDisplayOwnershipLost(NULL);
ResetDisplayParametersDeviceExtension = DeviceExtension;
IntVideoPortResetDisplayParameters(80, 50);
}
Irp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
PSTR
IoctlName(ULONG Ioctl)
{
switch(Ioctl)
{
case IOCTL_VIDEO_ENABLE_VDM:
return "IOCTL_VIDEO_ENABLE_VDM"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x00, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_DISABLE_VDM:
return "IOCTL_VIDEO_DISABLE_VDM"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x01, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_REGISTER_VDM:
return "IOCTL_VIDEO_REGISTER_VDM"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x02, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_OUTPUT_DEVICE_POWER_STATE:
return "IOCTL_VIDEO_SET_OUTPUT_DEVICE_POWER_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x03, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_GET_OUTPUT_DEVICE_POWER_STATE:
return "IOCTL_VIDEO_GET_OUTPUT_DEVICE_POWER_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x04, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_MONITOR_DEVICE:
return "IOCTL_VIDEO_MONITOR_DEVICE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x05, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_ENUM_MONITOR_PDO:
return "IOCTL_VIDEO_ENUM_MONITOR_PDO"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x06, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_INIT_WIN32K_CALLBACKS:
return "IOCTL_VIDEO_INIT_WIN32K_CALLBACKS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x07, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS:
return "IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x08, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_IS_VGA_DEVICE:
return "IOCTL_VIDEO_IS_VGA_DEVICE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x09, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_USE_DEVICE_IN_SESSION:
return "IOCTL_VIDEO_USE_DEVICE_IN_SESSION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x0a, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_PREPARE_FOR_EARECOVERY:
return "IOCTL_VIDEO_PREPARE_FOR_EARECOVERY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x0b, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SAVE_HARDWARE_STATE:
return "IOCTL_VIDEO_SAVE_HARDWARE_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x80, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_RESTORE_HARDWARE_STATE:
return "IOCTL_VIDEO_RESTORE_HARDWARE_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x81, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_QUERY_AVAIL_MODES:
return "IOCTL_VIDEO_QUERY_AVAIL_MODES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x100, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES:
return "IOCTL_VIDEO_QUERY_NUM_AVAIL_MODES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x101, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_QUERY_CURRENT_MODE:
return "IOCTL_VIDEO_QUERY_CURRENT_MODE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x102, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_CURRENT_MODE:
return "IOCTL_VIDEO_SET_CURRENT_MODE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x103, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_RESET_DEVICE:
return "IOCTL_VIDEO_RESET_DEVICE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x104, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_LOAD_AND_SET_FONT:
return "IOCTL_VIDEO_LOAD_AND_SET_FONT"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x105, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_PALETTE_REGISTERS:
return "IOCTL_VIDEO_SET_PALETTE_REGISTERS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x106, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_COLOR_REGISTERS:
return "IOCTL_VIDEO_SET_COLOR_REGISTERS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x107, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_ENABLE_CURSOR:
return "IOCTL_VIDEO_ENABLE_CURSOR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x108, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_DISABLE_CURSOR:
return "IOCTL_VIDEO_DISABLE_CURSOR"; // CTL_CODE (FILE_DEVICE_VIDEO, 0x109, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_CURSOR_ATTR:
return "IOCTL_VIDEO_SET_CURSOR_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10a, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_QUERY_CURSOR_ATTR:
return "IOCTL_VIDEO_QUERY_CURSOR_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10b, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_CURSOR_POSITION:
return "IOCTL_VIDEO_SET_CURSOR_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10c, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_QUERY_CURSOR_POSITION:
return "IOCTL_VIDEO_QUERY_CURSOR_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10d, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_ENABLE_POINTER:
return "IOCTL_VIDEO_ENABLE_POINTER"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10e, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_DISABLE_POINTER:
return "IOCTL_VIDEO_DISABLE_POINTER"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x10f, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_POINTER_ATTR:
return "IOCTL_VIDEO_SET_POINTER_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x110, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_QUERY_POINTER_ATTR:
return "IOCTL_VIDEO_QUERY_POINTER_ATTR"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x111, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_POINTER_POSITION:
return "IOCTL_VIDEO_SET_POINTER_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x112, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_QUERY_POINTER_POSITION:
return "IOCTL_VIDEO_QUERY_POINTER_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x113, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES:
return "IOCTL_VIDEO_QUERY_POINTER_CAPABILITIES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x114, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_GET_BANK_SELECT_CODE:
return "IOCTL_VIDEO_GET_BANK_SELECT_CODE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x115, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_MAP_VIDEO_MEMORY:
return "IOCTL_VIDEO_MAP_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x116, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY:
return "IOCTL_VIDEO_UNMAP_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x117, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES:
return "IOCTL_VIDEO_QUERY_PUBLIC_ACCESS_RANGES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x118, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES:
return "IOCTL_VIDEO_FREE_PUBLIC_ACCESS_RANGES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x119, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES:
return "IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11a, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_POWER_MANAGEMENT:
return "IOCTL_VIDEO_SET_POWER_MANAGEMENT"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11b, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_GET_POWER_MANAGEMENT:
return "IOCTL_VIDEO_GET_POWER_MANAGEMENT"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11c, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SHARE_VIDEO_MEMORY:
return "IOCTL_VIDEO_SHARE_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11d, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY:
return "IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11e, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_COLOR_LUT_DATA:
return "IOCTL_VIDEO_SET_COLOR_LUT_DATA"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x11f, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_GET_CHILD_STATE:
return "IOCTL_VIDEO_GET_CHILD_STATE"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x120, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_VALIDATE_CHILD_STATE_CONFIGURATION:
return "IOCTL_VIDEO_VALIDATE_CHILD_STATE_CONFIGURATION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x121, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_CHILD_STATE_CONFIGURATION:
return "IOCTL_VIDEO_SET_CHILD_STATE_CONFIGURATION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x122, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SWITCH_DUALVIEW:
return "IOCTL_VIDEO_SWITCH_DUALVIEW"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x123, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_BANK_POSITION:
return "IOCTL_VIDEO_SET_BANK_POSITION"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x124, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS:
return "IOCTL_VIDEO_QUERY_SUPPORTED_BRIGHTNESS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x125, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS:
return "IOCTL_VIDEO_QUERY_DISPLAY_BRIGHTNESS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x126, METHOD_BUFFERED, FILE_ANY_ACCESS)
case IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS:
return "IOCTL_VIDEO_SET_DISPLAY_BRIGHTNESS"; // CTL_CODE(FILE_DEVICE_VIDEO, 0x127, METHOD_BUFFERED, FILE_ANY_ACCESS)
}
return "<unknown ioctl code";
}
static
NTSTATUS
VideoPortUseDeviceInSession(
_Inout_ PDEVICE_OBJECT DeviceObject,
_Inout_ PVIDEO_DEVICE_SESSION_STATUS SessionState,
_In_ ULONG BufferLength,
_Out_ PULONG_PTR Information)
{
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
/* Check buffer size */
*Information = sizeof(VIDEO_DEVICE_SESSION_STATUS);
if (BufferLength < sizeof(VIDEO_DEVICE_SESSION_STATUS))
{
ERR_(VIDEOPRT, "Buffer too small for VIDEO_DEVICE_SESSION_STATUS: %lx\n",
BufferLength);
return STATUS_BUFFER_TOO_SMALL;
}
/* Get the device extension */
DeviceExtension = DeviceObject->DeviceExtension;
/* Shall we enable the session? */
if (SessionState->bEnable)
{
/* Check if we have no session yet */
if (DeviceExtension->SessionId == -1)
{
/* Use this session and return success */
DeviceExtension->SessionId = PsGetCurrentProcessSessionId();
SessionState->bSuccess = TRUE;
}
else
{
ERR_(VIDEOPRT, "Requested to set session, but session is already set to: 0x%lx\n",
DeviceExtension->SessionId);
SessionState->bSuccess = FALSE;
}
}
else
{
/* Check if we belong to the current session */
if (DeviceExtension->SessionId == PsGetCurrentProcessSessionId())
{
/* Reset the session and return success */
DeviceExtension->SessionId = -1;
SessionState->bSuccess = TRUE;
}
else
{
ERR_(VIDEOPRT, "Requested to reset session, but session is not set\n");
SessionState->bSuccess = FALSE;
}
}
return STATUS_SUCCESS;
}
static
NTSTATUS
VideoPortInitWin32kCallbacks(
_In_ PDEVICE_OBJECT DeviceObject,
_Inout_ PVIDEO_WIN32K_CALLBACKS Win32kCallbacks,
_In_ ULONG BufferLength,
_Out_ PULONG_PTR Information)
{
*Information = sizeof(VIDEO_WIN32K_CALLBACKS);
if (BufferLength < sizeof(VIDEO_WIN32K_CALLBACKS))
{
ERR_(VIDEOPRT, "Buffer too small for VIDEO_WIN32K_CALLBACKS: %lx\n",
BufferLength);
return STATUS_BUFFER_TOO_SMALL;
}
/* Save the callout function globally */
Win32kCallout = Win32kCallbacks->Callout;
/* Return reasonable values to win32k */
Win32kCallbacks->bACPI = FALSE;
Win32kCallbacks->pPhysDeviceObject = DeviceObject;
Win32kCallbacks->DualviewFlags = 0;
return STATUS_SUCCESS;
}
static
NTSTATUS
VideoPortForwardDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IrpStack;
PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
VIDEO_REQUEST_PACKET vrp;
TRACE_(VIDEOPRT, "VideoPortForwardDeviceControl\n");
IrpStack = IoGetCurrentIrpStackLocation(Irp);
DeviceExtension = DeviceObject->DeviceExtension;
DriverExtension = DeviceExtension->DriverExtension;
/* Translate the IRP to a VRP */
vrp.StatusBlock = (PSTATUS_BLOCK)&Irp->IoStatus;
vrp.IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
INFO_(VIDEOPRT, "- IoControlCode: %x\n", vrp.IoControlCode);
/* We're assuming METHOD_BUFFERED */
vrp.InputBuffer = Irp->AssociatedIrp.SystemBuffer;
vrp.InputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
vrp.OutputBuffer = Irp->AssociatedIrp.SystemBuffer;
vrp.OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
/* Call the Miniport Driver with the VRP */
DriverExtension->InitializationData.HwStartIO(&DeviceExtension->MiniPortDeviceExtension,
&vrp);
INFO_(VIDEOPRT, "- Returned status: %x\n", Irp->IoStatus.Status);
/* Map from win32 error codes to NT status values. */
switch (Irp->IoStatus.Status)
{
case NO_ERROR:
return STATUS_SUCCESS;
case ERROR_NOT_ENOUGH_MEMORY:
return STATUS_INSUFFICIENT_RESOURCES;
case ERROR_MORE_DATA:
return STATUS_BUFFER_OVERFLOW;
case ERROR_INVALID_FUNCTION:
return STATUS_NOT_IMPLEMENTED;
case ERROR_INVALID_PARAMETER:
return STATUS_INVALID_PARAMETER;
case ERROR_INSUFFICIENT_BUFFER:
return STATUS_BUFFER_TOO_SMALL;
case ERROR_DEV_NOT_EXIST:
return STATUS_DEVICE_DOES_NOT_EXIST;
case ERROR_IO_PENDING:
return STATUS_PENDING;
default:
return STATUS_UNSUCCESSFUL;
}
}
/*
* IntVideoPortDispatchDeviceControl
*
* Answer requests for device control calls.
*
* Run Level
* PASSIVE_LEVEL
*/
NTSTATUS
NTAPI
IntVideoPortDispatchDeviceControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IrpStack;
NTSTATUS Status;
ULONG IoControlCode;
TRACE_(VIDEOPRT, "IntVideoPortDispatchDeviceControl\n");
IrpStack = IoGetCurrentIrpStackLocation(Irp);
IoControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
INFO_(VIDEOPRT, "- IoControlCode: %x: %s\n", IoControlCode, IoctlName(IoControlCode));
switch(IoControlCode)
{
case IOCTL_VIDEO_INIT_WIN32K_CALLBACKS:
INFO_(VIDEOPRT, "- IOCTL_VIDEO_INIT_WIN32K_CALLBACKS\n");
Status = VideoPortInitWin32kCallbacks(DeviceObject,
Irp->AssociatedIrp.SystemBuffer,
IrpStack->Parameters.DeviceIoControl.InputBufferLength,
&Irp->IoStatus.Information);
break;
case IOCTL_VIDEO_USE_DEVICE_IN_SESSION:
INFO_(VIDEOPRT, "- IOCTL_VIDEO_USE_DEVICE_IN_SESSION\n");
Status = VideoPortUseDeviceInSession(DeviceObject,
Irp->AssociatedIrp.SystemBuffer,
IrpStack->Parameters.DeviceIoControl.InputBufferLength,
&Irp->IoStatus.Information);
break;
default:
/* Forward to the Miniport Driver */
Status = VideoPortForwardDeviceControl(DeviceObject, Irp);
break;
}
INFO_(VIDEOPRT, "- Returned status: %x\n", Irp->IoStatus.Status);
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
/*
* 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 */
FullList = AllocatedResources->List;
ASSERT(AllocatedResources->Count == 1);
INFO_(VIDEOPRT, "InterfaceType %u BusNumber List %u Device BusNumber %u Version %u Revision %u\n",
FullList->InterfaceType, FullList->BusNumber, DeviceExtension->SystemIoBusNumber, FullList->PartialResourceList.Version, FullList->PartialResourceList.Revision);
/* FIXME: Is this ASSERT ok for resources from the PNP manager? */
ASSERT(FullList->InterfaceType == PCIBus);
ASSERT(FullList->BusNumber == DeviceExtension->SystemIoBusNumber);
ASSERT(1 == FullList->PartialResourceList.Version);
ASSERT(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;
}
}
}
INFO_(VIDEOPRT, "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
IntVideoPortQueryBusRelations(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PDEVICE_RELATIONS DeviceRelations;
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
PVIDEO_PORT_CHILD_EXTENSION ChildExtension;
ULONG i;
PLIST_ENTRY CurrentEntry;
/* Count the children */
i = 0;
CurrentEntry = DeviceExtension->ChildDeviceList.Flink;
while (CurrentEntry != &DeviceExtension->ChildDeviceList)
{
i++;
CurrentEntry = CurrentEntry->Flink;
}
if (i == 0)
return Irp->IoStatus.Status;
DeviceRelations = ExAllocatePool(PagedPool,
sizeof(DEVICE_RELATIONS) + ((i - 1) * sizeof(PVOID)));
if (!DeviceRelations) return STATUS_NO_MEMORY;
DeviceRelations->Count = i;
/* Add the children */
i = 0;
CurrentEntry = DeviceExtension->ChildDeviceList.Flink;
while (CurrentEntry != &DeviceExtension->ChildDeviceList)
{
ChildExtension = CONTAINING_RECORD(CurrentEntry, VIDEO_PORT_CHILD_EXTENSION, ListEntry);
ObReferenceObject(ChildExtension->PhysicalDeviceObject);
DeviceRelations->Objects[i] = ChildExtension->PhysicalDeviceObject;
i++;
CurrentEntry = CurrentEntry->Flink;
}
INFO_(VIDEOPRT, "Reported %d PDOs\n", i);
Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
return STATUS_SUCCESS;
}
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
IntVideoPortDispatchFdoPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status;
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
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_FILTER_RESOURCE_REQUIREMENTS:
Status = IntVideoPortForwardIrpAndWait(DeviceObject, Irp);
if (NT_SUCCESS(Status) && NT_SUCCESS(Irp->IoStatus.Status))
Status = IntVideoPortFilterResourceRequirements(DeviceObject, Irp);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
case IRP_MN_QUERY_DEVICE_RELATIONS:
if (IrpSp->Parameters.QueryDeviceRelations.Type != BusRelations)
{
IoSkipCurrentIrpStackLocation(Irp);
Status = IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
}
else
{
Status = IntVideoPortQueryBusRelations(DeviceObject, Irp);
Irp->IoStatus.Status = Status;
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:
Status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
break;
}
return Status;
}
NTSTATUS
NTAPI
IntVideoPortDispatchPnp(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PVIDEO_PORT_COMMON_EXTENSION CommonExtension = DeviceObject->DeviceExtension;
if (CommonExtension->Fdo)
return IntVideoPortDispatchFdoPnp(DeviceObject, Irp);
else
return IntVideoPortDispatchPdoPnp(DeviceObject, Irp);
}
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)
{
PIO_STACK_LOCATION IrpSp;
NTSTATUS Status = Irp->IoStatus.Status;
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
if (DeviceExtension->Common.Fdo)
{
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(DeviceExtension->NextDeviceObject, Irp);
}
else
{
switch (IrpSp->MinorFunction)
{
case IRP_MN_QUERY_POWER:
case IRP_MN_SET_POWER:
Status = STATUS_SUCCESS;
break;
}
PoStartNextPowerIrp(Irp);
Irp->IoStatus.Status = Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
}
NTSTATUS
NTAPI
IntVideoPortDispatchSystemControl(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
NTSTATUS Status;
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension = DeviceObject->DeviceExtension;
if (DeviceExtension->Common.Fdo)
{
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(DeviceExtension->NextDeviceObject, Irp);
}
else
{
Status = Irp->IoStatus.Status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return Status;
}
}
VOID
NTAPI
IntVideoPortUnload(PDRIVER_OBJECT DriverObject)
{
}