如何显式锁定已挂载的文件系统?

How to explicitly lock a mounted file system?

如何在 Windows 7 中写入物理驱动器?

我正在尝试在 Windows 7 中写入物理磁盘(例如 \.\PhysicalDrive0)。

这个问题已经被问 ,但从未得到回答。它曾经在 Windows XP 中工作,但 Microsoft 有意破坏了 Windows Vista。 Microsoft 提供了有关如何执行此操作的提示,但甚至没有人能够弄清楚。

它曾经有效

在过去,写入物理磁盘是允许的(只要您是管理员)。知识库文章中甚至记录了执行此操作的方法:

INFO: Direct Drive Access Under Win32

To open a physical hard drive for direct disk access (raw I/O) in a Win32-based application, use a device name of the form

\.\PhysicalDriveN

where N is 0, 1, 2, and so forth, representing each of the physical drives in the system.

You can open a physical or logical drive using the CreateFile() application programming interface (API) with these device names provided that you have the appropriate access rights to the drive (that is, you must be an administrator). You must use both the CreateFile() FILE_SHARE_READ and FILE_SHARE_WRITE flags to gain access to the drive.

在 Windows Vista 中发生了所有变化,当增加了安全限制时。

如何写入物理磁盘?

许多人,许多答案,对许多Whosebug问题感到困惑:

微软注意到 restrictions placed on both kinds of operations:

Blocking Direct Write Operations to Volumes and Disks

Write operations on a DASD (Direct access storage device) volume handle will succeed if:

  • the file system is not mounted, or if
  • The sectors being written to are the boot sectors.
  • The sectors being written to reside outside file system space.
  • The file system has been locked implicitly by requesting exclusive write access.
  • The file system has been locked explicitly by sending down a lock/dismount request.
  • The write request has been flagged by a kernel-mode driver that indicates that this check should be bypassed. The flag is called SL_FORCE_DIRECT_WRITE and it is in the IrpSp->flags field. This flag is checked by both the file system and storage drivers.

在我的例子中,我问的是写入 Physical,而不是 Logical。 Microsoft 注意到写入物理磁盘句柄的新限制集:

Write operations on a disk handle will succeed if:

  • The sectors being written to do not fall within a file system.
  • The sectors being written to fall within a mounted file system that is locked explicitly.
  • The sectors being written to fall within a file system that is not mounted or the volume has no file system.

有关如何使其工作的提示围绕着:

但问题是如何卸载文件系统?如何锁定文件系统?

你现在在做什么?

我能够读取磁盘的所有物理扇区;那没问题。问题是当我想 写入 到磁盘的物理扇区时。

我目前的伪代码是:

void ZeroSector(Int64 PhysicalSectorNumber)
{
    String diskName := '\.\PhysicalDrive0'; 

    DWORD desiredAccess := GENERIC_READ or GENERIC_WRITE;

    //INFO: Direct Drive Access Under Win32
    //https://support.microsoft.com/en-us/kb/100027
    //says you nedd both
    DWORD shareMode := FILE_SHARE_READ or FILE_SHARE_WRITE;

    //Open the physical disk
    hDisk := CreateFile(diskName, desiredAccess, shareMode,
            nil, OPEN_EXISTING, 0, 0);
    if hDisk = INVALID_HANDLE_VALUE
        RaiseLastWin32Error();
    try
    {
        Int32 bytesPerPhysicalSector := 4096; //Determined elsewhere using IOCTL_STORAGE_QUERY_PROPERTY+STORAGE_ACCESS_ALIGNMENT_DESCRIPTOR

        //Setup buffer for what we will be writing
        Byte[] buffer = new Byte[bytesPerPhysicalSector];

        //Calculate the byte offset of where the sector is
        Int64 byteOffset = PhysicalSectorNumber * bytesPerPhysicalSector;

        //Seek to that byte offset
        SetFilePointer(hDisk, byteOffset.Lo, byteOffset.Hi, FILE_BEGIN); 

        //Write the buffer
        DWORD numberOfBytesWritten;
        if (!WriteFile(hDisk, buffer, bytesPerPhysicalSector, out numberOfBytesWritten, nil))
            RaiseLastWin32Error();
    }
    finally
    {
        CloseHandle(hDisk);
    }
}

令人惊讶的是:

如何按照微软所说的去做

Microsoft 说我的写入会失败,他们是对的。他们说我需要明确锁定文件系统:

Write operations on a disk handle will succeed if:

  • The sectors being written to fall within a mounted file system that is locked explicitly.

只是我不知道该怎么做。

我知道我可能不得不使用DeviceIoControlIOCTLS之一到"lock"一个卷。但这带来了三个挑战:

忽略了那些问题,我盲目地尝试了LockFile API。就在调用 WriteFile 之前:

//Try to lock the physical sector we will be writing
if (!LockFile(DiskHandle, byteOffset.Lo, byteOffset.Hi, bytesPerPhysicalSector, 0)
   RaiseLastWin32Error();

失败:

ERROR_INVALID_FUNCTION (1)

查看 FSCTL_LOCK_VOLUME、FSCTL_DISMOUNT_VOLUME 控制代码。我相信您必须枚举磁盘上的所有卷,然后卸载并锁定它们。锁定成功后,磁盘就是你的了

不过您可能无法在系统驱动器上执行此操作。我还猜测对于包含页面文件的卷会有警告。

完成后,我可以写入相应的\\.\PhysicalDrive3。我之前不能:

HANDLE hVol = CreateFileA(
    "\\.\X:", 
    FILE_READ_DATA | FILE_WRITE_DATA,
    FILE_SHARE_READ | FILE_SHARE_WRITE,
    NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD unused;
BOOL b = DeviceIoControl(hVol, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0, &unused, NULL);
if (!b) {
    printf("%u", GetLastError());
    abort();
}

...
HANDLE h = CreateFileA(
    argv[1], // that's my \physicaldrive3
    FILE_READ_DATA | FILE_WRITE_DATA, 
    FILE_SHARE_READ | FILE_SHARE_WRITE, 
    NULL,
    OPEN_EXISTING,
    0,
    NULL);
...
    bResult = WriteFile(h, buf, cb, &dwWritten, &foo);
    if (!bResult) {
        // used to fail without messing with vol handle
        printf("Failed writing data. Error = %d.\n", GetLastError()); 
        return 0;
    }