mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 00:12:57 +00:00
Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers into modules, and delete rossubsys.
This commit is contained in:
parent
b94e2d8ca0
commit
c2c66aff7d
24198 changed files with 0 additions and 37285 deletions
806
modules/rosapps/applications/fraginator/DriveVolume.cpp
Normal file
806
modules/rosapps/applications/fraginator/DriveVolume.cpp
Normal file
|
@ -0,0 +1,806 @@
|
|||
#include "DriveVolume.h"
|
||||
|
||||
|
||||
DriveVolume::DriveVolume ()
|
||||
{
|
||||
Handle = INVALID_HANDLE_VALUE;
|
||||
BitmapDetail = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
DriveVolume::~DriveVolume ()
|
||||
{
|
||||
Close ();
|
||||
Directories.clear ();
|
||||
Files.clear ();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void DriveVolume::Close (void)
|
||||
{
|
||||
if (Handle != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle (Handle);
|
||||
Handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
if (BitmapDetail != NULL)
|
||||
{
|
||||
free (BitmapDetail);
|
||||
BitmapDetail = NULL;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// "Name" should be the drive letter followed by a colon. ie, "c:"
|
||||
// It's a string to allow for further expansion (ie, defragging over the network?)
|
||||
// or some other baloney reason
|
||||
bool DriveVolume::Open (wstring Name)
|
||||
{
|
||||
wchar_t FileName[100];
|
||||
bool ReturnVal;
|
||||
|
||||
swprintf (FileName, L"\\\\.\\%s", Name.c_str());
|
||||
RootPath = Name.c_str();
|
||||
RootPath += L"\\";
|
||||
|
||||
Handle = CreateFileW
|
||||
(
|
||||
FileName,
|
||||
MAXIMUM_ALLOWED, // access
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, // share type
|
||||
NULL, // security descriptor
|
||||
OPEN_EXISTING, // open type
|
||||
0, // attributes (none)
|
||||
NULL // template
|
||||
);
|
||||
|
||||
if (Handle == INVALID_HANDLE_VALUE)
|
||||
ReturnVal = false;
|
||||
else
|
||||
{
|
||||
wchar_t VolName[64];
|
||||
DWORD VolSN;
|
||||
DWORD VolMaxFileLen;
|
||||
DWORD FSFlags;
|
||||
wchar_t FSName[64];
|
||||
BOOL Result;
|
||||
|
||||
ReturnVal = true;
|
||||
Result = GetVolumeInformationW
|
||||
(
|
||||
RootPath.c_str(),
|
||||
VolName,
|
||||
sizeof (VolName),
|
||||
&VolSN,
|
||||
&VolMaxFileLen,
|
||||
&FSFlags,
|
||||
FSName,
|
||||
sizeof (FSName)
|
||||
);
|
||||
|
||||
if (Result)
|
||||
{
|
||||
wchar_t SerialText[10];
|
||||
|
||||
VolInfo.FileSystem = FSName;
|
||||
VolInfo.MaxNameLen = VolMaxFileLen;
|
||||
VolInfo.Name = VolName;
|
||||
|
||||
swprintf (SerialText, L"%x-%x", (VolSN & 0xffff0000) >> 16,
|
||||
VolSN & 0x0000ffff);
|
||||
|
||||
_wcsupr (SerialText);
|
||||
VolInfo.Serial = SerialText;
|
||||
}
|
||||
else
|
||||
{
|
||||
VolInfo.FileSystem = L"(Unknown)";
|
||||
VolInfo.MaxNameLen = 255;
|
||||
VolInfo.Name = L"(Unknown)";
|
||||
VolInfo.Serial = L"(Unknown)";
|
||||
}
|
||||
}
|
||||
|
||||
return (ReturnVal);
|
||||
}
|
||||
|
||||
|
||||
bool DriveVolume::ObtainInfo (void)
|
||||
{
|
||||
BOOL Result;
|
||||
DWORD BytesGot;
|
||||
uint64 nan;
|
||||
|
||||
BytesGot = 0;
|
||||
ZeroMemory (&Geometry, sizeof (Geometry));
|
||||
Result = DeviceIoControl
|
||||
(
|
||||
Handle,
|
||||
IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
||||
NULL,
|
||||
0,
|
||||
&Geometry,
|
||||
sizeof (Geometry),
|
||||
&BytesGot,
|
||||
NULL
|
||||
);
|
||||
|
||||
// Call failed? Aww :(
|
||||
if (!Result)
|
||||
return (false);
|
||||
|
||||
// Get cluster size
|
||||
DWORD SectorsPerCluster;
|
||||
DWORD BytesPerSector;
|
||||
DWORD FreeClusters;
|
||||
DWORD TotalClusters;
|
||||
|
||||
Result = GetDiskFreeSpaceW
|
||||
(
|
||||
RootPath.c_str(),
|
||||
&SectorsPerCluster,
|
||||
&BytesPerSector,
|
||||
&FreeClusters,
|
||||
&TotalClusters
|
||||
);
|
||||
|
||||
// Failed? Weird.
|
||||
if (!Result)
|
||||
return (false);
|
||||
|
||||
VolInfo.ClusterSize = SectorsPerCluster * BytesPerSector;
|
||||
|
||||
Result = GetDiskFreeSpaceExW
|
||||
(
|
||||
RootPath.c_str(),
|
||||
(PULARGE_INTEGER)&nan,
|
||||
(PULARGE_INTEGER)&VolInfo.TotalBytes,
|
||||
(PULARGE_INTEGER)&VolInfo.FreeBytes
|
||||
);
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
// Get bitmap, several clusters at a time ...
|
||||
#define CLUSTERS 4096
|
||||
bool DriveVolume::GetBitmap (void)
|
||||
{
|
||||
STARTING_LCN_INPUT_BUFFER StartingLCN;
|
||||
VOLUME_BITMAP_BUFFER *Bitmap = NULL;
|
||||
uint32 BitmapSize;
|
||||
DWORD BytesReturned;
|
||||
BOOL Result;
|
||||
|
||||
StartingLCN.StartingLcn.QuadPart = 0;
|
||||
|
||||
// Allocate buffer
|
||||
// Call FSCTL_GET_VOLUME_BITMAP once with a very small buffer
|
||||
// This will leave the total number of clusters in Bitmap->BitmapSize and we can
|
||||
// then correctly allocate based off that
|
||||
// I suppose this won't work if your drive has only 40 clusters on it or so :)
|
||||
BitmapSize = sizeof (VOLUME_BITMAP_BUFFER) + 4;
|
||||
Bitmap = (VOLUME_BITMAP_BUFFER *) malloc (BitmapSize);
|
||||
|
||||
Result = DeviceIoControl
|
||||
(
|
||||
Handle,
|
||||
FSCTL_GET_VOLUME_BITMAP,
|
||||
&StartingLCN,
|
||||
sizeof (StartingLCN),
|
||||
Bitmap,
|
||||
BitmapSize,
|
||||
&BytesReturned,
|
||||
NULL
|
||||
);
|
||||
|
||||
// Bad result?
|
||||
if (Result == FALSE && GetLastError () != ERROR_MORE_DATA)
|
||||
{
|
||||
//wprintf ("\nDeviceIoControl returned false, GetLastError() was not ERROR_MORE_DATA\n");
|
||||
free (Bitmap);
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Otherwise, we're good
|
||||
BitmapSize = sizeof (VOLUME_BITMAP_BUFFER) + (Bitmap->BitmapSize.QuadPart / 8) + 1;
|
||||
Bitmap = (VOLUME_BITMAP_BUFFER *) realloc (Bitmap, BitmapSize);
|
||||
Result = DeviceIoControl
|
||||
(
|
||||
Handle,
|
||||
FSCTL_GET_VOLUME_BITMAP,
|
||||
&StartingLCN,
|
||||
sizeof (StartingLCN),
|
||||
Bitmap,
|
||||
BitmapSize,
|
||||
&BytesReturned,
|
||||
NULL
|
||||
);
|
||||
|
||||
//DWORD LastError = GetLastError ();
|
||||
|
||||
if (Result == FALSE)
|
||||
{
|
||||
wprintf (L"\nCouldn't properly read volume bitmap\n");
|
||||
free (Bitmap);
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Convert to a L'quick use' bitmap
|
||||
//const int BitShift[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
|
||||
|
||||
VolInfo.ClusterCount = Bitmap->BitmapSize.QuadPart;
|
||||
|
||||
if (BitmapDetail != NULL)
|
||||
free (BitmapDetail);
|
||||
|
||||
BitmapDetail = (uint32 *) malloc (sizeof(uint32) * (1 + (VolInfo.ClusterCount / 32)));
|
||||
memcpy (BitmapDetail, Bitmap->Buffer, sizeof(uint32) * (1 + (VolInfo.ClusterCount / 32)));
|
||||
|
||||
/*
|
||||
BitmapDetail = (Cluster *) malloc (VolInfo.ClusterCount * sizeof (Cluster));
|
||||
for (uint64 i = 0; i < VolInfo.ClusterCount; i++)
|
||||
{
|
||||
if (Bitmap->Buffer[i / 8] & BitShift[i % 8])
|
||||
BitmapDetail[i].Allocated = true;
|
||||
else
|
||||
BitmapDetail[i].Allocated = false;
|
||||
}
|
||||
*/
|
||||
|
||||
free (Bitmap);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
bool DriveVolume::IsClusterUsed (uint64 Cluster)
|
||||
{
|
||||
return ((BitmapDetail[Cluster / 32] & (1 << (Cluster % 32))) ? true : false);
|
||||
//return (BitmapDetail[Cluster].Allocated);
|
||||
}
|
||||
|
||||
|
||||
void DriveVolume::SetClusterUsed (uint64 Cluster, bool Used)
|
||||
{
|
||||
if (Used)
|
||||
BitmapDetail[Cluster / 32] |= (1 << (Cluster % 32));
|
||||
else
|
||||
BitmapDetail[Cluster / 32] &= ~(1 << (Cluster % 32));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DriveVolume *Volume;
|
||||
double *Percent;
|
||||
bool *QuitMonitor;
|
||||
uint64 ClusterCount;
|
||||
uint64 ClusterProgress;
|
||||
} BuildDBInfo;
|
||||
|
||||
|
||||
bool DriveVolume::BuildFileList (bool &QuitMonitor, double &Percent)
|
||||
{
|
||||
BuildDBInfo Info;
|
||||
|
||||
Files.clear ();
|
||||
Directories.clear ();
|
||||
Directories.push_back (RootPath);
|
||||
|
||||
Info.Volume = this;
|
||||
Info.QuitMonitor = &QuitMonitor;
|
||||
Info.ClusterCount = (GetVolumeInfo().TotalBytes - GetVolumeInfo().FreeBytes) / (uint64)GetVolumeInfo().ClusterSize;
|
||||
Info.ClusterProgress = 0;
|
||||
Info.Percent = &Percent;
|
||||
|
||||
ScanDirectory (RootPath, BuildDBCallback, &Info);
|
||||
|
||||
if (QuitMonitor == true)
|
||||
{
|
||||
Directories.resize (0);
|
||||
Files.resize (0);
|
||||
}
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
// UserData = pointer to BuildDBInfo instance
|
||||
bool BuildDBCallback (FileInfo &Info, HANDLE &FileHandle, void *UserData)
|
||||
{
|
||||
BuildDBInfo *DBInfo = (BuildDBInfo *) UserData;
|
||||
DriveVolume *Vol = DBInfo->Volume;
|
||||
|
||||
Vol->Files.push_back (Info);
|
||||
|
||||
if (*(DBInfo->QuitMonitor) == true)
|
||||
return (false);
|
||||
|
||||
DBInfo->ClusterProgress += (uint64)Info.Clusters;
|
||||
*(DBInfo->Percent) =
|
||||
((double)DBInfo->ClusterProgress / (double)DBInfo->ClusterCount) * 100.0f;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
wstring &DriveVolume::GetDBDir (uint32 Indice)
|
||||
{
|
||||
return (Directories[Indice]);
|
||||
}
|
||||
|
||||
|
||||
uint32 DriveVolume::GetDBDirCount (void)
|
||||
{
|
||||
return (Directories.size());
|
||||
}
|
||||
|
||||
|
||||
FileInfo &DriveVolume::GetDBFile (uint32 Indice)
|
||||
{
|
||||
return (Files[Indice]);
|
||||
}
|
||||
|
||||
|
||||
uint32 DriveVolume::GetDBFileCount (void)
|
||||
{
|
||||
return (Files.size());
|
||||
}
|
||||
|
||||
|
||||
uint32 DriveVolume::RemoveDBFile (uint32 Indice)
|
||||
{
|
||||
vector<FileInfo>::iterator it;
|
||||
|
||||
it = Files.begin() + Indice;
|
||||
Files.erase (it);
|
||||
return (GetDBFileCount());
|
||||
}
|
||||
|
||||
|
||||
bool DriveVolume::ScanDirectory (wstring DirPrefix, ScanCallback Callback, void *UserData)
|
||||
{
|
||||
WIN32_FIND_DATAW FindData;
|
||||
HANDLE FindHandle;
|
||||
wstring SearchString;
|
||||
uint32 DirIndice;
|
||||
|
||||
DirIndice = Directories.size() - 1;
|
||||
|
||||
SearchString = DirPrefix;
|
||||
SearchString += L"*.*";
|
||||
ZeroMemory (&FindData, sizeof (FindData));
|
||||
FindHandle = FindFirstFileW (SearchString.c_str(), &FindData);
|
||||
|
||||
if (FindHandle == INVALID_HANDLE_VALUE)
|
||||
return (false);
|
||||
|
||||
do
|
||||
{
|
||||
FileInfo Info;
|
||||
HANDLE Handle;
|
||||
bool CallbackResult;
|
||||
|
||||
Handle = INVALID_HANDLE_VALUE;
|
||||
|
||||
// First copy over the easy stuff.
|
||||
Info.Name = FindData.cFileName;
|
||||
|
||||
// DonLL't ever include '.L' and '..'
|
||||
if (Info.Name == L"." || Info.Name == L"..")
|
||||
continue;
|
||||
|
||||
//Info.FullName = DirPrefix + Info.Name;
|
||||
Info.Size = (uint64)FindData.nFileSizeLow + ((uint64)FindData.nFileSizeHigh << (uint64)32);
|
||||
Info.DirIndice = DirIndice;
|
||||
|
||||
Info.Attributes.Archive = (FindData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? 1 : 0;
|
||||
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 (size_t 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 (FindNextFileW (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 = CreateFileW
|
||||
(
|
||||
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
|
||||
|
||||
Info.Fragments.clear ();
|
||||
for (uint64 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 = CreateFileW
|
||||
(
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue