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

📄 pnproot.c

📁 winNT技术操作系统,国外开放的原代码和LIUX一样
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
 * COPYRIGHT:       See COPYING in the top level directory
 * PROJECT:         ReactOS kernel
 * FILE:            ntoskrnl/io/pnproot.c
 * PURPOSE:         PnP manager root device
 *
 * PROGRAMMERS:     Casper S. Hornstrup (chorns@users.sourceforge.net)
 */

/* INCLUDES ******************************************************************/

#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>

/* GLOBALS *******************************************************************/

#define ENUM_NAME_ROOT L"Root"

/* DATA **********************************************************************/

typedef struct _PNPROOT_DEVICE
{
  // Entry on device list
  LIST_ENTRY ListEntry;
  // Physical Device Object of device
  PDEVICE_OBJECT Pdo;
  // Service name
  UNICODE_STRING ServiceName;
  // Device ID
  UNICODE_STRING DeviceID;
  // Instance ID
  UNICODE_STRING InstanceID;
  // Device description
  UNICODE_STRING DeviceDescription;
  // Boot resource list
  PCM_FULL_RESOURCE_DESCRIPTOR BootResourceList;
  SIZE_T BootResourceListSize;
  // Resource requirement list
  PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirementsList;
} PNPROOT_DEVICE, *PPNPROOT_DEVICE;

typedef enum
{
  dsStopped,
  dsStarted,
  dsPaused,
  dsRemoved,
  dsSurpriseRemoved
} PNPROOT_DEVICE_STATE;


#include <pshpack1.h>

typedef struct _PNPROOT_COMMON_DEVICE_EXTENSION
{
  // Pointer to device object, this device extension is associated with
  PDEVICE_OBJECT DeviceObject;
  // Wether this device extension is for an FDO or PDO
  BOOLEAN IsFDO;
  // Wether the device is removed
  BOOLEAN Removed;
  // Current device power state for the device
  DEVICE_POWER_STATE DevicePowerState;
} PNPROOT_COMMON_DEVICE_EXTENSION, *PPNPROOT_COMMON_DEVICE_EXTENSION;


/* Physical Device Object device extension for a child device */
typedef struct _PNPROOT_PDO_DEVICE_EXTENSION
{
  // Common device data
  PNPROOT_COMMON_DEVICE_EXTENSION Common;
  // Device
  PPNPROOT_DEVICE Device;
} PNPROOT_PDO_DEVICE_EXTENSION, *PPNPROOT_PDO_DEVICE_EXTENSION;


/* Functional Device Object device extension for the PCI driver device object */
typedef struct _PNPROOT_FDO_DEVICE_EXTENSION
{
  // Common device data
  PNPROOT_COMMON_DEVICE_EXTENSION Common;
  // Physical Device Object
  PDEVICE_OBJECT Pdo;
  // Lower device object
  PDEVICE_OBJECT Ldo;
  // Current state of the driver
  PNPROOT_DEVICE_STATE State;
  // Namespace device list
  LIST_ENTRY DeviceListHead;
  // Number of (not removed) devices in device list
  ULONG DeviceListCount;
  // Lock for namespace device list
  // FIXME: Use fast mutex instead?
  KSPIN_LOCK DeviceListLock;
} PNPROOT_FDO_DEVICE_EXTENSION, *PPNPROOT_FDO_DEVICE_EXTENSION;

#include <poppack.h>



PDEVICE_OBJECT PnpRootDeviceObject;


/* FUNCTIONS *****************************************************************/

/* Physical Device Object routines */

NTSTATUS
PnpRootCreateDevice(
  PDEVICE_OBJECT *PhysicalDeviceObject)
{
  PPNPROOT_PDO_DEVICE_EXTENSION PdoDeviceExtension;
  PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
  PPNPROOT_DEVICE Device;
  NTSTATUS Status;

  /* This function should be obsoleted soon */

  DPRINT("Called\n");

  DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)PnpRootDeviceObject->DeviceExtension;

  Device = (PPNPROOT_DEVICE)ExAllocatePoolWithTag(PagedPool, sizeof(PNPROOT_DEVICE), TAG_PNP_ROOT);
  if (!Device)
    return STATUS_INSUFFICIENT_RESOURCES;

  RtlZeroMemory(Device, sizeof(PNPROOT_DEVICE));

  Status = IoCreateDevice(
    PnpRootDeviceObject->DriverObject,
    sizeof(PNPROOT_PDO_DEVICE_EXTENSION),
    NULL,
    FILE_DEVICE_CONTROLLER,
    FILE_AUTOGENERATED_DEVICE_NAME,
    FALSE,
    &Device->Pdo);
  if (!NT_SUCCESS(Status)) {
    DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
    ExFreePool(Device);
    return Status;
  }

  Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;

  Device->Pdo->Flags &= ~DO_DEVICE_INITIALIZING;

  //Device->Pdo->Flags |= DO_POWER_PAGABLE;

  PdoDeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)Device->Pdo->DeviceExtension;

  RtlZeroMemory(PdoDeviceExtension, sizeof(PNPROOT_PDO_DEVICE_EXTENSION));

  PdoDeviceExtension->Common.IsFDO = FALSE;

  PdoDeviceExtension->Common.DeviceObject = Device->Pdo;

  PdoDeviceExtension->Common.DevicePowerState = PowerDeviceD0;

  ExInterlockedInsertTailList(
    &DeviceExtension->DeviceListHead,
    &Device->ListEntry,
    &DeviceExtension->DeviceListLock);

  DeviceExtension->DeviceListCount++;

  *PhysicalDeviceObject = Device->Pdo;

  return STATUS_SUCCESS;
}


NTSTATUS
PdoQueryId(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
  UNICODE_STRING String;
  NTSTATUS Status;

  DPRINT("Called\n");

  DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

//  Irp->IoStatus.Information = 0;

  Status = STATUS_SUCCESS;

  RtlInitUnicodeString(&String, NULL);

  switch (IrpSp->Parameters.QueryId.IdType) {
    case BusQueryDeviceID:
      if (DeviceExtension->Device)
        Status = RtlDuplicateUnicodeString(TRUE,
                                         &DeviceExtension->Device->DeviceID,
                                         &String);
      else
        Status = RtlCreateUnicodeString(&String, ENUM_NAME_ROOT L"\\LEGACY_UNKNOWN");

      DPRINT("DeviceID: %wZ\n", &String);

      Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
      break;

    case BusQueryHardwareIDs:
    case BusQueryCompatibleIDs:
      Status = STATUS_NOT_IMPLEMENTED;
      break;

    case BusQueryInstanceID:
      if (DeviceExtension->Device)
        Status = RtlDuplicateUnicodeString(TRUE,
                                         &DeviceExtension->Device->InstanceID,
                                         &String);
      else
        Status = RtlCreateUnicodeString(&String, L"0000");

      DPRINT("InstanceID: %S\n", String.Buffer);

      Irp->IoStatus.Information = (ULONG_PTR)String.Buffer;
      break;

    case BusQueryDeviceSerialNumber:
    default:
      Status = STATUS_NOT_IMPLEMENTED;
  }

  return Status;
}


NTSTATUS
PdoQueryResources(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
  PCM_RESOURCE_LIST ResourceList;
  ULONG ResourceListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List);

  DPRINT("Called\n");

  DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  
  if (!DeviceExtension->Device || DeviceExtension->Device->BootResourceList == NULL)
  {
    /* Create an empty resource list */
    ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
    if (ResourceList == NULL)
      return STATUS_INSUFFICIENT_RESOURCES;

    ResourceList->Count = 0;

    Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
  }
  else
  {
    /* Copy existing resource list */
    ResourceList = ExAllocatePool(PagedPool,
      FIELD_OFFSET(CM_RESOURCE_LIST, List) +  DeviceExtension->Device->BootResourceListSize);
    if (ResourceList == NULL)
      return STATUS_INSUFFICIENT_RESOURCES;

    ResourceList->Count = 1;
    RtlCopyMemory(
      &ResourceList->List,
      DeviceExtension->Device->BootResourceList,
      DeviceExtension->Device->BootResourceListSize);
    Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
  }

  return STATUS_SUCCESS;
}


NTSTATUS
PdoQueryResourceRequirements(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PPNPROOT_PDO_DEVICE_EXTENSION DeviceExtension;
  PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
  ULONG ResourceListSize = FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List);

  DPRINT("Called\n");

  DeviceExtension = (PPNPROOT_PDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  
  if (!DeviceExtension->Device || DeviceExtension->Device->ResourceRequirementsList == NULL)
  {
    /* Create an empty resource list */
    ResourceList = ExAllocatePool(PagedPool, ResourceListSize);
    if (ResourceList == NULL)
      return STATUS_INSUFFICIENT_RESOURCES;

    RtlZeroMemory(ResourceList, ResourceListSize);
    ResourceList->ListSize = ResourceListSize;

    Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
  }
  else
  {
    /* Copy existing resource requirement list */
    ResourceList = ExAllocatePool(PagedPool, DeviceExtension->Device->ResourceRequirementsList->ListSize);
    if (ResourceList == NULL)
      return STATUS_INSUFFICIENT_RESOURCES;

    RtlCopyMemory(
      ResourceList,
      DeviceExtension->Device->ResourceRequirementsList,
      DeviceExtension->Device->ResourceRequirementsList->ListSize);
    Irp->IoStatus.Information = (ULONG_PTR)ResourceList;
  }

  return STATUS_SUCCESS;
}


static NTSTATUS
PnpRootPdoQueryCapabilities(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PPNPROOT_FDO_DEVICE_EXTENSION DeviceExtension;
  PDEVICE_CAPABILITIES DeviceCapabilities;

  DPRINT("Called\n");

  DeviceExtension = (PPNPROOT_FDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  DeviceCapabilities = IrpSp->Parameters.DeviceCapabilities.Capabilities;

  if (DeviceCapabilities->Version != 1)
    return STATUS_UNSUCCESSFUL;

  DeviceCapabilities->UniqueID = TRUE;
  /* FIXME: Fill other fields */

  return STATUS_SUCCESS;
}


/*
 * FUNCTION: Handle Plug and Play IRPs for the child device
 * ARGUMENTS:
 *     DeviceObject = Pointer to physical device object of the child device
 *     Irp          = Pointer to IRP that should be handled
 * RETURNS:
 *     Status
 */
NTSTATUS
PnpRootPdoPnpControl(
  PDEVICE_OBJECT DeviceObject,
  PIRP Irp)
{
  PIO_STACK_LOCATION IrpSp;
  NTSTATUS Status;

  DPRINT("Called\n");

  Status = Irp->IoStatus.Status;

  IrpSp = IoGetCurrentIrpStackLocation(Irp);

  switch (IrpSp->MinorFunction) {
#if 0
  case IRP_MN_QUERY_BUS_INFORMATION:
    break;

  case IRP_MN_QUERY_DEVICE_RELATIONS:
    /* FIXME: Handle for TargetDeviceRelation */
    break;
#endif

  case IRP_MN_QUERY_ID:
    Status = PdoQueryId(DeviceObject, Irp, IrpSp);
    break;

  case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
    Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
    break;

  case IRP_MN_QUERY_RESOURCES:
    Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
    break;

  case IRP_MN_QUERY_CAPABILITIES:
    Status = PnpRootPdoQueryCapabilities(DeviceObject, Irp, IrpSp);
    break;

  case IRP_MN_START_DEVICE:
  case IRP_MN_QUERY_STOP_DEVICE:
  case IRP_MN_CANCEL_STOP_DEVICE:
  case IRP_MN_STOP_DEVICE:
  case IRP_MN_QUERY_REMOVE_DEVICE:
  case IRP_MN_CANCEL_REMOVE_DEVICE:
  case IRP_MN_REMOVE_DEVICE:
  case IRP_MN_SURPRISE_REMOVAL:
    Status = STATUS_SUCCESS;
    break;

  default:
    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
    break;
  }

  Irp->IoStatus.Status = Status;
  IoCompleteRequest(Irp, IO_NO_INCREMENT);

  DPRINT("Leaving. Status 0x%X\n", Status);

  return Status;
}


/*
 * FUNCTION: Handle power management IRPs for the child device
 * ARGUMENTS:
 *     DeviceObject = Pointer to physical device object of the child device
 *     Irp          = Pointer to IRP that should be handled
 * RETURNS:
 *     Status
 */
NTSTATUS
PnpRootPdoPowerControl(
  PDEVICE_OBJECT DeviceObject,
  PIRP Irp)
{
  PIO_STACK_LOCATION IrpSp;
  NTSTATUS Status;

  DPRINT("Called\n");

  Status = Irp->IoStatus.Status;

  IrpSp = IoGetCurrentIrpStackLocation(Irp);

  switch (IrpSp->MinorFunction) {
  default:
    DPRINT("Unknown IOCTL 0x%X\n", IrpSp->MinorFunction);
    Status = STATUS_NOT_IMPLEMENTED;
    break;
  }

  Irp->IoStatus.Status = Status;
  IoCompleteRequest(Irp, IO_NO_INCREMENT);

  DPRINT("Leaving. Status 0x%X\n", Status);

  return Status;
}


/* Functional Device Object routines */

static NTSTATUS
PnpRootReadRegistryBinary(
  IN PWSTR KeyName,
  IN PWSTR ValueKeyName,
  OUT PVOID* Buffer,
  OUT SIZE_T* BufferSize OPTIONAL)
{
  OBJECT_ATTRIBUTES ObjectAttributes;
  UNICODE_STRING KeyNameU;
  UNICODE_STRING ValueKeyNameU;
  KEY_VALUE_PARTIAL_INFORMATION Size;
  PKEY_VALUE_PARTIAL_INFORMATION Data = NULL;
  ULONG DataSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION);
  HANDLE KeyHandle;
  NTSTATUS Status;
  
  DPRINT("Called\n");
  
  RtlInitUnicodeString(&KeyNameU, KeyName);
  RtlInitUnicodeString(&ValueKeyNameU, ValueKeyName);
  
  InitializeObjectAttributes(
    &ObjectAttributes,
    &KeyNameU,
    OBJ_CASE_INSENSITIVE,
    NULL, /* Root dir */
    NULL); /* Security descriptor */
  Status = ZwOpenKey(&KeyHandle, KEY_READ, &ObjectAttributes);
  if (!NT_SUCCESS(Status))
  {
    DPRINT("ZwOpenKey() failed (Status 0x%08lx)\n", Status);
    return Status;
  }
  
  Status = ZwQueryValueKey(
    KeyHandle,
    &ValueKeyNameU,
    KeyValuePartialInformation,
    &Size, DataSize,
    &DataSize);
  if (Status != STATUS_BUFFER_OVERFLOW)
  {
    DPRINT("ZwQueryValueKey() failed (Status 0x%08lx)\n", Status);
    ZwClose(KeyHandle);
    return Status;
  }
  
  while (Status == STATUS_BUFFER_OVERFLOW)
  {
    if (Data)
      ExFreePoolWithTag(Data, TAG_PNP_ROOT);
    Data = (PKEY_VALUE_PARTIAL_INFORMATION)ExAllocatePoolWithTag(PagedPool, DataSize, TAG_PNP_ROOT);
    if (!Data)
    {
      DPRINT("ExAllocatePoolWithTag() failed\n", Status);
      ZwClose(KeyHandle);
      return STATUS_NO_MEMORY;
    }
    
    Status = ZwQueryValueKey(
      KeyHandle,
      &ValueKeyNameU,
      KeyValuePartialInformation,
      Data, DataSize,
      &DataSize);
    if (NT_SUCCESS(Status))
    {
      *Buffer = ExAllocatePoolWithTag(PagedPool, Data->DataLength, TAG_PNP_ROOT);
      if (BufferSize) *BufferSize = Data->DataLength;
      if (!*Buffer)
      {
        DPRINT("ExAllocatePoolWithTag() failed\n", Status);
        ExFreePoolWithTag(Data, TAG_PNP_ROOT);
        ZwClose(KeyHandle);
        return STATUS_NO_MEMORY;
      }
      
      RtlCopyMemory(
        *Buffer,
        Data->Data,
        Data->DataLength);
      break;
    }
  }
  
  if (Data)
    ExFreePoolWithTag(Data, TAG_PNP_ROOT);
  ZwClose(KeyHandle);
  
  return Status;
}

NTSTATUS
PnpRootFdoReadDeviceInfo(
  PPNPROOT_DEVICE Device)
{
  RTL_QUERY_REGISTRY_TABLE QueryTable[2];
  PUNICODE_STRING DeviceDesc;
  WCHAR KeyName[MAX_PATH];
  NTSTATUS Status;

  DPRINT("Called\n");

  /* Retrieve configuration from Enum key */

  DeviceDesc = &Device->DeviceDescription;

  wcscpy(KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
  wcscat(KeyName, ENUM_NAME_ROOT);
  wcscat(KeyName, L"\\");
  wcscat(KeyName, Device->ServiceName.Buffer);
  wcscat(KeyName, L"\\");
  wcscat(KeyName, Device->InstanceID.Buffer);

  DPRINT("KeyName %S\n", KeyName);

  /* 1. Read informations in instance key */
  RtlZeroMemory(QueryTable, sizeof(QueryTable));

  RtlInitUnicodeString(DeviceDesc, NULL);

  QueryTable[0].Name = L"DeviceDesc";
  QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
  QueryTable[0].EntryContext = DeviceDesc;

  Status = RtlQueryRegistryValues(
    RTL_REGISTRY_ABSOLUTE | RTL_REGISTRY_OPTIONAL,
    KeyName,
    QueryTable,
    NULL,
    NULL);

  DPRINT("RtlQueryRegistryValues() returned status 0x%08lx\n", Status);

  if (!NT_SUCCESS(Status))
  {

⌨️ 快捷键说明

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