【发布时间】:2015-05-24 02:25:40
【问题描述】:
如何在 Windows 7 中写入物理驱动器?
我正在尝试在 Windows 7 中写入物理磁盘(例如 \\.\PhysicalDrive0)。
这个问题已经被问死了,但从未得到回答。它曾经在 Windows XP 中工作,但微软故意破坏了 Windows Vista。微软提供了有关如何做到这一点的提示,但甚至没有人能够弄清楚。
它曾经工作过
在过去,允许写入物理磁盘(只要您是管理员)。执行此操作的方法甚至记录在知识库文章中:
INFO: Direct Drive Access Under Win32
要在基于 Win32 的应用程序中打开物理硬盘驱动器以直接访问磁盘(原始 I/O),请使用以下形式的设备名称
\\.\PhysicalDriveN其中 N 是 0、1、2 等,代表系统中的每个物理驱动器。
您可以使用带有这些设备名称的 CreateFile() 应用程序编程接口 (API) 打开物理或逻辑驱动器,前提是您对驱动器具有适当的访问权限(即,您必须是管理员)。您必须同时使用 CreateFile() FILE_SHARE_READ 和 FILE_SHARE_WRITE 标志才能访问驱动器。
所有这些都在 Windows Vista 中发生了变化,因为附加了安全限制。
如何写入物理磁盘?
许多人,许多答案,对许多stackoverflow问题感到困惑:
- 写入物理磁盘(例如
\\.\PhysicalDrive0),以及 - 写入逻辑卷(例如
\\.\C$)
微软注意到restrictions placed on both kinds of operations:
阻止对卷和磁盘的直接写入操作
在 DASD(直接访问存储设备)卷句柄上的写操作将成功如果:
- 文件系统没有挂载,或者如果
- 写入的扇区是引导扇区。
- 要写入的扇区位于文件系统空间之外。
- 文件系统已通过请求独占写入权限被隐式锁定。
- 已通过发送锁定/卸载请求明确锁定文件系统。
- 内核模式驱动程序已标记写入请求,指示应绕过此检查。该标志称为 SL_FORCE_DIRECT_WRITE,它位于 IrpSp->flags 字段中。文件系统和存储驱动程序都会检查此标志。
在我的情况下,我问的是写一个Physical,而不是一个Logical。 Microsoft 注意到写入物理磁盘句柄的新限制:
在以下情况下,磁盘句柄上的写操作将成功:
- 写入的扇区不属于文件系统。
- 写入的扇区属于已挂载的文件系统,该文件系统已被明确锁定。
- 正在写入的扇区属于未安装的文件系统或卷没有文件系统。
- 我正在写入的扇区确实属于文件系统 --> 失败
- 我正在写入的扇区确实属于已安装、未锁定的文件系统 --> 失败
- 我正在写入的扇区确实位于已挂载的文件系统中,并且位于具有文件系统的逻辑卷中。
关于如何使它工作的提示围绕着:
- 卸载文件系统
- 锁定文件系统
但问题是如何卸载文件系统?如何锁定文件系统?
你现在在做什么?
我能够读取磁盘的所有物理扇区;那没问题。问题是当我想写入到磁盘的物理扇区时。
我的当前代码是伪代码:
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);
}
}
令人惊讶的是:
- 我可以打开物理磁盘以供
GENERIC_READ+GENERIC_WRITE访问 -
直到实际的
WriteFile失败,它才会失败:ERROR_ACCESS_DENIED
如何按照微软所说的去做
微软说我的写作会失败,他们是对的。他们说我需要明确锁定文件系统:
在以下情况下,磁盘句柄上的写操作将成功:
- 写入的扇区属于已挂载的文件系统,该文件系统已被明确锁定。
除非我不知道该怎么做。
我知道我可能必须使用DeviceIoControl 和IOCTLS 之一来“锁定”一个卷。但这带来了三个挑战:
- 找出所选物理磁盘上的卷
- 找出要使用的 IOCTL
- 了解如何解锁锁定的卷
忽略这些问题,我盲目地尝试了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)
【问题讨论】:
标签: windows winapi windows-7 disk