I'm trying to list WMI namespaces with C++. The problem is that "Next" method either fails or returns "ROOT" constantly (at best). So either I'm wrong with initialization or other method required to get it done.
Connecting to root namespace and listing everything with __NAMESPACE property. Example code:
// example connect func
bool WMIConnect(std::wstring namespacePath) {
::HRESULT hres = ::CoInitializeEx(0, ::COINIT_MULTITHREADED);
if (FAILED(hres)) {
return false;
}
hres = ::CoInitializeSecurity(
0,
-1, // COM authentication
0, // Authentication services
0, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
0, // Authentication info
::EOAC_NONE, // Additional capabilities
0 // Reserved
);
if (FAILED(hres)) {
::CoUninitialize();
return false;
}
hres = ::CoCreateInstance(::CLSID_WbemLocator, 0, ::CLSCTX_INPROC_SERVER, ::IID_IWbemLocator, (void**)&m_pLoc);
if (FAILED(hres)) {
::CoUninitialize();
return false;
}
hres = m_pLoc->ConnectServer(
_bstr_t(namespacePath.c_str()), // Object path of WMI namespace / L"ROOT" namespace
0, // User name. NULL = current user
0, // User password. NULL = current
0, // Locale. NULL indicates current
0, // Security flags.
0, // Authority (e.g. Kerberos)
0, // Context object
&m_pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres)) {
m_pLoc->Release();
::CoUninitialize();
m_pLoc = 0;
return false;
}
hres = ::CoSetProxyBlanket(
m_pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
0, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
0, // client identity
::EOAC_NONE // proxy capabilities
);
if (FAILED(hres)) {
m_pSvc->Release();
m_pLoc->Release();
::CoUninitialize();
m_pSvc = 0;
m_pLoc = 0;
return false;
}
m_WMIInitialized = true;
return true;
}
// example get code
bool getNamespaces(std::vector<std::wstring> namespaces) {
...
::IWbemClassObject* pObj = { 0 };
::IEnumWbemClassObject* pEnumerator = 0;
::BSTR className = ::_bstr_t(namespacePath.c_str());
::HRESULT hres = m_pSvc->CreateInstanceEnum(_bstr_t(L"__NAMESPACE"),
::WBEM_GENERIC_FLAG_TYPE::WBEM_FLAG_FORWARD_ONLY | ::WBEM_GENERIC_FLAG_TYPE::WBEM_FLAG_RETURN_IMMEDIATELY,
0, &pEnumerator);
...
if (FAILED(hres)) {
::VariantClear((::VARIANT*)className);
return WMIOpResult::Fail;
}
unsigned long uReturn = 0;
while (pEnumerator) {
hres = pEnumerator->Next(::WBEM_INFINITE, 1, &pObj, &uReturn);
if (!uReturn) {
if (FAILED(hres)) {
::VariantClear((::VARIANT*)className);
::IErrorInfo* errinf;
if (S_OK == GetErrorInfo(0, &errinf)) {
std::wstring errDesc;
getIObjectErrorDetails(errDesc, pEnumerator, errinf);
}
return WMIOpResult::Fail;
}
break;
}
if (FAILED(hres)) {
::VariantClear((::VARIANT*)className);
IErrorInfo* errinf;
GetErrorInfo(0, &errinf);
return WMIOpResult::Fail;
}
::VARIANT vtProp = { 0 };
hres = pObj->Get(L"__Namespace", 0, &vtProp, 0, 0);
if (FAILED(hres)) {
::VariantClear((::VARIANT*)&vtProp);
::VariantClear((::VARIANT*)className);
return WMIOpResult::Fail;
}
if (std::find(namespaces.begin(), namespaces.end(), vtProp.bstrVal) == namespaces.end()) {
namespaces.push_back(vtProp.bstrVal);
}
::VariantClear(&vtProp);
}
}
Where am I wrong?