我想知道我的操作系统安装在哪个硬盘上(目前在 Windows 上)。我想出了如何将物理驱动器与模型相匹配,但由于“C:”并不总是在驱动器 0 上,因此我希望得到一些帮助。
这是我到目前为止所拥有的:
#include <windows.h>
#include <iostream>
#include <comdef.h>
#include <Wbemidl.h>
int main() {
HRESULT hres;
// Initialize COM library
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres)) {
std::cout << "Failed to initialize COM library. Error code = 0x"
<< std::hex << hres << std::endl;
return 1;
}
// Initialize security
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres)) {
std::cout << "Failed to initialize security. Error code = 0x"
<< std::hex << hres << std::endl;
CoUninitialize();
return 1;
}
// Obtain the initial locator to WMI
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres)) {
std::cout << "Failed to create IWbemLocator object. Error code = 0x"
<< std::hex << hres << std::endl;
CoUninitialize();
return 1;
}
// Connect to WMI namespace
IWbemServices *pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"),
NULL, // User name
NULL, // Password
0, // Locale
NULL, // Security flags
0, // Authority
0, // Context object
&pSvc // IWbemServices proxy
);
if (FAILED(hres)) {
std::cout << "Could not connect. Error code = 0x"
<< std::hex << hres << std::endl;
pLoc->Release();
CoUninitialize();
return 1;
}
// Set security levels on the proxy
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres)) {
std::cout << "Could not set proxy blanket. Error code = 0x"
<< std::hex << hres << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1;
}
// Use the IWbemServices pointer to make requests of WMI
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT DeviceID, Model FROM Win32_DiskDrive"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres)) {
std::cout << "Query for disk drives failed. Error code = 0x"
<< std::hex << hres << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Get the data from the query
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator) {
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if(0 == uReturn) {
break;
}
VARIANT vtDeviceID;
VARIANT vtModel;
// Get the value of the DeviceID and Model properties
hr = pclsObj->Get(L"DeviceID", 0, &vtDeviceID, 0, 0);
hr = pclsObj->Get(L"Model", 0, &vtModel, 0, 0);
std::wcout << "Device ID : " << vtDeviceID.bstrVal << ", Model : " << vtModel.bstrVal << std::endl;
VariantClear(&vtDeviceID);
VariantClear(&vtModel);
pclsObj->Release();
}
// Cleanup
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
return 0;
}
我的输出是:
Device ID : \\.\PHYSICALDRIVE5, Model : Microsoft Virtual Disk
Device ID : \\.\PHYSICALDRIVE3, Model : NORELSYS 1081 SD USB Device
Device ID : \\.\PHYSICALDRIVE2, Model : ADATA SX8200PNP
Device ID : \\.\PHYSICALDRIVE0, Model : CT480BX500SSD1
Device ID : \\.\PHYSICALDRIVE4, Model : NORELSYS 1081 TF USB Device
Device ID : \\.\PHYSICALDRIVE1, Model : ADATA SP550
我当前的操作系统实际上是
PHYSICALDRIVE2
。那么我如何以编程方式确定这一点?
提前谢谢您!
编辑:虽然我认为目的并不重要(特别是在每个人都非常注重简洁性的SO上),但我想读取序列号以进行安全验证。但是,由于
SELECT * FROM Win32_DiskDrive
的顺序未知(在我的例子中是没有序列号的虚拟磁盘),所以我不能依赖它。
我们可以打开系统卷/分区(但不是卷上的文件/目录)并通过
IOCTL_STORAGE_GET_DEVICE_NUMBER
或 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
查询磁盘号,如果假设该卷位于多个磁盘上(我没有测试,在这种情况下会怎样 IOCTL_STORAGE_GET_DEVICE_NUMBER
返回)
在Windows 8+中,我们可以使用L“\Device\BootPartition”来打开系统磁盘上的卷。或 L"\?\GLOBALROOT\Device\BootPartition" 如果您想使用
CreateFileW
代替 NtOpenFile
从 Windows 10 开始,还可以使用 L"\Device\SystemPartition"(注意 - BootPartition != BootPartition
这是不同的卷,但我猜两者必须位于同一磁盘上。
从 win10+ 开始还存在 L"\?\BootPartition" 和 L"\?\SystemPartition" 。因此可以使用此名称代替 L"\?\GLOBALROOT\Device\BootPartition" 来表示
CreateFileW
在我们获得磁盘编号之后 - 我们可以发送
IOCTL_STORAGE_QUERY_PROPERTY
到它以获取“Model”字符串中的内容。或者我们可以通过 CM_Get_Device_Interface_ListW
和 &GUID_DEVINTERFACE_DISK
获取所有磁盘的列表,然后使用 IOCTL_STORAGE_GET_DEVICE_NUMBER
查询每个磁盘的磁盘编号,然后我们可以通过 CM_Get_Device_Interface_PropertyW
获取更多属性
在win7上存在问题,如何获取路径/打开系统卷。不存在
BootPartition
链接。可能打开 \SystemRoot
链接,然后使用 NtQueryObject
和 ObjectNameInformation
来获取设备路径。NtQueryInformationFile