📄 wffat.c
字号:
#include "precomp.h"
void WritePattern(void* buf, DWORD* pattern, long size)
{
char* buffer = (char*)buf;
int patternSize = sizeof(DWORD) * 256;
if(size <= patternSize)
{
memcpy(buffer, pattern, size);
}
else
{
int passes = size / patternSize;
int remainder = size % patternSize;
int i;
for(i = 0; i < passes; i++)
{
memcpy(buffer + (i * patternSize), pattern, patternSize);
}
memcpy(buffer + (i * patternSize), pattern, remainder);
}
}
DWORD ClusterToSector(VOLINFO *vi,DWORD Cluster)
{
return ((Cluster-0x2)*vi->sectors_per_clus)+vi->dwStartSector;
}
int ReadAbsoluteSectors( HANDLE hDev,int volume, DWORD start_sector,
WORD num_sectors, LPBYTE pBuf )
{
DIOC_REGISTERS reg;
DISKIO di;
BOOL bResult;
DWORD cb;
reg.reg_EAX = volume-1; // zero-based volume number
reg.reg_EBX = (DWORD)&di;
reg.reg_ECX = 0xffff; // use DISKIO structure
reg.reg_Flags = 1; // preset the carry flag
di.diStartSector = start_sector;
di.diSectors = num_sectors;
di.diBuffer = (DWORD)pBuf;
bResult = DeviceIoControl( hDev, VWIN32_DIOC_DOS_INT25,
®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 );
if ( !bResult || (reg.reg_Flags & 1) ) return -1;
return 0;
}
BOOL WriteAbsoluteSectors(HANDLE hDev,
int bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpSectBuff)
{
BOOL fResult;
DWORD cb;
DIOC_REGISTERS reg = {0};
DISKIO di = {0};
// if(bDrive!=1)
// return FALSE;
di.diStartSector = dwStartSector;
di.diSectors = wSectors;
di.diBuffer = (DWORD)lpSectBuff;
reg.reg_EAX = bDrive - 1; // Int 26h drive numbers are 0-based.
reg.reg_EBX = (DWORD)&di;
reg.reg_ECX = 0xFFFF; // use DISKIO struct
fResult = DeviceIoControl(hDev, VWIN32_DIOC_DOS_INT26,
®, sizeof(reg),
®, sizeof(reg), &cb, 0);
// Determine if the DeviceIoControl call and the write succeeded.
fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);
return fResult;
}
int ReadAbsoluteSectors32( HANDLE hDev,int volume, DWORD start_sector,
WORD num_sectors, LPBYTE pBuf )
{
DIOC_REGISTERS reg;
DISKIO di;
BOOL bResult;
DWORD cb;
reg.reg_EAX = 0x7305; // Ext_ABSDiskReadWrite
reg.reg_EBX = (DWORD)&di;
reg.reg_ECX = 0xffff; // use DISKIO structure
reg.reg_EDX = volume; // one-based volume number
reg.reg_ESI = 0; // READ operation
reg.reg_Flags = 0; // preset the carry flag
di.diStartSector = start_sector;
di.diSectors = num_sectors;
di.diBuffer = (DWORD)pBuf;
bResult = DeviceIoControl( hDev, VWIN32_DIOC_DOS_DRIVEINFO,
®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 );
if ( /*!bResult ||*/ (reg.reg_Flags & 1) ) return -1;
return 0;
}
BOOL WriteAbsoluteSectors32(HANDLE hDev,
int bDrive,
DWORD dwStartSector,
WORD wSectors,
LPBYTE lpSectBuff)
{
BOOL fResult;
DWORD cb;
DIOC_REGISTERS reg = {0};
DISKIO di;
// if(bDrive!=1)
// return FALSE;
di.diStartSector = dwStartSector;
di.diSectors = wSectors;
di.diBuffer = (DWORD)lpSectBuff;
reg.reg_EAX = 0x7305; // Ext_ABSDiskReadWrite
reg.reg_EBX = (DWORD)&di;
reg.reg_ECX = -1;
reg.reg_EDX = bDrive; // Int 21h, fn 7305h drive numbers are 1-based
reg.reg_ESI = 0x6001; // Normal file data (See function
// documentation for other values)
fResult = DeviceIoControl(hDev, VWIN32_DIOC_DOS_DRIVEINFO,
®, sizeof(reg),
®, sizeof(reg), &cb, 0);
// Determine if the DeviceIoControl call and the write succeeded.
fResult = fResult && !(reg.reg_Flags & CARRY_FLAG);
return fResult;
}
BOOL UserPressedCancel(VOLINFO *vi)
{
MSG msg;
while(PeekMessage(&msg,vi->hwnd,0,0,PM_REMOVE))
{
if(!IsDialogMessage(vi->hwnd,&msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
if(bGlobalCancel)
return TRUE;
return FALSE;
}
DWORD ReadSectors(VOLINFO *vi,DWORD start_sector,
WORD num_sectors,LPBYTE pBuf)
{
DWORD RetVal;
RetVal=WFE_NOERROR;
if(vi->dwFS==FS_FAT32)
{
if(ReadAbsoluteSectors32(vi->hVWin32,vi->vol1,
start_sector,num_sectors,pBuf)!=0)
RetVal=WFE_COULDNOTREAD;
}
else
{
if(ReadAbsoluteSectors(vi->hVWin32,vi->vol1,
start_sector,num_sectors,pBuf)<0)
RetVal=WFE_COULDNOTREAD;
}
if(UserPressedCancel(vi))
RetVal=WFE_USERCANCEL;
return RetVal;
}
int GetLockFlagState( HANDLE hDev,int volume,BOOL bFlatFAT )
{
DIOC_REGISTERS reg;
BOOL bResult,fResult;
DWORD cb;
reg.reg_EAX = 0x440d; // generic IOCTL
reg.reg_ECX = bFlatFAT ? 0x486c : 0x086c; // lock logical volume
reg.reg_EBX = volume; // 1 based
reg.reg_Flags = 1; // preset the carry flag
bResult = DeviceIoControl( hDev, VWIN32_DIOC_DOS_IOCTL,
®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 );
fResult = bResult && !(reg.reg_Flags & CARRY_FLAG);
if(!fResult)
return -1;
return (reg.reg_EAX & 0xffff);
}
int LockLogicalVolume( HANDLE hDev,int volume, int lock_level,
int permissions, BOOL bFlatFAT )
{
DIOC_REGISTERS reg;
BOOL bResult;
DWORD cb;
reg.reg_EAX = 0x440d; // generic IOCTL
reg.reg_ECX = bFlatFAT ? 0x484a : 0x084a; // lock logical volume
reg.reg_EBX = volume | (lock_level << 8);
reg.reg_EDX = permissions;
reg.reg_Flags = 1; // preset the carry flag
bResult = DeviceIoControl( hDev, VWIN32_DIOC_DOS_IOCTL,
®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 );
if(bResult)
return 0;
return (reg.reg_EAX & 0xffff);
// if ( !bResult || (reg.reg_Flags & 1) )
// return (reg.reg_EAX & 0xffff);
return 0;
}
int UnlockLogicalVolume( HANDLE hDev,int volume, BOOL bFlatFAT )
{
DIOC_REGISTERS reg;
BOOL bResult;
DWORD cb;
reg.reg_EAX = 0x440d;
reg.reg_ECX = bFlatFAT ? 0x486a : 0x086a; // lock logical volume
reg.reg_EBX = volume;
reg.reg_Flags = 1; // preset the carry flag
bResult = DeviceIoControl( hDev, VWIN32_DIOC_DOS_IOCTL,
®, sizeof( reg ), ®, sizeof( reg ), &cb, 0 );
if ( !bResult || (reg.reg_Flags & 1) ) return -1;
return 0;
}
DWORD WriteSectors(VOLINFO *vi,DWORD start_sector,
WORD num_sectors,LPBYTE pBuf)
{
DWORD RetVal;
BOOL bFat32;
RetVal=WFE_NOERROR;
bFat32=(vi->dwFS==FS_FAT32);
if(vi->bCountClusters)
{
char StrRes[500];
LoadString (g_hinst, IDS_SCANNINGDISK, StrRes, sizeof(StrRes));
if(vi->dwClusterCount==0)
StatusMessage(StrRes, FALSE);
vi->dwClusterCount++;
if(UserPressedCancel(vi))
RetVal=WFE_USERCANCEL;
return RetVal;
}
// Get Level2 Exclusive Volume Lock
if(LockLogicalVolume(vi->hVWin32,vi->vol1,
LEVEL2_LOCK,
0,
bFat32)!=0)
{
RetVal=WFE_COULDNOTLOCK;
}
else
{
// Get Level3 Exclusive Volume Lock
if(LockLogicalVolume(vi->hVWin32,vi->vol1,
LEVEL3_LOCK,
0,
bFat32)!=0)
{
RetVal=WFE_COULDNOTLOCK;
}
else
{
// Make sure nobody has been writing to the disk.
if(GetLockFlagState(vi->hVWin32,vi->vol1,bFat32)!=0)
{
RetVal=WFE_DISKMODIFIED;
}
else
{
if(bFat32)
{
if(!WriteAbsoluteSectors32(vi->hVWin32,
vi->vol1,start_sector,num_sectors,pBuf))
{
RetVal=WFE_COULDNOTWRITE;
}
}
else
{
if(!WriteAbsoluteSectors(vi->hVWin32,
vi->vol1,start_sector,num_sectors,pBuf))
{
RetVal=WFE_COULDNOTWRITE;
}
}
}
// Free Level 3 lock
UnlockLogicalVolume(
vi->hVWin32,
vi->vol1,
bFat32);
}
// Free Level 2 lock
UnlockLogicalVolume(
vi->hVWin32,
vi->vol1,
bFat32);
}
if(RetVal==WFE_NOERROR)
{
char StrRes[500];
char statusmsg[500];
vi->dwClustersWritten=vi->dwClustersWritten+1;
if(vi->dwClustersWritten%10==0)
{
float pos;
LoadString (g_hinst, IDS_PERCENTWRITTEN, StrRes, sizeof(StrRes));
sprintf(statusmsg,
StrRes,
vi->dwClustersWritten,vi->dwClusterCount);
StatusMessage(statusmsg, FALSE);
pos = 10 +
( (float)vi->dwClustersWritten /
(float)vi->dwClusterCount )
* 90;
WipeProgress((int)pos);
}
}
if(UserPressedCancel(vi))
RetVal=WFE_USERCANCEL;
return RetVal;
}
DWORD Fat32Item(unsigned char *FATbuffer,DWORD FlatIndex)
{
DWORD dwFat32index;
DWORD dwFat32value;
DWORD *pFat;
dwFat32index=FlatIndex*32/8;
pFat = (DWORD *)(&(FATbuffer[dwFat32index]));
// upper 4 bits are masked off
dwFat32value=0x0fffffff & (*pFat);
return dwFat32value;
}
DWORD Fat16Item(unsigned char *FATbuffer,DWORD FlatIndex)
{
DWORD dwFat16index;
DWORD dwFat16value;
WORD *pFat;
dwFat16index=FlatIndex*16/8;
pFat = (WORD *)(&(FATbuffer[dwFat16index]));
dwFat16value=0xffff & (DWORD)(*pFat);
return dwFat16value;
}
DWORD Fat12Item(unsigned char *FATbuffer,DWORD FlatIndex)
{
DWORD dwFat12index;
DWORD dwFat12value;
DWORD nib;
unsigned char* pFat;
// Depending if we're odd or even, we may
// get need 8 bits then 4 bits, or 4 bits
// then 8 bits.
dwFat12index=FlatIndex*12/8;
pFat = &(FATbuffer[dwFat12index]);
if(FlatIndex%2==0) // Even
{ // Get the 8 bits
dwFat12value = 0xff & (DWORD)(*pFat);
pFat++;
// Get the 4 bits
nib = 0x0f & (DWORD)(*pFat);
// Shift the 4 bit portion as MSB.
nib <<= 8;
dwFat12value |= nib;
}
else // Odd
{ // Get the 4 bits.
nib = 0xf0 & (DWORD)(*pFat);
pFat++;
// Get the 8 bits
dwFat12value = 0xff & (DWORD)(*pFat);
// Shift the 8 bit portion MSB.
dwFat12value <<= 4;
// Shift the 4 bit portion LSB.
nib >>= 4;
dwFat12value |= nib;
}
return dwFat12value;
}
DWORD FatItem(VOLINFO *vi,DWORD index)
{
switch(vi->dwFS)
{
case FS_FAT12:
return(Fat12Item(vi->pFatBuf,index));
case FS_FAT16:
return(Fat16Item(vi->pFatBuf,index));
case FS_FAT32:
return(Fat32Item(vi->pFatBuf,index));
}
return 0;
}
BOOL IsntEnd(VOLINFO *vi,DWORD dwIndexCluster)
{
switch(vi->dwFS)
{
case FS_FAT12:
if(dwIndexCluster<0xff0)
return TRUE;
break;
case FS_FAT16:
if(dwIndexCluster<0xfff0)
return TRUE;
break;
case FS_FAT32:
if(dwIndexCluster<0x0ffffff0)
return TRUE;
break;
}
return FALSE;
}
BOOL IsClusterError(VOLINFO *vi,DWORD dwIndexCluster)
{
switch(vi->dwFS)
{
case FS_FAT12:
if(dwIndexCluster==0xff7)
return TRUE;
break;
case FS_FAT16:
if(dwIndexCluster==0xfff7)
return TRUE;
break;
case FS_FAT32:
if(dwIndexCluster==0x0ffffff7)
return TRUE;
break;
}
return FALSE;
}
BOOL PushDirStack(DIRSTACK **ds,
DWORD dwStartCluster)
{
DIRSTACK *newds;
newds=(DIRSTACK *)malloc(sizeof(DIRSTACK));
if(newds)
{
memset(newds,0x00,sizeof(DIRSTACK));
newds->dwStartCluster=dwStartCluster;
newds->next=*ds;
*ds=newds;
return TRUE;
}
return FALSE;
}
BOOL PopDirStack(DIRSTACK **ds,
DWORD *dwStartCluster)
{
DIRSTACK *FreeAtLast;
if(*ds==0)
return FALSE;
FreeAtLast=*ds;
*dwStartCluster=(*ds)->dwStartCluster;
*ds=(*ds)->next;
free(FreeAtLast);
return TRUE;
}
DWORD DoFileSlack(VOLINFO *vi,
DWORD dwCluster,
DWORD dwLength)
{
DWORD dwLastCluster;
DWORD RetVal,err;
RetVal=WFE_NOERROR;
// Starting cluster is invalid? Something wrong
if(!IsntEnd(vi,dwCluster))
return WFE_CLUSTERERROR;
dwLastCluster=dwCluster;
dwCluster=FatItem(vi,dwCluster);
// Find the last cluster and the remainder length
while(IsntEnd(vi,dwCluster))
{
dwLastCluster=dwCluster;
dwLength-=vi->dwClusterSize;
dwCluster=FatItem(vi,dwCluster);
}
// Cluster with an error is in the chain
if(IsClusterError(vi,dwCluster))
return WFE_CLUSTERERROR;
// File length and cluster chain don't agree
// Since we're unsigned, less than zero is accounted for
if(dwLength>vi->dwClusterSize)
return WFE_CLUSTERERROR;
memset(vi->pClusterBuf,0x00,vi->dwClusterSize);
if(vi->bCountClusters)
{
// Since we're just counting, no need to read in
// the last sector.... it won't be written anyway.
// Speeds things up greatly.
err=WFE_NOERROR;
}
else
{
// Read in last cluster of file
err=ReadSectors(vi,
ClusterToSector(vi,dwLastCluster),
vi->sectors_per_clus,
vi->pClusterBuf);
}
if(err!=WFE_NOERROR)
{
RetVal=err;
}
else
{
// wipe off the slack
WritePattern( &((vi->pClusterBuf)[dwLength]),
vi->pattern_buffer,
vi->dwClusterSize-dwLength);
//memset(&((vi->pClusterBuf)[dwLength]),0x00,
// vi->dwClusterSize-dwLength);
// Write out last cluster of file
err=WriteSectors(vi,
ClusterToSector(vi,dwLastCluster),
vi->sectors_per_clus,
vi->pClusterBuf);
if(err!=WFE_NOERROR)
RetVal=err;
}
return RetVal;
}
DWORD DoDirAndSlack(VOLINFO *vi,
char *pBuf,int bufsize)
{
unsigned char *pDir = pBuf;
unsigned char *pEnd = pDir+bufsize;
DWORD dwStartCluster;
DWORD dwTotalLength,err,RetVal;
PDIRENTRY pd;
RetVal=WFE_NOERROR;
while((*pDir)&&(RetVal==WFE_NOERROR))
{
// Skip over and erase deleted directory entries
if (*pDir == 0xe5)
{
// WritePattern(&(pDir[1]),vi->pattern_buffer,sizeof(DIRENTRY)-1);
// Maybe this is a problem... yah.. long filenames are mislinked.
memset(&(pDir[1]),0x00,sizeof(DIRENTRY)-1);
pDir += sizeof( DIRENTRY );
}
else if (*(pDir+0x0b) == 0xf && *(pDir+0x0c) == 0 )
{
// Type 0 "long" directory entry
// We don't really care about these. leave em be.
pDir += sizeof( DIRENTRY );
}
// Other Type "long" directory entry
else if (*(pDir+0x0b) == 0xf && *(pDir+0x0c) != 0 )
{
// Other Type "long" directory entry
// We don't care about these either.
pDir += sizeof( DIRENTRY );
}
// "Short" directory entry
else
{
// "Short" directory entry
// Every file has one of these. It has our info.
pd = (PDIRENTRY)pDir;
dwTotalLength=pd->deFileSize;
if (vi->dwFS!=FS_FAT32)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -