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
;
210 *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 if (IoControlCode
== SIO_GET_INTERFACE_LIST
)
358 res
= WSHIoctl_GetInterfaceList(
361 NumberOfBytesReturned
,
368 DPRINT1("Ioctl: Unknown IOCTL code: %d\n", IoControlCode
);
377 IN PVOID HelperDllSocketContext
,
378 IN SOCKET SocketHandle
,
379 IN HANDLE TdiAddressObjectHandle
,
380 IN HANDLE TdiConnectionObjectHandle
,
381 IN PVOID LeafHelperDllSocketContext
,
382 IN SOCKET LeafSocketHandle
,
383 IN PSOCKADDR Sockaddr
,
384 IN DWORD SockaddrLength
,
385 IN LPWSABUF CallerData
,
386 IN LPWSABUF CalleeData
,
399 IN DWORD RequestSize
,
406 if (openTcpFile(&TcpCC
, FILE_READ_DATA
| FILE_WRITE_DATA
) != STATUS_SUCCESS
)
409 Success
= DeviceIoControl(TcpCC
,
420 DPRINT("DeviceIoControl: %ld\n", ((Success
!= FALSE
) ? 0 : GetLastError()));
431 IN PVOID HelperDllSocketContext
,
432 IN SOCKET SocketHandle
,
433 IN HANDLE TdiAddressObjectHandle
,
434 IN HANDLE TdiConnectionObjectHandle
,
435 IN DWORD NotifyEvent
)
437 PSOCKET_CONTEXT Context
= HelperDllSocketContext
;
440 TDIEntityID
*EntityIDs
;
441 DWORD EntityCount
, i
;
442 PQUEUED_REQUEST QueuedRequest
, NextQueuedRequest
;
446 case WSH_NOTIFY_CLOSE
:
447 DPRINT("WSHNotify: WSH_NOTIFY_CLOSE\n");
448 QueuedRequest
= Context
->RequestQueue
;
449 while (QueuedRequest
)
451 NextQueuedRequest
= QueuedRequest
->Next
;
453 HeapFree(GetProcessHeap(), 0, QueuedRequest
->Info
);
454 HeapFree(GetProcessHeap(), 0, QueuedRequest
);
456 QueuedRequest
= NextQueuedRequest
;
458 HeapFree(GetProcessHeap(), 0, HelperDllSocketContext
);
462 case WSH_NOTIFY_BIND
:
463 DPRINT("WSHNotify: WSH_NOTIFY_BIND\n");
464 Status
= openTcpFile(&TcpCC
, FILE_READ_DATA
);
465 if (Status
!= STATUS_SUCCESS
)
468 Status
= tdiGetEntityIDSet(TcpCC
,
474 if (Status
!= STATUS_SUCCESS
)
477 for (i
= 0; i
< EntityCount
; i
++)
479 if (EntityIDs
[i
].tei_entity
== CO_TL_ENTITY
||
480 EntityIDs
[i
].tei_entity
== CL_TL_ENTITY
||
481 EntityIDs
[i
].tei_entity
== ER_ENTITY
)
483 Context
->AddrFileInstance
= EntityIDs
[i
].tei_instance
;
484 Context
->AddrFileEntityType
= EntityIDs
[i
].tei_entity
;
488 DPRINT("Instance: %lx Type: %lx\n", Context
->AddrFileInstance
, Context
->AddrFileEntityType
);
490 tdiFreeThingSet(EntityIDs
);
492 Context
->SocketState
= SocketStateBound
;
494 QueuedRequest
= Context
->RequestQueue
;
495 while (QueuedRequest
)
497 QueuedRequest
->Info
->ID
.toi_entity
.tei_entity
= Context
->AddrFileEntityType
;
498 QueuedRequest
->Info
->ID
.toi_entity
.tei_instance
= Context
->AddrFileInstance
;
500 SendRequest(QueuedRequest
->Info
,
501 sizeof(*QueuedRequest
->Info
) + QueuedRequest
->Info
->BufferSize
,
502 IOCTL_TCP_SET_INFORMATION_EX
);
504 NextQueuedRequest
= QueuedRequest
->Next
;
506 HeapFree(GetProcessHeap(), 0, QueuedRequest
->Info
);
507 HeapFree(GetProcessHeap(), 0, QueuedRequest
);
509 QueuedRequest
= NextQueuedRequest
;
511 Context
->RequestQueue
= NULL
;
515 DPRINT1("Unwanted notification received! (%ld)\n", NotifyEvent
);
526 IN OUT PINT AddressFamily
,
527 IN OUT PINT SocketType
,
528 IN OUT PINT Protocol
,
529 OUT PUNICODE_STRING TransportDeviceName
,
530 OUT PVOID HelperDllSocketContext
,
531 OUT PDWORD NotificationEvents
)
533 * FUNCTION: Opens a socket
536 return WSHOpenSocket2(AddressFamily
,
542 HelperDllSocketContext
,
550 OUT PINT AddressFamily
,
551 IN OUT PINT SocketType
,
552 IN OUT PINT Protocol
,
555 OUT PUNICODE_STRING TransportDeviceName
,
556 OUT PVOID
*HelperDllSocketContext
,
557 OUT PDWORD NotificationEvents
)
559 * FUNCTION: Opens a socket
561 * AddressFamily = Address of buffer with address family (updated)
562 * SocketType = Address of buffer with type of socket (updated)
563 * Protocol = Address of buffer with protocol number (updated)
564 * Group = Socket group
565 * Flags = Socket flags
566 * TransportDeviceName = Address of buffer to place name of transport device
567 * HelperDllSocketContext = Address of buffer to place socket context pointer
568 * NotificationEvents = Address of buffer to place flags for event notification
570 * Status of operation
572 * Mapping tripple is returned in an canonicalized form
575 PSOCKET_CONTEXT Context
;
576 UNICODE_STRING String
;
577 UNICODE_STRING TcpDeviceName
= RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME
);
578 UNICODE_STRING UdpDeviceName
= RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME
);
579 UNICODE_STRING RawDeviceName
= RTL_CONSTANT_STRING(DD_RAW_IP_DEVICE_NAME
);
581 DPRINT("WSHOpenSocket2 called\n");
583 switch (*SocketType
) {
585 String
= TcpDeviceName
;
589 String
= UdpDeviceName
;
593 if ((*Protocol
< 0) || (*Protocol
> 255))
596 String
= RawDeviceName
;
603 RtlInitUnicodeString(TransportDeviceName
, NULL
);
605 TransportDeviceName
->MaximumLength
= String
.Length
+ /* Transport device name */
606 (4 * sizeof(WCHAR
) + /* Separator and protocol */
607 sizeof(UNICODE_NULL
)); /* Terminating null */
609 TransportDeviceName
->Buffer
= HeapAlloc(
612 TransportDeviceName
->MaximumLength
);
614 if (!TransportDeviceName
->Buffer
)
617 /* Append the transport device name */
618 RtlAppendUnicodeStringToString(TransportDeviceName
, &String
);
620 if (*SocketType
== SOCK_RAW
) {
621 /* Append a separator */
622 TransportDeviceName
->Buffer
[TransportDeviceName
->Length
/ sizeof(WCHAR
)] = OBJ_NAME_PATH_SEPARATOR
;
623 TransportDeviceName
->Length
+= sizeof(WCHAR
);
624 TransportDeviceName
->Buffer
[TransportDeviceName
->Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
626 /* Append the protocol number */
627 String
.Buffer
= TransportDeviceName
->Buffer
+ (TransportDeviceName
->Length
/ sizeof(WCHAR
));
629 String
.MaximumLength
= TransportDeviceName
->MaximumLength
- TransportDeviceName
->Length
;
631 RtlIntegerToUnicodeString((ULONG
)*Protocol
, 10, &String
);
633 TransportDeviceName
->Length
+= String
.Length
;
636 /* Setup a socket context area */
638 Context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(SOCKET_CONTEXT
));
640 RtlFreeUnicodeString(TransportDeviceName
);
644 Context
->AddressFamily
= *AddressFamily
;
645 Context
->SocketType
= *SocketType
;
646 Context
->Protocol
= *Protocol
;
647 Context
->Flags
= Flags
;
648 Context
->SocketState
= SocketStateCreated
;
650 *HelperDllSocketContext
= Context
;
651 *NotificationEvents
= WSH_NOTIFY_CLOSE
| WSH_NOTIFY_BIND
;
658 WSHSetSocketInformation(
659 IN PVOID HelperDllSocketContext
,
660 IN SOCKET SocketHandle
,
661 IN HANDLE TdiAddressObjectHandle
,
662 IN HANDLE TdiConnectionObjectHandle
,
665 IN PCHAR OptionValue
,
668 PSOCKET_CONTEXT Context
= HelperDllSocketContext
;
669 ULONG TdiType
, TdiId
;
671 PTCP_REQUEST_SET_INFORMATION_EX Info
;
672 PQUEUED_REQUEST Queued
, NextQueued
;
674 DPRINT("WSHSetSocketInformation\n");
676 /* FIXME: We only handle address file object here */
684 if (OptionLength
< sizeof(BOOL
))
688 Context
->DontRoute
= *(BOOL
*)OptionValue
;
689 /* This is silently ignored on Windows */
693 /* FIXME -- We'll send this to TCPIP */
694 DPRINT1("Set: SO_KEEPALIVE not yet supported\n");
699 DPRINT1("Set: Received unexpected SOL_SOCKET option %d\n", OptionName
);
700 return WSAENOPROTOOPT
;
708 case IP_DONTFRAGMENT
:
710 /* Send these to TCPIP */
714 /* Invalid option -- FIXME */
715 DPRINT1("Set: Received unsupported IPPROTO_IP option %d\n", OptionName
);
724 if (OptionLength
< sizeof(CHAR
))
732 DPRINT1("Set: Received unexpected IPPROTO_TCP option %d\n", OptionName
);
738 DPRINT1("Set: Received unexpected %d option %d\n", Level
, OptionName
);
742 /* If we get here, GetAddressOption must return something valid */
743 GetTdiTypeId(Level
, OptionName
, &TdiType
, &TdiId
);
744 ASSERT((TdiId
!= 0) && (TdiType
!= 0));
746 Info
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Info
) + OptionLength
);
750 Info
->ID
.toi_entity
.tei_entity
= Context
->AddrFileEntityType
;
751 Info
->ID
.toi_entity
.tei_instance
= Context
->AddrFileInstance
;
752 Info
->ID
.toi_class
= INFO_CLASS_PROTOCOL
;
753 Info
->ID
.toi_type
= TdiType
;
754 Info
->ID
.toi_id
= TdiId
;
755 Info
->BufferSize
= OptionLength
;
756 memcpy(Info
->Buffer
, OptionValue
, OptionLength
);
758 if (Context
->SocketState
== SocketStateCreated
)
760 if (Context
->RequestQueue
)
762 Queued
= Context
->RequestQueue
;
763 while ((NextQueued
= Queued
->Next
))
768 Queued
->Next
= HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST
));
771 HeapFree(GetProcessHeap(), 0, Info
);
775 NextQueued
= Queued
->Next
;
776 NextQueued
->Next
= NULL
;
777 NextQueued
->Info
= Info
;
781 Context
->RequestQueue
= HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST
));
782 if (!Context
->RequestQueue
)
784 HeapFree(GetProcessHeap(), 0, Info
);
788 Context
->RequestQueue
->Next
= NULL
;
789 Context
->RequestQueue
->Info
= Info
;
795 Status
= SendRequest(Info
, sizeof(*Info
) + Info
->BufferSize
, IOCTL_TCP_SET_INFORMATION_EX
);
797 HeapFree(GetProcessHeap(), 0, Info
);
806 IN LPWSTR AddressString
,
807 IN DWORD AddressFamily
,
808 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL
,
809 OUT LPSOCKADDR Address
,
810 IN OUT LPDWORD AddressStringLength
)