zl程序教程

您现在的位置是:首页 >  系统

当前栏目

reactos操作系统实现(77)

操作系统 实现 reactos 77
2023-09-14 09:10:38 时间

因为PC里一条总线上可以连接很多设备,就像一棵树一样,需要遍历所有总线上所有子设备,并且为每一个子设备安装相应的驱动程序,下面这个函数,实现枚举所有子设备,实现代码如下:

#001  NTSTATUS

#002  IopEnumerateDevice(

#003      IN PDEVICE_OBJECT DeviceObject)

#004  {

 

获取设备的节点。

#005      PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);

#006      DEVICETREE_TRAVERSE_CONTEXT Context;

#007      PDEVICE_RELATIONS DeviceRelations;

#008      PDEVICE_OBJECT ChildDeviceObject;

#009      IO_STATUS_BLOCK IoStatusBlock;

#010      PDEVICE_NODE ChildDeviceNode;

#011      IO_STACK_LOCATION Stack;

#012      NTSTATUS Status;

#013      ULONG i;

#014 

#015      DPRINT("DeviceObject 0x%p/n", DeviceObject);

#016 

#017      DPRINT("Sending GUID_DEVICE_ARRIVAL/n");

#018 

 

报告这个设备到用户模式的即插即用管理器。

#019      /* Report the device to the user-mode pnp manager */

#020      IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL,

#021                                &DeviceNode->InstancePath);

#022 

#023      DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack/n");

#024 

#025      Stack.Parameters.QueryDeviceRelations.Type = BusRelations;

#026 

 

发送查询设备之间相互关系。

#027      Status = IopInitiatePnpIrp(

#028          DeviceObject,

#029          &IoStatusBlock,

#030          IRP_MN_QUERY_DEVICE_RELATIONS,

#031          &Stack);

#032      if (!NT_SUCCESS(Status) || Status == STATUS_PENDING)

#033      {

#034          DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx/n", Status);

#035          return Status;

#036      }

#037 

 

获取设备相互关系。

#038      DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;

#039 

#040      if (!DeviceRelations)

#041      {

#042          DPRINT("No PDOs/n");

#043          return STATUS_UNSUCCESSFUL;

#044      }

#045 

#046      DPRINT("Got %u PDOs/n", DeviceRelations->Count);

#047 

 

创建所有这个根设备下面的子设备。

#048      /*

#049       * Create device nodes for all discovered devices

#050       */

#051      for (i = 0; i < DeviceRelations->Count; i++)

#052      {

#053          ChildDeviceObject = DeviceRelations->Objects[i];

#054          ASSERT((ChildDeviceObject->Flags & DO_DEVICE_INITIALIZING) == 0);

#055 

 

获取子设备节点是否存在。

#056          ChildDeviceNode = IopGetDeviceNode(ChildDeviceObject);

#057          if (!ChildDeviceNode)

#058          {

 

如果不存在,就创建这个子设备节点。

#059              /* One doesn't exist, create it */

#060              Status = IopCreateDeviceNode(

#061                  DeviceNode,

#062                  ChildDeviceObject,

#063                  NULL,

#064                  &ChildDeviceNode);

#065              if (NT_SUCCESS(Status))

#066              {

#067                  /* Mark the node as enumerated */

#068                  ChildDeviceNode->Flags |= DNF_ENUMERATED;

#069 

#070                  /* Mark the DO as bus enumerated */

#071                  ChildDeviceObject->Flags |= DO_BUS_ENUMERATED_DEVICE;

#072              }

#073              else

#074              {

#075                  /* Ignore this DO */

#076                  DPRINT1("IopCreateDeviceNode() failed with status 0x%08x. Skipping PDO %u/n", Status, i);

#077                  ObDereferenceObject(ChildDeviceNode);

#078              }

#079          }

#080          else

#081          {

#082              /* Mark it as enumerated */

#083              ChildDeviceNode->Flags |= DNF_ENUMERATED;

#084              ObDereferenceObject(ChildDeviceObject);

#085          }

#086      }

#087      ExFreePool(DeviceRelations);

#088 

 

获取这个总线驱动程序上所有设备。

#089      /*

#090       * Retrieve information about all discovered children from the bus driver

#091       */

#092      IopInitDeviceTreeTraverseContext(

#093          &Context,

#094          DeviceNode,

#095          IopActionInterrogateDeviceStack,

#096          DeviceNode);

#097 

#098      Status = IopTraverseDeviceTree(&Context);

#099      if (!NT_SUCCESS(Status))

#100      {

#101          DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx/n", Status);

#102          return Status;

#103      }

#104 

 

获取这个总线驱动程序上所有注册表里的信息。

#105      /*

#106       * Retrieve configuration from the registry for discovered children

#107       */

#108      IopInitDeviceTreeTraverseContext(

#109          &Context,

#110          DeviceNode,

#111          IopActionConfigureChildServices,

#112          DeviceNode);

#113 

#114      Status = IopTraverseDeviceTree(&Context);

#115      if (!NT_SUCCESS(Status))

#116      {

#117          DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx/n", Status);

#118          return Status;

#119      }

#120 

 

初始化所有发现的PnP设备驱动程序。

#121      /*

#122       * Initialize services for discovered children.

#123       */

#124      Status = IopInitializePnpServices(DeviceNode);

#125      if (!NT_SUCCESS(Status))

#126      {

#127          DPRINT("IopInitializePnpServices() failed with status 0x%08lx/n", Status);

#128          return Status;

#129      }

#130 

#131      DPRINT("IopEnumerateDevice() finished/n");

#132      return STATUS_SUCCESS;

#133  }

#134