* Sync up to trunk HEAD (r62975).
[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
13 #include <msafd.h>
14
15 #include <winreg.h>
16
17 CRITICAL_SECTION HelperDLLDatabaseLock;
18 LIST_ENTRY HelperDLLDatabaseListHead;
19
20
21 INT
22 SockGetTdiName(
23 PINT AddressFamily,
24 PINT SocketType,
25 PINT Protocol,
26 GROUP Group,
27 DWORD Flags,
28 PUNICODE_STRING TransportName,
29 PVOID *HelperDllContext,
30 PHELPER_DATA *HelperDllData,
31 PDWORD Events)
32 {
33 PHELPER_DATA HelperData;
34 PWSTR Transports;
35 PWSTR Transport;
36 PWINSOCK_MAPPING Mapping;
37 PLIST_ENTRY Helpers;
38 INT Status;
39
40 AFD_DbgPrint(MID_TRACE,("Called\n"));
41
42 /* Check in our Current Loaded Helpers */
43 for (Helpers = SockHelpersListHead.Flink;
44 Helpers != &SockHelpersListHead;
45 Helpers = Helpers->Flink ) {
46
47 HelperData = CONTAINING_RECORD(Helpers, HELPER_DATA, Helpers);
48
49 /* See if this Mapping works for us */
50 if (SockIsTripleInMapping (HelperData->Mapping,
51 *AddressFamily,
52 *SocketType,
53 *Protocol)) {
54
55 /* Call the Helper Dll function get the Transport Name */
56 if (HelperData->WSHOpenSocket2 == NULL ) {
57
58 /* DLL Doesn't support WSHOpenSocket2, call the old one */
59 HelperData->WSHOpenSocket(AddressFamily,
60 SocketType,
61 Protocol,
62 TransportName,
63 HelperDllContext,
64 Events
65 );
66 } else {
67 HelperData->WSHOpenSocket2(AddressFamily,
68 SocketType,
69 Protocol,
70 Group,
71 Flags,
72 TransportName,
73 HelperDllContext,
74 Events
75 );
76 }
77
78 /* Return the Helper Pointers */
79 *HelperDllData = HelperData;
80 return NO_ERROR;
81 }
82 }
83
84 /* Get the Transports available */
85 Status = SockLoadTransportList(&Transports);
86
87 /* Check for error */
88 if (Status) {
89 AFD_DbgPrint(MIN_TRACE, ("Can't get transport list\n"));
90 return Status;
91 }
92
93 /* Loop through each transport until we find one that can satisfy us */
94 for (Transport = Transports;
95 *Transports != 0;
96 Transport += wcslen(Transport) + 1) {
97 AFD_DbgPrint(MID_TRACE, ("Transport: %S\n", Transports));
98
99 /* See what mapping this Transport supports */
100 Status = SockLoadTransportMapping(Transport, &Mapping);
101
102 /* Check for error */
103 if (Status) {
104 AFD_DbgPrint(MIN_TRACE, ("Can't get mapping\n"));
105 HeapFree(GlobalHeap, 0, Transports);
106 return Status;
107 }
108
109 /* See if this Mapping works for us */
110 if (SockIsTripleInMapping(Mapping, *AddressFamily, *SocketType, *Protocol)) {
111
112 /* It does, so load the DLL associated with it */
113 Status = SockLoadHelperDll(Transport, Mapping, &HelperData);
114
115 /* Check for error */
116 if (Status) {
117 AFD_DbgPrint(MIN_TRACE, ("Can't load helper DLL\n"));
118 HeapFree(GlobalHeap, 0, Transports);
119 HeapFree(GlobalHeap, 0, Mapping);
120 return Status;
121 }
122
123 /* Call the Helper Dll function get the Transport Name */
124 if (HelperData->WSHOpenSocket2 == NULL) {
125 /* DLL Doesn't support WSHOpenSocket2, call the old one */
126 HelperData->WSHOpenSocket(AddressFamily,
127 SocketType,
128 Protocol,
129 TransportName,
130 HelperDllContext,
131 Events
132 );
133 } else {
134 HelperData->WSHOpenSocket2(AddressFamily,
135 SocketType,
136 Protocol,
137 Group,
138 Flags,
139 TransportName,
140 HelperDllContext,
141 Events
142 );
143 }
144
145 /* Return the Helper Pointers */
146 *HelperDllData = HelperData;
147 /* We actually cache these ... the can't be freed yet */
148 /*HeapFree(GlobalHeap, 0, Transports);*/
149 /*HeapFree(GlobalHeap, 0, Mapping);*/
150 return NO_ERROR;
151 }
152
153 HeapFree(GlobalHeap, 0, Mapping);
154 }
155 HeapFree(GlobalHeap, 0, Transports);
156 return WSAEINVAL;
157 }
158
159 INT
160 SockLoadTransportMapping(
161 PWSTR TransportName,
162 PWINSOCK_MAPPING *Mapping)
163 {
164 PWSTR TransportKey;
165 HKEY KeyHandle;
166 ULONG MappingSize;
167 LONG Status;
168
169 AFD_DbgPrint(MID_TRACE,("Called: TransportName %ws\n", TransportName));
170
171 /* Allocate a Buffer */
172 TransportKey = HeapAlloc(GlobalHeap, 0, (54 + wcslen(TransportName)) * sizeof(WCHAR));
173
174 /* Check for error */
175 if (TransportKey == NULL) {
176 AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n"));
177 return WSAEINVAL;
178 }
179
180 /* Generate the right key name */
181 wcscpy(TransportKey, L"System\\CurrentControlSet\\Services\\");
182 wcscat(TransportKey, TransportName);
183 wcscat(TransportKey, L"\\Parameters\\Winsock");
184
185 /* Open the Key */
186 Status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, TransportKey, 0, KEY_READ, &KeyHandle);
187
188 /* We don't need the Transport Key anymore */
189 HeapFree(GlobalHeap, 0, TransportKey);
190
191 /* Check for error */
192 if (Status) {
193 AFD_DbgPrint(MIN_TRACE, ("Error reading transport mapping registry\n"));
194 return WSAEINVAL;
195 }
196
197 /* Find out how much space we need for the Mapping */
198 Status = RegQueryValueExW(KeyHandle, L"Mapping", NULL, NULL, NULL, &MappingSize);
199
200 /* Check for error */
201 if (Status) {
202 AFD_DbgPrint(MIN_TRACE, ("Error reading transport mapping registry\n"));
203 return WSAEINVAL;
204 }
205
206 /* Allocate Memory for the Mapping */
207 *Mapping = HeapAlloc(GlobalHeap, 0, MappingSize);
208
209 /* Check for error */
210 if (*Mapping == NULL) {
211 AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n"));
212 return WSAEINVAL;
213 }
214
215 /* Read the Mapping */
216 Status = RegQueryValueExW(KeyHandle, L"Mapping", NULL, NULL, (LPBYTE)*Mapping, &MappingSize);
217
218 /* Check for error */
219 if (Status) {
220 AFD_DbgPrint(MIN_TRACE, ("Error reading transport mapping registry\n"));
221 HeapFree(GlobalHeap, 0, *Mapping);
222 return WSAEINVAL;
223 }
224
225 /* Close key and return */
226 RegCloseKey(KeyHandle);
227 return 0;
228 }
229
230 INT
231 SockLoadTransportList(
232 PWSTR *TransportList)
233 {
234 ULONG TransportListSize;
235 HKEY KeyHandle;
236 LONG Status;
237
238 AFD_DbgPrint(MID_TRACE,("Called\n"));
239
240 /* Open the Transports Key */
241 Status = RegOpenKeyExW (HKEY_LOCAL_MACHINE,
242 L"SYSTEM\\CurrentControlSet\\Services\\Winsock\\Parameters",
243 0,
244 KEY_READ,
245 &KeyHandle);
246
247 /* Check for error */
248 if (Status) {
249 AFD_DbgPrint(MIN_TRACE, ("Error reading transport list registry\n"));
250 return WSAEINVAL;
251 }
252
253 /* Get the Transport List Size */
254 Status = RegQueryValueExW(KeyHandle,
255 L"Transports",
256 NULL,
257 NULL,
258 NULL,
259 &TransportListSize);
260
261 /* Check for error */
262 if (Status) {
263 AFD_DbgPrint(MIN_TRACE, ("Error reading transport list registry\n"));
264 return WSAEINVAL;
265 }
266
267 /* Allocate Memory for the Transport List */
268 *TransportList = HeapAlloc(GlobalHeap, 0, TransportListSize);
269
270 /* Check for error */
271 if (*TransportList == NULL) {
272 AFD_DbgPrint(MIN_TRACE, ("Buffer allocation failed\n"));
273 return WSAEINVAL;
274 }
275
276 /* Get the Transports */
277 Status = RegQueryValueExW (KeyHandle,
278 L"Transports",
279 NULL,
280 NULL,
281 (LPBYTE)*TransportList,
282 &TransportListSize);
283
284 /* Check for error */
285 if (Status) {
286 AFD_DbgPrint(MIN_TRACE, ("Error reading transport list registry\n"));
287 HeapFree(GlobalHeap, 0, *TransportList);
288 return WSAEINVAL;
289 }
290
291 /* Close key and return */
292 RegCloseKey(KeyHandle);
293 return 0;
294 }
295
296 INT
297 SockLoadHelperDll(
298 PWSTR TransportName,
299 PWINSOCK_MAPPING Mapping,
300 PHELPER_DATA *HelperDllData)
301 {
302 PHELPER_DATA HelperData;
303 PWSTR HelperDllName;
304 PWSTR FullHelperDllName;
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 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 */