f715484b68821a3e471c0bfd6a0d17b1e0d393e1
[reactos.git] / reactos / dll / win32 / msafd / misc / dllmain.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver DLL
4 * FILE: dll/win32/msafd/misc/dllmain.c
5 * PURPOSE: DLL entry point
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Alex Ionescu (alex@relsoft.net)
8 * REVISIONS:
9 * CSH 01/09-2000 Created
10 * Alex 16/07/2004 - Complete Rewrite
11 */
12
13 #include <msafd.h>
14
15 #include <winuser.h>
16 #include <wchar.h>
17
18 #include <wine/debug.h>
19 WINE_DEFAULT_DEBUG_CHANNEL(msafd);
20
21 HANDLE GlobalHeap;
22 WSPUPCALLTABLE Upcalls;
23 DWORD CatalogEntryId; /* CatalogEntryId for upcalls */
24 LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest;
25 PSOCKET_INFORMATION SocketListHead = NULL;
26 CRITICAL_SECTION SocketListLock;
27 LIST_ENTRY SockHelpersListHead = { NULL, NULL };
28 ULONG SockAsyncThreadRefCount;
29 HANDLE SockAsyncHelperAfdHandle;
30 HANDLE SockAsyncCompletionPort = NULL;
31 BOOLEAN SockAsyncSelectCalled;
32
33
34
35 /*
36 * FUNCTION: Creates a new socket
37 * ARGUMENTS:
38 * af = Address family
39 * type = Socket type
40 * protocol = Protocol type
41 * lpProtocolInfo = Pointer to protocol information
42 * g = Reserved
43 * dwFlags = Socket flags
44 * lpErrno = Address of buffer for error information
45 * RETURNS:
46 * Created socket, or INVALID_SOCKET if it could not be created
47 */
48 SOCKET
49 WSPAPI
50 WSPSocket(int AddressFamily,
51 int SocketType,
52 int Protocol,
53 LPWSAPROTOCOL_INFOW lpProtocolInfo,
54 GROUP g,
55 DWORD dwFlags,
56 LPINT lpErrno)
57 {
58 OBJECT_ATTRIBUTES Object;
59 IO_STATUS_BLOCK IOSB;
60 USHORT SizeOfPacket;
61 ULONG SizeOfEA;
62 PAFD_CREATE_PACKET AfdPacket;
63 HANDLE Sock;
64 PSOCKET_INFORMATION Socket = NULL;
65 PFILE_FULL_EA_INFORMATION EABuffer = NULL;
66 PHELPER_DATA HelperData;
67 PVOID HelperDLLContext;
68 DWORD HelperEvents;
69 UNICODE_STRING TransportName;
70 UNICODE_STRING DevName;
71 LARGE_INTEGER GroupData;
72 INT Status;
73
74 TRACE("Creating Socket, getting TDI Name - AddressFamily (%d) SocketType (%d) Protocol (%d).\n",
75 AddressFamily, SocketType, Protocol);
76
77 if (AddressFamily == AF_UNSPEC && SocketType == 0 && Protocol == 0)
78 return WSAEINVAL;
79
80 /* Set the defaults */
81 if (AddressFamily == AF_UNSPEC)
82 AddressFamily = AF_INET;
83
84 if (SocketType == 0)
85 SocketType = SOCK_STREAM;
86
87 if (Protocol == 0)
88 {
89 if (SocketType == SOCK_STREAM)
90 Protocol = IPPROTO_TCP;
91
92 if (SocketType == SOCK_DGRAM)
93 Protocol = IPPROTO_UDP;
94 }
95
96 /* Get Helper Data and Transport */
97 Status = SockGetTdiName (&AddressFamily,
98 &SocketType,
99 &Protocol,
100 g,
101 dwFlags,
102 &TransportName,
103 &HelperDLLContext,
104 &HelperData,
105 &HelperEvents);
106
107 /* Check for error */
108 if (Status != NO_ERROR)
109 {
110 ERR("SockGetTdiName: Status %x\n", Status);
111 goto error;
112 }
113
114 /* AFD Device Name */
115 RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint");
116
117 /* Set Socket Data */
118 Socket = HeapAlloc(GlobalHeap, 0, sizeof(*Socket));
119 if (!Socket)
120 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
121
122 RtlZeroMemory(Socket, sizeof(*Socket));
123 Socket->RefCount = 2;
124 Socket->Handle = -1;
125 Socket->SharedData.Listening = FALSE;
126 Socket->SharedData.State = SocketOpen;
127 Socket->SharedData.AddressFamily = AddressFamily;
128 Socket->SharedData.SocketType = SocketType;
129 Socket->SharedData.Protocol = Protocol;
130 Socket->HelperContext = HelperDLLContext;
131 Socket->HelperData = HelperData;
132 Socket->HelperEvents = HelperEvents;
133 Socket->LocalAddress = &Socket->WSLocalAddress;
134 Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength;
135 Socket->RemoteAddress = &Socket->WSRemoteAddress;
136 Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength;
137 Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance;
138 Socket->SharedData.CreateFlags = dwFlags;
139 Socket->SharedData.ServiceFlags1 = lpProtocolInfo->dwServiceFlags1;
140 Socket->SharedData.ProviderFlags = lpProtocolInfo->dwProviderFlags;
141 Socket->SharedData.GroupID = g;
142 Socket->SharedData.GroupType = 0;
143 Socket->SharedData.UseSAN = FALSE;
144 Socket->SharedData.NonBlocking = FALSE; /* Sockets start blocking */
145 Socket->SanData = NULL;
146 RtlCopyMemory(&Socket->ProtocolInfo, lpProtocolInfo, sizeof(Socket->ProtocolInfo));
147
148 /* Ask alex about this */
149 if( Socket->SharedData.SocketType == SOCK_DGRAM ||
150 Socket->SharedData.SocketType == SOCK_RAW )
151 {
152 TRACE("Connectionless socket\n");
153 Socket->SharedData.ServiceFlags1 |= XP1_CONNECTIONLESS;
154 }
155
156 /* Packet Size */
157 SizeOfPacket = TransportName.Length + sizeof(AFD_CREATE_PACKET) + sizeof(WCHAR);
158
159 /* EA Size */
160 SizeOfEA = SizeOfPacket + sizeof(FILE_FULL_EA_INFORMATION) + AFD_PACKET_COMMAND_LENGTH;
161
162 /* Set up EA Buffer */
163 EABuffer = HeapAlloc(GlobalHeap, 0, SizeOfEA);
164 if (!EABuffer)
165 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
166
167 RtlZeroMemory(EABuffer, SizeOfEA);
168 EABuffer->NextEntryOffset = 0;
169 EABuffer->Flags = 0;
170 EABuffer->EaNameLength = AFD_PACKET_COMMAND_LENGTH;
171 RtlCopyMemory (EABuffer->EaName,
172 AfdCommand,
173 AFD_PACKET_COMMAND_LENGTH + 1);
174 EABuffer->EaValueLength = SizeOfPacket;
175
176 /* Set up AFD Packet */
177 AfdPacket = (PAFD_CREATE_PACKET)(EABuffer->EaName + EABuffer->EaNameLength + 1);
178 AfdPacket->SizeOfTransportName = TransportName.Length;
179 RtlCopyMemory (AfdPacket->TransportName,
180 TransportName.Buffer,
181 TransportName.Length + sizeof(WCHAR));
182 AfdPacket->GroupID = g;
183
184 /* Set up Endpoint Flags */
185 if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) != 0)
186 {
187 if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW))
188 {
189 /* Only RAW or UDP can be Connectionless */
190 goto error;
191 }
192 AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS;
193 }
194
195 if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED) != 0)
196 {
197 if (SocketType == SOCK_STREAM)
198 {
199 if ((Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM) == 0)
200 {
201 /* The Provider doesn't actually support Message Oriented Streams */
202 goto error;
203 }
204 }
205 AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED;
206 }
207
208 if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW;
209
210 if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT |
211 WSA_FLAG_MULTIPOINT_C_LEAF |
212 WSA_FLAG_MULTIPOINT_D_ROOT |
213 WSA_FLAG_MULTIPOINT_D_LEAF))
214 {
215 if ((Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT) == 0)
216 {
217 /* The Provider doesn't actually support Multipoint */
218 goto error;
219 }
220 AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT;
221
222 if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT)
223 {
224 if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_CONTROL_PLANE) == 0)
225 || ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF) != 0))
226 {
227 /* The Provider doesn't support Control Planes, or you already gave a leaf */
228 goto error;
229 }
230 AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT;
231 }
232
233 if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT)
234 {
235 if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_DATA_PLANE) == 0)
236 || ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF) != 0))
237 {
238 /* The Provider doesn't support Data Planes, or you already gave a leaf */
239 goto error;
240 }
241 AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT;
242 }
243 }
244
245 /* Set up Object Attributes */
246 InitializeObjectAttributes (&Object,
247 &DevName,
248 OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
249 0,
250 0);
251
252 /* Create the Socket as asynchronous. That means we have to block
253 ourselves after every call to NtDeviceIoControlFile. This is
254 because the kernel doesn't support overlapping synchronous I/O
255 requests (made from multiple threads) at this time (Sep 2005) */
256 Status = NtCreateFile(&Sock,
257 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
258 &Object,
259 &IOSB,
260 NULL,
261 0,
262 FILE_SHARE_READ | FILE_SHARE_WRITE,
263 FILE_OPEN_IF,
264 0,
265 EABuffer,
266 SizeOfEA);
267
268 HeapFree(GlobalHeap, 0, EABuffer);
269
270 if (!NT_SUCCESS(Status))
271 {
272 ERR("Failed to open socket. Status 0x%08x\n", Status);
273
274 HeapFree(GlobalHeap, 0, Socket);
275
276 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
277 }
278
279 /* Save Handle */
280 Socket->Handle = (SOCKET)Sock;
281
282 /* Save Group Info */
283 if (g != 0)
284 {
285 GetSocketInformation(Socket, AFD_INFO_GROUP_ID_TYPE, NULL, NULL, &GroupData);
286 Socket->SharedData.GroupID = GroupData.u.LowPart;
287 Socket->SharedData.GroupType = GroupData.u.HighPart;
288 }
289
290 /* Get Window Sizes and Save them */
291 GetSocketInformation (Socket,
292 AFD_INFO_SEND_WINDOW_SIZE,
293 NULL,
294 &Socket->SharedData.SizeOfSendBuffer,
295 NULL);
296
297 GetSocketInformation (Socket,
298 AFD_INFO_RECEIVE_WINDOW_SIZE,
299 NULL,
300 &Socket->SharedData.SizeOfRecvBuffer,
301 NULL);
302
303 /* Save in Process Sockets List */
304 EnterCriticalSection(&SocketListLock);
305 Socket->NextSocket = SocketListHead;
306 SocketListHead = Socket;
307 LeaveCriticalSection(&SocketListLock);
308
309 /* Create the Socket Context */
310 CreateContext(Socket);
311
312 /* Notify Winsock */
313 Upcalls.lpWPUModifyIFSHandle(Socket->ProtocolInfo.dwCatalogEntryId, (SOCKET)Sock, lpErrno);
314
315 /* Return Socket Handle */
316 TRACE("Success %x\n", Sock);
317
318 return (SOCKET)Sock;
319
320 error:
321 ERR("Ending %x\n", Status);
322
323 if( Socket )
324 HeapFree(GlobalHeap, 0, Socket);
325
326 if( EABuffer )
327 HeapFree(GlobalHeap, 0, EABuffer);
328
329 if( lpErrno )
330 *lpErrno = Status;
331
332 return INVALID_SOCKET;
333 }
334
335 INT
336 TranslateNtStatusError(NTSTATUS Status)
337 {
338 switch (Status)
339 {
340 case STATUS_CANT_WAIT:
341 return WSAEWOULDBLOCK;
342
343 case STATUS_TIMEOUT:
344 return WSAETIMEDOUT;
345
346 case STATUS_SUCCESS:
347 return NO_ERROR;
348
349 case STATUS_FILE_CLOSED:
350 case STATUS_END_OF_FILE:
351 return WSAESHUTDOWN;
352
353 case STATUS_PENDING:
354 return WSA_IO_PENDING;
355
356 case STATUS_BUFFER_TOO_SMALL:
357 case STATUS_BUFFER_OVERFLOW:
358 return WSAEMSGSIZE;
359
360 case STATUS_NO_MEMORY:
361 case STATUS_INSUFFICIENT_RESOURCES:
362 return WSAENOBUFS;
363
364 case STATUS_INVALID_CONNECTION:
365 return WSAENOTCONN;
366
367 case STATUS_PROTOCOL_NOT_SUPPORTED:
368 return WSAEAFNOSUPPORT;
369
370 case STATUS_INVALID_ADDRESS:
371 return WSAEADDRNOTAVAIL;
372
373 case STATUS_REMOTE_NOT_LISTENING:
374 return WSAECONNREFUSED;
375
376 case STATUS_NETWORK_UNREACHABLE:
377 return WSAENETUNREACH;
378
379 case STATUS_INVALID_PARAMETER:
380 return WSAEINVAL;
381
382 case STATUS_CANCELLED:
383 return WSA_OPERATION_ABORTED;
384
385 case STATUS_ADDRESS_ALREADY_EXISTS:
386 return WSAEADDRINUSE;
387
388 case STATUS_LOCAL_DISCONNECT:
389 return WSAECONNABORTED;
390
391 case STATUS_REMOTE_DISCONNECT:
392 return WSAECONNRESET;
393
394 case STATUS_ACCESS_VIOLATION:
395 return WSAEFAULT;
396
397 case STATUS_ACCESS_DENIED:
398 return WSAEACCES;
399
400 default:
401 ERR("MSAFD: Unhandled NTSTATUS value: 0x%x\n", Status);
402 return WSAENETDOWN;
403 }
404 }
405
406 /*
407 * FUNCTION: Closes an open socket
408 * ARGUMENTS:
409 * s = Socket descriptor
410 * lpErrno = Address of buffer for error information
411 * RETURNS:
412 * NO_ERROR, or SOCKET_ERROR if the socket could not be closed
413 */
414 INT
415 WSPAPI
416 WSPCloseSocket(IN SOCKET Handle,
417 OUT LPINT lpErrno)
418 {
419 IO_STATUS_BLOCK IoStatusBlock;
420 PSOCKET_INFORMATION Socket = NULL, CurrentSocket;
421 NTSTATUS Status;
422 HANDLE SockEvent;
423 AFD_DISCONNECT_INFO DisconnectInfo;
424 SOCKET_STATE OldState;
425 LONG LingerWait = -1;
426
427 /* Create the Wait Event */
428 Status = NtCreateEvent(&SockEvent,
429 EVENT_ALL_ACCESS,
430 NULL,
431 1,
432 FALSE);
433
434 if(!NT_SUCCESS(Status))
435 {
436 ERR("NtCreateEvent failed: 0x%08x", Status);
437 return SOCKET_ERROR;
438 }
439 /* Get the Socket Structure associate to this Socket*/
440 Socket = GetSocketStructure(Handle);
441 if (!Socket)
442 {
443 NtClose(SockEvent);
444 *lpErrno = WSAENOTSOCK;
445 return SOCKET_ERROR;
446 }
447
448 if (Socket->HelperEvents & WSH_NOTIFY_CLOSE)
449 {
450 Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
451 Socket->Handle,
452 Socket->TdiAddressHandle,
453 Socket->TdiConnectionHandle,
454 WSH_NOTIFY_CLOSE);
455
456 if (Status)
457 {
458 if (lpErrno) *lpErrno = Status;
459 ERR("WSHNotify failed. Error 0x%#x", Status);
460 NtClose(SockEvent);
461 return SOCKET_ERROR;
462 }
463 }
464
465 /* If a Close is already in Process, give up */
466 if (Socket->SharedData.State == SocketClosed)
467 {
468 WARN("Socket is closing.\n");
469 NtClose(SockEvent);
470 *lpErrno = WSAENOTSOCK;
471 return SOCKET_ERROR;
472 }
473
474 /* Set the state to close */
475 OldState = Socket->SharedData.State;
476 Socket->SharedData.State = SocketClosed;
477
478 /* If SO_LINGER is ON and the Socket is connected, we need to disconnect */
479 /* FIXME: Should we do this on Datagram Sockets too? */
480 if ((OldState == SocketConnected) && (Socket->SharedData.LingerData.l_onoff))
481 {
482 ULONG SendsInProgress;
483 ULONG SleepWait;
484
485 /* We need to respect the timeout */
486 SleepWait = 100;
487 LingerWait = Socket->SharedData.LingerData.l_linger * 1000;
488
489 /* Loop until no more sends are pending, within the timeout */
490 while (LingerWait)
491 {
492 /* Find out how many Sends are in Progress */
493 if (GetSocketInformation(Socket,
494 AFD_INFO_SENDS_IN_PROGRESS,
495 NULL,
496 &SendsInProgress,
497 NULL))
498 {
499 /* Bail out if anything but NO_ERROR */
500 LingerWait = 0;
501 break;
502 }
503
504 /* Bail out if no more sends are pending */
505 if (!SendsInProgress)
506 {
507 LingerWait = -1;
508 break;
509 }
510
511 /*
512 * We have to execute a sleep, so it's kind of like
513 * a block. If the socket is Nonblock, we cannot
514 * go on since asyncronous operation is expected
515 * and we cannot offer it
516 */
517 if (Socket->SharedData.NonBlocking)
518 {
519 WARN("Would block!\n");
520 NtClose(SockEvent);
521 Socket->SharedData.State = OldState;
522 *lpErrno = WSAEWOULDBLOCK;
523 return SOCKET_ERROR;
524 }
525
526 /* Now we can sleep, and decrement the linger wait */
527 /*
528 * FIXME: It seems Windows does some funky acceleration
529 * since the waiting seems to be longer and longer. I
530 * don't think this improves performance so much, so we
531 * wait a fixed time instead.
532 */
533 Sleep(SleepWait);
534 LingerWait -= SleepWait;
535 }
536 }
537
538 if (OldState == SocketConnected)
539 {
540 if (LingerWait <= 0)
541 {
542 DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0);
543 DisconnectInfo.DisconnectType = LingerWait < 0 ? AFD_DISCONNECT_SEND : AFD_DISCONNECT_ABORT;
544
545 if (((DisconnectInfo.DisconnectType & AFD_DISCONNECT_SEND) && (!Socket->SharedData.SendShutdown)) ||
546 ((DisconnectInfo.DisconnectType & AFD_DISCONNECT_ABORT) && (!Socket->SharedData.ReceiveShutdown)))
547 {
548 /* Send IOCTL */
549 Status = NtDeviceIoControlFile((HANDLE)Handle,
550 SockEvent,
551 NULL,
552 NULL,
553 &IoStatusBlock,
554 IOCTL_AFD_DISCONNECT,
555 &DisconnectInfo,
556 sizeof(DisconnectInfo),
557 NULL,
558 0);
559
560 /* Wait for return */
561 if (Status == STATUS_PENDING)
562 {
563 WaitForSingleObject(SockEvent, INFINITE);
564 Status = IoStatusBlock.Status;
565 }
566 }
567 }
568 }
569
570 /* Cleanup Time! */
571 Socket->HelperContext = NULL;
572 Socket->SharedData.AsyncDisabledEvents = -1;
573 NtClose(Socket->TdiAddressHandle);
574 Socket->TdiAddressHandle = NULL;
575 NtClose(Socket->TdiConnectionHandle);
576 Socket->TdiConnectionHandle = NULL;
577
578 EnterCriticalSection(&SocketListLock);
579 if (SocketListHead == Socket)
580 {
581 SocketListHead = SocketListHead->NextSocket;
582 }
583 else
584 {
585 CurrentSocket = SocketListHead;
586 while (CurrentSocket->NextSocket)
587 {
588 if (CurrentSocket->NextSocket == Socket)
589 {
590 CurrentSocket->NextSocket = CurrentSocket->NextSocket->NextSocket;
591 break;
592 }
593
594 CurrentSocket = CurrentSocket->NextSocket;
595 }
596 }
597 LeaveCriticalSection(&SocketListLock);
598
599 /* Close the handle */
600 NtClose((HANDLE)Handle);
601 NtClose(SockEvent);
602
603 HeapFree(GlobalHeap, 0, Socket);
604 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
605 }
606
607
608 /*
609 * FUNCTION: Associates a local address with a socket
610 * ARGUMENTS:
611 * s = Socket descriptor
612 * name = Pointer to local address
613 * namelen = Length of name
614 * lpErrno = Address of buffer for error information
615 * RETURNS:
616 * 0, or SOCKET_ERROR if the socket could not be bound
617 */
618 INT
619 WSPAPI
620 WSPBind(SOCKET Handle,
621 const struct sockaddr *SocketAddress,
622 int SocketAddressLength,
623 LPINT lpErrno)
624 {
625 IO_STATUS_BLOCK IOSB;
626 PAFD_BIND_DATA BindData;
627 PSOCKET_INFORMATION Socket = NULL;
628 NTSTATUS Status;
629 SOCKADDR_INFO SocketInfo;
630 HANDLE SockEvent;
631
632 /* See below */
633 BindData = HeapAlloc(GlobalHeap, 0, 0xA + SocketAddressLength);
634 if (!BindData)
635 {
636 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
637 }
638
639 Status = NtCreateEvent(&SockEvent,
640 EVENT_ALL_ACCESS,
641 NULL,
642 1,
643 FALSE);
644
645 if (!NT_SUCCESS(Status))
646 {
647 HeapFree(GlobalHeap, 0, BindData);
648 return SOCKET_ERROR;
649 }
650
651 /* Get the Socket Structure associate to this Socket*/
652 Socket = GetSocketStructure(Handle);
653 if (!Socket)
654 {
655 HeapFree(GlobalHeap, 0, BindData);
656 *lpErrno = WSAENOTSOCK;
657 return SOCKET_ERROR;
658 }
659
660 /* Set up Address in TDI Format */
661 BindData->Address.TAAddressCount = 1;
662 BindData->Address.Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family);
663 BindData->Address.Address[0].AddressType = SocketAddress->sa_family;
664 RtlCopyMemory (BindData->Address.Address[0].Address,
665 SocketAddress->sa_data,
666 SocketAddressLength - sizeof(SocketAddress->sa_family));
667
668 /* Get Address Information */
669 Socket->HelperData->WSHGetSockaddrType ((PSOCKADDR)SocketAddress,
670 SocketAddressLength,
671 &SocketInfo);
672
673 /* Set the Share Type */
674 if (Socket->SharedData.ExclusiveAddressUse)
675 {
676 BindData->ShareType = AFD_SHARE_EXCLUSIVE;
677 }
678 else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard)
679 {
680 BindData->ShareType = AFD_SHARE_WILDCARD;
681 }
682 else if (Socket->SharedData.ReuseAddresses)
683 {
684 BindData->ShareType = AFD_SHARE_REUSE;
685 }
686 else
687 {
688 BindData->ShareType = AFD_SHARE_UNIQUE;
689 }
690
691 /* Send IOCTL */
692 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
693 SockEvent,
694 NULL,
695 NULL,
696 &IOSB,
697 IOCTL_AFD_BIND,
698 BindData,
699 0xA + Socket->SharedData.SizeOfLocalAddress, /* Can't figure out a way to calculate this in C*/
700 BindData,
701 0xA + Socket->SharedData.SizeOfLocalAddress); /* Can't figure out a way to calculate this C */
702
703 /* Wait for return */
704 if (Status == STATUS_PENDING)
705 {
706 WaitForSingleObject(SockEvent, INFINITE);
707 Status = IOSB.Status;
708 }
709
710 NtClose( SockEvent );
711 HeapFree(GlobalHeap, 0, BindData);
712
713 if (Status != STATUS_SUCCESS)
714 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
715
716 /* Set up Socket Data */
717 Socket->SharedData.State = SocketBound;
718 Socket->TdiAddressHandle = (HANDLE)IOSB.Information;
719
720 if (Socket->HelperEvents & WSH_NOTIFY_BIND)
721 {
722 Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
723 Socket->Handle,
724 Socket->TdiAddressHandle,
725 Socket->TdiConnectionHandle,
726 WSH_NOTIFY_BIND);
727
728 if (Status)
729 {
730 if (lpErrno) *lpErrno = Status;
731 return SOCKET_ERROR;
732 }
733 }
734
735 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
736 }
737
738 int
739 WSPAPI
740 WSPListen(SOCKET Handle,
741 int Backlog,
742 LPINT lpErrno)
743 {
744 IO_STATUS_BLOCK IOSB;
745 AFD_LISTEN_DATA ListenData;
746 PSOCKET_INFORMATION Socket = NULL;
747 HANDLE SockEvent;
748 NTSTATUS Status;
749
750 /* Get the Socket Structure associate to this Socket*/
751 Socket = GetSocketStructure(Handle);
752 if (!Socket)
753 {
754 *lpErrno = WSAENOTSOCK;
755 return SOCKET_ERROR;
756 }
757
758 if (Socket->SharedData.Listening)
759 return 0;
760
761 Status = NtCreateEvent(&SockEvent,
762 EVENT_ALL_ACCESS,
763 NULL,
764 1,
765 FALSE);
766
767 if( !NT_SUCCESS(Status) )
768 return -1;
769
770 /* Set Up Listen Structure */
771 ListenData.UseSAN = FALSE;
772 ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance;
773 ListenData.Backlog = Backlog;
774
775 /* Send IOCTL */
776 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
777 SockEvent,
778 NULL,
779 NULL,
780 &IOSB,
781 IOCTL_AFD_START_LISTEN,
782 &ListenData,
783 sizeof(ListenData),
784 NULL,
785 0);
786
787 /* Wait for return */
788 if (Status == STATUS_PENDING)
789 {
790 WaitForSingleObject(SockEvent, INFINITE);
791 Status = IOSB.Status;
792 }
793
794 NtClose( SockEvent );
795
796 if (Status != STATUS_SUCCESS)
797 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
798
799 /* Set to Listening */
800 Socket->SharedData.Listening = TRUE;
801
802 if (Socket->HelperEvents & WSH_NOTIFY_LISTEN)
803 {
804 Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
805 Socket->Handle,
806 Socket->TdiAddressHandle,
807 Socket->TdiConnectionHandle,
808 WSH_NOTIFY_LISTEN);
809
810 if (Status)
811 {
812 if (lpErrno) *lpErrno = Status;
813 return SOCKET_ERROR;
814 }
815 }
816
817 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
818 }
819
820
821 int
822 WSPAPI
823 WSPSelect(IN int nfds,
824 IN OUT fd_set *readfds OPTIONAL,
825 IN OUT fd_set *writefds OPTIONAL,
826 IN OUT fd_set *exceptfds OPTIONAL,
827 IN const struct timeval *timeout OPTIONAL,
828 OUT LPINT lpErrno)
829 {
830 IO_STATUS_BLOCK IOSB;
831 PAFD_POLL_INFO PollInfo;
832 NTSTATUS Status;
833 ULONG HandleCount;
834 LONG OutCount = 0;
835 ULONG PollBufferSize;
836 PVOID PollBuffer;
837 ULONG i, j = 0, x;
838 HANDLE SockEvent;
839 BOOL HandleCounted;
840 LARGE_INTEGER Timeout;
841
842 /* Find out how many sockets we have, and how large the buffer needs
843 * to be */
844
845 HandleCount = ( readfds ? readfds->fd_count : 0 ) +
846 ( writefds ? writefds->fd_count : 0 ) +
847 ( exceptfds ? exceptfds->fd_count : 0 );
848
849 if ( HandleCount == 0 )
850 {
851 WARN("No handles! Returning SOCKET_ERROR\n", HandleCount);
852 if (lpErrno) *lpErrno = WSAEINVAL;
853 return SOCKET_ERROR;
854 }
855
856 PollBufferSize = sizeof(*PollInfo) + ((HandleCount - 1) * sizeof(AFD_HANDLE));
857
858 TRACE("HandleCount: %u BufferSize: %u\n", HandleCount, PollBufferSize);
859
860 /* Convert Timeout to NT Format */
861 if (timeout == NULL)
862 {
863 Timeout.u.LowPart = -1;
864 Timeout.u.HighPart = 0x7FFFFFFF;
865 TRACE("Infinite timeout\n");
866 }
867 else
868 {
869 Timeout = RtlEnlargedIntegerMultiply
870 ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000), -10000);
871 /* Negative timeouts are illegal. Since the kernel represents an
872 * incremental timeout as a negative number, we check for a positive
873 * result.
874 */
875 if (Timeout.QuadPart > 0)
876 {
877 if (lpErrno) *lpErrno = WSAEINVAL;
878 return SOCKET_ERROR;
879 }
880 TRACE("Timeout: Orig %d.%06d kernel %d\n",
881 timeout->tv_sec, timeout->tv_usec,
882 Timeout.u.LowPart);
883 }
884
885 Status = NtCreateEvent(&SockEvent,
886 EVENT_ALL_ACCESS,
887 NULL,
888 1,
889 FALSE);
890
891 if(!NT_SUCCESS(Status))
892 {
893 if (lpErrno)
894 *lpErrno = WSAEFAULT;
895
896 ERR("NtCreateEvent failed, 0x%08x\n", Status);
897 return SOCKET_ERROR;
898 }
899
900 /* Allocate */
901 PollBuffer = HeapAlloc(GlobalHeap, 0, PollBufferSize);
902
903 if (!PollBuffer)
904 {
905 if (lpErrno)
906 *lpErrno = WSAEFAULT;
907 NtClose(SockEvent);
908 return SOCKET_ERROR;
909 }
910
911 PollInfo = (PAFD_POLL_INFO)PollBuffer;
912
913 RtlZeroMemory( PollInfo, PollBufferSize );
914
915 /* Number of handles for AFD to Check */
916 PollInfo->Exclusive = FALSE;
917 PollInfo->Timeout = Timeout;
918
919 if (readfds != NULL) {
920 for (i = 0; i < readfds->fd_count; i++, j++)
921 {
922 PollInfo->Handles[j].Handle = readfds->fd_array[i];
923 PollInfo->Handles[j].Events = AFD_EVENT_RECEIVE |
924 AFD_EVENT_DISCONNECT |
925 AFD_EVENT_ABORT |
926 AFD_EVENT_CLOSE |
927 AFD_EVENT_ACCEPT;
928 }
929 }
930 if (writefds != NULL)
931 {
932 for (i = 0; i < writefds->fd_count; i++, j++)
933 {
934 PollInfo->Handles[j].Handle = writefds->fd_array[i];
935 PollInfo->Handles[j].Events = AFD_EVENT_SEND | AFD_EVENT_CONNECT;
936 }
937 }
938 if (exceptfds != NULL)
939 {
940 for (i = 0; i < exceptfds->fd_count; i++, j++)
941 {
942 PollInfo->Handles[j].Handle = exceptfds->fd_array[i];
943 PollInfo->Handles[j].Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL;
944 }
945 }
946
947 PollInfo->HandleCount = j;
948 PollBufferSize = FIELD_OFFSET(AFD_POLL_INFO, Handles) + PollInfo->HandleCount * sizeof(AFD_HANDLE);
949
950 /* Send IOCTL */
951 Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle,
952 SockEvent,
953 NULL,
954 NULL,
955 &IOSB,
956 IOCTL_AFD_SELECT,
957 PollInfo,
958 PollBufferSize,
959 PollInfo,
960 PollBufferSize);
961
962 TRACE("DeviceIoControlFile => %x\n", Status);
963
964 /* Wait for Completition */
965 if (Status == STATUS_PENDING)
966 {
967 WaitForSingleObject(SockEvent, INFINITE);
968 Status = IOSB.Status;
969 }
970
971 /* Clear the Structures */
972 if( readfds )
973 FD_ZERO(readfds);
974 if( writefds )
975 FD_ZERO(writefds);
976 if( exceptfds )
977 FD_ZERO(exceptfds);
978
979 /* Loop through return structure */
980 HandleCount = PollInfo->HandleCount;
981
982 /* Return in FDSET Format */
983 for (i = 0; i < HandleCount; i++)
984 {
985 HandleCounted = FALSE;
986 for(x = 1; x; x<<=1)
987 {
988 switch (PollInfo->Handles[i].Events & x)
989 {
990 case AFD_EVENT_RECEIVE:
991 case AFD_EVENT_DISCONNECT:
992 case AFD_EVENT_ABORT:
993 case AFD_EVENT_ACCEPT:
994 case AFD_EVENT_CLOSE:
995 TRACE("Event %x on handle %x\n",
996 PollInfo->Handles[i].Events,
997 PollInfo->Handles[i].Handle);
998 if (! HandleCounted)
999 {
1000 OutCount++;
1001 HandleCounted = TRUE;
1002 }
1003 if( readfds )
1004 FD_SET(PollInfo->Handles[i].Handle, readfds);
1005 break;
1006 case AFD_EVENT_SEND:
1007 case AFD_EVENT_CONNECT:
1008 TRACE("Event %x on handle %x\n",
1009 PollInfo->Handles[i].Events,
1010 PollInfo->Handles[i].Handle);
1011 if (! HandleCounted)
1012 {
1013 OutCount++;
1014 HandleCounted = TRUE;
1015 }
1016 if( writefds )
1017 FD_SET(PollInfo->Handles[i].Handle, writefds);
1018 break;
1019 case AFD_EVENT_OOB_RECEIVE:
1020 case AFD_EVENT_CONNECT_FAIL:
1021 TRACE("Event %x on handle %x\n",
1022 PollInfo->Handles[i].Events,
1023 PollInfo->Handles[i].Handle);
1024 if (! HandleCounted)
1025 {
1026 OutCount++;
1027 HandleCounted = TRUE;
1028 }
1029 if( exceptfds )
1030 FD_SET(PollInfo->Handles[i].Handle, exceptfds);
1031 break;
1032 }
1033 }
1034 }
1035
1036 HeapFree( GlobalHeap, 0, PollBuffer );
1037 NtClose( SockEvent );
1038
1039 if( lpErrno )
1040 {
1041 switch( IOSB.Status )
1042 {
1043 case STATUS_SUCCESS:
1044 case STATUS_TIMEOUT:
1045 *lpErrno = 0;
1046 break;
1047 default:
1048 *lpErrno = WSAEINVAL;
1049 break;
1050 }
1051 TRACE("*lpErrno = %x\n", *lpErrno);
1052 }
1053
1054 TRACE("%d events\n", OutCount);
1055
1056 return OutCount;
1057 }
1058
1059 SOCKET
1060 WSPAPI
1061 WSPAccept(SOCKET Handle,
1062 struct sockaddr *SocketAddress,
1063 int *SocketAddressLength,
1064 LPCONDITIONPROC lpfnCondition,
1065 DWORD dwCallbackData,
1066 LPINT lpErrno)
1067 {
1068 IO_STATUS_BLOCK IOSB;
1069 PAFD_RECEIVED_ACCEPT_DATA ListenReceiveData;
1070 AFD_ACCEPT_DATA AcceptData;
1071 AFD_DEFER_ACCEPT_DATA DeferData;
1072 AFD_PENDING_ACCEPT_DATA PendingAcceptData;
1073 PSOCKET_INFORMATION Socket = NULL;
1074 NTSTATUS Status;
1075 struct fd_set ReadSet;
1076 struct timeval Timeout;
1077 PVOID PendingData = NULL;
1078 ULONG PendingDataLength = 0;
1079 PVOID CalleeDataBuffer;
1080 WSABUF CallerData, CalleeID, CallerID, CalleeData;
1081 PSOCKADDR RemoteAddress = NULL;
1082 GROUP GroupID = 0;
1083 ULONG CallBack;
1084 SOCKET AcceptSocket;
1085 PSOCKET_INFORMATION AcceptSocketInfo;
1086 UCHAR ReceiveBuffer[0x1A];
1087 HANDLE SockEvent;
1088
1089 Status = NtCreateEvent(&SockEvent,
1090 EVENT_ALL_ACCESS,
1091 NULL,
1092 1,
1093 FALSE);
1094
1095 if( !NT_SUCCESS(Status) )
1096 {
1097 MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1098 return INVALID_SOCKET;
1099 }
1100
1101 /* Dynamic Structure...ugh */
1102 ListenReceiveData = (PAFD_RECEIVED_ACCEPT_DATA)ReceiveBuffer;
1103
1104 /* Get the Socket Structure associate to this Socket*/
1105 Socket = GetSocketStructure(Handle);
1106 if (!Socket)
1107 {
1108 NtClose(SockEvent);
1109 *lpErrno = WSAENOTSOCK;
1110 return INVALID_SOCKET;
1111 }
1112
1113 /* If this is non-blocking, make sure there's something for us to accept */
1114 FD_ZERO(&ReadSet);
1115 FD_SET(Socket->Handle, &ReadSet);
1116 Timeout.tv_sec=0;
1117 Timeout.tv_usec=0;
1118
1119 if (WSPSelect(0, &ReadSet, NULL, NULL, &Timeout, lpErrno) == SOCKET_ERROR)
1120 {
1121 NtClose(SockEvent);
1122 return INVALID_SOCKET;
1123 }
1124
1125 if (ReadSet.fd_array[0] != Socket->Handle)
1126 {
1127 NtClose(SockEvent);
1128 *lpErrno = WSAEWOULDBLOCK;
1129 return INVALID_SOCKET;
1130 }
1131
1132 /* Send IOCTL */
1133 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1134 SockEvent,
1135 NULL,
1136 NULL,
1137 &IOSB,
1138 IOCTL_AFD_WAIT_FOR_LISTEN,
1139 NULL,
1140 0,
1141 ListenReceiveData,
1142 0xA + sizeof(*ListenReceiveData));
1143
1144 /* Wait for return */
1145 if (Status == STATUS_PENDING)
1146 {
1147 WaitForSingleObject(SockEvent, INFINITE);
1148 Status = IOSB.Status;
1149 }
1150
1151 if (!NT_SUCCESS(Status))
1152 {
1153 NtClose( SockEvent );
1154 MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1155 return INVALID_SOCKET;
1156 }
1157
1158 if (lpfnCondition != NULL)
1159 {
1160 if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA) != 0)
1161 {
1162 /* Find out how much data is pending */
1163 PendingAcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
1164 PendingAcceptData.ReturnSize = TRUE;
1165
1166 /* Send IOCTL */
1167 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1168 SockEvent,
1169 NULL,
1170 NULL,
1171 &IOSB,
1172 IOCTL_AFD_GET_PENDING_CONNECT_DATA,
1173 &PendingAcceptData,
1174 sizeof(PendingAcceptData),
1175 &PendingAcceptData,
1176 sizeof(PendingAcceptData));
1177
1178 /* Wait for return */
1179 if (Status == STATUS_PENDING)
1180 {
1181 WaitForSingleObject(SockEvent, INFINITE);
1182 Status = IOSB.Status;
1183 }
1184
1185 if (!NT_SUCCESS(Status))
1186 {
1187 NtClose( SockEvent );
1188 MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1189 return INVALID_SOCKET;
1190 }
1191
1192 /* How much data to allocate */
1193 PendingDataLength = IOSB.Information;
1194
1195 if (PendingDataLength)
1196 {
1197 /* Allocate needed space */
1198 PendingData = HeapAlloc(GlobalHeap, 0, PendingDataLength);
1199 if (!PendingData)
1200 {
1201 MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
1202 return INVALID_SOCKET;
1203 }
1204
1205 /* We want the data now */
1206 PendingAcceptData.ReturnSize = FALSE;
1207
1208 /* Send IOCTL */
1209 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1210 SockEvent,
1211 NULL,
1212 NULL,
1213 &IOSB,
1214 IOCTL_AFD_GET_PENDING_CONNECT_DATA,
1215 &PendingAcceptData,
1216 sizeof(PendingAcceptData),
1217 PendingData,
1218 PendingDataLength);
1219
1220 /* Wait for return */
1221 if (Status == STATUS_PENDING)
1222 {
1223 WaitForSingleObject(SockEvent, INFINITE);
1224 Status = IOSB.Status;
1225 }
1226
1227 if (!NT_SUCCESS(Status))
1228 {
1229 NtClose( SockEvent );
1230 MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1231 return INVALID_SOCKET;
1232 }
1233 }
1234 }
1235
1236 if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED) != 0)
1237 {
1238 /* I don't support this yet */
1239 }
1240
1241 /* Build Callee ID */
1242 CalleeID.buf = (PVOID)Socket->LocalAddress;
1243 CalleeID.len = Socket->SharedData.SizeOfLocalAddress;
1244
1245 RemoteAddress = HeapAlloc(GlobalHeap, 0, sizeof(*RemoteAddress));
1246 if (!RemoteAddress)
1247 {
1248 MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
1249 return INVALID_SOCKET;
1250 }
1251
1252 /* Set up Address in SOCKADDR Format */
1253 RtlCopyMemory (RemoteAddress,
1254 &ListenReceiveData->Address.Address[0].AddressType,
1255 sizeof(*RemoteAddress));
1256
1257 /* Build Caller ID */
1258 CallerID.buf = (PVOID)RemoteAddress;
1259 CallerID.len = sizeof(*RemoteAddress);
1260
1261 /* Build Caller Data */
1262 CallerData.buf = PendingData;
1263 CallerData.len = PendingDataLength;
1264
1265 /* Check if socket supports Conditional Accept */
1266 if (Socket->SharedData.UseDelayedAcceptance != 0)
1267 {
1268 /* Allocate Buffer for Callee Data */
1269 CalleeDataBuffer = HeapAlloc(GlobalHeap, 0, 4096);
1270 if (!CalleeDataBuffer) {
1271 MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
1272 return INVALID_SOCKET;
1273 }
1274 CalleeData.buf = CalleeDataBuffer;
1275 CalleeData.len = 4096;
1276 }
1277 else
1278 {
1279 /* Nothing */
1280 CalleeData.buf = 0;
1281 CalleeData.len = 0;
1282 }
1283
1284 /* Call the Condition Function */
1285 CallBack = (lpfnCondition)(&CallerID,
1286 CallerData.buf == NULL ? NULL : &CallerData,
1287 NULL,
1288 NULL,
1289 &CalleeID,
1290 CalleeData.buf == NULL ? NULL : &CalleeData,
1291 &GroupID,
1292 dwCallbackData);
1293
1294 if (((CallBack == CF_ACCEPT) && GroupID) != 0)
1295 {
1296 /* TBD: Check for Validity */
1297 }
1298
1299 if (CallBack == CF_ACCEPT)
1300 {
1301 if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED) != 0)
1302 {
1303 /* I don't support this yet */
1304 }
1305 if (CalleeData.buf)
1306 {
1307 // SockSetConnectData Sockets(SocketID), IOCTL_AFD_SET_CONNECT_DATA, CalleeData.Buffer, CalleeData.BuffSize, 0
1308 }
1309 }
1310 else
1311 {
1312 /* Callback rejected. Build Defer Structure */
1313 DeferData.SequenceNumber = ListenReceiveData->SequenceNumber;
1314 DeferData.RejectConnection = (CallBack == CF_REJECT);
1315
1316 /* Send IOCTL */
1317 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1318 SockEvent,
1319 NULL,
1320 NULL,
1321 &IOSB,
1322 IOCTL_AFD_DEFER_ACCEPT,
1323 &DeferData,
1324 sizeof(DeferData),
1325 NULL,
1326 0);
1327
1328 /* Wait for return */
1329 if (Status == STATUS_PENDING)
1330 {
1331 WaitForSingleObject(SockEvent, INFINITE);
1332 Status = IOSB.Status;
1333 }
1334
1335 NtClose( SockEvent );
1336
1337 if (!NT_SUCCESS(Status))
1338 {
1339 MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1340 return INVALID_SOCKET;
1341 }
1342
1343 if (CallBack == CF_REJECT )
1344 {
1345 *lpErrno = WSAECONNREFUSED;
1346 return INVALID_SOCKET;
1347 }
1348 else
1349 {
1350 *lpErrno = WSAECONNREFUSED;
1351 return INVALID_SOCKET;
1352 }
1353 }
1354 }
1355
1356 /* Create a new Socket */
1357 AcceptSocket = WSPSocket (Socket->SharedData.AddressFamily,
1358 Socket->SharedData.SocketType,
1359 Socket->SharedData.Protocol,
1360 &Socket->ProtocolInfo,
1361 GroupID,
1362 Socket->SharedData.CreateFlags,
1363 lpErrno);
1364 if (AcceptSocket == INVALID_SOCKET)
1365 return INVALID_SOCKET;
1366
1367 /* Set up the Accept Structure */
1368 AcceptData.ListenHandle = (HANDLE)AcceptSocket;
1369 AcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
1370
1371 /* Send IOCTL to Accept */
1372 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1373 SockEvent,
1374 NULL,
1375 NULL,
1376 &IOSB,
1377 IOCTL_AFD_ACCEPT,
1378 &AcceptData,
1379 sizeof(AcceptData),
1380 NULL,
1381 0);
1382
1383 /* Wait for return */
1384 if (Status == STATUS_PENDING)
1385 {
1386 WaitForSingleObject(SockEvent, INFINITE);
1387 Status = IOSB.Status;
1388 }
1389
1390 if (!NT_SUCCESS(Status))
1391 {
1392 NtClose(SockEvent);
1393 WSPCloseSocket( AcceptSocket, lpErrno );
1394 MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1395 return INVALID_SOCKET;
1396 }
1397
1398 AcceptSocketInfo = GetSocketStructure(AcceptSocket);
1399 if (!AcceptSocketInfo)
1400 {
1401 NtClose(SockEvent);
1402 WSPCloseSocket( AcceptSocket, lpErrno );
1403 MsafdReturnWithErrno( STATUS_PROTOCOL_NOT_SUPPORTED, lpErrno, 0, NULL );
1404 return INVALID_SOCKET;
1405 }
1406
1407 AcceptSocketInfo->SharedData.State = SocketConnected;
1408
1409 /* Return Address in SOCKADDR FORMAT */
1410 if( SocketAddress )
1411 {
1412 RtlCopyMemory (SocketAddress,
1413 &ListenReceiveData->Address.Address[0].AddressType,
1414 sizeof(*RemoteAddress));
1415 if( SocketAddressLength )
1416 *SocketAddressLength = ListenReceiveData->Address.Address[0].AddressLength;
1417 }
1418
1419 NtClose( SockEvent );
1420
1421 /* Re-enable Async Event */
1422 SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
1423
1424 TRACE("Socket %x\n", AcceptSocket);
1425
1426 if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_ACCEPT))
1427 {
1428 Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
1429 Socket->Handle,
1430 Socket->TdiAddressHandle,
1431 Socket->TdiConnectionHandle,
1432 WSH_NOTIFY_ACCEPT);
1433
1434 if (Status)
1435 {
1436 if (lpErrno) *lpErrno = Status;
1437 return INVALID_SOCKET;
1438 }
1439 }
1440
1441 *lpErrno = 0;
1442
1443 /* Return Socket */
1444 return AcceptSocket;
1445 }
1446
1447 int
1448 WSPAPI
1449 WSPConnect(SOCKET Handle,
1450 const struct sockaddr * SocketAddress,
1451 int SocketAddressLength,
1452 LPWSABUF lpCallerData,
1453 LPWSABUF lpCalleeData,
1454 LPQOS lpSQOS,
1455 LPQOS lpGQOS,
1456 LPINT lpErrno)
1457 {
1458 IO_STATUS_BLOCK IOSB;
1459 PAFD_CONNECT_INFO ConnectInfo = NULL;
1460 PSOCKET_INFORMATION Socket;
1461 NTSTATUS Status;
1462 INT Errno;
1463 ULONG ConnectDataLength;
1464 ULONG InConnectDataLength;
1465 INT BindAddressLength;
1466 PSOCKADDR BindAddress;
1467 HANDLE SockEvent;
1468 int SocketDataLength;
1469
1470 Status = NtCreateEvent(&SockEvent,
1471 EVENT_ALL_ACCESS,
1472 NULL,
1473 1,
1474 FALSE);
1475
1476 if (!NT_SUCCESS(Status))
1477 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
1478
1479 TRACE("Called\n");
1480
1481 /* Get the Socket Structure associate to this Socket*/
1482 Socket = GetSocketStructure(Handle);
1483 if (!Socket)
1484 {
1485 NtClose(SockEvent);
1486 if (lpErrno) *lpErrno = WSAENOTSOCK;
1487 return SOCKET_ERROR;
1488 }
1489
1490 /* Bind us First */
1491 if (Socket->SharedData.State == SocketOpen)
1492 {
1493 /* Get the Wildcard Address */
1494 BindAddressLength = Socket->HelperData->MaxWSAddressLength;
1495 BindAddress = HeapAlloc(GetProcessHeap(), 0, BindAddressLength);
1496 if (!BindAddress)
1497 {
1498 NtClose(SockEvent);
1499 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
1500 }
1501 Socket->HelperData->WSHGetWildcardSockaddr (Socket->HelperContext,
1502 BindAddress,
1503 &BindAddressLength);
1504 /* Bind it */
1505 if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR)
1506 return SOCKET_ERROR;
1507 }
1508
1509 /* Set the Connect Data */
1510 if (lpCallerData != NULL)
1511 {
1512 ConnectDataLength = lpCallerData->len;
1513 Status = NtDeviceIoControlFile((HANDLE)Handle,
1514 SockEvent,
1515 NULL,
1516 NULL,
1517 &IOSB,
1518 IOCTL_AFD_SET_CONNECT_DATA,
1519 lpCallerData->buf,
1520 ConnectDataLength,
1521 NULL,
1522 0);
1523 /* Wait for return */
1524 if (Status == STATUS_PENDING)
1525 {
1526 WaitForSingleObject(SockEvent, INFINITE);
1527 Status = IOSB.Status;
1528 }
1529
1530 if (Status != STATUS_SUCCESS)
1531 goto notify;
1532 }
1533
1534 /* Calculate the size of SocketAddress->sa_data */
1535 SocketDataLength = SocketAddressLength - FIELD_OFFSET(struct sockaddr, sa_data);
1536
1537 /* Allocate a connection info buffer with SocketDataLength bytes of payload */
1538 ConnectInfo = HeapAlloc(GetProcessHeap(), 0,
1539 FIELD_OFFSET(AFD_CONNECT_INFO,
1540 RemoteAddress.Address[0].Address[SocketDataLength]));
1541 if (!ConnectInfo)
1542 {
1543 Status = STATUS_INSUFFICIENT_RESOURCES;
1544 goto notify;
1545 }
1546
1547 /* Set up Address in TDI Format */
1548 ConnectInfo->RemoteAddress.TAAddressCount = 1;
1549 ConnectInfo->RemoteAddress.Address[0].AddressLength = SocketDataLength;
1550 ConnectInfo->RemoteAddress.Address[0].AddressType = SocketAddress->sa_family;
1551 RtlCopyMemory(ConnectInfo->RemoteAddress.Address[0].Address,
1552 SocketAddress->sa_data,
1553 SocketDataLength);
1554
1555 /*
1556 * Disable FD_WRITE and FD_CONNECT
1557 * The latter fixes a race condition where the FD_CONNECT is re-enabled
1558 * at the end of this function right after the Async Thread disables it.
1559 * This should only happen at the *next* WSPConnect
1560 */
1561 if (Socket->SharedData.AsyncEvents & FD_CONNECT)
1562 {
1563 Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE;
1564 }
1565
1566 /* Tell AFD that we want Connection Data back, have it allocate a buffer */
1567 if (lpCalleeData != NULL)
1568 {
1569 InConnectDataLength = lpCalleeData->len;
1570 Status = NtDeviceIoControlFile((HANDLE)Handle,
1571 SockEvent,
1572 NULL,
1573 NULL,
1574 &IOSB,
1575 IOCTL_AFD_SET_CONNECT_DATA_SIZE,
1576 &InConnectDataLength,
1577 sizeof(InConnectDataLength),
1578 NULL,
1579 0);
1580
1581 /* Wait for return */
1582 if (Status == STATUS_PENDING)
1583 {
1584 WaitForSingleObject(SockEvent, INFINITE);
1585 Status = IOSB.Status;
1586 }
1587
1588 if (Status != STATUS_SUCCESS)
1589 goto notify;
1590 }
1591
1592 /* AFD doesn't seem to care if these are invalid, but let's 0 them anyways */
1593 ConnectInfo->Root = 0;
1594 ConnectInfo->UseSAN = FALSE;
1595 ConnectInfo->Unknown = 0;
1596
1597 /* FIXME: Handle Async Connect */
1598 if (Socket->SharedData.NonBlocking)
1599 {
1600 ERR("Async Connect UNIMPLEMENTED!\n");
1601 }
1602
1603 /* Send IOCTL */
1604 Status = NtDeviceIoControlFile((HANDLE)Handle,
1605 SockEvent,
1606 NULL,
1607 NULL,
1608 &IOSB,
1609 IOCTL_AFD_CONNECT,
1610 ConnectInfo,
1611 0x22,
1612 NULL,
1613 0);
1614 /* Wait for return */
1615 if (Status == STATUS_PENDING)
1616 {
1617 WaitForSingleObject(SockEvent, INFINITE);
1618 Status = IOSB.Status;
1619 }
1620
1621 if (Status != STATUS_SUCCESS)
1622 goto notify;
1623
1624 Socket->SharedData.State = SocketConnected;
1625 Socket->TdiConnectionHandle = (HANDLE)IOSB.Information;
1626
1627 /* Get any pending connect data */
1628 if (lpCalleeData != NULL)
1629 {
1630 Status = NtDeviceIoControlFile((HANDLE)Handle,
1631 SockEvent,
1632 NULL,
1633 NULL,
1634 &IOSB,
1635 IOCTL_AFD_GET_CONNECT_DATA,
1636 NULL,
1637 0,
1638 lpCalleeData->buf,
1639 lpCalleeData->len);
1640 /* Wait for return */
1641 if (Status == STATUS_PENDING)
1642 {
1643 WaitForSingleObject(SockEvent, INFINITE);
1644 Status = IOSB.Status;
1645 }
1646 }
1647
1648 TRACE("Ending\n");
1649
1650 notify:
1651 if (ConnectInfo) HeapFree(GetProcessHeap(), 0, ConnectInfo);
1652
1653 /* Re-enable Async Event */
1654 SockReenableAsyncSelectEvent(Socket, FD_WRITE);
1655
1656 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
1657 SockReenableAsyncSelectEvent(Socket, FD_CONNECT);
1658
1659 NtClose(SockEvent);
1660
1661 if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT))
1662 {
1663 Errno = Socket->HelperData->WSHNotify(Socket->HelperContext,
1664 Socket->Handle,
1665 Socket->TdiAddressHandle,
1666 Socket->TdiConnectionHandle,
1667 WSH_NOTIFY_CONNECT);
1668
1669 if (Errno)
1670 {
1671 if (lpErrno) *lpErrno = Errno;
1672 return SOCKET_ERROR;
1673 }
1674 }
1675 else if (Status != STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR))
1676 {
1677 Errno = Socket->HelperData->WSHNotify(Socket->HelperContext,
1678 Socket->Handle,
1679 Socket->TdiAddressHandle,
1680 Socket->TdiConnectionHandle,
1681 WSH_NOTIFY_CONNECT_ERROR);
1682
1683 if (Errno)
1684 {
1685 if (lpErrno) *lpErrno = Errno;
1686 return SOCKET_ERROR;
1687 }
1688 }
1689
1690 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
1691 }
1692 int
1693 WSPAPI
1694 WSPShutdown(SOCKET Handle,
1695 int HowTo,
1696 LPINT lpErrno)
1697
1698 {
1699 IO_STATUS_BLOCK IOSB;
1700 AFD_DISCONNECT_INFO DisconnectInfo;
1701 PSOCKET_INFORMATION Socket = NULL;
1702 NTSTATUS Status;
1703 HANDLE SockEvent;
1704
1705 Status = NtCreateEvent(&SockEvent,
1706 EVENT_ALL_ACCESS,
1707 NULL,
1708 1,
1709 FALSE);
1710
1711 if( !NT_SUCCESS(Status) )
1712 return -1;
1713
1714 TRACE("Called\n");
1715
1716 /* Get the Socket Structure associate to this Socket*/
1717 Socket = GetSocketStructure(Handle);
1718 if (!Socket)
1719 {
1720 NtClose(SockEvent);
1721 *lpErrno = WSAENOTSOCK;
1722 return SOCKET_ERROR;
1723 }
1724
1725 /* Set AFD Disconnect Type */
1726 switch (HowTo)
1727 {
1728 case SD_RECEIVE:
1729 DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV;
1730 Socket->SharedData.ReceiveShutdown = TRUE;
1731 break;
1732 case SD_SEND:
1733 DisconnectInfo.DisconnectType= AFD_DISCONNECT_SEND;
1734 Socket->SharedData.SendShutdown = TRUE;
1735 break;
1736 case SD_BOTH:
1737 DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND;
1738 Socket->SharedData.ReceiveShutdown = TRUE;
1739 Socket->SharedData.SendShutdown = TRUE;
1740 break;
1741 }
1742
1743 DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1000000);
1744
1745 /* Send IOCTL */
1746 Status = NtDeviceIoControlFile((HANDLE)Handle,
1747 SockEvent,
1748 NULL,
1749 NULL,
1750 &IOSB,
1751 IOCTL_AFD_DISCONNECT,
1752 &DisconnectInfo,
1753 sizeof(DisconnectInfo),
1754 NULL,
1755 0);
1756
1757 /* Wait for return */
1758 if (Status == STATUS_PENDING)
1759 {
1760 WaitForSingleObject(SockEvent, INFINITE);
1761 Status = IOSB.Status;
1762 }
1763
1764 TRACE("Ending\n");
1765
1766 NtClose( SockEvent );
1767
1768 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1769 }
1770
1771
1772 INT
1773 WSPAPI
1774 WSPGetSockName(IN SOCKET Handle,
1775 OUT LPSOCKADDR Name,
1776 IN OUT LPINT NameLength,
1777 OUT LPINT lpErrno)
1778 {
1779 IO_STATUS_BLOCK IOSB;
1780 ULONG TdiAddressSize;
1781 PTDI_ADDRESS_INFO TdiAddress;
1782 PTRANSPORT_ADDRESS SocketAddress;
1783 PSOCKET_INFORMATION Socket = NULL;
1784 NTSTATUS Status;
1785 HANDLE SockEvent;
1786
1787 Status = NtCreateEvent(&SockEvent,
1788 EVENT_ALL_ACCESS,
1789 NULL,
1790 1,
1791 FALSE);
1792
1793 if( !NT_SUCCESS(Status) )
1794 return SOCKET_ERROR;
1795
1796 /* Get the Socket Structure associate to this Socket*/
1797 Socket = GetSocketStructure(Handle);
1798 if (!Socket)
1799 {
1800 NtClose(SockEvent);
1801 *lpErrno = WSAENOTSOCK;
1802 return SOCKET_ERROR;
1803 }
1804
1805 if (!Name || !NameLength)
1806 {
1807 NtClose(SockEvent);
1808 *lpErrno = WSAEFAULT;
1809 return SOCKET_ERROR;
1810 }
1811
1812 /* Allocate a buffer for the address */
1813 TdiAddressSize =
1814 sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfLocalAddress;
1815 TdiAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize);
1816
1817 if ( TdiAddress == NULL )
1818 {
1819 NtClose( SockEvent );
1820 *lpErrno = WSAENOBUFS;
1821 return SOCKET_ERROR;
1822 }
1823
1824 SocketAddress = &TdiAddress->Address;
1825
1826 /* Send IOCTL */
1827 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1828 SockEvent,
1829 NULL,
1830 NULL,
1831 &IOSB,
1832 IOCTL_AFD_GET_SOCK_NAME,
1833 NULL,
1834 0,
1835 TdiAddress,
1836 TdiAddressSize);
1837
1838 /* Wait for return */
1839 if (Status == STATUS_PENDING)
1840 {
1841 WaitForSingleObject(SockEvent, INFINITE);
1842 Status = IOSB.Status;
1843 }
1844
1845 NtClose( SockEvent );
1846
1847 if (NT_SUCCESS(Status))
1848 {
1849 if (*NameLength >= Socket->SharedData.SizeOfLocalAddress)
1850 {
1851 Name->sa_family = SocketAddress->Address[0].AddressType;
1852 RtlCopyMemory (Name->sa_data,
1853 SocketAddress->Address[0].Address,
1854 SocketAddress->Address[0].AddressLength);
1855 *NameLength = Socket->SharedData.SizeOfLocalAddress;
1856 TRACE("NameLength %d Address: %x Port %x\n",
1857 *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr,
1858 ((struct sockaddr_in *)Name)->sin_port);
1859 HeapFree(GlobalHeap, 0, TdiAddress);
1860 return 0;
1861 }
1862 else
1863 {
1864 HeapFree(GlobalHeap, 0, TdiAddress);
1865 *lpErrno = WSAEFAULT;
1866 return SOCKET_ERROR;
1867 }
1868 }
1869
1870 HeapFree(GlobalHeap, 0, TdiAddress);
1871
1872 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
1873 }
1874
1875
1876 INT
1877 WSPAPI
1878 WSPGetPeerName(IN SOCKET s,
1879 OUT LPSOCKADDR Name,
1880 IN OUT LPINT NameLength,
1881 OUT LPINT lpErrno)
1882 {
1883 IO_STATUS_BLOCK IOSB;
1884 ULONG TdiAddressSize;
1885 PTRANSPORT_ADDRESS SocketAddress;
1886 PSOCKET_INFORMATION Socket = NULL;
1887 NTSTATUS Status;
1888 HANDLE SockEvent;
1889
1890 Status = NtCreateEvent(&SockEvent,
1891 EVENT_ALL_ACCESS,
1892 NULL,
1893 1,
1894 FALSE);
1895
1896 if( !NT_SUCCESS(Status) )
1897 return SOCKET_ERROR;
1898
1899 /* Get the Socket Structure associate to this Socket*/
1900 Socket = GetSocketStructure(s);
1901 if (!Socket)
1902 {
1903 NtClose(SockEvent);
1904 *lpErrno = WSAENOTSOCK;
1905 return SOCKET_ERROR;
1906 }
1907
1908 if (Socket->SharedData.State != SocketConnected)
1909 {
1910 NtClose(SockEvent);
1911 *lpErrno = WSAENOTCONN;
1912 return SOCKET_ERROR;
1913 }
1914
1915 if (!Name || !NameLength)
1916 {
1917 NtClose(SockEvent);
1918 *lpErrno = WSAEFAULT;
1919 return SOCKET_ERROR;
1920 }
1921
1922 /* Allocate a buffer for the address */
1923 TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfRemoteAddress;
1924 SocketAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize);
1925
1926 if ( SocketAddress == NULL )
1927 {
1928 NtClose( SockEvent );
1929 *lpErrno = WSAENOBUFS;
1930 return SOCKET_ERROR;
1931 }
1932
1933 /* Send IOCTL */
1934 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1935 SockEvent,
1936 NULL,
1937 NULL,
1938 &IOSB,
1939 IOCTL_AFD_GET_PEER_NAME,
1940 NULL,
1941 0,
1942 SocketAddress,
1943 TdiAddressSize);
1944
1945 /* Wait for return */
1946 if (Status == STATUS_PENDING)
1947 {
1948 WaitForSingleObject(SockEvent, INFINITE);
1949 Status = IOSB.Status;
1950 }
1951
1952 NtClose( SockEvent );
1953
1954 if (NT_SUCCESS(Status))
1955 {
1956 if (*NameLength >= Socket->SharedData.SizeOfRemoteAddress)
1957 {
1958 Name->sa_family = SocketAddress->Address[0].AddressType;
1959 RtlCopyMemory (Name->sa_data,
1960 SocketAddress->Address[0].Address,
1961 SocketAddress->Address[0].AddressLength);
1962 *NameLength = Socket->SharedData.SizeOfRemoteAddress;
1963 TRACE("NameLength %d Address: %x Port %x\n",
1964 *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr,
1965 ((struct sockaddr_in *)Name)->sin_port);
1966 HeapFree(GlobalHeap, 0, SocketAddress);
1967 return 0;
1968 }
1969 else
1970 {
1971 HeapFree(GlobalHeap, 0, SocketAddress);
1972 *lpErrno = WSAEFAULT;
1973 return SOCKET_ERROR;
1974 }
1975 }
1976
1977 HeapFree(GlobalHeap, 0, SocketAddress);
1978
1979 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
1980 }
1981
1982 INT
1983 WSPAPI
1984 WSPIoctl(IN SOCKET Handle,
1985 IN DWORD dwIoControlCode,
1986 IN LPVOID lpvInBuffer,
1987 IN DWORD cbInBuffer,
1988 OUT LPVOID lpvOutBuffer,
1989 IN DWORD cbOutBuffer,
1990 OUT LPDWORD lpcbBytesReturned,
1991 IN LPWSAOVERLAPPED lpOverlapped,
1992 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
1993 IN LPWSATHREADID lpThreadId,
1994 OUT LPINT lpErrno)
1995 {
1996 PSOCKET_INFORMATION Socket = NULL;
1997 BOOLEAN NeedsCompletion;
1998 BOOLEAN NonBlocking;
1999
2000 if (!lpcbBytesReturned)
2001 {
2002 *lpErrno = WSAEFAULT;
2003 return SOCKET_ERROR;
2004 }
2005
2006 /* Get the Socket Structure associate to this Socket*/
2007 Socket = GetSocketStructure(Handle);
2008 if (!Socket)
2009 {
2010 *lpErrno = WSAENOTSOCK;
2011 return SOCKET_ERROR;
2012 }
2013
2014 *lpcbBytesReturned = 0;
2015
2016 switch( dwIoControlCode )
2017 {
2018 case FIONBIO:
2019 if( cbInBuffer < sizeof(INT) || IS_INTRESOURCE(lpvInBuffer) )
2020 {
2021 *lpErrno = WSAEFAULT;
2022 return SOCKET_ERROR;
2023 }
2024 NonBlocking = *((PULONG)lpvInBuffer) ? TRUE : FALSE;
2025 Socket->SharedData.NonBlocking = NonBlocking ? 1 : 0;
2026 *lpErrno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &NonBlocking, NULL, NULL);
2027 if (*lpErrno != NO_ERROR)
2028 return SOCKET_ERROR;
2029 else
2030 return NO_ERROR;
2031 case FIONREAD:
2032 if( cbOutBuffer < sizeof(INT) || IS_INTRESOURCE(lpvOutBuffer) )
2033 {
2034 *lpErrno = WSAEFAULT;
2035 return SOCKET_ERROR;
2036 }
2037 *lpErrno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, NULL, (PULONG)lpvOutBuffer, NULL);
2038 if (*lpErrno != NO_ERROR)
2039 return SOCKET_ERROR;
2040 else
2041 {
2042 *lpcbBytesReturned = sizeof(ULONG);
2043 return NO_ERROR;
2044 }
2045 case SIOCATMARK:
2046 if (cbOutBuffer < sizeof(BOOL) || IS_INTRESOURCE(lpvOutBuffer))
2047 {
2048 *lpErrno = WSAEFAULT;
2049 return SOCKET_ERROR;
2050 }
2051
2052 /* FIXME: Return false for now */
2053 *(BOOL*)lpvOutBuffer = FALSE;
2054
2055 *lpcbBytesReturned = sizeof(BOOL);
2056 *lpErrno = NO_ERROR;
2057 return NO_ERROR;
2058 case SIO_GET_EXTENSION_FUNCTION_POINTER:
2059 *lpErrno = WSAEINVAL;
2060 return SOCKET_ERROR;
2061
2062 case SIO_ADDRESS_LIST_QUERY:
2063 if (cbOutBuffer < (sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->WSLocalAddress)) || IS_INTRESOURCE(lpvOutBuffer))
2064 {
2065 *lpErrno = WSAEINVAL;
2066 return SOCKET_ERROR;
2067 }
2068
2069 *lpcbBytesReturned = sizeof(SOCKET_ADDRESS_LIST) +
2070 sizeof(Socket->WSLocalAddress);
2071
2072 ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->iAddressCount = 1;
2073 ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].iSockaddrLength = sizeof(Socket->WSLocalAddress);
2074 ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].lpSockaddr = &Socket->WSLocalAddress;
2075
2076 *lpErrno = NO_ERROR;
2077 return NO_ERROR;
2078
2079 default:
2080 *lpErrno = Socket->HelperData->WSHIoctl(Socket->HelperContext,
2081 Handle,
2082 Socket->TdiAddressHandle,
2083 Socket->TdiConnectionHandle,
2084 dwIoControlCode,
2085 lpvInBuffer,
2086 cbInBuffer,
2087 lpvOutBuffer,
2088 cbOutBuffer,
2089 lpcbBytesReturned,
2090 lpOverlapped,
2091 lpCompletionRoutine,
2092 (LPBOOL)&NeedsCompletion);
2093
2094 if (*lpErrno != NO_ERROR)
2095 return SOCKET_ERROR;
2096 else
2097 return NO_ERROR;
2098 }
2099 }
2100
2101
2102 INT
2103 WSPAPI
2104 WSPGetSockOpt(IN SOCKET Handle,
2105 IN INT Level,
2106 IN INT OptionName,
2107 OUT CHAR FAR* OptionValue,
2108 IN OUT LPINT OptionLength,
2109 OUT LPINT lpErrno)
2110 {
2111 PSOCKET_INFORMATION Socket = NULL;
2112 PVOID Buffer;
2113 INT BufferSize;
2114 BOOL BoolBuffer;
2115 INT IntBuffer;
2116
2117 /* Get the Socket Structure associate to this Socket*/
2118 Socket = GetSocketStructure(Handle);
2119 if (Socket == NULL)
2120 {
2121 *lpErrno = WSAENOTSOCK;
2122 return SOCKET_ERROR;
2123 }
2124
2125 TRACE("Called\n");
2126
2127 switch (Level)
2128 {
2129 case SOL_SOCKET:
2130 switch (OptionName)
2131 {
2132 case SO_TYPE:
2133 Buffer = &Socket->SharedData.SocketType;
2134 BufferSize = sizeof(INT);
2135 break;
2136
2137 case SO_RCVBUF:
2138 Buffer = &Socket->SharedData.SizeOfRecvBuffer;
2139 BufferSize = sizeof(INT);
2140 break;
2141
2142 case SO_SNDBUF:
2143 Buffer = &Socket->SharedData.SizeOfSendBuffer;
2144 BufferSize = sizeof(INT);
2145 break;
2146
2147 case SO_ACCEPTCONN:
2148 BoolBuffer = Socket->SharedData.Listening;
2149 Buffer = &BoolBuffer;
2150 BufferSize = sizeof(BOOL);
2151 break;
2152
2153 case SO_BROADCAST:
2154 BoolBuffer = Socket->SharedData.Broadcast;
2155 Buffer = &BoolBuffer;
2156 BufferSize = sizeof(BOOL);
2157 break;
2158
2159 case SO_DEBUG:
2160 BoolBuffer = Socket->SharedData.Debug;
2161 Buffer = &BoolBuffer;
2162 BufferSize = sizeof(BOOL);
2163 break;
2164
2165 case SO_DONTLINGER:
2166 BoolBuffer = (Socket->SharedData.LingerData.l_onoff == 0);
2167 Buffer = &BoolBuffer;
2168 BufferSize = sizeof(BOOL);
2169 break;
2170
2171 case SO_LINGER:
2172 if (Socket->SharedData.SocketType == SOCK_DGRAM)
2173 {
2174 *lpErrno = WSAENOPROTOOPT;
2175 return SOCKET_ERROR;
2176 }
2177 Buffer = &Socket->SharedData.LingerData;
2178 BufferSize = sizeof(struct linger);
2179 break;
2180
2181 case SO_OOBINLINE:
2182 BoolBuffer = (Socket->SharedData.OobInline != 0);
2183 Buffer = &BoolBuffer;
2184 BufferSize = sizeof(BOOL);
2185 break;
2186
2187 case SO_KEEPALIVE:
2188 case SO_DONTROUTE:
2189 /* These guys go directly to the helper */
2190 goto SendToHelper;
2191
2192 case SO_CONDITIONAL_ACCEPT:
2193 BoolBuffer = (Socket->SharedData.UseDelayedAcceptance != 0);
2194 Buffer = &BoolBuffer;
2195 BufferSize = sizeof(BOOL);
2196 break;
2197
2198 case SO_REUSEADDR:
2199 BoolBuffer = (Socket->SharedData.ReuseAddresses != 0);
2200 Buffer = &BoolBuffer;
2201 BufferSize = sizeof(BOOL);
2202 break;
2203
2204 case SO_EXCLUSIVEADDRUSE:
2205 BoolBuffer = (Socket->SharedData.ExclusiveAddressUse != 0);
2206 Buffer = &BoolBuffer;
2207 BufferSize = sizeof(BOOL);
2208 break;
2209
2210 case SO_ERROR:
2211 /* HACK: This needs to be properly tracked */
2212 IntBuffer = 0;
2213 DbgPrint("MSAFD: Hacked SO_ERROR returning error %d\n", IntBuffer);
2214
2215 Buffer = &IntBuffer;
2216 BufferSize = sizeof(INT);
2217 break;
2218 case SO_SNDTIMEO:
2219 Buffer = &Socket->SharedData.SendTimeout;
2220 BufferSize = sizeof(DWORD);
2221 break;
2222 case SO_RCVTIMEO:
2223 Buffer = &Socket->SharedData.RecvTimeout;
2224 BufferSize = sizeof(DWORD);
2225 break;
2226 case SO_PROTOCOL_INFOW:
2227 Buffer = &Socket->ProtocolInfo;
2228 BufferSize = sizeof(Socket->ProtocolInfo);
2229 break;
2230
2231 case SO_GROUP_ID:
2232 case SO_GROUP_PRIORITY:
2233 case SO_MAX_MSG_SIZE:
2234
2235 default:
2236 DbgPrint("MSAFD: Get unknown optname %x\n", OptionName);
2237 *lpErrno = WSAENOPROTOOPT;
2238 return SOCKET_ERROR;
2239 }
2240
2241 if (*OptionLength < BufferSize)
2242 {
2243 *lpErrno = WSAEFAULT;
2244 *OptionLength = BufferSize;
2245 return SOCKET_ERROR;
2246 }
2247 RtlCopyMemory(OptionValue, Buffer, BufferSize);
2248
2249 return 0;
2250
2251 default:
2252 *lpErrno = WSAEINVAL;
2253 return SOCKET_ERROR;
2254 }
2255
2256 SendToHelper:
2257 *lpErrno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
2258 Handle,
2259 Socket->TdiAddressHandle,
2260 Socket->TdiConnectionHandle,
2261 Level,
2262 OptionName,
2263 OptionValue,
2264 (LPINT)OptionLength);
2265 return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
2266 }
2267
2268 INT
2269 WSPAPI
2270 WSPSetSockOpt(
2271 IN SOCKET s,
2272 IN INT level,
2273 IN INT optname,
2274 IN CONST CHAR FAR* optval,
2275 IN INT optlen,
2276 OUT LPINT lpErrno)
2277 {
2278 PSOCKET_INFORMATION Socket;
2279
2280 /* Get the Socket Structure associate to this Socket*/
2281 Socket = GetSocketStructure(s);
2282 if (Socket == NULL)
2283 {
2284 *lpErrno = WSAENOTSOCK;
2285 return SOCKET_ERROR;
2286 }
2287
2288
2289 /* FIXME: We should handle some more cases here */
2290 if (level == SOL_SOCKET)
2291 {
2292 switch (optname)
2293 {
2294 case SO_BROADCAST:
2295 if (optlen < sizeof(BOOL))
2296 {
2297 *lpErrno = WSAEFAULT;
2298 return SOCKET_ERROR;
2299 }
2300 Socket->SharedData.Broadcast = (*optval != 0) ? 1 : 0;
2301 return 0;
2302
2303 case SO_DONTLINGER:
2304 if (optlen < sizeof(BOOL))
2305 {
2306 *lpErrno = WSAEFAULT;
2307 return SOCKET_ERROR;
2308 }
2309 Socket->SharedData.LingerData.l_onoff = (*optval != 0) ? 0 : 1;
2310 return 0;
2311
2312 case SO_REUSEADDR:
2313 if (optlen < sizeof(BOOL))
2314 {
2315 *lpErrno = WSAEFAULT;
2316 return SOCKET_ERROR;
2317 }
2318 Socket->SharedData.ReuseAddresses = (*optval != 0) ? 1 : 0;
2319 return 0;
2320
2321 case SO_EXCLUSIVEADDRUSE:
2322 if (optlen < sizeof(BOOL))
2323 {
2324 *lpErrno = WSAEFAULT;
2325 return SOCKET_ERROR;
2326 }
2327 Socket->SharedData.ExclusiveAddressUse = (*optval != 0) ? 1 : 0;
2328 return 0;
2329
2330 case SO_LINGER:
2331 if (optlen < sizeof(struct linger))
2332 {
2333 *lpErrno = WSAEFAULT;
2334 return SOCKET_ERROR;
2335 }
2336 RtlCopyMemory(&Socket->SharedData.LingerData,
2337 optval,
2338 sizeof(struct linger));
2339 return 0;
2340
2341 case SO_SNDBUF:
2342 if (optlen < sizeof(DWORD))
2343 {
2344 *lpErrno = WSAEFAULT;
2345 return SOCKET_ERROR;
2346 }
2347
2348 /* TODO: The total per-socket buffer space reserved for sends */
2349 ERR("Setting send buf to %x is not implemented yet\n", optval);
2350 return 0;
2351
2352 case SO_SNDTIMEO:
2353 if (optlen < sizeof(DWORD))
2354 {
2355 *lpErrno = WSAEFAULT;
2356 return SOCKET_ERROR;
2357 }
2358
2359 RtlCopyMemory(&Socket->SharedData.SendTimeout,
2360 optval,
2361 sizeof(DWORD));
2362 return 0;
2363
2364 case SO_RCVTIMEO:
2365 if (optlen < sizeof(DWORD))
2366 {
2367 *lpErrno = WSAEFAULT;
2368 return SOCKET_ERROR;
2369 }
2370
2371 RtlCopyMemory(&Socket->SharedData.RecvTimeout,
2372 optval,
2373 sizeof(DWORD));
2374 return 0;
2375
2376 case SO_KEEPALIVE:
2377 case SO_DONTROUTE:
2378 /* These go directly to the helper dll */
2379 goto SendToHelper;
2380
2381 default:
2382 /* Obviously this is a hack */
2383 ERR("MSAFD: Set unknown optname %x\n", optname);
2384 return 0;
2385 }
2386 }
2387
2388 SendToHelper:
2389 *lpErrno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext,
2390 s,
2391 Socket->TdiAddressHandle,
2392 Socket->TdiConnectionHandle,
2393 level,
2394 optname,
2395 (PCHAR)optval,
2396 optlen);
2397 return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
2398 }
2399
2400 /*
2401 * FUNCTION: Initialize service provider for a client
2402 * ARGUMENTS:
2403 * wVersionRequested = Highest WinSock SPI version that the caller can use
2404 * lpWSPData = Address of WSPDATA structure to initialize
2405 * lpProtocolInfo = Pointer to structure that defines the desired protocol
2406 * UpcallTable = Pointer to upcall table of the WinSock DLL
2407 * lpProcTable = Address of procedure table to initialize
2408 * RETURNS:
2409 * Status of operation
2410 */
2411 INT
2412 WSPAPI
2413 WSPStartup(IN WORD wVersionRequested,
2414 OUT LPWSPDATA lpWSPData,
2415 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
2416 IN WSPUPCALLTABLE UpcallTable,
2417 OUT LPWSPPROC_TABLE lpProcTable)
2418
2419 {
2420 NTSTATUS Status;
2421
2422 if (((LOBYTE(wVersionRequested) == 2) && (HIBYTE(wVersionRequested) < 2)) ||
2423 (LOBYTE(wVersionRequested) < 2))
2424 {
2425 ERR("WSPStartup NOT SUPPORTED for version 0x%X\n", wVersionRequested);
2426 return WSAVERNOTSUPPORTED;
2427 }
2428 else
2429 Status = NO_ERROR;
2430 /* FIXME: Enable all cases of WSPStartup status */
2431 Upcalls = UpcallTable;
2432
2433 if (Status == NO_ERROR)
2434 {
2435 lpProcTable->lpWSPAccept = WSPAccept;
2436 lpProcTable->lpWSPAddressToString = WSPAddressToString;
2437 lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
2438 lpProcTable->lpWSPBind = WSPBind;
2439 lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
2440 lpProcTable->lpWSPCleanup = WSPCleanup;
2441 lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
2442 lpProcTable->lpWSPConnect = WSPConnect;
2443 lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
2444 lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
2445 lpProcTable->lpWSPEventSelect = WSPEventSelect;
2446 lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
2447 lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
2448 lpProcTable->lpWSPGetSockName = WSPGetSockName;
2449 lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
2450 lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
2451 lpProcTable->lpWSPIoctl = WSPIoctl;
2452 lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
2453 lpProcTable->lpWSPListen = WSPListen;
2454 lpProcTable->lpWSPRecv = WSPRecv;
2455 lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
2456 lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
2457 lpProcTable->lpWSPSelect = WSPSelect;
2458 lpProcTable->lpWSPSend = WSPSend;
2459 lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
2460 lpProcTable->lpWSPSendTo = WSPSendTo;
2461 lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
2462 lpProcTable->lpWSPShutdown = WSPShutdown;
2463 lpProcTable->lpWSPSocket = WSPSocket;
2464 lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
2465 lpWSPData->wVersion = MAKEWORD(2, 2);
2466 lpWSPData->wHighVersion = MAKEWORD(2, 2);
2467 /* Save CatalogEntryId for all upcalls */
2468 CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
2469 }
2470
2471 TRACE("Status (%d).\n", Status);
2472 return Status;
2473 }
2474
2475
2476 INT
2477 WSPAPI
2478 WSPAddressToString(IN LPSOCKADDR lpsaAddress,
2479 IN DWORD dwAddressLength,
2480 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
2481 OUT LPWSTR lpszAddressString,
2482 IN OUT LPDWORD lpdwAddressStringLength,
2483 OUT LPINT lpErrno)
2484 {
2485 DWORD size;
2486 WCHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
2487 WCHAR *p;
2488
2489 if (!lpsaAddress || !lpszAddressString || !lpdwAddressStringLength)
2490 {
2491 *lpErrno = WSAEFAULT;
2492 return SOCKET_ERROR;
2493 }
2494
2495 switch (lpsaAddress->sa_family)
2496 {
2497 case AF_INET:
2498 if (dwAddressLength < sizeof(SOCKADDR_IN))
2499 {
2500 *lpErrno = WSAEINVAL;
2501 return SOCKET_ERROR;
2502 }
2503 swprintf(buffer,
2504 L"%u.%u.%u.%u:%u",
2505 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 24 & 0xff),
2506 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 16 & 0xff),
2507 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 8 & 0xff),
2508 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) & 0xff),
2509 ntohs(((SOCKADDR_IN *)lpsaAddress)->sin_port));
2510
2511 p = wcschr(buffer, L':');
2512 if (!((SOCKADDR_IN *)lpsaAddress)->sin_port)
2513 {
2514 *p = 0;
2515 }
2516 break;
2517 default:
2518 *lpErrno = WSAEINVAL;
2519 return SOCKET_ERROR;
2520 }
2521
2522 size = wcslen(buffer) + 1;
2523
2524 if (*lpdwAddressStringLength < size)
2525 {
2526 *lpdwAddressStringLength = size;
2527 *lpErrno = WSAENOBUFS;
2528 return SOCKET_ERROR;
2529 }
2530
2531 *lpdwAddressStringLength = size;
2532 wcscpy(lpszAddressString, buffer);
2533 return 0;
2534 }
2535
2536 INT
2537 WSPAPI
2538 WSPStringToAddress(IN LPWSTR AddressString,
2539 IN INT AddressFamily,
2540 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
2541 OUT LPSOCKADDR lpAddress,
2542 IN OUT LPINT lpAddressLength,
2543 OUT LPINT lpErrno)
2544 {
2545 int pos = 0;
2546 LONG inetaddr = 0;
2547 LPWSTR *bp = NULL;
2548 SOCKADDR_IN *sockaddr;
2549
2550 if (!lpAddressLength || !lpAddress || !AddressString)
2551 {
2552 *lpErrno = WSAEINVAL;
2553 return SOCKET_ERROR;
2554 }
2555
2556 sockaddr = (SOCKADDR_IN *)lpAddress;
2557
2558 /* Set right address family */
2559 if (lpProtocolInfo != NULL)
2560 {
2561 sockaddr->sin_family = lpProtocolInfo->iAddressFamily;
2562 }
2563 else
2564 {
2565 sockaddr->sin_family = AddressFamily;
2566 }
2567
2568 /* Report size */
2569 if (AddressFamily == AF_INET)
2570 {
2571 if (*lpAddressLength < (INT)sizeof(SOCKADDR_IN))
2572 {
2573 *lpAddressLength = sizeof(SOCKADDR_IN);
2574 *lpErrno = WSAEFAULT;
2575 }
2576 else
2577 {
2578 // translate ip string to ip
2579
2580 /* rest sockaddr.sin_addr.s_addr
2581 for we need to be sure it is zero when we come to while */
2582 memset(lpAddress, 0, sizeof(SOCKADDR_IN));
2583
2584 /* Set right adress family */
2585 sockaddr->sin_family = AF_INET;
2586
2587 /* Get port number */
2588 pos = wcscspn(AddressString, L":") + 1;
2589
2590 if (pos < (int)wcslen(AddressString))
2591 {
2592 sockaddr->sin_port = wcstol(&AddressString[pos], bp, 10);
2593 }
2594 else
2595 {
2596 sockaddr->sin_port = 0;
2597 }
2598
2599 /* Get ip number */
2600 pos = 0;
2601 inetaddr = 0;
2602
2603 while (pos < (int)wcslen(AddressString))
2604 {
2605 inetaddr = (inetaddr << 8) +
2606 ((UCHAR)wcstol(&AddressString[pos], bp, 10));
2607
2608 pos += wcscspn(&AddressString[pos], L".") + 1;
2609 }
2610
2611 *lpErrno = 0;
2612 sockaddr->sin_addr.s_addr = inetaddr;
2613
2614 }
2615 }
2616
2617 if (!*lpErrno)
2618 {
2619 return 0;
2620 }
2621
2622 return SOCKET_ERROR;
2623 }
2624
2625 /*
2626 * FUNCTION: Cleans up service provider for a client
2627 * ARGUMENTS:
2628 * lpErrno = Address of buffer for error information
2629 * RETURNS:
2630 * 0 if successful, or SOCKET_ERROR if not
2631 */
2632 INT
2633 WSPAPI
2634 WSPCleanup(OUT LPINT lpErrno)
2635
2636 {
2637 TRACE("Leaving.\n");
2638 *lpErrno = NO_ERROR;
2639
2640 return 0;
2641 }
2642
2643
2644
2645 int
2646 GetSocketInformation(PSOCKET_INFORMATION Socket,
2647 ULONG AfdInformationClass,
2648 PBOOLEAN Boolean OPTIONAL,
2649 PULONG Ulong OPTIONAL,
2650 PLARGE_INTEGER LargeInteger OPTIONAL)
2651 {
2652 IO_STATUS_BLOCK IOSB;
2653 AFD_INFO InfoData;
2654 NTSTATUS Status;
2655 HANDLE SockEvent;
2656
2657 Status = NtCreateEvent(&SockEvent,
2658 EVENT_ALL_ACCESS,
2659 NULL,
2660 1,
2661 FALSE);
2662
2663 if( !NT_SUCCESS(Status) )
2664 return -1;
2665
2666 /* Set Info Class */
2667 InfoData.InformationClass = AfdInformationClass;
2668
2669 /* Send IOCTL */
2670 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2671 SockEvent,
2672 NULL,
2673 NULL,
2674 &IOSB,
2675 IOCTL_AFD_GET_INFO,
2676 &InfoData,
2677 sizeof(InfoData),
2678 &InfoData,
2679 sizeof(InfoData));
2680
2681 /* Wait for return */
2682 if (Status == STATUS_PENDING)
2683 {
2684 WaitForSingleObject(SockEvent, INFINITE);
2685 Status = IOSB.Status;
2686 }
2687
2688 if (Status != STATUS_SUCCESS)
2689 return -1;
2690
2691 /* Return Information */
2692 if (Ulong != NULL)
2693 {
2694 *Ulong = InfoData.Information.Ulong;
2695 }
2696 if (LargeInteger != NULL)
2697 {
2698 *LargeInteger = InfoData.Information.LargeInteger;
2699 }
2700 if (Boolean != NULL)
2701 {
2702 *Boolean = InfoData.Information.Boolean;
2703 }
2704
2705 NtClose( SockEvent );
2706
2707 return 0;
2708
2709 }
2710
2711
2712 int
2713 SetSocketInformation(PSOCKET_INFORMATION Socket,
2714 ULONG AfdInformationClass,
2715 PBOOLEAN Boolean OPTIONAL,
2716 PULONG Ulong OPTIONAL,
2717 PLARGE_INTEGER LargeInteger OPTIONAL)
2718 {
2719 IO_STATUS_BLOCK IOSB;
2720 AFD_INFO InfoData;
2721 NTSTATUS Status;
2722 HANDLE SockEvent;
2723
2724 Status = NtCreateEvent(&SockEvent,
2725 EVENT_ALL_ACCESS,
2726 NULL,
2727 1,
2728 FALSE);
2729
2730 if( !NT_SUCCESS(Status) )
2731 return -1;
2732
2733 /* Set Info Class */
2734 InfoData.InformationClass = AfdInformationClass;
2735
2736 /* Set Information */
2737 if (Ulong != NULL)
2738 {
2739 InfoData.Information.Ulong = *Ulong;
2740 }
2741 if (LargeInteger != NULL)
2742 {
2743 InfoData.Information.LargeInteger = *LargeInteger;
2744 }
2745 if (Boolean != NULL)
2746 {
2747 InfoData.Information.Boolean = *Boolean;
2748 }
2749
2750 /* Send IOCTL */
2751 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2752 SockEvent,
2753 NULL,
2754 NULL,
2755 &IOSB,
2756 IOCTL_AFD_SET_INFO,
2757 &InfoData,
2758 sizeof(InfoData),
2759 NULL,
2760 0);
2761
2762 /* Wait for return */
2763 if (Status == STATUS_PENDING)
2764 {
2765 WaitForSingleObject(SockEvent, INFINITE);
2766 Status = IOSB.Status;
2767 }
2768
2769 NtClose( SockEvent );
2770
2771 return Status == STATUS_SUCCESS ? 0 : -1;
2772
2773 }
2774
2775 PSOCKET_INFORMATION
2776 GetSocketStructure(SOCKET Handle)
2777 {
2778 PSOCKET_INFORMATION CurrentSocket;
2779
2780 EnterCriticalSection(&SocketListLock);
2781
2782 CurrentSocket = SocketListHead;
2783 while (CurrentSocket)
2784 {
2785 if (CurrentSocket->Handle == Handle)
2786 {
2787 LeaveCriticalSection(&SocketListLock);
2788 return CurrentSocket;
2789 }
2790
2791 CurrentSocket = CurrentSocket->NextSocket;
2792 }
2793
2794 LeaveCriticalSection(&SocketListLock);
2795
2796 return NULL;
2797 }
2798
2799 int CreateContext(PSOCKET_INFORMATION Socket)
2800 {
2801 IO_STATUS_BLOCK IOSB;
2802 SOCKET_CONTEXT ContextData;
2803 NTSTATUS Status;
2804 HANDLE SockEvent;
2805
2806 Status = NtCreateEvent(&SockEvent,
2807 EVENT_ALL_ACCESS,
2808 NULL,
2809 1,
2810 FALSE);
2811
2812 if( !NT_SUCCESS(Status) )
2813 return -1;
2814
2815 /* Create Context */
2816 ContextData.SharedData = Socket->SharedData;
2817 ContextData.SizeOfHelperData = 0;
2818 RtlCopyMemory (&ContextData.LocalAddress,
2819 Socket->LocalAddress,
2820 Socket->SharedData.SizeOfLocalAddress);
2821 RtlCopyMemory (&ContextData.RemoteAddress,
2822 Socket->RemoteAddress,
2823 Socket->SharedData.SizeOfRemoteAddress);
2824
2825 /* Send IOCTL */
2826 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2827 SockEvent,
2828 NULL,
2829 NULL,
2830 &IOSB,
2831 IOCTL_AFD_SET_CONTEXT,
2832 &ContextData,
2833 sizeof(ContextData),
2834 NULL,
2835 0);
2836
2837 /* Wait for Completition */
2838 if (Status == STATUS_PENDING)
2839 {
2840 WaitForSingleObject(SockEvent, INFINITE);
2841 Status = IOSB.Status;
2842 }
2843
2844 NtClose( SockEvent );
2845
2846 return Status == STATUS_SUCCESS ? 0 : -1;
2847 }
2848
2849 BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
2850 {
2851 HANDLE hAsyncThread;
2852 DWORD AsyncThreadId;
2853 HANDLE AsyncEvent;
2854 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
2855 NTSTATUS Status;
2856
2857 /* Check if the Thread Already Exists */
2858 if (SockAsyncThreadRefCount)
2859 {
2860 ASSERT(SockAsyncCompletionPort);
2861 return TRUE;
2862 }
2863
2864 /* Create the Completion Port */
2865 if (!SockAsyncCompletionPort)
2866 {
2867 Status = NtCreateIoCompletion(&SockAsyncCompletionPort,
2868 IO_COMPLETION_ALL_ACCESS,
2869 NULL,
2870 2); // Allow 2 threads only
2871 if (!NT_SUCCESS(Status))
2872 {
2873 ERR("Failed to create completion port: 0x%08x\n", Status);
2874 return FALSE;
2875 }
2876 /* Protect Handle */
2877 HandleFlags.ProtectFromClose = TRUE;
2878 HandleFlags.Inherit = FALSE;
2879 Status = NtSetInformationObject(SockAsyncCompletionPort,
2880 ObjectHandleFlagInformation,
2881 &HandleFlags,
2882 sizeof(HandleFlags));
2883 }
2884
2885 /* Create the Async Event */
2886 Status = NtCreateEvent(&AsyncEvent,
2887 EVENT_ALL_ACCESS,
2888 NULL,
2889 NotificationEvent,
2890 FALSE);
2891
2892 /* Create the Async Thread */
2893 hAsyncThread = CreateThread(NULL,
2894 0,
2895 (LPTHREAD_START_ROUTINE)SockAsyncThread,
2896 NULL,
2897 0,
2898 &AsyncThreadId);
2899
2900 /* Close the Handle */
2901 NtClose(hAsyncThread);
2902
2903 /* Increase the Reference Count */
2904 SockAsyncThreadRefCount++;
2905 return TRUE;
2906 }
2907
2908 int SockAsyncThread(PVOID ThreadParam)
2909 {
2910 PVOID AsyncContext;
2911 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
2912 IO_STATUS_BLOCK IOSB;
2913 NTSTATUS Status;
2914
2915 /* Make the Thread Higher Priority */
2916 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
2917
2918 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
2919 do
2920 {
2921 Status = NtRemoveIoCompletion (SockAsyncCompletionPort,
2922 (PVOID*)&AsyncCompletionRoutine,
2923 &AsyncContext,
2924 &IOSB,
2925 NULL);
2926 /* Call the Async Function */
2927 if (NT_SUCCESS(Status))
2928 {
2929 (*AsyncCompletionRoutine)(AsyncContext, &IOSB);
2930 }
2931 else
2932 {
2933 /* It Failed, sleep for a second */
2934 Sleep(1000);
2935 }
2936 } while ((Status != STATUS_TIMEOUT));
2937
2938 /* The Thread has Ended */
2939 return 0;
2940 }
2941
2942 BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
2943 {
2944 UNICODE_STRING AfdHelper;
2945 OBJECT_ATTRIBUTES ObjectAttributes;
2946 IO_STATUS_BLOCK IoSb;
2947 FILE_COMPLETION_INFORMATION CompletionInfo;
2948 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
2949
2950 /* First, make sure we're not already intialized */
2951 if (SockAsyncHelperAfdHandle)
2952 {
2953 return TRUE;
2954 }
2955
2956 /* Set up Handle Name and Object */
2957 RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" );
2958 InitializeObjectAttributes(&ObjectAttributes,
2959 &AfdHelper,
2960 OBJ_INHERIT | OBJ_CASE_INSENSITIVE,
2961 NULL,
2962 NULL);
2963
2964 /* Open the Handle to AFD */
2965 NtCreateFile(&SockAsyncHelperAfdHandle,
2966 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
2967 &ObjectAttributes,
2968 &IoSb,
2969 NULL,
2970 0,
2971 FILE_SHARE_READ | FILE_SHARE_WRITE,
2972 FILE_OPEN_IF,
2973 0,
2974 NULL,
2975 0);
2976
2977 /*
2978 * Now Set up the Completion Port Information
2979 * This means that whenever a Poll is finished, the routine will be executed
2980 */
2981 CompletionInfo.Port = SockAsyncCompletionPort;
2982 CompletionInfo.Key = SockAsyncSelectCompletionRoutine;
2983 NtSetInformationFile(SockAsyncHelperAfdHandle,
2984 &IoSb,
2985 &CompletionInfo,
2986 sizeof(CompletionInfo),
2987 FileCompletionInformation);
2988
2989
2990 /* Protect the Handle */
2991 HandleFlags.ProtectFromClose = TRUE;
2992 HandleFlags.Inherit = FALSE;
2993 NtSetInformationObject(SockAsyncCompletionPort,
2994 ObjectHandleFlagInformation,
2995 &HandleFlags,
2996 sizeof(HandleFlags));
2997
2998
2999 /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
3000 SockAsyncSelectCalled = TRUE;
3001 return TRUE;
3002 }
3003
3004 VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
3005 {
3006
3007 PASYNC_DATA AsyncData = Context;
3008 PSOCKET_INFORMATION Socket;
3009 ULONG x;
3010
3011 /* Get the Socket */
3012 Socket = AsyncData->ParentSocket;
3013
3014 /* Check if the Sequence Number Changed behind our back */
3015 if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber )
3016 {
3017 return;
3018 }
3019
3020 /* Check we were manually called b/c of a failure */
3021 if (!NT_SUCCESS(IoStatusBlock->Status))
3022 {
3023 /* FIXME: Perform Upcall */
3024 return;
3025 }
3026
3027 for (x = 1; x; x<<=1)
3028 {
3029 switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x)
3030 {
3031 case AFD_EVENT_RECEIVE:
3032 if (0 != (Socket->SharedData.AsyncEvents & FD_READ) &&
3033 0 == (Socket->SharedData.AsyncDisabledEvents & FD_READ))
3034 {
3035 /* Make the Notifcation */
3036 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
3037 Socket->SharedData.wMsg,
3038 Socket->Handle,
3039 WSAMAKESELECTREPLY(FD_READ, 0));
3040 /* Disable this event until the next read(); */
3041 Socket->SharedData.AsyncDisabledEvents |= FD_READ;
3042 }
3043 break;
3044
3045 case AFD_EVENT_OOB_RECEIVE:
3046 if (0 != (Socket->SharedData.AsyncEvents & FD_OOB) &&
3047 0 == (Socket->SharedData.AsyncDisabledEvents & FD_OOB))
3048 {
3049 /* Make the Notifcation */
3050 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
3051 Socket->SharedData.wMsg,
3052 Socket->Handle,
3053 WSAMAKESELECTREPLY(FD_OOB, 0));
3054 /* Disable this event until the next read(); */
3055 Socket->SharedData.AsyncDisabledEvents |= FD_OOB;
3056 }
3057 break;
3058
3059 case AFD_EVENT_SEND:
3060 if (0 != (Socket->SharedData.AsyncEvents & FD_WRITE) &&
3061 0 == (Socket->SharedData.AsyncDisabledEvents & FD_WRITE))
3062 {
3063 /* Make the Notifcation */
3064 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
3065 Socket->SharedData.wMsg,
3066 Socket->Handle,
3067 WSAMAKESELECTREPLY(FD_WRITE, 0));
3068 /* Disable this event until the next write(); */
3069 Socket->SharedData.AsyncDisabledEvents |= FD_WRITE;
3070 }
3071 break;
3072
3073 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
3074 case AFD_EVENT_CONNECT:
3075 case AFD_EVENT_CONNECT_FAIL:
3076 if (0 != (Socket->SharedData.AsyncEvents & FD_CONNECT) &&
3077 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CONNECT))
3078 {
3079 /* Make the Notifcation */
3080 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
3081 Socket->SharedData.wMsg,
3082 Socket->Handle,
3083 WSAMAKESELECTREPLY(FD_CONNECT, 0));
3084 /* Disable this event forever; */
3085 Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT;
3086 }
3087 break;
3088
3089 case AFD_EVENT_ACCEPT:
3090 if (0 != (Socket->SharedData.AsyncEvents & FD_ACCEPT) &&
3091 0 == (Socket->SharedData.AsyncDisabledEvents & FD_ACCEPT))
3092 {
3093 /* Make the Notifcation */
3094 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
3095 Socket->SharedData.wMsg,
3096 Socket->Handle,
3097 WSAMAKESELECTREPLY(FD_ACCEPT, 0));
3098 /* Disable this event until the next accept(); */
3099 Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT;
3100 }
3101 break;
3102
3103 case AFD_EVENT_DISCONNECT:
3104 case AFD_EVENT_ABORT:
3105 case AFD_EVENT_CLOSE:
3106 if (0 != (Socket->SharedData.AsyncEvents & FD_CLOSE) &&
3107 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CLOSE))
3108 {
3109 /* Make the Notifcation */
3110 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
3111 Socket->SharedData.wMsg,
3112 Socket->Handle,
3113 WSAMAKESELECTREPLY(FD_CLOSE, 0));
3114 /* Disable this event forever; */
3115 Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE;
3116 }
3117 break;
3118 /* FIXME: Support QOS */
3119 }
3120 }
3121
3122 /* Check if there are any events left for us to check */
3123 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 )
3124 {
3125 return;
3126 }
3127
3128 /* Keep Polling */
3129 SockProcessAsyncSelect(Socket, AsyncData);
3130 return;
3131 }
3132
3133 VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData)
3134 {
3135
3136 ULONG lNetworkEvents;
3137 NTSTATUS Status;
3138
3139 /* Set up the Async Data Event Info */
3140 AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF;
3141 AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF;
3142 AsyncData->AsyncSelectInfo.HandleCount = 1;
3143 AsyncData->AsyncSelectInfo.Exclusive = TRUE;
3144 AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle;
3145 AsyncData->AsyncSelectInfo.Handles[0].Events = 0;
3146
3147 /* Remove unwanted events */
3148 lNetworkEvents = Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents);
3149
3150 /* Set Events to wait for */
3151 if (lNetworkEvents & FD_READ)
3152 {
3153 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE;
3154 }
3155
3156 if (lNetworkEvents & FD_WRITE)
3157 {
3158 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND;
3159 }
3160
3161 if (lNetworkEvents & FD_OOB)
3162 {
3163 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE;
3164 }
3165
3166 if (lNetworkEvents & FD_ACCEPT)
3167 {
3168 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT;
3169 }
3170
3171 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
3172 if (lNetworkEvents & FD_CONNECT)
3173 {
3174 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
3175 }
3176
3177 if (lNetworkEvents & FD_CLOSE)
3178 {
3179 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE;
3180 }
3181
3182 if (lNetworkEvents & FD_QOS)
3183 {
3184 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS;
3185 }
3186
3187 if (lNetworkEvents & FD_GROUP_QOS)
3188 {
3189 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS;
3190 }
3191
3192 /* Send IOCTL */
3193 Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle,
3194 NULL,
3195 NULL,
3196 AsyncData,
3197 &AsyncData->IoStatusBlock,
3198 IOCTL_AFD_SELECT,
3199 &AsyncData->AsyncSelectInfo,
3200 sizeof(AsyncData->AsyncSelectInfo),
3201 &AsyncData->AsyncSelectInfo,
3202 sizeof(AsyncData->AsyncSelectInfo));
3203
3204 /* I/O Manager Won't call the completion routine, let's do it manually */
3205 if (NT_SUCCESS(Status))
3206 {
3207 return;
3208 }
3209 else
3210 {
3211 AsyncData->IoStatusBlock.Status = Status;
3212 SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock);
3213 }
3214 }
3215
3216 VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
3217 {
3218 PASYNC_DATA AsyncData = Context;
3219 BOOL FreeContext = TRUE;
3220 PSOCKET_INFORMATION Socket;
3221
3222 /* Get the Socket */
3223 Socket = AsyncData->ParentSocket;
3224
3225 /* If someone closed it, stop the function */
3226 if (Socket->SharedData.State != SocketClosed)
3227 {
3228 /* Check if the Sequence Number changed by now, in which case quit */
3229 if (AsyncData->SequenceNumber == Socket->SharedData.SequenceNumber)
3230 {
3231 /* Do the actuall select, if needed */
3232 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)))
3233 {
3234 SockProcessAsyncSelect(Socket, AsyncData);
3235 FreeContext = FALSE;
3236 }
3237 }
3238 }
3239
3240 /* Free the Context */
3241 if (FreeContext)
3242 {
3243 HeapFree(GetProcessHeap(), 0, AsyncData);
3244 }
3245
3246 return;
3247 }
3248
3249 VOID
3250 SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket,
3251 IN ULONG Event)
3252 {
3253 PASYNC_DATA AsyncData;
3254
3255 /* Make sure the event is actually disabled */
3256 if (!(Socket->SharedData.AsyncDisabledEvents & Event))
3257 {
3258 return;
3259 }
3260
3261 /* Re-enable it */
3262 Socket->SharedData.AsyncDisabledEvents &= ~Event;
3263
3264 /* Return if no more events are being polled */
3265 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 )
3266 {
3267 return;
3268 }
3269
3270 /* Wait on new events */
3271 AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA));
3272 if (!AsyncData) return;
3273
3274 /* Create the Asynch Thread if Needed */
3275 SockCreateOrReferenceAsyncThread();
3276
3277 /* Increase the sequence number to stop anything else */
3278 Socket->SharedData.SequenceNumber++;
3279
3280 /* Set up the Async Data */
3281 AsyncData->ParentSocket = Socket;
3282 AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber;
3283
3284 /* Begin Async Select by using I/O Completion */
3285 NtSetIoCompletion(SockAsyncCompletionPort,
3286 (PVOID)&SockProcessQueuedAsyncSelect,
3287 AsyncData,
3288 0,
3289 0);
3290
3291 /* All done */
3292 return;
3293 }
3294
3295 BOOL
3296 WINAPI
3297 DllMain(HANDLE hInstDll,
3298 ULONG dwReason,
3299 PVOID Reserved)
3300 {
3301
3302 switch (dwReason)
3303 {
3304 case DLL_PROCESS_ATTACH:
3305
3306 TRACE("Loading MSAFD.DLL \n");
3307
3308 /* Don't need thread attach notifications
3309 so disable them to improve performance */
3310 DisableThreadLibraryCalls(hInstDll);
3311
3312 /* List of DLL Helpers */
3313 InitializeListHead(&SockHelpersListHead);
3314
3315 /* Heap to use when allocating */
3316 GlobalHeap = GetProcessHeap();
3317
3318 /* Initialize the lock that protects our socket list */
3319 InitializeCriticalSection(&SocketListLock);
3320
3321 TRACE("MSAFD.DLL has been loaded\n");
3322
3323 break;
3324
3325 case DLL_THREAD_ATTACH:
3326 break;
3327
3328 case DLL_THREAD_DETACH:
3329 break;
3330
3331 case DLL_PROCESS_DETACH:
3332
3333 /* Delete the socket list lock */
3334 DeleteCriticalSection(&SocketListLock);
3335
3336 break;
3337 }
3338
3339 TRACE("DllMain of msafd.dll (leaving)\n");
3340
3341 return TRUE;
3342 }
3343
3344 /* EOF */
3345
3346