Commit a72f91f5 authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

nsi: Forward request to nsiproxy from NsiRequestChangeNotification().

parent dbe9f348
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(nsi); WINE_DEFAULT_DEBUG_CHANNEL(nsi);
static HANDLE nsi_device = INVALID_HANDLE_VALUE; static HANDLE nsi_device = INVALID_HANDLE_VALUE;
static HANDLE nsi_device_async = INVALID_HANDLE_VALUE;
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved)
{ {
...@@ -41,23 +42,26 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) ...@@ -41,23 +42,26 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved)
break; break;
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
if (nsi_device != INVALID_HANDLE_VALUE) CloseHandle( nsi_device ); if (nsi_device != INVALID_HANDLE_VALUE) CloseHandle( nsi_device );
if (nsi_device_async != INVALID_HANDLE_VALUE) CloseHandle( nsi_device_async );
break; break;
} }
return TRUE; 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; 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 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 ); 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, 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_ ...@@ -155,7 +159,7 @@ DWORD WINAPI NsiEnumerateObjectsAllParameters( DWORD unk, DWORD unk2, const NPI_
DWORD WINAPI NsiEnumerateObjectsAllParametersEx( struct nsi_enumerate_all_ex *params ) DWORD WINAPI NsiEnumerateObjectsAllParametersEx( struct nsi_enumerate_all_ex *params )
{ {
DWORD out_size, received, err = ERROR_SUCCESS; DWORD out_size, received, err = ERROR_SUCCESS;
HANDLE device = get_nsi_device(); HANDLE device = get_nsi_device( FALSE );
struct nsiproxy_enumerate_all in; struct nsiproxy_enumerate_all in;
BYTE *out, *ptr; BYTE *out, *ptr;
...@@ -235,7 +239,7 @@ DWORD WINAPI NsiGetAllParameters( DWORD unk, const NPI_MODULEID *module, DWORD t ...@@ -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 ) 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; struct nsiproxy_get_all_parameters *in;
ULONG in_size = FIELD_OFFSET( struct nsiproxy_get_all_parameters, key[params->key_size] ), received; 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; 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 ...@@ -304,7 +308,7 @@ DWORD WINAPI NsiGetParameter( DWORD unk, const NPI_MODULEID *module, DWORD table
DWORD WINAPI NsiGetParameterEx( struct nsi_get_parameter_ex *params ) 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; struct nsiproxy_get_parameter *in;
ULONG in_size = FIELD_OFFSET( struct nsiproxy_get_parameter, key[params->key_size] ), received; ULONG in_size = FIELD_OFFSET( struct nsiproxy_get_parameter, key[params->key_size] ), received;
DWORD err = ERROR_SUCCESS; DWORD err = ERROR_SUCCESS;
...@@ -345,7 +349,40 @@ DWORD WINAPI NsiRequestChangeNotification( DWORD unk, const NPI_MODULEID *module ...@@ -345,7 +349,40 @@ DWORD WINAPI NsiRequestChangeNotification( DWORD unk, const NPI_MODULEID *module
DWORD WINAPI NsiRequestChangeNotificationEx( struct nsi_request_change_notification_ex *params ) 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) ...@@ -1039,7 +1039,7 @@ void test_change_notifications(void)
handle = (HANDLE)0xdeadbeef; handle = (HANDLE)0xdeadbeef;
ret = NsiRequestChangeNotification( 0, &NPI_MS_NDIS_MODULEID, NSI_NDIS_IFINFO_TABLE, &ovr, &handle ); 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( &params, 0, sizeof(params) ); memset( &params, 0, sizeof(params) );
handle2 = (HANDLE)0xdeadbeef; handle2 = (HANDLE)0xdeadbeef;
...@@ -1049,11 +1049,11 @@ void test_change_notifications(void) ...@@ -1049,11 +1049,11 @@ void test_change_notifications(void)
params.ovr = &ovr2; params.ovr = &ovr2;
params.handle = &handle2; params.handle = &handle2;
ret = NsiRequestChangeNotificationEx( &params ); ret = NsiRequestChangeNotificationEx( &params );
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 ); ok( handle2 == handle, "got %p, %p.\n", handle, handle2 );
bret = GetOverlappedResult( handle, &ovr, &bytes, FALSE ); 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 ); ret = NsiCancelChangeNotification( NULL );
todo_wine ok( ret == ERROR_NOT_FOUND, "got %lu.\n", ret ); todo_wine ok( ret == ERROR_NOT_FOUND, "got %lu.\n", ret );
...@@ -1063,12 +1063,13 @@ void test_change_notifications(void) ...@@ -1063,12 +1063,13 @@ void test_change_notifications(void)
bytes = 0xdeadbeef; bytes = 0xdeadbeef;
bret = GetOverlappedResult( handle, &ovr, &bytes, FALSE ); 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( !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 ); 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 ); 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 ); ret = NsiCancelChangeNotification( &ovr2 );
todo_wine ok( !ret, "got %lu.\n", ret ); todo_wine ok( !ret, "got %lu.\n", ret );
bret = GetOverlappedResult( handle, &ovr, &bytes, FALSE ); bret = GetOverlappedResult( handle, &ovr, &bytes, FALSE );
...@@ -1078,7 +1079,7 @@ void test_change_notifications(void) ...@@ -1078,7 +1079,7 @@ void test_change_notifications(void)
todo_wine ok( ret == ERROR_INVALID_PARAMETER, "got %lu.\n", ret ); todo_wine ok( ret == ERROR_INVALID_PARAMETER, "got %lu.\n", ret );
ret = NsiRequestChangeNotification( 0, &NPI_MS_IPV4_MODULEID, NSI_IP_FORWARD_TABLE, &ovr, &handle ); 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 ); ret = NsiCancelChangeNotification( &ovr );
todo_wine ok( !ret, "got %lu.\n", ret ); todo_wine ok( !ret, "got %lu.\n", ret );
bret = GetOverlappedResult( handle, &ovr, &bytes, FALSE ); bret = GetOverlappedResult( handle, &ovr, &bytes, FALSE );
......
...@@ -49,6 +49,7 @@ DECLARE_CRITICAL_SECTION( nsiproxy_cs ); ...@@ -49,6 +49,7 @@ DECLARE_CRITICAL_SECTION( nsiproxy_cs );
#define LIST_ENTRY_INIT( list ) { .Flink = &(list), .Blink = &(list) } #define LIST_ENTRY_INIT( list ) { .Flink = &(list), .Blink = &(list) }
static LIST_ENTRY request_queue = LIST_ENTRY_INIT( request_queue ); 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 ) static NTSTATUS nsiproxy_call( unsigned int code, void *args )
{ {
...@@ -261,6 +262,47 @@ static NTSTATUS nsiproxy_icmp_echo( IRP *irp ) ...@@ -261,6 +262,47 @@ static NTSTATUS nsiproxy_icmp_echo( IRP *irp )
return STATUS_PENDING; 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( &notification_queue, &irp->Tail.Overlay.ListEntry );
IoMarkIrpPending( irp );
LeaveCriticalSection( &nsiproxy_cs );
return STATUS_PENDING;
}
static NTSTATUS WINAPI nsi_ioctl( DEVICE_OBJECT *device, IRP *irp ) static NTSTATUS WINAPI nsi_ioctl( DEVICE_OBJECT *device, IRP *irp )
{ {
IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp );
...@@ -289,6 +331,10 @@ static NTSTATUS WINAPI nsi_ioctl( DEVICE_OBJECT *device, IRP *irp ) ...@@ -289,6 +331,10 @@ static NTSTATUS WINAPI nsi_ioctl( DEVICE_OBJECT *device, IRP *irp )
status = nsiproxy_icmp_echo( irp ); status = nsiproxy_icmp_echo( irp );
break; break;
case IOCTL_NSIPROXY_WINE_CHANGE_NOTIFICATION:
status = nsiproxy_change_notification( irp );
break;
default: default:
FIXME( "ioctl %lx not supported\n", irpsp->Parameters.DeviceIoControl.IoControlCode ); FIXME( "ioctl %lx not supported\n", irpsp->Parameters.DeviceIoControl.IoControlCode );
status = STATUS_NOT_SUPPORTED; status = STATUS_NOT_SUPPORTED;
......
...@@ -380,6 +380,7 @@ struct nsi_udp_endpoint_static ...@@ -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_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_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_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 */ /* input for IOCTL_NSIPROXY_WINE_ENUMERATE_ALL */
struct nsiproxy_enumerate_all struct nsiproxy_enumerate_all
...@@ -436,6 +437,13 @@ struct nsiproxy_icmp_echo ...@@ -436,6 +437,13 @@ struct nsiproxy_icmp_echo
BYTE data[1]; /* ((opt_size + 3) & ~3) + req_size */ 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 */ /* Undocumented Nsi api */
#define NSI_PARAM_TYPE_RW 0 #define NSI_PARAM_TYPE_RW 0
......
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