+libcaptive/storage/cdrom.c
[captive.git] / src / libcaptive / storage / cdrom.c
1 /* $Id$
2  * "\Device\CdRom%d" storage emulation driver for reactos of libcaptive
3  * Copyright (C) 2002 Jan Kratochvil <project-captive@jankratochvil.net>
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; exactly version 2 of June 1991 is required
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 #include "config.h"
21
22 #include "captive/storage.h"    /* self */
23 #include "reactos/ddk/iotypes.h"        /* for DRIVER_OBJECT */
24 #include <glib/gmessages.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include "reactos/ddk/ntddscsi.h"       /* for IO_SCSI_CAPABILITIES */
29 #include "reactos/ddk/class2.h" /* for PDEVICE_EXTENSION */
30 #include "reactos/ddk/status.h" /* for STATUS_INVALID_PARAMETER */
31 #include "reactos/ddk/iofuncs.h"        /* for IoCreateDevice() */
32 #include "captive/unicode.h"
33
34
35 static DRIVER_OBJECT cdrom_DriverObject;
36 static int Image_fd=-1;
37 static off_t Image_size;        /* FIXME: lseek64() */
38
39
40
41 /* similiar to drivers/storage/cdrom/cdrom.c/DriverEntry()->...
42  * ...->CdromClassCreateDeviceObject()->
43  * ->reactos/drivers/storage/class2/class2.c/ScsiClassCreateDeviceObject()
44  * We should be driving a lower layer PortDevice but currently we
45  * do not provide it, I hope W32 filesystems don't touch it.
46  */
47 static NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
48 {
49 static IO_SCSI_CAPABILITIES PortCapabilities;   /* it is const filled in DriverEntry() */
50 PDEVICE_OBJECT DeviceObject;
51 PDEVICE_EXTENSION DeviceExtension;
52 NTSTATUS err;
53
54         g_return_val_if_fail(DriverObject!=NULL,STATUS_INVALID_PARAMETER);
55         g_return_val_if_fail(RegistryPath!=NULL,STATUS_INVALID_PARAMETER);
56
57         err=IoCreateDevice(
58                         DriverObject,   /* DriverObject */
59                         sizeof(DEVICE_EXTENSION),       /* DeviceExtensionSize; additional storage not used */
60                         captive_utf8_to_UnicodeString_alloca("\\Device\\CdRom0"),       /* DeviceName */
61                         FILE_DEVICE_CD_ROM,     /* DeviceType */
62                         FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE,     /* DeviceCharacteristics */
63                         FALSE,  /* Exclusive */
64                         &DeviceObject); /* DeviceObject */
65         g_return_val_if_fail(NT_SUCCESS(err),FALSE);
66
67         /* CdromClassCreateDeviceObject() sets:
68          *      DeviceObject->Flags|=DO_DIRECT_IO;
69          * but do we need it?
70          */
71         /* should be left from IoCreateDevice(DeviceCharacteristics) above: */
72         g_assert(DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA);
73         /* ignored: DeviceObject->StackSize */
74         /* ignored: DeviceObject->AlignmentRequirement */
75
76         /* from reactos/drivers/storage/scsiport/scsiport.c/ScsiPortCreatePortDevice() */
77         PortCapabilities.Length=sizeof(PortCapabilities);
78         PortCapabilities.MaximumTransferLength=0x10000; /* 64KB */
79         g_assert((PortCapabilities.MaximumTransferLength%PAGE_SIZE)==0);
80         PortCapabilities.MaximumPhysicalPages=PortCapabilities.MaximumTransferLength/PAGE_SIZE;
81         PortCapabilities.SupportedAsynchronousEvents=0;
82         PortCapabilities.AlignmentMask=1;       /* no alignment required by us; speced as "integer multiple" */
83         PortCapabilities.TaggedQueuing=FALSE;
84         PortCapabilities.AdapterScansDown=FALSE;
85         PortCapabilities.AdapterUsesPio=TRUE;
86
87         DeviceExtension=DeviceObject->DeviceExtension;
88         DeviceExtension->MediaChangeCount=0;
89         DeviceExtension->PhysicalDevice=DeviceObject;   /* no real PhysicalDeviceObject */
90         DeviceExtension->LockCount=0;
91         DeviceExtension->DeviceNumber=0;        /* corresponds to the # in "\\Device\\CdRom0" */
92         /* ignored DeviceExtension->PortDeviceObject
93          * as we are the final driver and we don't have any PortDeviceObject
94          */
95         DeviceExtension->PortCapabilities=&PortCapabilities;
96         DeviceExtension->StartingOffset.QuadPart=0;
97         DeviceExtension->PartitionLength.QuadPart=Image_size;
98         DeviceExtension->PortNumber=0;
99         DeviceExtension->PathId=0;
100         DeviceExtension->TargetId=0;
101         DeviceExtension->Lun=0;
102
103         /* FIXME: DriverObject->MajorFunction[IRP_MJ_CREATE] = ...; ... */
104
105         return STATUS_SUCCESS;
106 }
107
108 /**
109  * captive_cdrom_init:
110  * @image_pathname: Host OS file #utf8 pathname of the disk image to provide.
111  * %NULL value is forbidden.
112  *
113  * Creates system device "\Device\CdRom%d" providing readonly access
114  * to the given @image_pathname as emulation of CD-ROM driver.
115  *
116  * captive currently supports just one drive and thus "\Device\CdRom0"
117  * is always created. It is forbidden to call this function twice.
118  *
119  * Returns: %TRUE if the initialization was successful.
120  */
121 gboolean captive_cdrom_init(const gchar *image_pathname)
122 {
123 NTSTATUS err;
124
125         g_return_val_if_fail(image_pathname!=NULL,FALSE);
126
127         Image_fd=open(image_pathname,O_RDONLY
128 #ifdef O_BINARY
129                         |O_BINARY
130 #endif
131                         );      /* FIXME: lseek64() */
132         g_return_val_if_fail(Image_fd!=-1,FALSE);
133
134         Image_size=lseek(Image_fd,0,SEEK_END);  /* FIXME: lseek64() */
135         if (Image_size==(off_t)-1) {
136                 g_assert_not_reached();
137                 goto err_close;
138                 }
139
140         err=DriverEntry(
141                         &cdrom_DriverObject,    /* DriverEntry_DriverObject */
142                         captive_utf8_to_UnicodeString_alloca("\\captive\\storage\\cdrom"));     /* DriverEntry_RegistryPath; ignored */
143         g_return_val_if_fail(NT_SUCCESS(err),FALSE);
144
145         return TRUE;
146
147 err_close:
148         close(Image_fd);
149         Image_fd=-1;
150 /* err: */
151         g_return_val_if_reached(FALSE);
152 }