WinXP Pro SP2, Visual Studio 2005 SP1

I've been experimenting with the defrag API, just to see if I could get it working. I have had no trouble using FSCTL_GET_VOLUME_BITMAP and FSCTL_GET_RETRIEVAL_POINTERS, but I'm falling at the last hurdle when trying to use FSCTL_MOVE_FILE.

The disk I'm using for my testing is a FAT32 USB key of mine, so that I don't mess up this machine's disks!

I've tried opening the volume and file with

GENERIC_READ and FILE_SHARE_WRITE

and also

GENERIC_READ|GENERIC_WRITE and FILE_SHARE_WRITE

but in either case, DeviceIOControl() returns (via GetLastError() ) ERROR_INVALID_PARAMETER. There's no easy way to tell exactly what the fault is. In this particular case I was trying to move the entire 799 clusters of a file to an LCN that I am confident is free, since I gathered the free and filled ranges via FSCTL_GET_VOLUME_BITMAP.

The code I'm using around DeviceIOControl() is:

Code:
MOVE_FILE_DATA sData ;
sData.FileHandle = rhFile ;
sData.StartingVcn.QuadPart = 0 ;
sData.StartingLcn.QuadPart = llTargetIndex ;

DWORD dwSize ;
if (::DeviceIoControl(rhVolume, FSCTL_MOVE_FILE, 
                                 &sData, sizeof(sData), 
                                 NULL, 0, &dwSize, NULL) == 0)
{
         bMovedOK = false ;
         DWORD dwError = GetLastError();

}

Can anyone see anything potentially wrong, and does anyone know the minimum flags required for CreateFile() on both the volume and the file? I cannot seem to find anything from a Google that indicates the correct flags - I wish the function itself in MSDN would specify them.

Since this is neither an NTFS volume nor a compressed file / volume, I do not believe any of the restrictions mentioned apply.