Signed-off-by: Brendan Shanks bshanks@codeweavers.com --- Note that not all WMI properties referenced are implemented yet by Wine, future patches will add these.
programs/wineboot/Makefile.in | 4 +- programs/wineboot/wineboot.c | 143 ++++++++++++++++++++++++++++++++++ 2 files changed, 145 insertions(+), 2 deletions(-)
diff --git a/programs/wineboot/Makefile.in b/programs/wineboot/Makefile.in index 3921fa9644..67944a2444 100644 --- a/programs/wineboot/Makefile.in +++ b/programs/wineboot/Makefile.in @@ -1,7 +1,7 @@ MODULE = wineboot.exe APPMODE = -mconsole -IMPORTS = uuid advapi32 -DELAYIMPORTS = shell32 shlwapi version user32 setupapi newdev +IMPORTS = uuid advapi32 wbemuuid +DELAYIMPORTS = shell32 shlwapi version user32 setupapi newdev ole32 oleaut32
EXTRADLLFLAGS = -mno-cygwin
diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c index 8e3e234397..30d75b3214 100644 --- a/programs/wineboot/wineboot.c +++ b/programs/wineboot/wineboot.c @@ -72,6 +72,7 @@ #include <shellapi.h> #include <setupapi.h> #include <newdev.h> +#include <wbemcli.h> #include "resource.h"
WINE_DEFAULT_DEBUG_CHANNEL(wineboot); @@ -299,6 +300,145 @@ static void get_namestring( WCHAR *buf ) { }
#endif /* __i386__ || __x86_64__ */
+struct reg_wmi_map +{ + const WCHAR *registry_valname; + const WCHAR *wmi_propname; +}; +static const struct reg_wmi_map bios_map[] = +{ + { L"BiosMajorRelease", L"SystemBiosMajorVersion" }, + { L"BiosMinorRelease", L"SystemBiosMinorVersion" }, + { L"BIOSReleaseDate", L"ReleaseDate" }, + { L"BIOSVendor", L"Manufacturer" }, + { L"BIOSVersion", L"SMBIOSBIOSVersion" }, + { L"ECFirmwareMajorVersion", L"EmbeddedControllerMajorVersion" }, + { L"ECFirmwareMinorVersion", L"EmbeddedControllerMinorVersion" }, +}; +static const struct reg_wmi_map baseboard_map[] = +{ + { L"BaseBoardManufacturer", L"Manufacturer" }, + { L"BaseBoardProduct", L"Product" }, + { L"BaseBoardVersion", L"Version" }, +}; +static const struct reg_wmi_map computersystem_map[] = +{ + { L"SystemFamily", L"SystemFamily" }, + { L"SystemManufacturer", L"Manufacturer" }, + { L"SystemProductName", L"Model" }, + { L"SystemSKU", L"SystemSKUNumber" }, +}; +static const struct reg_wmi_map computersystemproduct_map[] = +{ + { L"SystemVersion", L"Version" }, +}; + +static void create_bios_values( HKEY bios_key, IWbemServices *services, const WCHAR *class, const struct reg_wmi_map *map, unsigned int map_size ) +{ + static const WCHAR select_allW[] = L"SELECT * FROM "; + HRESULT hr; + IEnumWbemClassObject *result = NULL; + LONG flags = WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY; + BSTR wql = NULL, query = NULL; + UINT len; + + len = lstrlenW( class ) + ARRAY_SIZE(select_allW); + if (!(query = SysAllocStringLen( NULL, len ))) goto done; + lstrcpyW( query, select_allW ); + lstrcatW( query, class ); + + if (!(wql = SysAllocString( L"WQL" ))) goto done; + hr = IWbemServices_ExecQuery( services, wql, query, flags, NULL, &result ); + if (hr != S_OK) goto done; + + for (;;) + { + IWbemClassObject *obj; + ULONG count; + unsigned int i; + + IEnumWbemClassObject_Next( result, WBEM_INFINITE, 1, &obj, &count ); + if (!count) break; + + for (i = 0; i < map_size; i++) + { + BSTR str = NULL; + CIMTYPE cimtype; + VARIANT v; + + if (!(str = SysAllocString( map[i].wmi_propname ))) break; + if (IWbemClassObject_Get( obj, str, 0, &v, &cimtype, NULL ) == WBEM_S_NO_ERROR) + { + if (V_VT( &v ) == VT_UI1) + { + DWORD dw = V_UI1( &v ); + RegSetValueExW( bios_key, map[i].registry_valname, 0, REG_DWORD, (const BYTE *)&dw, sizeof(dw) ); + } + else if (V_VT( &v ) == VT_BSTR) + { + if (cimtype == CIM_DATETIME) + { + /* WMI/CIM datetime starts with "YYYYMMDD", but BIOSReleaseDate uses "MM/DD/YYYY" */ + WCHAR date[] = L"MM/DD/YYYY"; + const WCHAR *cimdate = V_BSTR( &v ); + memcpy( &date[6], &cimdate[0], 4*sizeof(WCHAR) ); + memcpy( &date[0], &cimdate[4], 2*sizeof(WCHAR) ); + memcpy( &date[3], &cimdate[6], 2*sizeof(WCHAR) ); + set_reg_value( bios_key, map[i].registry_valname, date ); + } + else + set_reg_value( bios_key, map[i].registry_valname, V_BSTR( &v ) ); + } + VariantClear( &v ); + } + SysFreeString( str ); + } + IWbemClassObject_Release( obj ); + } + +done: + if (result) IEnumWbemClassObject_Release( result ); + SysFreeString( query ); + SysFreeString( wql ); +} + +static void create_bios_key( HKEY system_key ) +{ + HKEY bios_key; + HRESULT hr; + IWbemLocator *locator = NULL; + IWbemServices *services = NULL; + BSTR path = NULL; + + if (RegCreateKeyExW( system_key, L"BIOS", 0, NULL, REG_OPTION_VOLATILE, + KEY_ALL_ACCESS, NULL, &bios_key, NULL )) + return; + + CoInitialize( NULL ); + CoInitializeSecurity( NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT, + RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL ); + + hr = CoCreateInstance( &CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, &IID_IWbemLocator, + (void **)&locator ); + if (hr != S_OK) goto done; + + if (!(path = SysAllocString( L"ROOT\CIMV2" ))) goto done; + hr = IWbemLocator_ConnectServer( locator, path, NULL, NULL, NULL, 0, NULL, NULL, &services ); + if (hr != S_OK) goto done; + + create_bios_values( bios_key, services, L"Win32_BaseBoard", baseboard_map, ARRAY_SIZE(baseboard_map) ); + create_bios_values( bios_key, services, L"Win32_BIOS", bios_map, ARRAY_SIZE(bios_map) ); + create_bios_values( bios_key, services, L"Win32_ComputerSystem", computersystem_map, ARRAY_SIZE(computersystem_map) ); + create_bios_values( bios_key, services, L"Win32_ComputerSystemProduct", computersystemproduct_map, ARRAY_SIZE(computersystemproduct_map) ); + +done: + if (services) IWbemServices_Release( services ); + if (locator) IWbemLocator_Release( locator ); + SysFreeString( path ); + CoUninitialize(); + RegCloseKey( bios_key ); +} + /* create the volatile hardware registry keys */ static void create_hardware_registry_keys(void) { @@ -409,6 +549,9 @@ static void create_hardware_registry_keys(void) RegCloseKey( hkey ); } } + + create_bios_key( system_key ); + RegCloseKey( fpu_key ); RegCloseKey( cpu_key ); RegCloseKey( system_key );
On Tue, 2020-02-18 at 15:27 -0800, Brendan Shanks wrote:
Note that not all WMI properties referenced are implemented yet by Wine, future patches will add these.
This will fail to set the keys on prefix creation because the COM interface isn't registered yet. I'm not sure if it matters in practice, but to avoid that we might consider calling GetSystemFirmwareTable directly and duplicate the parsing code.
Hans Leidekker hans@codeweavers.com writes:
On Tue, 2020-02-18 at 15:27 -0800, Brendan Shanks wrote:
Note that not all WMI properties referenced are implemented yet by Wine, future patches will add these.
This will fail to set the keys on prefix creation because the COM interface isn't registered yet. I'm not sure if it matters in practice, but to avoid that we might consider calling GetSystemFirmwareTable directly and duplicate the parsing code.
Yes, I don't think we want wineboot to use WBEM.