c++ - 根据 GetLastError 直接写磁盘导致错误代码 5
问题描述
我正在尝试在 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);
}
解决方案
我认为您没有正确锁定音量。
FSCTL_DISMOUNT_VOLUME
IO 控制卸载文件系统,但我认为它不会锁定它以进行写入。之后使用FSCTL_LOCK_VOLUME
(或者,如果该卷没有 Windows 可读文件系统因此未安装)来请求写访问权。
PS我认为你需要你的应用程序运行提升才能使用该API。
推荐阅读
- vim - [Vim][Markdown] 如何禁用 url 折叠?
- intercom - 使用 Intercom 的 API 从分段请求用户时结果不一致
- ios - 文本字段和图像为零
- scala - 有条件地构建避免突变的列表
- format - 如何更改 WHMCS 价格小数分隔符?
- java - 在具有多个模块的配置中找不到 Java Bean
- openid - .AspNetCore.Correlation。未找到国家财产
- java - Spring MVC:无法连接到 Rest 服务
- sql-server-2008 - CTGIN2076E: 用于任务验证的异常运行数据库方法
- node.js - 查询期间要在服务器上执行的MongoDB密码