Attempting to use WMI to locate and set up (initialize/partition/format) newly minted VHD disks.
I have C++ code which appears to work perfectly well at finding and retrieving instances properties for both the MSFT_Partition and MSFT_Volume classes. When the MRE (below) is run it will faithfully display the new VHD attributes of interest (VHD was initialized/partitioned/formatted in disk manager).
The HRESULT is 0x8004101e which tends to indicate I'm using the wrong root or something.
hr = wbemLocator->ConnectServer(_bstr_t(L"ROOT\\microsoft\\windows\\storage"),...
I'm baffled. Can anyone set me right here please?
N.B. Exercise extreme caution here. This code is going to try and access WMI formatting capabilities and the MRE does attract the attention of Windows Defender.
N.B. The Format() method can be invoked successfully from WMI Explorer via the same path (https://github.com/vinaypamnani/wmie2). All testing is being done from a run-as-administrator instance of VS2022, Windows 10 x64.
The example of method invocation shown here does work (https://learn.microsoft.com/en-gb/windows/win32/wmisdk/example--calling-a-provider-method?redirectedfrom=MSDN)
SELECT * FROM MSFT_Volume WHERE FileSystemLabel="61MBVHD" =>
ObjId:{1}\\I7\root/Microsoft/Windows/Storage/Providers_v2\WSP_Volume.ObjectId="{f709bd83-a92c-11e8-a069-806e6f6e6963}:VO:\\?\Volume{00000001-0000-0000-0000-010000000000}\"
Path:\\?\Volume{00000001-0000-0000-0000-010000000000}\
UniqueId:\\?\Volume{00000001-0000-0000-0000-010000000000}\
FileSystemLabel:61MBVHD
Size:63959040
Here is the MRE. It will enumerate all partitions.
/*
MRE for WMI/WBEM setup/connection/query/enumeration
compile from a VS shell: cl /W4 /EHsc mre.cpp
WMI example link: https://github.com/vinaypamnani/wmie2.
*/
#include <windows.h>
#include <Wbemidl.h>
#include <comdef.h>
#include <vector>
#include <iostream>
#include <atlbase.h>
#include <atlcom.h>
#pragma comment(lib, "wbemuuid.lib")
//const char* pquery = R"(SELECT * FROM MSFT_Volume WHERE FileSystemLabel="61MBVHD")";
const char* pquery = R"(SELECT * FROM MSFT_Volume)";
//-----------------------------------------------------------------------------
// attempt to get a methods interface (?)
void GetMethod(CComPtr<IWbemClassObject>& storageWbemObject) {
// can we get the format method????
bstr_t methodName(L"Format");
CComPtr<IWbemClassObject> ppInSignature;
CComPtr<IWbemClassObject> ppOutSignature;
//HRESULT hr = storageWbemObject->GetMethod(methodName,0,&ppInSignature,&ppOutSignature);
IWbemClassObject* pInParamsDefinition = nullptr;
HRESULT hr = storageWbemObject->GetMethod((BSTR)methodName, 0, &pInParamsDefinition, NULL);
if (FAILED(hr))
std::wcout << _com_error(hr).ErrorMessage() << std::endl;
}
//-----------------------------------------------------------------------------
// try to enumerate all methods like WMI Explorer. Fails. No examples found.
void GetMethods(CComPtr<IWbemClassObject>& storageWbemObject) {
long lFlags = 0;
// fails here.
HRESULT hr = storageWbemObject->BeginMethodEnumeration(lFlags);
if (FAILED(hr)) {
std::wcout << _com_error(hr).ErrorMessage() << std::endl;
return;
}
for (;;) {
BSTR name = nullptr;
hr = storageWbemObject->NextMethod(0, &name, NULL, NULL);
if (FAILED(hr)) {
std::wcout << _com_error(hr).ErrorMessage() << std::endl;
break;
}
}
hr = storageWbemObject->EndMethodEnumeration();
}
//-----------------------------------------------------------------------------
void EnumVolume(CComPtr<IWbemServices>& wbemServices) {
// check we have a valid instance.
std::cout << pquery << " => " << std::endl;
CComPtr<IEnumWbemClassObject> storageEnumerator;
HRESULT hr = wbemServices->ExecQuery(bstr_t("WQL"),
bstr_t(pquery),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
NULL,
&storageEnumerator);
if (FAILED(hr))
throw std::runtime_error("Query for MSFT_Volume");
while (storageEnumerator) {
ULONG uReturn = 0;
CComPtr<IWbemClassObject> storageWbemObject;
hr = storageEnumerator->Next(WBEM_INFINITE, 1, &storageWbemObject, &uReturn);
if (0 == uReturn || hr != S_OK)
break;
VARIANT ObjectId;
storageWbemObject->Get(L"ObjectId", 0, &ObjectId, 0, 0);
VARIANT Path;
storageWbemObject->Get(L"Path", 0, &Path, 0, 0);
VARIANT UniqueId;
storageWbemObject->Get(L"UniqueId", 0, &UniqueId, 0, 0);
VARIANT FileSystemLabel;
storageWbemObject->Get(L"FileSystemLabel", 0, &FileSystemLabel, 0, 0);
VARIANT Size;
storageWbemObject->Get(L"Size", 0, &Size, 0, 0);
// we obviously(?) have a valaid instance as attributes as per WMI Explorer.
std::cout << "ObjId:" << std::string(ObjectId.bstrVal == NULL ? "NULL" : _bstr_t(ObjectId.bstrVal)) << std::endl
<< "Path:" << std::string(Path.bstrVal == NULL ? "NULL" : _bstr_t(Path.bstrVal)) << std::endl
<< "UniqueId:" << std::string(UniqueId.bstrVal == NULL ? "NULL" : _bstr_t(UniqueId.bstrVal)) << std::endl
<< "FileSystemLabel:" << std::string(FileSystemLabel.bstrVal == NULL ? "NULL" : _bstr_t(FileSystemLabel.bstrVal)) << std::endl
<< "Size:" << std::string(_bstr_t(Size.bstrVal)) << std::endl;
// enumerate methods???
GetMethods(storageWbemObject);
}
}
//-----------------------------------------------------------------------------
int main() {
int ret = -2;
try {
CComPtr<IWbemLocator> wbemLocator;
CComPtr<IWbemServices> wbemServices;
HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hr))
throw std::runtime_error("Failed to initialize COM");
// flag COM as initialized
ret = -1;
// Set general COM security levels --------------------------
hr = 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(hr))
throw std::runtime_error("Failed to initialize security");
// Obtain the initial locator to WMI -------------------------
hr = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID*)&wbemLocator);
if (FAILED(hr))
throw std::runtime_error("Failed to create IWbemLocator");
// Connect to the ROOT\\\microsoft\\windows\\storage
hr = wbemLocator->ConnectServer(
_bstr_t(L"ROOT\\microsoft\\windows\\storage"), // 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
&wbemServices); // pointer to IWbemServices proxy
if (FAILED(hr))
throw std::runtime_error("Could not connecct");
// Set security levels on the proxy -------------------------
hr = CoSetProxyBlanket(
wbemServices, // 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(hr))
throw std::runtime_error("CoSetProxyBlanket()");
// do the work
EnumVolume(wbemServices);
ret = 0;
}
catch (const std::exception& ex) {
std::cout << "Exception: " << ex.what() << std::endl;
}
// is it safe>?
if (ret >= -1)
CoUninitialize();
return ret;
}
