The test for ISmbiosInformationStatics_get_SerialNumber is broken on Window 10 testbot VMs, presumably because they don't have a serial number? It results in an HRESULT of E_UNEXPECTED. I added a broken test case for it. I'm assuming that normal installations of Windows return a valid serial number. Also, on my Linux OS running cat /sys/class/dmi/id/product_serial returns "To be filled by O.E.M". So I added a fallback to return 0 as the number. Or is it fine to just return whatever string is found?
On the Windows 8 VMs, the test crashes at line 75, hr = ISmbiosInformationStatics_get_SerialNumber( smbios_statics, &serial ). Not sure what I should do in this case. I was hoping for a flag that checks if the VM is Windows 8, but there doesn't seem to be one. Should I wrap the test in if (0) or is there an alternative way?
Another weird thing is the test fails prematurely on only the 32-bit version of debian11b, saying that the runtimeclass is not registered. I'm assuming it's an issue with the testbot. Debian11 32 bit runs fine.
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- include/Makefile.in | 1 + ...ows.system.profile.systemmanufacturers.idl | 60 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 include/windows.system.profile.systemmanufacturers.idl
diff --git a/include/Makefile.in b/include/Makefile.in index 62904d8d2a0..0790fbbb3e4 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -813,6 +813,7 @@ SOURCES = \ windows.storage.streams.idl \ windows.system.idl \ windows.system.power.idl \ + windows.system.profile.systemmanufacturers.idl \ windows.system.threading.idl \ windows.system.userprofile.idl \ windows.ui.idl \ diff --git a/include/windows.system.profile.systemmanufacturers.idl b/include/windows.system.profile.systemmanufacturers.idl new file mode 100644 index 00000000000..644a664020b --- /dev/null +++ b/include/windows.system.profile.systemmanufacturers.idl @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#ifdef __WIDL__ +#pragma winrt ns_prefix +#endif + +import "inspectable.idl"; +import "asyncinfo.idl"; +import "eventtoken.idl"; +import "windowscontracts.idl"; +import "windows.foundation.idl"; + +namespace Windows.System.Profile.SystemManufacturers +{ + apicontract SystemManufacturersContract; + interface ISmbiosInformationStatics; + runtimeclass SmbiosInformation; + + [ + contractversion(3.0) + ] + apicontract SystemManufacturersContract + { + } + + [ + contract(Windows.System.Profile.SystemManufacturers.SystemManufacturersContract, 1.0), + exclusiveto(Windows.System.Profile.SystemManufacturers.SmbiosInformation), + uuid(080cca7c-637c-48c4-b728-f9273812db8e) + ] + interface ISmbiosInformationStatics : IInspectable + { + [propget] HRESULT SerialNumber([out, retval] HSTRING *value); + } + + [ + contract(Windows.System.Profile.SystemManufacturers.SystemManufacturersContract, 1.0), + marshaling_behavior(agile), + static(Windows.System.Profile.SystemManufacturers.ISmbiosInformationStatics, Windows.System.Profile.SystemManufacturers.SystemManufacturersContract, 1.0) + ] + runtimeclass SmbiosInformation + { + } +}
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- configure.ac | 2 + .../Makefile.in | 8 + .../classes.idl | 23 +++ .../main.c | 148 ++++++++++++++++++ .../private.h | 69 ++++++++ .../tests/Makefile.in | 5 + .../tests/smbios.c | 83 ++++++++++ ...ws.system.profile.systemmanufacturers.spec | 3 + 8 files changed, 341 insertions(+) create mode 100644 dlls/windows.system.profile.systemmanufacturers/Makefile.in create mode 100644 dlls/windows.system.profile.systemmanufacturers/classes.idl create mode 100644 dlls/windows.system.profile.systemmanufacturers/main.c create mode 100644 dlls/windows.system.profile.systemmanufacturers/private.h create mode 100644 dlls/windows.system.profile.systemmanufacturers/tests/Makefile.in create mode 100644 dlls/windows.system.profile.systemmanufacturers/tests/smbios.c create mode 100644 dlls/windows.system.profile.systemmanufacturers/windows.system.profile.systemmanufacturers.spec
diff --git a/configure.ac b/configure.ac index cb91c9c02b5..321d5efa50d 100644 --- a/configure.ac +++ b/configure.ac @@ -3180,6 +3180,8 @@ WINE_CONFIG_MAKEFILE(dlls/windows.media.speech/tests) WINE_CONFIG_MAKEFILE(dlls/windows.media) WINE_CONFIG_MAKEFILE(dlls/windows.media/tests) WINE_CONFIG_MAKEFILE(dlls/windows.networking) +WINE_CONFIG_MAKEFILE(dlls/windows.system.profile.systemmanufacturers) +WINE_CONFIG_MAKEFILE(dlls/windows.system.profile.systemmanufacturers/tests) WINE_CONFIG_MAKEFILE(dlls/windowscodecs) WINE_CONFIG_MAKEFILE(dlls/windowscodecs/tests) WINE_CONFIG_MAKEFILE(dlls/windowscodecsext) diff --git a/dlls/windows.system.profile.systemmanufacturers/Makefile.in b/dlls/windows.system.profile.systemmanufacturers/Makefile.in new file mode 100644 index 00000000000..a2d6076740f --- /dev/null +++ b/dlls/windows.system.profile.systemmanufacturers/Makefile.in @@ -0,0 +1,8 @@ +MODULE = windows.system.profile.systemmanufacturers.dll +IMPORTS = combase + +C_SRCS = \ + main.c + +IDL_SRCS = \ + classes.idl diff --git a/dlls/windows.system.profile.systemmanufacturers/classes.idl b/dlls/windows.system.profile.systemmanufacturers/classes.idl new file mode 100644 index 00000000000..6072a782222 --- /dev/null +++ b/dlls/windows.system.profile.systemmanufacturers/classes.idl @@ -0,0 +1,23 @@ +/* + * Runtime Classes for windows.system.profile.systemmanufacturers.dll + * + * Copyright (C) 2022 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma makedep register + +#include "windows.system.profile.systemmanufacturers.idl" diff --git a/dlls/windows.system.profile.systemmanufacturers/main.c b/dlls/windows.system.profile.systemmanufacturers/main.c new file mode 100644 index 00000000000..3f5e937392e --- /dev/null +++ b/dlls/windows.system.profile.systemmanufacturers/main.c @@ -0,0 +1,148 @@ +/* WinRT Windows.System.Profile.SystemManufacturers Implementation + * + * Copyright (C) 2022 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "initguid.h" +#include "private.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(smbios); + +static const char *debugstr_hstring( HSTRING hstr ) +{ + const WCHAR *str; + UINT32 len; + if (hstr && !((ULONG_PTR)hstr >> 16)) return "(invalid)"; + str = WindowsGetStringRawBuffer(hstr, &len); + return wine_dbgstr_wn(str, len); +} + +struct smbios_statics +{ + IActivationFactory IActivationFactory_iface; + LONG ref; +}; + +static inline struct smbios_statics *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct smbios_statics, IActivationFactory_iface ); +} + +static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct smbios_statics *impl = impl_from_IActivationFactory( iface ); + + TRACE( "iface %p, iid %s, out %p.\n", iface, debugstr_guid( iid ), out ); + + if (IsEqualGUID( iid, &IID_IUnknown ) || + IsEqualGUID( iid, &IID_IInspectable ) || + IsEqualGUID( iid, &IID_IAgileObject ) || + IsEqualGUID( iid, &IID_IActivationFactory )) + { + *out = &impl->IActivationFactory_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI factory_AddRef( IActivationFactory *iface ) +{ + struct smbios_statics *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI factory_Release( IActivationFactory *iface ) +{ + struct smbios_statics *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); + return ref; +} + +static HRESULT WINAPI factory_GetIids( IActivationFactory *iface, ULONG *iid_count, IID **iids ) +{ + FIXME( "iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_GetRuntimeClassName( IActivationFactory *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_GetTrustLevel( IActivationFactory *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance ) +{ + FIXME( "iface %p, instance %p stub!\n", iface, instance ); + return E_NOTIMPL; +} + +static const struct IActivationFactoryVtbl factory_vtbl = +{ + factory_QueryInterface, + factory_AddRef, + factory_Release, + /* IInspectable methods */ + factory_GetIids, + factory_GetRuntimeClassName, + factory_GetTrustLevel, + /* IActivationFactory methods */ + factory_ActivateInstance, +}; + +static struct smbios_statics smbios_statics = +{ + {&factory_vtbl}, + 1, +}; + +static IActivationFactory *smbios_factory = &smbios_statics.IActivationFactory_iface; + +HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID riid, void **out ) +{ + FIXME( "clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out ); + return CLASS_E_CLASSNOTAVAILABLE; +} + +HRESULT WINAPI DllGetActivationFactory( HSTRING classid, IActivationFactory **factory ) +{ + const WCHAR *name = WindowsGetStringRawBuffer( classid, NULL ); + + TRACE( "classid %s, factory %p.\n", debugstr_hstring(classid), factory ); + + *factory = NULL; + + if (!wcscmp( name, RuntimeClass_Windows_System_Profile_SystemManufacturers_SmbiosInformation )) + IActivationFactory_QueryInterface( smbios_factory, &IID_IActivationFactory, (void **)factory ); + + if (*factory) return S_OK; + return CLASS_E_CLASSNOTAVAILABLE; +} diff --git a/dlls/windows.system.profile.systemmanufacturers/private.h b/dlls/windows.system.profile.systemmanufacturers/private.h new file mode 100644 index 00000000000..42c19710dcb --- /dev/null +++ b/dlls/windows.system.profile.systemmanufacturers/private.h @@ -0,0 +1,69 @@ +/* WinRT Windows.System.Profile.SystemManufacturers Implementation + * + * Copyright (C) 2022 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdarg.h> +#include <stddef.h> + +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winstring.h" + +#include "activation.h" + +#define WIDL_using_Windows_System_Profile_SystemManufacturers +#include "windows.system.profile.systemmanufacturers.h" + +#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \ + static inline impl_type *impl_from( iface_type *iface ) \ + { \ + return CONTAINING_RECORD( iface, impl_type, iface_mem ); \ + } \ + static HRESULT WINAPI pfx##_QueryInterface( iface_type *iface, REFIID iid, void **out ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_QueryInterface( (IInspectable *)(expr), iid, out ); \ + } \ + static ULONG WINAPI pfx##_AddRef( iface_type *iface ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_AddRef( (IInspectable *)(expr) ); \ + } \ + static ULONG WINAPI pfx##_Release( iface_type *iface ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_Release( (IInspectable *)(expr) ); \ + } \ + static HRESULT WINAPI pfx##_GetIids( iface_type *iface, ULONG *iid_count, IID **iids ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetIids( (IInspectable *)(expr), iid_count, iids ); \ + } \ + static HRESULT WINAPI pfx##_GetRuntimeClassName( iface_type *iface, HSTRING *class_name ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetRuntimeClassName( (IInspectable *)(expr), class_name ); \ + } \ + static HRESULT WINAPI pfx##_GetTrustLevel( iface_type *iface, TrustLevel *trust_level ) \ + { \ + impl_type *impl = impl_from( iface ); \ + return IInspectable_GetTrustLevel( (IInspectable *)(expr), trust_level ); \ + } +#define DEFINE_IINSPECTABLE( pfx, iface_type, impl_type, base_iface ) \ + DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, &impl->base_iface ) diff --git a/dlls/windows.system.profile.systemmanufacturers/tests/Makefile.in b/dlls/windows.system.profile.systemmanufacturers/tests/Makefile.in new file mode 100644 index 00000000000..ade0c6b12dd --- /dev/null +++ b/dlls/windows.system.profile.systemmanufacturers/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = windows.system.profile.systemmanufacturers.dll +IMPORTS = combase + +C_SRCS = \ + smbios.c diff --git a/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c b/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c new file mode 100644 index 00000000000..628c5f689bc --- /dev/null +++ b/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2022 Mohamad Al-Jaf + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ +#define COBJMACROS +#include "initguid.h" +#include <stdarg.h> + +#include "windef.h" +#include "winbase.h" +#include "winstring.h" + +#include "roapi.h" + +#define WIDL_using_Windows_System_Profile_SystemManufacturers +#include "windows.system.profile.systemmanufacturers.h" + +#include "wine/test.h" + +#define check_interface( obj, iid ) check_interface_( __LINE__, obj, iid ) +static void check_interface_( unsigned int line, void *obj, const IID *iid ) +{ + IUnknown *iface = obj; + IUnknown *unk; + HRESULT hr; + + hr = IUnknown_QueryInterface( iface, iid, (void **)&unk ); + ok_(__FILE__, line)( hr == S_OK, "got hr %#lx.\n", hr ); + IUnknown_Release( unk ); +} + +static void test_Smbios_Statics(void) +{ + static const WCHAR *smbios_statics_name = L"Windows.System.Profile.SystemManufacturers.SmbiosInformation"; + IActivationFactory *factory; + HSTRING str; + HRESULT hr; + LONG ref; + + hr = WindowsCreateString( smbios_statics_name, wcslen( smbios_statics_name ), &str ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory ); + WindowsDeleteString( str ); + ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr ); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( smbios_statics_name )); + return; + } + + check_interface( factory, &IID_IUnknown ); + check_interface( factory, &IID_IInspectable ); + check_interface( factory, &IID_IAgileObject ); + + ref = IActivationFactory_Release( factory ); + ok( ref == 1, "got ref %ld.\n", ref ); +} + +START_TEST(smbios) +{ + HRESULT hr; + + hr = RoInitialize( RO_INIT_MULTITHREADED ); + ok( hr == S_OK, "RoInitialize failed, hr %#lx\n", hr ); + + test_Smbios_Statics(); + + RoUninitialize(); +} diff --git a/dlls/windows.system.profile.systemmanufacturers/windows.system.profile.systemmanufacturers.spec b/dlls/windows.system.profile.systemmanufacturers/windows.system.profile.systemmanufacturers.spec new file mode 100644 index 00000000000..31a5eafe950 --- /dev/null +++ b/dlls/windows.system.profile.systemmanufacturers/windows.system.profile.systemmanufacturers.spec @@ -0,0 +1,3 @@ +@ stdcall -private DllGetActivationFactory(ptr ptr) +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetClassObject(ptr ptr ptr)
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- .../main.c | 30 +++++++++++++++++++ .../tests/smbios.c | 7 +++++ 2 files changed, 37 insertions(+)
diff --git a/dlls/windows.system.profile.systemmanufacturers/main.c b/dlls/windows.system.profile.systemmanufacturers/main.c index 3f5e937392e..35b4529ad7a 100644 --- a/dlls/windows.system.profile.systemmanufacturers/main.c +++ b/dlls/windows.system.profile.systemmanufacturers/main.c @@ -36,6 +36,7 @@ static const char *debugstr_hstring( HSTRING hstr ) struct smbios_statics { IActivationFactory IActivationFactory_iface; + ISmbiosInformationStatics ISmbiosInformationStatics_iface; LONG ref; };
@@ -60,6 +61,13 @@ static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID return S_OK; }
+ if (IsEqualGUID( iid, &IID_ISmbiosInformationStatics )) + { + *out = &impl->ISmbiosInformationStatics_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); *out = NULL; return E_NOINTERFACE; @@ -118,9 +126,31 @@ static const struct IActivationFactoryVtbl factory_vtbl = factory_ActivateInstance, };
+DEFINE_IINSPECTABLE( statics, ISmbiosInformationStatics, struct smbios_statics, IActivationFactory_iface ) + +static HRESULT WINAPI statics_get_SerialNumber( ISmbiosInformationStatics *iface, HSTRING *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static const struct ISmbiosInformationStaticsVtbl statics_vtbl = +{ + statics_QueryInterface, + statics_AddRef, + statics_Release, + /* IInspectable methods */ + statics_GetIids, + statics_GetRuntimeClassName, + statics_GetTrustLevel, + /* ISmbiosInformationStatics methods */ + statics_get_SerialNumber, +}; + static struct smbios_statics smbios_statics = { {&factory_vtbl}, + {&statics_vtbl}, 1, };
diff --git a/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c b/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c index 628c5f689bc..a9cf1d2b6d8 100644 --- a/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c +++ b/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c @@ -45,6 +45,7 @@ static void check_interface_( unsigned int line, void *obj, const IID *iid ) static void test_Smbios_Statics(void) { static const WCHAR *smbios_statics_name = L"Windows.System.Profile.SystemManufacturers.SmbiosInformation"; + ISmbiosInformationStatics *smbios_statics; IActivationFactory *factory; HSTRING str; HRESULT hr; @@ -66,6 +67,12 @@ static void test_Smbios_Statics(void) check_interface( factory, &IID_IInspectable ); check_interface( factory, &IID_IAgileObject );
+ hr = IActivationFactory_QueryInterface( factory, &IID_ISmbiosInformationStatics, (void **)&smbios_statics ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + ref = ISmbiosInformationStatics_Release( smbios_statics ); + ok( ref == 2, "got ref %ld.\n", ref ); + ref = IActivationFactory_Release( factory ); ok( ref == 1, "got ref %ld.\n", ref ); }
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- .../tests/smbios.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c b/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c index a9cf1d2b6d8..4b9f51a8fa1 100644 --- a/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c +++ b/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c @@ -47,8 +47,10 @@ static void test_Smbios_Statics(void) static const WCHAR *smbios_statics_name = L"Windows.System.Profile.SystemManufacturers.SmbiosInformation"; ISmbiosInformationStatics *smbios_statics; IActivationFactory *factory; - HSTRING str; + HSTRING str, serial; + const WCHAR *buf; HRESULT hr; + UINT32 len; LONG ref;
hr = WindowsCreateString( smbios_statics_name, wcslen( smbios_statics_name ), &str ); @@ -70,6 +72,15 @@ static void test_Smbios_Statics(void) hr = IActivationFactory_QueryInterface( factory, &IID_ISmbiosInformationStatics, (void **)&smbios_statics ); ok( hr == S_OK, "got hr %#lx.\n", hr );
+ hr = ISmbiosInformationStatics_get_SerialNumber( smbios_statics, &serial ); + todo_wine ok( hr == S_OK || broken(hr == E_UNEXPECTED), "got hr %#lx.\n", hr ); + if (hr == S_OK) + { + buf = WindowsGetStringRawBuffer( serial, &len ); + todo_wine ok( buf != NULL && len > 0, "WindowsGetStringRawBuffer returned buf %p, len %u\n", buf, len ); + WindowsDeleteString(serial); + } + ref = ISmbiosInformationStatics_Release( smbios_statics ); ok( ref == 2, "got ref %ld.\n", ref );
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53747 --- .../main.c | 113 +++++++++++++++++- .../private.h | 38 ++++++ .../tests/smbios.c | 4 +- 3 files changed, 151 insertions(+), 4 deletions(-)
diff --git a/dlls/windows.system.profile.systemmanufacturers/main.c b/dlls/windows.system.profile.systemmanufacturers/main.c index 35b4529ad7a..c4fa36f5216 100644 --- a/dlls/windows.system.profile.systemmanufacturers/main.c +++ b/dlls/windows.system.profile.systemmanufacturers/main.c @@ -128,10 +128,119 @@ static const struct IActivationFactoryVtbl factory_vtbl =
DEFINE_IINSPECTABLE( statics, ISmbiosInformationStatics, struct smbios_statics, IActivationFactory_iface )
+static const struct smbios_header *find_smbios_entry( enum smbios_type type, const char *buf, UINT len ) +{ + const struct smbios_prologue *prologue; + const struct smbios_header *hdr; + const char *ptr, *start; + + if (len < sizeof(struct smbios_prologue)) return NULL; + prologue = (const struct smbios_prologue *)buf; + if (prologue->length > len - sizeof(*prologue) || prologue->length < sizeof(*hdr)) return NULL; + + start = (const char *)(prologue + 1); + hdr = (const struct smbios_header *)start; + + for (;;) + { + if ((const char *)hdr - start >= prologue->length - sizeof(*hdr)) return NULL; + + if (!hdr->length) + { + WARN( "invalid entry\n" ); + return NULL; + } + + if (hdr->type == type) + { + if ((const char *)hdr - start + hdr->length > prologue->length) return NULL; + break; + } + else /* skip other entries and their strings */ + { + for (ptr = (const char *)hdr + hdr->length; ptr - buf < len && *ptr; ptr++) + { + for (; ptr - buf < len; ptr++) if (!*ptr) break; + } + if (ptr == (const char *)hdr + hdr->length) ptr++; + hdr = (const struct smbios_header *)(ptr + 1); + } + } + + return hdr; +} + +static inline WCHAR *heap_strdupAW( const char *src ) +{ + WCHAR *dst; + int len; + if (!src) return NULL; + len = MultiByteToWideChar( CP_ACP, 0, src, -1, NULL, 0 ); + if ((dst = HeapAlloc( GetProcessHeap(), 0, len * sizeof(*dst) ))) MultiByteToWideChar( CP_ACP, 0, src, -1, dst, len ); + return dst; +} + +static WCHAR *get_smbios_string( BYTE id, const char *buf, UINT offset, UINT buflen ) +{ + const char *ptr = buf + offset; + UINT i = 0; + + if (!id || offset >= buflen) return NULL; + for (ptr = buf + offset; ptr - buf < buflen && *ptr; ptr++) + { + if (++i == id) return heap_strdupAW( ptr ); + for (; ptr - buf < buflen; ptr++) if (!*ptr) break; + } + return NULL; +} + +static WCHAR *get_bios_system_serial( const char *buf, UINT len ) +{ + const struct smbios_system *system; + const struct smbios_header *hdr; + UINT offset; + + if (!(hdr = find_smbios_entry( SMBIOS_TYPE_SYSTEM, buf, len ))) return NULL; + system = (const struct smbios_system *)hdr; + offset = (const char *)system - buf + system->hdr.length; + + return get_smbios_string( system->serial, buf, offset, len ); +} + static HRESULT WINAPI statics_get_SerialNumber( ISmbiosInformationStatics *iface, HSTRING *value ) { - FIXME( "iface %p, value %p stub!\n", iface, value ); - return E_NOTIMPL; + WCHAR *serial; + HSTRING ret; + HRESULT hr; + char *buf; + UINT len; + + TRACE( "iface %p, value %p.\n", iface, value ); + + len = GetSystemFirmwareTable( RSMB, 0, NULL, 0 ); + if (!(buf = HeapAlloc( GetProcessHeap(), 0, len ))) + { + ERR( "Failed to allocate firmware table buffer.\n" ); + hr = E_OUTOFMEMORY; + goto error; + } + len = GetSystemFirmwareTable( RSMB, 0, buf, len ); + + serial = get_bios_system_serial( buf, len ); + if (!serial) + { + WARN( "Failed to get serial number, returning 0.\n" ); + serial = heap_strdupAW("0"); + } + + if (FAILED( hr = WindowsCreateString( serial, wcslen(serial), &ret ) )) goto done; + hr = WindowsDuplicateString( ret, value ); + WindowsDeleteString(ret); +done: + HeapFree( GetProcessHeap(), 0, serial ); +error: + HeapFree( GetProcessHeap(), 0, buf ); + return hr; }
static const struct ISmbiosInformationStaticsVtbl statics_vtbl = diff --git a/dlls/windows.system.profile.systemmanufacturers/private.h b/dlls/windows.system.profile.systemmanufacturers/private.h index 42c19710dcb..f6a5420a3cf 100644 --- a/dlls/windows.system.profile.systemmanufacturers/private.h +++ b/dlls/windows.system.profile.systemmanufacturers/private.h @@ -30,6 +30,44 @@ #define WIDL_using_Windows_System_Profile_SystemManufacturers #include "windows.system.profile.systemmanufacturers.h"
+struct smbios_prologue +{ + BYTE calling_method; + BYTE major_version; + BYTE minor_version; + BYTE revision; + DWORD length; +}; + +enum smbios_type +{ + SMBIOS_TYPE_BIOS, + SMBIOS_TYPE_SYSTEM, + SMBIOS_TYPE_BASEBOARD, +}; + +struct smbios_header +{ + BYTE type; + BYTE length; + WORD handle; +}; + +struct smbios_system +{ + struct smbios_header hdr; + BYTE vendor; + BYTE product; + BYTE version; + BYTE serial; + BYTE uuid[16]; + BYTE wake_up_type; + BYTE sku_number; + BYTE family; +}; + +#define RSMB (('R' << 24) | ('S' << 16) | ('M' << 8) | 'B') + #define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \ static inline impl_type *impl_from( iface_type *iface ) \ { \ diff --git a/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c b/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c index 4b9f51a8fa1..c1baf71631e 100644 --- a/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c +++ b/dlls/windows.system.profile.systemmanufacturers/tests/smbios.c @@ -73,11 +73,11 @@ static void test_Smbios_Statics(void) ok( hr == S_OK, "got hr %#lx.\n", hr );
hr = ISmbiosInformationStatics_get_SerialNumber( smbios_statics, &serial ); - todo_wine ok( hr == S_OK || broken(hr == E_UNEXPECTED), "got hr %#lx.\n", hr ); + ok( hr == S_OK || broken(hr == E_UNEXPECTED), "got hr %#lx.\n", hr ); if (hr == S_OK) { buf = WindowsGetStringRawBuffer( serial, &len ); - todo_wine ok( buf != NULL && len > 0, "WindowsGetStringRawBuffer returned buf %p, len %u\n", buf, len ); + ok( buf != NULL && len > 0, "WindowsGetStringRawBuffer returned buf %p, len %u\n", buf, len ); WindowsDeleteString(serial); }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=126914
Your paranoid android.
=== w8 (32 bit report) ===
windows.system.profile.systemmanufacturers: 0a80:smbios: unhandled exception c0000005 at 68622D95
=== w8adm (32 bit report) ===
windows.system.profile.systemmanufacturers: 07fc:smbios: unhandled exception c0000005 at 71A82D95
=== w864 (32 bit report) ===
windows.system.profile.systemmanufacturers: 0b3c:smbios: unhandled exception c0000005 at 73D62D95
=== w864 (64 bit report) ===
windows.system.profile.systemmanufacturers: 0b0c:smbios: unhandled exception c0000005 at 00007FFDBE20368E
=== debian11 (32 bit report) ===
ntoskrnl.exe: driver_pnp.c:737: Test failed: expected IRP_MN_REMOVE_DEVICE
=== debian11b (32 bit WoW report) ===
windows.system.profile.systemmanufacturers: smbios.c:61: Test failed: got hr 0x80040154. smbios.c:64: Test failed: L"Windows.System.Profile.SystemManufacturers.SmbiosInformation" runtimeclass not registered, skipping tests.
Mohamad Al-Jaf (@maljaf) commented about dlls/windows.system.profile.systemmanufacturers/private.h:
- */
+#include <stdarg.h> +#include <stddef.h>
+#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winstring.h"
+#include "activation.h"
+#define WIDL_using_Windows_System_Profile_SystemManufacturers +#include "windows.system.profile.systemmanufacturers.h"
+#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \
This should probably be in the third patch, the `DEFINE_IINSPECTABLE_` I mean.
I'd suggest to test this with a real machine, to at least get some idea of what to expect.
Rémi Bernon (@rbernon) commented about dlls/windows.system.profile.systemmanufacturers/tests/smbios.c:
+{
- static const WCHAR *smbios_statics_name = L"Windows.System.Profile.SystemManufacturers.SmbiosInformation";
- IActivationFactory *factory;
- HSTRING str;
- HRESULT hr;
- LONG ref;
- hr = WindowsCreateString( smbios_statics_name, wcslen( smbios_statics_name ), &str );
- ok( hr == S_OK, "got hr %#lx.\n", hr );
- hr = RoGetActivationFactory( str, &IID_IActivationFactory, (void **)&factory );
- WindowsDeleteString( str );
- ok( hr == S_OK || broken( hr == REGDB_E_CLASSNOTREG ), "got hr %#lx.\n", hr );
- if (hr == REGDB_E_CLASSNOTREG)
- {
win_skip( "%s runtimeclass not registered, skipping tests.\n", wine_dbgstr_w( smbios_statics_name ));
You're missing a space between closing paren.
Rémi Bernon (@rbernon) commented about dlls/windows.system.profile.systemmanufacturers/tests/smbios.c:
hr = IActivationFactory_QueryInterface( factory, &IID_ISmbiosInformationStatics, (void **)&smbios_statics ); ok( hr == S_OK, "got hr %#lx.\n", hr );
- hr = ISmbiosInformationStatics_get_SerialNumber( smbios_statics, &serial );
- todo_wine ok( hr == S_OK || broken(hr == E_UNEXPECTED), "got hr %#lx.\n", hr );
- if (hr == S_OK)
- {
buf = WindowsGetStringRawBuffer( serial, &len );
todo_wine ok( buf != NULL && len > 0, "WindowsGetStringRawBuffer returned buf %p, len %u\n", buf, len );
WindowsDeleteString(serial);
Missing spaces in paren here too.
Rémi Bernon (@rbernon) commented about dlls/windows.system.profile.systemmanufacturers/main.c:
+}
static HRESULT WINAPI statics_get_SerialNumber( ISmbiosInformationStatics *iface, HSTRING *value ) {
- FIXME( "iface %p, value %p stub!\n", iface, value );
- return E_NOTIMPL;
- WCHAR *serial;
- HSTRING ret;
- HRESULT hr;
- char *buf;
- UINT len;
- TRACE( "iface %p, value %p.\n", iface, value );
- len = GetSystemFirmwareTable( RSMB, 0, NULL, 0 );
- if (!(buf = HeapAlloc( GetProcessHeap(), 0, len )))
Please don't use `HeapAlloc`, prefer standard C functions. Same goes elsewhere for `heap_` functions.
Rémi Bernon (@rbernon) commented about dlls/windows.system.profile.systemmanufacturers/main.c:
for (; ptr - buf < buflen; ptr++) if (!*ptr) break;
- }
- return NULL;
+}
+static WCHAR *get_bios_system_serial( const char *buf, UINT len ) +{
- const struct smbios_system *system;
- const struct smbios_header *hdr;
- UINT offset;
- if (!(hdr = find_smbios_entry( SMBIOS_TYPE_SYSTEM, buf, len ))) return NULL;
- system = (const struct smbios_system *)hdr;
- offset = (const char *)system - buf + system->hdr.length;
- return get_smbios_string( system->serial, buf, offset, len );
I'm quite sure we don't want to duplicate all this code here again, and instead build this on top of wbemprox. WinRT is mostly just a new restructured interface on top of existing modules.
There's also something strange going on when the DLL is registered, which needs to be sorted out.
The registered module path includes a `drivers` component (ie: `"DllPath"="C:\windows\system32\drivers\windows.system.profile.systemmanufacturers.dll"`), which I think is incorrect.
I think it also breaks the wow64 tests, running the 32bit tests in a 64bit prefix, somehow. I didn't investigate, but a wild guess would be that it's maybe because of the very long module name.
On Tue Nov 29 17:45:15 2022 +0000, Rémi Bernon wrote:
You're missing a space between closing paren.
Good catch, thanks.
On Tue Nov 29 17:45:18 2022 +0000, Rémi Bernon wrote:
Please don't use `HeapAlloc`, prefer standard C functions. Same goes elsewhere for `heap_` functions.
Right, I forgot Wine is shifting towards standard C memory allocation functions. What exactly is the benefit of doing this though?
On Tue Nov 29 17:45:19 2022 +0000, Rémi Bernon wrote:
I'm quite sure we don't want to duplicate all this code here again, and instead build this on top of wbemprox. WinRT is mostly just a new restructured interface on top of existing modules.
You're right, I was going to use wbemprox but saw that the serial number property was just a stub returning 0 and for some reason didn't think to fix it.
On Wed Nov 30 07:25:45 2022 +0000, Rémi Bernon wrote:
There's also something strange going on when the DLL is registered, which needs to be sorted out. The registered module path includes a `drivers` component (ie: `"DllPath"="C:\windows\system32\drivers\windows.system.profile.systemmanufacturers.dll"`), which I think is incorrect. I think it also breaks the wow64 tests, running the 32bit tests in a 64bit prefix, somehow. I didn't investigate, but a wild guess would be that it's maybe because of the very long module name.
You're referring to the debian11b VM, right? On my Arch machine it's registered correctly as `C:\windows\system32\windows.system.profile.systemmanufacturers.dll`. BTW, how did you discover this?
It's likely the long name, yeah. I have no idea how to fix it myself. Do you think it would be difficult?
On Wed Nov 30 07:25:56 2022 +0000, Bernhard Kölbl wrote:
I'd suggest to test this with a real machine, to at least get some idea of what to expect.
Yeah, I tested it on an old laptop with Windows 10 prior to submitting the draft. It returned the correct serial number when compared to the command `wmic bios get serialnumber`.
I also tested it on my current machine, which returns "To be filled by O.E.M" on Linux as well as on Windows with the wmic command. The test returned the same string.
I can't test it on Windows 8. Not sure what to do about the crashing tests.
Also, would you like to be added as a reviewer? If so, feel free to add yourself. I prefer having multiple reviewers anyway.