使用IOCTL_CHANGER_GET_PRODUCT_DATA调用DeviceIoControl时出现ERROR_AC

ERROR_ACCESS_DENIED when calling DeviceIoControl with IOCTL_CHANGER_GET_PRODUCT_DATA

本文关键字:ERROR AC DeviceIoControl DATA CHANGER IOCTL GET PRODUCT 使用 调用      更新时间:2023-10-16

我有一项任务要获取作为磁盘安装的设备的VendorId和ProductId。代码看起来是这样的:

int main() {
HANDLE hDevice;
char cDisk = 'c';   // Get metadata about the C: disk
// Build the logical drive path and get the drive device handle
std::wstring logicalDrive = L"\\.\";
wchar_t drive[3];
drive[0] = cDisk;
drive[1] = L':';
drive[2] = L'';
logicalDrive.append(drive);
hDevice = CreateFile(
logicalDrive.c_str(),
FILE_READ_ATTRIBUTES,
0,
NULL,
OPEN_EXISTING,
0,
NULL);
_tprintf(_T("%sn"), logicalDrive.c_str());
if (hDevice == INVALID_HANDLE_VALUE)
{
std::cerr << "CreateFile error #" << GetLastError() << std::endl;
system("pause");
return -1;
}
// Now that we have the device handle for the disk, let us get disk's metadata  
CHANGER_PRODUCT_DATA dg = { 0 };
DWORD ioctlJnk;
if (!DeviceIoControl(hDevice,
IOCTL_CHANGER_GET_PRODUCT_DATA,
NULL,
0,
&dg,
sizeof(dg),
&ioctlJnk,
NULL)
)
{
std::cerr << "DeviceIoControl error #" << GetLastError() << std::endl;
CloseHandle(hDevice);
system("pause");
return -1;
}
// Success, now print the device manufacturer's name
std::cout << dg.VendorId << std::endl;
CloseHandle(hDevice);
}

问题是DeviceIoControl函数失败,GetLastError返回ERROR_ACCESS_DENIED。任何磁盘都会发生这种情况。

我能做些什么来使这个代码正常工作?任何其他想法如何得到VID&PID通过安装设备的特性?

提前感谢!

您可能需要以足够的访问权限和/或足够的权限打开设备来使用I/O控制功能,但您的根本问题是使用的设备类型不对。IOCTL_CHANGER_*功能仅适用于转换器设备,并且这些设备的文件名为\.Changer#。来自MSDN上的CreateFile文档:

转换器设备

DeviceIoControl的IOCTL_CHANGER_*控制代码接受转换器设备的句柄。要打开转换器设备,请使用以下格式的文件名:"\\。\Changerx";其中x是一个数字,表示要打开哪个设备,从零开始。要在用C或C++编写的应用程序中打开转换器设备零,请使用以下文件名:"\\\\\\转换器0";。

请注意,您不是第一个犯此错误的人。Juan Pablo在MinGW邮件列表中报告了同样的错误和类似的代码。Luke Dunstan指出,在该线程中,修复代码以使用GENERIC_READ会将失败更改为ERROR_INVALID_FUNCTION。

最后,我还要注意,您使用的\.C:文件名不是物理磁盘的名称。它是物理磁盘上的卷的名称。一个物理磁盘上可以有多个卷,并且一个卷可以跨越多个物理磁盘。

查找IOCTL_CHANGER_GET_PRODUCT_DATA定义:

#define IOCTL_CHANGER_GET_PRODUCT_DATA       CTL_CODE(IOCTL_CHANGER_BASE, 0x0002, METHOD_BUFFERED, FILE_READ_ACCESS)

注意FILE_READ_ACCESS,所以文件句柄必须有FILE_READ_DATA,但如何打开文件?

hDevice = CreateFile(
logicalDrive.c_str(),
0,
0,
NULL,
OPEN_EXISTING,
0,
NULL);

更改为

hDevice = CreateFile(
logicalDrive.c_str(),
FILE_GENERIC_READ,
0,
NULL,
OPEN_EXISTING,
0,
NULL);

在这之后,你已经得到了另一个错误-ERROR_NOT_SUPPORTED,因为你选择了不正确的设备来请求这个

相关文章: