C++ CreateFile:直接写入原始磁盘“访问被拒绝” - Vista、Win7

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8694713/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:59:21  来源:igfitidea点击:

CreateFile: direct write operation to raw disk "Access is denied" - Vista, Win7

c++.netcwinapiwindows-7

提问by Ali

The relevant Microsoft doc is:
Blocking Direct Write Operations to Volumes and Disks
CreateFile, remarks on Physical Disks and Volumes

相关的 Microsoft 文档是:
Blocking Direct Write Operations to Volumes and Disks
CreateFile,关于物理磁盘和卷的评论

The executable is written in C++ and it calls CreateFile()to open an SD card that has no filesystem. The CreateFile()and consecutive ReadFile()calls are successful for GENERIC_READwithout Administrator privileges.

可执行文件是用 C++ 编写的,它调用CreateFile()打开一个没有文件系统的 SD 卡。在CreateFile()和连续ReadFile()通话是成功的为GENERIC_READ没有管理员权限。

CreateFilefails for GENERIC_WRITEeven with Administrator privileges. In the explorer, I set Run as Administrator under Properties > Compatibility > Privilege Level. I also tried to run the executable from an Administrator cmd (started with Ctrl+Shift+Enter, "Administrator:" is in the window title, properly elevated). Still, I get ERROR_ACCESS_DENIED(0x5).

CreateFileGENERIC_WRITE即使具有管理员权限也失败。在资源管理器中,我在“属性”>“兼容性”>“权限级别”下设置“以管理员身份运行”。我还尝试从管理员 cmd 运行可执行文件(以 Ctrl+Shift+Enter 开始,“管理员:”在窗口标题中,正确提升)。不过,我得到ERROR_ACCESS_DENIED(0x5)。

Do I have to pass something else to CreateFile?I have no idea what security attributes are, I just pass NULL, relevant code is hereat line 92, and hereat line 48.

我必须传递其他东西CreateFile吗?我不知道什么样的安全属性,我只是通过NULL,相关的代码是在这里,在92行,和这里的48行。

Or is there anything else that should be set to run the process with Administrator privileges?

或者是否应该设置其他任何内容以使用管理员权限运行该进程?



一个相关问题:

Can I get write access to raw disk sectors under Vista and Windows 7 in user mode?
Raw partition access in Windows Vista
How 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?

我可以在用户模式下在 Vista 和 Windows 7 下获得对原始磁盘扇区的写访问权限吗?
Windows Vista 中的原始分区访问
如何直接访问 C 中的原始 HD 数据?
有没有一种干净的方法可以在 Windows 下获得对物理分区的独占访问权限?

采纳答案by MSalters

It's quite rare to want only GENERIC_WRITE. You most likely want GENERIC_READ|GENERIC_WRITE.

只想要 是很罕见的GENERIC_WRITE。你很可能想要GENERIC_READ|GENERIC_WRITE.

回答by wallyk

While the answer of @MSalters makes sense, it is not how my code works. In fact it is so counter-intuitive, I spent several days making sure the code does in fact work.

虽然@MSalters 的回答是有道理的,但这不是我的代码的工作方式。事实上,这太违反直觉了,我花了几天时间来确保代码确实有效。

These code snippets are in a proven, mass consumer market software product. When it needs to modify an on-disk structure, it dismounts the win32 volume so it can modify NTFS or FAT filesystem structures. Interestingly, the volume access handle is read-only:

这些代码片段位于经过验证的大众消费市场软件产品中。当它需要修改磁盘结构时,它会卸载 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 unable to get write access to a volume or partition, this code forces a dismount if the user authorizes such after a stern warning:

如果无法获得对卷或分区的写访问权限,如果用户在发出严厉警告后授权,此代码将强制卸载:

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
}

Writing is then fairly straightforward, except for positioning the file pointer by 512-byte sector:

写入相当简单,除了按 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;
    }

回答by rkosegi

There is note in MSDN in documentation of CreateFile:

MSDN 的 CreateFile 文档中有注释:

Direct access to the disk or to a volume is restricted. For more information, see "Changes to the file system and to the storage stack to restrict direct disk access and direct volume access in Windows Vista and in Windows Server 2008" in the Help and Support Knowledge Base at http://support.microsoft.com/kb/942448.

对磁盘或卷的直接访问受到限制。有关详细信息,请参阅http://support.microsoft 上帮助和支持知识库中的“更改文件系统和存储堆栈以限制 Windows Vista 和 Windows Server 2008 中的直接磁盘访问和直接卷访问” 。 com/kb/942448

It refers to Vista/2008, but maybe apply to Win7 also.

它指的是 Vista/2008,但也可能适用于 Win7。

回答by Sukasa

I had a similar issue when porting from x86 to x64 code. You mention that you are passing nullfor your SECURITY_ATTRIBUTES parameter; I was getting access-denied errors myself using this approach until I actually began creating/passing this parameter.

从 x86 移植到 x64 代码时,我遇到了类似的问题。您提到您正在传递nullSECURITY_ATTRIBUTES 参数;在我实际开始创建/传递此参数之前,我自己使用这种方法遇到了拒绝访问的错误。