[PATCH 2/4] ntoskrnl.exe: Broadcast device notifications to registered handlers.
Zebediah Figura
z.figura12 at gmail.com
Tue May 5 11:25:39 CDT 2020
Based on a patch by Micah N Gorrell.
Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
dlls/ntoskrnl.exe/Makefile.in | 5 +++-
dlls/ntoskrnl.exe/plugplay.idl | 2 ++
dlls/ntoskrnl.exe/pnp.c | 50 ++++++++++++++++++++++++++++++++--
include/wine/plugplay.idl | 1 +
programs/plugplay/main.c | 28 +++++++++++++++++++
5 files changed, 82 insertions(+), 4 deletions(-)
create mode 100644 dlls/ntoskrnl.exe/plugplay.idl
diff --git a/dlls/ntoskrnl.exe/Makefile.in b/dlls/ntoskrnl.exe/Makefile.in
index 67afa8f9d8a..85bc1ce6987 100644
--- a/dlls/ntoskrnl.exe/Makefile.in
+++ b/dlls/ntoskrnl.exe/Makefile.in
@@ -1,7 +1,7 @@
MODULE = ntoskrnl.exe
IMPORTLIB = ntoskrnl
IMPORTS = advapi32 hal msvcrt
-DELAYIMPORTS = setupapi user32
+DELAYIMPORTS = rpcrt4 setupapi user32
EXTRADLLFLAGS = -mno-cygwin
@@ -12,3 +12,6 @@ C_SRCS = \
sync.c
RC_SRCS = ntoskrnl.rc
+
+IDL_SRCS = \
+ plugplay.idl
diff --git a/dlls/ntoskrnl.exe/plugplay.idl b/dlls/ntoskrnl.exe/plugplay.idl
new file mode 100644
index 00000000000..05e040388e4
--- /dev/null
+++ b/dlls/ntoskrnl.exe/plugplay.idl
@@ -0,0 +1,2 @@
+#pragma makedep client
+#include "wine/plugplay.idl"
diff --git a/dlls/ntoskrnl.exe/pnp.c b/dlls/ntoskrnl.exe/pnp.c
index 9e4c2c1416a..470e2368fb5 100644
--- a/dlls/ntoskrnl.exe/pnp.c
+++ b/dlls/ntoskrnl.exe/pnp.c
@@ -39,10 +39,12 @@
#include "ddk/wdm.h"
#include "ddk/ntifs.h"
#include "wine/debug.h"
+#include "wine/exception.h"
#include "wine/heap.h"
#include "wine/rbtree.h"
#include "ntoskrnl_private.h"
+#include "plugplay.h"
#include "initguid.h"
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
@@ -651,6 +653,35 @@ static NTSTATUS create_device_symlink( DEVICE_OBJECT *device, UNICODE_STRING *sy
return ret;
}
+void __RPC_FAR * __RPC_USER MIDL_user_allocate( SIZE_T len )
+{
+ return heap_alloc( len );
+}
+
+void __RPC_USER MIDL_user_free( void __RPC_FAR *ptr )
+{
+ heap_free( ptr );
+}
+
+static LONG WINAPI rpc_filter( EXCEPTION_POINTERS *eptr )
+{
+ return I_RpcExceptionFilter( eptr->ExceptionRecord->ExceptionCode );
+}
+
+static void send_devicechange( DWORD code, void *data, unsigned int size )
+{
+ BroadcastSystemMessageW( BSF_FORCEIFHUNG | BSF_QUERY, NULL, WM_DEVICECHANGE, code, (LPARAM)data );
+ __TRY
+ {
+ plugplay_send_event( code, data, size );
+ }
+ __EXCEPT(rpc_filter)
+ {
+ WARN("Failed to send event, exception %#x.\n", GetExceptionCode());
+ }
+ __ENDTRY
+}
+
/***********************************************************************
* IoSetDeviceInterfaceState (NTOSKRNL.EXE.@)
*/
@@ -756,9 +787,7 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable
broadcast->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
broadcast->dbcc_classguid = iface->interface_class;
lstrcpynW( broadcast->dbcc_name, name->Buffer, namelen + 1 );
- BroadcastSystemMessageW( BSF_FORCEIFHUNG | BSF_QUERY, NULL, WM_DEVICECHANGE,
- enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, (LPARAM)broadcast );
-
+ send_devicechange( enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, broadcast, len );
heap_free( broadcast );
}
return ret;
@@ -1002,12 +1031,26 @@ static NTSTATUS WINAPI pnp_manager_driver_entry( DRIVER_OBJECT *driver, UNICODE_
void pnp_manager_start(void)
{
static const WCHAR driver_nameW[] = {'\\','D','r','i','v','e','r','\\','P','n','p','M','a','n','a','g','e','r',0};
+ WCHAR endpoint[] = L"\\pipe\\wine_plugplay";
+ WCHAR protseq[] = L"ncalrpc";
UNICODE_STRING driver_nameU;
+ RPC_WSTR binding_str;
NTSTATUS status;
+ RPC_STATUS err;
RtlInitUnicodeString( &driver_nameU, driver_nameW );
if ((status = IoCreateDriver( &driver_nameU, pnp_manager_driver_entry )))
ERR("Failed to create PnP manager driver, status %#x.\n", status);
+
+ if ((err = RpcStringBindingComposeW( NULL, protseq, NULL, endpoint, NULL, &binding_str )))
+ {
+ ERR("RpcStringBindingCompose() failed, error %#x\n", err);
+ return;
+ }
+ err = RpcBindingFromStringBindingW( binding_str, &plugplay_binding_handle );
+ RpcStringFreeW( &binding_str );
+ if (err)
+ ERR("RpcBindingFromStringBinding() failed, error %#x\n", err);
}
static void destroy_root_pnp_device( struct wine_rb_entry *entry, void *context )
@@ -1020,6 +1063,7 @@ void pnp_manager_stop(void)
{
wine_rb_destroy( &root_pnp_devices, destroy_root_pnp_device, NULL );
IoDeleteDriver( pnp_manager );
+ RpcBindingFree( &plugplay_binding_handle );
}
void pnp_manager_enumerate_root_devices( const WCHAR *driver_name )
diff --git a/include/wine/plugplay.idl b/include/wine/plugplay.idl
index 7cc59191248..8123b733ad1 100644
--- a/include/wine/plugplay.idl
+++ b/include/wine/plugplay.idl
@@ -29,4 +29,5 @@ interface plugplay
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);
}
diff --git a/programs/plugplay/main.c b/programs/plugplay/main.c
index 59561dca503..00af2b0adfa 100644
--- a/programs/plugplay/main.c
+++ b/programs/plugplay/main.c
@@ -136,6 +136,34 @@ 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 )
+{
+ struct listener *listener;
+ struct event *event;
+
+ EnterCriticalSection( &plugplay_cs );
+
+ LIST_FOR_EACH_ENTRY(listener, &listener_list, struct listener, entry)
+ {
+ if (!(event = malloc( sizeof(*event) )))
+ break;
+
+ if (!(event->data = malloc( size )))
+ {
+ free( event );
+ break;
+ }
+
+ event->code = code;
+ memcpy( event->data, data, size );
+ event->size = size;
+ list_add_tail( &listener->events, &event->entry );
+ WakeConditionVariable( &listener->cv );
+ }
+
+ LeaveCriticalSection( &plugplay_cs );
+}
+
static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context )
{
SERVICE_STATUS status;
--
2.26.2
More information about the wine-devel
mailing list