- Merge some small changes from aicom-network-branch to fix potential memory corrupt...
[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 DWORD 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 IPPROTO_IP:
165 switch (OptionName)
166 {
167 case IP_TTL:
168 return AO_OPTION_TTL;
169
170 case IP_DONTFRAGMENT:
171 return AO_OPTION_IP_DONTFRAGMENT;
172
173 #if 0
174 case IP_RECEIVE_BROADCAST:
175 return AO_OPTION_BROADCAST;
176 #endif
177
178 case IP_HDRINCL:
179 return AO_OPTION_IP_HDRINCL;
180
181 default:
182 DPRINT1("Unknown option name for IPPROTO_IP: %d\n", OptionName);
183 return 0;
184 }
185 break;
186
187 default:
188 DPRINT1("Unknown level: %d\n", Level);
189 return 0;
190 }
191 }
192
193 INT
194 EXPORT
195 WSHGetSocketInformation(
196 IN PVOID HelperDllSocketContext,
197 IN SOCKET SocketHandle,
198 IN HANDLE TdiAddressObjectHandle,
199 IN HANDLE TdiConnectionObjectHandle,
200 IN INT Level,
201 IN INT OptionName,
202 OUT PCHAR OptionValue,
203 OUT LPINT OptionLength)
204 {
205 UNIMPLEMENTED
206
207 return NO_ERROR;
208 }
209
210
211 INT
212 EXPORT
213 WSHGetWildcardSockaddr(
214 IN PVOID HelperDllSocketContext,
215 OUT PSOCKADDR Sockaddr,
216 OUT PINT SockaddrLength)
217 {
218 DWORD Size = 2 * sizeof(UINT);
219
220 if (*SockaddrLength < Size)
221 {
222 DPRINT1("Socket address length too small: %d\n", *SockaddrLength);
223 return WSAEFAULT;
224 }
225
226 RtlZeroMemory(Sockaddr, *SockaddrLength);
227
228 Sockaddr->sa_family = AF_INET;
229 *((PUINT)Sockaddr->sa_data) = INADDR_ANY;
230
231 /* *SockaddrLength = Size; */
232
233 return NO_ERROR;
234 }
235
236
237 DWORD
238 EXPORT
239 WSHGetWinsockMapping(
240 OUT PWINSOCK_MAPPING Mapping,
241 IN DWORD MappingLength)
242 {
243 DWORD Rows = 6;
244 DWORD Columns = 3;
245 DWORD Size = 2 * sizeof(DWORD) + Columns * Rows * sizeof(DWORD);
246
247 if (MappingLength < Size)
248 {
249 DPRINT1("Mapping length too small: %d\n", MappingLength);
250 return Size;
251 }
252
253 Mapping->Rows = Rows;
254 Mapping->Columns = Columns;
255
256 Mapping->Mapping[0].AddressFamily = AF_INET;
257 Mapping->Mapping[0].SocketType = SOCK_STREAM;
258 Mapping->Mapping[0].Protocol = 0;
259
260 Mapping->Mapping[1].AddressFamily = AF_INET;
261 Mapping->Mapping[1].SocketType = SOCK_STREAM;
262 Mapping->Mapping[1].Protocol = IPPROTO_TCP;
263
264 Mapping->Mapping[2].AddressFamily = AF_INET;
265 Mapping->Mapping[2].SocketType = SOCK_DGRAM;
266 Mapping->Mapping[2].Protocol = 0;
267
268 Mapping->Mapping[3].AddressFamily = AF_INET;
269 Mapping->Mapping[3].SocketType = SOCK_DGRAM;
270 Mapping->Mapping[3].Protocol = IPPROTO_UDP;
271
272 Mapping->Mapping[4].AddressFamily = AF_INET;
273 Mapping->Mapping[4].SocketType = SOCK_RAW;
274 Mapping->Mapping[4].Protocol = 0;
275
276 Mapping->Mapping[5].AddressFamily = AF_INET;
277 Mapping->Mapping[5].SocketType = SOCK_RAW;
278 Mapping->Mapping[5].Protocol = IPPROTO_ICMP;
279
280 return NO_ERROR;
281 }
282
283
284 INT
285 EXPORT
286 WSHGetWSAProtocolInfo(
287 IN LPWSTR ProviderName,
288 OUT LPWSAPROTOCOL_INFOW *ProtocolInfo,
289 OUT LPDWORD ProtocolInfoEntries)
290 {
291 UNIMPLEMENTED
292
293 return NO_ERROR;
294 }
295
296
297 INT
298 EXPORT
299 WSHIoctl(
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)
313 {
314 UNIMPLEMENTED
315
316 return NO_ERROR;
317 }
318
319
320 INT
321 EXPORT
322 WSHJoinLeaf(
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,
333 IN LPQOS SocketQOS,
334 IN LPQOS GroupQOS,
335 IN DWORD Flags)
336 {
337 UNIMPLEMENTED
338
339 return NO_ERROR;
340 }
341
342 INT
343 SendRequest(
344 IN PVOID Request,
345 IN DWORD RequestSize,
346 IN DWORD IOCTL)
347 {
348 BOOLEAN Status;
349 HANDLE TcpCC;
350 DWORD BytesReturned;
351
352 if (openTcpFile(&TcpCC) != STATUS_SUCCESS)
353 return WSAEINVAL;
354
355 Status = DeviceIoControl(TcpCC,
356 IOCTL,
357 Request,
358 RequestSize,
359 NULL,
360 0,
361 &BytesReturned,
362 NULL);
363
364 closeTcpFile(TcpCC);
365
366 DPRINT("DeviceIoControl: %d\n", ((Status == TRUE) ? 0 : GetLastError()));
367
368 if (!Status)
369 return WSAEINVAL;
370
371 return NO_ERROR;
372 }
373
374 INT
375 EXPORT
376 WSHNotify(
377 IN PVOID HelperDllSocketContext,
378 IN SOCKET SocketHandle,
379 IN HANDLE TdiAddressObjectHandle,
380 IN HANDLE TdiConnectionObjectHandle,
381 IN DWORD NotifyEvent)
382 {
383 PSOCKET_CONTEXT Context = HelperDllSocketContext;
384 NTSTATUS Status;
385 HANDLE TcpCC;
386 TDIEntityID *EntityIDs;
387 DWORD EntityCount, i;
388 PQUEUED_REQUEST QueuedRequest, NextQueuedRequest;
389
390 switch (NotifyEvent)
391 {
392 case WSH_NOTIFY_CLOSE:
393 DPRINT("WSHNotify: WSH_NOTIFY_CLOSE\n");
394 QueuedRequest = Context->RequestQueue;
395 while (QueuedRequest)
396 {
397 NextQueuedRequest = QueuedRequest->Next;
398
399 HeapFree(GetProcessHeap(), 0, QueuedRequest->Info);
400 HeapFree(GetProcessHeap(), 0, QueuedRequest);
401
402 QueuedRequest = NextQueuedRequest;
403 }
404 HeapFree(GetProcessHeap(), 0, HelperDllSocketContext);
405 break;
406
407
408 case WSH_NOTIFY_BIND:
409 DPRINT("WSHNotify: WSH_NOTIFY_BIND\n");
410 Status = openTcpFile(&TcpCC);
411 if (Status != STATUS_SUCCESS)
412 return WSAEINVAL;
413
414 Status = tdiGetEntityIDSet(TcpCC,
415 &EntityIDs,
416 &EntityCount);
417
418 closeTcpFile(TcpCC);
419
420 if (Status != STATUS_SUCCESS)
421 return WSAEINVAL;
422
423 for (i = 0; i < EntityCount; i++)
424 {
425 if (EntityIDs[i].tei_entity == CO_TL_ENTITY ||
426 EntityIDs[i].tei_entity == CL_TL_ENTITY ||
427 EntityIDs[i].tei_entity == ER_ENTITY)
428 {
429 Context->AddrFileInstance = EntityIDs[i].tei_instance;
430 Context->AddrFileEntityType = EntityIDs[i].tei_entity;
431 }
432 }
433
434 DPRINT("Instance: %x Type: %x\n", Context->AddrFileInstance, Context->AddrFileEntityType);
435
436 tdiFreeThingSet(EntityIDs);
437
438 Context->SocketState = SocketStateBound;
439
440 QueuedRequest = Context->RequestQueue;
441 while (QueuedRequest)
442 {
443 QueuedRequest->Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType;
444 QueuedRequest->Info->ID.toi_entity.tei_instance = Context->AddrFileInstance;
445
446 SendRequest(QueuedRequest->Info,
447 sizeof(*QueuedRequest->Info) + QueuedRequest->Info->BufferSize,
448 IOCTL_TCP_SET_INFORMATION_EX);
449
450 NextQueuedRequest = QueuedRequest->Next;
451
452 HeapFree(GetProcessHeap(), 0, QueuedRequest->Info);
453 HeapFree(GetProcessHeap(), 0, QueuedRequest);
454
455 QueuedRequest = NextQueuedRequest;
456 }
457 Context->RequestQueue = NULL;
458 break;
459
460 default:
461 DPRINT1("Unwanted notification received! (%d)\n", NotifyEvent);
462 break;
463 }
464
465 return NO_ERROR;
466 }
467
468
469 INT
470 EXPORT
471 WSHOpenSocket(
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)
478 /*
479 * FUNCTION: Opens a socket
480 */
481 {
482 return WSHOpenSocket2(AddressFamily,
483 SocketType,
484 Protocol,
485 0,
486 0,
487 TransportDeviceName,
488 HelperDllSocketContext,
489 NotificationEvents);
490 }
491
492
493 INT
494 EXPORT
495 WSHOpenSocket2(
496 OUT PINT AddressFamily,
497 IN OUT PINT SocketType,
498 IN OUT PINT Protocol,
499 IN GROUP Group,
500 IN DWORD Flags,
501 OUT PUNICODE_STRING TransportDeviceName,
502 OUT PVOID *HelperDllSocketContext,
503 OUT PDWORD NotificationEvents)
504 /*
505 * FUNCTION: Opens a socket
506 * ARGUMENTS:
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
515 * RETURNS:
516 * Status of operation
517 * NOTES:
518 * Mapping tripple is returned in an canonicalized form
519 */
520 {
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);
526 NTSTATUS Status;
527
528 DPRINT("WSHOpenSocket2 called\n");
529
530 switch (*SocketType) {
531 case SOCK_STREAM:
532 String = TcpDeviceName;
533 break;
534
535 case SOCK_DGRAM:
536 String = UdpDeviceName;
537 break;
538
539 case SOCK_RAW:
540 if ((*Protocol < 0) || (*Protocol > 255))
541 return WSAEINVAL;
542
543 String = RawDeviceName;
544 break;
545
546 default:
547 return WSAEINVAL;
548 }
549
550 RtlInitUnicodeString(TransportDeviceName, NULL);
551
552 TransportDeviceName->MaximumLength = String.Length + /* Transport device name */
553 (4 * sizeof(WCHAR) + /* Separator and protocol */
554 sizeof(UNICODE_NULL)); /* Terminating null */
555
556 TransportDeviceName->Buffer = HeapAlloc(
557 GetProcessHeap(),
558 0,
559 TransportDeviceName->MaximumLength);
560
561 if (!TransportDeviceName->Buffer)
562 return WSAENOBUFS;
563
564 /* Append the transport device name */
565 Status = RtlAppendUnicodeStringToString(TransportDeviceName, &String);
566
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;
572
573 /* Append the protocol number */
574 String.Buffer = TransportDeviceName->Buffer + (TransportDeviceName->Length / sizeof(WCHAR));
575 String.Length = 0;
576 String.MaximumLength = TransportDeviceName->MaximumLength - TransportDeviceName->Length;
577
578 Status = RtlIntegerToUnicodeString((ULONG)*Protocol, 10, &String);
579
580 TransportDeviceName->Length += String.Length;
581 }
582
583 /* Setup a socket context area */
584
585 Context = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(SOCKET_CONTEXT));
586 if (!Context) {
587 RtlFreeUnicodeString(TransportDeviceName);
588 return WSAENOBUFS;
589 }
590
591 Context->AddressFamily = *AddressFamily;
592 Context->SocketType = *SocketType;
593 Context->Protocol = *Protocol;
594 Context->Flags = Flags;
595 Context->SocketState = SocketStateCreated;
596
597 *HelperDllSocketContext = Context;
598 *NotificationEvents = WSH_NOTIFY_CLOSE | WSH_NOTIFY_BIND;
599
600 return NO_ERROR;
601 }
602
603 INT
604 EXPORT
605 WSHSetSocketInformation(
606 IN PVOID HelperDllSocketContext,
607 IN SOCKET SocketHandle,
608 IN HANDLE TdiAddressObjectHandle,
609 IN HANDLE TdiConnectionObjectHandle,
610 IN INT Level,
611 IN INT OptionName,
612 IN PCHAR OptionValue,
613 IN INT OptionLength)
614 {
615 PSOCKET_CONTEXT Context = HelperDllSocketContext;
616 UINT RealOptionName;
617 INT Status;
618 PTCP_REQUEST_SET_INFORMATION_EX Info;
619 PQUEUED_REQUEST Queued, NextQueued;
620
621 DPRINT("WSHSetSocketInformation\n");
622
623 /* FIXME: We only handle address file object here */
624
625 RealOptionName = GetAddressOption(Level, OptionName);
626
627 /* FIXME: Support all options */
628 if (!RealOptionName)
629 return 0; /* return WSAEINVAL; */
630
631 Info = HeapAlloc(GetProcessHeap(), 0, sizeof(*Info) + OptionLength);
632 if (!Info)
633 return WSAENOBUFS;
634
635 Info->ID.toi_entity.tei_entity = Context->AddrFileEntityType;
636 Info->ID.toi_entity.tei_instance = Context->AddrFileInstance;
637 Info->ID.toi_class = INFO_CLASS_PROTOCOL;
638 Info->ID.toi_type = INFO_TYPE_ADDRESS_OBJECT;
639 Info->ID.toi_id = RealOptionName;
640 Info->BufferSize = OptionLength;
641 memcpy(Info->Buffer, OptionValue, OptionLength);
642
643 if (Context->SocketState == SocketStateCreated)
644 {
645 if (Context->RequestQueue)
646 {
647 Queued = Context->RequestQueue;
648 while ((NextQueued = Queued->Next))
649 {
650 Queued = NextQueued;
651 }
652
653 Queued->Next = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
654 if (!Queued->Next)
655 {
656 HeapFree(GetProcessHeap(), 0, Info);
657 return WSAENOBUFS;
658 }
659
660 NextQueued = Queued->Next;
661 NextQueued->Next = NULL;
662 NextQueued->Info = Info;
663 }
664 else
665 {
666 Context->RequestQueue = HeapAlloc(GetProcessHeap(), 0, sizeof(QUEUED_REQUEST));
667 if (!Context->RequestQueue)
668 {
669 HeapFree(GetProcessHeap(), 0, Info);
670 return WSAENOBUFS;
671 }
672
673 Context->RequestQueue->Next = NULL;
674 Context->RequestQueue->Info = Info;
675 }
676
677 return 0;
678 }
679
680 Status = SendRequest(Info, sizeof(*Info) + Info->BufferSize, IOCTL_TCP_SET_INFORMATION_EX);
681
682 HeapFree(GetProcessHeap(), 0, Info);
683
684 return Status;
685 }
686
687
688 INT
689 EXPORT
690 WSHStringToAddress(
691 IN LPWSTR AddressString,
692 IN DWORD AddressFamily,
693 IN LPWSAPROTOCOL_INFOW ProtocolInfo OPTIONAL,
694 OUT LPSOCKADDR Address,
695 IN OUT LPDWORD AddressStringLength)
696 {
697 UNIMPLEMENTED
698
699 return NO_ERROR;
700 }
701
702 /* EOF */