CreateFile:直接写入原始磁盘操作“访问被拒绝” - Vista,Win7

时间:2012-01-01 18:29:59

标签: c++ .net c winapi windows-7

相关的Microsoft文档是:
Blocking Direct Write Operations to Volumes and Disks
CreateFile, remarks on Physical Disks and Volumes

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

即使拥有管理员权限,

CreateFile也无法GENERIC_WRITE。在资源管理器中,我在Properties>下设置Run as Administrator。兼容性>特权等级。我还尝试从Administrator cmd运行可执行文件(以Ctrl + Shift + Enter开头,“管理员:”在窗口标题中,正确提升)。我仍然得到ERROR_ACCESS_DENIED(0x5)。

我是否必须将其他内容传递给CreateFile我不知道安全属性是什么,我只是在第92行传递NULL,relevant code is here,{{ 3}}在第48行。

或者是否还有其他设置可以使用管理员权限运行该进程?

<小时/> 相关问题:

here
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?

4 个答案:

答案 0 :(得分:15)

虽然@MSalters的答案是有道理的,但我的代码并不是这样的。事实上,这是违反直觉的,我花了几天时间确保代码确实有效。

这些代码段是经过验证的大众消费者市场软件产品。当需要修改磁盘结构时,它会卸载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;
    }

答案 1 :(得分:13)

很少需要GENERIC_WRITE。您最有可能想要GENERIC_READ|GENERIC_WRITE

答案 2 :(得分:1)

在MSDN的CreateFile文档中有注释:

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

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

答案 3 :(得分:0)

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