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