mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-06 08:39:34 +00:00
nsi: Forward request to nsiproxy from NsiRequestChangeNotification().
This commit is contained in:
parent
dbe9f348d4
commit
a72f91f5f5
|
@ -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)
|
||||||
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_
|
||||||
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
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
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
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
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( ¶ms, 0, sizeof(params) );
|
memset( ¶ms, 0, sizeof(params) );
|
||||||
handle2 = (HANDLE)0xdeadbeef;
|
handle2 = (HANDLE)0xdeadbeef;
|
||||||
|
@ -1049,11 +1049,11 @@ void test_change_notifications(void)
|
||||||
params.ovr = &ovr2;
|
params.ovr = &ovr2;
|
||||||
params.handle = &handle2;
|
params.handle = &handle2;
|
||||||
ret = NsiRequestChangeNotificationEx( ¶ms );
|
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 );
|
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)
|
||||||
|
|
||||||
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)
|
||||||
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 );
|
||||||
|
|
||||||
#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 )
|
||||||
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( ¬ification_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 )
|
||||||
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
|
||||||
#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
|
||||||
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
|
||||||
|
|
Loading…
Reference in a new issue