videoprt.c

来自「一个类似windows」· C语言 代码 · 共 1,277 行 · 第 1/3 页

C
1,277
字号
   /* 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);
      }
      else
      {
         RtlInitUnicodeString(&DriverExtension->RegistryPath, NULL);
      }
   }

   /*
    * Copy the correct miniport initializtation 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;
   }

   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;
      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];
   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;
   QueryTable[0].EntryContext = NULL;
   QueryTable[0].DefaultType = REG_NONE;
   QueryTable[0].DefaultData = NULL;
   QueryTable[0].DefaultLength = 0;

   QueryTable[1].QueryRoutine = NULL;
   QueryTable[1].Name = NULL;

   if (!NT_SUCCESS(RtlQueryRegistryValues(
      RTL_REGISTRY_ABSOLUTE,
      DeviceExtension->RegistryPath.Buffer,
      QueryTable,
      &Context,
      NULL)))
      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)
{
   DPRINT("VideoPortSetRegistryParameters\n");
   ASSERT_IRQL(PASSIVE_LEVEL);
   return RtlWriteRegistryValue(
      RTL_REGISTRY_ABSOLUTE,
      VIDEO_PORT_GET_DEVICE_EXTENSION(HwDeviceExtension)->RegistryPath.Buffer,
      ValueName,
      REG_BINARY,
      ValueData,
      ValueLength);
}

/*
 * @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. */
   if (Length == 0)
   {
      if (RomImageBuffer != NULL)
      {
         ExFreePool(RomImageBuffer);
         RomImageBuffer = NULL;
      }
      return NULL;
   }
   else

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?