⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 geometry.c

📁 The Disk sample is used with Classpnp.sys as disk driver. The sample supports Plug and Play, Power M
💻 C
📖 第 1 页 / 共 3 页
字号:
    //

    irp = IoAllocateIrp(commonExtension->LowerDeviceObject->StackSize, FALSE);

    if(irp == NULL) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    irpStack = IoGetNextIrpStackLocation(irp);

    irpStack->MajorFunction = IRP_MJ_DEVICE_CONTROL;

    irpStack->Parameters.DeviceIoControl.IoControlCode = 
        IOCTL_DISK_GET_DRIVE_GEOMETRY;
    irpStack->Parameters.DeviceIoControl.OutputBufferLength = 
        sizeof(DISK_GEOMETRY);

    irp->AssociatedIrp.SystemBuffer = Geometry;

    KeInitializeEvent(&event, SynchronizationEvent, FALSE);

    IoSetCompletionRoutine(irp, 
                           ClassSignalCompletion,
                           &event,
                           TRUE,
                           TRUE,
                           TRUE);

    status = IoCallDriver(commonExtension->LowerDeviceObject, irp);
    KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);

    ASSERT((status == STATUS_PENDING) || (status == irp->IoStatus.Status));
    status = irp->IoStatus.Status;

    IoFreeIrp(irp);

    return status;
}



NTSTATUS
DiskReadDriveCapacity(
    IN PDEVICE_OBJECT Fdo
    )
/*++

Routine Description:

    This routine is used by disk.sys as a wrapper for the classpnp API 
    ClassReadDriveCapacity.  It will perform some additional operations to 
    attempt to determine drive geometry before it calls the classpnp version 
    of the routine.
    
    For fixed disks this involves calling DiskUpdateGeometry which will check 
    various sources (the BIOS, the port driver) for geometry information.
    
Arguments:

    Fdo - a pointer to the device object to be checked.    

Return Value:

    status of ClassReadDriveCapacity.
    
--*/        

{
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
    PDISK_DATA diskData = fdoExtension->CommonExtension.DriverData;
    DISK_GEOMETRY_SOURCE diskGeometrySource = DiskGeometryUnknown;
    NTSTATUS status;

    ASSERT_FDO(Fdo);

    if (TEST_FLAG(Fdo->Characteristics, FILE_REMOVABLE_MEDIA)) {
        DiskUpdateRemovableGeometry(fdoExtension);
    } else {
        diskGeometrySource = DiskUpdateGeometry(fdoExtension);
    }

    status = ClassReadDriveCapacity(Fdo);

    return status;
}



VOID
DiskDriverReinitialization(
    IN PDRIVER_OBJECT DriverObject,
    IN PVOID Nothing,
    IN ULONG Count
    )
/*++

Routine Description:

    This routine will scan through the current list of disks and attempt to 
    match them to any remaining geometry information.  This will only be done 
    on the first call to the routine.

    Note: This routine assumes that the system will not be adding or removing
          devices during this phase of the init process.  This is very likely
          a bad assumption but it greatly simplifies the code.

Arguments:

    DriverObject - a pointer to the object for the disk driver.
    
    Nothing - unused
    
    Count - an indication of how many times this routine has been called.
    
Return Value:

    none

--*/

{
    PDEVICE_OBJECT deviceObject;
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension;
    PDISK_DATA diskData;

    ULONG unmatchedDiskCount;
    PDEVICE_OBJECT unmatchedDisk = NULL;

    ULONG i;
    PDISK_DETECT_INFO diskInfo = NULL;

    if(Count != 1) {
        DebugPrint((1, "DiskDriverReinitialization: ignoring call %d\n", 
                    Count));
        return;
    }

    //
    // Check to see how many entries in the detect info list have been matched.
    // If there's only one remaining we'll see if we can find a disk to go with
    // it.
    //

    if(DetectInfoCount == 0) {
        DebugPrint((1, "DiskDriverReinitialization: no detect info saved\n"));
        return;
    }

    if((DetectInfoCount - DetectInfoUsedCount) != 1) {
        DebugPrint((1, "DiskDriverReinitialization: %d of %d geometry entries "
                       "used - will not attempt match\n"));
        return;
    }

    //
    // Scan through the list of disks and see if any of them are missing
    // geometry information.  If there is only one such disk we'll try to 
    // match it to the unmatched geometry.
    //
    
    
    //
    // ISSUE-2000/5/24-henrygab - figure out if there's a way to keep
    //                            removals from happening while doing this.
    //

    for(deviceObject = DriverObject->DeviceObject, unmatchedDiskCount = 0;
        deviceObject != NULL;
        deviceObject = deviceObject->NextDevice) {

        //
        // Make sure this is a disk and not a partition.
        //

        fdoExtension = deviceObject->DeviceExtension;
        if(fdoExtension->CommonExtension.IsFdo == FALSE) {
            DebugPrint((1, "DiskDriverReinit: DO %#p is not an FDO\n", 
                           deviceObject));
            continue;
        }

        //
        // If the geometry for this one is already known then skip it.
        //

        diskData = fdoExtension->CommonExtension.DriverData;
        if(diskData->GeometrySource != DiskGeometryUnknown) {
            DebugPrint((1, "DiskDriverReinit: FDO %#p has a geometry\n", 
                           deviceObject));
            continue;
        }

        DebugPrint((1, "DiskDriverReinit: FDO %#p has no geometry\n",
                       deviceObject));

        //
        // Mark this one as using the default.  It's past the time when disk
        // might blunder across the geometry info.  If we set the geometry 
        // from the bios we'll reset this field down below.
        //

        diskData->GeometrySource = DiskGeometryFromDefault;

        //
        // As long as we've only got one unmatched disk we're fine.
        //

        unmatchedDiskCount++;
        if(unmatchedDiskCount > 1) {
            ASSERT(unmatchedDisk != NULL);
            DebugPrint((1, "DiskDriverReinit: FDO %#p also has no geometry\n",
                           unmatchedDisk));
            unmatchedDisk = NULL;
            break;
        }

        unmatchedDisk = deviceObject;
    }

    //
    // If there's more or less than one ungeometried disk then we can't do 
    // anything about the geometry.
    //

    if(unmatchedDiskCount != 1) {
        DebugPrint((1, "DiskDriverReinit: Unable to match geometry\n"));
        return;

    }

    fdoExtension = unmatchedDisk->DeviceExtension;
    diskData = fdoExtension->CommonExtension.DriverData;

    DebugPrint((1, "DiskDriverReinit: Found possible match\n"));

    //
    // Find the geometry which wasn't assigned.
    //

    for(i = 0; i < DetectInfoCount; i++) {
        if(DetectInfoList[i].Device == NULL) {
            diskInfo = &(DetectInfoList[i]);
            break;
        }
    }

    ASSERT(diskInfo != NULL);

    {
        //
        // Save the geometry information away in the disk data block and 
        // set the bit indicating that we found a valid one.
        //

        ULONG cylinders;
        ULONG sectorsPerTrack;
        ULONG tracksPerCylinder;

        ULONG sectors;
        ULONG length;

        //
        // Point to the array of drive parameters.
        //
        
        cylinders = diskInfo->DriveParameters.MaxCylinders + 1;
        sectorsPerTrack = diskInfo->DriveParameters.SectorsPerTrack;
        tracksPerCylinder = diskInfo->DriveParameters.MaxHeads + 1;

        //
        // Since the BIOS may not report the full drive, recalculate the drive
        // size based on the volume size and the BIOS values for tracks per
        // cylinder and sectors per track..
        //
    
        length = tracksPerCylinder * sectorsPerTrack;
    
        if (length == 0) {
    
            //
            // The BIOS information is bogus.
            //
    
            DebugPrint((1, "DiskDriverReinit: H (%d) or S(%d) is zero\n",
                        tracksPerCylinder, sectorsPerTrack));
            return;
        }
    
        //
        // since we are copying the structure RealGeometry here, we should
        // really initialize all the fields, especially since a zero'd
        // BytesPerSector field would cause a trap in xHalReadPartitionTable()
        //
        
        diskData->RealGeometry = fdoExtension->DiskGeometry;
        
        //
        // Save the geometry information away in the disk data block and 
        // set the bit indicating that we found a valid one.
        //
    
        diskData->RealGeometry.SectorsPerTrack = sectorsPerTrack;
        diskData->RealGeometry.TracksPerCylinder = tracksPerCylinder;
        diskData->RealGeometry.Cylinders.QuadPart = (LONGLONG)cylinders;

        DebugPrint((1, "DiskDriverReinit: BIOS spt %#x, #heads %#x, "
                       "#cylinders %#x\n",
                   sectorsPerTrack, tracksPerCylinder, cylinders));

        diskData->GeometrySource = DiskGeometryGuessedFromBios;
        diskInfo->Device = unmatchedDisk;

        //
        // Now copy the geometry over to the fdo extension and call 
        // classpnp to redetermine the disk size and cylinder count.
        //

        fdoExtension->DiskGeometry = diskData->RealGeometry;
        
        //
        // BUGBUG - why not call DiskReadDriveCapacity()?
        //

        ClassReadDriveCapacity(unmatchedDisk);

        if (diskData->RealGeometry.BytesPerSector == 0) {

            //
            // if the BytesPerSector field is set to zero for a disk
            // listed in the bios, then the system will bugcheck in
            // xHalReadPartitionTable().  assert here since it is
            // easier to determine what is happening this way.
            //

            ASSERT(!"RealGeometry not set to non-zero bps\n");
        }
    }

    return;
}


NTSTATUS
DiskGetDetectInfo(
    IN PFUNCTIONAL_DEVICE_EXTENSION FdoExtension,
    OUT PDISK_DETECTION_INFO DetectInfo
    )
/*++

Routine Description:

    Get the Int13 information from the BIOS DetectInfoList.

Arguments:

    FdoExtension - Supplies a pointer to the FDO extension that we want to
            obtain the detect information for.

    DetectInfo - A buffer where the detect information will be copied to.

Return Value:

    NTSTATUS code.

--*/
{
    ULONG i;
    BOOLEAN found;
    PDISK_DETECT_INFO diskInfo;
    PDISK_DATA diskData = FdoExtension->CommonExtension.DriverData;

    PAGED_CODE ();

    ASSERT(FdoExtension->CommonExtension.IsFdo);

    //
    // Fail for non-fixed drives.
    //
    
    if (TEST_FLAG (FdoExtension->DeviceObject->Characteristics, FILE_REMOVABLE_MEDIA)) {
        return STATUS_NOT_SUPPORTED;
    }

    //
    // There is no GPT detection info, so fail this.
    //
    
    if (diskData->PartitionStyle == PARTITION_STYLE_GPT) {
        return STATUS_NOT_SUPPORTED;
    }

    for(i = 0; i < DetectInfoCount; i++) {

        
        ASSERT(DetectInfoList != NULL);

        diskInfo = &(DetectInfoList[i]);

        if((diskData->Mbr.Signature != 0) && 
           (diskData->Mbr.Signature == diskInfo->Signature)) { 
            DebugPrint((1, "DiskGetDetectInfo: found match for signature "
                           "%#08lx\n",
                        diskData->Mbr.Signature));
            found = TRUE;
            break;
        } else if((diskData->Mbr.Signature == 0) && 
                  (diskData->Mbr.MbrCheckSum != 0) &&
                  (diskData->Mbr.MbrCheckSum == diskInfo->MbrCheckSum)) {
            DebugPrint((1, "DiskGetDetectInfo: found match for xsum %#08lx\n",
                        diskData->Mbr.MbrCheckSum));
            found = TRUE;
            break;
        }
    }

    if ( found ) {
        DetectInfo->DetectionType = DetectInt13;
        DetectInfo->Int13.DriveSelect = diskInfo->DriveParameters.DriveSelect;
        DetectInfo->Int13.MaxCylinders = diskInfo->DriveParameters.MaxCylinders;
        DetectInfo->Int13.SectorsPerTrack = diskInfo->DriveParameters.SectorsPerTrack;
        DetectInfo->Int13.MaxHeads = diskInfo->DriveParameters.MaxHeads;
        DetectInfo->Int13.NumberDrives = diskInfo->DriveParameters.NumberDrives;
        RtlZeroMemory (&DetectInfo->ExInt13, sizeof (DetectInfo->ExInt13));
    }

    return (found ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL);
}


NTSTATUS
DiskReadSignature(
    IN PDEVICE_OBJECT Fdo
    )

/*++

Routine Description:

    Read the disks signature from the drive. The signature can be either
    a MBR signature or a GPT/EFI signature.

    The low-level signature reading is done by IoReadDiskSignature().

Arguments:

    Fdo - Pointer to the FDO of a disk to read the signature for.
    
Return Value:

    NTSTATUS code.

--*/


{
    NTSTATUS Status;
    PFUNCTIONAL_DEVICE_EXTENSION fdoExtension = Fdo->DeviceExtension;
    PDISK_DATA diskData = fdoExtension->CommonExtension.DriverData;
    DISK_SIGNATURE Signature;

    PAGED_CODE ();
    
    Status = IoReadDiskSignature (Fdo,
                                  fdoExtension->DiskGeometry.BytesPerSector,
                                  &Signature);

    if (!NT_SUCCESS (Status)) {
        return Status;
    }
    
    if (Signature.PartitionStyle == PARTITION_STYLE_GPT) {
        diskData->PartitionStyle = PARTITION_STYLE_GPT;
        diskData->Efi.DiskId = Signature.Gpt.DiskId;
    } else if (Signature.PartitionStyle == PARTITION_STYLE_MBR) {
        diskData->PartitionStyle = PARTITION_STYLE_MBR;
        diskData->Mbr.Signature = Signature.Mbr.Signature;
        diskData->Mbr.MbrCheckSum = Signature.Mbr.CheckSum;
    } else {
        ASSERT (FALSE);
        Status = STATUS_UNSUCCESSFUL;
    }

    return Status;
}

#endif // defined(_X86_)


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -