[MSAFD] Add some parameter checks on send/recv based on wine tests. CORE-12104
[reactos.git] / reactos / dll / win32 / msafd / misc / helpers.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver DLL
4 * FILE: dll/win32/msafd/misc/helpers.c
5 * PURPOSE: Helper DLL management
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Alex Ionescu (alex@relsoft.net)
8 * REVISIONS:
9 * CSH 01/09-2000 Created
10 * Alex 16/07/2004 - Complete Rewrite
11 */
12
13 #include <msafd.h>
14
15 #include <winreg.h>
16
17 #include <wine/debug.h>
18 WINE_DEFAULT_DEBUG_CHANNEL(msafd);
19
20 CRITICAL_SECTION HelperDLLDatabaseLock;
21 LIST_ENTRY HelperDLLDatabaseListHead;
22
23
24 INT
25 SockGetTdiName(
26 PINT AddressFamily,
27 PINT SocketType,
28 PINT Protocol,
29 GROUP Group,
30 DWORD Flags,
31 PUNICODE_STRING TransportName,
32 PVOID *HelperDllContext,
33 PHELPER_DATA *HelperDllData,
34 PDWORD Events)
35 {
36 PHELPER_DATA HelperData;
37 PWSTR Transports;
38 PWSTR Transport;
39 PWINSOCK_MAPPING Mapping;
40 PLIST_ENTRY Helpers;
41 INT Status;
42
43 TRACE("AddressFamily %p, SocketType %p, Protocol %p, Group %u, Flags %lx, TransportName %p, HelperDllContext %p, HelperDllData %p, Events %p\n",
44 AddressFamily, SocketType, Protocol, Group, Flags, TransportName, HelperDllContext, HelperDllData, Events);
45
46 /* Check in our Current Loaded Helpers */
47 for (Helpers = SockHelpersListHead.Flink;
48 Helpers != &SockHelpersListHead;
49 Helpers = Helpers->Flink ) {
50
51 HelperData = CONTAINING_RECORD(Helpers, HELPER_DATA, Helpers);
52
53 /* See if this Mapping works for us */
54 if (SockIsTripleInMapping (HelperData->Mapping,
55 *AddressFamily,
56 *SocketType,
57 *Protocol)) {
58
59 /* Call the Helper Dll function get the Transport Name */
60 if (HelperData->WSHOpenSocket2 == NULL ) {
61
62 /* DLL Doesn't support WSHOpenSocket2, call the old one */
63 HelperData->WSHOpenSocket(AddressFamily,
64 SocketType,
65 Protocol,
66 TransportName,
67 HelperDllContext,
68 Events
69 );
70 } else {
71 HelperData->WSHOpenSocket2(AddressFamily,
72 SocketType,
73 Protocol,
74 Group,
75 Flags,
76 TransportName,
77 HelperDllContext,
78 Events
79 );
80 }
81
82 /* Return the Helper Pointers */
83 *HelperDllData = HelperData;
84 return NO_ERROR;
85 }
86 }
87
88 /* Get the Transports available */
89 Status = SockLoadTransportList(&Transports);
90
91 /* Check for error */
92 if (Status) {
93 WARN("Can't get transport list\n");
94 return Status;
95 }
96
97 /* Loop through each transport until we find one that can satisfy us */
98 for (Transport = Transports;
99 *Transports != 0;
100 Transport += wcslen(Transport) + 1) {
101 TRACE("Transport: %S\n", Transports);
102
103 /* See what mapping this Transport supports */
104 Status = SockLoadTransportMapping(Transport, &Mapping);
105
106 /* Check for error */
107 if (Status) {
108 ERR("Can't get mapping for %S\n", Transports);
109 HeapFree(GlobalHeap, 0, Transports);
110 return Status;
111 }
112
113 /* See if this Mapping works for us */
114 if (SockIsTripleInMapping(Mapping, *AddressFamily, *SocketType, *Protocol)) {
115
116 /* It does, so load the DLL associated with it */
117 Status = SockLoadHelperDll(Transport, Mapping, &HelperData);
118
119 /* Check for error */
120 if (Status) {
121 ERR("Can't load helper DLL for Transport %S.\n", Transport);
122 HeapFree(GlobalHeap, 0, Transports);
123 HeapFree(GlobalHeap, 0, Mapping);
124 return Status;
125 }
126
127 /* Call the Helper Dll function get the Transport Name */
128 if (HelperData->WSHOpenSocket2 == NULL) {
129 /* DLL Doesn't support WSHOpenSocket2, call the old one */
130 HelperData->WSHOpenSocket(AddressFamily,
131 SocketType,
132 Protocol,
133 TransportName,
134 HelperDllContext,
135 Events
136 );
137 } else {
138 HelperData->WSHOpenSocket2(AddressFamily,
139 SocketType,
140 Protocol,
141 Group,
142 Flags,
143 TransportName,
144 HelperDllContext,
145 Events
146 );
147 }
148
149 /* Return the Helper Pointers */
150 *HelperDllData = HelperData;
151 /* We actually cache these ... the can't be freed yet */
152 /*HeapFree(GlobalHeap, 0, Transports);*/
153 /*HeapFree(GlobalHeap, 0, Mapping);*/
154 return NO_ERROR;
155 }
156
157 HeapFree(GlobalHeap, 0, Mapping);
158 }
159 HeapFree(GlobalHeap, 0, Transports);
160 return WSAEINVAL;
161 }
162
163 INT
164 SockLoadTransportMapping(
165 PWSTR TransportName,
166 PWINSOCK_MAPPING *Mapping)
167 {
168 PWSTR TransportKey;
169 HKEY KeyHandle;
170 ULONG MappingSize;
171 LONG Status;
172
173 TRACE("TransportName %ws\n", TransportName);
174
175 /* Allocate a Buffer */
176 TransportKey = HeapAlloc(GlobalHeap, 0, (54 + wcslen(TransportName)) * sizeof(WCHAR));
177
178 /* Check for error */
179 if (TransportKey == NULL) {
180 ERR("Buffer allocation failed\n");
181 return WSAEINVAL;
182 }
183
184 /* Generate the right key name */
185 wcscpy(TransportKey, L"System\\CurrentControlSet\\Services\\");
186 wcscat(TransportKey, TransportName);
187 wcscat(TransportKey, L"\\Parameters\\Winsock");
188
189 /* Open the Key */
190 Status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TransportKey, 0, KEY_READ, &KeyHandle);
191
192 /* We don't need the Transport Key anymore */
193 HeapFree(GlobalHeap, 0, TransportKey);
194
195 /* Check for error */
196 if (Status) {
197 ERR("Error reading transport mapping registry\n");
198 return WSAEINVAL;
199 }
200
201 /* Find out how much space we need for the Mapping */
202 Status = RegQueryValueExW(KeyHandle, L"Mapping", NULL, NULL, NULL, &MappingSize);
203
204 /* Check for error */
205 if (Status) {
206 ERR("Error reading transport mapping registry\n");
207 return WSAEINVAL;
208 }
209
210 /* Allocate Memory for the Mapping */
211 *Mapping = HeapAlloc(GlobalHeap, 0, MappingSize);
212
213 /* Check for error */
214 if (*Mapping == NULL) {
215 ERR("Buffer allocation failed\n");
216 return WSAEINVAL;
217 }
218
219 /* Read the Mapping */
220 Status = RegQueryValueExW(KeyHandle, L"Mapping", NULL, NULL, (LPBYTE)*Mapping, &MappingSize);
221
222 /* Check for error */
223 if (Status) {
224 ERR("Error reading transport mapping registry\n");
225 HeapFree(GlobalHeap, 0, *Mapping);
226 return WSAEINVAL;
227 }
228
229 /* Close key and return */
230 RegCloseKey(KeyHandle);
231 return 0;
232 }
233
234 INT
235 SockLoadTransportList(
236 PWSTR *TransportList)
237 {
238 ULONG TransportListSize;
239 HKEY KeyHandle;
240 LONG Status;
241
242 TRACE("Called\n");
243
244 /* Open the Transports Key */
245 Status = RegOpenKeyExW (HKEY_LOCAL_MACHINE,
246 L"SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters",
247 0,
248 KEY_READ,
249 &KeyHandle);
250
251 /* Check for error */
252 if (Status) {
253 ERR("Error reading transport list registry\n");
254 return WSAEINVAL;
255 }
256
257 /* Get the Transport List Size */
258 Status = RegQueryValueExW(KeyHandle,
259 L"Transports",
260 NULL,
261 NULL,
262 NULL,
263 &TransportListSize);
264
265 /* Check for error */
266 if (Status) {
267 ERR("Error reading transport list registry\n");
268 return WSAEINVAL;
269 }
270
271 /* Allocate Memory for the Transport List */
272 *TransportList = HeapAlloc(GlobalHeap, 0, TransportListSize);
273
274 /* Check for error */
275 if (*TransportList == NULL) {
276 ERR("Buffer allocation failed\n");
277 return WSAEINVAL;
278 }
279
280 /* Get the Transports */
281 Status = RegQueryValueExW (KeyHandle,
282 L"Transports",
283 NULL,
284 NULL,
285 (LPBYTE)*TransportList,
286 &TransportListSize);
287
288 /* Check for error */
289 if (Status) {
290 ERR("Error reading transport list registry\n");
291 HeapFree(GlobalHeap, 0, *TransportList);
292 return WSAEINVAL;
293 }
294
295 /* Close key and return */
296 RegCloseKey(KeyHandle);
297 return 0;
298 }
299
300 INT
301 SockLoadHelperDll(
302 PWSTR TransportName,
303 PWINSOCK_MAPPING Mapping,
304 PHELPER_DATA *HelperDllData)
305 {
306 PHELPER_DATA HelperData;
307 PWSTR HelperDllName;
308 PWSTR FullHelperDllName;
309 PWSTR HelperKey;
310 HKEY KeyHandle;
311 ULONG DataSize;
312 LONG Status;
313
314 /* Allocate space for the Helper Structure and TransportName */
315 HelperData = HeapAlloc(GlobalHeap, 0, sizeof(*HelperData) + (wcslen(TransportName) + 1) * sizeof(WCHAR));
316
317 /* Check for error */
318 if (HelperData == NULL) {
319 ERR("Buffer allocation failed\n");
320 return WSAEINVAL;
321 }
322
323 /* Allocate Space for the Helper DLL Key */
324 HelperKey = HeapAlloc(GlobalHeap, 0, (54 + wcslen(TransportName)) * sizeof(WCHAR));
325
326 /* Check for error */
327 if (HelperKey == NULL) {
328 ERR("Buffer allocation failed\n");
329 HeapFree(GlobalHeap, 0, HelperData);
330 return WSAEINVAL;
331 }
332
333 /* Generate the right key name */
334 wcscpy(HelperKey, L"System\\CurrentControlSet\\Services\\");
335 wcscat(HelperKey, TransportName);
336 wcscat(HelperKey, L"\\Parameters\\Winsock");
337
338 /* Open the Key */
339 Status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, HelperKey, 0, KEY_READ, &KeyHandle);
340
341 HeapFree(GlobalHeap, 0, HelperKey);
342
343 /* Check for error */
344 if (Status) {
345 ERR("Error reading helper DLL parameters\n");
346 HeapFree(GlobalHeap, 0, HelperData);
347 return WSAEINVAL;
348 }
349
350 /* Read Size of SockAddr Structures */
351 DataSize = sizeof(HelperData->MinWSAddressLength);
352 HelperData->MinWSAddressLength = 16;
353 RegQueryValueExW (KeyHandle,
354 L"MinSockaddrLength",
355 NULL,
356 NULL,
357 (LPBYTE)&HelperData->MinWSAddressLength,
358 &DataSize);
359 DataSize = sizeof(HelperData->MinWSAddressLength);
360 HelperData->MaxWSAddressLength = 16;
361 RegQueryValueExW (KeyHandle,
362 L"MaxSockaddrLength",
363 NULL,
364 NULL,
365 (LPBYTE)&HelperData->MaxWSAddressLength,
366 &DataSize);
367
368 /* Size of TDI Structures */
369 HelperData->MinTDIAddressLength = HelperData->MinWSAddressLength + 6;
370 HelperData->MaxTDIAddressLength = HelperData->MaxWSAddressLength + 6;
371
372 /* Read Delayed Acceptance Setting */
373 DataSize = sizeof(DWORD);
374 HelperData->UseDelayedAcceptance = FALSE;
375 RegQueryValueExW (KeyHandle,
376 L"UseDelayedAcceptance",
377 NULL,
378 NULL,
379 (LPBYTE)&HelperData->UseDelayedAcceptance,
380 &DataSize);
381
382 /* Allocate Space for the Helper DLL Names */
383 HelperDllName = HeapAlloc(GlobalHeap, 0, 512);
384
385 /* Check for error */
386 if (HelperDllName == NULL) {
387 ERR("Buffer allocation failed\n");
388 HeapFree(GlobalHeap, 0, HelperData);
389 return WSAEINVAL;
390 }
391
392 FullHelperDllName = HeapAlloc(GlobalHeap, 0, 512);
393
394 /* Check for error */
395 if (FullHelperDllName == NULL) {
396 ERR("Buffer allocation failed\n");
397 HeapFree(GlobalHeap, 0, HelperDllName);
398 HeapFree(GlobalHeap, 0, HelperData);
399 return WSAEINVAL;
400 }
401
402 /* Get the name of the Helper DLL*/
403 DataSize = 512;
404 Status = RegQueryValueExW (KeyHandle,
405 L"HelperDllName",
406 NULL,
407 NULL,
408 (LPBYTE)HelperDllName,
409 &DataSize);
410
411 /* Check for error */
412 if (Status) {
413 ERR("Error reading helper DLL parameters\n");
414 HeapFree(GlobalHeap, 0, FullHelperDllName);
415 HeapFree(GlobalHeap, 0, HelperDllName);
416 HeapFree(GlobalHeap, 0, HelperData);
417 return WSAEINVAL;
418 }
419
420 /* Get the Full name, expanding Environment Strings */
421 ExpandEnvironmentStringsW (HelperDllName,
422 FullHelperDllName,
423 256);
424
425 /* Load the DLL */
426 HelperData->hInstance = LoadLibraryW(FullHelperDllName);
427
428 HeapFree(GlobalHeap, 0, HelperDllName);
429 HeapFree(GlobalHeap, 0, FullHelperDllName);
430
431 if (HelperData->hInstance == NULL) {
432 ERR("Error loading helper DLL\n");
433 HeapFree(GlobalHeap, 0, HelperData);
434 return WSAEINVAL;
435 }
436
437 /* Close Key */
438 RegCloseKey(KeyHandle);
439
440 /* Get the Pointers to the Helper Routines */
441 HelperData->WSHOpenSocket = (PWSH_OPEN_SOCKET)
442 GetProcAddress(HelperData->hInstance,
443 "WSHOpenSocket");
444 HelperData->WSHOpenSocket2 = (PWSH_OPEN_SOCKET2)
445 GetProcAddress(HelperData->hInstance,
446 "WSHOpenSocket2");
447 HelperData->WSHJoinLeaf = (PWSH_JOIN_LEAF)
448 GetProcAddress(HelperData->hInstance,
449 "WSHJoinLeaf");
450 HelperData->WSHNotify = (PWSH_NOTIFY)
451 GetProcAddress(HelperData->hInstance, "WSHNotify");
452 HelperData->WSHGetSocketInformation = (PWSH_GET_SOCKET_INFORMATION)
453 GetProcAddress(HelperData->hInstance,
454 "WSHGetSocketInformation");
455 HelperData->WSHSetSocketInformation = (PWSH_SET_SOCKET_INFORMATION)
456 GetProcAddress(HelperData->hInstance,
457 "WSHSetSocketInformation");
458 HelperData->WSHGetSockaddrType = (PWSH_GET_SOCKADDR_TYPE)
459 GetProcAddress(HelperData->hInstance,
460 "WSHGetSockaddrType");
461 HelperData->WSHGetWildcardSockaddr = (PWSH_GET_WILDCARD_SOCKADDR)
462 GetProcAddress(HelperData->hInstance,
463 "WSHGetWildcardSockaddr");
464 HelperData->WSHGetBroadcastSockaddr = (PWSH_GET_BROADCAST_SOCKADDR)
465 GetProcAddress(HelperData->hInstance,
466 "WSHGetBroadcastSockaddr");
467 HelperData->WSHAddressToString = (PWSH_ADDRESS_TO_STRING)
468 GetProcAddress(HelperData->hInstance,
469 "WSHAddressToString");
470 HelperData->WSHStringToAddress = (PWSH_STRING_TO_ADDRESS)
471 GetProcAddress(HelperData->hInstance,
472 "WSHStringToAddress");
473 HelperData->WSHIoctl = (PWSH_IOCTL)
474 GetProcAddress(HelperData->hInstance,
475 "WSHIoctl");
476
477 /* Save the Mapping Structure and transport name */
478 HelperData->Mapping = Mapping;
479 wcscpy(HelperData->TransportName, TransportName);
480
481 /* Increment Reference Count */
482 HelperData->RefCount = 1;
483
484 /* Add it to our list */
485 InsertHeadList(&SockHelpersListHead, &HelperData->Helpers);
486
487 /* Return Pointers */
488 *HelperDllData = HelperData;
489 return 0;
490 }
491
492 BOOL
493 SockIsTripleInMapping(
494 PWINSOCK_MAPPING Mapping,
495 INT AddressFamily,
496 INT SocketType,
497 INT Protocol)
498 {
499 /* The Windows version returns more detailed information on which of the 3 parameters failed...we should do this later */
500 ULONG Row;
501
502 TRACE("Called, Mapping rows = %d\n", Mapping->Rows);
503
504 /* Loop through Mapping to Find a matching one */
505 for (Row = 0; Row < Mapping->Rows; Row++) {
506 TRACE("Examining: row %d: AF %d type %d proto %d\n",
507 Row,
508 (INT)Mapping->Mapping[Row].AddressFamily,
509 (INT)Mapping->Mapping[Row].SocketType,
510 (INT)Mapping->Mapping[Row].Protocol);
511
512 /* Check of all three values Match */
513 if (((INT)Mapping->Mapping[Row].AddressFamily == AddressFamily) &&
514 ((INT)Mapping->Mapping[Row].SocketType == SocketType) &&
515 ((INT)Mapping->Mapping[Row].Protocol == Protocol)) {
516 TRACE("Found\n");
517 return TRUE;
518 }
519 }
520 WARN("Not found\n");
521 return FALSE;
522 }
523
524 /* EOF */