(Das Binary benötigt MSVC Runtime 8.0.50727.762, ihr könnt's aber auch trivial selbstkompilieren da nicht plattformgebunden.)
Ein entsprechendes Tool zum Setzen von Valid- und Zero-Bereichen liefere ich noch nach. Generell geht das aber auch mit einem Komprimieren-Dekomprimieren-Zyklus.
#include <windows.h> #include <stdio.h> #include <tchar.h> #define maxErrorMsgSize 256 #define hasFlag & #define AND && __inline void PrintErrorMessageAndExit(wchar_t* msg) { wprintf_s( L"Error: %s\n", msg, maxErrorMsgSize ); exit(EXIT_FAILURE); } __inline void PrintFormattedErrorMessageAndExit() { wchar_t szMsg[maxErrorMsgSize]; // the size a guarantee by FormatMessage() if ( ::FormatMessage( FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_MAX_WIDTH_MASK | FORMAT_MESSAGE_FROM_SYSTEM, NULL, ::GetLastError(), 0, szMsg, sizeof(szMsg), NULL) ) PrintErrorMessageAndExit(szMsg); } int _tmain(const int argc, const _TCHAR* argv[]) { if (argc == 2) { HANDLE hFile; BY_HANDLE_FILE_INFORMATION fileInformation; wchar_t szPath[MAX_PATH], szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szFName[_MAX_FNAME], szExt[_MAX_EXT], szVolName[MAX_PATH], szFSName[MAX_PATH]; LPWSTR pszName; DWORD dwSN, dwMaxLen, dwVolFlags; if (! ::GetFullPathName( argv[1], MAX_PATH, szPath, &pszName) ) PrintFormattedErrorMessageAndExit(); _wsplitpath_s(szPath, szDrive, _MAX_DRIVE, szDir, _MAX_DIR, szFName, _MAX_FNAME, szExt, _MAX_EXT); size_t szDriveLen = wcsnlen_s(szDrive,_MAX_DRIVE); if ( (szDriveLen > 0) AND (szDriveLen < _MAX_DRIVE) ) wcscat_s(szDrive, _MAX_DRIVE+1, L"\\"); // see the check above! if (! ::GetVolumeInformation( szDrive, szVolName, MAX_PATH, &dwSN, &dwMaxLen, &dwVolFlags, szFSName, MAX_PATH) ) PrintFormattedErrorMessageAndExit(); if (! (dwVolFlags hasFlag FILE_SUPPORTS_SPARSE_FILES) ) PrintErrorMessageAndExit(L"This volume doesn't support sparse files."); hFile = ::CreateFile( argv[1], FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) PrintFormattedErrorMessageAndExit(); if (! ::GetFileInformationByHandle( hFile, &fileInformation) ) PrintFormattedErrorMessageAndExit(); if (fileInformation.dwFileAttributes hasFlag FILE_ATTRIBUTE_SPARSE_FILE) PrintErrorMessageAndExit(L"This file is sparse. Nothing to do."); DWORD dwTemp; if (! ::DeviceIoControl( hFile, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, &dwTemp, NULL) ) PrintFormattedErrorMessageAndExit(); ::CloseHandle(hFile); } else puts("Sets the sparse attribute on files\nUsage: SPARSE filename\n"); exit(EXIT_SUCCESS); }