📄 videoprt.c
字号:
}
}
}
else
{
/* FIXME: Need to figure out what string to pass as param 3. */
Status = DriverExtension->InitializationData.HwFindAdapter(
&DeviceExtension->MiniPortDeviceExtension,
DriverExtension->HwContext,
NULL,
&ConfigInfo,
&Again);
}
if (Status != NO_ERROR)
{
DPRINT("HwFindAdapter call failed with error 0x%X\n", Status);
RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
IoDeleteDevice(DeviceObject);
return Status;
}
/*
* Now we know the device is present, so let's do all additional tasks
* such as creating symlinks or setting up interrupts and timer.
*/
/* Create a unicode device name. */
swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber);
RtlInitUnicodeString(&DeviceName, DeviceBuffer);
/* Create symbolic link "\??\DISPLAYx" */
swprintf(SymlinkBuffer, L"\\??\\DISPLAY%lu", DeviceNumber + 1);
RtlInitUnicodeString(&SymlinkName, SymlinkBuffer);
IoCreateSymbolicLink(&SymlinkName, &DeviceName);
/* Add entry to DEVICEMAP\VIDEO key in registry. */
swprintf(DeviceVideoBuffer, L"\\Device\\Video%d", DeviceNumber);
RtlWriteRegistryValue(
RTL_REGISTRY_DEVICEMAP,
L"VIDEO",
DeviceVideoBuffer,
REG_SZ,
DeviceExtension->RegistryPath.Buffer,
DeviceExtension->RegistryPath.MaximumLength);
/* FIXME: Allocate hardware resources for device. */
/*
* Allocate interrupt for device.
*/
if (!IntVideoPortSetupInterrupt(DeviceObject, DriverExtension, &ConfigInfo))
{
RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
IoDeleteDevice(DeviceObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
/*
* Allocate timer for device.
*/
if (!IntVideoPortSetupTimer(DeviceObject, DriverExtension))
{
if (DeviceExtension->InterruptObject != NULL)
IoDisconnectInterrupt(DeviceExtension->InterruptObject);
RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
IoDeleteDevice(DeviceObject);
DPRINT("STATUS_INSUFFICIENT_RESOURCES\n");
return STATUS_INSUFFICIENT_RESOURCES;
}
/*
* Query children of the device.
*/
VideoPortEnumerateChildren(&DeviceExtension->MiniPortDeviceExtension, NULL);
DPRINT("STATUS_SUCCESS\n");
return STATUS_SUCCESS;
}
VOID FASTCALL
IntAttachToCSRSS(PKPROCESS *CallingProcess, PKAPC_STATE ApcState)
{
*CallingProcess = (PKPROCESS)PsGetCurrentProcess();
if (*CallingProcess != Csrss)
{
KeStackAttachProcess(Csrss, ApcState);
}
}
VOID FASTCALL
IntDetachFromCSRSS(PKPROCESS *CallingProcess, PKAPC_STATE ApcState)
{
if (*CallingProcess != Csrss)
{
KeUnstackDetachProcess(ApcState);
}
}
/* PUBLIC FUNCTIONS ***********************************************************/
/*
* @implemented
*/
ULONG NTAPI
VideoPortInitialize(
IN PVOID Context1,
IN PVOID Context2,
IN PVIDEO_HW_INITIALIZATION_DATA HwInitializationData,
IN PVOID HwContext)
{
PDRIVER_OBJECT DriverObject = Context1;
PUNICODE_STRING RegistryPath = Context2;
NTSTATUS Status;
PVIDEO_PORT_DRIVER_EXTENSION DriverExtension;
BOOL LegacyDetection = FALSE;
DPRINT("VideoPortInitialize\n");
/*
* As a first thing do parameter checks.
*/
if (HwInitializationData->HwInitDataSize > sizeof(VIDEO_HW_INITIALIZATION_DATA))
{
return STATUS_REVISION_MISMATCH;
}
if (HwInitializationData->HwFindAdapter == NULL ||
HwInitializationData->HwInitialize == NULL ||
HwInitializationData->HwStartIO == NULL)
{
return STATUS_INVALID_PARAMETER;
}
/*
* NOTE:
* The driver extension can be already allocated in case that we were
* called by legacy driver and failed detecting device. Some miniport
* drivers in that case adjust parameters and call VideoPortInitialize
* again.
*/
DriverExtension = IoGetDriverObjectExtension(DriverObject, DriverObject);
if (DriverExtension == NULL)
{
Status = IoAllocateDriverObjectExtension(
DriverObject,
DriverObject,
sizeof(VIDEO_PORT_DRIVER_EXTENSION),
(PVOID *)&DriverExtension);
if (!NT_SUCCESS(Status))
{
return Status;
}
/*
* Save the registry path. This should be done only once even if
* VideoPortInitialize is called multiple times.
*/
if (RegistryPath->Length != 0)
{
DriverExtension->RegistryPath.Length = 0;
DriverExtension->RegistryPath.MaximumLength =
RegistryPath->Length + sizeof(UNICODE_NULL);
DriverExtension->RegistryPath.Buffer =
ExAllocatePoolWithTag(
PagedPool,
DriverExtension->RegistryPath.MaximumLength,
TAG('U', 'S', 'T', 'R'));
if (DriverExtension->RegistryPath.Buffer == NULL)
{
RtlInitUnicodeString(&DriverExtension->RegistryPath, NULL);
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyUnicodeString(&DriverExtension->RegistryPath, RegistryPath);
DPRINT("RegistryPath: %wZ\n", &DriverExtension->RegistryPath);
}
else
{
RtlInitUnicodeString(&DriverExtension->RegistryPath, NULL);
}
}
/*
* Copy the correct miniport initialization data to the device extension.
*/
RtlCopyMemory(
&DriverExtension->InitializationData,
HwInitializationData,
HwInitializationData->HwInitDataSize);
if (HwInitializationData->HwInitDataSize <
sizeof(VIDEO_HW_INITIALIZATION_DATA))
{
RtlZeroMemory((PVOID)((ULONG_PTR)&DriverExtension->InitializationData +
HwInitializationData->HwInitDataSize),
sizeof(VIDEO_HW_INITIALIZATION_DATA) -
HwInitializationData->HwInitDataSize);
}
DriverExtension->HwContext = HwContext;
switch (HwInitializationData->HwInitDataSize)
{
/*
* NT4 drivers are special case, because we must use legacy method
* of detection instead of the Plug & Play one.
*/
case SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA:
DPRINT("We were loaded by a Windows NT miniport driver.\n");
LegacyDetection = TRUE;
break;
case SIZE_OF_W2K_VIDEO_HW_INITIALIZATION_DATA:
DPRINT("We were loaded by a Windows 2000 miniport driver.\n");
break;
case sizeof(VIDEO_HW_INITIALIZATION_DATA):
DPRINT("We were loaded by a Windows XP or later miniport driver.\n");
break;
default:
DPRINT("Invalid HwInitializationData size.\n");
return STATUS_UNSUCCESSFUL;
}
/* add no PNP bus here, add more bus type if it needed */
if ( (HwInitializationData->AdapterInterfaceType == InterfaceTypeUndefined) ||
(HwInitializationData->AdapterInterfaceType == Internal) )
{
DPRINT1("No PNP Videocard .\n");
LegacyDetection = TRUE;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = IntVideoPortDispatchOpen;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = IntVideoPortDispatchClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IntVideoPortDispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_WRITE] = IntVideoPortDispatchWrite;
DriverObject->DriverUnload = IntVideoPortUnload;
/*
* Plug & Play drivers registers the device in AddDevice routine. For
* legacy drivers we must do it now.
*/
if (LegacyDetection)
{
PDEVICE_OBJECT DeviceObject;
if (HwInitializationData->HwInitDataSize != SIZE_OF_NT4_VIDEO_HW_INITIALIZATION_DATA)
{
/* power management */
DriverObject->MajorFunction[IRP_MJ_POWER] = IntVideoPortDispatchPower;
}
Status = IntVideoPortCreateAdapterDeviceObject(DriverObject, DriverExtension,
NULL, &DeviceObject);
DPRINT("IntVideoPortCreateAdapterDeviceObject returned 0x%x\n", Status);
if (!NT_SUCCESS(Status))
return Status;
Status = IntVideoPortFindAdapter(DriverObject, DriverExtension, DeviceObject);
DPRINT("IntVideoPortFindAdapter returned 0x%x\n", Status);
return Status;
}
else
{
DriverObject->DriverExtension->AddDevice = IntVideoPortAddDevice;
DriverObject->MajorFunction[IRP_MJ_PNP] = IntVideoPortDispatchPnp;
DriverObject->MajorFunction[IRP_MJ_POWER] = IntVideoPortDispatchPower;
return STATUS_SUCCESS;
}
}
/*
* @implemented
*/
VOID
VideoPortDebugPrint(
IN VIDEO_DEBUG_LEVEL DebugPrintLevel,
IN PCHAR DebugMessage, ...)
{
char Buffer[256];
va_list ap;
va_start(ap, DebugMessage);
vsprintf(Buffer, DebugMessage, ap);
va_end(ap);
DbgPrintEx(DPFLTR_IHVVIDEO_ID, DebugPrintLevel, Buffer);
}
/*
* @unimplemented
*/
VOID NTAPI
VideoPortLogError(
IN PVOID HwDeviceExtension,
IN PVIDEO_REQUEST_PACKET Vrp OPTIONAL,
IN VP_STATUS ErrorCode,
IN ULONG UniqueId)
{
DPRINT1("VideoPortLogError ErrorCode %d (0x%x) UniqueId %lu (0x%lx)\n",
ErrorCode, ErrorCode, UniqueId, UniqueId);
if (NULL != Vrp)
{
DPRINT1("Vrp->IoControlCode %lu (0x%lx)\n", Vrp->IoControlCode, Vrp->IoControlCode);
}
}
/*
* @implemented
*/
UCHAR NTAPI
VideoPortGetCurrentIrql(VOID)
{
return KeGetCurrentIrql();
}
typedef struct QueryRegistryCallbackContext
{
PVOID HwDeviceExtension;
PVOID HwContext;
PMINIPORT_GET_REGISTRY_ROUTINE HwGetRegistryRoutine;
} QUERY_REGISTRY_CALLBACK_CONTEXT, *PQUERY_REGISTRY_CALLBACK_CONTEXT;
static NTSTATUS NTAPI
QueryRegistryCallback(
IN PWSTR ValueName,
IN ULONG ValueType,
IN PVOID ValueData,
IN ULONG ValueLength,
IN PVOID Context,
IN PVOID EntryContext)
{
PQUERY_REGISTRY_CALLBACK_CONTEXT CallbackContext = (PQUERY_REGISTRY_CALLBACK_CONTEXT) Context;
DPRINT("Found registry value for name %S: type %d, length %d\n",
ValueName, ValueType, ValueLength);
return (*(CallbackContext->HwGetRegistryRoutine))(
CallbackContext->HwDeviceExtension,
CallbackContext->HwContext,
ValueName,
ValueData,
ValueLength);
}
/*
* @unimplemented
*/
VP_STATUS NTAPI
VideoPortGetRegistryParameters(
IN PVOID HwDeviceExtension,
IN PWSTR ParameterName,
IN UCHAR IsParameterFileName,
IN PMINIPORT_GET_REGISTRY_ROUTINE GetRegistryRoutine,
IN PVOID HwContext)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[2] = {{0}};
QUERY_REGISTRY_CALLBACK_CONTEXT Context;
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
DPRINT("VideoPortGetRegistryParameters ParameterName %S\n", ParameterName);
DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
Context.HwDeviceExtension = HwDeviceExtension;
Context.HwContext = HwContext;
Context.HwGetRegistryRoutine = GetRegistryRoutine;
QueryTable[0].QueryRoutine = QueryRegistryCallback;
QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
QueryTable[0].Name = ParameterName;
if (!NT_SUCCESS(RtlQueryRegistryValues(
RTL_REGISTRY_ABSOLUTE,
DeviceExtension->RegistryPath.Buffer,
QueryTable,
&Context,
NULL)))
{
DPRINT("VideoPortGetRegistryParameters could not find the "
"requested parameter\n");
return ERROR_INVALID_PARAMETER;
}
if (IsParameterFileName)
{
/* FIXME: need to read the contents of the file */
UNIMPLEMENTED;
}
return ERROR_SUCCESS;
}
/*
* @implemented
*/
VP_STATUS NTAPI
VideoPortSetRegistryParameters(
IN PVOID HwDeviceExtension,
IN PWSTR ValueName,
IN PVOID ValueData,
IN ULONG ValueLength)
{
VP_STATUS Status;
DPRINT("VideoPortSetRegistryParameters ParameterName %S\n", ValueName);
ASSERT_IRQL(PASSIVE_LEVEL);
Status = RtlWriteRegistryValue(
RTL_REGISTRY_ABSOLUTE,
VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension)->RegistryPath.Buffer,
ValueName,
REG_BINARY,
ValueData,
ValueLength);
if (Status != ERROR_SUCCESS)
DPRINT("VideoPortSetRegistryParameters error 0x%x\n", Status);
return Status;
}
/*
* @implemented
*/
VP_STATUS NTAPI
VideoPortGetVgaStatus(
IN PVOID HwDeviceExtension,
OUT PULONG VgaStatus)
{
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
DPRINT("VideoPortGetVgaStatus\n");
DeviceExtension = VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension);
if (KeGetCurrentIrql() == PASSIVE_LEVEL)
{
if (DeviceExtension->AdapterInterfaceType == PCIBus)
{
/* VgaStatus: 0 == VGA not enabled, 1 == VGA enabled. */
/* Assumed for now */
*VgaStatus = 1;
return NO_ERROR;
}
}
return ERROR_INVALID_FUNCTION;
}
/*
* @implemented
*/
PVOID NTAPI
VideoPortGetRomImage(
IN PVOID HwDeviceExtension,
IN PVOID Unused1,
IN ULONG Unused2,
IN ULONG Length)
{
static PVOID RomImageBuffer = NULL;
PKPROCESS CallingProcess;
KAPC_STATE ApcState;
DPRINT("VideoPortGetRomImage(HwDeviceExtension 0x%X Length 0x%X)\n",
HwDeviceExtension, Length);
/* If the length is zero then free the existing buffer. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -