f21833c100e2e231304ca901eb31372e5d1edf03
[reactos.git] / reactos / dll / win32 / wshtcpip / wshtcpip.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock Helper DLL for TCP/IP
4 * FILE: wshtcpip.c
5 * PURPOSE: DLL entry
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/09-2000 Created
9 */
10 #include <wshtcpip.h>
11 #define NDEBUG
12 #include <debug.h>
13
14 BOOL
15 EXPORT
16 DllMain(HANDLE hInstDll,
17 ULONG dwReason,
18 PVOID Reserved)
19 {
20 DPRINT("DllMain of wshtcpip.dll\n");
21
22 switch (dwReason) {
23 case DLL_PROCESS_ATTACH:
24 /* Don't need thread attach notifications
25 so disable them to improve performance */
26 DisableThreadLibraryCalls(hInstDll);
27 break;
28
29 case DLL_THREAD_ATTACH:
30 break;
31
32 case DLL_THREAD_DETACH:
33 break;
34
35 case DLL_PROCESS_DETACH:
36 break;
37 }
38 return TRUE;
39 }
40
41
42 INT
43 EXPORT
44 WSHAddressToString(
45 IN LPSOCKADDR Address,
46 IN INT AddressLength,
47 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL,
48 OUT LPWSTR AddressString,
49 IN OUT LPDWORD AddressStringLength)
50 {
51 UNIMPLEMENTED
52
53 return NO_ERROR;
54 }
55
56
57 INT
58 EXPORT
59 WSHEnumProtocols(
60 IN LPINT lpiProtocols OPTIONAL,
61 IN LPWSTR lpTransportKeyName,
62 IN OUT LPVOID lpProtocolBuffer,
63 IN OUT LPDWORD lpdwBufferLength)
64 {
65 UNIMPLEMENTED
66
67 return NO_ERROR;
68 }
69
70
71 INT
72 EXPORT
73 WSHGetBroadcastSockaddr(
74 IN PVOID HelperDllSocketContext,
75 OUT PSOCKADDR Sockaddr,
76 OUT PINT SockaddrLength)
77 {
78 INT Size = 2 * sizeof(UINT);
79
80 if (*SockaddrLength < Size)
81 {
82 DPRINT1("Socket address length too small: %d\n", *SockaddrLength);
83 return WSAEFAULT;
84 }
85
86 RtlZeroMemory(Sockaddr, *SockaddrLength);
87
88 Sockaddr->sa_family = AF_INET;
89 *((PUINT)Sockaddr->sa_data) = INADDR_BROADCAST;
90
91 /* *SockaddrLength = Size; */
92
93 return NO_ERROR;
94 }
95
96
97 INT
98 EXPORT
99 WSHGetProviderGuid(
100 IN LPWSTR ProviderName,
101 OUT LPGUID ProviderGuid)
102 {
103 UNIMPLEMENTED
104
105 return NO_ERROR;
106 }
107
108
109 /*
110 Document from OSR how WSHGetSockaddrType works
111 http://www.osronline.com/ddkx/network/37wshfun_5lyq.htm
112 */
113
114 INT
115 EXPORT
116 WSHGetSockaddrType(
117 IN PSOCKADDR Sockaddr,
118 IN DWORD SockaddrLength,
119 OUT PSOCKADDR_INFO SockaddrInfo)
120 {
121 PSOCKADDR_IN ipv4 = (PSOCKADDR_IN)Sockaddr;
122
123 if (!ipv4 || !SockaddrInfo || SockaddrLength < sizeof(SOCKADDR_IN) ||
124 ipv4->sin_family != AF_INET)
125 {
126 DPRINT1("Invalid parameter: %x %x %d %u\n", ipv4, SockaddrInfo, SockaddrLength, (ipv4 ? ipv4->sin_family : 0));
127 return WSAEINVAL;
128 }
129
130 switch (ntohl(ipv4->sin_addr.s_addr))
131 {
132 case INADDR_ANY:
133 SockaddrInfo->AddressInfo = SockaddrAddressInfoWildcard;
134 break;
135
136 case INADDR_BROADCAST:
137 SockaddrInfo->AddressInfo = SockaddrAddressInfoBroadcast;
138 break;
139
140 case INADDR_LOOPBACK:
141 SockaddrInfo->AddressInfo = SockaddrAddressInfoLoopback;
142 break;
143
144 default:
145 SockaddrInfo->AddressInfo = SockaddrAddressInfoNormal;
146 break;
147 }
148
149 if (ntohs(ipv4->sin_port) == 0)
150 SockaddrInfo->EndpointInfo = SockaddrEndpointInfoWildcard;
151 else if (ntohs(ipv4->sin_port) < IPPORT_RESERVED)
152 SockaddrInfo->EndpointInfo = SockaddrEndpointInfoReserved;
153 else
154 SockaddrInfo->EndpointInfo = SockaddrEndpointInfoNormal;
155
156 return NO_ERROR;
157 }
158
159 UINT
160 GetAddressOption(INT Level, INT OptionName)
161 {
162 switch (Level)
163 {
164 case IPPROTO_IP:
165 switch (OptionName)
166 {
167 case IP_TTL:
168 return AO_OPTION_TTL;
169
170 case IP_DONTFRAGMENT:
171 return AO_OPTION_IP_DONTFRAGMENT;
172
173 #if 0
174 case IP_RECEIVE_BROADCAST:
175 return AO_OPTION_BROADCAST;
176 #endif
177
178 case IP_HDRINCL:
179 return AO_OPTION_IP_HDRINCL;
180
181 default:
182 DPRINT1("Unknown option name for IPPROTO_IP: %d\n", OptionName);
183 return 0;
184 }
185 break;
186
187 case SOL_SOCKET:
188 DPRINT1("SOL_SOCKET option %d\n", OptionName);
189 break;
190
191 default:
192 DPRINT1("Unknown level: %d\n", Level);
193 break;
194 }
195 return 0;
196 }
197
198 INT
199 EXPORT
200 WSHGetSocketInformation(
201 IN PVOID HelperDllSocketContext,
202 IN SOCKET SocketHandle,
203 IN HANDLE TdiAddressObjectHandle,
204 IN HANDLE TdiConnectionObjectHandle,
205 IN INT Level,
206 IN INT OptionName,
207 OUT PCHAR OptionValue,
208 OUT LPINT OptionLength)
209 {
210 UNIMPLEMENTED
211
212 return NO_ERROR;
213 }
214
215
216 INT
217 EXPORT
218 WSHGetWildcardSockaddr(
219 IN PVOID HelperDllSocketContext,
220 OUT PSOCKADDR Sockaddr,
221 OUT PINT SockaddrLength)
222 {
223 INT Size = 2 * sizeof(UINT);
224
225 if (*SockaddrLength < Size)
226 {
227 DPRINT1("Socket address length too small: %d\n", *SockaddrLength);
228 return WSAEFAULT;
229 }
230
231 RtlZeroMemory(Sockaddr, *SockaddrLength);
232
233 Sockaddr->sa_family = AF_INET;
234 *((PUINT)Sockaddr->sa_data) = INADDR_ANY;
235
236 /* *SockaddrLength = Size; */
237
238 return NO_ERROR;
239 }
240
241
242 DWORD
243 EXPORT
244 WSHGetWinsockMapping(
245 OUT PWINSOCK_MAPPING Mapping,
246 IN DWORD MappingLength)
247 {
248 DWORD Rows = 6;
249 DWORD Columns = 3;
250 DWORD Size = 2 * sizeof(DWORD) + Columns * Rows * sizeof(DWORD);
251
252 if (MappingLength < Size)
253 {
254 DPRINT1("Mapping length too small: %d\n", MappingLength);
255 return Size;
256 }
257
258 Mapping->Rows = Rows;
259 Mapping->Columns = Columns;
260
261 Mapping->Mapping[0].AddressFamily = AF_INET;
262 Mapping->Mapping[0].SocketType = SOCK_STREAM;
263 Mapping->Mapping[0].Protocol = 0;
264
265 Mapping->Mapping[1].AddressFamily = AF_INET;
266 Mapping->Mapping[1].SocketType = SOCK_STREAM;
267 Mapping->Mapping[1].Protocol = IPPROTO_TCP;
268
269 Mapping->Mapping[2].AddressFamily = AF_INET;
270 Mapping->Mapping[2].SocketType = SOCK_DGRAM;
271 Mapping->Mapping[2].Protocol = 0;
272
273 Mapping->Mapping[3].AddressFamily = AF_INET;
274 Mapping->Mapping[3].SocketType = SOCK_DGRAM;
275 Mapping->Mapping[3].Protocol = IPPROTO_UDP;
276
277 Mapping->Mapping[4].AddressFamily = AF_INET;
278 Mapping->Mapping[4].SocketType = SOCK_RAW;
279 Mapping->Mapping[4].Protocol = 0;
280
281 Mapping->Mapping[5].AddressFamily = AF_INET;
282 Mapping->Mapping[5].SocketType = SOCK_RAW;
283 Mapping->Mapping[5].Protocol = IPPROTO_ICMP;
284
285 return NO_ERROR;
286 }
287
288
289 INT
290 EXPORT
291 WSHGetWSAProtocolInfo(
292 IN LPWSTR ProviderName,
293 OUT LPWSAPROTOCOL_INFOW *ProtocolInfo,
294 OUT LPDWORD ProtocolInfoEntries)
295 {
296 UNIMPLEMENTED
297
298 return NO_ERROR;
299 }
300
301
302 INT
303 EXPORT
304 WSHIoctl(
305 IN PVOID HelperDllSocketContext,
306 IN SOCKET SocketHandle,
307 IN HANDLE TdiAddressObjectHandle,
308 IN HANDLE TdiConnectionObjectHandle,
309 IN DWORD IoControlCode,
310 IN LPVOID InputBuffer,
311 IN DWORD InputBufferLength,
312 IN LPVOID OutputBuffer,
313 IN DWORD OutputBufferLength,
314 OUT LPDWORD NumberOfBytesReturned,
315 IN LPWSAOVERLAPPED Overlapped,
316 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine,
317 OUT LPBOOL NeedsCompletion)
318 {
319 UNIMPLEMENTED
320
321 return NO_ERROR;
322 }
323
324
325 INT
326 EXPORT
327 WSHJoinLeaf(
328 IN PVOID HelperDllSocketContext,
329 IN SOCKET SocketHandle,
330 IN HANDLE TdiAddressObjectHandle,
331 IN HANDLE TdiConnectionObjectHandle,
332 IN PVOID LeafHelperDllSocketContext,
333 IN SOCKET LeafSocketHandle,
334 IN PSOCKADDR Sockaddr,
335 IN DWORD SockaddrLength,
336 IN LPWSABUF CallerData,
337 IN LPWSABUF CalleeData,
338 IN LPQOS SocketQOS,
339 IN LPQOS GroupQOS,
340 IN DWORD Flags)
341 {
342 UNIMPLEMENTED
343
344 return NO_ERROR;
345 }
346
347 INT
348 SendRequest(
349 IN PVOID Request,
350 IN DWORD RequestSize,
351 IN DWORD IOCTL)
352 {
353 BOOLEAN Status;
354 HANDLE TcpCC;
355 DWORD BytesReturned;
356
357 if (openTcpFile(&TcpCC) != STATUS_SUCCESS)
358 return WSAEINVAL;
359
360 Status = DeviceIoControl(TcpCC,
361 IOCTL,
362 Request,
363 RequestSize,
364 NULL,
365 0,
366 &BytesReturned,
367 NULL);
368
369 closeTcpFile(TcpCC);
370
371 DPRINT("DeviceIoControl: %d\n", ((Status == TRUE) ? 0 : GetLastError()));
372
373 if (!Status)
374 return WSAEINVAL;
375
376 return NO_ERROR;
377 }
378
379 INT
380 EXPORT
381 WSHNotify(
382 IN PVOID HelperDllSocketContext,
383 IN SOCKET SocketHandle,
384 IN HANDLE TdiAddressObjectHandle,
385 IN HANDLE TdiConnectionObjectHandle,
386 IN DWORD NotifyEvent)
387 {
388 PSOCKET_CONTEXT Context = HelperDllSocketContext;
389 NTSTATUS Status;
390 HANDLE TcpCC;
391 TDIEntityID *EntityIDs;
392 DWORD EntityCount, i;
393 PQUEUED_REQUEST QueuedRequest, NextQueuedRequest;
394
395 switch (NotifyEvent)
396 {
397 case WSH_NOTIFY_CLOSE:
398 DPRINT("WSHNotify: WSH_NOTIFY_CLOSE\n");
399 QueuedRequest = Context->RequestQueue;
400 while (QueuedRequest)
401 {
402 NextQueuedRequest = QueuedRequest->Next;
403
404 HeapFree(GetProcessHeap(), 0, QueuedRequest->Info);
405 HeapFree(GetProcessHeap(), 0, QueuedRequest);
406
407 QueuedRequest = NextQueuedRequest;
408 }
409 HeapFree(GetProcessHeap(), 0, HelperDllSocketContext);
410 break;
411
412
413 case WSH_NOTIFY_BIND:
414 DPRINT("WSHNotify: WSH_NOTIFY_BIND\n");
415 Status = openTcpFile(&TcpCC);
416 if (Status != STATUS_SUCCESS)
417 return WSAEINVAL;
418
419 Status = tdiGetEntityIDSet(TcpCC,
420 &EntityIDs,
421 &EntityCount);
422
423 closeTcpFile(TcpCC);
424
425 if (Status != STATUS_SUCCESS)
426 return WSAEINVAL;
427
428 for (i = 0; i < EntityCount; i++)
429 {
430 if (EntityIDs[i].tei_entity == CO_TL_ENTITY ||
431 EntityIDs[i].tei_entity == CL_TL_ENTITY ||
432 EntityIDs[i].tei_entity == ER_ENTITY)
433 {
434 Context->AddrFileInstance = EntityIDs[i].tei_instance;
435 Context->AddrFileEntityType = EntityIDs[i].tei_entity;
436 }
437 }
438
439 DPRINT("Instance: %x Type: %x\n", Context->AddrFileInstance, Context->AddrFileEntityType);
440
441 tdiFreeThingSet(EntityIDs);
442
443 Context->SocketState = SocketStateBound;
444
445 QueuedRequest = Context->RequestQueue;
446 while (QueuedRequest)
447 {
448 QueuedRequest->Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType;
449 QueuedRequest->Info->ID.toi_entity.tei_instance = Context->AddrFileInstance;
450
451 SendRequest(QueuedRequest->Info,
452 sizeof(*QueuedRequest->Info) + QueuedRequest->Info->BufferSize,
453 IOCTL_TCP_SET_INFORMATION_EX);
454
455 NextQueuedRequest = QueuedRequest->Next;
456
457 HeapFree(GetProcessHeap(), 0, QueuedRequest->Info);
458 HeapFree(GetProcessHeap(), 0, QueuedRequest);
459
460 QueuedRequest = NextQueuedRequest;
461 }
462 Context->RequestQueue = NULL;
463 break;
464
465 default:
466 DPRINT1("Unwanted notification received! (%d)\n", NotifyEvent);
467 break;
468 }
469
470 return NO_ERROR;
471 }
472
473
474 INT
475 EXPORT
476 WSHOpenSocket(
477 IN OUT PINT AddressFamily,
478 IN OUT PINT SocketType,
479 IN OUT PINT Protocol,
480 OUT PUNICODE_STRING TransportDeviceName,
481 OUT PVOID HelperDllSocketContext,
482 OUT PDWORD NotificationEvents)
483 /*
484 * FUNCTION: Opens a socket
485 */
486 {
487 return WSHOpenSocket2(AddressFamily,
488 SocketType,
489 Protocol,
490 0,
491 0,
492 TransportDeviceName,
493 HelperDllSocketContext,
494 NotificationEvents);
495 }
496
497
498 INT
499 EXPORT
500 WSHOpenSocket2(
501 OUT PINT AddressFamily,
502 IN OUT PINT SocketType,
503 IN OUT PINT Protocol,
504 IN GROUP Group,
505 IN DWORD Flags,
506 OUT PUNICODE_STRING TransportDeviceName,
507 OUT PVOID *HelperDllSocketContext,
508 OUT PDWORD NotificationEvents)
509 /*
510 * FUNCTION: Opens a socket
511 * ARGUMENTS:
512 * AddressFamily = Address of buffer with address family (updated)
513 * SocketType = Address of buffer with type of socket (updated)
514 * Protocol = Address of buffer with protocol number (updated)
515 * Group = Socket group
516 * Flags = Socket flags
517 * TransportDeviceName = Address of buffer to place name of transport device
518 * HelperDllSocketContext = Address of buffer to place socket context pointer
519 * NotificationEvents = Address of buffer to place flags for event notification
520 * RETURNS:
521 * Status of operation
522 * NOTES:
523 * Mapping tripple is returned in an canonicalized form
524 */
525 {
526 PSOCKET_CONTEXT Context;
527 UNICODE_STRING String;
528 UNICODE_STRING TcpDeviceName = RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME);
529 UNICODE_STRING UdpDeviceName = RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME);
530 UNICODE_STRING RawDeviceName = RTL_CONSTANT_STRING(DD_RAW_IP_DEVICE_NAME);
531
532 DPRINT("WSHOpenSocket2 called\n");
533
534 switch (*SocketType) {
535 case SOCK_STREAM:
536 String = TcpDeviceName;
537 break;
538
539 case SOCK_DGRAM:
540 String = UdpDeviceName;
541 break;
542
543 case SOCK_RAW:
544 if ((*Protocol < 0) || (*Protocol > 255))
545 return WSAEINVAL;
546
547 String = RawDeviceName;
548 break;
549
550 default:
551 return WSAEINVAL;
552 }
553
554 RtlInitUnicodeString(TransportDeviceName, NULL);
555
556 TransportDeviceName->MaximumLength = String.Length + /* Transport device name */
557 (4 * sizeof(WCHAR) + /* Separator and protocol */
558 sizeof(UNICODE_NULL)); /* Terminating null */
559
560 TransportDeviceName->Buffer = HeapAlloc(
561 GetProcessHeap(),
562 0,
563 TransportDeviceName->MaximumLength);
564
565 if (!TransportDeviceName->Buffer)
566 return WSAENOBUFS;
567
568 /* Append the transport device name */
569 RtlAppendUnicodeStringToString(TransportDeviceName, &String);
570
571 if (*SocketType == SOCK_RAW) {
572 /* Append a separator */
573 TransportDeviceName->Buffer[TransportDeviceName->Length / sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
574 TransportDeviceName->Length += sizeof(WCHAR);
575 TransportDeviceName->Buffer[TransportDeviceName->Length / sizeof(WCHAR)] = UNICODE_NULL;
576
577 /* Append the protocol number */
578 String.Buffer = TransportDeviceName->Buffer + (TransportDeviceName->Length / sizeof(WCHAR));
579 String.Length = 0;
580 String.MaximumLength = TransportDeviceName->MaximumLength - TransportDeviceName->Length;
581
582 RtlIntegerToUnicodeString((ULONG)*Protocol, 10, &String);
583
584 TransportDeviceName->Length += String.Length;
585 }
586
587 /* Setup a socket context area */
588
589 Context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOCKET_CONTEXT));
590 if (!Context) {
591 RtlFreeUnicodeString(TransportDeviceName);
592 return WSAENOBUFS;
593 }
594
595 Context->AddressFamily = *AddressFamily;
596 Context->SocketType = *SocketType;
597 Context->Protocol = *Protocol;
598 Context->Flags = Flags;
599 Context->SocketState = SocketStateCreated;
600
601 *HelperDllSocketContext = Context;
602 *NotificationEvents = WSH_NOTIFY_CLOSE | WSH_NOTIFY_BIND;
603
604 return NO_ERROR;
605 }
606
607 INT
608 EXPORT
609 WSHSetSocketInformation(
610 IN PVOID HelperDllSocketContext,
611 IN SOCKET SocketHandle,
612 IN HANDLE TdiAddressObjectHandle,
613 IN HANDLE TdiConnectionObjectHandle,
614 IN INT Level,
615 IN INT OptionName,
616 IN PCHAR OptionValue,
617 IN INT OptionLength)
618 {
619 PSOCKET_CONTEXT Context = HelperDllSocketContext;
620 UINT RealOptionName;
621 INT Status;
622 PTCP_REQUEST_SET_INFORMATION_EX Info;
623 PQUEUED_REQUEST Queued, NextQueued;
624
625 DPRINT("WSHSetSocketInformation\n");
626
627 /* FIXME: We only handle address file object here */
628
629 RealOptionName = GetAddressOption(Level, OptionName);
630
631 /* FIXME: Support all options */
632 if (!RealOptionName)
633 return 0; /* return WSAEINVAL; */
634
635 Info = HeapAlloc(GetProcessHeap(), 0, sizeof(*Info) + OptionLength);
636 if (!Info)
637 return WSAENOBUFS;
638
639 Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType;
640 Info->ID.toi_entity.tei_instance = Context->AddrFileInstance;
641 Info->ID.toi_class = INFO_CLASS_PROTOCOL;
642 Info->ID.toi_type = INFO_TYPE_ADDRESS_OBJECT;
643 Info->ID.toi_id = RealOptionName;
644 Info->BufferSize = OptionLength;
645 memcpy(Info->Buffer, OptionValue, OptionLength);
646
647 if (Context->SocketState == SocketStateCreated)
648 {
649 if (Context->RequestQueue)
650 {
651 Queued = Context->RequestQueue;
652 while ((NextQueued = Queued->Next))
653 {
654 Queued = NextQueued;
655 }
656
657 Queued->Next = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
658 if (!Queued->Next)
659 {
660 HeapFree(GetProcessHeap(), 0, Info);
661 return WSAENOBUFS;
662 }
663
664 NextQueued = Queued->Next;
665 NextQueued->Next = NULL;
666 NextQueued->Info = Info;
667 }
668 else
669 {
670 Context->RequestQueue = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
671 if (!Context->RequestQueue)
672 {
673 HeapFree(GetProcessHeap(), 0, Info);
674 return WSAENOBUFS;
675 }
676
677 Context->RequestQueue->Next = NULL;
678 Context->RequestQueue->Info = Info;
679 }
680
681 return 0;
682 }
683
684 Status = SendRequest(Info, sizeof(*Info) + Info->BufferSize, IOCTL_TCP_SET_INFORMATION_EX);
685
686 HeapFree(GetProcessHeap(), 0, Info);
687
688 return Status;
689 }
690
691
692 INT
693 EXPORT
694 WSHStringToAddress(
695 IN LPWSTR AddressString,
696 IN DWORD AddressFamily,
697 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL,
698 OUT LPSOCKADDR Address,
699 IN OUT LPDWORD AddressStringLength)
700 {
701 UNIMPLEMENTED
702
703 return NO_ERROR;
704 }
705
706 /* EOF */