Check for removable media and Partition length is 0, for DiskClassCheckReadWrite.
[reactos.git] / reactos / drivers / storage / disk / disk.c
index f4cf6d8..b0e8904 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ReactOS kernel
- *  Copyright (C) 2001, 2002, 2003 ReactOS Team
+ *  Copyright (C) 2001, 2002, 2003, 2004 ReactOS Team
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: disk.c,v 1.38 2004/03/31 05:25:36 jimtabor Exp $
+/* $Id$
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
  * FILE:            services/storage/disk/disk.c
  * PURPOSE:         disk class driver
- * PROGRAMMER:      Eric Kohl (ekohl@rz-online.de)
+ * PROGRAMMER:      Eric Kohl
  */
 
 /* INCLUDES *****************************************************************/
@@ -53,7 +53,7 @@ typedef struct _DISK_DATA
   BOOLEAN BootIndicator;
   BOOLEAN DriveNotReady;
 } DISK_DATA, *PDISK_DATA;
-    
+
 BOOLEAN STDCALL
 DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
                     PUNICODE_STRING RegistryPath,
@@ -218,7 +218,7 @@ DiskClassFindDevices(PDRIVER_OBJECT DriverObject,
   PCHAR Buffer;
   ULONG Bus;
   ULONG DeviceCount;
-  BOOLEAN FoundDevice;
+  BOOLEAN FoundDevice = FALSE;
   NTSTATUS Status;
 
   DPRINT("DiskClassFindDevices() called.\n");
@@ -390,6 +390,8 @@ DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
 {
   PDEVICE_EXTENSION DeviceExtension;
   PDISK_DATA DiskData;
+  PIO_STACK_LOCATION IrpStack;
+  ULARGE_INTEGER EndingOffset;
 
   DPRINT("DiskClassCheckReadWrite() called\n");
 
@@ -404,6 +406,32 @@ DiskClassCheckReadWrite(IN PDEVICE_OBJECT DeviceObject,
       return(STATUS_INVALID_PARAMETER);
     }
 
+
+
+  IrpStack = IoGetCurrentIrpStackLocation(Irp);  
+  EndingOffset.QuadPart = IrpStack->Parameters.Read.ByteOffset.QuadPart +
+                          IrpStack->Parameters.Read.Length;
+
+
+  DPRINT("Ending %I64d, and RealEnding %I64d! PartSize %I64d\n",EndingOffset.QuadPart,
+          DeviceExtension->PartitionLength.QuadPart,
+         DeviceExtension->PartitionLength.QuadPart /
+          DeviceExtension->DiskGeometry->BytesPerSector);
+
+  if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
+      (DeviceExtension->DiskGeometry->MediaType == RemovableMedia))
+    {
+/* Assume if removable media and if Partition length is 0, Partition not built yet! */
+       if (DeviceExtension->PartitionLength.QuadPart == 0)
+            return(STATUS_SUCCESS);
+    }
+
+  if (EndingOffset.QuadPart > DeviceExtension->PartitionLength.QuadPart)
+    {
+      Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
+      return(STATUS_INVALID_PARAMETER);
+    }
+
   return(STATUS_SUCCESS);
 }
 
@@ -548,6 +576,14 @@ DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
   DiskDeviceExtension->PathId = InquiryData->PathId;
   DiskDeviceExtension->TargetId = InquiryData->TargetId;
   DiskDeviceExtension->Lun = InquiryData->Lun;
+  DiskDeviceExtension->SrbFlags = 0;
+
+  /* Enable the command queueing, if it possible */
+  if (Capabilities->TaggedQueuing &&
+      ((PINQUIRYDATA)InquiryData->InquiryData)->CommandQueue)
+    {
+      DiskDeviceExtension->SrbFlags |= SRB_FLAGS_QUEUE_ACTION_ENABLE;
+    }
 
   /* Get timeout value */
   DiskDeviceExtension->TimeOutValue =
@@ -589,7 +625,7 @@ DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
     }
 
   /* Allocate sense data buffer */
-  DiskDeviceExtension->SenseData = ExAllocatePool(NonPagedPool,
+  DiskDeviceExtension->SenseData = ExAllocatePool(NonPagedPoolCacheAligned,
                                                  SENSE_BUFFER_SIZE);
   if (DiskDeviceExtension->SenseData == NULL)
     {
@@ -632,14 +668,12 @@ DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
 
   if ((DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
       (DiskDeviceExtension->DiskGeometry->MediaType == RemovableMedia))
-    { 
-
-       DiskClassCreateMediaChangeEvent(DiskDeviceExtension,DiskNumber); 
-       if(DiskDeviceExtension->MediaChangeEvent != NULL)
+    {
+      DiskClassCreateMediaChangeEvent(DiskDeviceExtension,DiskNumber); 
+      if (DiskDeviceExtension->MediaChangeEvent != NULL)
        {
-       DPRINT("Allocated media change event!\n");
+         DPRINT("Allocated media change event!\n");
        }
-
     }
 
   /* Check disk for presence of a disk manager */
@@ -660,9 +694,10 @@ DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
       ExFreePool(MbrBuffer);
       MbrBuffer = NULL;
     }
+
   if ((DiskDeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
       (DiskDeviceExtension->DiskGeometry->MediaType == RemovableMedia))
-    { 
+    {
       /* Allocate a partition list for a single entry. */
       PartitionList = ExAllocatePool(NonPagedPool,
                                     sizeof(DRIVE_LAYOUT_INFORMATION));
@@ -757,8 +792,10 @@ DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
                 PartitionEntry->PartitionNumber,
                 PartitionEntry->BootIndicator,
                 PartitionEntry->PartitionType,
-                PartitionEntry->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/,
-                PartitionEntry->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/);
+                PartitionEntry->StartingOffset.QuadPart /
+                  DiskDeviceExtension->DiskGeometry->BytesPerSector,
+                PartitionEntry->PartitionLength.QuadPart /
+                  DiskDeviceExtension->DiskGeometry->BytesPerSector);
 
          /* Create partition device object */
          sprintf(NameBuffer2,
@@ -839,11 +876,11 @@ DiskClassCreateDeviceObject(IN PDRIVER_OBJECT DriverObject,
 
 static NTSTATUS
 DiskBuildPartitionTable(IN PDEVICE_OBJECT DiskDeviceObject,
-                     IN PIRP Irp)
+                        IN PIRP Irp)
 {
   PDRIVE_LAYOUT_INFORMATION PartitionList = NULL;
-  PDEVICE_EXTENSION DiskDeviceExtension;
-  PDISK_DATA DiskData;
+  PDEVICE_EXTENSION DiskDeviceExtension, DDE;
+  PDISK_DATA DiskData, DD;
   PPARTITION_INFORMATION PartitionEntry;
   ULONG PartitionNumber;
   NTSTATUS Status;
@@ -853,19 +890,27 @@ DiskBuildPartitionTable(IN PDEVICE_OBJECT DiskDeviceObject,
   DiskDeviceExtension = (PDEVICE_EXTENSION)DiskDeviceObject->DeviceExtension;
   DiskData = (PDISK_DATA)(DiskDeviceExtension + 1);
 
-  if (DiskDeviceExtension->StartingOffset.QuadPart)
+  DDE = (PDEVICE_EXTENSION) DiskDeviceExtension->PhysicalDevice->DeviceExtension;
+  DD = (PDISK_DATA)(DDE +1);
+
+  /* Clear flag for Partition0, just incase it was set. */
+  DD->DriveNotReady = FALSE;
+
+  Status = ScsiClassReadDriveCapacity(DiskDeviceObject);
+  if (!NT_SUCCESS(Status))
     {
-      DPRINT("Partition already installed\n");
-      return(STATUS_SUCCESS);
+      /* Drive is not ready. */
+      DPRINT("Drive not ready\n");
+      DiskData->DriveNotReady = TRUE;
+      return Status;
     }
 
-      /* Read partition table */
-  Status = IoReadPartitionTable(DiskDeviceObject,
+  /* Read partition table */
+  Status = IoReadPartitionTable(DiskDeviceExtension->PhysicalDevice,
                                DiskDeviceExtension->DiskGeometry->BytesPerSector,
                                TRUE,
                                &PartitionList);
 
-
   DPRINT("IoReadPartitionTable(): Status: %lx\n", Status);
 
   if (!NT_SUCCESS(Status))
@@ -873,6 +918,8 @@ DiskBuildPartitionTable(IN PDEVICE_OBJECT DiskDeviceObject,
       /* Drive is not ready. */
       DPRINT("Drive not ready\n");
       DiskData->DriveNotReady = TRUE;
+      if (PartitionList != NULL)
+       ExFreePool(PartitionList);
       return Status;
     }
 
@@ -884,32 +931,50 @@ DiskBuildPartitionTable(IN PDEVICE_OBJECT DiskDeviceObject,
       /* Set disk signature */
       DiskData->Signature = PartitionList->Signature;
 
-      for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
-       {
-         PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber];
+      DiskData->NextPartition = NULL;
 
-       DiskData->NextPartition = NULL;
-       DiskData->PartitionType = PartitionEntry->PartitionType;
-       DiskData->PartitionNumber = PartitionNumber + 1;
-       DiskData->PartitionOrdinal = PartitionNumber + 1;
-       DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
-       DiskData->BootIndicator = PartitionEntry->BootIndicator;
-       DiskData->DriveNotReady = FALSE;
-       DiskDeviceExtension->StartingOffset = PartitionEntry->StartingOffset;
-       DiskDeviceExtension->PartitionLength = PartitionEntry->PartitionLength;
-               
-         DPRINT("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
-                PartitionNumber,
-                DiskData->PartitionNumber,
-                DiskData->BootIndicator,
-                DiskData->PartitionType,
-                DiskDeviceExtension->StartingOffset.QuadPart / 512 /*DrvParms.BytesPerSector*/,
-                DiskDeviceExtension->PartitionLength.QuadPart / 512 /* DrvParms.BytesPerSector*/);
-       }    
+      if (PartitionList->PartitionCount)
+        {
+         for (PartitionNumber = 0; PartitionNumber < PartitionList->PartitionCount; PartitionNumber++)
+           {
+             PartitionEntry = &PartitionList->PartitionEntry[PartitionNumber];
+
+             DiskData->PartitionType = PartitionEntry->PartitionType;
+             DiskData->PartitionNumber = PartitionNumber + 1;
+             DiskData->PartitionOrdinal = PartitionNumber + 1;
+             DiskData->HiddenSectors = PartitionEntry->HiddenSectors;
+             DiskData->BootIndicator = PartitionEntry->BootIndicator;
+             DiskData->DriveNotReady = FALSE;
+             DiskDeviceExtension->StartingOffset = PartitionEntry->StartingOffset;
+             DiskDeviceExtension->PartitionLength = PartitionEntry->PartitionLength;
+
+             DPRINT1("Partition %02ld: nr: %d boot: %1x type: %x offset: %I64d size: %I64d\n",
+                     PartitionNumber,
+                     DiskData->PartitionNumber,
+                     DiskData->BootIndicator,
+                     DiskData->PartitionType,
+                     DiskDeviceExtension->StartingOffset.QuadPart /
+                       DiskDeviceExtension->DiskGeometry->BytesPerSector,
+                     DiskDeviceExtension->PartitionLength.QuadPart /
+                       DiskDeviceExtension->DiskGeometry->BytesPerSector);
+           }
+       }
+      else
+       {
+         DiskData->PartitionType = 0;
+         DiskData->PartitionNumber = 1;
+         DiskData->PartitionOrdinal = 0;
+         DiskData->HiddenSectors = 0;
+         DiskData->BootIndicator = 0;
+         DiskData->DriveNotReady = FALSE;
+         DiskDeviceExtension->StartingOffset.QuadPart = 0;
+         DiskDeviceExtension->PartitionLength.QuadPart += DiskDeviceExtension->StartingOffset.QuadPart;
+       }
     }
 
   DPRINT("DiskBuildPartitionTable() done\n");
-
+  if (PartitionList != NULL)
+       ExFreePool(PartitionList);
   return(STATUS_SUCCESS);
 }
 
@@ -977,7 +1042,7 @@ DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
            if (!NT_SUCCESS(Status))
              {
                /* Drive is not ready */
-               DiskData->DriveNotReady = FALSE;
+               DiskData->DriveNotReady = TRUE;
                break;
              }
 
@@ -999,7 +1064,7 @@ DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
        if ((DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) &&
        (DeviceExtension->DiskGeometry->MediaType == RemovableMedia))
        {
-               /* Allocate a partition list for a single entry. */
+               /* Update a partition list for a single entry. */
                Status = DiskBuildPartitionTable(DeviceObject,Irp);
        }
        
@@ -1176,23 +1241,6 @@ DiskClassDeviceControl(IN PDEVICE_OBJECT DeviceObject,
          ExFreePool (ModeData);
        }
        break;
-
-      case IOCTL_DISK_CHECK_VERIFY:
-           DPRINT("IOCTL_DISK_CHECK_VERIFY\n");
-           if (DeviceObject->Flags & DO_VERIFY_VOLUME)
-           {
-               DPRINT("Do Verify Set\n");
-               Status = STATUS_VERIFY_REQUIRED;
-               Information = 0;
-           }
-           else
-           {
-               DPRINT("Do Verify Clear\n");
-               Status = STATUS_SUCCESS;
-               Information = 0;
-           }
-       break;
 
       case IOCTL_DISK_VERIFY:
       case IOCTL_DISK_FORMAT_TRACKS: