安全删除NTFS磁盘数据文件

很多时候,为了保护商业秘密,一些文件仅仅许可出现一次,就必须删除。

但是 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);
    
}