很多时候,为了保护商业秘密,一些文件仅仅许可出现一次,就必须删除。
但是Windows的删除是不完善的,可以通过回收站找回,即使Windows的彻底删除,也不是彻底删除。也可以通过数据恢复软件找回,
我们如何实现彻底删除,用二进制数据填充磁盘,来彻底清除相关数据呢
我们来亲身实践360自带的功能。
详细类源码如下,请见源码分析,安全删除NTFS
#include "stdafx.h" #include "SecureDelNTFS.h" #include <time.h> #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif #define OVERWRITE_PASSES 1 #define BUFFER_SIZE 1024 ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CSecureDelNTFS::CSecureDelNTFS() { Recurse = true; ZapFreeSpace = true; CleanCompressedFiles = FALSE; NumPasses = 1; FilesFound = 0; firstCall = false; deleteDirectories = false; // 以系统时间为种子构造随机数 srand( (unsigned)time( NULL )); } CSecureDelNTFS::~CSecureDelNTFS() { } ///////////////////////////////////////////////////////////////////////////// // 函数名: OverwriteFileName( PTCHAR FileName, PTCHAR LastFileName ) // 参数列表:PTCHAR FileName // PTCHAR LastFileName // 函数功能:该函数的功能是安全删除文件名 ///////////////////////////////////////////////////////////////////////////// VOID CSecureDelNTFS::OverwriteFileName( PTCHAR FileName, PTCHAR LastFileName ) { TCHAR newName[MAX_PATH]; PTCHAR lastSlash; DWORD i, j, index; _tcscpy( LastFileName, FileName ); lastSlash = _tcsrchr( LastFileName, _T('\\')); index = (lastSlash - LastFileName)/sizeof(TCHAR); // 产生一个新的名称 CString sz="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"; if(index>125) sz=sz.Left((130-(index-125))); CString NewName=((CString) LastFileName).Left(index)+"\\"+CryptString(sz); sprintf(LastFileName,"%s",NewName); MoveFile( FileName, NewName ); _tcscpy( LastFileName, NewName ); lastSlash = _tcsrchr( LastFileName, _T('\\')); index = (lastSlash - LastFileName)/sizeof(TCHAR); int k=_tcsclen( LastFileName ); _tcscpy( newName, NewName ); int number=rand()*20/32767+2; for( i = 0; i < number; i++ ) { // 用随机产生的符号替换文件名中非'.'符号 for( j = index+1 ; j < _tcsclen( LastFileName ); j++ ) { if( LastFileName[j] != _T('.')) { int random=int((rand()*74/32767)); if(random>=10 && random<=16) random=17; if(random>=43 && random<=48) random=49; newName[j] = (TCHAR) random + _T('0'); } } // 用产生的新名称重命名 MoveFile( LastFileName, newName ); _tcscpy( LastFileName, newName ); } } ///////////////////////////////////////////////////////////////////////////// // 函数名: OverwriteDirectoryName( PTCHAR FileName, PTCHAR LastFileName ) // 参数列表:PTCHAR FileName // PTCHAR LastFileName // 函数功能:该函数的功能是安全删除文件名 ///////////////////////////////////////////////////////////////////////////// VOID CSecureDelNTFS::OverwriteDirectoryName( PTCHAR FileName, PTCHAR LastFileName ) { TCHAR newName[MAX_PATH]; PTCHAR lastSlash; DWORD i, j, index; _tcscpy( LastFileName, FileName ); lastSlash = _tcsrchr( LastFileName, _T('\\')); index = (lastSlash - LastFileName)/sizeof(TCHAR); // 产生一个新的名称 CString NewName=((CString) LastFileName).Left(index)+"\\"+CryptString("abcdefgh.XYZ"); sprintf(LastFileName,"%s",NewName); MoveFile( FileName, NewName ); _tcscpy( LastFileName, NewName ); lastSlash = _tcsrchr( LastFileName, _T('\\')); index = (lastSlash - LastFileName)/sizeof(TCHAR); int k=_tcsclen( LastFileName ); _tcscpy( newName, NewName ); int number=rand()*20/32767+2; for( i = 0; i < number; i++ ) { // 用随机产生的符号替换文件名中非'.'符号 for( j = index+1 ; j < _tcsclen( LastFileName ); j++ ) { if( LastFileName[j] != _T('.')) { int random=int((rand()*74/32767)); if(random>=10 && random<=16) random=17; if(random>=43 && random<=48) random=49; newName[j] = (TCHAR) random + _T('0'); } } // 用产生的新名称重命名 MoveFile( LastFileName, newName ); _tcscpy( LastFileName, newName ); } } ///////////////////////////////////////////////////////////////////////////// // 函数名: CryptString(CString string) // 参数列表:CString string // 函数功能:该函数的功能是根据已有的字符串产生一个加密的字符串 ///////////////////////////////////////////////////////////////////////////// CString CSecureDelNTFS::CryptString(CString string) { TCHAR FirstString[MAX_PATH]; _tcscpy( FirstString, string ); srand( (unsigned)time( NULL ) ); // 产生一个随机字符替换字符串中非'.'字符 for( int j = 0 ; j < _tcsclen( FirstString ); j++ ) { if( FirstString[j] != _T('.')) { int random=int((rand()*74/32767)); if(random>=10 && random<=16) random=17; if(random>=43 && random<=48) random=49; FirstString[j] = (TCHAR) random + _T('0'); } } return (CString) FirstString; } ///////////////////////////////////////////////////////////////////////////// // 函数名: SecureOverwrite( HANDLE FileHandle, DWORD Length ) // 参数列表:HANDLE FileHandle // DWORD Length // 函数功能:该函数的功能是安全删除文件 ///////////////////////////////////////////////////////////////////////////// BOOLEAN CSecureDelNTFS::SecureOverwrite( HANDLE FileHandle, DWORD Length ) { #define CLEANBUFSIZE 65536 static PBYTE cleanBuffer[3]; static BOOLEAN buffersAlloced = FALSE; DWORD i, j, passes; DWORD bytesWritten, bytesToWrite, totalWritten; LONG seekLength; BOOLEAN status; // 分配执行清除操作所需的缓冲区 if( !buffersAlloced ) { // 设置系统时间为随机数种子 srand( (unsigned)time( NULL ) ); for( i = 0; i < 3; i++ ) { // 设置清除缓冲区内容 cleanBuffer[i] = (unsigned char *)VirtualAlloc( NULL, CLEANBUFSIZE, MEM_COMMIT, PAGE_READWRITE ); if( !cleanBuffer[i] ) { for( j = 0; j < i; j++ ) { VirtualFree( cleanBuffer[j], 0, MEM_RELEASE ); } return FALSE; } switch( i ) { case 0: // 缓冲区内容为0 break; case 1: // 缓冲区内容为0 - 0xFF memset( cleanBuffer[i], 0x00, CLEANBUFSIZE ); break; case 2: // 缓冲区内容为随机值 for( j = 0; j < CLEANBUFSIZE; j++ ) cleanBuffer[i][j] = (BYTE) rand(); break; } } buffersAlloced = TRUE; } // 执行覆盖操作 seekLength = (LONG) Length; for( passes = 0; passes < NumPasses; passes++ ) { if( passes != 0 ) { // 将指针设置为最开始 SetFilePointer( FileHandle, -seekLength, NULL, FILE_CURRENT ); } for( i = 0; i < 2; i++ ) { // 将指针设置为最开始 if( i != 0 ) { SetFilePointer( FileHandle, -seekLength, NULL, FILE_CURRENT ); } // 循环并覆盖 bytesToWrite = Length; totalWritten = 0; while( totalWritten < Length ) { bytesToWrite = Length - totalWritten; if( bytesToWrite > CLEANBUFSIZE ) bytesToWrite = CLEANBUFSIZE; status = WriteFile( FileHandle, cleanBuffer[i], bytesToWrite, &bytesWritten, NULL ); if( !status ) return FALSE; totalWritten += bytesWritten; } } } return TRUE; } ///////////////////////////////////////////////////////////////////////////// // 函数名: SecureDelete( PTCHAR FileName, DWORD FileLengthHi, DWORD FileLengthLo ) // 参数列表:PTCHAR FileName // DWORD FileLengthHi // DWORD FileLengthLo // DWORD Length // 函数功能:该函数的功能是安全删除指定的文件 ///////////////////////////////////////////////////////////////////////////// VOID CSecureDelNTFS::SecureDelete( PTCHAR FileName, DWORD FileLengthHi, DWORD FileLengthLo ) { HANDLE hFile; ULONGLONG bytesToWrite, bytesWritten; ULARGE_INTEGER fileLength; TCHAR lastFileName[MAX_PATH]; // 首先以覆盖的模式打开文件 hFile = CreateFile( FileName, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, NULL ); if( hFile == INVALID_HANDLE_VALUE ) return; // 如果文件的长度不为零,则将文件所占的所有簇填入0 if( FileLengthLo || FileLengthHi ) { // 找文件的后一簇 FileLengthLo--; if( FileLengthLo == (DWORD) -1 && FileLengthHi ) FileLengthHi--; SetFilePointer( hFile, FileLengthLo, (long *) &FileLengthHi, FILE_BEGIN ); // 在文件中填入0 if( !SecureOverwrite( hFile, 1 )) { CloseHandle( hFile ); return; } // 回到文件的头部,处理文件剩下的部分 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 )) { CloseHandle( hFile ); return; } bytesWritten += bytesToWrite; } } // 完成后关闭文件 CloseHandle( hFile ); // 重命名文件 OverwriteFileName( FileName, lastFileName ); // 删除文件 if( !DeleteFile( lastFileName ) ) return; } ///////////////////////////////////////////////////////////////////////////// // 函数名: BOOLEAN CSecureDelNTFS::ScanFile( HANDLE VolumeHandle, DWORD ClusterSize, // HANDLE FileHandle, PBOOLEAN ReallyCompressed, PBOOLEAN ZappedFile ) // 参数列表:ANDLE VolumeHandle // DWORD ClusterSize // HANDLE FileHandle // PBOOLEAN ReallyCompressed // PBOOLEAN ZappedFilePTCHAR // 函数功能:该函数的功能是当NTFS卷是压缩、加密时调用进行文件扫描 ///////////////////////////////////////////////////////////////////////////// BOOLEAN CSecureDelNTFS::ScanFile( HANDLE VolumeHandle, DWORD ClusterSize, HANDLE FileHandle, PBOOLEAN ReallyCompressed, PBOOLEAN ZappedFile ) { DWORD status; int i; IO_STATUS_BLOCK ioStatus; ULONGLONG startVcn, prevVcn; LARGE_INTEGER clusterOffset; ULONGLONG endOfPrevRun; PGET_RETRIEVAL_DESCRIPTOR fileMappings; ULONGLONG fileMap[ FILEMAPSIZE ]; int lines = 0; // 假设文件位于MFT记录中 *ReallyCompressed = FALSE; *ZappedFile = FALSE; startVcn = 0; endOfPrevRun = LLINVALID; fileMappings = (PGET_RETRIEVAL_DESCRIPTOR) fileMap; while( !(status = NtFsControlFile( FileHandle, NULL, NULL, 0, &ioStatus, FSCTL_GET_RETRIEVAL_POINTERS, &startVcn, sizeof( startVcn ), fileMappings, FILEMAPSIZE * sizeof(ULONGLONG) ) ) || status == STATUS_BUFFER_OVERFLOW || status == STATUS_PENDING ) { // 如果操作正在进行,则等待完成 if( status == STATUS_PENDING ) { WaitForSingleObject( FileHandle, INFINITE ); // 获取状态参数 if( ioStatus.Status != STATUS_SUCCESS && ioStatus.Status != STATUS_BUFFER_OVERFLOW ) { return ioStatus.Status == STATUS_SUCCESS; } } startVcn = fileMappings->StartVcn; prevVcn = fileMappings->StartVcn; for( i = 0; i < (ULONGLONG) fileMappings->NumberOfPairs; i++ ) { if( fileMappings->Pair[i].Lcn != LLINVALID ) { // 压缩模式 *ReallyCompressed = TRUE; // 覆盖所在的簇 if( VolumeHandle != INVALID_HANDLE_VALUE ) { clusterOffset.QuadPart = fileMappings->Pair[i].Lcn * ClusterSize; SetFilePointer( VolumeHandle, clusterOffset.LowPart, &clusterOffset.HighPart, FILE_BEGIN ); if( !SecureOverwrite( VolumeHandle, ClusterSize * (DWORD) (fileMappings->Pair[i].Vcn - startVcn) )) return TRUE; } else return TRUE; } startVcn = fileMappings->Pair[i].Vcn; } if( !status ) break; } if( status == STATUS_SUCCESS ) *ZappedFile = TRUE; return status == STATUS_SUCCESS; } ///////////////////////////////////////////////////////////////////////////// // 函数名: SecureDeleteCompressed( PTCHAR FileName ) // 参数列表:PTCHAR FileName // 函数功能:该函数的功能是删除压缩磁盘中的文件 ///////////////////////////////////////////////////////////////////////////// BOOLEAN CSecureDelNTFS::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( 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; } // 打开文件 hFile = CreateFile( FileName, GENERIC_READ, 0,NULL, OPEN_EXISTING, 0, NULL ); if( hFile == INVALID_HANDLE_VALUE ) return TRUE; // 确定文件的位置 if( !ScanFile( hVolume, clusterSize, hFile, &reallyCompressed, &zappedFile )) { CloseHandle( hFile ); return TRUE; } // 关闭文件 CloseHandle( hFile ); if( reallyCompressed ) { // 重新命名文件名 OverwriteFileName( FileName, lastFileName ); // 文件长度修改为0 FILE *fp=fopen(lastFileName,"w"); fclose(fp); // 删除文件 if( !DeleteFile( lastFileName )) { MoveFile( lastFileName, FileName ); return TRUE; } // 如果不能直接覆盖文件的簇,则通过清除磁盘的自由空间来覆盖 if( !zappedFile ) CleanCompressedFiles = TRUE; } return reallyCompressed; } ///////////////////////////////////////////////////////////////////////////// // 函数名: ProcessFile( PWIN32_FIND_DATA FindData, TCHAR *FileName ) // 参数列表:PWIN32_FIND_DATA FindData // TCHAR *FileName // 函数功能:该函数的功能是处理文件的删除 ///////////////////////////////////////////////////////////////////////////// VOID CSecureDelNTFS::ProcessFile( PWIN32_FIND_DATA FindData, TCHAR *FileName ) { // 如果是目录的删除,则直接返回 if( FindData->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) return; FilesFound++; // 如果文件是压缩的 if( FindData->dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED || FindData->dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED || FindData->dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE ) { // 处理压缩磁盘中的文件 if( SecureDeleteCompressed( FileName )) return; } // 删除常规(非压缩、非加密磁盘)文件 SecureDelete( FileName, FindData->nFileSizeHigh, FindData->nFileSizeLow ); } ///////////////////////////////////////////////////////////////////////////// // 函数名: ProcessDirectory( TCHAR *PathName, TCHAR *SearchPattern ) // 参数列表:TCHAR *PathName // TCHAR *SearchPattern // 函数功能:该函数的功能是处理目录的删除 ///////////////////////////////////////////////////////////////////////////// void CSecureDelNTFS::ProcessDirectory( TCHAR *PathName, TCHAR *SearchPattern ) { TCHAR subName[MAX_PATH], fileSearchName[MAX_PATH], searchName[MAX_PATH]; HANDLE dirHandle, patternHandle; WIN32_FIND_DATA foundFile; TCHAR lastFileName[MAX_PATH]; // 遍历所有的文件和目录 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 ); } // 处理所有的文件 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 ); // 处理文件 ProcessFile( &foundFile, subName ); } } while( FindNextFile( patternHandle, &foundFile )); FindClose( patternHandle ); } // 进行递归删除 if( Recurse ) { if( firstCall && !_tcsrchr( searchName, L'\\') ) { if( _tcsrchr( searchName, L'*' )) { if( (dirHandle = FindFirstFile( _T("*.*"), &foundFile )) == INVALID_HANDLE_VALUE) return; } else { if( (dirHandle = FindFirstFile( searchName, &foundFile )) == INVALID_HANDLE_VALUE) return; } } else { if( (dirHandle = FindFirstFile( searchName, &foundFile )) == INVALID_HANDLE_VALUE) 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 ); // 处理目录 ProcessDirectory( subName, SearchPattern ); // 删除目录 if( deleteDirectories ) { // 重新命名文件名 OverwriteDirectoryName( subName, lastFileName ); SetFileAttributes(lastFileName,FILE_ATTRIBUTE_NORMAL); RemoveDirectory( lastFileName ); } } } while( FindNextFile( dirHandle, &foundFile )); FindClose( dirHandle ); } } ///////////////////////////////////////////////////////////////////////////// // 函数名: CleanFreeSpace( PTCHAR DrivePath ) // 参数列表:PTCHAR DrivePath // 函数功能:该函数的功能是清除磁盘的自由空间 ///////////////////////////////////////////////////////////////////////////// BOOLEAN CSecureDelNTFS::CleanFreeSpace( PTCHAR DrivePath ) { TCHAR tempFileName[MAX_PATH]; ULARGE_INTEGER bytesAvail, totalBytes, freeBytes; DWORD sectorsPerCluster, bytesPerSector, totalClusters, freeClusters; ULONGLONG tempSize = 0; HANDLE hTempFile; BOOLEAN createdFile; DWORD cleanSize, mftFilesCreated; DWORD prevSize; CString strText; if( DrivePath[1] != ':' ) return FALSE; // 磁盘分区路径 DrivePath[3] = 0; if( !GetDiskFreeSpace( DrivePath, §orsPerCluster, &bytesPerSector, &freeClusters, &totalClusters )) return FALSE; #if UNICODE if( !(pGetDiskFreeSpaceEx = (int (__stdcall *)(const char *,union _ULARGE_INTEGER *,union _ULARGE_INTEGER *,union _ULARGE_INTEGER *)) GetProcAddress( GetModuleHandle( _T("kernel32.dll") ), "GetDiskFreeSpaceExW" ))) { #else if( !(pGetDiskFreeSpaceEx = (int (__stdcall *)(const char *,union _ULARGE_INTEGER *,union _ULARGE_INTEGER *,union _ULARGE_INTEGER *)) GetProcAddress( GetModuleHandle( _T("kernel32.dll") ), "GetDiskFreeSpaceExA" ))) { #endif bytesAvail.QuadPart = sectorsPerCluster * freeClusters * bytesPerSector; freeBytes.QuadPart = bytesAvail.QuadPart; } else { if( !pGetDiskFreeSpaceEx( DrivePath, &bytesAvail, &totalBytes, &freeBytes )) return FALSE; } if( bytesAvail.QuadPart != freeBytes.QuadPart ) return FALSE; _stprintf( tempFileName, _T("%sSDELTEMP"), DrivePath ); hTempFile = CreateFile( tempFileName, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_FLAG_NO_BUFFERING|FILE_FLAG_SEQUENTIAL_SCAN| FILE_FLAG_DELETE_ON_CLOSE|FILE_ATTRIBUTE_HIDDEN, NULL ); if( hTempFile == INVALID_HANDLE_VALUE ) return FALSE; // 分配清除缓冲区 cleanSize = sectorsPerCluster * bytesPerSector * 128; // 增大簇的容量直到超过极限 while( cleanSize > bytesPerSector * sectorsPerCluster ) { if( SecureOverwrite( hTempFile, cleanSize )) { tempSize += cleanSize; } else { cleanSize -= bytesPerSector * sectorsPerCluster; } } // 最后存在一个小于一个完整簇的空间,利用另外一个临时文件覆盖 _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 )) { tempSize += cleanSize; }else { cleanSize--; } } } if( ZapFreeSpace ) { mftFilesCreated = 0; // 最大的 MFT 记录大小 prevSize = 4096; 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; } cleanSize = prevSize; createdFile = FALSE; while( cleanSize ) { if( !SecureOverwrite( hTempFile, cleanSize )) { cleanSize--; } else { prevSize = cleanSize; createdFile = TRUE; tempSize += cleanSize; } } if( !createdFile ) break; } } return TRUE; } ///////////////////////////////////////////////////////////////////////////// // 函数名: LocateNativeEntryPoints() // 参数列表: // 函数功能:该函数的功能是定位NTDLL的入口点 ///////////////////////////////////////////////////////////////////////////// VOID CSecureDelNTFS::LocateNativeEntryPoints() { // 如果当前的Windows版本是Win9x,则直接返回 if( GetVersion() >= 0x80000000) return; // 装入所需的NTDLL入口点 if( !(NtFsControlFile = (unsigned int (__stdcall *)(void *,void *,void (__cdecl *)(void *,struct _IO_STATUS_BLOCK *,unsigned long),void *,struct _IO_STATUS_BLOCK *, unsigned long,void *,unsigned long,void *,unsigned long)) GetProcAddress( GetModuleHandle(_T("ntdll.dll")), "NtFsControlFile" )) ) { AfxMessageBox("Could not find NtFsControlFile entry point in NTDLL.DLL",MB_OK | MB_ICONERROR); exit(1); } if( !(RtlNtStatusToDosError = (unsigned long (__stdcall *)(unsigned int)) GetProcAddress( GetModuleHandle(_T("ntdll.dll")), "RtlNtStatusToDosError" )) ) { AfxMessageBox("Could not find RtlNtStatusToDosError entry point in NTDLL.DLL",MB_OK | MB_ICONERROR); exit(1); } } ///////////////////////////////////////////////////////////////////////////// // 函数名: WipeFileContent(LPCTSTR pFilePath) // 参数列表: // 函数功能:该函数主要用于将需要删除的文件全部清零 ///////////////////////////////////////////////////////////////////////////// BOOL CSecureDelNTFS::WipeFileContent(CString strfilename) { char filename[MAX_PATH]; sprintf(filename, "%s", strfilename); HANDLE hFile = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_FLAG_WRITE_THROUGH, NULL); if (hFile == INVALID_HANDLE_VALUE) return false; DWORD fileSize = GetFileSize(hFile, 0); // 如果文件是空,则直接返回 if (!fileSize) { CloseHandle(hFile); return false; } DWORD j=0; for (int passes = 0; passes < OVERWRITE_PASSES; passes++) { char newStorage[BUFFER_SIZE]; srand((unsigned)time(NULL)); if(passes<(OVERWRITE_PASSES-1)) FillMemory((void*)newStorage, BUFFER_SIZE, rand() % 255); else FillMemory((void*)newStorage, BUFFER_SIZE, 0); SetFilePointer(hFile, 0, NULL, FILE_BEGIN); DWORD left = fileSize; int write = BUFFER_SIZE; DWORD written = 0; while (left) { j=j+1; if (left < BUFFER_SIZE) write = left; BOOL status = WriteFile(hFile, newStorage, write, &written, NULL); if (!status) { CloseHandle(hFile); return false; } left -= write; } } CloseHandle(hFile); return true; }
类中的调用源码如下
void CSDeleteNTFSDlg::OnButtonSecuredel() { // TODO: Add your control notification handler code here if(m_filename!="") { // 采用全部清零的方法删除文件的内容 m_SdelNTFS.WipeFileContent(m_filename); // 设置文件的长度为零 FILE *fp=fopen(m_filename,"w"); fclose(fp); // 删除该文件的文件名 TCHAR searchPattern[MAX_PATH]; TCHAR searchPath[MAX_PATH]; sprintf(searchPath, "%s", m_filename); m_SdelNTFS.firstCall = true; m_SdelNTFS.deleteDirectories =false; m_SdelNTFS.ProcessDirectory( searchPath, searchPattern ); AfxMessageBox("安全删除完毕!"); m_filename=""; } UpdateData(false); }