More reliable way to DISMOUNT file system and synchronously invalidate the cache associated with it

Was using the follow CLI with Windows NT and early Windows XP/Me and it
appeared to
reliable dismount the file system and invalidate the file system cache.
It also appeared
to work with the initial version of Windows 2000. But lately, what we are
seeing is that
the file system data remains cached.

We are using faster hardware now than a year ago and that may have
uncovered an
inherit timing issue with this solution. But is there anything that could
be done beyond
what this is currently doing to ensure the the file system cache blocks are
invalidated.
The dirty blocks are being flushed but the cache entries appear to remain.

I have seen the knowledge base suggestion to use
DeleteVolumeMountPoint() and
wondered if this is any more reliable in invalidating the file system cache
blocks.
Sadly, the mountvol command distributed by microsoft is no more reliable
than NTdismount
below and I assume that it uses this DeleteVolumeMountPoint().

I have found no user level facility to synchronously invalidate the
cache blocks associated
with a dismounted file system. Am I missing something?

Any suggestions?

david linde

============================== NTdismount

//
// This is an example to illustrate how to unmount a
// NT file system
//

#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows
headers

// C RunTime Header Files
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <tchar.h>

// Local Header Files
#include <afxwin.h>

#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void display_usage()
{
printf(“usage:\n”);
printf(“NTdismount \n”);
exit(1);
}

void
NT_Remove_Device_Letter(char *pDeviceLetter)
{
char pNtDeviceName;
int nRetVal;
/

Remove the MS-DOS device name. First, get the name of the Windows
NT device from the symbolic link, then delete the symbolic link.
*/
pNtDeviceName = (char *)malloc ( MAX_PATH);
nRetVal = QueryDosDevice (pDeviceLetter, pNtDeviceName,
MAX_PATH);
if (nRetVal) {
nRetVal = DefineDosDevice (DDD_RAW_TARGET_PATH|
DDD_REMOVE_DEFINITION|
DDD_EXACT_MATCH_ON_REMOVE,
pDeviceLetter, pNtDeviceName);
}

if (!nRetVal)
printf(“NTdismount: error %lu: could not remove %s\n”, GetLastError(),
pDeviceLetter);

free (pNtDeviceName);

return;

}

//
//
//
int
NT_Device_Dismount(char pDeviceLetter, int nForceFlag)
{

HANDLE hFile;
UCHAR bRc;
DWORD dwError = 0;
int status;
ULONG bytesReturned;
char devicePath[256];

//
// Open the device
//
sprintf(devicePath, “\\.\%s”, pDeviceLetter);

hFile = CreateFile( devicePath,
GENERIC_READ | GENERIC_WRITE,
(FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE),
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_NO_BUFFERING,
NULL);

if ( hFile == INVALID_HANDLE_VALUE ){
if(nForceFlag == TRUE) {
//
// Go ahead and remove the Device letter
//
NT_Remove_Device_Letter(pDeviceLetter);
}
dwError = GetLastError();
SetLastError(dwError);
return ( -1 );
}

bRc = DeviceIoControl ( hFile,
FSCTL_LOCK_VOLUME,
NULL,
0,
NULL,
0,
&bytesReturned,
NULL
);

if ( bRc ) {

//
// Remove the Device letter
//
NT_Remove_Device_Letter(pDeviceLetter);

//
// syncronously flush file system cache before attempting dismount
// to ensure the dismount doesn’t need to schedule a flush.
//
(void) FlushFileBuffers(hFile);

//
// Performing Ioctl dismount the volume
//
bRc = DeviceIoControl ( hFile,
FSCTL_DISMOUNT_VOLUME,
NULL,
0,
NULL,
0,
&bytesReturned,
NULL
);

if ( !bRc ) {
dwError = GetLastError();
status = -1;
} else {
dwError = 0;
status = 0;
}

bRc = DeviceIoControl ( hFile,
FSCTL_UNLOCK_VOLUME,
NULL,
0,
NULL,
0,
&bytesReturned,
NULL
);

if ( !bRc ) {
dwError = GetLastError();
status = -1;
}

} else {
if(nForceFlag == TRUE) {
//
// Go ahead and remove the Device letter
//
NT_Remove_Device_Letter(pDeviceLetter);
}
dwError = GetLastError();
status = -1;
}

CloseHandle ( hFile );

SetLastError(dwError);

return ( status );

}

void __cdecl main(int argc, char
argv)
{
int retval;
char * deviceName, * farg;
DWORD dwError;

if ( argc == 2 ) {
deviceName = argv[1];
retval = NT_Device_Dismount(deviceName, FALSE);
if(retval == -1) {
dwError = GetLastError();
printf(“NTdismount: could not dismount volume %s errorcode 0x%x\n”,
deviceName, dwError);
exit(1);
}
} else {
display_usage();
}
exit ( retval );
}</string.h></stdlib.h></stdio.h></winioctl.h></windows.h></afxwin.h></tchar.h></memory.h></malloc.h></stdlib.h>