+IRP_MJ_READ handler
[captive.git] / src / libcaptive / storage / cdrom.c
index 6d6ed89..823df93 100644 (file)
@@ -40,6 +40,45 @@ static int Image_fd=-1;
 static off_t Image_size;       /* FIXME: lseek64() */
 
 
+static gboolean validate_DeviceObject(DEVICE_OBJECT *DeviceObject)
+{
+DEVICE_EXTENSION *DeviceExtension;
+DISK_GEOMETRY *DiskGeometry;
+
+       g_return_val_if_fail(DeviceObject!=NULL,FALSE);
+       g_return_val_if_fail(DeviceObject->DriverObject==&cdrom_DriverObject,FALSE);
+
+       DeviceExtension=DeviceObject->DeviceExtension;
+       DiskGeometry=DeviceExtension->DiskGeometry;
+       g_return_val_if_fail(DiskGeometry==&cdrom_DiskGeometry,FALSE);
+       g_return_val_if_fail(DiskGeometry->MediaType==cdrom_DiskGeometry_check.MediaType,FALSE);
+       g_return_val_if_fail(DiskGeometry->TracksPerCylinder==cdrom_DiskGeometry_check.TracksPerCylinder,FALSE);
+       g_return_val_if_fail(DiskGeometry->SectorsPerTrack==cdrom_DiskGeometry_check.SectorsPerTrack,FALSE);
+       g_return_val_if_fail(DiskGeometry->BytesPerSector==cdrom_DiskGeometry_check.BytesPerSector,FALSE);
+       g_return_val_if_fail(DiskGeometry->Cylinders.QuadPart==cdrom_DiskGeometry_check.Cylinders.QuadPart,FALSE);
+       g_return_val_if_fail(DeviceExtension->PartitionLength.QuadPart==Image_size,FALSE);
+
+       return TRUE;
+}
+
+
+static NTSTATUS MajorFunction_Irp_finish(DEVICE_OBJECT *DeviceObject,IRP *Irp)
+{
+       g_return_val_if_fail(TRUE==validate_DeviceObject(DeviceObject),STATUS_INVALID_PARAMETER);
+       g_return_val_if_fail(Irp!=NULL,STATUS_INVALID_PARAMETER);
+
+       /* 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;
+}
+
+
 /* 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?).
  */
@@ -47,26 +86,14 @@ static off_t Image_size;    /* FIXME: lseek64() */
 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(TRUE==validate_DeviceObject(DeviceObject),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);
 
+       Irp->IoStatus.Information=0;    /* request-specific, may get overriden later */
        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);
+       g_assert(IrpStack->MinorFunction==0);
 
        switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) {
 
@@ -148,15 +175,45 @@ CDROM_TOC *CdromToc;
        /* 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 */
-               }
+       return MajorFunction_Irp_finish(DeviceObject,Irp);
+}
 
-       IoCompleteRequest(Irp,IO_NO_INCREMENT); /* I hope it won't corrupt our Irp->IoStatus.Status */
-       return Irp->IoStatus.Status;
+
+/* 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_READ ((PDRIVER_DISPATCH)MajorFunction_READ_func)
+static NTSTATUS CAPTIVE_STDCALL MajorFunction_READ_func(IN DEVICE_OBJECT *DeviceObject,IN IRP *Irp)
+{
+IO_STACK_LOCATION *IrpStack;
+off_t offset;
+ssize_t count;
+
+       g_return_val_if_fail(TRUE==validate_DeviceObject(DeviceObject),STATUS_INVALID_PARAMETER);
+       g_return_val_if_fail(Irp!=NULL,STATUS_INVALID_PARAMETER);
+
+       Irp->IoStatus.Information=0;    /* request-specific, may get overriden later */
+       IrpStack=IoGetCurrentIrpStackLocation(Irp);
+       g_assert(IrpStack->MajorFunction==IRP_MJ_READ);
+       g_assert(IrpStack->MinorFunction==0);
+
+       /* What is 'IrpStack->Parameters.Read.Key'? */
+       g_assert(0==(IrpStack->Parameters.Read.Length%2048));
+       g_assert(0==(IrpStack->Parameters.Read.ByteOffset.QuadPart%2048));
+       g_assert(IrpStack->Parameters.Read.ByteOffset.QuadPart>=0);
+
+       offset=lseek(Image_fd,IrpStack->Parameters.Read.ByteOffset.QuadPart,SEEK_SET);
+       g_assert(offset==IrpStack->Parameters.Read.ByteOffset.QuadPart);
+
+       count=read(Image_fd,Irp->UserBuffer,IrpStack->Parameters.Read.Length);
+       g_assert((ULONG)count==IrpStack->Parameters.Read.Length);
+
+       Irp->IoStatus.Information=IrpStack->Parameters.Read.Length;
+       Irp->IoStatus.Status=STATUS_SUCCESS;
+
+       /* PASSTHRU */
+/* done: */    /* 'err:' but we flow here even during success */
+       return MajorFunction_Irp_finish(DeviceObject,Irp);
 }
 
 
@@ -235,6 +292,7 @@ NTSTATUS err;
        DeviceExtension->DiskGeometry=&cdrom_DiskGeometry;
 
        DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=MajorFunction_DEVICE_CONTROL;
+       DriverObject->MajorFunction[IRP_MJ_READ          ]=MajorFunction_READ;
 
        return STATUS_SUCCESS;
 }