Needed for Minecraft Windows 10.
-- v2: windows.storage.applicationdata: Implement IApplicationDataStatics::get_Current(). windows.storage.applicationdata/tests: Add IApplicationDataStatics::get_Current() tests.
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- configure.ac | 2 + .../Makefile.in | 9 ++ .../applicationdata.c | 116 ++++++++++++++++++ .../classes.idl | 23 ++++ dlls/windows.storage.applicationdata/main.c | 46 +++++++ .../windows.storage.applicationdata/private.h | 40 ++++++ .../tests/Makefile.in | 5 + .../tests/data.c | 86 +++++++++++++ .../windows.storage.applicationdata.spec | 4 + 9 files changed, 331 insertions(+) create mode 100644 dlls/windows.storage.applicationdata/Makefile.in create mode 100644 dlls/windows.storage.applicationdata/applicationdata.c create mode 100644 dlls/windows.storage.applicationdata/classes.idl create mode 100644 dlls/windows.storage.applicationdata/main.c create mode 100644 dlls/windows.storage.applicationdata/private.h create mode 100644 dlls/windows.storage.applicationdata/tests/Makefile.in create mode 100644 dlls/windows.storage.applicationdata/tests/data.c create mode 100644 dlls/windows.storage.applicationdata/windows.storage.applicationdata.spec
diff --git a/configure.ac b/configure.ac index 7229e25dbed..de02bb888d6 100644 --- a/configure.ac +++ b/configure.ac @@ -3164,6 +3164,8 @@ WINE_CONFIG_MAKEFILE(dlls/windows.networking.hostname/tests) WINE_CONFIG_MAKEFILE(dlls/windows.networking) WINE_CONFIG_MAKEFILE(dlls/windows.perception.stub) WINE_CONFIG_MAKEFILE(dlls/windows.perception.stub/tests) +WINE_CONFIG_MAKEFILE(dlls/windows.storage.applicationdata) +WINE_CONFIG_MAKEFILE(dlls/windows.storage.applicationdata/tests) WINE_CONFIG_MAKEFILE(dlls/windows.system.profile.systemmanufacturers) WINE_CONFIG_MAKEFILE(dlls/windows.system.profile.systemmanufacturers/tests) WINE_CONFIG_MAKEFILE(dlls/windows.ui) diff --git a/dlls/windows.storage.applicationdata/Makefile.in b/dlls/windows.storage.applicationdata/Makefile.in new file mode 100644 index 00000000000..68a21908592 --- /dev/null +++ b/dlls/windows.storage.applicationdata/Makefile.in @@ -0,0 +1,9 @@ +MODULE = windows.storage.applicationdata.dll +IMPORTS = combase + +C_SRCS = \ + applicationdata.c \ + main.c + +IDL_SRCS = \ + classes.idl diff --git a/dlls/windows.storage.applicationdata/applicationdata.c b/dlls/windows.storage.applicationdata/applicationdata.c new file mode 100644 index 00000000000..3c70a63e94b --- /dev/null +++ b/dlls/windows.storage.applicationdata/applicationdata.c @@ -0,0 +1,116 @@ +/* WinRT Windows.Storage.ApplicationData ApplicationData Implementation + * + * Copyright (C) 2023 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 "private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(data); + +struct application_data_statics +{ + IActivationFactory IActivationFactory_iface; + LONG ref; +}; + +static inline struct application_data_statics *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct application_data_statics, IActivationFactory_iface ); +} + +static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct application_data_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 application_data_statics *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI factory_Release( IActivationFactory *iface ) +{ + struct application_data_statics *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p decreasing refcount to %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 application_data_statics application_data_statics = +{ + {&factory_vtbl}, + 1, +}; + +IActivationFactory *application_data_factory = &application_data_statics.IActivationFactory_iface; diff --git a/dlls/windows.storage.applicationdata/classes.idl b/dlls/windows.storage.applicationdata/classes.idl new file mode 100644 index 00000000000..b24def16f0f --- /dev/null +++ b/dlls/windows.storage.applicationdata/classes.idl @@ -0,0 +1,23 @@ +/* + * Runtime Classes for windows.storage.applicationdata.dll + * + * Copyright (C) 2023 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.storage.idl" diff --git a/dlls/windows.storage.applicationdata/main.c b/dlls/windows.storage.applicationdata/main.c new file mode 100644 index 00000000000..508ba0ddc66 --- /dev/null +++ b/dlls/windows.storage.applicationdata/main.c @@ -0,0 +1,46 @@ +/* WinRT Windows.Storage.ApplicationData Implementation + * + * Copyright (C) 2023 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(data); + +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 *buffer = WindowsGetStringRawBuffer( classid, NULL ); + + TRACE( "class %s, factory %p.\n", debugstr_hstring( classid ), factory ); + + *factory = NULL; + + if (!wcscmp( buffer, RuntimeClass_Windows_Storage_ApplicationData )) + IActivationFactory_QueryInterface( application_data_factory, &IID_IActivationFactory, (void **)factory ); + + if (*factory) return S_OK; + return CLASS_E_CLASSNOTAVAILABLE; +} diff --git a/dlls/windows.storage.applicationdata/private.h b/dlls/windows.storage.applicationdata/private.h new file mode 100644 index 00000000000..1bfaf012b85 --- /dev/null +++ b/dlls/windows.storage.applicationdata/private.h @@ -0,0 +1,40 @@ +/* WinRT Windows.Storage.ApplicationData Implementation + * + * Copyright (C) 2023 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 + */ + +#ifndef __WINE_WINDOWS_STORAGE_APPLICATIONDATA_PRIVATE_H +#define __WINE_WINDOWS_STORAGE_APPLICATIONDATA_PRIVATE_H + +#include <stdarg.h> + +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winstring.h" + +#include "activation.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#define WIDL_using_Windows_Storage +#include "windows.storage.h" + +extern IActivationFactory *application_data_factory; + +#endif diff --git a/dlls/windows.storage.applicationdata/tests/Makefile.in b/dlls/windows.storage.applicationdata/tests/Makefile.in new file mode 100644 index 00000000000..8f23f6e64d0 --- /dev/null +++ b/dlls/windows.storage.applicationdata/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = windows.storage.applicationdata.dll +IMPORTS = combase + +C_SRCS = \ + data.c diff --git a/dlls/windows.storage.applicationdata/tests/data.c b/dlls/windows.storage.applicationdata/tests/data.c new file mode 100644 index 00000000000..1e2a5383358 --- /dev/null +++ b/dlls/windows.storage.applicationdata/tests/data.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2023 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_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#define WIDL_using_Windows_Storage +#include "windows.storage.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_ApplicationDataStatics(void) +{ + static const WCHAR *application_data_statics_name = L"Windows.Storage.ApplicationData"; + IActivationFactory *factory; + HSTRING str; + HRESULT hr; + LONG ref; + + hr = WindowsCreateString( application_data_statics_name, wcslen( application_data_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( application_data_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(data) +{ + HRESULT hr; + + hr = RoInitialize( RO_INIT_MULTITHREADED ); + ok( hr == S_OK, "RoInitialize failed, hr %#lx\n", hr ); + + test_ApplicationDataStatics(); + + RoUninitialize(); +} diff --git a/dlls/windows.storage.applicationdata/windows.storage.applicationdata.spec b/dlls/windows.storage.applicationdata/windows.storage.applicationdata.spec new file mode 100644 index 00000000000..344b8e3a84a --- /dev/null +++ b/dlls/windows.storage.applicationdata/windows.storage.applicationdata.spec @@ -0,0 +1,4 @@ +@ stub CleanupTemporaryState +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetActivationFactory(ptr ptr) +@ stdcall -private DllGetClassObject(ptr ptr ptr)
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
--- .../applicationdata.c | 30 +++++++++++++++ .../windows.storage.applicationdata/private.h | 38 +++++++++++++++++++ .../tests/data.c | 6 +++ 3 files changed, 74 insertions(+)
diff --git a/dlls/windows.storage.applicationdata/applicationdata.c b/dlls/windows.storage.applicationdata/applicationdata.c index 3c70a63e94b..6296253eee1 100644 --- a/dlls/windows.storage.applicationdata/applicationdata.c +++ b/dlls/windows.storage.applicationdata/applicationdata.c @@ -25,6 +25,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(data); struct application_data_statics { IActivationFactory IActivationFactory_iface; + IApplicationDataStatics IApplicationDataStatics_iface; LONG ref; };
@@ -49,6 +50,13 @@ static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID return S_OK; }
+ if (IsEqualGUID( iid, &IID_IApplicationDataStatics )) + { + *out = &impl->IApplicationDataStatics_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); *out = NULL; return E_NOINTERFACE; @@ -107,9 +115,31 @@ static const struct IActivationFactoryVtbl factory_vtbl = factory_ActivateInstance, };
+DEFINE_IINSPECTABLE( application_data_statics, IApplicationDataStatics, struct application_data_statics, IActivationFactory_iface ) + +static HRESULT WINAPI application_data_statics_get_Current( IApplicationDataStatics *iface, IApplicationData **value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static const struct IApplicationDataStaticsVtbl application_data_statics_vtbl = +{ + application_data_statics_QueryInterface, + application_data_statics_AddRef, + application_data_statics_Release, + /* IInspectable methods */ + application_data_statics_GetIids, + application_data_statics_GetRuntimeClassName, + application_data_statics_GetTrustLevel, + /* IApplicationDataStatics methods */ + application_data_statics_get_Current, +}; + static struct application_data_statics application_data_statics = { {&factory_vtbl}, + {&application_data_statics_vtbl}, 1, };
diff --git a/dlls/windows.storage.applicationdata/private.h b/dlls/windows.storage.applicationdata/private.h index 1bfaf012b85..6eebc9b25be 100644 --- a/dlls/windows.storage.applicationdata/private.h +++ b/dlls/windows.storage.applicationdata/private.h @@ -37,4 +37,42 @@
extern IActivationFactory *application_data_factory;
+#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 ) + #endif diff --git a/dlls/windows.storage.applicationdata/tests/data.c b/dlls/windows.storage.applicationdata/tests/data.c index 1e2a5383358..4365671e63d 100644 --- a/dlls/windows.storage.applicationdata/tests/data.c +++ b/dlls/windows.storage.applicationdata/tests/data.c @@ -48,6 +48,7 @@ static void check_interface_( unsigned int line, void *obj, const IID *iid ) static void test_ApplicationDataStatics(void) { static const WCHAR *application_data_statics_name = L"Windows.Storage.ApplicationData"; + IApplicationDataStatics *application_data_statics; IActivationFactory *factory; HSTRING str; HRESULT hr; @@ -69,6 +70,11 @@ static void test_ApplicationDataStatics(void) check_interface( factory, &IID_IInspectable ); check_interface( factory, &IID_IAgileObject );
+ hr = IActivationFactory_QueryInterface( factory, &IID_IApplicationDataStatics, (void **)&application_data_statics ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + ref = IApplicationDataStatics_Release( application_data_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/application.c | 43 +++++++++++++++++++ .../tests/data.c | 7 +++ 2 files changed, 50 insertions(+)
diff --git a/dlls/windows.applicationmodel/tests/application.c b/dlls/windows.applicationmodel/tests/application.c index 426d0d526a0..3cfbc5b765d 100644 --- a/dlls/windows.applicationmodel/tests/application.c +++ b/dlls/windows.applicationmodel/tests/application.c @@ -55,6 +55,48 @@ static void check_interface_( unsigned int line, void *obj, const IID *iid ) IUnknown_Release( unk ); }
+static void test_ApplicationDataStatics(void) +{ + static const WCHAR *application_data_statics_name = L"Windows.Storage.ApplicationData"; + IApplicationDataStatics *application_data_statics; + IApplicationData *application_data; + IActivationFactory *factory; + HSTRING str; + HRESULT hr; + LONG ref; + + hr = WindowsCreateString( application_data_statics_name, wcslen( application_data_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( application_data_statics_name ) ); + return; + } + + check_interface( factory, &IID_IUnknown ); + check_interface( factory, &IID_IInspectable ); + check_interface( factory, &IID_IAgileObject ); + + hr = IActivationFactory_QueryInterface( factory, &IID_IApplicationDataStatics, (void **)&application_data_statics ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + + hr = IApplicationDataStatics_get_Current( application_data_statics, NULL ); + todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = IApplicationDataStatics_get_Current( application_data_statics, &application_data ); + todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); + todo_wine ok( application_data != NULL, "got NULL application_data %p.\n", application_data ); + if (application_data) IApplicationData_Release( application_data ); + + ref = IApplicationDataStatics_Release( application_data_statics ); + ok( ref == 2, "got ref %ld.\n", ref ); + ref = IActivationFactory_Release( factory ); + ok( ref == 1, "got ref %ld.\n", ref ); +} + static void test_PackageStatics(void) { static const WCHAR *package_statics_name = L"Windows.ApplicationModel.Package"; @@ -144,6 +186,7 @@ int main( int argc, char const *argv[] ) hr = RoInitialize( RO_INIT_MULTITHREADED ); ok( hr == S_OK, "RoInitialize failed, hr %#lx\n", hr );
+ test_ApplicationDataStatics(); test_PackageStatics();
RoUninitialize(); diff --git a/dlls/windows.storage.applicationdata/tests/data.c b/dlls/windows.storage.applicationdata/tests/data.c index 4365671e63d..ca0ea0e7eba 100644 --- a/dlls/windows.storage.applicationdata/tests/data.c +++ b/dlls/windows.storage.applicationdata/tests/data.c @@ -49,6 +49,7 @@ static void test_ApplicationDataStatics(void) { static const WCHAR *application_data_statics_name = L"Windows.Storage.ApplicationData"; IApplicationDataStatics *application_data_statics; + IApplicationData *application_data = NULL; IActivationFactory *factory; HSTRING str; HRESULT hr; @@ -73,6 +74,12 @@ static void test_ApplicationDataStatics(void) hr = IActivationFactory_QueryInterface( factory, &IID_IApplicationDataStatics, (void **)&application_data_statics ); ok( hr == S_OK, "got hr %#lx.\n", hr );
+ hr = IApplicationDataStatics_get_Current( application_data_statics, NULL ); + todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + hr = IApplicationDataStatics_get_Current( application_data_statics, &application_data ); + todo_wine ok( hr == 0x80073d54, "got hr %#lx.\n", hr ); + todo_wine ok( !application_data, "got application_data %p.\n", application_data ); + ref = IApplicationDataStatics_Release( application_data_statics ); ok( ref == 2, "got ref %ld.\n", ref ); ref = IActivationFactory_Release( factory );
From: Mohamad Al-Jaf mohamadaljaf@gmail.com
Needed for Minecraft Windows 10. --- .../tests/application.c | 9 +- .../applicationdata.c | 189 +++++++++++++++++- .../tests/data.c | 2 +- 3 files changed, 193 insertions(+), 7 deletions(-)
diff --git a/dlls/windows.applicationmodel/tests/application.c b/dlls/windows.applicationmodel/tests/application.c index 3cfbc5b765d..0b717089cf6 100644 --- a/dlls/windows.applicationmodel/tests/application.c +++ b/dlls/windows.applicationmodel/tests/application.c @@ -85,12 +85,13 @@ static void test_ApplicationDataStatics(void) ok( hr == S_OK, "got hr %#lx.\n", hr );
hr = IApplicationDataStatics_get_Current( application_data_statics, NULL ); - todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); hr = IApplicationDataStatics_get_Current( application_data_statics, &application_data ); - todo_wine ok( hr == S_OK, "got hr %#lx.\n", hr ); - todo_wine ok( application_data != NULL, "got NULL application_data %p.\n", application_data ); - if (application_data) IApplicationData_Release( application_data ); + ok( hr == S_OK, "got hr %#lx.\n", hr ); + ok( application_data != NULL, "got NULL application_data %p.\n", application_data );
+ ref = IApplicationData_Release( application_data ); + ok( ref == 1, "got ref %ld.\n", ref ); ref = IApplicationDataStatics_Release( application_data_statics ); ok( ref == 2, "got ref %ld.\n", ref ); ref = IActivationFactory_Release( factory ); diff --git a/dlls/windows.storage.applicationdata/applicationdata.c b/dlls/windows.storage.applicationdata/applicationdata.c index 6296253eee1..dbe42b3a8d6 100644 --- a/dlls/windows.storage.applicationdata/applicationdata.c +++ b/dlls/windows.storage.applicationdata/applicationdata.c @@ -115,14 +115,199 @@ static const struct IActivationFactoryVtbl factory_vtbl = factory_ActivateInstance, };
-DEFINE_IINSPECTABLE( application_data_statics, IApplicationDataStatics, struct application_data_statics, IActivationFactory_iface ) +struct application_data +{ + IApplicationData IApplicationData_iface; + LONG ref; +};
-static HRESULT WINAPI application_data_statics_get_Current( IApplicationDataStatics *iface, IApplicationData **value ) +static inline struct application_data *impl_from_IApplicationData( IApplicationData *iface ) +{ + return CONTAINING_RECORD( iface, struct application_data, IApplicationData_iface ); +} + +static HRESULT WINAPI application_data_QueryInterface( IApplicationData *iface, REFIID iid, void **out ) +{ + struct application_data *impl = impl_from_IApplicationData( 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_IApplicationData )) + { + *out = &impl->IApplicationData_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 application_data_AddRef( IApplicationData *iface ) +{ + struct application_data *impl = impl_from_IApplicationData( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p increasing refcount to %lu.\n", iface, ref ); + return ref; +} + +static ULONG WINAPI application_data_Release( IApplicationData *iface ) +{ + struct application_data *impl = impl_from_IApplicationData( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + + TRACE( "iface %p decreasing refcount to %lu.\n", iface, ref ); + + if (!ref) free( impl ); + return ref; +} + +static HRESULT WINAPI application_data_GetIids( IApplicationData *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 application_data_GetRuntimeClassName( IApplicationData *iface, HSTRING *class_name ) +{ + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_GetTrustLevel( IApplicationData *iface, TrustLevel *trust_level ) +{ + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_get_Version( IApplicationData *iface, UINT32 *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_SetVersionAsync( IApplicationData *iface, UINT32 version, IApplicationDataSetVersionHandler *handler, + IAsyncAction **operation ) +{ + FIXME( "iface %p, version %d, handler %p, operation %p stub!\n", iface, version, handler, operation ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_ClearAllAsync( IApplicationData *iface, IAsyncAction **operation ) +{ + FIXME( "iface %p, operation %p stub!\n", iface, operation ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_ClearAsync( IApplicationData *iface, ApplicationDataLocality locality, IAsyncAction **operation ) +{ + FIXME( "iface %p, %d locality, operation %p stub!\n", iface, locality, operation ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_get_LocalSettings( IApplicationData *iface, IApplicationDataContainer **value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_get_RoamingSettings( IApplicationData *iface, IApplicationDataContainer **value ) { FIXME( "iface %p, value %p stub!\n", iface, value ); return E_NOTIMPL; }
+static HRESULT WINAPI application_data_get_LocalFolder( IApplicationData *iface, IStorageFolder **value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_get_RoamingFolder( IApplicationData *iface, IStorageFolder **value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_get_TemporaryFolder( IApplicationData *iface, IStorageFolder **value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_add_DataChanged( IApplicationData *iface, ITypedEventHandler_ApplicationData_IInspectable *handler, + EventRegistrationToken *token ) +{ + FIXME( "iface %p, handler %p, token %p stub!\n", iface, handler, token ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_remove_DataChanged( IApplicationData *iface, EventRegistrationToken token ) +{ + FIXME( "iface %p, token %#I64x stub!\n", iface, token.value ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_SignalDataChanged( IApplicationData *iface ) +{ + FIXME( "iface %p stub!\n", iface ); + return E_NOTIMPL; +} + +static HRESULT WINAPI application_data_get_RoamingStorageQuota( IApplicationData *iface, UINT64 *value ) +{ + FIXME( "iface %p, value %p stub!\n", iface, value ); + return E_NOTIMPL; +} + +static const struct IApplicationDataVtbl application_data_vtbl = +{ + application_data_QueryInterface, + application_data_AddRef, + application_data_Release, + /* IInspectable methods */ + application_data_GetIids, + application_data_GetRuntimeClassName, + application_data_GetTrustLevel, + /* IApplicationData methods */ + application_data_get_Version, + application_data_SetVersionAsync, + application_data_ClearAllAsync, + application_data_ClearAsync, + application_data_get_LocalSettings, + application_data_get_RoamingSettings, + application_data_get_LocalFolder, + application_data_get_RoamingFolder, + application_data_get_TemporaryFolder, + application_data_add_DataChanged, + application_data_remove_DataChanged, + application_data_SignalDataChanged, + application_data_get_RoamingStorageQuota, +}; + +DEFINE_IINSPECTABLE( application_data_statics, IApplicationDataStatics, struct application_data_statics, IActivationFactory_iface ) + +static HRESULT WINAPI application_data_statics_get_Current( IApplicationDataStatics *iface, IApplicationData **value ) +{ + struct application_data *impl; + + TRACE( "iface %p, value %p\n", iface, value ); + + if (!value) return E_INVALIDARG; + if (!(impl = calloc( 1, sizeof(*impl) ))) return E_OUTOFMEMORY; + + impl->IApplicationData_iface.lpVtbl = &application_data_vtbl; + impl->ref = 1; + + *value = &impl->IApplicationData_iface; + TRACE( "created IApplicationData %p.\n", *value ); + return S_OK; +} + static const struct IApplicationDataStaticsVtbl application_data_statics_vtbl = { application_data_statics_QueryInterface, diff --git a/dlls/windows.storage.applicationdata/tests/data.c b/dlls/windows.storage.applicationdata/tests/data.c index ca0ea0e7eba..c735d7aebb0 100644 --- a/dlls/windows.storage.applicationdata/tests/data.c +++ b/dlls/windows.storage.applicationdata/tests/data.c @@ -75,7 +75,7 @@ static void test_ApplicationDataStatics(void) ok( hr == S_OK, "got hr %#lx.\n", hr );
hr = IApplicationDataStatics_get_Current( application_data_statics, NULL ); - todo_wine ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); + ok( hr == E_INVALIDARG, "got hr %#lx.\n", hr ); hr = IApplicationDataStatics_get_Current( application_data_statics, &application_data ); todo_wine ok( hr == 0x80073d54, "got hr %#lx.\n", hr ); todo_wine ok( !application_data, "got application_data %p.\n", application_data );
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=138167
Your paranoid android.
=== w8 (32 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w8adm (32 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w864 (32 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w1064v1507 (32 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w1064v1809 (32 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w1064_tsign (32 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w10pro64 (32 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w10pro64_en_AE_u8 (32 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w11pro64 (32 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w864 (64 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w1064v1507 (64 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w1064v1809 (64 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w1064_2qxl (64 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w1064_adm (64 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w1064_tsign (64 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w10pro64 (64 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w10pro64_ar (64 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w10pro64_ja (64 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w10pro64_zh_CN (64 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
=== w11pro64_amd (64 bit report) ===
windows.applicationmodel: Fatal: test 'application' does not exist.
On Fri Sep 29 07:18:56 2023 +0000, Rémi Bernon wrote:
At this point, you're leaking application_data on Windows. You should add the Release from the next commit there, with a if for Wine (though Wine doesn't really reach this point for the moment).
I'm confused, is it only on Windows that we care about leaks? On the Wine side in tests/data.c, it returns a non-NULL `application_data`, so wouldn't that leak in Wine? It's the same for `IPackageStatics_get_Current`.
On Mon Oct 2 02:58:37 2023 +0000, Mohamad Al-Jaf wrote:
I'm confused, is it only on Windows that we care about leaks? On the Wine side in tests/data.c, it returns a non-NULL `application_data`, so wouldn't that leak in Wine? It's the same for `IPackageStatics_get_Current`.
No, we care about leaks everywhere, I just missed the other one.