From: Vibhav Pant vibhavp@gmail.com
Instead of sending a raw-bytes array, plugplay_{send, get}_event now accept a DEVICE_BROADCAST union. --- include/wine/plugplay.idl | 4 +- programs/plugplay/main.c | 126 ++++++++++++++++++++++++++++++-------- 2 files changed, 104 insertions(+), 26 deletions(-)
diff --git a/include/wine/plugplay.idl b/include/wine/plugplay.idl index 6dc63cbaa38..5e3c60d8bc7 100644 --- a/include/wine/plugplay.idl +++ b/include/wine/plugplay.idl @@ -65,7 +65,7 @@ interface plugplay typedef [context_handle] void *plugplay_rpc_handle;
plugplay_rpc_handle plugplay_register_listener(); - DWORD plugplay_get_event([in] plugplay_rpc_handle handle, [out, size_is(,*size)] BYTE **data, [out] unsigned int *size); void plugplay_unregister_listener([in] plugplay_rpc_handle handle); - void plugplay_send_event([in] DWORD event_code, [in, size_is(size)] const BYTE *data, [in] unsigned int size); + HRESULT plugplay_send_event([in] DWORD event_code, [in] const DEVICE_BROADCAST *broadcast); + DWORD plugplay_get_event([in] plugplay_rpc_handle handle, [out] DEVICE_BROADCAST *broadcast); } diff --git a/programs/plugplay/main.c b/programs/plugplay/main.c index 8426f2204a3..fe8ffb3dc71 100644 --- a/programs/plugplay/main.c +++ b/programs/plugplay/main.c @@ -19,12 +19,15 @@ #define WIN32_LEAN_AND_MEAN
#include <windows.h> +#include <winternl.h> #include <dbt.h> #include "winsvc.h" #include "wine/debug.h" #include "wine/list.h" #include "plugplay.h"
+#include "wine/dbt.h" + WINE_DEFAULT_DEBUG_CHANNEL(plugplay);
static WCHAR plugplayW[] = L"PlugPlay"; @@ -64,11 +67,9 @@ struct event { struct list entry; DWORD code; - BYTE *data; - unsigned int size; + DEVICE_BROADCAST data; };
- static void destroy_listener( struct listener *listener ) { struct event *event, *next; @@ -79,7 +80,18 @@ static void destroy_listener( struct listener *listener )
LIST_FOR_EACH_ENTRY_SAFE(event, next, &listener->events, struct event, entry) { - MIDL_user_free( event->data ); + switch (event->data.devicetype) + { + case DBT_DEVTYP_HANDLE: + MIDL_user_free( event->data.event.handle.name ); + MIDL_user_free( event->data.event.handle.handle_file_path ); + MIDL_user_free( event->data.event.handle.data ); + break; + case DBT_DEVTYP_DEVICEINTERFACE: + MIDL_user_free( event->data.event.device_interface.name ); + break; + } + list_remove( &event->entry ); free( event ); } @@ -108,7 +120,7 @@ plugplay_rpc_handle __cdecl plugplay_register_listener(void) return listener; }
-DWORD __cdecl plugplay_get_event( plugplay_rpc_handle handle, BYTE **data, unsigned int *size ) +DWORD __cdecl plugplay_get_event( plugplay_rpc_handle handle, DEVICE_BROADCAST *data ) { struct listener *listener = handle; struct event *event; @@ -117,17 +129,16 @@ DWORD __cdecl plugplay_get_event( plugplay_rpc_handle handle, BYTE **data, unsig
EnterCriticalSection( &plugplay_cs );
- while (!(entry = list_head( &listener->events ))) + while(!(entry = list_head( &listener->events ))) SleepConditionVariableCS( &listener->cv, &plugplay_cs, INFINITE );
- event = LIST_ENTRY(entry, struct event, entry); - list_remove( &event->entry ); + event = LIST_ENTRY( entry, struct event, entry ); + list_remove(&event->entry);
LeaveCriticalSection( &plugplay_cs );
ret = event->code; *data = event->data; - *size = event->size; free( event ); return ret; } @@ -137,35 +148,102 @@ void __cdecl plugplay_unregister_listener( plugplay_rpc_handle handle ) destroy_listener( handle ); }
-void __cdecl plugplay_send_event( DWORD code, const BYTE *data, unsigned int size ) +HRESULT __cdecl plugplay_send_event( DWORD event_code, const DEVICE_BROADCAST *data ) { struct listener *listener; - struct event *event; + const WCHAR *name_src = NULL; + DWORD str_size = 0;
- BroadcastSystemMessageW( 0, NULL, WM_DEVICECHANGE, code, (LPARAM)data ); - BroadcastSystemMessageW( 0, NULL, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0 ); + TRACE( "(%#lx, %s)\n", event_code, debugstr_DEVICE_BROADCAST( data ) );
- EnterCriticalSection( &plugplay_cs ); + switch(data->devicetype) + { + case DBT_DEVTYP_HANDLE: + name_src = data->event.handle.name; + break; + case DBT_DEVTYP_DEVICEINTERFACE: + { + const DEVICE_BROADCAST_DEVICEINTERFACE *event = &data->event.device_interface; + DWORD name_len = wcslen( event->name ) + 1; + DWORD dbcc_size = offsetof( DEV_BROADCAST_DEVICEINTERFACE_W, dbcc_name[name_len] ); + DEV_BROADCAST_DEVICEINTERFACE_W *iface; + + name_src = data->event.device_interface.name; + + iface = malloc( dbcc_size ); + if (!iface) break; + iface->dbcc_size = dbcc_size; + iface->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + iface->dbcc_reserved = event->header.reserved; + iface->dbcc_classguid = event->class_guid; + memcpy( iface->dbcc_name, event->name, name_len ); + BroadcastSystemMessageW( 0, NULL, WM_DEVICECHANGE, event_code, (LPARAM)event ); + BroadcastSystemMessageW( 0, NULL, WM_DEVICECHANGE, DBT_DEVNODES_CHANGED, 0 ); + break; + free( iface ); + } + default: + return E_INVALIDARG; + } + str_size = name_src ? (lstrlenW(name_src) + 1) * sizeof(WCHAR) : 0;
+ EnterCriticalSection( &plugplay_cs ); LIST_FOR_EACH_ENTRY(listener, &listener_list, struct listener, entry) { - if (!(event = malloc( sizeof(*event) ))) - break; + struct event *event = calloc( 1, sizeof(*event)); + if (!event) break; + + event->code = event_code;
- if (!(event->data = malloc( size ))) + event->data = *data; + if (data->devicetype == DBT_DEVTYP_HANDLE) { - free( event ); - break; + DWORD size = sizeof(WCHAR) * ( lstrlenW( data->event.handle.handle_file_path ) + 1 ); + event->data.event.handle.handle_file_path = malloc( size ); + if (!event->data.event.handle.handle_file_path) + { + free( event ); + break; + } + memcpy( event->data.event.handle.handle_file_path, data->event.handle.handle_file_path, size ); + + if (data->event.handle.data_size != 0) + { + event->data.event.handle.data = malloc( data->event.handle.data_size ); + if (!event->data.event.handle.data) + { + free( event->data.event.handle.handle_file_path ); + free( event ); + break; + } + memcpy( event->data.event.handle.data, data->event.handle.data, data->event.handle.data_size); + } + } + if (str_size != 0) + { + WCHAR *str = malloc( str_size ); + if (!str) + { + if (data->devicetype == DBT_DEVTYP_HANDLE) + { + free( event->data.event.handle.handle_file_path ); + free( event->data.event.handle.data ); + } + free( event ); + break; + } + memcpy( str, name_src, str_size ); + + if (data->devicetype == DBT_DEVTYP_HANDLE) + event->data.event.handle.name = str; + else + event->data.event.device_interface.name = str; } - - event->code = code; - memcpy( event->data, data, size ); - event->size = size; list_add_tail( &listener->events, &event->entry ); WakeConditionVariable( &listener->cv ); } - LeaveCriticalSection( &plugplay_cs ); + return S_OK; }
static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context )