core/windows/wmi: Add ability to exec methods on WMI results (#5504)

This commit is contained in:
mark m 2019-12-31 19:09:47 -05:00 committed by Teddy Reed
parent b5bddbef87
commit 826d1f3b44
6 changed files with 499 additions and 123 deletions

View File

@ -96,6 +96,9 @@ function(generateOsqueryCore)
add_test(NAME osquery_core_tests_querytests-test COMMAND osquery_core_tests_querytests-test)
add_test(NAME osquery_core_tests_processtests-test COMMAND osquery_core_tests_processtests-test)
if(DEFINED PLATFORM_WINDOWS)
add_test(NAME osquery_core_tests_wmitests-test COMMAND osquery_core_tests_wmitests-test)
endif()
endfunction()
osqueryCoreMain()

View File

@ -6,7 +6,7 @@
load("//tools/build_defs/oss/osquery:cxx.bzl", "osquery_cxx_test")
load("//tools/build_defs/oss/osquery:native.bzl", "osquery_target")
load("//tools/build_defs/oss/osquery:platforms.bzl", "POSIX")
load("//tools/build_defs/oss/osquery:platforms.bzl", "POSIX", "WINDOWS")
osquery_cxx_test(
name = "flags_tests",
@ -137,3 +137,24 @@ osquery_cxx_test(
osquery_target("specs:tables"),
],
)
osquery_cxx_test(
name = "wmi_tests",
platform_srcs = [
(
WINDOWS,
[
"windows/wmi_tests.cpp",
],
),
],
visibility = ["PUBLIC"],
deps = [
osquery_target("osquery/config/tests:test_utils"),
osquery_target("osquery/core:core"),
osquery_target("osquery/remote/enroll:tls_enroll"),
osquery_target("osquery/sql/tests:sql_test_utils"),
osquery_target("osquery/utils/info:info"),
osquery_target("tests:helper"),
],
)

View File

@ -11,6 +11,10 @@ function(osqueryCoreTestsMain)
generateOsqueryCoreTestsWatcherpermissionstestsTest()
generateOsqueryCoreTestsQuerytestsTest()
generateOsqueryCoreTestsProcesstestsTest()
if(DEFINED PLATFORM_WINDOWS)
generateOsqueryCoreTestsWmitestsTest()
endif()
endfunction()
function(generateOsqueryCoreTestsFlagstestsTest)
@ -139,6 +143,21 @@ function(generateOsqueryCoreTestsQuerytestsTest)
)
endfunction()
function(generateOsqueryCoreTestsWmitestsTest)
add_osquery_executable(osquery_core_tests_wmitests-test windows/wmi_tests.cpp)
target_link_libraries(osquery_core_tests_wmitests-test PRIVATE
osquery_cxx_settings
osquery_core
osquery_config_tests_testutils
osquery_remote_enroll_tlsenroll
osquery_sql_tests_sqltestutils
osquery_utils_info
tests_helper
thirdparty_googletest
)
endfunction()
function(generateOsqueryCoreTestsProcesstestsTest)
add_osquery_executable(osquery_core_tests_processtests-test process_tests.cpp)

View File

@ -0,0 +1,123 @@
/**
* Copyright (c) 2014-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under both the Apache 2.0 license (found in the
* LICENSE file in the root directory of this source tree) and the GPLv2 (found
* in the COPYING file in the root directory of this source tree).
* You may select, at your option, one of the above-listed licenses.
*/
#include <sstream>
#include <boost/algorithm/string.hpp>
#include <gtest/gtest.h>
#include <osquery/config/tests/test_utils.h>
#include <osquery/core.h>
#include <osquery/system.h>
#include <osquery/utils/system/env.h>
#include "osquery/core/windows/wmi.h"
namespace osquery {
class WmiTests : public testing::Test {
protected:
void SetUp() {
Initializer::platformSetup();
}
};
TEST_F(WmiTests, test_methodcall_inparams) {
auto windir = getEnvVar("WINDIR");
EXPECT_TRUE(windir);
std::stringstream ss;
ss << "SELECT * FROM Win32_Directory WHERE Name = \"" << *windir << "\"";
auto query = ss.str();
// This is dirty, we need to escape the WINDIR path
boost::replace_all(query, "\\", "\\\\");
WmiRequest req(query);
const auto& wmiResults = req.results();
EXPECT_EQ(wmiResults.size(), 1);
WmiMethodArgs args;
WmiResultItem out;
// Setting in-parameter Permissions to 1 (FILE_LIST_DIRECTORY)
// The odd part here is that despite Permissions requiring a uint32 in
// MSDN documentation, this is actually a VT_BSTR...
args.Put<std::string>("Permissions", "1");
// Get the first item off the result vector since we should only have one.
auto& resultItem = wmiResults.front();
auto status = req.ExecMethod(resultItem, "GetEffectivePermission", args, out);
EXPECT_EQ(status.getMessage(), "OK");
EXPECT_TRUE(status.ok());
bool retval = false;
// The return value is stored in the ReturnValue key within the out-parameter
// object
status = out.GetBool("ReturnValue", retval);
EXPECT_EQ(status.getMessage(), "OK");
EXPECT_TRUE(status.ok());
// As both Administrator and normal user, we should be able to
// FILE_LIST_DIRECTORY on WINDIR
EXPECT_TRUE(retval);
}
TEST_F(WmiTests, test_methodcall_outparams) {
WmiRequest req("SELECT * FROM Win32_Process WHERE Name = \"wininit.exe\"");
const auto& wmiResults = req.results();
// We should expect only one wininit.exe instance?
EXPECT_EQ(wmiResults.size(), 1);
WmiMethodArgs args;
WmiResultItem out;
// Get the first item off the result vector since we should only have one.
auto& resultItem = wmiResults.front();
auto status = req.ExecMethod(resultItem, "GetOwner", args, out);
// We use this check to make debugging errors faster
EXPECT_EQ(status.getMessage(), "OK");
EXPECT_TRUE(status.ok());
long retval;
// For some reason, this is a VT_I4
status = out.GetLong("ReturnValue", retval);
EXPECT_EQ(status.getMessage(), "OK");
EXPECT_TRUE(status.ok());
// Make sure the return value is successful
EXPECT_EQ(retval, 0);
std::string user_name;
std::string domain_name;
status = out.GetString("User", user_name);
EXPECT_EQ(status.getMessage(), "OK");
EXPECT_TRUE(status.ok());
status = out.GetString("Domain", domain_name);
EXPECT_EQ(status.getMessage(), "OK");
EXPECT_TRUE(status.ok());
// Only NT AUTHORITY\SYSTEM should be running wininit.exe
EXPECT_EQ(user_name, "SYSTEM");
EXPECT_EQ(domain_name, "NT AUTHORITY");
}
} // namespace osquery

View File

@ -15,6 +15,62 @@
namespace osquery {
WmiMethodArgs::WmiMethodArgs(WmiMethodArgs&& src) {
std::swap(arguments, src.arguments);
}
WmiMethodArgs::~WmiMethodArgs() {
for (const auto& p : arguments) {
auto var = p.second;
// BSTR variant types have a raw pointer we need to clean up
if (var.vt == VT_BSTR && var.bstrVal != nullptr) {
SysFreeString(var.bstrVal);
var.bstrVal = nullptr;
}
}
}
template <>
Status WmiMethodArgs::Put<unsigned int>(const std::string& name,
const unsigned int& value) {
VARIANT var;
var.vt = VT_UI4;
var.ulVal = value;
arguments.insert(std::pair<std::string, VARIANT>(name, var));
return Status::success();
}
template <>
Status WmiMethodArgs::Put<std::string>(const std::string& name,
const std::string& value) {
auto wide_value = stringToWstring(value);
VARIANT var;
var.vt = VT_BSTR;
var.bstrVal = SysAllocString(wide_value.c_str());
if (var.bstrVal == nullptr) {
return Status::failure("Out of memory");
}
arguments.insert(std::pair<std::string, VARIANT>(name, var));
return Status::success();
}
/// Utility function to help turn a property value into BSTR
inline BSTR WbemClassObjectPropToBSTR(const WmiResultItem& item,
const std::string& property) {
std::string value;
auto status = item.GetString(property, value);
if (!status.ok()) {
return nullptr;
}
auto wstr_value = stringToWstring(value);
return SysAllocString(wstr_value.c_str());
}
void WmiResultItem::PrintType(const std::string& name) const {
std::wstring property_name = stringToWstring(name);
VARIANT value;
@ -38,15 +94,15 @@ Status WmiResultItem::GetBool(const std::string& name, bool& ret) const {
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
if (hr != S_OK) {
return Status(-1, "Error retrieving data from WMI query.");
return Status::failure("Error retrieving data from WMI query.");
}
if (value.vt != VT_BOOL) {
VariantClear(&value);
return Status(-1, "Invalid data type returned.");
return Status::failure("Invalid data type returned.");
}
ret = value.boolVal == VARIANT_TRUE ? true : false;
VariantClear(&value);
return Status(0);
return Status::success();
}
Status WmiResultItem::GetDateTime(const std::string& name,
@ -57,12 +113,12 @@ Status WmiResultItem::GetDateTime(const std::string& name,
VARIANT value;
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
if (hr != S_OK) {
return Status(-1, "Error retrieving datetime from WMI query result.");
return Status::failure("Error retrieving datetime from WMI query result.");
}
if (value.vt != VT_BSTR) {
VariantClear(&value);
return Status(-1, "Expected VT_BSTR, got something else.");
return Status::failure("Expected VT_BSTR, got something else.");
}
ISWbemDateTime* dt = nullptr;
@ -70,7 +126,7 @@ Status WmiResultItem::GetDateTime(const std::string& name,
CLSID_SWbemDateTime, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&dt));
if (!SUCCEEDED(hr)) {
VariantClear(&value);
return Status(-1, "Failed to create SWbemDateTime object.");
return Status::failure("Failed to create SWbemDateTime object.");
}
hr = dt->put_Value(value.bstrVal);
@ -78,14 +134,14 @@ Status WmiResultItem::GetDateTime(const std::string& name,
if (!SUCCEEDED(hr)) {
dt->Release();
return Status(-1, "Failed to set SWbemDateTime value.");
return Status::failure("Failed to set SWbemDateTime value.");
}
BSTR filetime_str = {0};
hr = dt->GetFileTime(is_local ? VARIANT_TRUE : VARIANT_FALSE, &filetime_str);
if (!SUCCEEDED(hr)) {
dt->Release();
return Status(-1, "GetFileTime failed.");
return Status::failure("GetFileTime failed.");
}
ULARGE_INTEGER ui = {};
@ -97,7 +153,7 @@ Status WmiResultItem::GetDateTime(const std::string& name,
SysFreeString(filetime_str);
dt->Release();
return Status(0);
return Status::success();
}
Status WmiResultItem::GetUChar(const std::string& name,
@ -106,15 +162,15 @@ Status WmiResultItem::GetUChar(const std::string& name,
VARIANT value;
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
if (hr != S_OK) {
return Status(-1, "Error retrieving data from WMI query.");
return Status::failure("Error retrieving data from WMI query.");
}
if (value.vt != VT_UI1) {
VariantClear(&value);
return Status(-1, "Invalid data type returned.");
return Status::failure("Invalid data type returned.");
}
ret = value.bVal;
VariantClear(&value);
return Status(0);
return Status::success();
}
Status WmiResultItem::GetUnsignedShort(const std::string& name,
@ -124,15 +180,15 @@ Status WmiResultItem::GetUnsignedShort(const std::string& name,
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
if (hr != S_OK) {
return Status(-1, "Error retrieving data from WMI query.");
return Status::failure("Error retrieving data from WMI query.");
}
if (value.vt != VT_UI2) {
VariantClear(&value);
return Status(-1, "Invalid data type returned.");
return Status::failure("Invalid data type returned.");
}
ret = value.uiVal;
VariantClear(&value);
return Status(0);
return Status::success();
}
Status WmiResultItem::GetUnsignedInt32(const std::string& name,
@ -142,15 +198,15 @@ Status WmiResultItem::GetUnsignedInt32(const std::string& name,
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
if (hr != S_OK) {
return Status(-1, "Error retrieving data from WMI query.");
return Status::failure("Error retrieving data from WMI query.");
}
if (value.vt != VT_UINT) {
VariantClear(&value);
return Status(-1, "Invalid data type returned.");
return Status::failure("Invalid data type returned.");
}
ret = value.uiVal;
VariantClear(&value);
return Status(0);
return Status::success();
}
Status WmiResultItem::GetLong(const std::string& name, long& ret) const {
@ -158,15 +214,15 @@ Status WmiResultItem::GetLong(const std::string& name, long& ret) const {
VARIANT value;
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
if (hr != S_OK) {
return Status(-1, "Error retrieving data from WMI query.");
return Status::failure("Error retrieving data from WMI query.");
}
if (value.vt != VT_I4) {
VariantClear(&value);
return Status(-1, "Invalid data type returned.");
return Status::failure("Invalid data type returned.");
}
ret = value.lVal;
VariantClear(&value);
return Status(0);
return Status::success();
}
Status WmiResultItem::GetUnsignedLong(const std::string& name,
@ -175,15 +231,15 @@ Status WmiResultItem::GetUnsignedLong(const std::string& name,
VARIANT value;
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
if (hr != S_OK) {
return Status(-1, "Error retrieving data from WMI query.");
return Status::failure("Error retrieving data from WMI query.");
}
if (value.vt != VT_UI4) {
VariantClear(&value);
return Status(-1, "Invalid data type returned.");
return Status::failure("Invalid data type returned.");
}
ret = value.lVal;
VariantClear(&value);
return Status(0);
return Status::success();
}
Status WmiResultItem::GetLongLong(const std::string& name,
@ -192,15 +248,15 @@ Status WmiResultItem::GetLongLong(const std::string& name,
VARIANT value;
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
if (hr != S_OK) {
return Status(-1, "Error retrieving data from WMI query.");
return Status::failure("Error retrieving data from WMI query.");
}
if (value.vt != VT_I8) {
VariantClear(&value);
return Status(-1, "Invalid data type returned.");
return Status::failure("Invalid data type returned.");
}
ret = value.lVal;
VariantClear(&value);
return Status(0);
return Status::success();
}
Status WmiResultItem::GetUnsignedLongLong(const std::string& name,
@ -209,15 +265,15 @@ Status WmiResultItem::GetUnsignedLongLong(const std::string& name,
VARIANT value;
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
if (hr != S_OK) {
return Status(-1, "Error retrieving data from WMI query.");
return Status::failure("Error retrieving data from WMI query.");
}
if (value.vt != VT_UI8) {
VariantClear(&value);
return Status(-1, "Invalid data type returned.");
return Status::failure("Invalid data type returned.");
}
ret = value.lVal;
VariantClear(&value);
return Status(0);
return Status::success();
}
Status WmiResultItem::GetString(const std::string& name,
@ -227,16 +283,16 @@ Status WmiResultItem::GetString(const std::string& name,
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
if (hr != S_OK) {
ret = "";
return Status(-1, "Error retrieving data from WMI query.");
return Status::failure("Error retrieving data from WMI query.");
}
if (value.vt != VT_BSTR) {
ret = "";
VariantClear(&value);
return Status(-1, "Invalid data type returned.");
return Status::failure("Invalid data type returned.");
}
ret = bstrToString(value.bstrVal);
VariantClear(&value);
return Status(0);
return Status::success();
}
Status WmiResultItem::GetVectorOfStrings(const std::string& name,
@ -245,11 +301,11 @@ Status WmiResultItem::GetVectorOfStrings(const std::string& name,
VARIANT value;
HRESULT hr = result_->Get(property_name.c_str(), 0, &value, nullptr, nullptr);
if (hr != S_OK) {
return Status(-1, "Error retrieving data from WMI query.");
return Status::failure("Error retrieving data from WMI query.");
}
if (value.vt != (VT_BSTR | VT_ARRAY)) {
VariantClear(&value);
return Status(-1, "Invalid data type returned.");
return Status::failure("Invalid data type returned.");
}
long lbound, ubound;
SafeArrayGetLBound(value.parray, 1, &lbound);
@ -264,7 +320,7 @@ Status WmiResultItem::GetVectorOfStrings(const std::string& name,
}
SafeArrayUnaccessData(value.parray);
VariantClear(&value);
return Status(0);
return Status::success();
}
WmiRequest::WmiRequest(const std::string& query, BSTR nspace) {
@ -272,7 +328,7 @@ WmiRequest::WmiRequest(const std::string& query, BSTR nspace) {
HRESULT hr = E_FAIL;
IWbemLocator *locator = nullptr;
IWbemLocator* locator = nullptr;
hr = ::CoInitializeSecurity(nullptr,
-1,
nullptr,
@ -290,22 +346,23 @@ WmiRequest::WmiRequest(const std::string& query, BSTR nspace) {
if (hr != S_OK) {
return;
}
locator_.reset(locator);
IWbemServices *services = nullptr;
IWbemServices* services = nullptr;
hr = locator_->ConnectServer(
nspace, nullptr, nullptr, nullptr, 0, nullptr, nullptr, &services);
if (hr != S_OK) {
return;
}
services_.reset(services);
IEnumWbemClassObject *wbem_enum = nullptr;
IEnumWbemClassObject* wbem_enum = nullptr;
hr = services_->ExecQuery(
(BSTR)L"WQL", (BSTR)wql.c_str(), WBEM_FLAG_FORWARD_ONLY, nullptr, &wbem_enum);
hr = services_->ExecQuery((BSTR)L"WQL",
(BSTR)wql.c_str(),
WBEM_FLAG_FORWARD_ONLY,
nullptr,
&wbem_enum);
if (hr != S_OK) {
return;
}
@ -319,14 +376,109 @@ WmiRequest::WmiRequest(const std::string& query, BSTR nspace) {
hr = enum_->Next(WBEM_INFINITE, 1, &result, &result_count);
if (SUCCEEDED(hr) && result_count > 0) {
results_.push_back(WmiResultItem(result));
results_.emplace_back(result);
}
}
status_ = Status(0);
}
WmiRequest::~WmiRequest() {
results_.clear();
}
Status WmiRequest::ExecMethod(const WmiResultItem& object,
const std::string& method,
const WmiMethodArgs& args,
WmiResultItem& out_result) const {
std::wstring property_name = stringToWstring(method);
IWbemClassObject* raw = nullptr;
std::unique_ptr<IWbemClassObject, impl::WmiObjectDeleter> in_def{nullptr};
std::unique_ptr<IWbemClassObject, impl::WmiObjectDeleter> class_obj{nullptr};
BSTR wmi_class_name = WbemClassObjectPropToBSTR(object, "__CLASS");
if (wmi_class_name == nullptr) {
return Status::failure("Class name out of memory");
}
// GetObject obtains a CIM Class definition object
HRESULT hr = services_->GetObject(wmi_class_name, 0, nullptr, &raw, nullptr);
SysFreeString(wmi_class_name);
if (FAILED(hr)) {
return Status::failure("Failed to GetObject");
}
class_obj.reset(raw);
raw = nullptr;
// GetMethod only works on CIM class definition objects. This is why
// we don't use result_
hr = class_obj->GetMethod(property_name.c_str(), 0, &raw, nullptr);
if (FAILED(hr)) {
return Status::failure("Failed to GetMethod");
}
in_def.reset(raw);
raw = nullptr;
std::unique_ptr<IWbemClassObject, impl::WmiObjectDeleter> args_inst{nullptr};
// in_def can be nullptr if the chosen method has no in-parameters
if (in_def != nullptr) {
hr = in_def->SpawnInstance(0, &raw);
if (FAILED(hr)) {
return Status::failure("Failed to SpawnInstance");
}
args_inst.reset(raw);
// Build up the WMI method call arguments
for (const auto& p : args.GetArguments()) {
const auto& name = p.first;
auto pVal = p.second;
auto args_name = stringToWstring(name);
hr = args_inst->Put(args_name.c_str(), 0, &pVal, 0);
if (FAILED(hr)) {
return Status::failure("Failed to Put arguments");
}
}
}
// In order to execute a WMI method, we need to know the specific object name
// and method name
IWbemClassObject* out_params = nullptr;
auto wmi_meth_name = SysAllocString(property_name.c_str());
if (wmi_meth_name == nullptr) {
return Status::failure("Out of memory");
}
auto wmi_obj_path = WbemClassObjectPropToBSTR(object, "__PATH");
if (wmi_obj_path == nullptr) {
SysFreeString(wmi_meth_name);
return Status::failure("Out of memory");
}
// Execute the WMI method, the return value and out-params all exist in
// out_params
hr = services_->ExecMethod(wmi_obj_path,
wmi_meth_name,
0,
nullptr,
args_inst.get(),
&out_params,
nullptr);
SysFreeString(wmi_meth_name);
SysFreeString(wmi_obj_path);
if (FAILED(hr)) {
return Status::failure("Failed to ExecMethod");
}
out_result = std::move(WmiResultItem(out_params));
return Status::success();
}
} // namespace osquery

View File

@ -8,9 +8,11 @@
#pragma once
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <osquery/utils/system/system.h>
@ -21,22 +23,63 @@
namespace osquery {
namespace impl{
using WmiMethodArgsMap = std::unordered_map<std::string, VARIANT>;
const auto wmiObjectDeleter = [](auto *ptr) {
ptr->Release();
namespace impl {
struct WmiObjectDeleter {
void operator()(IUnknown* ptr) {
if (ptr != nullptr) {
ptr->Release();
}
}
};
} // namespace impl
/**
* @brief Helper class to construct and hold the arguments of a WMI method call
*
* This class is used somewhat exclusively with WmiResultItem::ExecMethod. It
* simplifies the construction of a WMI method argument
*/
class WmiMethodArgs {
public:
WmiMethodArgs() {}
WmiMethodArgs(WmiMethodArgs&& src);
WmiMethodArgs(WmiMethodArgs&) = delete;
~WmiMethodArgs();
/**
* @brief Helper function to add items to the arguments of a WMI method call
*
* @returns Status indicating the success of the query
*/
template <typename T>
Status Put(const std::string& name, const T& value);
/**
* @brief Getter method for argument dictionary
*
* @returns Map containing name, value pairs of the arguments
*/
const WmiMethodArgsMap& GetArguments() const {
return arguments;
}
private:
WmiMethodArgsMap arguments{};
};
/**
* @brief Helper class to hold 1 result object from a WMI request
*
* This class is used to return to the user just the base type
* and value requested from WMI. The class is largely used by
* the WmiRequest class defined below
*/
* @brief Helper class to hold 1 result object from a WMI request
*
* This class is used to return to the user just the base type
* and value requested from WMI. The class is largely used by
* the WmiRequest class defined below
*/
class WmiResultItem {
public:
explicit WmiResultItem() {}
@ -47,19 +90,25 @@ class WmiResultItem {
WmiResultItem(WmiResultItem&& src) = default;
WmiResultItem& operator=(WmiResultItem&& src) {
result_ = std::move(src.result_);
return *this;
}
/**
* @brief Windows WMI Helper function to print the type associated with results
*
* @returns None.
*/
* @brief Windows WMI Helper function to print the type associated with
* results
*
* @returns None.
*/
void PrintType(const std::string& name) const;
/**
* @brief Windows WMI Helper function to retrieve a bool result from a WMI
* query
*
* @returns Status indicating the success of the query
*/
* @brief Windows WMI Helper function to retrieve a bool result from a WMI
* query
*
* @returns Status indicating the success of the query
*/
Status GetBool(const std::string& name, bool& ret) const;
/**
@ -81,109 +130,118 @@ class WmiResultItem {
Status GetUChar(const std::string& name, unsigned char& ret) const;
/**
* @brief Windows WMI Helper function to retrieve an unsigned Short from WMI
* query
*
* @returns Status indiciating the success of the query
*/
* @brief Windows WMI Helper function to retrieve an unsigned Short from WMI
* query
*
* @returns Status indiciating the success of the query
*/
Status GetUnsignedShort(const std::string& name, unsigned short& ret) const;
/**
* @brief Windows WMI Helper function to retrieve an unsigned 32 bit integer
* from a WMI query
*
* @returns Status indicating the success of the query
*/
* @brief Windows WMI Helper function to retrieve an unsigned 32 bit integer
* from a WMI query
*
* @returns Status indicating the success of the query
*/
Status GetUnsignedInt32(const std::string& name, unsigned int& ret) const;
/**
* @brief Windows WMI Helper function to retrieve a Long result from a WMI
* query
*
* @returns Status indicating the success of the query
*/
* @brief Windows WMI Helper function to retrieve a Long result from a WMI
* query
*
* @returns Status indicating the success of the query
*/
Status GetLong(const std::string& name, long& ret) const;
/**
* @brief Windows WMI Helper function to retrieve an unsigned Long result from
* a WMI query
*
* @returns Status indicating the success of the query
*/
* @brief Windows WMI Helper function to retrieve an unsigned Long result from
* a WMI query
*
* @returns Status indicating the success of the query
*/
Status GetUnsignedLong(const std::string& name, unsigned long& ret) const;
/**
* @brief Windows WMI Helper function to retrieve a Long Long result from a WMI
* query
*
* @returns Status indicating the success of the query
*/
* @brief Windows WMI Helper function to retrieve a Long Long result from a
* WMI query
*
* @returns Status indicating the success of the query
*/
Status GetLongLong(const std::string& name, long long& ret) const;
/**
* @brief Windows WMI Helper function to retrieve an Unsigned Long Long result
* from a WMI query
*
* @returns Status indicating the success of the query
*/
* @brief Windows WMI Helper function to retrieve an Unsigned Long Long result
* from a WMI query
*
* @returns Status indicating the success of the query
*/
Status GetUnsignedLongLong(const std::string& name,
unsigned long long& ret) const;
/**
* @brief Windows WMI Helper function to retrieve a String result from a WMI
* query
*
* @returns Status indicating the success of the query
*/
* @brief Windows WMI Helper function to retrieve a String result from a WMI
* query
*
* @returns Status indicating the success of the query
*/
Status GetString(const std::string& name, std::string& ret) const;
/**
* @brief Windows WMI Helper function to retrieve a vector of String result
* from
* a WMI query
*
* @returns Status indicating the success of the query
*/
* @brief Windows WMI Helper function to retrieve a vector of String result
* from
* a WMI query
*
* @returns Status indicating the success of the query
*/
Status GetVectorOfStrings(const std::string& name,
std::vector<std::string>& ret) const;
private:
std::unique_ptr<IWbemClassObject, decltype(impl::wmiObjectDeleter)> result_{nullptr, impl::wmiObjectDeleter};
std::unique_ptr<IWbemClassObject, impl::WmiObjectDeleter> result_{nullptr};
};
/**
* @brief Windows wrapper class for querying WMI
*
* This class abstracts away the WMI querying logic and
* will return WMI results given a query string.
*/
* @brief Windows wrapper class for querying WMI
*
* This class abstracts away the WMI querying logic and
* will return WMI results given a query string.
*/
class WmiRequest {
public:
explicit WmiRequest(const std::string& query,
BSTR nspace = (BSTR)L"ROOT\\CIMV2");
WmiRequest(WmiRequest&& src) = default;
~WmiRequest();
const std::vector<WmiResultItem>& results() const {
return results_;
}
/**
* @brief Getter for retrieving the status of a WMI Request
*
* @returns the status of the WMI request.
*/
* @brief Getter for retrieving the status of a WMI Request
*
* @returns the status of the WMI request.
*/
Status getStatus() const {
return status_;
}
/**
* @brief Windows WMI Helper function to execute a WMI method call on
* the given object (wrapped in a result)
*
* @returns Status indicating the success of the query
*/
Status ExecMethod(const WmiResultItem& object,
const std::string& method,
const WmiMethodArgs& args,
WmiResultItem& out_result) const;
private:
Status status_;
std::vector<WmiResultItem> results_;
std::unique_ptr<IWbemLocator, decltype(impl::wmiObjectDeleter)> locator_{nullptr, impl::wmiObjectDeleter};
std::unique_ptr<IEnumWbemClassObject, decltype(impl::wmiObjectDeleter)> enum_{nullptr, impl::wmiObjectDeleter};
std::unique_ptr<IWbemServices, decltype(impl::wmiObjectDeleter)> services_{nullptr, impl::wmiObjectDeleter};
std::unique_ptr<IEnumWbemClassObject, impl::WmiObjectDeleter> enum_{nullptr};
std::unique_ptr<IWbemLocator, impl::WmiObjectDeleter> locator_{nullptr};
std::unique_ptr<IWbemServices, impl::WmiObjectDeleter> services_{nullptr};
};
}
} // namespace osquery