[MSAFD]
[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 UINT
160 GetAddressOption(INT Level, INT OptionName)
161 {
162 switch (Level)
163 {
164 case SOL_SOCKET:
165 switch (OptionName)
166 {
167 case SO_KEEPALIVE:
168 /* FIXME: Return proper option */
169 ASSERT(FALSE);
170 break;
171 default:
172 break;
173 }
174 break;
175
176 case IPPROTO_IP:
177 switch (OptionName)
178 {
179 case IP_TTL:
180 return AO_OPTION_TTL;
181
182 case IP_DONTFRAGMENT:
183 return AO_OPTION_IP_DONTFRAGMENT;
184
185 #if 0
186 case IP_RECEIVE_BROADCAST:
187 return AO_OPTION_BROADCAST;
188 #endif
189
190 case IP_HDRINCL:
191 return AO_OPTION_IP_HDRINCL;
192
193 default:
194 break;
195 }
196 break;
197
198 case IPPROTO_TCP:
199 switch (OptionName)
200 {
201 case TCP_NODELAY:
202 /* FIXME: Return proper option */
203 ASSERT(FALSE);
204 break;
205 default:
206 break;
207 }
208
209 default:
210 break;
211 }
212
213 DPRINT1("Unknown level/option name: %d %d\n", Level, OptionName);
214 return 0;
215 }
216
217 INT
218 EXPORT
219 WSHGetSocketInformation(
220 IN PVOID HelperDllSocketContext,
221 IN SOCKET SocketHandle,
222 IN HANDLE TdiAddressObjectHandle,
223 IN HANDLE TdiConnectionObjectHandle,
224 IN INT Level,
225 IN INT OptionName,
226 OUT PCHAR OptionValue,
227 OUT LPINT OptionLength)
228 {
229 UNIMPLEMENTED
230
231 DPRINT1("Get: Unknown level/option name: %d %d\n", Level, OptionName);
232
233 *OptionLength = 0;
234
235 return NO_ERROR;
236 }
237
238
239 INT
240 EXPORT
241 WSHGetWildcardSockaddr(
242 IN PVOID HelperDllSocketContext,
243 OUT PSOCKADDR Sockaddr,
244 OUT PINT SockaddrLength)
245 {
246 INT Size = 2 * sizeof(UINT);
247
248 if (*SockaddrLength < Size)
249 {
250 DPRINT1("Socket address length too small: %d\n", *SockaddrLength);
251 return WSAEFAULT;
252 }
253
254 RtlZeroMemory(Sockaddr, *SockaddrLength);
255
256 Sockaddr->sa_family = AF_INET;
257 *((PUINT)Sockaddr->sa_data) = INADDR_ANY;
258
259 /* *SockaddrLength = Size; */
260
261 return NO_ERROR;
262 }
263
264
265 DWORD
266 EXPORT
267 WSHGetWinsockMapping(
268 OUT PWINSOCK_MAPPING Mapping,
269 IN DWORD MappingLength)
270 {
271 DWORD Rows = 6;
272 DWORD Columns = 3;
273 DWORD Size = 2 * sizeof(DWORD) + Columns * Rows * sizeof(DWORD);
274
275 if (MappingLength < Size)
276 {
277 DPRINT1("Mapping length too small: %d\n", MappingLength);
278 return Size;
279 }
280
281 Mapping->Rows = Rows;
282 Mapping->Columns = Columns;
283
284 Mapping->Mapping[0].AddressFamily = AF_INET;
285 Mapping->Mapping[0].SocketType = SOCK_STREAM;
286 Mapping->Mapping[0].Protocol = 0;
287
288 Mapping->Mapping[1].AddressFamily = AF_INET;
289 Mapping->Mapping[1].SocketType = SOCK_STREAM;
290 Mapping->Mapping[1].Protocol = IPPROTO_TCP;
291
292 Mapping->Mapping[2].AddressFamily = AF_INET;
293 Mapping->Mapping[2].SocketType = SOCK_DGRAM;
294 Mapping->Mapping[2].Protocol = 0;
295
296 Mapping->Mapping[3].AddressFamily = AF_INET;
297 Mapping->Mapping[3].SocketType = SOCK_DGRAM;
298 Mapping->Mapping[3].Protocol = IPPROTO_UDP;
299
300 Mapping->Mapping[4].AddressFamily = AF_INET;
301 Mapping->Mapping[4].SocketType = SOCK_RAW;
302 Mapping->Mapping[4].Protocol = 0;
303
304 Mapping->Mapping[5].AddressFamily = AF_INET;
305 Mapping->Mapping[5].SocketType = SOCK_RAW;
306 Mapping->Mapping[5].Protocol = IPPROTO_ICMP;
307
308 return NO_ERROR;
309 }
310
311
312 INT
313 EXPORT
314 WSHGetWSAProtocolInfo(
315 IN LPWSTR ProviderName,
316 OUT LPWSAPROTOCOL_INFOW *ProtocolInfo,
317 OUT LPDWORD ProtocolInfoEntries)
318 {
319 UNIMPLEMENTED
320
321 return NO_ERROR;
322 }
323
324
325 INT
326 EXPORT
327 WSHIoctl(
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)
341 {
342 UNIMPLEMENTED
343
344 DPRINT1("Ioctl: Unknown IOCTL code: %d\n", IoControlCode);
345
346 return NO_ERROR;
347 }
348
349
350 INT
351 EXPORT
352 WSHJoinLeaf(
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,
363 IN LPQOS SocketQOS,
364 IN LPQOS GroupQOS,
365 IN DWORD Flags)
366 {
367 UNIMPLEMENTED
368
369 return NO_ERROR;
370 }
371
372 INT
373 SendRequest(
374 IN PVOID Request,
375 IN DWORD RequestSize,
376 IN DWORD IOCTL)
377 {
378 BOOLEAN Status;
379 HANDLE TcpCC;
380 DWORD BytesReturned;
381
382 if (openTcpFile(&TcpCC) != STATUS_SUCCESS)
383 return WSAEINVAL;
384
385 Status = DeviceIoControl(TcpCC,
386 IOCTL,
387 Request,
388 RequestSize,
389 NULL,
390 0,
391 &BytesReturned,
392 NULL);
393
394 closeTcpFile(TcpCC);
395
396 DPRINT("DeviceIoControl: %d\n", ((Status == TRUE) ? 0 : GetLastError()));
397
398 if (!Status)
399 return WSAEINVAL;
400
401 return NO_ERROR;
402 }
403
404 INT
405 EXPORT
406 WSHNotify(
407 IN PVOID HelperDllSocketContext,
408 IN SOCKET SocketHandle,
409 IN HANDLE TdiAddressObjectHandle,
410 IN HANDLE TdiConnectionObjectHandle,
411 IN DWORD NotifyEvent)
412 {
413 PSOCKET_CONTEXT Context = HelperDllSocketContext;
414 NTSTATUS Status;
415 HANDLE TcpCC;
416 TDIEntityID *EntityIDs;
417 DWORD EntityCount, i;
418 PQUEUED_REQUEST QueuedRequest, NextQueuedRequest;
419
420 switch (NotifyEvent)
421 {
422 case WSH_NOTIFY_CLOSE:
423 DPRINT("WSHNotify: WSH_NOTIFY_CLOSE\n");
424 QueuedRequest = Context->RequestQueue;
425 while (QueuedRequest)
426 {
427 NextQueuedRequest = QueuedRequest->Next;
428
429 HeapFree(GetProcessHeap(), 0, QueuedRequest->Info);
430 HeapFree(GetProcessHeap(), 0, QueuedRequest);
431
432 QueuedRequest = NextQueuedRequest;
433 }
434 HeapFree(GetProcessHeap(), 0, HelperDllSocketContext);
435 break;
436
437
438 case WSH_NOTIFY_BIND:
439 DPRINT("WSHNotify: WSH_NOTIFY_BIND\n");
440 Status = openTcpFile(&TcpCC);
441 if (Status != STATUS_SUCCESS)
442 return WSAEINVAL;
443
444 Status = tdiGetEntityIDSet(TcpCC,
445 &EntityIDs,
446 &EntityCount);
447
448 closeTcpFile(TcpCC);
449
450 if (Status != STATUS_SUCCESS)
451 return WSAEINVAL;
452
453 for (i = 0; i < EntityCount; i++)
454 {
455 if (EntityIDs[i].tei_entity == CO_TL_ENTITY ||
456 EntityIDs[i].tei_entity == CL_TL_ENTITY ||
457 EntityIDs[i].tei_entity == ER_ENTITY)
458 {
459 Context->AddrFileInstance = EntityIDs[i].tei_instance;
460 Context->AddrFileEntityType = EntityIDs[i].tei_entity;
461 }
462 }
463
464 DPRINT("Instance: %x Type: %x\n", Context->AddrFileInstance, Context->AddrFileEntityType);
465
466 tdiFreeThingSet(EntityIDs);
467
468 Context->SocketState = SocketStateBound;
469
470 QueuedRequest = Context->RequestQueue;
471 while (QueuedRequest)
472 {
473 QueuedRequest->Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType;
474 QueuedRequest->Info->ID.toi_entity.tei_instance = Context->AddrFileInstance;
475
476 SendRequest(QueuedRequest->Info,
477 sizeof(*QueuedRequest->Info) + QueuedRequest->Info->BufferSize,
478 IOCTL_TCP_SET_INFORMATION_EX);
479
480 NextQueuedRequest = QueuedRequest->Next;
481
482 HeapFree(GetProcessHeap(), 0, QueuedRequest->Info);
483 HeapFree(GetProcessHeap(), 0, QueuedRequest);
484
485 QueuedRequest = NextQueuedRequest;
486 }
487 Context->RequestQueue = NULL;
488 break;
489
490 default:
491 DPRINT1("Unwanted notification received! (%d)\n", NotifyEvent);
492 break;
493 }
494
495 return NO_ERROR;
496 }
497
498
499 INT
500 EXPORT
501 WSHOpenSocket(
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)
508 /*
509 * FUNCTION: Opens a socket
510 */
511 {
512 return WSHOpenSocket2(AddressFamily,
513 SocketType,
514 Protocol,
515 0,
516 0,
517 TransportDeviceName,
518 HelperDllSocketContext,
519 NotificationEvents);
520 }
521
522
523 INT
524 EXPORT
525 WSHOpenSocket2(
526 OUT PINT AddressFamily,
527 IN OUT PINT SocketType,
528 IN OUT PINT Protocol,
529 IN GROUP Group,
530 IN DWORD Flags,
531 OUT PUNICODE_STRING TransportDeviceName,
532 OUT PVOID *HelperDllSocketContext,
533 OUT PDWORD NotificationEvents)
534 /*
535 * FUNCTION: Opens a socket
536 * ARGUMENTS:
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
545 * RETURNS:
546 * Status of operation
547 * NOTES:
548 * Mapping tripple is returned in an canonicalized form
549 */
550 {
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);
556
557 DPRINT("WSHOpenSocket2 called\n");
558
559 switch (*SocketType) {
560 case SOCK_STREAM:
561 String = TcpDeviceName;
562 break;
563
564 case SOCK_DGRAM:
565 String = UdpDeviceName;
566 break;
567
568 case SOCK_RAW:
569 if ((*Protocol < 0) || (*Protocol > 255))
570 return WSAEINVAL;
571
572 String = RawDeviceName;
573 break;
574
575 default:
576 return WSAEINVAL;
577 }
578
579 RtlInitUnicodeString(TransportDeviceName, NULL);
580
581 TransportDeviceName->MaximumLength = String.Length + /* Transport device name */
582 (4 * sizeof(WCHAR) + /* Separator and protocol */
583 sizeof(UNICODE_NULL)); /* Terminating null */
584
585 TransportDeviceName->Buffer = HeapAlloc(
586 GetProcessHeap(),
587 0,
588 TransportDeviceName->MaximumLength);
589
590 if (!TransportDeviceName->Buffer)
591 return WSAENOBUFS;
592
593 /* Append the transport device name */
594 RtlAppendUnicodeStringToString(TransportDeviceName, &String);
595
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;
601
602 /* Append the protocol number */
603 String.Buffer = TransportDeviceName->Buffer + (TransportDeviceName->Length / sizeof(WCHAR));
604 String.Length = 0;
605 String.MaximumLength = TransportDeviceName->MaximumLength - TransportDeviceName->Length;
606
607 RtlIntegerToUnicodeString((ULONG)*Protocol, 10, &String);
608
609 TransportDeviceName->Length += String.Length;
610 }
611
612 /* Setup a socket context area */
613
614 Context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOCKET_CONTEXT));
615 if (!Context) {
616 RtlFreeUnicodeString(TransportDeviceName);
617 return WSAENOBUFS;
618 }
619
620 Context->AddressFamily = *AddressFamily;
621 Context->SocketType = *SocketType;
622 Context->Protocol = *Protocol;
623 Context->Flags = Flags;
624 Context->SocketState = SocketStateCreated;
625
626 *HelperDllSocketContext = Context;
627 *NotificationEvents = WSH_NOTIFY_CLOSE | WSH_NOTIFY_BIND;
628
629 return NO_ERROR;
630 }
631
632 INT
633 EXPORT
634 WSHSetSocketInformation(
635 IN PVOID HelperDllSocketContext,
636 IN SOCKET SocketHandle,
637 IN HANDLE TdiAddressObjectHandle,
638 IN HANDLE TdiConnectionObjectHandle,
639 IN INT Level,
640 IN INT OptionName,
641 IN PCHAR OptionValue,
642 IN INT OptionLength)
643 {
644 PSOCKET_CONTEXT Context = HelperDllSocketContext;
645 UINT RealOptionName;
646 INT Status;
647 PTCP_REQUEST_SET_INFORMATION_EX Info;
648 PQUEUED_REQUEST Queued, NextQueued;
649
650 DPRINT("WSHSetSocketInformation\n");
651
652 /* FIXME: We only handle address file object here */
653
654 switch (Level)
655 {
656 case SOL_SOCKET:
657 switch (OptionName)
658 {
659 case SO_DONTROUTE:
660 if (OptionLength < sizeof(BOOL))
661 {
662 return WSAEFAULT;
663 }
664 Context->DontRoute = *(BOOL*)OptionValue;
665 /* This is silently ignored on Windows */
666 return 0;
667
668 case SO_KEEPALIVE:
669 /* FIXME -- We'll send this to TCPIP */
670 DPRINT1("Set: SO_KEEPALIVE not yet supported\n");
671 return 0;
672
673 default:
674 /* Invalid option */
675 DPRINT1("Set: Received unexpected SOL_SOCKET option %d\n", OptionName);
676 return WSAENOPROTOOPT;
677 }
678 break;
679
680 case IPPROTO_IP:
681 switch (OptionName)
682 {
683 case IP_TTL:
684 case IP_DONTFRAGMENT:
685 case IP_HDRINCL:
686 /* Send these to TCPIP */
687 break;
688
689 default:
690 /* Invalid option -- FIXME */
691 DPRINT1("Set: Received unsupported IPPROTO_IP option %d\n", OptionName);
692 return 0;
693 }
694 break;
695
696 case IPPROTO_TCP:
697 switch (OptionName)
698 {
699 case TCP_NODELAY:
700 /* FIXME -- Send this to TCPIP */
701 DPRINT1("Set: TCP_NODELAY not yet supported\n");
702 return 0;
703
704 default:
705 /* Invalid option */
706 DPRINT1("Set: Received unexpected IPPROTO_TCP option %d\n", OptionName);
707 return 0;
708 }
709 break;
710
711 default:
712 DPRINT1("Set: Received unexpected %d option %d\n", Level, OptionName);
713 return 0;
714 }
715
716 /* If we get here, GetAddressOption must return something valid */
717 RealOptionName = GetAddressOption(Level, OptionName);
718 ASSERT(RealOptionName != 0);
719
720 Info = HeapAlloc(GetProcessHeap(), 0, sizeof(*Info) + OptionLength);
721 if (!Info)
722 return WSAENOBUFS;
723
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);
731
732 if (Context->SocketState == SocketStateCreated)
733 {
734 if (Context->RequestQueue)
735 {
736 Queued = Context->RequestQueue;
737 while ((NextQueued = Queued->Next))
738 {
739 Queued = NextQueued;
740 }
741
742 Queued->Next = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
743 if (!Queued->Next)
744 {
745 HeapFree(GetProcessHeap(), 0, Info);
746 return WSAENOBUFS;
747 }
748
749 NextQueued = Queued->Next;
750 NextQueued->Next = NULL;
751 NextQueued->Info = Info;
752 }
753 else
754 {
755 Context->RequestQueue = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
756 if (!Context->RequestQueue)
757 {
758 HeapFree(GetProcessHeap(), 0, Info);
759 return WSAENOBUFS;
760 }
761
762 Context->RequestQueue->Next = NULL;
763 Context->RequestQueue->Info = Info;
764 }
765
766 return 0;
767 }
768
769 Status = SendRequest(Info, sizeof(*Info) + Info->BufferSize, IOCTL_TCP_SET_INFORMATION_EX);
770
771 HeapFree(GetProcessHeap(), 0, Info);
772
773 return Status;
774 }
775
776
777 INT
778 EXPORT
779 WSHStringToAddress(
780 IN LPWSTR AddressString,
781 IN DWORD AddressFamily,
782 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL,
783 OUT LPSOCKADDR Address,
784 IN OUT LPDWORD AddressStringLength)
785 {
786 UNIMPLEMENTED
787
788 return NO_ERROR;
789 }
790
791 /* EOF */