// static FORCEINLINE BOOLEAN ShouldICheckThisPartition( IN PPARTENTRY PartEntry) { if (!PartEntry) return FALSE; return PartEntry->IsPartitioned && !IsContainerPartition(PartEntry->PartitionType) /* alternatively: PartEntry->PartitionNumber != 0 */ && !PartEntry->New && (PartEntry->FormatState == Preformatted /* || PartEntry->FormatState == Formatted */); }
VOID NTAPI DiskUpdatePartitions( IN PDEVICE_OBJECT Fdo, IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList ) /*++ Routine Description: This routine will synchronize the information held in the partition list with the device objects hanging off this Fdo. Any new partition objects will be created, any non-existant ones will be marked as un-enumerated. This will be done in several stages: * Clear state (partition number) from every entry in the partition list * Set IsMissing flag on every child of this FDO * For each child of the FDO: if a matching partition exists in the partition list, update the partition number in the table, update the ordinal in the object and mark the object as enumerated * For each un-enumerated device object zero out the partition information to invalidate the device delete the symbolic link if any * For each un-matched entry in the partition list: create a new partition object update the partition number in the list entry create a new symbolic link if necessary Arguments: Fdo - a pointer to the functional device object this partition list is for PartitionList - a pointer to the partition list being updated Return Value: none --*/ { PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; PPHYSICAL_DEVICE_EXTENSION oldChildList = NULL; PPHYSICAL_DEVICE_EXTENSION pdoExtension = NULL; ULONG partitionCount; ULONG partitionNumber; ULONG partitionOrdinal; ULONG newPartitionNumber; PPARTITION_INFORMATION_EX partitionEntry = NULL; PDISK_DATA pdoData; PARTITION_STYLE partitionStyle; NTSTATUS status; PAGED_CODE(); // // Get exclusive access to the child list. // ClassAcquireChildLock(fdoExtension); partitionStyle = PartitionList->PartitionStyle; partitionCount = PartitionList->PartitionCount; // // Pull all the child device objects off the children list. We'll // add them back later. // oldChildList = fdoExtension->CommonExtension.ChildList; fdoExtension->CommonExtension.ChildList = NULL; // // Clear the partition numbers from the list entries // for(partitionNumber = 0; partitionNumber < partitionCount; partitionNumber++) { partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]); partitionEntry->PartitionNumber = 0; } // // Now match each child partition to it's entry (if any) in the partition // list. // while(oldChildList != NULL) { pdoExtension = oldChildList; pdoData = pdoExtension->CommonExtension.DriverData; // // Check all partition entries for a match on offset and length // partitionOrdinal = 0; for(partitionNumber = 0; partitionNumber < partitionCount; partitionNumber++) { partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]); // // Is this an interesting partition entry? // if (partitionStyle == PARTITION_STYLE_MBR) { if((partitionEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED) || (IsContainerPartition(partitionEntry->Mbr.PartitionType))) { continue; } } partitionOrdinal++; if(partitionEntry->PartitionNumber) { // // This partition has already been found - skip it // continue; } // // Let's see if the partition information matches // if(partitionEntry->StartingOffset.QuadPart != pdoExtension->CommonExtension.StartingOffset.QuadPart) { continue; } if(partitionEntry->PartitionLength.QuadPart != pdoExtension->CommonExtension.PartitionLength.QuadPart) { continue; } // // Yep - it matches. Update the information in the entry // partitionEntry->PartitionNumber = pdoExtension->CommonExtension.PartitionNumber; if (partitionStyle == PARTITION_STYLE_MBR) { pdoData->Mbr.HiddenSectors = partitionEntry->Mbr.HiddenSectors; } break; } if(partitionNumber != partitionCount) { DebugPrint((1, "DiskUpdatePartitions: Matched %wZ to #%d, ordinal " "%d\n", &pdoExtension->CommonExtension.DeviceName, partitionEntry->PartitionNumber, partitionOrdinal)); ASSERT(partitionEntry->PartitionLength.LowPart != 0x23456789); // ASSERT(pdoExtension->CommonExtension.PartitionLength.QuadPart != 0); pdoData->PartitionStyle = partitionStyle; // // we found a match - update the information in the device object // extension and driverdata // pdoData->PartitionOrdinal = partitionOrdinal; // // If this partition is being re-written then update the type // information as well // if (partitionStyle == PARTITION_STYLE_MBR) { if(partitionEntry->RewritePartition) { pdoData->Mbr.PartitionType = partitionEntry->Mbr.PartitionType; } } else { DebugPrint((1, "DiskUpdatePartitions: EFI Partition %ws\n", pdoData->Efi.PartitionName )); pdoData->Efi.PartitionType = partitionEntry->Gpt.PartitionType; pdoData->Efi.PartitionId = partitionEntry->Gpt.PartitionId; pdoData->Efi.Attributes = partitionEntry->Gpt.Attributes; RtlCopyMemory( pdoData->Efi.PartitionName, partitionEntry->Gpt.Name, sizeof (pdoData->Efi.PartitionName) ); } // // Mark this one as found. // pdoExtension->IsMissing = FALSE; // // Pull it out of the old child list and add it into the // real one. // oldChildList = pdoExtension->CommonExtension.ChildList; pdoExtension->CommonExtension.ChildList = fdoExtension->CommonExtension.ChildList; fdoExtension->CommonExtension.ChildList = pdoExtension; } else { //PDEVICE_OBJECT nextPdo; DebugPrint ((1, "DiskUpdatePartitions: Deleting %wZ\n", &pdoExtension->CommonExtension.DeviceName)); if (partitionStyle == PARTITION_STYLE_GPT) { DebugPrint ((1, "DiskUpdatePartitions: EFI Partition %ws\n", pdoData->Efi.PartitionName )); } // // no matching entry in the partition list - throw this partition // object away // pdoExtension->CommonExtension.PartitionLength.QuadPart = 0; // // grab a pointer to the next child before we mark this one as // missing since missing devices could vanish at any time. // oldChildList = pdoExtension->CommonExtension.ChildList; pdoExtension->CommonExtension.ChildList = (PVOID) -1; // // Now tell the class driver that this child is "missing" - this // will cause it to be deleted. // ClassMarkChildMissing(pdoExtension, FALSE); } } // // At this point the old child list had best be empty. // ASSERT(oldChildList == NULL); // // Iterate through the partition entries and create any partition // objects that don't already exist // partitionOrdinal = 0; newPartitionNumber = 0; for(partitionNumber = 0; partitionNumber < partitionCount; partitionNumber++) { PDEVICE_OBJECT pdo; partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]); // // Is this partition interesting // if (partitionStyle == PARTITION_STYLE_MBR) { if((partitionEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED) || (IsContainerPartition(partitionEntry->Mbr.PartitionType))) { continue; } } // // Increment the count of interesting partitions // partitionOrdinal++; newPartitionNumber++; // // Has this already been matched // if(partitionEntry->PartitionNumber == 0) { LONG i; // // find the first safe partition number for this device // for(i = 0; i < (LONG) partitionCount; i++) { PPARTITION_INFORMATION_EX tmp = &(PartitionList->PartitionEntry[i]); if (partitionStyle == PARTITION_STYLE_MBR) { if (tmp->Mbr.PartitionType == PARTITION_ENTRY_UNUSED || IsContainerPartition(tmp->Mbr.PartitionType)) { continue; } } if(tmp->PartitionNumber == newPartitionNumber) { // // Found a matching partition number - increment the count // and restart the scan. // newPartitionNumber++; i = -1; continue; } } // // Assign this partition a partition number // partitionEntry->PartitionNumber = newPartitionNumber; DebugPrint((1, "DiskUpdatePartitions: Found new partition #%d, ord %d " "starting at %#016I64x and running for %#016I64x\n", partitionEntry->PartitionNumber, partitionOrdinal, partitionEntry->StartingOffset.QuadPart, partitionEntry->PartitionLength.QuadPart)); ClassReleaseChildLock(fdoExtension); status = DiskCreatePdo(Fdo, partitionOrdinal, partitionEntry, partitionStyle, &pdo); ClassAcquireChildLock(fdoExtension); if(!NT_SUCCESS(status)) { DebugPrint((1, "DiskUpdatePartitions: error %lx creating " "new PDO for partition ordinal %d, number %d\n", status, partitionOrdinal, partitionEntry->PartitionNumber)); // // don't increment the partition number - we'll try to reuse // it for the next child. // partitionEntry->PartitionNumber = 0; newPartitionNumber--; continue; } // // mark the new device as enumerated // pdoExtension = pdo->DeviceExtension; pdoExtension->IsMissing = FALSE; // // This number's taken already - try to scanning the partition // table more than once for a new number. // } } // // ISSUE - 2000/02/09 - math: Review. // Is PartitionStyle the only field that needs updating? // { PCOMMON_DEVICE_EXTENSION commonExtension; PDISK_DATA diskData; commonExtension = Fdo->DeviceExtension; diskData = (PDISK_DATA)(commonExtension->DriverData); diskData->PartitionStyle = partitionStyle; } ClassReleaseChildLock(fdoExtension); return; }
static VOID AddPartitionToDisk( ULONG DiskNumber, PDISKENTRY DiskEntry, ULONG PartitionIndex, BOOLEAN LogicalPartition) { PPARTITION_INFORMATION PartitionInfo; PPARTENTRY PartEntry; PartitionInfo = &DiskEntry->LayoutBuffer->PartitionEntry[PartitionIndex]; if (PartitionInfo->PartitionType == 0 || (LogicalPartition == TRUE && IsContainerPartition(PartitionInfo->PartitionType))) return; PartEntry = RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PARTENTRY)); if (PartEntry == NULL) { return; } PartEntry->DiskEntry = DiskEntry; PartEntry->StartSector.QuadPart = (ULONGLONG)PartitionInfo->StartingOffset.QuadPart / DiskEntry->BytesPerSector; PartEntry->SectorCount.QuadPart = (ULONGLONG)PartitionInfo->PartitionLength.QuadPart / DiskEntry->BytesPerSector; PartEntry->BootIndicator = PartitionInfo->BootIndicator; PartEntry->PartitionType = PartitionInfo->PartitionType; PartEntry->HiddenSectors = PartitionInfo->HiddenSectors; PartEntry->LogicalPartition = LogicalPartition; PartEntry->IsPartitioned = TRUE; PartEntry->PartitionNumber = PartitionInfo->PartitionNumber; PartEntry->PartitionIndex = PartitionIndex; if (IsContainerPartition(PartEntry->PartitionType)) { PartEntry->FormatState = Unformatted; if (LogicalPartition == FALSE && DiskEntry->ExtendedPartition == NULL) DiskEntry->ExtendedPartition = PartEntry; } else if ((PartEntry->PartitionType == PARTITION_FAT_12) || (PartEntry->PartitionType == PARTITION_FAT_16) || (PartEntry->PartitionType == PARTITION_HUGE) || (PartEntry->PartitionType == PARTITION_XINT13) || (PartEntry->PartitionType == PARTITION_FAT32) || (PartEntry->PartitionType == PARTITION_FAT32_XINT13)) { #if 0 if (CheckFatFormat()) { PartEntry->FormatState = Preformatted; } else { PartEntry->FormatState = Unformatted; } #endif PartEntry->FormatState = Preformatted; } else if (PartEntry->PartitionType == PARTITION_EXT2) { #if 0 if (CheckExt2Format()) { PartEntry->FormatState = Preformatted; } else { PartEntry->FormatState = Unformatted; } #endif PartEntry->FormatState = Preformatted; } else if (PartEntry->PartitionType == PARTITION_IFS) { #if 0 if (CheckNtfsFormat()) { PartEntry->FormatState = Preformatted; } else if (CheckHpfsFormat()) { PartEntry->FormatState = Preformatted; } else { PartEntry->FormatState = Unformatted; } #endif PartEntry->FormatState = Preformatted; } else { PartEntry->FormatState = UnknownFormat; } if (LogicalPartition) InsertTailList(&DiskEntry->LogicalPartListHead, &PartEntry->ListEntry); else InsertTailList(&DiskEntry->PrimaryPartListHead, &PartEntry->ListEntry); }
VOID NTAPI DiskUpdateRemovablePartitions( IN PDEVICE_OBJECT Fdo, IN OUT PDRIVE_LAYOUT_INFORMATION_EX PartitionList ) /*++ Routine Description: This routine is called by the class DLL to update the PDO list off of this FDO. The disk driver also calls it internally to re-create device objects. This routine will read the partition table and update the size of the single partition device object which always exists for removable devices. Arguments: Fdo - a pointer to the FDO being reenumerated. Return Value: status --*/ { PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension; PPHYSICAL_DEVICE_EXTENSION pdoExtension = NULL; ULONG partitionCount; ULONG partitionNumber; ULONG partitionOrdinal = 0; //ULONG newPartitionNumber; PDISK_DATA pdoData; NTSTATUS status; PPARTITION_INFORMATION_EX partitionEntry; PARTITION_STYLE partitionStyle; PAGED_CODE(); ASSERT(Fdo->Characteristics & FILE_REMOVABLE_MEDIA); partitionStyle = PartitionList->PartitionStyle; partitionCount = PartitionList->PartitionCount; for(partitionNumber = 0; partitionNumber < partitionCount; partitionNumber++) { partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]); partitionEntry->PartitionNumber = 0; } // // Get exclusive access to the child list while repartitioning. // ClassAcquireChildLock(fdoExtension); // // Removable media should never have more than one PDO. // pdoExtension = fdoExtension->CommonExtension.ChildList; if(pdoExtension == NULL) { PARTITION_INFORMATION_EX tmpPartitionEntry; PDEVICE_OBJECT pdo; // // There is no PDO currently. Create one and pre-initialize it with // a zero length. // RtlZeroMemory(&tmpPartitionEntry, sizeof(tmpPartitionEntry)); tmpPartitionEntry.PartitionNumber = 1; DebugPrint((1, "DiskUpdateRemovablePartitions: Creating RM partition\n")); status = DiskCreatePdo(Fdo, 0, &tmpPartitionEntry, partitionStyle, &pdo); if(!NT_SUCCESS(status)) { DebugPrint((1, "DiskUpdateRemovablePartitions: error %lx creating " "new PDO for RM partition\n", status)); ClassReleaseChildLock(fdoExtension); return; } // // mark the new device as enumerated // pdoExtension = pdo->DeviceExtension; pdoExtension->IsMissing = FALSE; } pdoData = pdoExtension->CommonExtension.DriverData; // // Search the partition list for a valid entry. We're looking for a // primary partition since we only support the one. // for(partitionNumber = 0; partitionNumber < partitionCount; partitionNumber++) { partitionEntry = &(PartitionList->PartitionEntry[partitionNumber]); // // Is this partition interesting? // if (partitionStyle == PARTITION_STYLE_MBR) { if(partitionEntry->Mbr.PartitionType == PARTITION_ENTRY_UNUSED || IsContainerPartition(partitionEntry->Mbr.PartitionType)) { continue; } } partitionOrdinal++; // // We have found the first and thus only partition allowed on // this disk. Update the information in the PDO to match the new // partition. // DebugPrint((1, "DiskUpdateRemovablePartitions: Matched %wZ to #%d, " "ordinal %d\n", &pdoExtension->CommonExtension.DeviceName, partitionEntry->PartitionNumber, partitionOrdinal)); partitionEntry->PartitionNumber = 1; pdoData->PartitionStyle = partitionStyle; pdoData->PartitionOrdinal = partitionOrdinal; ASSERT(partitionEntry->PartitionLength.LowPart != 0x23456789); pdoExtension->CommonExtension.StartingOffset = partitionEntry->StartingOffset; pdoExtension->CommonExtension.PartitionLength = partitionEntry->PartitionLength; if (partitionStyle == PARTITION_STYLE_MBR) { pdoData->Mbr.HiddenSectors = partitionEntry->Mbr.HiddenSectors; pdoData->Mbr.BootIndicator = partitionEntry->Mbr.BootIndicator; // // If this partition is being re-written then update the type // information as well // if (partitionEntry->RewritePartition) { pdoData->Mbr.PartitionType = partitionEntry->Mbr.PartitionType; } } else { pdoData->Efi.PartitionType = partitionEntry->Gpt.PartitionType; pdoData->Efi.PartitionId = partitionEntry->Gpt.PartitionId; pdoData->Efi.Attributes = partitionEntry->Gpt.Attributes; RtlCopyMemory( pdoData->Efi.PartitionName, partitionEntry->Gpt.Name, sizeof (pdoData->Efi.PartitionName) ); } // // Mark this one as found // pdoExtension->IsMissing = FALSE; ClassReleaseChildLock(fdoExtension); return; } // // No interesting partition was found. // if (partitionStyle == PARTITION_STYLE_MBR) { pdoData->Mbr.HiddenSectors = 0; pdoData->Mbr.PartitionType = PARTITION_ENTRY_UNUSED; } else { RtlZeroMemory (&pdoData->Efi, sizeof (pdoData->Efi) ); } pdoExtension->CommonExtension.StartingOffset.QuadPart = 0; pdoExtension->CommonExtension.PartitionLength.QuadPart = 0; ClassReleaseChildLock(fdoExtension); return; }
NTSTATUS FtpAttachDevices( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ) /*++ Routine Description: This is the completion routine for handling IOCTL_SET_DRIVE_LAYOUT. Arguments: DeviceObject - not used. Irp - completing IRP. Context - RCB Return Value: NTSTATUS --*/ { PRCB rcb = Context; IN PDRIVE_LAYOUT_INFORMATION partitionList; PDEVICE_EXTENSION deviceExtension = rcb->ZeroExtension; PDEVICE_EXTENSION ftRootExtension = deviceExtension->ObjectUnion.FtRootObject->DeviceExtension; PDRIVER_OBJECT driverObject = ftRootExtension->ObjectUnion.FtDriverObject; ULONG recognizedPartition = 0; ULONG partitionNumber; PPARTITION_INFORMATION partitionEntry; UCHAR ntNameBuffer[64]; UCHAR ftNameBuffer[64]; NTSTATUS status; // // Get partition list from IRP. // partitionList = Irp->AssociatedIrp.SystemBuffer; for (partitionNumber = 0; partitionNumber < partitionList->PartitionCount; partitionNumber++) { // // Get pointer to partition entry. // partitionEntry = &partitionList->PartitionEntry[partitionNumber]; // // Check if partition entry describes a partition. // if ((partitionEntry->PartitionType != PARTITION_ENTRY_UNUSED) && !IsContainerPartition(partitionEntry->PartitionType)) { // // Bump count of recognized partitions. // recognizedPartition++; // // Check if this partition entry has changed. // if (partitionEntry->RewritePartition) { // // Create NT device name for this partition. // sprintf(ntNameBuffer, "\\Device\\Harddisk%d\\Partition%d", deviceExtension->FtUnion.Identity.DiskNumber, recognizedPartition); sprintf(ftNameBuffer, "\\Device\\Harddisk%d\\Ft%d", deviceExtension->FtUnion.Identity.DiskNumber, recognizedPartition); status = FtpAttach(driverObject, ftNameBuffer, ntNameBuffer, &deviceExtension); if (!NT_SUCCESS(status)) { DebugPrint((1, "FtpAttachDevices: Couldn't attach to %s status %x\n", ntNameBuffer, status)); } } // end if (partitionEntry->RewritePartition) } // end if (partitionEntry->PartitionType ...) } // end for (partitionNumber ...) return STATUS_SUCCESS; } // end FtpAttachDevices()