Commit d80101f1 authored by Zebediah Figura's avatar Zebediah Figura Committed by Alexandre Julliard

ntoskrnl.exe: Broadcast device notifications to registered handlers.

Based on a patch by Micah N Gorrell. Signed-off-by: 's avatarZebediah Figura <zfigura@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 6cf777eb
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
#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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment