#ifndef BITMAP_H
#define BITMAP_H
#define _WIN32_WINNT 0x600
#include "windows.h"
#include "winioctl.h"
#include <vector>
#include <map>
using namespace std;
class BitMap
{
public:
void getMapList(const VOLUME_BITMAP_BUFFER *pInBuff);
void dispalyMapListOfFree() const;
void showVecOfBit() const;
const map<ULONGLONG, ULONGLONG> & returnMaplist() const;
const vector<bool> & returnBitVec() const;
private:
map<ULONGLONG, ULONGLONG> mapListOfFree;
vector<bool> vecOfBit;
};
#endif
#include "bitmap.h"
#include <iostream>
#include <bitset>
#include <fstream>
void BitMap::getMapList(const VOLUME_BITMAP_BUFFER *pInBuff)
{
ULONGLONG count_size = 0;
ULONGLONG size_clusterarray = (pInBuff -> BitmapSize.QuadPart + 7) / 8;
while (count_size != size_clusterarray)
{
bitset<8> bit(*(pInBuff -> Buffer + count_size));
for (int i = 0; i != 8; ++i)
{
vecOfBit.push_back(bit[i]);
}
count_size++;
}
if (vecOfBit.size() != pInBuff -> BitmapSize.QuadPart)
{
ULONGLONG popnum = vecOfBit.size() - pInBuff -> BitmapSize.QuadPart;
for (ULONGLONG i = 0; i < popnum; ++i)
{
vecOfBit.pop_back();
}
}
ULONGLONG add = 0;
__w64 unsigned int/*ULONGLONG*/ size = 0;
for (__w64 unsigned int/*ULONGLONG*/ i = 0; i < vecOfBit.size();)
{
size = 0;
if (vecOfBit[i] == 0)
{
add = i;
__w64 unsigned int/*ULONGLONG*/ idx = i;
while ((idx < vecOfBit.size()) && !vecOfBit[idx]) //
{
size ++;
idx++;
}
i += size;
mapListOfFree.insert(make_pair(add, size));
}
else
{
i++;
continue;
}
}
}
void BitMap::showVecOfBit() const
{
fstream vecbit("bitmap.txt", ios_base::out);
if (!vecbit) return;
for (__w64 unsigned int/*ULONGLONG*/ i = 0; i < vecOfBit.size(); ++i)
{
if (i % 32 == 0)
{
vecbit << endl;
}
vecbit << (DWORD)vecOfBit[i] << " ";
}
vecbit.close();
}
void BitMap::dispalyMapListOfFree() const
{
cout << "Free Space List <start cluster number, free space size>" << endl;
for (map<ULONGLONG, ULONGLONG>::const_iterator cit = mapListOfFree.begin(); cit != mapListOfFree.end(); ++cit)
{
cout << "address: " << ULONG((*cit).first) << "/tsize: " << ULONG((*cit).second) << endl;
}
}
const map<ULONGLONG, ULONGLONG>& BitMap::returnMaplist() const
{
return mapListOfFree;
}
const vector<bool>& BitMap::returnBitVec() const
{
return vecOfBit;
}
#ifndef MOVFLE_H
#define NOVFLE_H
#include <string>
#include <map>
using namespace std;
#define _WIN32_WINNT 0x600
#include "windows.h"
#include "winioctl.h"
#include "ddk.h"
class MovFle
{
public:
BOOL init(string str_fileFullPathName, MyNtFsControlFile ptr);
BOOL analysis(ULONGLONG ull_usedClusters, DWORD &rerCod);
BOOL move(HANDLE hVolum, map<ULONGLONG, ULONGLONG> &rmapList, DWORD &rerCod); //pair<addres, size> free space
void displayFileMapList() const;
~MovFle();
private:
HANDLE m_hFle;
map<ULONGLONG, ULONGLONG> m_mapAnalysised; //file should move
string m_strFileName;
MyNtFsControlFile m_mptr;
};
#endif
#include "movfle.h"
#include <vector>
#include <utility>
#include<fstream>
#include <iostream>
BOOL MovFle::init(string str_fileFullPathName, MyNtFsControlFile ptr)
{
m_strFileName = str_fileFullPathName;
m_hFle = CreateFile(str_fileFullPathName.c_str(), GENERIC_READ/* | GENERIC_WRITE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA| FILE_EXECUTE | FILE_READ_ATTRIBUTES*/,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
/*FILE_ATTRIBUTE_NORMAL*/FILE_FLAG_NO_BUFFERING, NULL);
if (INVALID_HANDLE_VALUE == m_hFle)
{
//may be a directory name
m_hFle = CreateFile (str_fileFullPathName.c_str(), GENERIC_READ | FILE_SHARE_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (INVALID_HANDLE_VALUE != m_hFle)
{
m_mptr = ptr;
return TRUE;
}
return FALSE;
}
m_mptr = ptr;
return TRUE;
}
MovFle::~MovFle()
{
if (INVALID_HANDLE_VALUE != m_hFle)
{
CloseHandle(m_hFle);
}
}
BOOL MovFle::analysis(ULONGLONG ull_usedClusters, DWORD &rerCod)
{
STARTING_VCN_INPUT_BUFFER inbuff;
inbuff.StartingVcn.QuadPart = 0;
RETRIEVAL_POINTERS_BUFFER outbuf;
ULONGLONG ull_DealedVcn = 0;
BOOL bIsOk;
DWORD dwReturnBytes = 0;
vector<pair<pair<ULONGLONG, ULONGLONG>, ULONGLONG> > vecFileBlock;
//<<startVcn, Lcn>, size>
do
{
bIsOk = DeviceIoControl(m_hFle, FSCTL_GET_RETRIEVAL_POINTERS, &inbuff,
sizeof(STARTING_VCN_INPUT_BUFFER), &outbuf, sizeof(RETRIEVAL_POINTERS_BUFFER), &dwReturnBytes, NULL);
rerCod = GetLastError();
//for dealing directory
if (outbuf.ExtentCount == 0)
break;
vecFileBlock.push_back(make_pair(make_pair(outbuf.StartingVcn.QuadPart, outbuf.Extents[0].Lcn.QuadPart), outbuf.Extents[0].NextVcn.QuadPart - outbuf.StartingVcn.QuadPart));
inbuff.StartingVcn.QuadPart = outbuf.Extents[0].NextVcn.QuadPart;
} while((!bIsOk) && (rerCod == ERROR_MORE_DATA));
//analysis and make
for (DWORD currentBlock = 0; currentBlock != vecFileBlock.size(); ++currentBlock)
{
if (vecFileBlock[currentBlock].first.second >= ull_usedClusters)
{
m_mapAnalysised.insert(make_pair(vecFileBlock[currentBlock].first.first, vecFileBlock[currentBlock].second));
}
else
{
if (vecFileBlock[currentBlock].first.second + vecFileBlock[currentBlock].second > ull_usedClusters)
{
m_mapAnalysised.insert(make_pair((vecFileBlock[currentBlock].first.first + (ull_usedClusters - vecFileBlock[currentBlock].first.second)),
(vecFileBlock[currentBlock].first.second + vecFileBlock[currentBlock].second - ull_usedClusters)));
}
}
}
if (m_mapAnalysised.size() != 0)
{
displayFileMapList();
}
BOOL result = (m_mapAnalysised.size() == 0) ? FALSE : TRUE;
return result;
}
void MovFle::displayFileMapList() const
{
cout << m_strFileName << "-> maplist : " << endl;
map<ULONGLONG, ULONGLONG>::const_iterator cit = m_mapAnalysised.begin();
for (; cit != m_mapAnalysised.end(); ++cit)
{
cout << "startVcn : " << cit -> first << " " << "size : " << cit -> second << endl;
}
cout << endl;
}
/*
BOOL MovFle::move(HANDLE hVolum, std::map<ULONGLONG,ULONGLONG> &rmapList, DWORD &rerCod)
{
MOVE_FILE_DATA mfd;
mfd.FileHandle = m_hFle;
BOOL bIsOk = TRUE;
DWORD dwReturnBytes = 0;
ULONGLONG ull_startVcnInBlock = 0;
if (rmapList.empty())
{
return FALSE;
}
map<ULONGLONG, ULONGLONG>::iterator ite = rmapList.begin();
for (map<ULONGLONG, ULONGLONG>::const_iterator cit = m_mapAnalysised.begin(); cit != m_mapAnalysised.end(); ++ cit)
{
//check rmaplist size
if (rmapList.size() == 0)
{
return FALSE;
}
//deal each block
ULONGLONG ull_vcnInBlock = cit -> second;
ULONGLONG ull_dealedVcnInBlock = 0;
ull_startVcnInBlock = cit -> first;
while (ull_dealedVcnInBlock < ull_vcnInBlock)
{
//check rmapList size
if (rmapList.size() == 0)
{
return FALSE;
}
ite = rmapList.begin(); //always points to the first item
if (ull_vcnInBlock - ull_dealedVcnInBlock <= ite -> second) //space is enough
{
if (ull_vcnInBlock - ull_dealedVcnInBlock == ite -> second) //==
{
mfd.ClusterCount = ite -> second;
mfd.StartingVcn.QuadPart = ull_startVcnInBlock + ull_dealedVcnInBlock;
mfd.StartingLcn.QuadPart = ite -> first;
//dbg
cout << "now mov clusters : " << endl;
cout << "ClusterCount : "<< mfd.ClusterCount << endl;
cout << "StartingVcn : "<< mfd.StartingVcn.QuadPart << endl;
cout << "StartingLcn : "<< mfd.StartingLcn.QuadPart << endl;
bIsOk = DeviceIoControl(m_hFle, FSCTL_MOVE_FILE, &mfd, sizeof(MOVE_FILE_DATA),
NULL, 0, &dwReturnBytes, NULL);
if (!bIsOk)
{
rerCod = GetLastError();
//dbg
cout << "error : " << endl;
cout << "ClusterCount : "<< mfd.ClusterCount << endl;
cout << "StartingVcn : "<< mfd.StartingVcn.QuadPart << endl;
cout << "StartingLcn : "<< mfd.StartingLcn.QuadPart << endl;
cout << "errcod : " << rerCod << endl;
return FALSE;
}
else
{
rmapList.erase(ite);
}
}
else //<
{
mfd.ClusterCount = ull_vcnInBlock - ull_dealedVcnInBlock;
mfd.StartingVcn.QuadPart = ull_startVcnInBlock + ull_dealedVcnInBlock;
mfd.StartingLcn.QuadPart = ite -> first;
//dbg
cout << "now mov clusters : " << endl;;
cout << "ClusterCount : "<< mfd.ClusterCount << endl;
cout << "StartingVcn : "<< mfd.StartingVcn.QuadPart << endl;
cout << "StartingLcn : "<< mfd.StartingLcn.QuadPart << endl;
bIsOk = DeviceIoControl(m_hFle, FSCTL_MOVE_FILE, &mfd, sizeof(MOVE_FILE_DATA),
NULL, 0, &dwReturnBytes, NULL);
if (!bIsOk)
{
rerCod = GetLastError();
//dbg
cout << "error : " << endl;
cout << "ClusterCount : "<< mfd.ClusterCount << endl;
cout << "StartingVcn : "<< mfd.StartingVcn.QuadPart << endl;
cout << "StartingLcn : "<< mfd.StartingLcn.QuadPart << endl;
cout << "errcod : " << rerCod << endl;
return FALSE;
}
else
{
pair<ULONGLONG, ULONGLONG> tmppar = *ite;
rmapList.erase(ite);
rmapList.insert(make_pair(tmppar.first + mfd.ClusterCount, tmppar.second - mfd.ClusterCount));
}
}
}
else //> space is not enough
{
mfd.ClusterCount = ite -> second;
mfd.StartingVcn.QuadPart = ull_startVcnInBlock + ull_dealedVcnInBlock;
mfd.StartingLcn.QuadPart = ite -> first;
bIsOk = DeviceIoControl(m_hFle, FSCTL_MOVE_FILE, &mfd, sizeof(MOVE_FILE_DATA),
NULL, 0, &dwReturnBytes, NULL);
if (!bIsOk)
{
rerCod = GetLastError();
return FALSE;
}
else
{
rmapList.erase(ite);
}
}
ull_dealedVcnInBlock += mfd.ClusterCount;
} //while
} //for
return TRUE;
}
*/
BOOL MovFle::move(HANDLE hVolum, std::map<ULONGLONG,ULONGLONG> &rmapList, DWORD &rerCod)
{
if (!m_mptr)
{
cout << "null function pointer" << endl;
return FALSE;
}
MOVEFILE_DESCRIPTOR mfd;
mfd.FileHandle = m_hFle;
DWORD status = 0;
IO_STATUS_BLOCK ioStatus;
BOOL bIsOk = TRUE;
DWORD dwReturnBytes = 0;
ULONGLONG ull_startVcnInBlock = 0;
if (rmapList.empty())
{
return FALSE;
}
map<ULONGLONG, ULONGLONG>::iterator ite = rmapList.begin();
for (map<ULONGLONG, ULONGLONG>::const_iterator cit = m_mapAnalysised.begin(); cit != m_mapAnalysised.end(); ++ cit)
{
//check rmaplist size
if (rmapList.size() == 0)
{
return FALSE;
}
//deal each block
ULONGLONG ull_vcnInBlock = cit -> second;
ULONGLONG ull_dealedVcnInBlock = 0;
ull_startVcnInBlock = cit -> first;
while (ull_dealedVcnInBlock < ull_vcnInBlock)
{
//check rmapList size
if (rmapList.size() == 0)
{
return FALSE;
}
ite = rmapList.begin(); //always points to the first item
if (ull_vcnInBlock - ull_dealedVcnInBlock <= ite -> second) //space is enough
{
if (ull_vcnInBlock - ull_dealedVcnInBlock == ite -> second) //==
{
mfd.NumVcns = ite -> second;
mfd.StartVcn.QuadPart = ull_startVcnInBlock + ull_dealedVcnInBlock;
mfd.TargetLcn.QuadPart = ite -> first;
/*
bIsOk = DeviceIoControl(m_hFle, FSCTL_MOVE_FILE, &mfd, sizeof(MOVE_FILE_DATA),
NULL, 0, &dwReturnBytes, NULL);
*/
status = m_mptr( hVolum, NULL, NULL, 0, &ioStatus,
FSCTLMOVEFILE,
&mfd, sizeof(mfd),
NULL, 0 );
//
// If the operation is pending, wait for it to finish
//
if( status == STATUS_PENDING ) {
WaitForSingleObject(m_hFle, INFINITE);
status = ioStatus.Status;
}
if (status != STATUS_SUCCESS)
{
rerCod = status;
return FALSE;
}
else
{
rmapList.erase(ite);
}
}
else //<
{
mfd.NumVcns = ull_vcnInBlock - ull_dealedVcnInBlock;
mfd.StartVcn.QuadPart = ull_startVcnInBlock + ull_dealedVcnInBlock;
mfd.TargetLcn.QuadPart = ite -> first;
/*
bIsOk = DeviceIoControl(m_hFle, FSCTL_MOVE_FILE, &mfd, sizeof(MOVE_FILE_DATA),
NULL, 0, &dwReturnBytes, NULL);
*/
status = m_mptr( hVolum, NULL, NULL, 0, &ioStatus,
FSCTLMOVEFILE,
&mfd, sizeof(mfd),
NULL, 0 );
if( status == STATUS_PENDING ) {
WaitForSingleObject(m_hFle, INFINITE);
status = ioStatus.Status;
}
if (status != STATUS_SUCCESS)
{
rerCod = status;
return FALSE;
}
else
{
pair<ULONGLONG, ULONGLONG> tmppar = *ite;
rmapList.erase(ite);
rmapList.insert(make_pair(tmppar.first + mfd.NumVcns, tmppar.second - mfd.NumVcns));
}
}
}
else //> space is not enough
{
mfd.NumVcns = ite -> second;
mfd.StartVcn.QuadPart = ull_startVcnInBlock + ull_dealedVcnInBlock;
mfd.TargetLcn.QuadPart = ite -> first;
/*
bIsOk = DeviceIoControl(m_hFle, FSCTL_MOVE_FILE, &mfd, sizeof(MOVE_FILE_DATA),
NULL, 0, &dwReturnBytes, NULL);
*/
status = m_mptr( hVolum, NULL, NULL, 0, &ioStatus,
FSCTLMOVEFILE,
&mfd, sizeof(mfd),
NULL, 0 );
//
// If the operation is pending, wait for it to finish
//
if( status == STATUS_PENDING ) {
WaitForSingleObject(m_hFle, INFINITE);
status = ioStatus.Status;
}
if (status != STATUS_SUCCESS)
{
rerCod = status;
return FALSE;
}
else
{
rmapList.erase(ite);
}
}
ull_dealedVcnInBlock += mfd.NumVcns;
} //while
} //for
return TRUE;
}
#ifndef VOLTDY_H
#define VOLTDY_H
#include "bitmap.h"
#include <string>
#include <algorithm>
#include <fstream>
using namespace std;
#include "windows.h"
#include "ddk.h"
class VolTdy
{
public:
BOOL initVolume(string str_volumeName, MyNtFsControlFile ptr);
BOOL getMapLst(DWORD &rerCod);
void beginBowse();
~VolTdy();
private:
void browse(string strdir);
map<ULONGLONG, ULONGLONG> m_mapLst;
HANDLE m_hVolum;
string m_volumeName;
ULONGLONG ull_usedClusters;
MyNtFsControlFile m_ptr;
fstream fleLog;
};
#endif
#include "voltdy.h"
#include <iostream>
#include "movfle.h"
BOOL VolTdy::initVolume(string str_volumeName, MyNtFsControlFile ptr)
{
m_volumeName = str_volumeName[0];
m_volumeName += ":";
m_volumeName = ".//" + m_volumeName;
m_hVolum = CreateFile(m_volumeName.c_str(), /*FILE_READ_DATA | FILE_WRITE_DATA |FILE_APPEND_DATA | FILE_EXECUTE | FILE_READ_ATTRIBUTES | */GENERIC_READ/* | GENERIC_WRITE*/,
FILE_SHARE_READ | FILE_SHARE_WRITE , NULL, OPEN_EXISTING,
/*FILE_ATTRIBUTE_NORMAL*/ 0, NULL);
if (INVALID_HANDLE_VALUE == m_hVolum)
{
return FALSE;
}
//for browse use
m_volumeName = str_volumeName[0];
m_volumeName += "://*";
ull_usedClusters = 0;
m_ptr = ptr;
return TRUE;
}
VolTdy::~VolTdy()
{
if (m_hVolum != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hVolum);
}
}
BOOL VolTdy::getMapLst(DWORD &rerCod)
{
BOOL bIsOk;
STARTING_LCN_INPUT_BUFFER start_lcn_buf;
start_lcn_buf.StartingLcn.QuadPart = 0;
VOLUME_BITMAP_BUFFER bitmap_buf_org;
VOLUME_BITMAP_BUFFER *pbitmap_buf = 0;
DWORD dwOutSize = 0;
ULONGLONG ullNumClusters = 0;
DWORD dwReturnBytes = 0;
bIsOk = DeviceIoControl(m_hVolum, FSCTL_GET_VOLUME_BITMAP, &start_lcn_buf, sizeof(STARTING_LCN_INPUT_BUFFER),
&bitmap_buf_org, sizeof(VOLUME_BITMAP_BUFFER), &dwReturnBytes, NULL);
if (!bIsOk && GetLastError() == ERROR_MORE_DATA)
{
//debug
ullNumClusters = bitmap_buf_org.BitmapSize.QuadPart - bitmap_buf_org.StartingLcn.QuadPart;
dwOutSize = ullNumClusters/sizeof(byte) + sizeof(VOLUME_BITMAP_BUFFER);
pbitmap_buf = (VOLUME_BITMAP_BUFFER *)new byte[dwOutSize];
if (!pbitmap_buf) return FALSE;
bIsOk = DeviceIoControl(m_hVolum, FSCTL_GET_VOLUME_BITMAP, &start_lcn_buf, sizeof(start_lcn_buf),
pbitmap_buf, dwOutSize, &dwReturnBytes, NULL);
if (!bIsOk)
{
if (pbitmap_buf)
{
delete [] pbitmap_buf;
pbitmap_buf = 0;
}
rerCod = GetLastError();
return FALSE;
}
}
BitMap bitmap;
bitmap.getMapList(pbitmap_buf);
delete [] pbitmap_buf;
pbitmap_buf = 0;
bitmap.dispalyMapListOfFree();
m_mapLst = bitmap.returnMaplist();
ull_usedClusters = count(bitmap.returnBitVec().begin(), bitmap.returnBitVec().end(), true);
cout << ull_usedClusters << "ull_usedClusters" << endl;
// bitmap.showVecOfBit();
return TRUE;
}
void VolTdy::browse(string strdir) //strdir, for directory, sample "F:/*"
{
WIN32_FIND_DATAA wfd;
HANDLE m_hFle = FindFirstFile(strdir.c_str(), &wfd);
strdir.resize(strdir.size() - 1);
DWORD errCod = 0;
if (INVALID_HANDLE_VALUE != m_hFle)
{
do
{
string str_fullName;
errCod = 0;
//directory dealed code
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
string tmp = wfd.cFileName;
if ((tmp != ".") && (tmp != ".."))
{
string stedbg = wfd.cFileName;
str_fullName = strdir + stedbg;
//for desturctor run
{
MovFle mvf;
fleLog.open("volLog.txt", ios_base::app);
fleLog << str_fullName << endl;
if(mvf.init(str_fullName, m_ptr))
{
errCod = 0;
if(mvf.analysis(ull_usedClusters, errCod))
{
errCod = 0;
if(mvf.move(m_hVolum, m_mapLst, errCod));
else fleLog << " mov ->" << str_fullName << endl << "errCod" << " = " << errCod << endl;
}
else
fleLog << " ana ->" << str_fullName << endl << "errCod" << " = " << errCod << endl;
}
else fleLog << " ini ->" << str_fullName << endl;
fleLog.close();
}
str_fullName += "//*";
browse(str_fullName);
}
}
//file dealed code
else
{
string stedbg = wfd.cFileName;
str_fullName = strdir + stedbg;
MovFle mvf;
fleLog.open("volLog.txt", ios_base::app);
fleLog << str_fullName << endl;
if(mvf.init(str_fullName, m_ptr))
{
errCod = 0;
if(mvf.analysis(ull_usedClusters, errCod))
{
errCod = 0;
//dbg
cout << "start mov " << str_fullName << endl;
if(mvf.move(m_hVolum, m_mapLst, errCod));
else fleLog << " mov ->" << str_fullName << endl << "errCod" << " = " << errCod << endl;
}
else
fleLog << " ana ->" << str_fullName << endl << "errCod" << " = " << errCod << endl;
}
else fleLog << " ini ->" << str_fullName << endl;
fleLog.close();
}
} while(FindNextFile(m_hFle, &wfd));
}
if (INVALID_HANDLE_VALUE != m_hFle)
{
FindClose(m_hFle);
}
}
void VolTdy::beginBowse()
{
browse(m_volumeName);
}
#ifndef DDK_H
#define DDK_H
#define FSCTLMOVEFILE 0x90074
//
// return code type
//
typedef UINT NTSTATUS;
//
// Error codes returned by NtFsControlFile (see NTSTATUS.H)
//
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
#define STATUS_ALREADY_COMMITTED ((NTSTATUS)0xC0000021L)
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS)0xC0000010L)
//--------------------------------------------------------------------
// F S C T L S P E C I F I C T Y P E D E F S
//--------------------------------------------------------------------
//
// This is the definition for a VCN/LCN (virtual cluster/logical cluster)
// mapping pair that is returned in the buffer passed to
// FSCTL_GET_RETRIEVAL_POINTERS
//
typedef struct {
ULONGLONG Vcn;
ULONGLONG Lcn;
} MAPPING_PAIR, *PMAPPING_PAIR;
//
// This is the definition for the buffer that FSCTL_GET_RETRIEVAL_POINTERS
// returns. It consists of a header followed by mapping pairs
//
typedef struct {
ULONG NumberOfPairs;
ULONGLONG StartVcn;
MAPPING_PAIR Pair[1];
} GET_RETRIEVAL_DESCRIPTOR, *PGET_RETRIEVAL_DESCRIPTOR;
//
// This is the definition of the buffer that FSCTL_GET_VOLUME_BITMAP
// returns. It consists of a header followed by the actual bitmap data
//
typedef struct {
ULONGLONG StartLcn;
ULONGLONG ClustersToEndOfVol;
BYTE Map[1];
} BITMAP_DESCRIPTOR, *PBITMAP_DESCRIPTOR;
//
// This is the definition for the data structure that is passed in to
// FSCTL_MOVE_FILE
//
typedef struct {
HANDLE FileHandle;
ULONG Reserved;
LARGE_INTEGER StartVcn;
LARGE_INTEGER TargetLcn;
ULONG NumVcns;
ULONG Reserved1;
} MOVEFILE_DESCRIPTOR, *PMOVEFILE_DESCRIPTOR;
/*
typedef struct {
HANDLE FileHandle;
ULONGLONG Reserved;
LARGE_INTEGER StartVcn;
LARGE_INTEGER TargetLcn;
ULONGLONG NumVcns;
ULONGLONG Reserved1;
} MOVEFILE_DESCRIPTOR, *PMOVEFILE_DESCRIPTOR;
*/
//--------------------------------------------------------------------
// N T F S C O N T R O L F I L E D E F I N I T I O N S
//--------------------------------------------------------------------
//
// Prototype for NtFsControlFile and data structures
// used in its definition
//
//
// Io Status block (see NTDDK.H)
//
typedef struct _IO_STATUS_BLOCK {
NTSTATUS Status;
ULONG Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
//
// Apc Routine (see NTDDK.H)
//
typedef VOID (*PIO_APC_ROUTINE) (
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved
);
//typedef int (*MYPROC)(LPTSTR);
typedef NTSTATUS (__stdcall *MyNtFsControlFile)(
HANDLE FileHandle,
HANDLE Event, // optional
PIO_APC_ROUTINE ApcRoutine, // optional
PVOID ApcContext, // optional
PIO_STATUS_BLOCK IoStatusBlock,
ULONG FsControlCode,
PVOID InputBuffer, // optional
ULONG InputBufferLength,
PVOID OutputBuffer, // optional
ULONG OutputBufferLength
);
#endif
#include "voltdy.h"
#include <iostream>
#include "windows.h"
#include "ddk.h"
int main(int argc, char **argv)
{
DWORD dwTime = GetTickCount();
//get ntfscontrolfile pointer
MyNtFsControlFile ntp = NULL;
ntp = (MyNtFsControlFile) GetProcAddress( GetModuleHandle("ntdll.dll"),"NtFsControlFile");
if(!ntp)
{
cout << "Could not find NtFsControlFile entry point in NTDLL.DLL/n";
return 1;
}
//clean log file
fstream outfle("volLog.txt", ios_base::out);
if (!outfle)
{
cout << "err clean log" << endl;
}
outfle.close();
//choose the disk
cout << "Please input disk : ";
string strdic;
cin >> strdic;
//run
VolTdy vtd;
BOOL bIsOk = vtd.initVolume(strdic, ntp); //ok
if (!bIsOk)
{
cout << "err initVolume function" << endl;
return 1;
}
DWORD errCod = 0;
bIsOk = vtd.getMapLst(errCod); //ok
if (!bIsOk)
{
cout << "err getMapLst function" << endl;
return 1;
}
vtd.beginBowse(); //ok
cout<< GetTickCount() - dwTime<<endl;
return 0;
}
#define BITMAP_H
#define _WIN32_WINNT 0x600
#include "windows.h"
#include "winioctl.h"
#include <vector>
#include <map>
using namespace std;
class BitMap
{
public:
void getMapList(const VOLUME_BITMAP_BUFFER *pInBuff);
void dispalyMapListOfFree() const;
void showVecOfBit() const;
const map<ULONGLONG, ULONGLONG> & returnMaplist() const;
const vector<bool> & returnBitVec() const;
private:
map<ULONGLONG, ULONGLONG> mapListOfFree;
vector<bool> vecOfBit;
};
#endif
#include "bitmap.h"
#include <iostream>
#include <bitset>
#include <fstream>
void BitMap::getMapList(const VOLUME_BITMAP_BUFFER *pInBuff)
{
ULONGLONG count_size = 0;
ULONGLONG size_clusterarray = (pInBuff -> BitmapSize.QuadPart + 7) / 8;
while (count_size != size_clusterarray)
{
bitset<8> bit(*(pInBuff -> Buffer + count_size));
for (int i = 0; i != 8; ++i)
{
vecOfBit.push_back(bit[i]);
}
count_size++;
}
if (vecOfBit.size() != pInBuff -> BitmapSize.QuadPart)
{
ULONGLONG popnum = vecOfBit.size() - pInBuff -> BitmapSize.QuadPart;
for (ULONGLONG i = 0; i < popnum; ++i)
{
vecOfBit.pop_back();
}
}
ULONGLONG add = 0;
__w64 unsigned int/*ULONGLONG*/ size = 0;
for (__w64 unsigned int/*ULONGLONG*/ i = 0; i < vecOfBit.size();)
{
size = 0;
if (vecOfBit[i] == 0)
{
add = i;
__w64 unsigned int/*ULONGLONG*/ idx = i;
while ((idx < vecOfBit.size()) && !vecOfBit[idx]) //
{
size ++;
idx++;
}
i += size;
mapListOfFree.insert(make_pair(add, size));
}
else
{
i++;
continue;
}
}
}
void BitMap::showVecOfBit() const
{
fstream vecbit("bitmap.txt", ios_base::out);
if (!vecbit) return;
for (__w64 unsigned int/*ULONGLONG*/ i = 0; i < vecOfBit.size(); ++i)
{
if (i % 32 == 0)
{
vecbit << endl;
}
vecbit << (DWORD)vecOfBit[i] << " ";
}
vecbit.close();
}
void BitMap::dispalyMapListOfFree() const
{
cout << "Free Space List <start cluster number, free space size>" << endl;
for (map<ULONGLONG, ULONGLONG>::const_iterator cit = mapListOfFree.begin(); cit != mapListOfFree.end(); ++cit)
{
cout << "address: " << ULONG((*cit).first) << "/tsize: " << ULONG((*cit).second) << endl;
}
}
const map<ULONGLONG, ULONGLONG>& BitMap::returnMaplist() const
{
return mapListOfFree;
}
const vector<bool>& BitMap::returnBitVec() const
{
return vecOfBit;
}
#ifndef MOVFLE_H
#define NOVFLE_H
#include <string>
#include <map>
using namespace std;
#define _WIN32_WINNT 0x600
#include "windows.h"
#include "winioctl.h"
#include "ddk.h"
class MovFle
{
public:
BOOL init(string str_fileFullPathName, MyNtFsControlFile ptr);
BOOL analysis(ULONGLONG ull_usedClusters, DWORD &rerCod);
BOOL move(HANDLE hVolum, map<ULONGLONG, ULONGLONG> &rmapList, DWORD &rerCod); //pair<addres, size> free space
void displayFileMapList() const;
~MovFle();
private:
HANDLE m_hFle;
map<ULONGLONG, ULONGLONG> m_mapAnalysised; //file should move
string m_strFileName;
MyNtFsControlFile m_mptr;
};
#endif
#include "movfle.h"
#include <vector>
#include <utility>
#include<fstream>
#include <iostream>
BOOL MovFle::init(string str_fileFullPathName, MyNtFsControlFile ptr)
{
m_strFileName = str_fileFullPathName;
m_hFle = CreateFile(str_fileFullPathName.c_str(), GENERIC_READ/* | GENERIC_WRITE | FILE_READ_DATA | FILE_WRITE_DATA | FILE_APPEND_DATA| FILE_EXECUTE | FILE_READ_ATTRIBUTES*/,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
/*FILE_ATTRIBUTE_NORMAL*/FILE_FLAG_NO_BUFFERING, NULL);
if (INVALID_HANDLE_VALUE == m_hFle)
{
//may be a directory name
m_hFle = CreateFile (str_fileFullPathName.c_str(), GENERIC_READ | FILE_SHARE_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
if (INVALID_HANDLE_VALUE != m_hFle)
{
m_mptr = ptr;
return TRUE;
}
return FALSE;
}
m_mptr = ptr;
return TRUE;
}
MovFle::~MovFle()
{
if (INVALID_HANDLE_VALUE != m_hFle)
{
CloseHandle(m_hFle);
}
}
BOOL MovFle::analysis(ULONGLONG ull_usedClusters, DWORD &rerCod)
{
STARTING_VCN_INPUT_BUFFER inbuff;
inbuff.StartingVcn.QuadPart = 0;
RETRIEVAL_POINTERS_BUFFER outbuf;
ULONGLONG ull_DealedVcn = 0;
BOOL bIsOk;
DWORD dwReturnBytes = 0;
vector<pair<pair<ULONGLONG, ULONGLONG>, ULONGLONG> > vecFileBlock;
//<<startVcn, Lcn>, size>
do
{
bIsOk = DeviceIoControl(m_hFle, FSCTL_GET_RETRIEVAL_POINTERS, &inbuff,
sizeof(STARTING_VCN_INPUT_BUFFER), &outbuf, sizeof(RETRIEVAL_POINTERS_BUFFER), &dwReturnBytes, NULL);
rerCod = GetLastError();
//for dealing directory
if (outbuf.ExtentCount == 0)
break;
vecFileBlock.push_back(make_pair(make_pair(outbuf.StartingVcn.QuadPart, outbuf.Extents[0].Lcn.QuadPart), outbuf.Extents[0].NextVcn.QuadPart - outbuf.StartingVcn.QuadPart));
inbuff.StartingVcn.QuadPart = outbuf.Extents[0].NextVcn.QuadPart;
} while((!bIsOk) && (rerCod == ERROR_MORE_DATA));
//analysis and make
for (DWORD currentBlock = 0; currentBlock != vecFileBlock.size(); ++currentBlock)
{
if (vecFileBlock[currentBlock].first.second >= ull_usedClusters)
{
m_mapAnalysised.insert(make_pair(vecFileBlock[currentBlock].first.first, vecFileBlock[currentBlock].second));
}
else
{
if (vecFileBlock[currentBlock].first.second + vecFileBlock[currentBlock].second > ull_usedClusters)
{
m_mapAnalysised.insert(make_pair((vecFileBlock[currentBlock].first.first + (ull_usedClusters - vecFileBlock[currentBlock].first.second)),
(vecFileBlock[currentBlock].first.second + vecFileBlock[currentBlock].second - ull_usedClusters)));
}
}
}
if (m_mapAnalysised.size() != 0)
{
displayFileMapList();
}
BOOL result = (m_mapAnalysised.size() == 0) ? FALSE : TRUE;
return result;
}
void MovFle::displayFileMapList() const
{
cout << m_strFileName << "-> maplist : " << endl;
map<ULONGLONG, ULONGLONG>::const_iterator cit = m_mapAnalysised.begin();
for (; cit != m_mapAnalysised.end(); ++cit)
{
cout << "startVcn : " << cit -> first << " " << "size : " << cit -> second << endl;
}
cout << endl;
}
/*
BOOL MovFle::move(HANDLE hVolum, std::map<ULONGLONG,ULONGLONG> &rmapList, DWORD &rerCod)
{
MOVE_FILE_DATA mfd;
mfd.FileHandle = m_hFle;
BOOL bIsOk = TRUE;
DWORD dwReturnBytes = 0;
ULONGLONG ull_startVcnInBlock = 0;
if (rmapList.empty())
{
return FALSE;
}
map<ULONGLONG, ULONGLONG>::iterator ite = rmapList.begin();
for (map<ULONGLONG, ULONGLONG>::const_iterator cit = m_mapAnalysised.begin(); cit != m_mapAnalysised.end(); ++ cit)
{
//check rmaplist size
if (rmapList.size() == 0)
{
return FALSE;
}
//deal each block
ULONGLONG ull_vcnInBlock = cit -> second;
ULONGLONG ull_dealedVcnInBlock = 0;
ull_startVcnInBlock = cit -> first;
while (ull_dealedVcnInBlock < ull_vcnInBlock)
{
//check rmapList size
if (rmapList.size() == 0)
{
return FALSE;
}
ite = rmapList.begin(); //always points to the first item
if (ull_vcnInBlock - ull_dealedVcnInBlock <= ite -> second) //space is enough
{
if (ull_vcnInBlock - ull_dealedVcnInBlock == ite -> second) //==
{
mfd.ClusterCount = ite -> second;
mfd.StartingVcn.QuadPart = ull_startVcnInBlock + ull_dealedVcnInBlock;
mfd.StartingLcn.QuadPart = ite -> first;
//dbg
cout << "now mov clusters : " << endl;
cout << "ClusterCount : "<< mfd.ClusterCount << endl;
cout << "StartingVcn : "<< mfd.StartingVcn.QuadPart << endl;
cout << "StartingLcn : "<< mfd.StartingLcn.QuadPart << endl;
bIsOk = DeviceIoControl(m_hFle, FSCTL_MOVE_FILE, &mfd, sizeof(MOVE_FILE_DATA),
NULL, 0, &dwReturnBytes, NULL);
if (!bIsOk)
{
rerCod = GetLastError();
//dbg
cout << "error : " << endl;
cout << "ClusterCount : "<< mfd.ClusterCount << endl;
cout << "StartingVcn : "<< mfd.StartingVcn.QuadPart << endl;
cout << "StartingLcn : "<< mfd.StartingLcn.QuadPart << endl;
cout << "errcod : " << rerCod << endl;
return FALSE;
}
else
{
rmapList.erase(ite);
}
}
else //<
{
mfd.ClusterCount = ull_vcnInBlock - ull_dealedVcnInBlock;
mfd.StartingVcn.QuadPart = ull_startVcnInBlock + ull_dealedVcnInBlock;
mfd.StartingLcn.QuadPart = ite -> first;
//dbg
cout << "now mov clusters : " << endl;;
cout << "ClusterCount : "<< mfd.ClusterCount << endl;
cout << "StartingVcn : "<< mfd.StartingVcn.QuadPart << endl;
cout << "StartingLcn : "<< mfd.StartingLcn.QuadPart << endl;
bIsOk = DeviceIoControl(m_hFle, FSCTL_MOVE_FILE, &mfd, sizeof(MOVE_FILE_DATA),
NULL, 0, &dwReturnBytes, NULL);
if (!bIsOk)
{
rerCod = GetLastError();
//dbg
cout << "error : " << endl;
cout << "ClusterCount : "<< mfd.ClusterCount << endl;
cout << "StartingVcn : "<< mfd.StartingVcn.QuadPart << endl;
cout << "StartingLcn : "<< mfd.StartingLcn.QuadPart << endl;
cout << "errcod : " << rerCod << endl;
return FALSE;
}
else
{
pair<ULONGLONG, ULONGLONG> tmppar = *ite;
rmapList.erase(ite);
rmapList.insert(make_pair(tmppar.first + mfd.ClusterCount, tmppar.second - mfd.ClusterCount));
}
}
}
else //> space is not enough
{
mfd.ClusterCount = ite -> second;
mfd.StartingVcn.QuadPart = ull_startVcnInBlock + ull_dealedVcnInBlock;
mfd.StartingLcn.QuadPart = ite -> first;
bIsOk = DeviceIoControl(m_hFle, FSCTL_MOVE_FILE, &mfd, sizeof(MOVE_FILE_DATA),
NULL, 0, &dwReturnBytes, NULL);
if (!bIsOk)
{
rerCod = GetLastError();
return FALSE;
}
else
{
rmapList.erase(ite);
}
}
ull_dealedVcnInBlock += mfd.ClusterCount;
} //while
} //for
return TRUE;
}
*/
BOOL MovFle::move(HANDLE hVolum, std::map<ULONGLONG,ULONGLONG> &rmapList, DWORD &rerCod)
{
if (!m_mptr)
{
cout << "null function pointer" << endl;
return FALSE;
}
MOVEFILE_DESCRIPTOR mfd;
mfd.FileHandle = m_hFle;
DWORD status = 0;
IO_STATUS_BLOCK ioStatus;
BOOL bIsOk = TRUE;
DWORD dwReturnBytes = 0;
ULONGLONG ull_startVcnInBlock = 0;
if (rmapList.empty())
{
return FALSE;
}
map<ULONGLONG, ULONGLONG>::iterator ite = rmapList.begin();
for (map<ULONGLONG, ULONGLONG>::const_iterator cit = m_mapAnalysised.begin(); cit != m_mapAnalysised.end(); ++ cit)
{
//check rmaplist size
if (rmapList.size() == 0)
{
return FALSE;
}
//deal each block
ULONGLONG ull_vcnInBlock = cit -> second;
ULONGLONG ull_dealedVcnInBlock = 0;
ull_startVcnInBlock = cit -> first;
while (ull_dealedVcnInBlock < ull_vcnInBlock)
{
//check rmapList size
if (rmapList.size() == 0)
{
return FALSE;
}
ite = rmapList.begin(); //always points to the first item
if (ull_vcnInBlock - ull_dealedVcnInBlock <= ite -> second) //space is enough
{
if (ull_vcnInBlock - ull_dealedVcnInBlock == ite -> second) //==
{
mfd.NumVcns = ite -> second;
mfd.StartVcn.QuadPart = ull_startVcnInBlock + ull_dealedVcnInBlock;
mfd.TargetLcn.QuadPart = ite -> first;
/*
bIsOk = DeviceIoControl(m_hFle, FSCTL_MOVE_FILE, &mfd, sizeof(MOVE_FILE_DATA),
NULL, 0, &dwReturnBytes, NULL);
*/
status = m_mptr( hVolum, NULL, NULL, 0, &ioStatus,
FSCTLMOVEFILE,
&mfd, sizeof(mfd),
NULL, 0 );
//
// If the operation is pending, wait for it to finish
//
if( status == STATUS_PENDING ) {
WaitForSingleObject(m_hFle, INFINITE);
status = ioStatus.Status;
}
if (status != STATUS_SUCCESS)
{
rerCod = status;
return FALSE;
}
else
{
rmapList.erase(ite);
}
}
else //<
{
mfd.NumVcns = ull_vcnInBlock - ull_dealedVcnInBlock;
mfd.StartVcn.QuadPart = ull_startVcnInBlock + ull_dealedVcnInBlock;
mfd.TargetLcn.QuadPart = ite -> first;
/*
bIsOk = DeviceIoControl(m_hFle, FSCTL_MOVE_FILE, &mfd, sizeof(MOVE_FILE_DATA),
NULL, 0, &dwReturnBytes, NULL);
*/
status = m_mptr( hVolum, NULL, NULL, 0, &ioStatus,
FSCTLMOVEFILE,
&mfd, sizeof(mfd),
NULL, 0 );
if( status == STATUS_PENDING ) {
WaitForSingleObject(m_hFle, INFINITE);
status = ioStatus.Status;
}
if (status != STATUS_SUCCESS)
{
rerCod = status;
return FALSE;
}
else
{
pair<ULONGLONG, ULONGLONG> tmppar = *ite;
rmapList.erase(ite);
rmapList.insert(make_pair(tmppar.first + mfd.NumVcns, tmppar.second - mfd.NumVcns));
}
}
}
else //> space is not enough
{
mfd.NumVcns = ite -> second;
mfd.StartVcn.QuadPart = ull_startVcnInBlock + ull_dealedVcnInBlock;
mfd.TargetLcn.QuadPart = ite -> first;
/*
bIsOk = DeviceIoControl(m_hFle, FSCTL_MOVE_FILE, &mfd, sizeof(MOVE_FILE_DATA),
NULL, 0, &dwReturnBytes, NULL);
*/
status = m_mptr( hVolum, NULL, NULL, 0, &ioStatus,
FSCTLMOVEFILE,
&mfd, sizeof(mfd),
NULL, 0 );
//
// If the operation is pending, wait for it to finish
//
if( status == STATUS_PENDING ) {
WaitForSingleObject(m_hFle, INFINITE);
status = ioStatus.Status;
}
if (status != STATUS_SUCCESS)
{
rerCod = status;
return FALSE;
}
else
{
rmapList.erase(ite);
}
}
ull_dealedVcnInBlock += mfd.NumVcns;
} //while
} //for
return TRUE;
}
#ifndef VOLTDY_H
#define VOLTDY_H
#include "bitmap.h"
#include <string>
#include <algorithm>
#include <fstream>
using namespace std;
#include "windows.h"
#include "ddk.h"
class VolTdy
{
public:
BOOL initVolume(string str_volumeName, MyNtFsControlFile ptr);
BOOL getMapLst(DWORD &rerCod);
void beginBowse();
~VolTdy();
private:
void browse(string strdir);
map<ULONGLONG, ULONGLONG> m_mapLst;
HANDLE m_hVolum;
string m_volumeName;
ULONGLONG ull_usedClusters;
MyNtFsControlFile m_ptr;
fstream fleLog;
};
#endif
#include "voltdy.h"
#include <iostream>
#include "movfle.h"
BOOL VolTdy::initVolume(string str_volumeName, MyNtFsControlFile ptr)
{
m_volumeName = str_volumeName[0];
m_volumeName += ":";
m_volumeName = ".//" + m_volumeName;
m_hVolum = CreateFile(m_volumeName.c_str(), /*FILE_READ_DATA | FILE_WRITE_DATA |FILE_APPEND_DATA | FILE_EXECUTE | FILE_READ_ATTRIBUTES | */GENERIC_READ/* | GENERIC_WRITE*/,
FILE_SHARE_READ | FILE_SHARE_WRITE , NULL, OPEN_EXISTING,
/*FILE_ATTRIBUTE_NORMAL*/ 0, NULL);
if (INVALID_HANDLE_VALUE == m_hVolum)
{
return FALSE;
}
//for browse use
m_volumeName = str_volumeName[0];
m_volumeName += "://*";
ull_usedClusters = 0;
m_ptr = ptr;
return TRUE;
}
VolTdy::~VolTdy()
{
if (m_hVolum != INVALID_HANDLE_VALUE)
{
CloseHandle(m_hVolum);
}
}
BOOL VolTdy::getMapLst(DWORD &rerCod)
{
BOOL bIsOk;
STARTING_LCN_INPUT_BUFFER start_lcn_buf;
start_lcn_buf.StartingLcn.QuadPart = 0;
VOLUME_BITMAP_BUFFER bitmap_buf_org;
VOLUME_BITMAP_BUFFER *pbitmap_buf = 0;
DWORD dwOutSize = 0;
ULONGLONG ullNumClusters = 0;
DWORD dwReturnBytes = 0;
bIsOk = DeviceIoControl(m_hVolum, FSCTL_GET_VOLUME_BITMAP, &start_lcn_buf, sizeof(STARTING_LCN_INPUT_BUFFER),
&bitmap_buf_org, sizeof(VOLUME_BITMAP_BUFFER), &dwReturnBytes, NULL);
if (!bIsOk && GetLastError() == ERROR_MORE_DATA)
{
//debug
ullNumClusters = bitmap_buf_org.BitmapSize.QuadPart - bitmap_buf_org.StartingLcn.QuadPart;
dwOutSize = ullNumClusters/sizeof(byte) + sizeof(VOLUME_BITMAP_BUFFER);
pbitmap_buf = (VOLUME_BITMAP_BUFFER *)new byte[dwOutSize];
if (!pbitmap_buf) return FALSE;
bIsOk = DeviceIoControl(m_hVolum, FSCTL_GET_VOLUME_BITMAP, &start_lcn_buf, sizeof(start_lcn_buf),
pbitmap_buf, dwOutSize, &dwReturnBytes, NULL);
if (!bIsOk)
{
if (pbitmap_buf)
{
delete [] pbitmap_buf;
pbitmap_buf = 0;
}
rerCod = GetLastError();
return FALSE;
}
}
BitMap bitmap;
bitmap.getMapList(pbitmap_buf);
delete [] pbitmap_buf;
pbitmap_buf = 0;
bitmap.dispalyMapListOfFree();
m_mapLst = bitmap.returnMaplist();
ull_usedClusters = count(bitmap.returnBitVec().begin(), bitmap.returnBitVec().end(), true);
cout << ull_usedClusters << "ull_usedClusters" << endl;
// bitmap.showVecOfBit();
return TRUE;
}
void VolTdy::browse(string strdir) //strdir, for directory, sample "F:/*"
{
WIN32_FIND_DATAA wfd;
HANDLE m_hFle = FindFirstFile(strdir.c_str(), &wfd);
strdir.resize(strdir.size() - 1);
DWORD errCod = 0;
if (INVALID_HANDLE_VALUE != m_hFle)
{
do
{
string str_fullName;
errCod = 0;
//directory dealed code
if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
string tmp = wfd.cFileName;
if ((tmp != ".") && (tmp != ".."))
{
string stedbg = wfd.cFileName;
str_fullName = strdir + stedbg;
//for desturctor run
{
MovFle mvf;
fleLog.open("volLog.txt", ios_base::app);
fleLog << str_fullName << endl;
if(mvf.init(str_fullName, m_ptr))
{
errCod = 0;
if(mvf.analysis(ull_usedClusters, errCod))
{
errCod = 0;
if(mvf.move(m_hVolum, m_mapLst, errCod));
else fleLog << " mov ->" << str_fullName << endl << "errCod" << " = " << errCod << endl;
}
else
fleLog << " ana ->" << str_fullName << endl << "errCod" << " = " << errCod << endl;
}
else fleLog << " ini ->" << str_fullName << endl;
fleLog.close();
}
str_fullName += "//*";
browse(str_fullName);
}
}
//file dealed code
else
{
string stedbg = wfd.cFileName;
str_fullName = strdir + stedbg;
MovFle mvf;
fleLog.open("volLog.txt", ios_base::app);
fleLog << str_fullName << endl;
if(mvf.init(str_fullName, m_ptr))
{
errCod = 0;
if(mvf.analysis(ull_usedClusters, errCod))
{
errCod = 0;
//dbg
cout << "start mov " << str_fullName << endl;
if(mvf.move(m_hVolum, m_mapLst, errCod));
else fleLog << " mov ->" << str_fullName << endl << "errCod" << " = " << errCod << endl;
}
else
fleLog << " ana ->" << str_fullName << endl << "errCod" << " = " << errCod << endl;
}
else fleLog << " ini ->" << str_fullName << endl;
fleLog.close();
}
} while(FindNextFile(m_hFle, &wfd));
}
if (INVALID_HANDLE_VALUE != m_hFle)
{
FindClose(m_hFle);
}
}
void VolTdy::beginBowse()
{
browse(m_volumeName);
}
#ifndef DDK_H
#define DDK_H
#define FSCTLMOVEFILE 0x90074
//
// return code type
//
typedef UINT NTSTATUS;
//
// Error codes returned by NtFsControlFile (see NTSTATUS.H)
//
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
#define STATUS_BUFFER_OVERFLOW ((NTSTATUS)0x80000005L)
#define STATUS_INVALID_PARAMETER ((NTSTATUS)0xC000000DL)
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
#define STATUS_ALREADY_COMMITTED ((NTSTATUS)0xC0000021L)
#define STATUS_INVALID_DEVICE_REQUEST ((NTSTATUS)0xC0000010L)
//--------------------------------------------------------------------
// F S C T L S P E C I F I C T Y P E D E F S
//--------------------------------------------------------------------
//
// This is the definition for a VCN/LCN (virtual cluster/logical cluster)
// mapping pair that is returned in the buffer passed to
// FSCTL_GET_RETRIEVAL_POINTERS
//
typedef struct {
ULONGLONG Vcn;
ULONGLONG Lcn;
} MAPPING_PAIR, *PMAPPING_PAIR;
//
// This is the definition for the buffer that FSCTL_GET_RETRIEVAL_POINTERS
// returns. It consists of a header followed by mapping pairs
//
typedef struct {
ULONG NumberOfPairs;
ULONGLONG StartVcn;
MAPPING_PAIR Pair[1];
} GET_RETRIEVAL_DESCRIPTOR, *PGET_RETRIEVAL_DESCRIPTOR;
//
// This is the definition of the buffer that FSCTL_GET_VOLUME_BITMAP
// returns. It consists of a header followed by the actual bitmap data
//
typedef struct {
ULONGLONG StartLcn;
ULONGLONG ClustersToEndOfVol;
BYTE Map[1];
} BITMAP_DESCRIPTOR, *PBITMAP_DESCRIPTOR;
//
// This is the definition for the data structure that is passed in to
// FSCTL_MOVE_FILE
//
typedef struct {
HANDLE FileHandle;
ULONG Reserved;
LARGE_INTEGER StartVcn;
LARGE_INTEGER TargetLcn;
ULONG NumVcns;
ULONG Reserved1;
} MOVEFILE_DESCRIPTOR, *PMOVEFILE_DESCRIPTOR;
/*
typedef struct {
HANDLE FileHandle;
ULONGLONG Reserved;
LARGE_INTEGER StartVcn;
LARGE_INTEGER TargetLcn;
ULONGLONG NumVcns;
ULONGLONG Reserved1;
} MOVEFILE_DESCRIPTOR, *PMOVEFILE_DESCRIPTOR;
*/
//--------------------------------------------------------------------
// N T F S C O N T R O L F I L E D E F I N I T I O N S
//--------------------------------------------------------------------
//
// Prototype for NtFsControlFile and data structures
// used in its definition
//
//
// Io Status block (see NTDDK.H)
//
typedef struct _IO_STATUS_BLOCK {
NTSTATUS Status;
ULONG Information;
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
//
// Apc Routine (see NTDDK.H)
//
typedef VOID (*PIO_APC_ROUTINE) (
PVOID ApcContext,
PIO_STATUS_BLOCK IoStatusBlock,
ULONG Reserved
);
//typedef int (*MYPROC)(LPTSTR);
typedef NTSTATUS (__stdcall *MyNtFsControlFile)(
HANDLE FileHandle,
HANDLE Event, // optional
PIO_APC_ROUTINE ApcRoutine, // optional
PVOID ApcContext, // optional
PIO_STATUS_BLOCK IoStatusBlock,
ULONG FsControlCode,
PVOID InputBuffer, // optional
ULONG InputBufferLength,
PVOID OutputBuffer, // optional
ULONG OutputBufferLength
);
#endif
#include "voltdy.h"
#include <iostream>
#include "windows.h"
#include "ddk.h"
int main(int argc, char **argv)
{
DWORD dwTime = GetTickCount();
//get ntfscontrolfile pointer
MyNtFsControlFile ntp = NULL;
ntp = (MyNtFsControlFile) GetProcAddress( GetModuleHandle("ntdll.dll"),"NtFsControlFile");
if(!ntp)
{
cout << "Could not find NtFsControlFile entry point in NTDLL.DLL/n";
return 1;
}
//clean log file
fstream outfle("volLog.txt", ios_base::out);
if (!outfle)
{
cout << "err clean log" << endl;
}
outfle.close();
//choose the disk
cout << "Please input disk : ";
string strdic;
cin >> strdic;
//run
VolTdy vtd;
BOOL bIsOk = vtd.initVolume(strdic, ntp); //ok
if (!bIsOk)
{
cout << "err initVolume function" << endl;
return 1;
}
DWORD errCod = 0;
bIsOk = vtd.getMapLst(errCod); //ok
if (!bIsOk)
{
cout << "err getMapLst function" << endl;
return 1;
}
vtd.beginBowse(); //ok
cout<< GetTickCount() - dwTime<<endl;
return 0;
}