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 ) \ { \