(This post has been modified a bit since I first posted it.)
(28 July 2008 - further update, added "DriveLetterN" to the list of registry settings.)
Documentation: I found that not much explanations are needed if you provide a lot of examples, starting with trivial sample and adding features one by one. It also helps in testing, as it's easy to play with a sample writing down what's happening
All driver settings are in a very "techincal" format in the registry, basically based on the data structure the user mode applications send to the driver when a new virtual disk is created. You can create a registry key HKLM\SYSTEM\CurrentControlSet\Services\ImDisk\Parameters. Under that key the following values can be created.MaxDevices
Optional value, default value is currently 16. If defined this should be a 32-bit (REG_DWORD) value and it can be used to specify the maximum number of virtual devices that can be created. This can be at most 32 because the driver keeps track of used device numbers in a 32-bit bit-field.LoadDevices
This should be a 32-bit (REG_DWORD) value and it can be used to automatically create virtual disks when the driver is loaded. This means that if the driver is setup to load at system boot, virtual disks will be created at system boot. The value specifies the number of virtual disks to create in this way.FileNameN
These values (string values of type REG_SZ) specifies which image file should be used for the virtual disks specified with the LoadDevices value. N should be replaced with 0 for the first virtual disk, 1 for the second and so on. Just like otherwise the filename is optional for RAM-disks and if a filename is specified for a RAM-disk this just specifies an image file to pre-load into the RAM-disk when it is created.SizeN
These values should be 64-bit binary values and specifies the size for virtual disks. For file backed disks, the file size is adjusted to this size. N should be replaced with 0 for the first virtual disk, 1 for the second and so on. These parameters are optional for file backed virtual disks. Note that the Size values are specified in reverse byte order, the first byte represent the least significant byte of the 64-bit size.FlagsN
These values specifies different options for creating the virtual disks. It should be a 32-bit (REG_DWORD) value. The flags are any reasonable combination of the flags specified in the source package in inc\imdisk.h (scroll down to "Bit constants for the Flags field in IMDISK_CREATE_DATA"). Note that most flags can be auto-selected so you will not always need to create the Flags value. For example, if you specify a size and no filename a r/w RAM-disk is created, if you specify a filename then a file backed virtual disk is created and so on.DriveLetterN
These values should be string values where the first character is used to create a drive letter for the virtual disk. If no DriveLetter setting is present for a virtual disk, no drive letter is created for it.
As it is right now there is no error reporting whatsoever if any of the disks specified by LoadDevices cannot be created, neither to attached kernel debuggers nor to the system event log. I will add some error reporting in the future.
Also, you have a lot of useful comments - just mark them somehow, then automatically extract to the docs.
Yes, I have been thinking about generating docs from comments with Doxygen but it did not understand Windows driver code very well so... Do anyone know anything better?
I think, it will be possible to boot from the network (PXE server). Eventually, I'll take care of that
I understand why it's not possible, but I think I know how to do it
Good. I like such comments.
I propose a feature (for better compatibility):
For each image create not only \\.\PHYSICALDRIVEx (drive), but also \\.\PHYSICALDRIVEn (volume),
where x-letter; n-number. The drive should have "fake MBR" with only one partition, which is the volume
All sectors from fake MBR till Boot Record are also supposed to be virtual (all 00h by default). MBR code, NT-signature, and (optionally) sectors are supposed to be user-definable.
I can see that this could be useful but it requires lots of modifications both to the driver logic itself and to the way it registers the new virtual disks on the system so this will probably not be implemented in a near future.
Another idea is to add more control over data buffering:
- optional asynchronous load of a full image (in background)
This should not be very difficult to implement. The image file is read into the memory by the newly created worker thread, but currently the calling thread waits for this to finish. I suppose there would be no big issues with just modifying this a little bit so that the image read-in is delayed to after the point the caller is waiting for.
- optional memory buffer with user-definable buffer size, policy (MRU?),
and percent of buffer which is non-pageable
- "fast mode" - return to caller right after writing to the buffer (temporary/dicardable data).
- "EWF mode" - changes are not reflected in source image
submodes: changes in memory, changes on another drive (local or virtual)
Interesting ideas. I have thought about some kind of write-copy mode that stores changed parts of the image in a memory buffer or in some kind of "undo file". The reason that is a heavy task to implement is that it needs some kind of cluster-indexing thingy in the background, some place where the driver can look in a table and see wether to read requested data from the original image file or from another place. But it is definitely something that I will try to implement in the future.
- all command line options available from registry (just as one string?)
- Complete uninstall, as if it never been installed.
- user-definable policy on priorities of execution threads (useful?)
All command line options are available, not as one string, but as described above.
The current uninstall routines should leave no traces. Is there anything in particular you think of here?
User-defined worker thread priority would probably be useful, yes, and hopefully not very difficult to implement as each virtual disk creates a worker thread in the System process and it can set which priority it likes when it is started.
I took a quick look at your code. I can read "C", but not write
That's what I noticed (I may be wrong, though),
- IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS - not supported
- IOCTL_DISK_GET_DRIVE_GEOMETRY (etc.) does not return Media Type and Total Cyl
IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS should only be implemented by disk drivers for volumes on hard disk drives and there are no hard disk drives associated with the ImDisk "partitions".
Which media type is returned depends on the drive type. It is for example 12 for virtual hard disk partitions and 11 for virtual CD/DVD-ROM drives. Total number of cylinders should be returned but possibly rounded down to nearest integer.
You can download my 'devioctl' tool: <a href="http://www.ltr-data....s/devioctl.zip"
Type for example
devioctl geometry C:
to see what disk.sys returns for drive C: and then
devioctl geometry E:
to see what imdisk.sys returns for an ImDisk drive E:.
BTW, general expression: very good professional work
Thanks a lot!
Regarding server-side of the communication proxy: I'd be interested in complete specification (I'm thinking about implementing it on windows). Even better it would be to have an API to a user-written DLL that provides virtual I/O (server side).
I mean something like this:
virtual disk<-->proxy client<-->transport<-->proxy server<--(API)-->UserDLL<-->whatever
The structures of the headers of the I/O packets sent between client and server are defined in inc\imdproxy.h and there is a sample implementation of it for TCP/IP redirection in the devio sub-directory. Most of the interesting stuff goes in devio/devio.c. I keep a compiled exe at <a href="http://www.ltr-data....iles/devio.exe"
target="_blank">http://www.ltr-data.se/files/devio.exe</a></a> too. The source for devio is pretty much POSIX-ish as it started off as a project for a FreeBSD Live CD but it should be fairly easy to start with that and extend it so that instead of opening a file or device it can call functions in a dll.