ntoskrnl.exe: Broadcast device notifications to registered handlers.
Based on a patch by Micah N Gorrell. Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6cf777ebd5
commit
d80101f17a
|
@ -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
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
#pragma makedep client
|
||||
#include "wine/plugplay.idl"
|
|
@ -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 )
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue