根据 GetLastError 直接写磁盘导致错误代码 5
Posted
技术标签:
【中文标题】根据 GetLastError 直接写磁盘导致错误代码 5【英文标题】:Direct writing a disk results in error code 5 according to GetLastError 【发布时间】:2019-03-26 01:14:19 【问题描述】:我正在尝试在 Windows 中直接写入 U 盘。我使用CreateFile
函数创建磁盘句柄并使用WriteFile
函数尝试写入文件。 WriteFile 函数失败,状态码为 5(根据 GetLastError)。我尝试使用FSCTL_DISMOUNT_VOLUME
锁定磁盘卷,但该卷被隐藏,所以我无法获取它的卷号。
代码:
u8 Disk::Init()
char fn[24] = 0 ;
sprintf(fn, "\\\\.\\PhysicalDrive%d", (int)m_nDiskNum);
m_hDisk = CreateFileA(fn, GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, 0);
if (INVALID_HANDLE_VALUE == m_hDisk)
return (FAIL);
//m_DiskInfo.Init();
return Lock();
u8 Disk::Lock()
STORAGE_DEVICE_NUMBER d1;
DWORD nr;
char dn[8], c;
if (!DeviceIoControl((HANDLE)m_hDisk, IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &d1, sizeof(d1), &nr, 0))
return (FAIL);
strcpy(dn, "\\\\.\\A:");
// some volume is hided, so I cannot get its letter
for (c = 'C'; c < 'Z'; c++)
HANDLE hd;
STORAGE_DEVICE_NUMBER d2;
dn[4] = c;
hd = CreateFileA(dn, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, 0, 0);
if (hd == INVALID_HANDLE_VALUE)
continue;
if ((!DeviceIoControl(hd, IOCTL_STORAGE_GET_DEVICE_NUMBER,
NULL, 0, &d2, sizeof(d2), &nr, 0)) ||
(d1.DeviceType != d2.DeviceType) ||
(d1.DeviceNumber != d2.DeviceNumber))
CloseHandle(hd);
continue;
if (!DeviceIoControl(hd, FSCTL_DISMOUNT_VOLUME, NULL, 0, NULL, 0,
&nr, 0))
CloseHandle(hd);
return (FAIL);
m_LockedVolums.push_back(hd);
return (SUCC);
u8 Disk::UnLock()
for (auto it : m_LockedVolums)
CloseHandle(it);
m_LockedVolums.clear();
return (SUCC);
u8 Disk::WriteSector(_Out_opt_ u8 * cBuf, int nStartSec, int nSecCont/* = 1*/)
if (Seek(nStartSec))
return(FAIL);
unsigned long nWrited;
if ((!WriteFile((HANDLE)m_hDisk, cBuf, nSecCont * m_nBytePerSec, &nWrited, NULL))
|| (nSecCont * m_nBytePerSec != (int)nWrited))
return(FAIL);
return(SUCC);
【问题讨论】:
【参考方案1】:我认为您没有正确锁定音量。
FSCTL_DISMOUNT_VOLUME
IO 控制卸载文件系统,但我认为它不会锁定它以进行写入。之后使用FSCTL_LOCK_VOLUME
(或者,如果该卷没有 Windows 可读的文件系统因此未挂载)来请求写入权限。
附:我认为您需要提升您的应用程序运行才能使用该 API。
【讨论】:
感谢您的回答!但是“FSCTL_DISMOUNT_VOLUME”对我来说已经足够写了,而且我的应用程序已经在“requireAdministrator (/level='requireAdministrator')”下运行了。要使用“FSCTL_DISMOUNT_VOLUME”应该有卷号,但在windows中没有隐藏卷的字母。所以这就是问题所在。 @yunate 这是你可以尝试的。安装例如硬盘原始复制工具。运行它,同时运行 sysinternals 进程监视器和设置过滤器以仅包含来自 RawCopy.exe 的事件。使用 HDD 原始副本将映像写入该 USB 驱动器。这样,在进程监视器中,您将看到 RawCopy.exe 究竟对哪个文件句柄做了什么,因此您可以复制该功能。以上是关于根据 GetLastError 直接写磁盘导致错误代码 5的主要内容,如果未能解决你的问题,请参考以下文章
无法访问移动磁盘显示设备硬件出现致命错误,导致请求失败的数据找到法子
FindWindow() 失败,但 GetLastError 返回 0