tags:

views:

813

answers:

6

I have a separate partition on my disk formatted with FAT32. When I hibernate windows, I want to be able to load another OS, create/modify files that are on that partition, then bring Windows out of hibernation and be able to see the changes that I've made.

I know what you're going to type, "Well, you're not supposed to do that!" and then link me to some specs about how what I'm trying to do is wrong/impossible/going to break EVERYTHING. However, I'm sure there's some way I can get around that. :)

I don't need the FAT32 partition in Windows, except to read the files that were written there, then I'm done - so whatever the solution is, it's acceptable for the disk to be completely inaccessible for a period of time. Unfortunately, I can't take the entire physical disk offline because it is just a partition of the same physical device that windows is installed on -- just the partition.

These are the things I've tried so far...

  1. Google it. I got at least one "this is NEVER going to happen" answer. Unacceptable! :)
  2. Unmount the disk before hibernating. Mount after coming out of hibernation. This seems to have no effect. Windows still thinks the FAT is the same as it was before, so whatever data I wrote to disk is lost, and any files I resized are corrupted. If any of the file was cached, it's even worse.
  3. Use DeviceIoControl to call IOCTL_DISK_UPDATE_PROPERTIES to try and refresh the disk (but the partition table hasn't changed, so this doesn't really do anything).

Is there any way to invalidate the disk/volume read cache to force windows to go back to the disk?

I thought about opening the partition and reading/writing directly by using libfat and bypassing the cache or something is overkill.

A: 

My memory is that the FAT table is read during the OS boot and mounting of the volume. Can't you do a shutdown, then modify the FAT, then reboot Windows?

Kluge
+2  A: 

Well, you're not supposed to do that! ;-)

Since the operating system (Windows in this case, but Linux is the same) writes some of its internal filesystem structures in the hibernation image, it is going to be very confused if the disk contents change while it's "running" (think of hibernation as just a long pause in the operating system's execution).

What I can suggest is that you completely bypass the issue: format the partition as ext2. There are Windows programs to read an ext2 partition, which you can use to get data out of it, and most modern operating systems should be able to read/write it (since it's a quite common Unix-style filesystem). Avoid ext2 IFS drivers; you want to take the filesystem access out of the kernel and into a program which you can open and close at will.

CesarB
+1  A: 

Use Linux to create the partition as a hidden FAT32 partition. Linux will let you mount the partition and write files. Windows will not let you mount the partition and read files, and Windows will not corrupt the partition. But there are third party libraries that will read the partition while Windows is running.

To clarify, hidden means that the partition type is different from an ordinary FAT32 partition type. If your ordinary partition type is 0x0C then the corresponding hidden type is 0x1C.

Windows programmer
A: 

Thanks for the comments.

@CesarB
I like this idea, it would definitely be a great way to guarantee the data is not modified.

@Kluge
Unfortunately, we can't shut the OS down. It has to work coming out of hibernation.

@Godeke
In this case, I can't add additional hardware, I have to work with existing hardware. I was hoping that I'd be able to do something like this with just the volume that I've modified, but it doesn't work that way :(.

@Windows programmer I like this idea as well. The application that writes to the drive in hibernation wouldn't need to be modified much at all. I think I'd run into patent issues if I tried to read the FAT32 partition directly in my app though, right?

Before I start implementing any changes... Will the disk READ cache defeat me no matter what? I know I can write directly to the disk, but I've never seen anything in the documentation about bypassing the read cache. And I have a feeling it's basically at the block device level regardless of whether windows understands the file system or not.

Nick
I would expect the disk read cache to be simply discarded when hibernating, since it's useless then (you have to read from the disk anyway). Also, a Windows application probably can bypass the disk cache (on Linux, with O_DIRECT; I don't know how to do it on Windows).
CesarB
IS it useless? I would have expected that as well, but in testing it appears that this isn't so... I'm still looking to see if there's something I can use to bypass the disk cache. I see a way to bypass the write cache, but not the read cache.
Nick
I don't know any way to bypass the read cache. Bypassing the write cache isn't good enough because if Windows wants to retain the written data for a while and consider it as a read cache it can do so. This is why ext2 or a hidden partition can work -- Windows refuses to read them normally.
Windows programmer
Good question about whether Microsoft requires a fee if your app accesses FAT32 outside of Windows. Does anyone know if Linux implementors paid Microsoft a fee?
Windows programmer
My point was that is the caching done at the file system level, the disk level, or both? If it's done at the disk level at all, I'm in trouble.
Nick
As far as I can tell, Windows does caching at the disk level. However, if a partition has a type that Windows refuses to read or write (ext2, hidden FAT32, etc.) then that partition's contents should never get into Windows caches in the first place.
Windows programmer
I am going to do some more investigation along these lines. Thanks
Nick
A: 

As far as I can tell, Windows does caching at the disk level. However, if a partition has a type that Windows refuses to read or write (ext2, hidden FAT32, etc.) then that partition's contents should never get into Windows caches in the first place.

Windows programmer
Sorry for accidentally typing the above as an "answer" before typing it where it belonged. Please just ignore this "answer".
Windows programmer
+1  A: 

So I finally got a solution to my problem. In my mind, I associated Mount Point with Mount. These are NOT the same thing. Removing all of the volume mount points does not make the volume unmounted. It's still mounted but not in the sense that you have a path you can access in explorer.

This is the article started it all: http://ubuntuforums.org/showthread.php?p=171082 It also goes to show that searching for your EXACT problem, as opposed to the perceived problem can help a lot!

So there were a couple of solutions, one was to constantly call NtSetSystemInformation() in a tight loop to set the "SYSTEMCACHEINFORMATION" property to essentially empty/clear the cache whenever the system is going to hibernation. Then stop the loop when you come out. This, to me, seemed like it could affect system performance. So I discarded it.

Even better though, is the recommended solution to a slightly different problem presented in this MSDN article, which provides direction to an even better solution to the problem: http://msdn.microsoft.com/en-us/library/dd143253.aspx

Now I have a service which will flush the write caches, then lock and dismount the volume whenever the system goes into hibernation/sleep and release the lock on the volume as soon as it comes out.

Here's a little bit of code. OnHibernate>

volumeHandle = CreateFile(volumePath,
                          GENERIC_READ|GENERIC_WRITE, 
                          FILE_SHARE_READ|FILE_SHARE_WRITE,
                          NULL,
                          OPEN_EXISTING, 
                          FILE_ATTRIBUTE_NORMAL,
                          0 );
FlushFileBuffers( volumeHandle );
DeviceIoControl( volumeHandle, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &cbReturned, NULL ) ;
DeviceIoControl( volumeHandle, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &cbReturned, NULL );
//Keep the handle open here.
//System hibernates.

OnResume>

DeviceIoControl( volumeHandle, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &cbReturned, NULL )
CloseHandle(volumeHandle)

Hopefully this helps someone else out in the future :)

Nick
Now, if only I could mark this as the accepted answer for future viewers... Ah well.
Nick