The story of the vfdwin 2.1 64-bit driver patch
Published on 2007/08/17 by Igor Levicki
Some time ago I experienced an urgent need for the 64-bit version of vfdwin 2.1, which in case you didn't know is a Virtual Floppy Drive 2.1. It is a very handy tool written by Ken Kato that allows you to create or unpack floppy images without having the physical floppy drive by means of drive emulation.
However, I ran into a problem immediately because he doesn't provide 64-bit build and according to him he doesn't intend to, even though doing so is pretty straightforward. Luckily, he does provide source code so you can build it yourself but that requires a lot of expertise — something that is not common for majority of ordinary computer users.
Since I am a software engineer that wasn't going to stop me, I downloaded the source code and immediately tried to compile it because I already had DDK installed for my own work. I unpacked the source code, set up the build environment and ran the build but it failed.
As it turned out, the error wasn't too serious. I quickly figured out that it is just a pointer precision issue and I informed the author of the proper way to fix it:
vfdimg.c: 466: < OUT PULONG ReturnLength) > OUT ULONG_PTR* ReturnLength) vfddrv.h < OUT PULONG ReturnLength); > OUT ULONG_PTR* ReturnLength); Rationale behind this change is that in ntddk.h IoStatus.Information field is defined as ULONG_PTR, and not as ULONG. In case you don't know the difference, ULONG_PTR is defined as unsigned __int3264 while ULONG is just unsigned long. So, ULONG_PTR should be used for portability reasons.
As you can see, only two lines of the source code needed changing to enable proper 64-bit compilation. However, someone beat me to it. Enter critical0 — the savior of the illiterate masses for his change was even simpler:
All I had to change was vfdioctl.c line 120 became : (PULONG)&Irp->IoStatus.Information); to fix up the warning about incompatible types.
I did my best to explain that my change is the proper one:
You should remove that other suggestion. That cast is bad. As I already told you, IoStatus.Information field is defined as ULONG_PTR in ntddk.h. ULONG_PTR is one of the "pointer precision" types. It means that if you compile your driver for 32-bit Windows, ULONG_PTR will be 32 bits long. But if you compile it for 64-bit Windows then ULONG_PTR will be 64 bits long. So if you do the cast like critical0 did: (PULONG)&Irp->IoStatus.Information) You are throwing away upper 32 bits of the value. It may work but it is not safe.
I have also told him that I have tested the driver and that it works fine on my system and even sent him the 64-bit executable I've built to replace the one built by critical0 which included the dreaded cast.
I couldn't believe that he didn't want to bother to update the source code with the fixed version, let alone include properly built 64-bit driver in the distribution. If it were me at least I would welcome any help. So I said:
Ken, My fix works too and it is safer than the casting. You do whatever you want -- it is your source code anyway. All I wanted is to help but it seems that you don't give a rat's tail. Regards, Igor
I thought that our discussion will end there, but he kept arguing that the other version works fine, that he is too busy and all together it sounded like it is actually not that important to have proper 64-bit build.
In the end I got pissed off by such an attitude, lost my patience, and sent him my last reply:
Listen buddy, Instead of wasting your precious time (you said you were busy, right?) explaining your stubborness you could've changed those two lines in your source code about a dozen times already. You wrote zero to that field before calling the function, so what? You still have another issue -- blocked store to load forwarding: "The store must be equal or greater in size than the size of data being loaded." VfdQueryImage() gets called and it writes 32-bit value because of the cast. Then the kernel wants to read whole 64-bit value in order to pass it back to the application. That 32-bit (4 byte) write has to go from the cache line to the main memory and then that whole cache line (64 bytes) has to be re-read to get the 64-bit value back. Net result -- wasted CPU and memory bus cycles. It is not in a critical code path but I don't see a single good reason for letting such sloppy code live. Anyway, I don't want to waste more of my time listening to your pathetic excuses, you certainly got more help from me than you deserved considering your attitude. Do whatever you want with it because (read my lips): I DON'T CARE. Regards, Igor
Some time ago I searched for "Igor Levicki" on Google to see how well indexed are some of the entries on my website, and I was surprised to find his Japanese vfdwin page mentioning me but with considerably more comments than the English one.
Since I do not speak Japanese, I felt it was a bit unfair of him to talk behind my back because I didn't do anthing like that to him. I run the page through Google Translation and Babel Fish in an attempt to understand what exactly he is talking about, but unfortunately machine translation is no match for a human translator which I didn't have available at the moment.
From what I did understand, it seems that beside some doubts he may still have about my good intention he continued to argue how performance penalty I spoke of is not that big. That is true indeed, but there is a thing called death by a thousand paper cuts, and developing a habit of doing bad things in your code, however small and unimportant they may be, is not something that any rational thinking person would insist on clinging to.
So Ken Kato, if you ever read this:
It took some of my time to find a proper fix, to build a driver and communicate with you. It wasn't something I was obliged to do -- I fixed the problem for myself and I could have easily stopped at that but I didn't because I wanted everyone else to benefit from what I did.
It took even more of my time and effort to argue with you, to try to explain and educate, but I was met only by a wall of your stubborness. I wasn't expecting that kind of response, just like I wasn't expecting you to appreciate what I did. After all, my effort wasn't originally directed at you. Hopefully you now understand my intention? Language can really be a barrier sometimes and not being able to see your correspondent makes it even harder, but that is something one has to get used to in order to "survive" on the Internet.
UPDATE (2009-03-04 @ 05:15:32 CET):
Now you can download the 64-bit version of vfdwin driver from my website Downloads section. I have made it available because several people asked for it. Vista x64 users, you know the drill — you will have to press F8 and disable driver signature checking in order to use it.