[CDFS]
[reactos.git] / reactos / drivers / filesystems / cdfs / fsctl.c
index a8543db..1a80c5e 100644 (file)
@@ -19,7 +19,7 @@
 /*
 * COPYRIGHT:        See COPYING in the top level directory
 * PROJECT:          ReactOS kernel
-* FILE:             drivers/fs/cdfs/fsctl.c
+* FILE:             drivers/filesystems/cdfs/fsctl.c
 * PURPOSE:          CDROM (ISO 9660) filesystem driver
 * PROGRAMMER:       Art Yerkes
 *                   Eric Kohl
@@ -41,9 +41,11 @@ int msf_to_lba (UCHAR m, UCHAR s, UCHAR f)
 }
 
 
-static VOID
-CdfsGetPVDData(PUCHAR Buffer,
-               PCDINFO CdInfo)
+static
+VOID
+CdfsGetPVDData(
+    PUCHAR Buffer,
+    PCDINFO CdInfo)
 {
     PPVD Pvd;
     USHORT i;
@@ -150,9 +152,11 @@ CdfsGetPVDData(PUCHAR Buffer,
 }
 
 
-static VOID
-CdfsGetSVDData(PUCHAR Buffer,
-               PCDINFO CdInfo)
+static
+VOID
+CdfsGetSVDData(
+    PUCHAR Buffer,
+    PCDINFO CdInfo)
 {
     PSVD Svd;
     ULONG JolietLevel = 0;
@@ -190,9 +194,11 @@ CdfsGetSVDData(PUCHAR Buffer,
 }
 
 
-static NTSTATUS
-CdfsGetVolumeData(PDEVICE_OBJECT DeviceObject,
-                  PCDINFO CdInfo)
+static
+NTSTATUS
+CdfsGetVolumeData(
+    PDEVICE_OBJECT DeviceObject,
+    PCDINFO CdInfo)
 {
     PUCHAR Buffer;
     NTSTATUS Status;
@@ -200,48 +206,46 @@ CdfsGetVolumeData(PDEVICE_OBJECT DeviceObject,
     PVD_HEADER VdHeader;
     ULONG Size;
     ULONG Offset;
-    ULONG i;
-    struct
-    {
-        UCHAR  Length[2];
-        UCHAR  FirstSession;
-        UCHAR  LastSession;
-        TRACK_DATA  TrackData;
-    }
-    Toc;
+    CDROM_TOC Toc;
 
     DPRINT("CdfsGetVolumeData\n");
 
-    Buffer = ExAllocatePool(NonPagedPool,
-        CDFS_BASIC_SECTOR);
+    Buffer = ExAllocatePoolWithTag(NonPagedPool, CDFS_BASIC_SECTOR, CDFS_TAG);
     if (Buffer == NULL)
         return STATUS_INSUFFICIENT_RESOURCES;
 
     Size = sizeof(Toc);
     Status = CdfsDeviceIoControl(DeviceObject,
-        IOCTL_CDROM_GET_LAST_SESSION,
-        NULL,
-        0,
-        &Toc,
-        &Size,
-        TRUE);
-    if (!NT_SUCCESS(Status))
+                                 IOCTL_CDROM_READ_TOC,
+                                 NULL,
+                                 0,
+                                 &Toc,
+                                 &Size,
+                                 TRUE);
+    if (NT_SUCCESS(Status))
     {
-        ExFreePool(Buffer);
-        return Status;
-    }
 
-    DPRINT("FirstSession %d, LastSession %d, FirstTrack %d\n",
-        Toc.FirstSession, Toc.LastSession, Toc.TrackData.TrackNumber);
+        DPRINT("FirstTrack %u, LastTrack %u, TrackNumber %u\n",
+               Toc.FirstTrack, Toc.LastTrack, Toc.TrackData[0].TrackNumber);
 
-    Offset = 0;
-    for (i = 0; i < 4; i++)
+        Offset =  Toc.TrackData[0].Address[1] * 60 * 75;
+        Offset += Toc.TrackData[0].Address[2] * 75;
+        Offset += Toc.TrackData[0].Address[3];
+        if (Offset >= 150)
+        {
+            /* Remove MSF numbering offset of first frame */
+            /* FIXME: should be done only for real cdroms? */
+            Offset -= 150;
+        }
+        CdInfo->VolumeOffset = Offset;
+    }
+    else
     {
-        Offset = (Offset << 8) + Toc.TrackData.Address[i];
+        DPRINT1("Allowing mount of CDFS volume on non-CD device\n");
+        CdInfo->VolumeOffset = 0;
     }
-    CdInfo->VolumeOffset = Offset;
-
-    DPRINT("Offset of first track in last session %d\n", Offset);
+    
+    DPRINT("Offset of first track in last session %u\n", Offset);
 
     CdInfo->JolietLevel = 0;
     VdHeader = (PVD_HEADER)Buffer;
@@ -250,14 +254,14 @@ CdfsGetVolumeData(PDEVICE_OBJECT DeviceObject,
     for (Sector = CDFS_PRIMARY_DESCRIPTOR_LOCATION; Sector < 100 && Buffer[0] != 255; Sector++)
     {
         /* Read the Primary Volume Descriptor (PVD) */
-        Status = CdfsReadSectors (DeviceObject,
-            Sector + Offset,
-            1,
-            Buffer,
-            TRUE);
+        Status = CdfsReadSectors(DeviceObject,
+                                 Sector + Offset,
+                                 1,
+                                 Buffer,
+                                 TRUE);
         if (!NT_SUCCESS(Status))
         {
-            ExFreePool(Buffer);
+            ExFreePoolWithTag(Buffer, CDFS_TAG);
             return Status;
         }
 
@@ -268,50 +272,52 @@ CdfsGetVolumeData(PDEVICE_OBJECT DeviceObject,
             if (Buffer[0] != 1 || Buffer[1] != 'C' || Buffer[2] != 'D' ||
                 Buffer[3] != '0' || Buffer[4] != '0' || Buffer[5] != '1')
             {
-                ExFreePool(Buffer);
+                ExFreePoolWithTag(Buffer, CDFS_TAG);
                 return STATUS_UNRECOGNIZED_VOLUME;
             }
         }
 
         switch (VdHeader->VdType)
         {
-        case 0:
-            DPRINT("BootVolumeDescriptor found!\n");
-            break;
-
-        case 1:
-            DPRINT("PrimaryVolumeDescriptor found!\n");
-            CdfsGetPVDData(Buffer, CdInfo);
-            break;
-
-        case 2:
-            DPRINT("SupplementaryVolumeDescriptor found!\n");
-            CdfsGetSVDData(Buffer, CdInfo);
-            break;
-
-        case 3:
-            DPRINT("VolumePartitionDescriptor found!\n");
-            break;
-
-        case 255:
-            DPRINT("VolumeDescriptorSetTerminator found!\n");
-            break;
-
-        default:
-            DPRINT1("Unknown volume descriptor type %u found!\n", VdHeader->VdType);
-            break;
+            case 0:
+                DPRINT("BootVolumeDescriptor found!\n");
+                break;
+
+            case 1:
+                DPRINT("PrimaryVolumeDescriptor found!\n");
+                CdfsGetPVDData(Buffer, CdInfo);
+                break;
+
+            case 2:
+                DPRINT("SupplementaryVolumeDescriptor found!\n");
+                CdfsGetSVDData(Buffer, CdInfo);
+                break;
+
+            case 3:
+                DPRINT("VolumePartitionDescriptor found!\n");
+                break;
+
+            case 255:
+                DPRINT("VolumeDescriptorSetTerminator found!\n");
+                break;
+
+            default:
+                DPRINT1("Unknown volume descriptor type %u found!\n", VdHeader->VdType);
+                break;
         }
     }
 
-    ExFreePool(Buffer);
+    ExFreePoolWithTag(Buffer, CDFS_TAG);
 
-    return(STATUS_SUCCESS);
+    return STATUS_SUCCESS;
 }
 
 
-static NTSTATUS
-CdfsMountVolume(PDEVICE_OBJECT DeviceObject,
-                PIRP Irp)
+static
+NTSTATUS
+CdfsMountVolume(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
 {
     PDEVICE_EXTENSION DeviceExt = NULL;
     PDEVICE_OBJECT NewDeviceObject = NULL;
@@ -322,10 +328,19 @@ CdfsMountVolume(PDEVICE_OBJECT DeviceObject,
     PVPB Vpb;
     NTSTATUS Status;
     CDINFO CdInfo;
+    DEVICE_TYPE FilesystemDeviceType;
 
     DPRINT("CdfsMountVolume() called\n");
 
-    if (DeviceObject != CdfsGlobalData->DeviceObject)
+    if (DeviceObject == CdfsGlobalData->CdFsDeviceObject)
+    {
+        FilesystemDeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
+    }
+    else if (DeviceObject == CdfsGlobalData->HddFsDeviceObject)
+    {
+        FilesystemDeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
+    }
+    else
     {
         Status = STATUS_INVALID_DEVICE_REQUEST;
         goto ByeBye;
@@ -342,12 +357,12 @@ CdfsMountVolume(PDEVICE_OBJECT DeviceObject,
     }
 
     Status = IoCreateDevice(CdfsGlobalData->DriverObject,
-        sizeof(DEVICE_EXTENSION),
-        NULL,
-        FILE_DEVICE_CD_ROM_FILE_SYSTEM,
-        DeviceToMount->Characteristics,
-        FALSE,
-        &NewDeviceObject);
+                            sizeof(DEVICE_EXTENSION),
+                            NULL,
+                            FilesystemDeviceType,
+                            DeviceToMount->Characteristics,
+                            FALSE,
+                            &NewDeviceObject);
     if (!NT_SUCCESS(Status))
         goto ByeBye;
 
@@ -355,7 +370,7 @@ CdfsMountVolume(PDEVICE_OBJECT DeviceObject,
     NewDeviceObject->Flags &= ~DO_VERIFY_VOLUME;
     DeviceExt = (PVOID)NewDeviceObject->DeviceExtension;
     RtlZeroMemory(DeviceExt,
-        sizeof(DEVICE_EXTENSION));
+                  sizeof(DEVICE_EXTENSION));
 
     Vpb->SerialNumber = CdInfo.SerialNumber;
     Vpb->VolumeLabelLength = CdInfo.VolumeLabelLength;
@@ -378,7 +393,7 @@ CdfsMountVolume(PDEVICE_OBJECT DeviceObject,
     ExInitializeResourceLite(&DeviceExt->DirResource);
 
     DeviceExt->StreamFileObject = IoCreateStreamFileObject(NULL,
-        DeviceExt->StorageDevice);
+                                                           DeviceExt->StorageDevice);
 
     Fcb = CdfsCreateFCB(NULL);
     if (Fcb == NULL)
@@ -387,16 +402,15 @@ CdfsMountVolume(PDEVICE_OBJECT DeviceObject,
         goto ByeBye;
     }
 
-    Ccb = ExAllocatePoolWithTag(NonPagedPool,
-        sizeof(CCB),
-        TAG_CCB);
+    Ccb = ExAllocatePoolWithTag(NonPagedPool, sizeof(CCB), CDFS_CCB_TAG);
     if (Ccb == NULL)
     {
         Status =  STATUS_INSUFFICIENT_RESOURCES;
         goto ByeBye;
     }
+
     RtlZeroMemory(Ccb,
-        sizeof(CCB));
+                  sizeof(CCB));
 
     DeviceExt->StreamFileObject->ReadAccess = TRUE;
     DeviceExt->StreamFileObject->WriteAccess = FALSE;
@@ -418,17 +432,29 @@ CdfsMountVolume(PDEVICE_OBJECT DeviceObject,
     Fcb->Entry.ExtentLocationL = 0;
     Fcb->Entry.DataLengthL = (DeviceExt->CdInfo.VolumeSpaceSize + DeviceExt->CdInfo.VolumeOffset) * BLOCKSIZE;
 
-    CcInitializeCacheMap(DeviceExt->StreamFileObject,
-        (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
-        TRUE,
-        &(CdfsGlobalData->CacheMgrCallbacks),
-        Fcb);
+    _SEH2_TRY
+    {
+        CcInitializeCacheMap(DeviceExt->StreamFileObject,
+                             (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
+                             TRUE,
+                             &(CdfsGlobalData->CacheMgrCallbacks),
+                             Fcb);
+    }
+    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+    {
+        Status = _SEH2_GetExceptionCode();
+        goto ByeBye;
+    }
+    _SEH2_END;
 
     ExInitializeResourceLite(&DeviceExt->VcbResource);
 
     KeInitializeSpinLock(&DeviceExt->FcbListLock);
     InitializeListHead(&DeviceExt->FcbListHead);
 
+    FsRtlNotifyInitializeSync(&DeviceExt->NotifySync);
+    InitializeListHead(&DeviceExt->NotifyList);
+
     Status = STATUS_SUCCESS;
 
 ByeBye:
@@ -438,69 +464,60 @@ ByeBye:
         if (DeviceExt && DeviceExt->StreamFileObject)
             ObDereferenceObject(DeviceExt->StreamFileObject);
         if (Fcb)
-            ExFreePool(Fcb);
-        if (Ccb)
-            ExFreePool(Ccb);
+            ExFreePoolWithTag(Fcb, CDFS_NONPAGED_FCB_TAG);
         if (NewDeviceObject)
             IoDeleteDevice(NewDeviceObject);
     }
 
     DPRINT("CdfsMountVolume() done (Status: %lx)\n", Status);
 
-    return(Status);
+    return Status;
 }
 
 
-static NTSTATUS
-CdfsVerifyVolume(PDEVICE_OBJECT DeviceObject,
-                 PIRP Irp)
+static
+NTSTATUS
+CdfsVerifyVolume(
+    PDEVICE_OBJECT DeviceObject,
+    PIRP Irp)
 {
     PDEVICE_EXTENSION DeviceExt;
-    PDEVICE_OBJECT DeviceToVerify;
     PIO_STACK_LOCATION Stack;
     NTSTATUS Status;
     CDINFO CdInfo;
-
     PLIST_ENTRY Entry;
     PFCB Fcb;
+    PVPB VpbToVerify;
 
-    DPRINT1 ("CdfsVerifyVolume() called\n");
-
-#if 0
-    if (DeviceObject != CdfsGlobalData->DeviceObject)
-    {
-        DPRINT1("DeviceObject != CdfsGlobalData->DeviceObject\n");
-        return(STATUS_INVALID_DEVICE_REQUEST);
-    }
-#endif
+    DPRINT("CdfsVerifyVolume() called\n");
 
     DeviceExt = DeviceObject->DeviceExtension;
 
     Stack = IoGetCurrentIrpStackLocation (Irp);
-    DeviceToVerify = Stack->Parameters.VerifyVolume.DeviceObject;
+    VpbToVerify = Stack->Parameters.VerifyVolume.Vpb;
 
     FsRtlEnterFileSystem();
-    ExAcquireResourceExclusiveLite (&DeviceExt->VcbResource,
-        TRUE);
+    ExAcquireResourceExclusiveLite(&DeviceExt->VcbResource,
+                                   TRUE);
 
-    if (!(DeviceToVerify->Flags & DO_VERIFY_VOLUME))
+    if (!(VpbToVerify->RealDevice->Flags & DO_VERIFY_VOLUME))
     {
-        DPRINT1 ("Volume has been verified!\n");
+        DPRINT1("Volume has been verified!\n");
         ExReleaseResourceLite (&DeviceExt->VcbResource);
         FsRtlExitFileSystem();
         return STATUS_SUCCESS;
     }
 
-    DPRINT1 ("Device object %p  Device to verify %p\n", DeviceObject, DeviceToVerify);
+    DPRINT1("Device object %p  Device to verify %p\n", DeviceObject, VpbToVerify->RealDevice);
 
-    Status = CdfsGetVolumeData (DeviceToVerify,
-        &CdInfo);
+    Status = CdfsGetVolumeData(VpbToVerify->RealDevice,
+                               &CdInfo);
     if (NT_SUCCESS(Status) &&
-        CdInfo.SerialNumber == DeviceToVerify->Vpb->SerialNumber &&
-        CdInfo.VolumeLabelLength == DeviceToVerify->Vpb->VolumeLabelLength &&
-        !wcsncmp (CdInfo.VolumeLabel, DeviceToVerify->Vpb->VolumeLabel, CdInfo.VolumeLabelLength))
+        CdInfo.SerialNumber == VpbToVerify->SerialNumber &&
+        CdInfo.VolumeLabelLength == VpbToVerify->VolumeLabelLength &&
+        !wcsncmp(CdInfo.VolumeLabel, VpbToVerify->VolumeLabel, CdInfo.VolumeLabelLength))
     {
-        DPRINT1 ("Same volume!\n");
+        DPRINT1("Same volume!\n");
 
         /* FIXME: Flush and purge metadata */
 
@@ -508,14 +525,14 @@ CdfsVerifyVolume(PDEVICE_OBJECT DeviceObject,
     }
     else
     {
-        DPRINT1 ("Different volume!\n");
+        DPRINT1("Different volume!\n");
 
         /* FIXME: force volume dismount */
         Entry = DeviceExt->FcbListHead.Flink;
         while (Entry != &DeviceExt->FcbListHead)
         {
             Fcb = (PFCB)CONTAINING_RECORD(Entry, FCB, FcbListEntry);
-            DPRINT1("OpenFile %S  RefCount %ld\n", Fcb->PathName, Fcb->RefCount);
+            DPRINT1("OpenFile %wZ  RefCount %ld\n", &Fcb->PathName, Fcb->RefCount);
 
             Entry = Entry->Flink;
         }
@@ -523,23 +540,26 @@ CdfsVerifyVolume(PDEVICE_OBJECT DeviceObject,
         Status = STATUS_WRONG_VOLUME;
     }
 
-    DeviceToVerify->Flags &= ~DO_VERIFY_VOLUME;
+    VpbToVerify->RealDevice->Flags &= ~DO_VERIFY_VOLUME;
 
-    ExReleaseResourceLite (&DeviceExt->VcbResource);
+    ExReleaseResourceLite(&DeviceExt->VcbResource);
     FsRtlExitFileSystem();
 
     return Status;
 }
 
 
-NTSTATUS NTAPI
+NTSTATUS
+NTAPI
 CdfsSetCompression(
-                   IN PDEVICE_OBJECT DeviceObject,
-                   IN PIRP Irp)
+    IN PDEVICE_OBJECT DeviceObject,
+    IN PIRP Irp)
 {
     PIO_STACK_LOCATION Stack;
     USHORT CompressionState;
 
+    UNREFERENCED_PARAMETER(DeviceObject);
+
     Stack = IoGetCurrentIrpStackLocation(Irp);
 
     if (Stack->Parameters.DeviceIoControl.InputBufferLength != sizeof(CompressionState))
@@ -553,57 +573,61 @@ CdfsSetCompression(
 }
 
 
-NTSTATUS NTAPI
-CdfsFileSystemControl(PDEVICE_OBJECT DeviceObject,
-                      PIRP Irp)
+NTSTATUS
+NTAPI
+CdfsFileSystemControl(
+    PCDFS_IRP_CONTEXT IrpContext)
 {
+    PIRP Irp;
+    PDEVICE_OBJECT DeviceObject;
     PIO_STACK_LOCATION Stack;
     NTSTATUS Status;
 
     DPRINT("CdfsFileSystemControl() called\n");
 
-    Stack = IoGetCurrentIrpStackLocation(Irp);
+    ASSERT(IrpContext);
+
+    DeviceObject = IrpContext->DeviceObject;
+    Irp = IrpContext->Irp;
+    Stack = IrpContext->Stack;
 
-    switch (Stack->MinorFunction)
+    Irp->IoStatus.Information = 0;
+
+    switch (IrpContext->MinorFunction)
     {
-    case IRP_MN_KERNEL_CALL:
-    case IRP_MN_USER_FS_REQUEST:
-        switch (Stack->Parameters.DeviceIoControl.IoControlCode)
-        {
-        case FSCTL_SET_COMPRESSION:
-            DPRINT("CDFS: IRP_MN_USER_FS_REQUEST / FSCTL_SET_COMPRESSION\n");
-            Status = CdfsSetCompression(DeviceObject, Irp);
+        case IRP_MN_KERNEL_CALL:
+        case IRP_MN_USER_FS_REQUEST:
+            switch (Stack->Parameters.DeviceIoControl.IoControlCode)
+            {
+                case FSCTL_SET_COMPRESSION:
+                    DPRINT("CDFS: IRP_MN_USER_FS_REQUEST / FSCTL_SET_COMPRESSION\n");
+                    Status = CdfsSetCompression(DeviceObject, Irp);
+                    break;
+
+                default:
+                    DPRINT1("CDFS: IRP_MN_USER_FS_REQUEST / Unknown IoControlCode 0x%x\n",
+                    Stack->Parameters.DeviceIoControl.IoControlCode);
+                    Status = STATUS_INVALID_DEVICE_REQUEST;
+            }
             break;
 
-        default:
-            DPRINT1("CDFS: IRP_MN_USER_FS_REQUEST / Unknown IoControlCode 0x%x\n",
-                Stack->Parameters.DeviceIoControl.IoControlCode);
-            Status = STATUS_INVALID_DEVICE_REQUEST;
-        }
-        break;
-
-    case IRP_MN_MOUNT_VOLUME:
-        DPRINT("CDFS: IRP_MN_MOUNT_VOLUME\n");
-        Status = CdfsMountVolume(DeviceObject, Irp);
-        break;
+        case IRP_MN_MOUNT_VOLUME:
+            DPRINT("CDFS: IRP_MN_MOUNT_VOLUME\n");
+            Status = CdfsMountVolume(DeviceObject, Irp);
+            break;
 
-    case IRP_MN_VERIFY_VOLUME:
-        DPRINT1("CDFS: IRP_MN_VERIFY_VOLUME\n");
-        Status = CdfsVerifyVolume(DeviceObject, Irp);
-        break;
+        case IRP_MN_VERIFY_VOLUME:
+            DPRINT1("CDFS: IRP_MN_VERIFY_VOLUME\n");
+            Status = CdfsVerifyVolume(DeviceObject, Irp);
+            break;
 
-    default:
-        DPRINT1("CDFS FSC: MinorFunction %d\n", Stack->MinorFunction);
-        Status = STATUS_INVALID_DEVICE_REQUEST;
-        break;
+        default:
+            DPRINT1("CDFS FSC: MinorFunction %u\n", Stack->MinorFunction);
+            Status = STATUS_INVALID_DEVICE_REQUEST;
+            break;
     }
 
-    Irp->IoStatus.Status = Status;
-    Irp->IoStatus.Information = 0;
-
-    IoCompleteRequest(Irp, IO_NO_INCREMENT);
-
-    return(Status);
+    return Status;
 }
 
 /* EOF */