forked from Mirrors/wine-wine
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>feature/deterministic
parent
6cf777ebd5
commit
d80101f17a
|
@ -1,7 +1,7 @@
|
||||||
MODULE = ntoskrnl.exe
|
MODULE = ntoskrnl.exe
|
||||||
IMPORTLIB = ntoskrnl
|
IMPORTLIB = ntoskrnl
|
||||||
IMPORTS = advapi32 hal msvcrt
|
IMPORTS = advapi32 hal msvcrt
|
||||||
DELAYIMPORTS = setupapi user32
|
DELAYIMPORTS = rpcrt4 setupapi user32
|
||||||
|
|
||||||
EXTRADLLFLAGS = -mno-cygwin
|
EXTRADLLFLAGS = -mno-cygwin
|
||||||
|
|
||||||
|
@ -12,3 +12,6 @@ C_SRCS = \
|
||||||
sync.c
|
sync.c
|
||||||
|
|
||||||
RC_SRCS = ntoskrnl.rc
|
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/wdm.h"
|
||||||
#include "ddk/ntifs.h"
|
#include "ddk/ntifs.h"
|
||||||
#include "wine/debug.h"
|
#include "wine/debug.h"
|
||||||
|
#include "wine/exception.h"
|
||||||
#include "wine/heap.h"
|
#include "wine/heap.h"
|
||||||
#include "wine/rbtree.h"
|
#include "wine/rbtree.h"
|
||||||
|
|
||||||
#include "ntoskrnl_private.h"
|
#include "ntoskrnl_private.h"
|
||||||
|
#include "plugplay.h"
|
||||||
|
|
||||||
#include "initguid.h"
|
#include "initguid.h"
|
||||||
DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
|
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;
|
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.@)
|
* IoSetDeviceInterfaceState (NTOSKRNL.EXE.@)
|
||||||
*/
|
*/
|
||||||
|
@ -756,9 +787,7 @@ NTSTATUS WINAPI IoSetDeviceInterfaceState( UNICODE_STRING *name, BOOLEAN enable
|
||||||
broadcast->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
broadcast->dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||||
broadcast->dbcc_classguid = iface->interface_class;
|
broadcast->dbcc_classguid = iface->interface_class;
|
||||||
lstrcpynW( broadcast->dbcc_name, name->Buffer, namelen + 1 );
|
lstrcpynW( broadcast->dbcc_name, name->Buffer, namelen + 1 );
|
||||||
BroadcastSystemMessageW( BSF_FORCEIFHUNG | BSF_QUERY, NULL, WM_DEVICECHANGE,
|
send_devicechange( enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, broadcast, len );
|
||||||
enable ? DBT_DEVICEARRIVAL : DBT_DEVICEREMOVECOMPLETE, (LPARAM)broadcast );
|
|
||||||
|
|
||||||
heap_free( broadcast );
|
heap_free( broadcast );
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1002,12 +1031,26 @@ static NTSTATUS WINAPI pnp_manager_driver_entry( DRIVER_OBJECT *driver, UNICODE_
|
||||||
void pnp_manager_start(void)
|
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};
|
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;
|
UNICODE_STRING driver_nameU;
|
||||||
|
RPC_WSTR binding_str;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
RPC_STATUS err;
|
||||||
|
|
||||||
RtlInitUnicodeString( &driver_nameU, driver_nameW );
|
RtlInitUnicodeString( &driver_nameU, driver_nameW );
|
||||||
if ((status = IoCreateDriver( &driver_nameU, pnp_manager_driver_entry )))
|
if ((status = IoCreateDriver( &driver_nameU, pnp_manager_driver_entry )))
|
||||||
ERR("Failed to create PnP manager driver, status %#x.\n", status);
|
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 )
|
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 );
|
wine_rb_destroy( &root_pnp_devices, destroy_root_pnp_device, NULL );
|
||||||
IoDeleteDriver( pnp_manager );
|
IoDeleteDriver( pnp_manager );
|
||||||
|
RpcBindingFree( &plugplay_binding_handle );
|
||||||
}
|
}
|
||||||
|
|
||||||
void pnp_manager_enumerate_root_devices( const WCHAR *driver_name )
|
void pnp_manager_enumerate_root_devices( const WCHAR *driver_name )
|
||||||
|
|
|
@ -29,4 +29,5 @@ interface plugplay
|
||||||
plugplay_rpc_handle plugplay_register_listener();
|
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);
|
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_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 );
|
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 )
|
static DWORD WINAPI service_handler( DWORD ctrl, DWORD event_type, LPVOID event_data, LPVOID context )
|
||||||
{
|
{
|
||||||
SERVICE_STATUS status;
|
SERVICE_STATUS status;
|
||||||
|
|
Loading…
Reference in New Issue