-- v2: nsi: Cache nsi device handle. nsi/tests: Add test for change notifications. nsi: Add stub for NsiCancelChangeNotification. nsi: Add stubs for NsiRequestChangeNotification[Ex].
From: Paul Gofman pgofman@codeweavers.com
--- dlls/nsi/nsi.c | 22 ++++++++++++++++++++++ dlls/nsi/nsi.spec | 4 ++-- include/wine/nsi.h | 12 ++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-)
diff --git a/dlls/nsi/nsi.c b/dlls/nsi/nsi.c index 3f324ef555b..e20aa6ef21a 100644 --- a/dlls/nsi/nsi.c +++ b/dlls/nsi/nsi.c @@ -307,3 +307,25 @@ err: CloseHandle( device ); return err; } + +DWORD WINAPI NsiRequestChangeNotification( DWORD unk, const NPI_MODULEID *module, DWORD table, OVERLAPPED *ovr, + HANDLE *handle ) +{ + struct nsi_request_change_notification_ex params; + + TRACE( "%lu %p %lu %p %p stub.\n", unk, module, table, ovr, handle ); + + params.unk = unk; + params.module = module; + params.table = table; + params.ovr = ovr; + params.handle = handle; + return NsiRequestChangeNotificationEx( ¶ms ); +} + +DWORD WINAPI NsiRequestChangeNotificationEx( struct nsi_request_change_notification_ex *params ) +{ + FIXME( "%p stub.\n", params ); + + return ERROR_NOT_SUPPORTED; +} diff --git a/dlls/nsi/nsi.spec b/dlls/nsi/nsi.spec index ba326572fb8..b343b228b9c 100644 --- a/dlls/nsi/nsi.spec +++ b/dlls/nsi/nsi.spec @@ -16,8 +16,8 @@ @ stdcall NsiGetParameterEx(ptr) @ stub NsiRegisterChangeNotification @ stub NsiRegisterChangeNotificationEx -@ stub NsiRequestChangeNotification -@ stub NsiRequestChangeNotificationEx +@ stdcall NsiRequestChangeNotification(long ptr long ptr ptr) +@ stdcall NsiRequestChangeNotificationEx(ptr) @ stub NsiSetAllParameters @ stub NsiSetAllParametersEx @ stub NsiSetAllPersistentParametersWithMask diff --git a/include/wine/nsi.h b/include/wine/nsi.h index af35593b29c..2f9fb0cb6e3 100644 --- a/include/wine/nsi.h +++ b/include/wine/nsi.h @@ -492,6 +492,15 @@ struct nsi_get_parameter_ex UINT data_offset; };
+struct nsi_request_change_notification_ex +{ + DWORD unk; + const NPI_MODULEID *module; + UINT_PTR table; + OVERLAPPED *ovr; + HANDLE *handle; +}; + DWORD WINAPI NsiAllocateAndGetTable( DWORD unk, const NPI_MODULEID *module, DWORD table, void **key_data, DWORD key_size, void **rw_data, DWORD rw_size, void **dynamic_data, DWORD dynamic_size, void **static_data, DWORD static_size, DWORD *count, DWORD unk2 ); @@ -508,5 +517,8 @@ DWORD WINAPI NsiGetAllParametersEx( struct nsi_get_all_parameters_ex *params ); DWORD WINAPI NsiGetParameter( DWORD unk, const NPI_MODULEID *module, DWORD table, const void *key, DWORD key_size, DWORD param_type, void *data, DWORD data_size, DWORD data_offset ); DWORD WINAPI NsiGetParameterEx( struct nsi_get_parameter_ex *params ); +DWORD WINAPI NsiRequestChangeNotification( DWORD unk, const NPI_MODULEID *module, DWORD table, OVERLAPPED *ovr, + HANDLE *handle ); +DWORD WINAPI NsiRequestChangeNotificationEx( struct nsi_request_change_notification_ex *params );
#endif /* __WINE_NSI_H */
From: Paul Gofman pgofman@codeweavers.com
--- dlls/nsi/nsi.c | 7 +++++++ dlls/nsi/nsi.spec | 2 +- include/wine/nsi.h | 1 + 3 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/dlls/nsi/nsi.c b/dlls/nsi/nsi.c index e20aa6ef21a..c00ec4f8684 100644 --- a/dlls/nsi/nsi.c +++ b/dlls/nsi/nsi.c @@ -88,6 +88,13 @@ err: return err; }
+DWORD WINAPI NsiCancelChangeNotification( OVERLAPPED *ovr ) +{ + FIXME( "%p stub.\n", ovr ); + + return ERROR_NOT_SUPPORTED; +} + DWORD WINAPI NsiEnumerateObjectsAllParameters( DWORD unk, DWORD unk2, const NPI_MODULEID *module, DWORD table, void *key_data, DWORD key_size, void *rw_data, DWORD rw_size, void *dynamic_data, DWORD dynamic_size, void *static_data, DWORD static_size, diff --git a/dlls/nsi/nsi.spec b/dlls/nsi/nsi.spec index b343b228b9c..9f1a2472362 100644 --- a/dlls/nsi/nsi.spec +++ b/dlls/nsi/nsi.spec @@ -1,6 +1,6 @@ @ stub NsiAllocateAndGetPersistentDataWithMaskTable @ stdcall NsiAllocateAndGetTable(long ptr long ptr long ptr long ptr long ptr long ptr long) -@ stub NsiCancelChangeNotification +@ stdcall NsiCancelChangeNotification(ptr) @ stub NsiDeregisterChangeNotification @ stub NsiDeregisterChangeNotificationEx @ stdcall NsiEnumerateObjectsAllParameters(long long ptr long ptr long ptr long ptr long ptr long ptr) diff --git a/include/wine/nsi.h b/include/wine/nsi.h index 2f9fb0cb6e3..1a562c3c36d 100644 --- a/include/wine/nsi.h +++ b/include/wine/nsi.h @@ -504,6 +504,7 @@ struct nsi_request_change_notification_ex DWORD WINAPI NsiAllocateAndGetTable( DWORD unk, const NPI_MODULEID *module, DWORD table, void **key_data, DWORD key_size, void **rw_data, DWORD rw_size, void **dynamic_data, DWORD dynamic_size, void **static_data, DWORD static_size, DWORD *count, DWORD unk2 ); +DWORD WINAPI NsiCancelChangeNotification( OVERLAPPED *ovr ); DWORD WINAPI NsiEnumerateObjectsAllParameters( DWORD unk, DWORD unk2, const NPI_MODULEID *module, DWORD table, void *key_data, DWORD key_size, void *rw_data, DWORD rw_size, void *dynamic_data, DWORD dynamic_size, void *static_data, DWORD static_size,
From: Paul Gofman pgofman@codeweavers.com
--- dlls/nsi/tests/nsi.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+)
diff --git a/dlls/nsi/tests/nsi.c b/dlls/nsi/tests/nsi.c index 4cf49993ea1..5b3a6775992 100644 --- a/dlls/nsi/tests/nsi.c +++ b/dlls/nsi/tests/nsi.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include "ntstatus.h" +#define WIN32_NO_STATUS #include "winsock2.h" #include "winternl.h" #include "ws2ipdef.h" @@ -1023,6 +1025,66 @@ static void test_udp_tables( int family ) winetest_pop_context(); }
+void test_change_notifications(void) +{ + struct nsi_request_change_notification_ex params; + HANDLE handle, handle2; + OVERLAPPED ovr, ovr2; + DWORD bytes; + DWORD ret; + BOOL bret; + + memset( &ovr, 0, sizeof(ovr) ); + ovr.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL ); + + 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 ); + + memset( ¶ms, 0, sizeof(params) ); + handle2 = (HANDLE)0xdeadbeef; + memset( &ovr2, 0, sizeof(ovr2) ); + params.module = &NPI_MS_NDIS_MODULEID; + params.table = NSI_NDIS_IFINFO_TABLE; + params.ovr = &ovr2; + params.handle = &handle2; + ret = NsiRequestChangeNotificationEx( ¶ms ); + todo_wine 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() ); + + ret = NsiCancelChangeNotification( NULL ); + todo_wine ok( ret == ERROR_NOT_FOUND, "got %lu.\n", ret ); + + ret = NsiCancelChangeNotification( &ovr ); + todo_wine ok( !ret, "got %lu.\n", ret ); + + 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 ); + + bret = GetOverlappedResult( handle2, &ovr2, &bytes, FALSE ); + todo_wine 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 ); + todo_wine ok( !bret && GetLastError() == ERROR_OPERATION_ABORTED, "got bret %d, err %lu.\n", bret, GetLastError() ); + + ret = NsiRequestChangeNotification( 0, &NPI_MS_NDIS_MODULEID, NSI_NDIS_INDEX_LUID_TABLE, &ovr, &handle ); + 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 ); + ret = NsiCancelChangeNotification( &ovr ); + todo_wine ok( !ret, "got %lu.\n", ret ); + bret = GetOverlappedResult( handle, &ovr, &bytes, FALSE ); + todo_wine ok( !bret && GetLastError() == ERROR_OPERATION_ABORTED, "got bret %d, err %lu.\n", bret, GetLastError() ); +} + START_TEST( nsi ) { test_nsi_api(); @@ -1056,4 +1118,6 @@ START_TEST( nsi ) test_udp_stats( AF_INET6 ); test_udp_tables( AF_INET ); test_udp_tables( AF_INET6 ); + + test_change_notifications(); }
From: Paul Gofman pgofman@codeweavers.com
--- dlls/nsi/nsi.c | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-)
diff --git a/dlls/nsi/nsi.c b/dlls/nsi/nsi.c index c00ec4f8684..c219d59ccf3 100644 --- a/dlls/nsi/nsi.c +++ b/dlls/nsi/nsi.c @@ -30,9 +30,34 @@
WINE_DEFAULT_DEBUG_CHANNEL(nsi);
+static HANDLE nsi_device = INVALID_HANDLE_VALUE; + +BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) +{ + switch (reason) + { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls( hinst ); + break; + case DLL_PROCESS_DETACH: + if (nsi_device != INVALID_HANDLE_VALUE) CloseHandle( nsi_device ); + break; + } + return TRUE; +} + static inline HANDLE get_nsi_device( void ) { - return CreateFileW( L"\\.\Nsi", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); + HANDLE device; + + if (nsi_device == INVALID_HANDLE_VALUE) + { + device = CreateFileW( L"\\.\Nsi", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL ); + if (device != INVALID_HANDLE_VALUE + && InterlockedCompareExchangePointer( &nsi_device, device, INVALID_HANDLE_VALUE ) != INVALID_HANDLE_VALUE) + CloseHandle( device ); + } + return nsi_device; }
DWORD WINAPI NsiAllocateAndGetTable( DWORD unk, const NPI_MODULEID *module, DWORD table, void **key_data, DWORD key_size, @@ -140,11 +165,7 @@ DWORD WINAPI NsiEnumerateObjectsAllParametersEx( struct nsi_enumerate_all_ex *pa (params->key_size + params->rw_size + params->dynamic_size + params->static_size) * params->count;
out = heap_alloc( out_size ); - if (!out) - { - CloseHandle( device ); - return ERROR_OUTOFMEMORY; - } + if (!out) return ERROR_OUTOFMEMORY;
in.module = *params->module; in.first_arg = params->first_arg; @@ -172,7 +193,6 @@ DWORD WINAPI NsiEnumerateObjectsAllParametersEx( struct nsi_enumerate_all_ex *pa }
heap_free( out ); - CloseHandle( device );
return err; } @@ -256,7 +276,6 @@ DWORD WINAPI NsiGetAllParametersEx( struct nsi_get_all_parameters_ex *params ) err: heap_free( out ); heap_free( in ); - CloseHandle( device ); return err; }
@@ -293,11 +312,7 @@ DWORD WINAPI NsiGetParameterEx( struct nsi_get_parameter_ex *params ) if (device == INVALID_HANDLE_VALUE) return GetLastError();
in = heap_alloc( in_size ); - if (!in) - { - err = ERROR_OUTOFMEMORY; - goto err; - } + if (!in) return ERROR_OUTOFMEMORY; in->module = *params->module; in->first_arg = params->first_arg; in->table = params->table; @@ -309,9 +324,7 @@ DWORD WINAPI NsiGetParameterEx( struct nsi_get_parameter_ex *params ) if (!DeviceIoControl( device, IOCTL_NSIPROXY_WINE_GET_PARAMETER, in, in_size, params->data, params->data_size, &received, NULL )) err = GetLastError();
-err: heap_free( in ); - CloseHandle( device ); return err; }