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