I'm using WMI to retrieve information about physical drives on the system:
SELECT * FROM Win32_PhysicalMedia
And the "Tag" property returns physical device paths such as "\.\PHYSICALDRIVE0", or "\.\CDROM0", etc.
Is there a way to associate it with the actual drive paths, stuff like "C:" or "D:" or at least a device path "\Device\HarddiskVolume1"?
PS. In despite of my use of WMI, I'm writing the code using WinAPIs and C++.
EDIT:
Below is how it's done in C++. Note that this code should not be called right-when-you-need-this because it is extremely slow. What I would do is run it in a worker thread when the app starts and cache it somewhere for later user. I'd also watch for the WM_DEVICECHANGE notification and rerun it if drive layout changes.
Whew. I know it's complicated ... but, hey, it's Windows.
The code below comes from comments to this page.
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
BOOL wmi_run();
BOOL wmi_getDriveLetters();
BOOL wmi_close();
IWbemLocator *pLoc = NULL;
IWbemServices *pSvc = NULL;
int main(int argc, char **argv)
{
wmi_run();
wmi_getDriveLetters();
system("pause");
wmi_close();
}
//
// Step 1-5 at:
// http://msdn.microsoft.com/en-us/library/aa390423(VS.85).aspx
BOOL wmi_run()
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
// Note: If you are using Windows 2000, you need to specify -
// the default authentication credentials for a user by using
// a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
// parameter of CoInitializeSecurity ------------------------
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))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
//IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object."
<< " Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
//IWbemServices *pSvc = NULL;
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (e.g. Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// 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))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
return 0;
}
//
// get Drives, logical Drives and Driveletters
BOOL wmi_getDriveLetters()
{
// Use the IWbemServices pointer to make requests of WMI.
// Make requests here:
HRESULT hres;
IEnumWbemClassObject* pEnumerator = NULL;
// get localdrives
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_DiskDrive"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres)) {
cout << "Query for processes failed. "
<< "Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return FALSE; // Program has failed.
}
else {
IWbemClassObject *pclsObj;
ULONG uReturn = 0;
while (pEnumerator) {
hres = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(0 == uReturn) break;
VARIANT vtProp;
hres = pclsObj->Get(_bstr_t(L"DeviceID"), 0, &vtProp, 0, 0);
// adjust string
wstring tmp = vtProp.bstrVal;
tmp = tmp.substr(4);
wstring wstrQuery = L"Associators of {Win32_DiskDrive.DeviceID='\\\\.\\";
wstrQuery += tmp;
wstrQuery += L"'} where AssocClass=Win32_DiskDriveToDiskPartition";
// reference drive to partition
IEnumWbemClassObject* pEnumerator1 = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t( wstrQuery.c_str()),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator1 );
if ( FAILED(hres) ) {
cout << "Query for processes failed. "
<< "Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return FALSE; // Program has failed.
} else {
IWbemClassObject *pclsObj1;
ULONG uReturn1 = 0;
while( pEnumerator1 ) {
hres = pEnumerator1->Next( WBEM_INFINITE, 1,
&pclsObj1, &uReturn1 );
if(0 == uReturn1) break;
// reference logical drive to partition
VARIANT vtProp1;
hres = pclsObj1->Get( _bstr_t(L"DeviceID"), 0, &vtProp1, 0, 0 );
wstring wstrQuery = L"Associators of {Win32_DiskPartition.DeviceID='";
wstrQuery += vtProp1.bstrVal;
wstrQuery += L"'} where AssocClass=Win32_LogicalDiskToPartition";
IEnumWbemClassObject* pEnumerator2 = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t(wstrQuery.c_str()),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator2 );
if ( FAILED(hres) ) {
cout << "Query for processes failed. "
<< "Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return FALSE; // Program has failed.
} else {
// get driveletter
IWbemClassObject *pclsObj2;
ULONG uReturn2 = 0;
while( pEnumerator2 ) {
hres = pEnumerator2->Next( WBEM_INFINITE, 1,
&pclsObj2, &uReturn2 );
if(0 == uReturn2) break;
VARIANT vtProp2;
hres = pclsObj2->Get( _bstr_t(L"DeviceID"), 0, &vtProp2, 0, 0 );
// print result
printf("%ls : %ls\n", vtProp.bstrVal, vtProp2.bstrVal);
VariantClear( &vtProp2 );
}
pclsObj1->Release();
}
VariantClear( &vtProp1 );
pEnumerator2->Release();
}
pclsObj->Release();
}
VariantClear( &vtProp );
pEnumerator1->Release();
}
}
pEnumerator->Release();
return TRUE;
}
BOOL wmi_close()
{
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 0; // Program successfully completed.
}
This MSDN article explains how to use WMI to get from a disk drive to a list of the drive letters on it (it's the final section of the page).
You can use Win32_DiskDrivePhysicalMedia to get from the physical media to the disk drive.
But if you actually want a list of partitions, why not start at Win32_LogicalDisk?
Related
I'm having problem detecting some graphics cards using DirectX API. The code I wrote looks like following:
#define _WIN32_DCOM
#include <iostream>
#include <Windows.h>
#include <d3d11.h>
#include <Dxgi1_6.h>
#include <atlbase.h>
#include <string>
#include <vector>
#include <comdef.h>
#include <Wbemidl.h>
struct AdapterInfo
{
std::wstring description;
size_t vRam;
D3D_FEATURE_LEVEL maxFeatureLevel;
};
void getGPUDescriptionVideoRam(IUnknown* pDevice, AdapterInfo & adapterInfo)
{
CComPtr<IDXGIDevice> pDXGIDevice;
pDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&pDXGIDevice);
if (pDXGIDevice)
{
CComPtr<IDXGIAdapter> pDXGIAdapter;
pDXGIDevice->GetAdapter(&pDXGIAdapter);
if (pDXGIAdapter != nullptr)
{
DXGI_ADAPTER_DESC adapterDesc;
pDXGIAdapter->GetDesc(&adapterDesc);
adapterInfo.description = std::wstring(adapterDesc.Description);
adapterInfo.vRam = adapterDesc.DedicatedVideoMemory;
}
}
}
std::vector<AdapterInfo> GetDescriptionVRamDirectx()
{
std::vector<AdapterInfo> result;
D3D_FEATURE_LEVEL featureLevels[10] = { D3D_FEATURE_LEVEL_12_1,
D3D_FEATURE_LEVEL_12_0,
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1,
D3D_FEATURE_LEVEL_1_0_CORE
};
CComPtr<IDXGIAdapter> higher_performance_adapter;
CComPtr<IDXGIFactory> pFactory;
HRESULT createDXGIFactoryResult = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)(&pFactory));
if (createDXGIFactoryResult != S_OK)
{
printf("Failed to create DXGI factory!\n");
return result;
}
printf("Trying to enumerate graphics adapters...\n");
int i = 0;
while (pFactory->EnumAdapters(i, &higher_performance_adapter) == S_OK)
/*
while (pFactory->EnumAdapterByGpuPreference(i,
DXGI_GPU_PREFERENCE_UNSPECIFIED,
__uuidof(IDXGIAdapter),
(void**)&higher_performance_adapter) == S_OK)
*/
{
i++;
CComPtr<ID3D11Device> device = nullptr;
D3D_FEATURE_LEVEL receivedFeatureLevel;
CComPtr<ID3D11DeviceContext> context = nullptr;
const HRESULT err = D3D11CreateDevice(
higher_performance_adapter,
D3D_DRIVER_TYPE_UNKNOWN,
nullptr,
0, // D3D11_CREATE_DEVICE_DEBUG
featureLevels,
1,
D3D11_SDK_VERSION,
&device,
&receivedFeatureLevel,
&context);
if (err != S_OK)
{
higher_performance_adapter = nullptr;
continue;
}
AdapterInfo info;
getGPUDescriptionVideoRam(device, info);
info.maxFeatureLevel = receivedFeatureLevel;
result.push_back(info);
higher_performance_adapter = CComPtr<IDXGIAdapter>();
}
return result;
}
void displayWMIAdapters()
{
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
std::cout << "Failed to initialize COM library. Error code = 0x"
<< std::hex << hres << std::endl;
return; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
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; // Program has failed.
}
// Step 3: ---------------------------------------------------
// 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."
<< " Err code = 0x"
<< std::hex << hres << std::endl;
CoUninitialize();
return; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices* pSvc = NULL;
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (for example, Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
std::cout << "Could not connect. Error code = 0x"
<< std::hex << hres << std::endl;
pLoc->Release();
CoUninitialize();
return; // Program has failed.
}
std::cout << "Connected to ROOT\\CIMV2 WMI namespace" << std::endl;
// Step 5: --------------------------------------------------
// 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; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_VideoController"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
std::cout << "Query for operating system name failed."
<< " Error code = 0x"
<< std::hex << hres << std::endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
IWbemClassObject* pclsObj = NULL;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if (0 == uReturn)
{
break;
}
VARIANT vtProp;
// Get the value of the Name property
hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
std::wcout << " OS Name : " << vtProp.bstrVal << std::endl;
VariantClear(&vtProp);
pclsObj->Release();
}
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
}
int main(int argc, char* argv[])
{
auto adapters = GetDescriptionVRamDirectx();
int i = 1;
for (AdapterInfo adapter : adapters)
{
printf("Adapter %d:\n", i);
printf("-----------\n");
printf("Description :");
wprintf(adapter.description.c_str());
printf("\n");
printf("Video RAM :");
wprintf(L"%d", adapter.vRam);
printf("\n");
printf("Feature level :");
if (adapter.maxFeatureLevel == D3D_FEATURE_LEVEL_12_1)
printf("12_1\n");
else if (adapter.maxFeatureLevel == D3D_FEATURE_LEVEL_12_0)
printf("12_0\n");
else if (adapter.maxFeatureLevel == D3D_FEATURE_LEVEL_11_1)
printf("11_1\n");
else if (adapter.maxFeatureLevel == D3D_FEATURE_LEVEL_11_0)
printf("11_0\n");
else if (adapter.maxFeatureLevel == D3D_FEATURE_LEVEL_10_1)
printf("10_1\n");
else if (adapter.maxFeatureLevel == D3D_FEATURE_LEVEL_10_0)
printf("10_0\n");
else if (adapter.maxFeatureLevel == D3D_FEATURE_LEVEL_9_3)
printf("9_3\n");
else if (adapter.maxFeatureLevel == D3D_FEATURE_LEVEL_9_2)
printf("9_2\n");
else if (adapter.maxFeatureLevel == D3D_FEATURE_LEVEL_9_1)
printf("9_1\n");
else if (adapter.maxFeatureLevel == D3D_FEATURE_LEVEL_1_0_CORE)
printf("1_0_CORE\n");
printf("\n");
i++;
}
displayWMIAdapters();
printf("Press any key...\n");
getchar();
}
Note, that I'm also using WMI to enumerate graphics cards.
So on most devices this works correctly, namely:
Trying to enumerate graphics adapters...
Adapter 1:
-----------
Description :NVIDIA GeForce MX250
Video RAM :2080038912
Feature level :12_1
Adapter 2:
-----------
Description :Intel(R) UHD Graphics 620
Video RAM :134217728
Feature level :12_1
Adapter 3:
-----------
Description :Microsoft Basic Render Driver
Video RAM :0
Feature level :12_1
Connected to ROOT\CIMV2 WMI namespace
OS Name : Intel(R) UHD Graphics 620
OS Name : NVIDIA GeForce MX250
Press any key...
However, I'm getting information, that on specific setups, no results are returned. For instance my friend said,
My notebook (not all information, installed graphics cards are 2xGT755m in SLI plus standard, integrated - 3 in total)
Adapter 1:
-----------
Description :Microsoft Basic Render Driver
Video RAM :0
Feature level :12_1
Press any key...
I'm having trouble finding out, why I am not getting all cards. Moreover, I have no idea, what kind of debugging could I perform to find out the reason of my problem.
Why am I not getting all installed graphics cards on all machines when using DirectX API?
I have been going through the windows docs to access the windows log files using C++ and WMI. I saw a sample code for creating a WMI application. But it shows an error when I compile it using the g++ compiler.
code:
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")
int main(int argc, char **argv)
{
HRESULT hres;
// Initialize COM.
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. "
<< "Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Initialize
hres = CoInitializeSecurity(
NULL,
-1, // COM negotiates service
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cout << "Failed to initialize security. "
<< "Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Obtain the initial locator to Windows Management
// on a particular host computer.
IWbemLocator *pLoc = 0;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object. "
<< "Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
IWbemServices *pSvc = 0;
// Connect to the root\cimv2 namespace with the
// current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // WMI namespace
NULL, // User name
NULL, // User password
0, // Locale
NULL, // Security flags
0, // Authority
0, // Context object
&pSvc // IWbemServices proxy
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// Set the IWbemServices proxy so that impersonation
// of the user (client) occurs.
hres = CoSetProxyBlanket(
pSvc, // the proxy to set
RPC_C_AUTHN_WINNT, // authentication service
RPC_C_AUTHZ_NONE, // authorization service
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // authentication level
RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation level
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Use the IWbemServices pointer to make requests of WMI.
// Make requests here:
// For example, query for all the running processes
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_Process"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
cout << "Query for processes failed. "
<< "Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
else
{
IWbemClassObject *pclsObj;
ULONG uReturn = 0;
while (pEnumerator)
{
hres = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(0 == uReturn)
{
break;
}
VARIANT vtProp;
// Get the value of the Name property
hres = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
wcout << "Process Name : " << vtProp.bstrVal << endl;
VariantClear(&vtProp);
pclsObj->Release();
pclsObj = NULL;
}
}
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
CoUninitialize();
return 0; // Program successfully completed.
}
If I saved it in a file named sample.cpp I compiled it suing the command
g++ -o sample sample.cpp
Is that a mistake? Should I be compiling it in a different way?
I'm new to this. Can somebody please guide me on how to learn the WMI using C++ in order to read the windows log files?
Kindly respond
Thank you.
It seems like you have just copy pasted the code from a website, due to which & has become & (because of HTML) as mentioned in the comments by #Vlad274.
If you're compiling in the command prompt, you have to link your libraries before compilation, probably ole32 and oleaut.
If you're using Visual Studio, make sure they are included in the linker settings.(Which they are by default in VS2017)
EXTRA: Before using the Get method, you could check for property names using the GetNames method to ensure that the property 'Name' exists.
I implemented 1-5 steps from :
https://msdn.microsoft.com/en-us/library/aa390423(v=vs.85).aspx
Everyting works, but i have problem with getting data from object which i retreive with query.
My code:
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
//cout << "Failed to initialize COM library. Error code = 0x"
// << hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
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))
{
//cout << "Failed to initialize security. Error code = 0x"
// << hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
//cout << "Failed to create IWbemLocator object."
// << " Err code = 0x"
// << hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
pSvc = NULL;
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (for example, Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
//cout << "Could not connect. Error code = 0x"
// << hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
//OutputDebugString("Connected to ROOT\\CIMV2 WMI namespace");
// Step 5: --------------------------------------------------
// 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))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
code above is the same as msdn example.
Problem is here:
// Get the currently inserted USB devices
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_USBControllerDevice"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
if (FAILED(hres))
{
//cout << "Query for USB devices at startup failed."
// << " Error code = 0x"
// << hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Get the data from the query
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
ostringstream os;
while (pEnumerator){
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(0 == uReturn){
break;
}
VARIANT vtProp;
VariantInit(&vtProp);
// Get the value of the accessstate property
hr = pclsObj->Get(L"Dependent", 0, &vtProp, 0, 0);
if (FAILED(hr)){
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
os.str("");
os.clear();
os << vtProp.bstrVal;
OutputDebugString(os.str().c_str());
AddDevice(os.str());//Add device to devices vector
VariantClear(&vtProp);
pclsObj->Release();
}
Exactly in this place:
hr = pclsObj->Get(L"Dependent", 0, &vtProp, 0, 0);
This link describes table elements:
https://msdn.microsoft.com/en-us/library/aa394505(v=vs.85).aspx
So i got Dependent value. My problem is how to get this Dependent properties:
https://msdn.microsoft.com/en-us/library/aa387884(v=vs.85).aspx
for example : DeviceID
If anyone can help i will be very very grateful!
I found some WMI C++ Application Examples in MSDN website.
I have tried the code form the below link
http://msdn.microsoft.com/en-us/library/aa390423%28v=VS.85%29.aspx
when I copied and run the application as win32 console application it worked well.
the same code I put into the Qt application ,
When I use QApplication anApplication ( argc, argv ); in my code it is not working
But if I use QCoreApplication anApplication ( argc, argv ); it is working
shows me error like "when i change QCoreApplication to QApplication The below source code not works and gives me error like " Failed to initialize COM library. Error code = 0x80010106 "
Any suggestions or help
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")
// Qt Includes
#include <QtCore>
#include <QtGui>
//----------------------------------------------------------------------------
// Main Function
int main( int a_argc, char *a_argv[] )
//************************************
{
// initialize the application
QApplication anapplication( a_argc, a_argv );
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
// Note: If you are using Windows 2000, you need to specify -
// the default authentication credentials for a user by using
// a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
// parameter of CoInitializeSecurity ------------------------
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))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object."
<< " Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (e.g. Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// 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))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(
bstr_t("WQL"),
bstr_t("SELECT * FROM Win32_USBControllerDevice"),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&pEnumerator);
//ExecQuery(L"WQL", L"SELECT * FROM Win32_LogicalDisk", WBEM_FLAG_FORWARD_ONLY, NULL, &iter);
if (FAILED(hres))
{
cout << "Query for operating system name failed."
<< " Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
IWbemClassObject *pclsObj;
ULONG uReturn = 0;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1,
&pclsObj, &uReturn);
if(FAILED(hr)||0 == uReturn)
{
break;
}
VARIANT vtProp;
// Get the value of the Name property
/*hr = pclsObj->Get(L"VolumeName", 0, &vtProp, 0, 0);
wcout << " VolumeName : " << vtProp.bstrVal << endl;
VariantClear(&vtProp);*/
if (FAILED(pclsObj->Get(L"Antecedent", 0, &vtProp, 0, 0)))
{
cout<<"The specified property is not found."<<endl;
}
else
{
wcout <<vtProp.bstrVal << endl;
}
pclsObj->Release();
}
// Cleanup
// ========
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
// pclsObj->Release();
CoUninitialize();
// return 0; // Program successfully completed.
//execute the application
int anInt = anapplication.exec();
return anInt;
}
//-----------------------------------------------------------------------------
The error you are receiving is due to the fact that COM is already initialized. QApplication calls OleInitialize in its constructor, but QCoreApplication does not, so that's why you get the error 0x80010106 (RPC_E_CHANGED_MODE) when you use QApplication. For further reading, see the documentation for CoInitializeEx. The following article should provide more insight.
At first I have used this code
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (hres == RPC_E_CHANGED_MODE) {
OleUninitialize();
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
}
When I get error "Failed to initialize COM library(0x80010106)
I just call OleUninitialize to deal with OleInitialize() in QApplication, but that could break some qt functionality.
As I found the best is to use flag COINIT_APARTMENTTHREADED for CoInitializeEx
MSDN
Generally, a thread that creates a window should use the COINIT_APARTMENTTHREADED flag, and other threads should use COINIT_MULTITHREADED. However, some COM components require a particular threading model. The MSDN documentation should tell you when that is the case.
For me it`s a black magic, but it helped me
I have this copied code from Example: Calling a Provider Method, it modified it now should it change CPU fan speed:
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")
int main(int iArgCnt, char ** argv)
{
if(IsDebuggerPresent())cout<<"Debugee?\n";
HRESULT hres;
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x"
<< hex << hres << endl;
return 1; // Program has failed.
}
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
// Note: If you are using Windows 2000, you must specify -
// the default authentication credentials for a user by using
// a SOLE_AUTHENTICATION_LIST structure in the pAuthList ----
// parameter of CoInitializeSecurity ------------------------
hres = CoInitializeSecurity(
NULL,
-1, // COM negotiates service
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))
{
cout << "Failed to initialize security. Error code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(
CLSID_WbemLocator,
0,
CLSCTX_INPROC_SERVER,
IID_IWbemLocator, (LPVOID *) &pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object. "
<< "Err code = 0x"
<< hex << hres << endl;
CoUninitialize();
return 1; // Program has failed.
}
// Step 4: ---------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
IWbemServices *pSvc = NULL;
// Connect to the local root\cimv2 namespace
// and obtain pointer pSvc to make IWbemServices calls.
hres = pLoc->ConnectServer(
_bstr_t(L"ROOT\\CIMV2"),
NULL,
NULL,
0,
NULL,
0,
0,
&pSvc
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x"
<< hex << hres << endl;
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;
// Step 5: --------------------------------------------------
// Set security levels for 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))
{
cout << "Could not set proxy blanket. Error code = 0x"
<< hex << hres << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
return 1; // Program has failed.
}
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
BSTR MethodName = SysAllocString(L"SetSpeed");
BSTR ClassName = SysAllocString(L"CIM_Fan");
IWbemClassObject* pClass = NULL;
hres = pSvc->GetObject(ClassName, 0, NULL, &pClass, NULL);
IWbemClassObject* pInParamsDefinition = NULL;
hres = pClass->GetMethod(MethodName, 0,
&pInParamsDefinition, NULL);
IWbemClassObject* pClassInstance = NULL;
hres = pInParamsDefinition->SpawnInstance(0, &pClassInstance);
// Create the values for the in parameters
VARIANT varCommand;
varCommand.vt = VT_BSTR;
varCommand.bstrVal = L"10";
// Store the value for the in parameters
hres = pClassInstance->Put(L"CommandLine", 0,
&varCommand, 0);
wprintf(L"The command is: %s\n", V_BSTR(&varCommand));
// Execute Method
IWbemClassObject* pOutParams = NULL;
hres = pSvc->ExecMethod(ClassName, MethodName, 0,
NULL, pClassInstance, &pOutParams, NULL);
if (FAILED(hres))
{
cout << "Could not execute method. Error code = 0x"
<< hex << hres << endl;
try{
VariantClear(&varCommand);
SysFreeString(ClassName);
SysFreeString(MethodName);
pClass->Release();
pInParamsDefinition->Release();
// pOutParams->Release();
pSvc->Release();
pLoc->Release();
CoUninitialize();
}
catch(...){
cout<<""; // NOTHING
};
system("pause");
return 1; // Program has failed.
}
// To see what the method returned,
// use the following code. The return value will
// be in &varReturnValue
VARIANT varReturnValue;
hres = pOutParams->Get(_bstr_t(L"ReturnValue"), 0,
&varReturnValue, NULL, 0);
// Clean up
//--------------------------
VariantClear(&varCommand);
VariantClear(&varReturnValue);
SysFreeString(ClassName);
SysFreeString(MethodName);
pClass->Release();
pInParamsDefinition->Release();
pOutParams->Release();
pLoc->Release();
pSvc->Release();
CoUninitialize();
system("pause");
return 0;
}
When I run this, it not work. What I should change?
Fan speed control via WMI is going to be pretty vendor-specific; there are no general controls for CPU/mainboard fans (though WMI is what people should be doing). Also, this would be way easier in PowerShell or even C# than trying to use C++ to play with WMI stuff. At least figure out how to do it in PSh first, then transcribe it to C++