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 );