reactos操作系统实现(120)

时间:2022-06-22 20:24:07

 CreateDiskDeviceObject函数主要就是为了物理设备创建磁盘对象,并且查找磁盘上每个分区和创建相应的对象。具体实现代码如下:

#001  NTSTATUS

#002  NTAPI

#003  CreateDiskDeviceObject(

#004      IN PDRIVER_OBJECTDriverObject,

#005      IN PUNICODE_STRINGRegistryPath,

#006      IN PDEVICE_OBJECTPortDeviceObject,

#007      IN ULONG PortNumber,

#008      IN PULONG DeviceCount,

#009      IN PIO_SCSI_CAPABILITIESPortCapabilities,

#010      IN PSCSI_INQUIRY_DATALunInfo,

#011      IN PCLASS_INIT_DATAInitData

#012      )

#013 

#014  /*++

#015 

#016  Routine Description:

#017 

#018      This routine creates anobject for the physical device and then searches

#019      the device for partitionsand creates an object for each partition.

#020 

#021  Arguments:

#022 

#023      DriverObject - Pointerto driver object created by system.

#024 

#025      PortDeviceObject -Miniport device object.

#026 

#027      PortNumber   - port number.  Used in creating disk objects.

#028 

#029      DeviceCount  - Number of previously installed devices.

#030 

#031      PortCapabilities -Capabilities of this SCSI port.

#032 

#033      LunInfo      - LUN specific information.

#034 

#035  Return Value:

#036 

#037      NTSTATUS

#038 

#039  --*/

#040  {

#041      CCHAR         ntNameBuffer[MAXIMUM_FILENAME_LENGTH];

#042      STRING         ntNameString;

#043      UNICODE_STRINGntUnicodeString;

#044      OBJECT_ATTRIBUTESobjectAttributes;

#045      HANDLE         handle;

#046      NTSTATUS       status;

#047      PDEVICE_OBJECTdeviceObject = NULL;

#048      PDEVICE_OBJECTphysicalDevice;

#049      PDISK_GEOMETRYdiskGeometry = NULL;

#050      PDEVICE_EXTENSIONdeviceExtension = NULL;

#051      PDEVICE_EXTENSIONphysicalDeviceExtension;

#052      UCHAR          pathId = LunInfo->PathId;

#053      UCHAR          targetId = LunInfo->TargetId;

#054      UCHAR          lun = LunInfo->Lun;

#055      BOOLEAN        writeCache;

#056      PVOID          senseData = NULL;

#057      ULONG          srbFlags;

#058      ULONG          timeOut = 0;

#059      BOOLEAN        srbListInitialized = FALSE;

#060 

#061 

 

保证运行这些代骊是非分页代码,如果是分页代码就抛出异常。

#062      PAGED_CODE();

#063 

#064      //

#065      // Set up an objectdirectory to contain the objects for this

#066      // device and all itspartitions.

#067      //

#068 

 

创建一个设备的磁盘目录对象。

#069      sprintf(ntNameBuffer,

#070             "//Device//Harddisk%lu",

#071              *DeviceCount);

#072 

#073      RtlInitString(&ntNameString,

#074                   ntNameBuffer);

#075 

#076      status =RtlAnsiStringToUnicodeString(&ntUnicodeString,

#077                                           &ntNameString,

#078                                           TRUE);

#079 

#080      if (!NT_SUCCESS(status)) {

#081          return(status);

#082      }

#083 

#084     InitializeObjectAttributes(&objectAttributes,

#085                                &ntUnicodeString,

#086                                OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,

#087                                NULL,

#088                                NULL);

#089 

 

调用函数ZwCreateDirectoryObject在对象管理器里创建设备目录对象。

#090      status =ZwCreateDirectoryObject(&handle,

#091                                      DIRECTORY_ALL_ACCESS,

#092                                      &objectAttributes);

#093 

#094     RtlFreeUnicodeString(&ntUnicodeString);

#095 

#096      if (!NT_SUCCESS(status)){

#097 

#098          DebugPrint((1,

#099                     "CreateDiskDeviceObjects: Could not create directory %s/n",

#100                     ntNameBuffer));

#101 

#102          return(status);

#103      }

#104 

#105      //

#106      // Claim the device.

#107      //

#108 

 

从端口驱动程序里申请一个端口驱动程序对象。

#109      status = ScsiClassClaimDevice(PortDeviceObject,

#110                                   LunInfo,

#111                                   FALSE,

#112                                   &PortDeviceObject);

#113 

#114      if (!NT_SUCCESS(status)){

#115          ZwMakeTemporaryObject(handle);

#116          ZwClose(handle);

#117          return status;

#118      }

#119 

#120      //

#121      // Create a deviceobject for this device. Each physical disk will

#122      // have at least onedevice object. The required device object

#123      // describes the entiredevice. Its directory path is

#124      ///Device/HarddiskN/Partition0, where N = device number.

#125      //

#126 

 

创建每个物理分区磁盘的名称。

#127      sprintf(ntNameBuffer,

#128             "//Device//Harddisk%lu//Partition0",

#129              *DeviceCount);

#130 

#131 

 

调用函数ScsiClassCreateDeviceObject为每个物理分区创建物理设备对象,并且设备驱动程序扩展的功能处理函数。

#132      status =ScsiClassCreateDeviceObject(DriverObject,

#133                                          ntNameBuffer,

#134                                           NULL,

#135                                          &deviceObject,

#136                                          InitData);

#137 

#138      if (!NT_SUCCESS(status)){

#139 

#140          DebugPrint((1,

#141                      "CreateDiskDeviceObjects: Can notcreate device object %s/n",

#142                     ntNameBuffer));

#143 

#144          gotoCreateDiskDeviceObjectsExit;

#145      }

#146 

#147      //

#148      // Indicate that IRPsshould include MDLs for data transfers.

#149      //

#150 

 

指明这个物理设备对象是直接IO缓冲区的访问方式。

#151      deviceObject->Flags|= DO_DIRECT_IO;

#152 

#153      //

#154      // Check if this isduring initialization. If not indicate that

#155      // system initializationalready took place and this disk is ready

#156      // to be accessed.

#157      //

#158 

 

如果这个物理设备没有在注册表里,说明它是没有被初始化的。

#159      if (!RegistryPath) {

#160         deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

#161      }

#162 

#163      //

#164      // Check for removable mediasupport.

#165      //

#166 

 

从端口驱动程序里查找到这个物理设备是可移动的设备,那么就设置为可移动的文件媒体。

#167      if(((PINQUIRYDATA)LunInfo->InquiryData)->RemovableMedia) {

#168         deviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;

#169      }

#170 

#171      //

#172      // Set up required stack size in deviceobject.

#173      //

#174 

 

设置设备栈的大小。

#175     deviceObject->StackSize = (CCHAR)PortDeviceObject->StackSize + 1;

#176 

 

获取设备驱动对象扩展。

#177      deviceExtension =deviceObject->DeviceExtension;

#178 

#179      //

#180      // Allocate spinlock forsplit request completion.

#181      //

#182 

 

分配共享请求的自旋锁。

#183     KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);

#184 

#185      //

#186      // Initialize lock countto zero. The lock count is used to

#187      // disable the ejectionmechanism on devices that support

#188      // removable media. Onlythe lock count in the physical

#189      // device extension isused.

#190      //

#191 

#192     deviceExtension->LockCount = 0;

#193 

#194      //

#195      // Save system disknumber.

#196      //

#197 

 

保存磁盘编号。

#198     deviceExtension->DeviceNumber = *DeviceCount;

#199 

#200      //

#201      // Copy port deviceobject pointer to the device extension.

#202      //

#203 

#204      deviceExtension->PortDeviceObject= PortDeviceObject;

#205 

#206      //

#207      // Set the alignmentrequirements for the device based on the

#208      // host adapterrequirements

#209      //

#210 

 

设置为主机适配器的对齐方式。

#211      if(PortDeviceObject->AlignmentRequirement >deviceObject->AlignmentRequirement) {

#212         deviceObject->AlignmentRequirement =PortDeviceObject->AlignmentRequirement;

#213      }

#214 

#215      //

#216      // This is the physicaldevice object.

#217      //

#218 

 

设置物理设备对象。

#219      physicalDevice =deviceObject;

#220      physicalDeviceExtension= deviceExtension;

#221 

#222      //

#223      // Save address of portdriver capabilities.

#224      //

#225 

#226     deviceExtension->PortCapabilities = PortCapabilities;

#227 

#228      //

#229      // Build the lookasidelist for srb's for the physical disk. Should only

#230      // need a couple.

#231      //

#232 

 

创建一个磁盘的后备列表,以便快速访问。

#233     ScsiClassInitializeSrbLookasideList(deviceExtension,

#234                                          PARTITION0_LIST_SIZE);

#235 

#236      srbListInitialized =TRUE;

#237 

#238      //

#239      // Initialize the srbflags.

#240      //

#241 

 

开始初始化SRB的属性。

#242      if(((PINQUIRYDATA)LunInfo->InquiryData)->CommandQueue &&

#243          PortCapabilities->TaggedQueuing){

#244 

#245         deviceExtension->SrbFlags  =SRB_FLAGS_QUEUE_ACTION_ENABLE;

#246 

#247      } else {

#248 

#249         deviceExtension->SrbFlags  = 0;

#250 

#251      }

#252 

#253      //

#254      // Allow queued requestsif this is not removable media.

#255      //

#256 

 

如果磁盘设备不是可移动设备,那么就创建一个队列来保存请求包。

#257      if(!(deviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {

#258 

#259         deviceExtension->SrbFlags |= SRB_FLAGS_NO_QUEUE_FREEZE;

#260 

#261      }

#262 

#263      //

#264      // Look for controllerthat require special flags.

#265      //

#266 

 

扫描设备的特别设置。

#267     ScanForSpecial(deviceObject,

#268                      LunInfo,

#269                     PortCapabilities);

#270 

#271      srbFlags = deviceExtension->SrbFlags;

#272 

#273      //

#274      // Allocate buffer fordrive geometry.

#275      //

#276 

 

分配磁盘物理组成属性,比如磁头个数,柱面,扇区数量等等。

#277      diskGeometry =ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY));

#278 

#279      if (diskGeometry ==NULL) {

#280 

#281          DebugPrint((1,

#282            "CreateDiskDeviceObjects: Can not allocate disk geometrybuffer/n"));

#283          status =STATUS_INSUFFICIENT_RESOURCES;

#284          gotoCreateDiskDeviceObjectsExit;

#285      }

#286 

#287     deviceExtension->DiskGeometry = diskGeometry;

#288 

#289      //

#290      // Allocate requestsense buffer.

#291      //

#292 

#293      senseData =ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);

#294 

#295      if (senseData == NULL) {

#296 

#297          //

#298          // The buffer cannot be allocated.

#299          //

#300 

#301          DebugPrint((1,

#302            "CreateDiskDeviceObjects: Can not allocate request sensebuffer/n"));

#303 

#304          status = STATUS_INSUFFICIENT_RESOURCES;

#305          gotoCreateDiskDeviceObjectsExit;

#306      }

#307 

#308      //

#309      // Set the sense datapointer in the device extension.

#310      //

#311 

 

保存有意义的数据指针。

#312     deviceExtension->SenseData = senseData;

#313 

#314      //

#315      // Physical deviceobject will describe the entire

#316      // device, starting atbyte offset 0.

#317      //

#318 

 

设置物理设备的偏移位置。

#319     deviceExtension->StartingOffset.QuadPart = (LONGLONG)(0);

#320 

#321      //

#322      // TargetId/LUNdescribes a device location on the SCSI bus.

#323      // This informationcomes from the inquiry buffer.

#324      //

#325 

 

设置SCSI总线上标识磁盘的内容。

#326     deviceExtension->PortNumber = (UCHAR)PortNumber;

#327      deviceExtension->PathId= pathId;

#328     deviceExtension->TargetId = targetId;

#329      deviceExtension->Lun= lun;

#330 

#331      //

#332      // Set timeout value inseconds.

#333      //

#334 

 

设置磁盘设备的命令处理的超时时间。

#335      timeOut =ScsiClassQueryTimeOutRegistryValue(RegistryPath);

#336      if (timeOut) {

#337         deviceExtension->TimeOutValue = timeOut;

#338      } else {

#339         deviceExtension->TimeOutValue = SCSI_DISK_TIMEOUT;

#340      }

#341 

#342      //

#343      // Back pointer to deviceobject.

#344      //

#345 

 

设备对象的指针。

#346     deviceExtension->DeviceObject = deviceObject;

#347 

#348      //

#349      // If this is aremovable device, then make sure it is not a floppy.

#350      // Perform a mode sensecommand to determine the media type. Note

#351      // IsFloppyDevice alsochecks for write cache enabled.

#352      //

#353 

 

如果设备是软盘设备,并且设备是可移设备,不可以直接访问时就创建失败。

#354      if(IsFloppyDevice(deviceObject) && deviceObject->Characteristics &FILE_REMOVABLE_MEDIA &&

#355          (((PINQUIRYDATA)LunInfo->InquiryData)->DeviceType== DIRECT_ACCESS_DEVICE)) {

#356 

#357          status =STATUS_NO_SUCH_DEVICE;

#358          gotoCreateDiskDeviceObjectsExit;

#359      }

#360 

 

关闭写缓存。

#361     DisableWriteCache(deviceObject,LunInfo);

#362 

#363      writeCache =deviceExtension->DeviceFlags & DEV_WRITE_CACHE;

#364 

#365      //

#366      // NOTE: At this pointone device object has been successfully created.

#367      // from here on outreturn success.

#368      //

#369 

#370      //

#371      // Do READ CAPACITY.This SCSI command

#372      // returns the number ofbytes on a device.

#373      // Device extension isupdated with device size.

#374      //

#375 

 

发送命令READ CAPACITY获取设备容量的大小,比如多少G数据可以保存。

#376      status = ScsiClassReadDriveCapacity(deviceObject);

#377 

#378      //

#379      // If the read capcityfailed then just return, unless this is a

#380      // removable disk wherea device object partition needs to be created.

#381      //

#382 

#383      if (!NT_SUCCESS(status)&&

#384         !(deviceObject->Characteristics & FILE_REMOVABLE_MEDIA)) {

#385 

#386          DebugPrint((1,

#387             "CreateDiskDeviceObjects: Can't read capacity for device%s/n",

#388              ntNameBuffer));

#389 

#390          return(STATUS_SUCCESS);

#391 

#392      } else {

#393 

#394          //

#395          // Make sure thevolume verification bit is off so that

#396          //IoReadPartitionTable will work.

#397          //

#398 

 

设置可以读取分区表格了。

#399          deviceObject->Flags&= ~DO_VERIFY_VOLUME;

#400      }

#401 

 

为磁盘所有分区创建分区设备对象,主要通过MBR的分区表格来分析有几个可以使用的分区。

#402      status =CreatePartitionDeviceObjects(deviceObject, RegistryPath);

#403 

#404      if (NT_SUCCESS(status))

#405          returnSTATUS_SUCCESS;

#406 

#407 

 

下面是删除已经分配的内存。

#408  CreateDiskDeviceObjectsExit:

#409 

#410      //

#411      // Release the devicesince an error occurred.

#412      //

#413 

#414     ScsiClassClaimDevice(PortDeviceObject,

#415                          LunInfo,

#416                           TRUE,

#417                          NULL);

#418 

#419      if (diskGeometry !=NULL) {

#420         ExFreePool(diskGeometry);

#421      }

#422 

#423      if (senseData != NULL) {

#424         ExFreePool(senseData);

#425      }

#426 

#427      if (deviceObject !=NULL) {

#428 

#429          if(srbListInitialized) {

#430             ExDeleteNPagedLookasideList(&deviceExtension->SrbLookasideListHead);

#431          }

#432 

#433         IoDeleteDevice(deviceObject);

#434      }

#435 

#436      //

#437      // Delete directory andreturn.

#438      //

#439 

#440      if (!NT_SUCCESS(status)){

#441         ZwMakeTemporaryObject(handle);

#442      }

#443 

#444      ZwClose(handle);

#445 

#446      return(status);

#447 

#448  } // endCreateDiskDeviceObjects()