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

📄 pdo.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
                              Length);
  return Size;
}


static BOOLEAN NTAPI
InterfacePciDevicePresent(
  IN USHORT VendorID,
  IN USHORT DeviceID,
  IN UCHAR RevisionID,
  IN USHORT SubVendorID,
  IN USHORT SubSystemID,
  IN ULONG Flags)
{
  PFDO_DEVICE_EXTENSION FdoDeviceExtension;
  PPCI_DEVICE PciDevice;
  PLIST_ENTRY CurrentBus, CurrentEntry;
  KIRQL OldIrql;
  BOOLEAN Found = FALSE;

  KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
  CurrentBus = DriverExtension->BusListHead.Flink;
  while (!Found && CurrentBus != &DriverExtension->BusListHead)
  {
    FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);

    KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
    CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
    while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
    {
      PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);
      if (PciDevice->PciConfig.VendorID == VendorID &&
        PciDevice->PciConfig.DeviceID == DeviceID)
      {
        if (!(Flags & PCI_USE_SUBSYSTEM_IDS) || (
          PciDevice->PciConfig.u.type0.SubVendorID == SubVendorID &&
          PciDevice->PciConfig.u.type0.SubSystemID == SubSystemID))
        {
          if (!(Flags & PCI_USE_REVISION) ||
            PciDevice->PciConfig.RevisionID == RevisionID)
          {
            DPRINT("Found the PCI device\n");
            Found = TRUE;
          }
        }
      }

      CurrentEntry = CurrentEntry->Flink;
    }

    KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
    CurrentBus = CurrentBus->Flink;
  }
  KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);

  return Found;
}


static BOOLEAN
CheckPciDevice(
  IN PPCI_COMMON_CONFIG PciConfig,
  IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
{
  if ((Parameters->Flags & PCI_USE_VENDEV_IDS) && (
    PciConfig->VendorID != Parameters->VendorID ||
    PciConfig->DeviceID != Parameters->DeviceID))
  {
    return FALSE;
  }
  if ((Parameters->Flags & PCI_USE_CLASS_SUBCLASS) && (
    PciConfig->BaseClass != Parameters->BaseClass ||
    PciConfig->SubClass != Parameters->SubClass))
  {
    return FALSE;
  }
  if ((Parameters->Flags & PCI_USE_PROGIF) &&
    PciConfig->ProgIf != Parameters->ProgIf)
  {
    return FALSE;
  }
  if ((Parameters->Flags & PCI_USE_SUBSYSTEM_IDS) && (
    PciConfig->u.type0.SubVendorID != Parameters->SubVendorID ||
    PciConfig->u.type0.SubSystemID != Parameters->SubSystemID))
  {
    return FALSE;
  }
  if ((Parameters->Flags & PCI_USE_REVISION) &&
    PciConfig->RevisionID != Parameters->RevisionID)
  {
    return FALSE;
  }
  return TRUE;
}


static BOOLEAN NTAPI
InterfacePciDevicePresentEx(
  IN PVOID Context,
  IN PPCI_DEVICE_PRESENCE_PARAMETERS Parameters)
{
  PPDO_DEVICE_EXTENSION DeviceExtension;
  PFDO_DEVICE_EXTENSION MyFdoDeviceExtension;
  PFDO_DEVICE_EXTENSION FdoDeviceExtension;
  PPCI_DEVICE PciDevice;
  PLIST_ENTRY CurrentBus, CurrentEntry;
  KIRQL OldIrql;
  BOOLEAN Found = FALSE;

  DPRINT("InterfacePciDevicePresentEx(%p %p) called\n",
    Context, Parameters);

  if (!Parameters || Parameters->Size != sizeof(PCI_DEVICE_PRESENCE_PARAMETERS))
    return FALSE;

  DeviceExtension = (PPDO_DEVICE_EXTENSION)((PDEVICE_OBJECT)Context)->DeviceExtension;
  MyFdoDeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceExtension->Fdo->DeviceExtension;

  if (Parameters->Flags & PCI_USE_LOCAL_DEVICE)
  {
    return CheckPciDevice(&DeviceExtension->PciDevice->PciConfig, Parameters);
  }

  KeAcquireSpinLock(&DriverExtension->BusListLock, &OldIrql);
  CurrentBus = DriverExtension->BusListHead.Flink;
  while (!Found && CurrentBus != &DriverExtension->BusListHead)
  {
    FdoDeviceExtension = CONTAINING_RECORD(CurrentBus, FDO_DEVICE_EXTENSION, ListEntry);
    if (!(Parameters->Flags & PCI_USE_LOCAL_BUS) || FdoDeviceExtension == MyFdoDeviceExtension)
    {
      KeAcquireSpinLockAtDpcLevel(&FdoDeviceExtension->DeviceListLock);
      CurrentEntry = FdoDeviceExtension->DeviceListHead.Flink;
      while (!Found && CurrentEntry != &FdoDeviceExtension->DeviceListHead)
      {
        PciDevice = CONTAINING_RECORD(CurrentEntry, PCI_DEVICE, ListEntry);

        if (CheckPciDevice(&PciDevice->PciConfig, Parameters))
        {
          DPRINT("Found the PCI device\n");
          Found = TRUE;
        }

        CurrentEntry = CurrentEntry->Flink;
      }

      KeReleaseSpinLockFromDpcLevel(&FdoDeviceExtension->DeviceListLock);
    }
    CurrentBus = CurrentBus->Flink;
  }
  KeReleaseSpinLock(&DriverExtension->BusListLock, OldIrql);

  return Found;
}


static NTSTATUS
PdoQueryInterface(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  NTSTATUS Status;

  if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
    &GUID_BUS_INTERFACE_STANDARD, sizeof(GUID)) == sizeof(GUID))
  {
    /* BUS_INTERFACE_STANDARD */
    if (IrpSp->Parameters.QueryInterface.Version < 1)
      Status = STATUS_NOT_SUPPORTED;
    else if (IrpSp->Parameters.QueryInterface.Size < sizeof(BUS_INTERFACE_STANDARD))
      Status = STATUS_BUFFER_TOO_SMALL;
    else
    {
      PBUS_INTERFACE_STANDARD BusInterface;
      BusInterface = (PBUS_INTERFACE_STANDARD)IrpSp->Parameters.QueryInterface.Interface;
      BusInterface->Size = sizeof(BUS_INTERFACE_STANDARD);
      BusInterface->Version = 1;
      BusInterface->TranslateBusAddress = InterfaceBusTranslateBusAddress;
      BusInterface->GetDmaAdapter = InterfaceBusGetDmaAdapter;
      BusInterface->SetBusData = InterfaceBusSetBusData;
      BusInterface->GetBusData = InterfaceBusGetBusData;
      Status = STATUS_SUCCESS;
    }
  }
  else if (RtlCompareMemory(IrpSp->Parameters.QueryInterface.InterfaceType,
    &GUID_PCI_DEVICE_PRESENT_INTERFACE, sizeof(GUID)) == sizeof(GUID))
  {
    /* PCI_DEVICE_PRESENT_INTERFACE */
    if (IrpSp->Parameters.QueryInterface.Version < 1)
      Status = STATUS_NOT_SUPPORTED;
    else if (IrpSp->Parameters.QueryInterface.Size < sizeof(PCI_DEVICE_PRESENT_INTERFACE))
      Status = STATUS_BUFFER_TOO_SMALL;
    else
    {
      PPCI_DEVICE_PRESENT_INTERFACE PciDevicePresentInterface;
      PciDevicePresentInterface = (PPCI_DEVICE_PRESENT_INTERFACE)IrpSp->Parameters.QueryInterface.Interface;
      PciDevicePresentInterface->Size = sizeof(PCI_DEVICE_PRESENT_INTERFACE);
      PciDevicePresentInterface->Version = 1;
      PciDevicePresentInterface->IsDevicePresent = InterfacePciDevicePresent;
      PciDevicePresentInterface->IsDevicePresentEx = InterfacePciDevicePresentEx;
      Status = STATUS_SUCCESS;
    }
  }
  else
  {
    /* Not a supported interface */
    return STATUS_NOT_SUPPORTED;
  }

  if (NT_SUCCESS(Status))
  {
    /* Add a reference for the returned interface */
    PINTERFACE Interface;
    Interface = (PINTERFACE)IrpSp->Parameters.QueryInterface.Interface;
    Interface->Context = DeviceObject;
    Interface->InterfaceReference = InterfaceReference;
    Interface->InterfaceDereference = InterfaceDereference;
    Interface->InterfaceReference(Interface->Context);
  }

  return Status;
}


static NTSTATUS
PdoReadConfig(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  ULONG Size;

  DPRINT("PdoReadConfig() called\n");

  Size = InterfaceBusGetBusData(
    DeviceObject,
    IrpSp->Parameters.ReadWriteConfig.WhichSpace,
    IrpSp->Parameters.ReadWriteConfig.Buffer,
    IrpSp->Parameters.ReadWriteConfig.Offset,
    IrpSp->Parameters.ReadWriteConfig.Length);

  if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
  {
    DPRINT1("Size %lu  Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
    Irp->IoStatus.Information = 0;
    return STATUS_UNSUCCESSFUL;
  }

  Irp->IoStatus.Information = Size;

  return STATUS_SUCCESS;
}


static NTSTATUS
PdoWriteConfig(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  ULONG Size;

  DPRINT1("PdoWriteConfig() called\n");

  /* Get PCI configuration space */
  Size = InterfaceBusSetBusData(
    DeviceObject,
    IrpSp->Parameters.ReadWriteConfig.WhichSpace,
    IrpSp->Parameters.ReadWriteConfig.Buffer,
    IrpSp->Parameters.ReadWriteConfig.Offset,
    IrpSp->Parameters.ReadWriteConfig.Length);

  if (Size != IrpSp->Parameters.ReadWriteConfig.Length)
  {
    DPRINT1("Size %lu  Length %lu\n", Size, IrpSp->Parameters.ReadWriteConfig.Length);
    Irp->IoStatus.Information = 0;
    return STATUS_UNSUCCESSFUL;
  }

  Irp->IoStatus.Information = Size;

  return STATUS_SUCCESS;
}


static NTSTATUS
PdoSetPower(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp,
  PIO_STACK_LOCATION IrpSp)
{
  PPDO_DEVICE_EXTENSION DeviceExtension;
  NTSTATUS Status;

  DPRINT("Called\n");

  DeviceExtension = (PPDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  if (IrpSp->Parameters.Power.Type == DevicePowerState) {
    Status = STATUS_SUCCESS;
    switch (IrpSp->Parameters.Power.State.SystemState) {
    default:
      Status = STATUS_UNSUCCESSFUL;
    }
  } else {
    Status = STATUS_UNSUCCESSFUL;
  }

  return Status;
}


/*** PUBLIC ******************************************************************/

NTSTATUS
PdoPnpControl(
  PDEVICE_OBJECT DeviceObject,
  PIRP Irp)
/*
 * 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
 */
{
  PIO_STACK_LOCATION IrpSp;
  NTSTATUS Status;

  DPRINT("Called\n");

  Status = Irp->IoStatus.Status;

  IrpSp = IoGetCurrentIrpStackLocation(Irp);

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

  case IRP_MN_EJECT:
    break;
#endif

  case IRP_MN_QUERY_BUS_INFORMATION:
    Status = PdoQueryBusInformation(DeviceObject, Irp, IrpSp);
    break;

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

#if 0
  case IRP_MN_QUERY_DEVICE_RELATIONS:
    /* FIXME: Possibly handle for RemovalRelations */
    break;
#endif

  case IRP_MN_QUERY_DEVICE_TEXT:
    DPRINT("IRP_MN_QUERY_DEVICE_TEXT received\n");
    Status = PdoQueryDeviceText(DeviceObject, Irp, IrpSp);
    break;

  case IRP_MN_QUERY_ID:
    DPRINT("IRP_MN_QUERY_ID received\n");
    Status = PdoQueryId(DeviceObject, Irp, IrpSp);
    break;

#if 0
  case IRP_MN_QUERY_PNP_DEVICE_STATE:
    break;
#endif

  case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
    DPRINT("IRP_MN_QUERY_RESOURCE_REQUIREMENTS received\n");
    Status = PdoQueryResourceRequirements(DeviceObject, Irp, IrpSp);
    break;

  case IRP_MN_QUERY_RESOURCES:
    DPRINT("IRP_MN_QUERY_RESOURCES received\n");
    Status = PdoQueryResources(DeviceObject, Irp, IrpSp);
    break;

#if 0
  case IRP_MN_SET_LOCK:
    break;
#endif

  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;

  case IRP_MN_QUERY_INTERFACE:
    DPRINT("IRP_MN_QUERY_INTERFACE received\n");
    Status = PdoQueryInterface(DeviceObject, Irp, IrpSp);
    break;

  case IRP_MN_READ_CONFIG:
    DPRINT("IRP_MN_READ_CONFIG received\n");
    Status = PdoReadConfig(DeviceObject, Irp, IrpSp);
    break;

  case IRP_MN_WRITE_CONFIG:
    DPRINT("IRP_MN_WRITE_CONFIG received\n");
    Status = PdoWriteConfig(DeviceObject, Irp, IrpSp);
    break;

  case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
    DPRINT("IRP_MN_FILTER_RESOURCE_REQUIREMENTS received\n");
    /* Nothing to do */
    Irp->IoStatus.Status = Status;
    break;

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

  if (Status != STATUS_PENDING) {
    Irp->IoStatus.Status = Status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
  }

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

  return Status;
}

NTSTATUS
PdoPowerControl(
  PDEVICE_OBJECT DeviceObject,
  PIRP Irp)
/*
 * 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
 */
{
  PIO_STACK_LOCATION IrpSp;
  NTSTATUS Status;

  DPRINT("Called\n");

  IrpSp = IoGetCurrentIrpStackLocation(Irp);

  switch (IrpSp->MinorFunction) {
  case IRP_MN_SET_POWER:
    Status = PdoSetPower(DeviceObject, Irp, IrpSp);
    break;

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

  if (Status != STATUS_PENDING) {
    Irp->IoStatus.Status = Status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
  }

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

  return Status;
}

/* EOF */

⌨️ 快捷键说明

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