Jump to content











Photo
- - - - -

Custom ImDisk proxy example

imdisk proxy example hello world

  • Please log in to reply
3 replies to this topic

#1 v77

v77

    Silver Member

  • Team Reboot
  • 602 posts
  •  
    France

Posted 27 September 2013 - 01:54 PM

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... :betasof:
Please also note that there is currently no Unicode support for devio.
 

 

Like Olof would say: happy coding! ;)


  • Olof Lagerkvist likes this

#2 Olof Lagerkvist

Olof Lagerkvist

    Gold Member

  • Developer
  • 1448 posts
  • Location:Borås, Sweden
  •  
    Sweden

Posted 27 September 2013 - 02:13 PM

Great guide, thanks!

 

Just one little thing to notice though, you have links to devio.h and devio_types.h that refer to some GitHub repository. Then, you recommend to download imdisk_source.7z from my website and extract the files from there instead. Although there are probably no differences and these file very rarely change, it could be worth knowing that they are not necessarily the same. As far as I know, there is nothing that automatically synchronize them (unless I am missing something).

 

Anyway again, thanks!



#3 v77

v77

    Silver Member

  • Team Reboot
  • 602 posts
  •  
    France

Posted 27 September 2013 - 02:20 PM

Just one little thing to notice though, you have links to devio.h and devio_types.h that refer to some GitHub repository. Then, you recommend to download imdisk_source.7z from my website and extract the files from there instead. Although there are probably no differences and these file very rarely change, it could be worth knowing that they are not necessarily the same. As far as I know, there is nothing that automatically synchronize them (unless I am missing something).

 

You are right, I have edited. :)


  • Olof Lagerkvist likes this

#4 erwan.l

erwan.l

    Platinum Member

  • Developer
  • 3041 posts
  • Location:Nantes - France
  •  
    France

Posted 20 July 2014 - 05:41 PM

Hi Gents,

 

Digging out this old thread but  for the delphi/freepascal dev guys out there, here below a delphi version of v77 ImDisk proxy example.

 

If any time, I'll post an example with EWF library which could allow one to mount an EWF file easily with imdisk.

 

Regards,

Erwan

library proxy;

uses
  SysUtils,
  Classes,windows;

{$R *.res}

type
  dllread_proc = function (handle:thandle; buf:pointer; size:cardinal; offset:int64): integer; cdecl;
  dllwrite_proc = function (handle:thandle; buf:pointer; size:cardinal; offset:int64): integer; cdecl;
  dllclose_proc = function (handle:thandle): integer; cdecl;

var
file_handle:thandle;

function SetFilePointerEx (hFile: THandle; lDistanceToMove: int64; lpNewFilePointer: Pointer; dwMoveMethod: DWORD): BOOL; stdcall; external 'kernel32.dll';
function GetFileSizeEx(hFile: THandle; var lpFileSize: Int64): BOOL; stdcall; external 'kernel32.dll' name 'GetFileSizeEx';

function my_read_proc(handle:thandle; buf:pointer; size:cardinal; offset:int64): integer; cdecl;
var
bytes_read:cardinal;
begin
	writeln('Read request - size:'+inttostr(size)+' offset:'+inttostr(offset));
	SetFilePointerEx(handle, offset, nil, FILE_BEGIN);
	ReadFile(handle, buf^, size, bytes_read, nil);
	result:=bytes_read;
end;

function my_write_proc(handle:thandle; buf:pointer; size:cardinal; offset:int64): integer; cdecl;
var
bytes_written:cardinal;
begin
	writeln('Write request - size:'+inttostr(size)+' offset:'+inttostr(offset));
	SetFilePointerEx(handle, offset, nil, FILE_BEGIN);
	WriteFile(handle, buf^, size, bytes_written, nil);
	result:=bytes_written;
end;

function my_close_proc(handle:thandle): integer; cdecl;
begin
	writeln('Close request');
	CloseHandle(handle);
	result:=0;
end;

function dllopen(filename:pchar; read_only:integer; var dllread:dllread_proc; var dllwrite:dllwrite_proc; var dllclose:dllclose_proc; var size:int64):thandle;cdecl;
begin
	writeln('File to open: '+filename);

	dllread := my_read_proc;
	dllwrite := my_write_proc;
	dllclose := my_close_proc;

	file_handle := CreateFile(filename, GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
	GetFileSizeEx(file_handle, size);

	result:=file_handle;
end;

exports
  dllopen index 1;

begin
end.






Also tagged with one or more of these keywords: imdisk, proxy, example, hello world

1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users