Дефрагментация и FSCTL_MOVE_FILE
От:
bixbit
Дата: 11.08.12 16:21
Оценка:
Делал так как пишет мсдн
откуда брать параметры для FSCTL_MOVE_FILE
int GetClusters(const char * name,bool d)
{
MOVE_FILE_DATA MoveParams;
ULONG ClCount;
LARGE_INTEGER FileSize;
HANDLE hFile;
ULONG OutSize;
ULONG Bytes,CnCount;
LARGE_INTEGER PrevVCN, Lcn;
STARTING_VCN_INPUT_BUFFER InBuf;
PRETRIEVAL_POINTERS_BUFFER OutBuf;
int next=1;
MOVE_FILE_DATA md;
hFile = CreateFile(name,FILE_READ_ATTRIBUTES,
FILE_READ_DATA| FILE_WRITE_DATA| FILE_APPEND_DATA,
NULL, OPEN_EXISTING, 0, 0);
char namef[MAX_PATH];
sprintf(namef,"\\\\.\\%c:" ,name[0]);
HANDLE hDisk = CreateFile(namef,FILE_READ_ATTRIBUTES,
FILE_READ_DATA| FILE_WRITE_DATA| FILE_APPEND_DATA,
NULL, OPEN_EXISTING, 0, 0);
MoveParams.FileHandle = hFile;
if (hFile != INVALID_HANDLE_VALUE)
{
GetFileSizeEx(hFile, &FileSize);
OutSize = (ULONG)sizeof (RETRIEVAL_POINTERS_BUFFER) + (FileSize.QuadPart / ClusterSize) * sizeof (OutBuf->Extents);
OutBuf = (PRETRIEVAL_POINTERS_BUFFER)malloc(OutSize);
InBuf.StartingVcn.QuadPart = 0;
MoveParams.StartingLcn.QuadPart = 0;
if (DeviceIoControl(hFile, FSCTL_GET_RETRIEVAL_POINTERS, &InBuf,sizeof (InBuf), OutBuf, OutSize, &Bytes, NULL))
{
ClCount = (FileSize.QuadPart + ClusterSize - 1) / ClusterSize;
LONGLONG prev_num=0;
MoveParams.ClusterCount = ClCount;
PrevVCN = OutBuf->StartingVcn;
MoveParams.StartingVcn.QuadPart = PrevVCN.QuadPart;
ULONG r = 0, Cls = 0, all;
bool first=0;
for (; r < OutBuf->ExtentCount; r++)
{
Lcn = OutBuf->Extents[r].Lcn ;
for (CnCount=OutBuf->Extents[r].NextVcn.QuadPart - PrevVCN.QuadPart; CnCount; CnCount--, Cls++, Lcn.QuadPart++)
{
if (prev_num+1!=Lcn.QuadPart&&first)
next++;
prev_num=Lcn.QuadPart;
first=1;
DWORD br;
if (d)
{
if (!DeviceIoControl(hDisk,FSCTL_MOVE_FILE,&MoveParams,sizeof (MoveParams),NULL,0,&br,NULL))
printf("error %d\n" ,GetLastError());
}
}
PrevVCN = OutBuf->Extents[r].NextVcn;
}
}
free(OutBuf);
CloseHandle(hFile);
}
else
printf("Error opening file %s\n" ,name);
if (next!=1)
{
if (!d)
{
frag_files.push_back(name);
}
}
return next;
}
/////////////////////////////////////////
bool GetBitmap (void )
{
HANDLE Handle = CreateFile("\\\\.\\f:" ,
MAXIMUM_ALLOWED, // access
FILE_SHARE_READ | FILE_SHARE_WRITE, // share type
NULL, // security descriptor
OPEN_EXISTING, // open type
NULL, // attributes (none)
NULL // template
);
STARTING_LCN_INPUT_BUFFER StartingLCN;
VOLUME_BITMAP_BUFFER *Bitmap = NULL;
int 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 );
}
free (Bitmap);
return (true );
}
11.08.12 23:33: Перенесено модератором из 'C/C++' — Кодт
Re: Дефрагментация и FSCTL_MOVE_FILE
Можно использовать функцию RtlFindClearBits, чтобы найти непрерывную последовательность кластеров в битмапе тома.
RTL_BITMAP Bitmap;
ULONG nBits = (ULONG) pVolumeBitmap->BitmapSize.QuadPart;
ULONG iFreeLCN;
RtlInitializeBitMap(&Bitmap, (PULONG) pVolumeBitmap->Buffer, nBits);
iFreeLCN = RtlFindClearBits(&Bitmap, nClustersRequired, 0);
typedef struct _RTL_BITMAP
{
ULONG SizeOfBitMap;
PULONG Buffer;
} RTL_BITMAP, *PRTL_BITMAP;
NTSYSAPI
VOID
NTAPI
RtlInitializeBitMap(
PRTL_BITMAP BitMapHeader,
PULONG BitMapBuffer,
ULONG SizeOfBitMap
);
ULONG
NTAPI
RtlFindClearBits (
PRTL_BITMAP BitMapHeader,
ULONG NumberToFind,
ULONG HintIndex
);
Re[2]: Дефрагментация и FSCTL_MOVE_FILE
От:
bixbit
Дата: 12.08.12 21:09
Оценка:
Спасибо, но в попытках понять как работает попал на такой
код
Оригинал работает, а моя версия нет, хотя все параметры передаются, по-моему, правильно и функция возвращает ненулевое значение
#include <stdio.h>
#include <Windows.h>
#include <conio.h>
#include <iostream>
#include <list>
#include <locale>
#include <string>
using namespace std;
void Search(char let);
int GetClusters(const char * name,bool d);
DWORD ClusterSize;
list<string> frag_files;
void ProcessVolume(char VolumeName);
int FindFreeBlock(
HANDLE VolumeHandle,
ULONG64 MinimumLcn, /* Cluster must be at or above this LCN. */
DWORD MinimumSize, /* Cluster must be at least this big. */
ULONG64 *BeginLcn, /* Result, LCN of begin of cluster. */
ULONG64 *EndLcn);
void main()
{
setlocale(LC_ALL,"" );
GetClusters("f:\\Wide_Wallpapers_pac\\1 (124).jpg" ,1);
return ;
}
/////////////////////////////////////////
void Search(char let)
{
//t=0;
//files=0;
frag_files.clear();
system("cls" );
char name[4];
sprintf(name,"%c:\\" ,let);
HANDLE hDevice = INVALID_HANDLE_VALUE;
char namef[31];
sprintf(namef,"\\\\.\\%c:" ,let);
hDevice =CreateFileA(namef,
0, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
DWORD SectorsPerCluster;
DWORD BytesPerSector;
DWORD NumberOfFreeClusters;
DWORD TotalNumberOfClusters;
strncat (namef,"\\" ,1);
GetDiskFreeSpaceA(namef,
&SectorsPerCluster,&BytesPerSector,&NumberOfFreeClusters,&TotalNumberOfClusters);
ClusterSize = SectorsPerCluster*BytesPerSector;
}
int GetClusters(const char * name,bool d)
{
MOVE_FILE_DATA MoveParams;
ULONG ClCount;
LARGE_INTEGER FileSize;
HANDLE hFile;
ULONG OutSize;
ULONG Bytes;
LARGE_INTEGER PrevVCN;
STARTING_VCN_INPUT_BUFFER InBuf;
PRETRIEVAL_POINTERS_BUFFER OutBuf;
hFile =CreateFile(name,FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,OPEN_EXISTING,FILE_FLAG_NO_BUFFERING,NULL);
char namef[MAX_PATH];
sprintf(namef,"\\\\.\\%c:" ,name[0]);
HANDLE hDisk = CreateFile(namef,GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
MoveParams.FileHandle = hFile;
if (hFile != INVALID_HANDLE_VALUE)
{
Search(name[0]);
GetFileSizeEx(hFile, &FileSize);
OutSize = (ULONG)sizeof (RETRIEVAL_POINTERS_BUFFER) + (FileSize.QuadPart / ClusterSize) * sizeof (OutBuf->Extents);
OutBuf = (PRETRIEVAL_POINTERS_BUFFER)malloc(OutSize);
InBuf.StartingVcn.QuadPart = 0;
if (DeviceIoControl(hFile, FSCTL_GET_RETRIEVAL_POINTERS, &InBuf,sizeof (InBuf), OutBuf, OutSize, &Bytes, NULL))
{
ClCount = (FileSize.QuadPart + ClusterSize - 1) / ClusterSize;
ProcessVolume(name[0]);
ULONG64 BLcn=-1,ELcn=-1;
FindFreeBlock(hDisk,0,ClCount,&BLcn,&ELcn);
MoveParams.ClusterCount = 0;
MoveParams.StartingLcn.QuadPart = BLcn;
PrevVCN = OutBuf->StartingVcn;
if (d==0)
{
frag_files.push_back(name);
int rez = OutBuf->ExtentCount;
free(OutBuf);
CloseHandle(hFile);
return rez;
}
for (ULONG r = 0; r < OutBuf->ExtentCount; r++)
{
DWORD br;
MoveParams.StartingVcn =OutBuf->Extents[r].Lcn;
MoveParams.ClusterCount =OutBuf->Extents[r].NextVcn.QuadPart - PrevVCN.QuadPart;
////////////////////////////////////////////
///FSCTL_MOVE_FILE
////////////////////////////////////////////
int z= DeviceIoControl(hDisk,FSCTL_MOVE_FILE,&MoveParams,sizeof (MoveParams),NULL,0,&br,NULL);
if (!z)
printf("error %d\n" ,GetLastError());
MoveParams.StartingLcn.QuadPart=MoveParams.StartingLcn.QuadPart+MoveParams.ClusterCount;
PrevVCN = OutBuf->Extents[r].NextVcn;
}
}
free(OutBuf);
CloseHandle(hFile);
CloseHandle(hDisk);
}
return 1;
}
/////////////////////////////////////////
ULONG64 MaxLcn; /* Highest possible LCN + 1. */
struct {
ULONG64 Start;
ULONG64 End;
} Excludes[3];
//HANDLE
void ProcessVolume(char VolumeName) {
HANDLE VolumeHandle;
STARTING_LCN_INPUT_BUFFER InBuffer;
struct {
ULONG64 StartingLcn;
ULONG64 BitmapSize;
BYTE Buffer[8];
} Data;
int Result;
NTFS_VOLUME_DATA_BUFFER NtfsData;
DWORD w;
/* Initialize. */
MaxLcn = 0;
Excludes[0].Start = 0;
Excludes[0].End = 0;
Excludes[1].Start = 0;
Excludes[1].End = 0;
Excludes[2].Start = 0;
Excludes[2].End = 0;
/* Initialize random number generator. */
char name[7];
sprintf(name,"\\\\.\\%c:" ,VolumeName);
/* Open the VolumeHandle. If error then leave. */
VolumeHandle = CreateFile(name,GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
if (VolumeHandle == INVALID_HANDLE_VALUE) {
printf("Error while opening volume \"%c\"" ,VolumeName);
//return INVALID_HANDLE_VALUE;
}
/* If the volume is not mounted then leave. Unmounted volumes can be
defragmented, but the system administrator probably has unmounted
the volume because he wants it untouched. */
if (DeviceIoControl(VolumeHandle,FSCTL_IS_VOLUME_MOUNTED,NULL,0,NULL,0,&w,NULL) == 0) {
printf("Skipping volume '%c' because it is not mounted." ,VolumeName);
CloseHandle(VolumeHandle);
//return INVALID_HANDLE_VALUE;
}
/* Determine the maximum LCN. A single call to FSCTL_GET_VOLUME_BITMAP
is enough, we don't have to walk through the entire bitmap.
It's a pity we have to do it in this roundabout manner, because
there is no system call that reports the total number of clusters
in a volume. GetDiskFreeSpace() does, but is limited to 2Gb volumes,
GetDiskFreeSpaceEx() reports in bytes, not clusters, and
FSCTL_GET_NTFS_VOLUME_DATA only works for NTFS volumes. */
InBuffer.StartingLcn.QuadPart = MaxLcn;
Result = DeviceIoControl(VolumeHandle,FSCTL_GET_VOLUME_BITMAP,
&InBuffer,sizeof (InBuffer),
&Data,sizeof (Data),
&w,NULL);
if (Result == 0) {
Result = GetLastError();
if (Result != ERROR_MORE_DATA) {
printf("Cannot defragment volume: %c" ,VolumeName);
CloseHandle(VolumeHandle);
//return INVALID_HANDLE_VALUE;
}
}
MaxLcn = Data.StartingLcn + Data.BitmapSize;
/* Setup the list of clusters that cannot be used. The Master File
Table cannot be moved and cannot be used by files. All this is
only necessary for NTFS volumes. */
Result = DeviceIoControl(VolumeHandle,FSCTL_GET_NTFS_VOLUME_DATA,
NULL,0,&NtfsData,sizeof (NtfsData),&w,NULL);
if (Result != 0) {
/* Note: NtfsData.TotalClusters.QuadPart should be exactly the same
as the MaxLcn that was determined in the previous block. */
Excludes[0].Start = NtfsData.MftStartLcn.QuadPart;
Excludes[0].End = NtfsData.MftStartLcn.QuadPart +
NtfsData.MftValidDataLength.QuadPart / NtfsData.BytesPerCluster;
Excludes[1].Start = NtfsData.MftZoneStart.QuadPart;
Excludes[1].End = NtfsData.MftZoneEnd.QuadPart;
Excludes[2].Start = NtfsData.Mft2StartLcn.QuadPart;
Excludes[2].End = NtfsData.Mft2StartLcn.QuadPart +
NtfsData.MftValidDataLength.QuadPart / NtfsData.BytesPerCluster;
/* Show debug info. */
}
//return VolumeHandle;
/* Close the volume handle. */
CloseHandle(VolumeHandle);
/* Cleanup the FileList. */
}
int FindFreeBlock(
HANDLE VolumeHandle,
ULONG64 MinimumLcn, /* Cluster must be at or above this LCN. */
DWORD MinimumSize, /* Cluster must be at least this big. */
ULONG64 *BeginLcn, /* Result, LCN of begin of cluster. */
ULONG64 *EndLcn) { /* Result, LCN of end of cluster. */
STARTING_LCN_INPUT_BUFFER InBuffer;
struct {
ULONG64 StartingLcn;
ULONG64 BitmapSize;
BYTE Buffer[32768]; /* Most efficient if binary multiple. */
} Data;
ULONG64 Lcn;
ULONG64 ClusterStart;
int Index;
int IndexMax;
BYTE Mask;
int InUse;
int PrevInUse;
int Result;
DWORD w;
/* Main loop to walk through the entire clustermap. */
Lcn = MinimumLcn;
ClusterStart = 0;
PrevInUse = 1;
do {
/* Sanity check. */
if ((MaxLcn > 0) && (Lcn >= MaxLcn)) return 0;
/* Fetch a block of cluster data. */
InBuffer.StartingLcn.QuadPart = Lcn;
Result = DeviceIoControl(VolumeHandle,FSCTL_GET_VOLUME_BITMAP,
&InBuffer,sizeof (InBuffer),
&Data,sizeof (Data),
&w,NULL);
if (Result == 0) {
Result = GetLastError();
if (Result != ERROR_MORE_DATA) {
return 0;
}
}
/* Analyze the clusterdata. We resume where the previous block left
off. If a cluster is found that matches the criteria then return
it's LCN (Logical Cluster Number). */
Lcn = Data.StartingLcn;
Index = 0;
Mask = 1;
IndexMax = sizeof (Data.Buffer);
if (Data.BitmapSize / 8 < IndexMax) IndexMax = (int )(Data.BitmapSize / 8);
while (Index < IndexMax) {
InUse = (Data.Buffer[Index] & Mask);
if (((Lcn >= Excludes[0].Start) && (Lcn < Excludes[0].End)) ||
((Lcn >= Excludes[1].Start) && (Lcn < Excludes[1].End)) ||
((Lcn >= Excludes[2].Start) && (Lcn < Excludes[2].End))) {
InUse = 1;
}
if ((PrevInUse == 0) && (InUse != 0)) {
if ((ClusterStart >= MinimumLcn) &&
(Lcn - ClusterStart >= MinimumSize)) {
*BeginLcn = ClusterStart;
if (EndLcn != NULL) *EndLcn = Lcn;
return 1;
}
}
if ((PrevInUse != 0) && (InUse == 0)) ClusterStart = Lcn;
PrevInUse = InUse;
if (Mask == 128) {
Mask = 1;
Index = Index + 1;
} else {
Mask = Mask << 1;
}
Lcn = Lcn + 1;
}
} while ((Result == ERROR_MORE_DATA) &&
(Lcn < Data.StartingLcn + Data.BitmapSize));
if (PrevInUse == 0) {
if ((ClusterStart >= MinimumLcn) &&
(Lcn - ClusterStart >= MinimumSize)) {
*BeginLcn = ClusterStart;
if (EndLcn != NULL) *EndLcn = Lcn;
return 1;
}
}
return 0;
}
Re[3]: Дефрагментация и FSCTL_MOVE_FILE
Во-первых, попробуйте добавить привилегию SeManageVolumePrivilege. Возможно, это поможет.
BOOL AddPrivilege(LPCTSTR PrivilegeName)
{
HANDLE hToken = NULL;
TOKEN_PRIVILEGES tkp;
BOOL ret = FALSE;
while (1)
{
if (!OpenProcessToken(GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
break ;
//------------------------------------------
if (!LookupPrivilegeValue(NULL, PrivilegeName,
&tkp.Privileges[0].Luid))
break ;
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
ret = AdjustTokenPrivileges(hToken, FALSE, &tkp, 0,
(PTOKEN_PRIVILEGES) NULL, 0);
break ;
}
if (hToken)
CloseHandle(hToken);
return ret;
}
void main()
{
setlocale(LC_ALL,"" );
AddPrivilege(SE_MANAGE_VOLUME_NAME);
GetClusters("f:\\Wide_Wallpapers_pac\\1 (124).jpg" ,1);
return ;
}
А во-вторых, никогда не вываливайте на форум кучу кода со словами "что-то тут не работает". Никто за вас не будет отлаживать этот код. Если хотите получить от кого-то помощи, всегда конкретизируйте проблему. Что именно не работает, как вы определили, что не работает, как должно быть. Если функция возвращает ошибку, то указывайте код ошибки.
B>Оригинал работает, а моя версия нет, хотя все параметры передаются, по-моему, правильно и функция возвращает ненулевое значение
Re[4]: Дефрагментация и FSCTL_MOVE_FILE
От:
bixbit
Дата: 13.08.12 17:51
Оценка:
D>Во-первых, попробуйте добавить привилегию SeManageVolumePrivilege. Возможно, это поможет.
Не помогло.
D>А во-вторых, никогда не вываливайте на форум кучу кода со словами "что-то тут не работает". Никто за вас не будет отлаживать этот код. Если хотите получить от кого-то помощи, всегда конкретизируйте проблему. Что именно не работает, как вы определили, что не работает, как должно быть. Если функция возвращает ошибку, то указывайте код ошибки.
Извиняюсь, прсто трудно объяснить.
Собираю все параметры так как пишет мсдн. Вызиваю функцию
////////////////////////////////////////////
///FSCTL_MOVE_FILE
////////////////////////////////////////////
int z= DeviceIoControl(hDisk,FSCTL_MOVE_FILE,&MoveParams,sizeof (MoveParams),NULL,0,&br,NULL);
А вот даные которые передаются в функцию и котоые она возвращает:
StartingVcn.QuadPart:775079 StartingLcn.QuadPart:837091 ClusterCount:1 GetLastError():0 DeviceIoControl return: 1 Bytes return: 0
StartingVcn.QuadPart:776211 StartingLcn.QuadPart:837092 ClusterCount:1 GetLastError():0 DeviceIoControl return: 1 Bytes return: 0
StartingVcn.QuadPart:1486965 StartingLcn.QuadPart:837093 ClusterCount:2 GetLastError():0 DeviceIoControl return: 1 Bytes return: 0
StartingVcn.QuadPart:11377226 StartingLcn.QuadPart:837095 ClusterCount:114 GetLastError():0 DeviceIoControl return: 1 Bytes return: 0
Кластеры файла заданы правильно (DiskExplorer)
В MFT таблице на месте на которое перемещается файл ничего нету
BytesPerSector 512
SectorsPerCluster 8
Перые сектора первых крастеров после копирования
775079*8=6200632 — источник
837091*8=6696728 — приемник
Re[5]: Дефрагментация и FSCTL_MOVE_FILE
По-моему, вы путаете VCN и LCN. VCN — это virtual cluster number. Допустим у вас есть файл. Он занимает на диске 5 кластеров. Тогда для этого файла VCN может принимать значения от 0 до 4. LCN — это logical cluster number, то есть номер кластера на томе.
Поэтому вот это
StartingVcn.QuadPart:775079
выглядит странно. Здесь должен быть ноль, а не 775079. 775079 — это текущее значение LCN для VCN=0.
B>А вот даные которые передаются в функцию и котоые она возвращает:
B>B>StartingVcn.QuadPart:775079 StartingLcn.QuadPart:837091 ClusterCount:1 GetLastError():0 DeviceIoControl return: 1 Bytes return: 0
B>StartingVcn.QuadPart:776211 StartingLcn.QuadPart:837092 ClusterCount:1 GetLastError():0 DeviceIoControl return: 1 Bytes return: 0
B>StartingVcn.QuadPart:1486965 StartingLcn.QuadPart:837093 ClusterCount:2 GetLastError():0 DeviceIoControl return: 1 Bytes return: 0
B>StartingVcn.QuadPart:11377226 StartingLcn.QuadPart:837095 ClusterCount:114 GetLastError():0 DeviceIoControl return: 1 Bytes return: 0
B>
Re[6]: Дефрагментация и FSCTL_MOVE_FILE
От:
bixbit
Дата: 13.08.12 21:08
Оценка:
D>По-моему, вы путаете VCN и LCN. VCN — это virtual cluster number. Допустим у вас есть файл. Он занимает на диске 5 кластеров. Тогда для этого файла VCN может принимать значения от 0 до 4. LCN — это logical cluster number, то есть номер кластера на томе.
Спасибо большое !
Именно VCN и LCN я и попутал.
Теперь всё работает.
Но я так и не понял почему в FSCTL_MOVE_FILE не прописана переверка этого параметра.
"Но это уже совсем другая история"
Ниже привожу исправленый кусок кода.
Он точно кому-то пригодится:
MoveParams.StartingVcn.QuadPart = 0;
for (ULONG r = 0; r < OutBuf->ExtentCount; r++)
{
DWORD br;
MoveParams.ClusterCount =OutBuf->Extents[r].NextVcn.QuadPart - PrevVCN.QuadPart;
if (DeviceIoControl(hDisk,FSCTL_MOVE_FILE,&MoveParams,sizeof (MoveParams),NULL,0,&br,NULL))
printf("error %d\n" ,GetLastError());
MoveParams.StartingLcn.QuadPart=MoveParams.StartingLcn.QuadPart+MoveParams.ClusterCount;
MoveParams.StartingVcn.QuadPart = MoveParams.StartingVcn.QuadPart +MoveParams.ClusterCount;
PrevVCN = OutBuf->Extents[r].NextVcn;
}
Пока на собственное сообщение не было ответов, его можно удалить.
Удалить