📄 drivevolume.cpp
字号:
Info.Attributes.Compressed = (FindData.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) ? 1 : 0;
Info.Attributes.Directory = (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
Info.Attributes.Encrypted = (FindData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) ? 1 : 0;
Info.Attributes.Hidden = (FindData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? 1 : 0;
Info.Attributes.Normal = (FindData.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ? 1 : 0;
Info.Attributes.Offline = (FindData.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) ? 1 : 0;
Info.Attributes.ReadOnly = (FindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 1 : 0;
Info.Attributes.Reparse = (FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0;
Info.Attributes.Sparse = (FindData.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) ? 1 : 0;
Info.Attributes.System = (FindData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? 1 : 0;
Info.Attributes.Temporary = (FindData.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? 1 : 0;
Info.Attributes.AccessDenied = 0;
Info.Attributes.Unmovable = 0;
Info.Attributes.Process = 1;
Info.Clusters = 0;
if (GetClusterInfo (Info, Handle))
{
uint64 TotalClusters = 0;
for (int i = 0; i < Info.Fragments.size(); i++)
{
TotalClusters += Info.Fragments[i].Length;
}
Info.Clusters = TotalClusters;
}
else
{
Info.Attributes.Unmovable = 1;
Info.Attributes.Process = 0;
}
if (Info.Attributes.Process == 1)
Info.Attributes.Process = ShouldProcess (Info.Attributes) ? 1 : 0;
// Run the user-defined callback function
CallbackResult = Callback (Info, Handle, UserData);
if (Handle != INVALID_HANDLE_VALUE)
CloseHandle (Handle);
if (!CallbackResult)
break;
// If directory, perform recursion
if (Info.Attributes.Directory == 1)
{
wstring Dir;
Dir = GetDBDir (Info.DirIndice);
Dir += Info.Name;
Dir += L"\\";
Directories.push_back (Dir);
ScanDirectory (Dir, Callback, UserData);
}
} while (FindNextFile (FindHandle, &FindData) == TRUE);
FindClose (FindHandle);
return (false);
}
bool DriveVolume::ShouldProcess (FileAttr Attr)
{
if (Attr.Offline == 1 || Attr.Reparse == 1 || Attr.Temporary == 1)
{
return (false);
}
return (true);
}
// Gets info on a file and returns a valid handle for read/write access
// Name, FullName, Clusters, Attributes, and Size should already be filled out.
// This function fills in the Fragments vector
bool DriveVolume::GetClusterInfo (FileInfo &Info, HANDLE &HandleResult)
{
BOOL Result;
HANDLE Handle;
wstring FullName;
BY_HANDLE_FILE_INFORMATION FileInfo;
Info.Fragments.resize (0);
/*
if (Info.Attributes.Directory == 1)
return (false);
*/
FullName = GetDBDir (Info.DirIndice) + Info.Name;
Handle = CreateFile
(
FullName.c_str(),
0, //GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
(Info.Attributes.Directory == 1) ? FILE_FLAG_BACKUP_SEMANTICS : 0,
NULL
);
if (Handle == INVALID_HANDLE_VALUE)
{
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf, 0, NULL );
Info.Attributes.AccessDenied = 1;
LocalFree( lpMsgBuf );
return (false);
}
ZeroMemory (&FileInfo, sizeof (FileInfo));
Result = GetFileInformationByHandle (Handle, &FileInfo);
if (Result == FALSE)
{
Info.Attributes.AccessDenied = 1;
wprintf (L"GetFileInformationByHandle ('%s%s') failed\n", GetDBDir (Info.DirIndice).c_str(),
Info.Name.c_str());
CloseHandle (Handle);
return (false);
}
// Get cluster allocation information
STARTING_VCN_INPUT_BUFFER StartingVCN;
RETRIEVAL_POINTERS_BUFFER *Retrieval;
uint64 RetSize;
uint64 Extents;
DWORD BytesReturned;
// Grab info one extent at a time, until it's done grabbing all the extent data
// Yeah, well it doesn't give us a way to ask L"how many extents?" that I know of ...
// btw, the Extents variable tends to only reflect memory usage, so when we have
// all the extents we look at the structure Win32 gives us for the REAL count!
Extents = 10;
Retrieval = NULL;
RetSize = 0;
StartingVCN.StartingVcn.QuadPart = 0;
do
{
Extents *= 2;
RetSize = sizeof (RETRIEVAL_POINTERS_BUFFER) + ((Extents - 1) * sizeof (LARGE_INTEGER) * 2);
if (Retrieval != NULL)
Retrieval = (RETRIEVAL_POINTERS_BUFFER *) realloc (Retrieval, RetSize);
else
Retrieval = (RETRIEVAL_POINTERS_BUFFER *) malloc (RetSize);
Result = DeviceIoControl
(
Handle,
FSCTL_GET_RETRIEVAL_POINTERS,
&StartingVCN,
sizeof (StartingVCN),
Retrieval,
RetSize,
&BytesReturned,
NULL
);
if (Result == FALSE)
{
if (GetLastError() != ERROR_MORE_DATA)
{
Info.Clusters = 0;
Info.Attributes.AccessDenied = 1;
Info.Attributes.Process = 0;
Info.Fragments.clear ();
CloseHandle (Handle);
free (Retrieval);
return (false);
}
Extents++;
}
} while (Result == FALSE);
// Readjust extents, as it only reflects how much memory was allocated and may not
// be accurate
Extents = Retrieval->ExtentCount;
// Ok, we have the info. Now translate it. hrmrmr
int i;
Info.Fragments.clear ();
for (i = 0; i < Extents; i++)
{
Extent Add;
Add.StartLCN = Retrieval->Extents[i].Lcn.QuadPart;
if (i != 0)
Add.Length = Retrieval->Extents[i].NextVcn.QuadPart - Retrieval->Extents[i - 1].NextVcn.QuadPart;
else
Add.Length = Retrieval->Extents[i].NextVcn.QuadPart - Retrieval->StartingVcn.QuadPart;
Info.Fragments.push_back (Add);
}
free (Retrieval);
HandleResult = Handle;
return (true);
}
bool DriveVolume::FindFreeRange (uint64 StartLCN, uint64 ReqLength, uint64 &LCNResult)
{
uint64 Max;
uint64 i;
uint64 j;
// Make sure we don't spill over our array
Max = VolInfo.ClusterCount - ReqLength;
for (i = StartLCN; i < Max; i++)
{
bool Found = true;
// First check the first cluster
if (IsClusterUsed (i))
Found = false;
else
// THen check the last cluster
if (IsClusterUsed (i + ReqLength - 1))
Found = false;
else
// Check the whole darn range.
for (j = (i + 1); j < (i + ReqLength - 2); j++)
{
if (IsClusterUsed (j) == true)
{
Found = false;
break;
}
}
if (!Found)
continue;
else
{
LCNResult = i;
return (true);
}
}
return (false);
}
// btw we have to move each fragment of the file, as per the Win32 API
bool DriveVolume::MoveFileDumb (uint32 FileIndice, uint64 NewLCN)
{
bool ReturnVal = false;
FileInfo Info;
HANDLE FileHandle;
wstring FullName;
MOVE_FILE_DATA MoveData;
uint64 CurrentLCN;
uint64 CurrentVCN;
// Set up variables
Info = GetDBFile (FileIndice);
FullName = GetDBDir (Info.DirIndice);
FullName += Info.Name;
CurrentLCN = NewLCN;
CurrentVCN = 0;
/*
if (Info.Attributes.Directory == 1)
{
//
}
*/
// Open file
FileHandle = CreateFile
(
FullName.c_str (),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
(Info.Attributes.Directory == 1) ? FILE_FLAG_BACKUP_SEMANTICS : 0,
NULL
);
if (FileHandle == INVALID_HANDLE_VALUE)
{
//
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf, 0, NULL );
LocalFree (lpMsgBuf);
//
ReturnVal = false;
}
else
{
ReturnVal = true; // innocent until proven guilty ...
for (uint32 i = 0; i < Info.Fragments.size(); i++)
{
BOOL Result;
DWORD BytesReturned;
//wprintf (L"%3u", i);
MoveData.ClusterCount = Info.Fragments[i].Length;
MoveData.StartingLcn.QuadPart = CurrentLCN;
MoveData.StartingVcn.QuadPart = CurrentVCN;
MoveData.FileHandle = FileHandle;
/*
wprintf (L"\n");
wprintf (L"StartLCN: %I64u\n", MoveData.StartingLcn.QuadPart);
wprintf (L"StartVCN: %I64u\n", MoveData.StartingVcn.QuadPart);
wprintf (L"Clusters: %u (%I64u-%I64u --> %I64u-%I64u)\n", MoveData.ClusterCount,
Info.Fragments[i].StartLCN,
Info.Fragments[i].StartLCN + MoveData.ClusterCount,
MoveData.StartingLcn.QuadPart,
MoveData.StartingLcn.QuadPart + MoveData.ClusterCount - 1);
wprintf (L"\n");
*/
Result = DeviceIoControl
(
Handle,
FSCTL_MOVE_FILE,
&MoveData,
sizeof (MoveData),
NULL,
0,
&BytesReturned,
NULL
);
//wprintf (L"\b\b\b");
if (Result == FALSE)
{
//
LPVOID lpMsgBuf;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &lpMsgBuf, 0, NULL );
LocalFree( lpMsgBuf );
//
ReturnVal = false;
goto FinishUp; // yeah, bite me
}
// Ok good. Now update our drive bitmap and file infos.
uint64 j;
for (j = 0;
j < Info.Fragments[i].Length;
j++)
{
SetClusterUsed (Info.Fragments[i].StartLCN + j, false);
SetClusterUsed (CurrentLCN + j, true);
//BitmapDetail[Info.Fragments[i].StartLCN + j].Allocated = false;
//BitmapDetail[CurrentLCN + j].Allocated = true;
}
CurrentLCN += Info.Fragments[i].Length;
CurrentVCN += Info.Fragments[i].Length;
}
// Update file info either way
FinishUp:
CloseHandle (FileHandle);
FileHandle = INVALID_HANDLE_VALUE;
GetClusterInfo (Files[FileIndice], FileHandle);
CloseHandle (FileHandle);
}
return (ReturnVal);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -