pts*_*pts 1 winapi ioctl windows-7
我正在尝试使用 IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER 获取磁盘的序列号:
HANDLE h = CreateFile ("\\\\.\\PhysicalDrive0", GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING,
FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING, 0);
if (h != INVALID_HANDLE_VALUE) {
struct {
USHORT Reserved;
USHORT SerialNumberLength;
UCHAR SerialNumber[252];
} dsn;
DWORD nr;
memset(&dsn, '\0', sizeof dsn);
if ((DeviceIoControl(h, IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER,
NULL, 0, &dsn, sizeof(dsn), &nr, 0))) {
printf("Serial number: %s\n", dsn.SerialNumber);
} else {
printf("No serial number, error %d.\n", (int)GetLastError());
}
}
Run Code Online (Sandbox Code Playgroud)
但是,GetLastError()返回 ERROR_INVALID_FUNCTION。
磁盘确实存在,并且它有一个序列号,请参阅此注册表项:
如何在不使用注册表的情况下从 C 代码中检索序列号?
我们可以使用IOCTL_STORAGE_QUERY_PROPERTYwith StorageDeviceProperty(表示调用者正在查询设备描述符, STORAGE_DEVICE_DESCRIPTOR)
并使用SerialNumberOffset成员STORAGE_DEVICE_DESCRIPTOR
指定从结构开头到包含设备序列号的以 NULL 结尾的 ASCII 字符串的字节偏移量。如果设备没有序列号,则该成员为零。
代码可以是这样的:
ULONG GetSerial(HANDLE hFile)
{
static STORAGE_PROPERTY_QUERY spq = { StorageDeviceProperty, PropertyStandardQuery };
union {
PVOID buf;
PSTR psz;
PSTORAGE_DEVICE_DESCRIPTOR psdd;
};
ULONG size = sizeof(STORAGE_DEVICE_DESCRIPTOR) + 0x100;
ULONG dwError;
do
{
dwError = ERROR_NO_SYSTEM_RESOURCES;
if (buf = LocalAlloc(0, size))
{
ULONG BytesReturned;
if (DeviceIoControl(hFile, IOCTL_STORAGE_QUERY_PROPERTY, &spq, sizeof(spq), buf, size, &BytesReturned, 0))
{
if (psdd->Version >= sizeof(STORAGE_DEVICE_DESCRIPTOR))
{
if (psdd->Size > size)
{
size = psdd->Size;
dwError = ERROR_MORE_DATA;
}
else
{
if (psdd->SerialNumberOffset)
{
DbgPrint("SerialNumber = %s\n", psz + psdd->SerialNumberOffset);
dwError = NOERROR;
}
else
{
dwError = ERROR_NO_DATA;
}
}
}
else
{
dwError = ERROR_GEN_FAILURE;
}
}
else
{
dwError = GetLastError();
}
LocalFree(buf);
}
} while (dwError == ERROR_MORE_DATA);
return dwError;
}
Run Code Online (Sandbox Code Playgroud)
同样对于我们可以使用的开放设备CreateFileW (L"\\\\.\\PhysicalDrive0", 0, 0, 0, OPEN_EXISTING, 0, 0);- 在适当的地方dwDesiredAccess我们可以使用 0 因为IOCTL_STORAGE_QUERY_PROPERTY定义为
CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)- 所以FILE_ANY_ACCESS- 接受任何文件访问并且FILE_FLAG_WRITE_THROUGH | FILE_FLAG_NO_BUFFERING只对文件系统设备有意义(更一般的使用缓存) - 对于磁盘设备 - 这无关紧要