调用 IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER 时句柄无效
Posted
技术标签:
【中文标题】调用 IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER 时句柄无效【英文标题】:Invalid handle when calling IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER 【发布时间】:2012-03-21 15:54:38 【问题描述】:有没有人有过 c/c++ IOCTL 调用的经验? 基本上,我试图确定 USB 记忆棒插入的端口。 我有所有的 USB 信息和音量信息。显然,要链接这两个信息块,我需要驱动程序密钥或序列号。 但是,当调用 DeviceIoControl 时,我得到无效句柄作为“最后一个错误代码”
我的驱动器 USB 驱动器安装到 c:\ 中的目录(不是驱动器号)见下文
//get a handle on the volume
HANDLE hVolume;
DWORD dwAccessFlags;
dwAccessFlags = GENERIC_READ | GENERIC_WRITE;
hVolume = CreateFile(L"C:\_USB\MP1",
dwAccessFlags,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL );
if (hVolume == INVALID_HANDLE_VALUE)
printf("Invalid Handle");
//use the handle
MEDIA_SERIAL_NUMBER_DATA* pserialNumberData = new MEDIA_SERIAL_NUMBER_DATA;
wstring result;
//HANDLE hVolume = OpenVolume(vname.substr(0, vname.length() - 1).c_str());
DWORD bytesReturned = 0;
LPDWORD lpBytesReturned = &bytesReturned;
OVERLAPPED over;
LPOVERLAPPED lpOver = &over;
BOOL success = 1;
success = DeviceIoControl(
(HANDLE) hVolume, // handle to device
IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER, // dwIoControlCode
NULL, // lpInBuffer
0, // nInBufferSize
(LPVOID) pserialNumberData, // output buffer
(DWORD) sizeof(MEDIA_SERIAL_NUMBER_DATA), // size of output buffer
(LPDWORD) lpBytesReturned, // number of bytes returned
(LPOVERLAPPED) lpOver // OVERLAPPED structure
);
wcout << L"--> GetSn() DeviceIoControl success " << success << endl;
wcout << L"--> GetSn() DeviceIoControl Last error number " << GetLastError() << endl;
wcout << L"--> GetSn() DeviceIoControl Bytes Returned " << bytesReturned << endl;
wcout << L"--> GetSn() DeviceIoControl struct size " << sizeof(MEDIA_SERIAL_NUMBER_DATA) << endl;
【问题讨论】:
为什么到处都是不必要的错误隐藏演员? C风格的演员在那!为什么要调用new
来获取MEDIA_SERIAL_NUMBER_DATA
结构?
谢谢比利,实际上我需要我能得到的所有帮助。我是一名 Java 开发人员,这东西很可怕!! :-) 理想情况下,我也想为此编写单元测试,但我猜那是不可能的。
【参考方案1】:
如果您查看 DeviceIoControl 函数的备注部分,它会显示:
要检索设备句柄,您必须使用设备名称或与设备关联的驱动程序名称调用
CreateFile
函数。要指定设备名称,请使用以下格式:\\.\DeviceName
DeviceIoControl 可以接受特定设备的句柄。例如,要打开逻辑驱动器 A 的句柄:使用
CreateFile
,指定\\.\a:
。或者,您可以使用名称\\.\PhysicalDrive0
、\\.\PhysicalDrive1
等来打开系统上物理驱动器的句柄。
您没有打开设备句柄,因此 DeviceIoControl 不适用于这种情况。
【讨论】:
【参考方案2】:我看到的第一个大问题是必须使用 FILE_FLAG_BACKUP_SEMANTICS 标志调用 CreateFile 函数才能获得目录的有效句柄。因此,对于初学者,请尝试:
hVolume = CreateFile( L"C:\_USB\MP1",
dwAccessFlags,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL );
【讨论】:
【参考方案3】:嗯...我认为您从 CreateFile 获得的句柄是您将驱动器安装到的目录的句柄,而不是驱动器本身。为确保您获得所需设备的句柄,您应该使用设备路径,例如\\.\Device\HarddiskVolume1
。 WinObj 或 DeviceTree 可能会帮助您找到 USB 驱动器的路径。
【讨论】:
HarddiskVolume1 不是一个设备,它是一个卷。您必须针对物理设备句柄进行调用,例如\\.\PhysicalDrive0
,如 DeviceIoControl
文档中所述。
我只是提供了一个设备路径的例子。以上是关于调用 IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER 时句柄无效的主要内容,如果未能解决你的问题,请参考以下文章