📄 videoprt.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 Library General Public
* License as published by the Free Software Foundation; either
* version 2 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
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; see the file COPYING.LIB.
* If not, write to the Free Software Foundation,
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Id: videoprt.c 28127 2007-08-03 12:10:43Z cfinck $
*/
#include "videoprt.h"
#include <wdmguid.h>
/* GLOBAL VARIABLES ***********************************************************/
ULONG CsrssInitialized = FALSE;
PKPROCESS Csrss = NULL;
ULONG VideoPortDeviceNumber = 0;
/* PRIVATE FUNCTIONS **********************************************************/
NTSTATUS NTAPI
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
return STATUS_SUCCESS;
}
PVOID NTAPI
IntVideoPortImageDirectoryEntryToData(
PVOID BaseAddress,
ULONG Directory)
{
PIMAGE_NT_HEADERS NtHeader;
ULONG Va;
NtHeader = RtlImageNtHeader(BaseAddress);
if (NtHeader == NULL)
return NULL;
if (Directory >= NtHeader->OptionalHeader.NumberOfRvaAndSizes)
return NULL;
Va = NtHeader->OptionalHeader.DataDirectory[Directory].VirtualAddress;
if (Va == 0)
return NULL;
return (PVOID)((ULONG_PTR)BaseAddress + Va);
}
PVOID NTAPI
IntVideoPortGetProcAddress(
IN PVOID HwDeviceExtension,
IN PUCHAR FunctionName)
{
SYSTEM_GDI_DRIVER_INFORMATION GdiDriverInfo;
PVOID BaseAddress;
PIMAGE_EXPORT_DIRECTORY ExportDir;
PUSHORT OrdinalPtr;
PULONG NamePtr;
PULONG AddressPtr;
ULONG i = 0;
NTSTATUS Status;
DPRINT("VideoPortGetProcAddress(%s)\n", FunctionName);
RtlInitUnicodeString(&GdiDriverInfo.DriverName, L"videoprt");
Status = ZwSetSystemInformation(
SystemLoadGdiDriverInformation,
&GdiDriverInfo,
sizeof(SYSTEM_GDI_DRIVER_INFORMATION));
if (!NT_SUCCESS(Status))
{
DPRINT("Couldn't get our own module handle?\n");
return NULL;
}
BaseAddress = GdiDriverInfo.ImageAddress;
/* Get the pointer to the export directory */
ExportDir = (PIMAGE_EXPORT_DIRECTORY)IntVideoPortImageDirectoryEntryToData(
BaseAddress,
IMAGE_DIRECTORY_ENTRY_EXPORT);
/* Search by name */
AddressPtr = (PULONG)
((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfFunctions);
OrdinalPtr = (PUSHORT)
((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNameOrdinals);
NamePtr = (PULONG)
((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNames);
for (i = 0; i < ExportDir->NumberOfNames; i++, NamePtr++, OrdinalPtr++)
{
if (!_strnicmp((PCHAR)FunctionName, (PCHAR)((ULONG_PTR)BaseAddress + *NamePtr),
strlen((PCHAR)FunctionName)))
{
return (PVOID)((ULONG_PTR)BaseAddress +
(ULONG_PTR)AddressPtr[*OrdinalPtr]);
}
}
DPRINT("VideoPortGetProcAddress: Can't resolve symbol %s\n", FunctionName);
return NULL;
}
VOID NTAPI
IntVideoPortDeferredRoutine(
IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
PVOID HwDeviceExtension =
&((PVIDEO_PORT_DEVICE_EXTENSION)DeferredContext)->MiniPortDeviceExtension;
((PMINIPORT_DPC_ROUTINE)SystemArgument1)(HwDeviceExtension, SystemArgument2);
}
NTSTATUS
IntCreateRegistryPath(
IN PCUNICODE_STRING DriverRegistryPath,
OUT PUNICODE_STRING DeviceRegistryPath)
{
static WCHAR RegistryMachineSystem[] = L"\\REGISTRY\\MACHINE\\SYSTEM\\";
static WCHAR CurrentControlSet[] = L"CURRENTCONTROLSET\\";
static WCHAR ControlSet[] = L"CONTROLSET";
static WCHAR Insert1[] = L"Hardware Profiles\\Current\\System\\CurrentControlSet\\";
static WCHAR Insert2[] = L"\\Device0";
LPWSTR ProfilePath = NULL;
BOOLEAN Valid;
PWCHAR AfterControlSet;
Valid = (0 == _wcsnicmp(DriverRegistryPath->Buffer, RegistryMachineSystem,
wcslen(RegistryMachineSystem)));
{
AfterControlSet = DriverRegistryPath->Buffer + wcslen(RegistryMachineSystem);
if (0 == _wcsnicmp(AfterControlSet, CurrentControlSet, wcslen(CurrentControlSet)))
{
AfterControlSet += wcslen(CurrentControlSet);
}
else if (0 == _wcsnicmp(AfterControlSet, ControlSet, wcslen(ControlSet)))
{
AfterControlSet += wcslen(ControlSet);
while (L'0' <= *AfterControlSet && L'9' <= *AfterControlSet)
{
AfterControlSet++;
}
Valid = (L'\\' == *AfterControlSet);
AfterControlSet++;
}
else
{
Valid = FALSE;
}
}
if (Valid)
{
ProfilePath = ExAllocatePoolWithTag(PagedPool,
(wcslen(DriverRegistryPath->Buffer) +
wcslen(Insert1) + wcslen(Insert2) + 1) * sizeof(WCHAR),
TAG_VIDEO_PORT);
if (NULL != ProfilePath)
{
wcsncpy(ProfilePath, DriverRegistryPath->Buffer, AfterControlSet - DriverRegistryPath->Buffer);
wcscpy(ProfilePath + (AfterControlSet - DriverRegistryPath->Buffer), Insert1);
wcscat(ProfilePath, AfterControlSet);
wcscat(ProfilePath, Insert2);
Valid = NT_SUCCESS(RtlCheckRegistryKey(RTL_REGISTRY_ABSOLUTE, ProfilePath));
}
else
{
Valid = FALSE;
}
}
else
{
DPRINT1("Unparsable registry path %wZ", DriverRegistryPath);
}
if (Valid)
{
RtlInitUnicodeString(DeviceRegistryPath, ProfilePath);
}
else
{
if (ProfilePath)
ExFreePoolWithTag(ProfilePath, TAG_VIDEO_PORT);
DeviceRegistryPath->Length =
DeviceRegistryPath->MaximumLength =
DriverRegistryPath->Length + (9 * sizeof(WCHAR));
DeviceRegistryPath->Length -= sizeof(WCHAR);
DeviceRegistryPath->Buffer = ExAllocatePoolWithTag(
NonPagedPool,
DeviceRegistryPath->MaximumLength,
TAG_VIDEO_PORT);
if (!DeviceRegistryPath->Buffer)
return STATUS_NO_MEMORY;
swprintf(DeviceRegistryPath->Buffer, L"%s\\Device0",
DriverRegistryPath->Buffer);
}
return STATUS_SUCCESS;
}
NTSTATUS NTAPI
IntVideoPortCreateAdapterDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,
IN PDEVICE_OBJECT PhysicalDeviceObject,
OUT PDEVICE_OBJECT *DeviceObject OPTIONAL)
{
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
ULONG DeviceNumber;
ULONG PciSlotNumber;
PCI_SLOT_NUMBER SlotNumber;
ULONG Size;
NTSTATUS Status;
WCHAR DeviceBuffer[20];
UNICODE_STRING DeviceName;
PDEVICE_OBJECT DeviceObject_;
if (DeviceObject == NULL)
DeviceObject = &DeviceObject_;
/*
* Find the first free device number that can be used for video device
* object names and symlinks.
*/
DeviceNumber = VideoPortDeviceNumber++;
if (DeviceNumber == 0xFFFFFFFF)
{
DPRINT("Can't find free device number\n");
return STATUS_UNSUCCESSFUL;
}
/*
* Create the device object.
*/
/* Create a unicode device name. */
swprintf(DeviceBuffer, L"\\Device\\Video%lu", DeviceNumber);
RtlInitUnicodeString(&DeviceName, DeviceBuffer);
/* Create the device object. */
Status = IoCreateDevice(
DriverObject,
sizeof(VIDEO_PORT_DEVICE_EXTENSION) +
DriverExtension->InitializationData.HwDeviceExtensionSize,
&DeviceName,
FILE_DEVICE_VIDEO,
0,
TRUE,
DeviceObject);
if (!NT_SUCCESS(Status))
{
DPRINT("IoCreateDevice call failed with status 0x%08x\n", Status);
return Status;
}
/*
* Set the buffering strategy here. If you change this, remember
* to change VidDispatchDeviceControl too.
*/
(*DeviceObject)->Flags |= DO_BUFFERED_IO;
/*
* Initialize device extension.
*/
DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)((*DeviceObject)->DeviceExtension);
DeviceExtension->DeviceNumber = DeviceNumber;
DeviceExtension->DriverObject = DriverObject;
DeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject;
DeviceExtension->FunctionalDeviceObject = *DeviceObject;
DeviceExtension->DriverExtension = DriverExtension;
/*
* Get the registry path associated with this driver.
*/
Status = IntCreateRegistryPath(
&DriverExtension->RegistryPath,
&DeviceExtension->RegistryPath);
if (!NT_SUCCESS(Status))
{
DPRINT("IntCreateRegistryPath() call failed with status 0x%08x\n", Status);
IoDeleteDevice(*DeviceObject);
*DeviceObject = NULL;
return Status;
}
if (PhysicalDeviceObject != NULL)
{
/* Get bus number from the upper level bus driver. */
Size = sizeof(ULONG);
Status = IoGetDeviceProperty(
PhysicalDeviceObject,
DevicePropertyBusNumber,
Size,
&DeviceExtension->SystemIoBusNumber,
&Size);
if (!NT_SUCCESS(Status))
{
DPRINT("Couldn't get an information from bus driver. We will try to\n"
"use legacy detection method, but even that doesn't mean that\n"
"it will work.\n");
DeviceExtension->PhysicalDeviceObject = NULL;
}
}
DeviceExtension->AdapterInterfaceType =
DriverExtension->InitializationData.AdapterInterfaceType;
if (PhysicalDeviceObject != NULL)
{
/* Get bus type from the upper level bus driver. */
Size = sizeof(ULONG);
IoGetDeviceProperty(
PhysicalDeviceObject,
DevicePropertyLegacyBusType,
Size,
&DeviceExtension->AdapterInterfaceType,
&Size);
/* Get bus device address from the upper level bus driver. */
Size = sizeof(ULONG);
IoGetDeviceProperty(
PhysicalDeviceObject,
DevicePropertyAddress,
Size,
&PciSlotNumber,
&Size);
/* Convert slotnumber to PCI_SLOT_NUMBER */
SlotNumber.u.AsULONG = 0;
SlotNumber.u.bits.DeviceNumber = (PciSlotNumber >> 16) & 0xFFFF;
SlotNumber.u.bits.FunctionNumber = PciSlotNumber & 0xFFFF;
DeviceExtension->SystemIoSlotNumber = SlotNumber.u.AsULONG;
}
InitializeListHead(&DeviceExtension->AddressMappingListHead);
KeInitializeDpc(
&DeviceExtension->DpcObject,
IntVideoPortDeferredRoutine,
DeviceExtension);
KeInitializeMutex(&DeviceExtension->DeviceLock, 0);
/* Attach the device. */
if (PhysicalDeviceObject != NULL)
DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(
*DeviceObject, PhysicalDeviceObject);
/* Remove the initailizing flag */
(*DeviceObject)->Flags &= ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}
/* FIXME: we have to detach the device object in IntVideoPortFindAdapter if it fails */
NTSTATUS NTAPI
IntVideoPortFindAdapter(
IN PDRIVER_OBJECT DriverObject,
IN PVIDEO_PORT_DRIVER_EXTENSION DriverExtension,
IN PDEVICE_OBJECT DeviceObject)
{
WCHAR DeviceVideoBuffer[20];
PVIDEO_PORT_DEVICE_EXTENSION DeviceExtension;
ULONG Size;
NTSTATUS Status;
VIDEO_PORT_CONFIG_INFO ConfigInfo;
SYSTEM_BASIC_INFORMATION SystemBasicInfo;
UCHAR Again = FALSE;
WCHAR DeviceBuffer[20];
UNICODE_STRING DeviceName;
WCHAR SymlinkBuffer[20];
UNICODE_STRING SymlinkName;
BOOL LegacyDetection = FALSE;
ULONG DeviceNumber;
DeviceExtension = (PVIDEO_PORT_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
DeviceNumber = DeviceExtension->DeviceNumber;
/*
* Setup a ConfigInfo structure that we will pass to HwFindAdapter.
*/
RtlZeroMemory(&ConfigInfo, sizeof(VIDEO_PORT_CONFIG_INFO));
ConfigInfo.Length = sizeof(VIDEO_PORT_CONFIG_INFO);
ConfigInfo.AdapterInterfaceType = DeviceExtension->AdapterInterfaceType;
if (ConfigInfo.AdapterInterfaceType == PCIBus)
ConfigInfo.InterruptMode = LevelSensitive;
else
ConfigInfo.InterruptMode = Latched;
ConfigInfo.DriverRegistryPath = DriverExtension->RegistryPath.Buffer;
ConfigInfo.VideoPortGetProcAddress = IntVideoPortGetProcAddress;
ConfigInfo.SystemIoBusNumber = DeviceExtension->SystemIoBusNumber;
ConfigInfo.BusInterruptLevel = DeviceExtension->InterruptLevel;
ConfigInfo.BusInterruptVector = DeviceExtension->InterruptVector;
Size = sizeof(SystemBasicInfo);
Status = ZwQuerySystemInformation(
SystemBasicInformation,
&SystemBasicInfo,
Size,
&Size);
if (NT_SUCCESS(Status))
{
ConfigInfo.SystemMemorySize =
SystemBasicInfo.NumberOfPhysicalPages *
SystemBasicInfo.PageSize;
}
/*
* Call miniport HwVidFindAdapter entry point to detect if
* particular device is present. There are two possible code
* paths. The first one is for Legacy drivers (NT4) and cases
* when we don't have information about what bus we're on. The
* second case is the standard one for Plug & Play drivers.
*/
if (DeviceExtension->PhysicalDeviceObject == NULL)
{
LegacyDetection = TRUE;
}
if (LegacyDetection)
{
ULONG BusNumber, MaxBuses;
MaxBuses = DeviceExtension->AdapterInterfaceType == PCIBus ? 8 : 1;
for (BusNumber = 0; BusNumber < MaxBuses; BusNumber++)
{
DeviceExtension->SystemIoBusNumber =
ConfigInfo.SystemIoBusNumber = BusNumber;
RtlZeroMemory(&DeviceExtension->MiniPortDeviceExtension,
DriverExtension->InitializationData.HwDeviceExtensionSize);
/* 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 == ERROR_DEV_NOT_EXIST)
{
continue;
}
else if (Status == NO_ERROR)
{
break;
}
else
{
DPRINT("HwFindAdapter call failed with error 0x%X\n", Status);
RtlFreeUnicodeString(&DeviceExtension->RegistryPath);
IoDeleteDevice(DeviceObject);
return Status;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -