Beispiel #1
0
// 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 */);
}
Beispiel #2
0
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;
}
Beispiel #3
0
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);
}
Beispiel #4
0
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;
}
Beispiel #5
0
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()