diff --git a/OpenAuraSDK/OpenAuraSDK.cpp b/OpenAuraSDK/OpenAuraSDK.cpp
index adaab0fe..32449be0 100644
Binary files a/OpenAuraSDK/OpenAuraSDK.cpp and b/OpenAuraSDK/OpenAuraSDK.cpp differ
diff --git a/OpenAuraSDK/OpenAuraSDK.vcxproj b/OpenAuraSDK/OpenAuraSDK.vcxproj
index 9a42de14..1a176d5d 100644
--- a/OpenAuraSDK/OpenAuraSDK.vcxproj
+++ b/OpenAuraSDK/OpenAuraSDK.vcxproj
@@ -115,10 +115,12 @@
true
+ ..\dependencies\inpout32_1501\Win32;%(AdditionalIncludeDirectories)
Windows
true
+ ..\dependencies\inpout32_1501\Win32;%(AdditionalLibraryDirectories)
@@ -156,12 +158,14 @@
true
+ ..\dependencies\inpout32_1501\Win32;%(AdditionalIncludeDirectories)
Windows
true
true
true
+ ..\dependencies\inpout32_1501\Win32;%(AdditionalLibraryDirectories)
@@ -169,6 +173,7 @@
+
@@ -177,6 +182,7 @@
+
diff --git a/OpenAuraSDK/OpenAuraSDK.vcxproj.filters b/OpenAuraSDK/OpenAuraSDK.vcxproj.filters
index bc7567ac..fe80664a 100644
--- a/OpenAuraSDK/OpenAuraSDK.vcxproj.filters
+++ b/OpenAuraSDK/OpenAuraSDK.vcxproj.filters
@@ -30,6 +30,9 @@
Header Files
+
+ Header Files
+
@@ -50,5 +53,8 @@
Source Files
+
+ Source Files
+
\ No newline at end of file
diff --git a/OpenAuraSDK/wmi.cpp b/OpenAuraSDK/wmi.cpp
new file mode 100644
index 00000000..7ca8e80d
--- /dev/null
+++ b/OpenAuraSDK/wmi.cpp
@@ -0,0 +1,262 @@
+#include "wmi.h"
+
+// Taken from https://stackoverflow.com/questions/215963/
+// Convert a wide Unicode string to an UTF8 string
+std::string utf8_encode(const std::wstring& wstr)
+{
+ if (wstr.empty()) return std::string();
+
+ int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int) wstr.size(), nullptr, 0, nullptr, nullptr);
+ std::string strTo(size_needed, 0);
+ WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int) wstr.size(), &strTo[0], size_needed, nullptr, nullptr);
+
+ return strTo;
+}
+
+// Convert an UTF8 string to a wide Unicode String
+std::wstring utf8_decode(const std::string& str)
+{
+ if (str.empty())
+ {
+ return std::wstring();
+ }
+
+ int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int) str.size(), nullptr, 0);
+ std::wstring wstrTo(size_needed, 0);
+ MultiByteToWideChar(CP_UTF8, 0, &str[0], (int) str.size(), &wstrTo[0], size_needed);
+ return wstrTo;
+}
+
+bool isMatch(const std::string& value, const std::regex& re)
+{
+ return std::regex_match(value, re);
+}
+
+Wmi::Wmi() : pLoc(nullptr), pSvc(nullptr)
+{
+
+};
+
+Wmi::~Wmi()
+{
+ pSvc->Release();
+ pLoc->Release();
+ CoUninitialize();
+}
+
+HRESULT Wmi::init()
+{
+ HRESULT hres;
+
+ // Initialize COM. ------------------------------------------
+ hres = CoInitializeEx(0, COINIT_MULTITHREADED);
+ if (FAILED(hres))
+ {
+ return hres;
+ }
+
+ // Set general COM security levels --------------------------
+ hres = CoInitializeSecurity(
+ nullptr,
+ -1, // COM authentication
+ nullptr, // Authentication services
+ nullptr, // Reserved
+ RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
+ RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
+ nullptr, // Authentication info
+ EOAC_NONE, // Additional capabilities
+ nullptr // Reserved
+ );
+
+ if (FAILED(hres))
+ {
+ CoUninitialize();
+ return hres;
+ }
+
+ // Obtain the initial locator to WMI -------------------------
+ hres = CoCreateInstance(
+ CLSID_WbemLocator,
+ nullptr,
+ CLSCTX_INPROC_SERVER,
+ IID_IWbemLocator, (LPVOID*) &pLoc
+ );
+
+ if (FAILED(hres))
+ {
+ CoUninitialize();
+ return hres;
+ }
+
+ hres = pLoc->ConnectServer(
+ _bstr_t(L"ROOT\\CIMV2"), // Object path of WMI namespace
+ nullptr, // User name. NULL = current user
+ nullptr, // User password. NULL = current
+ nullptr, // Locale. NULL indicates current
+ 0, // Security flags.
+ nullptr, // Authority (for example, Kerberos)
+ nullptr, // Context object
+ &pSvc // pointer to IWbemServices proxy
+ );
+
+ if (FAILED(hres))
+ {
+ pLoc->Release();
+ CoUninitialize();
+ return hres;
+ }
+
+ // 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
+ nullptr, // Server principal name
+ RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
+ RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
+ nullptr, // client identity
+ EOAC_NONE // proxy capabilities
+ );
+
+ if (FAILED(hres))
+ {
+ pSvc->Release();
+ pLoc->Release();
+ CoUninitialize();
+ return hres;
+ }
+
+ // Initialised WMI successfully
+ return S_OK;
+}
+
+HRESULT Wmi::query(std::string queryStr, std::vector& queryVectorOut, const AdditionalFilters* filters)
+{
+ HRESULT hres;
+ int nIdx = 0;
+ IEnumWbemClassObject* pEnumerator = nullptr;
+
+ // Make the WMI query
+ hres = pSvc->ExecQuery(
+ bstr_t("WQL"),
+ bstr_t(queryStr.c_str()),
+ WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
+ nullptr,
+ &pEnumerator
+ );
+
+ if (FAILED(hres))
+ {
+ return hres;
+ }
+
+ IWbemClassObject* pclsObj = nullptr;
+ ULONG uReturn = 0;
+
+ while (pEnumerator)
+ {
+ hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
+
+ if (0==uReturn)
+ {
+ break;
+ }
+
+ VARIANT vtProp;
+ if (filters)
+ {
+ for (auto filter: *filters)
+ {
+ hres = pclsObj->Get(utf8_decode(filter.first).c_str(), 0, &vtProp, nullptr, nullptr);
+
+ if (FAILED(hres))
+ {
+ continue;
+ }
+
+ auto val = utf8_encode(vtProp.bstrVal);
+
+ if (!std::regex_match(val, filter.second))
+ {
+ goto _NextElement;
+ }
+ }
+ }
+
+ SAFEARRAY* sfArray;
+ LONG lstart, lend;
+
+ //Get Wmi objects names
+ hres = pclsObj->GetNames(0, WBEM_FLAG_ALWAYS, nullptr, &sfArray);
+
+ if (FAILED(hres))
+ {
+ continue;
+ }
+
+ // Find safe array boundaries
+ SafeArrayGetLBound(sfArray, 1, &lstart);
+ SafeArrayGetUBound(sfArray, 1, &lend);
+
+ BSTR* pbstr;
+ hres = SafeArrayAccessData(sfArray, (void HUGEP**) &pbstr);
+ nIdx = 0;
+
+ if (FAILED(hres))
+ {
+ continue;
+ }
+
+ {
+ CIMTYPE pType;
+ QueryObj item;
+
+ for (nIdx = lstart; nIdx < lend; nIdx++)
+ {
+ hres = pclsObj->Get(pbstr[nIdx], 0, &vtProp, &pType, 0);
+
+ if (FAILED(hres))
+ {
+ continue;
+ }
+
+ if (vtProp.vt == VT_NULL)
+ {
+ continue;
+ }
+
+ if ((pType == CIM_STRING || pType == CIM_REFERENCE) && pType != CIM_EMPTY && pType != CIM_ILLEGAL)
+ {
+ item.emplace(utf8_encode(pbstr[nIdx]), utf8_encode(vtProp.bstrVal));
+ }
+
+ VariantClear(&vtProp);
+ }
+
+ hres = pclsObj->Get(L"Dependent", 0, &vtProp, &pType, nullptr);
+
+ if (pType != CIM_EMPTY && pType != CIM_ILLEGAL && SUCCEEDED(hres))
+ {
+ item.emplace(utf8_encode(pbstr[nIdx]), utf8_encode(vtProp.bstrVal));
+ }
+
+ // Push item to vector
+ queryVectorOut.emplace_back(item);
+
+ // Empty sfArray
+ SafeArrayUnaccessData(sfArray);
+
+ SafeArrayDestroy(sfArray); // Delete sfArray
+ sfArray = nullptr; // Avoid dangling pointers
+ }
+
+ _NextElement:
+ VariantClear(&vtProp); // Clear vtProp
+ pclsObj->Release(); // Release pclsObj
+ }
+
+ pEnumerator->Release();
+ pEnumerator = nullptr;
+
+ return S_OK;
+}
diff --git a/OpenAuraSDK/wmi.h b/OpenAuraSDK/wmi.h
new file mode 100644
index 00000000..73bb7099
--- /dev/null
+++ b/OpenAuraSDK/wmi.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include
+#include
+#include