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?).
*/
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) {
/* 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);
}
DeviceExtension->DiskGeometry=&cdrom_DiskGeometry;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=MajorFunction_DEVICE_CONTROL;
+ DriverObject->MajorFunction[IRP_MJ_READ ]=MajorFunction_READ;
return STATUS_SUCCESS;
}