[WSHTCPIP]
[reactos.git] / reactos / dll / win32 / wshtcpip / wshtcpip.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS WinSock Helper DLL for TCP/IP
4 * FILE: wshtcpip.c
5 * PURPOSE: DLL entry
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * REVISIONS:
8 * CSH 01/09-2000 Created
9 */
10 #include "wshtcpip.h"
11 #define NDEBUG
12 #include <debug.h>
13
14 BOOL
15 EXPORT
16 DllMain(HANDLE hInstDll,
17 ULONG dwReason,
18 PVOID Reserved)
19 {
20 DPRINT("DllMain of wshtcpip.dll\n");
21
22 switch (dwReason) {
23 case DLL_PROCESS_ATTACH:
24 /* Don't need thread attach notifications
25 so disable them to improve performance */
26 DisableThreadLibraryCalls(hInstDll);
27 break;
28
29 case DLL_THREAD_ATTACH:
30 break;
31
32 case DLL_THREAD_DETACH:
33 break;
34
35 case DLL_PROCESS_DETACH:
36 break;
37 }
38 return TRUE;
39 }
40
41
42 INT
43 EXPORT
44 WSHAddressToString(
45 IN LPSOCKADDR Address,
46 IN INT AddressLength,
47 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL,
48 OUT LPWSTR AddressString,
49 IN OUT LPDWORD AddressStringLength)
50 {
51 UNIMPLEMENTED
52
53 return NO_ERROR;
54 }
55
56
57 INT
58 EXPORT
59 WSHEnumProtocols(
60 IN LPINT lpiProtocols OPTIONAL,
61 IN LPWSTR lpTransportKeyName,
62 IN OUT LPVOID lpProtocolBuffer,
63 IN OUT LPDWORD lpdwBufferLength)
64 {
65 UNIMPLEMENTED
66
67 return NO_ERROR;
68 }
69
70
71 INT
72 EXPORT
73 WSHGetBroadcastSockaddr(
74 IN PVOID HelperDllSocketContext,
75 OUT PSOCKADDR Sockaddr,
76 OUT PINT SockaddrLength)
77 {
78 INT Size = 2 * sizeof(UINT);
79
80 if (*SockaddrLength < Size)
81 {
82 DPRINT1("Socket address length too small: %d\n", *SockaddrLength);
83 return WSAEFAULT;
84 }
85
86 RtlZeroMemory(Sockaddr, *SockaddrLength);
87
88 Sockaddr->sa_family = AF_INET;
89 *((PUINT)Sockaddr->sa_data) = INADDR_BROADCAST;
90
91 /* *SockaddrLength = Size; */
92
93 return NO_ERROR;
94 }
95
96
97 INT
98 EXPORT
99 WSHGetProviderGuid(
100 IN LPWSTR ProviderName,
101 OUT LPGUID ProviderGuid)
102 {
103 UNIMPLEMENTED
104
105 return NO_ERROR;
106 }
107
108
109 /*
110 Document from OSR how WSHGetSockaddrType works
111 http://www.osronline.com/ddkx/network/37wshfun_5lyq.htm
112 */
113
114 INT
115 EXPORT
116 WSHGetSockaddrType(
117 IN PSOCKADDR Sockaddr,
118 IN DWORD SockaddrLength,
119 OUT PSOCKADDR_INFO SockaddrInfo)
120 {
121 PSOCKADDR_IN ipv4 = (PSOCKADDR_IN)Sockaddr;
122
123 if (!ipv4 || !SockaddrInfo || SockaddrLength < sizeof(SOCKADDR_IN) ||
124 ipv4->sin_family != AF_INET)
125 {
126 DPRINT1("Invalid parameter: %x %x %d %u\n", ipv4, SockaddrInfo, SockaddrLength, (ipv4 ? ipv4->sin_family : 0));
127 return WSAEINVAL;
128 }
129
130 switch (ntohl(ipv4->sin_addr.s_addr))
131 {
132 case INADDR_ANY:
133 SockaddrInfo->AddressInfo = SockaddrAddressInfoWildcard;
134 break;
135
136 case INADDR_BROADCAST:
137 SockaddrInfo->AddressInfo = SockaddrAddressInfoBroadcast;
138 break;
139
140 case INADDR_LOOPBACK:
141 SockaddrInfo->AddressInfo = SockaddrAddressInfoLoopback;
142 break;
143
144 default:
145 SockaddrInfo->AddressInfo = SockaddrAddressInfoNormal;
146 break;
147 }
148
149 if (ntohs(ipv4->sin_port) == 0)
150 SockaddrInfo->EndpointInfo = SockaddrEndpointInfoWildcard;
151 else if (ntohs(ipv4->sin_port) < IPPORT_RESERVED)
152 SockaddrInfo->EndpointInfo = SockaddrEndpointInfoReserved;
153 else
154 SockaddrInfo->EndpointInfo = SockaddrEndpointInfoNormal;
155
156 return NO_ERROR;
157 }
158
159 static
160 void
161 GetTdiTypeId(
162 _In_ INT Level,
163 _In_ INT OptionName,
164 _Out_ PULONG TdiType,
165 _Out_ PULONG TdiId)
166 {
167 switch (Level)
168 {
169 case SOL_SOCKET:
170 *TdiType = INFO_TYPE_ADDRESS_OBJECT;
171 switch (OptionName)
172 {
173 case SO_KEEPALIVE:
174 /* FIXME: Return proper option */
175 ASSERT(FALSE);
176 break;
177 default:
178 break;
179 }
180 break;
181
182 case IPPROTO_IP:
183 *TdiType = INFO_TYPE_ADDRESS_OBJECT;
184 switch (OptionName)
185 {
186 case IP_TTL:
187 *TdiId = AO_OPTION_TTL;
188 return;
189
190 case IP_DONTFRAGMENT:
191 *TdiId = AO_OPTION_IP_DONTFRAGMENT;
192 return;
193
194 #if 0
195 case IP_RECEIVE_BROADCAST:
196 *TdiId = AO_OPTION_BROADCAST;
197 return;
198 #endif
199
200 case IP_HDRINCL:
201 *TdiId = AO_OPTION_IP_HDRINCL;
202 return;
203
204 default:
205 break;
206 }
207 break;
208
209 case IPPROTO_TCP:
210 switch (OptionName)
211 {
212 *TdiType = INFO_TYPE_CONNECTION;
213 case TCP_NODELAY:
214 *TdiId = TCP_SOCKET_NODELAY;
215 return;
216 default:
217 break;
218 }
219
220 default:
221 break;
222 }
223
224 DPRINT1("Unknown level/option name: %d %d\n", Level, OptionName);
225 *TdiType = 0;
226 *TdiId = 0;
227 }
228
229 INT
230 EXPORT
231 WSHGetSocketInformation(
232 IN PVOID HelperDllSocketContext,
233 IN SOCKET SocketHandle,
234 IN HANDLE TdiAddressObjectHandle,
235 IN HANDLE TdiConnectionObjectHandle,
236 IN INT Level,
237 IN INT OptionName,
238 OUT PCHAR OptionValue,
239 OUT LPINT OptionLength)
240 {
241 UNIMPLEMENTED
242
243 DPRINT1("Get: Unknown level/option name: %d %d\n", Level, OptionName);
244
245 *OptionLength = 0;
246
247 return NO_ERROR;
248 }
249
250
251 INT
252 EXPORT
253 WSHGetWildcardSockaddr(
254 IN PVOID HelperDllSocketContext,
255 OUT PSOCKADDR Sockaddr,
256 OUT PINT SockaddrLength)
257 {
258 INT Size = 2 * sizeof(UINT);
259
260 if (*SockaddrLength < Size)
261 {
262 DPRINT1("Socket address length too small: %d\n", *SockaddrLength);
263 return WSAEFAULT;
264 }
265
266 RtlZeroMemory(Sockaddr, *SockaddrLength);
267
268 Sockaddr->sa_family = AF_INET;
269 *((PUINT)Sockaddr->sa_data) = INADDR_ANY;
270
271 /* *SockaddrLength = Size; */
272
273 return NO_ERROR;
274 }
275
276
277 DWORD
278 EXPORT
279 WSHGetWinsockMapping(
280 OUT PWINSOCK_MAPPING Mapping,
281 IN DWORD MappingLength)
282 {
283 DWORD Rows = 6;
284 DWORD Columns = 3;
285 DWORD Size = 2 * sizeof(DWORD) + Columns * Rows * sizeof(DWORD);
286
287 if (MappingLength < Size)
288 {
289 DPRINT1("Mapping length too small: %d\n", MappingLength);
290 return Size;
291 }
292
293 Mapping->Rows = Rows;
294 Mapping->Columns = Columns;
295
296 Mapping->Mapping[0].AddressFamily = AF_INET;
297 Mapping->Mapping[0].SocketType = SOCK_STREAM;
298 Mapping->Mapping[0].Protocol = 0;
299
300 Mapping->Mapping[1].AddressFamily = AF_INET;
301 Mapping->Mapping[1].SocketType = SOCK_STREAM;
302 Mapping->Mapping[1].Protocol = IPPROTO_TCP;
303
304 Mapping->Mapping[2].AddressFamily = AF_INET;
305 Mapping->Mapping[2].SocketType = SOCK_DGRAM;
306 Mapping->Mapping[2].Protocol = 0;
307
308 Mapping->Mapping[3].AddressFamily = AF_INET;
309 Mapping->Mapping[3].SocketType = SOCK_DGRAM;
310 Mapping->Mapping[3].Protocol = IPPROTO_UDP;
311
312 Mapping->Mapping[4].AddressFamily = AF_INET;
313 Mapping->Mapping[4].SocketType = SOCK_RAW;
314 Mapping->Mapping[4].Protocol = 0;
315
316 Mapping->Mapping[5].AddressFamily = AF_INET;
317 Mapping->Mapping[5].SocketType = SOCK_RAW;
318 Mapping->Mapping[5].Protocol = IPPROTO_ICMP;
319
320 return NO_ERROR;
321 }
322
323
324 INT
325 EXPORT
326 WSHGetWSAProtocolInfo(
327 IN LPWSTR ProviderName,
328 OUT LPWSAPROTOCOL_INFOW *ProtocolInfo,
329 OUT LPDWORD ProtocolInfoEntries)
330 {
331 UNIMPLEMENTED
332
333 return NO_ERROR;
334 }
335
336
337 INT
338 EXPORT
339 WSHIoctl(
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)
353 {
354 UNIMPLEMENTED
355
356 DPRINT1("Ioctl: Unknown IOCTL code: %d\n", IoControlCode);
357
358 return NO_ERROR;
359 }
360
361
362 INT
363 EXPORT
364 WSHJoinLeaf(
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,
375 IN LPQOS SocketQOS,
376 IN LPQOS GroupQOS,
377 IN DWORD Flags)
378 {
379 UNIMPLEMENTED
380
381 return NO_ERROR;
382 }
383
384 INT
385 SendRequest(
386 IN PVOID Request,
387 IN DWORD RequestSize,
388 IN DWORD IOCTL)
389 {
390 BOOLEAN Status;
391 HANDLE TcpCC;
392 DWORD BytesReturned;
393
394 if (openTcpFile(&TcpCC) != STATUS_SUCCESS)
395 return WSAEINVAL;
396
397 Status = DeviceIoControl(TcpCC,
398 IOCTL,
399 Request,
400 RequestSize,
401 NULL,
402 0,
403 &BytesReturned,
404 NULL);
405
406 closeTcpFile(TcpCC);
407
408 DPRINT("DeviceIoControl: %d\n", ((Status == TRUE) ? 0 : GetLastError()));
409
410 if (!Status)
411 return WSAEINVAL;
412
413 return NO_ERROR;
414 }
415
416 INT
417 EXPORT
418 WSHNotify(
419 IN PVOID HelperDllSocketContext,
420 IN SOCKET SocketHandle,
421 IN HANDLE TdiAddressObjectHandle,
422 IN HANDLE TdiConnectionObjectHandle,
423 IN DWORD NotifyEvent)
424 {
425 PSOCKET_CONTEXT Context = HelperDllSocketContext;
426 NTSTATUS Status;
427 HANDLE TcpCC;
428 TDIEntityID *EntityIDs;
429 DWORD EntityCount, i;
430 PQUEUED_REQUEST QueuedRequest, NextQueuedRequest;
431
432 switch (NotifyEvent)
433 {
434 case WSH_NOTIFY_CLOSE:
435 DPRINT("WSHNotify: WSH_NOTIFY_CLOSE\n");
436 QueuedRequest = Context->RequestQueue;
437 while (QueuedRequest)
438 {
439 NextQueuedRequest = QueuedRequest->Next;
440
441 HeapFree(GetProcessHeap(), 0, QueuedRequest->Info);
442 HeapFree(GetProcessHeap(), 0, QueuedRequest);
443
444 QueuedRequest = NextQueuedRequest;
445 }
446 HeapFree(GetProcessHeap(), 0, HelperDllSocketContext);
447 break;
448
449
450 case WSH_NOTIFY_BIND:
451 DPRINT("WSHNotify: WSH_NOTIFY_BIND\n");
452 Status = openTcpFile(&TcpCC);
453 if (Status != STATUS_SUCCESS)
454 return WSAEINVAL;
455
456 Status = tdiGetEntityIDSet(TcpCC,
457 &EntityIDs,
458 &EntityCount);
459
460 closeTcpFile(TcpCC);
461
462 if (Status != STATUS_SUCCESS)
463 return WSAEINVAL;
464
465 for (i = 0; i < EntityCount; i++)
466 {
467 if (EntityIDs[i].tei_entity == CO_TL_ENTITY ||
468 EntityIDs[i].tei_entity == CL_TL_ENTITY ||
469 EntityIDs[i].tei_entity == ER_ENTITY)
470 {
471 Context->AddrFileInstance = EntityIDs[i].tei_instance;
472 Context->AddrFileEntityType = EntityIDs[i].tei_entity;
473 }
474 }
475
476 DPRINT("Instance: %x Type: %x\n", Context->AddrFileInstance, Context->AddrFileEntityType);
477
478 tdiFreeThingSet(EntityIDs);
479
480 Context->SocketState = SocketStateBound;
481
482 QueuedRequest = Context->RequestQueue;
483 while (QueuedRequest)
484 {
485 QueuedRequest->Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType;
486 QueuedRequest->Info->ID.toi_entity.tei_instance = Context->AddrFileInstance;
487
488 SendRequest(QueuedRequest->Info,
489 sizeof(*QueuedRequest->Info) + QueuedRequest->Info->BufferSize,
490 IOCTL_TCP_SET_INFORMATION_EX);
491
492 NextQueuedRequest = QueuedRequest->Next;
493
494 HeapFree(GetProcessHeap(), 0, QueuedRequest->Info);
495 HeapFree(GetProcessHeap(), 0, QueuedRequest);
496
497 QueuedRequest = NextQueuedRequest;
498 }
499 Context->RequestQueue = NULL;
500 break;
501
502 default:
503 DPRINT1("Unwanted notification received! (%d)\n", NotifyEvent);
504 break;
505 }
506
507 return NO_ERROR;
508 }
509
510
511 INT
512 EXPORT
513 WSHOpenSocket(
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)
520 /*
521 * FUNCTION: Opens a socket
522 */
523 {
524 return WSHOpenSocket2(AddressFamily,
525 SocketType,
526 Protocol,
527 0,
528 0,
529 TransportDeviceName,
530 HelperDllSocketContext,
531 NotificationEvents);
532 }
533
534
535 INT
536 EXPORT
537 WSHOpenSocket2(
538 OUT PINT AddressFamily,
539 IN OUT PINT SocketType,
540 IN OUT PINT Protocol,
541 IN GROUP Group,
542 IN DWORD Flags,
543 OUT PUNICODE_STRING TransportDeviceName,
544 OUT PVOID *HelperDllSocketContext,
545 OUT PDWORD NotificationEvents)
546 /*
547 * FUNCTION: Opens a socket
548 * ARGUMENTS:
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
557 * RETURNS:
558 * Status of operation
559 * NOTES:
560 * Mapping tripple is returned in an canonicalized form
561 */
562 {
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);
568
569 DPRINT("WSHOpenSocket2 called\n");
570
571 switch (*SocketType) {
572 case SOCK_STREAM:
573 String = TcpDeviceName;
574 break;
575
576 case SOCK_DGRAM:
577 String = UdpDeviceName;
578 break;
579
580 case SOCK_RAW:
581 if ((*Protocol < 0) || (*Protocol > 255))
582 return WSAEINVAL;
583
584 String = RawDeviceName;
585 break;
586
587 default:
588 return WSAEINVAL;
589 }
590
591 RtlInitUnicodeString(TransportDeviceName, NULL);
592
593 TransportDeviceName->MaximumLength = String.Length + /* Transport device name */
594 (4 * sizeof(WCHAR) + /* Separator and protocol */
595 sizeof(UNICODE_NULL)); /* Terminating null */
596
597 TransportDeviceName->Buffer = HeapAlloc(
598 GetProcessHeap(),
599 0,
600 TransportDeviceName->MaximumLength);
601
602 if (!TransportDeviceName->Buffer)
603 return WSAENOBUFS;
604
605 /* Append the transport device name */
606 RtlAppendUnicodeStringToString(TransportDeviceName, &String);
607
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;
613
614 /* Append the protocol number */
615 String.Buffer = TransportDeviceName->Buffer + (TransportDeviceName->Length / sizeof(WCHAR));
616 String.Length = 0;
617 String.MaximumLength = TransportDeviceName->MaximumLength - TransportDeviceName->Length;
618
619 RtlIntegerToUnicodeString((ULONG)*Protocol, 10, &String);
620
621 TransportDeviceName->Length += String.Length;
622 }
623
624 /* Setup a socket context area */
625
626 Context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOCKET_CONTEXT));
627 if (!Context) {
628 RtlFreeUnicodeString(TransportDeviceName);
629 return WSAENOBUFS;
630 }
631
632 Context->AddressFamily = *AddressFamily;
633 Context->SocketType = *SocketType;
634 Context->Protocol = *Protocol;
635 Context->Flags = Flags;
636 Context->SocketState = SocketStateCreated;
637
638 *HelperDllSocketContext = Context;
639 *NotificationEvents = WSH_NOTIFY_CLOSE | WSH_NOTIFY_BIND;
640
641 return NO_ERROR;
642 }
643
644 INT
645 EXPORT
646 WSHSetSocketInformation(
647 IN PVOID HelperDllSocketContext,
648 IN SOCKET SocketHandle,
649 IN HANDLE TdiAddressObjectHandle,
650 IN HANDLE TdiConnectionObjectHandle,
651 IN INT Level,
652 IN INT OptionName,
653 IN PCHAR OptionValue,
654 IN INT OptionLength)
655 {
656 PSOCKET_CONTEXT Context = HelperDllSocketContext;
657 ULONG TdiType, TdiId;
658 INT Status;
659 PTCP_REQUEST_SET_INFORMATION_EX Info;
660 PQUEUED_REQUEST Queued, NextQueued;
661
662 DPRINT("WSHSetSocketInformation\n");
663
664 /* FIXME: We only handle address file object here */
665
666 switch (Level)
667 {
668 case SOL_SOCKET:
669 switch (OptionName)
670 {
671 case SO_DONTROUTE:
672 if (OptionLength < sizeof(BOOL))
673 {
674 return WSAEFAULT;
675 }
676 Context->DontRoute = *(BOOL*)OptionValue;
677 /* This is silently ignored on Windows */
678 return 0;
679
680 case SO_KEEPALIVE:
681 /* FIXME -- We'll send this to TCPIP */
682 DPRINT1("Set: SO_KEEPALIVE not yet supported\n");
683 return 0;
684
685 default:
686 /* Invalid option */
687 DPRINT1("Set: Received unexpected SOL_SOCKET option %d\n", OptionName);
688 return WSAENOPROTOOPT;
689 }
690 break;
691
692 case IPPROTO_IP:
693 switch (OptionName)
694 {
695 case IP_TTL:
696 case IP_DONTFRAGMENT:
697 case IP_HDRINCL:
698 /* Send these to TCPIP */
699 break;
700
701 default:
702 /* Invalid option -- FIXME */
703 DPRINT1("Set: Received unsupported IPPROTO_IP option %d\n", OptionName);
704 return 0;
705 }
706 break;
707
708 case IPPROTO_TCP:
709 switch (OptionName)
710 {
711 case TCP_NODELAY:
712 if (OptionLength < sizeof(CHAR))
713 {
714 return WSAEFAULT;
715 }
716 break;
717
718 default:
719 /* Invalid option */
720 DPRINT1("Set: Received unexpected IPPROTO_TCP option %d\n", OptionName);
721 return 0;
722 }
723 break;
724
725 default:
726 DPRINT1("Set: Received unexpected %d option %d\n", Level, OptionName);
727 return 0;
728 }
729
730 /* If we get here, GetAddressOption must return something valid */
731 GetTdiTypeId(Level, OptionName, &TdiId, &TdiType);
732 ASSERT((TdiId != 0) && (TdiType != 0));
733
734 Info = HeapAlloc(GetProcessHeap(), 0, sizeof(*Info) + OptionLength);
735 if (!Info)
736 return WSAENOBUFS;
737
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);
745
746 if (Context->SocketState == SocketStateCreated)
747 {
748 if (Context->RequestQueue)
749 {
750 Queued = Context->RequestQueue;
751 while ((NextQueued = Queued->Next))
752 {
753 Queued = NextQueued;
754 }
755
756 Queued->Next = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
757 if (!Queued->Next)
758 {
759 HeapFree(GetProcessHeap(), 0, Info);
760 return WSAENOBUFS;
761 }
762
763 NextQueued = Queued->Next;
764 NextQueued->Next = NULL;
765 NextQueued->Info = Info;
766 }
767 else
768 {
769 Context->RequestQueue = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
770 if (!Context->RequestQueue)
771 {
772 HeapFree(GetProcessHeap(), 0, Info);
773 return WSAENOBUFS;
774 }
775
776 Context->RequestQueue->Next = NULL;
777 Context->RequestQueue->Info = Info;
778 }
779
780 return 0;
781 }
782
783 Status = SendRequest(Info, sizeof(*Info) + Info->BufferSize, IOCTL_TCP_SET_INFORMATION_EX);
784
785 HeapFree(GetProcessHeap(), 0, Info);
786
787 return Status;
788 }
789
790
791 INT
792 EXPORT
793 WSHStringToAddress(
794 IN LPWSTR AddressString,
795 IN DWORD AddressFamily,
796 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL,
797 OUT LPSOCKADDR Address,
798 IN OUT LPDWORD AddressStringLength)
799 {
800 UNIMPLEMENTED
801
802 return NO_ERROR;
803 }
804
805 /* EOF */