samedi 11 juin 2016

SetFilePointer from FILE_END always fails for a volume handle

I simply want to move the file-pointer of a volume handle backwards from FILE_END. Unfortunately, the operation fails regardless of any input value I pass to it !

I'm using the following code:

HANDLE vol_handle = CreateFile ("\\.\C:",
                         GENERIC_READ | GENERIC_WRITE,
                         FILE_SHARE_READ | FILE_SHARE_WRITE,
                         NULL, OPEN_EXISTING, 0, NULL);

if (vol_handle == INVALID_HANDLE_VALUE)
{
    printf("Failed to create volume handle!n");
    print_last_error(GetLastError());
    return ERROR;
}
printf("Handle acquired for volume %s n", VOLUME);

long int dist = 512000; // 500 KB forwards

SetLastError(0);
int result = SetFilePointer (vol_handle, dist, NULL, FILE_BEGIN);
if (result == INVALID_SET_FILE_POINTER)
{
    printf("SetFilePointer (BEGIN) FAILED!n");
    print_last_error(GetLastError());
}
else
    printf("SetFilePointer (BEGIN) SUCCESS!n");

dist = -5120; // 50 KB backwards

SetLastError(0);
result = SetFilePointer (vol_handle, dist, NULL, FILE_END);
if (result == INVALID_SET_FILE_POINTER)
{
    printf("SetFilePointer (END) FAILED!n");
    print_last_error(GetLastError());
}
else
    printf("SetFilePointer (END) SUCCESS!n");

SetLastError(0);
result = SetFilePointer (vol_handle, dist, NULL, FILE_CURRENT);
if (result == INVALID_SET_FILE_POINTER)
{
    printf("SetFilePointer (CURRENT) FAILED!n", offset_low_part);
    print_last_error(GetLastError());
}
else
    printf("SetFilePointer (CURRENT) SUCCESS!n");

The output:

  Handle acquired for volume \.C:
  SetFilePointer (BEGIN) SUCCESS!
  SetFilePointer (END) FAILED!
     Error 0x57: The parameter is incorrect.
  SetFilePointer (CURRENT) SUCCESS!

As you can see, the seek works fine for FILE_BEGIN and FILE_CURRENT, but it always fails for FILE_END with error code 0x57 (87 in decimal) saying:

  The parameter is incorrect

Note that changing dist to a positive value doesn't change the situation.

What am I missing here?

( NOTE: Testing on Windows-5.1.2600 (XP SP3) in latest Code::Blocks IDE 16.01 with MinGW compiler, and Administrator privileges )


NOTE: This is absolutely not a duplicate of this question, since I am not accessing physical disk (volume access is different from physical disk) and the distance value is a multiple of 512 bytes (the logical sector size). If the distance length was incorrect, then the other seeks (BEGIN and CURRENT) would have failed as well, yet they don't.


Update

Based on Rohans' answer, I performed another check with the following code:

long long int offset_64 = 5120000 // 5000 KB distance;
long int offset_low_part = -(0xffffffff & offset_64);
long int offset_hig_part = offset_64 >> 32;

printf("offset_64 = %lldn", offset_64);
printf("low_part  = %ldn", offset_low_part);
printf("high_part = %ldnn", offset_hig_part);

// Get volume handle using CreateFile(...) exactly as before;

SetLastError(0);
int result = SetFilePointer (vol_handle, offset_low_part, &offset_hig_part, FILE_END);

if (result == INVALID_SET_FILE_POINTER)
{
    print_last_error(GetLastError());
    printf("Failed to set file pointer!n");
    printf("high_part after SetFilePointer = %ldn", offset_hig_part);
    return ERROR;
}

Although I believe Rohans' point is important, it still doesn't solve the problem:

offset_64 = 5120000
low_part  = -5120000
high_part = 0

Handle acquired for volume \.C:
Error 0x57: The parameter is incorrect.
Failed to set file pointer!
high_part after SetFilePointer = 0

Using a positive value for low_part doesn't change the situation.


Update

Based on David Heffernan's comment below, I acknowledge that this code can be shorter and easier using SetFilePointerEx, but the result is still the same and the operation fails to seek from FILE_END on the volume handle.

Aucun commentaire:

Enregistrer un commentaire