⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 videoprt.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * 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 + -