This fixes the crash when launching ClipStudioPaint.exe with Windows 10 compatiblity mode by adding the minimum required windows.ui and windows.storage definitions and stubs.
From: Ignacy Kuchciński ignacykuchcinski@gmail.com
--- include/Makefile.in | 2 + .../radialcontrollerconfigurationinterop.idl | 27 ++++++++ include/radialcontrollerinterop.idl | 27 ++++++++ include/windows.ui.input.idl | 63 +++++++++++++++++++ 4 files changed, 119 insertions(+) create mode 100644 include/radialcontrollerconfigurationinterop.idl create mode 100644 include/radialcontrollerinterop.idl
diff --git a/include/Makefile.in b/include/Makefile.in index 650d69815f8..cb2c12fef7f 100644 --- a/include/Makefile.in +++ b/include/Makefile.in @@ -663,6 +663,8 @@ SOURCES = \ pstore.idl \ qedit.idl \ qos2.h \ + radialcontrollerinterop.idl \ + radialcontrollerconfigurationinterop.idl \ ras.h \ rasdlg.h \ raserror.h \ diff --git a/include/radialcontrollerconfigurationinterop.idl b/include/radialcontrollerconfigurationinterop.idl new file mode 100644 index 00000000000..3d427b9f3ab --- /dev/null +++ b/include/radialcontrollerconfigurationinterop.idl @@ -0,0 +1,27 @@ +/* + * Copyright 2025 Ignacy Kuchciński + * + * 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 + */ + +import "inspectable.idl"; + +[ + uuid(787cdaac-3186-476d-87e4-b9374a7b9970) +] +interface IRadialControllerConfigurationInterop : IInspectable +{ + HRESULT GetForWindow([in] HWND window, [in] REFIID riid, [out, retval, iid_is(riid)] void **radialcontrollerconfiguration); +} diff --git a/include/radialcontrollerinterop.idl b/include/radialcontrollerinterop.idl new file mode 100644 index 00000000000..d5ba5f54922 --- /dev/null +++ b/include/radialcontrollerinterop.idl @@ -0,0 +1,27 @@ +/* + * Copyright 2025 Ignacy Kuchciński + * + * 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 + */ + +import "inspectable.idl"; + +[ + uuid(1b0535c9-57ad-45c1-9d79-ad5c34360513) +] +interface IRadialControllerInterop : IInspectable +{ + HRESULT GetForWindow([in] HWND window, [in] REFIID riid, [out, retval, iid_is(riid)] void **radialcontroller); +} diff --git a/include/windows.ui.input.idl b/include/windows.ui.input.idl index f160671f232..256d8bc243a 100644 --- a/include/windows.ui.input.idl +++ b/include/windows.ui.input.idl @@ -40,9 +40,17 @@ namespace Windows.UI.Input { interface IPointerPointStatics; interface IPointerPointTransform;
+ interface IRadialControllerConfigurationStatics; + interface IRadialControllerMenuItemStatics; + interface IRadialControllerStatics; + runtimeclass PointerPoint; runtimeclass PointerPointProperties;
+ runtimeclass RadialController; + runtimeclass RadialControllerConfiguration; + runtimeclass RadialControllerMenuItem; + declare { interface Windows.Foundation.Collections.IVectorView<Windows.UI.Input.PointerPoint *>; interface Windows.Foundation.Collections.IVector<Windows.UI.Input.PointerPoint *>; @@ -150,6 +158,33 @@ namespace Windows.UI.Input { HRESULT TransformBounds([in] Windows.Foundation.Rect rect, [out, retval] Windows.Foundation.Rect *value); }
+ [ + contract(Windows.Foundation.UniversalApiContract, 3.0), + exclusiveto(Windows.UI.Input.RadialControllerConfiguration), + uuid(79b6b0e5-069a-4486-a99d-8db772b9642f) + ] + interface IRadialControllerConfigurationStatics : IInspectable + { + } + + [ + contract(Windows.Foundation.UniversalApiContract, 3.0), + exclusiveto(Windows.UI.Input.RadialControllerMenuItem), + uuid(249e0887-d842-4524-9df8-e0d647edc887) + ] + interface IRadialControllerMenuItemStatics : IInspectable + { + } + + [ + contract(Windows.Foundation.UniversalApiContract, 3.0), + exclusiveto(Windows.UI.Input.RadialController), + uuid(faded0b7-b84c-4894-87aa-8f25aa5f288b) + ] + interface IRadialControllerStatics : IInspectable + { + } + [ contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(none), @@ -169,4 +204,32 @@ namespace Windows.UI.Input { [default] interface Windows.UI.Input.IPointerPointProperties; [contract(Windows.Foundation.UniversalApiContract, 1.0)] interface Windows.UI.Input.IPointerPointProperties2; } + + [ + static(Windows.UI.Input.IRadialControllerStatics, Windows.Foundation.UniversalApiContract, 3.0), + contract(Windows.Foundation.UniversalApiContract, 3.0), + marshaling_behavior(agile) + ] + runtimeclass RadialController + { + } + + [ + static(Windows.UI.Input.IRadialControllerConfigurationStatics, Windows.Foundation.UniversalApiContract, 3.0), + contract(Windows.Foundation.UniversalApiContract, 3.0), + marshaling_behavior(agile) + ] + runtimeclass RadialControllerConfiguration + { + } + + + [ + static(Windows.UI.Input.IRadialControllerMenuItemStatics, Windows.Foundation.UniversalApiContract, 3.0), + contract(Windows.Foundation.UniversalApiContract, 3.0), + marshaling_behavior(agile) + ] + runtimeclass RadialControllerMenuItem + { + } }
From: Ignacy Kuchciński ignacykuchcinski@gmail.com
--- dlls/windows.ui/Makefile.in | 3 + dlls/windows.ui/main.c | 9 + dlls/windows.ui/private.h | 5 + dlls/windows.ui/radialcontroller.c | 179 ++++++++++++++++++ .../radialcontrollerconfiguration.c | 179 ++++++++++++++++++ dlls/windows.ui/radialcontrollermenuitem.c | 143 ++++++++++++++ 6 files changed, 518 insertions(+) create mode 100644 dlls/windows.ui/radialcontroller.c create mode 100644 dlls/windows.ui/radialcontrollerconfiguration.c create mode 100644 dlls/windows.ui/radialcontrollermenuitem.c
diff --git a/dlls/windows.ui/Makefile.in b/dlls/windows.ui/Makefile.in index e88a40188b1..efd4871f434 100644 --- a/dlls/windows.ui/Makefile.in +++ b/dlls/windows.ui/Makefile.in @@ -5,6 +5,9 @@ SOURCES = \ classes.idl \ inputpane.c \ main.c \ + radialcontroller.c \ + radialcontrollerconfiguration.c \ + radialcontrollermenuitem.c \ uisettings.c \ uiviewsettings.c \ weakref.c diff --git a/dlls/windows.ui/main.c b/dlls/windows.ui/main.c index 87b8f87561a..d61c1a7e1d6 100644 --- a/dlls/windows.ui/main.c +++ b/dlls/windows.ui/main.c @@ -38,6 +38,15 @@ HRESULT WINAPI DllGetActivationFactory( HSTRING classid, IActivationFactory **fa
*factory = NULL;
+ if (!wcscmp( buffer, RuntimeClass_Windows_UI_Input_RadialController )) + IActivationFactory_QueryInterface( radialcontroller_factory, &IID_IActivationFactory, (void **)factory ); + + if (!wcscmp( buffer, RuntimeClass_Windows_UI_Input_RadialControllerConfiguration )) + IActivationFactory_QueryInterface( radialcontrollerconfiguration_factory, &IID_IActivationFactory, (void **)factory ); + + if (!wcscmp( buffer, RuntimeClass_Windows_UI_Input_RadialControllerMenuItem )) + IActivationFactory_QueryInterface( radialcontrollermenuitem_factory, &IID_IActivationFactory, (void **)factory ); + if (!wcscmp( buffer, RuntimeClass_Windows_UI_ViewManagement_UISettings )) IActivationFactory_QueryInterface( uisettings_factory, &IID_IActivationFactory, (void **)factory );
diff --git a/dlls/windows.ui/private.h b/dlls/windows.ui/private.h index 6e611e5d5d3..e11cfc40523 100644 --- a/dlls/windows.ui/private.h +++ b/dlls/windows.ui/private.h @@ -33,9 +33,14 @@ #include "windows.foundation.h" #define WIDL_using_Windows_UI #include "windows.ui.h" +#define WIDL_using_Windows_UI_Input +#include "windows.ui.input.h" #define WIDL_using_Windows_UI_ViewManagement #include "windows.ui.viewmanagement.h"
+extern IActivationFactory *radialcontroller_factory; +extern IActivationFactory *radialcontrollerconfiguration_factory; +extern IActivationFactory *radialcontrollermenuitem_factory; extern IActivationFactory *uisettings_factory; extern IActivationFactory *uiviewsettings_factory; extern IActivationFactory *inputpane_factory; diff --git a/dlls/windows.ui/radialcontroller.c b/dlls/windows.ui/radialcontroller.c new file mode 100644 index 00000000000..d7ed09f44cf --- /dev/null +++ b/dlls/windows.ui/radialcontroller.c @@ -0,0 +1,179 @@ +/* WinRT Windows.UI Implementation + * + * Copyright (C) 2025 Ignacy Kuchciński + * + * 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 "initguid.h" +#include "radialcontrollerinterop.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ui); + +struct radialcontroller_statics +{ + IActivationFactory IActivationFactory_iface; + IRadialControllerInterop IRadialControllerInterop_iface; + IRadialControllerStatics IRadialControllerStatics_iface; + LONG ref; +}; + +static inline struct radialcontroller_statics *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct radialcontroller_statics, IActivationFactory_iface ); +} + +static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct radialcontroller_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_IActivationFactory )) + { + *out = &impl->IActivationFactory_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + else if (IsEqualGUID( iid, &IID_IRadialControllerInterop)) + { + *out = &impl->IRadialControllerInterop_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + else if (IsEqualGUID( iid, &IID_IRadialControllerStatics )) + { + *out = &impl->IRadialControllerStatics_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 radialcontroller_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 radialcontroller_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_name %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, +}; + +DEFINE_IINSPECTABLE( radialcontroller_interop, IRadialControllerInterop, struct radialcontroller_statics, IActivationFactory_iface ); + +static HRESULT WINAPI radialcontroller_interop_GetForWindow( IRadialControllerInterop *iface, HWND window, REFIID riid, void **radialcontroller ) +{ + struct radialcontroller_statics *impl = impl_from_IRadialControllerInterop ( iface ); + + TRACE( "(window %p, riid %s, radialcontroller %p)\n", window, debugstr_guid( riid ), radialcontroller ); + + factory_ActivateInstance( &impl->IActivationFactory_iface, (IInspectable **)radialcontroller ); + return S_OK; +} + +static const struct IRadialControllerInteropVtbl radialcontroller_interop_vtbl = +{ + radialcontroller_interop_QueryInterface, + radialcontroller_interop_AddRef, + radialcontroller_interop_Release, + + /* IInspectable methods */ + radialcontroller_interop_GetIids, + radialcontroller_interop_GetRuntimeClassName, + radialcontroller_interop_GetTrustLevel, + + /* IRadialControllerInterop methods */ + radialcontroller_interop_GetForWindow, +}; + +DEFINE_IINSPECTABLE( radialcontroller_statics, IRadialControllerStatics, struct radialcontroller_statics, IActivationFactory_iface ); + +static const struct IRadialControllerStaticsVtbl radialcontroller_statics_vtbl = +{ + radialcontroller_statics_QueryInterface, + radialcontroller_statics_AddRef, + radialcontroller_statics_Release, + + /* IInspectable methods */ + radialcontroller_statics_GetIids, + radialcontroller_statics_GetRuntimeClassName, + radialcontroller_statics_GetTrustLevel, + + /* IRadialControllerStatics methods */ +}; + +static struct radialcontroller_statics radialcontroller_statics = +{ + {&factory_vtbl}, + {&radialcontroller_interop_vtbl}, + {&radialcontroller_statics_vtbl}, + 1, +}; + +IActivationFactory *radialcontroller_factory = &radialcontroller_statics.IActivationFactory_iface; diff --git a/dlls/windows.ui/radialcontrollerconfiguration.c b/dlls/windows.ui/radialcontrollerconfiguration.c new file mode 100644 index 00000000000..1f0342bed11 --- /dev/null +++ b/dlls/windows.ui/radialcontrollerconfiguration.c @@ -0,0 +1,179 @@ +/* WinRT Windows.UI Implementation + * + * Copyright (C) 2025 Ignacy Kuchciński + * + * 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 "initguid.h" +#include "radialcontrollerconfigurationinterop.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ui); + +struct radialcontrollerconfiguration_statics +{ + IActivationFactory IActivationFactory_iface; + IRadialControllerConfigurationInterop IRadialControllerConfigurationInterop_iface; + IRadialControllerConfigurationStatics IRadialControllerConfigurationStatics_iface; + LONG ref; +}; + +static inline struct radialcontrollerconfiguration_statics *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct radialcontrollerconfiguration_statics, IActivationFactory_iface ); +} + +static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct radialcontrollerconfiguration_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_IActivationFactory )) + { + *out = &impl->IActivationFactory_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + else if (IsEqualGUID( iid, &IID_IRadialControllerConfigurationInterop )) + { + *out = &impl->IRadialControllerConfigurationInterop_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + else if (IsEqualGUID( iid, &IID_IRadialControllerConfigurationStatics )) + { + *out = &impl->IRadialControllerConfigurationStatics_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 radialcontrollerconfiguration_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 radialcontrollerconfiguration_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_name %p stub!\n", iface, trust_level ); + return E_NOTIMPL; +} + +static HRESULT WINAPI factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance ) +{ + FIXME( "iface %p, instance %p.\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, +}; + +DEFINE_IINSPECTABLE( radialcontrollerconfiguration_interop, IRadialControllerConfigurationInterop, struct radialcontrollerconfiguration_statics, IActivationFactory_iface ); + +static HRESULT WINAPI radialcontrollerconfiguration_interop_GetForWindow( IRadialControllerConfigurationInterop *iface, HWND window, REFIID riid, void **radialcontrollerconfiguration ) +{ + struct radialcontrollerconfiguration_statics *impl = impl_from_IRadialControllerConfigurationInterop ( iface ); + + TRACE( "(window %p, riid %s, radialcontrollerconfiguration %p)\n", window, debugstr_guid( riid ), radialcontrollerconfiguration ); + + factory_ActivateInstance( &impl->IActivationFactory_iface, (IInspectable **)radialcontrollerconfiguration ); + return S_OK; +} + +static const struct IRadialControllerConfigurationInteropVtbl radialcontrollerconfiguration_interop_vtbl = +{ + radialcontrollerconfiguration_interop_QueryInterface, + radialcontrollerconfiguration_interop_AddRef, + radialcontrollerconfiguration_interop_Release, + + /* IInspectable methods */ + radialcontrollerconfiguration_interop_GetIids, + radialcontrollerconfiguration_interop_GetRuntimeClassName, + radialcontrollerconfiguration_interop_GetTrustLevel, + + /* IRadialControllerConfigurationInterop methods */ + radialcontrollerconfiguration_interop_GetForWindow, +}; + +DEFINE_IINSPECTABLE( radialcontrollerconfiguration_statics, IRadialControllerConfigurationStatics, struct radialcontrollerconfiguration_statics, IActivationFactory_iface ); + +static const struct IRadialControllerConfigurationStaticsVtbl radialcontrollerconfiguration_statics_vtbl = +{ + radialcontrollerconfiguration_statics_QueryInterface, + radialcontrollerconfiguration_statics_AddRef, + radialcontrollerconfiguration_statics_Release, + + /* IInspectable methods */ + radialcontrollerconfiguration_statics_GetIids, + radialcontrollerconfiguration_statics_GetRuntimeClassName, + radialcontrollerconfiguration_statics_GetTrustLevel, + + /* IRadialControllerConfigurationStatics methods */ +}; + +static struct radialcontrollerconfiguration_statics radialcontrollerconfiguration_statics = +{ + {&factory_vtbl}, + {&radialcontrollerconfiguration_interop_vtbl}, + {&radialcontrollerconfiguration_statics_vtbl}, + 1, +}; + +IActivationFactory *radialcontrollerconfiguration_factory = &radialcontrollerconfiguration_statics.IActivationFactory_iface; diff --git a/dlls/windows.ui/radialcontrollermenuitem.c b/dlls/windows.ui/radialcontrollermenuitem.c new file mode 100644 index 00000000000..f679f975f54 --- /dev/null +++ b/dlls/windows.ui/radialcontrollermenuitem.c @@ -0,0 +1,143 @@ +/* WinRT Windows.UI Implementation + * + * Copyright (C) 2025 Ignacy Kuchciński + * + * 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 "initguid.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(ui); + +struct radialcontrollermenuitem_statics +{ + IActivationFactory IActivationFactory_iface; + IRadialControllerMenuItemStatics IRadialControllerMenuItemStatics_iface; + LONG ref; +}; + +static inline struct radialcontrollermenuitem_statics *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct radialcontrollermenuitem_statics, IActivationFactory_iface ); +} + +static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct radialcontrollermenuitem_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_IActivationFactory )) + { + *out = &impl->IActivationFactory_iface; + IInspectable_AddRef( *out ); + return S_OK; + } + else if (IsEqualGUID( iid, &IID_IRadialControllerMenuItemStatics )) + { + *out = &impl->IRadialControllerMenuItemStatics_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 radialcontrollermenuitem_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 radialcontrollermenuitem_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_name %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, +}; + +DEFINE_IINSPECTABLE( radialcontrollermenuitem_statics, IRadialControllerMenuItemStatics, struct radialcontrollermenuitem_statics, IActivationFactory_iface ); + +static const struct IRadialControllerMenuItemStaticsVtbl radialcontrollermenuitem_statics_vtbl = +{ + radialcontrollermenuitem_statics_QueryInterface, + radialcontrollermenuitem_statics_AddRef, + radialcontrollermenuitem_statics_Release, + + /* IInspectable methods */ + radialcontrollermenuitem_statics_GetIids, + radialcontrollermenuitem_statics_GetRuntimeClassName, + radialcontrollermenuitem_statics_GetTrustLevel, + + /* IRadialControllerMenuItemStatics methods */ +}; + +static struct radialcontrollermenuitem_statics radialcontrollermenuitem_statics = +{ + {&factory_vtbl}, + {&radialcontrollermenuitem_statics_vtbl}, + 1, +}; + +IActivationFactory *radialcontrollermenuitem_factory = &radialcontrollermenuitem_statics.IActivationFactory_iface;
From: Ignacy Kuchciński ignacykuchcinski@gmail.com
--- include/windows.storage.idl | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)
diff --git a/include/windows.storage.idl b/include/windows.storage.idl index 483fc5a957e..ac36265aad0 100644 --- a/include/windows.storage.idl +++ b/include/windows.storage.idl @@ -64,12 +64,14 @@ namespace Windows.Storage { interface IStorageFileStatics; interface IStorageFileStatics2; interface IStorageItem; + interface IStreamedFileDataRequest;
runtimeclass ApplicationData; runtimeclass ApplicationDataContainer; runtimeclass KnownFolders; runtimeclass SetVersionDeferral; runtimeclass SetVersionRequest; + runtimeclass StreamedFileDataRequest; runtimeclass StorageFolder; runtimeclass StorageFile; runtimeclass StorageStreamTransaction; @@ -239,6 +241,12 @@ namespace Windows.Storage { ] delegate HRESULT ApplicationDataSetVersionHandler([in] Windows.Storage.SetVersionRequest *version);
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + uuid(fef6a824-2fe1-4d07-a35b-b77c50b5f4cc) + ] + delegate HRESULT StreamedFileDataRequestedHandler([in] Windows.Storage.StreamedFileDataRequest *stream); + [ contract(Windows.Foundation.UniversalApiContract, 1.0), exclusiveto(Windows.Storage.ApplicationData), @@ -512,6 +520,21 @@ namespace Windows.Storage { HRESULT MoveAndReplaceAsync([in] Windows.Storage.IStorageFile *file, [out, retval] Windows.Foundation.IAsyncAction **operation); }
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Storage.StorageFile), + uuid(5984c710-daf2-43c8-8bb4-a4d3eacfd03f) + ] + interface IStorageFileStatics : IInspectable + { + HRESULT CreateStreamedFileAsync( + [in] HSTRING display_name_with_extensions, + [in] Windows.Storage.StreamedFileDataRequestedHandler *data_requested, + [in] Windows.Storage.Streams.IRandomAccessStreamReference *thumbnail, + [out, retval] Windows.Foundation.IAsyncOperation<Windows.Storage.StorageFile *> **operation + ); + } + [ contract(Windows.Foundation.UniversalApiContract, 1.0), uuid(72d1cb78-b3ef-4f75-a80b-6fd9dae2944b) @@ -650,6 +673,14 @@ namespace Windows.Storage { [default] interface Windows.Storage.ISetVersionRequest; }
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + ] + runtimeclass StreamedFileDataRequest + { + [default] interface Windows.Storage.IStreamedFileDataRequest; + } + [ contract(Windows.Foundation.UniversalApiContract, 1.0), static(Windows.Storage.IStorageFileStatics, Windows.Foundation.UniversalApiContract, 1.0),
From: Ignacy Kuchciński ignacykuchcinski@gmail.com
--- dlls/windows.storage/Makefile.in | 1 + dlls/windows.storage/main.c | 3 + dlls/windows.storage/private.h | 1 + dlls/windows.storage/storagefile.c | 152 +++++++++++++++++++++++++++++ 4 files changed, 157 insertions(+) create mode 100644 dlls/windows.storage/storagefile.c
diff --git a/dlls/windows.storage/Makefile.in b/dlls/windows.storage/Makefile.in index 050b31cac25..2345d1617f1 100644 --- a/dlls/windows.storage/Makefile.in +++ b/dlls/windows.storage/Makefile.in @@ -4,4 +4,5 @@ IMPORTS = combase SOURCES = \ classes.idl \ main.c \ + storagefile.c \ streams.c diff --git a/dlls/windows.storage/main.c b/dlls/windows.storage/main.c index 390f2dec742..dbfe1bde20e 100644 --- a/dlls/windows.storage/main.c +++ b/dlls/windows.storage/main.c @@ -36,6 +36,9 @@ HRESULT WINAPI DllGetActivationFactory( HSTRING classid, IActivationFactory **fa
*factory = NULL;
+ if (!wcscmp( buffer, RuntimeClass_Windows_Storage_StorageFile )) + IActivationFactory_QueryInterface( storagefile_factory, &IID_IActivationFactory, (void **)factory ); + if (!wcscmp( buffer, RuntimeClass_Windows_Storage_Streams_RandomAccessStreamReference )) IActivationFactory_QueryInterface( random_access_stream_reference_factory, &IID_IActivationFactory, (void **)factory );
diff --git a/dlls/windows.storage/private.h b/dlls/windows.storage/private.h index 62c9d226d07..48a5b3146bf 100644 --- a/dlls/windows.storage/private.h +++ b/dlls/windows.storage/private.h @@ -39,6 +39,7 @@ #include "windows.storage.h" #include "windows.storage.streams.h"
+extern IActivationFactory *storagefile_factory; extern IActivationFactory *random_access_stream_reference_factory;
#define DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from, iface_mem, expr ) \ diff --git a/dlls/windows.storage/storagefile.c b/dlls/windows.storage/storagefile.c new file mode 100644 index 00000000000..7aa63efb732 --- /dev/null +++ b/dlls/windows.storage/storagefile.c @@ -0,0 +1,152 @@ +/* WinRT Windows.Storage Implementation + * + * Copyright (C) 2025 Ignacy Kuchciński + * + * 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 "initguid.h" + +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(storage); + +struct storagefile_statics +{ + IActivationFactory IActivationFactory_iface; + IStorageFileStatics IStorageFileStatics_iface; + LONG ref; +}; + +static inline struct storagefile_statics *impl_from_IActivationFactory( IActivationFactory *iface ) +{ + return CONTAINING_RECORD( iface, struct storagefile_statics, IActivationFactory_iface ); +} + +static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) +{ + struct storagefile_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; + } + + if (IsEqualGUID( iid, &IID_IStorageFileStatics )) + { + *out = &impl->IStorageFileStatics_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 storagefile_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 storagefile_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, +}; + +DEFINE_IINSPECTABLE( storagefile_statics, IStorageFileStatics, struct storagefile_statics, IActivationFactory_iface ) + +static HRESULT WINAPI storagefile_statics_CreateStreamedFileAsync( IStorageFileStatics *iface, + HSTRING display_name_with_extensions, + IStreamedFileDataRequestedHandler *data_requested, + IRandomAccessStreamReference *thumbnail, + IAsyncOperation_StorageFile **operation ) +{ + FIXME( "iface %p, display_name_with_extensions %p, data_requested %p, thumbnail %p, operation %p stub!\n", iface,display_name_with_extensions, data_requested, thumbnail, operation ); + return E_NOTIMPL; +} + +static const struct IStorageFileStaticsVtbl storagefile_statics_vtbl = +{ + storagefile_statics_QueryInterface, + storagefile_statics_AddRef, + storagefile_statics_Release, + /* IInspectable methods */ + storagefile_statics_GetIids, + storagefile_statics_GetRuntimeClassName, + storagefile_statics_GetTrustLevel, + /* IStorageFileStatics methods */ + storagefile_statics_CreateStreamedFileAsync, +}; + +static struct storagefile_statics storagefile_statics = +{ + {&factory_vtbl}, + {&storagefile_statics_vtbl}, + 0, +}; + +IActivationFactory *storagefile_factory = &storagefile_statics.IActivationFactory_iface;
From: Ignacy Kuchciński ignacykuchcinski@gmail.com
--- dlls/combase/roapi.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/combase/roapi.c b/dlls/combase/roapi.c index df3a3c5c176..0585ddb1758 100644 --- a/dlls/combase/roapi.c +++ b/dlls/combase/roapi.c @@ -167,6 +167,11 @@ HRESULT WINAPI DECLSPEC_HOTPATCH RoGetActivationFactory(HSTRING classid, REFIID return hr; }
+ if (strcmp(debugstr_hstring(classid), "L"Windows.Storage.StorageFile"") == 0) + { + library = L"C:\windows\system32\windows.storage.dll"; + } + if (!(module = LoadLibraryW(library))) { ERR("Failed to load module %s\n", debugstr_w(library));
Ignacy Kuchciński (@ignapk) commented about dlls/combase/roapi.c:
return hr; }
- if (strcmp(debugstr_hstring(classid), "L"Windows.Storage.StorageFile"") == 0)
- {
library = L"C:\\windows\\system32\\windows.storage.dll";
- }
Without this temporary fix, following error occurs:
``` 02dc:fixme:combase:RoGetActivationFactory (L"Windows.Storage.StorageFile", {5984c710-daf2-43c8-8bb4-a4d3eacfd03f}, 00006FFFF25BB468): semi-stub 02dc:trace:combase:RoGetActivationFactory Found library L"C:\windows\system32\windows.storage.applicationdata.dll" for class L"Windows.Storage.StorageFile" 02dc:err:combase:RoGetActivationFactory Class L"Windows.Storage.StorageFile" not found in L"C:\windows\system32\windows.storage.applicationdata.dll", hr 0x80040111. ```
This should be figured out and the commit should be dropped afterwards
On Sat Jun 21 15:58:10 2025 +0000, Ignacy Kuchciński wrote:
Without this temporary fix, following error occurs:
02dc:fixme:combase:RoGetActivationFactory (L"Windows.Storage.StorageFile", {5984c710-daf2-43c8-8bb4-a4d3eacfd03f}, 00006FFFF25BB468): semi-stub 02dc:trace:combase:RoGetActivationFactory Found library L"C:\\windows\\system32\\windows.storage.applicationdata.dll" for class L"Windows.Storage.StorageFile" 02dc:err:combase:RoGetActivationFactory Class L"Windows.Storage.StorageFile" not found in L"C:\\windows\\system32\\windows.storage.applicationdata.dll", hr 0x80040111.
This should be figured out and the commit should be dropped afterwards
The class is defined here: https://gitlab.winehq.org/wine/wine/-/blob/master/include/windows.storage.id...
But is never imported into `windows.storage.dll` but is imported into `windows.storage.applicationdata.dll` (Check for `windows.storage.idl` in `Makefile.in` and `classes.idl`) - https://gitlab.winehq.org/wine/wine/-/tree/master/dlls/windows.storage?ref_t... - https://gitlab.winehq.org/wine/wine/-/tree/master/dlls/windows.storage.appli...
`Windows.Storage.StorageFile` should be in `windows.storage.applicationdata.dll` and not `windows.storage.dll` according to wine source code.
So `windows.storage: Add stubs for StorageFile class.` should be `windows.storage.applicationdata: Add stubs for StorageFile class.` instead.
I don't currently have a Windows VM setup to check in which dll the class is actually located on Windows, but if you want to check, the registry key to check with regedit is: - `HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsRuntime\ActivatableClassId\Windows.Storage.StorageFile`
On Sun Jun 22 10:03:43 2025 +0000, Loïc Rebmeister wrote:
The class is defined here: https://gitlab.winehq.org/wine/wine/-/blob/master/include/windows.storage.id... But is never imported into `windows.storage.dll` but is imported into `windows.storage.applicationdata.dll` (Check for `windows.storage.idl` in `Makefile.in` and `classes.idl`)
- https://gitlab.winehq.org/wine/wine/-/tree/master/dlls/windows.storage?ref_t...
- https://gitlab.winehq.org/wine/wine/-/tree/master/dlls/windows.storage.appli...
`Windows.Storage.StorageFile` should be in `windows.storage.applicationdata.dll` and not `windows.storage.dll` according to wine source code. So `windows.storage: Add stubs for StorageFile class.` should be `windows.storage.applicationdata: Add stubs for StorageFile class.` instead. I don't currently have a Windows VM setup to check in which dll the class is actually located on Windows, but if you want to check, the registry key to check with regedit is:
- `HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsRuntime\ActivatableClassId\Windows.Storage.StorageFile`
I checked that registry key and it turns out the `Windows.Storage.StorageFile` class should be in `windows.storage.dll` after all.
Maybe I should split `Windows.Storage.ApplicationData` definitions out of `windows.storage.idl` to `windows.storage.applicationdata.idl`, and import that instead of whole `windows.storage.idl` into `windows.storage.applicationdata.dll`?
On Sun Jun 22 11:45:21 2025 +0000, Ignacy Kuchciński wrote:
I checked that registry key and it turns out the `Windows.Storage.StorageFile` class should be in `windows.storage.dll` after all. Maybe I should split `Windows.Storage.ApplicationData` definitions out of `windows.storage.idl` to `windows.storage.applicationdata.idl`, and import that instead of whole `windows.storage.idl` into `windows.storage.applicationdata.dll`?
Does `windows.storage.applicationdata.dll` exists on Windows?
Maybe `windows.storage.applicationdata.dll` doesn't exists on Windows and everything should be put in `windows.storage.dll`?
We are clearly lacking info, would putting `Windows.Storage.StorageFile` inside `windows.storage.applicationdata.dll` be fine in the meantime?
On Sun Jun 22 14:06:18 2025 +0000, Loïc Rebmeister wrote:
Does `windows.storage.applicationdata.dll` exists on Windows? Maybe `windows.storage.applicationdata.dll` doesn't exists on Windows and everything should be put in `windows.storage.dll`? We are clearly lacking info, would putting `Windows.Storage.StorageFile` inside `windows.storage.applicationdata.dll` be fine in the meantime?
I checked on a windows installation, and the equivalent registry key for `Windows.Storage.ApplicationData` does point to `windows.storage.applicationdata.dll`, all of other not related Windows.Storage definitions also point there, and the file itself does exist on Windows, is that enough information? Also, thanks for helping with this :)
On Sun Jun 22 19:50:39 2025 +0000, Ignacy Kuchciński wrote:
I checked on a windows installation, and the equivalent registry key for `Windows.Storage.ApplicationData` does point to `windows.storage.applicationdata.dll`, all of other not related Windows.Storage.ApplicationData definitions also point there, and the file itself does exist on Windows, is that enough information? Also, thanks for helping with this :)
Ok, the idl files are wrong and need fixing, probs giving it its own MR would be the way to go?
On Mon Jun 23 12:21:18 2025 +0000, Loïc Rebmeister wrote:
Ok, the idl files are wrong and need fixing, probs giving it its own MR would be the way to go?
I created https://gitlab.winehq.org/wine/wine/-/merge_requests/8416
@ignapk https://gitlab.winehq.org/wine/wine/-/merge_requests/8416 got merged, so you may want to update this MR.
On Mon Aug 25 15:43:08 2025 +0000, Loïc Rebmeister wrote:
@ignapk https://gitlab.winehq.org/wine/wine/-/merge_requests/8416 got merged, so you may want to update this MR.
Thanks for letting me know, I will try to get to it shortly :)