2021-06-25 09:22:44 +00:00
|
|
|
/*
|
|
|
|
* Network Store Interface
|
|
|
|
*
|
|
|
|
* Copyright 2021 Huw Davies
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
#include "winsock2.h"
|
|
|
|
#include "winternl.h"
|
|
|
|
#include "ws2ipdef.h"
|
|
|
|
#include "iphlpapi.h"
|
|
|
|
#include "netioapi.h"
|
|
|
|
#include "iptypes.h"
|
|
|
|
#include "netiodef.h"
|
|
|
|
#include "wine/nsi.h"
|
2021-06-29 07:04:22 +00:00
|
|
|
#include "wine/heap.h"
|
2021-06-25 09:22:44 +00:00
|
|
|
#include "wine/debug.h"
|
|
|
|
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(nsi);
|
|
|
|
|
2021-06-29 07:04:22 +00:00
|
|
|
static inline HANDLE get_nsi_device( void )
|
|
|
|
{
|
|
|
|
return CreateFileW( L"\\\\.\\Nsi", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
|
|
|
|
}
|
|
|
|
|
2021-06-25 09:22:44 +00:00
|
|
|
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 )
|
|
|
|
{
|
2021-06-30 08:59:25 +00:00
|
|
|
DWORD err, num = 0;
|
|
|
|
void *data[4] = { NULL };
|
|
|
|
DWORD sizes[4] = { key_size, rw_size, dynamic_size, static_size };
|
|
|
|
int i, attempt;
|
|
|
|
|
|
|
|
TRACE( "%d %p %d %p %d %p %d %p %d %p %d %p %d\n", unk, module, table, key_data, key_size,
|
2021-06-25 09:22:44 +00:00
|
|
|
rw_data, rw_size, dynamic_data, dynamic_size, static_data, static_size, count, unk2 );
|
2021-06-30 08:59:25 +00:00
|
|
|
|
|
|
|
for (attempt = 0; attempt < 5; attempt++)
|
|
|
|
{
|
|
|
|
err = NsiEnumerateObjectsAllParameters( unk, 0, module, table, NULL, 0, NULL, 0, NULL, 0, NULL, 0, &num );
|
|
|
|
if (err) return err;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(data); i++)
|
|
|
|
{
|
|
|
|
if (sizes[i])
|
|
|
|
{
|
|
|
|
data[i] = heap_alloc( sizes[i] * num );
|
|
|
|
if (!data[i])
|
|
|
|
{
|
|
|
|
err = ERROR_OUTOFMEMORY;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = NsiEnumerateObjectsAllParameters( unk, 0, module, table, data[0], sizes[0], data[1], sizes[1],
|
|
|
|
data[2], sizes[2], data[3], sizes[3], &num );
|
|
|
|
if (err != ERROR_MORE_DATA) break;
|
|
|
|
|
|
|
|
NsiFreeTable( data[0], data[1], data[2], data[3] );
|
|
|
|
memset( data, 0, sizeof(data) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!err)
|
|
|
|
{
|
|
|
|
if (sizes[0]) *key_data = data[0];
|
|
|
|
if (sizes[1]) *rw_data = data[1];
|
|
|
|
if (sizes[2]) *dynamic_data = data[2];
|
|
|
|
if (sizes[3]) *static_data = data[3];
|
|
|
|
*count = num;
|
|
|
|
}
|
|
|
|
|
|
|
|
err:
|
|
|
|
if (err) NsiFreeTable( data[0], data[1], data[2], data[3] );
|
|
|
|
return err;
|
2021-06-25 09:22:44 +00:00
|
|
|
}
|
|
|
|
|
2021-06-28 07:35:47 +00:00
|
|
|
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,
|
|
|
|
DWORD *count )
|
|
|
|
{
|
2021-06-28 07:35:48 +00:00
|
|
|
struct nsi_enumerate_all_ex params;
|
|
|
|
DWORD err;
|
|
|
|
|
2021-06-29 07:04:22 +00:00
|
|
|
TRACE( "%d %d %p %d %p %d %p %d %p %d %p %d %p\n", unk, unk2, module, table, key_data, key_size,
|
2021-06-28 07:35:47 +00:00
|
|
|
rw_data, rw_size, dynamic_data, dynamic_size, static_data, static_size, count );
|
2021-06-28 07:35:48 +00:00
|
|
|
|
|
|
|
params.unknown[0] = 0;
|
|
|
|
params.unknown[1] = 0;
|
|
|
|
params.module = module;
|
|
|
|
params.table = table;
|
|
|
|
params.first_arg = unk;
|
|
|
|
params.second_arg = unk2;
|
|
|
|
params.key_data = key_data;
|
|
|
|
params.key_size = key_size;
|
|
|
|
params.rw_data = rw_data;
|
|
|
|
params.rw_size = rw_size;
|
|
|
|
params.dynamic_data = dynamic_data;
|
|
|
|
params.dynamic_size = dynamic_size;
|
|
|
|
params.static_data = static_data;
|
|
|
|
params.static_size = static_size;
|
|
|
|
params.count = *count;
|
|
|
|
|
|
|
|
err = NsiEnumerateObjectsAllParametersEx( ¶ms );
|
|
|
|
*count = params.count;
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD WINAPI NsiEnumerateObjectsAllParametersEx( struct nsi_enumerate_all_ex *params )
|
|
|
|
{
|
2021-06-29 07:04:22 +00:00
|
|
|
DWORD out_size, received, err = ERROR_SUCCESS;
|
|
|
|
HANDLE device = get_nsi_device();
|
|
|
|
struct nsiproxy_enumerate_all in;
|
|
|
|
BYTE *out, *ptr;
|
|
|
|
|
|
|
|
if (device == INVALID_HANDLE_VALUE) return GetLastError();
|
|
|
|
|
|
|
|
out_size = sizeof(DWORD) +
|
|
|
|
(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;
|
|
|
|
}
|
|
|
|
|
|
|
|
in.module = *params->module;
|
|
|
|
in.first_arg = params->first_arg;
|
|
|
|
in.second_arg = params->second_arg;
|
|
|
|
in.table = params->table;
|
|
|
|
in.key_size = params->key_size;
|
|
|
|
in.rw_size = params->rw_size;
|
|
|
|
in.dynamic_size = params->dynamic_size;
|
|
|
|
in.static_size = params->static_size;
|
|
|
|
in.count = params->count;
|
|
|
|
|
|
|
|
if (!DeviceIoControl( device, IOCTL_NSIPROXY_WINE_ENUMERATE_ALL, &in, sizeof(in), out, out_size, &received, NULL ))
|
|
|
|
err = GetLastError();
|
|
|
|
if (err == ERROR_SUCCESS || err == ERROR_MORE_DATA)
|
|
|
|
{
|
|
|
|
params->count = *(DWORD *)out;
|
|
|
|
ptr = out + sizeof(DWORD);
|
|
|
|
if (params->key_size) memcpy( params->key_data, ptr, params->key_size * params->count );
|
|
|
|
ptr += params->key_size * in.count;
|
|
|
|
if (params->rw_size) memcpy( params->rw_data, ptr, params->rw_size * params->count );
|
|
|
|
ptr += params->rw_size * in.count;
|
|
|
|
if (params->dynamic_size) memcpy( params->dynamic_data, ptr, params->dynamic_size * params->count );
|
|
|
|
ptr += params->dynamic_size * in.count;
|
|
|
|
if (params->static_size) memcpy( params->static_data, ptr, params->static_size * params->count );
|
|
|
|
}
|
|
|
|
|
|
|
|
heap_free( out );
|
|
|
|
CloseHandle( device );
|
|
|
|
|
|
|
|
return err;
|
2021-06-28 07:35:47 +00:00
|
|
|
}
|
|
|
|
|
2021-06-25 09:22:44 +00:00
|
|
|
void WINAPI NsiFreeTable( void *key_data, void *rw_data, void *dynamic_data, void *static_data )
|
|
|
|
{
|
2021-06-30 08:59:25 +00:00
|
|
|
TRACE( "%p %p %p %p\n", key_data, rw_data, dynamic_data, static_data );
|
|
|
|
heap_free( key_data );
|
|
|
|
heap_free( rw_data );
|
|
|
|
heap_free( dynamic_data );
|
|
|
|
heap_free( static_data );
|
2021-06-25 09:22:44 +00:00
|
|
|
}
|
2021-06-28 07:35:45 +00:00
|
|
|
|
|
|
|
DWORD WINAPI NsiGetAllParameters( DWORD unk, const NPI_MODULEID *module, DWORD table, const void *key, DWORD key_size,
|
|
|
|
void *rw_data, DWORD rw_size, void *dynamic_data, DWORD dynamic_size,
|
|
|
|
void *static_data, DWORD static_size )
|
|
|
|
{
|
2021-06-28 07:35:49 +00:00
|
|
|
struct nsi_get_all_parameters_ex params;
|
|
|
|
|
2021-07-01 08:27:04 +00:00
|
|
|
TRACE( "%d %p %d %p %d %p %d %p %d %p %d\n", unk, module, table, key, key_size,
|
2021-06-28 07:35:45 +00:00
|
|
|
rw_data, rw_size, dynamic_data, dynamic_size, static_data, static_size );
|
2021-06-28 07:35:49 +00:00
|
|
|
|
|
|
|
params.unknown[0] = 0;
|
|
|
|
params.unknown[1] = 0;
|
|
|
|
params.module = module;
|
|
|
|
params.table = table;
|
|
|
|
params.first_arg = unk;
|
|
|
|
params.unknown2 = 0;
|
|
|
|
params.key = key;
|
|
|
|
params.key_size = key_size;
|
|
|
|
params.rw_data = rw_data;
|
|
|
|
params.rw_size = rw_size;
|
|
|
|
params.dynamic_data = dynamic_data;
|
|
|
|
params.dynamic_size = dynamic_size;
|
|
|
|
params.static_data = static_data;
|
|
|
|
params.static_size = static_size;
|
|
|
|
|
|
|
|
return NsiGetAllParametersEx( ¶ms );
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD WINAPI NsiGetAllParametersEx( struct nsi_get_all_parameters_ex *params )
|
|
|
|
{
|
2021-07-01 08:27:04 +00:00
|
|
|
HANDLE device = get_nsi_device();
|
|
|
|
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;
|
|
|
|
DWORD err = ERROR_SUCCESS;
|
|
|
|
BYTE *out, *ptr;
|
|
|
|
|
|
|
|
if (device == INVALID_HANDLE_VALUE) return GetLastError();
|
|
|
|
|
|
|
|
in = heap_alloc( in_size );
|
|
|
|
out = heap_alloc( out_size );
|
|
|
|
if (!in || !out)
|
|
|
|
{
|
|
|
|
err = ERROR_OUTOFMEMORY;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
in->module = *params->module;
|
|
|
|
in->first_arg = params->first_arg;
|
|
|
|
in->table = params->table;
|
|
|
|
in->key_size = params->key_size;
|
|
|
|
in->rw_size = params->rw_size;
|
|
|
|
in->dynamic_size = params->dynamic_size;
|
|
|
|
in->static_size = params->static_size;
|
|
|
|
memcpy( in->key, params->key, params->key_size );
|
|
|
|
|
|
|
|
if (!DeviceIoControl( device, IOCTL_NSIPROXY_WINE_GET_ALL_PARAMETERS, in, in_size, out, out_size, &received, NULL ))
|
|
|
|
err = GetLastError();
|
|
|
|
if (err == ERROR_SUCCESS)
|
|
|
|
{
|
|
|
|
ptr = out;
|
|
|
|
if (params->rw_size) memcpy( params->rw_data, ptr, params->rw_size );
|
|
|
|
ptr += params->rw_size;
|
|
|
|
if (params->dynamic_size) memcpy( params->dynamic_data, ptr, params->dynamic_size );
|
|
|
|
ptr += params->dynamic_size;
|
|
|
|
if (params->static_size) memcpy( params->static_data, ptr, params->static_size );
|
|
|
|
}
|
|
|
|
|
|
|
|
err:
|
|
|
|
heap_free( out );
|
|
|
|
heap_free( in );
|
|
|
|
CloseHandle( device );
|
|
|
|
return err;
|
2021-06-28 07:35:45 +00:00
|
|
|
}
|
2021-06-28 07:35:46 +00:00
|
|
|
|
|
|
|
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 )
|
|
|
|
{
|
2021-06-29 07:04:18 +00:00
|
|
|
struct nsi_get_parameter_ex params;
|
|
|
|
|
2021-07-01 08:27:07 +00:00
|
|
|
TRACE( "%d %p %d %p %d %d %p %d %d\n", unk, module, table, key, key_size,
|
2021-06-28 07:35:46 +00:00
|
|
|
param_type, data, data_size, data_offset );
|
2021-06-29 07:04:18 +00:00
|
|
|
|
|
|
|
params.unknown[0] = 0;
|
|
|
|
params.unknown[1] = 0;
|
|
|
|
params.module = module;
|
|
|
|
params.table = table;
|
|
|
|
params.first_arg = unk;
|
|
|
|
params.unknown2 = 0;
|
|
|
|
params.key = key;
|
|
|
|
params.key_size = key_size;
|
|
|
|
params.param_type = param_type;
|
|
|
|
params.data = data;
|
|
|
|
params.data_size = data_size;
|
|
|
|
params.data_offset = data_offset;
|
|
|
|
return NsiGetParameterEx( ¶ms );
|
|
|
|
}
|
|
|
|
|
|
|
|
DWORD WINAPI NsiGetParameterEx( struct nsi_get_parameter_ex *params )
|
|
|
|
{
|
2021-07-01 08:27:07 +00:00
|
|
|
HANDLE device = get_nsi_device();
|
|
|
|
struct nsiproxy_get_parameter *in;
|
|
|
|
ULONG in_size = FIELD_OFFSET( struct nsiproxy_get_parameter, key[params->key_size] ), received;
|
|
|
|
DWORD err = ERROR_SUCCESS;
|
|
|
|
|
|
|
|
if (device == INVALID_HANDLE_VALUE) return GetLastError();
|
|
|
|
|
|
|
|
in = heap_alloc( in_size );
|
|
|
|
if (!in)
|
|
|
|
{
|
|
|
|
err = ERROR_OUTOFMEMORY;
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
in->module = *params->module;
|
|
|
|
in->first_arg = params->first_arg;
|
|
|
|
in->table = params->table;
|
|
|
|
in->key_size = params->key_size;
|
|
|
|
in->param_type = params->param_type;
|
|
|
|
in->data_offset = params->data_offset;
|
|
|
|
memcpy( in->key, params->key, params->key_size );
|
|
|
|
|
|
|
|
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;
|
2021-06-28 07:35:46 +00:00
|
|
|
}
|