Initial original import from: fuse-2.4.2-2.fc4
[captive.git] / src / libcaptive / storage / cdrom.c
index f557a5c..e7d8e09 100644 (file)
 #include "config.h"
 
 #include "captive/storage.h"   /* self */
-#include "reactos/ddk/iotypes.h"       /* for DRIVER_OBJECT */
+#include "media.h"
 #include <glib/gmessages.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include "reactos/ddk/ntddscsi.h"      /* for IO_SCSI_CAPABILITIES */
-#include "reactos/ddk/class2.h"        /* for PDEVICE_EXTENSION */
-#include "reactos/ddk/status.h"        /* for STATUS_INVALID_PARAMETER */
-#include "reactos/ddk/iofuncs.h"       /* for IoCreateDevice() */
 #include "captive/unicode.h"
+#include "reactos/ddk/status.h"        /* for NT_SUCCESS() */
+#include "captive/options.h"
 
 
-static DRIVER_OBJECT cdrom_DriverObject;
-static DISK_GEOMETRY cdrom_DiskGeometry;
-static DISK_GEOMETRY cdrom_DiskGeometry_check; /* for g_assert() checking against foreign modifications */
-static int Image_fd=-1;
-static off_t Image_size;       /* FIXME: lseek64() */
-
-
-/* FIXME: We should comply with PDRIVER_DISPATCH prototype but unfortunately
- * CAPTIVE_STDCALL prevents us to do so at least in RedHat gcc-3.2-4 (gcc bug?).
- */
-#define MajorFunction_DEVICE_CONTROL ((PDRIVER_DISPATCH)MajorFunction_DEVICE_CONTROL_func)
-static NTSTATUS CAPTIVE_STDCALL MajorFunction_DEVICE_CONTROL_func(IN DEVICE_OBJECT *DeviceObject,IN IRP *Irp)
-{
-IO_STACK_LOCATION *IrpStack;
-DEVICE_EXTENSION *DeviceExtension;
-DISK_GEOMETRY *DiskGeometry;
-
-       g_return_val_if_fail(DeviceObject!=NULL,STATUS_INVALID_PARAMETER);
-       g_return_val_if_fail(Irp!=NULL,STATUS_INVALID_PARAMETER);
-       g_return_val_if_fail(DeviceObject->DriverObject==&cdrom_DriverObject,STATUS_INVALID_PARAMETER);
-
-       IrpStack=IoGetCurrentIrpStackLocation(Irp);
-       g_assert(IrpStack->MajorFunction==IRP_MJ_DEVICE_CONTROL);
-       Irp->IoStatus.Information=0;    /* request-specific, may get overriden later */
-       DeviceExtension=DeviceObject->DeviceExtension;
-
-       DiskGeometry=DeviceExtension->DiskGeometry;
-       g_assert(DiskGeometry==&cdrom_DiskGeometry);
-       g_assert(DiskGeometry->MediaType==cdrom_DiskGeometry_check.MediaType);
-       g_assert(DiskGeometry->TracksPerCylinder==cdrom_DiskGeometry_check.TracksPerCylinder);
-       g_assert(DiskGeometry->SectorsPerTrack==cdrom_DiskGeometry_check.SectorsPerTrack);
-       g_assert(DiskGeometry->BytesPerSector==cdrom_DiskGeometry_check.BytesPerSector);
-       g_assert(DiskGeometry->Cylinders.QuadPart==cdrom_DiskGeometry_check.Cylinders.QuadPart);
-       g_assert(DeviceExtension->PartitionLength.QuadPart==Image_size);
-
-       switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) {
-
-               case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
-                       if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength<sizeof(DISK_GEOMETRY)) {
-                               Irp->IoStatus.Status=STATUS_BUFFER_TOO_SMALL;
-                               Irp->IoStatus.Information=sizeof(DISK_GEOMETRY);
-                               g_assert_not_reached();
-                               goto done;
-                               }
-                       *(DISK_GEOMETRY *)Irp->AssociatedIrp.SystemBuffer=cdrom_DiskGeometry;
-                       Irp->IoStatus.Information=sizeof(DISK_GEOMETRY);
-                       Irp->IoStatus.Status=STATUS_SUCCESS;
-                       break;
-
-               case IOCTL_CDROM_CHECK_VERIFY: {
-                       if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength) {
-                               if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength<sizeof(ULONG)) {
-                                       Irp->IoStatus.Status=STATUS_BUFFER_TOO_SMALL;
-                                       Irp->IoStatus.Information=sizeof(ULONG);
-                                       g_assert_not_reached();
-                                       goto done;
-                                       }
-                               *(ULONG *)Irp->AssociatedIrp.SystemBuffer=0;    /* MediaChangeCount */
-                               Irp->IoStatus.Information=sizeof(ULONG);
-                               }
-                       else {
-                               Irp->IoStatus.Information=0;
-                               }
-                       Irp->IoStatus.Status=STATUS_SUCCESS;
-                       } break;
-
-               default:
-                       Irp->IoStatus.Status=STATUS_INVALID_DEVICE_REQUEST;
-                       g_assert_not_reached();
-                       goto done;
-               }
-       /* PASSTHRU */
-
-done:  /* 'err:' but we flow here even during success */
-       /* required for removable media only */
-       if (!NT_SUCCESS(Irp->IoStatus.Status) && IoIsErrorUserInduced(Irp->IoStatus.Status)) {
-               g_assert(Irp->Tail.Overlay.Thread!=NULL);       /* FIXME: Error should be postponed to first !=NULL Irp later */
-               IoSetHardErrorOrVerifyDevice(Irp,DeviceObject);
-               Irp->IoStatus.Information=0;    /* may got set during some processing before error occured */
-               }
-
-       IoCompleteRequest(Irp,IO_NO_INCREMENT); /* I hope it won't corrupt our Irp->IoStatus.Status */
-       return Irp->IoStatus.Status;
-}
-
-
-/* similiar to drivers/storage/cdrom/cdrom.c/DriverEntry()->...
- * ...->CdromClassCreateDeviceObject()->
- * ->reactos/drivers/storage/class2/class2.c/ScsiClassCreateDeviceObject()
- * We should be driving a lower layer PortDevice but currently we
- * do not provide it, I hope W32 filesystems don't touch it.
- */
-static NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
-{
-static IO_SCSI_CAPABILITIES PortCapabilities;  /* it is const filled in DriverEntry() */
-PDEVICE_OBJECT DeviceObject;
-PDEVICE_EXTENSION DeviceExtension;
-NTSTATUS err;
-
-       g_return_val_if_fail(DriverObject!=NULL,STATUS_INVALID_PARAMETER);
-       g_return_val_if_fail(RegistryPath!=NULL,STATUS_INVALID_PARAMETER);
-
-       err=IoCreateDevice(
-                       DriverObject,   /* DriverObject */
-                       sizeof(DEVICE_EXTENSION),       /* DeviceExtensionSize; additional storage not used */
-                       captive_utf8_to_UnicodeString_alloca("\\Device\\CdRom0"),       /* DeviceName */
-                       FILE_DEVICE_CD_ROM,     /* DeviceType */
-                       FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE,     /* DeviceCharacteristics */
-                       FALSE,  /* Exclusive */
-                       &DeviceObject); /* DeviceObject */
-       g_return_val_if_fail(NT_SUCCESS(err),FALSE);
-
-       /* CdromClassCreateDeviceObject() sets:
-        *      DeviceObject->Flags|=DO_DIRECT_IO;
-        * but do we need it?
-        */
-       /* should be left from IoCreateDevice(DeviceCharacteristics) above: */
-       g_assert(DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA);
-       /* ignored: DeviceObject->StackSize */
-       /* ignored: DeviceObject->AlignmentRequirement */
-
-       /* from reactos/drivers/storage/scsiport/scsiport.c/ScsiPortCreatePortDevice() */
-       PortCapabilities.Length=sizeof(PortCapabilities);
-       PortCapabilities.MaximumTransferLength=0x10000; /* 64KB */
-       g_assert((PortCapabilities.MaximumTransferLength%PAGE_SIZE)==0);
-       PortCapabilities.MaximumPhysicalPages=PortCapabilities.MaximumTransferLength/PAGE_SIZE;
-       PortCapabilities.SupportedAsynchronousEvents=0;
-       PortCapabilities.AlignmentMask=1;       /* no alignment required by us; speced as "integer multiple" */
-       PortCapabilities.TaggedQueuing=FALSE;
-       PortCapabilities.AdapterScansDown=FALSE;
-       PortCapabilities.AdapterUsesPio=TRUE;
-
-       DeviceExtension=DeviceObject->DeviceExtension;
-       DeviceExtension->MediaChangeCount=0;
-       DeviceExtension->PhysicalDevice=DeviceObject;   /* no real PhysicalDeviceObject */
-       DeviceExtension->LockCount=0;
-       DeviceExtension->DeviceNumber=0;        /* corresponds to the # in "\\Device\\CdRom0" */
-       /* ignored DeviceExtension->PortDeviceObject
-        * as we are the final driver and we don't have any PortDeviceObject
-        */
-       DeviceExtension->PortCapabilities=&PortCapabilities;
-       DeviceExtension->StartingOffset.QuadPart=0;
-       DeviceExtension->PartitionLength.QuadPart=Image_size;
-       DeviceExtension->PortNumber=0;
-       DeviceExtension->PathId=0;
-       DeviceExtension->TargetId=0;
-       DeviceExtension->Lun=0;
-
-       cdrom_DiskGeometry.MediaType=RemovableMedia;
-       cdrom_DiskGeometry.TracksPerCylinder=64;
-       cdrom_DiskGeometry.SectorsPerTrack=32;
-       cdrom_DiskGeometry.BytesPerSector=2048;
-       cdrom_DiskGeometry.Cylinders.QuadPart=Image_size
-                       /cdrom_DiskGeometry.BytesPerSector
-                       /cdrom_DiskGeometry.SectorsPerTrack
-                       /cdrom_DiskGeometry.TracksPerCylinder;
-       /* 'DeviceExtension->DiskGeometry' is NULL! */
-       cdrom_DiskGeometry_check=cdrom_DiskGeometry;    /* for g_assert() checking against foreign modifications */
-       DeviceExtension->DiskGeometry=&cdrom_DiskGeometry;
-
-       DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=MajorFunction_DEVICE_CONTROL;
-
-       return STATUS_SUCCESS;
-}
-
 /**
  * captive_cdrom_init:
- * @image_pathname: Host OS file #utf8 pathname of the disk image to provide.
- * %NULL value is forbidden.
  *
  * Creates system device "\Device\CdRom%d" providing readonly access
- * to the given @image_pathname as emulation of CD-ROM driver.
+ * to the given #captive_image_iochannel as emulation of CD-ROM driver.
  *
- * captive currently supports just one drive and thus "\Device\CdRom0"
+ * libcaptive currently supports just one drive and thus "\Device\CdRom0"
  * is always created. It is forbidden to call this function twice.
  *
  * Returns: %TRUE if the initialization was successful.
  */
-gboolean captive_cdrom_init(const gchar *image_pathname)
+gboolean captive_cdrom_init(void)
 {
+static struct captive_DriverObject cdrom_captive_DriverObject;
 NTSTATUS err;
 
-       g_return_val_if_fail(image_pathname!=NULL,FALSE);
-
-       Image_fd=open(image_pathname,O_RDONLY
-#ifdef O_BINARY
-                       |O_BINARY
-#endif
-                       );      /* FIXME: lseek64() */
-       g_return_val_if_fail(Image_fd!=-1,FALSE);
+       g_return_val_if_fail(captive_image_iochannel!=NULL,FALSE);
 
-       Image_size=lseek(Image_fd,0,SEEK_END);  /* FIXME: lseek64() */
-       if (Image_size==(off_t)-1) {
-               g_assert_not_reached();
-               goto err_close;
-               }
-
-       err=DriverEntry(
-                       &cdrom_DriverObject,    /* DriverEntry_DriverObject */
+       cdrom_captive_DriverObject.DiskGeometry.BytesPerSector=2048;
+       cdrom_captive_DriverObject.DiskGeometry.MediaType=RemovableMedia;
+       cdrom_captive_DriverObject.DeviceName_utf8="\\Device\\CdRom0";
+       cdrom_captive_DriverObject.DeviceType=FILE_DEVICE_CD_ROM;
+       cdrom_captive_DriverObject.DeviceCharacteristics=FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE;
+       err=captive_media_DriverEntry(
+                       &cdrom_captive_DriverObject,    /* DriverEntry_DriverObject */
                        captive_utf8_to_UnicodeString_alloca("\\captive\\storage\\cdrom"));     /* DriverEntry_RegistryPath; ignored */
        g_return_val_if_fail(NT_SUCCESS(err),FALSE);
 
        return TRUE;
-
-err_close:
-       close(Image_fd);
-       Image_fd=-1;
-/* err: */
-       g_return_val_if_reached(FALSE);
 }