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

Side by Side Diff: chrome/browser/metrics/antivirus_metrics_provider_win.cc

Issue 2078093002: Revert "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>
10 #include <windows.h> 9 #include <windows.h>
11 #include <wscapi.h> 10 #include <wscapi.h>
12 11
13 #include <string> 12 #include <string>
14 13
15 #include "base/bind.h" 14 #include "base/bind.h"
16 #include "base/callback.h" 15 #include "base/callback.h"
17 #include "base/feature_list.h" 16 #include "base/feature_list.h"
18 #include "base/file_version_info_win.h" 17 #include "base/file_version_info_win.h"
19 #include "base/files/file_path.h" 18 #include "base/files/file_path.h"
20 #include "base/files/file_util.h" 19 #include "base/files/file_util.h"
21 #include "base/metrics/field_trial.h" 20 #include "base/metrics/field_trial.h"
22 #include "base/metrics/histogram.h" 21 #include "base/metrics/histogram.h"
23 #include "base/path_service.h" 22 #include "base/path_service.h"
24 #include "base/strings/string_util.h" 23 #include "base/strings/string_util.h"
25 #include "base/strings/sys_string_conversions.h" 24 #include "base/strings/sys_string_conversions.h"
26 #include "base/task_runner_util.h" 25 #include "base/task_runner_util.h"
27 #include "base/threading/thread_restrictions.h" 26 #include "base/threading/thread_restrictions.h"
28 #include "base/version.h" 27 #include "base/version.h"
29 #include "base/win/scoped_bstr.h" 28 #include "base/win/scoped_bstr.h"
30 #include "base/win/scoped_com_initializer.h" 29 #include "base/win/scoped_com_initializer.h"
31 #include "base/win/scoped_comptr.h" 30 #include "base/win/scoped_comptr.h"
32 #include "base/win/scoped_variant.h"
33 #include "base/win/windows_version.h" 31 #include "base/win/windows_version.h"
34 #include "chrome/common/channel_info.h" 32 #include "chrome/common/channel_info.h"
35 #include "components/metrics/proto/system_profile.pb.h" 33 #include "components/metrics/proto/system_profile.pb.h"
36 #include "components/variations/metrics_util.h" 34 #include "components/variations/metrics_util.h"
37 #include "components/version_info/version_info.h" 35 #include "components/version_info/version_info.h"
38 36
39 namespace { 37 namespace {
40 38
41 // This is an undocumented structure returned from querying the "productState"
42 // uint32 from the AntiVirusProduct in WMI.
43 // http://neophob.com/2010/03/wmi-query-windows-securitycenter2/ gives a good
44 // summary and testing was also done with a variety of AV products to determine
45 // these values as accurately as possible.
46 #pragma pack(push)
47 #pragma pack(1)
48 struct PRODUCT_STATE {
49 uint8_t unknown_1 : 4;
50 uint8_t definition_state : 4; // 1 = Out of date, 0 = Up to date.
51 uint8_t unknown_2 : 4;
52 uint8_t security_state : 4; // 0 = Inactive, 1 = Active, 2 = Snoozed.
53 uint8_t security_provider; // matches WSC_SECURITY_PROVIDER in wscapi.h.
54 uint8_t unknown_3;
55 };
56 #pragma pack(pop)
57
58 static_assert(sizeof(PRODUCT_STATE) == 4, "Wrong packing!");
59
60 bool ShouldReportFullNames() { 39 bool ShouldReportFullNames() {
61 // The expectation is that this will be disabled for the majority of users, 40 // The expectation is that this will be disabled for the majority of users,
62 // but this allows a small group to be enabled on other channels if there are 41 // but this allows a small group to be enabled on other channels if there are
63 // a large percentage of hashes collected on these channels that are not 42 // a large percentage of hashes collected on these channels that are not
64 // resolved to names previously collected on Canary channel. 43 // resolved to names previously collected on Canary channel.
65 bool enabled = base::FeatureList::IsEnabled( 44 bool enabled = base::FeatureList::IsEnabled(
66 AntiVirusMetricsProvider::kReportNamesFeature); 45 AntiVirusMetricsProvider::kReportNamesFeature);
67 46
68 if (chrome::GetChannel() == version_info::Channel::CANARY) 47 if (chrome::GetChannel() == version_info::Channel::CANARY)
69 return true; 48 return true;
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 base::Bind(&AntiVirusMetricsProvider::GetAntiVirusProductsOnFileThread), 130 base::Bind(&AntiVirusMetricsProvider::GetAntiVirusProductsOnFileThread),
152 base::Bind(&AntiVirusMetricsProvider::GotAntiVirusProducts, 131 base::Bind(&AntiVirusMetricsProvider::GotAntiVirusProducts,
153 weak_ptr_factory_.GetWeakPtr(), done_callback)); 132 weak_ptr_factory_.GetWeakPtr(), done_callback));
154 } 133 }
155 134
156 // static 135 // static
157 std::vector<AntiVirusMetricsProvider::AvProduct> 136 std::vector<AntiVirusMetricsProvider::AvProduct>
158 AntiVirusMetricsProvider::GetAntiVirusProductsOnFileThread() { 137 AntiVirusMetricsProvider::GetAntiVirusProductsOnFileThread() {
159 std::vector<AvProduct> av_products; 138 std::vector<AvProduct> av_products;
160 139
161 ResultCode result = RESULT_GENERIC_FAILURE; 140 ResultCode result = FillAntiVirusProducts(&av_products);
162
163 // The WSC interface is preferred here as it's fully documented, but this code
164 // will fall-back to the undocumented WMI interface on Windows 7 and below.
165 if (base::win::GetVersion() >= base::win::VERSION_WIN8)
166 result = FillAntiVirusProductsFromWSC(&av_products);
167 else
168 result = FillAntiVirusProductsFromWMI(&av_products);
169 141
170 UMA_HISTOGRAM_ENUMERATION("UMA.AntiVirusMetricsProvider.Result", 142 UMA_HISTOGRAM_ENUMERATION("UMA.AntiVirusMetricsProvider.Result",
171 result, 143 result,
172 RESULT_COUNT); 144 RESULT_COUNT);
173 145
174 return av_products; 146 return av_products;
175 } 147 }
176 148
177 void AntiVirusMetricsProvider::GotAntiVirusProducts( 149 void AntiVirusMetricsProvider::GotAntiVirusProducts(
178 const base::Closure& done_callback, 150 const base::Closure& done_callback,
179 const std::vector<AvProduct>& av_products) { 151 const std::vector<AvProduct>& av_products) {
180 DCHECK(thread_checker_.CalledOnValidThread()); 152 DCHECK(thread_checker_.CalledOnValidThread());
181 av_products_ = av_products; 153 av_products_ = av_products;
182 done_callback.Run(); 154 done_callback.Run();
183 } 155 }
184 156
185 // static 157 // static
186 AntiVirusMetricsProvider::ResultCode 158 AntiVirusMetricsProvider::ResultCode
187 AntiVirusMetricsProvider::FillAntiVirusProductsFromWSC( 159 AntiVirusMetricsProvider::FillAntiVirusProducts(
188 std::vector<AvProduct>* products) { 160 std::vector<AvProduct>* products) {
189 std::vector<AvProduct> result_list; 161 std::vector<AvProduct> result_list;
190 base::ThreadRestrictions::AssertIOAllowed(); 162 base::ThreadRestrictions::AssertIOAllowed();
191 base::win::ScopedCOMInitializer com_initializer; 163 base::win::ScopedCOMInitializer com_initializer;
192 164
193 if (!com_initializer.succeeded()) 165 if (!com_initializer.succeeded())
194 return RESULT_FAILED_TO_INITIALIZE_COM; 166 return RESULT_FAILED_TO_INITIALIZE_COM;
195 167
196 base::win::ScopedComPtr<IWSCProductList> product_list; 168 base::win::ScopedComPtr<IWSCProductList> product_list;
197 HRESULT result = 169 HRESULT result =
198 CoCreateInstance(__uuidof(WSCProductList), nullptr, CLSCTX_INPROC_SERVER, 170 CoCreateInstance(__uuidof(WSCProductList), NULL, CLSCTX_INPROC_SERVER,
199 __uuidof(IWSCProductList), product_list.ReceiveVoid()); 171 __uuidof(IWSCProductList), product_list.ReceiveVoid());
200 if (FAILED(result)) 172 if (FAILED(result))
201 return RESULT_FAILED_TO_CREATE_INSTANCE; 173 return RESULT_FAILED_TO_CREATE_INSTANCE;
202 174
203 result = product_list->Initialize(WSC_SECURITY_PROVIDER_ANTIVIRUS); 175 result = product_list->Initialize(WSC_SECURITY_PROVIDER_ANTIVIRUS);
204 if (FAILED(result)) 176 if (FAILED(result))
205 return RESULT_FAILED_TO_INITIALIZE_PRODUCT_LIST; 177 return RESULT_FAILED_TO_INITIALIZE_PRODUCT_LIST;
206 178
207 LONG product_count; 179 LONG product_count;
208 result = product_list->get_Count(&product_count); 180 result = product_list->get_Count(&product_count);
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
276 av_product.set_product_version_hash(metrics::HashName(product_version)); 248 av_product.set_product_version_hash(metrics::HashName(product_version));
277 } 249 }
278 250
279 result_list.push_back(av_product); 251 result_list.push_back(av_product);
280 } 252 }
281 253
282 *products = std::move(result_list); 254 *products = std::move(result_list);
283 255
284 return RESULT_SUCCESS; 256 return RESULT_SUCCESS;
285 } 257 }
286
287 AntiVirusMetricsProvider::ResultCode
288 AntiVirusMetricsProvider::FillAntiVirusProductsFromWMI(
289 std::vector<AvProduct>* products) {
290 std::vector<AvProduct> result_list;
291 base::ThreadRestrictions::AssertIOAllowed();
292 base::win::ScopedCOMInitializer com_initializer;
293
294 if (!com_initializer.succeeded())
295 return RESULT_FAILED_TO_INITIALIZE_COM;
296
297 base::win::ScopedComPtr<IWbemLocator> wmi_locator;
298 HRESULT hr = wmi_locator.CreateInstance(CLSID_WbemLocator, nullptr,
299 CLSCTX_INPROC_SERVER);
300 if (FAILED(hr))
301 return RESULT_FAILED_TO_CREATE_INSTANCE;
302
303 base::win::ScopedComPtr<IWbemServices> wmi_services;
304 hr = wmi_locator->ConnectServer(
305 base::win::ScopedBstr(L"ROOT\\SecurityCenter2"), nullptr, nullptr,
306 nullptr, 0, nullptr, nullptr, wmi_services.Receive());
307 if (FAILED(hr))
308 return RESULT_FAILED_TO_CONNECT_TO_WMI;
309
310 hr = ::CoSetProxyBlanket(wmi_services.get(), RPC_C_AUTHN_WINNT,
311 RPC_C_AUTHZ_NONE, nullptr, RPC_C_AUTHN_LEVEL_CALL,
312 RPC_C_IMP_LEVEL_IMPERSONATE, nullptr, EOAC_NONE);
313 if (FAILED(hr))
314 return RESULT_FAILED_TO_SET_SECURITY_BLANKET;
315
316 // This interface is available on Windows Vista and above, and is officially
317 // undocumented.
318 base::win::ScopedBstr query_language(L"WQL");
319 base::win::ScopedBstr query(L"SELECT * FROM AntiVirusProduct");
320 base::win::ScopedComPtr<IEnumWbemClassObject> enumerator;
321
322 hr = wmi_services->ExecQuery(
323 query_language, query,
324 WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, nullptr,
325 enumerator.Receive());
326 if (FAILED(hr))
327 return RESULT_FAILED_TO_EXEC_WMI_QUERY;
328
329 // Iterate over the results of the WMI query. Each result will be an
330 // AntiVirusProduct instance.
331 while (true) {
332 base::win::ScopedComPtr<IWbemClassObject> class_object;
333 ULONG items_returned = 0;
334 hr = enumerator->Next(WBEM_INFINITE, 1, class_object.Receive(),
335 &items_returned);
336 if (FAILED(hr))
337 return RESULT_FAILED_TO_ITERATE_RESULTS;
338
339 if (hr == WBEM_S_FALSE || items_returned == 0)
340 break;
341
342 AvProduct av_product;
343 av_product.set_product_state(
344 metrics::SystemProfileProto::AntiVirusState::
345 SystemProfileProto_AntiVirusState_STATE_ON);
346
347 // See definition of PRODUCT_STATE structure above for how this is being
348 // used.
349 base::win::ScopedVariant product_state;
350 hr = class_object->Get(L"productState", 0, product_state.Receive(), 0, 0);
351
352 if (FAILED(hr) || product_state.type() != VT_I4)
353 return RESULT_FAILED_TO_GET_PRODUCT_STATE;
354
355 LONG state_val = V_I4(product_state.ptr());
356 // Map the values from product_state to the proto values.
357 switch (reinterpret_cast<PRODUCT_STATE*>(&state_val)->security_state) {
358 case 0:
359 av_product.set_product_state(
360 metrics::SystemProfileProto::AntiVirusState::
361 SystemProfileProto_AntiVirusState_STATE_OFF);
362 break;
363 case 1:
364 av_product.set_product_state(
365 metrics::SystemProfileProto::AntiVirusState::
366 SystemProfileProto_AntiVirusState_STATE_ON);
367 break;
368 case 2:
369 av_product.set_product_state(
370 metrics::SystemProfileProto::AntiVirusState::
371 SystemProfileProto_AntiVirusState_STATE_SNOOZED);
372 break;
373 default:
374 // unknown state.
375 return RESULT_PRODUCT_STATE_INVALID;
376 break;
377 }
378
379 base::win::ScopedVariant display_name;
380 hr = class_object->Get(L"displayName", 0, display_name.Receive(), 0, 0);
381
382 if (FAILED(hr) || display_name.type() != VT_BSTR)
383 return RESULT_FAILED_TO_GET_PRODUCT_NAME;
384
385 // Owned by ScopedVariant.
386 BSTR temp_bstr = V_BSTR(display_name.ptr());
387 std::string name(base::SysWideToUTF8(
388 std::wstring(temp_bstr, ::SysStringLen(temp_bstr))));
389
390 if (ShouldReportFullNames())
391 av_product.set_product_name(name);
392 av_product.set_product_name_hash(metrics::HashName(name));
393
394 base::win::ScopedVariant exe_path;
395 hr = class_object->Get(L"pathToSignedProductExe", 0, exe_path.Receive(), 0,
396 0);
397
398 if (FAILED(hr) || exe_path.type() != VT_BSTR)
399 return RESULT_FAILED_TO_GET_REMEDIATION_PATH;
400
401 temp_bstr = V_BSTR(exe_path.ptr());
402 std::wstring path_str(temp_bstr, ::SysStringLen(temp_bstr));
403
404 std::string product_version;
405 // Not a failure if the product version cannot be read from the file on
406 // disk.
407 if (GetProductVersion(&path_str, &product_version)) {
408 if (ShouldReportFullNames())
409 av_product.set_product_version(product_version);
410 av_product.set_product_version_hash(metrics::HashName(product_version));
411 }
412
413 result_list.push_back(av_product);
414 }
415
416 *products = std::move(result_list);
417
418 return RESULT_SUCCESS;
419 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698