From: Julian Klemann jklemann@codeweavers.com
Wine-bug: https://bugs.winehq.org/show_bug.cgi?id=53328 --- v5: Split commit. --- dlls/windows.devices.enumeration/Makefile.in | 1 + .../event_handlers.c | 109 ++++++++++++++++++ dlls/windows.devices.enumeration/main.c | 40 +++++-- dlls/windows.devices.enumeration/private.h | 5 + 4 files changed, 146 insertions(+), 9 deletions(-) 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 3252587bed1..e0bde936e30 100644 --- a/dlls/windows.devices.enumeration/main.c +++ b/dlls/windows.devices.enumeration/main.c @@ -38,6 +38,8 @@ struct device_watcher { IDeviceWatcher IDeviceWatcher_iface; LONG ref; + + struct list stopped_handlers; };
static inline struct device_watcher *impl_from_IDeviceWatcher( IDeviceWatcher *iface ) @@ -77,6 +79,13 @@ 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; }
@@ -102,7 +111,7 @@ static HRESULT WINAPI device_watcher_add_Added( IDeviceWatcher *iface, ITypedEve EventRegistrationToken *token ) { FIXME( "iface %p, handler %p, token %p stub!\n", iface, handler, token ); - return E_NOTIMPL; + return S_OK; }
static HRESULT WINAPI device_watcher_remove_Added( IDeviceWatcher *iface, EventRegistrationToken token ) @@ -115,7 +124,7 @@ static HRESULT WINAPI device_watcher_add_Updated( IDeviceWatcher *iface, ITypedE EventRegistrationToken *token ) { FIXME( "iface %p, handler %p, token %p stub!\n", iface, handler, token ); - return E_NOTIMPL; + return S_OK; }
static HRESULT WINAPI device_watcher_remove_Updated( IDeviceWatcher *iface, EventRegistrationToken token ) @@ -152,14 +161,18 @@ static HRESULT WINAPI device_watcher_remove_EnumerationCompleted( IDeviceWatcher
static HRESULT WINAPI device_watcher_add_Stopped( IDeviceWatcher *iface, ITypedEventHandler_DeviceWatcher_IInspectable *handler, EventRegistrationToken *token ) { - FIXME( "iface %p, handler %p, token %p stub!\n", iface, handler, token ); - return E_NOTIMPL; + 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 ) { - FIXME( "iface %p, token %#I64x stub!\n", iface, token.value ); - return E_NOTIMPL; + 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 ) @@ -171,13 +184,20 @@ static HRESULT WINAPI device_watcher_Status( IDeviceWatcher *iface, DeviceWatche static HRESULT WINAPI device_watcher_Start( IDeviceWatcher *iface ) { FIXME( "iface %p stub!\n", iface ); - return E_NOTIMPL; + return S_OK; }
static HRESULT WINAPI device_watcher_Stop( IDeviceWatcher *iface ) { - FIXME( "iface %p stub!\n", iface ); - return E_NOTIMPL; + 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 = @@ -337,6 +357,8 @@ static HRESULT WINAPI device_statics2_CreateWatcher( IDeviceInformationStatics2 this->IDeviceWatcher_iface.lpVtbl = &device_watcher_vtbl; this->ref = 1;
+ list_init( &this->stopped_handlers ); + *watcher = &this->IDeviceWatcher_iface; return S_OK; } 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 ) \ { \