示例#1
0
//----------------------------------------------------------------------
//
// WMain
//
// Engine. Just get command line switches and fire off a format. This
// could also be done in a GUI like Explorer does when you select a
// drive and run a check on it.
//
// We do this in UNICODE because the chkdsk command expects PWCHAR
// arguments.
//
//----------------------------------------------------------------------
int
_tmain(int argc, TCHAR *argv[])
{
	int badArg;
	DWORD media = FMIFS_HARDDISK;
	DWORD driveType;
	TCHAR fileSystem[1024];
	TCHAR volumeName[1024];
	TCHAR input[1024];
	DWORD serialNumber;
	DWORD flags, maxComponent;
	ULARGE_INTEGER freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes;
#ifndef UNICODE
	WCHAR RootDirectoryW[MAX_PATH], FormatW[MAX_PATH], LabelW[MAX_PATH];
#endif
	TCHAR szMsg[RC_STRING_MAX_SIZE];

	//
	// Get function pointers
	//
	if( !LoadFMIFSEntryPoints()) {
		LoadStringAndOem( GetModuleHandle(NULL), STRING_FMIFS_FAIL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		_tprintf("%s", szMsg);
		return -1;
	}

	//
	// Parse command line
	//
	if( (badArg = ParseCommandLine( argc, argv ))) {

		LoadStringAndOem( GetModuleHandle(NULL), STRING_UNKNOW_ARG, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		_tprintf(szMsg, argv[badArg] );

		Usage(argv[0]);
		return -1;
	}

	//
	// Get the drive's format
	//
	if( !Drive ) {

		LoadStringAndOem( GetModuleHandle(NULL), STRING_DRIVE_PARM, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		_tprintf(szMsg);
		Usage( argv[0] );
		return -1;

	} else {

		_tcscpy( RootDirectory, Drive );
	}
	RootDirectory[2] = _T('\\');
	RootDirectory[3] = _T('\0');

	//
	// See if the drive is removable or not
	//
	driveType = GetDriveType( RootDirectory );

	if( driveType == 0 ) {
		LoadStringAndOem( GetModuleHandle(NULL), STRING_ERROR_DRIVE_TYPE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		PrintWin32Error( szMsg, GetLastError());
		return -1;
	}
	else if ( driveType == 1 )
	{
		LoadString( GetModuleHandle(NULL), STRING_NO_VOLUME, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		PrintWin32Error( szMsg, GetLastError());
		return -1;
	}

	if( driveType != DRIVE_FIXED ) {
		LoadStringAndOem( GetModuleHandle(NULL), STRING_INSERT_DISK, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		_tprintf(szMsg, RootDirectory[0] );
		_fgetts( input, sizeof(input)/2, stdin );

		media = FMIFS_FLOPPY;
	}

	//
	// Determine the drive's file system format
	//
	if( !GetVolumeInformation( RootDirectory,
						volumeName, sizeof(volumeName)/2,
						&serialNumber, &maxComponent, &flags,
						fileSystem, sizeof(fileSystem)/2)) {

		LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_VOLUME, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		PrintWin32Error( szMsg, GetLastError());
		return -1;
	}

	if( !GetDiskFreeSpaceEx( RootDirectory,
			&freeBytesAvailableToCaller,
			&totalNumberOfBytes,
			&totalNumberOfFreeBytes )) {

		LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_VOLUME_SIZE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		PrintWin32Error( szMsg, GetLastError());
		return -1;
	}
	LoadStringAndOem( GetModuleHandle(NULL), STRING_FILESYSTEM, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
	_tprintf(szMsg, fileSystem );

	//
	// Make sure they want to do this
	//
	if( driveType == DRIVE_FIXED ) {

		if( volumeName[0] ) {

			while(1 ) {

				LoadStringAndOem( GetModuleHandle(NULL), STRING_LABEL_NAME_EDIT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
				_tprintf(szMsg, RootDirectory[0] );
				_fgetts( input, sizeof(input)/2, stdin );
				input[ _tcslen( input ) - 1] = 0;

				if( !_tcsicmp( input, volumeName )) {

					break;
				}
				LoadStringAndOem( GetModuleHandle(NULL), STRING_ERROR_LABEL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
				_tprintf("%s", szMsg);
			}
		}

		LoadStringAndOem( GetModuleHandle(NULL), STRING_YN_FORMAT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		_tprintf(szMsg, RootDirectory[0] );

		LoadStringAndOem( GetModuleHandle(NULL), STRING_YES_NO_FAQ, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);

		while( 1 ) {
			_fgetts( input, sizeof(input)/2, stdin );
			if(_strnicmp(&input[0],&szMsg[0],1) == 0) break;
			if(_strnicmp(&input[0],&szMsg[1],1) == 0) {
				_tprintf(_T("\n"));
				return 0;
			}
		}
		media = FMIFS_HARDDISK;
	}

	//
	// Tell the user we're doing a long format if appropriate
	//
	if( !QuickFormat ) {

		LoadString( GetModuleHandle(NULL), STRING_VERIFYING, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);

		if( totalNumberOfBytes.QuadPart > 1024*1024*10 ) {

			_tprintf(_T("%s %luM\n"),szMsg, (DWORD) (totalNumberOfBytes.QuadPart/(1024*1024)));

		} else {

			_tprintf(_T("%s %.1fM\n"),szMsg,
				((float)(LONGLONG)totalNumberOfBytes.QuadPart)/(float)(1024.0*1024.0));
		}
	} else {

		LoadStringAndOem( GetModuleHandle(NULL), STRING_FAST_FMT, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		if( totalNumberOfBytes.QuadPart > 1024*1024*10 ) {

			_tprintf(_T("%s %luM\n"),szMsg, (DWORD) (totalNumberOfBytes.QuadPart/(1024*1024)));

		} else {

			_tprintf(_T("%s %.2fM\n"),szMsg,
				((float)(LONGLONG)totalNumberOfBytes.QuadPart)/(float)(1024.0*1024.0));
		}
		LoadStringAndOem( GetModuleHandle(NULL), STRING_CREATE_FSYS, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		_tprintf("%s", szMsg);
	}

	//
	// Format away!
	//
#ifndef UNICODE
	MultiByteToWideChar(CP_ACP, 0, RootDirectory, -1, RootDirectoryW, MAX_PATH);
	MultiByteToWideChar(CP_ACP, 0, Format, -1, FormatW, MAX_PATH);
	MultiByteToWideChar(CP_ACP, 0, Label, -1, LabelW, MAX_PATH);
	FormatEx( RootDirectoryW, media, FormatW, LabelW, QuickFormat,
			ClusterSize, FormatExCallback );
#else
	FormatEx( RootDirectory, media, Format, Label, QuickFormat,
			ClusterSize, FormatExCallback );
#endif
	if( Error ) return -1;
	LoadStringAndOem( GetModuleHandle(NULL), STRING_FMT_COMPLETE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
	_tprintf("%s", szMsg);

	//
	// Enable compression if desired
	//
	if( CompressDrive ) {

#ifndef UNICODE
		MultiByteToWideChar(CP_ACP, 0, RootDirectory, -1, RootDirectoryW, MAX_PATH);
		if( !EnableVolumeCompression( RootDirectoryW, TRUE )) {
#else
		if( !EnableVolumeCompression( RootDirectory, TRUE )) {
#endif

			LoadStringAndOem( GetModuleHandle(NULL), STRING_VOL_COMPRESS, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
			_tprintf("%s", szMsg);
		}
	}

	//
	// Get the label if we don't have it
	//
	if( !GotALabel ) {

		LoadString( GetModuleHandle(NULL), STRING_ENTER_LABEL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		_tprintf("%s", szMsg);
		_fgetts( input, sizeof(LabelString)/2, stdin );

		input[ _tcslen(input)-1] = 0;
		if( !SetVolumeLabel( RootDirectory, input )) {

			LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_LABEL, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
			PrintWin32Error(szMsg, GetLastError());
			return -1;
		}
	}

	if( !GetVolumeInformation( RootDirectory,
						volumeName, sizeof(volumeName)/2,
						&serialNumber, &maxComponent, &flags,
						fileSystem, sizeof(fileSystem)/2)) {

		LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_VOLUME, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		PrintWin32Error( szMsg, GetLastError());
		return -1;
	}

	//
	// Print out some stuff including the formatted size
	//
	if( !GetDiskFreeSpaceEx( RootDirectory,
			&freeBytesAvailableToCaller,
			&totalNumberOfBytes,
			&totalNumberOfFreeBytes )) {

		LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_VOLUME_SIZE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		PrintWin32Error(szMsg, GetLastError());
		return -1;
	}

	LoadStringAndOem( GetModuleHandle(NULL), STRING_FREE_SPACE, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
	_tprintf(szMsg, totalNumberOfBytes.QuadPart, totalNumberOfFreeBytes.QuadPart );

	//
	// Get the drive's serial number
	//
	if( !GetVolumeInformation( RootDirectory,
						volumeName, sizeof(volumeName)/2,
						&serialNumber, &maxComponent, &flags,
						fileSystem, sizeof(fileSystem)/2)) {

		LoadStringAndOem( GetModuleHandle(NULL), STRING_NO_VOLUME, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
		PrintWin32Error( szMsg, GetLastError());
		return -1;
	}
	LoadStringAndOem( GetModuleHandle(NULL), STRING_SERIAL_NUMBER, (LPTSTR) szMsg,RC_STRING_MAX_SIZE);
	_tprintf(szMsg, (unsigned int)(serialNumber >> 16),
					(unsigned int)(serialNumber & 0xFFFF) );

	return 0;
}
示例#2
0
文件: Sdel.c 项目: caidongyun/libs
//--------------------------------------------------------------------
//
// ProcessDirectory
// 
// Recursive routine that passes files to the delete function.
//
//--------------------------------------------------------------------
void ProcessDirectory( TCHAR *PathName, TCHAR *SearchPattern )
{
	TCHAR			subName[MAX_PATH], fileSearchName[MAX_PATH], searchName[MAX_PATH];
	HANDLE			dirHandle, patternHandle;
	static BOOLEAN	firstCall = TRUE;
	static BOOLEAN  deleteDirectories = FALSE;
	WIN32_FIND_DATA foundFile;

	//
	// Scan the files and/or directories if this is a directory
	//
	if( firstCall ) {

		if( _tcsrchr( PathName, '*' ) ) {
	
            if( _tcsrchr( PathName, '\\' ) ) {

                _stprintf( SearchPattern, _tcsrchr( PathName, '\\' )+1 );
                _tcscpy( searchName, PathName );
                _tcscpy( _tcsrchr( searchName, '\\')+1, _T("*.*") );
				if( !_tcscmp( SearchPattern, _T("*.*")) ||
					!_tcscmp( SearchPattern, _T("*"))) {

					deleteDirectories = TRUE;
				}

            } else {
                
                _stprintf( SearchPattern, PathName );
                _tcscpy( searchName, PathName );
            }
            _stprintf( fileSearchName, _T("%s"), PathName );

		} else {

			_stprintf( SearchPattern, _T("*.*") );
			_stprintf( searchName, _T("%s"), PathName );
            _stprintf( fileSearchName, _T("%s"), PathName );
			deleteDirectories = TRUE;
		}

	} else {

		_stprintf( searchName, _T("%s\\*.*"), PathName );
		_stprintf( fileSearchName, _T("%s\\%s"), PathName, SearchPattern );
	}

	//
	// Process all the files, according to the search pattern
	//
	if( (patternHandle = FindFirstFile( fileSearchName, &foundFile )) != 
		INVALID_HANDLE_VALUE  ) {

		do {

			if( _tcscmp( foundFile.cFileName, _T(".") ) &&
				_tcscmp( foundFile.cFileName, _T("..") )) {

				_tcscpy( subName, searchName );
				if( _tcsrchr( subName, '\\' ) ) 
					_tcscpy( _tcsrchr( subName, '\\')+1, foundFile.cFileName );
				else
					_tcscpy( subName, foundFile.cFileName );

				//
				// Do this file/directory
				//
				ProcessFile( &foundFile, subName );
			}
		} while( FindNextFile( patternHandle, &foundFile ));
		FindClose( patternHandle );
	}

	//
	// Now recurse if we're supposed to
	//
	if( Recurse ) {

        if( firstCall && !_tcsrchr( searchName, L'\\') ) {

            if( _tcsrchr( searchName, L'*' )) {

                if( (dirHandle = FindFirstFile( _T("*.*"), &foundFile )) == 
                    INVALID_HANDLE_VALUE  ) {

                    //
                    // Nothing to process
                    //
                    return;
                }
            } else {

                if( (dirHandle = FindFirstFile( searchName, &foundFile )) == 
                    INVALID_HANDLE_VALUE  ) {

                    //
                    // Nothing to process
                    //
                    return;
                }
            }
        } else {

            if( (dirHandle = FindFirstFile( searchName, &foundFile )) == 
                INVALID_HANDLE_VALUE  ) {

                //
                // Nothing to process
                //
                return;
            }
        }
        firstCall = FALSE;

		do {

			if( (foundFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
				_tcscmp( foundFile.cFileName, _T(".") ) &&
				_tcscmp( foundFile.cFileName, _T("..") )) {

				_tcscpy( subName, searchName );
				if( _tcsrchr( subName, '\\' ) ) 
					_tcscpy( _tcsrchr( subName, '\\')+1, foundFile.cFileName );
				else
					_tcscpy( subName, foundFile.cFileName );

				//
				// Go into this directory
				//
				ProcessDirectory( subName, SearchPattern );

				//
				// Delete the directory if we're supposed to
				//
				if( deleteDirectories ) {

					if( !RemoveDirectory( subName )) {

						_tprintf( _T("\nError deleting %s: "), subName );
						PrintWin32Error( GetLastError() );
					}
				}
			}

		} while( FindNextFile( dirHandle, &foundFile ));
		FindClose( dirHandle );
	}
}
示例#3
0
文件: Sdel.c 项目: caidongyun/libs
//--------------------------------------------------------------------
//
// CleanFreeSpace
//
// This function overwrites all free-space data areas on a disk, 
// including free space in the MFT. Note that it does not overwrite 
// freespace filename information.
//
//--------------------------------------------------------------------
BOOLEAN CleanFreeSpace( PTCHAR DrivePath )
{
	TCHAR		tempFileName[MAX_PATH];
	ULARGE_INTEGER bytesAvail, totalBytes, freeBytes;
	DWORD		sectorsPerCluster, bytesPerSector, totalClusters, freeClusters;
	ULONGLONG	prevSize, tempSize = 0, cleanSize;
	TCHAR		progress[] = _T("|/-\\|/-\\");
	HANDLE		hTempFile;
	BOOLEAN		createdFile;
	DWORD		percent, mftFilesCreated;
	DWORD		prevPercent = 0;
	USHORT Compression = COMPRESSION_FORMAT_NONE;
	DWORD BytesReturned;	

	if( DrivePath[1] != ':' ) {

		_tprintf( _T("Cannot clean free space for UNC drive\n\n"));
		return FALSE;
	}

	//
	// Drive letter - move to one past slash
	//
	DrivePath[3] = 0;

	if( CleanCompressedFiles ) {

		_tprintf(_T("Cleaning free space to securely delete compressed files: 0%%"));
	} else {

		_tprintf(_T("Cleaning free space on %s: 0%%"), DrivePath );
	}
	fflush( stdout );

	if( !GetDiskFreeSpace( DrivePath, &sectorsPerCluster, &bytesPerSector,
		&freeClusters, &totalClusters )) {

		_tprintf( _T("Could not determine disk cluster size: "));
		PrintWin32Error( GetLastError());
		return FALSE;
	}

#if UNICODE
	if( !(pGetDiskFreeSpaceEx = (PVOID) GetProcAddress( GetModuleHandle( _T("kernel32.dll") ),
											"GetDiskFreeSpaceExW" ))) {
#else
	if( !(pGetDiskFreeSpaceEx = (PVOID) GetProcAddress( GetModuleHandle( _T("kernel32.dll") ),
											"GetDiskFreeSpaceExA" ))) {
#endif

		bytesAvail.QuadPart = sectorsPerCluster * freeClusters * bytesPerSector;
        freeBytes.QuadPart = bytesAvail.QuadPart;

	} else {
	
		if( !pGetDiskFreeSpaceEx( DrivePath, &bytesAvail, &totalBytes, &freeBytes )) {

			_tprintf( _T("Could not determine amount of free space: "));
			PrintWin32Error( GetLastError());
			return FALSE;
		}
	}

	//
	// If the user doesn't have access to all the free space, we can't perform a full clean
	//
	if( bytesAvail.QuadPart != freeBytes.QuadPart ) {

		_tprintf(_T("Your disk quota prevents you from cleaning free space on this drive.\n\n"));
		return FALSE;
	}

	_stprintf( tempFileName, _T("%sSDELTEMP"), DrivePath );
	hTempFile = CreateFile( tempFileName, GENERIC_WRITE|GENERIC_READ, 
					0, NULL, CREATE_ALWAYS, 
					FILE_FLAG_NO_BUFFERING|FILE_FLAG_SEQUENTIAL_SCAN|
					FILE_FLAG_DELETE_ON_CLOSE|FILE_ATTRIBUTE_HIDDEN, NULL );

	if( hTempFile == INVALID_HANDLE_VALUE ) {

		_tprintf( _T("Could not create free-space cleanup file: "));
		PrintWin32Error( GetLastError());
		CloseHandle( hTempFile );
		return FALSE;
	}

	//
	// Turn off compression for the file - ignore errors since this might
	// be a FAT volume
	//
	DeviceIoControl( hTempFile, FSCTL_SET_COMPRESSION, &Compression,
			sizeof(Compression), NULL, 0, &BytesReturned, NULL);

	//
	// Allcate a buffer that is a cluster in size
	//
	cleanSize = (ULONGLONG) sectorsPerCluster * (ULONGLONG) bytesPerSector * 128;

	//
	// Grow the file by cluster size chunks until we fail
	//
	while( cleanSize > bytesPerSector * sectorsPerCluster ) {

		if( SecureOverwrite( hTempFile, cleanSize )) {

			tempSize += cleanSize;

			percent = (DWORD) ((tempSize * 100)/ freeBytes.QuadPart );

			if( percent != prevPercent ) {
				if( CleanCompressedFiles ) {

					_tprintf(_T("\rCleaning free space to securely delete compressed files: %d%%"),
						percent );
				} else {

					_tprintf(_T("\rCleaning free space on %s: %d%%"), DrivePath, percent );
				}
				prevPercent = percent;
			}
		} else {

			cleanSize -= bytesPerSector * sectorsPerCluster;
		}
	}

	//
	// There's less than a full cluster (outside the MFT if this is NTFS) free. 
	// Let's allocate another file to take care of it.
	//
	_stprintf( tempFileName, _T("%sSDELTEMP1"), DrivePath );
	hTempFile = CreateFile( tempFileName, GENERIC_WRITE, 
					0, NULL, CREATE_NEW, 
					FILE_FLAG_SEQUENTIAL_SCAN|FILE_FLAG_DELETE_ON_CLOSE|
					FILE_ATTRIBUTE_HIDDEN|FILE_FLAG_WRITE_THROUGH, NULL );

	if( hTempFile != INVALID_HANDLE_VALUE ) {

		while( cleanSize ) {

			if( !SecureOverwrite( hTempFile, cleanSize )) {

				cleanSize--;
			}
		}
	}

	//
	// If we're just zapping free space, and this is NTFS, we have to take care of
	// deleted files within the MFT. We do this by creating as many of the largest sized
	// files we can (if there is space in the MFT, we'll be able to create non-zero sized
	// files, where the data is resident in the MFT record).
	//
	if( ZapFreeSpace ) {

		mftFilesCreated = 0;
		prevSize = 4096; // max MFT record size
		while( 1 ) {

			_stprintf( tempFileName, _T("%sSDELMFT%06d"), DrivePath, mftFilesCreated++ );
			hTempFile = CreateFile( tempFileName, GENERIC_WRITE, 
							0, NULL, CREATE_NEW, 
							FILE_FLAG_SEQUENTIAL_SCAN|FILE_FLAG_DELETE_ON_CLOSE|
							FILE_ATTRIBUTE_HIDDEN, NULL );
			if( hTempFile == INVALID_HANDLE_VALUE ) {

				break;
			}

			//
			// Mft record can be up to 4K in size
			//
			cleanSize = prevSize;
			createdFile = FALSE;
			while( cleanSize ) {

				if( !SecureOverwrite( hTempFile, cleanSize )) {

					cleanSize--;

				} else {

					prevSize = cleanSize;
					createdFile = TRUE;
				}
			}	
			
			//
			// If the only file we could create is length 0, then this is FAT
			//
			if( !createdFile ) break;

			if( mftFilesCreated == 1 ) {
				_tprintf( _T("\r                                                           "));
				
			} 

			_tprintf( _T("\rCleaning MFT...%c"),
				progress[ mftFilesCreated % 8 ]);

			// Don't close the file, since we want it to keep the space until we're
			// done.
		}
	}

	//
	// Done. No need to close our handles, since they are all delete-on-close.
	//
	_tprintf(_T("\rFree space cleaned on %s                                       \n"),
		DrivePath );
	return TRUE;
}


//--------------------------------------------------------------------
//
// LocateNativeEntryPoints
//
//--------------------------------------------------------------------
VOID LocateNativeEntryPoints()
{
	//
	// If we're on Win9x, just return
	//
	if( GetVersion() >= 0x80000000) return;

    //
    // Load the NTDLL entry point we need
    //
	if( !(NtFsControlFile = (void *) GetProcAddress( GetModuleHandle(_T("ntdll.dll")),
			"NtFsControlFile" )) ) {

		_tprintf(_T("\nCould not find NtFsControlFile entry point in NTDLL.DLL\n"));
		exit(1);
	}
	if( !(RtlNtStatusToDosError = (void *) GetProcAddress( GetModuleHandle(_T("ntdll.dll")),
							"RtlNtStatusToDosError" )) ) {

		_tprintf(_T("\nCould not find RtlNtStatusToDosError entry point in NTDLL.DLL\n"));
		exit(1);
	}
}


//--------------------------------------------------------------------
//
// Usage
//
// Tell user how to use the program.
//
//--------------------------------------------------------------------
int Usage( TCHAR *ProgramName ) 
{
    _tprintf(_T("usage: %s [-p passes] [-s] [-q] <file or directory>\n"), ProgramName );
	_tprintf(_T("       %s [-p passes] [-z|-c] [drive letter]\n"), ProgramName );
	_tprintf(_T("   -c         Zero free space (good for virtual disk optimization)\n"));
	_tprintf(_T("   -p passes  Specifies number of overwrite passes (default is 1)\n"));
    _tprintf(_T("   -q         Don't print errors (Quiet)\n"));
    _tprintf(_T("   -s         Recurse subdirectories\n"));
	_tprintf(_T("   -z         Clean free space\n\n"));
    return -1;
}
示例#4
0
文件: Sdel.c 项目: caidongyun/libs
//--------------------------------------------------------------------
//
// SecureDeleteCompressed
//
// More complicated than a regular file - we actually try to use
// direct disk access to overwrite the clusters that are used by a 
// compressed file. The function returns FALSE if the file is
// not really compressed (it is stored as resident data in the MFT).
//
//--------------------------------------------------------------------
BOOLEAN SecureDeleteCompressed( PTCHAR FileName ) 
{
	HANDLE			hFile;
	BOOLEAN			reallyCompressed = FALSE;
	BOOLEAN			zappedFile = FALSE;
	TCHAR			lastFileName[MAX_PATH];
	static TCHAR	volumeName[] = _T("\\\\.\\A:");
	static TCHAR	volumeRoot[] = _T("A:\\");
	static HANDLE	hVolume = INVALID_HANDLE_VALUE;
	static DWORD	clusterSize;
	DWORD			sectorsPerCluster, bytesPerSector, freeClusters, totalClusters;

	//
	// If we haven't opened the volume, attempt it now
	//
	if( hVolume == INVALID_HANDLE_VALUE ) {

		volumeName[4] = FileName[0];
		hVolume = CreateFile( volumeName, GENERIC_READ|GENERIC_WRITE,
							FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
							0, 0 );

		volumeRoot[0] = FileName[0];
		GetDiskFreeSpace( volumeRoot, &sectorsPerCluster, &bytesPerSector,
						&freeClusters, &totalClusters );

		clusterSize = bytesPerSector * sectorsPerCluster;
	}

	//
	// Open the file exclusively
	//
	hFile = CreateFile( FileName, GENERIC_READ, 
						0,NULL, OPEN_EXISTING, 0, NULL );
	if( hFile == INVALID_HANDLE_VALUE ) {

		_tprintf( _T("\nError opening %s for compressed file scan: "), FileName );
		PrintWin32Error( GetLastError());
		return TRUE;
	}
	
	//
	// Scan the location of the file
	//
	if( !ScanFile( hVolume, clusterSize, hFile, 
			&reallyCompressed, &zappedFile )) {

		CloseHandle( hFile );
		return TRUE;
	}

	// 
	// Done with the file handle
	//
	CloseHandle( hFile );

	//
	// If the file is really compressed (it is non-resident),
	// we can delete it now.
	//
	if( reallyCompressed ) {

		//
		// Rename the file a few times
		//
		OverwriteFileName( FileName, lastFileName );

		if( !DeleteFile( lastFileName )) {

			//
			// Rename back to the original name on error so as
			// not to confuse the user
			//
			_tprintf( _T("\nError deleting %s: "), FileName );
			PrintWin32Error( GetLastError() );
			if( !MoveFile( lastFileName, FileName )) {

				_tprintf( _T("\nError renaming file back to original name. File is left as %s\n"),
					lastFileName );
			}
			return TRUE;
		}

		//
		// If we couldn't directly overwrite the file's clusters, we'll
		// have to clean free space to overwrite them indirectly
		//
		if( !zappedFile ) CleanCompressedFiles = TRUE;

		if( !Silent ) _tprintf( _T("deleted.\n"));
	}

	//
	// Return TRUE if the file had clusters outside the MFT
	//
	return reallyCompressed;
}
示例#5
0
文件: Sdel.c 项目: caidongyun/libs
//--------------------------------------------------------------------
//
// SecureDelete
//
// Performs a secure delete on the specified file.
//
//--------------------------------------------------------------------
VOID SecureDelete( PTCHAR FileName, DWORD FileLengthHi,
					DWORD FileLengthLo ) 
{
	HANDLE	hFile;
	ULONGLONG bytesToWrite, bytesWritten;
	ULARGE_INTEGER fileLength;
	TCHAR   lastFileName[MAX_PATH];

	//
	// First, open the file in overwrite mode
	//
	hFile = CreateFile( FileName, GENERIC_WRITE, 
						FILE_SHARE_READ|FILE_SHARE_WRITE,
						NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL );
	if( hFile == INVALID_HANDLE_VALUE ) {

		_tprintf( _T("\nError opening %s for delete: "), FileName );
		PrintWin32Error( GetLastError());
		return;
	}

	//
	// If the file has a non-zero length, fill it with 0's first in order
	// to preserve is cluster allocation.
	//
	if( FileLengthLo || FileLengthHi ) {

		//
		// Seek to the last byte of the file
		//
		FileLengthLo--;
		if( FileLengthLo == (DWORD) -1 && FileLengthHi ) FileLengthHi--;
		SetFilePointer( hFile, FileLengthLo, &FileLengthHi, FILE_BEGIN );

		//
		// Write one zero byte, which causes the file system to fill the entire
		// file's on-disk contents with 0.
		//
		if( !SecureOverwrite( hFile, 1 )) {

			_tprintf( _T("\nError overwriting %s: "), FileName );
			PrintWin32Error( GetLastError() );
			CloseHandle( hFile );
			return;
		}

		//
		// Now go back to the start of the file and overwrite the rest of the
		// file.
		//
		SetFilePointer( hFile, 0, NULL, FILE_BEGIN );
		fileLength.LowPart = FileLengthLo;
		fileLength.HighPart = FileLengthHi;
		bytesWritten = 0;
		while( bytesWritten < fileLength.QuadPart ) {

			bytesToWrite = min( fileLength.QuadPart - bytesWritten, 65536 );
			if( !SecureOverwrite( hFile, (DWORD) bytesToWrite )) {

				_tprintf( _T("\nError overwriting %s: "), FileName );
				PrintWin32Error( GetLastError() );
				CloseHandle( hFile );
				return;
			}
			bytesWritten += bytesToWrite;
		}
	}

	//
	// Done!
	//
	CloseHandle( hFile );
	
	//
	// Rename the file a few times
	//
	OverwriteFileName( FileName, lastFileName );

	//
	// Now we can delete the file
	//
	if( !DeleteFile( lastFileName ) ) {

		_tprintf( _T("\nError deleting %s: "), FileName );
		PrintWin32Error( GetLastError() );

		//
		// Rename back to original name so as not to confuse the user
		//
		if( !MoveFile( lastFileName, FileName )) {

			_tprintf( _T("\nError renaming file back to original name. File is left as %s\n"),
				lastFileName );
		}
		return;
	}

	if( !Silent ) _tprintf( _T("deleted.\n"));
}
示例#6
0
文件: FORMAT.C 项目: caidongyun/libs
//----------------------------------------------------------------------
// 
// WMain
//
// Engine. Just get command line switches and fire off a format. This 
// could also be done in a GUI like Explorer does when you select a 
// drive and run a check on it.
//
// We do this in UNICODE because the chkdsk command expects PWCHAR
// arguments.
//
//----------------------------------------------------------------------
int wmain( int argc, WCHAR *argv[] )
{
	int badArg;
	DWORD media;
	DWORD driveType;
	WCHAR fileSystem[1024];
	WCHAR volumeName[1024];
	WCHAR input[1024];
	DWORD serialNumber;
	DWORD flags, maxComponent;
	ULARGE_INTEGER freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes;

	_tprintf(L"\nFormatx v1.0 by Mark Russinovich\n");
	_tprintf(L"Systems Internals - http://www.sysinternals.com\n\n");

	//
	// Get function pointers
	//
	if( !LoadFMIFSEntryPoints()) {

		_tprintf(L"Could not located FMIFS entry points.\n\n");
		return -1;
	}

	//
	// Parse command line
	//
	if( (badArg = ParseCommandLine( argc, argv ))) {

		_tprintf(L"Unknown argument: %s\n", argv[badArg] );

		Usage(argv[0]);
		return -1;
	}

	// 
	// Get the drive's format
	//
	if( !Drive ) {

		_tprintf(L"Required drive parameter is missing.\n\n");
		Usage( argv[0] );
		return -1;

	} else {

		wcscpy( RootDirectory, Drive );
	}
	RootDirectory[2] = L'\\';
	RootDirectory[3] = (WCHAR) 0;

	//
	// See if the drive is removable or not
	//
	driveType = GetDriveTypeW( RootDirectory );

	if( driveType != DRIVE_FIXED ) {

		_tprintf(L"Insert a new floppy in drive %C:\nand press Enter when ready...",
			RootDirectory[0] );
		fgetws( input, sizeof(input)/2, stdin );

		media = FMIFS_FLOPPY;
	}

	//
	// Determine the drive's file system format
	//
	if( !GetVolumeInformationW( RootDirectory, 
						volumeName, sizeof(volumeName)/2, 
						&serialNumber, &maxComponent, &flags, 
						fileSystem, sizeof(fileSystem)/2)) {

		PrintWin32Error( L"Could not query volume", GetLastError());
		return -1;
	}

	if( !GetDiskFreeSpaceExW( RootDirectory, 
			&freeBytesAvailableToCaller,
			&totalNumberOfBytes,
			&totalNumberOfFreeBytes )) {

		PrintWin32Error( L"Could not query volume size", GetLastError());
		return -1;
	}
	_tprintf(L"The type of the file system is %s.\n", fileSystem );

	//
	// Make sure they want to do this
	//
	if( driveType == DRIVE_FIXED ) {

		if( volumeName[0] ) {

			while(1 ) {

				_tprintf(L"Enter current volume label for drive %C: ", RootDirectory[0] );
				fgetws( input, sizeof(input)/2, stdin );
				input[ wcslen( input ) - 1] = 0;
				
				if( !wcsicmp( input, volumeName )) {

					break;
				}
				_tprintf(L"An incorrect volume label was entered for this drive.\n");
			}
		}

		while( 1 ) {

			_tprintf(L"\nWARNING, ALL DATA ON NON_REMOVABLE DISK\n");
			_tprintf(L"DRIVE %C: WILL BE LOST!\n", RootDirectory[0] );
			_tprintf(L"Proceed with Format (Y/N)? " );
			fgetws( input, sizeof(input)/2, stdin );
		
			if( input[0] == L'Y' || input[0] == L'y' ) break;

			if(	input[0] == L'N' || input[0] == L'n' ) {
				
				_tprintf(L"\n");
				return 0;
			}
		}
		media = FMIFS_HARDDISK;
	} 

	//
	// Tell the user we're doing a long format if appropriate
	//
	if( !QuickFormat ) {
		
		if( totalNumberOfBytes.QuadPart > 1024*1024*10 ) {
			
			_tprintf(L"Verifying %dM\n", (DWORD) (totalNumberOfBytes.QuadPart/(1024*1024)));
			
		} else {

			_tprintf(L"Verifying %.1fM\n", 
				((float)(LONGLONG)totalNumberOfBytes.QuadPart)/(float)(1024.0*1024.0));
		}
	} else  {

		if( totalNumberOfBytes.QuadPart > 1024*1024*10 ) {
			
			_tprintf(L"QuickFormatting %dM\n", (DWORD) (totalNumberOfBytes.QuadPart/(1024*1024)));
			
		} else {

			_tprintf(L"QuickFormatting %.2fM\n", 
				((float)(LONGLONG)totalNumberOfBytes.QuadPart)/(float)(1024.0*1024.0));
		}
		_tprintf(L"Creating file system structures.\n");
	}

	//
	// Format away!
	//			
	FormatEx( RootDirectory, media, Format, Label, QuickFormat,
			ClusterSize, FormatExCallback );
	if( Error ) return -1;
	_tprintf(L"Format complete.\n");

	//
	// Enable compression if desired
	//
	if( CompressDrive ) {

		if( !EnableVolumeCompression( RootDirectory, TRUE )) {

			_tprintf(L"Volume does not support compression.\n");
		}
	}

	//
	// Get the label if we don't have it
	//
	if( !GotALabel ) {

		_tprintf(L"Volume Label (11 characters, Enter for none)? " );
		fgetws( input, sizeof(LabelString)/2, stdin );

		input[ wcslen(input)-1] = 0;
		if( !SetVolumeLabelW( RootDirectory, input )) {

			PrintWin32Error(L"Could not label volume", GetLastError());
			return -1;
		}	
	}

	if( !GetVolumeInformationW( RootDirectory, 
						volumeName, sizeof(volumeName)/2, 
						&serialNumber, &maxComponent, &flags, 
						fileSystem, sizeof(fileSystem)/2)) {

		PrintWin32Error( L"Could not query volume", GetLastError());
		return -1;
	}

	// 
	// Print out some stuff including the formatted size
	//
	if( !GetDiskFreeSpaceExW( RootDirectory, 
			&freeBytesAvailableToCaller,
			&totalNumberOfBytes,
			&totalNumberOfFreeBytes )) {

		PrintWin32Error( L"Could not query volume size", GetLastError());
		return -1;
	}

	_tprintf(L"\n%I64d bytes total disk space.\n", totalNumberOfBytes.QuadPart );
	_tprintf(L"%I64d bytes available on disk.\n", totalNumberOfFreeBytes.QuadPart );

	//
	// Get the drive's serial number
	//
	if( !GetVolumeInformationW( RootDirectory, 
						volumeName, sizeof(volumeName)/2, 
						&serialNumber, &maxComponent, &flags, 
						fileSystem, sizeof(fileSystem)/2)) {

		PrintWin32Error( L"Could not query volume", GetLastError());
		return -1;
	}
	_tprintf(L"\nVolume Serial Number is %04X-%04X\n", serialNumber >> 16,
					serialNumber & 0xFFFF );
			
	return 0;
}
int main( int argc, char** argv )
{
	fprintf( stderr, "DLL base address scheduler v.1.2, copyright 2001-2002 (c) George Hazan.\n\n" );

   //----[ Command line parsing ]--------------------------------------------------------

   for ( int i=1; i < argc; i++ )
   {
      if ( argv[ i ][ 0 ] != '/' )
      {
LBL_Usage:
         fprintf( stderr, "Usage: Rebaser.exe [/BASE:<hex_digit>] [/CHECK]\n" );
		   return 200;
      }

      if ( memicmp( &argv[ i ][ 1 ], "BASE:", 5 ) == 0 )
         sscanf( &argv[ i ][ 6 ], "%08X", &glbOffset );
		else if ( memicmp( &argv[ i ][ 1 ], "CHECK", 5 ) == 0 )
		{
			glbCheckMode = true;
			glbOffset = 0x400000;
		}
      else goto LBL_Usage;
   }

   //----[ Command line ok, opening data files ]-----------------------------------------

	fprintf( stdout, "Scanning DLLs...\n" );

	int  locResult = 0;
	char locFileName[ MAX_PATH ];

	while ( fgets( locFileName, sizeof( locFileName ), stdin ) != NULL )
	{
		rtrim( locFileName );
		fprintf( stdout, "Processing '%s'...\n", locFileName );

		//----| If we need to check files only, check them |-------------------------------
		if ( glbCheckMode )
		{
			DWORD locOldImageSize, locOldBase, locNewSize, locNewBase;
			if ( !ReBaseImage( locFileName, NULL, FALSE, FALSE, FALSE, FALSE, &locOldImageSize,
																&locOldBase, &locNewSize, &locNewBase, 0 ))
				PrintWin32Error( GetLastError() );

			if ( locOldBase == glbOffset )
			{
				fprintf( stdout, "Image is not based\n\n" );
				locResult = 2;
			}

			continue;
		}

		//----| Preparing files |----------------------------------------------------------
LBL_Ok:
		HANDLE locFileHandle = CreateFile( locFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
		if ( locFileHandle == INVALID_HANDLE_VALUE )
		{
			fprintf( stdout, "File '%s' cannot be opened, skipped.\n\n", locFileName );
			locResult = 2;
			continue;
		}

		FILETIME locCreateTime, locAccessTime, locModifyTime;
		GetFileTime( locFileHandle, &locCreateTime, &locAccessTime, &locModifyTime );
		CloseHandle( locFileHandle );

		//----| Processing |---------------------------------------------------------------

		DWORD locOldImageSize, locOldBase, locNewSize;
		if ( !ReBaseImage( locFileName, NULL, TRUE, FALSE, FALSE, FALSE, &locOldImageSize,
															&locOldBase, &locNewSize, &glbOffset, 0 ))
		{
			PrintWin32Error( GetLastError() );
			locResult = 2;
		}

		glbOffset += locNewSize;

		//----| Write down the original file timestamp |-----------------------------------

		locFileHandle = CreateFile( locFileName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0 );
		if ( locFileHandle != INVALID_HANDLE_VALUE )
		{
			SetFileTime( locFileHandle, &locCreateTime, &locAccessTime, &locModifyTime );
			CloseHandle( locFileHandle );
	}	}

   return locResult;
}
示例#8
0
文件: format.c 项目: GYGit/reactos
//----------------------------------------------------------------------
//
// WMain
//
// Engine. Just get command line switches and fire off a format. This
// could also be done in a GUI like Explorer does when you select a
// drive and run a check on it.
//
// We do this in UNICODE because the chkdsk command expects PWCHAR
// arguments.
//
//----------------------------------------------------------------------
int wmain(int argc, WCHAR *argv[])
{
    int badArg;
    DWORD media = FMIFS_HARDDISK;
    DWORD driveType;
    WCHAR fileSystem[1024];
    WCHAR volumeName[1024];
    WCHAR input[1024];
    DWORD serialNumber;
    DWORD flags, maxComponent;
    ULARGE_INTEGER freeBytesAvailableToCaller, totalNumberOfBytes, totalNumberOfFreeBytes;
    WCHAR szMsg[RC_STRING_MAX_SIZE];

    wprintf(L"\n"
            L"Formatx v1.0 by Mark Russinovich\n"
            L"Systems Internals - http://www.sysinternals.com\n"
            L"ReactOS adaptation 1999 by Emanuele Aliberti\n\n");

#ifndef FMIFS_IMPORT_DLL
    //
    // Get function pointers
    //
    if (!LoadFMIFSEntryPoints())
    {
        PrintResourceString(STRING_FMIFS_FAIL);
        return -1;
    }
#endif

    //
    // Parse command line
    //
    badArg = ParseCommandLine(argc, argv);
    if (badArg)
    {
        PrintResourceString(STRING_UNKNOW_ARG, argv[badArg]);
        Usage(argv[0]);
        return -1;
    }

    //
    // Get the drive's format
    //
    if (!Drive)
    {
        PrintResourceString(STRING_DRIVE_PARM);
        Usage(argv[0]);
        return -1;
    }
    else
    {
        wcscpy(RootDirectory, Drive);
    }
    RootDirectory[2] = L'\\';
    RootDirectory[3] = L'\0';

    //
    // See if the drive is removable or not
    //
    driveType = GetDriveTypeW(RootDirectory);
    switch (driveType)
    {
        case DRIVE_UNKNOWN :
            LoadStringW(GetModuleHandle(NULL), STRING_ERROR_DRIVE_TYPE, szMsg, ARRAYSIZE(szMsg));
            PrintWin32Error(szMsg, GetLastError());
            return -1;

        case DRIVE_REMOTE:
        case DRIVE_CDROM:
            PrintResourceString(STRING_NO_SUPPORT);
            return -1;

        case DRIVE_NO_ROOT_DIR:
            LoadStringW(GetModuleHandle(NULL), STRING_NO_VOLUME, szMsg, ARRAYSIZE(szMsg));
            PrintWin32Error(szMsg, GetLastError());
            return -1;

        case DRIVE_REMOVABLE:
            PrintResourceString(STRING_INSERT_DISK, RootDirectory[0]);
            fgetws(input, ARRAYSIZE(input), stdin);
            media = FMIFS_FLOPPY;
            break;

        case DRIVE_FIXED:
        case DRIVE_RAMDISK:
            media = FMIFS_HARDDISK;
            break;
    }

    // Reject attempts to format the system drive
    {
        WCHAR path[MAX_PATH + 1];
        UINT rc;
        rc = GetWindowsDirectoryW(path, MAX_PATH);
        if (rc == 0 || rc > MAX_PATH)
            // todo: Report "Unable to query system directory"
            return -1;
        if (towlower(path[0]) == towlower(Drive[0]))
        {
            // todo: report "Cannot format system drive"
            PrintResourceString(STRING_NO_SUPPORT);
            return -1;
        }
    }

    //
    // Determine the drive's file system format
    //
    if (!GetVolumeInformationW(RootDirectory,
                               volumeName, ARRAYSIZE(volumeName),
                               &serialNumber, &maxComponent, &flags,
                               fileSystem, ARRAYSIZE(fileSystem)))
    {
        LoadStringW(GetModuleHandle(NULL), STRING_NO_VOLUME, szMsg, ARRAYSIZE(szMsg));
        PrintWin32Error(szMsg, GetLastError());
        return -1;
    }

    if (!GetDiskFreeSpaceExW(RootDirectory,
                             &freeBytesAvailableToCaller,
                             &totalNumberOfBytes,
                             &totalNumberOfFreeBytes))
    {
        LoadStringW(GetModuleHandle(NULL), STRING_NO_VOLUME_SIZE, szMsg, ARRAYSIZE(szMsg));
        PrintWin32Error(szMsg, GetLastError());
        return -1;
    }
    PrintResourceString(STRING_FILESYSTEM, fileSystem);

    //
    // Make sure they want to do this
    //
    if (driveType == DRIVE_FIXED)
    {
        if (volumeName[0])
        {
            while (TRUE)
            {
                PrintResourceString(STRING_LABEL_NAME_EDIT, RootDirectory[0]);
                fgetws(input, ARRAYSIZE(input), stdin);
                input[wcslen(input) - 1] = 0;

                if (!wcsicmp(input, volumeName))
                    break;

                PrintResourceString(STRING_ERROR_LABEL);
            }
        }

        PrintResourceString(STRING_YN_FORMAT, RootDirectory[0]);

        LoadStringW(GetModuleHandle(NULL), STRING_YES_NO_FAQ, szMsg, ARRAYSIZE(szMsg));
        while (TRUE)
        {
            fgetws(input, ARRAYSIZE(input), stdin);
            if (_wcsnicmp(&input[0], &szMsg[0], 1) == 0) break;
            if (_wcsnicmp(&input[0], &szMsg[1], 1) == 0)
            {
                wprintf(L"\n");
                return 0;
            }
        }
    }

    //
    // Tell the user we're doing a long format if appropriate
    //
    if (!QuickFormat)
    {
        LoadStringW(GetModuleHandle(NULL), STRING_VERIFYING, szMsg, ARRAYSIZE(szMsg));
        if (totalNumberOfBytes.QuadPart > 1024*1024*10)
        {
            PrintString(L"%s %luM\n", szMsg, (DWORD)(totalNumberOfBytes.QuadPart/(1024*1024)));
        }
        else
        {
            PrintString(L"%s %.1fM\n", szMsg,
                ((float)(LONGLONG)totalNumberOfBytes.QuadPart)/(float)(1024.0*1024.0));
        }
    }
    else
    {
        LoadStringW(GetModuleHandle(NULL), STRING_FAST_FMT, szMsg, ARRAYSIZE(szMsg));
        if (totalNumberOfBytes.QuadPart > 1024*1024*10)
        {
            PrintString(L"%s %luM\n", szMsg, (DWORD)(totalNumberOfBytes.QuadPart/(1024*1024)));
        }
        else
        {
            PrintString(L"%s %.2fM\n", szMsg,
                ((float)(LONGLONG)totalNumberOfBytes.QuadPart)/(float)(1024.0*1024.0));
        }
        PrintResourceString(STRING_CREATE_FSYS);
    }

    //
    // Format away!
    //
    FormatEx(RootDirectory, media, FileSystem, Label, QuickFormat,
             ClusterSize, FormatExCallback);
    if (Error) return -1;
    PrintResourceString(STRING_FMT_COMPLETE);

    //
    // Enable compression if desired
    //
    if (CompressDrive)
    {
        if (!EnableVolumeCompression(RootDirectory, TRUE))
            PrintResourceString(STRING_VOL_COMPRESS);
    }

    //
    // Get the label if we don't have it
    //
    if (!GotALabel)
    {
        PrintResourceString(STRING_ENTER_LABEL);
        fgetws(input, ARRAYSIZE(LabelString), stdin);

        input[wcslen(input) - 1] = 0;
        if (!SetVolumeLabelW(RootDirectory, input))
        {
            LoadStringW(GetModuleHandle(NULL), STRING_NO_LABEL, szMsg, ARRAYSIZE(szMsg));
            PrintWin32Error(szMsg, GetLastError());
            return -1;
        }
    }

    if (!GetVolumeInformationW(RootDirectory,
                               volumeName, ARRAYSIZE(volumeName),
                               &serialNumber, &maxComponent, &flags,
                               fileSystem, ARRAYSIZE(fileSystem)))
    {
        LoadStringW(GetModuleHandle(NULL), STRING_NO_VOLUME, szMsg, ARRAYSIZE(szMsg));
        PrintWin32Error(szMsg, GetLastError());
        return -1;
    }

    //
    // Print out some stuff including the formatted size
    //
    if (!GetDiskFreeSpaceExW(RootDirectory,
                             &freeBytesAvailableToCaller,
                             &totalNumberOfBytes,
                             &totalNumberOfFreeBytes))
    {
        LoadStringW(GetModuleHandle(NULL), STRING_NO_VOLUME_SIZE, szMsg, ARRAYSIZE(szMsg));
        PrintWin32Error(szMsg, GetLastError());
        return -1;
    }

    PrintResourceString(STRING_FREE_SPACE, totalNumberOfBytes.QuadPart,
                                           totalNumberOfFreeBytes.QuadPart);

    //
    // Get the drive's serial number
    //
    if (!GetVolumeInformationW(RootDirectory,
                               volumeName, ARRAYSIZE(volumeName),
                               &serialNumber, &maxComponent, &flags,
                               fileSystem, ARRAYSIZE(fileSystem)))
    {
        LoadStringW(GetModuleHandle(NULL), STRING_NO_VOLUME, szMsg, ARRAYSIZE(szMsg));
        PrintWin32Error(szMsg, GetLastError());
        return -1;
    }
    PrintResourceString(STRING_SERIAL_NUMBER,
                        (unsigned int)(serialNumber >> 16),
                        (unsigned int)(serialNumber & 0xFFFF));

    return 0;
}