wineusb.sys: Move event handling to a single thread.
[wine.git] / dlls / nsi / nsi.c
blob345dce6dfe6406b3270750b96c3f5b706fd1f4d6
1 /*
2 * Network Store Interface
4 * Copyright 2021 Huw Davies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #include "winsock2.h"
21 #include "winternl.h"
22 #include "ws2ipdef.h"
23 #include "iphlpapi.h"
24 #include "netioapi.h"
25 #include "iptypes.h"
26 #include "netiodef.h"
27 #include "wine/nsi.h"
28 #include "wine/heap.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(nsi);
33 static inline HANDLE get_nsi_device( void )
35 return CreateFileW( L"\\\\.\\Nsi", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL );
38 DWORD WINAPI NsiAllocateAndGetTable( DWORD unk, const NPI_MODULEID *module, DWORD table, void **key_data, DWORD key_size,
39 void **rw_data, DWORD rw_size, void **dynamic_data, DWORD dynamic_size,
40 void **static_data, DWORD static_size, DWORD *count, DWORD unk2 )
42 DWORD err, num = 64;
43 void *data[4] = { NULL };
44 DWORD sizes[4] = { key_size, rw_size, dynamic_size, static_size };
45 int i, attempt;
47 TRACE( "%ld %p %ld %p %ld %p %ld %p %ld %p %ld %p %ld\n", unk, module, table, key_data, key_size,
48 rw_data, rw_size, dynamic_data, dynamic_size, static_data, static_size, count, unk2 );
50 for (attempt = 0; attempt < 5; attempt++)
52 for (i = 0; i < ARRAY_SIZE(data); i++)
54 if (sizes[i])
56 data[i] = heap_alloc( sizes[i] * num );
57 if (!data[i])
59 err = ERROR_OUTOFMEMORY;
60 goto err;
65 err = NsiEnumerateObjectsAllParameters( unk, 0, module, table, data[0], sizes[0], data[1], sizes[1],
66 data[2], sizes[2], data[3], sizes[3], &num );
67 if (err != ERROR_MORE_DATA) break;
68 TRACE( "Short buffer, attempt %d.\n", attempt );
69 NsiFreeTable( data[0], data[1], data[2], data[3] );
70 memset( data, 0, sizeof(data) );
71 err = NsiEnumerateObjectsAllParameters( unk, 0, module, table, NULL, 0, NULL, 0, NULL, 0, NULL, 0, &num );
72 if (err) return err;
75 if (!err)
77 if (sizes[0]) *key_data = data[0];
78 if (sizes[1]) *rw_data = data[1];
79 if (sizes[2]) *dynamic_data = data[2];
80 if (sizes[3]) *static_data = data[3];
81 *count = num;
84 err:
85 if (err) NsiFreeTable( data[0], data[1], data[2], data[3] );
86 return err;
89 DWORD WINAPI NsiEnumerateObjectsAllParameters( DWORD unk, DWORD unk2, const NPI_MODULEID *module, DWORD table,
90 void *key_data, DWORD key_size, void *rw_data, DWORD rw_size,
91 void *dynamic_data, DWORD dynamic_size, void *static_data, DWORD static_size,
92 DWORD *count )
94 struct nsi_enumerate_all_ex params;
95 DWORD err;
97 TRACE( "%ld %ld %p %ld %p %ld %p %ld %p %ld %p %ld %p\n", unk, unk2, module, table, key_data, key_size,
98 rw_data, rw_size, dynamic_data, dynamic_size, static_data, static_size, count );
100 params.unknown[0] = 0;
101 params.unknown[1] = 0;
102 params.module = module;
103 params.table = table;
104 params.first_arg = unk;
105 params.second_arg = unk2;
106 params.key_data = key_data;
107 params.key_size = key_size;
108 params.rw_data = rw_data;
109 params.rw_size = rw_size;
110 params.dynamic_data = dynamic_data;
111 params.dynamic_size = dynamic_size;
112 params.static_data = static_data;
113 params.static_size = static_size;
114 params.count = *count;
116 err = NsiEnumerateObjectsAllParametersEx( &params );
117 *count = params.count;
118 return err;
121 DWORD WINAPI NsiEnumerateObjectsAllParametersEx( struct nsi_enumerate_all_ex *params )
123 DWORD out_size, received, err = ERROR_SUCCESS;
124 HANDLE device = get_nsi_device();
125 struct nsiproxy_enumerate_all in;
126 BYTE *out, *ptr;
128 if (device == INVALID_HANDLE_VALUE) return GetLastError();
130 out_size = sizeof(DWORD) +
131 (params->key_size + params->rw_size + params->dynamic_size + params->static_size) * params->count;
133 out = heap_alloc( out_size );
134 if (!out)
136 CloseHandle( device );
137 return ERROR_OUTOFMEMORY;
140 in.module = *params->module;
141 in.first_arg = params->first_arg;
142 in.second_arg = params->second_arg;
143 in.table = params->table;
144 in.key_size = params->key_size;
145 in.rw_size = params->rw_size;
146 in.dynamic_size = params->dynamic_size;
147 in.static_size = params->static_size;
148 in.count = params->count;
150 if (!DeviceIoControl( device, IOCTL_NSIPROXY_WINE_ENUMERATE_ALL, &in, sizeof(in), out, out_size, &received, NULL ))
151 err = GetLastError();
152 if (err == ERROR_SUCCESS || err == ERROR_MORE_DATA)
154 params->count = *(DWORD *)out;
155 ptr = out + sizeof(DWORD);
156 if (params->key_size) memcpy( params->key_data, ptr, params->key_size * params->count );
157 ptr += params->key_size * in.count;
158 if (params->rw_size) memcpy( params->rw_data, ptr, params->rw_size * params->count );
159 ptr += params->rw_size * in.count;
160 if (params->dynamic_size) memcpy( params->dynamic_data, ptr, params->dynamic_size * params->count );
161 ptr += params->dynamic_size * in.count;
162 if (params->static_size) memcpy( params->static_data, ptr, params->static_size * params->count );
165 heap_free( out );
166 CloseHandle( device );
168 return err;
171 void WINAPI NsiFreeTable( void *key_data, void *rw_data, void *dynamic_data, void *static_data )
173 TRACE( "%p %p %p %p\n", key_data, rw_data, dynamic_data, static_data );
174 heap_free( key_data );
175 heap_free( rw_data );
176 heap_free( dynamic_data );
177 heap_free( static_data );
180 DWORD WINAPI NsiGetAllParameters( DWORD unk, const NPI_MODULEID *module, DWORD table, const void *key, DWORD key_size,
181 void *rw_data, DWORD rw_size, void *dynamic_data, DWORD dynamic_size,
182 void *static_data, DWORD static_size )
184 struct nsi_get_all_parameters_ex params;
186 TRACE( "%ld %p %ld %p %ld %p %ld %p %ld %p %ld\n", unk, module, table, key, key_size,
187 rw_data, rw_size, dynamic_data, dynamic_size, static_data, static_size );
189 params.unknown[0] = 0;
190 params.unknown[1] = 0;
191 params.module = module;
192 params.table = table;
193 params.first_arg = unk;
194 params.unknown2 = 0;
195 params.key = key;
196 params.key_size = key_size;
197 params.rw_data = rw_data;
198 params.rw_size = rw_size;
199 params.dynamic_data = dynamic_data;
200 params.dynamic_size = dynamic_size;
201 params.static_data = static_data;
202 params.static_size = static_size;
204 return NsiGetAllParametersEx( &params );
207 DWORD WINAPI NsiGetAllParametersEx( struct nsi_get_all_parameters_ex *params )
209 HANDLE device = get_nsi_device();
210 struct nsiproxy_get_all_parameters *in;
211 ULONG in_size = FIELD_OFFSET( struct nsiproxy_get_all_parameters, key[params->key_size] ), received;
212 ULONG out_size = params->rw_size + params->dynamic_size + params->static_size;
213 DWORD err = ERROR_SUCCESS;
214 BYTE *out, *ptr;
216 if (device == INVALID_HANDLE_VALUE) return GetLastError();
218 in = heap_alloc( in_size );
219 out = heap_alloc( out_size );
220 if (!in || !out)
222 err = ERROR_OUTOFMEMORY;
223 goto err;
226 in->module = *params->module;
227 in->first_arg = params->first_arg;
228 in->table = params->table;
229 in->key_size = params->key_size;
230 in->rw_size = params->rw_size;
231 in->dynamic_size = params->dynamic_size;
232 in->static_size = params->static_size;
233 memcpy( in->key, params->key, params->key_size );
235 if (!DeviceIoControl( device, IOCTL_NSIPROXY_WINE_GET_ALL_PARAMETERS, in, in_size, out, out_size, &received, NULL ))
236 err = GetLastError();
237 if (err == ERROR_SUCCESS)
239 ptr = out;
240 if (params->rw_size) memcpy( params->rw_data, ptr, params->rw_size );
241 ptr += params->rw_size;
242 if (params->dynamic_size) memcpy( params->dynamic_data, ptr, params->dynamic_size );
243 ptr += params->dynamic_size;
244 if (params->static_size) memcpy( params->static_data, ptr, params->static_size );
247 err:
248 heap_free( out );
249 heap_free( in );
250 CloseHandle( device );
251 return err;
254 DWORD WINAPI NsiGetParameter( DWORD unk, const NPI_MODULEID *module, DWORD table, const void *key, DWORD key_size,
255 DWORD param_type, void *data, DWORD data_size, DWORD data_offset )
257 struct nsi_get_parameter_ex params;
259 TRACE( "%ld %p %ld %p %ld %ld %p %ld %ld\n", unk, module, table, key, key_size,
260 param_type, data, data_size, data_offset );
262 params.unknown[0] = 0;
263 params.unknown[1] = 0;
264 params.module = module;
265 params.table = table;
266 params.first_arg = unk;
267 params.unknown2 = 0;
268 params.key = key;
269 params.key_size = key_size;
270 params.param_type = param_type;
271 params.data = data;
272 params.data_size = data_size;
273 params.data_offset = data_offset;
274 return NsiGetParameterEx( &params );
277 DWORD WINAPI NsiGetParameterEx( struct nsi_get_parameter_ex *params )
279 HANDLE device = get_nsi_device();
280 struct nsiproxy_get_parameter *in;
281 ULONG in_size = FIELD_OFFSET( struct nsiproxy_get_parameter, key[params->key_size] ), received;
282 DWORD err = ERROR_SUCCESS;
284 if (device == INVALID_HANDLE_VALUE) return GetLastError();
286 in = heap_alloc( in_size );
287 if (!in)
289 err = ERROR_OUTOFMEMORY;
290 goto err;
292 in->module = *params->module;
293 in->first_arg = params->first_arg;
294 in->table = params->table;
295 in->key_size = params->key_size;
296 in->param_type = params->param_type;
297 in->data_offset = params->data_offset;
298 memcpy( in->key, params->key, params->key_size );
300 if (!DeviceIoControl( device, IOCTL_NSIPROXY_WINE_GET_PARAMETER, in, in_size, params->data, params->data_size, &received, NULL ))
301 err = GetLastError();
303 err:
304 heap_free( in );
305 CloseHandle( device );
306 return err;