Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(787)

Unified Diff: chrome/browser/metrics/antivirus_metrics_provider_win.cc

Issue 2064313004: Add support for obtaining AV products on Win7. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/metrics/antivirus_metrics_provider_win.cc
diff --git a/chrome/browser/metrics/antivirus_metrics_provider_win.cc b/chrome/browser/metrics/antivirus_metrics_provider_win.cc
index cc098a473921cb5fe3d2f00b14a09c173ff82ad2..025d907e3f15b4334ee66f4be026eb57ca8f99f8 100644
--- a/chrome/browser/metrics/antivirus_metrics_provider_win.cc
+++ b/chrome/browser/metrics/antivirus_metrics_provider_win.cc
@@ -6,6 +6,7 @@
#include <iwscapi.h>
#include <stddef.h>
+#include <wbemidl.h>
#include <windows.h>
#include <wscapi.h>
@@ -28,6 +29,7 @@
#include "base/win/scoped_bstr.h"
#include "base/win/scoped_com_initializer.h"
#include "base/win/scoped_comptr.h"
+#include "base/win/scoped_variant.h"
#include "base/win/windows_version.h"
#include "chrome/common/channel_info.h"
#include "components/metrics/proto/system_profile.pb.h"
@@ -36,6 +38,20 @@
namespace {
+#pragma pack(push)
+#pragma pack(1)
+struct PRODUCT_STATE {
Will Harris 2016/06/16 19:05:33 Source: http://neophob.com/2010/03/wmi-query-windo
+ uint8_t unknown_1 : 4;
+ uint8_t definition_state : 4; // 1 = out of date, 0 = up to date.
+ uint8_t unknown_2 : 4;
+ uint8_t security_state : 4; // 0 = inactive, 1 = active, 2 = snoozed.
+ uint8_t security_provider; // matches WSC_SECURITY_PROVIDER enum.
+ uint8_t unknown_3;
+};
+#pragma pack(pop)
+
+static_assert(sizeof(PRODUCT_STATE) == 4, "wrong packing!");
+
bool ShouldReportFullNames() {
// The expectation is that this will be disabled for the majority of users,
// but this allows a small group to be enabled on other channels if there are
@@ -137,7 +153,12 @@ std::vector<AntiVirusMetricsProvider::AvProduct>
AntiVirusMetricsProvider::GetAntiVirusProductsOnFileThread() {
std::vector<AvProduct> av_products;
- ResultCode result = FillAntiVirusProducts(&av_products);
+ ResultCode result = RESULT_GENERIC_FAILURE;
+
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8)
+ result = FillAntiVirusProductsFromWSC(&av_products);
+ else
+ result = FillAntiVirusProductsFromWMI(&av_products);
Will Harris 2016/06/16 19:05:33 Note: The WMI interface is not officially document
UMA_HISTOGRAM_ENUMERATION("UMA.AntiVirusMetricsProvider.Result",
result,
@@ -156,7 +177,7 @@ void AntiVirusMetricsProvider::GotAntiVirusProducts(
// static
AntiVirusMetricsProvider::ResultCode
-AntiVirusMetricsProvider::FillAntiVirusProducts(
+AntiVirusMetricsProvider::FillAntiVirusProductsFromWSC(
std::vector<AvProduct>* products) {
std::vector<AvProduct> result_list;
base::ThreadRestrictions::AssertIOAllowed();
@@ -251,7 +272,134 @@ AntiVirusMetricsProvider::FillAntiVirusProducts(
result_list.push_back(av_product);
}
- *products = std::move(result_list);
+ products->insert(products->end(), result_list.begin(), result_list.end());
+
+ return RESULT_SUCCESS;
+}
+
+AntiVirusMetricsProvider::ResultCode
+AntiVirusMetricsProvider::FillAntiVirusProductsFromWMI(
+ std::vector<AvProduct>* products) {
+ std::vector<AvProduct> result_list;
+ base::ThreadRestrictions::AssertIOAllowed();
+ base::win::ScopedCOMInitializer com_initializer;
+
+ if (!com_initializer.succeeded())
+ return RESULT_FAILED_TO_INITIALIZE_COM;
+
+ base::win::ScopedComPtr<IWbemLocator> wmi_locator;
+ HRESULT hr =
+ wmi_locator.CreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER);
+ if (FAILED(hr))
+ return RESULT_FAILED_TO_CREATE_INSTANCE;
+
+ base::win::ScopedComPtr<IWbemServices> wmi_services;
+ hr = wmi_locator->ConnectServer(
+ base::win::ScopedBstr(L"ROOT\\SecurityCenter2"), NULL, NULL, 0, NULL, 0,
+ 0, wmi_services.Receive());
+ if (FAILED(hr))
+ return RESULT_FAILED_TO_CONNECT_TO_WMI;
+
+ hr = ::CoSetProxyBlanket(wmi_services.get(), RPC_C_AUTHN_WINNT,
+ RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL,
+ RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
+ if (FAILED(hr))
+ return RESULT_FAILED_TO_SET_SECURITY_BLANKET;
+
+ base::win::ScopedBstr query_language(L"WQL");
+ base::win::ScopedBstr query(L"SELECT * FROM AntiVirusProduct");
+ base::win::ScopedComPtr<IEnumWbemClassObject> enumerator;
+
+ hr = wmi_services->ExecQuery(
+ query_language, query,
+ WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL,
+ enumerator.Receive());
+ if (FAILED(hr))
+ return RESULT_FAILED_TO_EXEC_WMI_QUERY;
+
+ while (true) {
+ base::win::ScopedComPtr<IWbemClassObject> class_object;
+ ULONG items_returned = 0;
+ hr = enumerator->Next(WBEM_INFINITE, 1, class_object.Receive(),
+ &items_returned);
+ if (FAILED(hr))
+ return RESULT_FAILED_TO_ITERATE_RESULTS;
+
+ if (hr == WBEM_S_FALSE || items_returned == 0)
+ break;
+
+ AvProduct av_product;
+ av_product.set_product_state(
+ metrics::SystemProfileProto::AntiVirusState::
+ SystemProfileProto_AntiVirusState_STATE_ON);
+
+ base::win::ScopedVariant product_state;
+ hr = class_object->Get(L"productState", 0, product_state.Receive(), 0, 0);
+
+ if (FAILED(hr) || product_state.type() != VT_I4)
+ return RESULT_FAILED_TO_GET_PRODUCT_STATE;
+
+ LONG state_val = V_I4(product_state.ptr());
+ switch (reinterpret_cast<PRODUCT_STATE*>(&state_val)->security_state) {
+ case 0:
+ av_product.set_product_state(
+ metrics::SystemProfileProto::AntiVirusState::
+ SystemProfileProto_AntiVirusState_STATE_OFF);
+ break;
+ case 1:
+ av_product.set_product_state(
+ metrics::SystemProfileProto::AntiVirusState::
+ SystemProfileProto_AntiVirusState_STATE_ON);
+ break;
+ case 2:
+ av_product.set_product_state(
+ metrics::SystemProfileProto::AntiVirusState::
+ SystemProfileProto_AntiVirusState_STATE_SNOOZED);
+ break;
+ default:
+ // unknown state.
+ return RESULT_PRODUCT_STATE_INVALID;
+ break;
+ }
+
+ base::win::ScopedVariant display_name;
+ hr = class_object->Get(L"displayName", 0, display_name.Receive(), 0, 0);
+
+ if (FAILED(hr) || display_name.type() != VT_BSTR)
+ return RESULT_FAILED_TO_GET_PRODUCT_NAME;
+
+ // Owned by ScopedVariant.
+ BSTR temp_bstr = V_BSTR(display_name.ptr());
+ std::string name(base::SysWideToUTF8(
+ std::wstring(temp_bstr, ::SysStringLen(temp_bstr))));
+
+ if (ShouldReportFullNames())
+ av_product.set_product_name(name);
+ av_product.set_product_name_hash(metrics::HashName(name));
+
+ base::win::ScopedVariant exe_path;
+ hr = class_object->Get(L"pathToSignedProductExe", 0, exe_path.Receive(), 0,
+ 0);
+
+ if (FAILED(hr) || exe_path.type() != VT_BSTR)
+ return RESULT_FAILED_TO_GET_REMEDIATION_PATH;
+
+ temp_bstr = V_BSTR(exe_path.ptr());
+ std::wstring path_str(temp_bstr, ::SysStringLen(temp_bstr));
+
+ std::string product_version;
+ // Not a failure if the product version cannot be read from the file on
+ // disk.
+ if (GetProductVersion(&path_str, &product_version)) {
+ if (ShouldReportFullNames())
+ av_product.set_product_version(product_version);
+ av_product.set_product_version_hash(metrics::HashName(product_version));
+ }
+
+ result_list.push_back(av_product);
+ }
+
+ products->insert(products->end(), result_list.begin(), result_list.end());
return RESULT_SUCCESS;
}

Powered by Google App Engine
This is Rietveld 408576698