barrett
asked on
Sparse file help!
Trying to mark a file as sparse, but keep getting an "Incorrect function" error. Relevant code:
DWORD dwAccess = GENERIC_WRITE;
m_hFile = CreateFile(m_strFilename,
dwAccess,
0, // Exclusive access
NULL,
dwCreateFlag,
FILE_ATTRIBUTE_NORMAL,
NULL );
if( m_hFile == (HANDLE) INVALID_HANDLE_VALUE )
{
RETURN_FILE_ERROR(_T("Unab le to create Cache file"));
}
DWORD dwBytesReturned = 0;
QCHECK_RETURN( DeviceIoControl(
m_hFile, // handle to a file
FSCTL_SET_SPARSE, // dwIoControlCode operation
NULL, // lpInBuffer; must be NULL
0, // nInBufferSize; must be zero
NULL, // lpOutBuffer; must be NULL
0, // nOutBufferSize; must be zero
&dwBytesReturned, // number of bytes returned
NULL // OVERLAPPED structure
), E_FAIL );
I've tried a number of combinations of flags, to no avail.
The DeviceIoControl code is taken straight from the Platform SDK docs -- what could possibly be going wrong?
I'm on DevStudio sp5, Win2k sp1.
DWORD dwAccess = GENERIC_WRITE;
m_hFile = CreateFile(m_strFilename,
dwAccess,
0, // Exclusive access
NULL,
dwCreateFlag,
FILE_ATTRIBUTE_NORMAL,
NULL );
if( m_hFile == (HANDLE) INVALID_HANDLE_VALUE )
{
RETURN_FILE_ERROR(_T("Unab
}
DWORD dwBytesReturned = 0;
QCHECK_RETURN( DeviceIoControl(
m_hFile, // handle to a file
FSCTL_SET_SPARSE, // dwIoControlCode operation
NULL, // lpInBuffer; must be NULL
0, // nInBufferSize; must be zero
NULL, // lpOutBuffer; must be NULL
0, // nOutBufferSize; must be zero
&dwBytesReturned, // number of bytes returned
NULL // OVERLAPPED structure
), E_FAIL );
I've tried a number of combinations of flags, to no avail.
The DeviceIoControl code is taken straight from the Platform SDK docs -- what could possibly be going wrong?
I'm on DevStudio sp5, Win2k sp1.
ASKER
Yes, Win2k sp1 with NTFS. Can't find any documentation on the "incorrect function" error with sparse files.
Maybe for some unknown reason your NTFS doesn't support spare files. The only reason I can think of is because maybe the NTFS drive is marked as version 4 or maybe theres some system setting that inhibits use of sparse files - I don't know.
PS Does GetVolumeInformation() return the FILE_SUPPORTS_SPARSE_FILES flag?
PS Does GetVolumeInformation() return the FILE_SUPPORTS_SPARSE_FILES
ASKER
It appears the volume supports sparse files:
TCHAR tzRootDir[MAX_PATH] = _T( "D:\\" );
TCHAR tzVolumeName[MAX_PATH] = _T( "\0" );
TCHAR tzFileSystemNameBuffer[MAX _PATH] = _T( "\0" );
DWORD dwFileSystemFlags = 0;
DWORD dwMaximumComponentLength = 0;
BOOL bRetVal = GetVolumeInformation(
tzRootDir, // root directory
tzVolumeName, // volume name buffer
MAX_PATH, // length of name buffer
NULL, // volume serial number
&dwMaximumComponentLength, // maximum file name length
&dwFileSystemFlags, // file system options
tzFileSystemNameBuffer, // file system name buffer
MAX_PATH // length of file system name buffer
);
ATLASSERT( dwFileSystemFlags & 0x000700ff );
This assertion succeeds, and tzFileSystemNameBuffer holds "NTFS".
TCHAR tzRootDir[MAX_PATH] = _T( "D:\\" );
TCHAR tzVolumeName[MAX_PATH] = _T( "\0" );
TCHAR tzFileSystemNameBuffer[MAX
DWORD dwFileSystemFlags = 0;
DWORD dwMaximumComponentLength = 0;
BOOL bRetVal = GetVolumeInformation(
tzRootDir, // root directory
tzVolumeName, // volume name buffer
MAX_PATH, // length of name buffer
NULL, // volume serial number
&dwMaximumComponentLength,
&dwFileSystemFlags, // file system options
tzFileSystemNameBuffer, // file system name buffer
MAX_PATH // length of file system name buffer
);
ATLASSERT( dwFileSystemFlags & 0x000700ff );
This assertion succeeds, and tzFileSystemNameBuffer holds "NTFS".
ASKER
er, that assertion should read:
ATLASSERT( dwFileSystemFlags & FILE_SUPPORTS_SPARSE_FILES );
The value of dwFileSystemFlags is 0x000700ff.
ATLASSERT( dwFileSystemFlags & FILE_SUPPORTS_SPARSE_FILES
The value of dwFileSystemFlags is 0x000700ff.
ASKER
INterestingly, the code straight out of MSDN fails the same way:
HANDLE h = CreateFile("A huge file.txt",
GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, 0, NULL);
DWORD dw;
DeviceIoControl(h, FSCTL_SET_SPARSE, NULL,
0, NULL, 0, &dw, NULL);
LONG lDist = 8; // 32 GB!!!
SetFilePointer(h, 0, &lDist, FILE_BEGIN);
SetEndOfFile(h);
CloseHandle(h);
So something must be wrong with my configuration. Haven't a clue what it could be.
HANDLE h = CreateFile("A huge file.txt",
GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, 0, NULL);
DWORD dw;
DeviceIoControl(h, FSCTL_SET_SPARSE, NULL,
0, NULL, 0, &dw, NULL);
LONG lDist = 8; // 32 GB!!!
SetFilePointer(h, 0, &lDist, FILE_BEGIN);
SetEndOfFile(h);
CloseHandle(h);
So something must be wrong with my configuration. Haven't a clue what it could be.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
I do not know what is QCHECK_RETURN(..., E_FAIL )
But I'm pretty sure that E_FAIL is 0x80004005L, which is neither TRUE nor FALSE.
But I'm pretty sure that E_FAIL is 0x80004005L, which is neither TRUE nor FALSE.
ASKER
Unfortunately this code fails the same way on both of my machines, "Incorrect function". This really is Win2k sp1 with an NTFS volume. What could possibly be going wrong?
I shouldn't have included that QCHECK_RETURN macro -- it's part of our shop's error-handling framework. Doesn't affect this test.
I give up!
You just seem to have a "special" machine that just will not let you use sparse files despite the fact that it should let you.
You just seem to have a "special" machine that just will not let you use sparse files despite the fact that it should let you.
the same effect took me hours today.
A hint was "IOCTL: 0x980C4" from sysinternal's "File Monitor", where "fsutil sparse setflag" would just work.
I checked with winIOCTL.h (24APR98), which contains
#define FILE_DEVICE_FILE_SYSTEM 0x00000009
#define CTL_CODE(DeviceType, Function, Method, Access) \
((DeviceType)<<16) | ((Access)<<14) | ((Function)<<2) | (Method))
#define METHOD_BUFFERED 0
#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
#define FSCTL_SET_SPARSE CTL_CODE(FILE_DEVICE_FILE_ SYSTEM, 49, METHOD_BUFFERED, FILE_WRITE_DATA)
giving the value above. I guessed DeviceType and Function were above suspicion, so I fiddled with access and method:
a "control code" of 0x900c4 seems to work fine. This corresponds to "FILE_ANY_ACCESS", I found "FILE_ACCESS_SPECIAL" with cygwin. I spent hours trying to track down english and german versions of VS6 & service packs: the english VS contains the same definitions, no service pack I ran into any winIOCTL.h at all. google found the above digit sequence in proximity with FSCTL_SET_SPARSE and VB. Is this one of those non-existant cases where installing a current service pack does not take you to the same state as installing all of them sequentially?
A hint was "IOCTL: 0x980C4" from sysinternal's "File Monitor", where "fsutil sparse setflag" would just work.
I checked with winIOCTL.h (24APR98), which contains
#define FILE_DEVICE_FILE_SYSTEM 0x00000009
#define CTL_CODE(DeviceType, Function, Method, Access) \
((DeviceType)<<16) | ((Access)<<14) | ((Function)<<2) | (Method))
#define METHOD_BUFFERED 0
#define FILE_WRITE_ACCESS ( 0x0002 ) // file & pipe
#define FSCTL_SET_SPARSE CTL_CODE(FILE_DEVICE_FILE_
giving the value above. I guessed DeviceType and Function were above suspicion, so I fiddled with access and method:
a "control code" of 0x900c4 seems to work fine. This corresponds to "FILE_ANY_ACCESS", I found "FILE_ACCESS_SPECIAL" with cygwin. I spent hours trying to track down english and german versions of VS6 & service packs: the english VS contains the same definitions, no service pack I ran into any winIOCTL.h at all. google found the above digit sequence in proximity with FSCTL_SET_SPARSE and VB. Is this one of those non-existant cases where installing a current service pack does not take you to the same state as installing all of them sequentially?
It is running on 2000 with NTFS, yes?
Rob