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