windowscodecs: Silence fixme for IID_CMetaBitmapRenderTarget.
[wine.git] / dlls / nsi / nsi.c
blobc5f481efb48f0ba116f29e601de6eb9364656431
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 HANDLE nsi_device = INVALID_HANDLE_VALUE;
34 static HANDLE nsi_device_async = INVALID_HANDLE_VALUE;
36 BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved)
38 switch (reason)
40 case DLL_PROCESS_ATTACH:
41 DisableThreadLibraryCalls( hinst );
42 break;
43 case DLL_PROCESS_DETACH:
44 if (nsi_device != INVALID_HANDLE_VALUE) CloseHandle( nsi_device );
45 if (nsi_device_async != INVALID_HANDLE_VALUE) CloseHandle( nsi_device_async );
46 break;
48 return TRUE;
51 static inline HANDLE get_nsi_device( BOOL async )
53 HANDLE *cached_device = async ? &nsi_device_async : &nsi_device;
54 HANDLE device;
56 if (*cached_device == INVALID_HANDLE_VALUE)
58 device = CreateFileW( L"\\\\.\\Nsi", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
59 async ? FILE_FLAG_OVERLAPPED : 0, NULL );
60 if (device != INVALID_HANDLE_VALUE
61 && InterlockedCompareExchangePointer( cached_device, device, INVALID_HANDLE_VALUE ) != INVALID_HANDLE_VALUE)
62 CloseHandle( device );
64 return *cached_device;
67 DWORD WINAPI NsiAllocateAndGetTable( DWORD unk, const NPI_MODULEID *module, DWORD table, void **key_data, DWORD key_size,
68 void **rw_data, DWORD rw_size, void **dynamic_data, DWORD dynamic_size,
69 void **static_data, DWORD static_size, DWORD *count, DWORD unk2 )
71 DWORD err, num = 64;
72 void *data[4] = { NULL };
73 DWORD sizes[4] = { key_size, rw_size, dynamic_size, static_size };
74 int i, attempt;
76 TRACE( "%ld %p %ld %p %ld %p %ld %p %ld %p %ld %p %ld\n", unk, module, table, key_data, key_size,
77 rw_data, rw_size, dynamic_data, dynamic_size, static_data, static_size, count, unk2 );
79 for (attempt = 0; attempt < 5; attempt++)
81 for (i = 0; i < ARRAY_SIZE(data); i++)
83 if (sizes[i])
85 data[i] = heap_alloc( sizes[i] * num );
86 if (!data[i])
88 err = ERROR_OUTOFMEMORY;
89 goto err;
94 err = NsiEnumerateObjectsAllParameters( unk, 0, module, table, data[0], sizes[0], data[1], sizes[1],
95 data[2], sizes[2], data[3], sizes[3], &num );
96 if (err != ERROR_MORE_DATA) break;
97 TRACE( "Short buffer, attempt %d.\n", attempt );
98 NsiFreeTable( data[0], data[1], data[2], data[3] );
99 memset( data, 0, sizeof(data) );
100 err = NsiEnumerateObjectsAllParameters( unk, 0, module, table, NULL, 0, NULL, 0, NULL, 0, NULL, 0, &num );
101 if (err) return err;
102 err = ERROR_OUTOFMEMORY; /* fail if this is the last attempt */
103 num += num >> 4; /* the tables may grow before the next iteration; get ahead */
106 if (!err)
108 if (sizes[0]) *key_data = data[0];
109 if (sizes[1]) *rw_data = data[1];
110 if (sizes[2]) *dynamic_data = data[2];
111 if (sizes[3]) *static_data = data[3];
112 *count = num;
115 err:
116 if (err) NsiFreeTable( data[0], data[1], data[2], data[3] );
117 return err;
120 DWORD WINAPI NsiCancelChangeNotification( OVERLAPPED *ovr )
122 DWORD err = ERROR_SUCCESS;
124 TRACE( "%p.\n", ovr );
126 if (!ovr) return ERROR_NOT_FOUND;
127 if (!CancelIoEx( get_nsi_device( TRUE ), ovr ))
128 err = GetLastError();
130 return err;
133 DWORD WINAPI NsiEnumerateObjectsAllParameters( DWORD unk, DWORD unk2, const NPI_MODULEID *module, DWORD table,
134 void *key_data, DWORD key_size, void *rw_data, DWORD rw_size,
135 void *dynamic_data, DWORD dynamic_size, void *static_data, DWORD static_size,
136 DWORD *count )
138 struct nsi_enumerate_all_ex params;
139 DWORD err;
141 TRACE( "%ld %ld %p %ld %p %ld %p %ld %p %ld %p %ld %p\n", unk, unk2, module, table, key_data, key_size,
142 rw_data, rw_size, dynamic_data, dynamic_size, static_data, static_size, count );
144 params.unknown[0] = 0;
145 params.unknown[1] = 0;
146 params.module = module;
147 params.table = table;
148 params.first_arg = unk;
149 params.second_arg = unk2;
150 params.key_data = key_data;
151 params.key_size = key_size;
152 params.rw_data = rw_data;
153 params.rw_size = rw_size;
154 params.dynamic_data = dynamic_data;
155 params.dynamic_size = dynamic_size;
156 params.static_data = static_data;
157 params.static_size = static_size;
158 params.count = *count;
160 err = NsiEnumerateObjectsAllParametersEx( &params );
161 *count = params.count;
162 return err;
165 DWORD WINAPI NsiEnumerateObjectsAllParametersEx( struct nsi_enumerate_all_ex *params )
167 DWORD out_size, received, err = ERROR_SUCCESS;
168 HANDLE device = get_nsi_device( FALSE );
169 struct nsiproxy_enumerate_all in;
170 BYTE *out, *ptr;
172 if (device == INVALID_HANDLE_VALUE) return GetLastError();
174 out_size = sizeof(DWORD) +
175 (params->key_size + params->rw_size + params->dynamic_size + params->static_size) * params->count;
177 out = malloc( out_size );
178 if (!out) return ERROR_OUTOFMEMORY;
180 in.module = *params->module;
181 in.first_arg = params->first_arg;
182 in.second_arg = params->second_arg;
183 in.table = params->table;
184 in.key_size = params->key_size;
185 in.rw_size = params->rw_size;
186 in.dynamic_size = params->dynamic_size;
187 in.static_size = params->static_size;
188 in.count = params->count;
190 if (!DeviceIoControl( device, IOCTL_NSIPROXY_WINE_ENUMERATE_ALL, &in, sizeof(in), out, out_size, &received, NULL ))
191 err = GetLastError();
192 if (err == ERROR_SUCCESS || err == ERROR_MORE_DATA)
194 params->count = *(DWORD *)out;
195 ptr = out + sizeof(DWORD);
196 if (params->key_size) memcpy( params->key_data, ptr, params->key_size * params->count );
197 ptr += params->key_size * in.count;
198 if (params->rw_size) memcpy( params->rw_data, ptr, params->rw_size * params->count );
199 ptr += params->rw_size * in.count;
200 if (params->dynamic_size) memcpy( params->dynamic_data, ptr, params->dynamic_size * params->count );
201 ptr += params->dynamic_size * in.count;
202 if (params->static_size) memcpy( params->static_data, ptr, params->static_size * params->count );
205 free( out );
207 return err;
210 void WINAPI NsiFreeTable( void *key_data, void *rw_data, void *dynamic_data, void *static_data )
212 TRACE( "%p %p %p %p\n", key_data, rw_data, dynamic_data, static_data );
213 heap_free( key_data );
214 heap_free( rw_data );
215 heap_free( dynamic_data );
216 heap_free( static_data );
219 DWORD WINAPI NsiGetAllParameters( DWORD unk, const NPI_MODULEID *module, DWORD table, const void *key, DWORD key_size,
220 void *rw_data, DWORD rw_size, void *dynamic_data, DWORD dynamic_size,
221 void *static_data, DWORD static_size )
223 struct nsi_get_all_parameters_ex params;
225 TRACE( "%ld %p %ld %p %ld %p %ld %p %ld %p %ld\n", unk, module, table, key, key_size,
226 rw_data, rw_size, dynamic_data, dynamic_size, static_data, static_size );
228 params.unknown[0] = 0;
229 params.unknown[1] = 0;
230 params.module = module;
231 params.table = table;
232 params.first_arg = unk;
233 params.unknown2 = 0;
234 params.key = key;
235 params.key_size = key_size;
236 params.rw_data = rw_data;
237 params.rw_size = rw_size;
238 params.dynamic_data = dynamic_data;
239 params.dynamic_size = dynamic_size;
240 params.static_data = static_data;
241 params.static_size = static_size;
243 return NsiGetAllParametersEx( &params );
246 DWORD WINAPI NsiGetAllParametersEx( struct nsi_get_all_parameters_ex *params )
248 HANDLE device = get_nsi_device( FALSE );
249 struct nsiproxy_get_all_parameters *in;
250 ULONG in_size = FIELD_OFFSET( struct nsiproxy_get_all_parameters, key[params->key_size] ), received;
251 ULONG out_size = params->rw_size + params->dynamic_size + params->static_size;
252 DWORD err = ERROR_SUCCESS;
253 BYTE *out, *ptr;
255 if (device == INVALID_HANDLE_VALUE) return GetLastError();
257 in = malloc( in_size );
258 out = malloc( out_size );
259 if (!in || !out)
261 err = ERROR_OUTOFMEMORY;
262 goto err;
265 in->module = *params->module;
266 in->first_arg = params->first_arg;
267 in->table = params->table;
268 in->key_size = params->key_size;
269 in->rw_size = params->rw_size;
270 in->dynamic_size = params->dynamic_size;
271 in->static_size = params->static_size;
272 memcpy( in->key, params->key, params->key_size );
274 if (!DeviceIoControl( device, IOCTL_NSIPROXY_WINE_GET_ALL_PARAMETERS, in, in_size, out, out_size, &received, NULL ))
275 err = GetLastError();
276 if (err == ERROR_SUCCESS)
278 ptr = out;
279 if (params->rw_size) memcpy( params->rw_data, ptr, params->rw_size );
280 ptr += params->rw_size;
281 if (params->dynamic_size) memcpy( params->dynamic_data, ptr, params->dynamic_size );
282 ptr += params->dynamic_size;
283 if (params->static_size) memcpy( params->static_data, ptr, params->static_size );
286 err:
287 free( out );
288 free( in );
289 return err;
292 DWORD WINAPI NsiGetParameter( DWORD unk, const NPI_MODULEID *module, DWORD table, const void *key, DWORD key_size,
293 DWORD param_type, void *data, DWORD data_size, DWORD data_offset )
295 struct nsi_get_parameter_ex params;
297 TRACE( "%ld %p %ld %p %ld %ld %p %ld %ld\n", unk, module, table, key, key_size,
298 param_type, data, data_size, data_offset );
300 params.unknown[0] = 0;
301 params.unknown[1] = 0;
302 params.module = module;
303 params.table = table;
304 params.first_arg = unk;
305 params.unknown2 = 0;
306 params.key = key;
307 params.key_size = key_size;
308 params.param_type = param_type;
309 params.data = data;
310 params.data_size = data_size;
311 params.data_offset = data_offset;
312 return NsiGetParameterEx( &params );
315 DWORD WINAPI NsiGetParameterEx( struct nsi_get_parameter_ex *params )
317 HANDLE device = get_nsi_device( FALSE );
318 struct nsiproxy_get_parameter *in;
319 ULONG in_size = FIELD_OFFSET( struct nsiproxy_get_parameter, key[params->key_size] ), received;
320 DWORD err = ERROR_SUCCESS;
322 if (device == INVALID_HANDLE_VALUE) return GetLastError();
324 in = malloc( in_size );
325 if (!in) return ERROR_OUTOFMEMORY;
326 in->module = *params->module;
327 in->first_arg = params->first_arg;
328 in->table = params->table;
329 in->key_size = params->key_size;
330 in->param_type = params->param_type;
331 in->data_offset = params->data_offset;
332 memcpy( in->key, params->key, params->key_size );
334 if (!DeviceIoControl( device, IOCTL_NSIPROXY_WINE_GET_PARAMETER, in, in_size, params->data, params->data_size, &received, NULL ))
335 err = GetLastError();
337 free( in );
338 return err;
341 DWORD WINAPI NsiRequestChangeNotification( DWORD unk, const NPI_MODULEID *module, DWORD table, OVERLAPPED *ovr,
342 HANDLE *handle )
344 struct nsi_request_change_notification_ex params;
346 TRACE( "%lu %p %lu %p %p stub.\n", unk, module, table, ovr, handle );
348 params.unk = unk;
349 params.module = module;
350 params.table = table;
351 params.ovr = ovr;
352 params.handle = handle;
353 return NsiRequestChangeNotificationEx( &params );
356 DWORD WINAPI NsiRequestChangeNotificationEx( struct nsi_request_change_notification_ex *params )
358 HANDLE device = get_nsi_device( TRUE );
359 struct nsiproxy_request_notification *in;
360 ULONG in_size = sizeof(struct nsiproxy_get_parameter), received;
361 OVERLAPPED overlapped, *ovr;
362 DWORD err = ERROR_SUCCESS;
363 DWORD len;
365 TRACE( "%p.\n", params );
367 if (params->unk) FIXME( "unknown parameter %#lx.\n", params->unk );
369 if (device == INVALID_HANDLE_VALUE) return GetLastError();
371 in = malloc( in_size );
372 if (!in) return ERROR_OUTOFMEMORY;
373 in->module = *params->module;
374 in->table = params->table;
376 if (!(ovr = params->ovr))
378 overlapped.hEvent = CreateEventW( NULL, FALSE, FALSE, NULL );
379 ovr = &overlapped;
381 if (!DeviceIoControl( device, IOCTL_NSIPROXY_WINE_CHANGE_NOTIFICATION, in, in_size, NULL, 0, &received, ovr ))
382 err = GetLastError();
383 if (ovr == &overlapped)
385 if (err == ERROR_IO_PENDING)
386 err = GetOverlappedResult( device, ovr, &len, TRUE ) ? 0 : GetLastError();
387 CloseHandle( overlapped.hEvent );
389 else if (params->handle && ovr && err == ERROR_IO_PENDING)
390 *params->handle = device;
392 free( in );
393 return err;