Jump to content











Photo
- - - - -

Need help creating custom virtual disk driver


  • Please log in to reply
23 replies to this topic

#1 darkwhisperer

darkwhisperer

    Newbie

  • Members
  • 11 posts
  •  
    South Africa

Posted 06 September 2007 - 06:49 AM

Hi all,

Im writing an application thats going to use unused space on machines across our network, and present that space to the user as a "drive".

A local service on the machine will control the drive. Any attempts to read or write to the drive will be intercepted by or passed to the service. The service will query the database and get the information regarding where on the network this data is stored, and then proceed to either get or send the data to this location.

I was looking at the source code for ImDisk, to try to figure out how the disk space is presented as a drive to the system. But its a work in progress, and very difficult for me to figure out. :loleverybody:

Please can someone explain in more detail, or at least point me in the right direction regarding working on things at this level. Maybe a good site that explains how to write these drivers.

Thanks in advance for any help given. :w00t:

#2 Olof Lagerkvist

Olof Lagerkvist

    Gold Member

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

Posted 06 September 2007 - 08:23 AM

Interesting project!

Maybe you could take a look at the proxy functions of ImDisk. Under the source tree there is a directory called devio with a sample proxy service that just listens to I/O requests over a TCP/IP socket and then uses an ordinary file as storage.

The actual I/O requests are sent by the ImDisk driver and they are really very easy, basically a code that indicates whether it is a read or write request, the size of the date and then the data itself. Because the requests are sent over an ordinary TCP/IP socket it should be possible for you to implement a service for it in practically any programming language without any particular knowledge of driver development.

#3 darkwhisperer

darkwhisperer

    Newbie

  • Members
  • 11 posts
  •  
    South Africa

Posted 06 September 2007 - 09:21 AM

Hi,

Thanks for that! Looks like my problem may be solved... Just have to figure out how to listen over a TCP/IP socket (doesn't sound too tough), and then kidnap the read & write calls to your RAMDISK.

If Im using those same calls, what will happen to the RAMDISK? IE The actual space used in memory? Additionally, wont size be a problem? Say my available space is 4Tb. Will the driver have any problems with that amount of space? Or will it just send and receive the data, and not really care how things are stored on the backend?

Thanks for all your help! And for your totally great App!

#4 Olof Lagerkvist

Olof Lagerkvist

    Gold Member

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

Posted 06 September 2007 - 09:30 AM

If Im using those same calls, what will happen to the RAMDISK? IE The actual space used in memory? Additionally, wont size be a problem? Say my available space is 4Tb. Will the driver have any problems with that amount of space? Or will it just send and receive the data, and not really care how things are stored on the backend?

Exactly, when you create an ImDisk device with redirection of the I/O requests no RAMDISK storage is allocated by the ImDisk driver. All it will do is taking the I/O requests from the filesystem for the virtual disk and redirect it to your application.

#5 darkwhisperer

darkwhisperer

    Newbie

  • Members
  • 11 posts
  •  
    South Africa

Posted 06 September 2007 - 01:22 PM

Ok, cool.

Its seems that setting up TCPIP listening is a little tricky in C#, or it could be that Im just tired. :loleverybody: I'll continue working on that tomorrow.

I have a question about the data thats set up when a drive is created...

If you set up a drive, via a proxy, is it still formatted?

Each person who logs in should have their own drive, with only their data on it. This will be handled (what belongs to whom) by the service. But can I create an image, as a formatted drive with the NTFS file structure, but no actual data, and set that up to use with the proxy, so that when the data is being accessed, the proxy deals with returning the data(which isnt on the image)? Does the idea make sense, or am I missing something? :w00t:

#6 Olof Lagerkvist

Olof Lagerkvist

    Gold Member

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

Posted 06 September 2007 - 01:44 PM

Its seems that setting up TCPIP listening is a little tricky in C#, or it could be that Im just tired. :loleverybody: I'll continue working on that tomorrow.

Try to search for some sample code... there are lots of examples on the web. It is a lot easier to start from something already written.

If you set up a drive, via a proxy, is it still formatted?

No, ImDisk never formats any kind of virtual disk or in any other way modifies the contents of it by its own. You can use the ordinary Windows ways to format the virtual disk.

Each person who logs in should have their own drive, with only their data on it. This will be handled (what belongs to whom) by the service. But can I create an image, as a formatted drive with the NTFS file structure, but no actual data, and set that up to use with the proxy, so that when the data is being accessed, the proxy deals with returning the data(which isnt on the image)? Does the idea make sense, or am I missing something? :w00t:

Should be possible. For example, when a new drive is first mounted you could fill it with an empty NTFS filesystem structue and present that to the driver.

#7 darkwhisperer

darkwhisperer

    Newbie

  • Members
  • 11 posts
  •  
    South Africa

Posted 06 September 2007 - 02:42 PM

Ok, got the TCPIP socket listener working, but having a problem with setting up the drive. Command used:

imdisk -a -t proxy -o ip -f 127.0.0.1:4567 -m W:

Error:

The ImDisk Virtual Disk Driver was loaded into the kernel.
The ImDisk Virtual Disk Driver Helper Service was started.
Error creating virtual disk: The parameter is incorrect.

So Im guessing one of my parameters was wrong. Cant figure out which one it is tho. Is any response expected when the drive is to be mounted? When I run this, a smiley face and about 4 newlines appear on my Console as the data the listener received. Could it be that it needs to send some data back before the drive is initialized?

#8 Olof Lagerkvist

Olof Lagerkvist

    Gold Member

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

Posted 06 September 2007 - 04:01 PM

So Im guessing one of my parameters was wrong. Cant figure out which one it is tho. Is any response expected when the drive is to be mounted? When I run this, a smiley face and about 4 newlines appear on my Console as the data the listener received. Could it be that it needs to send some data back before the drive is initialized?

Okay, the data sent between the ImDisk driver and your application should follow a special protocol. Basically, first the driver asks your application for some information (sends IMDPROXY_REQ_INFO) and your application should respond with an IMDPROXY_INFO_RESP structure filled with some information about the virtual drive, for example the size of it. After that, the driver sends either IMDPROXY_READ_REQ or IMDPROXY_WRITE_REQ structures and your application should carry out the request and respond with an IMDPROXY_READ_RESP or IMDPROXY_WRITE_RESP structure.

The definitions for the structures are in inc\imdproxy.h and an implementation sample in C++ goes in devio\devio.c.

Hope this helps! :loleverybody:

#9 darkwhisperer

darkwhisperer

    Newbie

  • Members
  • 11 posts
  •  
    South Africa

Posted 07 September 2007 - 10:40 AM

Hi,

Thanks for that, the deeper details are starting to make sense now, and they just bring more questions...

Basically if I create a byte array 16777216 large, and just write/read all requests to there, I'll have a 16meg RamDisk. As I format it, I'll get to see how the FileSystem is set up on the disk. That right?

The only problem Im having is that I cant find a definition for IMDPROXY_REQ_INFO in imdproxy.h. I suspect its probably just my lack of C++ understanding.

This is what I understand so far of imdproxy.h:

The driver can send me 5 requests:
IMDPROXY_REQ_NULL, IMDPROXY_REQ_INFO, IMDPROXY_REQ_READ, IMDPROXY_REQ_WRITE, IMDPROXY_REQ_CONNECT, which is set up in the enum.

Now below that I see READ, WRITE, CONNECT - request & response pairs for each. Also an INFO response(no request?).
Now all the requests send 3*ULONGLONG pieces of data, probably as one chunk. I read the first 8 bytes, to get the request code. Now how will I know which number means which request code?
Then say I know its a read request, to read from offset to (offset+length). My response is errorno (perhaps 0 if all is well, but what are the other errors?) + length + a string of bytes as the data itself. Is that right?
If it wants to write, will it be sending me request_code+offset+length+(string of bytes as data)?

I hope you forgive me these questions, but Im really not used to programming at this level.
Thanks for all your assistance.

#10 Olof Lagerkvist

Olof Lagerkvist

    Gold Member

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

Posted 07 September 2007 - 04:26 PM

Basically if I create a byte array 16777216 large, and just write/read all requests to there, I'll have a 16meg RamDisk. As I format it, I'll get to see how the FileSystem is set up on the disk. That right?

Correct.

The driver can send me 5 requests:
IMDPROXY_REQ_NULL, IMDPROXY_REQ_INFO, IMDPROXY_REQ_READ, IMDPROXY_REQ_WRITE, IMDPROXY_REQ_CONNECT, which is set up in the enum.

Now below that I see READ, WRITE, CONNECT - request & response pairs for each. Also an INFO response(no request?).

Agree, that is not very well explained. What it actually does is that it just sends IMDPROXY_REQ_INFO as an ULONGLONG. There is no more data needed than the request code itself in this case, therefore there is no request structure for it.

Now all the requests send 3*ULONGLONG pieces of data, probably as one chunk. I read the first 8 bytes, to get the request code. Now how will I know which number means which request code?

The request code will be one of the values defined in the enum you mention above. Compare the request code to them to find out which one it is.

Then say I know its a read request, to read from offset to (offset+length). My response is errorno (perhaps 0 if all is well, but what are the other errors?) + length + a string of bytes as the data itself. Is that right?

Correct. The error codes are in this case traditional Unix/Posix error codes (same as C/C++ libraries use). Practically, all you need is to return 0 if ok and a non-zero value otherwise.

If it wants to write, will it be sending me request_code+offset+length+(string of bytes as data)?

Correct.

I hope you forgive me these questions, but Im really not used to programming at this level.
Thanks for all your assistance.

No problem! Happy coding! :loleverybody:

#11 darkwhisperer

darkwhisperer

    Newbie

  • Members
  • 11 posts
  •  
    South Africa

Posted 10 September 2007 - 06:30 AM

Excellent!

Now all I got to do is create a fake FAT file system to go between my backend and your frontend. No point in giving the users an unformatted drive...

By the way, I was playing with ImDisk over the weekend, and I managed to create a drive with your proxy-tester application. However, I couldnt format it with FAT, only NTFS. Any ideas why, or did I probably just do something wrong?

Thanks...

#12 Olof Lagerkvist

Olof Lagerkvist

    Gold Member

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

Posted 10 September 2007 - 07:43 PM

By the way, I was playing with ImDisk over the weekend, and I managed to create a drive with your proxy-tester application. However, I couldnt format it with FAT, only NTFS. Any ideas why, or did I probably just do something wrong?

You have to explain exactly what you did, otherwise I don't know...

Example:
fsutil file createnew imagefile 0

devio 9000 imagefile 400M

imdisk -a -t proxy -o ip -f localhost:9000 -m T:


#13 darkwhisperer

darkwhisperer

    Newbie

  • Members
  • 11 posts
  •  
    South Africa

Posted 11 September 2007 - 01:52 PM

Dont worry about the FAT/NTFS thing, I've forgotten what commands I was using...

My latest problem is with 'My Computer' hanging upon initialization of the drive.

I setup my proxy to listen. Then I execute:
imdisk -a -t proxy -o ip -f 127.0.0.1:4567 -m W:

At that point my listener receives the drive info request, and I send back 4194304, 512, 0. BTW, what are the flags that I can use for this last value?

The Prompt says:
Created device 0: W: -> 127.0.0.1:4567.

So that seems to be fine. But when I go to 'My Computer', the window just hangs. Then when I shut down my proxy, 'My Computer' returns to normal, with a W: there as expected. When I try to do something with that drive, it says "The Device is not ready".

Im looking out for read/write/other type requests, but none are coming through when 'My Computer' stalls. Im wondering if theres some flag Im supposed to send back. Or do you think its something else?

Thanks...

#14 darkwhisperer

darkwhisperer

    Newbie

  • Members
  • 11 posts
  •  
    South Africa

Posted 13 September 2007 - 08:13 AM

Hi,

I've managed to solve the "hang" problem, by changing the way my application handles the socket connection.

Now there seems to be be something wrong with my "write" function, according to windows at least.

I start up my proxy. This loads into my byte[] "drive" a previously created empty FAT image(.img file). And so my proxy is up & listening.

Then I execute: "imdisk -a -t proxy -o ip -f 127.0.0.1:4567 -m M:", and the response is "Created device 1: M: -> 127.0.0.1:4567". So all is well so far.

Some read requests come through, and they are handled. I can browse into the drive. Then I take a tiny file and paste it into the drive. Some write requests come through, and the file appears, and I can read it. But after about 5 seconds, a popup appears, as shown in the attachment. It is strange, because the write seemed to have worked fine. I can read the data perfectly. So Im guessing Im not sending something back to the driver to say, "write complete". Any ideas what could be causing this?

Thanks...

Attached Thumbnails

  • error.JPG


#15 Olof Lagerkvist

Olof Lagerkvist

    Gold Member

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

Posted 13 September 2007 - 10:16 AM

Some write requests come through, and the file appears, and I can read it. But after about 5 seconds, a popup appears, as shown in the attachment. It is strange, because the write seemed to have worked fine. I can read the data perfectly. So Im guessing Im not sending something back to the driver to say, "write complete". Any ideas what could be causing this?

I think you mistakenly make the assumption that the write operation has been sucessful just because you can read the file back again. But filesystems do not work that way, everything goes through a filesystem cache and that is probably where your file is and where it is been read back from, not from the actual disk image your proxy handles. You can check that by dismounting and remounting the image and see if the file is still there.

There must be something wrong with how you handle write requests though. You are supposed to send back an IMDPROXY_WRITE_RESP structure that contains first an error code which you should set to zero and then a field that indicates the length successfully written. You should set that field to the number of bytes you have written, that is, the number of byte you were asked to write.

#16 darkwhisperer

darkwhisperer

    Newbie

  • Members
  • 11 posts
  •  
    South Africa

Posted 13 September 2007 - 10:39 AM

Hi,

Well, Im pretty sure that Im sending back what you're asking me to.

An example of a write:
Val: 0003 | 8000 | 0e00 W R : Sent: 0000 | 0e00 | Write from 32768 to 36352 (3584 bytes).

The 3 Val values are what I get(in hex). "W R" implies write request. The two "Sent" values are what I send back. And then a general description.
So it seems right to me.

Question though, when Im sending data back, should I first send a 0 back, then send the bytes written? Or can I just join the 2 into a 16 byte [] and send it off(current method)? Does it make a difference which I use?

Also, does the driver send data in bursts if it cant send it in one go?

#17 Olof Lagerkvist

Olof Lagerkvist

    Gold Member

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

Posted 13 September 2007 - 10:57 AM

Hi,

Well, Im pretty sure that Im sending back what you're asking me to.

An example of a write:
Val: 0003 | 8000 | 0e00 W R : Sent: 0000 | 0e00 | Write from 32768 to 36352 (3584 bytes).

The 3 Val values are what I get(in hex). "W R" implies write request. The two "Sent" values are what I send back. And then a general description.
So it seems right to me.

Yes, indeed that looks correct...

Question though, when Im sending data back, should I first send a 0 back, then send the bytes written? Or can I just join the 2 into a 16 byte [] and send it off(current method)? Does it make a difference which I use?

That does not matter. If you send 16 bytes the first 8 bytes should be zero and the last 16 bytes should form an ulonglong with the number of bytes written. In your example:

{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }

Also, does the driver send data in bursts if it cant send it in one go?

There is no such concept in TCP/IP. TCP connections are streams and there are no "message boundaries" or something like that. If a writer writes first 1000 bytes and then 1000 more bytes the receiver may get all 2000 bytes at once, or 500 bytes first and then 1500 bytes or anything like that.

#18 darkwhisperer

darkwhisperer

    Newbie

  • Members
  • 11 posts
  •  
    South Africa

Posted 13 September 2007 - 11:30 AM

Shew...

So if Im listening for data in an endless while loop once the connection is created, then the logic I should use is something like this:

Once data becomes available, read first 24 bytes. If it can be broken down into a message, then its a request. If it cant, then it must be data belonging to a previous request.

Im wondering because previously when I tried copying a 400Kb file to my proxy, it did a write request for 65kb, and then sent through about 8 nonsensical requests. So Im guessing that was still data belonging to the previous write request.

My understanding was that the data comes through when its all arrived. But if you say that it comes through in bits and pieces, that makes things more tricky.

Well, Im gonna keep trying to get this thing working.

Thanks for all your help :loleverybody:

#19 Olof Lagerkvist

Olof Lagerkvist

    Gold Member

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

Posted 13 September 2007 - 01:17 PM

So if Im listening for data in an endless while loop once the connection is created, then the logic I should use is something like this:

Once data becomes available, read first 24 bytes. If it can be broken down into a message, then its a request. If it cant, then it must be data belonging to a previous request.

I would not recommend exactly that though, you should rather check what the initial message header tells you. It includes information about how many bytes you are supposed to write and then it sends that number of bytes to you. You have to treat all further data up to that number of bytes as the data you should write.

Thanks for all your help :loleverybody:

No problem! :w00t:

#20 darkwhisperer

darkwhisperer

    Newbie

  • Members
  • 11 posts
  •  
    South Africa

Posted 14 September 2007 - 12:31 PM

Hi,

I've finally got the drive working properly. :loleverybody: I recoded from scratch both the listening and data send/receive functions. I think something was going wrong when I was trying to combine my ulongs into a byte [] and sending that. Now I just send the data that I want to send through, straight from the variable, and it seems to have solved the problem :w00t:

Now onto the tougher part of simulating the FAT, so that I can determine the DATA read&writes from the FileSystem read&writes. So its onto learning the FAT/FAT32 spec for me. :w00t:

Once more, thanks for your help, and even more thanks for a great application! :w00t: :w00t:

#21 Olof Lagerkvist

Olof Lagerkvist

    Gold Member

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

Posted 14 September 2007 - 04:12 PM

Once more, thanks for your help, and even more thanks for a great application! :loleverybody: :w00t:

Glad you made this part out and good luck with the rest of your project! :w00t: :w00t:

#22 RTTYLand

RTTYLand
  • Members
  • 2 posts

Posted 02 July 2010 - 11:00 AM

Hello, I had the same problem
Posted by your server, and tried to connect to it using ImDisk
This log of my server:
----------------------------
Receive: 8 bytes
01 00 00 00 00 00 00 00 (UInt64 = 1)
End

Send: 24 Bytes
00 66 4A C7 09 00 00 00 (UInt64 = 41'998'247'424)
00 02 00 00 00 00 00 00 (UInt64 = 512)
01 00 00 00 00 00 00 00 (UInt64 = 1)
End

Receive: 8 bytes
00 00 00 00 00 00 00 00 (UInt64 = 0)
End

Receive: 8 bytes
00 00 00 00 00 00 00 00 (UInt64 = 0)
End

Receive: 8 bytes
00 00 00 00 00 00 00 00 (UInt64 = 0)
End
----------------------------
I can not understand the last 3 request ... :cheers:

#23 RTTYLand

RTTYLand
  • Members
  • 2 posts

Posted 04 July 2010 - 05:22 PM

For a long time suffered, and decided to rewrite the code from scratch, learned what was the reason why I have it overwrote the first bytes. Now everything works! :cheers:
But the question remains: why ImDisk sends a query?
02 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00
he's does not mean anything...? :unsure:

#24 Olof Lagerkvist

Olof Lagerkvist

    Gold Member

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

Posted 07 July 2010 - 08:37 AM

For a long time suffered, and decided to rewrite the code from scratch, learned what was the reason why I have it overwrote the first bytes. Now everything works! :cheers:
But the question remains: why ImDisk sends a query?
02 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00 | 00 00 00 00 00 00 00 00
he's does not mean anything...? :cheers:


I don't know exactly why filesystem drivers send queries like that, but I suppose it is to check that the drive is "readable" without actually reading anything.

Btw, glad to hear that your ImDisk proxy project successfully talks with ImDisk! :rofl:




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users