[DISK]
[reactos.git] / reactos / drivers / storage / class / disk / disk.c
index eee8624..ffdd3b5 100644 (file)
 #include <ntddscsi.h>
 #include <mountdev.h>
 #include <mountmgr.h>
+#include <ntiologc.h>
 #include <include/class2.h>
 #include <stdio.h>
 
 #define NDEBUG
 #include <debug.h>
 
-#define IO_WRITE_CACHE_ENABLED  ((NTSTATUS)0x80040020L)
-#define IO_WRITE_CACHE_DISABLED ((NTSTATUS)0x80040022L)
 
 #ifdef POOL_TAGGING
 #ifdef ExAllocatePool
@@ -68,7 +67,7 @@ typedef struct _DISK_DATA {
     // Partition number of this device object
     //
     // This field is set during driver initialization or when the partition
-    // is created to identify a parition to the system.
+    // is created to identify a partition to the system.
     //
 
     ULONG PartitionNumber;
@@ -105,7 +104,7 @@ typedef struct _DISK_DATA {
     BOOLEAN BootIndicator;
 
     //
-    // DriveNotReady - inidicates that the this device is currenly not ready
+    // DriveNotReady - indicates that the this device is currently not ready
     // because there is no media in the device.
     //
 
@@ -120,7 +119,7 @@ typedef struct _DISK_DATA {
 } DISK_DATA, *PDISK_DATA;
 
 //
-// Define a general structure of identfing disk controllers with bad
+// Define a general structure of identifying disk controllers with bad
 // hardware.
 //
 
@@ -385,11 +384,6 @@ Return Value:
     InitializationData.ClassShutdownFlush = ScsiDiskShutdownFlush;
     InitializationData.ClassCreateClose = NULL;
 
-    //
-    // HACK! Please check below to the implementation of the function
-    //
-    DriverObject->MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = ScsiDiskFileSystemControl;
-
     //
     // Call the class init routine
     //
@@ -511,7 +505,6 @@ Return Value:
     // SRB zone elements to allocate.
     //
 
-    adapterDisk = 0;
     adapterInfo = (PVOID) buffer;
 
     adapterDisk = ScsiClassFindUnclaimedDevices(InitializationData, adapterInfo);
@@ -992,7 +985,7 @@ Return Value:
     status = ScsiClassReadDriveCapacity(deviceObject);
 
     //
-    // If the read capcity failed then just return, unless this is a
+    // If the read capacity failed then just return, unless this is a
     // removable disk where a device object partition needs to be created.
     //
 
@@ -1145,7 +1138,7 @@ CreatePartitionDeviceObjects(
         physicalDeviceExtension->DMByteSkew = physicalDeviceExtension->DMSkew * bytesPerSector;
 
         //
-        // Save away the infomation that we need, since this deviceExtension will soon be
+        // Save away the information that we need, since this deviceExtension will soon be
         // blown away.
         //
 
@@ -1254,7 +1247,7 @@ CreatePartitionDeviceObjects(
         if (!initData)
         {
             DebugPrint((1,
-                        "Disk.CreatePartionDeviceObjects - Allocation of initData failed\n"));
+                        "Disk.CreatePartitionDeviceObjects - Allocation of initData failed\n"));
 
             status = STATUS_INSUFFICIENT_RESOURCES;
             goto CreatePartitionDeviceObjectsExit;
@@ -1519,6 +1512,15 @@ Return Value:
     ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
     LARGE_INTEGER startingOffset;
 
+    //
+    // HACK: How can we end here with null sector size?!
+    //
+
+    if (deviceExtension->DiskGeometry->Geometry.BytesPerSector == 0) {
+        DPRINT1("Hack! Received invalid sector size\n");
+        deviceExtension->DiskGeometry->Geometry.BytesPerSector = 512;
+    }
+
     //
     // Verify parameters of this request.
     // Check that ending sector is within partition and
@@ -1539,7 +1541,7 @@ Return Value:
         if (((PDISK_DATA)(deviceExtension + 1))->DriveNotReady) {
 
             //
-            // Flag this as a user errror so that a popup is generated.
+            // Flag this as a user error so that a popup is generated.
             //
 
             Irp->IoStatus.Status = STATUS_DEVICE_NOT_READY;
@@ -1555,7 +1557,18 @@ Return Value:
             Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
         }
 
-        DPRINT1("STATUS_INVALID_PARAMETER\n");
+        if (startingOffset.QuadPart > deviceExtension->PartitionLength.QuadPart) {
+            DPRINT1("Reading beyond partition end! startingOffset: %I64d, PartitionLength: %I64d\n", startingOffset.QuadPart, deviceExtension->PartitionLength.QuadPart);
+        }
+
+        if (transferByteCount & (deviceExtension->DiskGeometry->Geometry.BytesPerSector - 1)) {
+            DPRINT1("Not reading sectors! TransferByteCount: %lu, BytesPerSector: %lu\n", transferByteCount, deviceExtension->DiskGeometry->Geometry.BytesPerSector);
+        }
+
+        if (Irp->IoStatus.Status == STATUS_DEVICE_NOT_READY) {
+            DPRINT1("Failing due to device not ready!\n");
+        }
+
         return STATUS_INVALID_PARAMETER;
     }
 
@@ -2041,16 +2054,27 @@ Return Value:
         PDISK_DATA        physicalDiskData;
         BOOLEAN           removable = FALSE;
         BOOLEAN           listInitialized = FALSE;
+        ULONG             copyLength;
 
-        if ((irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY &&
-             irpStack->Parameters.DeviceIoControl.OutputBufferLength <
-            sizeof(DISK_GEOMETRY)) ||
-             (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY_EX &&
-             irpStack->Parameters.DeviceIoControl.OutputBufferLength <
-            sizeof(DISK_GEOMETRY_EX))) {
+        if (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) {
+            if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY)) {
+                status = STATUS_BUFFER_TOO_SMALL;
+                break;
+            }
 
-            status = STATUS_INFO_LENGTH_MISMATCH;
-            break;
+            copyLength = sizeof(DISK_GEOMETRY);
+        } else {
+            ASSERT(irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY_EX);
+            if (irpStack->Parameters.DeviceIoControl.OutputBufferLength < FIELD_OFFSET(DISK_GEOMETRY_EX, Data)) {
+                status = STATUS_BUFFER_TOO_SMALL;
+                break;
+            }
+
+            if (irpStack->Parameters.DeviceIoControl.OutputBufferLength >= sizeof(DISK_GEOMETRY_EX)) {
+                copyLength = sizeof(DISK_GEOMETRY_EX);
+            } else {
+                copyLength = FIELD_OFFSET(DISK_GEOMETRY_EX, Data);
+            }
         }
 
         status = STATUS_SUCCESS;
@@ -2093,7 +2117,7 @@ Return Value:
 
         } else if (NT_SUCCESS(status)) {
 
-            // ReadDriveCapacity was allright, create Partition Objects
+            // ReadDriveCapacity was alright, create Partition Objects
 
             if (physicalDiskData->PartitionListState == NotInitialized) {
                     status = CreatePartitionDeviceObjects(deviceExtension->PhysicalDevice, NULL);
@@ -2108,15 +2132,10 @@ Return Value:
 
             RtlMoveMemory(Irp->AssociatedIrp.SystemBuffer,
                           deviceExtension->DiskGeometry,
-                          (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) ?
-                          sizeof(DISK_GEOMETRY) :
-                          sizeof(DISK_GEOMETRY_EX));
+                          copyLength);
 
             status = STATUS_SUCCESS;
-            Irp->IoStatus.Information =
-               (irpStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_DISK_GET_DRIVE_GEOMETRY) ?
-               sizeof(DISK_GEOMETRY) :
-               sizeof(DISK_GEOMETRY_EX);
+            Irp->IoStatus.Information = copyLength;
         }
 
         break;
@@ -2222,7 +2241,7 @@ Return Value:
         else if (diskData->PartitionNumber == 0) {
 
             //
-            // Paritition zero is not a partition so this is not a
+            // Partition zero is not a partition so this is not a
             // reasonable request.
             //
 
@@ -2234,6 +2253,11 @@ Return Value:
 
             PPARTITION_INFORMATION outputBuffer;
 
+            if (diskData->PartitionNumber == 0) {
+                DPRINT1("HACK: Handling partition 0 request!\n");
+                //ASSERT(FALSE);
+            }
+
             //
             // Update the geometry in case it has changed.
             //
@@ -2255,12 +2279,6 @@ Return Value:
             //
 
             diskData->DriveNotReady = FALSE;
-// HACK: ReactOS partition numbers must be wrong (>0 part)
-            if (diskData->PartitionType == 0 && (diskData->PartitionNumber > 0)) {
-
-                status = STATUS_INVALID_DEVICE_REQUEST;
-                break;
-            }
 
             outputBuffer =
                     (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
@@ -2297,20 +2315,27 @@ Return Value:
             status = STATUS_INFO_LENGTH_MISMATCH;
 
         }
+#if 0 // HACK: ReactOS partition numbers must be wrong
         else if (diskData->PartitionNumber == 0) {
 
             //
-            // Paritition zero is not a partition so this is not a
+            // Partition zero is not a partition so this is not a
             // reasonable request.
             //
 
             status = STATUS_INVALID_DEVICE_REQUEST;
 
         }
+#endif
         else {
 
             PPARTITION_INFORMATION_EX outputBuffer;
 
+            if (diskData->PartitionNumber == 0) {
+                DPRINT1("HACK: Handling partition 0 request!\n");
+                //ASSERT(FALSE);
+            }
+
             //
             // Update the geometry in case it has changed.
             //
@@ -2446,7 +2471,7 @@ Return Value:
             //
             // The disk layout has been returned in the partitionList
             // buffer.  Determine its size and, if the data will fit
-            // into the intermediatery buffer, return it.
+            // into the intermediary buffer, return it.
             //
 
             tempSize = FIELD_OFFSET(DRIVE_LAYOUT_INFORMATION,PartitionEntry[0]);
@@ -2504,7 +2529,7 @@ Return Value:
                     partitionEntry = &partitionList->PartitionEntry[i];
 
                     //
-                    // Check if empty, or describes extended partiton or hasn't changed.
+                    // Check if empty, or describes extended partition or hasn't changed.
                     //
 
                     if (partitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
@@ -3001,7 +3026,7 @@ Return Value:
                                              0,
                                              TRUE);
 
-        DebugPrint((1, "ScsiDiskShutdownFlush: Synchonize cache sent. Status = %lx\n", status ));
+        DebugPrint((1, "ScsiDiskShutdownFlush: Synchronize cache sent. Status = %lx\n", status ));
     }
 
     //
@@ -3095,7 +3120,7 @@ Routine Description:
 
     The routine performs the necessary functions to determine if a device is
     really a floppy rather than a harddisk.  This is done by a mode sense
-    command.  First, a check is made to see if the medimum type is set.  Second
+    command.  First, a check is made to see if the media type is set.  Second
     a check is made for the flexible parameters mode page.  Also a check is
     made to see if the write cache is enabled.
 
@@ -3702,7 +3727,7 @@ EnumerateBusKey(
 Routine Description:
 
     The routine queries the registry to determine if this disk is visible to
-    the BIOS.  If the disk is visable to the BIOS, then the geometry information
+    the BIOS.  If the disk is visible to the BIOS, then the geometry information
     is updated.
 
 Arguments:
@@ -3979,7 +4004,7 @@ Return Value:
                 ExFreePool(keyData);
 
                 //
-                // Readjust indentifier string if necessary.
+                // Readjust identifier string if necessary.
                 //
 
                 if (!diskData->MbrCheckSum) {
@@ -4015,7 +4040,7 @@ UpdateGeometry(
 Routine Description:
 
     The routine queries the registry to determine if this disk is visible to
-    the BIOS.  If the disk is visable to the BIOS, then the geometry information
+    the BIOS.  If the disk is visible to the BIOS, then the geometry information
     is updated.
 
 Arguments:
@@ -4173,7 +4198,7 @@ diskMatched:
 
     //
     // Check that the data is long enough to hold a full resource descriptor,
-    // and that the last resouce list is device-specific and long enough.
+    // and that the last resource list is device-specific and long enough.
     //
 
     if (keyData->DataLength < sizeof(CM_FULL_RESOURCE_DESCRIPTOR) ||
@@ -4264,7 +4289,7 @@ diskMatched:
     DeviceExtension->DiskGeometry->Geometry.SectorsPerTrack = sectorsPerTrack;
     DeviceExtension->DiskGeometry->Geometry.TracksPerCylinder = tracksPerCylinder;
     DeviceExtension->DiskGeometry->Geometry.Cylinders.QuadPart = (LONGLONG)cylinders;
-    DeviceExtension->DiskGeometry->DiskSize.QuadPart = cylinders * tracksPerCylinder * sectorsPerTrack *
+    DeviceExtension->DiskGeometry->DiskSize.QuadPart = (LONGLONG)cylinders * tracksPerCylinder * sectorsPerTrack *
                                                        DeviceExtension->DiskGeometry->Geometry.BytesPerSector;
 
     DebugPrint((3,
@@ -4368,7 +4393,7 @@ Arguments:
 
 Return Value:
 
-    Returns the status of the opertion.
+    Returns the status of the operation.
 
 --*/
 {
@@ -4398,7 +4423,7 @@ Return Value:
     diskData = (PDISK_DATA) (deviceExtension + 1);
 
     //
-    // Read the drive capcity.  If that fails, give up.
+    // Read the drive capacity.  If that fails, give up.
     //
 
     status = ScsiClassReadDriveCapacity(deviceExtension->PhysicalDevice);
@@ -4408,7 +4433,7 @@ Return Value:
     }
 
     //
-    // Read the partition table agian.
+    // Read the partition table again.
     //
 
     status = IoReadPartitionTable(deviceExtension->PhysicalDevice,
@@ -4432,7 +4457,7 @@ Return Value:
         partitionNumber = diskData->PartitionNumber - 1;
 
         //
-        // Update the partition information for this parition.
+        // Update the partition information for this partition.
         //
 
         diskData->PartitionType =
@@ -4456,7 +4481,7 @@ Return Value:
     } else if (diskData->PartitionNumber != 0) {
 
         //
-        // The paritition does not exist.  Zero all the data.
+        // The partition does not exist.  Zero all the data.
         //
 
         diskData->PartitionType = 0;
@@ -4467,7 +4492,7 @@ Return Value:
     }
 
     //
-    // Free the parition list allocate by I/O read partition table.
+    // Free the partition list allocate by I/O read partition table.
     //
 
     ExFreePool(partitionList);
@@ -4553,7 +4578,7 @@ ScanForSpecial(
 
 Routine Description:
 
-    This function checks to see if an SCSI logical unit requires speical
+    This function checks to see if an SCSI logical unit requires special
     flags to be set.
 
 Arguments:
@@ -4865,7 +4890,7 @@ Return Value:
             partitionEntry = &partitionList->PartitionEntry[partition];
 
             //
-            // Check if empty, or describes extended partiton or hasn't changed.
+            // Check if empty, or describes extended partition or hasn't changed.
             //
 
             if (partitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
@@ -4975,7 +5000,7 @@ Return Value:
         partitionEntry = &partitionList->PartitionEntry[partition];
 
         //
-        // Check if empty, or describes an extended partiton.
+        // Check if empty, or describes an extended partition.
         //
 
         if (partitionEntry->PartitionType == PARTITION_ENTRY_UNUSED ||
@@ -5214,116 +5239,3 @@ Return Value:
 
 } // end UpdateDeviceObjects()
 
-//
-// This function is supposed only to support NTFS tools
-// from M. Russinovich. This is kind of huge hack and is
-// totally undocumented :-).
-//
-NTSTATUS
-NtfsRussinovichism(PDEVICE_OBJECT DeviceObject,
-                   PIRP Irp)
-{
-#define FSCTL_GET_VOLUME_INFORMATION 0x90064
-    typedef struct {   
-        LARGE_INTEGER       SerialNumber;   
-        LARGE_INTEGER       NumberOfSectors;   
-        LARGE_INTEGER       TotalClusters;   
-        LARGE_INTEGER       FreeClusters;   
-        LARGE_INTEGER       Reserved;   
-        ULONG               BytesPerSector;   
-        ULONG               BytesPerCluster;   
-        ULONG               BytesPerMFTRecord;   
-        ULONG               ClustersPerMFTRecord;   
-        LARGE_INTEGER       MFTLength;   
-        LARGE_INTEGER       MFTStart;   
-        LARGE_INTEGER       MFTMirrorStart;   
-        LARGE_INTEGER       MFTZoneStart;   
-        LARGE_INTEGER       MFTZoneEnd;   
-    } NTFS_VOLUME_DATA_BUFFER, *PNTFS_VOLUME_DATA_BUFFER;
-
-    PIO_STACK_LOCATION Stack;
-    NTSTATUS Status;
-    PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
-    PDISK_DATA diskData;
-
-    DPRINT1("NtfsRussinovichism(%p, %p)\n", DeviceObject, Irp);
-
-    Stack = IoGetCurrentIrpStackLocation(Irp);
-
-    switch (Stack->Parameters.FileSystemControl.FsControlCode)
-    {
-        case FSCTL_GET_VOLUME_INFORMATION:
-            //
-            // Check we received something we understand
-            //
-            if (Stack->Parameters.FileSystemControl.OutputBufferLength < sizeof(NTFS_VOLUME_DATA_BUFFER) ||
-                Irp->UserBuffer == NULL)
-            {
-                DPRINT1("Invalid output! %d %p\n", Stack->Parameters.FileSystemControl.OutputBufferLength, Irp->UserBuffer);
-                Status = STATUS_INVALID_PARAMETER;
-                break;
-            }
-
-            //
-            // Now, quickly check we are supposed to have a NTFS volume
-            //
-            diskData = (PDISK_DATA)(deviceExtension + 1);
-            if (diskData->PartitionType != PARTITION_IFS)
-            {
-                DPRINT1("Invalid partition type! %x\n", diskData->PartitionType);
-                Status = STATUS_INVALID_PARAMETER;
-                break;
-            }
-
-            UNIMPLEMENTED;
-            Status = STATUS_NOT_IMPLEMENTED;
-            break;
-
-        default:
-            Status = STATUS_INVALID_DEVICE_REQUEST;
-            break;
-    }
-
-    return Status;
-#undef FSCTL_GET_VOLUME_INFORMATION
-}
-
-//
-// Hack: this function is not supposed to be implemented
-// Even though it's required to enable some M. Russinovich
-// to directly request disks so that they can dump NTFS data
-// without going through the driver.
-// We don't expect doing more from here, hence the limited
-// implementation and support.
-//
-NTSTATUS
-NTAPI
-ScsiDiskFileSystemControl(PDEVICE_OBJECT DeviceObject,
-                          PIRP Irp)
-{
-    PIO_STACK_LOCATION Stack;
-    NTSTATUS Status;
-
-    DPRINT1("ScsiDiskFileSystemControl(%p, %p)\n", DeviceObject, Irp);
-
-    Stack = IoGetCurrentIrpStackLocation(Irp);
-
-    switch (Stack->MinorFunction)
-    {
-        case IRP_MN_USER_FS_REQUEST:
-            Status = NtfsRussinovichism(DeviceObject, Irp);
-            break;
-
-        default:
-            DPRINT("MinorFunction %d\n", Stack->MinorFunction);
-            Status = STATUS_INVALID_DEVICE_REQUEST;
-            break;
-    }
-
-    Irp->IoStatus.Status = Status;
-    Irp->IoStatus.Information = 0;
-
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return Status;
-}