1547 lines
44 KiB
C
1547 lines
44 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1992 Microsoft Corporation
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
fsvga.c
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This is the console fullscreen driver for the VGA card.
|
||
|
|
||
|
Environment:
|
||
|
|
||
|
kernel mode only
|
||
|
|
||
|
Notes:
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "fsvga.h"
|
||
|
|
||
|
//
|
||
|
// Use the alloc_text pragma to specify the driver initialization routines
|
||
|
// (they can be paged out).
|
||
|
//
|
||
|
|
||
|
#if defined(ALLOC_PRAGMA)
|
||
|
#pragma alloc_text(INIT,DriverEntry)
|
||
|
#pragma alloc_text(INIT,FsVgaQueryDevice)
|
||
|
#pragma alloc_text(INIT,FsVgaPeripheralCallout)
|
||
|
#pragma alloc_text(INIT,FsVgaServiceParameters)
|
||
|
#endif
|
||
|
|
||
|
|
||
|
GLOBALS Globals;
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
DriverEntry(
|
||
|
IN PDRIVER_OBJECT DriverObject,
|
||
|
IN PUNICODE_STRING RegistryPath
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Installable driver initialization entry point.
|
||
|
This entry point is called directly by the I/O system.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DriverObject - Pointer to driver object created by system.
|
||
|
|
||
|
RegistryPath - Pointer to the Unicode name of the registry path
|
||
|
for this driver.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
The function value is the final status from the initialization operation.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
NTSTATUS status = STATUS_SUCCESS;
|
||
|
ULONG uniqueErrorValue;
|
||
|
NTSTATUS errorCode = STATUS_SUCCESS;
|
||
|
ULONG dumpCount = 0;
|
||
|
ULONG dumpData[DUMP_COUNT];
|
||
|
|
||
|
FsVgaPrint((1,
|
||
|
"\n\nFSVGA-FSVGAInitialize: enter\n"));
|
||
|
|
||
|
//
|
||
|
// Zero-initialize various structures.
|
||
|
//
|
||
|
RtlZeroMemory(&Globals, sizeof(GLOBALS));
|
||
|
|
||
|
Globals.FsVgaDebug = DEFAULT_DEBUG_LEVEL;
|
||
|
|
||
|
//
|
||
|
// Query the device resource information for this driver.
|
||
|
//
|
||
|
FsVgaQueryDevice(&Globals.Resource);
|
||
|
|
||
|
if (!(Globals.Resource.HardwarePresent & FSVGA_HARDWARE_PRESENT)) {
|
||
|
//
|
||
|
// There is neither a Full Screen Video attached. Free
|
||
|
// resources and return with unsuccessful status.
|
||
|
//
|
||
|
|
||
|
FsVgaPrint((1,
|
||
|
"FSVGA-FsVgaInitialize: No Full Screen Video attached.\n"));
|
||
|
status = STATUS_NO_SUCH_DEVICE;
|
||
|
errorCode = FSVGA_NO_SUCH_DEVICE;
|
||
|
uniqueErrorValue = FSVGA_ERROR_VALUE_BASE + 4;
|
||
|
goto FsVgaInitializeExit;
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//
|
||
|
// Need to ensure that the registry path is null-terminated.
|
||
|
// Allocate pool to hold a null-terminated copy of the path.
|
||
|
//
|
||
|
|
||
|
Globals.RegistryPath.Length = RegistryPath->Length;
|
||
|
Globals.RegistryPath.MaximumLength = RegistryPath->Length
|
||
|
+ sizeof (UNICODE_NULL);
|
||
|
|
||
|
Globals.RegistryPath.Buffer = ExAllocatePool(
|
||
|
NonPagedPool,
|
||
|
Globals.RegistryPath.MaximumLength);
|
||
|
|
||
|
if (!Globals.RegistryPath.Buffer) {
|
||
|
FsVgaPrint((
|
||
|
1,
|
||
|
"FSVGA-FsVgaInitialize: Couldn't allocate pool for registry path\n"
|
||
|
));
|
||
|
|
||
|
status = STATUS_UNSUCCESSFUL;
|
||
|
errorCode = FSVGA_INSUFFICIENT_RESOURCES;
|
||
|
uniqueErrorValue = FSVGA_ERROR_VALUE_BASE + 2;
|
||
|
dumpData[0] = 0;
|
||
|
dumpCount = 1;
|
||
|
goto FsVgaInitializeExit;
|
||
|
|
||
|
}
|
||
|
|
||
|
RtlMoveMemory(Globals.RegistryPath.Buffer,
|
||
|
RegistryPath->Buffer,
|
||
|
RegistryPath->Length);
|
||
|
Globals.RegistryPath.Buffer [RegistryPath->Length / sizeof (WCHAR)] = L'\0';
|
||
|
|
||
|
//
|
||
|
// Get the service parameters (e.g., user-configurable number
|
||
|
// of resends, polling iterations, etc.).
|
||
|
//
|
||
|
|
||
|
FsVgaServiceParameters(&Globals.Configuration,
|
||
|
&Globals.RegistryPath);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Once initialization is finished, load the device map information
|
||
|
// into the registry so that setup can determine which full screen
|
||
|
// port are active.
|
||
|
//
|
||
|
|
||
|
if (Globals.Resource.HardwarePresent & FSVGA_HARDWARE_PRESENT) {
|
||
|
|
||
|
status = RtlWriteRegistryValue(RTL_REGISTRY_DEVICEMAP,
|
||
|
L"FullScreenVideo",
|
||
|
DD_FULLSCREEN_VIDEO_DEVICE_NAME,
|
||
|
REG_SZ,
|
||
|
Globals.RegistryPath.Buffer,
|
||
|
Globals.RegistryPath.Length);
|
||
|
|
||
|
if (!NT_SUCCESS(status))
|
||
|
{
|
||
|
FsVgaPrint((1,
|
||
|
"FSVGA-FSVGAInitialize: Could not store keyboard name in DeviceMap\n"));
|
||
|
errorCode = FSVGA_NO_DEVICEMAP_CREATED;
|
||
|
uniqueErrorValue = FSVGA_ERROR_VALUE_BASE + 90;
|
||
|
dumpCount = 0;
|
||
|
goto FsVgaInitializeExit;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FsVgaPrint((1,
|
||
|
"FSVGA-FSVGAInitialize: Stored pointer name in DeviceMap\n"));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
ASSERT(status == STATUS_SUCCESS);
|
||
|
|
||
|
//
|
||
|
// Set up the device driver entry points.
|
||
|
//
|
||
|
DriverObject->MajorFunction[IRP_MJ_CREATE] = FsVgaOpenCloseDispatch;
|
||
|
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FsVgaOpenCloseDispatch;
|
||
|
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = FsVgaDeviceControl;
|
||
|
|
||
|
DriverObject->DriverUnload = FsVgaDriverUnload;
|
||
|
DriverObject->DriverExtension->AddDevice = FsVgaAddDevice;
|
||
|
DriverObject->MajorFunction[IRP_MJ_PNP] = FsVgaDevicePnp;
|
||
|
DriverObject->MajorFunction[IRP_MJ_POWER] = FsVgaDevicePower;
|
||
|
|
||
|
FsVgaInitializeExit:
|
||
|
|
||
|
if (errorCode != STATUS_SUCCESS)
|
||
|
{
|
||
|
//
|
||
|
// Log an error/warning message.
|
||
|
//
|
||
|
FsVgaLogError(DriverObject,
|
||
|
errorCode,
|
||
|
uniqueErrorValue,
|
||
|
status,
|
||
|
dumpData,
|
||
|
dumpCount
|
||
|
);
|
||
|
}
|
||
|
|
||
|
FsVgaPrint((1,
|
||
|
"FSVGA-FsVgaInitialize: exit\n"));
|
||
|
|
||
|
return(status);
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
FsVgaQueryDevice(
|
||
|
IN PFSVGA_RESOURCE_INFORMATION Resource
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine retrieves the resource information for the video.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Resource - Pointer to the resource information.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
INTERFACE_TYPE interfaceType;
|
||
|
ULONG i;
|
||
|
|
||
|
for (i = 0; i < MaximumInterfaceType; i++)
|
||
|
{
|
||
|
|
||
|
//
|
||
|
// Get the registry information for this device.
|
||
|
//
|
||
|
|
||
|
interfaceType = i;
|
||
|
IoQueryDeviceDescription(&interfaceType, // Bus type
|
||
|
NULL, // Bus number
|
||
|
NULL, // Controller type
|
||
|
NULL, // Controller number
|
||
|
NULL, // Peripheral type
|
||
|
NULL, // Peripheral number
|
||
|
FsVgaPeripheralCallout,
|
||
|
(PVOID) Resource);
|
||
|
|
||
|
if (Resource->HardwarePresent & FSVGA_HARDWARE_PRESENT)
|
||
|
{
|
||
|
break;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
FsVgaPrint((1,
|
||
|
"FSVGA-FsVgaConfiguration: IoQueryDeviceDescription for bus type %d failed\n",
|
||
|
interfaceType));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
FsVgaPeripheralCallout(
|
||
|
IN PVOID Context,
|
||
|
IN PUNICODE_STRING PathName,
|
||
|
IN INTERFACE_TYPE BusType,
|
||
|
IN ULONG BusNumber,
|
||
|
IN PKEY_VALUE_FULL_INFORMATION *BusInformation,
|
||
|
IN CONFIGURATION_TYPE ControllerType,
|
||
|
IN ULONG ControllerNumber,
|
||
|
IN PKEY_VALUE_FULL_INFORMATION *ControllerInformation,
|
||
|
IN CONFIGURATION_TYPE PeripheralType,
|
||
|
IN ULONG PeripheralNumber,
|
||
|
IN PKEY_VALUE_FULL_INFORMATION *PeripheralInformation
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the callout routine sent as a parameter to
|
||
|
IoQueryDeviceDescription. It grabs the Display controller
|
||
|
configuration information.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Context - Context parameter that was passed in by the routine
|
||
|
that called IoQueryDeviceDescription.
|
||
|
|
||
|
PathName - The full pathname for the registry key.
|
||
|
|
||
|
BusType - Bus interface type (Isa, Eisa, Mca, etc.).
|
||
|
|
||
|
BusNumber - The bus sub-key (0, 1, etc.).
|
||
|
|
||
|
BusInformation - Pointer to the array of pointers to the full value
|
||
|
information for the bus.
|
||
|
|
||
|
ControllerType - The controller type (should be DisplayController).
|
||
|
|
||
|
ControllerNumber - The controller sub-key (0, 1, etc.).
|
||
|
|
||
|
ControllerInformation - Pointer to the array of pointers to the full
|
||
|
value information for the controller key.
|
||
|
|
||
|
PeripheralType - The peripheral type (should be MonitorPeripheral).
|
||
|
|
||
|
PeripheralNumber - The peripheral sub-key.
|
||
|
|
||
|
PeripheralInformation - Pointer to the array of pointers to the full
|
||
|
value information for the peripheral key.
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None. If successful, will have the following side-effects:
|
||
|
|
||
|
- Sets DeviceObject->DeviceExtension->HardwarePresent.
|
||
|
- Sets configuration fields in
|
||
|
DeviceObject->DeviceExtension->Configuration.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PFSVGA_RESOURCE_INFORMATION resource;
|
||
|
NTSTATUS status = STATUS_SUCCESS;
|
||
|
|
||
|
FsVgaPrint((1,
|
||
|
"FSVGA-FsVgaPeripheralCallout: Path @ 0x%x, Bus Type 0x%x, Bus Number 0x%x\n",
|
||
|
PathName, BusType, BusNumber));
|
||
|
FsVgaPrint((1,
|
||
|
" Controller Type 0x%x, Controller Number 0x%x, Controller info @ 0x%x\n",
|
||
|
ControllerType, ControllerNumber, ControllerInformation));
|
||
|
FsVgaPrint((1,
|
||
|
" Peripheral Type 0x%x, Peripheral Number 0x%x, Peripheral info @ 0x%x\n",
|
||
|
PeripheralType, PeripheralNumber, PeripheralInformation));
|
||
|
|
||
|
//
|
||
|
// If we already have the configuration information for the
|
||
|
// keyboard peripheral, or if the peripheral identifier is missing,
|
||
|
// just return.
|
||
|
//
|
||
|
|
||
|
resource = (PFSVGA_RESOURCE_INFORMATION) Context;
|
||
|
if (resource->HardwarePresent & FSVGA_HARDWARE_PRESENT)
|
||
|
{
|
||
|
return (status);
|
||
|
}
|
||
|
|
||
|
|
||
|
resource->HardwarePresent |= FSVGA_HARDWARE_PRESENT;
|
||
|
|
||
|
#ifdef RESOURCE_REQUIREMENTS
|
||
|
//
|
||
|
// Get the bus information.
|
||
|
//
|
||
|
|
||
|
resource->InterfaceType = BusType;
|
||
|
resource->BusNumber = BusNumber;
|
||
|
#endif
|
||
|
|
||
|
return(status);
|
||
|
}
|
||
|
|
||
|
#ifdef RESOURCE_REQUIREMENTS
|
||
|
NTSTATUS
|
||
|
FsVgaQueryAperture(
|
||
|
OUT PIO_RESOURCE_LIST *pApertureRequirements
|
||
|
// OUT PFSVGA_RESOURCE_INFORMATION Resource
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Queries the possible FsVga settings.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ApertureRequirements - returns the possible FsVga settings
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NTSTATUS
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PIO_RESOURCE_LIST Requirements;
|
||
|
ULONG PortLength;
|
||
|
ULONG RangeStart;
|
||
|
ULONG i;
|
||
|
|
||
|
Requirements = ExAllocatePool(PagedPool,
|
||
|
sizeof(IO_RESOURCE_LIST) + (MaximumPortCount-1) * sizeof(IO_RESOURCE_DESCRIPTOR));
|
||
|
if (Requirements == NULL) {
|
||
|
FsVgaPrint((1,
|
||
|
"FSVGA-FsVgaQueryAperture: Could not allocate resource list\n"));
|
||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
|
||
|
Requirements->Version =
|
||
|
Requirements->Revision = 1;
|
||
|
Requirements->Count = MaximumPortCount;
|
||
|
for (i = 0; i < MaximumPortCount; i++) {
|
||
|
Requirements->Descriptors[i].Option = IO_RESOURCE_PREFERRED;
|
||
|
Requirements->Descriptors[i].Type = CmResourceTypePort;
|
||
|
Requirements->Descriptors[i].ShareDisposition = CmResourceShareShared;
|
||
|
Requirements->Descriptors[i].Flags = CM_RESOURCE_PORT_IO;
|
||
|
switch (i) {
|
||
|
case CRTCAddressPortColor:
|
||
|
PortLength = 1;
|
||
|
RangeStart = VGA_BASE_IO_PORT + CRTC_ADDRESS_PORT_COLOR;
|
||
|
break;
|
||
|
case CRTCDataPortColor:
|
||
|
PortLength = 1;
|
||
|
RangeStart = VGA_BASE_IO_PORT + CRTC_DATA_PORT_COLOR;
|
||
|
break;
|
||
|
case GRAPHAddressPort:
|
||
|
PortLength = 2;
|
||
|
RangeStart = VGA_BASE_IO_PORT + GRAPH_ADDRESS_PORT;
|
||
|
break;
|
||
|
case SEQAddressPort:
|
||
|
PortLength = 2;
|
||
|
RangeStart = VGA_BASE_IO_PORT + SEQ_ADDRESS_PORT;
|
||
|
break;
|
||
|
}
|
||
|
Requirements->Descriptors[i].u.Port.MinimumAddress.QuadPart = RangeStart;
|
||
|
Requirements->Descriptors[i].u.Port.MaximumAddress.QuadPart = RangeStart +
|
||
|
(PortLength - 1);
|
||
|
Requirements->Descriptors[i].u.Port.Alignment = 1;
|
||
|
Requirements->Descriptors[i].u.Port.Length = PortLength;
|
||
|
|
||
|
}
|
||
|
|
||
|
*pApertureRequirements = Requirements;
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
NTSTATUS
|
||
|
FsVgaCreateResource(
|
||
|
IN PFSVGA_CONFIGURATION_INFORMATION configuration,
|
||
|
OUT PCM_PARTIAL_RESOURCE_LIST *pResourceList
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Create the possible FsVga resousrce settings.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
ResourceList - returns the possible FsVga settings
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
NTSTATUS
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PCM_PARTIAL_RESOURCE_LIST Requirements;
|
||
|
ULONG PortLength;
|
||
|
ULONG RangeStart;
|
||
|
ULONG i;
|
||
|
USHORT IOPort = configuration->IOPort;
|
||
|
|
||
|
Requirements = ExAllocatePool(PagedPool,
|
||
|
sizeof(CM_PARTIAL_RESOURCE_LIST) + (MaximumPortCount-1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
|
||
|
if (Requirements == NULL) {
|
||
|
FsVgaPrint((1,
|
||
|
"FSVGA-FsVgaCreateResoursce: Could not allocate resource list\n"));
|
||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||
|
}
|
||
|
|
||
|
Requirements->Version =
|
||
|
Requirements->Revision = 1;
|
||
|
Requirements->Count = MaximumPortCount;
|
||
|
for (i = 0; i < MaximumPortCount; i++) {
|
||
|
Requirements->PartialDescriptors[i].Type = CmResourceTypePort;
|
||
|
Requirements->PartialDescriptors[i].ShareDisposition = CmResourceShareShared;
|
||
|
Requirements->PartialDescriptors[i].Flags = CM_RESOURCE_PORT_IO;
|
||
|
switch (i) {
|
||
|
case CRTCAddressPortColor:
|
||
|
PortLength = 1;
|
||
|
RangeStart = IOPort + CRTC_ADDRESS_PORT_COLOR;
|
||
|
break;
|
||
|
case CRTCDataPortColor:
|
||
|
PortLength = 1;
|
||
|
RangeStart = IOPort + CRTC_DATA_PORT_COLOR;
|
||
|
break;
|
||
|
case GRAPHAddressPort:
|
||
|
PortLength = 2;
|
||
|
RangeStart = IOPort + GRAPH_ADDRESS_PORT;
|
||
|
break;
|
||
|
case SEQAddressPort:
|
||
|
PortLength = 2;
|
||
|
RangeStart = IOPort + SEQ_ADDRESS_PORT;
|
||
|
break;
|
||
|
}
|
||
|
Requirements->PartialDescriptors[i].u.Port.Start.QuadPart = RangeStart;
|
||
|
Requirements->PartialDescriptors[i].u.Port.Length = PortLength;
|
||
|
|
||
|
}
|
||
|
|
||
|
*pResourceList = Requirements;
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
FsVgaServiceParameters(
|
||
|
IN PFSVGA_CONFIGURATION_INFORMATION configuration,
|
||
|
IN PUNICODE_STRING RegistryPath
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine retrieves this driver's service parameters information
|
||
|
from the registry.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
configuration - Pointer to the configuration information.
|
||
|
|
||
|
RegistryPath - Pointer to the null-terminated Unicode name of the
|
||
|
registry path for this driver.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
UNICODE_STRING parametersPath;
|
||
|
PWSTR path;
|
||
|
PRTL_QUERY_REGISTRY_TABLE parameters = NULL;
|
||
|
USHORT queriesPlusOne = 5;
|
||
|
NTSTATUS status = STATUS_SUCCESS;
|
||
|
#define PARAMETER_MAX 256
|
||
|
ULONG EmulationMode;
|
||
|
ULONG HardwareCursor;
|
||
|
ULONG HardwareScroll;
|
||
|
ULONG IOPort;
|
||
|
USHORT defaultEmulationMode = 0;
|
||
|
USHORT defaultHardwareCursor = NO_HARDWARE_CURSOR;
|
||
|
USHORT defaultHardwareScroll = NO_HARDWARE_SCROLL;
|
||
|
USHORT defaultIOPort = VGA_BASE_IO_PORT;
|
||
|
|
||
|
parametersPath.Buffer = NULL;
|
||
|
|
||
|
//
|
||
|
// Registry path is already null-terminated, so just use it.
|
||
|
//
|
||
|
|
||
|
path = RegistryPath->Buffer;
|
||
|
|
||
|
//
|
||
|
// Allocate the Rtl query table.
|
||
|
//
|
||
|
|
||
|
parameters = ExAllocatePool(PagedPool,
|
||
|
sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne);
|
||
|
if (!parameters)
|
||
|
{
|
||
|
FsVgaPrint((1,
|
||
|
"FSVGA-FsVgaServiceParameters: Couldn't allocate table for Rtl query to parameters for %ws\n",
|
||
|
path));
|
||
|
status = STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
RtlZeroMemory(parameters,
|
||
|
sizeof(RTL_QUERY_REGISTRY_TABLE) * queriesPlusOne);
|
||
|
|
||
|
//
|
||
|
// Form a path to this driver's Parameters subkey.
|
||
|
//
|
||
|
|
||
|
RtlInitUnicodeString(¶metersPath,
|
||
|
NULL);
|
||
|
|
||
|
parametersPath.MaximumLength = RegistryPath->Length +
|
||
|
sizeof(L"\\Parameters");
|
||
|
parametersPath.Buffer = ExAllocatePool(PagedPool,
|
||
|
parametersPath.MaximumLength);
|
||
|
if (!parametersPath.Buffer)
|
||
|
{
|
||
|
FsVgaPrint((1,
|
||
|
"FSVGA-FsVgaServiceParameters: Couldn't allocate string for path to parameters for %ws\n",
|
||
|
path));
|
||
|
status = STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (NT_SUCCESS(status))
|
||
|
{
|
||
|
//
|
||
|
// Form the parameters path.
|
||
|
//
|
||
|
RtlZeroMemory(parametersPath.Buffer,
|
||
|
parametersPath.MaximumLength);
|
||
|
RtlAppendUnicodeToString(¶metersPath,
|
||
|
path);
|
||
|
RtlAppendUnicodeToString(¶metersPath,
|
||
|
L"\\Parameters");
|
||
|
|
||
|
FsVgaPrint((1,
|
||
|
"FsVga-FsVgaServiceParameters: parameters path is %ws\n",
|
||
|
parametersPath.Buffer));
|
||
|
|
||
|
//
|
||
|
// Gather all of the "user specified" information from
|
||
|
// the registry.
|
||
|
//
|
||
|
parameters[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||
|
parameters[0].Name = L"ConsoleFullScreen.EmulationMode";
|
||
|
parameters[0].EntryContext = &EmulationMode;
|
||
|
parameters[0].DefaultType = REG_DWORD;
|
||
|
parameters[0].DefaultData = &defaultEmulationMode;
|
||
|
parameters[0].DefaultLength = sizeof(USHORT);
|
||
|
|
||
|
parameters[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||
|
parameters[1].Name = L"ConsoleFullScreen.HardwareCursor";
|
||
|
parameters[1].EntryContext = &HardwareCursor;
|
||
|
parameters[1].DefaultType = REG_DWORD;
|
||
|
parameters[1].DefaultData = &defaultHardwareCursor;
|
||
|
parameters[1].DefaultLength = sizeof(USHORT);
|
||
|
|
||
|
parameters[2].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||
|
parameters[2].Name = L"ConsoleFullScreen.HardwareScroll";
|
||
|
parameters[2].EntryContext = &HardwareScroll;
|
||
|
parameters[2].DefaultType = REG_DWORD;
|
||
|
parameters[2].DefaultData = &defaultHardwareScroll;
|
||
|
parameters[2].DefaultLength = sizeof(USHORT);
|
||
|
|
||
|
parameters[3].Flags = RTL_QUERY_REGISTRY_DIRECT;
|
||
|
parameters[3].Name = L"IO Port";
|
||
|
parameters[3].EntryContext = &IOPort;
|
||
|
parameters[3].DefaultType = REG_DWORD;
|
||
|
parameters[3].DefaultData = &defaultIOPort;
|
||
|
parameters[3].DefaultLength = sizeof(USHORT);
|
||
|
|
||
|
status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
|
||
|
parametersPath.Buffer,
|
||
|
parameters,
|
||
|
NULL,
|
||
|
NULL);
|
||
|
if (!NT_SUCCESS(status))
|
||
|
{
|
||
|
FsVgaPrint((1,
|
||
|
"FsVga-FsVgaServiceParameters: RtlQueryRegistryValues failed with 0x%x\n",
|
||
|
status));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!NT_SUCCESS(status))
|
||
|
{
|
||
|
//
|
||
|
// Go ahead and assign driver defaults.
|
||
|
//
|
||
|
configuration->EmulationMode = defaultEmulationMode;
|
||
|
configuration->HardwareCursor = defaultHardwareCursor;
|
||
|
configuration->HardwareScroll = defaultHardwareScroll;
|
||
|
configuration->IOPort = defaultIOPort;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
configuration->EmulationMode = (USHORT)EmulationMode;
|
||
|
configuration->HardwareCursor = (USHORT)HardwareCursor;
|
||
|
configuration->HardwareScroll = (USHORT)HardwareScroll;
|
||
|
configuration->IOPort = (USHORT)IOPort;
|
||
|
}
|
||
|
|
||
|
FsVgaPrint((1,
|
||
|
"FsVga-FsVgaServiceParameters: Emulation Mode = %d\n",
|
||
|
configuration->EmulationMode));
|
||
|
|
||
|
FsVgaPrint((1,
|
||
|
"FsVga-FsVgaServiceParameters: Hardware Cursor = %d\n",
|
||
|
configuration->HardwareCursor));
|
||
|
|
||
|
FsVgaPrint((1,
|
||
|
"FsVga-FsVgaServiceParameters: Hardware Scroll = %d\n",
|
||
|
configuration->HardwareScroll));
|
||
|
|
||
|
FsVgaPrint((1,
|
||
|
"FsVga-FsVgaServiceParameters: IO Port = %x\n",
|
||
|
configuration->IOPort));
|
||
|
|
||
|
//
|
||
|
// Free the allocated memory before returning.
|
||
|
//
|
||
|
|
||
|
if (parametersPath.Buffer)
|
||
|
ExFreePool(parametersPath.Buffer);
|
||
|
if (parameters)
|
||
|
ExFreePool(parameters);
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
FsVgaOpenCloseDispatch(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This is the dispatch routine for create/open and close requests.
|
||
|
These requests complete successfully.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject - Pointer to the device object.
|
||
|
|
||
|
Irp - Pointer to the request packet.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status is returned.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
UNREFERENCED_PARAMETER(DeviceObject);
|
||
|
|
||
|
FsVgaPrint((3,"FSVGA-FsVgaOpenCloseDispatch: enter\n"));
|
||
|
|
||
|
PAGED_CODE();
|
||
|
|
||
|
//
|
||
|
// Complete the request with successful status.
|
||
|
//
|
||
|
|
||
|
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||
|
Irp->IoStatus.Information = 0;
|
||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||
|
|
||
|
FsVgaPrint((3,"FSVGA-FsVgaOpenCloseDispatch: exit\n"));
|
||
|
|
||
|
return(STATUS_SUCCESS);
|
||
|
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
FsVgaDeviceControl(
|
||
|
IN PDEVICE_OBJECT DeviceObject,
|
||
|
IN PIRP Irp
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine is the dispatch routine for device control requests.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceObject - Pointer to the device object.
|
||
|
|
||
|
Irp - Pointer to the request packet.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
Status is returned.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PIO_STACK_LOCATION irpSp;
|
||
|
PVOID ioBuffer;
|
||
|
ULONG inputBufferLength;
|
||
|
ULONG outputBufferLength;
|
||
|
PDEVICE_EXTENSION deviceExtension;
|
||
|
NTSTATUS status = STATUS_SUCCESS;
|
||
|
|
||
|
FsVgaPrint((2,"FSVGA-FsVgaDeviceControl: enter\n"));
|
||
|
|
||
|
PAGED_CODE();
|
||
|
|
||
|
//
|
||
|
// Get a pointer to the device extension.
|
||
|
//
|
||
|
|
||
|
deviceExtension = DeviceObject->DeviceExtension;
|
||
|
|
||
|
//
|
||
|
// Initialize the returned Information field.
|
||
|
//
|
||
|
|
||
|
Irp->IoStatus.Information = 0;
|
||
|
|
||
|
//
|
||
|
// Get a pointer to the current parameters for this request. The
|
||
|
// information is contained in the current stack location.
|
||
|
//
|
||
|
|
||
|
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
||
|
|
||
|
//
|
||
|
// Get the pointer to the input/output buffer and it's length
|
||
|
//
|
||
|
|
||
|
ioBuffer = Irp->AssociatedIrp.SystemBuffer;
|
||
|
inputBufferLength = irpSp->Parameters.DeviceIoControl.InputBufferLength;
|
||
|
outputBufferLength = irpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
||
|
|
||
|
//
|
||
|
// Case on the device control subfunction that is being performed by the
|
||
|
// requestor.
|
||
|
//
|
||
|
|
||
|
switch (irpSp->Parameters.DeviceIoControl.IoControlCode)
|
||
|
{
|
||
|
case IOCTL_FSVIDEO_COPY_FRAME_BUFFER:
|
||
|
FsVgaPrint((2, "FsVgaDeviceControl - CopyFrameBuffer\n"));
|
||
|
status = FsVgaCopyFrameBuffer(deviceExtension,
|
||
|
(PFSVIDEO_COPY_FRAME_BUFFER) ioBuffer,
|
||
|
inputBufferLength);
|
||
|
break;
|
||
|
|
||
|
case IOCTL_FSVIDEO_WRITE_TO_FRAME_BUFFER:
|
||
|
FsVgaPrint((2, "FsVgaDeviceControl - WriteToFrameBuffer\n"));
|
||
|
status = FsVgaWriteToFrameBuffer(deviceExtension,
|
||
|
(PFSVIDEO_WRITE_TO_FRAME_BUFFER) ioBuffer,
|
||
|
inputBufferLength);
|
||
|
break;
|
||
|
|
||
|
case IOCTL_FSVIDEO_REVERSE_MOUSE_POINTER:
|
||
|
FsVgaPrint((2, "FsVgaDeviceControl - ReverseMousePointer\n"));
|
||
|
status = FsVgaReverseMousePointer(deviceExtension,
|
||
|
(PFSVIDEO_REVERSE_MOUSE_POINTER) ioBuffer,
|
||
|
inputBufferLength);
|
||
|
break;
|
||
|
|
||
|
case IOCTL_FSVIDEO_SET_CURRENT_MODE:
|
||
|
FsVgaPrint((2, "FsVgaDeviceControl - SetCurrentModes\n"));
|
||
|
status = FsVgaSetMode(deviceExtension,
|
||
|
(PFSVIDEO_MODE_INFORMATION) ioBuffer,
|
||
|
inputBufferLength);
|
||
|
break;
|
||
|
|
||
|
case IOCTL_FSVIDEO_SET_SCREEN_INFORMATION:
|
||
|
FsVgaPrint((2, "FsVgaDeviceControl - SetScreenInformation\n"));
|
||
|
status = FsVgaSetScreenInformation(deviceExtension,
|
||
|
(PFSVIDEO_SCREEN_INFORMATION) ioBuffer,
|
||
|
inputBufferLength);
|
||
|
break;
|
||
|
|
||
|
case IOCTL_FSVIDEO_SET_CURSOR_POSITION:
|
||
|
FsVgaPrint((2, "FsVgaDeviceControl - SetCursorPosition\n"));
|
||
|
status = FsVgaSetCursorPosition(deviceExtension,
|
||
|
(PFSVIDEO_CURSOR_POSITION) ioBuffer,
|
||
|
inputBufferLength);
|
||
|
break;
|
||
|
|
||
|
case IOCTL_VIDEO_SET_CURSOR_ATTR:
|
||
|
FsVgaPrint((2, "FsVgaDeviceControl - SetCursorAttribute\n"));
|
||
|
status = FsVgaSetCursorAttribute(deviceExtension,
|
||
|
(PVIDEO_CURSOR_ATTRIBUTES) ioBuffer,
|
||
|
inputBufferLength);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
FsVgaPrint((1,
|
||
|
"FSVGA-FsVgaDeviceControl: INVALID REQUEST (0x%x)\n",
|
||
|
irpSp->Parameters.DeviceIoControl.IoControlCode));
|
||
|
|
||
|
status = STATUS_INVALID_DEVICE_REQUEST;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
Irp->IoStatus.Status = status;
|
||
|
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||
|
|
||
|
FsVgaPrint((2,"FSVGA-FsVgaDeviceControl: exit\n"));
|
||
|
|
||
|
return(status);
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
FsVgaCopyFrameBuffer(
|
||
|
PDEVICE_EXTENSION DeviceExtension,
|
||
|
PFSVIDEO_COPY_FRAME_BUFFER CopyFrameBuffer,
|
||
|
ULONG inputBufferLength
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine copy the frame buffer.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceExtension - Pointer to the miniport driver's device extension.
|
||
|
|
||
|
CopyFrameBuffer - Pointer to the structure containing the information about the copy frame buffer.
|
||
|
|
||
|
inputBufferLength - Length of the input buffer supplied by the user.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_INSUFFICIENT_BUFFER if the input buffer was not large enough
|
||
|
for the input data.
|
||
|
|
||
|
STATUS_SUCCESS if the operation completed successfully.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// Check if the size of the data in the input buffer is large enough.
|
||
|
//
|
||
|
|
||
|
if (inputBufferLength < sizeof(FSVIDEO_COPY_FRAME_BUFFER)) {
|
||
|
return STATUS_INVALID_BUFFER_SIZE;
|
||
|
}
|
||
|
|
||
|
if (CopyFrameBuffer->SrcScreen.nNumberOfChars != CopyFrameBuffer->DestScreen.nNumberOfChars) {
|
||
|
return STATUS_INVALID_PARAMETER;
|
||
|
}
|
||
|
|
||
|
if (! (DeviceExtension->CurrentMode.VideoMode.AttributeFlags & VIDEO_MODE_GRAPHICS))
|
||
|
{
|
||
|
/*
|
||
|
* This is the TEXT frame buffer.
|
||
|
*/
|
||
|
|
||
|
ULONG OffsSrc;
|
||
|
ULONG OffsDest;
|
||
|
PUCHAR pFrameBuf = DeviceExtension->CurrentMode.VideoMemory.FrameBufferBase;
|
||
|
COORD ScreenSize ;
|
||
|
COORD SrcScrnSize ;
|
||
|
COORD SrcScrnPos ;
|
||
|
COORD DstScrnSize ;
|
||
|
COORD DstScrnPos ;
|
||
|
|
||
|
ScreenSize = DeviceExtension->ScreenAndFont.ScreenSize ;
|
||
|
SrcScrnSize = CopyFrameBuffer->SrcScreen.ScreenSize ;
|
||
|
DstScrnSize = CopyFrameBuffer->DestScreen.ScreenSize ;
|
||
|
SrcScrnPos = CopyFrameBuffer->SrcScreen.Position ;
|
||
|
DstScrnPos = CopyFrameBuffer->DestScreen.Position ;
|
||
|
|
||
|
if ((SrcScrnPos.X > ScreenSize.X) ||
|
||
|
(SrcScrnPos.Y > ScreenSize.Y) ||
|
||
|
(SrcScrnSize.X > ScreenSize.X) ||
|
||
|
(DstScrnPos.X > ScreenSize.X) ||
|
||
|
(DstScrnPos.Y > ScreenSize.Y) ||
|
||
|
(DstScrnSize.X > ScreenSize.X) ||
|
||
|
(SrcScrnPos.Y * SrcScrnSize.X + SrcScrnPos.X + CopyFrameBuffer->SrcScreen.nNumberOfChars
|
||
|
> (ULONG)ScreenSize.X * ScreenSize.Y) ||
|
||
|
(DstScrnPos.Y * DstScrnSize.X + DstScrnPos.X + CopyFrameBuffer->DestScreen.nNumberOfChars
|
||
|
> (ULONG)ScreenSize.X * ScreenSize.Y)
|
||
|
)
|
||
|
{
|
||
|
return STATUS_INVALID_BUFFER_SIZE;
|
||
|
}
|
||
|
|
||
|
OffsSrc = SCREEN_BUFFER_POINTER(CopyFrameBuffer->SrcScreen.Position.X,
|
||
|
CopyFrameBuffer->SrcScreen.Position.Y,
|
||
|
CopyFrameBuffer->SrcScreen.ScreenSize.X,
|
||
|
sizeof(VGA_CHAR));
|
||
|
|
||
|
OffsDest = SCREEN_BUFFER_POINTER(CopyFrameBuffer->DestScreen.Position.X,
|
||
|
CopyFrameBuffer->DestScreen.Position.Y,
|
||
|
CopyFrameBuffer->DestScreen.ScreenSize.X,
|
||
|
sizeof(VGA_CHAR));
|
||
|
|
||
|
RtlMoveMemory(pFrameBuf + OffsDest,
|
||
|
pFrameBuf + OffsSrc,
|
||
|
CopyFrameBuffer->SrcScreen.nNumberOfChars * sizeof(VGA_CHAR));
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*
|
||
|
* This is the GRAPHICS frame buffer.
|
||
|
*/
|
||
|
return FsgCopyFrameBuffer(DeviceExtension,
|
||
|
CopyFrameBuffer,
|
||
|
inputBufferLength);
|
||
|
}
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
FsVgaWriteToFrameBuffer(
|
||
|
PDEVICE_EXTENSION DeviceExtension,
|
||
|
PFSVIDEO_WRITE_TO_FRAME_BUFFER WriteFrameBuffer,
|
||
|
ULONG inputBufferLength
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine write the frame buffer.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceExtension - Pointer to the miniport driver's device extension.
|
||
|
|
||
|
WriteFrameBuffer - Pointer to the structure containing the information about the write frame buffer.
|
||
|
|
||
|
inputBufferLength - Length of the input buffer supplied by the user.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_INSUFFICIENT_BUFFER if the input buffer was not large enough
|
||
|
for the input data.
|
||
|
|
||
|
STATUS_SUCCESS if the operation completed successfully.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// Check if the size of the data in the input buffer is large enough.
|
||
|
//
|
||
|
|
||
|
if (inputBufferLength < sizeof(FSVIDEO_WRITE_TO_FRAME_BUFFER)) {
|
||
|
FsVgaPrint((1, "FsVgaWriteToFrameBuffer: Fail of STATUS_INVALID_BUFFER_SIZE\n"));
|
||
|
return STATUS_INVALID_BUFFER_SIZE;
|
||
|
}
|
||
|
|
||
|
if (WriteFrameBuffer->DestScreen.Position.X < 0 ||
|
||
|
WriteFrameBuffer->DestScreen.Position.X > DeviceExtension->ScreenAndFont.ScreenSize.X ||
|
||
|
(SHORT)(WriteFrameBuffer->DestScreen.Position.X +
|
||
|
WriteFrameBuffer->DestScreen.nNumberOfChars)
|
||
|
> DeviceExtension->ScreenAndFont.ScreenSize.X ||
|
||
|
WriteFrameBuffer->DestScreen.Position.Y < 0 ||
|
||
|
WriteFrameBuffer->DestScreen.Position.Y > DeviceExtension->ScreenAndFont.ScreenSize.Y) {
|
||
|
|
||
|
FsVgaPrint((1, "FsVgaWriteToFrameBuffer: Fail of STATUS_INVALID_BUFFER_SIZE\n"));
|
||
|
|
||
|
return STATUS_INVALID_BUFFER_SIZE;
|
||
|
}
|
||
|
|
||
|
if (! (DeviceExtension->CurrentMode.VideoMode.AttributeFlags & VIDEO_MODE_GRAPHICS))
|
||
|
{
|
||
|
/*
|
||
|
* This is the TEXT frame buffer.
|
||
|
*/
|
||
|
|
||
|
ULONG Offs;
|
||
|
PUCHAR pFrameBuf = DeviceExtension->CurrentMode.VideoMemory.FrameBufferBase;
|
||
|
PCHAR_IMAGE_INFO pCharInfoUni = WriteFrameBuffer->SrcBuffer;
|
||
|
PCHAR_IMAGE_INFO pCharInfoAsc;
|
||
|
ULONG Length = WriteFrameBuffer->DestScreen.nNumberOfChars;
|
||
|
PVOID pCapBuffer = NULL;
|
||
|
ULONG cCapBuffer = 0;
|
||
|
|
||
|
Offs = SCREEN_BUFFER_POINTER(WriteFrameBuffer->DestScreen.Position.X,
|
||
|
WriteFrameBuffer->DestScreen.Position.Y,
|
||
|
WriteFrameBuffer->DestScreen.ScreenSize.X,
|
||
|
sizeof(VGA_CHAR));
|
||
|
|
||
|
cCapBuffer = Length * sizeof(CHAR_IMAGE_INFO);
|
||
|
pCapBuffer = ExAllocatePool(PagedPool, cCapBuffer);
|
||
|
|
||
|
if (!pCapBuffer) {
|
||
|
ULONG dumpData[DUMP_COUNT];
|
||
|
|
||
|
FsVgaPrint((1,
|
||
|
"FSVGA-FsVgaWriteToFrameBuffer: Could not allocate resource list\n"));
|
||
|
//
|
||
|
// Log an error.
|
||
|
//
|
||
|
dumpData[0] = cCapBuffer;
|
||
|
FsVgaLogError(DeviceExtension->DeviceObject,
|
||
|
FSVGA_INSUFFICIENT_RESOURCES,
|
||
|
FSVGA_ERROR_VALUE_BASE + 200,
|
||
|
STATUS_INSUFFICIENT_RESOURCES,
|
||
|
dumpData,
|
||
|
1
|
||
|
);
|
||
|
return STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
|
||
|
TranslateOutputToOem(pCapBuffer, pCharInfoUni, Length);
|
||
|
|
||
|
pCharInfoAsc = pCapBuffer;
|
||
|
pFrameBuf += Offs;
|
||
|
while (Length--)
|
||
|
{
|
||
|
*pFrameBuf++ = pCharInfoAsc->CharInfo.Char.AsciiChar;
|
||
|
*pFrameBuf++ = (UCHAR) (pCharInfoAsc->CharInfo.Attributes);
|
||
|
pCharInfoAsc++;
|
||
|
}
|
||
|
|
||
|
ExFreePool(pCapBuffer);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*
|
||
|
* This is the GRAPHICS frame buffer.
|
||
|
*/
|
||
|
return FsgWriteToFrameBuffer(DeviceExtension,
|
||
|
WriteFrameBuffer,
|
||
|
inputBufferLength);
|
||
|
}
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
FsVgaReverseMousePointer(
|
||
|
PDEVICE_EXTENSION DeviceExtension,
|
||
|
PFSVIDEO_REVERSE_MOUSE_POINTER MouseBuffer,
|
||
|
ULONG inputBufferLength
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine reverse the frame buffer for mouse pointer.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceExtension - Pointer to the miniport driver's device extension.
|
||
|
|
||
|
MouseBuffer - Pointer to the structure containing the information about the mouse frame buffer.
|
||
|
|
||
|
inputBufferLength - Length of the input buffer supplied by the user.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_INSUFFICIENT_BUFFER if the input buffer was not large enough
|
||
|
for the input data.
|
||
|
|
||
|
STATUS_SUCCESS if the operation completed successfully.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// Check if the size of the data in the input buffer is large enough.
|
||
|
//
|
||
|
|
||
|
if (inputBufferLength < sizeof(FSVIDEO_REVERSE_MOUSE_POINTER)) {
|
||
|
return STATUS_INVALID_BUFFER_SIZE;
|
||
|
}
|
||
|
|
||
|
if (! (DeviceExtension->CurrentMode.VideoMode.AttributeFlags & VIDEO_MODE_GRAPHICS))
|
||
|
{
|
||
|
/*
|
||
|
* This is the TEXT frame buffer.
|
||
|
*/
|
||
|
|
||
|
ULONG Offs;
|
||
|
PUCHAR pFrameBuf = DeviceExtension->CurrentMode.VideoMemory.FrameBufferBase;
|
||
|
UCHAR Attribute;
|
||
|
|
||
|
Offs = SCREEN_BUFFER_POINTER(MouseBuffer->Screen.Position.X,
|
||
|
MouseBuffer->Screen.Position.Y,
|
||
|
MouseBuffer->Screen.ScreenSize.X,
|
||
|
sizeof(VGA_CHAR));
|
||
|
pFrameBuf += Offs;
|
||
|
|
||
|
Attribute = (*(pFrameBuf + 1) & 0xF0) >> 4;
|
||
|
Attribute |= (*(pFrameBuf + 1) & 0x0F) << 4;
|
||
|
*(pFrameBuf + 1) = Attribute;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*
|
||
|
* This is the GRAPHICS frame buffer.
|
||
|
*/
|
||
|
return FsgReverseMousePointer(DeviceExtension,
|
||
|
MouseBuffer,
|
||
|
inputBufferLength);
|
||
|
}
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
FsVgaSetMode(
|
||
|
PDEVICE_EXTENSION DeviceExtension,
|
||
|
PFSVIDEO_MODE_INFORMATION ModeInformation,
|
||
|
ULONG inputBufferLength
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine sets the current video information.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceExtension - Pointer to the miniport driver's device extension.
|
||
|
|
||
|
ModeInformation - Pointer to the structure containing the information about the
|
||
|
full screen video.
|
||
|
|
||
|
inputBufferLength - Length of the input buffer supplied by the user.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_INSUFFICIENT_BUFFER if the input buffer was not large enough
|
||
|
for the input data.
|
||
|
|
||
|
STATUS_SUCCESS if the operation completed successfully.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// Check if the size of the data in the input buffer is large enough.
|
||
|
//
|
||
|
|
||
|
if (inputBufferLength < sizeof(FSVIDEO_MODE_INFORMATION)) {
|
||
|
return STATUS_INVALID_BUFFER_SIZE;
|
||
|
}
|
||
|
|
||
|
DeviceExtension->CurrentMode = *ModeInformation;
|
||
|
|
||
|
FsVgaPrint((3, "FsVgaSetMode: Video Mode:\n"));
|
||
|
FsVgaPrint((3, " ModeIndex = %x\n", DeviceExtension->CurrentMode.VideoMode.ModeIndex));
|
||
|
FsVgaPrint((3, " VisScreenWidth = %d\n", DeviceExtension->CurrentMode.VideoMode.VisScreenWidth));
|
||
|
FsVgaPrint((3, " VisScreenHeight = %d\n", DeviceExtension->CurrentMode.VideoMode.VisScreenHeight));
|
||
|
FsVgaPrint((3, " NumberOfPlanes = %d\n", DeviceExtension->CurrentMode.VideoMode.NumberOfPlanes));
|
||
|
FsVgaPrint((3, " BitsPerPlane = %d\n", DeviceExtension->CurrentMode.VideoMode.BitsPerPlane));
|
||
|
|
||
|
FsVgaPrint((3, "FsVgaSetMode: Video Memory:\n"));
|
||
|
FsVgaPrint((3, " VideoRamBase = %x\n", DeviceExtension->CurrentMode.VideoMemory.VideoRamBase));
|
||
|
FsVgaPrint((3, " VideoRamLength = %x\n", DeviceExtension->CurrentMode.VideoMemory.VideoRamLength));
|
||
|
FsVgaPrint((3, " FrameBufferBase = %x\n", DeviceExtension->CurrentMode.VideoMemory.FrameBufferBase));
|
||
|
FsVgaPrint((3, " FrameBufferLength = %x\n", DeviceExtension->CurrentMode.VideoMemory.FrameBufferLength));
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
FsVgaSetScreenInformation(
|
||
|
PDEVICE_EXTENSION DeviceExtension,
|
||
|
PFSVIDEO_SCREEN_INFORMATION ScreenInformation,
|
||
|
ULONG inputBufferLength
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine sets the screen and font information.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceExtension - Pointer to the miniport driver's device extension.
|
||
|
|
||
|
ScreenInformation - Pointer to the structure containing the information about the
|
||
|
screen anf font.
|
||
|
|
||
|
inputBufferLength - Length of the input buffer supplied by the user.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_INSUFFICIENT_BUFFER if the input buffer was not large enough
|
||
|
for the input data.
|
||
|
|
||
|
STATUS_SUCCESS if the operation completed successfully.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// Check if the size of the data in the input buffer is large enough.
|
||
|
//
|
||
|
|
||
|
if (inputBufferLength < sizeof(FSVIDEO_SCREEN_INFORMATION)) {
|
||
|
return STATUS_INVALID_BUFFER_SIZE;
|
||
|
}
|
||
|
|
||
|
DeviceExtension->ScreenAndFont = *ScreenInformation;
|
||
|
|
||
|
FsVgaPrint((3, "FsVgaSetScreenInformation:\n"));
|
||
|
FsVgaPrint((3, " ScreenSize.X = %d, Y = %d\n",
|
||
|
DeviceExtension->ScreenAndFont.ScreenSize.X,
|
||
|
DeviceExtension->ScreenAndFont.ScreenSize.Y));
|
||
|
FsVgaPrint((3, " FontSize.X = %d, Y = %d\n",
|
||
|
DeviceExtension->ScreenAndFont.FontSize.X,
|
||
|
DeviceExtension->ScreenAndFont.FontSize.Y));
|
||
|
|
||
|
FsgVgaInitializeHWFlags(DeviceExtension);
|
||
|
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
|
||
|
NTSTATUS
|
||
|
FsVgaSetCursorPosition(
|
||
|
PDEVICE_EXTENSION DeviceExtension,
|
||
|
PFSVIDEO_CURSOR_POSITION CursorPosition,
|
||
|
ULONG inputBufferLength
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine sets the cursor position.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceExtension - Pointer to the miniport driver's device extension.
|
||
|
|
||
|
CursorPosition - Pointer to the structure containing the information about the
|
||
|
cursor position.
|
||
|
|
||
|
inputBufferLength - Length of the input buffer supplied by the user.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_INSUFFICIENT_BUFFER if the input buffer was not large enough
|
||
|
for the input data.
|
||
|
|
||
|
STATUS_SUCCESS if the operation completed successfully.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// Check if the size of the data in the input buffer is large enough.
|
||
|
//
|
||
|
|
||
|
if (inputBufferLength < sizeof(VIDEO_CURSOR_POSITION)) {
|
||
|
return STATUS_INVALID_BUFFER_SIZE;
|
||
|
}
|
||
|
|
||
|
if (DeviceExtension->CurrentMode.VideoMode.AttributeFlags & VIDEO_MODE_GRAPHICS)
|
||
|
{
|
||
|
FsgInvertCursor(DeviceExtension,FALSE);
|
||
|
}
|
||
|
|
||
|
DeviceExtension->EmulateInfo.CursorPosition = *CursorPosition;
|
||
|
|
||
|
if (DeviceExtension->CurrentMode.VideoMode.AttributeFlags & VIDEO_MODE_GRAPHICS)
|
||
|
{
|
||
|
FsgInvertCursor(DeviceExtension,TRUE);
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*
|
||
|
* If current video mode is a TEXT MODE.
|
||
|
* FSVGA.SYS didn't handling hardware cursor
|
||
|
* because I don't know device of VGA.SYS or others.
|
||
|
*
|
||
|
* In this case, by returns STATUS_UNSUCCESSFUL, caller
|
||
|
* do DeviceIoControl to VGA miniport driver.
|
||
|
*/
|
||
|
return STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
NTSTATUS
|
||
|
FsVgaSetCursorAttribute(
|
||
|
PDEVICE_EXTENSION DeviceExtension,
|
||
|
PVIDEO_CURSOR_ATTRIBUTES CursorAttributes,
|
||
|
ULONG inputBufferLength
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine sets the cursor attributes.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DeviceExtension - Pointer to the miniport driver's device extension.
|
||
|
|
||
|
CursorAttributes - Pointer to the structure containing the information about the
|
||
|
cursor attributes.
|
||
|
|
||
|
inputBufferLength - Length of the input buffer supplied by the user.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
STATUS_INSUFFICIENT_BUFFER if the input buffer was not large enough
|
||
|
for the input data.
|
||
|
|
||
|
STATUS_SUCCESS if the operation completed successfully.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
//
|
||
|
// Check if the size of the data in the input buffer is large enough.
|
||
|
//
|
||
|
|
||
|
if (inputBufferLength < sizeof(VIDEO_CURSOR_ATTRIBUTES)) {
|
||
|
return STATUS_INVALID_BUFFER_SIZE;
|
||
|
}
|
||
|
|
||
|
if (DeviceExtension->CurrentMode.VideoMode.AttributeFlags & VIDEO_MODE_GRAPHICS)
|
||
|
{
|
||
|
FsgInvertCursor(DeviceExtension,FALSE);
|
||
|
}
|
||
|
|
||
|
DeviceExtension->EmulateInfo.CursorAttributes = *CursorAttributes;
|
||
|
|
||
|
if (DeviceExtension->CurrentMode.VideoMode.AttributeFlags & VIDEO_MODE_GRAPHICS)
|
||
|
{
|
||
|
FsgInvertCursor(DeviceExtension,TRUE);
|
||
|
return STATUS_SUCCESS;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
/*
|
||
|
* If current video mode is a TEXT MODE.
|
||
|
* FSVGA.SYS didn't handling hardware cursor
|
||
|
* because I don't know device of VGA.SYS or others.
|
||
|
*
|
||
|
* In this case, by returns STATUS_UNSUCCESSFUL, caller
|
||
|
* do DeviceIoControl to VGA miniport driver.
|
||
|
*/
|
||
|
return STATUS_UNSUCCESSFUL;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
VOID
|
||
|
FsVgaLogError(
|
||
|
IN PVOID Object,
|
||
|
IN NTSTATUS ErrorCode,
|
||
|
IN ULONG UniqueErrorValue,
|
||
|
IN NTSTATUS FinalStatus,
|
||
|
IN PULONG DumpData,
|
||
|
IN ULONG DumpCount
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
This routine contains common code to write an error log entry. It is
|
||
|
called from other routines, especially FsVgaInitialize, to avoid
|
||
|
duplication of code. Note that some routines continue to have their
|
||
|
own error logging code (especially in the case where the error logging
|
||
|
can be localized and/or the routine has more data because there is
|
||
|
and IRP).
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Object - Pointer to the device or driver object.
|
||
|
|
||
|
ErrorCode - The error code for the error log packet.
|
||
|
|
||
|
UniqueErrorValue - The unique error value for the error log packet.
|
||
|
|
||
|
FinalStatus - The final status of the operation for the error log packet.
|
||
|
|
||
|
DumpData - Pointer to an array of dump data for the error log packet.
|
||
|
|
||
|
DumpCount - The number of entries in the dump data array.
|
||
|
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
PIO_ERROR_LOG_PACKET errorLogEntry;
|
||
|
ULONG i;
|
||
|
|
||
|
errorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry(
|
||
|
(PVOID) Object,
|
||
|
(UCHAR) (sizeof(IO_ERROR_LOG_PACKET)
|
||
|
+ (DumpCount * sizeof(ULONG)))
|
||
|
);
|
||
|
|
||
|
if (errorLogEntry != NULL) {
|
||
|
|
||
|
errorLogEntry->ErrorCode = ErrorCode;
|
||
|
errorLogEntry->DumpDataSize = (USHORT) (DumpCount * sizeof(ULONG));
|
||
|
errorLogEntry->SequenceNumber = 0;
|
||
|
errorLogEntry->MajorFunctionCode = 0;
|
||
|
errorLogEntry->IoControlCode = 0;
|
||
|
errorLogEntry->RetryCount = 0;
|
||
|
errorLogEntry->UniqueErrorValue = UniqueErrorValue;
|
||
|
errorLogEntry->FinalStatus = FinalStatus;
|
||
|
for (i = 0; i < DumpCount; i++)
|
||
|
errorLogEntry->DumpData[i] = DumpData[i];
|
||
|
|
||
|
IoWriteErrorLogEntry(errorLogEntry);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#if DBG
|
||
|
VOID
|
||
|
FsVgaDebugPrint(
|
||
|
ULONG DebugPrintLevel,
|
||
|
PCCHAR DebugMessage,
|
||
|
...
|
||
|
)
|
||
|
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Debug print routine.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
Debug print level between 0 and 3, with 3 being the most verbose.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None.
|
||
|
|
||
|
--*/
|
||
|
|
||
|
{
|
||
|
va_list ap;
|
||
|
|
||
|
va_start(ap, DebugMessage);
|
||
|
|
||
|
if (DebugPrintLevel <= Globals.FsVgaDebug) {
|
||
|
|
||
|
char buffer[128];
|
||
|
|
||
|
(VOID) vsprintf(buffer, DebugMessage, ap);
|
||
|
|
||
|
DbgPrint(buffer);
|
||
|
}
|
||
|
|
||
|
va_end(ap);
|
||
|
|
||
|
}
|
||
|
#endif
|