//---------------------------------------------------------------------- // // 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; }
//-------------------------------------------------------------------- // // 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 ); } }
//-------------------------------------------------------------------- // // 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, §orsPerCluster, &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; }
//-------------------------------------------------------------------- // // 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, §orsPerCluster, &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; }
//-------------------------------------------------------------------- // // 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")); }
//---------------------------------------------------------------------- // // 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; }
//---------------------------------------------------------------------- // // 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; }