Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=53328
-- v4: windows.devices.enumeration/tests: Add test for Stopped DeviceWatcher event. windows.devices.enumeration: Add DeviceWatcher class. windows.devices.enumeration: Create private header file. windows.devices.enumeration: Add IDeviceInformationStatics2 interface. windows.devices.enumeration: Replace STDMETHODCALLTYPE with WINAPI. include/windows.devices.enumeration: Update file to newer formatting. widl: Use "cinterface(IInspectable)" for IInspectable signature.
From: Julian Klemann jklemann@codeweavers.com
Fixes the UUID of ITypedEventHandler<DeviceWatcher*, IInspectable*> to match MIDL. --- v4: No change. --- 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. --- v4: No change. --- 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
--- v4: No change. --- 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 --- v4: No change. --- dlls/windows.devices.enumeration/main.c | 198 +++++++++++++++++------- include/windows.devices.enumeration.idl | 75 ++++++++- 2 files changed, 219 insertions(+), 54 deletions(-)
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index b5cc5b63e14..b120c45ed70 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 for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -35,123 +36,216 @@ #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) +static const char *debugstr_hstring( HSTRING hstr ) { const WCHAR *str; UINT32 len; if (hstr && !((ULONG_PTR)hstr >> 16)) return "(invalid)"; - str = WindowsGetStringRawBuffer(hstr, &len); - return wine_dbgstr_wn(str, len); + str = WindowsGetStringRawBuffer( hstr, &len ); + return wine_dbgstr_wn( str, len ); }
-struct windows_devices_enumeration +struct device_information_statics { IActivationFactory IActivationFactory_iface; + IDeviceInformationStatics2 IDeviceInformationStatics2_iface; LONG ref; };
-static inline struct windows_devices_enumeration *impl_from_IActivationFactory(IActivationFactory *iface) +static inline struct device_information_statics *impl_from_IActivationFactory( IActivationFactory *iface ) { - return CONTAINING_RECORD(iface, struct windows_devices_enumeration, IActivationFactory_iface); + return CONTAINING_RECORD( iface, struct device_information_statics, IActivationFactory_iface ); }
-static HRESULT WINAPI windows_devices_enumeration_QueryInterface( - IActivationFactory *iface, REFIID iid, void **out) +static HRESULT WINAPI activation_factory_QueryInterface( IActivationFactory *iface, REFIID iid, void **out ) { - TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out); + struct device_information_statics *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_IActivationFactory )) + { + IInspectable_AddRef( (*out = &impl->IActivationFactory_iface) ); + return S_OK; + }
- if (IsEqualGUID(iid, &IID_IUnknown) || - IsEqualGUID(iid, &IID_IInspectable) || - IsEqualGUID(iid, &IID_IAgileObject) || - IsEqualGUID(iid, &IID_IActivationFactory)) + if (IsEqualGUID( iid, &IID_IDeviceInformationStatics2 )) { - IUnknown_AddRef(iface); - *out = iface; + IInspectable_AddRef( (*out = &impl->IDeviceInformationStatics2_iface) ); return S_OK; }
- FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + FIXME( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) ); *out = NULL; return E_NOINTERFACE; }
-static ULONG WINAPI windows_devices_enumeration_AddRef( - IActivationFactory *iface) +static ULONG WINAPI activation_factory_AddRef( IActivationFactory *iface ) { - struct windows_devices_enumeration *impl = impl_from_IActivationFactory(iface); - ULONG ref = InterlockedIncrement(&impl->ref); - TRACE("iface %p, ref %lu.\n", iface, ref); + struct device_information_statics *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedIncrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); return ref; }
-static ULONG WINAPI windows_devices_enumeration_Release( - IActivationFactory *iface) +static ULONG WINAPI activation_factory_Release( IActivationFactory *iface ) { - struct windows_devices_enumeration *impl = impl_from_IActivationFactory(iface); - ULONG ref = InterlockedDecrement(&impl->ref); - TRACE("iface %p, ref %lu.\n", iface, ref); + struct device_information_statics *impl = impl_from_IActivationFactory( iface ); + ULONG ref = InterlockedDecrement( &impl->ref ); + TRACE( "iface %p, ref %lu.\n", iface, ref ); return ref; }
-static HRESULT WINAPI windows_devices_enumeration_GetIids( - IActivationFactory *iface, ULONG *iid_count, IID **iids) +static HRESULT WINAPI activation_factory_GetIids( IActivationFactory *iface, ULONG *iid_count, IID **iids ) { - FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, 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( - IActivationFactory *iface, HSTRING *class_name) +static HRESULT WINAPI activation_factory_GetRuntimeClassName( IActivationFactory *iface, HSTRING *class_name ) { - FIXME("iface %p, class_name %p stub!\n", iface, class_name); + FIXME( "iface %p, class_name %p stub!\n", iface, class_name ); return E_NOTIMPL; }
-static HRESULT WINAPI windows_devices_enumeration_GetTrustLevel( - IActivationFactory *iface, TrustLevel *trust_level) +static HRESULT WINAPI activation_factory_GetTrustLevel( IActivationFactory *iface, TrustLevel *trust_level ) { - FIXME("iface %p, trust_level %p stub!\n", iface, trust_level); + FIXME( "iface %p, trust_level %p stub!\n", iface, trust_level ); return E_NOTIMPL; }
-static HRESULT WINAPI windows_devices_enumeration_ActivateInstance( - IActivationFactory *iface, IInspectable **instance) +static HRESULT WINAPI activation_factory_ActivateInstance( IActivationFactory *iface, IInspectable **instance ) { - FIXME("iface %p, instance %p stub!\n", iface, instance); + FIXME( "iface %p, instance %p stub!\n", iface, instance ); return E_NOTIMPL; }
static const struct IActivationFactoryVtbl activation_factory_vtbl = { - windows_devices_enumeration_QueryInterface, - windows_devices_enumeration_AddRef, - windows_devices_enumeration_Release, + activation_factory_QueryInterface, + activation_factory_AddRef, + activation_factory_Release, /* IInspectable methods */ - windows_devices_enumeration_GetIids, - windows_devices_enumeration_GetRuntimeClassName, - windows_devices_enumeration_GetTrustLevel, + activation_factory_GetIids, + activation_factory_GetRuntimeClassName, + activation_factory_GetTrustLevel, /* IActivationFactory methods */ - windows_devices_enumeration_ActivateInstance, + activation_factory_ActivateInstance, +}; + +DEFINE_IINSPECTABLE( device_statics2, IDeviceInformationStatics2, struct device_information_statics, IActivationFactory_iface ); + +static HRESULT WINAPI device_statics2_GetAqsFilterFromDeviceClass( IDeviceInformationStatics2 *iface, DeviceClass device_class, + HSTRING *filter ) +{ + FIXME( "iface %p, device_class %u, filter %p stub!\n", iface, device_class, filter ); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_statics2_CreateFromIdAsync( IDeviceInformationStatics2 *iface, HSTRING device_id, + IIterable_HSTRING *additional_properties, DeviceInformationKind kind, + IAsyncOperation_DeviceInformation **async_operation ) +{ + FIXME( "iface %p, device_id %s, additional_properties %p, kind %u, async_operation %p stub!\n", + iface, debugstr_hstring( device_id ), additional_properties, kind, async_operation ); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_statics2_FindAllAsync( IDeviceInformationStatics2 *iface, HSTRING filter, + IIterable_HSTRING *additional_properties, DeviceInformationKind kind, + IAsyncOperation_DeviceInformationCollection **async_operation ) +{ + FIXME( "iface %p, filter %s, additional_properties %p, kind %u, async_operation %p stub!\n", + iface, debugstr_hstring( filter ), additional_properties, kind, async_operation ); + return E_NOTIMPL; +} + +static HRESULT WINAPI device_statics2_CreateWatcher( IDeviceInformationStatics2 *iface, HSTRING filter, + IIterable_HSTRING *additional_properties, DeviceInformationKind kind, + IDeviceWatcher **watcher ) +{ + FIXME( "iface %p, filter %s, additional_properties %p, kind %u, watcher %p stub!\n", + iface, debugstr_hstring( filter ), additional_properties, 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 = +static struct device_information_statics device_information_statics = { {&activation_factory_vtbl}, + {&device_statics2_vtbl}, 1 };
-HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **out) +HRESULT WINAPI DllGetClassObject( REFCLSID clsid, REFIID riid, void **out ) { - FIXME("clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out); + FIXME( "clsid %s, riid %s, out %p stub!\n", debugstr_guid( clsid ), debugstr_guid( riid ), out ); return CLASS_E_CLASSNOTAVAILABLE; }
-HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **factory) +HRESULT WINAPI DllGetActivationFactory( HSTRING classid, IActivationFactory **factory ) { - TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory); - *factory = &windows_devices_enumeration.IActivationFactory_iface; - IUnknown_AddRef(*factory); + TRACE( "classid %s, factory %p.\n", debugstr_hstring( classid ), factory ); + *factory = &device_information_statics.IActivationFactory_iface; + IUnknown_AddRef( *factory ); return S_OK; } diff --git a/include/windows.devices.enumeration.idl b/include/windows.devices.enumeration.idl index f47df3795fa..2f73ba8310c 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, @@ -64,7 +98,7 @@ namespace Windows.Devices.Enumeration { EnumerationCompleted = 2, Stopping = 3, Stopped = 4, - Aborted = 5 + Aborted = 5, };
enum Panel @@ -75,7 +109,7 @@ namespace Windows.Devices.Enumeration { Top = 3, Bottom = 4, Left = 5, - Right = 6 + Right = 6, };
[ @@ -142,6 +176,31 @@ 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 device_class, [out, retval] HSTRING *filter); + [overload("CreateFromIdAsync")] + HRESULT CreateFromIdAsyncWithKindAndAdditionalProperties([in] HSTRING device_id, + [in] Windows.Foundation.Collections.IIterable<HSTRING> *additional_properties, + [in] Windows.Devices.Enumeration.DeviceInformationKind kind, + [out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceInformation *> **async_operation); + [overload("FindAllAsync")] + HRESULT FindAllAsyncWithKindAqsFilterAndAdditionalProperties([in] HSTRING filter, + [in] Windows.Foundation.Collections.IIterable<HSTRING> *additional_properties, + [in] Windows.Devices.Enumeration.DeviceInformationKind kind, + [out, retval] Windows.Foundation.IAsyncOperation<Windows.Devices.Enumeration.DeviceInformationCollection *> **async_operation); + [overload("CreateWatcher")] + HRESULT CreateWatcherWithKindAqsFilterAndAdditionalProperties([in] HSTRING filter, + [in] Windows.Foundation.Collections.IIterable<HSTRING> *additional_properties, + [in] Windows.Devices.Enumeration.DeviceInformationKind kind, + [out, retval] Windows.Devices.Enumeration.DeviceWatcher **watcher); + } + [ contract(Windows.Foundation.UniversalApiContract, 1.0), marshaling_behavior(agile), @@ -155,6 +214,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
--- v4: No change. --- dlls/windows.devices.enumeration/main.c | 57 +-------------- dlls/windows.devices.enumeration/private.h | 82 ++++++++++++++++++++++ 2 files changed, 84 insertions(+), 55 deletions(-) create mode 100644 dlls/windows.devices.enumeration/private.h
diff --git a/dlls/windows.devices.enumeration/main.c b/dlls/windows.devices.enumeration/main.c index b120c45ed70..48cc70fc517 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);
diff --git a/dlls/windows.devices.enumeration/private.h b/dlls/windows.devices.enumeration/private.h new file mode 100644 index 00000000000..4f82ad1cc64 --- /dev/null +++ b/dlls/windows.devices.enumeration/private.h @@ -0,0 +1,82 @@ +/* WinRT Windows.Devices.Enumeration implementation + * + * Copyright 2021 Gijs Vermeulen + * 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 + */ + +#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" + +#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
Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=53328 --- v4: No change. --- dlls/windows.devices.enumeration/Makefile.in | 1 + .../event_handlers.c | 109 ++++++++++ dlls/windows.devices.enumeration/main.c | 205 +++++++++++++++++- dlls/windows.devices.enumeration/private.h | 5 + 4 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 dlls/windows.devices.enumeration/event_handlers.c
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..4989a983e55 --- /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 48cc70fc517..fedfb5604d4 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -34,6 +34,197 @@ 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 semi-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 device_information_statics { IActivationFactory IActivationFactory_iface; @@ -155,9 +346,21 @@ static HRESULT WINAPI device_statics2_CreateWatcher( IDeviceInformationStatics2 IIterable_HSTRING *additional_properties, DeviceInformationKind kind, IDeviceWatcher **watcher ) { + struct device_watcher *this; + FIXME( "iface %p, filter %s, additional_properties %p, kind %u, watcher %p stub!\n", iface, debugstr_hstring( filter ), additional_properties, kind, watcher ); - return E_NOTIMPL; + + if (!(this = calloc( 1, sizeof(*this) ))) + return E_OUTOFMEMORY; + + this->IDeviceWatcher_iface.lpVtbl = &device_watcher_vtbl; + this->ref = 1; + + list_init( &this->stopped_handlers ); + + *watcher = &this->IDeviceWatcher_iface; + return S_OK; }
static const struct IDeviceInformationStatics2Vtbl device_statics2_vtbl = diff --git a/dlls/windows.devices.enumeration/private.h b/dlls/windows.devices.enumeration/private.h index 4f82ad1cc64..7ce7d11bc46 100644 --- a/dlls/windows.devices.enumeration/private.h +++ b/dlls/windows.devices.enumeration/private.h @@ -39,6 +39,11 @@
#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 ) \ { \
From: Julian Klemann jklemann@codeweavers.com
--- v4: Move more cleanup to goto statements, IAgileObject should not be optional, add test for waiting on event. --- configure | 1 + configure.ac | 1 + .../tests/Makefile.in | 5 + .../tests/devices.c | 233 ++++++++++++++++++ 4 files changed, 240 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 8104ac5f0ba..26a449c45e4 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..55116d1755f --- /dev/null +++ b/dlls/windows.devices.enumeration/tests/devices.c @@ -0,0 +1,233 @@ +/* + * 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" + +#define check_interface( obj, iid, exp ) check_interface_( __LINE__, obj, iid, exp, FALSE ) +#define check_optional_interface( obj, iid, exp ) check_interface_( __LINE__, obj, iid, exp, TRUE ) +static void check_interface_(unsigned int line, void *obj, const IID *iid, BOOL supported, BOOL optional) +{ + IUnknown *iface = obj; + HRESULT hr, expected_hr; + IUnknown *unk; + + expected_hr = supported ? S_OK : E_NOINTERFACE; + + hr = IUnknown_QueryInterface(iface, iid, (void **)&unk); + ok_(__FILE__, line)(hr == expected_hr || broken(hr == E_NOINTERFACE && optional), "Got hr %#lx, expected %#lx.\n", hr, expected_hr); + if (SUCCEEDED(hr)) + IUnknown_Release(unk); +} + + +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_DeviceInformation( void ) +{ + static const WCHAR *device_info_name = L"Windows.Devices.Enumeration.DeviceInformation"; + + struct device_watcher_handler stopped_handler, added_handler; + EventRegistrationToken stopped_token, added_token; + IInspectable *inspectable, *inspectable2; + IActivationFactory *factory; + IDeviceInformationStatics2 *device_info_statics2; + IDeviceWatcher *device_watcher; + DeviceWatcherStatus status = 0xdeadbeef; + ULONG ref; + HSTRING str; + HRESULT hr; + + device_watcher_handler_create( &added_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 ); + if ( hr == REGDB_E_CLASSNOTREG ) + { + win_skip( "%s runtimeclass, not registered.\n", wine_dbgstr_w( device_info_name ) ); + goto done; + } + + hr = IActivationFactory_QueryInterface( factory, &IID_IInspectable, (void **)&inspectable ); + ok( hr == S_OK, "got hr %#lx\n", hr ); + check_interface( factory, &IID_IAgileObject, FALSE ); + + hr = IActivationFactory_QueryInterface( factory, &IID_IDeviceInformationStatics2, (void **)&device_info_statics2 ); + ok( hr == S_OK || broken( hr == E_NOINTERFACE ), "got hr %#lx\n", hr ); + if (FAILED( hr )) + { + win_skip( "IDeviceInformationStatics2 not supported.\n" ); + goto skip_device_statics2; + } + + 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 ); + + hr = IDeviceInformationStatics2_CreateWatcherWithKindAqsFilterAndAdditionalProperties( + device_info_statics2, NULL, NULL, DeviceInformationKind_AssociationEndpoint, &device_watcher ); + + hr = IDeviceWatcher_add_Added( + device_watcher, + (ITypedEventHandler_DeviceWatcher_DeviceInformation *)&added_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 ); + ok( !WaitForSingleObject( stopped_handler.event, 1000 ), "wait for stopped_handler.event failed\n" ); + + 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" ); + + IDeviceWatcher_Release( device_watcher ); + IInspectable_Release( inspectable2 ); + IDeviceInformationStatics2_Release( device_info_statics2 ); + +skip_device_statics2: + IInspectable_Release( inspectable ); + ref = IActivationFactory_Release( factory ); + ok( ref == 1, "got ref %lu\n", ref ); + +done: + WindowsDeleteString( str ); + CloseHandle( stopped_handler.event ); + + RoUninitialize(); +} + +START_TEST( devices ) +{ + test_DeviceInformation(); +}
On Mon Aug 29 18:58:25 2022 +0000, Julian Klemann wrote:
The line is still 147 characters long when I do that so either way I am creating a second line, so this doesn't seem worth it to me.
140 isn't too bad. We usually have lines up to 160 chars.
On Mon Aug 29 19:37:08 2022 +0000, Bernhard K��lbl wrote:
140 isn't too bad. We usually have lines up to 160 chars.
Yeah it's not awful, but I just feel like the difference is negligible. If there is other stuff that I need to do for a v5 I guess I can include it then.
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.
I don't understand how it makes any difference. Is the application releasing the last reference to the IDeviceWatcher in its event handler Invoke method? If that's really what happens, it'd be good to have the test do the same thing.
Do I need to make more commits for the stubs or can I just leave it for this time?
I think it'd be clearer. And you can indeed change the message to semi-stub with the partial implementation.