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 return AO_OPTION_TTL
;
170 case IP_DONTFRAGMENT
:
171 return AO_OPTION_IP_DONTFRAGMENT
;
174 case IP_RECEIVE_BROADCAST
:
175 return AO_OPTION_BROADCAST
;
179 return AO_OPTION_IP_HDRINCL
;
182 DPRINT1("Unknown option name for IPPROTO_IP: %d\n", OptionName
);
188 DPRINT1("SOL_SOCKET option %d\n", OptionName
);
192 DPRINT1("Unknown level: %d\n", Level
);
200 WSHGetSocketInformation(
201 IN PVOID HelperDllSocketContext
,
202 IN SOCKET SocketHandle
,
203 IN HANDLE TdiAddressObjectHandle
,
204 IN HANDLE TdiConnectionObjectHandle
,
207 OUT PCHAR OptionValue
,
208 OUT LPINT OptionLength
)
218 WSHGetWildcardSockaddr(
219 IN PVOID HelperDllSocketContext
,
220 OUT PSOCKADDR Sockaddr
,
221 OUT PINT SockaddrLength
)
223 INT Size
= 2 * sizeof(UINT
);
225 if (*SockaddrLength
< Size
)
227 DPRINT1("Socket address length too small: %d\n", *SockaddrLength
);
231 RtlZeroMemory(Sockaddr
, *SockaddrLength
);
233 Sockaddr
->sa_family
= AF_INET
;
234 *((PUINT
)Sockaddr
->sa_data
) = INADDR_ANY
;
236 /* *SockaddrLength = Size; */
244 WSHGetWinsockMapping(
245 OUT PWINSOCK_MAPPING Mapping
,
246 IN DWORD MappingLength
)
250 DWORD Size
= 2 * sizeof(DWORD
) + Columns
* Rows
* sizeof(DWORD
);
252 if (MappingLength
< Size
)
254 DPRINT1("Mapping length too small: %d\n", MappingLength
);
258 Mapping
->Rows
= Rows
;
259 Mapping
->Columns
= Columns
;
261 Mapping
->Mapping
[0].AddressFamily
= AF_INET
;
262 Mapping
->Mapping
[0].SocketType
= SOCK_STREAM
;
263 Mapping
->Mapping
[0].Protocol
= 0;
265 Mapping
->Mapping
[1].AddressFamily
= AF_INET
;
266 Mapping
->Mapping
[1].SocketType
= SOCK_STREAM
;
267 Mapping
->Mapping
[1].Protocol
= IPPROTO_TCP
;
269 Mapping
->Mapping
[2].AddressFamily
= AF_INET
;
270 Mapping
->Mapping
[2].SocketType
= SOCK_DGRAM
;
271 Mapping
->Mapping
[2].Protocol
= 0;
273 Mapping
->Mapping
[3].AddressFamily
= AF_INET
;
274 Mapping
->Mapping
[3].SocketType
= SOCK_DGRAM
;
275 Mapping
->Mapping
[3].Protocol
= IPPROTO_UDP
;
277 Mapping
->Mapping
[4].AddressFamily
= AF_INET
;
278 Mapping
->Mapping
[4].SocketType
= SOCK_RAW
;
279 Mapping
->Mapping
[4].Protocol
= 0;
281 Mapping
->Mapping
[5].AddressFamily
= AF_INET
;
282 Mapping
->Mapping
[5].SocketType
= SOCK_RAW
;
283 Mapping
->Mapping
[5].Protocol
= IPPROTO_ICMP
;
291 WSHGetWSAProtocolInfo(
292 IN LPWSTR ProviderName
,
293 OUT LPWSAPROTOCOL_INFOW
*ProtocolInfo
,
294 OUT LPDWORD ProtocolInfoEntries
)
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
)
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
,
350 IN DWORD RequestSize
,
357 if (openTcpFile(&TcpCC
) != STATUS_SUCCESS
)
360 Status
= DeviceIoControl(TcpCC
,
371 DPRINT("DeviceIoControl: %d\n", ((Status
== TRUE
) ? 0 : GetLastError()));
382 IN PVOID HelperDllSocketContext
,
383 IN SOCKET SocketHandle
,
384 IN HANDLE TdiAddressObjectHandle
,
385 IN HANDLE TdiConnectionObjectHandle
,
386 IN DWORD NotifyEvent
)
388 PSOCKET_CONTEXT Context
= HelperDllSocketContext
;
391 TDIEntityID
*EntityIDs
;
392 DWORD EntityCount
, i
;
393 PQUEUED_REQUEST QueuedRequest
, NextQueuedRequest
;
397 case WSH_NOTIFY_CLOSE
:
398 DPRINT("WSHNotify: WSH_NOTIFY_CLOSE\n");
399 QueuedRequest
= Context
->RequestQueue
;
400 while (QueuedRequest
)
402 NextQueuedRequest
= QueuedRequest
->Next
;
404 HeapFree(GetProcessHeap(), 0, QueuedRequest
->Info
);
405 HeapFree(GetProcessHeap(), 0, QueuedRequest
);
407 QueuedRequest
= NextQueuedRequest
;
409 HeapFree(GetProcessHeap(), 0, HelperDllSocketContext
);
413 case WSH_NOTIFY_BIND
:
414 DPRINT("WSHNotify: WSH_NOTIFY_BIND\n");
415 Status
= openTcpFile(&TcpCC
);
416 if (Status
!= STATUS_SUCCESS
)
419 Status
= tdiGetEntityIDSet(TcpCC
,
425 if (Status
!= STATUS_SUCCESS
)
428 for (i
= 0; i
< EntityCount
; i
++)
430 if (EntityIDs
[i
].tei_entity
== CO_TL_ENTITY
||
431 EntityIDs
[i
].tei_entity
== CL_TL_ENTITY
||
432 EntityIDs
[i
].tei_entity
== ER_ENTITY
)
434 Context
->AddrFileInstance
= EntityIDs
[i
].tei_instance
;
435 Context
->AddrFileEntityType
= EntityIDs
[i
].tei_entity
;
439 DPRINT("Instance: %x Type: %x\n", Context
->AddrFileInstance
, Context
->AddrFileEntityType
);
441 tdiFreeThingSet(EntityIDs
);
443 Context
->SocketState
= SocketStateBound
;
445 QueuedRequest
= Context
->RequestQueue
;
446 while (QueuedRequest
)
448 QueuedRequest
->Info
->ID
.toi_entity
.tei_entity
= Context
->AddrFileEntityType
;
449 QueuedRequest
->Info
->ID
.toi_entity
.tei_instance
= Context
->AddrFileInstance
;
451 SendRequest(QueuedRequest
->Info
,
452 sizeof(*QueuedRequest
->Info
) + QueuedRequest
->Info
->BufferSize
,
453 IOCTL_TCP_SET_INFORMATION_EX
);
455 NextQueuedRequest
= QueuedRequest
->Next
;
457 HeapFree(GetProcessHeap(), 0, QueuedRequest
->Info
);
458 HeapFree(GetProcessHeap(), 0, QueuedRequest
);
460 QueuedRequest
= NextQueuedRequest
;
462 Context
->RequestQueue
= NULL
;
466 DPRINT1("Unwanted notification received! (%d)\n", NotifyEvent
);
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
)
484 * FUNCTION: Opens a socket
487 return WSHOpenSocket2(AddressFamily
,
493 HelperDllSocketContext
,
501 OUT PINT AddressFamily
,
502 IN OUT PINT SocketType
,
503 IN OUT PINT Protocol
,
506 OUT PUNICODE_STRING TransportDeviceName
,
507 OUT PVOID
*HelperDllSocketContext
,
508 OUT PDWORD NotificationEvents
)
510 * FUNCTION: Opens a socket
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
521 * Status of operation
523 * Mapping tripple is returned in an canonicalized form
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
);
532 DPRINT("WSHOpenSocket2 called\n");
534 switch (*SocketType
) {
536 String
= TcpDeviceName
;
540 String
= UdpDeviceName
;
544 if ((*Protocol
< 0) || (*Protocol
> 255))
547 String
= RawDeviceName
;
554 RtlInitUnicodeString(TransportDeviceName
, NULL
);
556 TransportDeviceName
->MaximumLength
= String
.Length
+ /* Transport device name */
557 (4 * sizeof(WCHAR
) + /* Separator and protocol */
558 sizeof(UNICODE_NULL
)); /* Terminating null */
560 TransportDeviceName
->Buffer
= HeapAlloc(
563 TransportDeviceName
->MaximumLength
);
565 if (!TransportDeviceName
->Buffer
)
568 /* Append the transport device name */
569 RtlAppendUnicodeStringToString(TransportDeviceName
, &String
);
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
;
577 /* Append the protocol number */
578 String
.Buffer
= TransportDeviceName
->Buffer
+ (TransportDeviceName
->Length
/ sizeof(WCHAR
));
580 String
.MaximumLength
= TransportDeviceName
->MaximumLength
- TransportDeviceName
->Length
;
582 RtlIntegerToUnicodeString((ULONG
)*Protocol
, 10, &String
);
584 TransportDeviceName
->Length
+= String
.Length
;
587 /* Setup a socket context area */
589 Context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(SOCKET_CONTEXT
));
591 RtlFreeUnicodeString(TransportDeviceName
);
595 Context
->AddressFamily
= *AddressFamily
;
596 Context
->SocketType
= *SocketType
;
597 Context
->Protocol
= *Protocol
;
598 Context
->Flags
= Flags
;
599 Context
->SocketState
= SocketStateCreated
;
601 *HelperDllSocketContext
= Context
;
602 *NotificationEvents
= WSH_NOTIFY_CLOSE
| WSH_NOTIFY_BIND
;
609 WSHSetSocketInformation(
610 IN PVOID HelperDllSocketContext
,
611 IN SOCKET SocketHandle
,
612 IN HANDLE TdiAddressObjectHandle
,
613 IN HANDLE TdiConnectionObjectHandle
,
616 IN PCHAR OptionValue
,
619 PSOCKET_CONTEXT Context
= HelperDllSocketContext
;
622 PTCP_REQUEST_SET_INFORMATION_EX Info
;
623 PQUEUED_REQUEST Queued
, NextQueued
;
625 DPRINT("WSHSetSocketInformation\n");
627 /* FIXME: We only handle address file object here */
629 RealOptionName
= GetAddressOption(Level
, OptionName
);
631 /* FIXME: Support all options */
633 return 0; /* return WSAEINVAL; */
635 Info
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Info
) + OptionLength
);
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
);
647 if (Context
->SocketState
== SocketStateCreated
)
649 if (Context
->RequestQueue
)
651 Queued
= Context
->RequestQueue
;
652 while ((NextQueued
= Queued
->Next
))
657 Queued
->Next
= HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST
));
660 HeapFree(GetProcessHeap(), 0, Info
);
664 NextQueued
= Queued
->Next
;
665 NextQueued
->Next
= NULL
;
666 NextQueued
->Info
= Info
;
670 Context
->RequestQueue
= HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST
));
671 if (!Context
->RequestQueue
)
673 HeapFree(GetProcessHeap(), 0, Info
);
677 Context
->RequestQueue
->Next
= NULL
;
678 Context
->RequestQueue
->Info
= Info
;
684 Status
= SendRequest(Info
, sizeof(*Info
) + Info
->BufferSize
, IOCTL_TCP_SET_INFORMATION_EX
);
686 HeapFree(GetProcessHeap(), 0, Info
);
695 IN LPWSTR AddressString
,
696 IN DWORD AddressFamily
,
697 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL
,
698 OUT LPSOCKADDR Address
,
699 IN OUT LPDWORD AddressStringLength
)