Дефрагментация и 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++' — Кодт
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.