2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock Helper DLL for TCP/IP
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
8 * CSH 01/09-2000 Created
16 DllMain(HANDLE hInstDll
,
20 DPRINT("DllMain of wshtcpip.dll\n");
23 case DLL_PROCESS_ATTACH
:
24 /* Don't need thread attach notifications
25 so disable them to improve performance */
26 DisableThreadLibraryCalls(hInstDll
);
29 case DLL_THREAD_ATTACH
:
32 case DLL_THREAD_DETACH
:
35 case DLL_PROCESS_DETACH
:
45 IN LPSOCKADDR Address
,
47 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL
,
48 OUT LPWSTR AddressString
,
49 IN OUT LPDWORD AddressStringLength
)
60 IN LPINT lpiProtocols OPTIONAL
,
61 IN LPWSTR lpTransportKeyName
,
62 IN OUT LPVOID lpProtocolBuffer
,
63 IN OUT LPDWORD lpdwBufferLength
)
73 WSHGetBroadcastSockaddr(
74 IN PVOID HelperDllSocketContext
,
75 OUT PSOCKADDR Sockaddr
,
76 OUT PINT SockaddrLength
)
78 INT Size
= 2 * sizeof(UINT
);
80 if (*SockaddrLength
< Size
)
82 DPRINT1("Socket address length too small: %d\n", *SockaddrLength
);
86 RtlZeroMemory(Sockaddr
, *SockaddrLength
);
88 Sockaddr
->sa_family
= AF_INET
;
89 *((PUINT
)Sockaddr
->sa_data
) = INADDR_BROADCAST
;
91 /* *SockaddrLength = Size; */
100 IN LPWSTR ProviderName
,
101 OUT LPGUID ProviderGuid
)
110 Document from OSR how WSHGetSockaddrType works
111 http://www.osronline.com/ddkx/network/37wshfun_5lyq.htm
117 IN PSOCKADDR Sockaddr
,
118 IN DWORD SockaddrLength
,
119 OUT PSOCKADDR_INFO SockaddrInfo
)
121 PSOCKADDR_IN ipv4
= (PSOCKADDR_IN
)Sockaddr
;
123 if (!ipv4
|| !SockaddrInfo
|| SockaddrLength
< sizeof(SOCKADDR_IN
) ||
124 ipv4
->sin_family
!= AF_INET
)
126 DPRINT1("Invalid parameter: %x %x %d %u\n", ipv4
, SockaddrInfo
, SockaddrLength
, (ipv4
? ipv4
->sin_family
: 0));
130 switch (ntohl(ipv4
->sin_addr
.s_addr
))
133 SockaddrInfo
->AddressInfo
= SockaddrAddressInfoWildcard
;
136 case INADDR_BROADCAST
:
137 SockaddrInfo
->AddressInfo
= SockaddrAddressInfoBroadcast
;
140 case INADDR_LOOPBACK
:
141 SockaddrInfo
->AddressInfo
= SockaddrAddressInfoLoopback
;
145 SockaddrInfo
->AddressInfo
= SockaddrAddressInfoNormal
;
149 if (ntohs(ipv4
->sin_port
) == 0)
150 SockaddrInfo
->EndpointInfo
= SockaddrEndpointInfoWildcard
;
151 else if (ntohs(ipv4
->sin_port
) < IPPORT_RESERVED
)
152 SockaddrInfo
->EndpointInfo
= SockaddrEndpointInfoReserved
;
154 SockaddrInfo
->EndpointInfo
= SockaddrEndpointInfoNormal
;
164 _Out_ PULONG TdiType
,
170 *TdiType
= INFO_TYPE_ADDRESS_OBJECT
;
174 /* FIXME: Return proper option */
183 *TdiType
= INFO_TYPE_ADDRESS_OBJECT
;
187 *TdiId
= AO_OPTION_TTL
;
190 case IP_DONTFRAGMENT
:
191 *TdiId
= AO_OPTION_IP_DONTFRAGMENT
;
195 case IP_RECEIVE_BROADCAST
:
196 *TdiId
= AO_OPTION_BROADCAST
;
201 *TdiId
= AO_OPTION_IP_HDRINCL
;
212 *TdiType
= INFO_TYPE_CONNECTION
;
214 *TdiId
= TCP_SOCKET_NODELAY
;
224 DPRINT1("Unknown level/option name: %d %d\n", Level
, OptionName
);
231 WSHGetSocketInformation(
232 IN PVOID HelperDllSocketContext
,
233 IN SOCKET SocketHandle
,
234 IN HANDLE TdiAddressObjectHandle
,
235 IN HANDLE TdiConnectionObjectHandle
,
238 OUT PCHAR OptionValue
,
239 OUT LPINT OptionLength
)
243 DPRINT1("Get: Unknown level/option name: %d %d\n", Level
, OptionName
);
253 WSHGetWildcardSockaddr(
254 IN PVOID HelperDllSocketContext
,
255 OUT PSOCKADDR Sockaddr
,
256 OUT PINT SockaddrLength
)
258 INT Size
= 2 * sizeof(UINT
);
260 if (*SockaddrLength
< Size
)
262 DPRINT1("Socket address length too small: %d\n", *SockaddrLength
);
266 RtlZeroMemory(Sockaddr
, *SockaddrLength
);
268 Sockaddr
->sa_family
= AF_INET
;
269 *((PUINT
)Sockaddr
->sa_data
) = INADDR_ANY
;
271 /* *SockaddrLength = Size; */
279 WSHGetWinsockMapping(
280 OUT PWINSOCK_MAPPING Mapping
,
281 IN DWORD MappingLength
)
285 DWORD Size
= 2 * sizeof(DWORD
) + Columns
* Rows
* sizeof(DWORD
);
287 if (MappingLength
< Size
)
289 DPRINT1("Mapping length too small: %d\n", MappingLength
);
293 Mapping
->Rows
= Rows
;
294 Mapping
->Columns
= Columns
;
296 Mapping
->Mapping
[0].AddressFamily
= AF_INET
;
297 Mapping
->Mapping
[0].SocketType
= SOCK_STREAM
;
298 Mapping
->Mapping
[0].Protocol
= 0;
300 Mapping
->Mapping
[1].AddressFamily
= AF_INET
;
301 Mapping
->Mapping
[1].SocketType
= SOCK_STREAM
;
302 Mapping
->Mapping
[1].Protocol
= IPPROTO_TCP
;
304 Mapping
->Mapping
[2].AddressFamily
= AF_INET
;
305 Mapping
->Mapping
[2].SocketType
= SOCK_DGRAM
;
306 Mapping
->Mapping
[2].Protocol
= 0;
308 Mapping
->Mapping
[3].AddressFamily
= AF_INET
;
309 Mapping
->Mapping
[3].SocketType
= SOCK_DGRAM
;
310 Mapping
->Mapping
[3].Protocol
= IPPROTO_UDP
;
312 Mapping
->Mapping
[4].AddressFamily
= AF_INET
;
313 Mapping
->Mapping
[4].SocketType
= SOCK_RAW
;
314 Mapping
->Mapping
[4].Protocol
= 0;
316 Mapping
->Mapping
[5].AddressFamily
= AF_INET
;
317 Mapping
->Mapping
[5].SocketType
= SOCK_RAW
;
318 Mapping
->Mapping
[5].Protocol
= IPPROTO_ICMP
;
326 WSHGetWSAProtocolInfo(
327 IN LPWSTR ProviderName
,
328 OUT LPWSAPROTOCOL_INFOW
*ProtocolInfo
,
329 OUT LPDWORD ProtocolInfoEntries
)
340 IN PVOID HelperDllSocketContext
,
341 IN SOCKET SocketHandle
,
342 IN HANDLE TdiAddressObjectHandle
,
343 IN HANDLE TdiConnectionObjectHandle
,
344 IN DWORD IoControlCode
,
345 IN LPVOID InputBuffer
,
346 IN DWORD InputBufferLength
,
347 IN LPVOID OutputBuffer
,
348 IN DWORD OutputBufferLength
,
349 OUT LPDWORD NumberOfBytesReturned
,
350 IN LPWSAOVERLAPPED Overlapped
,
351 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
,
352 OUT LPBOOL NeedsCompletion
)
356 DPRINT1("Ioctl: Unknown IOCTL code: %d\n", IoControlCode
);
365 IN PVOID HelperDllSocketContext
,
366 IN SOCKET SocketHandle
,
367 IN HANDLE TdiAddressObjectHandle
,
368 IN HANDLE TdiConnectionObjectHandle
,
369 IN PVOID LeafHelperDllSocketContext
,
370 IN SOCKET LeafSocketHandle
,
371 IN PSOCKADDR Sockaddr
,
372 IN DWORD SockaddrLength
,
373 IN LPWSABUF CallerData
,
374 IN LPWSABUF CalleeData
,
387 IN DWORD RequestSize
,
394 if (openTcpFile(&TcpCC
) != STATUS_SUCCESS
)
397 Status
= DeviceIoControl(TcpCC
,
408 DPRINT("DeviceIoControl: %d\n", ((Status
== TRUE
) ? 0 : GetLastError()));
419 IN PVOID HelperDllSocketContext
,
420 IN SOCKET SocketHandle
,
421 IN HANDLE TdiAddressObjectHandle
,
422 IN HANDLE TdiConnectionObjectHandle
,
423 IN DWORD NotifyEvent
)
425 PSOCKET_CONTEXT Context
= HelperDllSocketContext
;
428 TDIEntityID
*EntityIDs
;
429 DWORD EntityCount
, i
;
430 PQUEUED_REQUEST QueuedRequest
, NextQueuedRequest
;
434 case WSH_NOTIFY_CLOSE
:
435 DPRINT("WSHNotify: WSH_NOTIFY_CLOSE\n");
436 QueuedRequest
= Context
->RequestQueue
;
437 while (QueuedRequest
)
439 NextQueuedRequest
= QueuedRequest
->Next
;
441 HeapFree(GetProcessHeap(), 0, QueuedRequest
->Info
);
442 HeapFree(GetProcessHeap(), 0, QueuedRequest
);
444 QueuedRequest
= NextQueuedRequest
;
446 HeapFree(GetProcessHeap(), 0, HelperDllSocketContext
);
450 case WSH_NOTIFY_BIND
:
451 DPRINT("WSHNotify: WSH_NOTIFY_BIND\n");
452 Status
= openTcpFile(&TcpCC
);
453 if (Status
!= STATUS_SUCCESS
)
456 Status
= tdiGetEntityIDSet(TcpCC
,
462 if (Status
!= STATUS_SUCCESS
)
465 for (i
= 0; i
< EntityCount
; i
++)
467 if (EntityIDs
[i
].tei_entity
== CO_TL_ENTITY
||
468 EntityIDs
[i
].tei_entity
== CL_TL_ENTITY
||
469 EntityIDs
[i
].tei_entity
== ER_ENTITY
)
471 Context
->AddrFileInstance
= EntityIDs
[i
].tei_instance
;
472 Context
->AddrFileEntityType
= EntityIDs
[i
].tei_entity
;
476 DPRINT("Instance: %x Type: %x\n", Context
->AddrFileInstance
, Context
->AddrFileEntityType
);
478 tdiFreeThingSet(EntityIDs
);
480 Context
->SocketState
= SocketStateBound
;
482 QueuedRequest
= Context
->RequestQueue
;
483 while (QueuedRequest
)
485 QueuedRequest
->Info
->ID
.toi_entity
.tei_entity
= Context
->AddrFileEntityType
;
486 QueuedRequest
->Info
->ID
.toi_entity
.tei_instance
= Context
->AddrFileInstance
;
488 SendRequest(QueuedRequest
->Info
,
489 sizeof(*QueuedRequest
->Info
) + QueuedRequest
->Info
->BufferSize
,
490 IOCTL_TCP_SET_INFORMATION_EX
);
492 NextQueuedRequest
= QueuedRequest
->Next
;
494 HeapFree(GetProcessHeap(), 0, QueuedRequest
->Info
);
495 HeapFree(GetProcessHeap(), 0, QueuedRequest
);
497 QueuedRequest
= NextQueuedRequest
;
499 Context
->RequestQueue
= NULL
;
503 DPRINT1("Unwanted notification received! (%d)\n", NotifyEvent
);
514 IN OUT PINT AddressFamily
,
515 IN OUT PINT SocketType
,
516 IN OUT PINT Protocol
,
517 OUT PUNICODE_STRING TransportDeviceName
,
518 OUT PVOID HelperDllSocketContext
,
519 OUT PDWORD NotificationEvents
)
521 * FUNCTION: Opens a socket
524 return WSHOpenSocket2(AddressFamily
,
530 HelperDllSocketContext
,
538 OUT PINT AddressFamily
,
539 IN OUT PINT SocketType
,
540 IN OUT PINT Protocol
,
543 OUT PUNICODE_STRING TransportDeviceName
,
544 OUT PVOID
*HelperDllSocketContext
,
545 OUT PDWORD NotificationEvents
)
547 * FUNCTION: Opens a socket
549 * AddressFamily = Address of buffer with address family (updated)
550 * SocketType = Address of buffer with type of socket (updated)
551 * Protocol = Address of buffer with protocol number (updated)
552 * Group = Socket group
553 * Flags = Socket flags
554 * TransportDeviceName = Address of buffer to place name of transport device
555 * HelperDllSocketContext = Address of buffer to place socket context pointer
556 * NotificationEvents = Address of buffer to place flags for event notification
558 * Status of operation
560 * Mapping tripple is returned in an canonicalized form
563 PSOCKET_CONTEXT Context
;
564 UNICODE_STRING String
;
565 UNICODE_STRING TcpDeviceName
= RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME
);
566 UNICODE_STRING UdpDeviceName
= RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME
);
567 UNICODE_STRING RawDeviceName
= RTL_CONSTANT_STRING(DD_RAW_IP_DEVICE_NAME
);
569 DPRINT("WSHOpenSocket2 called\n");
571 switch (*SocketType
) {
573 String
= TcpDeviceName
;
577 String
= UdpDeviceName
;
581 if ((*Protocol
< 0) || (*Protocol
> 255))
584 String
= RawDeviceName
;
591 RtlInitUnicodeString(TransportDeviceName
, NULL
);
593 TransportDeviceName
->MaximumLength
= String
.Length
+ /* Transport device name */
594 (4 * sizeof(WCHAR
) + /* Separator and protocol */
595 sizeof(UNICODE_NULL
)); /* Terminating null */
597 TransportDeviceName
->Buffer
= HeapAlloc(
600 TransportDeviceName
->MaximumLength
);
602 if (!TransportDeviceName
->Buffer
)
605 /* Append the transport device name */
606 RtlAppendUnicodeStringToString(TransportDeviceName
, &String
);
608 if (*SocketType
== SOCK_RAW
) {
609 /* Append a separator */
610 TransportDeviceName
->Buffer
[TransportDeviceName
->Length
/ sizeof(WCHAR
)] = OBJ_NAME_PATH_SEPARATOR
;
611 TransportDeviceName
->Length
+= sizeof(WCHAR
);
612 TransportDeviceName
->Buffer
[TransportDeviceName
->Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
614 /* Append the protocol number */
615 String
.Buffer
= TransportDeviceName
->Buffer
+ (TransportDeviceName
->Length
/ sizeof(WCHAR
));
617 String
.MaximumLength
= TransportDeviceName
->MaximumLength
- TransportDeviceName
->Length
;
619 RtlIntegerToUnicodeString((ULONG
)*Protocol
, 10, &String
);
621 TransportDeviceName
->Length
+= String
.Length
;
624 /* Setup a socket context area */
626 Context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(SOCKET_CONTEXT
));
628 RtlFreeUnicodeString(TransportDeviceName
);
632 Context
->AddressFamily
= *AddressFamily
;
633 Context
->SocketType
= *SocketType
;
634 Context
->Protocol
= *Protocol
;
635 Context
->Flags
= Flags
;
636 Context
->SocketState
= SocketStateCreated
;
638 *HelperDllSocketContext
= Context
;
639 *NotificationEvents
= WSH_NOTIFY_CLOSE
| WSH_NOTIFY_BIND
;
646 WSHSetSocketInformation(
647 IN PVOID HelperDllSocketContext
,
648 IN SOCKET SocketHandle
,
649 IN HANDLE TdiAddressObjectHandle
,
650 IN HANDLE TdiConnectionObjectHandle
,
653 IN PCHAR OptionValue
,
656 PSOCKET_CONTEXT Context
= HelperDllSocketContext
;
657 ULONG TdiType
, TdiId
;
659 PTCP_REQUEST_SET_INFORMATION_EX Info
;
660 PQUEUED_REQUEST Queued
, NextQueued
;
662 DPRINT("WSHSetSocketInformation\n");
664 /* FIXME: We only handle address file object here */
672 if (OptionLength
< sizeof(BOOL
))
676 Context
->DontRoute
= *(BOOL
*)OptionValue
;
677 /* This is silently ignored on Windows */
681 /* FIXME -- We'll send this to TCPIP */
682 DPRINT1("Set: SO_KEEPALIVE not yet supported\n");
687 DPRINT1("Set: Received unexpected SOL_SOCKET option %d\n", OptionName
);
688 return WSAENOPROTOOPT
;
696 case IP_DONTFRAGMENT
:
698 /* Send these to TCPIP */
702 /* Invalid option -- FIXME */
703 DPRINT1("Set: Received unsupported IPPROTO_IP option %d\n", OptionName
);
712 if (OptionLength
< sizeof(CHAR
))
720 DPRINT1("Set: Received unexpected IPPROTO_TCP option %d\n", OptionName
);
726 DPRINT1("Set: Received unexpected %d option %d\n", Level
, OptionName
);
730 /* If we get here, GetAddressOption must return something valid */
731 GetTdiTypeId(Level
, OptionName
, &TdiType
, &TdiId
);
732 ASSERT((TdiId
!= 0) && (TdiType
!= 0));
734 Info
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Info
) + OptionLength
);
738 Info
->ID
.toi_entity
.tei_entity
= Context
->AddrFileEntityType
;
739 Info
->ID
.toi_entity
.tei_instance
= Context
->AddrFileInstance
;
740 Info
->ID
.toi_class
= INFO_CLASS_PROTOCOL
;
741 Info
->ID
.toi_type
= TdiType
;
742 Info
->ID
.toi_id
= TdiId
;
743 Info
->BufferSize
= OptionLength
;
744 memcpy(Info
->Buffer
, OptionValue
, OptionLength
);
746 if (Context
->SocketState
== SocketStateCreated
)
748 if (Context
->RequestQueue
)
750 Queued
= Context
->RequestQueue
;
751 while ((NextQueued
= Queued
->Next
))
756 Queued
->Next
= HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST
));
759 HeapFree(GetProcessHeap(), 0, Info
);
763 NextQueued
= Queued
->Next
;
764 NextQueued
->Next
= NULL
;
765 NextQueued
->Info
= Info
;
769 Context
->RequestQueue
= HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST
));
770 if (!Context
->RequestQueue
)
772 HeapFree(GetProcessHeap(), 0, Info
);
776 Context
->RequestQueue
->Next
= NULL
;
777 Context
->RequestQueue
->Info
= Info
;
783 Status
= SendRequest(Info
, sizeof(*Info
) + Info
->BufferSize
, IOCTL_TCP_SET_INFORMATION_EX
);
785 HeapFree(GetProcessHeap(), 0, Info
);
794 IN LPWSTR AddressString
,
795 IN DWORD AddressFamily
,
796 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL
,
797 OUT LPSOCKADDR Address
,
798 IN OUT LPDWORD AddressStringLength
)