f00fc3eac1b3d5c0a10e91d65b9a8cdd59af13c5
[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 *TdiType = INFO_TYPE_CONNECTION;
211 switch (OptionName)
212 {
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 INT res;
355
356 if (IoControlCode == SIO_GET_INTERFACE_LIST)
357 {
358 res = WSHIoctl_GetInterfaceList(
359 OutputBuffer,
360 OutputBufferLength,
361 NumberOfBytesReturned,
362 NeedsCompletion);
363 return res;
364 }
365
366 UNIMPLEMENTED;
367
368 DPRINT1("Ioctl: Unknown IOCTL code: %d\n", IoControlCode);
369
370 return WSAEINVAL;
371 }
372
373
374 INT
375 EXPORT
376 WSHJoinLeaf(
377 IN PVOID HelperDllSocketContext,
378 IN SOCKET SocketHandle,
379 IN HANDLE TdiAddressObjectHandle,
380 IN HANDLE TdiConnectionObjectHandle,
381 IN PVOID LeafHelperDllSocketContext,
382 IN SOCKET LeafSocketHandle,
383 IN PSOCKADDR Sockaddr,
384 IN DWORD SockaddrLength,
385 IN LPWSABUF CallerData,
386 IN LPWSABUF CalleeData,
387 IN LPQOS SocketQOS,
388 IN LPQOS GroupQOS,
389 IN DWORD Flags)
390 {
391 UNIMPLEMENTED;
392
393 return NO_ERROR;
394 }
395
396 INT
397 SendRequest(
398 IN PVOID Request,
399 IN DWORD RequestSize,
400 IN DWORD IOCTL)
401 {
402 BOOLEAN Status;
403 HANDLE TcpCC;
404 DWORD BytesReturned;
405
406 if (openTcpFile(&TcpCC, FILE_READ_DATA | FILE_WRITE_DATA) != STATUS_SUCCESS)
407 return WSAEINVAL;
408
409 Status = DeviceIoControl(TcpCC,
410 IOCTL,
411 Request,
412 RequestSize,
413 NULL,
414 0,
415 &BytesReturned,
416 NULL);
417
418 closeTcpFile(TcpCC);
419
420 DPRINT("DeviceIoControl: %ld\n", ((Status == TRUE) ? 0 : GetLastError()));
421
422 if (!Status)
423 return WSAEINVAL;
424
425 return NO_ERROR;
426 }
427
428 INT
429 EXPORT
430 WSHNotify(
431 IN PVOID HelperDllSocketContext,
432 IN SOCKET SocketHandle,
433 IN HANDLE TdiAddressObjectHandle,
434 IN HANDLE TdiConnectionObjectHandle,
435 IN DWORD NotifyEvent)
436 {
437 PSOCKET_CONTEXT Context = HelperDllSocketContext;
438 NTSTATUS Status;
439 HANDLE TcpCC;
440 TDIEntityID *EntityIDs;
441 DWORD EntityCount, i;
442 PQUEUED_REQUEST QueuedRequest, NextQueuedRequest;
443
444 switch (NotifyEvent)
445 {
446 case WSH_NOTIFY_CLOSE:
447 DPRINT("WSHNotify: WSH_NOTIFY_CLOSE\n");
448 QueuedRequest = Context->RequestQueue;
449 while (QueuedRequest)
450 {
451 NextQueuedRequest = QueuedRequest->Next;
452
453 HeapFree(GetProcessHeap(), 0, QueuedRequest->Info);
454 HeapFree(GetProcessHeap(), 0, QueuedRequest);
455
456 QueuedRequest = NextQueuedRequest;
457 }
458 HeapFree(GetProcessHeap(), 0, HelperDllSocketContext);
459 break;
460
461
462 case WSH_NOTIFY_BIND:
463 DPRINT("WSHNotify: WSH_NOTIFY_BIND\n");
464 Status = openTcpFile(&TcpCC, FILE_READ_DATA);
465 if (Status != STATUS_SUCCESS)
466 return WSAEINVAL;
467
468 Status = tdiGetEntityIDSet(TcpCC,
469 &EntityIDs,
470 &EntityCount);
471
472 closeTcpFile(TcpCC);
473
474 if (Status != STATUS_SUCCESS)
475 return WSAEINVAL;
476
477 for (i = 0; i < EntityCount; i++)
478 {
479 if (EntityIDs[i].tei_entity == CO_TL_ENTITY ||
480 EntityIDs[i].tei_entity == CL_TL_ENTITY ||
481 EntityIDs[i].tei_entity == ER_ENTITY)
482 {
483 Context->AddrFileInstance = EntityIDs[i].tei_instance;
484 Context->AddrFileEntityType = EntityIDs[i].tei_entity;
485 }
486 }
487
488 DPRINT("Instance: %lx Type: %lx\n", Context->AddrFileInstance, Context->AddrFileEntityType);
489
490 tdiFreeThingSet(EntityIDs);
491
492 Context->SocketState = SocketStateBound;
493
494 QueuedRequest = Context->RequestQueue;
495 while (QueuedRequest)
496 {
497 QueuedRequest->Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType;
498 QueuedRequest->Info->ID.toi_entity.tei_instance = Context->AddrFileInstance;
499
500 SendRequest(QueuedRequest->Info,
501 sizeof(*QueuedRequest->Info) + QueuedRequest->Info->BufferSize,
502 IOCTL_TCP_SET_INFORMATION_EX);
503
504 NextQueuedRequest = QueuedRequest->Next;
505
506 HeapFree(GetProcessHeap(), 0, QueuedRequest->Info);
507 HeapFree(GetProcessHeap(), 0, QueuedRequest);
508
509 QueuedRequest = NextQueuedRequest;
510 }
511 Context->RequestQueue = NULL;
512 break;
513
514 default:
515 DPRINT1("Unwanted notification received! (%ld)\n", NotifyEvent);
516 break;
517 }
518
519 return NO_ERROR;
520 }
521
522
523 INT
524 EXPORT
525 WSHOpenSocket(
526 IN OUT PINT AddressFamily,
527 IN OUT PINT SocketType,
528 IN OUT PINT Protocol,
529 OUT PUNICODE_STRING TransportDeviceName,
530 OUT PVOID HelperDllSocketContext,
531 OUT PDWORD NotificationEvents)
532 /*
533 * FUNCTION: Opens a socket
534 */
535 {
536 return WSHOpenSocket2(AddressFamily,
537 SocketType,
538 Protocol,
539 0,
540 0,
541 TransportDeviceName,
542 HelperDllSocketContext,
543 NotificationEvents);
544 }
545
546
547 INT
548 EXPORT
549 WSHOpenSocket2(
550 OUT PINT AddressFamily,
551 IN OUT PINT SocketType,
552 IN OUT PINT Protocol,
553 IN GROUP Group,
554 IN DWORD Flags,
555 OUT PUNICODE_STRING TransportDeviceName,
556 OUT PVOID *HelperDllSocketContext,
557 OUT PDWORD NotificationEvents)
558 /*
559 * FUNCTION: Opens a socket
560 * ARGUMENTS:
561 * AddressFamily = Address of buffer with address family (updated)
562 * SocketType = Address of buffer with type of socket (updated)
563 * Protocol = Address of buffer with protocol number (updated)
564 * Group = Socket group
565 * Flags = Socket flags
566 * TransportDeviceName = Address of buffer to place name of transport device
567 * HelperDllSocketContext = Address of buffer to place socket context pointer
568 * NotificationEvents = Address of buffer to place flags for event notification
569 * RETURNS:
570 * Status of operation
571 * NOTES:
572 * Mapping tripple is returned in an canonicalized form
573 */
574 {
575 PSOCKET_CONTEXT Context;
576 UNICODE_STRING String;
577 UNICODE_STRING TcpDeviceName = RTL_CONSTANT_STRING(DD_TCP_DEVICE_NAME);
578 UNICODE_STRING UdpDeviceName = RTL_CONSTANT_STRING(DD_UDP_DEVICE_NAME);
579 UNICODE_STRING RawDeviceName = RTL_CONSTANT_STRING(DD_RAW_IP_DEVICE_NAME);
580
581 DPRINT("WSHOpenSocket2 called\n");
582
583 switch (*SocketType) {
584 case SOCK_STREAM:
585 String = TcpDeviceName;
586 break;
587
588 case SOCK_DGRAM:
589 String = UdpDeviceName;
590 break;
591
592 case SOCK_RAW:
593 if ((*Protocol < 0) || (*Protocol > 255))
594 return WSAEINVAL;
595
596 String = RawDeviceName;
597 break;
598
599 default:
600 return WSAEINVAL;
601 }
602
603 RtlInitUnicodeString(TransportDeviceName, NULL);
604
605 TransportDeviceName->MaximumLength = String.Length + /* Transport device name */
606 (4 * sizeof(WCHAR) + /* Separator and protocol */
607 sizeof(UNICODE_NULL)); /* Terminating null */
608
609 TransportDeviceName->Buffer = HeapAlloc(
610 GetProcessHeap(),
611 0,
612 TransportDeviceName->MaximumLength);
613
614 if (!TransportDeviceName->Buffer)
615 return WSAENOBUFS;
616
617 /* Append the transport device name */
618 RtlAppendUnicodeStringToString(TransportDeviceName, &String);
619
620 if (*SocketType == SOCK_RAW) {
621 /* Append a separator */
622 TransportDeviceName->Buffer[TransportDeviceName->Length / sizeof(WCHAR)] = OBJ_NAME_PATH_SEPARATOR;
623 TransportDeviceName->Length += sizeof(WCHAR);
624 TransportDeviceName->Buffer[TransportDeviceName->Length / sizeof(WCHAR)] = UNICODE_NULL;
625
626 /* Append the protocol number */
627 String.Buffer = TransportDeviceName->Buffer + (TransportDeviceName->Length / sizeof(WCHAR));
628 String.Length = 0;
629 String.MaximumLength = TransportDeviceName->MaximumLength - TransportDeviceName->Length;
630
631 RtlIntegerToUnicodeString((ULONG)*Protocol, 10, &String);
632
633 TransportDeviceName->Length += String.Length;
634 }
635
636 /* Setup a socket context area */
637
638 Context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOCKET_CONTEXT));
639 if (!Context) {
640 RtlFreeUnicodeString(TransportDeviceName);
641 return WSAENOBUFS;
642 }
643
644 Context->AddressFamily = *AddressFamily;
645 Context->SocketType = *SocketType;
646 Context->Protocol = *Protocol;
647 Context->Flags = Flags;
648 Context->SocketState = SocketStateCreated;
649
650 *HelperDllSocketContext = Context;
651 *NotificationEvents = WSH_NOTIFY_CLOSE | WSH_NOTIFY_BIND;
652
653 return NO_ERROR;
654 }
655
656 INT
657 EXPORT
658 WSHSetSocketInformation(
659 IN PVOID HelperDllSocketContext,
660 IN SOCKET SocketHandle,
661 IN HANDLE TdiAddressObjectHandle,
662 IN HANDLE TdiConnectionObjectHandle,
663 IN INT Level,
664 IN INT OptionName,
665 IN PCHAR OptionValue,
666 IN INT OptionLength)
667 {
668 PSOCKET_CONTEXT Context = HelperDllSocketContext;
669 ULONG TdiType, TdiId;
670 INT Status;
671 PTCP_REQUEST_SET_INFORMATION_EX Info;
672 PQUEUED_REQUEST Queued, NextQueued;
673
674 DPRINT("WSHSetSocketInformation\n");
675
676 /* FIXME: We only handle address file object here */
677
678 switch (Level)
679 {
680 case SOL_SOCKET:
681 switch (OptionName)
682 {
683 case SO_DONTROUTE:
684 if (OptionLength < sizeof(BOOL))
685 {
686 return WSAEFAULT;
687 }
688 Context->DontRoute = *(BOOL*)OptionValue;
689 /* This is silently ignored on Windows */
690 return 0;
691
692 case SO_KEEPALIVE:
693 /* FIXME -- We'll send this to TCPIP */
694 DPRINT1("Set: SO_KEEPALIVE not yet supported\n");
695 return 0;
696
697 default:
698 /* Invalid option */
699 DPRINT1("Set: Received unexpected SOL_SOCKET option %d\n", OptionName);
700 return WSAENOPROTOOPT;
701 }
702 break;
703
704 case IPPROTO_IP:
705 switch (OptionName)
706 {
707 case IP_TTL:
708 case IP_DONTFRAGMENT:
709 case IP_HDRINCL:
710 /* Send these to TCPIP */
711 break;
712
713 default:
714 /* Invalid option -- FIXME */
715 DPRINT1("Set: Received unsupported IPPROTO_IP option %d\n", OptionName);
716 return 0;
717 }
718 break;
719
720 case IPPROTO_TCP:
721 switch (OptionName)
722 {
723 case TCP_NODELAY:
724 if (OptionLength < sizeof(CHAR))
725 {
726 return WSAEFAULT;
727 }
728 break;
729
730 default:
731 /* Invalid option */
732 DPRINT1("Set: Received unexpected IPPROTO_TCP option %d\n", OptionName);
733 return 0;
734 }
735 break;
736
737 default:
738 DPRINT1("Set: Received unexpected %d option %d\n", Level, OptionName);
739 return 0;
740 }
741
742 /* If we get here, GetAddressOption must return something valid */
743 GetTdiTypeId(Level, OptionName, &TdiType, &TdiId);
744 ASSERT((TdiId != 0) && (TdiType != 0));
745
746 Info = HeapAlloc(GetProcessHeap(), 0, sizeof(*Info) + OptionLength);
747 if (!Info)
748 return WSAENOBUFS;
749
750 Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType;
751 Info->ID.toi_entity.tei_instance = Context->AddrFileInstance;
752 Info->ID.toi_class = INFO_CLASS_PROTOCOL;
753 Info->ID.toi_type = TdiType;
754 Info->ID.toi_id = TdiId;
755 Info->BufferSize = OptionLength;
756 memcpy(Info->Buffer, OptionValue, OptionLength);
757
758 if (Context->SocketState == SocketStateCreated)
759 {
760 if (Context->RequestQueue)
761 {
762 Queued = Context->RequestQueue;
763 while ((NextQueued = Queued->Next))
764 {
765 Queued = NextQueued;
766 }
767
768 Queued->Next = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
769 if (!Queued->Next)
770 {
771 HeapFree(GetProcessHeap(), 0, Info);
772 return WSAENOBUFS;
773 }
774
775 NextQueued = Queued->Next;
776 NextQueued->Next = NULL;
777 NextQueued->Info = Info;
778 }
779 else
780 {
781 Context->RequestQueue = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
782 if (!Context->RequestQueue)
783 {
784 HeapFree(GetProcessHeap(), 0, Info);
785 return WSAENOBUFS;
786 }
787
788 Context->RequestQueue->Next = NULL;
789 Context->RequestQueue->Info = Info;
790 }
791
792 return 0;
793 }
794
795 Status = SendRequest(Info, sizeof(*Info) + Info->BufferSize, IOCTL_TCP_SET_INFORMATION_EX);
796
797 HeapFree(GetProcessHeap(), 0, Info);
798
799 return Status;
800 }
801
802
803 INT
804 EXPORT
805 WSHStringToAddress(
806 IN LPWSTR AddressString,
807 IN DWORD AddressFamily,
808 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL,
809 OUT LPSOCKADDR Address,
810 IN OUT LPDWORD AddressStringLength)
811 {
812 UNIMPLEMENTED;
813
814 return NO_ERROR;
815 }
816
817 /* EOF */