FlushFileBuffers (again)

Hi all,

I searched through all the past messages on FlushFileBuffers used on a raw device, and I couldn’t find anything that helps with my problem. It seems to be with Vista and Windows 7, with particular types of drives (seemingly IDE drives, although I’m not sure if it’s a subclass of IDE drives), my FlushFileBuffers does not cause all the file system cached data to be written to the device. My code looks like this:

HANDLE hDrive;

char drive[100] ; // buffer to construct the drive name to open

// Flush has to be open with shared access:

sprintf(drive, “\\.\PHYSICALDRIVE%d”, driveNum) ;

hDrive = CreateFile ( drive,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);

if (hDrive == INVALID_HANDLE_VALUE)
return ERR_OPEN ;

if( !FlushFileBuffers(hDrive) )
{
DWORD result = GetLastError();

CloseHandle(hDrive) ;
return (int) result;
}

CloseHandle(hDrive);

return RETURN_OK;

I am doing a sector-by-sector image of the drive, from sector 0 to sector N, but before I do that, I add some drivers to the image. What I find is that there is around a 30% chance of my drivers being present in the finished image - in the 70% case some of the drivers will be missing, or one of them will be corrupted. Immediately after this CloseHandle, I re-open the raw device without the Share attributes to get more exclusive access to the disk.

All of this works perfectly in XP, but it seems that Vista / Windows 7, with certain drives, the flush doesn’t work all the time (as stated above). Note that I am using a single partition installation in both Vista and Windows 7 case - I don’t have the 100mB system partition.

Should the “PHYSICALDRIVE0” filename work here, or should it be “\.\c:” (with appropriate escapes added for the back-slashes)? GetLastError is returning an error code of “1” (invalid function), which according the the google is normal for a raw device, although it seems a little weird to me.

Bumping this for additional info, and I really, really need an answer of course. I tried switchnig the FlushFileBuffers to the drive letter, as in replacing the sprintf text to “\\.\c:”, and it no longer returns “invalid function”. However, I still have problems with files being missing in the scanned image. Presumably the files are there, but the directory entry is not, but I can’t be sure of that - I just know that sometimes chkdsk can recover the files.

SHould I put a delay after the “Flush”? Would that work? I’m only asking because it’s difficult to see if it works or not - sometimes the image scans successfully, and I think it’s all fixed, but then the next day it fails again without any software changes. Anyone who’s successfully done something like this, I would much appreciate some info, or sample code.

Thanks

I think you need to dismount the volume for the image to actually be complete.

Regards,
Alex.
This posting is provided “AS IS” with no warranties, and confers no rights.

Hi Alex,

Thanks. From what I can tell, I can’t do that while the system is running, unless i misread the docs - there would be open file handles (like the one to my executable), which would cause problems after the remount. That means this processing can only be done as part of shutdown, startup, or from a separate shell (like WinPE, for example)? Or am I overthinking this.

I guess what we are doing is not strictly supported by the o/s / filesystem, but it has always worked in the past (XP and earlier). There’s also the write-caching policy for the drive. In my experimentation, when I disable the write-caching the drive does seem to mirror accurately, although as with all caching it could be a numbers game, and I just got lucky the two or three times I ran with caching disabled.

As ever, the customers don’t like reboots, and it seems to me (again unless I misread) that all my options require a reboot - either run the capture as part of shutdown or startup in order to dismount, change the disk-caching policy and reboot for it to take effect, or even put the drivers in place and reboot, since then we’re guaranteed their both on the disk and in the filesystem.

Did I miss something, or misunderstand something?

Thanks

John

> Should the “PHYSICALDRIVE0” filename work here, or should it be “\.\c:”

I think yes, this can easily be the issue. I would not use PhysicalDrive%d for any read/writes except the raw partition tables.

Also consider using VSS snapshot for the task.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com