winston 发表于 2012-3-8 15:05:51

[原]VC++信息安全编程(17)安全删除FAT磁盘数据文件

很多时候,为了保护商业秘密,一些文件仅仅许可出现一次,就必须删除。
但是windows的删除是不完善的,可以通过回收站找回,即使windows的彻底删除,也不是彻底删除。也可以通过数据恢复软件找回,
我们如何实现彻底删除,用二进制数据填充磁盘,来彻底清除相关数据呢
我们来亲身实践360自带的功能。
详细类源码如下,请见源码分析,安全删除fat的类



#include "stdafx.h"
#include "SecureDelFAT.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSecureDelFAT::CSecureDelFAT()
{

}

CSecureDelFAT::~CSecureDelFAT()
{

}



int CSecureDelFAT::NtOr98()
{
        OSVERSIONINFO osvi;
               
        //判断本软件运行所在的系统版本号
        osvi.dwOSVersionInfoSize=sizeof(OSVERSIONINFO);
        GetVersionEx (&osvi);
        if(osvi.dwPlatformId == VER_PLATFORM_WIN32_NT)
                return 2000;
        else
        {
                if((osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
                        ( (osvi.dwMajorVersion > 4) ||
                        ( (osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion > 0) ) ))
                        return 98;
                else
                        return 0;
        }
}

//*******************锁定分区***************************
//形参:    驱动器号、锁定允许、锁定等级
//返回值:成功返回1,否则返回0
BOOL CSecureDelFAT::LockVolume(BYTE bDrive,DWORD dwPermission,BYTE bLevel)
{
        BOOL fResult;
        DWORD cb;
        HANDLE hDev;
        DIOC_REGISTERS reg;
        reg.reg_EAX=0x440d;
        reg.reg_EBX=MAKEWORD(bDrive,bLevel);
        reg.reg_ECX=0x484a;
        reg.reg_EDX=dwPermission;
       
        hDev=::CreateFile("\\\\.\\vwin32",0,0,NULL,0,FILE_FLAG_DELETE_ON_CLOSE,NULL);
        fResult=::DeviceIoControl(hDev,VWIN32_DIOC_DOS_IOCTL,
                                ®,sizeof(reg),®,sizeof(reg),&cb,0);
       

        fResult=fResult && !(reg.reg_Flags & CARRY_FLAG);
        CloseHandle(hDev);       
        return fResult;

}

//********************分区解锁*****************************
//形参:   驱动器号
//返回值:   成功返回1,否则返回0
BOOL CSecureDelFAT::UnlockVolume(BYTE bDrive)
{
        BOOL fResult;
        DWORD cb;
        HANDLE hDev;
        DIOC_REGISTERS reg={0};
        reg.reg_EAX=0x440d;
        reg.reg_EBX=bDrive;
        reg.reg_ECX=0x486a;
       
        hDev=::CreateFile("\\\\.\\vwin32",0,0,NULL,0,FILE_FLAG_DELETE_ON_CLOSE,NULL);
        fResult=::DeviceIoControl(hDev,VWIN32_DIOC_DOS_IOCTL,
                                ®,sizeof(reg),®,sizeof(reg),&cb,0);

        fResult=fResult && !(reg.reg_Flags & CARRY_FLAG);
        CloseHandle(hDev);       
        return fResult;

}

//*************读取指定扇区的内容***************
//形参:      驱动器号、起始扇区、要读取扇区数、内存区
//返回值:    成功返回1,否则返回0
BOOL CSecureDelFAT::ReadSectors(BYTE bDrive,
                     DWORD dwStartSector,WORD wSectors,LPBYTE lpSectBuff)
{
        BOOL        fResult;
        DWORD        cb;
        DISKIO        dio={0};
        DIOC_REGISTERS reg={0};

        HANDLE        hDev;
        hDev=CreateFile("\\\\.\\vwin32",0,0,NULL,0,FILE_FLAG_DELETE_ON_CLOSE,NULL);

        dio.dwStartSector=dwStartSector; //要读取的起始扇区
        dio.wSectors=wSectors;//要读取的扇区数
        dio.dwBuffer=(DWORD)lpSectBuff; //存放读出扇区的缓冲区

        reg.reg_EAX=0x7305;   
        reg.reg_EBX=(DWORD)&dio;
        reg.reg_ECX=-1;
        reg.reg_EDX=bDrive;
       

        fResult=::DeviceIoControl(hDev,VWIN32_DIOC_DOS_DRIVEINFO,
                                ®,sizeof(reg),®,sizeof(reg),&cb,0);

        fResult=fResult && !(reg.reg_Flags & CARRY_FLAG);
       
        CloseHandle(hDev);
        return fResult;

}

//*******************向指定扇区写*******************
//形参:      驱动器号、起始扇区、要写的扇区数、内存区
//返回值:    成功返回1,否则返回0

BOOL CSecureDelFAT::WriteSectors(BYTE bDrive,
                     DWORD dwStartSector,WORD wSectors,LPBYTE lpSectBuff)
{
        BOOL        fResult,IfLock;
        DWORD        cb;
        DISKIO dio={0};
        DIOC_REGISTERS reg={0};
        IfLock=LockVolume(bDrive,0,1);
        HANDLE        hDev;
        hDev=CreateFile("\\\\.\\vwin32",0,0,NULL,0,FILE_FLAG_DELETE_ON_CLOSE,NULL);
       

        dio.dwStartSector=dwStartSector; //要写入的起始扇区
        dio.wSectors=wSectors;         //要写入的扇区数
        dio.dwBuffer=(DWORD)lpSectBuff;//存放要写入内容的缓冲区

        reg.reg_EAX=0x7305;            
        reg.reg_EBX=(DWORD)&dio;
        reg.reg_ECX=-1;
        reg.reg_EDX=bDrive;
        reg.reg_ESI=0x0001;
       
        fResult=::DeviceIoControl(hDev,VWIN32_DIOC_DOS_DRIVEINFO,
                                ®,sizeof(reg),®,sizeof(reg),&cb,0);

        fResult=fResult && !(reg.reg_Flags & CARRY_FLAG);
       
        CloseHandle(hDev);
        IfLock=UnlockVolume(bDrive);
        return fResult;

}
//*************读取指定扇区的内容***************
//形参:      驱动器号、起始扇区、要读取扇区数、内存区
//返回值:    成功返回1,否则返回0
BOOL CSecureDelFAT::ReadSectors2000(BYTE bDrive,
                     DWORD dwStartSector,WORD wSectors,LPBYTE lpSectBuff)
{
        BOOL        fResult;
        char InfoFileName="";
        ULONGLONG MoveDistanceOfByte;
        LONG LowDistanceOfByte,HighDistanceOfByte;
        PLONG lpDistance;
        DWORD dwBytesToRead;
        HANDLE        hDev;
        DWORD dwFilePointer;

        //得到要读取的起始扇区及要读取的字节数
        MoveDistanceOfByte=((ULONGLONG)512*(ULONGLONG)dwStartSector);
        LowDistanceOfByte=(LONG)(MoveDistanceOfByte);
        MoveDistanceOfByte=Int64ShrlMod32(MoveDistanceOfByte,0x10);
        MoveDistanceOfByte=Int64ShrlMod32(MoveDistanceOfByte,0x10);
        HighDistanceOfByte=(LONG)(MoveDistanceOfByte);
        lpDistance=(PLONG)(&HighDistanceOfByte);
        dwBytesToRead=512*wSectors;
        //得到要读取的驱动器
        strcat(InfoFileName,"\\\\.\\");
        InfoFileName=bDrive-1+'A';
        strcat(InfoFileName,":");
        //将要读取的驱动器当作一文件打开
        hDev=CreateFile(InfoFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
        //设置文件指针,对驱动器来说就是起始位置
        dwFilePointer=SetFilePointer(hDev,LowDistanceOfByte,lpDistance, FILE_BEGIN);
        //读取驱动器上数据
        fResult=ReadFile(hDev,lpSectBuff,dwBytesToRead,&dwBytesToRead,NULL);
        CloseHandle(hDev);
        return fResult;

}

//*******************向指定扇区写*******************
//形参:      驱动器号、起始扇区、要写的扇区数、内存区
//返回值:    成功返回1,否则返回0

BOOL CSecureDelFAT::WriteSectors2000(BYTE bDrive,
                     DWORD dwStartSector,WORD wSectors,LPBYTE lpSectBuff)
{
        BOOL        fResult;
        char InfoFileName="";
        ULONGLONG MoveDistanceOfByte;
        LONG LowDistanceOfByte,HighDistanceOfByte;
        PLONG lpDistance;
        DWORD dwBytesToWrite;
        HANDLE        hDev;
        DWORD dwFilePointer;
        //得到要写的起始扇区及要读取的字节数
        MoveDistanceOfByte=((ULONGLONG)512*(ULONGLONG)dwStartSector);
        LowDistanceOfByte=(LONG)(MoveDistanceOfByte);
        MoveDistanceOfByte=Int64ShrlMod32(MoveDistanceOfByte,0x10);
        MoveDistanceOfByte=Int64ShrlMod32(MoveDistanceOfByte,0x10);
        HighDistanceOfByte=(LONG)(MoveDistanceOfByte);
        lpDistance=(PLONG)(&HighDistanceOfByte);
        dwBytesToWrite=512*wSectors;
        //得到要写的驱动器
        strcat(InfoFileName,"\\\\.\\");
        InfoFileName=bDrive-1+'A';
        strcat(InfoFileName,":");
        //将要写的驱动器当作一文件打开
        hDev=CreateFile(InfoFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
        //设置文件指针
        dwFilePointer=SetFilePointer(hDev,LowDistanceOfByte,lpDistance, FILE_BEGIN);
        //向文件写数据
        fResult=WriteFile(hDev,lpSectBuff,dwBytesToWrite,&dwBytesToWrite,NULL);
        CloseHandle(hDev);       
        return fResult;

}



//***********判断驱动器是否FAT文件系统*************
//形参:      驱动器号
//返回值:    非Fat返回0,fat12返回12;fat16返回16;fat32返回32
int CSecureDelFAT::IfFatX(BYTE bDrive)
{
        int i;
        int IsNtOr98;
       
        LPBYTE lpSectBuff;
       
        char FileStyle12={0};
        char FileStyle16={0};
        char FileStyle32={0};
        //**************************

        lpSectBuff=(LPBYTE)malloc(1024);
        //判断操作系统的版本号
        IsNtOr98=NtOr98();
        //读取指定驱动器的文件系统
        if(IsNtOr98==2000)
                ReadSectors2000(bDrive,0,1,lpSectBuff);
        else
                ReadSectors(bDrive,0,1,lpSectBuff);
        //根据驱动器类型不同来获得表示文件系统的字节
        //如果是软盘
        for(i=0;i<5;i++)
                FileStyle12=*(lpSectBuff+54+i);

        for(i=0;i<5;i++)
                FileStyle16=*(lpSectBuff+54+i);

        for(i=0;i<5;i++)
                FileStyle32=*(lpSectBuff+82+i);

        free(lpSectBuff);
        //下面判断是什么FAT文件系统
        if(strcmp(FileStyle12,"FAT12")==0)
                return 12;
        else if(strcmp(FileStyle16,"FAT16")==0)
                return 16;
        else if(strcmp(FileStyle32,"FAT32")==0)
                return 32;
        else
                return 0;

}


//*************磁盘基本信息**************
//形参:    驱动器号、磁盘基本信息数据结构
//返回值:        无
void CSecureDelFAT::fDiskInfo(FILEINFO InfoOfFile,PINFOFDISK pDiskInfo)               
{
        WORD wLow,wHigh;
        LPBYTE lpSectBuff;//缓冲区
        INFOFDISK di={0};
        int IsNtOr98;

        lpSectBuff=(LPBYTE)malloc(1024);
        //判断操作系统版本号
        IsNtOr98=NtOr98();
        if(IsNtOr98==2000)
                ReadSectors2000(InfoOfFile.bDrive,0,1,lpSectBuff);//读BPB表
        else
                ReadSectors(InfoOfFile.bDrive,0,1,lpSectBuff);//读BPB表
        //**********Fat16信息***************
        if(InfoOfFile.IfFat==16)//fat16
        {
                //每扇区字节数
                di.wNumOfByteEachSec=MAKEWORD(*(lpSectBuff+11),*(lpSectBuff+12));
                //保留扇区数
                di.wReserveSector=MAKEWORD(*(lpSectBuff+14),*(lpSectBuff+15));
                //FAT表数目
                di.bNumOfFat=*(lpSectBuff+16);
                //FAT表长度
                di.dwLenOfFat=(DWORD)(MAKEWORD(*(lpSectBuff+22),*(lpSectBuff+23)));
                //每簇扇区数
                di.bNumOfSectorsEachClu=*(lpSectBuff+13);
                //目录表项数
                di.wNumOfIndex=MAKEWORD(*(lpSectBuff+17),*(lpSectBuff+18));
        }

        //*************fat32信息*************
        else
        {               
                //每扇区字节数
                di.wNumOfByteEachSec=MAKEWORD(*(lpSectBuff+11),*(lpSectBuff+12));
                //保留扇区数
                di.wReserveSector=MAKEWORD(*(lpSectBuff+14),*(lpSectBuff+15));
                //FAT表数目
                di.bNumOfFat=*(lpSectBuff+16);
               
                //FAT表长度
                wLow=MAKEWORD(*(lpSectBuff+36),*(lpSectBuff+37));
                wHigh=MAKEWORD(*(lpSectBuff+38),*(lpSectBuff+39));
                di.dwLenOfFat=MAKELONG(wLow,wHigh);
                //每簇扇区数
                di.bNumOfSectorsEachClu=*(lpSectBuff+13);
                //根目录首簇号
                wLow=MAKEWORD(*(lpSectBuff+44),*(lpSectBuff+45));
                wHigh=MAKEWORD(*(lpSectBuff+46),*(lpSectBuff+47));
                di.dwFirstCluOfIndex=MAKELONG(wLow,wHigh);
        }
        pDiskInfo->bNumOfFat=di.bNumOfFat;
        pDiskInfo->bNumOfSectorsEachClu=di.bNumOfSectorsEachClu;
        pDiskInfo->dwFirstCluOfIndex=di.dwFirstCluOfIndex;
        pDiskInfo->dwLenOfFat=di.dwLenOfFat;
        pDiskInfo->wNumOfByteEachSec=di.wNumOfByteEachSec;
        pDiskInfo->wNumOfIndex=di.wNumOfIndex;
        pDiskInfo->wReserveSector=di.wReserveSector;

        free(lpSectBuff);
       
       
}
//**********************************************************************************


//*********得到fat表的逻辑起始扇区***************
//形参:        驱动器号、磁盘基本信息数据结构
//返回值:fat表逻辑起始扇区
DWORD CSecureDelFAT::FatStartSec(INFOFDISK DiskInfo)
{

        WORD wReserveSector;//保留扇区数
        DWORD dwFatSec;
       
        wReserveSector=DiskInfo.wReserveSector;
        dwFatSec=wReserveSector;
        return dwFatSec;
}

//********得到备份FAT表的起始扇区*********
//形参:   驱动器号、磁盘基本信息数据结构
//返回值: 备份FAT表的起始扇区
DWORD CSecureDelFAT::FatBakStartSec(INFOFDISK DiskInfo)
{
        DWORD dwFatBakStaSec;//备份FAT表的起始扇区
        DWORD dwLenOfFat;
        WORD wReserveSector;
       
        dwLenOfFat=DiskInfo.dwLenOfFat;
        wReserveSector=DiskInfo.wReserveSector;
        dwFatBakStaSec=wReserveSector+dwLenOfFat;
        return dwFatBakStaSec;

}

//***********获得逻辑盘根目录起始扇区*************
//形参:    磁盘信息结构、文件信息结构
//返回值:根目录起始扇区
DWORD CSecureDelFAT::DiskIndex(INFOFDISK DiskInfo,FILEINFO InfoOfFile)
{
        BYTE bNumOfFat;//fat表个数
        BYTE bNumOfSectorsEachClu;//每簇扇区数

        WORD wReserveSector;//保留扇区数

        DWORD dwLenOfFat;//fat表长度
        DWORD dwFirstCluOfIndex;//根目录首簇
        DWORD dwPositonOfIndex;//根目录起始扇区

        //保留扇区
        wReserveSector=DiskInfo.wReserveSector;
        //FAT表个数
        bNumOfFat=DiskInfo.bNumOfFat;
        //FAT表长度
        dwLenOfFat=DiskInfo.dwLenOfFat;
        //每簇扇区数
        bNumOfSectorsEachClu=DiskInfo.bNumOfSectorsEachClu;
        //根目录首簇
        dwFirstCluOfIndex=DiskInfo.dwFirstCluOfIndex;
        //**********fat12或fat16***************
        if(InfoOfFile.IfFat==16)
        {               
                //fat16的根目录起始扇区为:
                dwPositonOfIndex=wReserveSector+bNumOfFat*dwLenOfFat;
        }
       
        //*************fat32*************
        else
        {               
                //fat32根目录的起始扇区为:
                dwPositonOfIndex=wReserveSector+bNumOfFat*dwLenOfFat+
                                             (dwFirstCluOfIndex-2)*bNumOfSectorsEachClu;
               
        }
        //*************硬盘*************
        return dwPositonOfIndex;
}
//*************************************************************************************




//**********将簇号转化为扇区*********
//形参:      磁盘信息结构、关键位置信息结构、文件信息结构、要转化的簇号
//返回值:   文件起始扇区
DWORD CSecureDelFAT::SectorOfFile(INFOFDISK DiskInfo,INFOFPOSITION PositionInfo,FILEINFO InfoOfFile,DWORD dwTheClu)
{
        BYTE bNumOfSectorsEachClu;//每簇扇区数
        DWORD dwPositonOfData;//数据区起始扇区
        DWORD dwFirstCluOfRootIndex;//根目录起始簇
       
        DWORD dwSectorFromClu;//由簇号转化得到的扇区号
       
        //每簇扇区数
        bNumOfSectorsEachClu=DiskInfo.bNumOfSectorsEachClu;
        //根目录首簇
        dwFirstCluOfRootIndex=DiskInfo.dwFirstCluOfIndex;
       
        //数据区起始扇区
        dwPositonOfData=PositionInfo.dwDataStartSec;
       
        if(InfoOfFile.IfFat==32)
                dwSectorFromClu=bNumOfSectorsEachClu*(dwTheClu-dwFirstCluOfRootIndex)+dwPositonOfData;
        else
                dwSectorFromClu=bNumOfSectorsEachClu*(dwTheClu-2)+dwPositonOfData;
        return dwSectorFromClu;
}


//***********根据文件全路径获得驱动器号、文件所在目录************
//形参:   文件全路径、驱动器号指针、文件所在目录指针
//返回值:    文件所在目录的字符串长度
int CSecureDelFAT::SplitPath(const char *pFilePath,char *pDrive,char *pDir)
{
        char path_buffer;
        char drive;
        char dir;
        char fname;
        char ext;
        int i;
        int length;

        _splitpath( pFilePath, drive, dir, fname, ext);
        for(i=0;i<_MAX_DRIVE;i++)
                *(pDrive+i)=drive;
        _makepath(path_buffer,drive,dir,NULL,NULL);
        length=strlen(path_buffer);
        for(i=0;i<length-1;i++)
                *(pDir+i)=path_buffer;
        return length-1;
       
}

//***************************************************************************************



//************根据簇号读到FAT表的下一簇***************
//形参:   磁盘信息结构、关键位置信息结构、文件信息结构、指定簇号
//返回值:   文件的下一簇号
DWORD CSecureDelFAT::NextCluster(INFOFDISK DiskInfo,INFOFPOSITION PositionInfo,FILEINFO InfoOfFile,DWORD dwCluster)
{
       
        DWORD FatSartSector;
        DWORD dwReadStartSec;
        DWORD NextClu;

        WORD wSectors;
        WORD wNumOfBytesEachSec;
        WORD LowClu,HighClu;

        BYTE NextClu0,NextClu1,NextClu2,NextClu3;
       
        LPBYTE lpSectBuff;
        int IsNtOr98;
        //********************************
        wSectors=1;
        lpSectBuff=(LPBYTE)malloc(1536);
        //判断系统版本号
        IsNtOr98=NtOr98();
        //每扇区字节数
        wNumOfBytesEachSec=DiskInfo.wNumOfByteEachSec;       
        //取得FAT表起始扇区
        FatSartSector=PositionInfo.dwFatStartSec;

        if(InfoOfFile.IfFat==16)
        {
                //取得指定簇号的起始扇区数
                dwReadStartSec=FatSartSector+(dwCluster*2)/wNumOfBytesEachSec;
                if(IsNtOr98==2000)
                        ReadSectors2000(InfoOfFile.bDrive, dwReadStartSec,wSectors,lpSectBuff);
                else
                        ReadSectors(InfoOfFile.bDrive, dwReadStartSec,wSectors,lpSectBuff);


                //取得指定簇号的对应FAT表项内容
                NextClu0=*(lpSectBuff+(int)fmod(dwCluster*2,wNumOfBytesEachSec));
                NextClu1=*(lpSectBuff+(int)fmod(dwCluster*2,wNumOfBytesEachSec)+1);
               
                LowClu=MAKEWORD(NextClu0,NextClu1);
                HighClu=0x0000;
                NextClu=MAKELONG(LowClu,HighClu);
        }
        if(InfoOfFile.IfFat==32)
        {
                //取得指定簇号的起始扇区数
                dwReadStartSec=FatSartSector+(dwCluster*4)/wNumOfBytesEachSec;
                if(IsNtOr98==2000)
                        ReadSectors2000(InfoOfFile.bDrive, dwReadStartSec,wSectors,lpSectBuff);
                else
                        ReadSectors(InfoOfFile.bDrive, dwReadStartSec,wSectors,lpSectBuff);

                //取得指定簇号的对应FAT表项内容
                NextClu0=*(lpSectBuff+(int)fmod(dwCluster*4,wNumOfBytesEachSec));
                NextClu1=*(lpSectBuff+(int)fmod(dwCluster*4,wNumOfBytesEachSec)+1);
                NextClu2=*(lpSectBuff+(int)fmod(dwCluster*4,wNumOfBytesEachSec)+2);
                NextClu3=*(lpSectBuff+(int)fmod(dwCluster*4,wNumOfBytesEachSec)+3);
                LowClu=MAKEWORD(NextClu0,NextClu1);
                HighClu=MAKEWORD(NextClu2,NextClu3);
                NextClu=MAKELONG(LowClu,HighClu);
        }
                free(lpSectBuff);
                return NextClu;
}


//**********获得文件的首簇号***************
//形参:    文件信息结构、文件首簇指针
//返回值:无
void CSecureDelFAT::GetCluster2000(INFOFDISK DiskInfo,INFOFPOSITION PositionInfo,FILEINFO InfoOfFile,DWORD* FirstCluster)
{
       
        LPBYTE lpSectBuff;//缓冲区
        BY_HANDLE_FILE_INFORMATION FileInfo;

        BOOL IfResult;
       
        HANDLE hFile;

        LONG lDistanceToMove,lDistanceToMoveHigh;
    PLONG lpDistanceToMoveHigh;
        ULONGLONG MoveDistanceOfByte;

        char InfoFileName="";
       
        DWORD dwBytesToRead;
        WORD wLow,wHigh;
        DWORD dwFilePointer;
        DWORD dwSectorPosition;
        DWORD dwNumOfClu;
        DWORD dwMod;
        DWORD dwNextCluster;
        DWORD dwSectorPosition1;
        ULONGLONG BytePosition;
        ULONGLONG BytePosition1;

        ULONGLONG OffSet;
       
       
        int nmod;
        int nDirLeng;
        int i,j,k;
        int nNumOfDir;
        char cDrive;
        char cDir;
        char pDir="";
        const char *pFilePath;
        char cFilePath={0};
        DWORD dwFileFirstClu;//根目录中存放起始扇区,其它各级目录中存放首簇
        //*****************************
        pFilePath=InfoOfFile.pFilePath;
        i=0;
        strcpy(pDir,pFilePath);
        //将文件各级目录的路径赋予cFilePath
        do
        {
                strcpy(cFilePath,pDir);
                //由文件全路径得到文件目录及驱动器号
                nDirLeng=SplitPath(pDir,cDrive,cDir);
                for(k=0;k<_MAX_DIR;k++)
                        pDir=0;
                strncpy(pDir,cDir,nDirLeng);
                i+=1;
                if(nDirLeng<=2)
                {
                        strcpy(cFilePath,pDir);
                        break;
                }
        }while(1);
        //记录文件目录的级数
        nNumOfDir=i;
        //从根目录开始求各级目录的起始扇区
        for(i=nNumOfDir;i>=0;i--)
        {
                //如果是根目录
                if(i==nNumOfDir)
                {
                        //得到根目录的起始扇区
                        dwFileFirstClu=DiskIndex(DiskInfo,InfoOfFile);
                }
                else
                {
                        //取得此文件路径的信息
                        hFile=CreateFile(cFilePath,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
                        IfResult=GetFileInformationByHandle(hFile,&FileInfo);
                        CloseHandle(hFile);
                        if(IfResult==0)
                        {
                                ::MessageBox(NULL,"得到文件信息结构失败!","错误",MB_OK);
                                return;
                        }
                        else
                        {
                                //得到要读取的字节起始位置
                                MoveDistanceOfByte=(ULONGLONG)(FileInfo.nFileIndexHigh);
                                MoveDistanceOfByte=Int64ShllMod32(MoveDistanceOfByte,0x10);
                                MoveDistanceOfByte=Int64ShllMod32(MoveDistanceOfByte,0x10);
                                MoveDistanceOfByte+=(ULONGLONG)(FileInfo.nFileIndexLow);
                                //得到上级目录的起始字节位置
                                //得到上级目录的起始扇区号
                                //如果上级目录是根目录
                                if((i+1)==nNumOfDir)
                                        dwSectorPosition=dwFileFirstClu;
                                else
                                        dwSectorPosition=SectorOfFile(DiskInfo,PositionInfo,InfoOfFile,dwFileFirstClu);
                                //将扇区号转化为字节位置
                                BytePosition=(ULONGLONG)dwSectorPosition*(ULONGLONG)(DiskInfo.wNumOfByteEachSec);
                                //求本级目录项的字节位置与上级目录字节位置的距离
                                OffSet=MoveDistanceOfByte-BytePosition;
                                if(InfoOfFile.IfFat==16 && (i+1)==nNumOfDir)
                                {       
                                        MoveDistanceOfByte=MoveDistanceOfByte;
                                }
                                else
                                {
                                        //根据这个距离判断本级目录项在上级目录簇链中的序号及字节余数
                                        dwNumOfClu=(DWORD)OffSet/(DiskInfo.bNumOfSectorsEachClu*DiskInfo.wNumOfByteEachSec)+1;
                                        dwMod=(DWORD)(OffSet-OffSet/(DiskInfo.bNumOfSectorsEachClu*DiskInfo.wNumOfByteEachSec)*(DiskInfo.bNumOfSectorsEachClu*DiskInfo.wNumOfByteEachSec));
                                        //判断这个序号得到其所在簇
                                        if((i+1)==nNumOfDir)
                                        {
                                                dwNextCluster=DiskInfo.dwFirstCluOfIndex;
                                        }
                                        else
                                        {
                                                dwNextCluster=dwFileFirstClu;
                                        }
                                        for(j=1;j<(int)dwNumOfClu;j++)
                                        {
                                                dwNextCluster=NextCluster(DiskInfo,PositionInfo,InfoOfFile,dwNextCluster);
                                        }
                                        //将上级目录的首簇号转化为扇区号
                                        dwSectorPosition1=SectorOfFile(DiskInfo,PositionInfo,InfoOfFile,dwNextCluster);
                                        //将扇区号转化为字节位置
                                        BytePosition1=(ULONGLONG)dwSectorPosition1*(ULONGLONG)(DiskInfo.wNumOfByteEachSec);
                                        //将此字节位置加上前面的那个字节余数即为此目录项的正确字节位置
                                        MoveDistanceOfByte=BytePosition1+dwMod;
                                }
                                //下面求此文件的首簇
                                lpSectBuff=(LPBYTE)malloc(1024);
                                if(lpSectBuff==NULL)
                                {
                                        ::MessageBox( NULL, "开辟内存失败", "错误", MB_OK );
                                        return;
                                }
                                dwBytesToRead=0x200;
                                nmod=(int)(MoveDistanceOfByte-MoveDistanceOfByte/512*512);
                                MoveDistanceOfByte=MoveDistanceOfByte/512*512;

                                lDistanceToMove=(LONG)MoveDistanceOfByte;

                                MoveDistanceOfByte=Int64ShrlMod32(MoveDistanceOfByte,0x10);
                                MoveDistanceOfByte=Int64ShrlMod32(MoveDistanceOfByte,0x10);
                                lDistanceToMoveHigh=(LONG)MoveDistanceOfByte;
       
                                lpDistanceToMoveHigh=&lDistanceToMoveHigh;
               
                                //从得到的字节起始位置读512个字节
                                //得到要读取的驱动器
                                strcat(InfoFileName,"\\\\.\\");
                                InfoFileName=InfoOfFile.bDrive-1+'A';
                                strcat(InfoFileName,":");
                                //将要读取的驱动器当作一文件打开
                                hFile=CreateFile(InfoFileName,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,0,OPEN_EXISTING,0,0);
                                //将InfoFileName清零
                                for(k=0;k<20;k++)
                                        InfoFileName=0;
                                //设置文件指针,对驱动器来说就是起始位置
                                dwFilePointer=SetFilePointer(hFile,lDistanceToMove,lpDistanceToMoveHigh, FILE_BEGIN);
                                //读取驱动器上数据
                                IfResult=ReadFile(hFile,lpSectBuff,dwBytesToRead,&dwBytesToRead,NULL);
                                CloseHandle(hFile);
                                if(IfResult==0)
                                {
                                        ::MessageBox(NULL,"读取失败!","错误",MB_OK);
                                        return;
                                }
                                else
                                {
                                        wLow=MAKEWORD((*(lpSectBuff+26+nmod)),(*(lpSectBuff+27+nmod)));
                                        wHigh=MAKEWORD((*(lpSectBuff+20+nmod)),(*(lpSectBuff+21+nmod)));
                                        *FirstCluster=MAKELONG(wLow,wHigh);
                                }
                                free(lpSectBuff);
                                //将本级目录的首簇号转化为扇区号
                                dwFileFirstClu=*FirstCluster;
                        }
                }
        }

}
//************取得文件(或目录)首簇号的基本函数*************
//形参:   文件全路径、文件首簇指针
//返回值:成功返回1,否则返回0
BOOL CSecureDelFAT::GetFirstCluster(LPCTSTR lpFileName,DWORD* FirstCluster)
{
        BOOL fResult;
        DWORD cb;
        HANDLE hDev;
        DIOC_REGISTERS reg={0};
        reg.reg_EAX=0x440d;
        reg.reg_EBX=0x0000;
        reg.reg_ECX=0x4871;
        reg.reg_EDX=(DWORD)lpFileName;
       
        hDev=::CreateFile("\\\\.\\vwin32",0,0,NULL,0,FILE_FLAG_DELETE_ON_CLOSE,NULL);
        fResult=::DeviceIoControl(hDev,VWIN32_DIOC_DOS_IOCTL,
                                ®,sizeof(reg),®,sizeof(reg),&cb,0);

        fResult=fResult && !(reg.reg_Flags & CARRY_FLAG);
        if(fResult)
                *FirstCluster=MAKELONG((WORD)reg.reg_EAX,(WORD)reg.reg_EDX);
        CloseHandle(hDev);       
        return fResult;

}

//**********获得文件(或目录)的首簇号***************
//形参:    文件信息结构、文件首簇指针
//返回值:无
void CSecureDelFAT::GetCluster(FILEINFO InfoOfFile,DWORD* pFirstCluster)
{
        BOOL IfSucForLock,IfSucForGetClu,IfSucForUnlock;
        BYTE Level;
        DWORD Permission;
               
        Level=1;
        Permission=0;
               
        //调用锁定分区函数
        IfSucForLock=LockVolume(InfoOfFile.bDrive,Permission,Level);
        if(IfSucForLock)
        {
                //如果锁定成功就接着调用取得文件首簇的函数
                IfSucForGetClu=GetFirstCluster(InfoOfFile.pFilePath,pFirstCluster);
                //如果取得文件首簇,就显示出来,否则就显示出错
                if(!IfSucForGetClu)
                {
                       
                        ::MessageBox(NULL,"获得文件首簇失败,可能是存放文件的文件夹已不存在,请先建立文件夹","警告!",MB_OK);
                        return;
                }
                //解锁
                IfSucForUnlock=UnlockVolume(InfoOfFile.bDrive);
                if(!IfSucForUnlock)
                {
                       
                        ::MessageBox(NULL,"解锁失败!","警告!",MB_OK);
                        return;
                }
        }
        else
        {
               
                ::MessageBox(NULL,"加锁失败!","警告!",MB_OK);
                return;
        }

}
//*******************************************************************************************





//*************文件(或目录)在其目录表中位置(fat32的所有目录或FAT16的非根目录)*********************
//形参:      磁盘信息结构、关键位置信息结构、文件信息结构、文件所在目录信息结构、
//            文件ms-dos目录项所在簇的起始扇区指针、是否目录项跨簇(如果跨就返回所跨两簇的前一簇号,否则返回0)
//返回值:   从文件ms-dos目录项所在簇的起始扇区算起,文件ms-dos目录项的位置
DWORD CSecureDelFAT::FilePositionFat32(INFOFDISK DiskInfo,INFOFPOSITION PositionInfo,
                                                FILEINFO InfoOfFile,FILEINFO InfoOfDir,
                                                DWORD *dwStartSec,DWORD *pIfCrossCluster)
{
       
        DWORD dwStartSectorOld;
        DWORD dwStartSector;
        DWORD dwStartClu;
        DWORD dwOldCluster;
        DWORD dwFilePosition;//返回值

        WORD wLowFirstClu,wHighFirstClu,wLow,wHigh;
        WORD wNumOfBytesEachSec;

        BYTE bFileProperty,bFileProperty1;
        BYTE bIfDelete;
        BYTE bNumOfSectorsEachClu;

        LPBYTE lpSectBuff;
       
        BOOL IfSuccessForRead,IfFind;
       
        int i;
        int nIf0f;
        int nIfCrossClu;
        int IsNtOr98;
        //*****************************
        //判断系统的版本号
        IsNtOr98=NtOr98();
        //得到每扇区的字节数及每簇扇区数
        wNumOfBytesEachSec=DiskInfo.wNumOfByteEachSec;       
        bNumOfSectorsEachClu=DiskInfo.bNumOfSectorsEachClu;
        //分离文件首簇号的高位与低位
        wLowFirstClu=(WORD)(InfoOfFile.dwFileFirstClu);
        wHighFirstClu=(WORD)(InfoOfFile.dwFileFirstClu>>16);

        IfFind=0;
        nIf0f=0;
        nIfCrossClu=0;
        bFileProperty=0;
        //得到文件所在目录的起始扇区
        dwStartSector=InfoOfDir.dwFileStartSec;
        dwStartSectorOld=dwStartSector;
        //文件所在目录首簇
        dwStartClu=InfoOfDir.dwFileFirstClu;
        //分配内存
        lpSectBuff=(LPBYTE)malloc(1024);
        do
        {
                //从起始扇区开始读取一个扇区
                if(IsNtOr98==2000)
                        IfSuccessForRead=ReadSectors2000(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff);
                else
                        IfSuccessForRead=ReadSectors(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff);
                if(IfSuccessForRead)
                {
                        for(i=0;i<(wNumOfBytesEachSec/32);i++)
                        {
                                bFileProperty1=bFileProperty;
                                wLow=MAKEWORD((*(lpSectBuff+26+i*32)),(*(lpSectBuff+27+i*32)));
                                wHigh=MAKEWORD((*(lpSectBuff+20+i*32)),(*(lpSectBuff+21+i*32)));
                                bFileProperty=*(lpSectBuff+11+i*32);
                                bIfDelete=*(lpSectBuff+i*32);
                                //判断此目录项上一目录项是否长文件名附加目录项
                                if(bFileProperty1==0x0f)
                                        nIf0f=1;
                                else
                                {
                                        nIf0f=0;
                                        nIfCrossClu=0;
                                }
                                //**************************
                                if((wLow==wLowFirstClu) && (wHigh==wHighFirstClu) && (bFileProperty!=0x0f) && (bIfDelete!=0xe5))
                                {
                                        if(nIf0f==1 && nIfCrossClu==1)
                                                *pIfCrossCluster=dwOldCluster;//本目录项跨簇
                                        else
                                                *pIfCrossCluster=0;
                                        IfFind=1;
                                        dwFilePosition=(dwStartSector-dwStartSectorOld)*(wNumOfBytesEachSec/32)+i;
                                        *dwStartSec=dwStartSectorOld;//得到另一返回值
                                        break;
                                }
                        }
                }
                else
                {
                        ::MessageBox(NULL,"读取失败!","警告!",MB_OK);
                        return NULL;
                }
                //如果在一个扇区中没找到就将起始扇区加1
                dwStartSector+=1;
                //判断扇区数目增加是否已经超过一簇
                if((dwStartSector-dwStartSectorOld)>=bNumOfSectorsEachClu)
                        nIfCrossClu=1;
                //如果已经超簇,而且还没找到文件目录项
                if((dwStartSector-dwStartSectorOld)>=bNumOfSectorsEachClu && IfFind==0)
                {
                        //将上一簇先保存在一暂时变量中
                        dwOldCluster=dwStartClu;
                        //得到下一簇
                        dwStartClu=NextCluster(DiskInfo,PositionInfo,InfoOfFile,dwStartClu);
                        //由簇号得到扇区号
                        dwStartSector=SectorOfFile(DiskInfo,PositionInfo,InfoOfFile,dwStartClu);
                        //将本簇的起始扇区保存在一暂时变量中
                        dwStartSectorOld=dwStartSector;
                }
        }while(!IfFind);
        free(lpSectBuff);
        return dwFilePosition;
}

//***********文件(或目录)在其目录表中位置(fat16的根目录)*****************
//形参:   驱动器号、文件系统格式、磁盘基本信息数据结构、
//            文件所在目录起始扇区、文件首簇号
//返回值:   从文件所在目录起始扇区算起,文件ms-dos目录项的位置
DWORD CSecureDelFAT::FilePosition(BYTE bDrive,INFOFDISK DiskInfo,DWORD dwStartSector,
                                   DWORD dwFirstClu)
{
       
        DWORD dwStartSectorOld;
        DWORD dwFilePosition;

        WORD wLowFirstClu,wHighFirstClu,wLow,wHigh;
        WORD wNumOfBytesEachSec;
       
        LPBYTE lpSectBuff;

        BOOL IfSuccessForRead,IfFind;
       
        BYTE bFileProperty;
        BYTE bIfDelete;
        int i;
        int IsNtOr98;
        //*************************

        //判断系统版本号
        IsNtOr98=NtOr98();
        //每扇区字节数
        wNumOfBytesEachSec=DiskInfo.wNumOfByteEachSec;       
        //分离文件首簇号的高位与低位
        wLowFirstClu=(WORD)dwFirstClu;
        wHighFirstClu=(WORD)(dwFirstClu>>16);

        IfFind=0;
       
        //将文件目录起始扇区保存在一暂时变量中
        dwStartSectorOld=dwStartSector;
        //分配内存
        lpSectBuff=(LPBYTE)malloc(1024);
        do
        {
                //从起始扇区开始读取一个扇区
                if(IsNtOr98==2000)
                        IfSuccessForRead=ReadSectors2000(bDrive,dwStartSector,1,lpSectBuff);
                else
                        IfSuccessForRead=ReadSectors(bDrive,dwStartSector,1,lpSectBuff);
                if(IfSuccessForRead)
                {
                        for(i=0;i<(wNumOfBytesEachSec/32);i++)
                        {
                                wLow=MAKEWORD((*(lpSectBuff+26+i*32)),(*(lpSectBuff+27+i*32)));
                                wHigh=MAKEWORD((*(lpSectBuff+20+i*32)),(*(lpSectBuff+21+i*32)));
                                bFileProperty=*(lpSectBuff+11+i*32);
                                bIfDelete=*(lpSectBuff+i*32);
                                if((wLow==wLowFirstClu) && (wHigh==wHighFirstClu) && (bFileProperty!=0x0f) && (bIfDelete!=0xe5))
                                {
                                        IfFind=1;
                                        dwFilePosition=(dwStartSector-dwStartSectorOld)*16+i;
                                        break;
                                }
                        }
                }
                else
                {
                        ::MessageBox(NULL,"读取失败!","警告!",MB_OK);
                        return NULL;
                }
                //如果在一个扇区中没有找到文件目录项就将起始扇区加1
                dwStartSector+=1;
        }while(!IfFind);
        free(lpSectBuff);
        return dwFilePosition;
}


//**************文件共占有几个目录项****************
//形参:    磁盘信息结构、关键位置信息结构、文件信息结构、
//          文件ms-dos目录项所在扇区、文件ms-dos目录项距给定扇区的字节偏移量
//返回值:   文件共占有的目录项数,包括ms-dos目录项
int CSecureDelFAT::NumOfLongfile(INFOFDISK DiskInfo,INFOFPOSITION PositionInfo,
                                  FILEINFO InfoOfFile,DWORD dwStartSector,
                                  int nFilePosOffStartSector)
{
        LPBYTE lpSectBuff;
       
        BYTE bNumOfSectorsEachClu;

        WORD wNumOfBytesEachSec;
       
        DWORD dwStartSector1;

        int i;
        int IsNtOr98;
        //*************************
       
        i=1;
        lpSectBuff=(LPBYTE)malloc(1024);
        //判断操作系统版本号
        IsNtOr98=NtOr98();
        //每扇区字节数
        wNumOfBytesEachSec=DiskInfo.wNumOfByteEachSec;       
        //每簇扇区数
        bNumOfSectorsEachClu=DiskInfo.bNumOfSectorsEachClu;
       
        //如果起始扇区不是第0个扇区就从前一扇区开始读取2个扇区
        if(dwStartSector>=1)
        {       
                //如果文件目录项没有跨簇
                if(InfoOfFile.dwIfCrossClu==0)
                {
                        //从起始扇区的前一扇区读取两个扇区
                        if(IsNtOr98==2000)
                                ReadSectors2000(InfoOfFile.bDrive,dwStartSector-1,2,lpSectBuff);
                        else
                                ReadSectors(InfoOfFile.bDrive,dwStartSector-1,2,lpSectBuff);
                        //接着将文件目录项的字节偏移量相应增加
                        nFilePosOffStartSector+=wNumOfBytesEachSec;
                        //根据属性字节来检查共有几个目录项
                        do
                        {
                                if(*(lpSectBuff+nFilePosOffStartSector-i*32+11)!=0x0f)
                                        break;
                                else
                                        i+=1;
                        }while(1);
                }
                //如果跨簇
                else
                {
                        //根据文件信息结构中保存的文件目录项所跨簇得到前一簇的起始扇区
                        dwStartSector1=SectorOfFile(DiskInfo,PositionInfo,InfoOfFile,InfoOfFile.dwIfCrossClu);
                        //得到前一簇的最后一个扇区作为起始扇区
                        dwStartSector1=dwStartSector1+bNumOfSectorsEachClu-1;
                        //从起始扇区开始读取一簇
                        if(IsNtOr98==2000)
                                ReadSectors2000(InfoOfFile.bDrive,dwStartSector1,1,lpSectBuff);
                        else
                                ReadSectors(InfoOfFile.bDrive,dwStartSector1,1,lpSectBuff);
                        //从最靠近文件ms-dos目录项起始扇区开始读取一簇
                        if(IsNtOr98==2000)
                                ReadSectors2000(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff+512);
                        else
                                ReadSectors(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff+512);
                        //相应增加文件目录项的字节偏移量
                        nFilePosOffStartSector+=wNumOfBytesEachSec;
                        //根据偏移量来检查共有几个目录项
                        do
                        {
                                if(*(lpSectBuff+nFilePosOffStartSector-i*32+11)!=0x0f)
                                        break;
                                else
                                        i+=1;
                        }while(1);
                }
        }
        //如果起始扇区是0扇区
        else
        {
                //从起始扇区开始读取一个扇区
                if(IsNtOr98==2000)
                        ReadSectors2000(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff);
                else
                        ReadSectors(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff);
                //根据偏移量来检查共有几个目录项
                do
                {
                        if(*(lpSectBuff+nFilePosOffStartSector-i*32+11)!=0x0f)
                                break;
                        else
                                i+=1;
                }while(1);
        }
        free(lpSectBuff);
        return i;
}

//***********判断文件所占有的目录项是否跨扇区************
//形参:    磁盘信息结构、关键位置信息结构、文件信息结构、
//          文件ms-dos目录项所在扇区、文件ms-dos目录项距给定扇区的字节偏移量
//返回值:如果跨扇区返回最前面的目录项在前一扇区的字节偏移量
//          如果没有跨扇区就返回0;
int CSecureDelFAT::IfCrossSector(INFOFDISK DiskInfo,INFOFPOSITION PositionInfo,
                                  FILEINFO InfoOfFile,DWORD dwStartSector,
                                  int nFilePosOffStartSector)
{
        int NumOfFile;//文件所占有的目录项数
        int OffSet;
       
        WORD wNumOfBytesEachSec;
        //************************
        //每扇区字节数
        wNumOfBytesEachSec=DiskInfo.wNumOfByteEachSec;       
        //文件目录项的数目
        NumOfFile=NumOfLongfile(DiskInfo,PositionInfo,InfoOfFile,dwStartSector,nFilePosOffStartSector);
       
        OffSet=NumOfFile-(nFilePosOffStartSector/32)-1;

        if(OffSet>0)
                return wNumOfBytesEachSec-OffSet*32;
        else
                return 0;
}


//***********在文件中修改目录项****************
//形参:   驱动器号、文件系统格式、磁盘基本信息数据结构
//         文件全路径、文件目录项所在簇的起始扇区
//            文件ms-dos目录项在本簇中位置、文件首簇号
//返回值:    无
void CSecureDelFAT::FileIndex(INFOFDISK DiskInfo,INFOFPOSITION PositionInfo,
                               FILEINFO InfoOfFile,FILEINFO InfoOfDir)
{
        WORD wNumOfBytesEachSec;
        DWORD dwStartSector;
        LPBYTE lpSectBuff;
        int i,j;
        int IfCrossSec;
        int nFilePosOffStartSector;
        int NumOfFile;
        int IsNtOr98;
        char FullPath={0};
        char DustName="";
        char InfoFileName="";

        //分配一段内存
        lpSectBuff=(LPBYTE)malloc(1024);

        //判断系统的版本号
        IsNtOr98=NtOr98();
        //每扇区字节数
        wNumOfBytesEachSec=DiskInfo.wNumOfByteEachSec;
        //得到要读取的起始扇区
        dwStartSector=InfoOfDir.dwFileStartSec+(InfoOfFile.dwFileIndexPosition*32)/wNumOfBytesEachSec;
        //文件ms-dos目录项在起始扇区中的字节偏移量
        nFilePosOffStartSector=(int)fmod(InfoOfFile.dwFileIndexPosition*32,wNumOfBytesEachSec);
        //文件共有几个目录项
       NumOfFile=NumOfLongfile(DiskInfo,PositionInfo,InfoOfFile,dwStartSector,
                                     nFilePosOffStartSector);
       //判断该文件的所有目录项是否跨扇区
        IfCrossSec=IfCrossSector(DiskInfo,PositionInfo,InfoOfFile,dwStartSector,
                                     nFilePosOffStartSector);

        if(IfCrossSec>0)//如果跨了扇区
        {
                //从起始扇区的前一扇区开始读2个扇区
                if(IsNtOr98==2000)
                        ReadSectors2000(InfoOfFile.bDrive,dwStartSector-1,2,lpSectBuff);
                else
                        ReadSectors(InfoOfFile.bDrive,dwStartSector-1,2,lpSectBuff);

                //修改文件的目录项
                for(i=0;i<NumOfFile;i++)
                {
                        for(j=0;j<32;j++)
                        {       
                                *(lpSectBuff+IfCrossSec+i*32+j)=0x00;
                                       
                        }       
                        *(lpSectBuff+IfCrossSec+i*32)=0xe5;
                       
                }
                //将修改后的目录表存入磁盘
                if(IsNtOr98==2000)
                        WriteSectors2000(InfoOfFile.bDrive,dwStartSector-1,2,lpSectBuff);
                else
                        WriteSectors(InfoOfFile.bDrive,dwStartSector-1,2,lpSectBuff);
               
        }
        else
        {
                //从起始扇区开始读一个扇区
                if(IsNtOr98==2000)
                        ReadSectors2000(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff);
                else
                        ReadSectors(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff);
               
                //修改文件的目录项
                for(i=0;i<NumOfFile;i++)
                {
                        for(j=0;j<32;j++)
                        {       
                                *(lpSectBuff+nFilePosOffStartSector-(NumOfFile-1)*32+i*32+j)=0x00;
                               
                        }       
                        *(lpSectBuff+nFilePosOffStartSector-(NumOfFile-1)*32+i*32)=0xe5;
               
                }
               
                //将修改后的目录表存入磁盘
                if(IsNtOr98==2000)
                        WriteSectors2000(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff);
                else
                        WriteSectors(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff);
                               
        }
        free(lpSectBuff);
               
       
}


//************在文件中修改目录项*****************
//形参:   驱动器号、文件系统格式、磁盘基本信息数据结构
//         文件全路径、文件目录项所在簇的起始扇区
//            文件ms-dos目录项在本簇中位置、文件所在目录的起始扇区
//             文件首簇号
//返回值:    无
void CSecureDelFAT::FileIndex32(INFOFDISK DiskInfo,INFOFPOSITION PositionInfo,
                               FILEINFO InfoOfFile,FILEINFO InfoOfDir)
{
        char FullPath={0};
        WORD wNumOfBytesEachSec;
        BYTE bNumOfSectorsEachClu;
        DWORD dwStartSector,dwBefore;
        LPBYTE lpSectBuff;
        int nFilePosOffStartSector;
        int IfCrossSec;
        int NumOfFile;
        int Reserved;
        int IsNtOr98;
        int i,j;

        lpSectBuff=(LPBYTE)malloc(1024);
        Reserved=0;

        //判断系统版本号
        IsNtOr98=NtOr98();
        //得到每扇区的字节数
        wNumOfBytesEachSec=DiskInfo.wNumOfByteEachSec;
        bNumOfSectorsEachClu=DiskInfo.bNumOfSectorsEachClu;
        //得到要读取的起始扇区
        dwStartSector=InfoOfFile.dwSecNearFileIndex+(InfoOfFile.dwFileIndexPosition*32)/wNumOfBytesEachSec;
       
        //文件ms-dos目录项在起始扇区中的字节偏移量
        nFilePosOffStartSector=(int)fmod(InfoOfFile.dwFileIndexPosition*32,wNumOfBytesEachSec);
        //文件共有几个目录项
        NumOfFile=NumOfLongfile(DiskInfo,PositionInfo,InfoOfFile,dwStartSector,
                                     nFilePosOffStartSector);
        InfoOfFile.nNumOfFileIndex=NumOfFile;
        //判断该文件的所有目录项是否跨扇区
        IfCrossSec=IfCrossSector(DiskInfo,PositionInfo,InfoOfFile,dwStartSector,
                                     nFilePosOffStartSector);

        if(IfCrossSec>0)//如果跨了扇区
        {
                if(InfoOfFile.dwIfCrossClu==0)
                //从起始扇区的前一扇区开始读2个扇区
                {
                        if(IsNtOr98==2000)
                                ReadSectors2000(InfoOfFile.bDrive,dwStartSector-1,2,lpSectBuff);               
                        else
                                ReadSectors(InfoOfFile.bDrive,dwStartSector-1,2,lpSectBuff);               
                }
                else
                {
                        dwBefore=SectorOfFile(DiskInfo,PositionInfo,InfoOfFile,InfoOfFile.dwIfCrossClu);
                        dwBefore=dwBefore+bNumOfSectorsEachClu-1;
                        if(IsNtOr98==2000)
                        {
                                ReadSectors2000(InfoOfFile.bDrive,dwBefore,1,lpSectBuff);               
                                ReadSectors2000(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff+512);               
                        }
                        else
                        {
                                ReadSectors(InfoOfFile.bDrive,dwBefore,1,lpSectBuff);               
                                ReadSectors(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff+512);               
                        }
                }
               
                //修改文件的目录项
                for(i=0;i<NumOfFile;i++)
                {
                        for(j=0;j<32;j++)
                        {       
                                *(lpSectBuff+IfCrossSec+i*32+j)=0x00;
                                       
                        }       
                        *(lpSectBuff+IfCrossSec+i*32)=0xe5;
                       
                }
                if(InfoOfFile.dwIfCrossClu==0)
                {
                        //将修改后的目录表存入磁盘
                        if(IsNtOr98==2000)
                                WriteSectors2000(InfoOfFile.bDrive,dwStartSector-1,2,lpSectBuff);
                        else
                                WriteSectors(InfoOfFile.bDrive,dwStartSector-1,2,lpSectBuff);
                }
                else
                {
                        if(IsNtOr98==2000)
                        {
                                WriteSectors2000(InfoOfFile.bDrive,dwBefore,1,lpSectBuff);
                                WriteSectors2000(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff+512);
                        }
                        else
                                WriteSectors(InfoOfFile.bDrive,dwBefore,1,lpSectBuff);
                                WriteSectors(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff+512);
                }
        }
        else //如果没有跨扇区
        {
                //从起始扇区开始读一个扇区
                if(IsNtOr98==2000)
                        ReadSectors2000(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff);
                else
                        ReadSectors(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff);
       

                //修改文件的目录项
                for(i=0;i<NumOfFile;i++)
                {
                        for(j=0;j<32;j++)
                        {       
                                *(lpSectBuff+nFilePosOffStartSector-(NumOfFile-1)*32+i*32+j)=0x00;
                                       
                        }       
                        *(lpSectBuff+nFilePosOffStartSector-(NumOfFile-1)*32+i*32)=0xe5;
                       
                }
               
                //将修改后的目录表存入磁盘
                if(IsNtOr98==2000)
                        WriteSectors2000(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff);
                else
                        WriteSectors(InfoOfFile.bDrive,dwStartSector,1,lpSectBuff);

        }

        free(lpSectBuff);

}

//************************隐藏文件***********************
//形参:    驱动器基本信息结构体,文件信息结构体,文件所在目录信息结构体
//返回值:无
void CSecureDelFAT::DeleteFile(INFOFDISK DiskInfo,INFOFPOSITION PositionInfo,
                          FILEINFO InfoOfFile,FILEINFO InfoOfDir)
{
       
        char cDesktop="";
        char cRecycled="";
        char HomeFileName="";
        char InfoFileName="";
        char RecycledName="";
        char DriveName="";

        int IsNtOr98;
        char pDir="";
        __int64FileLen=0;

        DWORD dwFileFirstCluster;//文件首簇
        DWORD dwDirFirstCluster;//目录首簇
        DWORD dwFilePosition;//文件在目录表中位置
        DWORD dwStartSecOfIndx;//目录表起始扇区
        DWORD dwStartSec;//最靠近目标文件的要读取的起始扇区
        DWORD dwFirstCluOfIndex;//根目录的首簇

        DWORD dwIfCrossClu;
        INFOFDISK pDiskInfo={0};

        //判断系统版本号
        IsNtOr98=NtOr98();
        //驱动器名
        DriveName=InfoOfFile.bDrive-1+'A';
        strcat(DriveName,":\\");
       
        //取得文件起始扇区
        if(IsNtOr98==2000)
                GetCluster2000(DiskInfo,PositionInfo,InfoOfFile,&dwFileFirstCluster);
        else
                GetCluster(InfoOfFile,&dwFileFirstCluster);

        InfoOfFile.dwFileFirstClu=dwFileFirstCluster;
       
        InfoOfFile.dwFileStartSec=SectorOfFile(DiskInfo,PositionInfo,InfoOfFile,dwFileFirstCluster);
       
       
        //如果文件所在目录不是根目录
        if(strlen(InfoOfFile.pFileDirPath)>3)
        {
                //取得文件所在目录的首簇号
                if(IsNtOr98==2000)
                        GetCluster2000(DiskInfo,PositionInfo,InfoOfDir,&dwDirFirstCluster);
                else
                        GetCluster(InfoOfDir,&dwDirFirstCluster);

                InfoOfDir.dwFileFirstClu=dwDirFirstCluster;
                //取得文件所在目录的起始扇区
                dwStartSecOfIndx=SectorOfFile(DiskInfo,PositionInfo,
                                                  InfoOfDir,dwDirFirstCluster);
                InfoOfDir.dwFileStartSec=dwStartSecOfIndx;

                //************************************************

                //取得文件目录项在其目录中的位置
                dwFilePosition=FilePositionFat32(DiskInfo,PositionInfo,InfoOfFile,
                                                     InfoOfDir,&dwStartSec,&dwIfCrossClu);
                InfoOfFile.dwFileIndexPosition=dwFilePosition;
                InfoOfFile.dwSecNearFileIndex=dwStartSec;
                InfoOfFile.dwIfCrossClu=dwIfCrossClu;

                //修改目录项及fat表
                FileIndex32(DiskInfo,PositionInfo,InfoOfFile,InfoOfDir);
               
        }
        //如果文件所在目录是根目录
        else
        {
                //文件所在驱动器根目录首簇
                dwFirstCluOfIndex=DiskInfo.dwFirstCluOfIndex;
                InfoOfDir.dwFileFirstClu=dwFirstCluOfIndex;
                //得到文件所在目录的起始扇区
                dwStartSecOfIndx=DiskIndex(DiskInfo,InfoOfFile);
                InfoOfDir.dwFileStartSec=dwStartSecOfIndx;

                //由于根目录对FAT16、FAT32有不同,所以在此分开考虑
                if(InfoOfFile.IfFat==32)
                {
                        //取得文件目录项在其目录中的位置
                        dwFilePosition=FilePositionFat32(DiskInfo,PositionInfo,InfoOfFile,
                                                     InfoOfDir,&dwStartSec,&dwIfCrossClu);
                        InfoOfFile.dwFileIndexPosition=dwFilePosition;
                        InfoOfFile.dwSecNearFileIndex=dwStartSec;
                        InfoOfFile.dwIfCrossClu=dwIfCrossClu;

                        //修改目录项及fat表
                        FileIndex32(DiskInfo,PositionInfo,InfoOfFile,InfoOfDir);

                }
                else
                {
                        //取得文件目录项在其目录中的位置
                        dwFilePosition=FilePosition(InfoOfFile.bDrive,DiskInfo,dwStartSecOfIndx,
                                                        dwFileFirstCluster);
                        InfoOfFile.dwFileIndexPosition=dwFilePosition;
                        InfoOfFile.dwIfCrossClu=0;

                        //在文件中保存要隐藏的文件的目录项、fat表链及其它一些信息,最后修改目录项及fat表
                        FileIndex(DiskInfo,PositionInfo,InfoOfFile,InfoOfDir);

                }
        }
}

BOOL CSecureDelFAT::SecureDelFatFile(CString FileName)
{
        //文件或目录路径
        CString        m_File=FileName;
        FILEINFO InfoOfFile;//文件相关信息结构体
        INFOFDISK DiskInfo={0};//文件所在驱动器基本信息结构体
        FILEINFO InfoOfDir;//文件所在目录相关信息结构体
        INFOFPOSITION PositionInfo;//文件所在驱动器一些关键位置结构体
        int nDirLeng;//文件所在目录全路径的字符长度
        char cDrive;
        char cDir;
        char pDir="";
        char cDesktop="";
        char cRecycled="";
        char cFileName1="";
        char cFileName2="";
        //从文件全路径得到文件所在驱动器号及文件所在目录全路径
        nDirLeng=SplitPath(m_File,cDrive,cDir);
        strncpy(pDir,cDir,nDirLeng);

        InfoOfFile.pFilePath=m_File;
        InfoOfFile.bDrive=(BYTE)cDrive-'A'+1;
        InfoOfFile.pFileDirPath=&pDir;
        InfoOfDir.bDrive=(BYTE)cDrive-'A'+1;
        InfoOfDir.pFilePath=&pDir;
        //判断文件所在驱动器的文件系统类别
        InfoOfFile.IfFat=IfFatX(InfoOfFile.bDrive);
        InfoOfDir.IfFat=IfFatX(InfoOfFile.bDrive);
        if(InfoOfFile.IfFat!=16 && InfoOfFile.IfFat!=32 )
        {
                ::MessageBox(NULL,"文件所在驱动器不是FAT16/32文件系统","错误",MB_OK);
                return false;
        }
        //得到文件所在驱动器的基本信息
        fDiskInfo(InfoOfFile,&DiskInfo);
        //得到FAT表、备份FAT表位置
        PositionInfo.dwFatStartSec=FatStartSec(DiskInfo);
        PositionInfo.dwBakFatStartSec=FatBakStartSec(DiskInfo);
        //隐藏文件
        DeleteFile(DiskInfo,PositionInfo,InfoOfFile,InfoOfDir);
        return true;
}

/////////////////////////////////////////////////////////////////////////////
// 函数名:WipeFileContent(LPCTSTR pFilePath)
// 参数列表:
// 函数功能:该函数主要用于将需要删除的文件全部清零
/////////////////////////////////////////////////////////////////////////////
BOOL CSecureDelFAT::WipeFileContent(CString strfilename)
{
        char        filename;
        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;
                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 CSDeleteFATDlg::OnButtonSecuredel()
{
        // TODO: Add your control notification handler code here
        if(m_filename!="")
        {
                //采用全部清零的方法删除文件的内容
                m_SdelFAT.WipeFileContent(m_filename);
                //设置文件的长度为零
                FILE *fp=fopen(m_filename,"w");
                fclose(fp);
                //        删除该文件的文件名       
                m_SdelFAT.SecureDelFatFile(m_filename);       
                AfxMessageBox("安全删除完毕!");
                m_filename="";
        }
        UpdateData(false);
       
}



作者:yincheng01 发表于2011-12-15 7:57:12 原文链接

页: [1]
查看完整版本: [原]VC++信息安全编程(17)安全删除FAT磁盘数据文件