Here is a little example of custom imdisk proxy for Windows.
But first, what is a proxy for imdisk? It is a set of functions that is used to access something just before imdisk. You can intercept the datas that are read or written, and do what you want with them.
By reading or writing ourself an image file, we can for instance change the datas themselves, change their location, etc.
This example shows how to open an image file and reply to the requests of the system. With the help of the devio tool, this can be done quite easily.
So, what do you need?
- Install the ImDisk Virtual Disk Driver
- Download devio.exe
- Extract devio.h and devio_types.h from the imdisk source (in devio directory)
- An image file that can be mounted by imdisk. You can create one with the following command in an elevated command prompt:
imdisk -a -s 1M -m Z: -f test -p "/fs:FAT /q /y"
(don't forget to unmount it before continuing!)
Now, you have to compile the following code as a DLL. In fact, this is not a true DLL, because there is no DllMain function. If you are using MinGW, here is the command:
gcc.exe proxy.c -o proxy.dll -shared -s -Wall
.
#include <windows.h> #include <stdio.h> #include "devio_types.h" #include "devio.h" HANDLE file_handle; safeio_ssize_t __cdecl my_read_proc(void *handle, void *buf, int size, off_t_64 offset) { int bytes_read; printf("? Read request: %d bytes at offset %I64d\n", size, offset); SetFilePointerEx(*(HANDLE*)handle, (LARGE_INTEGER)offset, NULL, FILE_BEGIN); ReadFile(*(HANDLE*)handle, buf, size, (LPDWORD)&bytes_read, NULL); printf("? Bytes read: %d\n\n", bytes_read); return (safeio_ssize_t)bytes_read; } safeio_ssize_t __cdecl my_write_proc(void *handle, void *buf, int size, off_t_64 offset) { int bytes_written; printf("! Write request: %d bytes at offset %I64d\n", size, offset); SetFilePointerEx(*(HANDLE*)handle, (LARGE_INTEGER)offset, NULL, FILE_BEGIN); WriteFile(*(HANDLE*)handle, buf, size, (LPDWORD)&bytes_written, NULL); printf("! Bytes written: %d\n\n", bytes_written); return (safeio_ssize_t)bytes_written; } int __cdecl my_close_proc(void *handle) { printf("* Closing file...\n"); CloseHandle(*(HANDLE*)handle); return 0; } void * __cdecl dllopen(const char *file, int read_only, dllread_proc *dllread, dllwrite_proc *dllwrite, dllclose_proc *dllclose, off_t_64 *size) { printf("File to open: %s\nRead only: %d\n", file, read_only); *dllread = my_read_proc; *dllwrite = my_write_proc; *dllclose = my_close_proc; file_handle = CreateFile(file, read_only ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); GetFileSizeEx(file_handle, (LARGE_INTEGER*)size); return &file_handle; }
.
As you can see, there is 4 functions: the first one is called when datas must be read from the image file, the second for the writing, the third when the drive is unmounted, and the last one at the initialization.
Next, with your new "proxy.dll", you have to enter the following command in an elevated command prompt:
devio --dll=proxy.dll;dllopen shm:test_proxy test
and this one in another elevated command prompt:
imdisk -a -t proxy -o shm -f test_proxy -m Z:
And you're done!
Now, try to copy a small file into Z: and take a look at the first command prompt... (you may have to wait some seconds because of the Windows write caching)
Here, imdisk and devio are communicating through shared memory. But you can also do it through the network... With the command line switches of imdisk and devio, and with a bit of imagination, the possibilities are almost unlimited!
Of course, in order to keep this example as small and simple as possible, there is no checks. So...
Please also note that there is currently no Unicode support for devio.
Like Olof would say: happy coding!