videoprt.c
来自「一个类似windows」· C语言 代码 · 共 1,277 行 · 第 1/3 页
C
1,277 行
/*
* 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 21844 2006-05-07 19:34:23Z ion $
*/
#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 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 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;
DeviceExtension->RegistryPath.Length =
DeviceExtension->RegistryPath.MaximumLength =
DriverExtension->RegistryPath.Length + (9 * sizeof(WCHAR));
DeviceExtension->RegistryPath.Length -= sizeof(WCHAR);
DeviceExtension->RegistryPath.Buffer = ExAllocatePoolWithTag(
NonPagedPool,
DeviceExtension->RegistryPath.MaximumLength,
TAG_VIDEO_PORT);
swprintf(DeviceExtension->RegistryPath.Buffer, L"%s\\Device0",
DriverExtension->RegistryPath.Buffer);
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,
&DeviceExtension->SystemIoSlotNumber,
&Size);
}
InitializeListHead(&DeviceExtension->AddressMappingListHead);
KeInitializeDpc(
&DeviceExtension->DpcObject,
IntVideoPortDeferredRoutine,
DeviceExtension);
KeInitializeMutex(&DeviceExtension->DeviceLock, 0);
/* Attach the device. */
if (PhysicalDeviceObject != NULL)
DeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(
*DeviceObject, PhysicalDeviceObject);
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;
}
}
}
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);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?