reactos操作系统实现(120)

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

#001  NTSTATUS

#002  NTAPI

#003  CreateDiskDeviceObject(

#004      IN PDRIVER_OBJECT DriverObject,

#005      IN PUNICODE_STRING RegistryPath,

#006      IN PDEVICE_OBJECT PortDeviceObject,

#007      IN ULONG PortNumber,

#008      IN PULONG DeviceCount,

#009      IN PIO_SCSI_CAPABILITIES PortCapabilities,

#010      IN PSCSI_INQUIRY_DATA LunInfo,

#011      IN PCLASS_INIT_DATA InitData

#012      )

#013 

#014  /*++

#015 

#016  Routine Description:

#017 

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

#019      the device for partitions and creates an object for each partition.

#020 

#021  Arguments:

#022 

#023      DriverObject - Pointer to 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_STRING ntUnicodeString;

#044      OBJECT_ATTRIBUTES objectAttributes;

#045      HANDLE         handle;

#046      NTSTATUS       status;

#047      PDEVICE_OBJECT deviceObject = NULL;

#048      PDEVICE_OBJECT physicalDevice;

#049      PDISK_GEOMETRY diskGeometry = NULL;

#050      PDEVICE_EXTENSION deviceExtension = NULL;

#051      PDEVICE_EXTENSION physicalDeviceExtension;

#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 object directory to contain the objects for this

#066      // device and all its partitions.

#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 device object for this device. Each physical disk will

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

#123      // describes the entire device. 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 not create device object %s/n",

#142                      ntNameBuffer));

#143 

#144          goto CreateDiskDeviceObjectsExit;

#145      }

#146 

#147      //

#148      // Indicate that IRPs should include MDLs for data transfers.

#149      //

#150 

 

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

#151      deviceObject->Flags |= DO_DIRECT_IO;

#152 

#153      //

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

#155      // system initialization already 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 media support.

#165      //

#166 

 

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

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

#168          deviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;

#169      }

#170 

#171      //

#172      // Set up required stack size in device object.

#173      //

#174 

 

设置设备栈的大小。

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

#176 

 

获取设备驱动对象扩展。

#177      deviceExtension = deviceObject->DeviceExtension;

#178 

#179      //

#180      // Allocate spinlock for split request completion.

#181      //

#182 

 

分配共享请求的自旋锁。

#183      KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);

#184 

#185      //

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

#187      // disable the ejection mechanism on devices that support

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

#189      // device extension is used.

#190      //

#191 

#192      deviceExtension->LockCount = 0;

#193 

#194      //

#195      // Save system disk number.

#196      //

#197 

 

保存磁盘编号。

#198      deviceExtension->DeviceNumber = *DeviceCount;

#199 

#200      //

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

#202      //

#203 

#204      deviceExtension->PortDeviceObject = PortDeviceObject;

#205 

#206      //

#207      // Set the alignment requirements for the device based on the

#208      // host adapter requirements

#209      //

#210 

 

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

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

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

#213      }

#214 

#215      //

#216      // This is the physical device object.

#217      //

#218 

 

设置物理设备对象。

#219      physicalDevice = deviceObject;

#220      physicalDeviceExtension = deviceExtension;

#221 

#222      //

#223      // Save address of port driver capabilities.

#224      //

#225 

#226      deviceExtension->PortCapabilities = PortCapabilities;

#227 

#228      //

#229      // Build the lookaside list 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 srb flags.

#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 requests if 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 controller that require special flags.

#265      //

#266 

 

扫描设备的特别设置。

#267      ScanForSpecial(deviceObject,

#268                      LunInfo,

#269                      PortCapabilities);

#270 

#271      srbFlags = deviceExtension->SrbFlags;

#272 

#273      //

#274      // Allocate buffer for drive 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 geometry buffer/n"));

#283          status = STATUS_INSUFFICIENT_RESOURCES;

#284          goto CreateDiskDeviceObjectsExit;

#285      }

#286 

#287      deviceExtension->DiskGeometry = diskGeometry;

#288 

#289      //

#290      // Allocate request sense buffer.

#291      //

#292 

#293      senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);

#294 

#295      if (senseData == NULL) {

#296 

#297          //

#298          // The buffer can not be allocated.

#299          //

#300 

#301          DebugPrint((1,

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

#303 

#304          status = STATUS_INSUFFICIENT_RESOURCES;

#305          goto CreateDiskDeviceObjectsExit;

#306      }

#307 

#308      //

#309      // Set the sense data pointer in the device extension.

#310      //

#311 

 

保存有意义的数据指针。

#312      deviceExtension->SenseData = senseData;

#313 

#314      //

#315      // Physical device object will describe the entire

#316      // device, starting at byte offset 0.

#317      //

#318 

 

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

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

#320 

#321      //

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

#323      // This information comes 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 in seconds.

#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 device object.

#344      //

#345 

 

设备对象的指针。

#346      deviceExtension->DeviceObject = deviceObject;

#347 

#348      //

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

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

#351      // IsFloppyDevice also checks 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          goto CreateDiskDeviceObjectsExit;

#359      }

#360 

 

关闭写缓存。

#361      DisableWriteCache(deviceObject,LunInfo);

#362 

#363      writeCache = deviceExtension->DeviceFlags & DEV_WRITE_CACHE;

#364 

#365      //

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

#367      // from here on out return success.

#368      //

#369 

#370      //

#371      // Do READ CAPACITY. This SCSI command

#372      // returns the number of bytes on a device.

#373      // Device extension is updated with device size.

#374      //

#375 

 

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

#376      status = ScsiClassReadDriveCapacity(deviceObject);

#377 

#378      //

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

#380      // removable disk where a 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 the volume 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          return STATUS_SUCCESS;

#406 

#407 

 

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

#408  CreateDiskDeviceObjectsExit:

#409 

#410      //

#411      // Release the device since 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 and return.

#438      //

#439 

#440      if (!NT_SUCCESS(status)) {

#441          ZwMakeTemporaryObject(handle);

#442      }

#443 

#444      ZwClose(handle);

#445 

#446      return(status);

#447 

#448  } // end CreateDiskDeviceObjects()

转载于:https://www.cnblogs.com/ajuanabc/archive/2009/10/30/2463645.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值