[USBSTOR] Do not leak fields of DeviceExtensions upon device removal
[reactos.git] / drivers / usb / usbstor / fdo.c
index f1c7643..6879b4e 100644 (file)
@@ -1,12 +1,10 @@
 /*
  * PROJECT:     ReactOS Universal Serial Bus Bulk Storage Driver
- * LICENSE:     GPL - See COPYING in the top level directory
- * FILE:        drivers/usb/usbstor/fdo.c
+ * LICENSE:     GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
  * PURPOSE:     USB block storage device driver.
- * PROGRAMMERS:
- *              James Tabor
- *              Michael Martin (michael.martin@reactos.org)
- *              Johannes Anderwald (johannes.anderwald@reactos.org)
+ * COPYRIGHT:   2005-2006 James Tabor
+ *              2011-2012 Michael Martin (michael.martin@reactos.org)
+ *              2011-2013 Johannes Anderwald (johannes.anderwald@reactos.org)
  */
 
 #include "usbstor.h"
@@ -14,6 +12,7 @@
 #define NDEBUG
 #include <debug.h>
 
+
 VOID
 USBSTOR_DumpDeviceDescriptor(PUSB_DEVICE_DESCRIPTOR DeviceDescriptor)
 {
@@ -40,84 +39,51 @@ USBSTOR_FdoHandleDeviceRelations(
     IN OUT PIRP Irp)
 {
     ULONG DeviceCount = 0;
-    ULONG Index;
+    LONG Index;
     PDEVICE_RELATIONS DeviceRelations;
     PIO_STACK_LOCATION IoStack;
 
-    //
-    // get current irp stack location
-    //
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
-    //
     // check if relation type is BusRelations
-    //
     if (IoStack->Parameters.QueryDeviceRelations.Type != BusRelations)
     {
-        //
         // FDO always only handles bus relations
-        //
         return USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
     }
 
-    //
     // go through array and count device objects
-    //
-    for(Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
+    for (Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
     {
         if (DeviceExtension->ChildPDO[Index])
         {
-            //
-            // child pdo
-            //
             DeviceCount++;
         }
     }
 
-    //
-    // allocate device relations
-    //
     DeviceRelations = (PDEVICE_RELATIONS)AllocateItem(PagedPool, sizeof(DEVICE_RELATIONS) + (DeviceCount > 1 ? (DeviceCount-1) * sizeof(PDEVICE_OBJECT) : 0));
     if (!DeviceRelations)
     {
-        //
-        // no memory
-        //
         return STATUS_INSUFFICIENT_RESOURCES;
     }
 
-    //
     // add device objects
-    //
-    for(Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
+    for (Index = 0; Index < max(DeviceExtension->MaxLUN, 1); Index++)
     {
         if (DeviceExtension->ChildPDO[Index])
         {
-            //
             // store child pdo
-            //
             DeviceRelations->Objects[DeviceRelations->Count] = DeviceExtension->ChildPDO[Index];
 
-            //
             // add reference
-            //
             ObReferenceObject(DeviceExtension->ChildPDO[Index]);
 
-            //
-            // increment count
-            //
             DeviceRelations->Count++;
         }
     }
 
-    //
-    // store result
-    //
     Irp->IoStatus.Information = (ULONG_PTR)DeviceRelations;
 
-    //
-    // request completed successfully
-    //
     return STATUS_SUCCESS;
 }
 
@@ -132,8 +98,8 @@ USBSTOR_FdoHandleRemoveDevice(
 
     DPRINT("Handling FDO removal %p\n", DeviceObject);
 
-    /* FIXME: wait for devices finished processing */
-    for(Index = 0; Index < 16; Index++)
+    // FIXME: wait for devices finished processing
+    for (Index = 0; Index < 16; Index++)
     {
         if (DeviceExtension->ChildPDO[Index] != NULL)
         {
@@ -142,14 +108,32 @@ USBSTOR_FdoHandleRemoveDevice(
         }
     }
 
-    /* Send the IRP down the stack */
+    // Freeing everything in DeviceExtension
+    ASSERT(
+        DeviceExtension->DeviceDescriptor &&
+        DeviceExtension->ConfigurationDescriptor &&
+        DeviceExtension->InterfaceInformation &&
+        DeviceExtension->ResetDeviceWorkItem
+    );
+
+    ExFreePoolWithTag(DeviceExtension->DeviceDescriptor, USB_STOR_TAG);
+    ExFreePoolWithTag(DeviceExtension->ConfigurationDescriptor, USB_STOR_TAG);
+    ExFreePoolWithTag(DeviceExtension->InterfaceInformation, USB_STOR_TAG);
+    IoFreeWorkItem(DeviceExtension->ResetDeviceWorkItem);
+
+    if (DeviceExtension->SerialNumber)
+    {
+        ExFreePoolWithTag(DeviceExtension->SerialNumber, USB_STOR_TAG);
+    }
+
+    // Send the IRP down the stack
     IoSkipCurrentIrpStackLocation(Irp);
+    Irp->IoStatus.Status = STATUS_SUCCESS;
     Status = IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
 
-    /* Detach from the device stack */
+    // Detach from the device stack
     IoDetachDevice(DeviceExtension->LowerDeviceObject);
 
-    /* Delete the device object */
     IoDeleteDevice(DeviceObject);
 
     return Status;
@@ -164,51 +148,44 @@ USBSTOR_FdoHandleStartDevice(
     PUSB_INTERFACE_DESCRIPTOR InterfaceDesc;
     NTSTATUS Status;
     UCHAR Index = 0;
+    PIO_WORKITEM WorkItem;
 
-    //
     // forward irp to lower device
-    //
     Status = USBSTOR_SyncForwardIrp(DeviceExtension->LowerDeviceObject, Irp);
     if (!NT_SUCCESS(Status))
     {
-        //
-        // failed to start
-        //
         DPRINT1("USBSTOR_FdoHandleStartDevice Lower device failed to start %x\n", Status);
         return Status;
     }
 
-    //
-    // intialize irp queue
-    //
+    if (!DeviceExtension->ResetDeviceWorkItem)
+    {
+        WorkItem = IoAllocateWorkItem(DeviceObject);
+        DeviceExtension->ResetDeviceWorkItem = WorkItem;
+
+        if (!WorkItem)
+        {
+            return STATUS_INSUFFICIENT_RESOURCES;
+        }
+    }
+
+    // initialize irp queue
     USBSTOR_QueueInitialize(DeviceExtension);
 
-    //
     // first get device & configuration & string descriptor
-    //
     Status = USBSTOR_GetDescriptors(DeviceObject);
     if (!NT_SUCCESS(Status))
     {
-        //
-        // failed to get device descriptor
-        //
         DPRINT1("USBSTOR_FdoHandleStartDevice failed to get device descriptor with %x\n", Status);
         return Status;
     }
 
-    //
-    // dump device descriptor
-    //
     USBSTOR_DumpDeviceDescriptor(DeviceExtension->DeviceDescriptor);
 
-    //
+
     // Check that this device uses bulk transfers and is SCSI
-    //
-    InterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)DeviceExtension->ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR));
 
-    //
-    // sanity check
-    //
+    InterfaceDesc = (PUSB_INTERFACE_DESCRIPTOR)((ULONG_PTR)DeviceExtension->ConfigurationDescriptor + sizeof(USB_CONFIGURATION_DESCRIPTOR));
     ASSERT(InterfaceDesc->bDescriptorType == USB_INTERFACE_DESCRIPTOR_TYPE);
     ASSERT(InterfaceDesc->bLength == sizeof(USB_INTERFACE_DESCRIPTOR));
 
@@ -219,84 +196,53 @@ USBSTOR_FdoHandleStartDevice(
         return STATUS_NOT_SUPPORTED;
     }
 
-    if (InterfaceDesc->bInterfaceSubClass != 0x06)
+    if (InterfaceDesc->bInterfaceSubClass == 0x04) // UFI subclass
     {
-        //
         // FIXME: need to pad CDBs to 12 byte
         // mode select commands must be translated from 1AH / 15h to 5AH / 55h
-        //
         DPRINT1("[USBSTOR] Error: need to pad CDBs\n");
-        return STATUS_NOT_IMPLEMENTED;
+        return STATUS_NOT_SUPPORTED;
     }
 
-    //
     // now select an interface
-    //
     Status = USBSTOR_SelectConfigurationAndInterface(DeviceObject, DeviceExtension);
     if (!NT_SUCCESS(Status))
     {
-        //
         // failed to get device descriptor
-        //
         DPRINT1("USBSTOR_FdoHandleStartDevice failed to select configuration / interface with %x\n", Status);
         return Status;
     }
 
-    //
     // check if we got a bulk in + bulk out endpoint
-    //
     Status = USBSTOR_GetPipeHandles(DeviceExtension);
     if (!NT_SUCCESS(Status))
     {
-        //
-        // failed to get pipe handles descriptor
-        //
         DPRINT1("USBSTOR_FdoHandleStartDevice no pipe handles %x\n", Status);
         return Status;
     }
 
-    //
-    // get num of lun which are supported
-    //
     Status = USBSTOR_GetMaxLUN(DeviceExtension->LowerDeviceObject, DeviceExtension);
     if (!NT_SUCCESS(Status))
     {
-        //
-        // failed to get max LUN
-        //
         DPRINT1("USBSTOR_FdoHandleStartDevice failed to get max lun %x\n", Status);
         return Status;
     }
 
-    //
     // now create for each LUN a device object, 1 minimum
-    //
     do
     {
-        //
-        // create pdo
-        //
         Status = USBSTOR_CreatePDO(DeviceObject, Index);
 
-        //
-        // check for failure
-        //
         if (!NT_SUCCESS(Status))
         {
-            //
-            // failed to create child pdo
-            //
             DPRINT1("USBSTOR_FdoHandleStartDevice USBSTOR_CreatePDO failed for Index %lu with Status %x\n", Index, Status);
             return Status;
         }
 
-        //
-        // increment pdo index
-        //
         Index++;
         DeviceExtension->InstanceCount++;
 
-    }while(Index < DeviceExtension->MaxLUN);
+    } while(Index < DeviceExtension->MaxLUN);
 
 #if 0
     //
@@ -313,16 +259,8 @@ USBSTOR_FdoHandleStartDevice(
     }
 #endif
 
-
-    //
-    // start the timer
-    //
     //IoStartTimer(DeviceObject);
 
-
-    //
-    // fdo is now initialized
-    //
     DPRINT("USBSTOR_FdoHandleStartDevice FDO is initialized\n");
     return STATUS_SUCCESS;
 }
@@ -336,126 +274,94 @@ USBSTOR_FdoHandlePnp(
     PFDO_DEVICE_EXTENSION DeviceExtension;
     NTSTATUS Status;
 
-    //
-    // get current stack location
-    //
     IoStack = IoGetCurrentIrpStackLocation(Irp);
-
-    //
-    // get device extension
-    //
     DeviceExtension = (PFDO_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-    //
-    // sanity check
-    //
     ASSERT(DeviceExtension->Common.IsFDO);
 
     switch(IoStack->MinorFunction)
     {
-       case IRP_MN_SURPRISE_REMOVAL:
-       {
-           DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject);
-           Irp->IoStatus.Status = STATUS_SUCCESS;
+        case IRP_MN_SURPRISE_REMOVAL:
+        {
+            DPRINT("IRP_MN_SURPRISE_REMOVAL %p\n", DeviceObject);
+            Irp->IoStatus.Status = STATUS_SUCCESS;
 
-            //
             // forward irp to next device object
-            //
             IoSkipCurrentIrpStackLocation(Irp);
             return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
-       }
-       case IRP_MN_QUERY_DEVICE_RELATIONS:
-       {
-           DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject);
-           Status = USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp);
-           break;
-       }
-       case IRP_MN_STOP_DEVICE:
-       {
-           DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
-           IoStopTimer(DeviceObject);
-           Irp->IoStatus.Status = STATUS_SUCCESS;
+        }
+        case IRP_MN_QUERY_DEVICE_RELATIONS:
+        {
+            DPRINT("IRP_MN_QUERY_DEVICE_RELATIONS %p\n", DeviceObject);
+            Status = USBSTOR_FdoHandleDeviceRelations(DeviceExtension, Irp);
+            break;
+        }
+        case IRP_MN_STOP_DEVICE:
+        {
+            DPRINT1("USBSTOR_FdoHandlePnp: IRP_MN_STOP_DEVICE unimplemented\n");
+            IoStopTimer(DeviceObject);
+            Irp->IoStatus.Status = STATUS_SUCCESS;
 
-            //
             // forward irp to next device object
-            //
             IoSkipCurrentIrpStackLocation(Irp);
             return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
-       }
-       case IRP_MN_REMOVE_DEVICE:
-       {
-           DPRINT("IRP_MN_REMOVE_DEVICE\n");
-
-           return USBSTOR_FdoHandleRemoveDevice(DeviceObject, DeviceExtension, Irp);
-       }
-       case IRP_MN_QUERY_CAPABILITIES:
-       {
-           //
-           // FIXME: set custom capabilities 
-           //
-           IoSkipCurrentIrpStackLocation(Irp);
-           return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
-       }
-       case IRP_MN_QUERY_STOP_DEVICE:
-       case IRP_MN_QUERY_REMOVE_DEVICE:
-       {
+        }
+        case IRP_MN_REMOVE_DEVICE:
+        {
+            DPRINT("IRP_MN_REMOVE_DEVICE\n");
+
+            return USBSTOR_FdoHandleRemoveDevice(DeviceObject, DeviceExtension, Irp);
+        }
+        case IRP_MN_QUERY_CAPABILITIES:
+        {
+            // FIXME: set custom capabilities
+            IoSkipCurrentIrpStackLocation(Irp);
+            return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
+        }
+        case IRP_MN_QUERY_STOP_DEVICE:
+        case IRP_MN_QUERY_REMOVE_DEVICE:
+        {
 #if 0
-           //
-           // we can if nothing is pending
-           //
-           if (DeviceExtension->IrpPendingCount != 0 ||
-               DeviceExtension->ActiveSrb != NULL)
+            //
+            // we can if nothing is pending
+            //
+            if (DeviceExtension->IrpPendingCount != 0 ||
+                DeviceExtension->ActiveSrb != NULL)
 #else
-           if (TRUE)
+            if (TRUE)
 #endif
-           {
-               /* We have pending requests */
-               DPRINT1("Failing removal/stop request due to pending requests present\n");
-               Status = STATUS_UNSUCCESSFUL;
-           }
-           else
-           {
-               /* We're all clear */
-               Irp->IoStatus.Status = STATUS_SUCCESS;
-
-               IoSkipCurrentIrpStackLocation(Irp);
-               return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
-           }
-           break;
-       }
-       case IRP_MN_START_DEVICE:
-       {
-           Status = USBSTOR_FdoHandleStartDevice(DeviceObject, DeviceExtension, Irp);
-           break;
-       }
-       default:
+            {
+                /* We have pending requests */
+                DPRINT1("Failing removal/stop request due to pending requests present\n");
+                Status = STATUS_UNSUCCESSFUL;
+            }
+            else
+            {
+                /* We're all clear */
+                Irp->IoStatus.Status = STATUS_SUCCESS;
+
+                IoSkipCurrentIrpStackLocation(Irp);
+                return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
+            }
+            break;
+        }
+        case IRP_MN_START_DEVICE:
+        {
+            Status = USBSTOR_FdoHandleStartDevice(DeviceObject, DeviceExtension, Irp);
+            break;
+        }
+        default:
         {
-            //
             // forward irp to next device object
-            //
             IoSkipCurrentIrpStackLocation(Irp);
             return IoCallDriver(DeviceExtension->LowerDeviceObject, Irp);
         }
     }
 
-    //
-    // complete request
-    //
     if (Status != STATUS_PENDING)
     {
-        //
-        // store result
-        //
         Irp->IoStatus.Status = Status;
-
-        //
-        // complete request
-        //
         IoCompleteRequest(Irp, IO_NO_INCREMENT);
     }
 
-    //
-    // done processing
-    //
     return Status;
 }