我只想从FILE_END
向后移动卷句柄的文件指针。不幸的是,无论我传递给它的任何输入值,操作都会失败!
我使用以下代码:
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");
输出:
Handle acquired for volume \\.\C: SetFilePointer (BEGIN) SUCCESS! SetFilePointer (END) FAILED! Error 0x57: The parameter is incorrect. SetFilePointer (CURRENT) SUCCESS!
正如您所看到的,该搜索适用于FILE_BEGIN
和FILE_CURRENT
,但FILE_END
的错误代码始终失败,错误代码为0x57
(十进制为87),表示:
The parameter is incorrect
请注意,将dist
更改为正值并不会改变这种情况。
我在这里缺少什么?
(注意:在最新的Code :: Blocks IDE 16.01中使用MinGW编译器和管理员权限在Windows-5.1.2600(XP SP3)上进行测试)
注意:这绝对不是this question的重复,因为我没有访问物理磁盘(卷访问与物理磁盘不同),距离值是512的倍数字节(逻辑扇区大小)。如果距离长度不正确,那么另一个寻求(BEGIN和CURRENT)也会失败,但他们不会。
根据Rohans'回答,我使用以下代码执行了另一项检查:
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 = %lld\n", offset_64);
printf("low_part = %ld\n", offset_low_part);
printf("high_part = %ld\n\n", 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 = %ld\n", offset_hig_part);
return ERROR;
}
虽然我相信Rohans'重要的是,它仍然没有解决问题:
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
使用low_part
的正值并不会改变这种情况。
根据David Heffernan在下面的评论,我承认使用SetFilePointerEx
可以缩短和简化此代码,但结果仍然相同,操作无法从FILE_END
寻求在音量处理上。
答案 0 :(得分:3)
这并不令人惊讶。卷不是文件,因此它没有文件结束位置。
Windows 当然可以使用卷长度作为文件结束位置,但没有特别的理由来处理这种特殊情况。
您必须自己计算偏移量。
答案 1 :(得分:2)
您可能必须在api调用中传递第3个参数的非NULL值。
result = SetFilePointer (vol_handle, dist, NULL, FILE_END);
//-----------------------------------------^
所以改为
LONG distToMoveHigh = 0;
result = SetFilePointer (vol_handle, dist, &distToMoveHigh, FILE_END);
...
MSDN页面上提到的原因是
如果lpDistanceToMoveHigh为NULL并且新文件位置不适合32位值,则该函数将失败并返回INVALID_SET_FILE_POINTER。
当您使用音量时,它很可能是> 2GB。因此SetFilePointer()
api如果成功,将无法返回新的偏移量。