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
;
160 GetAddressOption(INT Level
, INT OptionName
)
168 /* FIXME: Return proper option */
180 return AO_OPTION_TTL
;
182 case IP_DONTFRAGMENT
:
183 return AO_OPTION_IP_DONTFRAGMENT
;
186 case IP_RECEIVE_BROADCAST
:
187 return AO_OPTION_BROADCAST
;
191 return AO_OPTION_IP_HDRINCL
;
202 /* FIXME: Return proper option */
213 DPRINT1("Unknown level/option name: %d %d\n", Level
, OptionName
);
219 WSHGetSocketInformation(
220 IN PVOID HelperDllSocketContext
,
221 IN SOCKET SocketHandle
,
222 IN HANDLE TdiAddressObjectHandle
,
223 IN HANDLE TdiConnectionObjectHandle
,
226 OUT PCHAR OptionValue
,
227 OUT LPINT OptionLength
)
231 DPRINT1("Get: Unknown level/option name: %d %d\n", Level
, OptionName
);
241 WSHGetWildcardSockaddr(
242 IN PVOID HelperDllSocketContext
,
243 OUT PSOCKADDR Sockaddr
,
244 OUT PINT SockaddrLength
)
246 INT Size
= 2 * sizeof(UINT
);
248 if (*SockaddrLength
< Size
)
250 DPRINT1("Socket address length too small: %d\n", *SockaddrLength
);
254 RtlZeroMemory(Sockaddr
, *SockaddrLength
);
256 Sockaddr
->sa_family
= AF_INET
;
257 *((PUINT
)Sockaddr
->sa_data
) = INADDR_ANY
;
259 /* *SockaddrLength = Size; */
267 WSHGetWinsockMapping(
268 OUT PWINSOCK_MAPPING Mapping
,
269 IN DWORD MappingLength
)
273 DWORD Size
= 2 * sizeof(DWORD
) + Columns
* Rows
* sizeof(DWORD
);
275 if (MappingLength
< Size
)
277 DPRINT1("Mapping length too small: %d\n", MappingLength
);
281 Mapping
->Rows
= Rows
;
282 Mapping
->Columns
= Columns
;
284 Mapping
->Mapping
[0].AddressFamily
= AF_INET
;
285 Mapping
->Mapping
[0].SocketType
= SOCK_STREAM
;
286 Mapping
->Mapping
[0].Protocol
= 0;
288 Mapping
->Mapping
[1].AddressFamily
= AF_INET
;
289 Mapping
->Mapping
[1].SocketType
= SOCK_STREAM
;
290 Mapping
->Mapping
[1].Protocol
= IPPROTO_TCP
;
292 Mapping
->Mapping
[2].AddressFamily
= AF_INET
;
293 Mapping
->Mapping
[2].SocketType
= SOCK_DGRAM
;
294 Mapping
->Mapping
[2].Protocol
= 0;
296 Mapping
->Mapping
[3].AddressFamily
= AF_INET
;
297 Mapping
->Mapping
[3].SocketType
= SOCK_DGRAM
;
298 Mapping
->Mapping
[3].Protocol
= IPPROTO_UDP
;
300 Mapping
->Mapping
[4].AddressFamily
= AF_INET
;
301 Mapping
->Mapping
[4].SocketType
= SOCK_RAW
;
302 Mapping
->Mapping
[4].Protocol
= 0;
304 Mapping
->Mapping
[5].AddressFamily
= AF_INET
;
305 Mapping
->Mapping
[5].SocketType
= SOCK_RAW
;
306 Mapping
->Mapping
[5].Protocol
= IPPROTO_ICMP
;
314 WSHGetWSAProtocolInfo(
315 IN LPWSTR ProviderName
,
316 OUT LPWSAPROTOCOL_INFOW
*ProtocolInfo
,
317 OUT LPDWORD ProtocolInfoEntries
)
328 IN PVOID HelperDllSocketContext
,
329 IN SOCKET SocketHandle
,
330 IN HANDLE TdiAddressObjectHandle
,
331 IN HANDLE TdiConnectionObjectHandle
,
332 IN DWORD IoControlCode
,
333 IN LPVOID InputBuffer
,
334 IN DWORD InputBufferLength
,
335 IN LPVOID OutputBuffer
,
336 IN DWORD OutputBufferLength
,
337 OUT LPDWORD NumberOfBytesReturned
,
338 IN LPWSAOVERLAPPED Overlapped
,
339 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
,
340 OUT LPBOOL NeedsCompletion
)
344 DPRINT1("Ioctl: Unknown IOCTL code: %d\n", IoControlCode
);
353 IN PVOID HelperDllSocketContext
,
354 IN SOCKET SocketHandle
,
355 IN HANDLE TdiAddressObjectHandle
,
356 IN HANDLE TdiConnectionObjectHandle
,
357 IN PVOID LeafHelperDllSocketContext
,
358 IN SOCKET LeafSocketHandle
,
359 IN PSOCKADDR Sockaddr
,
360 IN DWORD SockaddrLength
,
361 IN LPWSABUF CallerData
,
362 IN LPWSABUF CalleeData
,
375 IN DWORD RequestSize
,
382 if (openTcpFile(&TcpCC
) != STATUS_SUCCESS
)
385 Status
= DeviceIoControl(TcpCC
,
396 DPRINT("DeviceIoControl: %d\n", ((Status
== TRUE
) ? 0 : GetLastError()));
407 IN PVOID HelperDllSocketContext
,
408 IN SOCKET SocketHandle
,
409 IN HANDLE TdiAddressObjectHandle
,
410 IN HANDLE TdiConnectionObjectHandle
,
411 IN DWORD NotifyEvent
)
413 PSOCKET_CONTEXT Context
= HelperDllSocketContext
;
416 TDIEntityID
*EntityIDs
;
417 DWORD EntityCount
, i
;
418 PQUEUED_REQUEST QueuedRequest
, NextQueuedRequest
;
422 case WSH_NOTIFY_CLOSE
:
423 DPRINT("WSHNotify: WSH_NOTIFY_CLOSE\n");
424 QueuedRequest
= Context
->RequestQueue
;
425 while (QueuedRequest
)
427 NextQueuedRequest
= QueuedRequest
->Next
;
429 HeapFree(GetProcessHeap(), 0, QueuedRequest
->Info
);
430 HeapFree(GetProcessHeap(), 0, QueuedRequest
);
432 QueuedRequest
= NextQueuedRequest
;
434 HeapFree(GetProcessHeap(), 0, HelperDllSocketContext
);
438 case WSH_NOTIFY_BIND
:
439 DPRINT("WSHNotify: WSH_NOTIFY_BIND\n");
440 Status
= openTcpFile(&TcpCC
);
441 if (Status
!= STATUS_SUCCESS
)
444 Status
= tdiGetEntityIDSet(TcpCC
,
450 if (Status
!= STATUS_SUCCESS
)
453 for (i
= 0; i
< EntityCount
; i
++)
455 if (EntityIDs
[i
].tei_entity
== CO_TL_ENTITY
||
456 EntityIDs
[i
].tei_entity
== CL_TL_ENTITY
||
457 EntityIDs
[i
].tei_entity
== ER_ENTITY
)
459 Context
->AddrFileInstance
= EntityIDs
[i
].tei_instance
;
460 Context
->AddrFileEntityType
= EntityIDs
[i
].tei_entity
;
464 DPRINT("Instance: %x Type: %x\n", Context
->AddrFileInstance
, Context
->AddrFileEntityType
);
466 tdiFreeThingSet(EntityIDs
);
468 Context
->SocketState
= SocketStateBound
;
470 QueuedRequest
= Context
->RequestQueue
;
471 while (QueuedRequest
)
473 QueuedRequest
->Info
->ID
.toi_entity
.tei_entity
= Context
->AddrFileEntityType
;
474 QueuedRequest
->Info
->ID
.toi_entity
.tei_instance
= Context
->AddrFileInstance
;
476 SendRequest(QueuedRequest
->Info
,
477 sizeof(*QueuedRequest
->Info
) + QueuedRequest
->Info
->BufferSize
,
478 IOCTL_TCP_SET_INFORMATION_EX
);
480 NextQueuedRequest
= QueuedRequest
->Next
;
482 HeapFree(GetProcessHeap(), 0, QueuedRequest
->Info
);
483 HeapFree(GetProcessHeap(), 0, QueuedRequest
);
485 QueuedRequest
= NextQueuedRequest
;
487 Context
->RequestQueue
= NULL
;
491 DPRINT1("Unwanted notification received! (%d)\n", NotifyEvent
);
502 IN OUT PINT AddressFamily
,
503 IN OUT PINT SocketType
,
504 IN OUT PINT Protocol
,
505 OUT PUNICODE_STRING TransportDeviceName
,
506 OUT PVOID HelperDllSocketContext
,
507 OUT PDWORD NotificationEvents
)
509 * FUNCTION: Opens a socket
512 return WSHOpenSocket2(AddressFamily
,
518 HelperDllSocketContext
,
526 OUT PINT AddressFamily
,
527 IN OUT PINT SocketType
,
528 IN OUT PINT Protocol
,
531 OUT PUNICODE_STRING TransportDeviceName
,
532 OUT PVOID
*HelperDllSocketContext
,
533 OUT PDWORD NotificationEvents
)
535 * FUNCTION: Opens a socket
537 * AddressFamily = Address of buffer with address family (updated)
538 * SocketType = Address of buffer with type of socket (updated)
539 * Protocol = Address of buffer with protocol number (updated)
540 * Group = Socket group
541 * Flags = Socket flags
542 * TransportDeviceName = Address of buffer to place name of transport device
543 * HelperDllSocketContext = Address of buffer to place socket context pointer
544 * NotificationEvents = Address of buffer to place flags for event notification
546 * Status of operation
548 * Mapping tripple is returned in an canonicalized form
551 PSOCKET_CONTEXT Context
;
552 UNICODE_STRING String
;
553 UNICODE_STRING TcpDeviceName
= RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME
);
554 UNICODE_STRING UdpDeviceName
= RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME
);
555 UNICODE_STRING RawDeviceName
= RTL_CONSTANT_STRING(DD_RAW_IP_DEVICE_NAME
);
557 DPRINT("WSHOpenSocket2 called\n");
559 switch (*SocketType
) {
561 String
= TcpDeviceName
;
565 String
= UdpDeviceName
;
569 if ((*Protocol
< 0) || (*Protocol
> 255))
572 String
= RawDeviceName
;
579 RtlInitUnicodeString(TransportDeviceName
, NULL
);
581 TransportDeviceName
->MaximumLength
= String
.Length
+ /* Transport device name */
582 (4 * sizeof(WCHAR
) + /* Separator and protocol */
583 sizeof(UNICODE_NULL
)); /* Terminating null */
585 TransportDeviceName
->Buffer
= HeapAlloc(
588 TransportDeviceName
->MaximumLength
);
590 if (!TransportDeviceName
->Buffer
)
593 /* Append the transport device name */
594 RtlAppendUnicodeStringToString(TransportDeviceName
, &String
);
596 if (*SocketType
== SOCK_RAW
) {
597 /* Append a separator */
598 TransportDeviceName
->Buffer
[TransportDeviceName
->Length
/ sizeof(WCHAR
)] = OBJ_NAME_PATH_SEPARATOR
;
599 TransportDeviceName
->Length
+= sizeof(WCHAR
);
600 TransportDeviceName
->Buffer
[TransportDeviceName
->Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
602 /* Append the protocol number */
603 String
.Buffer
= TransportDeviceName
->Buffer
+ (TransportDeviceName
->Length
/ sizeof(WCHAR
));
605 String
.MaximumLength
= TransportDeviceName
->MaximumLength
- TransportDeviceName
->Length
;
607 RtlIntegerToUnicodeString((ULONG
)*Protocol
, 10, &String
);
609 TransportDeviceName
->Length
+= String
.Length
;
612 /* Setup a socket context area */
614 Context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(SOCKET_CONTEXT
));
616 RtlFreeUnicodeString(TransportDeviceName
);
620 Context
->AddressFamily
= *AddressFamily
;
621 Context
->SocketType
= *SocketType
;
622 Context
->Protocol
= *Protocol
;
623 Context
->Flags
= Flags
;
624 Context
->SocketState
= SocketStateCreated
;
626 *HelperDllSocketContext
= Context
;
627 *NotificationEvents
= WSH_NOTIFY_CLOSE
| WSH_NOTIFY_BIND
;
634 WSHSetSocketInformation(
635 IN PVOID HelperDllSocketContext
,
636 IN SOCKET SocketHandle
,
637 IN HANDLE TdiAddressObjectHandle
,
638 IN HANDLE TdiConnectionObjectHandle
,
641 IN PCHAR OptionValue
,
644 PSOCKET_CONTEXT Context
= HelperDllSocketContext
;
647 PTCP_REQUEST_SET_INFORMATION_EX Info
;
648 PQUEUED_REQUEST Queued
, NextQueued
;
650 DPRINT("WSHSetSocketInformation\n");
652 /* FIXME: We only handle address file object here */
660 if (OptionLength
< sizeof(BOOL
))
664 Context
->DontRoute
= *(BOOL
*)OptionValue
;
665 /* This is silently ignored on Windows */
669 /* FIXME -- We'll send this to TCPIP */
670 DPRINT1("Set: SO_KEEPALIVE not yet supported\n");
675 DPRINT1("Set: Received unexpected SOL_SOCKET option %d\n", OptionName
);
676 return WSAENOPROTOOPT
;
684 case IP_DONTFRAGMENT
:
686 /* Send these to TCPIP */
690 /* Invalid option -- FIXME */
691 DPRINT1("Set: Received unsupported IPPROTO_IP option %d\n", OptionName
);
700 /* FIXME -- Send this to TCPIP */
701 DPRINT1("Set: TCP_NODELAY not yet supported\n");
706 DPRINT1("Set: Received unexpected IPPROTO_TCP option %d\n", OptionName
);
712 DPRINT1("Set: Received unexpected %d option %d\n", Level
, OptionName
);
716 /* If we get here, GetAddressOption must return something valid */
717 RealOptionName
= GetAddressOption(Level
, OptionName
);
718 ASSERT(RealOptionName
!= 0);
720 Info
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Info
) + OptionLength
);
724 Info
->ID
.toi_entity
.tei_entity
= Context
->AddrFileEntityType
;
725 Info
->ID
.toi_entity
.tei_instance
= Context
->AddrFileInstance
;
726 Info
->ID
.toi_class
= INFO_CLASS_PROTOCOL
;
727 Info
->ID
.toi_type
= INFO_TYPE_ADDRESS_OBJECT
;
728 Info
->ID
.toi_id
= RealOptionName
;
729 Info
->BufferSize
= OptionLength
;
730 memcpy(Info
->Buffer
, OptionValue
, OptionLength
);
732 if (Context
->SocketState
== SocketStateCreated
)
734 if (Context
->RequestQueue
)
736 Queued
= Context
->RequestQueue
;
737 while ((NextQueued
= Queued
->Next
))
742 Queued
->Next
= HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST
));
745 HeapFree(GetProcessHeap(), 0, Info
);
749 NextQueued
= Queued
->Next
;
750 NextQueued
->Next
= NULL
;
751 NextQueued
->Info
= Info
;
755 Context
->RequestQueue
= HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST
));
756 if (!Context
->RequestQueue
)
758 HeapFree(GetProcessHeap(), 0, Info
);
762 Context
->RequestQueue
->Next
= NULL
;
763 Context
->RequestQueue
->Info
= Info
;
769 Status
= SendRequest(Info
, sizeof(*Info
) + Info
->BufferSize
, IOCTL_TCP_SET_INFORMATION_EX
);
771 HeapFree(GetProcessHeap(), 0, Info
);
780 IN LPWSTR AddressString
,
781 IN DWORD AddressFamily
,
782 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL
,
783 OUT LPSOCKADDR Address
,
784 IN OUT LPDWORD AddressStringLength
)