Commit 4dcdac24 authored by Georges Khalil's avatar Georges Khalil Committed by Commit Bot

Add serial_number to base::SysInfo::HardwareInfo (Windows only).

This patch adds the serial number to base::SysInfo::HardwareInfo on
Windows only, where it represents the BIOS serial number. This is
grabbed through a WMI call.

Other platforms will follow.

Bug: 907518
Change-Id: I1b2b23c00cda286f325a0a09722dbfc5e974eb77
Reviewed-on: https://chromium-review.googlesource.com/c/1346869Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Reviewed-by: default avatarRobert Liao <robliao@chromium.org>
Reviewed-by: default avatarRoger Tawa <rogerta@chromium.org>
Commit-Queue: Georges Khalil <georgesak@chromium.org>
Cr-Commit-Position: refs/heads/master@{#611685}
parent 7156aa54
......@@ -78,6 +78,11 @@ class BASE_EXPORT SysInfo {
struct HardwareInfo {
std::string manufacturer;
std::string model;
// On Windows, this is the BIOS serial number. Unsupported platforms will be
// set to an empty string.
// Note: validate any new usage with the privacy team.
// TODO(crbug.com/907518): Implement support on other platforms.
std::string serial_number;
};
// Returns via |callback| a struct containing descriptive UTF-8 strings for
// the current machine manufacturer and model, or empty strings if the
......
......@@ -161,6 +161,13 @@ TEST_F(SysInfoTest, GetHardwareInfo) {
#endif
EXPECT_EQ(hardware_info->manufacturer.empty(), empty_result_expected);
EXPECT_EQ(hardware_info->model.empty(), empty_result_expected);
#if defined(OS_WIN)
EXPECT_FALSE(hardware_info->serial_number.empty());
#else
// TODO(crbug.com/907518): Implement support on other platforms.
EXPECT_EQ(hardware_info->serial_number, std::string());
#endif
}
#if defined(OS_CHROMEOS)
......
......@@ -169,8 +169,10 @@ SysInfo::HardwareInfo SysInfo::GetHardwareInfoSync() {
HardwareInfo info;
info.manufacturer = UTF16ToUTF8(wmi_info.manufacturer());
info.model = UTF16ToUTF8(wmi_info.model());
info.serial_number = UTF16ToUTF8(wmi_info.serial_number());
DCHECK(IsStringUTF8(info.manufacturer));
DCHECK(IsStringUTF8(info.model));
DCHECK(IsStringUTF8(info.serial_number));
return info;
}
......
......@@ -28,9 +28,9 @@ bool CreateLocalWmiConnection(bool set_blanket,
return false;
ComPtr<IWbemServices> wmi_services_r;
hr = wmi_locator->ConnectServer(ScopedBstr(L"ROOT\\CIMV2"), nullptr, nullptr,
nullptr, 0, nullptr, nullptr,
wmi_services_r.GetAddressOf());
hr =
wmi_locator->ConnectServer(ScopedBstr(L"ROOT\\CIMV2"), nullptr, nullptr,
nullptr, 0, nullptr, nullptr, &wmi_services_r);
if (FAILED(hr))
return false;
......@@ -56,14 +56,13 @@ bool CreateWmiClassMethodObject(IWbemServices* wmi_services,
ScopedBstr b_method_name(method_name);
ComPtr<IWbemClassObject> class_object;
HRESULT hr;
hr = wmi_services->GetObject(b_class_name, 0, nullptr,
class_object.GetAddressOf(), nullptr);
hr =
wmi_services->GetObject(b_class_name, 0, nullptr, &class_object, nullptr);
if (FAILED(hr))
return false;
ComPtr<IWbemClassObject> params_def;
hr = class_object->GetMethod(b_method_name, 0, params_def.GetAddressOf(),
nullptr);
hr = class_object->GetMethod(b_method_name, 0, &params_def, nullptr);
if (FAILED(hr))
return false;
......@@ -113,7 +112,7 @@ bool WmiLaunchProcess(const string16& command_line, int* process_id) {
ComPtr<IWbemClassObject> out_params;
HRESULT hr = wmi_local->ExecMethod(
ScopedBstr(class_name), ScopedBstr(method_name), 0, nullptr,
process_create.Get(), out_params.GetAddressOf(), nullptr);
process_create.Get(), &out_params, nullptr);
if (FAILED(hr))
return false;
......@@ -135,41 +134,77 @@ bool WmiLaunchProcess(const string16& command_line, int* process_id) {
return true;
}
// static
WmiComputerSystemInfo WmiComputerSystemInfo::Get() {
ComPtr<IWbemServices> services;
WmiComputerSystemInfo info;
if (!CreateLocalWmiConnection(true, &services))
return WmiComputerSystemInfo();
return info;
info.PopulateModelAndManufacturer(services);
info.PopulateSerialNumber(services);
return info;
}
ScopedBstr query_language(L"WQL");
ScopedBstr query(L"SELECT * FROM Win32_ComputerSystem");
ComPtr<IEnumWbemClassObject> enumerator;
void WmiComputerSystemInfo::PopulateModelAndManufacturer(
const ComPtr<IWbemServices>& services) {
static constexpr base::StringPiece16 query_computer_system(
L"SELECT Manufacturer,Model FROM Win32_ComputerSystem");
ComPtr<IEnumWbemClassObject> enumerator_computer_system;
HRESULT hr =
services->ExecQuery(query_language, query,
services->ExecQuery(ScopedBstr(L"WQL"), ScopedBstr(query_computer_system),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
nullptr, enumerator.GetAddressOf());
if (FAILED(hr) || !enumerator.Get())
return WmiComputerSystemInfo();
nullptr, &enumerator_computer_system);
if (FAILED(hr) || !enumerator_computer_system.Get())
return;
ComPtr<IWbemClassObject> class_object;
ULONG items_returned = 0;
hr = enumerator->Next(WBEM_INFINITE, 1, class_object.GetAddressOf(),
&items_returned);
if (!items_returned)
return WmiComputerSystemInfo();
hr = enumerator_computer_system->Next(WBEM_INFINITE, 1, &class_object,
&items_returned);
if (FAILED(hr) || !items_returned)
return;
ScopedVariant manufacturer;
class_object->Get(L"Manufacturer", 0, manufacturer.Receive(), 0, 0);
hr = class_object->Get(L"Manufacturer", 0, manufacturer.Receive(), 0, 0);
if (SUCCEEDED(hr) && manufacturer.type() == VT_BSTR) {
manufacturer_.assign(V_BSTR(manufacturer.ptr()),
::SysStringLen(V_BSTR(manufacturer.ptr())));
}
ScopedVariant model;
class_object->Get(L"Model", 0, model.Receive(), 0, 0);
hr = class_object->Get(L"Model", 0, model.Receive(), 0, 0);
if (SUCCEEDED(hr) && model.type() == VT_BSTR)
model_.assign(V_BSTR(model.ptr()), ::SysStringLen(V_BSTR(model.ptr())));
}
WmiComputerSystemInfo info;
if (manufacturer.type() == VT_BSTR)
info.manufacturer_ = V_BSTR(manufacturer.ptr());
void WmiComputerSystemInfo::PopulateSerialNumber(
const ComPtr<IWbemServices>& services) {
static constexpr base::StringPiece16 query_bios(
L"SELECT SerialNumber FROM Win32_Bios");
if (model.type() == VT_BSTR)
info.model_ = V_BSTR(model.ptr());
ComPtr<IEnumWbemClassObject> enumerator_bios;
HRESULT hr =
services->ExecQuery(ScopedBstr(L"WQL"), ScopedBstr(query_bios),
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY,
nullptr, &enumerator_bios);
if (FAILED(hr) || !enumerator_bios.Get())
return;
return info;
ComPtr<IWbemClassObject> class_obj;
ULONG items_returned = 0;
hr = enumerator_bios->Next(WBEM_INFINITE, 1, &class_obj, &items_returned);
if (FAILED(hr) || !items_returned)
return;
ScopedVariant serial_number;
hr = class_obj->Get(L"SerialNumber", 0, serial_number.Receive(), 0, 0);
if (SUCCEEDED(hr) && serial_number.type() == VT_BSTR) {
serial_number_.assign(V_BSTR(serial_number.ptr()),
::SysStringLen(V_BSTR(serial_number.ptr())));
}
}
} // namespace win
......
......@@ -71,18 +71,27 @@ BASE_EXPORT bool SetWmiClassMethodParameter(IWbemClassObject* class_method,
BASE_EXPORT bool WmiLaunchProcess(const string16& command_line,
int* process_id);
// This class contains functionality of the WMI class 'Win32_ComputerSystem'.
// More info: http://msdn.microsoft.com/en-us/library/aa394102(VS.85).aspx
// An encapsulation of information retrieved from the 'Win32_ComputerSystem' and
// 'Win32_Bios' WMI classes; see :
// https://docs.microsoft.com/en-us/windows/desktop/CIMWin32Prov/win32-computersystem
// https://docs.microsoft.com/en-us/windows/desktop/CIMWin32Prov/win32-systembios
class BASE_EXPORT WmiComputerSystemInfo {
public:
static WmiComputerSystemInfo Get();
const string16& manufacturer() const { return manufacturer_; }
const string16& model() const { return model_; }
const string16& serial_number() const { return serial_number_; }
private:
void PopulateModelAndManufacturer(
const Microsoft::WRL::ComPtr<IWbemServices>& services);
void PopulateSerialNumber(
const Microsoft::WRL::ComPtr<IWbemServices>& services);
string16 manufacturer_;
string16 model_;
string16 serial_number_;
};
} // namespace win
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment