83789067c92d47c8a37d25786890a2a8547ae18d
[reactos.git] / dll / win32 / mswsock / msafd / accept.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Winsock 2 SPI
4 * FILE: lib/mswsock/lib/init.c
5 * PURPOSE: DLL Initialization
6 */
7
8 /* INCLUDES ******************************************************************/
9 #include "msafd.h"
10
11 /* DATA **********************************************************************/
12
13 /* FUNCTIONS *****************************************************************/
14
15 INT
16 WSPAPI
17 SockCoreAccept(IN PSOCKET_INFORMATION Socket,
18 IN PSOCKET_INFORMATION AcceptedSocket)
19 {
20 INT ErrorCode, ReturnValue;
21 BOOLEAN BlockMode = Socket->SharedData.NonBlocking;
22 BOOLEAN Oob = Socket->SharedData.OobInline;
23 INT HelperContextSize;
24 PVOID HelperContext = NULL;
25 HWND hWnd = 0;
26 UINT wMsg = 0;
27 HANDLE EventObject = NULL;
28 ULONG AsyncEvents = 0, NetworkEvents = 0;
29 CHAR HelperBuffer[256];
30
31 /* Set the new state */
32 AcceptedSocket->SharedData.State = SocketConnected;
33
34 /* Copy some of the settings */
35 AcceptedSocket->SharedData.LingerData = Socket->SharedData.LingerData;
36 AcceptedSocket->SharedData.SizeOfRecvBuffer = Socket->SharedData.SizeOfRecvBuffer;
37 AcceptedSocket->SharedData.SizeOfSendBuffer = Socket->SharedData.SizeOfSendBuffer;
38 AcceptedSocket->SharedData.Broadcast = Socket->SharedData.Broadcast;
39 AcceptedSocket->SharedData.Debug = Socket->SharedData.Debug;
40 AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline;
41 AcceptedSocket->SharedData.ReuseAddresses = Socket->SharedData.ReuseAddresses;
42 AcceptedSocket->SharedData.SendTimeout = Socket->SharedData.SendTimeout;
43 AcceptedSocket->SharedData.RecvTimeout = Socket->SharedData.RecvTimeout;
44
45 /* Check if the old socket had async select */
46 if (Socket->SharedData.AsyncEvents)
47 {
48 /* Copy the data while we're still under the lock */
49 AsyncEvents = Socket->SharedData.AsyncEvents;
50 hWnd = Socket->SharedData.hWnd;
51 wMsg = Socket->SharedData.wMsg;
52 }
53 else if (Socket->NetworkEvents)
54 {
55 /* Copy the data while we're still under the lock */
56 NetworkEvents = Socket->NetworkEvents;
57 EventObject = Socket->EventObject;
58 }
59
60 /* Check how much space is needed for the context */
61 ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
62 Socket->Handle,
63 Socket->TdiAddressHandle,
64 Socket->TdiConnectionHandle,
65 SOL_INTERNAL,
66 SO_CONTEXT,
67 NULL,
68 &HelperContextSize);
69 if (ReturnValue == NO_ERROR)
70 {
71 /* Check if our stack buffer is large enough to hold it */
72 if (HelperContextSize <= sizeof(HelperBuffer))
73 {
74 /* Use it */
75 HelperContext = (PVOID)HelperBuffer;
76 }
77 else
78 {
79 /* Allocate from the heap instead */
80 HelperContext = SockAllocateHeapRoutine(SockPrivateHeap,
81 0,
82 HelperContextSize);
83 if (!HelperContext)
84 {
85 /* Unlock the socket and fail */
86 LeaveCriticalSection(&Socket->Lock);
87 return WSAENOBUFS;
88 }
89 }
90
91 /* Get the context */
92 ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
93 Socket->Handle,
94 Socket->TdiAddressHandle,
95 Socket->TdiConnectionHandle,
96 SOL_INTERNAL,
97 SO_CONTEXT,
98 HelperContext,
99 &HelperContextSize);
100 }
101
102 /* We're done with the old socket, so we can release the lock */
103 LeaveCriticalSection(&Socket->Lock);
104
105 /* Get the TDI Handles for the new socket */
106 ErrorCode = SockGetTdiHandles(AcceptedSocket);
107
108 /* Check if we have the handles and the context */
109 if ((ErrorCode == NO_ERROR) && (ReturnValue == NO_ERROR))
110 {
111 /* Set the context */
112 AcceptedSocket->HelperData->WSHGetSocketInformation(AcceptedSocket->HelperContext,
113 AcceptedSocket->Handle,
114 AcceptedSocket->TdiAddressHandle,
115 AcceptedSocket->TdiConnectionHandle,
116 SOL_INTERNAL,
117 SO_CONTEXT,
118 HelperContext,
119 &HelperContextSize);
120 }
121
122 /* Check if we should free from heap */
123 if (HelperContext && (HelperContext != (PVOID)HelperBuffer))
124 {
125 /* Free it */
126 RtlFreeHeap(SockPrivateHeap, 0, HelperContext);
127 }
128
129 /* Check if the old socket was non-blocking */
130 if (BlockMode)
131 {
132 /* Set the new one like that too */
133 ErrorCode = SockSetInformation(AcceptedSocket,
134 AFD_INFO_BLOCKING_MODE,
135 &BlockMode,
136 NULL,
137 NULL);
138 if (ErrorCode != NO_ERROR) return ErrorCode;
139 }
140
141 /* Set it internally as well */
142 AcceptedSocket->SharedData.NonBlocking = Socket->SharedData.NonBlocking;
143
144 /* Check if inlined OOB was enabled */
145 if (Oob)
146 {
147 /* Set the new one like that too */
148 ErrorCode = SockSetInformation(AcceptedSocket,
149 AFD_INFO_INLINING_MODE,
150 &Oob,
151 NULL,
152 NULL);
153 if (ErrorCode != NO_ERROR) return ErrorCode;
154 }
155
156 /* Set it internally as well */
157 AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline;
158
159 /* Update the Window Sizes */
160 ErrorCode = SockUpdateWindowSizes(AcceptedSocket, FALSE);
161 if (ErrorCode != NO_ERROR) return ErrorCode;
162
163 /* Check if async select was enabled */
164 if (AsyncEvents)
165 {
166 /* Call WSPAsyncSelect on the accepted socket too */
167 ErrorCode = SockAsyncSelectHelper(AcceptedSocket,
168 hWnd,
169 wMsg,
170 AsyncEvents);
171 }
172 else if (NetworkEvents)
173 {
174 /* WSPEventSelect was enabled instead, call it on the new socket */
175 ErrorCode = SockEventSelectHelper(AcceptedSocket,
176 EventObject,
177 NetworkEvents);
178 }
179
180 /* Check for failure */
181 if (ErrorCode != NO_ERROR) return ErrorCode;
182
183 /* Set the new context in AFD */
184 ErrorCode = SockSetHandleContext(AcceptedSocket);
185 if (ErrorCode != NO_ERROR) return ErrorCode;
186
187 /* Return success*/
188 return NO_ERROR;
189 }
190
191 SOCKET
192 WSPAPI
193 WSPAccept(SOCKET Handle,
194 SOCKADDR FAR * SocketAddress,
195 LPINT SocketAddressLength,
196 LPCONDITIONPROC lpfnCondition,
197 DWORD_PTR dwCallbackData,
198 LPINT lpErrno)
199 {
200 INT ErrorCode, ReturnValue;
201 PSOCKET_INFORMATION Socket, AcceptedSocket = NULL;
202 PWINSOCK_TEB_DATA ThreadData;
203 CHAR AfdAcceptBuffer[32];
204 PAFD_RECEIVED_ACCEPT_DATA ReceivedAcceptData = NULL;
205 ULONG ReceiveBufferSize;
206 FD_SET ReadFds;
207 TIMEVAL Timeout;
208 NTSTATUS Status;
209 IO_STATUS_BLOCK IoStatusBlock;
210 ULONG AddressBufferSize;
211 CHAR AddressBuffer[sizeof(SOCKADDR)];
212 PVOID SockAddress;
213 ULONG ConnectDataSize;
214 PVOID ConnectData = NULL;
215 AFD_PENDING_ACCEPT_DATA PendingAcceptData;
216 INT AddressSize;
217 PVOID CalleeDataBuffer = NULL;
218 WSABUF CallerId, CalleeId, CallerData, CalleeData;
219 GROUP GroupId;
220 LPQOS Qos = NULL, GroupQos = NULL;
221 BOOLEAN ValidGroup = TRUE;
222 AFD_DEFER_ACCEPT_DATA DeferData;
223 ULONG BytesReturned;
224 SOCKET AcceptedHandle = INVALID_SOCKET;
225 AFD_ACCEPT_DATA AcceptData;
226
227 /* Enter prolog */
228 ErrorCode = SockEnterApiFast(&ThreadData);
229 if (ErrorCode != NO_ERROR)
230 {
231 /* Fail */
232 *lpErrno = ErrorCode;
233 return SOCKET_ERROR;
234 }
235
236 /* Get the socket structure */
237 Socket = SockFindAndReferenceSocket(Handle, TRUE);
238 if (!Socket)
239 {
240 /* Fail */
241 ErrorCode = WSAENOTSOCK;
242 goto error;
243 }
244
245 /* Lock the socket */
246 EnterCriticalSection(&Socket->Lock);
247
248 /* Invalid for datagram sockets */
249 if (MSAFD_IS_DGRAM_SOCK(Socket))
250 {
251 /* Fail */
252 ErrorCode = WSAEOPNOTSUPP;
253 goto error;
254 }
255
256 /* Only valid if the socket is listening */
257 if (!Socket->SharedData.Listening)
258 {
259 /* Fail */
260 ErrorCode = WSAEINVAL;
261 goto error;
262 }
263
264 /* Validate address length */
265 if (SocketAddressLength &&
266 (Socket->HelperData->MinWSAddressLength > *SocketAddressLength))
267 {
268 /* Fail */
269 ErrorCode = WSAEINVAL;
270 goto error;
271 }
272
273 /* Calculate how much space we'll need for the Receive Buffer */
274 ReceiveBufferSize = sizeof(AFD_RECEIVED_ACCEPT_DATA) +
275 sizeof(TRANSPORT_ADDRESS) +
276 Socket->HelperData->MaxTDIAddressLength;
277
278 /* Check if our stack buffer is large enough */
279 if (ReceiveBufferSize <= sizeof(AfdAcceptBuffer))
280 {
281 /* Use the stack */
282 ReceivedAcceptData = (PVOID)AfdAcceptBuffer;
283 }
284 else
285 {
286 /* Allocate from heap */
287 ReceivedAcceptData = SockAllocateHeapRoutine(SockPrivateHeap,
288 0,
289 ReceiveBufferSize);
290 if (!ReceivedAcceptData)
291 {
292 /* Fail */
293 ErrorCode = WSAENOBUFS;
294 goto error;
295 }
296 }
297
298 /* If this is non-blocking, make sure there's something for us to accept */
299 if (Socket->SharedData.NonBlocking)
300 {
301 /* Set up a nonblocking select */
302 FD_ZERO(&ReadFds);
303 FD_SET(Handle, &ReadFds);
304 Timeout.tv_sec = 0;
305 Timeout.tv_usec = 0;
306
307 /* See if there's any data */
308 ReturnValue = WSPSelect(1,
309 &ReadFds,
310 NULL,
311 NULL,
312 &Timeout,
313 lpErrno);
314 if (ReturnValue == SOCKET_ERROR)
315 {
316 /* Fail */
317 ErrorCode = *lpErrno;
318 goto error;
319 }
320
321 /* Make sure we got a read back */
322 if (!FD_ISSET(Handle, &ReadFds))
323 {
324 /* Fail */
325 ErrorCode = WSAEWOULDBLOCK;
326 goto error;
327 }
328 }
329
330 /* Send IOCTL */
331 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
332 ThreadData->EventHandle,
333 NULL,
334 NULL,
335 &IoStatusBlock,
336 IOCTL_AFD_WAIT_FOR_LISTEN,
337 NULL,
338 0,
339 ReceivedAcceptData,
340 ReceiveBufferSize);
341 /* Check if we need to wait */
342 if (Status == STATUS_PENDING)
343 {
344 /* Wait for completion outside the lock */
345 LeaveCriticalSection(&Socket->Lock);
346 SockWaitForSingleObject(ThreadData->EventHandle,
347 Handle,
348 MAYBE_BLOCKING_HOOK,
349 NO_TIMEOUT);
350 EnterCriticalSection(&Socket->Lock);
351
352 /* Get new status */
353 Status = IoStatusBlock.Status;
354 }
355
356 /* Check for error */
357 if (!NT_SUCCESS(Status))
358 {
359 /* Fail */
360 ErrorCode = NtStatusToSocketError(Status);
361 goto error;
362 }
363
364 /* Check if we got a condition callback */
365 if (lpfnCondition)
366 {
367 /* Find out how much space we'll need for the address */
368 AddressBufferSize = Socket->HelperData->MaxWSAddressLength;
369
370 /* Check if our local buffer is enough */
371 if (AddressBufferSize <= sizeof(AddressBuffer))
372 {
373 /* It is, use the stack */
374 SockAddress = (PVOID)AddressBuffer;
375 }
376 else
377 {
378 /* Allocate from heap */
379 SockAddress = SockAllocateHeapRoutine(SockPrivateHeap,
380 0,
381 AddressBufferSize);
382 if (!SockAddress)
383 {
384 /* Fail */
385 ErrorCode = WSAENOBUFS;
386 goto error;
387 }
388 }
389
390 /* Assume no connect data */
391 ConnectDataSize = 0;
392
393 /* Make sure we support connect data */
394 if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA))
395 {
396 /* Find out how much data is pending */
397 PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
398 PendingAcceptData.ReturnSize = TRUE;
399
400 /* Send IOCTL */
401 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
402 ThreadData->EventHandle,
403 NULL,
404 NULL,
405 &IoStatusBlock,
406 IOCTL_AFD_GET_PENDING_CONNECT_DATA,
407 &PendingAcceptData,
408 sizeof(PendingAcceptData),
409 &PendingAcceptData,
410 sizeof(PendingAcceptData));
411 /* Check if we need to wait */
412 if (Status == STATUS_PENDING)
413 {
414 /* Wait for completion */
415 SockWaitForSingleObject(ThreadData->EventHandle,
416 Handle,
417 NO_BLOCKING_HOOK,
418 NO_TIMEOUT);
419 /* Get new status */
420 Status = IoStatusBlock.Status;
421 }
422
423 /* Check for error */
424 if (!NT_SUCCESS(Status))
425 {
426 /* Fail */
427 ErrorCode = NtStatusToSocketError(Status);
428 goto error;
429 }
430
431 /* How much data to allocate */
432 ConnectDataSize = PtrToUlong(IoStatusBlock.Information);
433 if (ConnectDataSize)
434 {
435 /* Allocate needed space */
436 ConnectData = SockAllocateHeapRoutine(SockPrivateHeap,
437 0,
438 ConnectDataSize);
439 if (!ConnectData)
440 {
441 /* Fail */
442 ErrorCode = WSAENOBUFS;
443 goto error;
444 }
445
446 /* Setup the structure to actually get the data now */
447 PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
448 PendingAcceptData.ReturnSize = FALSE;
449
450 /* Send IOCTL */
451 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
452 ThreadData->EventHandle,
453 NULL,
454 NULL,
455 &IoStatusBlock,
456 IOCTL_AFD_GET_PENDING_CONNECT_DATA,
457 &PendingAcceptData,
458 sizeof(PendingAcceptData),
459 ConnectData,
460 ConnectDataSize);
461 /* Check if we need to wait */
462 if (Status == STATUS_PENDING)
463 {
464 /* Wait for completion */
465 SockWaitForSingleObject(ThreadData->EventHandle,
466 Handle,
467 NO_BLOCKING_HOOK,
468 NO_TIMEOUT);
469 /* Get new status */
470 Status = IoStatusBlock.Status;
471 }
472
473 /* Check for error */
474 if (!NT_SUCCESS(Status))
475 {
476 /* Fail */
477 ErrorCode = NtStatusToSocketError(Status);
478 goto error;
479 }
480 }
481 }
482
483 if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED))
484 {
485 /* Set the accept data */
486 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
487 AcceptData.ListenHandle = Socket->WshContext.Handle;
488
489 /* Save it in the TEB */
490 ThreadData->AcceptData = &AcceptData;
491
492 /* Send the IOCTL to get QOS Size */
493 BytesReturned = 0;
494 ReturnValue = WSPIoctl(Handle,
495 SIO_GET_QOS,
496 NULL,
497 0,
498 NULL,
499 0,
500 &BytesReturned,
501 NULL,
502 NULL,
503 NULL,
504 &ErrorCode);
505
506 /* Check if it failed (it should) */
507 if (ReturnValue == SOCKET_ERROR)
508 {
509 /* Check if it failed because it had no buffer (it should) */
510 if (ErrorCode == WSAEFAULT)
511 {
512 /* Make sure it told us how many bytes it needed */
513 if (BytesReturned)
514 {
515 /* Allocate memory for it */
516 Qos = SockAllocateHeapRoutine(SockPrivateHeap,
517 0,
518 BytesReturned);
519 if (!Qos)
520 {
521 /* Fail */
522 ErrorCode = WSAENOBUFS;
523 goto error;
524 }
525
526 /* Save the accept data and set the QoS */
527 ThreadData->AcceptData = &AcceptData;
528 ReturnValue = WSPIoctl(Handle,
529 SIO_GET_QOS,
530 NULL,
531 0,
532 Qos,
533 BytesReturned,
534 &BytesReturned,
535 NULL,
536 NULL,
537 NULL,
538 &ErrorCode);
539 }
540 }
541 else
542 {
543 /* We got some other weird, error, fail. */
544 goto error;
545 }
546 }
547
548 /* Save the accept in the TEB */
549 ThreadData->AcceptData = &AcceptData;
550
551 /* Send the IOCTL to get Group QOS Size */
552 BytesReturned = 0;
553 ReturnValue = WSPIoctl(Handle,
554 SIO_GET_GROUP_QOS,
555 NULL,
556 0,
557 NULL,
558 0,
559 &BytesReturned,
560 NULL,
561 NULL,
562 NULL,
563 &ErrorCode);
564
565 /* Check if it failed (it should) */
566 if (ReturnValue == SOCKET_ERROR)
567 {
568 /* Check if it failed because it had no buffer (it should) */
569 if (ErrorCode == WSAEFAULT)
570 {
571 /* Make sure it told us how many bytes it needed */
572 if (BytesReturned)
573 {
574 /* Allocate memory for it */
575 GroupQos = SockAllocateHeapRoutine(SockPrivateHeap,
576 0,
577 BytesReturned);
578 if (!GroupQos)
579 {
580 /* Fail */
581 ErrorCode = WSAENOBUFS;
582 goto error;
583 }
584
585 /* Save the accept data and set the QoS */
586 ThreadData->AcceptData = &AcceptData;
587 ReturnValue = WSPIoctl(Handle,
588 SIO_GET_QOS,
589 NULL,
590 0,
591 GroupQos,
592 BytesReturned,
593 &BytesReturned,
594 NULL,
595 NULL,
596 NULL,
597 &ErrorCode);
598 }
599 }
600 else
601 {
602 /* We got some other weird, error, fail. */
603 goto error;
604 }
605 }
606 }
607
608 /* Build Callee ID */
609 CalleeId.buf = (PVOID)Socket->LocalAddress;
610 CalleeId.len = Socket->SharedData.SizeOfLocalAddress;
611
612 /* Set up Address in SOCKADDR Format */
613 SockBuildSockaddr((PSOCKADDR)SockAddress,
614 &AddressSize,
615 &ReceivedAcceptData->Address);
616
617 /* Build Caller ID */
618 CallerId.buf = (PVOID)SockAddress;
619 CallerId.len = AddressSize;
620
621 /* Build Caller Data */
622 CallerData.buf = ConnectData;
623 CallerData.len = ConnectDataSize;
624
625 /* Check if socket supports Conditional Accept */
626 if (Socket->SharedData.UseDelayedAcceptance)
627 {
628 /* Allocate Buffer for Callee Data */
629 CalleeDataBuffer = SockAllocateHeapRoutine(SockPrivateHeap, 0, 4096);
630 if (CalleeDataBuffer)
631 {
632 /* Fill the structure */
633 CalleeData.buf = CalleeDataBuffer;
634 CalleeData.len = 4096;
635 }
636 else
637 {
638 /* Don't fail, just don't use this... */
639 CalleeData.len = 0;
640 }
641 }
642 else
643 {
644 /* Nothing */
645 CalleeData.buf = NULL;
646 CalleeData.len = 0;
647 }
648
649 /* Call the Condition Function */
650 ReturnValue = (lpfnCondition)(&CallerId,
651 !CallerData.buf ? NULL : & CallerData,
652 NULL,
653 NULL,
654 &CalleeId,
655 !CalleeData.buf ? NULL: & CalleeData,
656 &GroupId,
657 dwCallbackData);
658
659 if ((ReturnValue == CF_ACCEPT) &&
660 (GroupId) &&
661 (GroupId != SG_UNCONSTRAINED_GROUP) &&
662 (GroupId != SG_CONSTRAINED_GROUP))
663 {
664 /* Check for validity */
665 ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket,
666 GroupId,
667 SockAddress,
668 AddressSize);
669 ValidGroup = (ErrorCode == NO_ERROR);
670 }
671
672 /* Check if the address was from the heap */
673 if (SockAddress != AddressBuffer)
674 {
675 /* Free it */
676 RtlFreeHeap(SockPrivateHeap, 0, SockAddress);
677 }
678
679 /* Check if it was accepted */
680 if (ReturnValue == CF_ACCEPT)
681 {
682 /* Check if the group is invalid, however */
683 if (!ValidGroup) goto error;
684
685 /* Now check if QOS is supported */
686 if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED))
687 {
688 /* Check if we had Qos */
689 if (Qos)
690 {
691 /* Set the accept data */
692 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
693 AcceptData.ListenHandle = Socket->WshContext.Handle;
694
695 /* Save it in the TEB */
696 ThreadData->AcceptData = &AcceptData;
697
698 /* Send the IOCTL */
699 BytesReturned = 0;
700 ReturnValue = WSPIoctl(Handle,
701 SIO_SET_QOS,
702 Qos,
703 sizeof(*Qos),
704 NULL,
705 0,
706 &BytesReturned,
707 NULL,
708 NULL,
709 NULL,
710 &ErrorCode);
711 if (ReturnValue == SOCKET_ERROR) goto error;
712 }
713
714 /* Check if we had Group Qos */
715 if (GroupQos)
716 {
717 /* Set the accept data */
718 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
719 AcceptData.ListenHandle = Socket->WshContext.Handle;
720
721 /* Save it in the TEB */
722 ThreadData->AcceptData = &AcceptData;
723
724 /* Send the IOCTL */
725 ReturnValue = WSPIoctl(Handle,
726 SIO_SET_GROUP_QOS,
727 GroupQos,
728 sizeof(*GroupQos),
729 NULL,
730 0,
731 &BytesReturned,
732 NULL,
733 NULL,
734 NULL,
735 &ErrorCode);
736 if (ReturnValue == SOCKET_ERROR) goto error;
737 }
738 }
739
740 /* Check if delayed acceptance is used and we have callee data */
741 if ((Socket->HelperData->UseDelayedAcceptance) && (CalleeData.len))
742 {
743 /* Save the accept data in the TEB */
744 ThreadData->AcceptData = &AcceptData;
745
746 /* Set the connect data */
747 ErrorCode = SockGetConnectData(Socket,
748 IOCTL_AFD_SET_CONNECT_DATA,
749 CalleeData.buf,
750 CalleeData.len,
751 NULL);
752 if (ErrorCode == SOCKET_ERROR) goto error;
753 }
754 }
755 else
756 {
757 /* Callback rejected. Build Defer Structure */
758 DeferData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
759 DeferData.RejectConnection = (ReturnValue == CF_REJECT);
760
761 /* Send IOCTL */
762 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
763 ThreadData->EventHandle,
764 NULL,
765 NULL,
766 &IoStatusBlock,
767 IOCTL_AFD_DEFER_ACCEPT,
768 &DeferData,
769 sizeof(DeferData),
770 NULL,
771 0);
772 /* Check for error */
773 if (!NT_SUCCESS(Status))
774 {
775 /* Fail */
776 ErrorCode = NtStatusToSocketError(Status);
777 goto error;
778 }
779
780 if (ReturnValue == CF_REJECT)
781 {
782 /* The connection was refused */
783 ErrorCode = WSAECONNREFUSED;
784 }
785 else
786 {
787 /* The connection was deferred */
788 ErrorCode = WSATRY_AGAIN;
789 }
790
791 /* Fail */
792 goto error;
793 }
794 }
795
796 /* Create a new Socket */
797 ErrorCode = SockSocket(Socket->SharedData.AddressFamily,
798 Socket->SharedData.SocketType,
799 Socket->SharedData.Protocol,
800 &Socket->ProviderId,
801 GroupId,
802 Socket->SharedData.CreateFlags,
803 Socket->SharedData.ProviderFlags,
804 Socket->SharedData.ServiceFlags1,
805 Socket->SharedData.CatalogEntryId,
806 &AcceptedSocket);
807 if (ErrorCode != NO_ERROR)
808 {
809 /* Fail */
810 goto error;
811 }
812
813 /* Set up the Accept Structure */
814 AcceptData.ListenHandle = AcceptedSocket->WshContext.Handle;
815 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
816
817 /* Build the socket address */
818 SockBuildSockaddr(AcceptedSocket->RemoteAddress,
819 &AcceptedSocket->SharedData.SizeOfRemoteAddress,
820 &ReceivedAcceptData->Address);
821
822 /* Copy the local address */
823 RtlCopyMemory(AcceptedSocket->LocalAddress,
824 Socket->LocalAddress,
825 Socket->SharedData.SizeOfLocalAddress);
826 AcceptedSocket->SharedData.SizeOfLocalAddress = Socket->SharedData.SizeOfLocalAddress;
827
828 /* We can release the accepted socket's lock now */
829 LeaveCriticalSection(&AcceptedSocket->Lock);
830
831 /* Send IOCTL to Accept */
832 AcceptData.UseSAN = SockSanEnabled;
833 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
834 ThreadData->EventHandle,
835 NULL,
836 NULL,
837 &IoStatusBlock,
838 IOCTL_AFD_ACCEPT,
839 &AcceptData,
840 sizeof(AcceptData),
841 NULL,
842 0);
843 /* Check if we need to wait */
844 if (Status == STATUS_PENDING)
845 {
846 /* Wait for completion outside the lock */
847 LeaveCriticalSection(&Socket->Lock);
848 SockWaitForSingleObject(ThreadData->EventHandle,
849 Handle,
850 MAYBE_BLOCKING_HOOK,
851 NO_TIMEOUT);
852 EnterCriticalSection(&Socket->Lock);
853
854 /* Get new status */
855 Status = IoStatusBlock.Status;
856 }
857
858 /* Check for error */
859 if (!NT_SUCCESS(Status))
860 {
861 /* Fail */
862 ErrorCode = NtStatusToSocketError(Status);
863 goto error;
864 }
865
866 /* Notify the helper DLL */
867 ErrorCode = SockNotifyHelperDll(AcceptedSocket, WSH_NOTIFY_ACCEPT);
868 if (ErrorCode != NO_ERROR) goto error;
869
870 /* If the caller sent a socket address pointer and length */
871 if (SocketAddress && SocketAddressLength)
872 {
873 /* Return the address in its buffer */
874 ErrorCode = SockBuildSockaddr(SocketAddress,
875 SocketAddressLength,
876 &ReceivedAcceptData->Address);
877 if (ErrorCode != NO_ERROR) goto error;
878 }
879
880 /* Check if async select was active */
881 if (SockAsyncSelectCalled)
882 {
883 /* Re-enable the regular accept event */
884 SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
885 }
886
887 /* Finally, do the internal core accept code */
888 ErrorCode = SockCoreAccept(Socket, AcceptedSocket);
889 if (ErrorCode != NO_ERROR) goto error;
890
891 /* Call WPU to tell it about the new handle */
892 AcceptedHandle = SockUpcallTable->lpWPUModifyIFSHandle(AcceptedSocket->SharedData.CatalogEntryId,
893 (SOCKET)AcceptedSocket->WshContext.Handle,
894 &ErrorCode);
895
896 /* Dereference the socket and clear its pointer for error code logic */
897 SockDereferenceSocket(Socket);
898 Socket = NULL;
899
900 error:
901
902 /* Check if we have a socket here */
903 if (Socket)
904 {
905 /* Check if async select was active */
906 if (SockAsyncSelectCalled)
907 {
908 /* Re-enable the regular accept event */
909 SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
910 }
911
912 /* Unlock and dereference it */
913 LeaveCriticalSection(&Socket->Lock);
914 SockDereferenceSocket(Socket);
915 }
916
917 /* Check if we got the accepted socket */
918 if (AcceptedSocket)
919 {
920 /* Check if the accepted socket also has a handle */
921 if (ErrorCode == NO_ERROR)
922 {
923 /* Close the socket */
924 SockCloseSocket(AcceptedSocket);
925 }
926
927 /* Dereference it */
928 SockDereferenceSocket(AcceptedSocket);
929 }
930
931 /* Check if the accept buffer was from the heap */
932 if (ReceivedAcceptData && (ReceivedAcceptData != (PVOID)AfdAcceptBuffer))
933 {
934 /* Free it */
935 RtlFreeHeap(SockPrivateHeap, 0, ReceivedAcceptData);
936 }
937
938 /* Check if we have a connect data buffer */
939 if (ConnectData)
940 {
941 /* Free it */
942 RtlFreeHeap(SockPrivateHeap, 0, ConnectData);
943 }
944
945 /* Check if we have a callee data buffer */
946 if (CalleeDataBuffer)
947 {
948 /* Free it */
949 RtlFreeHeap(SockPrivateHeap, 0, CalleeDataBuffer);
950 }
951
952 /* Check if we have allocated QOS structures */
953 if (Qos)
954 {
955 /* Free it */
956 RtlFreeHeap(SockPrivateHeap, 0, Qos);
957 }
958 if (GroupQos)
959 {
960 /* Free it */
961 RtlFreeHeap(SockPrivateHeap, 0, GroupQos);
962 }
963
964 /* Check for error */
965 if (ErrorCode != NO_ERROR)
966 {
967 /* Fail */
968 *lpErrno = ErrorCode;
969 return INVALID_SOCKET;
970 }
971
972 /* Return the new handle */
973 return AcceptedHandle;
974 }
975
976 /*
977 * COPYRIGHT: See COPYING in the top level directory
978 * PROJECT: ReactOS Winsock 2 SPI
979 * FILE: lib/mswsock/lib/init.c
980 * PURPOSE: DLL Initialization
981 */
982
983 /* INCLUDES ******************************************************************/
984 #include "msafd.h"
985
986 /* DATA **********************************************************************/
987
988 /* FUNCTIONS *****************************************************************/
989
990 INT
991 WSPAPI
992 SockCoreAccept(IN PSOCKET_INFORMATION Socket,
993 IN PSOCKET_INFORMATION AcceptedSocket)
994 {
995 INT ErrorCode, ReturnValue;
996 BOOLEAN BlockMode = Socket->SharedData.NonBlocking;
997 BOOLEAN Oob = Socket->SharedData.OobInline;
998 INT HelperContextSize;
999 PVOID HelperContext = NULL;
1000 HWND hWnd = 0;
1001 UINT wMsg = 0;
1002 HANDLE EventObject = NULL;
1003 ULONG AsyncEvents = 0, NetworkEvents = 0;
1004 CHAR HelperBuffer[256];
1005
1006 /* Set the new state */
1007 AcceptedSocket->SharedData.State = SocketConnected;
1008
1009 /* Copy some of the settings */
1010 AcceptedSocket->SharedData.LingerData = Socket->SharedData.LingerData;
1011 AcceptedSocket->SharedData.SizeOfRecvBuffer = Socket->SharedData.SizeOfRecvBuffer;
1012 AcceptedSocket->SharedData.SizeOfSendBuffer = Socket->SharedData.SizeOfSendBuffer;
1013 AcceptedSocket->SharedData.Broadcast = Socket->SharedData.Broadcast;
1014 AcceptedSocket->SharedData.Debug = Socket->SharedData.Debug;
1015 AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline;
1016 AcceptedSocket->SharedData.ReuseAddresses = Socket->SharedData.ReuseAddresses;
1017 AcceptedSocket->SharedData.SendTimeout = Socket->SharedData.SendTimeout;
1018 AcceptedSocket->SharedData.RecvTimeout = Socket->SharedData.RecvTimeout;
1019
1020 /* Check if the old socket had async select */
1021 if (Socket->SharedData.AsyncEvents)
1022 {
1023 /* Copy the data while we're still under the lock */
1024 AsyncEvents = Socket->SharedData.AsyncEvents;
1025 hWnd = Socket->SharedData.hWnd;
1026 wMsg = Socket->SharedData.wMsg;
1027 }
1028 else if (Socket->NetworkEvents)
1029 {
1030 /* Copy the data while we're still under the lock */
1031 NetworkEvents = Socket->NetworkEvents;
1032 EventObject = Socket->EventObject;
1033 }
1034
1035 /* Check how much space is needed for the context */
1036 ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
1037 Socket->Handle,
1038 Socket->TdiAddressHandle,
1039 Socket->TdiConnectionHandle,
1040 SOL_INTERNAL,
1041 SO_CONTEXT,
1042 NULL,
1043 &HelperContextSize);
1044 if (ReturnValue == NO_ERROR)
1045 {
1046 /* Check if our stack buffer is large enough to hold it */
1047 if (HelperContextSize <= sizeof(HelperBuffer))
1048 {
1049 /* Use it */
1050 HelperContext = (PVOID)HelperBuffer;
1051 }
1052 else
1053 {
1054 /* Allocate from the heap instead */
1055 HelperContext = SockAllocateHeapRoutine(SockPrivateHeap,
1056 0,
1057 HelperContextSize);
1058 if (!HelperContext)
1059 {
1060 /* Unlock the socket and fail */
1061 LeaveCriticalSection(&Socket->Lock);
1062 return WSAENOBUFS;
1063 }
1064 }
1065
1066 /* Get the context */
1067 ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
1068 Socket->Handle,
1069 Socket->TdiAddressHandle,
1070 Socket->TdiConnectionHandle,
1071 SOL_INTERNAL,
1072 SO_CONTEXT,
1073 HelperContext,
1074 &HelperContextSize);
1075 }
1076
1077 /* We're done with the old socket, so we can release the lock */
1078 LeaveCriticalSection(&Socket->Lock);
1079
1080 /* Get the TDI Handles for the new socket */
1081 ErrorCode = SockGetTdiHandles(AcceptedSocket);
1082
1083 /* Check if we have the handles and the context */
1084 if ((ErrorCode == NO_ERROR) && (ReturnValue == NO_ERROR))
1085 {
1086 /* Set the context */
1087 AcceptedSocket->HelperData->WSHGetSocketInformation(AcceptedSocket->HelperContext,
1088 AcceptedSocket->Handle,
1089 AcceptedSocket->TdiAddressHandle,
1090 AcceptedSocket->TdiConnectionHandle,
1091 SOL_INTERNAL,
1092 SO_CONTEXT,
1093 HelperContext,
1094 &HelperContextSize);
1095 }
1096
1097 /* Check if we should free from heap */
1098 if (HelperContext && (HelperContext != (PVOID)HelperBuffer))
1099 {
1100 /* Free it */
1101 RtlFreeHeap(SockPrivateHeap, 0, HelperContext);
1102 }
1103
1104 /* Check if the old socket was non-blocking */
1105 if (BlockMode)
1106 {
1107 /* Set the new one like that too */
1108 ErrorCode = SockSetInformation(AcceptedSocket,
1109 AFD_INFO_BLOCKING_MODE,
1110 &BlockMode,
1111 NULL,
1112 NULL);
1113 if (ErrorCode != NO_ERROR) return ErrorCode;
1114 }
1115
1116 /* Set it internally as well */
1117 AcceptedSocket->SharedData.NonBlocking = Socket->SharedData.NonBlocking;
1118
1119 /* Check if inlined OOB was enabled */
1120 if (Oob)
1121 {
1122 /* Set the new one like that too */
1123 ErrorCode = SockSetInformation(AcceptedSocket,
1124 AFD_INFO_INLINING_MODE,
1125 &Oob,
1126 NULL,
1127 NULL);
1128 if (ErrorCode != NO_ERROR) return ErrorCode;
1129 }
1130
1131 /* Set it internally as well */
1132 AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline;
1133
1134 /* Update the Window Sizes */
1135 ErrorCode = SockUpdateWindowSizes(AcceptedSocket, FALSE);
1136 if (ErrorCode != NO_ERROR) return ErrorCode;
1137
1138 /* Check if async select was enabled */
1139 if (AsyncEvents)
1140 {
1141 /* Call WSPAsyncSelect on the accepted socket too */
1142 ErrorCode = SockAsyncSelectHelper(AcceptedSocket,
1143 hWnd,
1144 wMsg,
1145 AsyncEvents);
1146 }
1147 else if (NetworkEvents)
1148 {
1149 /* WSPEventSelect was enabled instead, call it on the new socket */
1150 ErrorCode = SockEventSelectHelper(AcceptedSocket,
1151 EventObject,
1152 NetworkEvents);
1153 }
1154
1155 /* Check for failure */
1156 if (ErrorCode != NO_ERROR) return ErrorCode;
1157
1158 /* Set the new context in AFD */
1159 ErrorCode = SockSetHandleContext(AcceptedSocket);
1160 if (ErrorCode != NO_ERROR) return ErrorCode;
1161
1162 /* Return success*/
1163 return NO_ERROR;
1164 }
1165
1166 SOCKET
1167 WSPAPI
1168 WSPAccept(SOCKET Handle,
1169 SOCKADDR FAR * SocketAddress,
1170 LPINT SocketAddressLength,
1171 LPCONDITIONPROC lpfnCondition,
1172 DWORD_PTR dwCallbackData,
1173 LPINT lpErrno)
1174 {
1175 INT ErrorCode, ReturnValue;
1176 PSOCKET_INFORMATION Socket, AcceptedSocket = NULL;
1177 PWINSOCK_TEB_DATA ThreadData;
1178 CHAR AfdAcceptBuffer[32];
1179 PAFD_RECEIVED_ACCEPT_DATA ReceivedAcceptData = NULL;
1180 ULONG ReceiveBufferSize;
1181 FD_SET ReadFds;
1182 TIMEVAL Timeout;
1183 NTSTATUS Status;
1184 IO_STATUS_BLOCK IoStatusBlock;
1185 ULONG AddressBufferSize;
1186 CHAR AddressBuffer[sizeof(SOCKADDR)];
1187 PVOID SockAddress;
1188 ULONG ConnectDataSize;
1189 PVOID ConnectData = NULL;
1190 AFD_PENDING_ACCEPT_DATA PendingAcceptData;
1191 INT AddressSize;
1192 PVOID CalleeDataBuffer = NULL;
1193 WSABUF CallerId, CalleeId, CallerData, CalleeData;
1194 GROUP GroupId;
1195 LPQOS Qos = NULL, GroupQos = NULL;
1196 BOOLEAN ValidGroup = TRUE;
1197 AFD_DEFER_ACCEPT_DATA DeferData;
1198 ULONG BytesReturned;
1199 SOCKET AcceptedHandle = INVALID_SOCKET;
1200 AFD_ACCEPT_DATA AcceptData;
1201
1202 /* Enter prolog */
1203 ErrorCode = SockEnterApiFast(&ThreadData);
1204 if (ErrorCode != NO_ERROR)
1205 {
1206 /* Fail */
1207 *lpErrno = ErrorCode;
1208 return SOCKET_ERROR;
1209 }
1210
1211 /* Get the socket structure */
1212 Socket = SockFindAndReferenceSocket(Handle, TRUE);
1213 if (!Socket)
1214 {
1215 /* Fail */
1216 ErrorCode = WSAENOTSOCK;
1217 goto error;
1218 }
1219
1220 /* Lock the socket */
1221 EnterCriticalSection(&Socket->Lock);
1222
1223 /* Invalid for datagram sockets */
1224 if (MSAFD_IS_DGRAM_SOCK(Socket))
1225 {
1226 /* Fail */
1227 ErrorCode = WSAEOPNOTSUPP;
1228 goto error;
1229 }
1230
1231 /* Only valid if the socket is listening */
1232 if (!Socket->SharedData.Listening)
1233 {
1234 /* Fail */
1235 ErrorCode = WSAEINVAL;
1236 goto error;
1237 }
1238
1239 /* Validate address length */
1240 if (SocketAddressLength &&
1241 (Socket->HelperData->MinWSAddressLength > *SocketAddressLength))
1242 {
1243 /* Fail */
1244 ErrorCode = WSAEINVAL;
1245 goto error;
1246 }
1247
1248 /* Calculate how much space we'll need for the Receive Buffer */
1249 ReceiveBufferSize = sizeof(AFD_RECEIVED_ACCEPT_DATA) +
1250 sizeof(TRANSPORT_ADDRESS) +
1251 Socket->HelperData->MaxTDIAddressLength;
1252
1253 /* Check if our stack buffer is large enough */
1254 if (ReceiveBufferSize <= sizeof(AfdAcceptBuffer))
1255 {
1256 /* Use the stack */
1257 ReceivedAcceptData = (PVOID)AfdAcceptBuffer;
1258 }
1259 else
1260 {
1261 /* Allocate from heap */
1262 ReceivedAcceptData = SockAllocateHeapRoutine(SockPrivateHeap,
1263 0,
1264 ReceiveBufferSize);
1265 if (!ReceivedAcceptData)
1266 {
1267 /* Fail */
1268 ErrorCode = WSAENOBUFS;
1269 goto error;
1270 }
1271 }
1272
1273 /* If this is non-blocking, make sure there's something for us to accept */
1274 if (Socket->SharedData.NonBlocking)
1275 {
1276 /* Set up a nonblocking select */
1277 FD_ZERO(&ReadFds);
1278 FD_SET(Handle, &ReadFds);
1279 Timeout.tv_sec = 0;
1280 Timeout.tv_usec = 0;
1281
1282 /* See if there's any data */
1283 ReturnValue = WSPSelect(1,
1284 &ReadFds,
1285 NULL,
1286 NULL,
1287 &Timeout,
1288 lpErrno);
1289 if (ReturnValue == SOCKET_ERROR)
1290 {
1291 /* Fail */
1292 ErrorCode = *lpErrno;
1293 goto error;
1294 }
1295
1296 /* Make sure we got a read back */
1297 if (!FD_ISSET(Handle, &ReadFds))
1298 {
1299 /* Fail */
1300 ErrorCode = WSAEWOULDBLOCK;
1301 goto error;
1302 }
1303 }
1304
1305 /* Send IOCTL */
1306 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
1307 ThreadData->EventHandle,
1308 NULL,
1309 NULL,
1310 &IoStatusBlock,
1311 IOCTL_AFD_WAIT_FOR_LISTEN,
1312 NULL,
1313 0,
1314 ReceivedAcceptData,
1315 ReceiveBufferSize);
1316 /* Check if we need to wait */
1317 if (Status == STATUS_PENDING)
1318 {
1319 /* Wait for completion outside the lock */
1320 LeaveCriticalSection(&Socket->Lock);
1321 SockWaitForSingleObject(ThreadData->EventHandle,
1322 Handle,
1323 MAYBE_BLOCKING_HOOK,
1324 NO_TIMEOUT);
1325 EnterCriticalSection(&Socket->Lock);
1326
1327 /* Get new status */
1328 Status = IoStatusBlock.Status;
1329 }
1330
1331 /* Check for error */
1332 if (!NT_SUCCESS(Status))
1333 {
1334 /* Fail */
1335 ErrorCode = NtStatusToSocketError(Status);
1336 goto error;
1337 }
1338
1339 /* Check if we got a condition callback */
1340 if (lpfnCondition)
1341 {
1342 /* Find out how much space we'll need for the address */
1343 AddressBufferSize = Socket->HelperData->MaxWSAddressLength;
1344
1345 /* Check if our local buffer is enough */
1346 if (AddressBufferSize <= sizeof(AddressBuffer))
1347 {
1348 /* It is, use the stack */
1349 SockAddress = (PVOID)AddressBuffer;
1350 }
1351 else
1352 {
1353 /* Allocate from heap */
1354 SockAddress = SockAllocateHeapRoutine(SockPrivateHeap,
1355 0,
1356 AddressBufferSize);
1357 if (!SockAddress)
1358 {
1359 /* Fail */
1360 ErrorCode = WSAENOBUFS;
1361 goto error;
1362 }
1363 }
1364
1365 /* Assume no connect data */
1366 ConnectDataSize = 0;
1367
1368 /* Make sure we support connect data */
1369 if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA))
1370 {
1371 /* Find out how much data is pending */
1372 PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
1373 PendingAcceptData.ReturnSize = TRUE;
1374
1375 /* Send IOCTL */
1376 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
1377 ThreadData->EventHandle,
1378 NULL,
1379 NULL,
1380 &IoStatusBlock,
1381 IOCTL_AFD_GET_PENDING_CONNECT_DATA,
1382 &PendingAcceptData,
1383 sizeof(PendingAcceptData),
1384 &PendingAcceptData,
1385 sizeof(PendingAcceptData));
1386 /* Check if we need to wait */
1387 if (Status == STATUS_PENDING)
1388 {
1389 /* Wait for completion */
1390 SockWaitForSingleObject(ThreadData->EventHandle,
1391 Handle,
1392 NO_BLOCKING_HOOK,
1393 NO_TIMEOUT);
1394 /* Get new status */
1395 Status = IoStatusBlock.Status;
1396 }
1397
1398 /* Check for error */
1399 if (!NT_SUCCESS(Status))
1400 {
1401 /* Fail */
1402 ErrorCode = NtStatusToSocketError(Status);
1403 goto error;
1404 }
1405
1406 /* How much data to allocate */
1407 ConnectDataSize = PtrToUlong(IoStatusBlock.Information);
1408 if (ConnectDataSize)
1409 {
1410 /* Allocate needed space */
1411 ConnectData = SockAllocateHeapRoutine(SockPrivateHeap,
1412 0,
1413 ConnectDataSize);
1414 if (!ConnectData)
1415 {
1416 /* Fail */
1417 ErrorCode = WSAENOBUFS;
1418 goto error;
1419 }
1420
1421 /* Setup the structure to actually get the data now */
1422 PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
1423 PendingAcceptData.ReturnSize = FALSE;
1424
1425 /* Send IOCTL */
1426 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
1427 ThreadData->EventHandle,
1428 NULL,
1429 NULL,
1430 &IoStatusBlock,
1431 IOCTL_AFD_GET_PENDING_CONNECT_DATA,
1432 &PendingAcceptData,
1433 sizeof(PendingAcceptData),
1434 ConnectData,
1435 ConnectDataSize);
1436 /* Check if we need to wait */
1437 if (Status == STATUS_PENDING)
1438 {
1439 /* Wait for completion */
1440 SockWaitForSingleObject(ThreadData->EventHandle,
1441 Handle,
1442 NO_BLOCKING_HOOK,
1443 NO_TIMEOUT);
1444 /* Get new status */
1445 Status = IoStatusBlock.Status;
1446 }
1447
1448 /* Check for error */
1449 if (!NT_SUCCESS(Status))
1450 {
1451 /* Fail */
1452 ErrorCode = NtStatusToSocketError(Status);
1453 goto error;
1454 }
1455 }
1456 }
1457
1458 if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED))
1459 {
1460 /* Set the accept data */
1461 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
1462 AcceptData.ListenHandle = Socket->WshContext.Handle;
1463
1464 /* Save it in the TEB */
1465 ThreadData->AcceptData = &AcceptData;
1466
1467 /* Send the IOCTL to get QOS Size */
1468 BytesReturned = 0;
1469 ReturnValue = WSPIoctl(Handle,
1470 SIO_GET_QOS,
1471 NULL,
1472 0,
1473 NULL,
1474 0,
1475 &BytesReturned,
1476 NULL,
1477 NULL,
1478 NULL,
1479 &ErrorCode);
1480
1481 /* Check if it failed (it should) */
1482 if (ReturnValue == SOCKET_ERROR)
1483 {
1484 /* Check if it failed because it had no buffer (it should) */
1485 if (ErrorCode == WSAEFAULT)
1486 {
1487 /* Make sure it told us how many bytes it needed */
1488 if (BytesReturned)
1489 {
1490 /* Allocate memory for it */
1491 Qos = SockAllocateHeapRoutine(SockPrivateHeap,
1492 0,
1493 BytesReturned);
1494 if (!Qos)
1495 {
1496 /* Fail */
1497 ErrorCode = WSAENOBUFS;
1498 goto error;
1499 }
1500
1501 /* Save the accept data and set the QoS */
1502 ThreadData->AcceptData = &AcceptData;
1503 ReturnValue = WSPIoctl(Handle,
1504 SIO_GET_QOS,
1505 NULL,
1506 0,
1507 Qos,
1508 BytesReturned,
1509 &BytesReturned,
1510 NULL,
1511 NULL,
1512 NULL,
1513 &ErrorCode);
1514 }
1515 }
1516 else
1517 {
1518 /* We got some other weird, error, fail. */
1519 goto error;
1520 }
1521 }
1522
1523 /* Save the accept in the TEB */
1524 ThreadData->AcceptData = &AcceptData;
1525
1526 /* Send the IOCTL to get Group QOS Size */
1527 BytesReturned = 0;
1528 ReturnValue = WSPIoctl(Handle,
1529 SIO_GET_GROUP_QOS,
1530 NULL,
1531 0,
1532 NULL,
1533 0,
1534 &BytesReturned,
1535 NULL,
1536 NULL,
1537 NULL,
1538 &ErrorCode);
1539
1540 /* Check if it failed (it should) */
1541 if (ReturnValue == SOCKET_ERROR)
1542 {
1543 /* Check if it failed because it had no buffer (it should) */
1544 if (ErrorCode == WSAEFAULT)
1545 {
1546 /* Make sure it told us how many bytes it needed */
1547 if (BytesReturned)
1548 {
1549 /* Allocate memory for it */
1550 GroupQos = SockAllocateHeapRoutine(SockPrivateHeap,
1551 0,
1552 BytesReturned);
1553 if (!GroupQos)
1554 {
1555 /* Fail */
1556 ErrorCode = WSAENOBUFS;
1557 goto error;
1558 }
1559
1560 /* Save the accept data and set the QoS */
1561 ThreadData->AcceptData = &AcceptData;
1562 ReturnValue = WSPIoctl(Handle,
1563 SIO_GET_QOS,
1564 NULL,
1565 0,
1566 GroupQos,
1567 BytesReturned,
1568 &BytesReturned,
1569 NULL,
1570 NULL,
1571 NULL,
1572 &ErrorCode);
1573 }
1574 }
1575 else
1576 {
1577 /* We got some other weird, error, fail. */
1578 goto error;
1579 }
1580 }
1581 }
1582
1583 /* Build Callee ID */
1584 CalleeId.buf = (PVOID)Socket->LocalAddress;
1585 CalleeId.len = Socket->SharedData.SizeOfLocalAddress;
1586
1587 /* Set up Address in SOCKADDR Format */
1588 SockBuildSockaddr((PSOCKADDR)SockAddress,
1589 &AddressSize,
1590 &ReceivedAcceptData->Address);
1591
1592 /* Build Caller ID */
1593 CallerId.buf = (PVOID)SockAddress;
1594 CallerId.len = AddressSize;
1595
1596 /* Build Caller Data */
1597 CallerData.buf = ConnectData;
1598 CallerData.len = ConnectDataSize;
1599
1600 /* Check if socket supports Conditional Accept */
1601 if (Socket->SharedData.UseDelayedAcceptance)
1602 {
1603 /* Allocate Buffer for Callee Data */
1604 CalleeDataBuffer = SockAllocateHeapRoutine(SockPrivateHeap, 0, 4096);
1605 if (CalleeDataBuffer)
1606 {
1607 /* Fill the structure */
1608 CalleeData.buf = CalleeDataBuffer;
1609 CalleeData.len = 4096;
1610 }
1611 else
1612 {
1613 /* Don't fail, just don't use this... */
1614 CalleeData.len = 0;
1615 }
1616 }
1617 else
1618 {
1619 /* Nothing */
1620 CalleeData.buf = NULL;
1621 CalleeData.len = 0;
1622 }
1623
1624 /* Call the Condition Function */
1625 ReturnValue = (lpfnCondition)(&CallerId,
1626 !CallerData.buf ? NULL : & CallerData,
1627 NULL,
1628 NULL,
1629 &CalleeId,
1630 !CalleeData.buf ? NULL: & CalleeData,
1631 &GroupId,
1632 dwCallbackData);
1633
1634 if ((ReturnValue == CF_ACCEPT) &&
1635 (GroupId) &&
1636 (GroupId != SG_UNCONSTRAINED_GROUP) &&
1637 (GroupId != SG_CONSTRAINED_GROUP))
1638 {
1639 /* Check for validity */
1640 ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket,
1641 GroupId,
1642 SockAddress,
1643 AddressSize);
1644 ValidGroup = (ErrorCode == NO_ERROR);
1645 }
1646
1647 /* Check if the address was from the heap */
1648 if (SockAddress != AddressBuffer)
1649 {
1650 /* Free it */
1651 RtlFreeHeap(SockPrivateHeap, 0, SockAddress);
1652 }
1653
1654 /* Check if it was accepted */
1655 if (ReturnValue == CF_ACCEPT)
1656 {
1657 /* Check if the group is invalid, however */
1658 if (!ValidGroup) goto error;
1659
1660 /* Now check if QOS is supported */
1661 if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED))
1662 {
1663 /* Check if we had Qos */
1664 if (Qos)
1665 {
1666 /* Set the accept data */
1667 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
1668 AcceptData.ListenHandle = Socket->WshContext.Handle;
1669
1670 /* Save it in the TEB */
1671 ThreadData->AcceptData = &AcceptData;
1672
1673 /* Send the IOCTL */
1674 BytesReturned = 0;
1675 ReturnValue = WSPIoctl(Handle,
1676 SIO_SET_QOS,
1677 Qos,
1678 sizeof(*Qos),
1679 NULL,
1680 0,
1681 &BytesReturned,
1682 NULL,
1683 NULL,
1684 NULL,
1685 &ErrorCode);
1686 if (ReturnValue == SOCKET_ERROR) goto error;
1687 }
1688
1689 /* Check if we had Group Qos */
1690 if (GroupQos)
1691 {
1692 /* Set the accept data */
1693 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
1694 AcceptData.ListenHandle = Socket->WshContext.Handle;
1695
1696 /* Save it in the TEB */
1697 ThreadData->AcceptData = &AcceptData;
1698
1699 /* Send the IOCTL */
1700 ReturnValue = WSPIoctl(Handle,
1701 SIO_SET_GROUP_QOS,
1702 GroupQos,
1703 sizeof(*GroupQos),
1704 NULL,
1705 0,
1706 &BytesReturned,
1707 NULL,
1708 NULL,
1709 NULL,
1710 &ErrorCode);
1711 if (ReturnValue == SOCKET_ERROR) goto error;
1712 }
1713 }
1714
1715 /* Check if delayed acceptance is used and we have callee data */
1716 if ((Socket->HelperData->UseDelayedAcceptance) && (CalleeData.len))
1717 {
1718 /* Save the accept data in the TEB */
1719 ThreadData->AcceptData = &AcceptData;
1720
1721 /* Set the connect data */
1722 ErrorCode = SockGetConnectData(Socket,
1723 IOCTL_AFD_SET_CONNECT_DATA,
1724 CalleeData.buf,
1725 CalleeData.len,
1726 NULL);
1727 if (ErrorCode == SOCKET_ERROR) goto error;
1728 }
1729 }
1730 else
1731 {
1732 /* Callback rejected. Build Defer Structure */
1733 DeferData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
1734 DeferData.RejectConnection = (ReturnValue == CF_REJECT);
1735
1736 /* Send IOCTL */
1737 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
1738 ThreadData->EventHandle,
1739 NULL,
1740 NULL,
1741 &IoStatusBlock,
1742 IOCTL_AFD_DEFER_ACCEPT,
1743 &DeferData,
1744 sizeof(DeferData),
1745 NULL,
1746 0);
1747 /* Check for error */
1748 if (!NT_SUCCESS(Status))
1749 {
1750 /* Fail */
1751 ErrorCode = NtStatusToSocketError(Status);
1752 goto error;
1753 }
1754
1755 if (ReturnValue == CF_REJECT)
1756 {
1757 /* The connection was refused */
1758 ErrorCode = WSAECONNREFUSED;
1759 }
1760 else
1761 {
1762 /* The connection was deferred */
1763 ErrorCode = WSATRY_AGAIN;
1764 }
1765
1766 /* Fail */
1767 goto error;
1768 }
1769 }
1770
1771 /* Create a new Socket */
1772 ErrorCode = SockSocket(Socket->SharedData.AddressFamily,
1773 Socket->SharedData.SocketType,
1774 Socket->SharedData.Protocol,
1775 &Socket->ProviderId,
1776 GroupId,
1777 Socket->SharedData.CreateFlags,
1778 Socket->SharedData.ProviderFlags,
1779 Socket->SharedData.ServiceFlags1,
1780 Socket->SharedData.CatalogEntryId,
1781 &AcceptedSocket);
1782 if (ErrorCode != NO_ERROR)
1783 {
1784 /* Fail */
1785 goto error;
1786 }
1787
1788 /* Set up the Accept Structure */
1789 AcceptData.ListenHandle = AcceptedSocket->WshContext.Handle;
1790 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
1791
1792 /* Build the socket address */
1793 SockBuildSockaddr(AcceptedSocket->RemoteAddress,
1794 &AcceptedSocket->SharedData.SizeOfRemoteAddress,
1795 &ReceivedAcceptData->Address);
1796
1797 /* Copy the local address */
1798 RtlCopyMemory(AcceptedSocket->LocalAddress,
1799 Socket->LocalAddress,
1800 Socket->SharedData.SizeOfLocalAddress);
1801 AcceptedSocket->SharedData.SizeOfLocalAddress = Socket->SharedData.SizeOfLocalAddress;
1802
1803 /* We can release the accepted socket's lock now */
1804 LeaveCriticalSection(&AcceptedSocket->Lock);
1805
1806 /* Send IOCTL to Accept */
1807 AcceptData.UseSAN = SockSanEnabled;
1808 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
1809 ThreadData->EventHandle,
1810 NULL,
1811 NULL,
1812 &IoStatusBlock,
1813 IOCTL_AFD_ACCEPT,
1814 &AcceptData,
1815 sizeof(AcceptData),
1816 NULL,
1817 0);
1818 /* Check if we need to wait */
1819 if (Status == STATUS_PENDING)
1820 {
1821 /* Wait for completion outside the lock */
1822 LeaveCriticalSection(&Socket->Lock);
1823 SockWaitForSingleObject(ThreadData->EventHandle,
1824 Handle,
1825 MAYBE_BLOCKING_HOOK,
1826 NO_TIMEOUT);
1827 EnterCriticalSection(&Socket->Lock);
1828
1829 /* Get new status */
1830 Status = IoStatusBlock.Status;
1831 }
1832
1833 /* Check for error */
1834 if (!NT_SUCCESS(Status))
1835 {
1836 /* Fail */
1837 ErrorCode = NtStatusToSocketError(Status);
1838 goto error;
1839 }
1840
1841 /* Notify the helper DLL */
1842 ErrorCode = SockNotifyHelperDll(AcceptedSocket, WSH_NOTIFY_ACCEPT);
1843 if (ErrorCode != NO_ERROR) goto error;
1844
1845 /* If the caller sent a socket address pointer and length */
1846 if (SocketAddress && SocketAddressLength)
1847 {
1848 /* Return the address in its buffer */
1849 ErrorCode = SockBuildSockaddr(SocketAddress,
1850 SocketAddressLength,
1851 &ReceivedAcceptData->Address);
1852 if (ErrorCode != NO_ERROR) goto error;
1853 }
1854
1855 /* Check if async select was active */
1856 if (SockAsyncSelectCalled)
1857 {
1858 /* Re-enable the regular accept event */
1859 SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
1860 }
1861
1862 /* Finally, do the internal core accept code */
1863 ErrorCode = SockCoreAccept(Socket, AcceptedSocket);
1864 if (ErrorCode != NO_ERROR) goto error;
1865
1866 /* Call WPU to tell it about the new handle */
1867 AcceptedHandle = SockUpcallTable->lpWPUModifyIFSHandle(AcceptedSocket->SharedData.CatalogEntryId,
1868 (SOCKET)AcceptedSocket->WshContext.Handle,
1869 &ErrorCode);
1870
1871 /* Dereference the socket and clear its pointer for error code logic */
1872 SockDereferenceSocket(Socket);
1873 Socket = NULL;
1874
1875 error:
1876
1877 /* Check if we have a socket here */
1878 if (Socket)
1879 {
1880 /* Check if async select was active */
1881 if (SockAsyncSelectCalled)
1882 {
1883 /* Re-enable the regular accept event */
1884 SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
1885 }
1886
1887 /* Unlock and dereference it */
1888 LeaveCriticalSection(&Socket->Lock);
1889 SockDereferenceSocket(Socket);
1890 }
1891
1892 /* Check if we got the accepted socket */
1893 if (AcceptedSocket)
1894 {
1895 /* Check if the accepted socket also has a handle */
1896 if (ErrorCode == NO_ERROR)
1897 {
1898 /* Close the socket */
1899 SockCloseSocket(AcceptedSocket);
1900 }
1901
1902 /* Dereference it */
1903 SockDereferenceSocket(AcceptedSocket);
1904 }
1905
1906 /* Check if the accept buffer was from the heap */
1907 if (ReceivedAcceptData && (ReceivedAcceptData != (PVOID)AfdAcceptBuffer))
1908 {
1909 /* Free it */
1910 RtlFreeHeap(SockPrivateHeap, 0, ReceivedAcceptData);
1911 }
1912
1913 /* Check if we have a connect data buffer */
1914 if (ConnectData)
1915 {
1916 /* Free it */
1917 RtlFreeHeap(SockPrivateHeap, 0, ConnectData);
1918 }
1919
1920 /* Check if we have a callee data buffer */
1921 if (CalleeDataBuffer)
1922 {
1923 /* Free it */
1924 RtlFreeHeap(SockPrivateHeap, 0, CalleeDataBuffer);
1925 }
1926
1927 /* Check if we have allocated QOS structures */
1928 if (Qos)
1929 {
1930 /* Free it */
1931 RtlFreeHeap(SockPrivateHeap, 0, Qos);
1932 }
1933 if (GroupQos)
1934 {
1935 /* Free it */
1936 RtlFreeHeap(SockPrivateHeap, 0, GroupQos);
1937 }
1938
1939 /* Check for error */
1940 if (ErrorCode != NO_ERROR)
1941 {
1942 /* Fail */
1943 *lpErrno = ErrorCode;
1944 return INVALID_SOCKET;
1945 }
1946
1947 /* Return the new handle */
1948 return AcceptedHandle;
1949 }
1950
1951 /*
1952 * COPYRIGHT: See COPYING in the top level directory
1953 * PROJECT: ReactOS Winsock 2 SPI
1954 * FILE: lib/mswsock/lib/init.c
1955 * PURPOSE: DLL Initialization
1956 */
1957
1958 /* INCLUDES ******************************************************************/
1959 #include "msafd.h"
1960
1961 /* DATA **********************************************************************/
1962
1963 /* FUNCTIONS *****************************************************************/
1964
1965 INT
1966 WSPAPI
1967 SockCoreAccept(IN PSOCKET_INFORMATION Socket,
1968 IN PSOCKET_INFORMATION AcceptedSocket)
1969 {
1970 INT ErrorCode, ReturnValue;
1971 BOOLEAN BlockMode = Socket->SharedData.NonBlocking;
1972 BOOLEAN Oob = Socket->SharedData.OobInline;
1973 INT HelperContextSize;
1974 PVOID HelperContext = NULL;
1975 HWND hWnd = 0;
1976 UINT wMsg = 0;
1977 HANDLE EventObject = NULL;
1978 ULONG AsyncEvents = 0, NetworkEvents = 0;
1979 CHAR HelperBuffer[256];
1980
1981 /* Set the new state */
1982 AcceptedSocket->SharedData.State = SocketConnected;
1983
1984 /* Copy some of the settings */
1985 AcceptedSocket->SharedData.LingerData = Socket->SharedData.LingerData;
1986 AcceptedSocket->SharedData.SizeOfRecvBuffer = Socket->SharedData.SizeOfRecvBuffer;
1987 AcceptedSocket->SharedData.SizeOfSendBuffer = Socket->SharedData.SizeOfSendBuffer;
1988 AcceptedSocket->SharedData.Broadcast = Socket->SharedData.Broadcast;
1989 AcceptedSocket->SharedData.Debug = Socket->SharedData.Debug;
1990 AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline;
1991 AcceptedSocket->SharedData.ReuseAddresses = Socket->SharedData.ReuseAddresses;
1992 AcceptedSocket->SharedData.SendTimeout = Socket->SharedData.SendTimeout;
1993 AcceptedSocket->SharedData.RecvTimeout = Socket->SharedData.RecvTimeout;
1994
1995 /* Check if the old socket had async select */
1996 if (Socket->SharedData.AsyncEvents)
1997 {
1998 /* Copy the data while we're still under the lock */
1999 AsyncEvents = Socket->SharedData.AsyncEvents;
2000 hWnd = Socket->SharedData.hWnd;
2001 wMsg = Socket->SharedData.wMsg;
2002 }
2003 else if (Socket->NetworkEvents)
2004 {
2005 /* Copy the data while we're still under the lock */
2006 NetworkEvents = Socket->NetworkEvents;
2007 EventObject = Socket->EventObject;
2008 }
2009
2010 /* Check how much space is needed for the context */
2011 ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
2012 Socket->Handle,
2013 Socket->TdiAddressHandle,
2014 Socket->TdiConnectionHandle,
2015 SOL_INTERNAL,
2016 SO_CONTEXT,
2017 NULL,
2018 &HelperContextSize);
2019 if (ReturnValue == NO_ERROR)
2020 {
2021 /* Check if our stack buffer is large enough to hold it */
2022 if (HelperContextSize <= sizeof(HelperBuffer))
2023 {
2024 /* Use it */
2025 HelperContext = (PVOID)HelperBuffer;
2026 }
2027 else
2028 {
2029 /* Allocate from the heap instead */
2030 HelperContext = SockAllocateHeapRoutine(SockPrivateHeap,
2031 0,
2032 HelperContextSize);
2033 if (!HelperContext)
2034 {
2035 /* Unlock the socket and fail */
2036 LeaveCriticalSection(&Socket->Lock);
2037 return WSAENOBUFS;
2038 }
2039 }
2040
2041 /* Get the context */
2042 ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
2043 Socket->Handle,
2044 Socket->TdiAddressHandle,
2045 Socket->TdiConnectionHandle,
2046 SOL_INTERNAL,
2047 SO_CONTEXT,
2048 HelperContext,
2049 &HelperContextSize);
2050 }
2051
2052 /* We're done with the old socket, so we can release the lock */
2053 LeaveCriticalSection(&Socket->Lock);
2054
2055 /* Get the TDI Handles for the new socket */
2056 ErrorCode = SockGetTdiHandles(AcceptedSocket);
2057
2058 /* Check if we have the handles and the context */
2059 if ((ErrorCode == NO_ERROR) && (ReturnValue == NO_ERROR))
2060 {
2061 /* Set the context */
2062 AcceptedSocket->HelperData->WSHGetSocketInformation(AcceptedSocket->HelperContext,
2063 AcceptedSocket->Handle,
2064 AcceptedSocket->TdiAddressHandle,
2065 AcceptedSocket->TdiConnectionHandle,
2066 SOL_INTERNAL,
2067 SO_CONTEXT,
2068 HelperContext,
2069 &HelperContextSize);
2070 }
2071
2072 /* Check if we should free from heap */
2073 if (HelperContext && (HelperContext != (PVOID)HelperBuffer))
2074 {
2075 /* Free it */
2076 RtlFreeHeap(SockPrivateHeap, 0, HelperContext);
2077 }
2078
2079 /* Check if the old socket was non-blocking */
2080 if (BlockMode)
2081 {
2082 /* Set the new one like that too */
2083 ErrorCode = SockSetInformation(AcceptedSocket,
2084 AFD_INFO_BLOCKING_MODE,
2085 &BlockMode,
2086 NULL,
2087 NULL);
2088 if (ErrorCode != NO_ERROR) return ErrorCode;
2089 }
2090
2091 /* Set it internally as well */
2092 AcceptedSocket->SharedData.NonBlocking = Socket->SharedData.NonBlocking;
2093
2094 /* Check if inlined OOB was enabled */
2095 if (Oob)
2096 {
2097 /* Set the new one like that too */
2098 ErrorCode = SockSetInformation(AcceptedSocket,
2099 AFD_INFO_INLINING_MODE,
2100 &Oob,
2101 NULL,
2102 NULL);
2103 if (ErrorCode != NO_ERROR) return ErrorCode;
2104 }
2105
2106 /* Set it internally as well */
2107 AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline;
2108
2109 /* Update the Window Sizes */
2110 ErrorCode = SockUpdateWindowSizes(AcceptedSocket, FALSE);
2111 if (ErrorCode != NO_ERROR) return ErrorCode;
2112
2113 /* Check if async select was enabled */
2114 if (AsyncEvents)
2115 {
2116 /* Call WSPAsyncSelect on the accepted socket too */
2117 ErrorCode = SockAsyncSelectHelper(AcceptedSocket,
2118 hWnd,
2119 wMsg,
2120 AsyncEvents);
2121 }
2122 else if (NetworkEvents)
2123 {
2124 /* WSPEventSelect was enabled instead, call it on the new socket */
2125 ErrorCode = SockEventSelectHelper(AcceptedSocket,
2126 EventObject,
2127 NetworkEvents);
2128 }
2129
2130 /* Check for failure */
2131 if (ErrorCode != NO_ERROR) return ErrorCode;
2132
2133 /* Set the new context in AFD */
2134 ErrorCode = SockSetHandleContext(AcceptedSocket);
2135 if (ErrorCode != NO_ERROR) return ErrorCode;
2136
2137 /* Return success*/
2138 return NO_ERROR;
2139 }
2140
2141 SOCKET
2142 WSPAPI
2143 WSPAccept(SOCKET Handle,
2144 SOCKADDR FAR * SocketAddress,
2145 LPINT SocketAddressLength,
2146 LPCONDITIONPROC lpfnCondition,
2147 DWORD_PTR dwCallbackData,
2148 LPINT lpErrno)
2149 {
2150 INT ErrorCode, ReturnValue;
2151 PSOCKET_INFORMATION Socket, AcceptedSocket = NULL;
2152 PWINSOCK_TEB_DATA ThreadData;
2153 CHAR AfdAcceptBuffer[32];
2154 PAFD_RECEIVED_ACCEPT_DATA ReceivedAcceptData = NULL;
2155 ULONG ReceiveBufferSize;
2156 FD_SET ReadFds;
2157 TIMEVAL Timeout;
2158 NTSTATUS Status;
2159 IO_STATUS_BLOCK IoStatusBlock;
2160 ULONG AddressBufferSize;
2161 CHAR AddressBuffer[sizeof(SOCKADDR)];
2162 PVOID SockAddress;
2163 ULONG ConnectDataSize;
2164 PVOID ConnectData = NULL;
2165 AFD_PENDING_ACCEPT_DATA PendingAcceptData;
2166 INT AddressSize;
2167 PVOID CalleeDataBuffer = NULL;
2168 WSABUF CallerId, CalleeId, CallerData, CalleeData;
2169 GROUP GroupId;
2170 LPQOS Qos = NULL, GroupQos = NULL;
2171 BOOLEAN ValidGroup = TRUE;
2172 AFD_DEFER_ACCEPT_DATA DeferData;
2173 ULONG BytesReturned;
2174 SOCKET AcceptedHandle = INVALID_SOCKET;
2175 AFD_ACCEPT_DATA AcceptData;
2176
2177 /* Enter prolog */
2178 ErrorCode = SockEnterApiFast(&ThreadData);
2179 if (ErrorCode != NO_ERROR)
2180 {
2181 /* Fail */
2182 *lpErrno = ErrorCode;
2183 return SOCKET_ERROR;
2184 }
2185
2186 /* Get the socket structure */
2187 Socket = SockFindAndReferenceSocket(Handle, TRUE);
2188 if (!Socket)
2189 {
2190 /* Fail */
2191 ErrorCode = WSAENOTSOCK;
2192 goto error;
2193 }
2194
2195 /* Lock the socket */
2196 EnterCriticalSection(&Socket->Lock);
2197
2198 /* Invalid for datagram sockets */
2199 if (MSAFD_IS_DGRAM_SOCK(Socket))
2200 {
2201 /* Fail */
2202 ErrorCode = WSAEOPNOTSUPP;
2203 goto error;
2204 }
2205
2206 /* Only valid if the socket is listening */
2207 if (!Socket->SharedData.Listening)
2208 {
2209 /* Fail */
2210 ErrorCode = WSAEINVAL;
2211 goto error;
2212 }
2213
2214 /* Validate address length */
2215 if (SocketAddressLength &&
2216 (Socket->HelperData->MinWSAddressLength > *SocketAddressLength))
2217 {
2218 /* Fail */
2219 ErrorCode = WSAEINVAL;
2220 goto error;
2221 }
2222
2223 /* Calculate how much space we'll need for the Receive Buffer */
2224 ReceiveBufferSize = sizeof(AFD_RECEIVED_ACCEPT_DATA) +
2225 sizeof(TRANSPORT_ADDRESS) +
2226 Socket->HelperData->MaxTDIAddressLength;
2227
2228 /* Check if our stack buffer is large enough */
2229 if (ReceiveBufferSize <= sizeof(AfdAcceptBuffer))
2230 {
2231 /* Use the stack */
2232 ReceivedAcceptData = (PVOID)AfdAcceptBuffer;
2233 }
2234 else
2235 {
2236 /* Allocate from heap */
2237 ReceivedAcceptData = SockAllocateHeapRoutine(SockPrivateHeap,
2238 0,
2239 ReceiveBufferSize);
2240 if (!ReceivedAcceptData)
2241 {
2242 /* Fail */
2243 ErrorCode = WSAENOBUFS;
2244 goto error;
2245 }
2246 }
2247
2248 /* If this is non-blocking, make sure there's something for us to accept */
2249 if (Socket->SharedData.NonBlocking)
2250 {
2251 /* Set up a nonblocking select */
2252 FD_ZERO(&ReadFds);
2253 FD_SET(Handle, &ReadFds);
2254 Timeout.tv_sec = 0;
2255 Timeout.tv_usec = 0;
2256
2257 /* See if there's any data */
2258 ReturnValue = WSPSelect(1,
2259 &ReadFds,
2260 NULL,
2261 NULL,
2262 &Timeout,
2263 lpErrno);
2264 if (ReturnValue == SOCKET_ERROR)
2265 {
2266 /* Fail */
2267 ErrorCode = *lpErrno;
2268 goto error;
2269 }
2270
2271 /* Make sure we got a read back */
2272 if (!FD_ISSET(Handle, &ReadFds))
2273 {
2274 /* Fail */
2275 ErrorCode = WSAEWOULDBLOCK;
2276 goto error;
2277 }
2278 }
2279
2280 /* Send IOCTL */
2281 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
2282 ThreadData->EventHandle,
2283 NULL,
2284 NULL,
2285 &IoStatusBlock,
2286 IOCTL_AFD_WAIT_FOR_LISTEN,
2287 NULL,
2288 0,
2289 ReceivedAcceptData,
2290 ReceiveBufferSize);
2291 /* Check if we need to wait */
2292 if (Status == STATUS_PENDING)
2293 {
2294 /* Wait for completion outside the lock */
2295 LeaveCriticalSection(&Socket->Lock);
2296 SockWaitForSingleObject(ThreadData->EventHandle,
2297 Handle,
2298 MAYBE_BLOCKING_HOOK,
2299 NO_TIMEOUT);
2300 EnterCriticalSection(&Socket->Lock);
2301
2302 /* Get new status */
2303 Status = IoStatusBlock.Status;
2304 }
2305
2306 /* Check for error */
2307 if (!NT_SUCCESS(Status))
2308 {
2309 /* Fail */
2310 ErrorCode = NtStatusToSocketError(Status);
2311 goto error;
2312 }
2313
2314 /* Check if we got a condition callback */
2315 if (lpfnCondition)
2316 {
2317 /* Find out how much space we'll need for the address */
2318 AddressBufferSize = Socket->HelperData->MaxWSAddressLength;
2319
2320 /* Check if our local buffer is enough */
2321 if (AddressBufferSize <= sizeof(AddressBuffer))
2322 {
2323 /* It is, use the stack */
2324 SockAddress = (PVOID)AddressBuffer;
2325 }
2326 else
2327 {
2328 /* Allocate from heap */
2329 SockAddress = SockAllocateHeapRoutine(SockPrivateHeap,
2330 0,
2331 AddressBufferSize);
2332 if (!SockAddress)
2333 {
2334 /* Fail */
2335 ErrorCode = WSAENOBUFS;
2336 goto error;
2337 }
2338 }
2339
2340 /* Assume no connect data */
2341 ConnectDataSize = 0;
2342
2343 /* Make sure we support connect data */
2344 if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA))
2345 {
2346 /* Find out how much data is pending */
2347 PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
2348 PendingAcceptData.ReturnSize = TRUE;
2349
2350 /* Send IOCTL */
2351 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
2352 ThreadData->EventHandle,
2353 NULL,
2354 NULL,
2355 &IoStatusBlock,
2356 IOCTL_AFD_GET_PENDING_CONNECT_DATA,
2357 &PendingAcceptData,
2358 sizeof(PendingAcceptData),
2359 &PendingAcceptData,
2360 sizeof(PendingAcceptData));
2361 /* Check if we need to wait */
2362 if (Status == STATUS_PENDING)
2363 {
2364 /* Wait for completion */
2365 SockWaitForSingleObject(ThreadData->EventHandle,
2366 Handle,
2367 NO_BLOCKING_HOOK,
2368 NO_TIMEOUT);
2369 /* Get new status */
2370 Status = IoStatusBlock.Status;
2371 }
2372
2373 /* Check for error */
2374 if (!NT_SUCCESS(Status))
2375 {
2376 /* Fail */
2377 ErrorCode = NtStatusToSocketError(Status);
2378 goto error;
2379 }
2380
2381 /* How much data to allocate */
2382 ConnectDataSize = PtrToUlong(IoStatusBlock.Information);
2383 if (ConnectDataSize)
2384 {
2385 /* Allocate needed space */
2386 ConnectData = SockAllocateHeapRoutine(SockPrivateHeap,
2387 0,
2388 ConnectDataSize);
2389 if (!ConnectData)
2390 {
2391 /* Fail */
2392 ErrorCode = WSAENOBUFS;
2393 goto error;
2394 }
2395
2396 /* Setup the structure to actually get the data now */
2397 PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
2398 PendingAcceptData.ReturnSize = FALSE;
2399
2400 /* Send IOCTL */
2401 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
2402 ThreadData->EventHandle,
2403 NULL,
2404 NULL,
2405 &IoStatusBlock,
2406 IOCTL_AFD_GET_PENDING_CONNECT_DATA,
2407 &PendingAcceptData,
2408 sizeof(PendingAcceptData),
2409 ConnectData,
2410 ConnectDataSize);
2411 /* Check if we need to wait */
2412 if (Status == STATUS_PENDING)
2413 {
2414 /* Wait for completion */
2415 SockWaitForSingleObject(ThreadData->EventHandle,
2416 Handle,
2417 NO_BLOCKING_HOOK,
2418 NO_TIMEOUT);
2419 /* Get new status */
2420 Status = IoStatusBlock.Status;
2421 }
2422
2423 /* Check for error */
2424 if (!NT_SUCCESS(Status))
2425 {
2426 /* Fail */
2427 ErrorCode = NtStatusToSocketError(Status);
2428 goto error;
2429 }
2430 }
2431 }
2432
2433 if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED))
2434 {
2435 /* Set the accept data */
2436 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
2437 AcceptData.ListenHandle = Socket->WshContext.Handle;
2438
2439 /* Save it in the TEB */
2440 ThreadData->AcceptData = &AcceptData;
2441
2442 /* Send the IOCTL to get QOS Size */
2443 BytesReturned = 0;
2444 ReturnValue = WSPIoctl(Handle,
2445 SIO_GET_QOS,
2446 NULL,
2447 0,
2448 NULL,
2449 0,
2450 &BytesReturned,
2451 NULL,
2452 NULL,
2453 NULL,
2454 &ErrorCode);
2455
2456 /* Check if it failed (it should) */
2457 if (ReturnValue == SOCKET_ERROR)
2458 {
2459 /* Check if it failed because it had no buffer (it should) */
2460 if (ErrorCode == WSAEFAULT)
2461 {
2462 /* Make sure it told us how many bytes it needed */
2463 if (BytesReturned)
2464 {
2465 /* Allocate memory for it */
2466 Qos = SockAllocateHeapRoutine(SockPrivateHeap,
2467 0,
2468 BytesReturned);
2469 if (!Qos)
2470 {
2471 /* Fail */
2472 ErrorCode = WSAENOBUFS;
2473 goto error;
2474 }
2475
2476 /* Save the accept data and set the QoS */
2477 ThreadData->AcceptData = &AcceptData;
2478 ReturnValue = WSPIoctl(Handle,
2479 SIO_GET_QOS,
2480 NULL,
2481 0,
2482 Qos,
2483 BytesReturned,
2484 &BytesReturned,
2485 NULL,
2486 NULL,
2487 NULL,
2488 &ErrorCode);
2489 }
2490 }
2491 else
2492 {
2493 /* We got some other weird, error, fail. */
2494 goto error;
2495 }
2496 }
2497
2498 /* Save the accept in the TEB */
2499 ThreadData->AcceptData = &AcceptData;
2500
2501 /* Send the IOCTL to get Group QOS Size */
2502 BytesReturned = 0;
2503 ReturnValue = WSPIoctl(Handle,
2504 SIO_GET_GROUP_QOS,
2505 NULL,
2506 0,
2507 NULL,
2508 0,
2509 &BytesReturned,
2510 NULL,
2511 NULL,
2512 NULL,
2513 &ErrorCode);
2514
2515 /* Check if it failed (it should) */
2516 if (ReturnValue == SOCKET_ERROR)
2517 {
2518 /* Check if it failed because it had no buffer (it should) */
2519 if (ErrorCode == WSAEFAULT)
2520 {
2521 /* Make sure it told us how many bytes it needed */
2522 if (BytesReturned)
2523 {
2524 /* Allocate memory for it */
2525 GroupQos = SockAllocateHeapRoutine(SockPrivateHeap,
2526 0,
2527 BytesReturned);
2528 if (!GroupQos)
2529 {
2530 /* Fail */
2531 ErrorCode = WSAENOBUFS;
2532 goto error;
2533 }
2534
2535 /* Save the accept data and set the QoS */
2536 ThreadData->AcceptData = &AcceptData;
2537 ReturnValue = WSPIoctl(Handle,
2538 SIO_GET_QOS,
2539 NULL,
2540 0,
2541 GroupQos,
2542 BytesReturned,
2543 &BytesReturned,
2544 NULL,
2545 NULL,
2546 NULL,
2547 &ErrorCode);
2548 }
2549 }
2550 else
2551 {
2552 /* We got some other weird, error, fail. */
2553 goto error;
2554 }
2555 }
2556 }
2557
2558 /* Build Callee ID */
2559 CalleeId.buf = (PVOID)Socket->LocalAddress;
2560 CalleeId.len = Socket->SharedData.SizeOfLocalAddress;
2561
2562 /* Set up Address in SOCKADDR Format */
2563 SockBuildSockaddr((PSOCKADDR)SockAddress,
2564 &AddressSize,
2565 &ReceivedAcceptData->Address);
2566
2567 /* Build Caller ID */
2568 CallerId.buf = (PVOID)SockAddress;
2569 CallerId.len = AddressSize;
2570
2571 /* Build Caller Data */
2572 CallerData.buf = ConnectData;
2573 CallerData.len = ConnectDataSize;
2574
2575 /* Check if socket supports Conditional Accept */
2576 if (Socket->SharedData.UseDelayedAcceptance)
2577 {
2578 /* Allocate Buffer for Callee Data */
2579 CalleeDataBuffer = SockAllocateHeapRoutine(SockPrivateHeap, 0, 4096);
2580 if (CalleeDataBuffer)
2581 {
2582 /* Fill the structure */
2583 CalleeData.buf = CalleeDataBuffer;
2584 CalleeData.len = 4096;
2585 }
2586 else
2587 {
2588 /* Don't fail, just don't use this... */
2589 CalleeData.len = 0;
2590 }
2591 }
2592 else
2593 {
2594 /* Nothing */
2595 CalleeData.buf = NULL;
2596 CalleeData.len = 0;
2597 }
2598
2599 /* Call the Condition Function */
2600 ReturnValue = (lpfnCondition)(&CallerId,
2601 !CallerData.buf ? NULL : & CallerData,
2602 NULL,
2603 NULL,
2604 &CalleeId,
2605 !CalleeData.buf ? NULL: & CalleeData,
2606 &GroupId,
2607 dwCallbackData);
2608
2609 if ((ReturnValue == CF_ACCEPT) &&
2610 (GroupId) &&
2611 (GroupId != SG_UNCONSTRAINED_GROUP) &&
2612 (GroupId != SG_CONSTRAINED_GROUP))
2613 {
2614 /* Check for validity */
2615 ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket,
2616 GroupId,
2617 SockAddress,
2618 AddressSize);
2619 ValidGroup = (ErrorCode == NO_ERROR);
2620 }
2621
2622 /* Check if the address was from the heap */
2623 if (SockAddress != AddressBuffer)
2624 {
2625 /* Free it */
2626 RtlFreeHeap(SockPrivateHeap, 0, SockAddress);
2627 }
2628
2629 /* Check if it was accepted */
2630 if (ReturnValue == CF_ACCEPT)
2631 {
2632 /* Check if the group is invalid, however */
2633 if (!ValidGroup) goto error;
2634
2635 /* Now check if QOS is supported */
2636 if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED))
2637 {
2638 /* Check if we had Qos */
2639 if (Qos)
2640 {
2641 /* Set the accept data */
2642 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
2643 AcceptData.ListenHandle = Socket->WshContext.Handle;
2644
2645 /* Save it in the TEB */
2646 ThreadData->AcceptData = &AcceptData;
2647
2648 /* Send the IOCTL */
2649 BytesReturned = 0;
2650 ReturnValue = WSPIoctl(Handle,
2651 SIO_SET_QOS,
2652 Qos,
2653 sizeof(*Qos),
2654 NULL,
2655 0,
2656 &BytesReturned,
2657 NULL,
2658 NULL,
2659 NULL,
2660 &ErrorCode);
2661 if (ReturnValue == SOCKET_ERROR) goto error;
2662 }
2663
2664 /* Check if we had Group Qos */
2665 if (GroupQos)
2666 {
2667 /* Set the accept data */
2668 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
2669 AcceptData.ListenHandle = Socket->WshContext.Handle;
2670
2671 /* Save it in the TEB */
2672 ThreadData->AcceptData = &AcceptData;
2673
2674 /* Send the IOCTL */
2675 ReturnValue = WSPIoctl(Handle,
2676 SIO_SET_GROUP_QOS,
2677 GroupQos,
2678 sizeof(*GroupQos),
2679 NULL,
2680 0,
2681 &BytesReturned,
2682 NULL,
2683 NULL,
2684 NULL,
2685 &ErrorCode);
2686 if (ReturnValue == SOCKET_ERROR) goto error;
2687 }
2688 }
2689
2690 /* Check if delayed acceptance is used and we have callee data */
2691 if ((Socket->HelperData->UseDelayedAcceptance) && (CalleeData.len))
2692 {
2693 /* Save the accept data in the TEB */
2694 ThreadData->AcceptData = &AcceptData;
2695
2696 /* Set the connect data */
2697 ErrorCode = SockGetConnectData(Socket,
2698 IOCTL_AFD_SET_CONNECT_DATA,
2699 CalleeData.buf,
2700 CalleeData.len,
2701 NULL);
2702 if (ErrorCode == SOCKET_ERROR) goto error;
2703 }
2704 }
2705 else
2706 {
2707 /* Callback rejected. Build Defer Structure */
2708 DeferData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
2709 DeferData.RejectConnection = (ReturnValue == CF_REJECT);
2710
2711 /* Send IOCTL */
2712 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
2713 ThreadData->EventHandle,
2714 NULL,
2715 NULL,
2716 &IoStatusBlock,
2717 IOCTL_AFD_DEFER_ACCEPT,
2718 &DeferData,
2719 sizeof(DeferData),
2720 NULL,
2721 0);
2722 /* Check for error */
2723 if (!NT_SUCCESS(Status))
2724 {
2725 /* Fail */
2726 ErrorCode = NtStatusToSocketError(Status);
2727 goto error;
2728 }
2729
2730 if (ReturnValue == CF_REJECT)
2731 {
2732 /* The connection was refused */
2733 ErrorCode = WSAECONNREFUSED;
2734 }
2735 else
2736 {
2737 /* The connection was deferred */
2738 ErrorCode = WSATRY_AGAIN;
2739 }
2740
2741 /* Fail */
2742 goto error;
2743 }
2744 }
2745
2746 /* Create a new Socket */
2747 ErrorCode = SockSocket(Socket->SharedData.AddressFamily,
2748 Socket->SharedData.SocketType,
2749 Socket->SharedData.Protocol,
2750 &Socket->ProviderId,
2751 GroupId,
2752 Socket->SharedData.CreateFlags,
2753 Socket->SharedData.ProviderFlags,
2754 Socket->SharedData.ServiceFlags1,
2755 Socket->SharedData.CatalogEntryId,
2756 &AcceptedSocket);
2757 if (ErrorCode != NO_ERROR)
2758 {
2759 /* Fail */
2760 goto error;
2761 }
2762
2763 /* Set up the Accept Structure */
2764 AcceptData.ListenHandle = AcceptedSocket->WshContext.Handle;
2765 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
2766
2767 /* Build the socket address */
2768 SockBuildSockaddr(AcceptedSocket->RemoteAddress,
2769 &AcceptedSocket->SharedData.SizeOfRemoteAddress,
2770 &ReceivedAcceptData->Address);
2771
2772 /* Copy the local address */
2773 RtlCopyMemory(AcceptedSocket->LocalAddress,
2774 Socket->LocalAddress,
2775 Socket->SharedData.SizeOfLocalAddress);
2776 AcceptedSocket->SharedData.SizeOfLocalAddress = Socket->SharedData.SizeOfLocalAddress;
2777
2778 /* We can release the accepted socket's lock now */
2779 LeaveCriticalSection(&AcceptedSocket->Lock);
2780
2781 /* Send IOCTL to Accept */
2782 AcceptData.UseSAN = SockSanEnabled;
2783 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
2784 ThreadData->EventHandle,
2785 NULL,
2786 NULL,
2787 &IoStatusBlock,
2788 IOCTL_AFD_ACCEPT,
2789 &AcceptData,
2790 sizeof(AcceptData),
2791 NULL,
2792 0);
2793 /* Check if we need to wait */
2794 if (Status == STATUS_PENDING)
2795 {
2796 /* Wait for completion outside the lock */
2797 LeaveCriticalSection(&Socket->Lock);
2798 SockWaitForSingleObject(ThreadData->EventHandle,
2799 Handle,
2800 MAYBE_BLOCKING_HOOK,
2801 NO_TIMEOUT);
2802 EnterCriticalSection(&Socket->Lock);
2803
2804 /* Get new status */
2805 Status = IoStatusBlock.Status;
2806 }
2807
2808 /* Check for error */
2809 if (!NT_SUCCESS(Status))
2810 {
2811 /* Fail */
2812 ErrorCode = NtStatusToSocketError(Status);
2813 goto error;
2814 }
2815
2816 /* Notify the helper DLL */
2817 ErrorCode = SockNotifyHelperDll(AcceptedSocket, WSH_NOTIFY_ACCEPT);
2818 if (ErrorCode != NO_ERROR) goto error;
2819
2820 /* If the caller sent a socket address pointer and length */
2821 if (SocketAddress && SocketAddressLength)
2822 {
2823 /* Return the address in its buffer */
2824 ErrorCode = SockBuildSockaddr(SocketAddress,
2825 SocketAddressLength,
2826 &ReceivedAcceptData->Address);
2827 if (ErrorCode != NO_ERROR) goto error;
2828 }
2829
2830 /* Check if async select was active */
2831 if (SockAsyncSelectCalled)
2832 {
2833 /* Re-enable the regular accept event */
2834 SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
2835 }
2836
2837 /* Finally, do the internal core accept code */
2838 ErrorCode = SockCoreAccept(Socket, AcceptedSocket);
2839 if (ErrorCode != NO_ERROR) goto error;
2840
2841 /* Call WPU to tell it about the new handle */
2842 AcceptedHandle = SockUpcallTable->lpWPUModifyIFSHandle(AcceptedSocket->SharedData.CatalogEntryId,
2843 (SOCKET)AcceptedSocket->WshContext.Handle,
2844 &ErrorCode);
2845
2846 /* Dereference the socket and clear its pointer for error code logic */
2847 SockDereferenceSocket(Socket);
2848 Socket = NULL;
2849
2850 error:
2851
2852 /* Check if we have a socket here */
2853 if (Socket)
2854 {
2855 /* Check if async select was active */
2856 if (SockAsyncSelectCalled)
2857 {
2858 /* Re-enable the regular accept event */
2859 SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
2860 }
2861
2862 /* Unlock and dereference it */
2863 LeaveCriticalSection(&Socket->Lock);
2864 SockDereferenceSocket(Socket);
2865 }
2866
2867 /* Check if we got the accepted socket */
2868 if (AcceptedSocket)
2869 {
2870 /* Check if the accepted socket also has a handle */
2871 if (ErrorCode == NO_ERROR)
2872 {
2873 /* Close the socket */
2874 SockCloseSocket(AcceptedSocket);
2875 }
2876
2877 /* Dereference it */
2878 SockDereferenceSocket(AcceptedSocket);
2879 }
2880
2881 /* Check if the accept buffer was from the heap */
2882 if (ReceivedAcceptData && (ReceivedAcceptData != (PVOID)AfdAcceptBuffer))
2883 {
2884 /* Free it */
2885 RtlFreeHeap(SockPrivateHeap, 0, ReceivedAcceptData);
2886 }
2887
2888 /* Check if we have a connect data buffer */
2889 if (ConnectData)
2890 {
2891 /* Free it */
2892 RtlFreeHeap(SockPrivateHeap, 0, ConnectData);
2893 }
2894
2895 /* Check if we have a callee data buffer */
2896 if (CalleeDataBuffer)
2897 {
2898 /* Free it */
2899 RtlFreeHeap(SockPrivateHeap, 0, CalleeDataBuffer);
2900 }
2901
2902 /* Check if we have allocated QOS structures */
2903 if (Qos)
2904 {
2905 /* Free it */
2906 RtlFreeHeap(SockPrivateHeap, 0, Qos);
2907 }
2908 if (GroupQos)
2909 {
2910 /* Free it */
2911 RtlFreeHeap(SockPrivateHeap, 0, GroupQos);
2912 }
2913
2914 /* Check for error */
2915 if (ErrorCode != NO_ERROR)
2916 {
2917 /* Fail */
2918 *lpErrno = ErrorCode;
2919 return INVALID_SOCKET;
2920 }
2921
2922 /* Return the new handle */
2923 return AcceptedHandle;
2924 }
2925
2926 /*
2927 * COPYRIGHT: See COPYING in the top level directory
2928 * PROJECT: ReactOS Winsock 2 SPI
2929 * FILE: lib/mswsock/lib/init.c
2930 * PURPOSE: DLL Initialization
2931 */
2932
2933 /* INCLUDES ******************************************************************/
2934 #include "msafd.h"
2935
2936 /* DATA **********************************************************************/
2937
2938 /* FUNCTIONS *****************************************************************/
2939
2940 INT
2941 WSPAPI
2942 SockCoreAccept(IN PSOCKET_INFORMATION Socket,
2943 IN PSOCKET_INFORMATION AcceptedSocket)
2944 {
2945 INT ErrorCode, ReturnValue;
2946 BOOLEAN BlockMode = Socket->SharedData.NonBlocking;
2947 BOOLEAN Oob = Socket->SharedData.OobInline;
2948 INT HelperContextSize;
2949 PVOID HelperContext = NULL;
2950 HWND hWnd = 0;
2951 UINT wMsg = 0;
2952 HANDLE EventObject = NULL;
2953 ULONG AsyncEvents = 0, NetworkEvents = 0;
2954 CHAR HelperBuffer[256];
2955
2956 /* Set the new state */
2957 AcceptedSocket->SharedData.State = SocketConnected;
2958
2959 /* Copy some of the settings */
2960 AcceptedSocket->SharedData.LingerData = Socket->SharedData.LingerData;
2961 AcceptedSocket->SharedData.SizeOfRecvBuffer = Socket->SharedData.SizeOfRecvBuffer;
2962 AcceptedSocket->SharedData.SizeOfSendBuffer = Socket->SharedData.SizeOfSendBuffer;
2963 AcceptedSocket->SharedData.Broadcast = Socket->SharedData.Broadcast;
2964 AcceptedSocket->SharedData.Debug = Socket->SharedData.Debug;
2965 AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline;
2966 AcceptedSocket->SharedData.ReuseAddresses = Socket->SharedData.ReuseAddresses;
2967 AcceptedSocket->SharedData.SendTimeout = Socket->SharedData.SendTimeout;
2968 AcceptedSocket->SharedData.RecvTimeout = Socket->SharedData.RecvTimeout;
2969
2970 /* Check if the old socket had async select */
2971 if (Socket->SharedData.AsyncEvents)
2972 {
2973 /* Copy the data while we're still under the lock */
2974 AsyncEvents = Socket->SharedData.AsyncEvents;
2975 hWnd = Socket->SharedData.hWnd;
2976 wMsg = Socket->SharedData.wMsg;
2977 }
2978 else if (Socket->NetworkEvents)
2979 {
2980 /* Copy the data while we're still under the lock */
2981 NetworkEvents = Socket->NetworkEvents;
2982 EventObject = Socket->EventObject;
2983 }
2984
2985 /* Check how much space is needed for the context */
2986 ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
2987 Socket->Handle,
2988 Socket->TdiAddressHandle,
2989 Socket->TdiConnectionHandle,
2990 SOL_INTERNAL,
2991 SO_CONTEXT,
2992 NULL,
2993 &HelperContextSize);
2994 if (ReturnValue == NO_ERROR)
2995 {
2996 /* Check if our stack buffer is large enough to hold it */
2997 if (HelperContextSize <= sizeof(HelperBuffer))
2998 {
2999 /* Use it */
3000 HelperContext = (PVOID)HelperBuffer;
3001 }
3002 else
3003 {
3004 /* Allocate from the heap instead */
3005 HelperContext = SockAllocateHeapRoutine(SockPrivateHeap,
3006 0,
3007 HelperContextSize);
3008 if (!HelperContext)
3009 {
3010 /* Unlock the socket and fail */
3011 LeaveCriticalSection(&Socket->Lock);
3012 return WSAENOBUFS;
3013 }
3014 }
3015
3016 /* Get the context */
3017 ReturnValue = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
3018 Socket->Handle,
3019 Socket->TdiAddressHandle,
3020 Socket->TdiConnectionHandle,
3021 SOL_INTERNAL,
3022 SO_CONTEXT,
3023 HelperContext,
3024 &HelperContextSize);
3025 }
3026
3027 /* We're done with the old socket, so we can release the lock */
3028 LeaveCriticalSection(&Socket->Lock);
3029
3030 /* Get the TDI Handles for the new socket */
3031 ErrorCode = SockGetTdiHandles(AcceptedSocket);
3032
3033 /* Check if we have the handles and the context */
3034 if ((ErrorCode == NO_ERROR) && (ReturnValue == NO_ERROR))
3035 {
3036 /* Set the context */
3037 AcceptedSocket->HelperData->WSHGetSocketInformation(AcceptedSocket->HelperContext,
3038 AcceptedSocket->Handle,
3039 AcceptedSocket->TdiAddressHandle,
3040 AcceptedSocket->TdiConnectionHandle,
3041 SOL_INTERNAL,
3042 SO_CONTEXT,
3043 HelperContext,
3044 &HelperContextSize);
3045 }
3046
3047 /* Check if we should free from heap */
3048 if (HelperContext && (HelperContext != (PVOID)HelperBuffer))
3049 {
3050 /* Free it */
3051 RtlFreeHeap(SockPrivateHeap, 0, HelperContext);
3052 }
3053
3054 /* Check if the old socket was non-blocking */
3055 if (BlockMode)
3056 {
3057 /* Set the new one like that too */
3058 ErrorCode = SockSetInformation(AcceptedSocket,
3059 AFD_INFO_BLOCKING_MODE,
3060 &BlockMode,
3061 NULL,
3062 NULL);
3063 if (ErrorCode != NO_ERROR) return ErrorCode;
3064 }
3065
3066 /* Set it internally as well */
3067 AcceptedSocket->SharedData.NonBlocking = Socket->SharedData.NonBlocking;
3068
3069 /* Check if inlined OOB was enabled */
3070 if (Oob)
3071 {
3072 /* Set the new one like that too */
3073 ErrorCode = SockSetInformation(AcceptedSocket,
3074 AFD_INFO_INLINING_MODE,
3075 &Oob,
3076 NULL,
3077 NULL);
3078 if (ErrorCode != NO_ERROR) return ErrorCode;
3079 }
3080
3081 /* Set it internally as well */
3082 AcceptedSocket->SharedData.OobInline = Socket->SharedData.OobInline;
3083
3084 /* Update the Window Sizes */
3085 ErrorCode = SockUpdateWindowSizes(AcceptedSocket, FALSE);
3086 if (ErrorCode != NO_ERROR) return ErrorCode;
3087
3088 /* Check if async select was enabled */
3089 if (AsyncEvents)
3090 {
3091 /* Call WSPAsyncSelect on the accepted socket too */
3092 ErrorCode = SockAsyncSelectHelper(AcceptedSocket,
3093 hWnd,
3094 wMsg,
3095 AsyncEvents);
3096 }
3097 else if (NetworkEvents)
3098 {
3099 /* WSPEventSelect was enabled instead, call it on the new socket */
3100 ErrorCode = SockEventSelectHelper(AcceptedSocket,
3101 EventObject,
3102 NetworkEvents);
3103 }
3104
3105 /* Check for failure */
3106 if (ErrorCode != NO_ERROR) return ErrorCode;
3107
3108 /* Set the new context in AFD */
3109 ErrorCode = SockSetHandleContext(AcceptedSocket);
3110 if (ErrorCode != NO_ERROR) return ErrorCode;
3111
3112 /* Return success*/
3113 return NO_ERROR;
3114 }
3115
3116 SOCKET
3117 WSPAPI
3118 WSPAccept(SOCKET Handle,
3119 SOCKADDR FAR * SocketAddress,
3120 LPINT SocketAddressLength,
3121 LPCONDITIONPROC lpfnCondition,
3122 DWORD_PTR dwCallbackData,
3123 LPINT lpErrno)
3124 {
3125 INT ErrorCode, ReturnValue;
3126 PSOCKET_INFORMATION Socket, AcceptedSocket = NULL;
3127 PWINSOCK_TEB_DATA ThreadData;
3128 CHAR AfdAcceptBuffer[32];
3129 PAFD_RECEIVED_ACCEPT_DATA ReceivedAcceptData = NULL;
3130 ULONG ReceiveBufferSize;
3131 FD_SET ReadFds;
3132 TIMEVAL Timeout;
3133 NTSTATUS Status;
3134 IO_STATUS_BLOCK IoStatusBlock;
3135 ULONG AddressBufferSize;
3136 CHAR AddressBuffer[sizeof(SOCKADDR)];
3137 PVOID SockAddress;
3138 ULONG ConnectDataSize;
3139 PVOID ConnectData = NULL;
3140 AFD_PENDING_ACCEPT_DATA PendingAcceptData;
3141 INT AddressSize;
3142 PVOID CalleeDataBuffer = NULL;
3143 WSABUF CallerId, CalleeId, CallerData, CalleeData;
3144 GROUP GroupId;
3145 LPQOS Qos = NULL, GroupQos = NULL;
3146 BOOLEAN ValidGroup = TRUE;
3147 AFD_DEFER_ACCEPT_DATA DeferData;
3148 ULONG BytesReturned;
3149 SOCKET AcceptedHandle = INVALID_SOCKET;
3150 AFD_ACCEPT_DATA AcceptData;
3151
3152 /* Enter prolog */
3153 ErrorCode = SockEnterApiFast(&ThreadData);
3154 if (ErrorCode != NO_ERROR)
3155 {
3156 /* Fail */
3157 *lpErrno = ErrorCode;
3158 return SOCKET_ERROR;
3159 }
3160
3161 /* Get the socket structure */
3162 Socket = SockFindAndReferenceSocket(Handle, TRUE);
3163 if (!Socket)
3164 {
3165 /* Fail */
3166 ErrorCode = WSAENOTSOCK;
3167 goto error;
3168 }
3169
3170 /* Lock the socket */
3171 EnterCriticalSection(&Socket->Lock);
3172
3173 /* Invalid for datagram sockets */
3174 if (MSAFD_IS_DGRAM_SOCK(Socket))
3175 {
3176 /* Fail */
3177 ErrorCode = WSAEOPNOTSUPP;
3178 goto error;
3179 }
3180
3181 /* Only valid if the socket is listening */
3182 if (!Socket->SharedData.Listening)
3183 {
3184 /* Fail */
3185 ErrorCode = WSAEINVAL;
3186 goto error;
3187 }
3188
3189 /* Validate address length */
3190 if (SocketAddressLength &&
3191 (Socket->HelperData->MinWSAddressLength > *SocketAddressLength))
3192 {
3193 /* Fail */
3194 ErrorCode = WSAEINVAL;
3195 goto error;
3196 }
3197
3198 /* Calculate how much space we'll need for the Receive Buffer */
3199 ReceiveBufferSize = sizeof(AFD_RECEIVED_ACCEPT_DATA) +
3200 sizeof(TRANSPORT_ADDRESS) +
3201 Socket->HelperData->MaxTDIAddressLength;
3202
3203 /* Check if our stack buffer is large enough */
3204 if (ReceiveBufferSize <= sizeof(AfdAcceptBuffer))
3205 {
3206 /* Use the stack */
3207 ReceivedAcceptData = (PVOID)AfdAcceptBuffer;
3208 }
3209 else
3210 {
3211 /* Allocate from heap */
3212 ReceivedAcceptData = SockAllocateHeapRoutine(SockPrivateHeap,
3213 0,
3214 ReceiveBufferSize);
3215 if (!ReceivedAcceptData)
3216 {
3217 /* Fail */
3218 ErrorCode = WSAENOBUFS;
3219 goto error;
3220 }
3221 }
3222
3223 /* If this is non-blocking, make sure there's something for us to accept */
3224 if (Socket->SharedData.NonBlocking)
3225 {
3226 /* Set up a nonblocking select */
3227 FD_ZERO(&ReadFds);
3228 FD_SET(Handle, &ReadFds);
3229 Timeout.tv_sec = 0;
3230 Timeout.tv_usec = 0;
3231
3232 /* See if there's any data */
3233 ReturnValue = WSPSelect(1,
3234 &ReadFds,
3235 NULL,
3236 NULL,
3237 &Timeout,
3238 lpErrno);
3239 if (ReturnValue == SOCKET_ERROR)
3240 {
3241 /* Fail */
3242 ErrorCode = *lpErrno;
3243 goto error;
3244 }
3245
3246 /* Make sure we got a read back */
3247 if (!FD_ISSET(Handle, &ReadFds))
3248 {
3249 /* Fail */
3250 ErrorCode = WSAEWOULDBLOCK;
3251 goto error;
3252 }
3253 }
3254
3255 /* Send IOCTL */
3256 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
3257 ThreadData->EventHandle,
3258 NULL,
3259 NULL,
3260 &IoStatusBlock,
3261 IOCTL_AFD_WAIT_FOR_LISTEN,
3262 NULL,
3263 0,
3264 ReceivedAcceptData,
3265 ReceiveBufferSize);
3266 /* Check if we need to wait */
3267 if (Status == STATUS_PENDING)
3268 {
3269 /* Wait for completion outside the lock */
3270 LeaveCriticalSection(&Socket->Lock);
3271 SockWaitForSingleObject(ThreadData->EventHandle,
3272 Handle,
3273 MAYBE_BLOCKING_HOOK,
3274 NO_TIMEOUT);
3275 EnterCriticalSection(&Socket->Lock);
3276
3277 /* Get new status */
3278 Status = IoStatusBlock.Status;
3279 }
3280
3281 /* Check for error */
3282 if (!NT_SUCCESS(Status))
3283 {
3284 /* Fail */
3285 ErrorCode = NtStatusToSocketError(Status);
3286 goto error;
3287 }
3288
3289 /* Check if we got a condition callback */
3290 if (lpfnCondition)
3291 {
3292 /* Find out how much space we'll need for the address */
3293 AddressBufferSize = Socket->HelperData->MaxWSAddressLength;
3294
3295 /* Check if our local buffer is enough */
3296 if (AddressBufferSize <= sizeof(AddressBuffer))
3297 {
3298 /* It is, use the stack */
3299 SockAddress = (PVOID)AddressBuffer;
3300 }
3301 else
3302 {
3303 /* Allocate from heap */
3304 SockAddress = SockAllocateHeapRoutine(SockPrivateHeap,
3305 0,
3306 AddressBufferSize);
3307 if (!SockAddress)
3308 {
3309 /* Fail */
3310 ErrorCode = WSAENOBUFS;
3311 goto error;
3312 }
3313 }
3314
3315 /* Assume no connect data */
3316 ConnectDataSize = 0;
3317
3318 /* Make sure we support connect data */
3319 if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA))
3320 {
3321 /* Find out how much data is pending */
3322 PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
3323 PendingAcceptData.ReturnSize = TRUE;
3324
3325 /* Send IOCTL */
3326 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
3327 ThreadData->EventHandle,
3328 NULL,
3329 NULL,
3330 &IoStatusBlock,
3331 IOCTL_AFD_GET_PENDING_CONNECT_DATA,
3332 &PendingAcceptData,
3333 sizeof(PendingAcceptData),
3334 &PendingAcceptData,
3335 sizeof(PendingAcceptData));
3336 /* Check if we need to wait */
3337 if (Status == STATUS_PENDING)
3338 {
3339 /* Wait for completion */
3340 SockWaitForSingleObject(ThreadData->EventHandle,
3341 Handle,
3342 NO_BLOCKING_HOOK,
3343 NO_TIMEOUT);
3344 /* Get new status */
3345 Status = IoStatusBlock.Status;
3346 }
3347
3348 /* Check for error */
3349 if (!NT_SUCCESS(Status))
3350 {
3351 /* Fail */
3352 ErrorCode = NtStatusToSocketError(Status);
3353 goto error;
3354 }
3355
3356 /* How much data to allocate */
3357 ConnectDataSize = PtrToUlong(IoStatusBlock.Information);
3358 if (ConnectDataSize)
3359 {
3360 /* Allocate needed space */
3361 ConnectData = SockAllocateHeapRoutine(SockPrivateHeap,
3362 0,
3363 ConnectDataSize);
3364 if (!ConnectData)
3365 {
3366 /* Fail */
3367 ErrorCode = WSAENOBUFS;
3368 goto error;
3369 }
3370
3371 /* Setup the structure to actually get the data now */
3372 PendingAcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
3373 PendingAcceptData.ReturnSize = FALSE;
3374
3375 /* Send IOCTL */
3376 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
3377 ThreadData->EventHandle,
3378 NULL,
3379 NULL,
3380 &IoStatusBlock,
3381 IOCTL_AFD_GET_PENDING_CONNECT_DATA,
3382 &PendingAcceptData,
3383 sizeof(PendingAcceptData),
3384 ConnectData,
3385 ConnectDataSize);
3386 /* Check if we need to wait */
3387 if (Status == STATUS_PENDING)
3388 {
3389 /* Wait for completion */
3390 SockWaitForSingleObject(ThreadData->EventHandle,
3391 Handle,
3392 NO_BLOCKING_HOOK,
3393 NO_TIMEOUT);
3394 /* Get new status */
3395 Status = IoStatusBlock.Status;
3396 }
3397
3398 /* Check for error */
3399 if (!NT_SUCCESS(Status))
3400 {
3401 /* Fail */
3402 ErrorCode = NtStatusToSocketError(Status);
3403 goto error;
3404 }
3405 }
3406 }
3407
3408 if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED))
3409 {
3410 /* Set the accept data */
3411 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
3412 AcceptData.ListenHandle = Socket->WshContext.Handle;
3413
3414 /* Save it in the TEB */
3415 ThreadData->AcceptData = &AcceptData;
3416
3417 /* Send the IOCTL to get QOS Size */
3418 BytesReturned = 0;
3419 ReturnValue = WSPIoctl(Handle,
3420 SIO_GET_QOS,
3421 NULL,
3422 0,
3423 NULL,
3424 0,
3425 &BytesReturned,
3426 NULL,
3427 NULL,
3428 NULL,
3429 &ErrorCode);
3430
3431 /* Check if it failed (it should) */
3432 if (ReturnValue == SOCKET_ERROR)
3433 {
3434 /* Check if it failed because it had no buffer (it should) */
3435 if (ErrorCode == WSAEFAULT)
3436 {
3437 /* Make sure it told us how many bytes it needed */
3438 if (BytesReturned)
3439 {
3440 /* Allocate memory for it */
3441 Qos = SockAllocateHeapRoutine(SockPrivateHeap,
3442 0,
3443 BytesReturned);
3444 if (!Qos)
3445 {
3446 /* Fail */
3447 ErrorCode = WSAENOBUFS;
3448 goto error;
3449 }
3450
3451 /* Save the accept data and set the QoS */
3452 ThreadData->AcceptData = &AcceptData;
3453 ReturnValue = WSPIoctl(Handle,
3454 SIO_GET_QOS,
3455 NULL,
3456 0,
3457 Qos,
3458 BytesReturned,
3459 &BytesReturned,
3460 NULL,
3461 NULL,
3462 NULL,
3463 &ErrorCode);
3464 }
3465 }
3466 else
3467 {
3468 /* We got some other weird, error, fail. */
3469 goto error;
3470 }
3471 }
3472
3473 /* Save the accept in the TEB */
3474 ThreadData->AcceptData = &AcceptData;
3475
3476 /* Send the IOCTL to get Group QOS Size */
3477 BytesReturned = 0;
3478 ReturnValue = WSPIoctl(Handle,
3479 SIO_GET_GROUP_QOS,
3480 NULL,
3481 0,
3482 NULL,
3483 0,
3484 &BytesReturned,
3485 NULL,
3486 NULL,
3487 NULL,
3488 &ErrorCode);
3489
3490 /* Check if it failed (it should) */
3491 if (ReturnValue == SOCKET_ERROR)
3492 {
3493 /* Check if it failed because it had no buffer (it should) */
3494 if (ErrorCode == WSAEFAULT)
3495 {
3496 /* Make sure it told us how many bytes it needed */
3497 if (BytesReturned)
3498 {
3499 /* Allocate memory for it */
3500 GroupQos = SockAllocateHeapRoutine(SockPrivateHeap,
3501 0,
3502 BytesReturned);
3503 if (!GroupQos)
3504 {
3505 /* Fail */
3506 ErrorCode = WSAENOBUFS;
3507 goto error;
3508 }
3509
3510 /* Save the accept data and set the QoS */
3511 ThreadData->AcceptData = &AcceptData;
3512 ReturnValue = WSPIoctl(Handle,
3513 SIO_GET_QOS,
3514 NULL,
3515 0,
3516 GroupQos,
3517 BytesReturned,
3518 &BytesReturned,
3519 NULL,
3520 NULL,
3521 NULL,
3522 &ErrorCode);
3523 }
3524 }
3525 else
3526 {
3527 /* We got some other weird, error, fail. */
3528 goto error;
3529 }
3530 }
3531 }
3532
3533 /* Build Callee ID */
3534 CalleeId.buf = (PVOID)Socket->LocalAddress;
3535 CalleeId.len = Socket->SharedData.SizeOfLocalAddress;
3536
3537 /* Set up Address in SOCKADDR Format */
3538 SockBuildSockaddr((PSOCKADDR)SockAddress,
3539 &AddressSize,
3540 &ReceivedAcceptData->Address);
3541
3542 /* Build Caller ID */
3543 CallerId.buf = (PVOID)SockAddress;
3544 CallerId.len = AddressSize;
3545
3546 /* Build Caller Data */
3547 CallerData.buf = ConnectData;
3548 CallerData.len = ConnectDataSize;
3549
3550 /* Check if socket supports Conditional Accept */
3551 if (Socket->SharedData.UseDelayedAcceptance)
3552 {
3553 /* Allocate Buffer for Callee Data */
3554 CalleeDataBuffer = SockAllocateHeapRoutine(SockPrivateHeap, 0, 4096);
3555 if (CalleeDataBuffer)
3556 {
3557 /* Fill the structure */
3558 CalleeData.buf = CalleeDataBuffer;
3559 CalleeData.len = 4096;
3560 }
3561 else
3562 {
3563 /* Don't fail, just don't use this... */
3564 CalleeData.len = 0;
3565 }
3566 }
3567 else
3568 {
3569 /* Nothing */
3570 CalleeData.buf = NULL;
3571 CalleeData.len = 0;
3572 }
3573
3574 /* Call the Condition Function */
3575 ReturnValue = (lpfnCondition)(&CallerId,
3576 !CallerData.buf ? NULL : & CallerData,
3577 NULL,
3578 NULL,
3579 &CalleeId,
3580 !CalleeData.buf ? NULL: & CalleeData,
3581 &GroupId,
3582 dwCallbackData);
3583
3584 if ((ReturnValue == CF_ACCEPT) &&
3585 (GroupId) &&
3586 (GroupId != SG_UNCONSTRAINED_GROUP) &&
3587 (GroupId != SG_CONSTRAINED_GROUP))
3588 {
3589 /* Check for validity */
3590 ErrorCode = SockIsAddressConsistentWithConstrainedGroup(Socket,
3591 GroupId,
3592 SockAddress,
3593 AddressSize);
3594 ValidGroup = (ErrorCode == NO_ERROR);
3595 }
3596
3597 /* Check if the address was from the heap */
3598 if (SockAddress != AddressBuffer)
3599 {
3600 /* Free it */
3601 RtlFreeHeap(SockPrivateHeap, 0, SockAddress);
3602 }
3603
3604 /* Check if it was accepted */
3605 if (ReturnValue == CF_ACCEPT)
3606 {
3607 /* Check if the group is invalid, however */
3608 if (!ValidGroup) goto error;
3609
3610 /* Now check if QOS is supported */
3611 if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED))
3612 {
3613 /* Check if we had Qos */
3614 if (Qos)
3615 {
3616 /* Set the accept data */
3617 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
3618 AcceptData.ListenHandle = Socket->WshContext.Handle;
3619
3620 /* Save it in the TEB */
3621 ThreadData->AcceptData = &AcceptData;
3622
3623 /* Send the IOCTL */
3624 BytesReturned = 0;
3625 ReturnValue = WSPIoctl(Handle,
3626 SIO_SET_QOS,
3627 Qos,
3628 sizeof(*Qos),
3629 NULL,
3630 0,
3631 &BytesReturned,
3632 NULL,
3633 NULL,
3634 NULL,
3635 &ErrorCode);
3636 if (ReturnValue == SOCKET_ERROR) goto error;
3637 }
3638
3639 /* Check if we had Group Qos */
3640 if (GroupQos)
3641 {
3642 /* Set the accept data */
3643 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
3644 AcceptData.ListenHandle = Socket->WshContext.Handle;
3645
3646 /* Save it in the TEB */
3647 ThreadData->AcceptData = &AcceptData;
3648
3649 /* Send the IOCTL */
3650 ReturnValue = WSPIoctl(Handle,
3651 SIO_SET_GROUP_QOS,
3652 GroupQos,
3653 sizeof(*GroupQos),
3654 NULL,
3655 0,
3656 &BytesReturned,
3657 NULL,
3658 NULL,
3659 NULL,
3660 &ErrorCode);
3661 if (ReturnValue == SOCKET_ERROR) goto error;
3662 }
3663 }
3664
3665 /* Check if delayed acceptance is used and we have callee data */
3666 if ((Socket->HelperData->UseDelayedAcceptance) && (CalleeData.len))
3667 {
3668 /* Save the accept data in the TEB */
3669 ThreadData->AcceptData = &AcceptData;
3670
3671 /* Set the connect data */
3672 ErrorCode = SockGetConnectData(Socket,
3673 IOCTL_AFD_SET_CONNECT_DATA,
3674 CalleeData.buf,
3675 CalleeData.len,
3676 NULL);
3677 if (ErrorCode == SOCKET_ERROR) goto error;
3678 }
3679 }
3680 else
3681 {
3682 /* Callback rejected. Build Defer Structure */
3683 DeferData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
3684 DeferData.RejectConnection = (ReturnValue == CF_REJECT);
3685
3686 /* Send IOCTL */
3687 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
3688 ThreadData->EventHandle,
3689 NULL,
3690 NULL,
3691 &IoStatusBlock,
3692 IOCTL_AFD_DEFER_ACCEPT,
3693 &DeferData,
3694 sizeof(DeferData),
3695 NULL,
3696 0);
3697 /* Check for error */
3698 if (!NT_SUCCESS(Status))
3699 {
3700 /* Fail */
3701 ErrorCode = NtStatusToSocketError(Status);
3702 goto error;
3703 }
3704
3705 if (ReturnValue == CF_REJECT)
3706 {
3707 /* The connection was refused */
3708 ErrorCode = WSAECONNREFUSED;
3709 }
3710 else
3711 {
3712 /* The connection was deferred */
3713 ErrorCode = WSATRY_AGAIN;
3714 }
3715
3716 /* Fail */
3717 goto error;
3718 }
3719 }
3720
3721 /* Create a new Socket */
3722 ErrorCode = SockSocket(Socket->SharedData.AddressFamily,
3723 Socket->SharedData.SocketType,
3724 Socket->SharedData.Protocol,
3725 &Socket->ProviderId,
3726 GroupId,
3727 Socket->SharedData.CreateFlags,
3728 Socket->SharedData.ProviderFlags,
3729 Socket->SharedData.ServiceFlags1,
3730 Socket->SharedData.CatalogEntryId,
3731 &AcceptedSocket);
3732 if (ErrorCode != NO_ERROR)
3733 {
3734 /* Fail */
3735 goto error;
3736 }
3737
3738 /* Set up the Accept Structure */
3739 AcceptData.ListenHandle = AcceptedSocket->WshContext.Handle;
3740 AcceptData.SequenceNumber = ReceivedAcceptData->SequenceNumber;
3741
3742 /* Build the socket address */
3743 SockBuildSockaddr(AcceptedSocket->RemoteAddress,
3744 &AcceptedSocket->SharedData.SizeOfRemoteAddress,
3745 &ReceivedAcceptData->Address);
3746
3747 /* Copy the local address */
3748 RtlCopyMemory(AcceptedSocket->LocalAddress,
3749 Socket->LocalAddress,
3750 Socket->SharedData.SizeOfLocalAddress);
3751 AcceptedSocket->SharedData.SizeOfLocalAddress = Socket->SharedData.SizeOfLocalAddress;
3752
3753 /* We can release the accepted socket's lock now */
3754 LeaveCriticalSection(&AcceptedSocket->Lock);
3755
3756 /* Send IOCTL to Accept */
3757 AcceptData.UseSAN = SockSanEnabled;
3758 Status = NtDeviceIoControlFile(Socket->WshContext.Handle,
3759 ThreadData->EventHandle,
3760 NULL,
3761 NULL,
3762 &IoStatusBlock,
3763 IOCTL_AFD_ACCEPT,
3764 &AcceptData,
3765 sizeof(AcceptData),
3766 NULL,
3767 0);
3768 /* Check if we need to wait */
3769 if (Status == STATUS_PENDING)
3770 {
3771 /* Wait for completion outside the lock */
3772 LeaveCriticalSection(&Socket->Lock);
3773 SockWaitForSingleObject(ThreadData->EventHandle,
3774 Handle,
3775 MAYBE_BLOCKING_HOOK,
3776 NO_TIMEOUT);
3777 EnterCriticalSection(&Socket->Lock);
3778
3779 /* Get new status */
3780 Status = IoStatusBlock.Status;
3781 }
3782
3783 /* Check for error */
3784 if (!NT_SUCCESS(Status))
3785 {
3786 /* Fail */
3787 ErrorCode = NtStatusToSocketError(Status);
3788 goto error;
3789 }
3790
3791 /* Notify the helper DLL */
3792 ErrorCode = SockNotifyHelperDll(AcceptedSocket, WSH_NOTIFY_ACCEPT);
3793 if (ErrorCode != NO_ERROR) goto error;
3794
3795 /* If the caller sent a socket address pointer and length */
3796 if (SocketAddress && SocketAddressLength)
3797 {
3798 /* Return the address in its buffer */
3799 ErrorCode = SockBuildSockaddr(SocketAddress,
3800 SocketAddressLength,
3801 &ReceivedAcceptData->Address);
3802 if (ErrorCode != NO_ERROR) goto error;
3803 }
3804
3805 /* Check if async select was active */
3806 if (SockAsyncSelectCalled)
3807 {
3808 /* Re-enable the regular accept event */
3809 SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
3810 }
3811
3812 /* Finally, do the internal core accept code */
3813 ErrorCode = SockCoreAccept(Socket, AcceptedSocket);
3814 if (ErrorCode != NO_ERROR) goto error;
3815
3816 /* Call WPU to tell it about the new handle */
3817 AcceptedHandle = SockUpcallTable->lpWPUModifyIFSHandle(AcceptedSocket->SharedData.CatalogEntryId,
3818 (SOCKET)AcceptedSocket->WshContext.Handle,
3819 &ErrorCode);
3820
3821 /* Dereference the socket and clear its pointer for error code logic */
3822 SockDereferenceSocket(Socket);
3823 Socket = NULL;
3824
3825 error:
3826
3827 /* Check if we have a socket here */
3828 if (Socket)
3829 {
3830 /* Check if async select was active */
3831 if (SockAsyncSelectCalled)
3832 {
3833 /* Re-enable the regular accept event */
3834 SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
3835 }
3836
3837 /* Unlock and dereference it */
3838 LeaveCriticalSection(&Socket->Lock);
3839 SockDereferenceSocket(Socket);
3840 }
3841
3842 /* Check if we got the accepted socket */
3843 if (AcceptedSocket)
3844 {
3845 /* Check if the accepted socket also has a handle */
3846 if (ErrorCode == NO_ERROR)
3847 {
3848 /* Close the socket */
3849 SockCloseSocket(AcceptedSocket);
3850 }
3851
3852 /* Dereference it */
3853 SockDereferenceSocket(AcceptedSocket);
3854 }
3855
3856 /* Check if the accept buffer was from the heap */
3857 if (ReceivedAcceptData && (ReceivedAcceptData != (PVOID)AfdAcceptBuffer))
3858 {
3859 /* Free it */
3860 RtlFreeHeap(SockPrivateHeap, 0, ReceivedAcceptData);
3861 }
3862
3863 /* Check if we have a connect data buffer */
3864 if (ConnectData)
3865 {
3866 /* Free it */
3867 RtlFreeHeap(SockPrivateHeap, 0, ConnectData);
3868 }
3869
3870 /* Check if we have a callee data buffer */
3871 if (CalleeDataBuffer)
3872 {
3873 /* Free it */
3874 RtlFreeHeap(SockPrivateHeap, 0, CalleeDataBuffer);
3875 }
3876
3877 /* Check if we have allocated QOS structures */
3878 if (Qos)
3879 {
3880 /* Free it */
3881 RtlFreeHeap(SockPrivateHeap, 0, Qos);
3882 }
3883 if (GroupQos)
3884 {
3885 /* Free it */
3886 RtlFreeHeap(SockPrivateHeap, 0, GroupQos);
3887 }
3888
3889 /* Check for error */
3890 if (ErrorCode != NO_ERROR)
3891 {
3892 /* Fail */
3893 *lpErrno = ErrorCode;
3894 return INVALID_SOCKET;
3895 }
3896
3897 /* Return the new handle */
3898 return AcceptedHandle;
3899 }
3900