CreatePartitionDeviceObjects函数是通过分析MBR扇区的数据,然后来创建所有分区对象。具体实现代码如下:
#001 NTSTATUS
#002 NTAPI
#003 CreatePartitionDeviceObjects(
#004 IN PDEVICE_OBJECT PhysicalDeviceObject,
#005 IN PUNICODE_STRING RegistryPath
#006 )
#007 {
#008 CCHAR ntNameBuffer[MAXIMUM_FILENAME_LENGTH];
#009 ULONG partitionNumber = 0;
#010 NTSTATUS status;
#011 PDEVICE_OBJECT deviceObject = NULL;
#012 PDISK_GEOMETRY diskGeometry = NULL;
#013 PDRIVE_LAYOUT_INFORMATION partitionList = NULL;
#014 PDEVICE_EXTENSION deviceExtension;
#015 PDEVICE_EXTENSION physicalDeviceExtension;
#016 PCLASS_INIT_DATA initData = NULL;
#017 PDISK_DATA diskData;
#018 PDISK_DATA physicalDiskData;
#019 ULONG bytesPerSector;
#020 UCHAR sectorShift;
#021 ULONG srbFlags;
#022 ULONG dmByteSkew = 0;
#023 PULONG dmSkew;
#024 BOOLEAN dmActive = FALSE;
#025 ULONG numberListElements = 0;
#026
#027
#028 //
#029 // Get physical device geometry information for partition table reads.
#030 //
#031
通过磁盘描述信息来获取磁盘组成结构,比如每扇区多少个字节。
#032 physicalDeviceExtension = PhysicalDeviceObject->DeviceExtension;
#033 diskGeometry = physicalDeviceExtension->DiskGeometry;
#034 bytesPerSector = diskGeometry->BytesPerSector;
#035
#036 //
#037 // Make sure sector size is not zero.
#038 //
#039
确保每个扇区的字节数不为0,如果为0的时候,就让它缺省为512个字节。
#040 if (bytesPerSector == 0) {
#041
#042 //
#043 // Default sector size for disk is 512.
#044 //
#045
#046 bytesPerSector = diskGeometry->BytesPerSector = 512;
#047 }
#048
#049 sectorShift = physicalDeviceExtension->SectorShift;
#050
#051 //
#052 // Set pointer to disk data area that follows device extension.
#053 //
#054
设置指向磁盘结构数据指针。
#055 diskData = (PDISK_DATA)(physicalDeviceExtension + 1);
设置磁盘分区表格正在初始化。
#056 diskData->PartitionListState = Initializing;
#057
#058 //
#059 // Determine is DM Driver is loaded on an IDE drive that is
#060 // under control of Atapi - this could be either a crashdump or
#061 // an Atapi device is sharing the controller with an IDE disk.
#062 //
#063
调用函数HalExamineMBR来读取指定类型的MBR扇区数据。其实这个函数调用IO管理器后,生成一个IRP调用ATAPI驱动程序去读取磁盘0扇区数据。
#064 HalExamineMBR(PhysicalDeviceObject,
#065 physicalDeviceExtension->DiskGeometry->BytesPerSector,
#066 (ULONG)0x54,
#067 (PVOID)&dmSkew);
#068
判断是否有DM驱动程序,如果有就需要调整相关的磁盘信息。
#069 if (dmSkew) {
#070
#071 //
#072 // Update the device extension,so that the call to IoReadPartitionTable
#073 // will get the correct information. Any I/O to this disk will have
#074 // to be skewed by *dmSkew sectors aka DMByteSkew.
#075 //
#076
#077 physicalDeviceExtension->DMSkew = *dmSkew;
#078 physicalDeviceExtension->DMActive = TRUE;
#079 physicalDeviceExtension->DMByteSkew = physicalDeviceExtension->DMSkew * bytesPerSector;
#080
#081 //
#082 // Save away the infomation that we need,since this deviceExtension will soon be
#083 // blown away.
#084 //
#085
#086 dmActive = TRUE;
#087 dmByteSkew = physicalDeviceExtension->DMByteSkew;
#088
#089 }
#090
#091 //
#092 // Create objects for all the partitions on the device.
#093 //
#094
为这个磁盘设备的所有分区创建分区对象。
#095 status = IoReadPartitionTable(PhysicalDeviceObject,
#096 physicalDeviceExtension->DiskGeometry->BytesPerSector,
#097 TRUE,
#098 (PVOID)&partitionList);
#099
#100 //
#101 // If the I/O read partition table Failed and this is a removable device,
#102 // then fix up the partition list to make it look like there is one
#103 // zero length partition.
#104 //
#105 DPRINT("IoReadPartitionTable() status: 0x%08X/n",status);
#106 if ((!NT_SUCCESS(status) || partitionList->PartitionCount == 0) &&
#107 PhysicalDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
#108
如果读分区表出错,就设置磁盘没有准备好。
#109 if (!NT_SUCCESS(status)) {
#110
#111 //
#112 // Remember this disk is not ready.
#113 //
#114
#115 diskData->DriveNotReady = TRUE;
#116
#117 } else {
#118
#119 //
#120 // Free the partition list allocated by IoReadPartitionTable.
#121 //
#122
#123 ExFreePool(partitionList);
#124 }
#125
#126 //
#127 // Allocate and zero a partition list.
#128 //
#129
分配分区列表。
#130 partitionList = ExAllocatePool(NonPagedPool,sizeof(*partitionList ));
#131
#132
#133 if (partitionList != NULL) {
#134
#135 RtlZeroMemory( partitionList,sizeof( *partitionList ));
#136
#137 //
#138 // Set the partition count to one and the status to success
#139 // so one device object will be created. Set the partition type
#140 // to a bogus value.
#141 //
#142
#143 partitionList->PartitionCount = 1;
#144
#145 status = STATUS_SUCCESS;
#146 }
#147 }
#148
#149 if (NT_SUCCESS(status)) {
#150
#151 //
#152 // Record disk signature.
#153 //
#154
保存磁盘的标志。
#155 diskData->Signature = partitionList->Signature;
#156
#157 //
#158 // If disk signature is zero,then calculate the MBR checksum.
#159 //
#160
如果磁盘的标志为0,那么就计算MBR的校验码是否正确。
#161 if (!diskData->Signature) {
#162
#163 if (!CalculateMbrCheckSum(physicalDeviceExtension,
#164 &diskData->MbrCheckSum)) {
#165
#166 DebugPrint((1,
#167 "SCSIDISK: Can't calculate MBR checksum for disk %x/n",
#168 physicalDeviceExtension->DeviceNumber));
#169 } else {
#170
#171 DebugPrint((2,
#172 "SCSIDISK: MBR checksum for disk %x is %x/n",
#173 physicalDeviceExtension->DeviceNumber,
#174 diskData->MbrCheckSum));
#175 }
#176 }
#177
#178 //
#179 // Check the registry and determine if the BIOS knew about this drive. If
#180 // it did then update the geometry with the BIOS information.
#181 //
#182
#183 UpdateGeometry(physicalDeviceExtension);
#184
#185 srbFlags = physicalDeviceExtension->SrbFlags;
#186
创建磁盘的操作函数。
#187 initData = ExAllocatePool(NonPagedPool,sizeof(CLASS_INIT_DATA));
#188 if (!initData)
#189 {
#190 DebugPrint((1,
#191 "Disk.CreatePartionDeviceObjects - Allocation of initData Failed/n"));
#192
#193 status = STATUS_INSUFFICIENT_RESOURCES;
#194 goto CreatePartitionDeviceObjectsExit;
#195 }
#196
#197 RtlZeroMemory(initData,sizeof(CLASS_INIT_DATA));
#198
#199 initData->InitializationDataSize = sizeof(CLASS_INIT_DATA);
#200 initData->DeviceExtensionSize = DEVICE_EXTENSION_SIZE;
#201 initData->DeviceType = FILE_DEVICE_DISK;
#202 initData->DeviceCharacteristics = PhysicalDeviceObject->Characteristics;
#203 initData->ClassError = physicalDeviceExtension->ClassError;
#204 initData->ClassReadWriteVerification = physicalDeviceExtension->ClassReadWriteVerification;
#205 initData->ClassFindDevices = physicalDeviceExtension->ClassFindDevices;
#206 initData->ClassDeviceControl = physicalDeviceExtension->ClassDeviceControl;
#207 initData->ClassShutdownFlush = physicalDeviceExtension->ClassShutdownFlush;
#208 initData->ClassCreateClose = physicalDeviceExtension->ClassCreateClose;
#209 initData->ClassStartIo = physicalDeviceExtension->ClassStartIo;
#210
#211 //
#212 // Create device objects for the device partitions (if any).
#213 // PartitionCount includes physical device partition 0,
#214 // so only one partition means no objects to create.
#215 //
#216
#217 DebugPrint((2,
#218 "CreateDiskDeviceObjects: Number of partitions is %d/n",
#219 partitionList->PartitionCount));
#220
为所有磁盘分区创建分区对象。
#221 for (partitionNumber = 0; partitionNumber <
#222 partitionList->PartitionCount; partitionNumber++) {
#223
#224 //
#225 // Create partition object and set up partition parameters.
#226 //
#227
#228 sprintf(ntNameBuffer,
#229 "//Device//Harddisk%lu//Partition%lu",
#230 physicalDeviceExtension->DeviceNumber,
#231 partitionNumber + 1);
#232
#233 DebugPrint((2,
#234 "CreateDiskDeviceObjects: Create device object %s/n",
#235 ntNameBuffer));
#236
#237 status = ScsiClassCreateDeviceObject(PhysicalDeviceObject->DriverObject,
#238 ntNameBuffer,
#239 PhysicalDeviceObject,
#240 &deviceObject,
#241 initData);
#242
#243 if (!NT_SUCCESS(status)) {
#244
#245 DebugPrint((1,"CreateDiskDeviceObjects: Can't create device object for %s/n",ntNameBuffer));
#246
#247 break;
#248 }
#249
#250 //
#251 // Set up device object fields.
#252 //
#253
设置设备是直接通过IO访问。
#254 deviceObject->Flags |= DO_DIRECT_IO;
#255
#256 //
#257 // Check if this is during initialization. If not indicate that
#258 // system initialization already took place and this disk is ready
#259 // to be accessed.
#260 //
#261
#262 if (!RegistryPath) {
#263 deviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
#264 }
#265
设置设备栈。
#266 deviceObject->StackSize = (CCHAR)physicalDeviceExtension->PortDeviceObject->StackSize + 1;
#267
#268 //
#269 // Set up device extension fields.
#270 //
#271
设置设备扩展结构。
#272 deviceExtension = deviceObject->DeviceExtension;
#273
#274 if (dmActive) {
#275
#276 //
#277 // Restore any saved DM values.
#278 //
#279
#280 deviceExtension->DMByteSkew = dmByteSkew;
#281 deviceExtension->DMSkew = *dmSkew;
#282 deviceExtension->DMActive = TRUE;
#283
#284 }
#285
#286 //
#287 // Link new device extension to prevIoUs disk data
#288 // to support dynamic partitioning.
#289 //
#290
设置设备连接下一个分区。
#291 diskData->NextPartition = deviceExtension;
#292
#293 //
#294 // Get pointer to new disk data.
#295 //
#296
#297 diskData = (PDISK_DATA)(deviceExtension + 1);
#298
#299 //
#300 // Set next partition pointer to NULL in case this is the
#301 // last partition.
#302 //
#303
#304 diskData->NextPartition = NULL;
#305
#306 //
#307 // Allocate spinlock for zoning for split-request completion.
#308 //
#309
#310 KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
#311
#312 //
#313 // Copy port device object pointer to device extension.
#314 //
#315
设置设备指向端口驱动程序。
#316 deviceExtension->PortDeviceObject = physicalDeviceExtension->PortDeviceObject;
#317
#318 //
#319 // Set the alignment requirements for the device based on the
#320 // host adapter requirements
#321 //
#322
#323 if (physicalDeviceExtension->PortDeviceObject->AlignmentRequirement > deviceObject->AlignmentRequirement) {
#324 deviceObject->AlignmentRequirement = physicalDeviceExtension->PortDeviceObject->AlignmentRequirement;
#325 }
#326
#327
#328 if (srbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) {
#329 numberListElements = 30;
#330 } else {
#331 numberListElements = 8;
#332 }
#333
#334 //
#335 // Build the lookaside list for srb's for this partition based on
#336 // whether the adapter and disk can do tagged queueing.
#337 //
#338
设置设备扩展的后备缓冲列表。
#339 ScsiClassInitializeSrbLookasideList(deviceExtension,
#340 numberListElements);
#341
#342 deviceExtension->SrbFlags = srbFlags;
#343
#344 //
#345 // Set the sense-data pointer in the device extension.
#346 //
#347
#348 deviceExtension->SenseData = physicalDeviceExtension->SenseData;
#349 deviceExtension->PortCapabilities = physicalDeviceExtension->PortCapabilities;
#350 deviceExtension->DiskGeometry = diskGeometry;
#351 diskData->PartitionOrdinal = diskData->PartitionNumber = partitionNumber + 1;
#352 diskData->PartitionType = partitionList->PartitionEntry[partitionNumber].PartitionType;
#353 diskData->BootIndicator = partitionList->PartitionEntry[partitionNumber].BootIndicator;
#354
#355 DebugPrint((2,"CreateDiskDeviceObjects: Partition type is %x/n",
#356 diskData->PartitionType));
#357
#358 deviceExtension->StartingOffset = partitionList->PartitionEntry[partitionNumber].StartingOffset;
#359 deviceExtension->PartitionLength = partitionList->PartitionEntry[partitionNumber].PartitionLength;
#360 diskData->HiddenSectors = partitionList->PartitionEntry[partitionNumber].HiddenSectors;
#361 deviceExtension->PortNumber = physicalDeviceExtension->PortNumber;
#362 deviceExtension->PathId = physicalDeviceExtension->PathId;
#363 deviceExtension->TargetId = physicalDeviceExtension->TargetId;
#364 deviceExtension->Lun = physicalDeviceExtension->Lun;
#365
#366 //
#367 // Check for removable media support.
#368 //
#369
检查可移动磁盘的支持。
#370 if (PhysicalDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
#371 deviceObject->Characteristics |= FILE_REMOVABLE_MEDIA;
#372 }
#373
#374 //
#375 // Set timeout value in seconds.
#376 //
#377
设置设备超时时间。
#378 deviceExtension->TimeOutValue = physicalDeviceExtension->TimeOutValue;
#379 deviceExtension->DiskGeometry->BytesPerSector = bytesPerSector;
#380 deviceExtension->SectorShift = sectorShift;
#381 deviceExtension->DeviceObject = deviceObject;
#382 deviceExtension->DeviceFlags |= physicalDeviceExtension->DeviceFlags;
#383
#384 } // end for (partitionNumber) ...
#385
#386 //
#387 // Free the buffer allocated by reading the
#388 // partition table.
#389 //
#390
#391 ExFreePool(partitionList);
#392
#393 } else {
#394
#395 CreatePartitionDeviceObjectsExit:
#396
#397 if (partitionList) {
#398 ExFreePool(partitionList);
#399 }
#400 if (initData) {
#401 ExFreePool(initData);
#402 }
#403
#404 return status;
#405
#406 } // end if...else
#407
#408
#409 physicalDiskData = (PDISK_DATA)(physicalDeviceExtension + 1);
#410 physicalDiskData->PartitionListState = Initialized;
#411
#412 return(STATUS_SUCCESS);
#413
#414
#415 } // end CreatePartitionDeviceObjects()
#416