CreateFile:直接对原始磁盘进行写入操作“访问被拒绝” - Vista,Win7
Posted
技术标签:
【中文标题】CreateFile:直接对原始磁盘进行写入操作“访问被拒绝” - Vista,Win7【英文标题】:CreateFile: direct write operation to raw disk "Access is denied" - Vista, Win7 【发布时间】:2012-01-31 10:57:24 【问题描述】:相关的微软文档是:Blocking Direct Write Operations to Volumes and DisksCreateFile, remarks on Physical Disks and Volumes
可执行文件是用 C++ 编写的,它调用CreateFile()
打开一个没有文件系统的 SD 卡。在没有管理员权限的情况下,CreateFile()
和连续的 ReadFile()
调用对于 GENERIC_READ
是成功的。
CreateFile
对GENERIC_WRITE
失败,即使具有管理员权限也是如此。在资源管理器中,我在属性 > 兼容性 > 权限级别下设置了以管理员身份运行。我还尝试从管理员 cmd 运行可执行文件(以 Ctrl+Shift+Enter 开头,“管理员:”在窗口标题中,适当提升)。尽管如此,我还是得到了ERROR_ACCESS_DENIED
(0x5)。
我是否必须将其他内容传递给CreateFile
? 我不知道什么是安全属性,我只是在第 92 行传递 NULL、relevant code is here,在第 48 行传递 here .
或者是否应该设置其他任何东西来以管理员权限运行该进程?
一个相关问题:
Can I get write access to raw disk sectors under Vista and Windows 7 in user mode?Raw partition access in Windows VistaHow to obtain direct access to raw HD data in C?Is there a clean way to obtain exclusive access to a physical partition under Windows?
【问题讨论】:
如果没有文件系统创建文件应该失败。也许在读取至少一个字节之前它不会失败,而写入则试图在打开时创建一个实际(空)文件。 @DannyVarod 阅读就像一个魅力,我已经阅读了大量数据并且数据是正确的。请参阅Microsoft's doc、CreateFile
是处理没有文件系统的驱动器的方法。
什么值作为 access 参数传递给open_device()
?
@wallyk GENERIC_WRITE
,另见line 48。我已经在这个问题上设置了赏金。
让我们从基础开始:是否已请求独占写入权限?
【参考方案1】:
虽然@MSalters 的答案是有道理的,但这不是我的代码的工作方式。事实上,它是如此违反直觉,我花了几天时间确保代码确实有效。
这些代码 sn-ps 位于经过验证的大众消费市场软件产品中。当它需要修改磁盘结构时,它会卸载 win32 卷,以便修改 NTFS 或 FAT 文件系统结构。有趣的是,卷访问句柄是只读的:
char fn [30];
snprintf (fn, sizeof fn, "\\\\.\\%s:", vol -> GetVolName ());
vol_handle = CreateFile (fn, GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_FLAG_NO_BUFFERING | FILE_FLAG_RANDOM_ACCESS,
NULL);
if (vol_handle == INVALID_HANDLE_VALUE)
// show error message and exit
如果无法获得对卷或分区的写入权限,如果用户在严厉警告后授权,则此代码会强制卸载:
if (!DeviceIoControl (vol_handle, FSCTL_DISMOUNT_VOLUME,
NULL, 0, NULL, 0, &status, NULL))
DWORD err = GetLastError ();
errormsg ("Error %d attempting to dismount volume: %s",
err, w32errtxt (err));
// lock volume
if (!DeviceIoControl (vol_handle, FSCTL_LOCK_VOLUME,
NULL, 0, NULL, 0, &status, NULL))
// error handling; not sure if retrying is useful
然后写入相当简单,除了将文件指针定位为 512 字节扇区:
long hipart = sect >> (32-9);
long lopart = sect << 9;
long err;
SetLastError (0); // needed before SetFilePointer post err detection
lopart = SetFilePointer (vol_handle, lopart, &hipart, FILE_BEGIN);
if (lopart == -1 && NO_ERROR != (err = GetLastError ()))
errormsg ("HWWrite: error %d seeking drive %x sector %ld: %s",
err, drive, sect, w32errtxt (err));
return false;
DWORD n;
if (!WriteFile (vol_handle, buf, num_sects*512, &n, NULL))
err = GetLastError ();
errormsg ("WriteFile: error %d writing drive %x sectors %lu..%lu: %s",
err, drv, sect, sect + num_sects - 1,
w32errtxt (err));
return false;
【讨论】:
对不起,当我注意到你的回答时,我已经奖励了赏金。无论如何,你能把你的答案说得更明确一些吗?您是否想说仅 GENERIC_READ 就足以获得写访问权限? @Ali:GENERIC_READ 确实如此。一旦锁定成功,后续的写操作就可以正常工作。至于积分,也许你可以投票? :-) 是的,对于赏金我真的很抱歉,我赞成你的问题。我会试试你写的东西,如果它真的有效,我会在问题的末尾添加一个注释。这是我现在能做的最好的了…… 谢谢你,它拯救了我的一天。但是我仍然需要五个小时来弄清楚对于 \\.\PhysicalDriveX 路径,没有 GENERIC_WRITE 它不会让你在 Windows 7 上编写。 @daminetreg:自从几年前公司被出售以来,我不知道客户在 Vista/Win7/Win8 上运行我的代码的任何反馈,但是,从你们的 cmets 看来,API变得更加直观。【参考方案2】:很少需要GENERIC_WRITE
。你很可能想要GENERIC_READ|GENERIC_WRITE
。
【讨论】:
好的,这就是问题所在 :) 你能解释一下为什么吗? 不是 100% 确定,还没有审查你的整个代码。许多“修改”风格的操作通过读取大量数据、更改他们想要的位并将整个数据块写回来工作。例如。您无法将一个字节物理地写入硬盘,但文件系统却假装您可以。显然你需要读写权限。 顺便提一下,SD 卡的块大小异常大,通常为 128k。我不知道 Windows 如何在低级别处理此问题,但很可能您需要读取访问权限才能写入小于此数量的数量(在硬件级别,您将 128k 读入内存,更改部分您需要更改、擦除块并将其写回;Windows 内核很可能会决定需要读取访问权限才能执行此操作,即使读取不是由用户级代码启动)。 @Jules:这对操作系统是隐藏的。【参考方案3】:在 MSDN 的 CreateFile 文档中有注释:
对磁盘或卷的直接访问受到限制。有关详细信息,请参阅帮助和支持知识库http://support.microsoft.com/kb/942448 中的“更改文件系统和存储堆栈以限制 Windows Vista 和 Windows Server 2008 中的直接磁盘访问和直接卷访问”。
它指的是Vista/2008,但可能也适用于Win7。
【讨论】:
我已经阅读了,但我该怎么办?问题是什么?在文档中,如果未安装卷或 如果卷有没有文件系统。”就我而言,没有文件系统。【参考方案4】:从 x86 移植到 x64 代码时,我遇到了类似的问题。您提到您正在为您的 SECURITY_ATTRIBUTES 参数传递null
;在我真正开始创建/传递此参数之前,我自己使用这种方法遇到了拒绝访问错误。
【讨论】:
不幸的是,我只有 VB.NET 代码来展示这个,而且因为我使用的是 .NET 框架,所以发布它可能只是浪费你的时间 - 但如果你知道,请告诉我无论如何希望我这样做。以上是关于CreateFile:直接对原始磁盘进行写入操作“访问被拒绝” - Vista,Win7的主要内容,如果未能解决你的问题,请参考以下文章