Split cdrom.c to media.c with clients cdrom.c and disk.c
authorshort <>
Thu, 16 Jan 2003 04:07:23 +0000 (04:07 +0000)
committershort <>
Thu, 16 Jan 2003 04:07:23 +0000 (04:07 +0000)
+options --cdrom and --disk

src/libcaptive/storage/Makefile.am
src/libcaptive/storage/cdrom.c
src/libcaptive/storage/disk.c [new file with mode: 0644]
src/libcaptive/storage/media.c [new file with mode: 0644]
src/libcaptive/storage/media.h [new file with mode: 0644]

index 78e1c81..5cb0b0a 100644 (file)
@@ -22,4 +22,7 @@ include $(top_srcdir)/src/libcaptive/Makefile-libcaptive.am
 noinst_LTLIBRARIES=libstorage.la
 libstorage_la_SOURCES= \
                cdrom.c \
+               disk.c \
+               media.c \
+               media.h \
                size.c
index c9aca8a..fdf09da 100644 (file)
 #include "config.h"
 
 #include "captive/storage.h"   /* self */
-#include "captive/client.h"    /* for captive_image_iochannel */
-#include "reactos/ddk/iotypes.h"       /* for DRIVER_OBJECT */
+#include "captive/client.h"
+#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 "captive/macros.h"
-#include "reactos/ddk/mmfuncs.h"       /* for MmGetSystemAddressForMdl() */
+#include "reactos/ddk/status.h"        /* for NT_SUCCESS() */
 
 
-static DRIVER_OBJECT cdrom_DriverObject;
-static DISK_GEOMETRY cdrom_DiskGeometry;
-static DISK_GEOMETRY cdrom_DiskGeometry_check; /* for g_assert() checking against foreign modifications */
-static IO_SCSI_CAPABILITIES cdrom_PortCapabilities;
-static IO_SCSI_CAPABILITIES cdrom_PortCapabilities_check;      /* for g_assert() checking against foreign modifications */
-
-
-static gboolean validate_DeviceObject(DEVICE_OBJECT *DeviceObject)
-{
-DEVICE_EXTENSION *DeviceExtension;
-DISK_GEOMETRY *DiskGeometry;
-IO_SCSI_CAPABILITIES *PortCapabilities;
-
-       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==(gint64)captive_image_size,FALSE);
-
-       PortCapabilities=DeviceExtension->PortCapabilities;
-       g_return_val_if_fail(PortCapabilities==&cdrom_PortCapabilities,FALSE);
-       g_return_val_if_fail(PortCapabilities->Length==cdrom_PortCapabilities_check.Length,FALSE);
-       g_return_val_if_fail(PortCapabilities->MaximumTransferLength==cdrom_PortCapabilities_check.MaximumTransferLength,FALSE);
-       g_return_val_if_fail(PortCapabilities->MaximumPhysicalPages==cdrom_PortCapabilities_check.MaximumPhysicalPages,FALSE);
-       g_return_val_if_fail(PortCapabilities->SupportedAsynchronousEvents==cdrom_PortCapabilities_check.SupportedAsynchronousEvents,FALSE);
-       g_return_val_if_fail(PortCapabilities->AlignmentMask==cdrom_PortCapabilities_check.AlignmentMask,FALSE);
-       g_return_val_if_fail(PortCapabilities->TaggedQueuing==cdrom_PortCapabilities_check.TaggedQueuing,FALSE);
-       g_return_val_if_fail(PortCapabilities->AdapterScansDown==cdrom_PortCapabilities_check.AdapterScansDown,FALSE);
-       g_return_val_if_fail(PortCapabilities->AdapterUsesPio==cdrom_PortCapabilities_check.AdapterUsesPio,FALSE);
-
-       return TRUE;
-}
-
-
-static NTSTATUS MajorFunction_Irp_finish(DEVICE_OBJECT *DeviceObject,IRP *Irp)
-{
-NTSTATUS r;
-
-       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() will do 'IoFreeIrp(Irp);'!
-        * 'IoStatus.Status' must be saved before its invocation!
-        */
-       r=Irp->IoStatus.Status;
-       IoCompleteRequest(Irp,IO_NO_INCREMENT);
-       return r;
-}
-
-
-/* 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;
-
-       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_DEVICE_CONTROL);
-       g_assert(IrpStack->MinorFunction==0);
-
-       switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) {
-
-               case IOCTL_CDROM_GET_LAST_SESSION:
-                       /* Nothing interesting to see, move along.
-                        * FIXME: This call is somehow multisession related - must we care?
-                        */
-                       /* PASSTHRU */
-
-               case IOCTL_CDROM_READ_TOC: {
-CDROM_TOC *CdromToc;
-
-                       if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength<sizeof(CDROM_TOC)) {
-                               Irp->IoStatus.Status=STATUS_BUFFER_TOO_SMALL;
-                               Irp->IoStatus.Information=sizeof(CDROM_TOC);
-                               g_assert_not_reached();
-                               goto done;
-                               }
-                       CdromToc=(CDROM_TOC *)Irp->AssociatedIrp.SystemBuffer;
-                       CAPTIVE_MEMZERO(CdromToc);
-                       CdromToc->Length[0]=((sizeof(*CdromToc)-2)>>0U)&0xFFU;  /* little-endian */
-                       CdromToc->Length[1]=((sizeof(*CdromToc)-2)>>8U)&0xFFU;
-                       CdromToc->FirstTrack=0; /* one track; TOC_LAST_TRACK does not count */
-                       CdromToc->LastTrack =0; /* one track; TOC_LAST_TRACK does not count */
-                       CdromToc->TrackData[0].Control=TOC_DATA_TRACK;
-                       CdromToc->TrackData[0].Adr=0;   /* Q-subchannel subinfo */
-                       CdromToc->TrackData[0].TrackNumber=0;
-                       CdromToc->TrackData[0].Address[0]=0>>24U;       /* LBA offset; big-endian */
-                       CdromToc->TrackData[0].Address[1]=0>>16U;
-                       CdromToc->TrackData[0].Address[2]=0>> 8U;
-                       CdromToc->TrackData[0].Address[3]=0>> 0U;
-                       CdromToc->TrackData[1].Control=0;
-                       CdromToc->TrackData[1].Adr=0;   /* Q-subchannel subinfo */
-                       CdromToc->TrackData[1].TrackNumber=TOC_LAST_TRACK;
-                       /* FIXME: should we put the captive_image_size to TOC_LAST_TRACK? */
-                       CdromToc->TrackData[1].Address[0]=(captive_image_size/512)>>24U;        /* LBA offset; big-endian */
-                       CdromToc->TrackData[1].Address[1]=(captive_image_size/512)>>16U;
-                       CdromToc->TrackData[1].Address[2]=(captive_image_size/512)>> 8U;
-                       CdromToc->TrackData[1].Address[3]=(captive_image_size/512)>> 0U;
-
-                       Irp->IoStatus.Information=sizeof(DISK_GEOMETRY);
-                       Irp->IoStatus.Status=STATUS_SUCCESS;
-                       } break;
-
-               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;
-
-               case IOCTL_SCSI_GET_CAPABILITIES:
-                       if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength<sizeof(IO_SCSI_CAPABILITIES)) {
-                               Irp->IoStatus.Status=STATUS_BUFFER_TOO_SMALL;
-                               Irp->IoStatus.Information=sizeof(IO_SCSI_CAPABILITIES);
-                               g_assert_not_reached();
-                               goto done;
-                               }
-                       *(IO_SCSI_CAPABILITIES *)Irp->AssociatedIrp.SystemBuffer=cdrom_PortCapabilities;
-                       Irp->IoStatus.Information=sizeof(IO_SCSI_CAPABILITIES);
-                       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 */
-       return MajorFunction_Irp_finish(DeviceObject,Irp);
-}
-
-
-/* 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;
-gsize bytesread;
-gpointer buffer=NULL;
-GIOStatus erriostatus;
-
-       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);
-
-       /* Autodetect 'buffer' as we are !DO_BUFFERED_IO && !DO_DIRECT_IO hybrid */
-       if (Irp->UserBuffer) {
-               g_assert(buffer==NULL);
-               buffer=Irp->UserBuffer;
-               }
-       if (Irp->AssociatedIrp.SystemBuffer) {
-               g_assert(buffer==NULL);
-               buffer=Irp->AssociatedIrp.SystemBuffer;
-               }
-       if (Irp->MdlAddress) {
-               g_assert(buffer==NULL);
-               g_assert(IrpStack->Parameters.Read.Length<=MmGetMdlByteCount(Irp->MdlAddress));
-               buffer=MmGetSystemAddressForMdl(Irp->MdlAddress);
-               }
-       g_assert(buffer!=NULL);
-
-       erriostatus=g_io_channel_seek_position(captive_image_iochannel,
-                       IrpStack->Parameters.Read.ByteOffset.QuadPart,  /* offset */
-                       G_SEEK_SET,     /* type */
-                       NULL);  /* error */
-       g_assert(erriostatus==G_IO_STATUS_NORMAL);
-
-       erriostatus=g_io_channel_read_chars(captive_image_iochannel,
-                       buffer, /* buf */
-                       IrpStack->Parameters.Read.Length,       /* count */
-                       &bytesread,     /* bytesread */
-                       NULL);  /* error */
-       g_assert(erriostatus==G_IO_STATUS_NORMAL);
-       g_assert(bytesread==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);
-}
-
-
-/* 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)
-{
-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);
-
-       /* Currently we are !DO_BUFFERED_IO && !DO_DIRECT_IO and we must solve
-        * being called with 'Irp->UserBuffer', 'Irp->AssociatedIrp.SystemBuffer' or 'Irp->MdlAddress'.
-        */
-       /* 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() */
-       cdrom_PortCapabilities.Length=sizeof(cdrom_PortCapabilities);
-       cdrom_PortCapabilities.MaximumTransferLength=0x10000;   /* 64KB */
-       g_assert((cdrom_PortCapabilities.MaximumTransferLength%PAGE_SIZE)==0);
-       cdrom_PortCapabilities.MaximumPhysicalPages=cdrom_PortCapabilities.MaximumTransferLength/PAGE_SIZE;
-       cdrom_PortCapabilities.SupportedAsynchronousEvents=0;
-       cdrom_PortCapabilities.AlignmentMask=1; /* no alignment required by us; speced as "integer multiple" */
-       cdrom_PortCapabilities.TaggedQueuing=FALSE;
-       cdrom_PortCapabilities.AdapterScansDown=FALSE;
-       cdrom_PortCapabilities.AdapterUsesPio=TRUE;
-       cdrom_PortCapabilities_check=cdrom_PortCapabilities;    /* for g_assert() checking against foreign modifications */
-
-       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=&cdrom_PortCapabilities;
-       DeviceExtension->StartingOffset.QuadPart=0;
-       DeviceExtension->PartitionLength.QuadPart=captive_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=captive_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;
-       DriverObject->MajorFunction[IRP_MJ_READ          ]=MajorFunction_READ;
-
-       return STATUS_SUCCESS;
-}
-
 /**
  * captive_cdrom_init:
  *
  * 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(void)
 {
+static struct captive_DriverObject cdrom_captive_DriverObject;
 NTSTATUS err;
 
        g_return_val_if_fail(captive_image_iochannel!=NULL,FALSE);
 
-       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);
 
diff --git a/src/libcaptive/storage/disk.c b/src/libcaptive/storage/disk.c
new file mode 100644 (file)
index 0000000..2bb7f13
--- /dev/null
@@ -0,0 +1,68 @@
+/* $Id$
+ * "\Device\CaptiveHarddisk%d" storage emulation driver for reactos of libcaptive
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "config.h"
+
+#include "captive/storage.h"   /* self */
+#include "captive/client.h"
+#include "media.h"
+#include <glib/gmessages.h>
+#include "captive/unicode.h"
+#include "reactos/ddk/status.h"        /* for NT_SUCCESS() */
+
+
+/**
+ * captive_disk_init:
+ *
+ * Creates system device "\Device\CaptiveHarddisk%d" providing readwrite access
+ * to the given #captive_image_iochannel as emulation of harddisk driver.
+ * reactos initializes "\Device\Harddisk%d\Partition0" as the whole disk
+ * and each partition it founds by IoReadPartitionTable() it will create
+ * as "\Device\Harddisk%d\Partition1", "\Device\Harddisk%d\Partition2" etc.
+ *
+ * libcaptive does not (yet?) support any partitions and it will always create
+ * just the disk device for the whole given #captive_image_iochannel.
+ * As this behaviour is a bit specific we rather create some non-standard name
+ * of the device; anyway I have seen some "\Device\Harddisk%dVolume%d" on W32
+ * system.
+ *
+ * captive currently supports just one drive and thus "\Device\CaptiveHarddisk0"
+ * is always created. It is forbidden to call this function twice.
+ *
+ * Returns: %TRUE if the initialization was successful.
+ */
+gboolean captive_disk_init(void)
+{
+static struct captive_DriverObject disk_captive_DriverObject;
+NTSTATUS err;
+
+       g_return_val_if_fail(captive_image_iochannel!=NULL,FALSE);
+
+       disk_captive_DriverObject.DiskGeometry.BytesPerSector=512;
+       disk_captive_DriverObject.DiskGeometry.MediaType=FixedMedia;
+       disk_captive_DriverObject.DeviceName_utf8="\\Device\\CaptiveHarddisk0";
+       disk_captive_DriverObject.DeviceType=FILE_DEVICE_DISK;
+       disk_captive_DriverObject.DeviceCharacteristics=0;      /* !FILE_REMOVABLE_MEDIA && !FILE_READ_ONLY_DEVICE */
+       err=captive_media_DriverEntry(
+                       &disk_captive_DriverObject,     /* DriverEntry_DriverObject */
+                       captive_utf8_to_UnicodeString_alloca("\\captive\\storage\\disk"));      /* DriverEntry_RegistryPath; ignored */
+       g_return_val_if_fail(NT_SUCCESS(err),FALSE);
+
+       return TRUE;
+}
diff --git a/src/libcaptive/storage/media.c b/src/libcaptive/storage/media.c
new file mode 100644 (file)
index 0000000..adc0489
--- /dev/null
@@ -0,0 +1,379 @@
+/* $Id$
+ * captive media (cdrom/disk) emulation for reactos
+ * Copyright (C) 2002 Jan Kratochvil <project-captive@jankratochvil.net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#include "config.h"
+
+#include "media.h"     /* self */
+#include <glib/gmessages.h>
+#include "reactos/ddk/class2.h"        /* for DEVICE_EXTENSION */
+#include "captive/client.h"
+#include "reactos/ddk/status.h"
+#include "reactos/ddk/iofuncs.h"       /* for IoIsErrorUserInduced() */
+#include "captive/macros.h"
+#include "reactos/ddk/mmfuncs.h"       /* for MmGetMdlByteCount() */
+#include "captive/unicode.h"
+
+
+static gboolean validate_DeviceObject(DEVICE_OBJECT *DeviceObject)
+{
+DEVICE_EXTENSION *DeviceExtension;
+DISK_GEOMETRY *DiskGeometry;
+IO_SCSI_CAPABILITIES *PortCapabilities;
+struct captive_DriverObject *captive_DriverObject;
+
+       g_return_val_if_fail(DeviceObject!=NULL,FALSE);
+
+       captive_DriverObject=(struct captive_DriverObject *)DeviceObject->DriverObject;
+       DeviceExtension=DeviceObject->DeviceExtension;
+
+       DiskGeometry=DeviceExtension->DiskGeometry;
+       g_return_val_if_fail(DiskGeometry==&captive_DriverObject->DiskGeometry,FALSE);
+       g_return_val_if_fail(DiskGeometry->MediaType==captive_DriverObject->DiskGeometry_check.MediaType,FALSE);
+       g_return_val_if_fail(DiskGeometry->TracksPerCylinder==captive_DriverObject->DiskGeometry_check.TracksPerCylinder,FALSE);
+       g_return_val_if_fail(DiskGeometry->SectorsPerTrack==captive_DriverObject->DiskGeometry_check.SectorsPerTrack,FALSE);
+       g_return_val_if_fail(DiskGeometry->BytesPerSector==captive_DriverObject->DiskGeometry_check.BytesPerSector,FALSE);
+       g_return_val_if_fail(DiskGeometry->Cylinders.QuadPart==captive_DriverObject->DiskGeometry_check.Cylinders.QuadPart,FALSE);
+       g_return_val_if_fail(DeviceExtension->PartitionLength.QuadPart==(gint64)captive_image_size,FALSE);
+
+       PortCapabilities=DeviceExtension->PortCapabilities;
+       g_return_val_if_fail(PortCapabilities==&captive_DriverObject->PortCapabilities,FALSE);
+       g_return_val_if_fail(PortCapabilities->Length==captive_DriverObject->PortCapabilities_check.Length,FALSE);
+       g_return_val_if_fail(PortCapabilities->MaximumTransferLength==captive_DriverObject->PortCapabilities_check.MaximumTransferLength,FALSE);
+       g_return_val_if_fail(PortCapabilities->MaximumPhysicalPages==captive_DriverObject->PortCapabilities_check.MaximumPhysicalPages,FALSE);
+       g_return_val_if_fail(PortCapabilities->SupportedAsynchronousEvents==captive_DriverObject->PortCapabilities_check.SupportedAsynchronousEvents,FALSE);
+       g_return_val_if_fail(PortCapabilities->AlignmentMask==captive_DriverObject->PortCapabilities_check.AlignmentMask,FALSE);
+       g_return_val_if_fail(PortCapabilities->TaggedQueuing==captive_DriverObject->PortCapabilities_check.TaggedQueuing,FALSE);
+       g_return_val_if_fail(PortCapabilities->AdapterScansDown==captive_DriverObject->PortCapabilities_check.AdapterScansDown,FALSE);
+       g_return_val_if_fail(PortCapabilities->AdapterUsesPio==captive_DriverObject->PortCapabilities_check.AdapterUsesPio,FALSE);
+
+       return TRUE;
+}
+
+
+static NTSTATUS MajorFunction_Irp_finish(DEVICE_OBJECT *DeviceObject,IRP *Irp)
+{
+NTSTATUS r;
+
+       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() will do 'IoFreeIrp(Irp);'!
+        * 'IoStatus.Status' must be saved before its invocation!
+        */
+       r=Irp->IoStatus.Status;
+       IoCompleteRequest(Irp,IO_NO_INCREMENT);
+       return r;
+}
+
+
+/* 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)
+{
+struct captive_DriverObject *captive_DriverObject;
+IO_STACK_LOCATION *IrpStack;
+
+       g_return_val_if_fail(TRUE==validate_DeviceObject(DeviceObject),STATUS_INVALID_PARAMETER);
+       g_return_val_if_fail(Irp!=NULL,STATUS_INVALID_PARAMETER);
+
+       captive_DriverObject=(struct captive_DriverObject *)DeviceObject->DriverObject;
+
+       Irp->IoStatus.Information=0;    /* request-specific, may get overriden later */
+       IrpStack=IoGetCurrentIrpStackLocation(Irp);
+       g_assert(IrpStack->MajorFunction==IRP_MJ_DEVICE_CONTROL);
+       g_assert(IrpStack->MinorFunction==0);
+
+       switch (IrpStack->Parameters.DeviceIoControl.IoControlCode) {
+
+               case IOCTL_CDROM_GET_LAST_SESSION:
+                       /* Nothing interesting to see, move along.
+                        * FIXME: This call is somehow multisession related - must we care?
+                        */
+                       /* PASSTHRU */
+
+               case IOCTL_CDROM_READ_TOC: {
+CDROM_TOC *CdromToc;
+
+                       if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength<sizeof(CDROM_TOC)) {
+                               Irp->IoStatus.Status=STATUS_BUFFER_TOO_SMALL;
+                               Irp->IoStatus.Information=sizeof(CDROM_TOC);
+                               g_assert_not_reached();
+                               goto done;
+                               }
+                       CdromToc=(CDROM_TOC *)Irp->AssociatedIrp.SystemBuffer;
+                       CAPTIVE_MEMZERO(CdromToc);
+                       CdromToc->Length[0]=((sizeof(*CdromToc)-2)>>0U)&0xFFU;  /* little-endian */
+                       CdromToc->Length[1]=((sizeof(*CdromToc)-2)>>8U)&0xFFU;
+                       CdromToc->FirstTrack=0; /* one track; TOC_LAST_TRACK does not count */
+                       CdromToc->LastTrack =0; /* one track; TOC_LAST_TRACK does not count */
+                       CdromToc->TrackData[0].Control=TOC_DATA_TRACK;
+                       CdromToc->TrackData[0].Adr=0;   /* Q-subchannel subinfo */
+                       CdromToc->TrackData[0].TrackNumber=0;
+                       CdromToc->TrackData[0].Address[0]=0>>24U;       /* LBA offset; big-endian */
+                       CdromToc->TrackData[0].Address[1]=0>>16U;
+                       CdromToc->TrackData[0].Address[2]=0>> 8U;
+                       CdromToc->TrackData[0].Address[3]=0>> 0U;
+                       CdromToc->TrackData[1].Control=0;
+                       CdromToc->TrackData[1].Adr=0;   /* Q-subchannel subinfo */
+                       CdromToc->TrackData[1].TrackNumber=TOC_LAST_TRACK;
+                       /* FIXME: should we put the captive_image_size to TOC_LAST_TRACK? */
+                       CdromToc->TrackData[1].Address[0]=(captive_image_size/512)>>24U;        /* LBA offset; big-endian */
+                       CdromToc->TrackData[1].Address[1]=(captive_image_size/512)>>16U;
+                       CdromToc->TrackData[1].Address[2]=(captive_image_size/512)>> 8U;
+                       CdromToc->TrackData[1].Address[3]=(captive_image_size/512)>> 0U;
+
+                       Irp->IoStatus.Information=sizeof(DISK_GEOMETRY);
+                       Irp->IoStatus.Status=STATUS_SUCCESS;
+                       } break;
+
+               case IOCTL_CDROM_GET_DRIVE_GEOMETRY:
+               case IOCTL_DISK_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=captive_DriverObject->DiskGeometry;
+                       Irp->IoStatus.Information=sizeof(DISK_GEOMETRY);
+                       Irp->IoStatus.Status=STATUS_SUCCESS;
+                       break;
+
+               case IOCTL_CDROM_CHECK_VERIFY:
+               case IOCTL_DISK_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;
+
+               case IOCTL_SCSI_GET_CAPABILITIES:
+                       if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength<sizeof(IO_SCSI_CAPABILITIES)) {
+                               Irp->IoStatus.Status=STATUS_BUFFER_TOO_SMALL;
+                               Irp->IoStatus.Information=sizeof(IO_SCSI_CAPABILITIES);
+                               g_assert_not_reached();
+                               goto done;
+                               }
+                       *(IO_SCSI_CAPABILITIES *)Irp->AssociatedIrp.SystemBuffer=captive_DriverObject->PortCapabilities;
+                       Irp->IoStatus.Information=sizeof(IO_SCSI_CAPABILITIES);
+                       Irp->IoStatus.Status=STATUS_SUCCESS;
+                       break;
+
+               case IOCTL_DISK_GET_PARTITION_INFO_EX: {
+PARTITION_INFORMATION_EX *PartitionInformationEx;
+
+                       if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength<sizeof(PARTITION_INFORMATION_EX)) {
+                               Irp->IoStatus.Status=STATUS_BUFFER_TOO_SMALL;
+                               Irp->IoStatus.Information=sizeof(PARTITION_INFORMATION_EX);
+                               g_assert_not_reached();
+                               goto done;
+                               }
+                       PartitionInformationEx=(PARTITION_INFORMATION_EX *)Irp->AssociatedIrp.SystemBuffer;
+                       PartitionInformationEx->PartitionStyle=PARTITION_STYLE_RAW;     /* not MBR or GPT */
+                       PartitionInformationEx->StartingOffset.QuadPart=0;
+                       PartitionInformationEx->PartitionLength.QuadPart=captive_image_size;    /* FIXME: what units? */
+                       PartitionInformationEx->PartitionNumber=0;      /* FIXME: what number? */
+                       PartitionInformationEx->RewritePartition=FALSE; /* FIXME: meaning? */
+                       Irp->IoStatus.Information=sizeof(PARTITION_INFORMATION_EX);
+                       Irp->IoStatus.Status=STATUS_SUCCESS;
+                       } break;
+
+               case IOCTL_STORAGE_GET_HOTPLUG_INFO:
+                       Irp->IoStatus.Status=STATUS_NOT_SUPPORTED;
+                       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 */
+       return MajorFunction_Irp_finish(DeviceObject,Irp);
+}
+
+
+/* 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;
+gsize bytesread;
+gpointer buffer=NULL;
+GIOStatus erriostatus;
+struct captive_DriverObject *captive_DriverObject;
+
+  g_return_val_if_fail(TRUE==validate_DeviceObject(DeviceObject),STATUS_INVALID_PARAMETER);
+       g_return_val_if_fail(Irp!=NULL,STATUS_INVALID_PARAMETER);
+
+       captive_DriverObject=(struct captive_DriverObject *)DeviceObject->DriverObject;
+
+       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%captive_DriverObject->DiskGeometry.BytesPerSector));
+       g_assert(0==(IrpStack->Parameters.Read.ByteOffset.QuadPart%captive_DriverObject->DiskGeometry.BytesPerSector));
+       g_assert(IrpStack->Parameters.Read.ByteOffset.QuadPart>=0);
+
+       /* Autodetect 'buffer' as we are !DO_BUFFERED_IO && !DO_DIRECT_IO hybrid */
+       if (Irp->UserBuffer) {
+               g_assert(buffer==NULL);
+               buffer=Irp->UserBuffer;
+               }
+       if (Irp->AssociatedIrp.SystemBuffer) {
+               g_assert(buffer==NULL);
+               buffer=Irp->AssociatedIrp.SystemBuffer;
+               }
+       if (Irp->MdlAddress) {
+               g_assert(buffer==NULL);
+               g_assert(IrpStack->Parameters.Read.Length<=MmGetMdlByteCount(Irp->MdlAddress));
+               buffer=MmGetSystemAddressForMdl(Irp->MdlAddress);
+               }
+       g_assert(buffer!=NULL);
+
+       erriostatus=g_io_channel_seek_position(captive_image_iochannel,
+                       IrpStack->Parameters.Read.ByteOffset.QuadPart,  /* offset */
+                       G_SEEK_SET,     /* type */
+                       NULL);  /* error */
+       g_assert(erriostatus==G_IO_STATUS_NORMAL);
+
+       erriostatus=g_io_channel_read_chars(captive_image_iochannel,
+                       buffer, /* buf */
+                       IrpStack->Parameters.Read.Length,       /* count */
+                       &bytesread,     /* bytesread */
+                       NULL);  /* error */
+       g_assert(erriostatus==G_IO_STATUS_NORMAL);
+       g_assert(bytesread==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);
+}
+
+
+/* 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.
+ */
+NTSTATUS captive_media_DriverEntry(IN struct captive_DriverObject *captive_DriverObject,IN PUNICODE_STRING RegistryPath)
+{
+DRIVER_OBJECT *DriverObject;
+DEVICE_OBJECT *DeviceObject;
+DEVICE_EXTENSION *DeviceExtension;
+NTSTATUS err;
+
+       g_return_val_if_fail(captive_DriverObject!=NULL,STATUS_INVALID_PARAMETER);
+       g_return_val_if_fail(RegistryPath!=NULL,STATUS_INVALID_PARAMETER);
+
+       DriverObject=(DRIVER_OBJECT *)captive_DriverObject;
+
+       err=IoCreateDevice(
+                       DriverObject,   /* DriverObject */
+                       sizeof(DEVICE_EXTENSION),       /* DeviceExtensionSize; additional storage not used */
+                       captive_utf8_to_UnicodeString_alloca(captive_DriverObject->DeviceName_utf8),    /* DeviceName */
+                       captive_DriverObject->DeviceType,       /* DeviceType */
+                       captive_DriverObject->DeviceCharacteristics,    /* DeviceCharacteristics */
+                       FALSE,  /* Exclusive */
+                       &DeviceObject); /* DeviceObject */
+       g_return_val_if_fail(NT_SUCCESS(err),FALSE);
+
+       /* Currently we are !DO_BUFFERED_IO && !DO_DIRECT_IO and we must solve
+        * being called with 'Irp->UserBuffer', 'Irp->AssociatedIrp.SystemBuffer' or 'Irp->MdlAddress'.
+        */
+       /* should be left from IoCreateDevice(DeviceCharacteristics) above: */
+       if (captive_DriverObject->DeviceCharacteristics & FILE_REMOVABLE_MEDIA)
+               g_assert(DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA);
+       /* ignored: DeviceObject->StackSize */
+       /* ignored: DeviceObject->AlignmentRequirement */
+
+       /* from reactos/drivers/storage/scsiport/scsiport.c/ScsiPortCreatePortDevice() */
+       captive_DriverObject->PortCapabilities.Length=sizeof(captive_DriverObject->PortCapabilities);
+       captive_DriverObject->PortCapabilities.MaximumTransferLength=0x10000;   /* 64KB */
+       g_assert((captive_DriverObject->PortCapabilities.MaximumTransferLength%PAGE_SIZE)==0);
+       captive_DriverObject->PortCapabilities.MaximumPhysicalPages=captive_DriverObject->PortCapabilities.MaximumTransferLength/PAGE_SIZE;
+       captive_DriverObject->PortCapabilities.SupportedAsynchronousEvents=0;
+       captive_DriverObject->PortCapabilities.AlignmentMask=1; /* no alignment required by us; speced as "integer multiple" */
+       captive_DriverObject->PortCapabilities.TaggedQueuing=FALSE;
+       captive_DriverObject->PortCapabilities.AdapterScansDown=FALSE;
+       captive_DriverObject->PortCapabilities.AdapterUsesPio=TRUE;
+       captive_DriverObject->PortCapabilities_check=captive_DriverObject->PortCapabilities;    /* for g_assert() checking against foreign modifications */
+
+       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=&captive_DriverObject->PortCapabilities;
+       DeviceExtension->StartingOffset.QuadPart=0;
+       DeviceExtension->PartitionLength.QuadPart=captive_image_size;
+       DeviceExtension->PortNumber=0;
+       DeviceExtension->PathId=0;
+       DeviceExtension->TargetId=0;
+       DeviceExtension->Lun=0;
+
+       /* expect 'captive_DriverObject->DiskGeometry.MediaType' */
+       captive_DriverObject->DiskGeometry.TracksPerCylinder=64;
+       captive_DriverObject->DiskGeometry.SectorsPerTrack=32;
+       /* expect 'captive_DriverObject->DiskGeometry.BytesPerSector' */
+       captive_DriverObject->DiskGeometry.Cylinders.QuadPart=captive_image_size
+                       /captive_DriverObject->DiskGeometry.BytesPerSector
+                       /captive_DriverObject->DiskGeometry.SectorsPerTrack
+                       /captive_DriverObject->DiskGeometry.TracksPerCylinder;
+       /* 'DeviceExtension->DiskGeometry' is NULL! */
+       captive_DriverObject->DiskGeometry_check=captive_DriverObject->DiskGeometry;    /* for g_assert() checking against foreign modifications */
+       DeviceExtension->DiskGeometry=&captive_DriverObject->DiskGeometry;
+
+       DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=MajorFunction_DEVICE_CONTROL;
+       DriverObject->MajorFunction[IRP_MJ_READ          ]=MajorFunction_READ;
+
+       return STATUS_SUCCESS;
+}
diff --git a/src/libcaptive/storage/media.h b/src/libcaptive/storage/media.h
new file mode 100644 (file)
index 0000000..023f544
--- /dev/null
@@ -0,0 +1,51 @@
+/* $Id$
+ * Include file for captive media (cdrom/disk) emulation for reactos
+ * Copyright (C) 2003 Jan Kratochvil <project-captive@jankratochvil.net>
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; exactly version 2 of June 1991 is required
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+
+#ifndef _CAPTIVE_CLIENT_MEDIA_H
+#define _CAPTIVE_CLIENT_MEDIA_H 1
+
+
+#include <glib/gmacros.h>
+#include "reactos/ddk/iotypes.h"       /* for DRIVER_OBJECT */
+#include "reactos/ddk/ntddscsi.h"      /* for IO_SCSI_CAPABILITIES */
+
+
+G_BEGIN_DECLS
+
+struct captive_DriverObject {
+       DRIVER_OBJECT DriverObject;     /* keep first! */
+
+       DISK_GEOMETRY DiskGeometry;
+       DISK_GEOMETRY DiskGeometry_check;       /* for g_assert() checking against foreign modifications */
+       IO_SCSI_CAPABILITIES PortCapabilities;
+       IO_SCSI_CAPABILITIES PortCapabilities_check;    /* for g_assert() checking against foreign modifications */
+
+       /* expect: */
+       const gchar *DeviceName_utf8;
+       DEVICE_TYPE DeviceType;
+       ULONG DeviceCharacteristics;
+       };
+
+
+NTSTATUS captive_media_DriverEntry(IN struct captive_DriverObject *captive_DriverObject,IN PUNICODE_STRING RegistryPath);
+
+G_END_DECLS
+
+
+#endif /* _CAPTIVE_CLIENT_MEDIA_H */