Дефрагментация и 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
От: dimb82  
Дата: 12.08.12 05:56
Оценка: 1 (1)
Можно использовать функцию 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
От: dimb82  
Дата: 13.08.12 03:54
Оценка: 1 (1)
Во-первых, попробуйте добавить привилегию 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
От: dimb82  
Дата: 13.08.12 18:01
Оценка: 3 (1)
По-моему, вы путаете 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;
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.