fdo.c

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

C
591
字号
      Status = PciCreateDeviceDescriptionString(&PdoDeviceExtension->DeviceDescription, Device);
      if (!NT_SUCCESS(Status))
      {
        ErrorStatus = Status;
        ErrorOccurred = TRUE;
        break;
      }

      /* Add device location string */
      Status = PciCreateDeviceLocationString(&PdoDeviceExtension->DeviceLocation, Device);
      if (!NT_SUCCESS(Status))
      {
        ErrorStatus = Status;
        ErrorOccurred = TRUE;
        break;
      }
    }

    if (!Device->RemovePending) {
      /* Reference the physical device object. The PnP manager
         will dereference it again when it is no longer needed */
      ObReferenceObject(Device->Pdo);

      Relations->Objects[i] = Device->Pdo;

      i++;
    }

    CurrentEntry = CurrentEntry->Flink;
  }

  if (ErrorOccurred) {
    /* FIXME: Cleanup all new PDOs created in this call. Please give me SEH!!! ;-) */
    /* FIXME: Should IoAttachDeviceToDeviceStack() be undone? */
    if (PdoDeviceExtension) {
      RtlFreeUnicodeString(&PdoDeviceExtension->DeviceID);
      RtlFreeUnicodeString(&PdoDeviceExtension->InstanceID);
      RtlFreeUnicodeString(&PdoDeviceExtension->HardwareIDs);
      RtlFreeUnicodeString(&PdoDeviceExtension->CompatibleIDs);
      RtlFreeUnicodeString(&PdoDeviceExtension->DeviceDescription);
      RtlFreeUnicodeString(&PdoDeviceExtension->DeviceLocation);
    }

    ExFreePool(Relations);
    return ErrorStatus;
  }

  Irp->IoStatus.Information = (ULONG_PTR)Relations;

  DPRINT("Done\n");

  return Status;
}


static NTSTATUS
FdoStartDevice(
  IN PDEVICE_OBJECT DeviceObject,
  IN PIRP Irp)
{
  PFDO_DEVICE_EXTENSION DeviceExtension;
  PCM_RESOURCE_LIST AllocatedResources;
  PCM_PARTIAL_RESOURCE_DESCRIPTOR ResourceDescriptor;
  ULONG FoundBusNumber = FALSE;
  ULONG i;

  DPRINT("Called\n");

  DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
  
  AllocatedResources = IoGetCurrentIrpStackLocation(Irp)->Parameters.StartDevice.AllocatedResources;
  if (!AllocatedResources)
  {
    DPRINT("No allocated resources sent to driver\n");
    return STATUS_INSUFFICIENT_RESOURCES;
  }
  if (AllocatedResources->Count < 1)
  {
    DPRINT("Not enough allocated resources sent to driver\n");
    return STATUS_INSUFFICIENT_RESOURCES;
  }
  if (AllocatedResources->List[0].PartialResourceList.Version != 1
    || AllocatedResources->List[0].PartialResourceList.Revision != 1)
    return STATUS_REVISION_MISMATCH;

  ASSERT(DeviceExtension->State == dsStopped);

  for (i = 0; i < AllocatedResources->List[0].PartialResourceList.Count; i++)
  {
    ResourceDescriptor = &AllocatedResources->List[0].PartialResourceList.PartialDescriptors[i];
    switch (ResourceDescriptor->Type)
    {
      case CmResourceTypeBusNumber:
      {
        if (FoundBusNumber || ResourceDescriptor->u.BusNumber.Length != 1)
          return STATUS_INVALID_PARAMETER;
        DeviceExtension->BusNumber = ResourceDescriptor->u.BusNumber.Start;
        DPRINT("Found bus number resource: %lu\n", DeviceExtension->BusNumber);
        FoundBusNumber = TRUE;
        break;
      }
      default:
        DPRINT1("Unknown resource descriptor type 0x%x\n", ResourceDescriptor->Type);
    }
  }
  if (!FoundBusNumber)
  {
    DPRINT("Some required resources were not found in allocated resources list\n");
    return STATUS_INSUFFICIENT_RESOURCES;
  }

  InitializeListHead(&DeviceExtension->DeviceListHead);
  KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
  DeviceExtension->DeviceListCount = 0;
  DeviceExtension->State = dsStarted;

  ExInterlockedInsertTailList(
    &DriverExtension->BusListHead,
    &DeviceExtension->ListEntry,
    &DriverExtension->BusListLock);

  Irp->IoStatus.Information = 0;

  return STATUS_SUCCESS;
}


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

  DPRINT("Called\n");

  DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  if (IrpSp->Parameters.Power.Type == DevicePowerState) {
    /* FIXME: Set device power state for the device */
    Status = STATUS_UNSUCCESSFUL;
  } else {
    Status = STATUS_UNSUCCESSFUL;
  }

  return Status;
}


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

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

  DPRINT("Called\n");

  DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;

  IrpSp = IoGetCurrentIrpStackLocation(Irp);
  switch (IrpSp->MinorFunction) {
#if 0
  case IRP_MN_CANCEL_REMOVE_DEVICE:
    Status = STATUS_NOT_IMPLEMENTED;
    break;

  case IRP_MN_CANCEL_STOP_DEVICE:
    Status = STATUS_NOT_IMPLEMENTED;
    break;

  case IRP_MN_DEVICE_USAGE_NOTIFICATION:
    Status = STATUS_NOT_IMPLEMENTED;
    break;

  case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
    Status = STATUS_NOT_IMPLEMENTED;
    break;
#endif
  case IRP_MN_QUERY_DEVICE_RELATIONS:
    Status = FdoQueryBusRelations(DeviceObject, Irp, IrpSp);
    break;
#if 0
  case IRP_MN_QUERY_PNP_DEVICE_STATE:
    Status = STATUS_NOT_IMPLEMENTED;
    break;

  case IRP_MN_QUERY_REMOVE_DEVICE:
    Status = STATUS_NOT_IMPLEMENTED;
    break;

  case IRP_MN_QUERY_STOP_DEVICE:
    Status = STATUS_NOT_IMPLEMENTED;
    break;

  case IRP_MN_REMOVE_DEVICE:
    Status = STATUS_NOT_IMPLEMENTED;
    break;
#endif
  case IRP_MN_START_DEVICE:
    DPRINT("IRP_MN_START_DEVICE received\n");
    Status = FdoStartDevice(DeviceObject, Irp);
    break;
  case IRP_MN_STOP_DEVICE:
    /* Currently not supported */
    Status = STATUS_UNSUCCESSFUL;
    break;
#if 0
  case IRP_MN_SURPRISE_REMOVAL:
    Status = STATUS_NOT_IMPLEMENTED;
    break;
#endif
  default:
    DPRINT1("Unknown IOCTL 0x%lx\n", IrpSp->MinorFunction);

    /*
     * Do NOT complete the IRP as it will be processed by the lower
     * device object, which will complete the IRP
     */
    IoSkipCurrentIrpStackLocation(Irp);
    Status = IoCallDriver(DeviceExtension->Ldo, Irp);
    return Status;
    break;
  }


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

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

  return Status;
}


NTSTATUS
FdoPowerControl(
  PDEVICE_OBJECT DeviceObject,
  PIRP Irp)
/*
 * FUNCTION: Handle power management IRPs for the PCI device object
 * ARGUMENTS:
 *     DeviceObject = Pointer to functional device object of the PCI driver
 *     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 = FdoSetPower(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 + =
减小字号Ctrl + -
显示快捷键?