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

Side by Side 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 unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/metrics/antivirus_metrics_provider_win.h" 5 #include "chrome/browser/metrics/antivirus_metrics_provider_win.h"
6 6
7 #include <iwscapi.h> 7 #include <iwscapi.h>
8 #include <stddef.h> 8 #include <stddef.h>
9 #include <wbemidl.h>
9 #include <windows.h> 10 #include <windows.h>
10 #include <wscapi.h> 11 #include <wscapi.h>
11 12
12 #include <string> 13 #include <string>
13 14
14 #include "base/bind.h" 15 #include "base/bind.h"
15 #include "base/callback.h" 16 #include "base/callback.h"
16 #include "base/feature_list.h" 17 #include "base/feature_list.h"
17 #include "base/file_version_info_win.h" 18 #include "base/file_version_info_win.h"
18 #include "base/files/file_path.h" 19 #include "base/files/file_path.h"
19 #include "base/files/file_util.h" 20 #include "base/files/file_util.h"
20 #include "base/metrics/field_trial.h" 21 #include "base/metrics/field_trial.h"
21 #include "base/metrics/histogram.h" 22 #include "base/metrics/histogram.h"
22 #include "base/path_service.h" 23 #include "base/path_service.h"
23 #include "base/strings/string_util.h" 24 #include "base/strings/string_util.h"
24 #include "base/strings/sys_string_conversions.h" 25 #include "base/strings/sys_string_conversions.h"
25 #include "base/task_runner_util.h" 26 #include "base/task_runner_util.h"
26 #include "base/threading/thread_restrictions.h" 27 #include "base/threading/thread_restrictions.h"
27 #include "base/version.h" 28 #include "base/version.h"
28 #include "base/win/scoped_bstr.h" 29 #include "base/win/scoped_bstr.h"
29 #include "base/win/scoped_com_initializer.h" 30 #include "base/win/scoped_com_initializer.h"
30 #include "base/win/scoped_comptr.h" 31 #include "base/win/scoped_comptr.h"
32 #include "base/win/scoped_variant.h"
31 #include "base/win/windows_version.h" 33 #include "base/win/windows_version.h"
32 #include "chrome/common/channel_info.h" 34 #include "chrome/common/channel_info.h"
33 #include "components/metrics/proto/system_profile.pb.h" 35 #include "components/metrics/proto/system_profile.pb.h"
34 #include "components/variations/metrics_util.h" 36 #include "components/variations/metrics_util.h"
35 #include "components/version_info/version_info.h" 37 #include "components/version_info/version_info.h"
36 38
37 namespace { 39 namespace {
38 40
41 #pragma pack(push)
42 #pragma pack(1)
43 struct PRODUCT_STATE {
Will Harris 2016/06/16 19:05:33 Source: http://neophob.com/2010/03/wmi-query-windo
44 uint8_t unknown_1 : 4;
45 uint8_t definition_state : 4; // 1 = out of date, 0 = up to date.
46 uint8_t unknown_2 : 4;
47 uint8_t security_state : 4; // 0 = inactive, 1 = active, 2 = snoozed.
48 uint8_t security_provider; // matches WSC_SECURITY_PROVIDER enum.
49 uint8_t unknown_3;
50 };
51 #pragma pack(pop)
52
53 static_assert(sizeof(PRODUCT_STATE) == 4, "wrong packing!");
54
39 bool ShouldReportFullNames() { 55 bool ShouldReportFullNames() {
40 // The expectation is that this will be disabled for the majority of users, 56 // The expectation is that this will be disabled for the majority of users,
41 // but this allows a small group to be enabled on other channels if there are 57 // but this allows a small group to be enabled on other channels if there are
42 // a large percentage of hashes collected on these channels that are not 58 // a large percentage of hashes collected on these channels that are not
43 // resolved to names previously collected on Canary channel. 59 // resolved to names previously collected on Canary channel.
44 bool enabled = base::FeatureList::IsEnabled( 60 bool enabled = base::FeatureList::IsEnabled(
45 AntiVirusMetricsProvider::kReportNamesFeature); 61 AntiVirusMetricsProvider::kReportNamesFeature);
46 62
47 if (chrome::GetChannel() == version_info::Channel::CANARY) 63 if (chrome::GetChannel() == version_info::Channel::CANARY)
48 return true; 64 return true;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
130 base::Bind(&AntiVirusMetricsProvider::GetAntiVirusProductsOnFileThread), 146 base::Bind(&AntiVirusMetricsProvider::GetAntiVirusProductsOnFileThread),
131 base::Bind(&AntiVirusMetricsProvider::GotAntiVirusProducts, 147 base::Bind(&AntiVirusMetricsProvider::GotAntiVirusProducts,
132 weak_ptr_factory_.GetWeakPtr(), done_callback)); 148 weak_ptr_factory_.GetWeakPtr(), done_callback));
133 } 149 }
134 150
135 // static 151 // static
136 std::vector<AntiVirusMetricsProvider::AvProduct> 152 std::vector<AntiVirusMetricsProvider::AvProduct>
137 AntiVirusMetricsProvider::GetAntiVirusProductsOnFileThread() { 153 AntiVirusMetricsProvider::GetAntiVirusProductsOnFileThread() {
138 std::vector<AvProduct> av_products; 154 std::vector<AvProduct> av_products;
139 155
140 ResultCode result = FillAntiVirusProducts(&av_products); 156 ResultCode result = RESULT_GENERIC_FAILURE;
157
158 if (base::win::GetVersion() >= base::win::VERSION_WIN8)
159 result = FillAntiVirusProductsFromWSC(&av_products);
160 else
161 result = FillAntiVirusProductsFromWMI(&av_products);
Will Harris 2016/06/16 19:05:33 Note: The WMI interface is not officially document
141 162
142 UMA_HISTOGRAM_ENUMERATION("UMA.AntiVirusMetricsProvider.Result", 163 UMA_HISTOGRAM_ENUMERATION("UMA.AntiVirusMetricsProvider.Result",
143 result, 164 result,
144 RESULT_COUNT); 165 RESULT_COUNT);
145 166
146 return av_products; 167 return av_products;
147 } 168 }
148 169
149 void AntiVirusMetricsProvider::GotAntiVirusProducts( 170 void AntiVirusMetricsProvider::GotAntiVirusProducts(
150 const base::Closure& done_callback, 171 const base::Closure& done_callback,
151 const std::vector<AvProduct>& av_products) { 172 const std::vector<AvProduct>& av_products) {
152 DCHECK(thread_checker_.CalledOnValidThread()); 173 DCHECK(thread_checker_.CalledOnValidThread());
153 av_products_ = av_products; 174 av_products_ = av_products;
154 done_callback.Run(); 175 done_callback.Run();
155 } 176 }
156 177
157 // static 178 // static
158 AntiVirusMetricsProvider::ResultCode 179 AntiVirusMetricsProvider::ResultCode
159 AntiVirusMetricsProvider::FillAntiVirusProducts( 180 AntiVirusMetricsProvider::FillAntiVirusProductsFromWSC(
160 std::vector<AvProduct>* products) { 181 std::vector<AvProduct>* products) {
161 std::vector<AvProduct> result_list; 182 std::vector<AvProduct> result_list;
162 base::ThreadRestrictions::AssertIOAllowed(); 183 base::ThreadRestrictions::AssertIOAllowed();
163 base::win::ScopedCOMInitializer com_initializer; 184 base::win::ScopedCOMInitializer com_initializer;
164 185
165 if (!com_initializer.succeeded()) 186 if (!com_initializer.succeeded())
166 return RESULT_FAILED_TO_INITIALIZE_COM; 187 return RESULT_FAILED_TO_INITIALIZE_COM;
167 188
168 base::win::ScopedComPtr<IWSCProductList> product_list; 189 base::win::ScopedComPtr<IWSCProductList> product_list;
169 HRESULT result = 190 HRESULT result =
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 // disk. 265 // disk.
245 if (GetProductVersion(&path_str, &product_version)) { 266 if (GetProductVersion(&path_str, &product_version)) {
246 if (ShouldReportFullNames()) 267 if (ShouldReportFullNames())
247 av_product.set_product_version(product_version); 268 av_product.set_product_version(product_version);
248 av_product.set_product_version_hash(metrics::HashName(product_version)); 269 av_product.set_product_version_hash(metrics::HashName(product_version));
249 } 270 }
250 271
251 result_list.push_back(av_product); 272 result_list.push_back(av_product);
252 } 273 }
253 274
254 *products = std::move(result_list); 275 products->insert(products->end(), result_list.begin(), result_list.end());
255 276
256 return RESULT_SUCCESS; 277 return RESULT_SUCCESS;
257 } 278 }
279
280 AntiVirusMetricsProvider::ResultCode
281 AntiVirusMetricsProvider::FillAntiVirusProductsFromWMI(
282 std::vector<AvProduct>* products) {
283 std::vector<AvProduct> result_list;
284 base::ThreadRestrictions::AssertIOAllowed();
285 base::win::ScopedCOMInitializer com_initializer;
286
287 if (!com_initializer.succeeded())
288 return RESULT_FAILED_TO_INITIALIZE_COM;
289
290 base::win::ScopedComPtr<IWbemLocator> wmi_locator;
291 HRESULT hr =
292 wmi_locator.CreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER);
293 if (FAILED(hr))
294 return RESULT_FAILED_TO_CREATE_INSTANCE;
295
296 base::win::ScopedComPtr<IWbemServices> wmi_services;
297 hr = wmi_locator->ConnectServer(
298 base::win::ScopedBstr(L"ROOT\\SecurityCenter2"), NULL, NULL, 0, NULL, 0,
299 0, wmi_services.Receive());
300 if (FAILED(hr))
301 return RESULT_FAILED_TO_CONNECT_TO_WMI;
302
303 hr = ::CoSetProxyBlanket(wmi_services.get(), RPC_C_AUTHN_WINNT,
304 RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL,
305 RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
306 if (FAILED(hr))
307 return RESULT_FAILED_TO_SET_SECURITY_BLANKET;
308
309 base::win::ScopedBstr query_language(L"WQL");
310 base::win::ScopedBstr query(L"SELECT * FROM AntiVirusProduct");
311 base::win::ScopedComPtr<IEnumWbemClassObject> enumerator;
312
313 hr = wmi_services->ExecQuery(
314 query_language, query,
315 WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL,
316 enumerator.Receive());
317 if (FAILED(hr))
318 return RESULT_FAILED_TO_EXEC_WMI_QUERY;
319
320 while (true) {
321 base::win::ScopedComPtr<IWbemClassObject> class_object;
322 ULONG items_returned = 0;
323 hr = enumerator->Next(WBEM_INFINITE, 1, class_object.Receive(),
324 &items_returned);
325 if (FAILED(hr))
326 return RESULT_FAILED_TO_ITERATE_RESULTS;
327
328 if (hr == WBEM_S_FALSE || items_returned == 0)
329 break;
330
331 AvProduct av_product;
332 av_product.set_product_state(
333 metrics::SystemProfileProto::AntiVirusState::
334 SystemProfileProto_AntiVirusState_STATE_ON);
335
336 base::win::ScopedVariant product_state;
337 hr = class_object->Get(L"productState", 0, product_state.Receive(), 0, 0);
338
339 if (FAILED(hr) || product_state.type() != VT_I4)
340 return RESULT_FAILED_TO_GET_PRODUCT_STATE;
341
342 LONG state_val = V_I4(product_state.ptr());
343 switch (reinterpret_cast<PRODUCT_STATE*>(&state_val)->security_state) {
344 case 0:
345 av_product.set_product_state(
346 metrics::SystemProfileProto::AntiVirusState::
347 SystemProfileProto_AntiVirusState_STATE_OFF);
348 break;
349 case 1:
350 av_product.set_product_state(
351 metrics::SystemProfileProto::AntiVirusState::
352 SystemProfileProto_AntiVirusState_STATE_ON);
353 break;
354 case 2:
355 av_product.set_product_state(
356 metrics::SystemProfileProto::AntiVirusState::
357 SystemProfileProto_AntiVirusState_STATE_SNOOZED);
358 break;
359 default:
360 // unknown state.
361 return RESULT_PRODUCT_STATE_INVALID;
362 break;
363 }
364
365 base::win::ScopedVariant display_name;
366 hr = class_object->Get(L"displayName", 0, display_name.Receive(), 0, 0);
367
368 if (FAILED(hr) || display_name.type() != VT_BSTR)
369 return RESULT_FAILED_TO_GET_PRODUCT_NAME;
370
371 // Owned by ScopedVariant.
372 BSTR temp_bstr = V_BSTR(display_name.ptr());
373 std::string name(base::SysWideToUTF8(
374 std::wstring(temp_bstr, ::SysStringLen(temp_bstr))));
375
376 if (ShouldReportFullNames())
377 av_product.set_product_name(name);
378 av_product.set_product_name_hash(metrics::HashName(name));
379
380 base::win::ScopedVariant exe_path;
381 hr = class_object->Get(L"pathToSignedProductExe", 0, exe_path.Receive(), 0,
382 0);
383
384 if (FAILED(hr) || exe_path.type() != VT_BSTR)
385 return RESULT_FAILED_TO_GET_REMEDIATION_PATH;
386
387 temp_bstr = V_BSTR(exe_path.ptr());
388 std::wstring path_str(temp_bstr, ::SysStringLen(temp_bstr));
389
390 std::string product_version;
391 // Not a failure if the product version cannot be read from the file on
392 // disk.
393 if (GetProductVersion(&path_str, &product_version)) {
394 if (ShouldReportFullNames())
395 av_product.set_product_version(product_version);
396 av_product.set_product_version_hash(metrics::HashName(product_version));
397 }
398
399 result_list.push_back(av_product);
400 }
401
402 products->insert(products->end(), result_list.begin(), result_list.end());
403
404 return RESULT_SUCCESS;
405 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698