【发布时间】:2016-10-10 20:55:30
【问题描述】:
我只想将卷句柄的文件指针从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");
输出:
为卷 \\.\C 获取的句柄: 设置文件指针(开始)成功! 设置文件指针(结束)失败! 错误 0x57:参数不正确。 设置文件指针(当前)成功!如您所见,对于 FILE_BEGIN 和 FILE_CURRENT,搜索工作正常,但对于 FILE_END 总是失败,错误代码为 0x57(十进制为 87):
请注意,将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 查找。
【问题讨论】:
-
printf("SetFilePointer (BEGIN) FAILED!\n");离题,但您不应该冒险调用可能会设置错误标志的函数。您应该尽快使用GetLastError的值。例如,在调用任何其他函数之前立即将 GetLastError 的值保存在变量中,然后使用该变量输出信息。 -
为了记录,卷访问与物理磁盘访问遵循相同的对齐规则。
-
@HarryJohnston 是的,但存在差异。卷访问可以通过对齐逻辑扇区大小(很容易获得,并且在 Windows 上的 HDD 几乎普遍为 512 字节)来执行,但物理访问对齐取决于硬件并且不太容易获得。
-
@SeyedMohammad:我认为这不是真的。 Windows 应该只关心逻辑扇区大小,即使您正在写入物理磁盘对象。你有参考吗?
-
@HarryJohnston 是的,这在这篇 MSDN 文章中进行了讨论:msdn.microsoft.com/en-us/library/cc644950%28v=vs.85%29.aspx