首页 >> 编程开发 >> 其他 >> 正文

reactos操作系统实现(77)

  因为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