📄 scwfnt.c
字号:
/*__________________________________________________________________________
Copyright (C) 2002 PGP Corporation
All rights reserved.
$Id: SCwfNT.c,v 1.15 2002/11/16 08:55:23 wjb Exp $
__________________________________________________________________________*/
#include "precomp.h"
#define RETRIES 1
//
// Invalid longlong number
//
#define LLINVALID ((ULONGLONG) -1)
//
// Size of the buffer we read file mapping information into.
// The buffer is big enough to hold the 16 bytes that
// come back at the head of the buffer (the number of entries
// and the starting virtual cluster), as well as 512 pairs
// of [virtual cluster, logical cluster] pairs.
//
#define FILEMAPSIZE (512+2)
//
// Size of the bitmap buffer we pass in. Its large enough to
// hold information for the 16-byte header that's returned
// plus the indicated number of bytes, each of which has 8 bits
// (imagine that!)
//
#define BITMAPBYTES 4096
#define BITMAPSIZE (BITMAPBYTES+2*sizeof(ULONGLONG))
//
// Bit shifting array for efficient processing of the bitmap
//
BYTE BitShift[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
// StatusToError
//
// Takes the status messages and turns them into our
// native wipe free codes.
DWORD StatusToError( NTSTATUS Status )
{
switch( Status )
{
case STATUS_SUCCESS:
return WFE_NOERROR;
case STATUS_INVALID_PARAMETER:
return WFE_INVALPARAM; // Must be the metafile
case STATUS_BUFFER_TOO_SMALL:
return WFE_OUTOFMEMORY;
case STATUS_ALREADY_COMMITTED:
case STATUS_DELETE_PENDING:
return WFE_ALREADYCOMMIT; // NTFS won't let us. Try anyway
case STATUS_INVALID_DEVICE_REQUEST:
return WFE_DRIVENOTSUPPORTED;
case STATUS_DEVICELOCKED:
return WFE_COULDNOTLOCK;
case ERROR_ACCESS_DENIED:
return WFE_ACCESSDENIED;
default:
/*
#if _DEBUG
{
char szWarn[100];
sprintf(szWarn,"Status Error %d",Status);
MessageBox(NULL,szWarn,"DEBUG INFO ONLY",MB_OK);
}
#endif // _DEBUG
*/
return WFE_CLUSTERERROR;
}
}
// OpenVolume
//
// Grabs the handle of our logical volume
DWORD OpenVolume( VOLINFO *vi )
{
static char volumeName[] = "\\\\.\\A:";
//
// open the volume
//
volumeName[4] = (char)vi->vol0 + 'A';
vi->VolHandle = CreateFile( volumeName, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
0, 0 );
if( vi->VolHandle == INVALID_HANDLE_VALUE ) {
return GetLastError();
}
return ERROR_SUCCESS;
}
// WipeCluster
//
// WipeCluster uses the patterns stored in filename to
// eradicate the data in the target cluster of the logical
// drive specified.
DWORD ClusterNTWipeCluster( HANDLE sourceFile,VOLINFO *vi, ULONGLONG Vcn, ULONGLONG target,DWORD numClusters)
{
DWORD status;
IO_STATUS_BLOCK ioStatus;
LARGE_INTEGER startVcn, targetLcn;
MOVEFILE_DESCRIPTOR moveFile;
DWORD RetVal;
RetVal=WFE_NOERROR;
if(numClusters>16)
{
int i;
i=0;
}
//
// Get numeric parameters
//
startVcn.QuadPart=Vcn;
targetLcn.QuadPart=target;
//
// Setup movefile descriptor and make the call
//
memset(&moveFile,0x00,sizeof(MOVEFILE_DESCRIPTOR));
memset(&ioStatus,0x00,sizeof(IO_STATUS_BLOCK));
moveFile.FileHandle = sourceFile;
moveFile.StartVcn = startVcn;
moveFile.TargetLcn = targetLcn;
moveFile.NumVcns = numClusters;
status = NtFsControlFile( vi->VolHandle, NULL, NULL, 0, &ioStatus,
FSCTL_MOVE_FILE,
&moveFile, sizeof( moveFile ),
NULL, 0 );
RetVal=StatusToError(status);
//
// If the operation is pending, wait for it to finish
//
if( status == STATUS_PENDING )
{
WaitForSingleObject( sourceFile, INFINITE );
RetVal=StatusToError(ioStatus.Status);
}
if(status!=STATUS_SUCCESS)
{
int i;
i=0;
}
// // Handle our progress bars and look out for user cancel
// vi->dwClustersWritten=vi->dwClustersWritten+1;
// if(vi->dwFS==FS_NTFS)
// NTFS works with 16 cluster segments
// vi->dwClustersWritten=vi->dwClustersWritten+15;
return RetVal;
}
// WipeFreeClusters
//
// Given a logical drive number, routine iterates through free
// clusters and calls WipeCluster to zap the information stored
// there. Note that if changes take place on the drive while
// routine is executes, some clusters may be missed.
DWORD ClusterWipeFreeClusters( VOLINFO *vi, BOOL bWipe)
{
DWORD status,wipestatus;
PBITMAP_DESCRIPTOR bitMappings;
ULONGLONG startLcn;
ULONGLONG nextLcn;
IO_STATUS_BLOCK ioStatus;
ULONGLONG i;
DWORD numClusters;
wipestatus=WFE_NOERROR;
if(bWipe)
StatusMessage(vi,"Wiping free space with cluster move method...", FALSE);
else
StatusMessage(vi,"Counting clusters for slack wipe...", FALSE);
bitMappings=(PBITMAP_DESCRIPTOR)malloc(BITMAPSIZE*sizeof(BYTE)+1);
//
// Start scanning at the cluster offset the user specifies
//
nextLcn = 0;
while( !(status = NtFsControlFile( vi->VolHandle, NULL, NULL, 0, &ioStatus,
FSCTL_GET_VOLUME_BITMAP,
&nextLcn, sizeof( ULONGLONG ),
bitMappings, BITMAPSIZE )) ||
status == STATUS_BUFFER_OVERFLOW ||
status == STATUS_PENDING )
{
//
// If the operation is pending, wait for it to finish
//
if( status == STATUS_PENDING )
{
WaitForSingleObject( vi->VolHandle, INFINITE );
//
// Get the status from the status block
//
if( ioStatus.Status != STATUS_SUCCESS &&
ioStatus.Status != STATUS_BUFFER_OVERFLOW )
{
free(bitMappings);
// Error out
return StatusToError(ioStatus.Status);
}
}
//
// Scan through the returned bitmap info, looking for empty clusters
//
startLcn = bitMappings->StartLcn;
for( i = 0; i < min( bitMappings->ClustersToEndOfVol, 8*BITMAPBYTES); i++)
{
numClusters=0;
if(vi->bCancel)
{
free(bitMappings);
return WFE_USERCANCEL;
}
if( !(bitMappings->Map[ i/8 ] & BitShift[ i % 8 ]))
{
for(numClusters=1;
((numClusters<16)&&((i+numClusters)<min( bitMappings->ClustersToEndOfVol, 8*BITMAPBYTES)));
numClusters++)
{
if((bitMappings->Map[ (i+numClusters)/8 ] & BitShift[ (i+numClusters) % 8 ]))
{
break;
}
}
if(bWipe)
{
wipestatus=ClusterNTWipeCluster(vi->hWipe,vi, 0, startLcn + i,numClusters);
vi->dwClustersWritten=vi->dwClustersWritten+numClusters;
}
if(wipestatus==WFE_NOERROR)
{
// Save this cluster for later slack movement operations
if((vi->SlackBufferIndex<SLACKBUFFER)&&((vi->dwFS!=FS_NTFS)||(numClusters==16)))
{
vi->SlackBuffer[vi->SlackBufferIndex]=startLcn + i;
vi->SlackBufferIndex=vi->SlackBufferIndex+1;
}
}
i=i+numClusters-1;
if(((wipestatus==WFE_ALREADYCOMMIT)||(wipestatus==WFE_INVALPARAM))&&(vi->dwFS==FS_NTFS))
{
// Couldn't do the move because of MFT, or user is mucking
// around.... just skip it and we'll get it on the next pass.
// Only applies to NTFS
wipestatus=WFE_NOERROR;
}
if(wipestatus!=WFE_NOERROR)
{
free(bitMappings);
return wipestatus;
}
}
}
//
// End of volume?
//
if( status != STATUS_BUFFER_OVERFLOW )
{
free(bitMappings);
return StatusToError(STATUS_SUCCESS);
}
//
// Move to the next block
//
nextLcn = bitMappings->StartLcn + i;
}
//
// We only get here when there's an error
//
free(bitMappings);
return StatusToError(status);
}
DWORD ClusterCountFreeClusters( VOLINFO *vi)
{
DWORD status;
PBITMAP_DESCRIPTOR bitMappings;
ULONGLONG startLcn;
ULONGLONG nextLcn;
IO_STATUS_BLOCK ioStatus;
ULONGLONG i;
StatusMessage(vi,"Counting free clusters...", FALSE);
bitMappings=(PBITMAP_DESCRIPTOR)malloc(BITMAPSIZE*sizeof(BYTE)+1);
if(bitMappings==NULL)
return WFE_OUTOFMEMORY;
//
// Start scanning at the cluster offset the user specifies
//
nextLcn = 0;
while( !(status = NtFsControlFile( vi->VolHandle, NULL, NULL, 0, &ioStatus,
FSCTL_GET_VOLUME_BITMAP,
&nextLcn, sizeof( ULONGLONG ),
bitMappings, BITMAPSIZE )) ||
status == STATUS_BUFFER_OVERFLOW ||
status == STATUS_PENDING )
{
//
// If the operation is pending, wait for it to finish
//
if( status == STATUS_PENDING )
{
WaitForSingleObject( vi->VolHandle, INFINITE );
//
// Get the status from the status block
//
if( ioStatus.Status != STATUS_SUCCESS &&
ioStatus.Status != STATUS_BUFFER_OVERFLOW )
{
free(bitMappings);
// Error out
return StatusToError(ioStatus.Status);
}
}
//
// Scan through the returned bitmap info, looking for empty clusters
//
startLcn = bitMappings->StartLcn;
for( i = 0; i < min( bitMappings->ClustersToEndOfVol, 8*BITMAPBYTES); i++)
{
if(vi->bCancel)
{
free(bitMappings);
return WFE_USERCANCEL;
}
if( !(bitMappings->Map[ i/8 ] & BitShift[ i % 8 ]))
{
vi->dwClusterCount++;
}
}
//
// End of volume?
//
if( status != STATUS_BUFFER_OVERFLOW )
{
free(bitMappings);
return StatusToError(STATUS_SUCCESS);
}
//
// Move to the next block
//
nextLcn = bitMappings->StartLcn + i;
}
//
// We only get here when there's an error
//
free(bitMappings);
return StatusToError(status);
}
// GetLastClusterOfFile
//
// Loops through till it finds the last cluster in the chain
DWORD GetLastClusterOfFile(VOLINFO *vi, char *fileName, SLACKMOVE *sm)
{
DWORD status;
int i;
HANDLE sourceFile;
IO_STATUS_BLOCK ioStatus;
ULONGLONG startVcn;
PGET_RETRIEVAL_DESCRIPTOR fileMappings;
int lines = 0;
// Save name of file for later
sm->name=fileName;
sm->Orig=sm->Vcn=sm->Size=0;
//
// Open the file
//
sourceFile = CreateFile( fileName, GENERIC_READ,
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING, 0 );
if( sourceFile == INVALID_HANDLE_VALUE )
return WFE_COULDNOTREAD;
//
// Start dumping the mapping information. Go until we hit the end of the
// file.
//
startVcn = 0;
fileMappings = (PGET_RETRIEVAL_DESCRIPTOR)
malloc(FILEMAPSIZE*sizeof(ULONGLONG));
while( !(status = NtFsControlFile( sourceFile, NULL, NULL, 0, &ioStatus,
FSCTL_GET_RETRIEVAL_POINTERS,
&startVcn, sizeof( startVcn ),
fileMappings, FILEMAPSIZE * sizeof(LARGE_INTEGER) ) ) ||
status == STATUS_BUFFER_OVERFLOW ||
status == STATUS_PENDING )
{
//
// If the operation is pending, wait for it to finish
//
if( status == STATUS_PENDING ) {
WaitForSingleObject( sourceFile, INFINITE );
//
// Get the status from the status block
//
if( ioStatus.Status != STATUS_SUCCESS &&
ioStatus.Status != STATUS_BUFFER_OVERFLOW )
{
free(fileMappings);
// Error out
return StatusToError(ioStatus.Status);
}
}
//
// Loop through the buffer of number/cluster pairs, printing them
// out.
//
startVcn = fileMappings->StartVcn;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -