Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=53328
-- v2: windows.devices.enumeration/tests: Add test for Stopped DeviceWatcher event. windows.devices.enumeration: Add DeviceWatcher class. windows.devices.enumeration: Add IDeviceInformationStatics2 interface.
From: Julian Klemann jklemann@codeweavers.com
Fixes the UUID of ITypedEventHandler<DeviceWatcher*, IInspectable*> to match MIDL. --- tools/widl/typetree.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/tools/widl/typetree.c b/tools/widl/typetree.c index fef9d2e5c03..ee71a7a2899 100644 --- a/tools/widl/typetree.c +++ b/tools/widl/typetree.c @@ -168,7 +168,8 @@ static size_t append_type_signature(char **buf, size_t *len, size_t pos, type_t switch (type->type_type) { case TYPE_INTERFACE: - if (type->signature) n += strappend(buf, len, pos + n, "%s", type->signature); + if (!strcmp(type->name, "IInspectable")) n += strappend(buf, len, pos + n, "cinterface(IInspectable)"); + else if (type->signature) n += strappend(buf, len, pos + n, "%s", type->signature); else { if (!(uuid = get_attrp(type->attrs, ATTR_UUID)))
From: Julian Klemann jklemann@codeweavers.com
Remove nested namespaces and forward declares. --- include/windows.devices.enumeration.idl | 344 +++++++++++------------- 1 file changed, 156 insertions(+), 188 deletions(-)
diff --git a/include/windows.devices.enumeration.idl b/include/windows.devices.enumeration.idl index 7cde49224a1..f47df3795fa 100644 --- a/include/windows.devices.enumeration.idl +++ b/include/windows.devices.enumeration.idl @@ -27,202 +27,170 @@ import "windowscontracts.idl"; import "windows.storage.streams.idl"; import "windows.foundation.idl";
-namespace Windows { - namespace Devices { - namespace Enumeration { - typedef enum DeviceWatcherStatus DeviceWatcherStatus; - typedef enum Panel Panel; - - interface IDeviceInformation; - interface IDeviceInformationStatics; - interface IDeviceInformationStatics2; - interface IDeviceInformationUpdate; - interface IEnclosureLocation; - - runtimeclass DeviceInformation; - runtimeclass DeviceInformationUpdate; - runtimeclass DeviceThumbnail; - runtimeclass DeviceWatcher; - runtimeclass EnclosureLocation; - } +namespace Windows.Devices.Enumeration { + typedef enum DeviceWatcherStatus DeviceWatcherStatus; + typedef enum Panel Panel; + + interface IDeviceInformation; + interface IDeviceInformationStatics; + interface IDeviceInformationStatics2; + interface IDeviceInformationUpdate; + interface IEnclosureLocation; + + runtimeclass DeviceInformation; + runtimeclass DeviceInformationUpdate; + runtimeclass DeviceThumbnail; + runtimeclass DeviceWatcher; + runtimeclass EnclosureLocation; + + declare + { + interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Devices.Enumeration.DeviceInformation *>; + interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Devices.Enumeration.DeviceThumbnail *>; + interface Windows.Foundation.Collections.IMapView<HSTRING, IInspectable *>; + interface Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceInformation *>; + interface Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceThumbnail *>; + interface Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, IInspectable *>; + interface Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, Windows.Devices.Enumeration.DeviceInformation *>; + interface Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, Windows.Devices.Enumeration.DeviceInformationUpdate *>; } }
-namespace Windows -{ - namespace Devices +namespace Windows.Devices.Enumeration { + enum DeviceWatcherStatus + { + Created = 0, + Started = 1, + EnumerationCompleted = 2, + Stopping = 3, + Stopped = 4, + Aborted = 5 + }; + + enum Panel + { + Unknown = 0, + Front = 1, + Back = 2, + Top = 3, + Bottom = 4, + Left = 5, + Right = 6 + }; + + [ + exclusiveto(Windows.Devices.Enumeration.DeviceInformation), + uuid(aba0fb95-4398-489d-8e44-e6130927011f) + ] + interface IDeviceInformation : IInspectable { - namespace Enumeration - { - declare - { - interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Devices.Enumeration.DeviceInformation *>; - interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Devices.Enumeration.DeviceThumbnail *>; - interface Windows.Foundation.Collections.IMapView<HSTRING, IInspectable *>; - interface Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceInformation *>; - interface Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceThumbnail *>; - interface Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, IInspectable *>; - interface Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, Windows.Devices.Enumeration.DeviceInformation *>; - interface Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, Windows.Devices.Enumeration.DeviceInformationUpdate *>; - } - } + [propget] HRESULT Id([out, retval] HSTRING *value); + [propget] HRESULT Name([out, retval] HSTRING *value); + [propget] HRESULT IsEnabled([out, retval] boolean *value); + [propget] HRESULT IsDefault([out, retval] boolean *value); + [propget] HRESULT EnclosureLocation([out, retval] Windows.Devices.Enumeration.EnclosureLocation **value); + [propget] HRESULT Properties([out, retval] Windows.Foundation.Collections.IMapView<HSTRING, IInspectable *> **value); + HRESULT Update([in] Windows.Devices.Enumeration.DeviceInformationUpdate *info); + HRESULT GetThumbnailAsync([out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceThumbnail *> **operation); + HRESULT GetGlyphThumbnailAsync([out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceThumbnail *> **operation); } -}
-namespace Windows -{ - namespace Storage + [ + exclusiveto(Windows.Devices.Enumeration.DeviceInformationUpdate), + uuid(8f315305-d972-44b7-a37e-9e822c78213b) + ] + interface IDeviceInformationUpdate : IInspectable { - namespace Streams - { - interface IContentTypeProvider; - interface IInputStream; - interface IOutputStream; - interface IRandomAccessStream; - interface IRandomAccessStreamWithContentType; - } + [propget] HRESULT Id([out, retval] HSTRING *value); + [propget] HRESULT Properties([out, retval] Windows.Foundation.Collections.IMapView<HSTRING, IInspectable *> **value); + } + + [ + exclusiveto(Windows.Devices.Enumeration.DeviceWatcher), + uuid(c9eab97d-8f6b-4f96-a9f4-abc814e22271), + ] + interface IDeviceWatcher : IInspectable + { + [eventadd] HRESULT Added([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, + Windows.Devices.Enumeration.DeviceInformation *> *handler, [out, retval] EventRegistrationToken *token); + [eventremove] HRESULT Added([in] EventRegistrationToken token); + [eventadd] HRESULT Updated([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, + Windows.Devices.Enumeration.DeviceInformationUpdate *> *handler, [out, retval] EventRegistrationToken *token); + [eventremove] HRESULT Updated([in] EventRegistrationToken token); + [eventadd] HRESULT Removed([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, + Windows.Devices.Enumeration.DeviceInformationUpdate *> *handler, [out, retval] EventRegistrationToken *token); + [eventremove] HRESULT Removed([in] EventRegistrationToken token); + [eventadd] HRESULT EnumerationCompleted([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, + IInspectable *> *handler, [out, retval] EventRegistrationToken *token); + [eventremove] HRESULT EnumerationCompleted([in] EventRegistrationToken token); + [eventadd] HRESULT Stopped([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, + IInspectable *> *handler, [out, retval] EventRegistrationToken *token); + [eventremove] HRESULT Stopped([in] EventRegistrationToken token); + [propget] HRESULT Status([out, retval] Windows.Devices.Enumeration.DeviceWatcherStatus *status); + HRESULT Start(); + HRESULT Stop(); + } + + [ + exclusiveto(Windows.Devices.Enumeration.EnclosureLocation), + uuid(42340a27-5810-459c-aabb-c65e1f813ecf) + ] + interface IEnclosureLocation : IInspectable + { + [propget] HRESULT InDock([out, retval] boolean *value); + [propget] HRESULT InLid([out, retval] boolean *value); + [propget] HRESULT Panel([out, retval] Windows.Devices.Enumeration.Panel *value); + } + + [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + static(Windows.Devices.Enumeration.IDeviceInformationStatics, Windows.Foundation.UniversalApiContract, 1.0), + static(Windows.Devices.Enumeration.IDeviceInformationStatics2, Windows.Foundation.UniversalApiContract, 1.0), + threading(both) + ] + runtimeclass DeviceInformation + { + [default] interface Windows.Devices.Enumeration.IDeviceInformation; + [contract(Windows.Foundation.UniversalApiContract, 1.0)] interface Windows.Devices.Enumeration.IDeviceInformation2; + } + + [ + marshaling_behavior(agile), + ] + runtimeclass DeviceInformationUpdate + { + [default] interface Windows.Devices.Enumeration.IDeviceInformationUpdate; + interface Windows.Devices.Enumeration.IDeviceInformationUpdate2; + } + + [ + marshaling_behavior(agile), + ] + runtimeclass DeviceThumbnail + { + [default] interface Windows.Storage.Streams.IRandomAccessStreamWithContentType; + interface Windows.Storage.Streams.IContentTypeProvider; + interface Windows.Storage.Streams.IRandomAccessStream; + interface Windows.Storage.Streams.IOutputStream; + interface Windows.Foundation.IClosable; + interface Windows.Storage.Streams.IInputStream; + } + + [ + marshaling_behavior(agile), + ] + runtimeclass DeviceWatcher + { + [default] interface Windows.Devices.Enumeration.IDeviceWatcher; + interface Windows.Devices.Enumeration.IDeviceWatcher2; } -}
-namespace Windows { - namespace Devices { - namespace Enumeration { - enum DeviceWatcherStatus - { - Created = 0, - Started = 1, - EnumerationCompleted = 2, - Stopping = 3, - Stopped = 4, - Aborted = 5 - }; - - enum Panel - { - Unknown = 0, - Front = 1, - Back = 2, - Top = 3, - Bottom = 4, - Left = 5, - Right = 6 - }; - - [ - exclusiveto(Windows.Devices.Enumeration.DeviceInformation), - uuid(aba0fb95-4398-489d-8e44-e6130927011f) - ] - interface IDeviceInformation : IInspectable - { - [propget] HRESULT Id([out, retval] HSTRING *value); - [propget] HRESULT Name([out, retval] HSTRING *value); - [propget] HRESULT IsEnabled([out, retval] boolean *value); - [propget] HRESULT IsDefault([out, retval] boolean *value); - [propget] HRESULT EnclosureLocation([out, retval] Windows.Devices.Enumeration.EnclosureLocation **value); - [propget] HRESULT Properties([out, retval] Windows.Foundation.Collections.IMapView<HSTRING, IInspectable *> **value); - HRESULT Update([in] Windows.Devices.Enumeration.DeviceInformationUpdate *info); - HRESULT GetThumbnailAsync([out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceThumbnail *> **operation); - HRESULT GetGlyphThumbnailAsync([out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceThumbnail *> **operation); - } - - [ - exclusiveto(Windows.Devices.Enumeration.DeviceInformationUpdate), - uuid(8f315305-d972-44b7-a37e-9e822c78213b) - ] - interface IDeviceInformationUpdate : IInspectable - { - [propget] HRESULT Id([out, retval] HSTRING *value); - [propget] HRESULT Properties([out, retval] Windows.Foundation.Collections.IMapView<HSTRING, IInspectable *> **value); - } - - [ - exclusiveto(Windows.Devices.Enumeration.DeviceWatcher), - uuid(c9eab97d-8f6b-4f96-a9f4-abc814e22271), - ] - interface IDeviceWatcher : IInspectable - { - [eventadd] HRESULT Added([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher*, - Windows.Devices.Enumeration.DeviceInformation *> *handler, [out, retval] EventRegistrationToken *token); - [eventremove] HRESULT Added([in] EventRegistrationToken token); - [eventadd] HRESULT Updated([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, - Windows.Devices.Enumeration.DeviceInformationUpdate *> *handler, [out, retval] EventRegistrationToken *token); - [eventremove] HRESULT Updated([in] EventRegistrationToken token); - [eventadd] HRESULT Removed([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, - Windows.Devices.Enumeration.DeviceInformationUpdate *> *handler, [out, retval] EventRegistrationToken *token); - [eventremove] HRESULT Removed([in] EventRegistrationToken token); - [eventadd] HRESULT EnumerationCompleted([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, - IInspectable *> *handler, [out, retval] EventRegistrationToken *token); - [eventremove] HRESULT EnumerationCompleted([in] EventRegistrationToken token); - [eventadd] HRESULT Stopped([in] Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, - IInspectable *> *handler, [out, retval] EventRegistrationToken *token); - [eventremove] HRESULT Stopped([in] EventRegistrationToken token); - [propget] HRESULT Status([out, retval] Windows.Devices.Enumeration.DeviceWatcherStatus *status); - HRESULT Start(); - HRESULT Stop(); - } - - [ - exclusiveto(Windows.Devices.Enumeration.EnclosureLocation), - uuid(42340a27-5810-459c-aabb-c65e1f813ecf) - ] - interface IEnclosureLocation : IInspectable - { - [propget] HRESULT InDock([out, retval] boolean *value); - [propget] HRESULT InLid([out, retval] boolean *value); - [propget] HRESULT Panel([out, retval] Windows.Devices.Enumeration.Panel *value); - } - - [ - contract(Windows.Foundation.UniversalApiContract, 1.0), - marshaling_behavior(agile), - static(Windows.Devices.Enumeration.IDeviceInformationStatics, Windows.Foundation.UniversalApiContract, 1.0), - static(Windows.Devices.Enumeration.IDeviceInformationStatics2, Windows.Foundation.UniversalApiContract, 1.0), - threading(both) - ] - runtimeclass DeviceInformation - { - [default] interface Windows.Devices.Enumeration.IDeviceInformation; - [contract(Windows.Foundation.UniversalApiContract, 1.0)] interface Windows.Devices.Enumeration.IDeviceInformation2; - } - - [ - marshaling_behavior(agile), - ] - runtimeclass DeviceInformationUpdate - { - [default] interface Windows.Devices.Enumeration.IDeviceInformationUpdate; - interface Windows.Devices.Enumeration.IDeviceInformationUpdate2; - } - - [ - marshaling_behavior(agile), - ] - runtimeclass DeviceThumbnail - { - [default] interface Windows.Storage.Streams.IRandomAccessStreamWithContentType; - interface Windows.Storage.Streams.IContentTypeProvider; - interface Windows.Storage.Streams.IRandomAccessStream; - interface Windows.Storage.Streams.IOutputStream; - interface Windows.Foundation.IClosable; - interface Windows.Storage.Streams.IInputStream; - } - - [ - marshaling_behavior(agile), - ] - runtimeclass DeviceWatcher - { - [default] interface Windows.Devices.Enumeration.IDeviceWatcher; - interface Windows.Devices.Enumeration.IDeviceWatcher2; - } - - [ - marshaling_behavior(agile) - ] - runtimeclass EnclosureLocation - { - [default] interface Windows.Devices.Enumeration.IEnclosureLocation; - } - } + [ + marshaling_behavior(agile) + ] + runtimeclass EnclosureLocation + { + [default] interface Windows.Devices.Enumeration.IEnclosureLocation; } }
From: Julian Klemann jklemann@codeweavers.com
--- dlls/windows.devices.enumeration/main.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index 0e44251de08..b5cc5b63e14 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -57,7 +57,7 @@ static inline struct windows_devices_enumeration *impl_from_IActivationFactory(I return CONTAINING_RECORD(iface, struct windows_devices_enumeration, IActivationFactory_iface); }
-static HRESULT STDMETHODCALLTYPE windows_devices_enumeration_QueryInterface( +static HRESULT WINAPI windows_devices_enumeration_QueryInterface( IActivationFactory *iface, REFIID iid, void **out) { TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out); @@ -77,7 +77,7 @@ static HRESULT STDMETHODCALLTYPE windows_devices_enumeration_QueryInterface( return E_NOINTERFACE; }
-static ULONG STDMETHODCALLTYPE windows_devices_enumeration_AddRef( +static ULONG WINAPI windows_devices_enumeration_AddRef( IActivationFactory *iface) { struct windows_devices_enumeration *impl = impl_from_IActivationFactory(iface); @@ -86,7 +86,7 @@ static ULONG STDMETHODCALLTYPE windows_devices_enumeration_AddRef( return ref; }
-static ULONG STDMETHODCALLTYPE windows_devices_enumeration_Release( +static ULONG WINAPI windows_devices_enumeration_Release( IActivationFactory *iface) { struct windows_devices_enumeration *impl = impl_from_IActivationFactory(iface); @@ -95,28 +95,28 @@ static ULONG STDMETHODCALLTYPE windows_devices_enumeration_Release( return ref; }
-static HRESULT STDMETHODCALLTYPE windows_devices_enumeration_GetIids( +static HRESULT WINAPI windows_devices_enumeration_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 STDMETHODCALLTYPE windows_devices_enumeration_GetRuntimeClassName( +static HRESULT WINAPI windows_devices_enumeration_GetRuntimeClassName( IActivationFactory *iface, HSTRING *class_name) { FIXME("iface %p, class_name %p stub!\n", iface, class_name); return E_NOTIMPL; }
-static HRESULT STDMETHODCALLTYPE windows_devices_enumeration_GetTrustLevel( +static HRESULT WINAPI windows_devices_enumeration_GetTrustLevel( IActivationFactory *iface, TrustLevel *trust_level) { FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); return E_NOTIMPL; }
-static HRESULT STDMETHODCALLTYPE windows_devices_enumeration_ActivateInstance( +static HRESULT WINAPI windows_devices_enumeration_ActivateInstance( IActivationFactory *iface, IInspectable **instance) { FIXME("iface %p, instance %p stub!\n", iface, instance);
From: Julian Klemann jklemann@codeweavers.com
Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=53328 --- dlls/windows.devices.enumeration/main.c | 135 +++++++++++++++++++++--- include/windows.devices.enumeration.idl | 68 ++++++++++++ 2 files changed, 186 insertions(+), 17 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index b5cc5b63e14..b6cab670bce 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -1,6 +1,7 @@ /* WinRT Windows.Devices.Enumeration implementation * * Copyright 2021 Gijs Vermeulen + * Copyright 2022 Julian Klemann * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,6 +36,46 @@ #define WIDL_using_Windows_Devices_Enumeration #include "windows.devices.enumeration.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 ) +#define DEFINE_IINSPECTABLE_OUTER( pfx, iface_type, impl_type, outer_iface ) \ + DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, impl->outer_iface ) + WINE_DEFAULT_DEBUG_CHANNEL(enumeration);
static const char *debugstr_hstring(HSTRING hstr) @@ -49,6 +90,7 @@ static const char *debugstr_hstring(HSTRING hstr) struct windows_devices_enumeration { IActivationFactory IActivationFactory_iface; + IDeviceInformationStatics2 IDeviceInformationStatics2_iface; LONG ref; };
@@ -57,18 +99,24 @@ static inline struct windows_devices_enumeration *impl_from_IActivationFactory(I return CONTAINING_RECORD(iface, struct windows_devices_enumeration, IActivationFactory_iface); }
-static HRESULT WINAPI windows_devices_enumeration_QueryInterface( +static HRESULT WINAPI factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out) { + struct windows_devices_enumeration *impl = impl_from_IActivationFactory(iface); + TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out);
if (IsEqualGUID(iid, &IID_IUnknown) || IsEqualGUID(iid, &IID_IInspectable) || - IsEqualGUID(iid, &IID_IAgileObject) || IsEqualGUID(iid, &IID_IActivationFactory)) { - IUnknown_AddRef(iface); - *out = iface; + IInspectable_AddRef((*out = &impl->IActivationFactory_iface)); + return S_OK; + } + + if (IsEqualGUID(iid, &IID_IDeviceInformationStatics2)) + { + IInspectable_AddRef((*out = &impl->IDeviceInformationStatics2_iface)); return S_OK; }
@@ -77,7 +125,7 @@ static HRESULT WINAPI windows_devices_enumeration_QueryInterface( return E_NOINTERFACE; }
-static ULONG WINAPI windows_devices_enumeration_AddRef( +static ULONG WINAPI factory_AddRef( IActivationFactory *iface) { struct windows_devices_enumeration *impl = impl_from_IActivationFactory(iface); @@ -86,7 +134,7 @@ static ULONG WINAPI windows_devices_enumeration_AddRef( return ref; }
-static ULONG WINAPI windows_devices_enumeration_Release( +static ULONG WINAPI factory_Release( IActivationFactory *iface) { struct windows_devices_enumeration *impl = impl_from_IActivationFactory(iface); @@ -95,28 +143,28 @@ static ULONG WINAPI windows_devices_enumeration_Release( return ref; }
-static HRESULT WINAPI windows_devices_enumeration_GetIids( +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 windows_devices_enumeration_GetRuntimeClassName( +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 windows_devices_enumeration_GetTrustLevel( +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 windows_devices_enumeration_ActivateInstance( +static HRESULT WINAPI factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance) { FIXME("iface %p, instance %p stub!\n", iface, instance); @@ -125,20 +173,73 @@ static HRESULT WINAPI windows_devices_enumeration_ActivateInstance(
static const struct IActivationFactoryVtbl activation_factory_vtbl = { - windows_devices_enumeration_QueryInterface, - windows_devices_enumeration_AddRef, - windows_devices_enumeration_Release, + factory_QueryInterface, + factory_AddRef, + factory_Release, /* IInspectable methods */ - windows_devices_enumeration_GetIids, - windows_devices_enumeration_GetRuntimeClassName, - windows_devices_enumeration_GetTrustLevel, + factory_GetIids, + factory_GetRuntimeClassName, + factory_GetTrustLevel, /* IActivationFactory methods */ - windows_devices_enumeration_ActivateInstance, + factory_ActivateInstance, +}; + +DEFINE_IINSPECTABLE(device_statics2, IDeviceInformationStatics2, struct windows_devices_enumeration, IActivationFactory_iface); + +static HRESULT WINAPI device_statics2_GetAqsFilterFromDeviceClass( + IDeviceInformationStatics2 *iface, DeviceClass deviceClass, HSTRING *aqsFilter) +{ + FIXME("iface %p, deviceClass %u, aqsFilter %p stub!\n", iface, deviceClass, aqsFilter); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_statics2_CreateFromIdAsync( + IDeviceInformationStatics2 *iface, HSTRING deviceId, IIterable_HSTRING *additionalProperties, + DeviceInformationKind kind, IAsyncOperation_DeviceInformation **asyncOperation) +{ + FIXME("iface %p, deviceId %s, additionalProperties %p, kind %u, asyncOperation %p stub!\n", + iface, debugstr_hstring(deviceId), additionalProperties, kind, asyncOperation); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_statics2_FindAllAsync( + IDeviceInformationStatics2 *iface, HSTRING filter, IIterable_HSTRING *additionalProperties, + DeviceInformationKind kind, IAsyncOperation_DeviceInformationCollection **asyncOperation) +{ + FIXME("iface %p, filter %s, additionalProperties %p, kind %u, asyncOperation %p stub!\n", + iface, debugstr_hstring(filter), additionalProperties, kind, asyncOperation); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_statics2_CreateWatcher( + IDeviceInformationStatics2 *iface, HSTRING filter, IIterable_HSTRING *additionalProperties, + DeviceInformationKind kind, IDeviceWatcher **watcher) +{ + FIXME("iface %p, filter %s, additionalProperties %p, kind %u, watcher %p stub!\n", + iface, debugstr_hstring(filter), additionalProperties, kind, watcher); + return E_NOTIMPL; +} + +static const struct IDeviceInformationStatics2Vtbl device_statics2_vtbl = +{ + device_statics2_QueryInterface, + device_statics2_AddRef, + device_statics2_Release, + /* IInspectable methods */ + device_statics2_GetIids, + device_statics2_GetRuntimeClassName, + device_statics2_GetTrustLevel, + /* IDeviceInformationStatics2 methods */ + device_statics2_GetAqsFilterFromDeviceClass, + device_statics2_CreateFromIdAsync, + device_statics2_FindAllAsync, + device_statics2_CreateWatcher };
static struct windows_devices_enumeration windows_devices_enumeration = { {&activation_factory_vtbl}, + {&device_statics2_vtbl}, 1 };
diff --git a/include/windows.devices.enumeration.idl b/include/windows.devices.enumeration.idl index f47df3795fa..a7cab7aba3d 100644 --- a/include/windows.devices.enumeration.idl +++ b/include/windows.devices.enumeration.idl @@ -28,6 +28,8 @@ import "windows.storage.streams.idl"; import "windows.foundation.idl";
namespace Windows.Devices.Enumeration { + typedef enum DeviceClass DeviceClass; + typedef enum DeviceInformationKind DeviceInformationKind; typedef enum DeviceWatcherStatus DeviceWatcherStatus; typedef enum Panel Panel;
@@ -38,6 +40,7 @@ namespace Windows.Devices.Enumeration { interface IEnclosureLocation;
runtimeclass DeviceInformation; + runtimeclass DeviceInformationCollection; runtimeclass DeviceInformationUpdate; runtimeclass DeviceThumbnail; runtimeclass DeviceWatcher; @@ -46,9 +49,11 @@ namespace Windows.Devices.Enumeration { declare { interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Devices.Enumeration.DeviceInformation *>; + interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Devices.Enumeration.DeviceInformationCollection *>; interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Devices.Enumeration.DeviceThumbnail *>; interface Windows.Foundation.Collections.IMapView<HSTRING, IInspectable *>; interface Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceInformation *>; + interface Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceInformationCollection *>; interface Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceThumbnail *>; interface Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, IInspectable *>; interface Windows.Foundation.TypedEventHandler<Windows.Devices.Enumeration.DeviceWatcher *, Windows.Devices.Enumeration.DeviceInformation *>; @@ -57,6 +62,35 @@ namespace Windows.Devices.Enumeration { }
namespace Windows.Devices.Enumeration { + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + enum DeviceClass + { + All = 0, + AudioCapture = 1, + AudioRender = 2, + PortableStorageDevice = 3, + VideoCapture = 4, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + ImageScanner = 5, + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + Location = 6 + }; + + [contract(Windows.Foundation.UniversalApiContract, 1.0)] + enum DeviceInformationKind + { + Unknown = 0, + DeviceInterface = 1, + DeviceContainer = 2, + Device = 3, + DeviceInterfaceClass = 4, + AssociationEndpoint = 5, + AssociationEndpointContainer = 6, + AssociationEndpointService = 7, + [contract(Windows.Foundation.UniversalApiContract, 7.0)] + DevicePanel = 8 + }; + enum DeviceWatcherStatus { Created = 0, @@ -142,6 +176,28 @@ namespace Windows.Devices.Enumeration { [propget] HRESULT Panel([out, retval] Windows.Devices.Enumeration.Panel *value); }
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + exclusiveto(Windows.Devices.Enumeration.DeviceInformation), + uuid(493b4f34-a84f-45fd-9167-15d1cb1bd1f9) + ] + interface IDeviceInformationStatics2 : IInspectable + { + HRESULT GetAqsFilterFromDeviceClass([in] Windows.Devices.Enumeration.DeviceClass deviceClass, [out, retval] HSTRING *filter); + [overload("CreateFromIdAsync")] HRESULT CreateFromIdAsyncWithKindAndAdditionalProperties([in] HSTRING deviceId, + [in] Windows.Foundation.Collections.IIterable<HSTRING> *additionalProperties, + [in] Windows.Devices.Enumeration.DeviceInformationKind kind, + [out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceInformation *> **asyncOperation); + [overload("FindAllAsync")] HRESULT FindAllAsyncWithKindAqsFilterAndAdditionalProperties([in] HSTRING filter, + [in] Windows.Foundation.Collections.IIterable<HSTRING> *additionalProperties, + [in] Windows.Devices.Enumeration.DeviceInformationKind kind, + [out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceInformationCollection *> **asyncOperation); + [overload("CreateWatcher")] HRESULT CreateWatcherWithKindAqsFilterAndAdditionalProperties([in] HSTRING filter, + [in] Windows.Foundation.Collections.IIterable<HSTRING> *additionalProperties, + [in] Windows.Devices.Enumeration.DeviceInformationKind kind, + [out, retval] Windows.Devices.Enumeration.DeviceWatcher **watcher); + } + [ contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile), @@ -155,6 +211,18 @@ namespace Windows.Devices.Enumeration { [contract(Windows.Foundation.UniversalApiContract, 1.0)] interface Windows.Devices.Enumeration.IDeviceInformation2; }
+ [ + contract(Windows.Foundation.UniversalApiContract, 1.0), + marshaling_behavior(agile), + ] + runtimeclass DeviceInformationCollection + { + /* FIXME: This should be: + [default] interface Windows.Foundation.Collections.IVectorView<Windows.Devices.Enumeration.DeviceInformation *>; + interface Windows.Foundation.Collections.IIterable<Windows.Devices.Enumeration.DeviceInformation *>; */ + [default] interface IInspectable; + } + [ marshaling_behavior(agile), ]
From: Julian Klemann jklemann@codeweavers.com
Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=53328 --- dlls/windows.devices.enumeration/Makefile.in | 1 + .../event_handlers.c | 109 +++++++ dlls/windows.devices.enumeration/main.c | 275 ++++++++++++++---- dlls/windows.devices.enumeration/private.h | 86 ++++++ 4 files changed, 415 insertions(+), 56 deletions(-) create mode 100644 dlls/windows.devices.enumeration/event_handlers.c create mode 100644 dlls/windows.devices.enumeration/private.h
diff --git a/dlls/windows.devices.enumeration/Makefile.in b/dlls/windows.devices.enumeration/Makefile.in index a2058b3d002..77aa007c0dc 100644 --- a/dlls/windows.devices.enumeration/Makefile.in +++ b/dlls/windows.devices.enumeration/Makefile.in @@ -2,6 +2,7 @@ MODULE = windows.devices.enumeration.dll IMPORTS = combase uuid
C_SRCS = \ + event_handlers.c \ main.c
IDL_SRCS = classes.idl diff --git a/dlls/windows.devices.enumeration/event_handlers.c b/dlls/windows.devices.enumeration/event_handlers.c new file mode 100644 index 00000000000..8451cd72a76 --- /dev/null +++ b/dlls/windows.devices.enumeration/event_handlers.c @@ -0,0 +1,109 @@ +/* WinRT Windows.Devices.Enumeration implementation + * + * Copyright 2022 Bernhard K��lbl + * + * 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" + +static CRITICAL_SECTION handlers_cs; +static CRITICAL_SECTION_DEBUG handlers_cs_debug = +{ + 0, 0, &handlers_cs, + { &handlers_cs_debug.ProcessLocksList, &handlers_cs_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": handlers_cs") } +}; +static CRITICAL_SECTION handlers_cs = { &handlers_cs_debug, -1, 0, 0, 0, 0 }; +static EventRegistrationToken next_token = {.value = 1}; + +struct typed_event_handler_entry +{ + struct list entry; + EventRegistrationToken token; + ITypedEventHandler_IInspectable_IInspectable *handler; +}; + +HRESULT typed_event_handlers_append(struct list *list, ITypedEventHandler_IInspectable_IInspectable *handler, EventRegistrationToken *token) +{ + struct typed_event_handler_entry *entry; + + if (!(entry = calloc(1, sizeof(*entry)))) return E_OUTOFMEMORY; + ITypedEventHandler_IInspectable_IInspectable_AddRef((entry->handler = handler)); + + EnterCriticalSection(&handlers_cs); + + *token = entry->token = next_token; + next_token.value++; + list_add_tail(list, &entry->entry); + + LeaveCriticalSection(&handlers_cs); + + return S_OK; +} + +HRESULT typed_event_handlers_remove(struct list *list, EventRegistrationToken *token) +{ + struct typed_event_handler_entry *entry; + BOOL found = FALSE; + + EnterCriticalSection(&handlers_cs); + + LIST_FOR_EACH_ENTRY(entry, list, struct typed_event_handler_entry, entry) + if ((found = !memcmp(&entry->token, token, sizeof(*token)))) break; + if (found) list_remove(&entry->entry); + + LeaveCriticalSection(&handlers_cs); + + if (found) + { + ITypedEventHandler_IInspectable_IInspectable_Release(entry->handler); + free(entry); + } + + return S_OK; +} + +HRESULT typed_event_handlers_notify(struct list *list, IInspectable *sender, IInspectable *args) +{ + struct typed_event_handler_entry *entry; + + EnterCriticalSection(&handlers_cs); + + LIST_FOR_EACH_ENTRY(entry, list, struct typed_event_handler_entry, entry) + ITypedEventHandler_IInspectable_IInspectable_Invoke(entry->handler, sender, args); + + LeaveCriticalSection(&handlers_cs); + + return S_OK; +} + +HRESULT typed_event_handlers_clear(struct list *list) +{ + struct typed_event_handler_entry *entry, *entry_cursor2; + + EnterCriticalSection(&handlers_cs); + + LIST_FOR_EACH_ENTRY_SAFE(entry, entry_cursor2, list, struct typed_event_handler_entry, entry) + { + list_remove(&entry->entry); + ITypedEventHandler_IInspectable_IInspectable_Release(entry->handler); + free(entry); + } + + LeaveCriticalSection(&handlers_cs); + + return S_OK; +} diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index b6cab670bce..3b3719756cc 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -18,63 +18,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
-#include <stdarg.h> +#include "initguid.h" +#include "private.h"
-#define COBJMACROS -#include "windef.h" -#include "winbase.h" -#include "winstring.h" #include "wine/debug.h" -#include "objbase.h" - -#include "initguid.h" -#include "activation.h" - -#define WIDL_using_Windows_Foundation -#define WIDL_using_Windows_Foundation_Collections -#include "windows.foundation.h" -#define WIDL_using_Windows_Devices_Enumeration -#include "windows.devices.enumeration.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 ) -#define DEFINE_IINSPECTABLE_OUTER( pfx, iface_type, impl_type, outer_iface ) \ - DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, impl->outer_iface )
WINE_DEFAULT_DEBUG_CHANNEL(enumeration);
@@ -87,6 +34,208 @@ static const char *debugstr_hstring(HSTRING hstr) return wine_dbgstr_wn(str, len); }
+struct device_watcher +{ + IDeviceWatcher IDeviceWatcher_iface; + LONG ref; + + struct list stopped_handlers; +}; + +static inline struct device_watcher *impl_from_IDeviceWatcher(IDeviceWatcher *iface) +{ + return CONTAINING_RECORD(iface, struct device_watcher, IDeviceWatcher_iface); +} + +static HRESULT WINAPI device_watcher_QueryInterface( + IDeviceWatcher *iface, REFIID iid, void **out) +{ + struct device_watcher *impl = impl_from_IDeviceWatcher(iface); + + TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_IInspectable) || + IsEqualGUID(iid, &IID_IDeviceWatcher)) + { + IInspectable_AddRef((*out = &impl->IDeviceWatcher_iface)); + return S_OK; + } + + FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI device_watcher_AddRef( + IDeviceWatcher *iface) +{ + struct device_watcher *impl = impl_from_IDeviceWatcher(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + return ref; +} + +static ULONG WINAPI device_watcher_Release( + IDeviceWatcher *iface) +{ + struct device_watcher *impl = impl_from_IDeviceWatcher(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + TRACE("iface %p, ref %lu.\n", iface, ref); + + if (!ref) + { + typed_event_handlers_clear(&impl->stopped_handlers); + free(impl); + } + + return ref; +} + +static HRESULT WINAPI device_watcher_GetIids( + IDeviceWatcher *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 device_watcher_GetRuntimeClassName( + IDeviceWatcher *iface, HSTRING *class_name) +{ + FIXME("iface %p, class_name %p stub!\n", iface, class_name); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_watcher_GetTrustLevel( + IDeviceWatcher *iface, TrustLevel *trust_level) +{ + FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_watcher_add_Added( + IDeviceWatcher *iface, ITypedEventHandler_DeviceWatcher_DeviceInformation *handler, + EventRegistrationToken *token) +{ + FIXME("iface %p, handler %p, token %p stub!\n", iface, handler, token); + return S_OK; +} + +static HRESULT WINAPI device_watcher_remove_Added(IDeviceWatcher *iface, EventRegistrationToken token) +{ + FIXME("iface %p, token %#I64x stub!\n", iface, token.value); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_watcher_add_Updated( + IDeviceWatcher *iface, ITypedEventHandler_DeviceWatcher_DeviceInformationUpdate *handler, + EventRegistrationToken *token) +{ + FIXME("iface %p, handler %p, token %p stub!\n", iface, handler, token); + return S_OK; +} + +static HRESULT WINAPI device_watcher_remove_Updated(IDeviceWatcher *iface, EventRegistrationToken token) +{ + FIXME("iface %p, token %#I64x stub!\n", iface, token.value); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_watcher_add_Removed( + IDeviceWatcher *iface, ITypedEventHandler_DeviceWatcher_DeviceInformationUpdate *handler, + EventRegistrationToken *token) +{ + FIXME("iface %p, handler %p, token %p stub!\n", iface, handler, token); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_watcher_remove_Removed(IDeviceWatcher *iface, EventRegistrationToken token) +{ + FIXME("iface %p, token %#I64x stub!\n", iface, token.value); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_watcher_add_EnumerationCompleted( + IDeviceWatcher *iface, ITypedEventHandler_DeviceWatcher_IInspectable *handler, EventRegistrationToken *token) +{ + FIXME("iface %p, handler %p, token %p stub!\n", iface, handler, token); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_watcher_remove_EnumerationCompleted( + IDeviceWatcher *iface, EventRegistrationToken token) +{ + FIXME("iface %p, token %#I64x stub!\n", iface, token.value); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_watcher_add_Stopped( + IDeviceWatcher *iface, ITypedEventHandler_DeviceWatcher_IInspectable *handler, EventRegistrationToken *token) +{ + struct device_watcher *impl = impl_from_IDeviceWatcher(iface); + + TRACE("iface %p, handler %p, token %p.\n", iface, handler, token); + return typed_event_handlers_append(&impl->stopped_handlers, (ITypedEventHandler_IInspectable_IInspectable *)handler, token); +} + +static HRESULT WINAPI device_watcher_remove_Stopped(IDeviceWatcher *iface, EventRegistrationToken token) +{ + struct device_watcher *impl = impl_from_IDeviceWatcher(iface); + + TRACE("iface %p, token %#I64x.\n", iface, token.value); + return typed_event_handlers_remove(&impl->stopped_handlers, &token); +} + +static HRESULT WINAPI device_watcher_Status(IDeviceWatcher *iface, DeviceWatcherStatus *status) +{ + FIXME("iface %p, status %p stub!\n", iface, status); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_watcher_Start(IDeviceWatcher *iface) +{ + FIXME("iface %p stub!\n", iface); + return S_OK; +} + +static HRESULT WINAPI device_watcher_Stop(IDeviceWatcher *iface) +{ + struct device_watcher *impl = impl_from_IDeviceWatcher(iface); + HRESULT hr; + + FIXME("iface %p stub!\n", iface); + + IDeviceWatcher_AddRef(&impl->IDeviceWatcher_iface); + hr = typed_event_handlers_notify(&impl->stopped_handlers, (IInspectable *)iface, NULL); + IDeviceWatcher_Release(&impl->IDeviceWatcher_iface); + return hr; +} + +static const struct IDeviceWatcherVtbl device_watcher_vtbl = +{ + device_watcher_QueryInterface, + device_watcher_AddRef, + device_watcher_Release, + /* IInspectable methods */ + device_watcher_GetIids, + device_watcher_GetRuntimeClassName, + device_watcher_GetTrustLevel, + /* IDeviceWatcher methods */ + device_watcher_add_Added, + device_watcher_remove_Added, + device_watcher_add_Updated, + device_watcher_remove_Updated, + device_watcher_add_Removed, + device_watcher_remove_Removed, + device_watcher_add_EnumerationCompleted, + device_watcher_remove_EnumerationCompleted, + device_watcher_add_Stopped, + device_watcher_remove_Stopped, + device_watcher_Status, + device_watcher_Start, + device_watcher_Stop, +}; + struct windows_devices_enumeration { IActivationFactory IActivationFactory_iface; @@ -215,9 +364,23 @@ static HRESULT WINAPI device_statics2_CreateWatcher( IDeviceInformationStatics2 *iface, HSTRING filter, IIterable_HSTRING *additionalProperties, DeviceInformationKind kind, IDeviceWatcher **watcher) { + struct device_watcher *this; + HRESULT hr; + FIXME("iface %p, filter %s, additionalProperties %p, kind %u, watcher %p stub!\n", iface, debugstr_hstring(filter), additionalProperties, kind, watcher); - return E_NOTIMPL; + + if (!(this = malloc(sizeof(*this)))) + return E_OUTOFMEMORY; + + this->IDeviceWatcher_iface.lpVtbl = &device_watcher_vtbl; + this->ref = 1; + + list_init(&this->stopped_handlers); + + hr = IDeviceWatcher_QueryInterface(&this->IDeviceWatcher_iface, &IID_IDeviceWatcher, (void **)watcher); + IDeviceWatcher_Release(&this->IDeviceWatcher_iface); + return hr; }
static const struct IDeviceInformationStatics2Vtbl device_statics2_vtbl = diff --git a/dlls/windows.devices.enumeration/private.h b/dlls/windows.devices.enumeration/private.h new file mode 100644 index 00000000000..13ac54723cd --- /dev/null +++ b/dlls/windows.devices.enumeration/private.h @@ -0,0 +1,86 @@ +/* WinRT Windows.Devices.Enumeration implementation + * + * Copyright 2021 Gijs Vermeulen + * + * 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_DEVICES_ENUMERATION_PRIVATE_H +#define __WINE_WINDOWS_DEVICES_ENUMERATION_PRIVATE_H + +#include <stdarg.h> + +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winstring.h" +#include "objbase.h" + +#include "activation.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#define WIDL_using_Windows_Devices_Enumeration +#include "windows.devices.enumeration.h" + +#include "wine/list.h" + +HRESULT typed_event_handlers_append(struct list *list, ITypedEventHandler_IInspectable_IInspectable *handler, EventRegistrationToken *token); +HRESULT typed_event_handlers_remove(struct list *list, EventRegistrationToken *token); +HRESULT typed_event_handlers_notify(struct list *list, IInspectable *sender, IInspectable *args); +HRESULT typed_event_handlers_clear(struct list *list); + +#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 ) +#define DEFINE_IINSPECTABLE_OUTER( pfx, iface_type, impl_type, outer_iface ) \ + DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, impl->outer_iface ) + +#endif
From: Julian Klemann jklemann@codeweavers.com
--- configure | 1 + configure.ac | 1 + .../tests/Makefile.in | 5 + .../tests/devices.c | 210 ++++++++++++++++++ 4 files changed, 217 insertions(+) create mode 100644 dlls/windows.devices.enumeration/tests/Makefile.in create mode 100644 dlls/windows.devices.enumeration/tests/devices.c
diff --git a/configure b/configure index 89500dc8f7a..19c151f0b19 100755 --- a/configure +++ b/configure @@ -22005,6 +22005,7 @@ wine_fn_config_makefile dlls/win87em.dll16 enable_win16 wine_fn_config_makefile dlls/winaspi.dll16 enable_win16 wine_fn_config_makefile dlls/windebug.dll16 enable_win16 wine_fn_config_makefile dlls/windows.devices.enumeration enable_windows_devices_enumeration +wine_fn_config_makefile dlls/windows.devices.enumeration/tests enable_tests wine_fn_config_makefile dlls/windows.gaming.input enable_windows_gaming_input wine_fn_config_makefile dlls/windows.gaming.input/tests enable_tests wine_fn_config_makefile dlls/windows.globalization enable_windows_globalization diff --git a/configure.ac b/configure.ac index 49d414e1d17..d75f5231f82 100644 --- a/configure.ac +++ b/configure.ac @@ -3144,6 +3144,7 @@ WINE_CONFIG_MAKEFILE(dlls/win87em.dll16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/winaspi.dll16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/windebug.dll16,enable_win16) WINE_CONFIG_MAKEFILE(dlls/windows.devices.enumeration) +WINE_CONFIG_MAKEFILE(dlls/windows.devices.enumeration/tests) WINE_CONFIG_MAKEFILE(dlls/windows.gaming.input) WINE_CONFIG_MAKEFILE(dlls/windows.gaming.input/tests) WINE_CONFIG_MAKEFILE(dlls/windows.globalization) diff --git a/dlls/windows.devices.enumeration/tests/Makefile.in b/dlls/windows.devices.enumeration/tests/Makefile.in new file mode 100644 index 00000000000..fe8780974c8 --- /dev/null +++ b/dlls/windows.devices.enumeration/tests/Makefile.in @@ -0,0 +1,5 @@ +TESTDLL = windows.devices.enumeration.dll +IMPORTS = combase uuid + +C_SRCS = \ + devices.c diff --git a/dlls/windows.devices.enumeration/tests/devices.c b/dlls/windows.devices.enumeration/tests/devices.c new file mode 100644 index 00000000000..ab50e4dbb3c --- /dev/null +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -0,0 +1,210 @@ +/* + * Copyright 2022 Julian Klemann for CodeWeavers + * + * 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> + +#define COBJMACROS +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "winstring.h" + +#include "initguid.h" +#include "roapi.h" + +#define WIDL_using_Windows_Foundation +#define WIDL_using_Windows_Foundation_Collections +#include "windows.foundation.h" +#define WIDL_using_Windows_Devices_Enumeration +#include "windows.devices.enumeration.h" + +#include "wine/test.h" + +struct device_watcher_handler +{ + ITypedEventHandler_DeviceWatcher_IInspectable ITypedEventHandler_DeviceWatcher_IInspectable_iface; + LONG ref; + + HANDLE event; + BOOL invoked; + IInspectable *args; +}; + +static inline struct device_watcher_handler *impl_from_ITypedEventHandler_DeviceWatcher_IInspectable( + ITypedEventHandler_DeviceWatcher_IInspectable *iface) +{ + return CONTAINING_RECORD(iface, struct device_watcher_handler, ITypedEventHandler_DeviceWatcher_IInspectable_iface); +} + +static HRESULT WINAPI device_watcher_handler_QueryInterface( + ITypedEventHandler_DeviceWatcher_IInspectable *iface, REFIID iid, void **out) +{ + struct device_watcher_handler *impl = impl_from_ITypedEventHandler_DeviceWatcher_IInspectable(iface); + + if (IsEqualGUID(iid, &IID_IUnknown) || + IsEqualGUID(iid, &IID_ITypedEventHandler_DeviceWatcher_IInspectable)) + { + IUnknown_AddRef(&impl->ITypedEventHandler_DeviceWatcher_IInspectable_iface); + *out = &impl->ITypedEventHandler_DeviceWatcher_IInspectable_iface; + return S_OK; + } + + trace("%s not implemented, returning E_NO_INTERFACE.\n", debugstr_guid(iid)); + *out = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI device_watcher_handler_AddRef(ITypedEventHandler_DeviceWatcher_IInspectable *iface) +{ + struct device_watcher_handler *impl = impl_from_ITypedEventHandler_DeviceWatcher_IInspectable(iface); + ULONG ref = InterlockedIncrement(&impl->ref); + return ref; +} + +static ULONG WINAPI device_watcher_handler_Release(ITypedEventHandler_DeviceWatcher_IInspectable *iface) +{ + struct device_watcher_handler *impl = impl_from_ITypedEventHandler_DeviceWatcher_IInspectable(iface); + ULONG ref = InterlockedDecrement(&impl->ref); + return ref; +} + +static HRESULT WINAPI device_watcher_handler_Invoke( + ITypedEventHandler_DeviceWatcher_IInspectable *iface, IDeviceWatcher *sender, IInspectable *args) +{ + struct device_watcher_handler *impl = impl_from_ITypedEventHandler_DeviceWatcher_IInspectable(iface); + trace("iface %p, sender %p, args %p\n", iface, sender, args); + + impl->invoked = TRUE; + impl->args = args; + SetEvent(impl->event); + + return S_OK; +} + +static const ITypedEventHandler_DeviceWatcher_IInspectableVtbl device_watcher_handler_vtbl = +{ + device_watcher_handler_QueryInterface, + device_watcher_handler_AddRef, + device_watcher_handler_Release, + /* ITypedEventHandler<DeviceWatcher*,IInspectable*> methods */ + device_watcher_handler_Invoke, +}; + +static void device_watcher_handler_create(struct device_watcher_handler *impl) +{ + impl->ITypedEventHandler_DeviceWatcher_IInspectable_iface.lpVtbl = &device_watcher_handler_vtbl; + impl->invoked = FALSE; + impl->ref = 1; +} + +static void test_device_watcher_stop(void) +{ + static const WCHAR *device_info_name = L"Windows.Devices.Enumeration.DeviceInformation"; + + struct device_watcher_handler stopped_handler, dummy_handler; + EventRegistrationToken stopped_token, added_token; + IInspectable *inspectable, *inspectable2; + IActivationFactory *factory; + IDeviceInformationStatics2 *device_info_statics2; + IDeviceWatcher *device_watcher; + DeviceWatcherStatus status = 0xdeadbeef; + HSTRING str; + HRESULT hr; + + device_watcher_handler_create(&dummy_handler); + device_watcher_handler_create(&stopped_handler); + stopped_handler.event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!stopped_handler.event, "failed to create event, got error %lu\n", GetLastError()); + + hr = RoInitialize(RO_INIT_MULTITHREADED); + ok(hr == S_OK, "got hr %#lx\n", hr); + + hr = WindowsCreateString(device_info_name, wcslen(device_info_name), &str); + ok(hr == S_OK, "got hr %#lx\n", hr); + hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory); + ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "got hr %#lx\n", hr); + WindowsDeleteString(str); + if (hr == REGDB_E_CLASSNOTREG) + { + win_skip("%s runtimeclass, not registered.\n", wine_dbgstr_w(device_info_name)); + return; + } + + hr = IActivationFactory_QueryInterface(factory, &IID_IInspectable, (void **)&inspectable); + ok(hr == S_OK, "got hr %#lx\n", hr); + + hr = IActivationFactory_QueryInterface(factory, &IID_IDeviceInformationStatics2, (void **)&device_info_statics2); + ok(hr == S_OK || broken(hr == E_NOINTERFACE), "got hr %#lx\n", hr); + IActivationFactory_Release(factory); + if (hr != S_OK) + { + IInspectable_Release(inspectable); + win_skip("IDeviceInformationStatics2 not supported.\n"); + return; + } + + hr = IDeviceInformationStatics2_QueryInterface(device_info_statics2, &IID_IInspectable, (void **)&inspectable2); + ok(hr == S_OK, "got hr %#lx\n", hr); + ok(inspectable == inspectable2, "got inspectable %p, inspectable2 %p\n", inspectable, inspectable2); + IInspectable_Release(inspectable); + IInspectable_Release(inspectable2); + + hr = IDeviceInformationStatics2_CreateWatcherWithKindAqsFilterAndAdditionalProperties( + device_info_statics2, NULL, NULL, DeviceInformationKind_AssociationEndpoint, &device_watcher); + IDeviceInformationStatics2_Release(device_info_statics2); + + hr = IDeviceWatcher_add_Added( + device_watcher, + (ITypedEventHandler_DeviceWatcher_DeviceInformation *)&dummy_handler.ITypedEventHandler_DeviceWatcher_IInspectable_iface, + &added_token); + ok(hr == S_OK, "got hr %#lx\n", hr); + hr = IDeviceWatcher_add_Stopped( + device_watcher, &stopped_handler.ITypedEventHandler_DeviceWatcher_IInspectable_iface, + &stopped_token); + ok(hr == S_OK, "got hr %#lx\n", hr); + + hr = IDeviceWatcher_get_Status(device_watcher, &status); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(status == DeviceWatcherStatus_Created, "got status %u\n", status); + + hr = IDeviceWatcher_Start(device_watcher); + ok(hr == S_OK, "got hr %#lx\n", hr); + hr = IDeviceWatcher_get_Status(device_watcher, &status); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(status == DeviceWatcherStatus_Started, "got status %u\n", status); + + hr = IDeviceWatcher_Stop(device_watcher); + ok(hr == S_OK, "got hr %#lx\n", hr); + WaitForSingleObject(stopped_handler.event, INFINITE); + + hr = IDeviceWatcher_get_Status(device_watcher, &status); + todo_wine ok(hr == S_OK, "got hr %#lx\n", hr); + todo_wine ok(status == DeviceWatcherStatus_Stopped, "got status %u\n", status); + ok(stopped_handler.invoked, "stopped_handler not invoked\n"); + ok(stopped_handler.args == NULL, "stopped_handler not invoked\n"); + + CloseHandle(stopped_handler.event); + IDeviceWatcher_Release(device_watcher); + + RoUninitialize(); +} + +START_TEST(devices) +{ + test_device_watcher_stop(); +}
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/main.c:
IActivationFactory *iface, HSTRING *class_name)
{ FIXME("iface %p, class_name %p stub!\n", iface, class_name); return E_NOTIMPL; }
-static HRESULT WINAPI windows_devices_enumeration_GetTrustLevel( +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 windows_devices_enumeration_ActivateInstance( +static HRESULT WINAPI factory_ActivateInstance(
Here the prefix "factory" is used, but the vtbl is named "activation_factory_..."
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/main.c:
struct windows_devices_enumeration
I'd rename this struct to device_information_statics, because the runtimeclass is called DeviceInformation
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/main.c:
+{
- device_statics2_QueryInterface,
- device_statics2_AddRef,
- device_statics2_Release,
- /* IInspectable methods */
- device_statics2_GetIids,
- device_statics2_GetRuntimeClassName,
- device_statics2_GetTrustLevel,
- /* IDeviceInformationStatics2 methods */
- device_statics2_GetAqsFilterFromDeviceClass,
- device_statics2_CreateFromIdAsync,
- device_statics2_FindAllAsync,
- device_statics2_CreateWatcher
};
static struct windows_devices_enumeration windows_devices_enumeration =
Same renaming to device_information_statics for the instance here.
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/main.c:
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 )
-#define DEFINE_IINSPECTABLE_OUTER( pfx, iface_type, impl_type, outer_iface ) \
- DEFINE_IINSPECTABLE_( pfx, iface_type, impl_type, impl_from_##iface_type, iface_type##_iface, impl->outer_iface )
Moving this stuff in a private header _could_ be done in a separate commit.
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/event_handlers.c:
+};
+HRESULT typed_event_handlers_append(struct list *list, ITypedEventHandler_IInspectable_IInspectable *handler, EventRegistrationToken *token) +{
- struct typed_event_handler_entry *entry;
- if (!(entry = calloc(1, sizeof(*entry)))) return E_OUTOFMEMORY;
- ITypedEventHandler_IInspectable_IInspectable_AddRef((entry->handler = handler));
- EnterCriticalSection(&handlers_cs);
- *token = entry->token = next_token;
- next_token.value++;
- list_add_tail(list, &entry->entry);
- LeaveCriticalSection(&handlers_cs);
A nice to have thing would be to format function calls with spaces after the opening ( and before the closing ). Instead of `Foo(bar, baz)` do `Foo( bar, baz )`. That's a coding style me and R��mi kinda agreed on. I just didn't use it for speech, because most parts were already done in the other style. Since you're adding "new" code anyway, it would be the perfect opportunity to do so,
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/private.h:
+/* WinRT Windows.Devices.Enumeration implementation
- Copyright 2021 Gijs Vermeulen
Maybe update the copyright notice. :smile:
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/main.c:
- struct device_watcher *this;
- HRESULT hr;
- FIXME("iface %p, filter %s, additionalProperties %p, kind %u, watcher %p stub!\n", iface, debugstr_hstring(filter), additionalProperties, kind, watcher);
- return E_NOTIMPL;
- if (!(this = malloc(sizeof(*this))))
return E_OUTOFMEMORY;
- this->IDeviceWatcher_iface.lpVtbl = &device_watcher_vtbl;
- this->ref = 1;
- list_init(&this->stopped_handlers);
- hr = IDeviceWatcher_QueryInterface(&this->IDeviceWatcher_iface, &IID_IDeviceWatcher, (void **)watcher);
For WinRT we usually just do `*watcher = &impl->IDeviceWatcher_iface` .
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/tests/devices.c:
+{
- device_watcher_handler_QueryInterface,
- device_watcher_handler_AddRef,
- device_watcher_handler_Release,
- /* ITypedEventHandler<DeviceWatcher*,IInspectable*> methods */
- device_watcher_handler_Invoke,
+};
+static void device_watcher_handler_create(struct device_watcher_handler *impl) +{
- impl->ITypedEventHandler_DeviceWatcher_IInspectable_iface.lpVtbl = &device_watcher_handler_vtbl;
- impl->invoked = FALSE;
- impl->ref = 1;
+}
+static void test_device_watcher_stop(void)
test_DeviceInformation
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/tests/devices.c:
- hr = IActivationFactory_QueryInterface(factory, &IID_IDeviceInformationStatics2, (void **)&device_info_statics2);
- ok(hr == S_OK || broken(hr == E_NOINTERFACE), "got hr %#lx\n", hr);
- IActivationFactory_Release(factory);
- if (hr != S_OK)
- {
IInspectable_Release(inspectable);
win_skip("IDeviceInformationStatics2 not supported.\n");
return;
- }
- hr = IDeviceInformationStatics2_QueryInterface(device_info_statics2, &IID_IInspectable, (void **)&inspectable2);
- ok(hr == S_OK, "got hr %#lx\n", hr);
- ok(inspectable == inspectable2, "got inspectable %p, inspectable2 %p\n", inspectable, inspectable2);
- IInspectable_Release(inspectable);
- IInspectable_Release(inspectable2);
Release in reverse order here, it's a bit cleaner.
``` IInspectable_Release(inspectable2); IInspectable_Release(inspectable); IActivationFactory_Release(factory); ```
And you could probably do a ref check == 1 on the last release. (Yeah yeah, me and ref checks, lol.)
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/tests/devices.c:
- hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
- ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "got hr %#lx\n", hr);
- WindowsDeleteString(str);
- if (hr == REGDB_E_CLASSNOTREG)
- {
win_skip("%s runtimeclass, not registered.\n", wine_dbgstr_w(device_info_name));
return;
- }
- hr = IActivationFactory_QueryInterface(factory, &IID_IInspectable, (void **)&inspectable);
- ok(hr == S_OK, "got hr %#lx\n", hr);
- hr = IActivationFactory_QueryInterface(factory, &IID_IDeviceInformationStatics2, (void **)&device_info_statics2);
- ok(hr == S_OK || broken(hr == E_NOINTERFACE), "got hr %#lx\n", hr);
- IActivationFactory_Release(factory);
- if (hr != S_OK)
`if (FAILED( hr ))`
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/tests/devices.c:
- {
win_skip("%s runtimeclass, not registered.\n", wine_dbgstr_w(device_info_name));
return;
- }
- hr = IActivationFactory_QueryInterface(factory, &IID_IInspectable, (void **)&inspectable);
- ok(hr == S_OK, "got hr %#lx\n", hr);
- hr = IActivationFactory_QueryInterface(factory, &IID_IDeviceInformationStatics2, (void **)&device_info_statics2);
- ok(hr == S_OK || broken(hr == E_NOINTERFACE), "got hr %#lx\n", hr);
- IActivationFactory_Release(factory);
- if (hr != S_OK)
- {
IInspectable_Release(inspectable);
win_skip("IDeviceInformationStatics2 not supported.\n");
return;
Instead of returning, I'd do a goto to a cleanup routine at the end of the function.
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/tests/devices.c:
- todo_wine ok(hr == S_OK, "got hr %#lx\n", hr);
- todo_wine ok(status == DeviceWatcherStatus_Started, "got status %u\n", status);
- hr = IDeviceWatcher_Stop(device_watcher);
- ok(hr == S_OK, "got hr %#lx\n", hr);
- WaitForSingleObject(stopped_handler.event, INFINITE);
- hr = IDeviceWatcher_get_Status(device_watcher, &status);
- todo_wine ok(hr == S_OK, "got hr %#lx\n", hr);
- todo_wine ok(status == DeviceWatcherStatus_Stopped, "got status %u\n", status);
- ok(stopped_handler.invoked, "stopped_handler not invoked\n");
- ok(stopped_handler.args == NULL, "stopped_handler not invoked\n");
- CloseHandle(stopped_handler.event);
- IDeviceWatcher_Release(device_watcher);
Release here in reverse order:
``` IDeviceInformationStatics2_Release(device_info_statics2);
skip_statics2: IInspectable_Release(inspectable2); IInspectable_Release(inspectable); ```
And maybe add a ref check to the last release. (Yeah yeah, me and ref checks, haha)
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/tests/devices.c:
&stopped_token);
- ok(hr == S_OK, "got hr %#lx\n", hr);
- hr = IDeviceWatcher_get_Status(device_watcher, &status);
- todo_wine ok(hr == S_OK, "got hr %#lx\n", hr);
- todo_wine ok(status == DeviceWatcherStatus_Created, "got status %u\n", status);
- hr = IDeviceWatcher_Start(device_watcher);
- ok(hr == S_OK, "got hr %#lx\n", hr);
- hr = IDeviceWatcher_get_Status(device_watcher, &status);
- todo_wine ok(hr == S_OK, "got hr %#lx\n", hr);
- todo_wine ok(status == DeviceWatcherStatus_Started, "got status %u\n", status);
- hr = IDeviceWatcher_Stop(device_watcher);
- ok(hr == S_OK, "got hr %#lx\n", hr);
- WaitForSingleObject(stopped_handler.event, INFINITE);
It's not good to block the test infinitely. Just put this to 1000 and add a test to check it didn't time out.
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/tests/devices.c:
- /* ITypedEventHandler<DeviceWatcher*,IInspectable*> methods */
- device_watcher_handler_Invoke,
+};
+static void device_watcher_handler_create(struct device_watcher_handler *impl) +{
- impl->ITypedEventHandler_DeviceWatcher_IInspectable_iface.lpVtbl = &device_watcher_handler_vtbl;
- impl->invoked = FALSE;
- impl->ref = 1;
+}
+static void test_device_watcher_stop(void) +{
- static const WCHAR *device_info_name = L"Windows.Devices.Enumeration.DeviceInformation";
- struct device_watcher_handler stopped_handler, dummy_handler;
s/dummy_handler/added_handler
On Fri Aug 26 12:10:08 2022 +0000, Bernhard K��lbl wrote:
Release here in reverse order:
IDeviceInformationStatics2_Release(device_info_statics2); skip_statics2: IInspectable_Release(inspectable2); IInspectable_Release(inspectable);
And maybe add a ref check to the last release. (Yeah yeah, me and ref checks, haha)
With that goto, wouldn't the inspectable2 release need to be above the label, since we never actually created that inspectable2 until after the skip?
On Fri Aug 26 16:52:24 2022 +0000, Julian Klemann wrote:
With that goto, wouldn't the inspectable2 release need to be above the label, since we never actually created that inspectable2 until after the skip?
Right, you need to put the label one down.
R��mi Bernon (@rbernon) commented about dlls/windows.devices.enumeration/main.c:
/* IInspectable methods */
- windows_devices_enumeration_GetIids,
- windows_devices_enumeration_GetRuntimeClassName,
- windows_devices_enumeration_GetTrustLevel,
- factory_GetIids,
- factory_GetRuntimeClassName,
- factory_GetTrustLevel, /* IActivationFactory methods */
- windows_devices_enumeration_ActivateInstance,
- factory_ActivateInstance,
+};
+DEFINE_IINSPECTABLE(device_statics2, IDeviceInformationStatics2, struct windows_devices_enumeration, IActivationFactory_iface);
+static HRESULT WINAPI device_statics2_GetAqsFilterFromDeviceClass(
IDeviceInformationStatics2 *iface, DeviceClass deviceClass, HSTRING *aqsFilter)
Please use snake_case identifiers.
R��mi Bernon (@rbernon) commented about include/windows.devices.enumeration.idl:
}
namespace Windows.Devices.Enumeration {
- [contract(Windows.Foundation.UniversalApiContract, 1.0)]
- enum DeviceClass
- {
All = 0,
AudioCapture = 1,
AudioRender = 2,
PortableStorageDevice = 3,
VideoCapture = 4,
[contract(Windows.Foundation.UniversalApiContract, 1.0)]
ImageScanner = 5,
[contract(Windows.Foundation.UniversalApiContract, 1.0)]
Location = 6
It's not done for the existing code but I think it's best to add a comma to the last element, so that future additions do not need to touch this line.
R��mi Bernon (@rbernon) commented about include/windows.devices.enumeration.idl:
[propget] HRESULT Panel([out, retval] Windows.Devices.Enumeration.Panel *value); }
- [
contract(Windows.Foundation.UniversalApiContract, 1.0),
exclusiveto(Windows.Devices.Enumeration.DeviceInformation),
uuid(493b4f34-a84f-45fd-9167-15d1cb1bd1f9)
- ]
- interface IDeviceInformationStatics2 : IInspectable
- {
HRESULT GetAqsFilterFromDeviceClass([in] Windows.Devices.Enumeration.DeviceClass deviceClass, [out, retval] HSTRING *filter);
[overload("CreateFromIdAsync")] HRESULT CreateFromIdAsyncWithKindAndAdditionalProperties([in] HSTRING deviceId,
You could probably put a line feed after the attribute. Please use snake_case identifiers too, like elsewhere.
R��mi Bernon (@rbernon) commented about include/windows.devices.enumeration.idl:
[contract(Windows.Foundation.UniversalApiContract, 1.0)] interface Windows.Devices.Enumeration.IDeviceInformation2; }
- [
contract(Windows.Foundation.UniversalApiContract, 1.0),
marshaling_behavior(agile),
- ]
- runtimeclass DeviceInformationCollection
- {
/* FIXME: This should be:
[default] interface Windows.Foundation.Collections.IVectorView<Windows.Devices.Enumeration.DeviceInformation *>;
interface Windows.Foundation.Collections.IIterable<Windows.Devices.Enumeration.DeviceInformation *>; */
I think you should fix widl first if it's not accepting that, and avoid these kind of FIXMEs. Otherwise they tend to stay unfixed, or missed when the feature is implemented.
R��mi Bernon (@rbernon) commented about dlls/windows.devices.enumeration/main.c:
IDeviceInformationStatics2 *iface, HSTRING filter, IIterable_HSTRING *additionalProperties, DeviceInformationKind kind, IDeviceWatcher **watcher)
{
- struct device_watcher *this;
- HRESULT hr;
- FIXME("iface %p, filter %s, additionalProperties %p, kind %u, watcher %p stub!\n", iface, debugstr_hstring(filter), additionalProperties, kind, watcher);
- return E_NOTIMPL;
- if (!(this = malloc(sizeof(*this))))
Please use calloc for object allocation, like everywhere else. It avoids issues with uninitialized members and saves you the initialization to 0 / NULL. As you're implementing the function you should probably change the FIXME into a TRACE and remove the "stub!".
R��mi Bernon (@rbernon) commented about dlls/windows.devices.enumeration/main.c:
+static HRESULT WINAPI device_watcher_Start(IDeviceWatcher *iface) +{
- FIXME("iface %p stub!\n", iface);
- return S_OK;
+}
+static HRESULT WINAPI device_watcher_Stop(IDeviceWatcher *iface) +{
- struct device_watcher *impl = impl_from_IDeviceWatcher(iface);
- HRESULT hr;
- FIXME("iface %p stub!\n", iface);
- IDeviceWatcher_AddRef(&impl->IDeviceWatcher_iface);
- hr = typed_event_handlers_notify(&impl->stopped_handlers, (IInspectable *)iface, NULL);
- IDeviceWatcher_Release(&impl->IDeviceWatcher_iface);
You don't need to AddRef / Release here. Also I'm just reading this quickly but if it's actually implemented you could probably change the trace to TRACE and not FIXME / stub.
One good habit is also to first implement a class or an interface as complete stub first, then implement each method individually (or a few at a time), adding the required members and code to the class and removing the FIXME. Eventually interleaving with new tests for the methods in a first commits with todo_wine, and then the commit implementing the methods with the todo_wine removed.
Bernhard K��lbl (@besentv) commented about dlls/windows.devices.enumeration/tests/devices.c:
- hr = RoInitialize(RO_INIT_MULTITHREADED);
- ok(hr == S_OK, "got hr %#lx\n", hr);
- hr = WindowsCreateString(device_info_name, wcslen(device_info_name), &str);
- ok(hr == S_OK, "got hr %#lx\n", hr);
- hr = RoGetActivationFactory(str, &IID_IActivationFactory, (void **)&factory);
- ok(hr == S_OK || broken(hr == REGDB_E_CLASSNOTREG), "got hr %#lx\n", hr);
- WindowsDeleteString(str);
- if (hr == REGDB_E_CLASSNOTREG)
- {
win_skip("%s runtimeclass, not registered.\n", wine_dbgstr_w(device_info_name));
return;
- }
- hr = IActivationFactory_QueryInterface(factory, &IID_IInspectable, (void **)&inspectable);
While you're at it, also check for IID_IAgileObject.
On Fri Aug 26 18:31:28 2022 +0000, Bernhard K��lbl wrote:
While you're at it, also check for IID_IAgileObject.
That was what caused the first set of conformance test failures. Line 153 was querying the factory and 173 was querying IDeviceInformationStatics2 for it.
On Fri Aug 26 17:30:23 2022 +0000, R��mi Bernon wrote:
I think you should fix widl first if it's not accepting that, and avoid these kind of FIXMEs. Otherwise they tend to stay unfixed, or missed when the feature is implemented.
I was planning to do this but I ran out of time, I am going to try to work on this while I am in school.
On Fri Aug 26 20:24:43 2022 +0000, Julian Klemann wrote:
That was what caused the first set of conformance test failures. Line 153 was querying the factory and 173 was querying IDeviceInformationStatics2 for it.
Not sure if I understand: Just test for E_NOINTERFACE ?
On Fri Aug 26 20:35:07 2022 +0000, Bernhard K��lbl wrote:
Not sure if I understand: Just test for E_NOINTERFACE ?
Oh I thought you meant to readd all the tests I had before, sorry never mind
On Fri Aug 26 17:30:24 2022 +0000, R��mi Bernon wrote:
You don't need to AddRef / Release here. Also I'm just reading this quickly but if it's actually implemented you could probably change the trace to TRACE and not FIXME / stub. One good habit is also to first implement a class or an interface as complete stub first, then implement each method individually (or a few at a time), adding the required members and code to the class and removing the FIXME. Eventually interleaving with new tests for the methods in a first commits with todo_wine, and then the commit implementing the methods with the todo_wine removed.
I did the AddRef/Release there because otherwise the bug I am fixing does not actually fix. It will free itself while invoking event handlers and it just causes a lot of issues, and this is also what I think the internal behavior on Windows is from tests I had written earlier.
Do I need to make more commits for the stubs or can I just leave it for this time?
On Fri Aug 26 20:40:57 2022 +0000, Julian Klemann wrote:
I did the AddRef/Release there because otherwise the bug I am fixing does not actually fix. It will free itself while invoking event handlers and it just causes a lot of issues, and this is also what I think the internal behavior on Windows is from tests I had written earlier. Do I need to make more commits for the stubs or can I just leave it for this time?
Also the reason I said it was a stub was because I am not actually setting any statuses, I am just firing stopped event handlers, so I guess it is a little more of a semi-stub, but it doesn't have even close to the full functionality it wants, where only certain states can be stopped.