nsi: Forward request to nsiproxy from NsiRequestChangeNotification().
This commit is contained in:
parent
dbe9f348d4
commit
a72f91f5f5
4 changed files with 108 additions and 16 deletions
|
@ -31,6 +31,7 @@
|
|||
WINE_DEFAULT_DEBUG_CHANNEL(nsi);
|
||||
|
||||
static HANDLE nsi_device = INVALID_HANDLE_VALUE;
|
||||
static HANDLE nsi_device_async = INVALID_HANDLE_VALUE;
|
||||
|
||||
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved)
|
||||
{
|
||||
|
@ -41,23 +42,26 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved)
|
|||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
if (nsi_device != INVALID_HANDLE_VALUE) CloseHandle( nsi_device );
|
||||
if (nsi_device_async != INVALID_HANDLE_VALUE) CloseHandle( nsi_device_async );
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline HANDLE get_nsi_device( void )
|
||||
static inline HANDLE get_nsi_device( BOOL async )
|
||||
{
|
||||
HANDLE *cached_device = async ? &nsi_device_async : &nsi_device;
|
||||
HANDLE device;
|
||||
|
||||
if (nsi_device == INVALID_HANDLE_VALUE)
|
||||
if (*cached_device == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
device = CreateFileW( L"\\\\.\\Nsi", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
|
||||
device = CreateFileW( L"\\\\.\\Nsi", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
|
||||
async ? FILE_FLAG_OVERLAPPED : 0, NULL );
|
||||
if (device != INVALID_HANDLE_VALUE
|
||||
&& InterlockedCompareExchangePointer( &nsi_device, device, INVALID_HANDLE_VALUE ) != INVALID_HANDLE_VALUE)
|
||||
&& InterlockedCompareExchangePointer( cached_device, device, INVALID_HANDLE_VALUE ) != INVALID_HANDLE_VALUE)
|
||||
CloseHandle( device );
|
||||
}
|
||||
return nsi_device;
|
||||
return *cached_device;
|
||||
}
|
||||
|
||||
DWORD WINAPI NsiAllocateAndGetTable( DWORD unk, const NPI_MODULEID *module, DWORD table, void **key_data, DWORD key_size,
|
||||
|
@ -155,7 +159,7 @@ DWORD WINAPI NsiEnumerateObjectsAllParameters( DWORD unk, DWORD unk2, const NPI_
|
|||
DWORD WINAPI NsiEnumerateObjectsAllParametersEx( struct nsi_enumerate_all_ex *params )
|
||||
{
|
||||
DWORD out_size, received, err = ERROR_SUCCESS;
|
||||
HANDLE device = get_nsi_device();
|
||||
HANDLE device = get_nsi_device( FALSE );
|
||||
struct nsiproxy_enumerate_all in;
|
||||
BYTE *out, *ptr;
|
||||
|
||||
|
@ -235,7 +239,7 @@ DWORD WINAPI NsiGetAllParameters( DWORD unk, const NPI_MODULEID *module, DWORD t
|
|||
|
||||
DWORD WINAPI NsiGetAllParametersEx( struct nsi_get_all_parameters_ex *params )
|
||||
{
|
||||
HANDLE device = get_nsi_device();
|
||||
HANDLE device = get_nsi_device( FALSE );
|
||||
struct nsiproxy_get_all_parameters *in;
|
||||
ULONG in_size = FIELD_OFFSET( struct nsiproxy_get_all_parameters, key[params->key_size] ), received;
|
||||
ULONG out_size = params->rw_size + params->dynamic_size + params->static_size;
|
||||
|
@ -304,7 +308,7 @@ DWORD WINAPI NsiGetParameter( DWORD unk, const NPI_MODULEID *module, DWORD table
|
|||
|
||||
DWORD WINAPI NsiGetParameterEx( struct nsi_get_parameter_ex *params )
|
||||
{
|
||||
HANDLE device = get_nsi_device();
|
||||
HANDLE device = get_nsi_device( FALSE );
|
||||
struct nsiproxy_get_parameter *in;
|
||||
ULONG in_size = FIELD_OFFSET( struct nsiproxy_get_parameter, key[params->key_size] ), received;
|
||||
DWORD err = ERROR_SUCCESS;
|
||||
|
@ -345,7 +349,40 @@ DWORD WINAPI NsiRequestChangeNotification( DWORD unk, const NPI_MODULEID *module
|
|||
|
||||
DWORD WINAPI NsiRequestChangeNotificationEx( struct nsi_request_change_notification_ex *params )
|
||||
{
|
||||
FIXME( "%p stub.\n", params );
|
||||
HANDLE device = get_nsi_device( TRUE );
|
||||
struct nsiproxy_request_notification *in;
|
||||
ULONG in_size = sizeof(struct nsiproxy_get_parameter), received;
|
||||
OVERLAPPED overlapped, *ovr;
|
||||
DWORD err = ERROR_SUCCESS;
|
||||
DWORD len;
|
||||
|
||||
return ERROR_NOT_SUPPORTED;
|
||||
TRACE( "%p.\n", params );
|
||||
|
||||
if (params->unk) FIXME( "unknown parameter %#lx.\n", params->unk );
|
||||
|
||||
if (device == INVALID_HANDLE_VALUE) return GetLastError();
|
||||
|
||||
in = malloc( in_size );
|
||||
if (!in) return ERROR_OUTOFMEMORY;
|
||||
in->module = *params->module;
|
||||
in->table = params->table;
|
||||
|
||||
if (!(ovr = params->ovr))
|
||||
{
|
||||
overlapped.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
|
||||
ovr = &overlapped;
|
||||
}
|
||||
if (!DeviceIoControl( device, IOCTL_NSIPROXY_WINE_CHANGE_NOTIFICATION, in, in_size, NULL, 0, &received, ovr ))
|
||||
err = GetLastError();
|
||||
if (ovr == &overlapped)
|
||||
{
|
||||
if (err == ERROR_IO_PENDING)
|
||||
err = GetOverlappedResult( device, ovr, &len, TRUE ) ? 0 : GetLastError();
|
||||
CloseHandle( overlapped.hEvent );
|
||||
}
|
||||
else if (params->handle && ovr && err == ERROR_IO_PENDING)
|
||||
*params->handle = device;
|
||||
|
||||
free( in );
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -1039,7 +1039,7 @@ void test_change_notifications(void)
|
|||
|
||||
handle = (HANDLE)0xdeadbeef;
|
||||
ret = NsiRequestChangeNotification( 0, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, &ovr, &handle );
|
||||
todo_wine ok( ret == ERROR_IO_PENDING, "got %lu.\n", ret );
|
||||
ok( ret == ERROR_IO_PENDING, "got %lu.\n", ret );
|
||||
|
||||
memset( ¶ms, 0, sizeof(params) );
|
||||
handle2 = (HANDLE)0xdeadbeef;
|
||||
|
@ -1049,11 +1049,11 @@ void test_change_notifications(void)
|
|||
params.ovr = &ovr2;
|
||||
params.handle = &handle2;
|
||||
ret = NsiRequestChangeNotificationEx( ¶ms );
|
||||
todo_wine ok( ret == ERROR_IO_PENDING, "got %lu.\n", ret );
|
||||
ok( ret == ERROR_IO_PENDING, "got %lu.\n", ret );
|
||||
|
||||
ok( handle2 == handle, "got %p, %p.\n", handle, handle2 );
|
||||
bret = GetOverlappedResult( handle, &ovr, &bytes, FALSE );
|
||||
todo_wine ok( !bret && GetLastError() == ERROR_IO_INCOMPLETE, "got bret %d, err %lu.\n", bret, GetLastError() );
|
||||
ok( !bret && GetLastError() == ERROR_IO_INCOMPLETE, "got bret %d, err %lu.\n", bret, GetLastError() );
|
||||
|
||||
ret = NsiCancelChangeNotification( NULL );
|
||||
todo_wine ok( ret == ERROR_NOT_FOUND, "got %lu.\n", ret );
|
||||
|
@ -1063,12 +1063,13 @@ void test_change_notifications(void)
|
|||
|
||||
bytes = 0xdeadbeef;
|
||||
bret = GetOverlappedResult( handle, &ovr, &bytes, FALSE );
|
||||
|
||||
todo_wine ok( !bret && GetLastError() == ERROR_OPERATION_ABORTED, "got bret %d, err %lu.\n", bret, GetLastError() );
|
||||
todo_wine ok( ovr.Internal == (ULONG)STATUS_CANCELLED, "got %Ix.\n", ovr.Internal );
|
||||
ok( !bytes, "got %lu.\n", bytes );
|
||||
todo_wine ok( !bytes, "got %lu.\n", bytes );
|
||||
|
||||
bret = GetOverlappedResult( handle2, &ovr2, &bytes, FALSE );
|
||||
todo_wine ok( !bret && GetLastError() == ERROR_IO_INCOMPLETE, "got bret %d, err %lu.\n", bret, GetLastError() );
|
||||
ok( !bret && GetLastError() == ERROR_IO_INCOMPLETE, "got bret %d, err %lu.\n", bret, GetLastError() );
|
||||
ret = NsiCancelChangeNotification( &ovr2 );
|
||||
todo_wine ok( !ret, "got %lu.\n", ret );
|
||||
bret = GetOverlappedResult( handle, &ovr, &bytes, FALSE );
|
||||
|
@ -1078,7 +1079,7 @@ void test_change_notifications(void)
|
|||
todo_wine ok( ret == ERROR_INVALID_PARAMETER, "got %lu.\n", ret );
|
||||
|
||||
ret = NsiRequestChangeNotification( 0, &NPI_MS_IPV4_MODULEID, NSI_IP_FORWARD_TABLE, &ovr, &handle );
|
||||
todo_wine ok( ret == ERROR_IO_PENDING, "got %lu.\n", ret );
|
||||
ok( ret == ERROR_IO_PENDING, "got %lu.\n", ret );
|
||||
ret = NsiCancelChangeNotification( &ovr );
|
||||
todo_wine ok( !ret, "got %lu.\n", ret );
|
||||
bret = GetOverlappedResult( handle, &ovr, &bytes, FALSE );
|
||||
|
|
|
@ -49,6 +49,7 @@ DECLARE_CRITICAL_SECTION( nsiproxy_cs );
|
|||
|
||||
#define LIST_ENTRY_INIT( list ) { .Flink = &(list), .Blink = &(list) }
|
||||
static LIST_ENTRY request_queue = LIST_ENTRY_INIT( request_queue );
|
||||
static LIST_ENTRY notification_queue = LIST_ENTRY_INIT( notification_queue );
|
||||
|
||||
static NTSTATUS nsiproxy_call( unsigned int code, void *args )
|
||||
{
|
||||
|
@ -261,6 +262,47 @@ static NTSTATUS nsiproxy_icmp_echo( IRP *irp )
|
|||
return STATUS_PENDING;
|
||||
}
|
||||
|
||||
static void WINAPI change_notification_cancel( DEVICE_OBJECT *device, IRP *irp )
|
||||
{
|
||||
TRACE( "device %p, irp %p.\n", device, irp );
|
||||
|
||||
IoReleaseCancelSpinLock( irp->CancelIrql );
|
||||
|
||||
EnterCriticalSection( &nsiproxy_cs );
|
||||
RemoveEntryList( &irp->Tail.Overlay.ListEntry );
|
||||
LeaveCriticalSection( &nsiproxy_cs );
|
||||
|
||||
irp->IoStatus.Status = STATUS_CANCELLED;
|
||||
IoCompleteRequest( irp, IO_NO_INCREMENT );
|
||||
}
|
||||
|
||||
static NTSTATUS nsiproxy_change_notification( IRP *irp )
|
||||
{
|
||||
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
|
||||
struct nsiproxy_request_notification *in = (struct nsiproxy_request_notification *)irp->AssociatedIrp.SystemBuffer;
|
||||
DWORD in_len = irpsp->Parameters.DeviceIoControl.InputBufferLength;
|
||||
|
||||
FIXME( "\n" );
|
||||
|
||||
if (in_len < sizeof(*in)) return STATUS_INVALID_PARAMETER;
|
||||
/* FIXME: validate module and table. */
|
||||
|
||||
EnterCriticalSection( &nsiproxy_cs );
|
||||
IoSetCancelRoutine( irp, change_notification_cancel );
|
||||
if (irp->Cancel && !IoSetCancelRoutine( irp, NULL ))
|
||||
{
|
||||
/* IRP was canceled before we set cancel routine */
|
||||
InitializeListHead( &irp->Tail.Overlay.ListEntry );
|
||||
LeaveCriticalSection( &nsiproxy_cs );
|
||||
return STATUS_CANCELLED;
|
||||
}
|
||||
InsertTailList( ¬ification_queue, &irp->Tail.Overlay.ListEntry );
|
||||
IoMarkIrpPending( irp );
|
||||
LeaveCriticalSection( &nsiproxy_cs );
|
||||
|
||||
return STATUS_PENDING;
|
||||
}
|
||||
|
||||
static NTSTATUS WINAPI nsi_ioctl( DEVICE_OBJECT *device, IRP *irp )
|
||||
{
|
||||
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
|
||||
|
@ -289,6 +331,10 @@ static NTSTATUS WINAPI nsi_ioctl( DEVICE_OBJECT *device, IRP *irp )
|
|||
status = nsiproxy_icmp_echo( irp );
|
||||
break;
|
||||
|
||||
case IOCTL_NSIPROXY_WINE_CHANGE_NOTIFICATION:
|
||||
status = nsiproxy_change_notification( irp );
|
||||
break;
|
||||
|
||||
default:
|
||||
FIXME( "ioctl %lx not supported\n", irpsp->Parameters.DeviceIoControl.IoControlCode );
|
||||
status = STATUS_NOT_SUPPORTED;
|
||||
|
|
|
@ -380,6 +380,7 @@ struct nsi_udp_endpoint_static
|
|||
#define IOCTL_NSIPROXY_WINE_GET_ALL_PARAMETERS CTL_CODE(FILE_DEVICE_NETWORK, 0x401, METHOD_BUFFERED, 0)
|
||||
#define IOCTL_NSIPROXY_WINE_GET_PARAMETER CTL_CODE(FILE_DEVICE_NETWORK, 0x402, METHOD_BUFFERED, 0)
|
||||
#define IOCTL_NSIPROXY_WINE_ICMP_ECHO CTL_CODE(FILE_DEVICE_NETWORK, 0x403, METHOD_BUFFERED, 0)
|
||||
#define IOCTL_NSIPROXY_WINE_CHANGE_NOTIFICATION CTL_CODE(FILE_DEVICE_NETWORK, 0x404, METHOD_BUFFERED, 0)
|
||||
|
||||
/* input for IOCTL_NSIPROXY_WINE_ENUMERATE_ALL */
|
||||
struct nsiproxy_enumerate_all
|
||||
|
@ -436,6 +437,13 @@ struct nsiproxy_icmp_echo
|
|||
BYTE data[1]; /* ((opt_size + 3) & ~3) + req_size */
|
||||
};
|
||||
|
||||
/* input for IOCTL_NSIPROXY_WINE_CHANGE_NOTIFICATION */
|
||||
struct nsiproxy_request_notification
|
||||
{
|
||||
NPI_MODULEID module;
|
||||
UINT table;
|
||||
};
|
||||
|
||||
/* Undocumented Nsi api */
|
||||
|
||||
#define NSI_PARAM_TYPE_RW 0
|
||||
|
|
Loading…
Add table
Reference in a new issue