+++ /dev/null
-#include "DriveVolume.h"\r
-\r
-\r
-DriveVolume::DriveVolume ()\r
-{\r
- Handle = INVALID_HANDLE_VALUE;\r
- BitmapDetail = NULL;\r
- return;\r
-}\r
-\r
-\r
-DriveVolume::~DriveVolume ()\r
-{\r
- Close ();\r
- Directories.clear ();\r
- Files.clear ();\r
- return;\r
-}\r
-\r
-\r
-void DriveVolume::Close (void)\r
-{\r
- if (Handle != INVALID_HANDLE_VALUE)\r
- {\r
- CloseHandle (Handle);\r
- Handle = INVALID_HANDLE_VALUE;\r
- }\r
-\r
- if (BitmapDetail != NULL)\r
- {\r
- free (BitmapDetail);\r
- BitmapDetail = NULL;\r
- }\r
-\r
- return;\r
-}\r
-\r
-\r
-// "Name" should be the drive letter followed by a colon. ie, "c:"\r
-// It's a string to allow for further expansion (ie, defragging over the network?)\r
-// or some other baloney reason\r
-bool DriveVolume::Open (wstring Name)\r
-{\r
- wchar_t FileName[100];\r
- bool ReturnVal;\r
-\r
- swprintf (FileName, L"\\\\.\\%s", Name.c_str());\r
- RootPath = Name.c_str();\r
- RootPath += L"\\";\r
-\r
- Handle = CreateFileW\r
- (\r
- FileName,\r
- MAXIMUM_ALLOWED, // access\r
- FILE_SHARE_READ | FILE_SHARE_WRITE, // share type\r
- NULL, // security descriptor\r
- OPEN_EXISTING, // open type\r
- 0, // attributes (none)\r
- NULL // template\r
- );\r
-\r
- if (Handle == INVALID_HANDLE_VALUE)\r
- ReturnVal = false;\r
- else\r
- {\r
- wchar_t VolName[64];\r
- DWORD VolSN;\r
- DWORD VolMaxFileLen;\r
- DWORD FSFlags;\r
- wchar_t FSName[64];\r
- BOOL Result;\r
-\r
- ReturnVal = true;\r
- Result = GetVolumeInformationW\r
- (\r
- RootPath.c_str(),\r
- VolName,\r
- sizeof (VolName),\r
- &VolSN,\r
- &VolMaxFileLen,\r
- &FSFlags,\r
- FSName,\r
- sizeof (FSName)\r
- );\r
-\r
- if (Result)\r
- {\r
- wchar_t SerialText[10];\r
-\r
- VolInfo.FileSystem = FSName;\r
- VolInfo.MaxNameLen = VolMaxFileLen;\r
- VolInfo.Name = VolName;\r
-\r
- swprintf (SerialText, L"%x-%x", (VolSN & 0xffff0000) >> 16,\r
- VolSN & 0x0000ffff);\r
-\r
- _wcsupr (SerialText);\r
- VolInfo.Serial = SerialText;\r
- }\r
- else\r
- {\r
- VolInfo.FileSystem = L"(Unknown)";\r
- VolInfo.MaxNameLen = 255;\r
- VolInfo.Name = L"(Unknown)";\r
- VolInfo.Serial = L"(Unknown)";\r
- }\r
- }\r
-\r
- return (ReturnVal);\r
-}\r
-\r
-\r
-bool DriveVolume::ObtainInfo (void)\r
-{\r
- BOOL Result;\r
- DWORD BytesGot;\r
- uint64 nan;\r
-\r
- BytesGot = 0;\r
- ZeroMemory (&Geometry, sizeof (Geometry));\r
- Result = DeviceIoControl\r
- (\r
- Handle,\r
- IOCTL_DISK_GET_DRIVE_GEOMETRY,\r
- NULL,\r
- 0,\r
- &Geometry,\r
- sizeof (Geometry),\r
- &BytesGot,\r
- NULL\r
- );\r
-\r
- // Call failed? Aww :(\r
- if (!Result)\r
- return (false);\r
-\r
- // Get cluster size\r
- DWORD SectorsPerCluster;\r
- DWORD BytesPerSector;\r
- DWORD FreeClusters;\r
- DWORD TotalClusters;\r
-\r
- Result = GetDiskFreeSpaceW\r
- (\r
- RootPath.c_str(),\r
- &SectorsPerCluster,\r
- &BytesPerSector,\r
- &FreeClusters,\r
- &TotalClusters\r
- );\r
-\r
- // Failed? Weird.\r
- if (!Result)\r
- return (false);\r
-\r
- VolInfo.ClusterSize = SectorsPerCluster * BytesPerSector;\r
-\r
- Result = GetDiskFreeSpaceExW\r
- (\r
- RootPath.c_str(),\r
- (PULARGE_INTEGER)&nan,\r
- (PULARGE_INTEGER)&VolInfo.TotalBytes,\r
- (PULARGE_INTEGER)&VolInfo.FreeBytes\r
- );\r
-\r
- return (true);\r
-}\r
-\r
-\r
-// Get bitmap, several clusters at a time ...\r
-#define CLUSTERS 4096\r
-bool DriveVolume::GetBitmap (void)\r
-{\r
- STARTING_LCN_INPUT_BUFFER StartingLCN;\r
- VOLUME_BITMAP_BUFFER *Bitmap = NULL;\r
- uint32 BitmapSize;\r
- DWORD BytesReturned;\r
- BOOL Result;\r
-\r
- StartingLCN.StartingLcn.QuadPart = 0;\r
-\r
- // Allocate buffer\r
- // Call FSCTL_GET_VOLUME_BITMAP once with a very small buffer\r
- // This will leave the total number of clusters in Bitmap->BitmapSize and we can\r
- // then correctly allocate based off that\r
- // I suppose this won't work if your drive has only 40 clusters on it or so :)\r
- BitmapSize = sizeof (VOLUME_BITMAP_BUFFER) + 4;\r
- Bitmap = (VOLUME_BITMAP_BUFFER *) malloc (BitmapSize);\r
-\r
- Result = DeviceIoControl\r
- (\r
- Handle,\r
- FSCTL_GET_VOLUME_BITMAP,\r
- &StartingLCN,\r
- sizeof (StartingLCN),\r
- Bitmap,\r
- BitmapSize,\r
- &BytesReturned,\r
- NULL\r
- );\r
-\r
- // Bad result?\r
- if (Result == FALSE && GetLastError () != ERROR_MORE_DATA)\r
- {\r
- //wprintf ("\nDeviceIoControl returned false, GetLastError() was not ERROR_MORE_DATA\n");\r
- free (Bitmap);\r
- return (false);\r
- }\r
-\r
- // Otherwise, we're good\r
- BitmapSize = sizeof (VOLUME_BITMAP_BUFFER) + (Bitmap->BitmapSize.QuadPart / 8) + 1;\r
- Bitmap = (VOLUME_BITMAP_BUFFER *) realloc (Bitmap, BitmapSize);\r
- Result = DeviceIoControl\r
- (\r
- Handle,\r
- FSCTL_GET_VOLUME_BITMAP,\r
- &StartingLCN,\r
- sizeof (StartingLCN),\r
- Bitmap,\r
- BitmapSize,\r
- &BytesReturned,\r
- NULL\r
- );\r
-\r
- //DWORD LastError = GetLastError ();\r
-\r
- if (Result == FALSE)\r
- {\r
- wprintf (L"\nCouldn't properly read volume bitmap\n");\r
- free (Bitmap);\r
- return (false);\r
- }\r
-\r
- // Convert to a L'quick use' bitmap\r
- //const int BitShift[] = { 1, 2, 4, 8, 16, 32, 64, 128 };\r
-\r
- VolInfo.ClusterCount = Bitmap->BitmapSize.QuadPart;\r
-\r
- if (BitmapDetail != NULL)\r
- free (BitmapDetail);\r
-\r
- BitmapDetail = (uint32 *) malloc (sizeof(uint32) * (1 + (VolInfo.ClusterCount / 32)));\r
- memcpy (BitmapDetail, Bitmap->Buffer, sizeof(uint32) * (1 + (VolInfo.ClusterCount / 32)));\r
-\r
- /*\r
- BitmapDetail = (Cluster *) malloc (VolInfo.ClusterCount * sizeof (Cluster));\r
- for (uint64 i = 0; i < VolInfo.ClusterCount; i++)\r
- {\r
- if (Bitmap->Buffer[i / 8] & BitShift[i % 8])\r
- BitmapDetail[i].Allocated = true;\r
- else\r
- BitmapDetail[i].Allocated = false;\r
- }\r
- */\r
-\r
- free (Bitmap);\r
- return (true);\r
-}\r
-\r
-\r
-bool DriveVolume::IsClusterUsed (uint64 Cluster)\r
-{\r
- return ((BitmapDetail[Cluster / 32] & (1 << (Cluster % 32))) ? true : false);\r
- //return (BitmapDetail[Cluster].Allocated);\r
-}\r
-\r
-\r
-void DriveVolume::SetClusterUsed (uint64 Cluster, bool Used)\r
-{\r
- if (Used)\r
- BitmapDetail[Cluster / 32] |= (1 << (Cluster % 32));\r
- else\r
- BitmapDetail[Cluster / 32] &= ~(1 << (Cluster % 32));\r
-\r
- return;\r
-}\r
-\r
-\r
-typedef struct\r
-{\r
- DriveVolume *Volume;\r
- double *Percent;\r
- bool *QuitMonitor;\r
- uint64 ClusterCount;\r
- uint64 ClusterProgress;\r
-} BuildDBInfo;\r
-\r
-\r
-bool DriveVolume::BuildFileList (bool &QuitMonitor, double &Percent)\r
-{\r
- BuildDBInfo Info;\r
-\r
- Files.clear ();\r
- Directories.clear ();\r
- Directories.push_back (RootPath);\r
-\r
- Info.Volume = this;\r
- Info.QuitMonitor = &QuitMonitor;\r
- Info.ClusterCount = (GetVolumeInfo().TotalBytes - GetVolumeInfo().FreeBytes) / (uint64)GetVolumeInfo().ClusterSize;\r
- Info.ClusterProgress = 0;\r
- Info.Percent = &Percent;\r
-\r
- ScanDirectory (RootPath, BuildDBCallback, &Info);\r
-\r
- if (QuitMonitor == true)\r
- {\r
- Directories.resize (0);\r
- Files.resize (0);\r
- }\r
-\r
- return (true);\r
-}\r
-\r
-\r
-// UserData = pointer to BuildDBInfo instance\r
-bool BuildDBCallback (FileInfo &Info, HANDLE &FileHandle, void *UserData)\r
-{\r
- BuildDBInfo *DBInfo = (BuildDBInfo *) UserData;\r
- DriveVolume *Vol = DBInfo->Volume;\r
-\r
- Vol->Files.push_back (Info);\r
-\r
- if (*(DBInfo->QuitMonitor) == true)\r
- return (false);\r
-\r
- DBInfo->ClusterProgress += (uint64)Info.Clusters;\r
- *(DBInfo->Percent) =\r
- ((double)DBInfo->ClusterProgress / (double)DBInfo->ClusterCount) * 100.0f;\r
-\r
- return (true);\r
-}\r
-\r
-\r
-wstring &DriveVolume::GetDBDir (uint32 Indice)\r
-{\r
- return (Directories[Indice]);\r
-}\r
-\r
-\r
-uint32 DriveVolume::GetDBDirCount (void)\r
-{\r
- return (Directories.size());\r
-}\r
-\r
-\r
-FileInfo &DriveVolume::GetDBFile (uint32 Indice)\r
-{\r
- return (Files[Indice]);\r
-}\r
-\r
-\r
-uint32 DriveVolume::GetDBFileCount (void)\r
-{\r
- return (Files.size());\r
-}\r
-\r
-\r
-uint32 DriveVolume::RemoveDBFile (uint32 Indice)\r
-{\r
- vector<FileInfo>::iterator it;\r
-\r
- it = Files.begin() + Indice;\r
- Files.erase (it);\r
- return (GetDBFileCount());\r
-}\r
-\r
-\r
-bool DriveVolume::ScanDirectory (wstring DirPrefix, ScanCallback Callback, void *UserData)\r
-{\r
- WIN32_FIND_DATAW FindData;\r
- HANDLE FindHandle;\r
- wstring SearchString;\r
- uint32 DirIndice;\r
-\r
- DirIndice = Directories.size() - 1;\r
-\r
- SearchString = DirPrefix;\r
- SearchString += L"*.*";\r
- ZeroMemory (&FindData, sizeof (FindData));\r
- FindHandle = FindFirstFileW (SearchString.c_str(), &FindData);\r
-\r
- if (FindHandle == INVALID_HANDLE_VALUE)\r
- return (false);\r
-\r
- do\r
- {\r
- FileInfo Info;\r
- HANDLE Handle;\r
- bool CallbackResult;\r
-\r
- Handle = INVALID_HANDLE_VALUE;\r
-\r
- // First copy over the easy stuff.\r
- Info.Name = FindData.cFileName;\r
-\r
- // DonLL't ever include '.L' and '..'\r
- if (Info.Name == L"." || Info.Name == L"..")\r
- continue;\r
-\r
- //Info.FullName = DirPrefix + Info.Name;\r
- Info.Size = (uint64)FindData.nFileSizeLow + ((uint64)FindData.nFileSizeHigh << (uint64)32);\r
- Info.DirIndice = DirIndice;\r
-\r
- Info.Attributes.Archive = (FindData.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) ? 1 : 0;\r
- Info.Attributes.Compressed = (FindData.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) ? 1 : 0;\r
- Info.Attributes.Directory = (FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;\r
- Info.Attributes.Encrypted = (FindData.dwFileAttributes & FILE_ATTRIBUTE_ENCRYPTED) ? 1 : 0;\r
- Info.Attributes.Hidden = (FindData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ? 1 : 0;\r
- Info.Attributes.Normal = (FindData.dwFileAttributes & FILE_ATTRIBUTE_NORMAL) ? 1 : 0;\r
- Info.Attributes.Offline = (FindData.dwFileAttributes & FILE_ATTRIBUTE_OFFLINE) ? 1 : 0;\r
- Info.Attributes.ReadOnly = (FindData.dwFileAttributes & FILE_ATTRIBUTE_READONLY) ? 1 : 0;\r
- Info.Attributes.Reparse = (FindData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) ? 1 : 0;\r
- Info.Attributes.Sparse = (FindData.dwFileAttributes & FILE_ATTRIBUTE_SPARSE_FILE) ? 1 : 0;\r
- Info.Attributes.System = (FindData.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) ? 1 : 0;\r
- Info.Attributes.Temporary = (FindData.dwFileAttributes & FILE_ATTRIBUTE_TEMPORARY) ? 1 : 0;\r
- Info.Attributes.AccessDenied = 0;\r
- Info.Attributes.Unmovable = 0;\r
- Info.Attributes.Process = 1;\r
-\r
- Info.Clusters = 0;\r
- if (GetClusterInfo (Info, Handle))\r
- {\r
- uint64 TotalClusters = 0;\r
-\r
- for (size_t i = 0; i < Info.Fragments.size(); i++)\r
- {\r
- TotalClusters += Info.Fragments[i].Length;\r
- }\r
-\r
- Info.Clusters = TotalClusters;\r
- }\r
- else\r
- {\r
- Info.Attributes.Unmovable = 1;\r
- Info.Attributes.Process = 0;\r
- }\r
-\r
- if (Info.Attributes.Process == 1)\r
- Info.Attributes.Process = ShouldProcess (Info.Attributes) ? 1 : 0;\r
-\r
- // Run the user-defined callback function\r
- CallbackResult = Callback (Info, Handle, UserData);\r
-\r
- if (Handle != INVALID_HANDLE_VALUE)\r
- CloseHandle (Handle);\r
-\r
- if (!CallbackResult)\r
- break;\r
-\r
- // If directory, perform recursion\r
- if (Info.Attributes.Directory == 1)\r
- {\r
- wstring Dir;\r
-\r
- Dir = GetDBDir (Info.DirIndice);\r
- Dir += Info.Name;\r
- Dir += L"\\";\r
-\r
- Directories.push_back (Dir);\r
- ScanDirectory (Dir, Callback, UserData);\r
- }\r
-\r
- } while (FindNextFileW (FindHandle, &FindData) == TRUE);\r
-\r
- FindClose (FindHandle);\r
- return (false);\r
-}\r
-\r
-\r
-bool DriveVolume::ShouldProcess (FileAttr Attr)\r
-{\r
- if (Attr.Offline == 1 || Attr.Reparse == 1 || Attr.Temporary == 1)\r
- {\r
- return (false);\r
- }\r
-\r
- return (true);\r
-}\r
-\r
-\r
-// Gets info on a file and returns a valid handle for read/write access\r
-// Name, FullName, Clusters, Attributes, and Size should already be filled out.\r
-// This function fills in the Fragments vector\r
-bool DriveVolume::GetClusterInfo (FileInfo &Info, HANDLE &HandleResult)\r
-{\r
- BOOL Result;\r
- HANDLE Handle;\r
- wstring FullName;\r
- BY_HANDLE_FILE_INFORMATION FileInfo;\r
-\r
- Info.Fragments.resize (0);\r
-\r
- /*\r
- if (Info.Attributes.Directory == 1)\r
- return (false);\r
- */\r
-\r
- FullName = GetDBDir (Info.DirIndice) + Info.Name;\r
-\r
- Handle = CreateFileW\r
- (\r
- FullName.c_str(),\r
- 0, //GENERIC_READ,\r
- FILE_SHARE_READ,\r
- NULL,\r
- OPEN_EXISTING,\r
- (Info.Attributes.Directory == 1) ? FILE_FLAG_BACKUP_SEMANTICS : 0,\r
- NULL\r
- );\r
-\r
- if (Handle == INVALID_HANDLE_VALUE)\r
- {\r
- LPVOID lpMsgBuf;\r
-\r
- FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,\r
- NULL, GetLastError(),\r
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
- (LPTSTR) &lpMsgBuf, 0, NULL );\r
-\r
-\r
- Info.Attributes.AccessDenied = 1;\r
- LocalFree( lpMsgBuf );\r
- return (false);\r
- }\r
-\r
- ZeroMemory (&FileInfo, sizeof (FileInfo));\r
- Result = GetFileInformationByHandle (Handle, &FileInfo);\r
-\r
- if (Result == FALSE)\r
- {\r
- Info.Attributes.AccessDenied = 1;\r
- wprintf (L"GetFileInformationByHandle ('%s%s') failed\n", GetDBDir (Info.DirIndice).c_str(),\r
- Info.Name.c_str());\r
-\r
- CloseHandle (Handle);\r
- return (false);\r
- }\r
-\r
- // Get cluster allocation information\r
- STARTING_VCN_INPUT_BUFFER StartingVCN;\r
- RETRIEVAL_POINTERS_BUFFER *Retrieval;\r
- uint64 RetSize;\r
- uint64 Extents;\r
- DWORD BytesReturned;\r
-\r
- // Grab info one extent at a time, until it's done grabbing all the extent data\r
- // Yeah, well it doesn't give us a way to ask L"how many extents?" that I know of ...\r
- // btw, the Extents variable tends to only reflect memory usage, so when we have\r
- // all the extents we look at the structure Win32 gives us for the REAL count!\r
- Extents = 10;\r
- Retrieval = NULL;\r
- RetSize = 0;\r
- StartingVCN.StartingVcn.QuadPart = 0;\r
-\r
- do\r
- {\r
- Extents *= 2;\r
- RetSize = sizeof (RETRIEVAL_POINTERS_BUFFER) + ((Extents - 1) * sizeof (LARGE_INTEGER) * 2);\r
-\r
- if (Retrieval != NULL)\r
- Retrieval = (RETRIEVAL_POINTERS_BUFFER *) realloc (Retrieval, RetSize);\r
- else\r
- Retrieval = (RETRIEVAL_POINTERS_BUFFER *) malloc (RetSize);\r
-\r
- Result = DeviceIoControl\r
- (\r
- Handle,\r
- FSCTL_GET_RETRIEVAL_POINTERS,\r
- &StartingVCN,\r
- sizeof (StartingVCN),\r
- Retrieval,\r
- RetSize,\r
- &BytesReturned,\r
- NULL\r
- );\r
-\r
- if (Result == FALSE)\r
- {\r
- if (GetLastError() != ERROR_MORE_DATA)\r
- {\r
- Info.Clusters = 0;\r
- Info.Attributes.AccessDenied = 1;\r
- Info.Attributes.Process = 0;\r
- Info.Fragments.clear ();\r
- CloseHandle (Handle);\r
- free (Retrieval);\r
-\r
- return (false);\r
- }\r
-\r
- Extents++;\r
- }\r
- } while (Result == FALSE);\r
-\r
- // Readjust extents, as it only reflects how much memory was allocated and may not\r
- // be accurate\r
- Extents = Retrieval->ExtentCount;\r
-\r
- // Ok, we have the info. Now translate it. hrmrmr\r
- \r
- Info.Fragments.clear ();\r
- for (uint64 i = 0; i < Extents; i++)\r
- {\r
- Extent Add;\r
-\r
- Add.StartLCN = Retrieval->Extents[i].Lcn.QuadPart;\r
- if (i != 0)\r
- Add.Length = Retrieval->Extents[i].NextVcn.QuadPart - Retrieval->Extents[i - 1].NextVcn.QuadPart;\r
- else\r
- Add.Length = Retrieval->Extents[i].NextVcn.QuadPart - Retrieval->StartingVcn.QuadPart;\r
-\r
- Info.Fragments.push_back (Add);\r
- }\r
-\r
- free (Retrieval);\r
- HandleResult = Handle;\r
- return (true);\r
-}\r
-\r
-\r
-bool DriveVolume::FindFreeRange (uint64 StartLCN, uint64 ReqLength, uint64 &LCNResult)\r
-{\r
- uint64 Max;\r
- uint64 i;\r
- uint64 j;\r
-\r
- // Make sure we don't spill over our array\r
- Max = VolInfo.ClusterCount - ReqLength;\r
-\r
- for (i = StartLCN; i < Max; i++)\r
- {\r
- bool Found = true;\r
-\r
- // First check the first cluster\r
- if (IsClusterUsed (i))\r
- Found = false;\r
- else\r
- // THen check the last cluster\r
- if (IsClusterUsed (i + ReqLength - 1))\r
- Found = false;\r
- else\r
- // Check the whole darn range.\r
- for (j = (i + 1); j < (i + ReqLength - 2); j++)\r
- {\r
- if (IsClusterUsed (j) == true)\r
- {\r
- Found = false;\r
- break;\r
- }\r
- }\r
-\r
- if (!Found)\r
- continue;\r
- else\r
- {\r
- LCNResult = i;\r
- return (true);\r
- }\r
- }\r
-\r
- return (false);\r
-}\r
-\r
-\r
-// btw we have to move each fragment of the file, as per the Win32 API\r
-bool DriveVolume::MoveFileDumb (uint32 FileIndice, uint64 NewLCN)\r
-{\r
- bool ReturnVal = false;\r
- FileInfo Info;\r
- HANDLE FileHandle;\r
- wstring FullName;\r
- MOVE_FILE_DATA MoveData;\r
- uint64 CurrentLCN;\r
- uint64 CurrentVCN;\r
-\r
- // Set up variables\r
- Info = GetDBFile (FileIndice);\r
- FullName = GetDBDir (Info.DirIndice);\r
- FullName += Info.Name;\r
- CurrentLCN = NewLCN;\r
- CurrentVCN = 0;\r
-\r
- /*\r
- if (Info.Attributes.Directory == 1)\r
- {\r
- //\r
- }\r
- */\r
-\r
- // Open file\r
- FileHandle = CreateFileW\r
- (\r
- FullName.c_str (),\r
- GENERIC_READ,\r
- FILE_SHARE_READ,\r
- NULL,\r
- OPEN_EXISTING,\r
- (Info.Attributes.Directory == 1) ? FILE_FLAG_BACKUP_SEMANTICS : 0,\r
- NULL\r
- );\r
-\r
- if (FileHandle == INVALID_HANDLE_VALUE)\r
- {\r
- //\r
- LPVOID lpMsgBuf;\r
-\r
- FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,\r
- NULL, GetLastError(),\r
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
- (LPTSTR) &lpMsgBuf, 0, NULL );\r
-\r
-\r
- LocalFree (lpMsgBuf);\r
- //\r
-\r
- ReturnVal = false;\r
- }\r
- else\r
- {\r
- ReturnVal = true; // innocent until proven guilty ...\r
-\r
- for (uint32 i = 0; i < Info.Fragments.size(); i++)\r
- {\r
- BOOL Result;\r
- DWORD BytesReturned;\r
-\r
- //wprintf (L"%3u", i);\r
-\r
- MoveData.ClusterCount = Info.Fragments[i].Length;\r
- MoveData.StartingLcn.QuadPart = CurrentLCN;\r
- MoveData.StartingVcn.QuadPart = CurrentVCN;\r
-\r
- MoveData.FileHandle = FileHandle;\r
-\r
- /*\r
- wprintf (L"\n");\r
- wprintf (L"StartLCN: %I64u\n", MoveData.StartingLcn.QuadPart);\r
- wprintf (L"StartVCN: %I64u\n", MoveData.StartingVcn.QuadPart);\r
- wprintf (L"Clusters: %u (%I64u-%I64u --> %I64u-%I64u)\n", MoveData.ClusterCount,\r
- Info.Fragments[i].StartLCN,\r
- Info.Fragments[i].StartLCN + MoveData.ClusterCount,\r
- MoveData.StartingLcn.QuadPart,\r
- MoveData.StartingLcn.QuadPart + MoveData.ClusterCount - 1);\r
- wprintf (L"\n");\r
- */\r
-\r
- Result = DeviceIoControl\r
- (\r
- Handle,\r
- FSCTL_MOVE_FILE,\r
- &MoveData,\r
- sizeof (MoveData),\r
- NULL,\r
- 0,\r
- &BytesReturned,\r
- NULL\r
- );\r
-\r
- //wprintf (L"\b\b\b");\r
-\r
- if (Result == FALSE)\r
- {\r
- //\r
- LPVOID lpMsgBuf;\r
-\r
- FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,\r
- NULL, GetLastError(),\r
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),\r
- (LPTSTR) &lpMsgBuf, 0, NULL );\r
-\r
-\r
- LocalFree( lpMsgBuf );\r
- //\r
-\r
- ReturnVal = false;\r
- goto FinishUp; // yeah, bite me\r
- }\r
-\r
- // Ok good. Now update our drive bitmap and file infos.\r
- uint64 j;\r
- for (j = 0;\r
- j < Info.Fragments[i].Length;\r
- j++)\r
- {\r
- SetClusterUsed (Info.Fragments[i].StartLCN + j, false);\r
- SetClusterUsed (CurrentLCN + j, true);\r
- //BitmapDetail[Info.Fragments[i].StartLCN + j].Allocated = false;\r
- //BitmapDetail[CurrentLCN + j].Allocated = true;\r
- }\r
-\r
- CurrentLCN += Info.Fragments[i].Length;\r
- CurrentVCN += Info.Fragments[i].Length;\r
- }\r
-\r
- // Update file info either way\r
- FinishUp:\r
- CloseHandle (FileHandle);\r
- FileHandle = INVALID_HANDLE_VALUE;\r
- GetClusterInfo (Files[FileIndice], FileHandle);\r
- CloseHandle (FileHandle);\r
- }\r
-\r
- return (ReturnVal);\r
-}\r
-\r
-\r