Win Vista/7 下的 WriteFile 错误 #5“拒绝访问”

问题描述 投票:0回答:3

我有一个 C++ 控制台应用程序,可以读取 1GB SD 卡,修复不正确关闭的文件并相应地写入 FAT 表。 SD 卡一开始是由定制设备中的固件写入的。 它在 Xp 之前工作正常,在 Win Vista/7 中停止工作。 我尝试提升权限:在管理员帐户类型中,我使用“以管理员身份运行”方法启动了一个cmd窗口,但没有成功。 我还尝试使用清单请求最高可用权限,但没有成功。

我在一些帖子中读到“Windows Vista 根本不允许您从用户模式进程访问磁盘。有人知道绕过这种行为的方法吗?

我正在研究解决方法,但我想知道这是否不可能

编辑:

这是我在这里发表的第一篇文章,所以我不太了解链接问题...但我根本没有对任何垃圾邮件有任何反应...只是在社区驱动的网站中询问:)

代码看起来像

hDevice = CreateFile(buffer,GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,NULL, OPEN_EXISTING,0,NULL); 

然后我从 SD 读取 BTB 信息并查找未正确关闭的文件。

最后尝试写入 SD 时

WriteFile(hDevice,buffer,SD_SECTOR_SIZE, &temp, 0)

我收到拒绝访问(错误#5)

CreateFile() 上的字符串是 \.\g:因为 g 字母对应于我机器上的 SD 卡。所有这些都可以正常工作,正如我之前所说,它可以在 XP 上工作。我还尝试使用:DeviceIoControl 和 FSCTL_LOCK_VOLUME,但这会产生内存故障错误。

c++ winapi fat32
3个回答
1
投票

我认为这是由于路径字符串“buffer”造成的;我遇到了同样的问题。 您用于获取设备访问权限的路径需要类似于“\.\PhysicalDrive%d” %d 是驱动器的十进制数。

从 Vista 开始,此字符串区分大小写。 检查拼写。您还需要管理员权限,就像以前在 XP 中一样。

对于卷,。这封信需要大写 例如“\.\G:”

另请注意,将 SD 卡作为设备而不是卷进行访问要好得多,因为如果 Windows 挂载它,则可能会挂载一个带有写入缓存的文件系统。

此外:我忘了提到,您读取/写入数据的缓冲区应该是页面对齐的,并且读取的数据是扇区大小的倍数。 VirtualAlloc() 就是这样做的


1
投票

写入原始数据之前必须先卸载卷。

来自 MSDN:

如果卷没有安装的文件系统,或者满足以下条件之一,则对卷句柄的写入将会成功:

  • 要写入的扇区是引导扇区。
  • 要写入的扇区位于文件系统空间之外。
  • 您已使用 FSCTL_LOCK_VOLUME 或 FSCTL_DISMOUNT_VOLUME 显式锁定或卸载卷。
  • 该卷没有实际的文件系统。 (换句话说,它安装了 RAW 文件系统。)

如果满足以下条件之一,则对磁盘句柄的写入将会成功:

  • 要写入的扇区不在卷的范围内。
  • 要写入的扇区属于已安装的卷,但您已使用 FSCTL_LOCK_VOLUME 或 FSCTL_DISMOUNT_VOLUME 显式锁定或卸载该卷。
  • 要写入的扇区属于未安装除 RAW 之外的文件系统的卷。

示例代码

BOOL bResult = DeviceIoControl(hDevice,                // device to be queried
                               FSCTL_DISMOUNT_VOLUME,  // operation to perform
                               NULL, 0,                // no input buffer
                               pdg, sizeof(*pdg),      // output buffer
                               &junk,                  // # of bytes returned
                               (LPOVERLAPPED)NULL);    // synchronous I/O

0
投票

为了能够进行原始写入,您需要卸载卷,然后继续锁定它以执行操作,然后解锁它。您可以通过 FSCTL_DISMOUNT_VOLUME 和 FSCTL_LOCK_VOLUME 的 IO 控制来实现此目的

BOOL dismountVolume = DeviceIoControl(hDevice, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, NULL, NULL)

BOOL lockVolume  =  DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, NULL, NULL)

最好在创建句柄时设置文件属性 FILE_FLAG_WRITE_THROUGH 和 FILE_FLAG_NO_BUFFERING,以便直接写入内容,而不是使用缓冲区和缓存。

HANDLE hDevice = CreateFileA(
    hDevice.c_str(),
    GENERIC_WRITE,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL,
    OPEN_EXISTING,
    FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING,
    NULL
);

MSDN 链接:
https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile https://learn.microsoft.com/en-us/windows/win32/api/ioapiset/nf-ioapiset-deviceiocontrol

© www.soinside.com 2019 - 2024. All rights reserved.