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 DWORD 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("Unknown level: %d\n", Level
);
195 WSHGetSocketInformation(
196 IN PVOID HelperDllSocketContext
,
197 IN SOCKET SocketHandle
,
198 IN HANDLE TdiAddressObjectHandle
,
199 IN HANDLE TdiConnectionObjectHandle
,
202 OUT PCHAR OptionValue
,
203 OUT LPINT OptionLength
)
213 WSHGetWildcardSockaddr(
214 IN PVOID HelperDllSocketContext
,
215 OUT PSOCKADDR Sockaddr
,
216 OUT PINT SockaddrLength
)
218 DWORD Size
= 2 * sizeof(UINT
);
220 if (*SockaddrLength
< Size
)
222 DPRINT1("Socket address length too small: %d\n", *SockaddrLength
);
226 RtlZeroMemory(Sockaddr
, *SockaddrLength
);
228 Sockaddr
->sa_family
= AF_INET
;
229 *((PUINT
)Sockaddr
->sa_data
) = INADDR_ANY
;
231 /* *SockaddrLength = Size; */
239 WSHGetWinsockMapping(
240 OUT PWINSOCK_MAPPING Mapping
,
241 IN DWORD MappingLength
)
245 DWORD Size
= 2 * sizeof(DWORD
) + Columns
* Rows
* sizeof(DWORD
);
247 if (MappingLength
< Size
)
249 DPRINT1("Mapping length too small: %d\n", MappingLength
);
253 Mapping
->Rows
= Rows
;
254 Mapping
->Columns
= Columns
;
256 Mapping
->Mapping
[0].AddressFamily
= AF_INET
;
257 Mapping
->Mapping
[0].SocketType
= SOCK_STREAM
;
258 Mapping
->Mapping
[0].Protocol
= 0;
260 Mapping
->Mapping
[1].AddressFamily
= AF_INET
;
261 Mapping
->Mapping
[1].SocketType
= SOCK_STREAM
;
262 Mapping
->Mapping
[1].Protocol
= IPPROTO_TCP
;
264 Mapping
->Mapping
[2].AddressFamily
= AF_INET
;
265 Mapping
->Mapping
[2].SocketType
= SOCK_DGRAM
;
266 Mapping
->Mapping
[2].Protocol
= 0;
268 Mapping
->Mapping
[3].AddressFamily
= AF_INET
;
269 Mapping
->Mapping
[3].SocketType
= SOCK_DGRAM
;
270 Mapping
->Mapping
[3].Protocol
= IPPROTO_UDP
;
272 Mapping
->Mapping
[4].AddressFamily
= AF_INET
;
273 Mapping
->Mapping
[4].SocketType
= SOCK_RAW
;
274 Mapping
->Mapping
[4].Protocol
= 0;
276 Mapping
->Mapping
[5].AddressFamily
= AF_INET
;
277 Mapping
->Mapping
[5].SocketType
= SOCK_RAW
;
278 Mapping
->Mapping
[5].Protocol
= IPPROTO_ICMP
;
286 WSHGetWSAProtocolInfo(
287 IN LPWSTR ProviderName
,
288 OUT LPWSAPROTOCOL_INFOW
*ProtocolInfo
,
289 OUT LPDWORD ProtocolInfoEntries
)
300 IN PVOID HelperDllSocketContext
,
301 IN SOCKET SocketHandle
,
302 IN HANDLE TdiAddressObjectHandle
,
303 IN HANDLE TdiConnectionObjectHandle
,
304 IN DWORD IoControlCode
,
305 IN LPVOID InputBuffer
,
306 IN DWORD InputBufferLength
,
307 IN LPVOID OutputBuffer
,
308 IN DWORD OutputBufferLength
,
309 OUT LPDWORD NumberOfBytesReturned
,
310 IN LPWSAOVERLAPPED Overlapped
,
311 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine
,
312 OUT LPBOOL NeedsCompletion
)
323 IN PVOID HelperDllSocketContext
,
324 IN SOCKET SocketHandle
,
325 IN HANDLE TdiAddressObjectHandle
,
326 IN HANDLE TdiConnectionObjectHandle
,
327 IN PVOID LeafHelperDllSocketContext
,
328 IN SOCKET LeafSocketHandle
,
329 IN PSOCKADDR Sockaddr
,
330 IN DWORD SockaddrLength
,
331 IN LPWSABUF CallerData
,
332 IN LPWSABUF CalleeData
,
345 IN DWORD RequestSize
,
352 if (openTcpFile(&TcpCC
) != STATUS_SUCCESS
)
355 Status
= DeviceIoControl(TcpCC
,
366 DPRINT("DeviceIoControl: %d\n", ((Status
== TRUE
) ? 0 : GetLastError()));
377 IN PVOID HelperDllSocketContext
,
378 IN SOCKET SocketHandle
,
379 IN HANDLE TdiAddressObjectHandle
,
380 IN HANDLE TdiConnectionObjectHandle
,
381 IN DWORD NotifyEvent
)
383 PSOCKET_CONTEXT Context
= HelperDllSocketContext
;
386 TDIEntityID
*EntityIDs
;
387 DWORD EntityCount
, i
;
388 PQUEUED_REQUEST QueuedRequest
, NextQueuedRequest
;
392 case WSH_NOTIFY_CLOSE
:
393 DPRINT("WSHNotify: WSH_NOTIFY_CLOSE\n");
394 QueuedRequest
= Context
->RequestQueue
;
395 while (QueuedRequest
)
397 NextQueuedRequest
= QueuedRequest
->Next
;
399 HeapFree(GetProcessHeap(), 0, QueuedRequest
->Info
);
400 HeapFree(GetProcessHeap(), 0, QueuedRequest
);
402 QueuedRequest
= NextQueuedRequest
;
404 HeapFree(GetProcessHeap(), 0, HelperDllSocketContext
);
408 case WSH_NOTIFY_BIND
:
409 DPRINT("WSHNotify: WSH_NOTIFY_BIND\n");
410 Status
= openTcpFile(&TcpCC
);
411 if (Status
!= STATUS_SUCCESS
)
414 Status
= tdiGetEntityIDSet(TcpCC
,
420 if (Status
!= STATUS_SUCCESS
)
423 for (i
= 0; i
< EntityCount
; i
++)
425 if (EntityIDs
[i
].tei_entity
== CO_TL_ENTITY
||
426 EntityIDs
[i
].tei_entity
== CL_TL_ENTITY
||
427 EntityIDs
[i
].tei_entity
== ER_ENTITY
)
429 Context
->AddrFileInstance
= EntityIDs
[i
].tei_instance
;
430 Context
->AddrFileEntityType
= EntityIDs
[i
].tei_entity
;
434 DPRINT("Instance: %x Type: %x\n", Context
->AddrFileInstance
, Context
->AddrFileEntityType
);
436 tdiFreeThingSet(EntityIDs
);
438 Context
->SocketState
= SocketStateBound
;
440 QueuedRequest
= Context
->RequestQueue
;
441 while (QueuedRequest
)
443 QueuedRequest
->Info
->ID
.toi_entity
.tei_entity
= Context
->AddrFileEntityType
;
444 QueuedRequest
->Info
->ID
.toi_entity
.tei_instance
= Context
->AddrFileInstance
;
446 SendRequest(QueuedRequest
->Info
,
447 sizeof(*QueuedRequest
->Info
) + QueuedRequest
->Info
->BufferSize
,
448 IOCTL_TCP_SET_INFORMATION_EX
);
450 NextQueuedRequest
= QueuedRequest
->Next
;
452 HeapFree(GetProcessHeap(), 0, QueuedRequest
->Info
);
453 HeapFree(GetProcessHeap(), 0, QueuedRequest
);
455 QueuedRequest
= NextQueuedRequest
;
457 Context
->RequestQueue
= NULL
;
461 DPRINT1("Unwanted notification received! (%d)\n", NotifyEvent
);
472 IN OUT PINT AddressFamily
,
473 IN OUT PINT SocketType
,
474 IN OUT PINT Protocol
,
475 OUT PUNICODE_STRING TransportDeviceName
,
476 OUT PVOID HelperDllSocketContext
,
477 OUT PDWORD NotificationEvents
)
479 * FUNCTION: Opens a socket
482 return WSHOpenSocket2(AddressFamily
,
488 HelperDllSocketContext
,
496 OUT PINT AddressFamily
,
497 IN OUT PINT SocketType
,
498 IN OUT PINT Protocol
,
501 OUT PUNICODE_STRING TransportDeviceName
,
502 OUT PVOID
*HelperDllSocketContext
,
503 OUT PDWORD NotificationEvents
)
505 * FUNCTION: Opens a socket
507 * AddressFamily = Address of buffer with address family (updated)
508 * SocketType = Address of buffer with type of socket (updated)
509 * Protocol = Address of buffer with protocol number (updated)
510 * Group = Socket group
511 * Flags = Socket flags
512 * TransportDeviceName = Address of buffer to place name of transport device
513 * HelperDllSocketContext = Address of buffer to place socket context pointer
514 * NotificationEvents = Address of buffer to place flags for event notification
516 * Status of operation
518 * Mapping tripple is returned in an canonicalized form
521 PSOCKET_CONTEXT Context
;
522 UNICODE_STRING String
;
523 UNICODE_STRING TcpDeviceName
= RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME
);
524 UNICODE_STRING UdpDeviceName
= RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME
);
525 UNICODE_STRING RawDeviceName
= RTL_CONSTANT_STRING(DD_RAW_IP_DEVICE_NAME
);
528 DPRINT("WSHOpenSocket2 called\n");
530 switch (*SocketType
) {
532 String
= TcpDeviceName
;
536 String
= UdpDeviceName
;
540 if ((*Protocol
< 0) || (*Protocol
> 255))
543 String
= RawDeviceName
;
550 RtlInitUnicodeString(TransportDeviceName
, NULL
);
552 TransportDeviceName
->MaximumLength
= String
.Length
+ /* Transport device name */
553 (4 * sizeof(WCHAR
) + /* Separator and protocol */
554 sizeof(UNICODE_NULL
)); /* Terminating null */
556 TransportDeviceName
->Buffer
= HeapAlloc(
559 TransportDeviceName
->MaximumLength
);
561 if (!TransportDeviceName
->Buffer
)
564 /* Append the transport device name */
565 Status
= RtlAppendUnicodeStringToString(TransportDeviceName
, &String
);
567 if (*SocketType
== SOCK_RAW
) {
568 /* Append a separator */
569 TransportDeviceName
->Buffer
[TransportDeviceName
->Length
/ sizeof(WCHAR
)] = OBJ_NAME_PATH_SEPARATOR
;
570 TransportDeviceName
->Length
+= sizeof(WCHAR
);
571 TransportDeviceName
->Buffer
[TransportDeviceName
->Length
/ sizeof(WCHAR
)] = UNICODE_NULL
;
573 /* Append the protocol number */
574 String
.Buffer
= TransportDeviceName
->Buffer
+ (TransportDeviceName
->Length
/ sizeof(WCHAR
));
576 String
.MaximumLength
= TransportDeviceName
->MaximumLength
- TransportDeviceName
->Length
;
578 Status
= RtlIntegerToUnicodeString((ULONG
)*Protocol
, 10, &String
);
580 TransportDeviceName
->Length
+= String
.Length
;
583 /* Setup a socket context area */
585 Context
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(SOCKET_CONTEXT
));
587 RtlFreeUnicodeString(TransportDeviceName
);
591 Context
->AddressFamily
= *AddressFamily
;
592 Context
->SocketType
= *SocketType
;
593 Context
->Protocol
= *Protocol
;
594 Context
->Flags
= Flags
;
595 Context
->SocketState
= SocketStateCreated
;
597 *HelperDllSocketContext
= Context
;
598 *NotificationEvents
= WSH_NOTIFY_CLOSE
| WSH_NOTIFY_BIND
;
605 WSHSetSocketInformation(
606 IN PVOID HelperDllSocketContext
,
607 IN SOCKET SocketHandle
,
608 IN HANDLE TdiAddressObjectHandle
,
609 IN HANDLE TdiConnectionObjectHandle
,
612 IN PCHAR OptionValue
,
615 PSOCKET_CONTEXT Context
= HelperDllSocketContext
;
618 PTCP_REQUEST_SET_INFORMATION_EX Info
;
619 PQUEUED_REQUEST Queued
, NextQueued
;
621 DPRINT("WSHSetSocketInformation\n");
623 /* FIXME: We only handle address file object here */
625 RealOptionName
= GetAddressOption(Level
, OptionName
);
629 Info
= HeapAlloc(GetProcessHeap(), 0, sizeof(*Info
) + OptionLength
);
633 Info
->ID
.toi_entity
.tei_entity
= Context
->AddrFileEntityType
;
634 Info
->ID
.toi_entity
.tei_instance
= Context
->AddrFileInstance
;
635 Info
->ID
.toi_class
= INFO_CLASS_PROTOCOL
;
636 Info
->ID
.toi_type
= INFO_TYPE_ADDRESS_OBJECT
;
637 Info
->ID
.toi_id
= RealOptionName
;
638 Info
->BufferSize
= OptionLength
;
639 memcpy(Info
->Buffer
, OptionValue
, OptionLength
);
641 if (Context
->SocketState
== SocketStateCreated
)
643 if (Context
->RequestQueue
)
645 Queued
= Context
->RequestQueue
;
646 while ((NextQueued
= Queued
->Next
))
651 Queued
->Next
= HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST
));
654 HeapFree(GetProcessHeap(), 0, Info
);
658 NextQueued
= Queued
->Next
;
659 NextQueued
->Next
= NULL
;
660 NextQueued
->Info
= Info
;
664 Context
->RequestQueue
= HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST
));
665 if (!Context
->RequestQueue
)
667 HeapFree(GetProcessHeap(), 0, Info
);
671 Context
->RequestQueue
->Next
= NULL
;
672 Context
->RequestQueue
->Info
= Info
;
678 Status
= SendRequest(Info
, sizeof(*Info
) + Info
->BufferSize
, IOCTL_TCP_SET_INFORMATION_EX
);
680 HeapFree(GetProcessHeap(), 0, Info
);
689 IN LPWSTR AddressString
,
690 IN DWORD AddressFamily
,
691 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL
,
692 OUT LPSOCKADDR Address
,
693 IN OUT LPDWORD AddressStringLength
)