[DISK] Properly implement querying partition information for partition 0.
[reactos.git] / drivers / storage / class / disk / disk.c
index fd3a475..cb84565 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.
 //
 
@@ -310,6 +309,11 @@ ResetScsiBus(
     IN PDEVICE_OBJECT DeviceObject
     );
 
+NTSTATUS
+NTAPI
+ScsiDiskFileSystemControl(PDEVICE_OBJECT DeviceObject,
+                          PIRP Irp);
+
 #ifdef ALLOC_PRAGMA
 #pragma alloc_text(PAGE, DriverEntry)
 #pragma alloc_text(PAGE, FindScsiDisks)
@@ -501,7 +505,6 @@ Return Value:
     // SRB zone elements to allocate.
     //
 
-    adapterDisk = 0;
     adapterInfo = (PVOID) buffer;
 
     adapterDisk = ScsiClassFindUnclaimedDevices(InitializationData, adapterInfo);
@@ -982,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.
     //
 
@@ -1135,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.
         //
 
@@ -1183,7 +1186,7 @@ CreatePartitionDeviceObjects(
         // Allocate and zero a partition list.
         //
 
-        partitionList = ExAllocatePool(NonPagedPool, sizeof(*partitionList ));
+        partitionList = ExAllocatePool(NonPagedPool, sizeof(*partitionList));
 
 
         if (partitionList != NULL) {
@@ -1244,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;
@@ -1446,6 +1449,10 @@ CreatePartitionDeviceObjects(
 
         ExFreePool(partitionList);
 
+        if (dmSkew) {
+            ExFreePool(dmSkew);
+        }
+
     } else {
 
 CreatePartitionDeviceObjectsExit:
@@ -1457,6 +1464,10 @@ CreatePartitionDeviceObjectsExit:
             ExFreePool(initData);
         }
 
+        if (dmSkew) {
+            ExFreePool(dmSkew);
+        }
+
         return status;
 
     } // end if...else
@@ -1501,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
@@ -1521,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;
@@ -1537,6 +1557,18 @@ Return Value:
             Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
         }
 
+        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;
     }
 
@@ -1909,7 +1941,7 @@ Return Value:
                 case EXECUTE_OFFLINE_DIAGS:
                     controlCode = IOCTL_SCSI_MINIPORT_EXECUTE_OFFLINE_DIAGS;
                     break;
-      
+
           default:
                     status = STATUS_INVALID_PARAMETER;
                     break;
@@ -2022,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;
@@ -2074,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);
@@ -2089,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;
@@ -2197,59 +2235,69 @@ Return Value:
             sizeof(PARTITION_INFORMATION)) {
 
             status = STATUS_INFO_LENGTH_MISMATCH;
-
+            break;
         }
-#if 0 // HACK: ReactOS partition numbers must be wrong
-        else if (diskData->PartitionNumber == 0) {
+
+        //
+        // Update the geometry in case it has changed.
+        //
+
+        status = UpdateRemovableGeometry (DeviceObject, Irp);
+
+        if (!NT_SUCCESS(status)) {
 
             //
-            // Paritition zero is not a partition so this is not a
-            // reasonable request.
+            // Note the drive is not ready.
             //
 
-            status = STATUS_INVALID_DEVICE_REQUEST;
-
+            diskData->DriveNotReady = TRUE;
+            break;
         }
-#endif
-        else {
+
+        //
+        // Note the drive is now ready.
+        //
+
+        diskData->DriveNotReady = FALSE;
+
+        //
+        // Handle the case were we query the whole disk
+        //
+
+        if (diskData->PartitionNumber == 0) {
 
             PPARTITION_INFORMATION outputBuffer;
 
-            //
-            // Update the geometry in case it has changed.
-            //
+            outputBuffer =
+                    (PPARTITION_INFORMATION)Irp->AssociatedIrp.SystemBuffer;
 
-            status = UpdateRemovableGeometry (DeviceObject, Irp);
+            outputBuffer->PartitionType = PARTITION_ENTRY_UNUSED;
+            outputBuffer->StartingOffset = deviceExtension->StartingOffset;
+            outputBuffer->PartitionLength.QuadPart = deviceExtension->PartitionLength.QuadPart;
+            outputBuffer->HiddenSectors = 0;
+            outputBuffer->PartitionNumber = diskData->PartitionNumber;
+            outputBuffer->BootIndicator = FALSE;
+            outputBuffer->RewritePartition = FALSE;
+            outputBuffer->RecognizedPartition = FALSE;
 
-            if (!NT_SUCCESS(status)) {
+            status = STATUS_SUCCESS;
+            Irp->IoStatus.Information = sizeof(PARTITION_INFORMATION);
 
-                //
-                // Note the drive is not ready.
-                //
+        } else {
 
-                diskData->DriveNotReady = TRUE;
-                break;
-            }
+            PPARTITION_INFORMATION outputBuffer;
 
             //
-            // Note the drive is now ready.
+            // We query a single partition here
+            // FIXME: this can only work for MBR-based disks, check for this!
             //
 
-            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;
 
             outputBuffer->PartitionType = diskData->PartitionType;
             outputBuffer->StartingOffset = deviceExtension->StartingOffset;
-            outputBuffer->PartitionLength.QuadPart = (diskData->PartitionNumber) ?
-                deviceExtension->PartitionLength.QuadPart : 2305843009213693951LL; // HACK
+            outputBuffer->PartitionLength.QuadPart = deviceExtension->PartitionLength.QuadPart;
             outputBuffer->HiddenSectors = diskData->HiddenSectors;
             outputBuffer->PartitionNumber = diskData->PartitionNumber;
             outputBuffer->BootIndicator = diskData->BootIndicator;
@@ -2278,20 +2326,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.
             //
@@ -2427,7 +2482,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]);
@@ -2485,7 +2540,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 ||
@@ -2982,7 +3037,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 ));
     }
 
     //
@@ -3076,7 +3131,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.
 
@@ -3683,7 +3738,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:
@@ -3877,6 +3932,17 @@ Return Value:
                 ZwClose(targetKey);
 
                 if (!NT_SUCCESS(status)) {
+                    ExFreePool(keyData);
+                    continue;
+                }
+
+                if (keyData->DataLength < 9*sizeof(WCHAR)) {
+                    //
+                    // the data is too short to use (we subtract 9 chars in normal path)
+                    //
+                    DebugPrint((1, "EnumerateBusKey: Saved data was invalid, "
+                                "not enough data in registry!\n"));
+                    ExFreePool(keyData);
                     continue;
                 }
 
@@ -3899,6 +3965,7 @@ Return Value:
                                                  TRUE);
 
                 if (!NT_SUCCESS(status)) {
+                    ExFreePool(keyData);
                     continue;
                 }
 
@@ -3960,7 +4027,7 @@ Return Value:
                 ExFreePool(keyData);
 
                 //
-                // Readjust indentifier string if necessary.
+                // Readjust identifier string if necessary.
                 //
 
                 if (!diskData->MbrCheckSum) {
@@ -3996,7 +4063,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:
@@ -4080,6 +4147,7 @@ Return Value:
         DebugPrint((1,
                    "SCSIDISK: ExtractBiosGeometry: Can't query configuration data (%x)\n",
                    status));
+        ZwClose(hardwareKey);
         ExFreePool(keyData);
         return;
     }
@@ -4154,7 +4222,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) ||
@@ -4245,7 +4313,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,
@@ -4349,7 +4417,7 @@ Arguments:
 
 Return Value:
 
-    Returns the status of the opertion.
+    Returns the status of the operation.
 
 --*/
 {
@@ -4379,7 +4447,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);
@@ -4389,7 +4457,7 @@ Return Value:
     }
 
     //
-    // Read the partition table agian.
+    // Read the partition table again.
     //
 
     status = IoReadPartitionTable(deviceExtension->PhysicalDevice,
@@ -4413,7 +4481,7 @@ Return Value:
         partitionNumber = diskData->PartitionNumber - 1;
 
         //
-        // Update the partition information for this parition.
+        // Update the partition information for this partition.
         //
 
         diskData->PartitionType =
@@ -4437,7 +4505,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;
@@ -4448,7 +4516,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);
@@ -4534,7 +4602,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:
@@ -4846,7 +4914,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 ||
@@ -4956,7 +5024,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 ||
@@ -5194,3 +5262,4 @@ Return Value:
     }
 
 } // end UpdateDeviceObjects()
+