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() (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |