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
8 /* INCLUDES ******************************************************************/
11 #define MSAFD_CHECK_EVENT(e, s) \
12 (!(s->SharedData.AsyncDisabledEvents & e) && \
13 (s->SharedData.AsyncEvents & e))
15 #define HANDLES_IN_SET(s) \
16 s == NULL ? 0 : (s->fd_count & 0xFFFF)
18 /* DATA **********************************************************************/
20 HANDLE SockAsyncSelectHelperHandle
;
21 BOOLEAN SockAsyncSelectCalled
;
23 /* FUNCTIONS *****************************************************************/
27 SockCheckAndInitAsyncSelectHelper(VOID
)
29 UNICODE_STRING AfdHelper
;
30 OBJECT_ATTRIBUTES ObjectAttributes
;
31 IO_STATUS_BLOCK IoStatusBlock
;
33 FILE_COMPLETION_INFORMATION CompletionInfo
;
34 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags
;
36 /* First, make sure we're not already intialized */
37 if (SockAsyncSelectHelperHandle
) return TRUE
;
39 /* Acquire the global lock */
40 SockAcquireRwLockExclusive(&SocketGlobalLock
);
42 /* Check again, under the lock */
43 if (SockAsyncSelectHelperHandle
)
45 /* Return without lock */
46 SockReleaseRwLockExclusive(&SocketGlobalLock
);
50 /* Set up Handle Name and Object */
51 RtlInitUnicodeString(&AfdHelper
, L
"\\Device\\Afd\\AsyncSelectHlp" );
52 InitializeObjectAttributes(&ObjectAttributes
,
54 OBJ_INHERIT
| OBJ_CASE_INSENSITIVE
,
58 /* Open the Handle to AFD */
59 Status
= NtCreateFile(&SockAsyncSelectHelperHandle
,
60 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
65 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
70 if (!NT_SUCCESS(Status
))
72 /* Return without lock */
73 SockReleaseRwLockExclusive(&SocketGlobalLock
);
77 /* Check if the port exists, and if not, create it */
78 if (SockAsyncQueuePort
) SockCreateAsyncQueuePort();
81 * Now Set up the Completion Port Information
82 * This means that whenever a Poll is finished, the routine will be executed
84 CompletionInfo
.Port
= SockAsyncQueuePort
;
85 CompletionInfo
.Key
= SockAsyncSelectCompletion
;
86 Status
= NtSetInformationFile(SockAsyncSelectHelperHandle
,
89 sizeof(CompletionInfo
),
90 FileCompletionInformation
);
92 /* Protect the Handle */
93 HandleFlags
.ProtectFromClose
= TRUE
;
94 HandleFlags
.Inherit
= FALSE
;
95 Status
= NtSetInformationObject(SockAsyncQueuePort
,
96 ObjectHandleFlagInformation
,
101 * Set this variable to true so that Send/Recv/Accept will know whether
102 * to renable disabled events
104 SockAsyncSelectCalled
= TRUE
;
106 /* Release lock and return */
107 SockReleaseRwLockExclusive(&SocketGlobalLock
);
113 SockAsyncSelectCompletion(PVOID Context
,
114 PIO_STATUS_BLOCK IoStatusBlock
)
116 PASYNC_DATA AsyncData
= Context
;
117 PSOCKET_INFORMATION Socket
= AsyncData
->ParentSocket
;
121 /* Acquire the socket lock */
122 EnterCriticalSection(&Socket
->Lock
);
124 /* Check if the socket was closed or the I/O cancelled */
125 if ((Socket
->SharedData
.State
== SocketClosed
) ||
126 (IoStatusBlock
->Status
== STATUS_CANCELLED
))
129 LeaveCriticalSection(&Socket
->Lock
);
133 /* Check if the Sequence Number Changed behind our back */
134 if (AsyncData
->SequenceNumber
!= Socket
->SharedData
.SequenceNumber
)
137 LeaveCriticalSection(&Socket
->Lock
);
141 /* Check we were manually called b/c of a failure */
142 if (!NT_SUCCESS(IoStatusBlock
->Status
))
144 /* Get the error and tell WPU about it */
145 ErrorCode
= NtStatusToSocketError(IoStatusBlock
->Status
);
146 SockUpcallTable
->lpWPUPostMessage(Socket
->SharedData
.hWnd
,
147 Socket
->SharedData
.wMsg
,
149 WSAMAKESELECTREPLY(0, ErrorCode
));
152 LeaveCriticalSection(&Socket
->Lock
);
156 /* Select the event bits */
157 Events
= AsyncData
->AsyncSelectInfo
.Handles
[0].Events
;
159 /* Check for receive event */
160 if (MSAFD_CHECK_EVENT(FD_READ
, Socket
) && (Events
& AFD_EVENT_RECEIVE
))
162 /* Make the Notifcation */
163 SockUpcallTable
->lpWPUPostMessage(Socket
->SharedData
.hWnd
,
164 Socket
->SharedData
.wMsg
,
166 WSAMAKESELECTREPLY(FD_READ
, 0));
168 /* Disable this event until the next read(); */
169 Socket
->SharedData
.AsyncDisabledEvents
|= FD_READ
;
172 /* Check for oob receive event */
173 if (MSAFD_CHECK_EVENT(FD_OOB
, Socket
) && (Events
& AFD_EVENT_OOB_RECEIVE
))
175 /* Make the Notifcation */
176 SockUpcallTable
->lpWPUPostMessage(Socket
->SharedData
.hWnd
,
177 Socket
->SharedData
.wMsg
,
179 WSAMAKESELECTREPLY(FD_OOB
, 0));
181 /* Disable this event until the next read(); */
182 Socket
->SharedData
.AsyncDisabledEvents
|= FD_OOB
;
185 /* Check for write event */
186 if (MSAFD_CHECK_EVENT(FD_WRITE
, Socket
) && (Events
& AFD_EVENT_SEND
))
188 /* Make the Notifcation */
189 SockUpcallTable
->lpWPUPostMessage(Socket
->SharedData
.hWnd
,
190 Socket
->SharedData
.wMsg
,
192 WSAMAKESELECTREPLY(FD_WRITE
, 0));
194 /* Disable this event until the next read(); */
195 Socket
->SharedData
.AsyncDisabledEvents
|= FD_WRITE
;
198 /* Check for accept event */
199 if (MSAFD_CHECK_EVENT(FD_ACCEPT
, Socket
) && (Events
& AFD_EVENT_ACCEPT
))
201 /* Make the Notifcation */
202 SockUpcallTable
->lpWPUPostMessage(Socket
->SharedData
.hWnd
,
203 Socket
->SharedData
.wMsg
,
205 WSAMAKESELECTREPLY(FD_ACCEPT
, 0));
207 /* Disable this event until the next read(); */
208 Socket
->SharedData
.AsyncDisabledEvents
|= FD_ACCEPT
;
211 /* Check for close events */
212 if (MSAFD_CHECK_EVENT(FD_CLOSE
, Socket
) && ((Events
& AFD_EVENT_ACCEPT
) ||
213 (Events
& AFD_EVENT_ABORT
) ||
214 (Events
& AFD_EVENT_CLOSE
)))
216 /* Make the Notifcation */
217 SockUpcallTable
->lpWPUPostMessage(Socket
->SharedData
.hWnd
,
218 Socket
->SharedData
.wMsg
,
220 WSAMAKESELECTREPLY(FD_CLOSE
, 0));
222 /* Disable this event until the next read(); */
223 Socket
->SharedData
.AsyncDisabledEvents
|= FD_CLOSE
;
226 /* Check for QOS event */
227 if (MSAFD_CHECK_EVENT(FD_QOS
, Socket
) && (Events
& AFD_EVENT_QOS
))
229 /* Make the Notifcation */
230 SockUpcallTable
->lpWPUPostMessage(Socket
->SharedData
.hWnd
,
231 Socket
->SharedData
.wMsg
,
233 WSAMAKESELECTREPLY(FD_QOS
, 0));
235 /* Disable this event until the next read(); */
236 Socket
->SharedData
.AsyncDisabledEvents
|= FD_QOS
;
239 /* Check for Group QOS event */
240 if (MSAFD_CHECK_EVENT(FD_GROUP_QOS
, Socket
) && (Events
& AFD_EVENT_GROUP_QOS
))
242 /* Make the Notifcation */
243 SockUpcallTable
->lpWPUPostMessage(Socket
->SharedData
.hWnd
,
244 Socket
->SharedData
.wMsg
,
246 WSAMAKESELECTREPLY(FD_GROUP_QOS
, 0));
248 /* Disable this event until the next read(); */
249 Socket
->SharedData
.AsyncDisabledEvents
|= FD_GROUP_QOS
;
252 /* Check for Routing Interface Change event */
253 if (MSAFD_CHECK_EVENT(FD_ROUTING_INTERFACE_CHANGE
, Socket
) &&
254 (Events
& AFD_EVENT_ROUTING_INTERFACE_CHANGE
))
256 /* Make the Notifcation */
257 SockUpcallTable
->lpWPUPostMessage(Socket
->SharedData
.hWnd
,
258 Socket
->SharedData
.wMsg
,
260 WSAMAKESELECTREPLY(FD_ROUTING_INTERFACE_CHANGE
, 0));
262 /* Disable this event until the next read(); */
263 Socket
->SharedData
.AsyncDisabledEvents
|= FD_ROUTING_INTERFACE_CHANGE
;
266 /* Check for Address List Change event */
267 if (MSAFD_CHECK_EVENT(FD_ADDRESS_LIST_CHANGE
, Socket
) &&
268 (Events
& AFD_EVENT_ADDRESS_LIST_CHANGE
))
270 /* Make the Notifcation */
271 SockUpcallTable
->lpWPUPostMessage(Socket
->SharedData
.hWnd
,
272 Socket
->SharedData
.wMsg
,
274 WSAMAKESELECTREPLY(FD_ADDRESS_LIST_CHANGE
, 0));
276 /* Disable this event until the next read(); */
277 Socket
->SharedData
.AsyncDisabledEvents
|= FD_ADDRESS_LIST_CHANGE
;
280 /* Check if there are any events left for us to check */
281 if (!((Socket
->SharedData
.AsyncEvents
) &
282 (~Socket
->SharedData
.AsyncDisabledEvents
)))
284 /* Nothing left, release lock and return */
285 LeaveCriticalSection(&Socket
->Lock
);
290 SockProcessAsyncSelect(Socket
, AsyncData
);
292 /* Leave lock and return */
293 LeaveCriticalSection(&Socket
->Lock
);
297 /* Dereference the socket and free the Async Data */
298 SockDereferenceSocket(Socket
);
299 RtlFreeHeap(SockPrivateHeap
, 0, AsyncData
);
301 /* Dereference this thread and return */
302 InterlockedDecrement(&SockAsyncThreadReferenceCount
);
308 SockProcessAsyncSelect(PSOCKET_INFORMATION Socket
,
309 PASYNC_DATA AsyncData
)
311 ULONG lNetworkEvents
;
314 /* Set up the Async Data Event Info */
315 AsyncData
->AsyncSelectInfo
.Timeout
.HighPart
= 0x7FFFFFFF;
316 AsyncData
->AsyncSelectInfo
.Timeout
.LowPart
= 0xFFFFFFFF;
317 AsyncData
->AsyncSelectInfo
.HandleCount
= 1;
318 AsyncData
->AsyncSelectInfo
.Exclusive
= TRUE
;
319 AsyncData
->AsyncSelectInfo
.Handles
[0].Handle
= (SOCKET
)Socket
->WshContext
.Handle
;
320 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
= 0;
322 /* Remove unwanted events */
323 lNetworkEvents
= Socket
->SharedData
.AsyncEvents
&
324 (~Socket
->SharedData
.AsyncDisabledEvents
);
326 /* Set Events to wait for */
327 if (lNetworkEvents
& FD_READ
)
329 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_RECEIVE
;
331 if (lNetworkEvents
& FD_WRITE
)
333 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_SEND
;
335 if (lNetworkEvents
& FD_OOB
)
337 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_OOB_RECEIVE
;
339 if (lNetworkEvents
& FD_ACCEPT
)
341 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_ACCEPT
;
343 if (lNetworkEvents
& FD_CLOSE
)
345 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_DISCONNECT
|
349 if (lNetworkEvents
& FD_QOS
)
351 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_QOS
;
353 if (lNetworkEvents
& FD_GROUP_QOS
)
355 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_GROUP_QOS
;
357 if (lNetworkEvents
& FD_ROUTING_INTERFACE_CHANGE
)
359 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_ROUTING_INTERFACE_CHANGE
;
361 if (lNetworkEvents
& FD_ADDRESS_LIST_CHANGE
)
363 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_ADDRESS_LIST_CHANGE
;
367 Status
= NtDeviceIoControlFile(SockAsyncSelectHelperHandle
,
371 &AsyncData
->IoStatusBlock
,
373 &AsyncData
->AsyncSelectInfo
,
374 sizeof(AsyncData
->AsyncSelectInfo
),
375 &AsyncData
->AsyncSelectInfo
,
376 sizeof(AsyncData
->AsyncSelectInfo
));
377 /* Check for failure */
378 if (NT_ERROR(Status
))
380 /* I/O Manager Won't call the completion routine; do it manually */
381 AsyncData
->IoStatusBlock
.Status
= Status
;
382 SockAsyncSelectCompletion(AsyncData
, &AsyncData
->IoStatusBlock
);
388 SockProcessQueuedAsyncSelect(PVOID Context
,
389 PIO_STATUS_BLOCK IoStatusBlock
)
391 PASYNC_DATA AsyncData
= Context
;
392 PSOCKET_INFORMATION Socket
= AsyncData
->ParentSocket
;
394 /* Lock the socket */
395 EnterCriticalSection(&Socket
->Lock
);
397 /* Make sure it's not closed */
398 if (Socket
->SharedData
.State
== SocketClosed
)
401 LeaveCriticalSection(&Socket
->Lock
);
405 /* Check if the Sequence Number changed by now */
406 if (AsyncData
->SequenceNumber
!= Socket
->SharedData
.SequenceNumber
)
409 LeaveCriticalSection(&Socket
->Lock
);
413 /* Check if select is needed */
414 if (!((Socket
->SharedData
.AsyncEvents
&
415 ~Socket
->SharedData
.AsyncDisabledEvents
)))
418 LeaveCriticalSection(&Socket
->Lock
);
422 /* Do the actual select */
423 SockProcessAsyncSelect(Socket
, AsyncData
);
426 LeaveCriticalSection(&Socket
->Lock
);
430 /* Dereference the socket and free the async data */
431 SockDereferenceSocket(Socket
);
432 RtlFreeHeap(SockPrivateHeap
, 0, AsyncData
);
434 /* Dereference this thread */
435 InterlockedDecrement(&SockAsyncThreadReferenceCount
);
440 SockReenableAsyncSelectEvent(IN PSOCKET_INFORMATION Socket
,
443 PASYNC_DATA AsyncData
;
446 /* Make sure the event is actually disabled */
447 if (!(Socket
->SharedData
.AsyncDisabledEvents
& Event
)) return NO_ERROR
;
449 /* Make sure we're not closed */
450 if (Socket
->SharedData
.State
== SocketClosed
) return NO_ERROR
;
453 Socket
->SharedData
.AsyncDisabledEvents
&= ~Event
;
455 /* Return if no more events are being polled */
456 if (!((Socket
->SharedData
.AsyncEvents
&
457 ~Socket
->SharedData
.AsyncDisabledEvents
)))
462 /* Allocate Async Data */
463 AsyncData
= SockAllocateHeapRoutine(SockPrivateHeap
, 0, sizeof(ASYNC_DATA
));
465 /* Increase the sequence number to stop anything else */
466 Socket
->SharedData
.SequenceNumber
++;
468 /* Set up the Async Data */
469 AsyncData
->ParentSocket
= Socket
;
470 AsyncData
->SequenceNumber
= Socket
->SharedData
.SequenceNumber
;
472 /* Begin Async Select by using I/O Completion */
473 Status
= NtSetIoCompletion(SockAsyncQueuePort
,
474 (PVOID
)&SockProcessQueuedAsyncSelect
,
478 if (!NT_SUCCESS(Status
))
480 /* Dereference the socket and fail */
481 SockDereferenceSocket(Socket
);
482 RtlFreeHeap(SockPrivateHeap
, 0, AsyncData
);
483 return NtStatusToSocketError(Status
);
492 SockAsyncSelectHelper(IN PSOCKET_INFORMATION Socket
,
497 PASYNC_DATA AsyncData
= NULL
;
502 /* Allocate the Async Data Structure to pass on to the Thread later */
503 AsyncData
= SockAllocateHeapRoutine(SockPrivateHeap
, 0, sizeof(*AsyncData
));
504 if (!AsyncData
) return WSAENOBUFS
;
506 /* Acquire socket lock */
507 EnterCriticalSection(&Socket
->Lock
);
509 /* Is there an active WSPEventSelect? */
510 if (Socket
->SharedData
.AsyncEvents
)
512 /* Call the helper to process it */
513 ErrorCode
= SockEventSelectHelper(Socket
, NULL
, 0);
514 if (ErrorCode
!= NO_ERROR
) goto error
;
517 /* Set Socket to Non-Blocking */
519 ErrorCode
= SockSetInformation(Socket
,
520 AFD_INFO_BLOCKING_MODE
,
524 if (ErrorCode
!= NO_ERROR
) goto error
;
526 /* AFD was notified, set it locally as well */
527 Socket
->SharedData
.NonBlocking
= TRUE
;
529 /* Store Socket Data */
530 Socket
->SharedData
.hWnd
= hWnd
;
531 Socket
->SharedData
.wMsg
= wMsg
;
532 Socket
->SharedData
.AsyncEvents
= lEvent
;
533 Socket
->SharedData
.AsyncDisabledEvents
= 0;
535 /* Check if the socket is not connected and not a datagram socket */
536 if ((!SockIsSocketConnected(Socket
)) && !MSAFD_IS_DGRAM_SOCK(Socket
))
538 /* Disable FD_WRITE for now, so we don't get it before FD_CONNECT */
539 Socket
->SharedData
.AsyncDisabledEvents
|= FD_WRITE
;
542 /* Increase the sequence number */
543 Socket
->SharedData
.SequenceNumber
++;
545 /* Return if there are no more Events */
546 if (!(Socket
->SharedData
.AsyncEvents
&
547 (~Socket
->SharedData
.AsyncDisabledEvents
)))
549 /* Release the lock, dereference the async thread and the socket */
550 LeaveCriticalSection(&Socket
->Lock
);
551 InterlockedDecrement(&SockAsyncThreadReferenceCount
);
552 SockDereferenceSocket(Socket
);
554 /* Free the Async Data */
555 RtlFreeHeap(SockPrivateHeap
, 0, AsyncData
);
559 /* Set up the Async Data */
560 AsyncData
->ParentSocket
= Socket
;
561 AsyncData
->SequenceNumber
= Socket
->SharedData
.SequenceNumber
;
563 /* Release the lock now */
564 LeaveCriticalSection(&Socket
->Lock
);
566 /* Begin Async Select by using I/O Completion */
567 Status
= NtSetIoCompletion(SockAsyncQueuePort
,
568 (PVOID
)&SockProcessQueuedAsyncSelect
,
572 if (!NT_SUCCESS(Status
))
574 /* Dereference the async thread and fail */
575 InterlockedDecrement(&SockAsyncThreadReferenceCount
);
576 ErrorCode
= NtStatusToSocketError(Status
);
580 /* Check for error */
581 if (ErrorCode
!= NO_ERROR
)
583 /* Free the async data */
584 RtlFreeHeap(SockPrivateHeap
, 0, AsyncData
);
590 /* Increment the socket reference */
591 InterlockedIncrement(&Socket
->RefCount
);
599 WSPAsyncSelect(IN SOCKET Handle
,
605 PSOCKET_INFORMATION Socket
;
607 PWINSOCK_TEB_DATA ThreadData
;
610 ErrorCode
= SockEnterApiFast(&ThreadData
);
611 if (ErrorCode
!= NO_ERROR
)
614 *lpErrno
= ErrorCode
;
618 /* Check for valid events */
619 if (lEvent
& ~FD_ALL_EVENTS
)
622 ErrorCode
= WSAEINVAL
;
626 /* Check for valid window handle */
630 ErrorCode
= WSAEINVAL
;
634 /* Create the Asynch Thread if Needed */
635 if (!SockCheckAndReferenceAsyncThread())
638 ErrorCode
= WSAENOBUFS
;
642 /* Open a Handle to AFD's Async Helper */
643 if (!SockCheckAndInitAsyncSelectHelper())
645 /* Dereference async thread and fail */
646 InterlockedDecrement(&SockAsyncThreadReferenceCount
);
647 ErrorCode
= WSAENOBUFS
;
651 /* Get the socket structure */
652 Socket
= SockFindAndReferenceSocket(Handle
, TRUE
);
656 ErrorCode
= WSAENOTSOCK
;
660 /* Call the helper to do the work */
661 ErrorCode
= SockAsyncSelectHelper(Socket
,
666 /* Dereference the socket */
667 SockDereferenceSocket(Socket
);
670 /* Check for error */
671 if (ErrorCode
!= NO_ERROR
)
674 *lpErrno
= ErrorCode
;
688 CONST LPTIMEVAL timeout
,
691 IO_STATUS_BLOCK IoStatusBlock
;
692 PAFD_POLL_INFO PollInfo
= NULL
;
694 CHAR PollBuffer
[sizeof(AFD_POLL_INFO
) + 3 * sizeof(AFD_HANDLE
)];
695 PAFD_HANDLE HandleArray
;
696 ULONG HandleCount
, OutCount
= 0;
697 ULONG PollBufferSize
;
699 PWINSOCK_TEB_DATA ThreadData
;
705 ErrorCode
= SockEnterApiFast(&ThreadData
);
706 if (ErrorCode
!= NO_ERROR
)
709 *lpErrno
= ErrorCode
;
713 /* How many sockets will we check? */
714 HandleCount
= HANDLES_IN_SET(readfds
) +
715 HANDLES_IN_SET(writefds
) +
716 HANDLES_IN_SET(exceptfds
);
718 /* Leave if none are */
719 if (!HandleCount
) return NO_ERROR
;
721 /* How much space will they require? */
722 PollBufferSize
= sizeof(*PollInfo
) + (HandleCount
* sizeof(AFD_HANDLE
));
724 /* Check if our stack is big enough to hold it */
725 if (PollBufferSize
<= sizeof(PollBuffer
))
728 PollInfo
= (PVOID
)PollBuffer
;
732 /* Allocate from heap instead */
733 PollInfo
= SockAllocateHeapRoutine(SockPrivateHeap
, 0, PollBufferSize
);
737 ErrorCode
= WSAENOBUFS
;
742 /* Number of handles for AFD to Check */
743 PollInfo
->HandleCount
= HandleCount
;
744 PollInfo
->Exclusive
= FALSE
;
745 HandleArray
= PollInfo
->Handles
;
747 /* Select the Read Events */
748 for (i
= 0; readfds
&& i
< (readfds
->fd_count
& 0xFFFF); i
++)
750 /* Fill out handle info */
751 HandleArray
->Handle
= (SOCKET
)readfds
->fd_array
[i
];
752 HandleArray
->Events
= AFD_EVENT_RECEIVE
|
753 AFD_EVENT_DISCONNECT
|
756 /* Move to the next one */
759 for (i
= 0; writefds
&& i
< (writefds
->fd_count
& 0xFFFF); i
++)
761 /* Fill out handle info */
762 HandleArray
->Handle
= (SOCKET
)writefds
->fd_array
[i
];
763 HandleArray
->Events
= AFD_EVENT_SEND
;
765 /* Move to the next one */
768 for (i
= 0; exceptfds
&& i
< (exceptfds
->fd_count
& 0xFFFF); i
++)
770 /* Fill out handle info */
771 HandleArray
->Handle
= (SOCKET
)exceptfds
->fd_array
[i
];
772 HandleArray
->Events
= AFD_EVENT_OOB_RECEIVE
| AFD_EVENT_CONNECT_FAIL
;
774 /* Move to the next one */
778 /* Check if a timeout was given */
781 /* Inifinte Timeout */
782 PollInfo
->Timeout
.u
.LowPart
= -1;
783 PollInfo
->Timeout
.u
.HighPart
= 0x7FFFFFFF;
787 /* Calculate microseconds */
788 uSec
= RtlEnlargedIntegerMultiply(timeout
->tv_usec
, -10);
790 /* Calculate seconds */
791 PollInfo
->Timeout
= RtlEnlargedIntegerMultiply(timeout
->tv_sec
,
792 -1 * 1000 * 1000 * 10);
794 /* Add microseconds */
795 PollInfo
->Timeout
.QuadPart
+= uSec
.QuadPart
;
799 Status
= NtDeviceIoControlFile((HANDLE
)PollInfo
->Handles
[0].Handle
,
800 ThreadData
->EventHandle
,
810 /* Check if we have to wait */
811 if (Status
== STATUS_PENDING
)
813 /* Check if we'll call the blocking hook */
814 if (!PollInfo
->Timeout
.QuadPart
) BlockType
= NO_BLOCKING_HOOK
;
816 /* Wait for completion */
817 SockWaitForSingleObject(ThreadData
->EventHandle
,
818 (SOCKET
)PollInfo
->Handles
[0].Handle
,
823 Status
= IoStatusBlock
.Status
;
826 /* Check for failure */
827 if (!NT_SUCCESS(Status
))
830 ErrorCode
= NtStatusToSocketError(Status
);
834 /* Clear the Structures */
835 if(readfds
) FD_ZERO(readfds
);
836 if(writefds
) FD_ZERO(writefds
);
837 if(exceptfds
) FD_ZERO(exceptfds
);
839 /* Get the handle info again */
840 HandleCount
= PollInfo
->HandleCount
;
841 HandleArray
= PollInfo
->Handles
;
843 /* Loop the Handles that got an event */
844 for (i
= 0; i
< HandleCount
; i
++)
846 /* Check for a match */
847 if (HandleArray
->Events
& AFD_EVENT_RECEIVE
)
849 /* Check if it's not already set */
850 if (!FD_ISSET((SOCKET
)HandleArray
->Handle
, readfds
))
852 /* Increase Handles with an Event */
855 /* Set this handle */
856 FD_SET((SOCKET
)HandleArray
->Handle
, readfds
);
859 /* Check for a match */
860 if (HandleArray
->Events
& AFD_EVENT_SEND
)
862 /* Check if it's not already set */
863 if (!FD_ISSET((SOCKET
)HandleArray
->Handle
, writefds
))
865 /* Increase Handles with an Event */
868 /* Set this handle */
869 FD_SET((SOCKET
)HandleArray
->Handle
, writefds
);
872 /* Check for a match */
873 if (HandleArray
->Events
& AFD_EVENT_OOB_RECEIVE
)
875 /* Check if it's not already set */
876 if (!FD_ISSET((SOCKET
)HandleArray
->Handle
, exceptfds
))
878 /* Increase Handles with an Event */
881 /* Set this handle */
882 FD_SET((SOCKET
)HandleArray
->Handle
, exceptfds
);
885 /* Check for a match */
886 if (HandleArray
->Events
& AFD_EVENT_ACCEPT
)
888 /* Check if it's not already set */
889 if (!FD_ISSET((SOCKET
)HandleArray
->Handle
, readfds
))
891 /* Increase Handles with an Event */
894 /* Set this handle */
895 FD_SET((SOCKET
)HandleArray
->Handle
, readfds
);
898 /* Check for a match */
899 if (HandleArray
->Events
& AFD_EVENT_CONNECT
)
901 /* Check if it's not already set */
902 if (!FD_ISSET((SOCKET
)HandleArray
->Handle
, writefds
))
904 /* Increase Handles with an Event */
907 /* Set this handle */
908 FD_SET((SOCKET
)HandleArray
->Handle
, writefds
);
911 /* Check for a match */
912 if (HandleArray
->Events
& AFD_EVENT_CONNECT_FAIL
)
914 /* Check if it's not already set */
915 if (!FD_ISSET((SOCKET
)HandleArray
->Handle
, exceptfds
))
917 /* Increase Handles with an Event */
920 /* Set this handle */
921 FD_SET((SOCKET
)HandleArray
->Handle
, exceptfds
);
924 /* Check for a match */
925 if (HandleArray
->Events
& AFD_EVENT_DISCONNECT
)
927 /* Check if it's not already set */
928 if (!FD_ISSET((SOCKET
)HandleArray
->Handle
, readfds
))
930 /* Increase Handles with an Event */
933 /* Set this handle */
934 FD_SET((SOCKET
)HandleArray
->Handle
, readfds
);
937 /* Check for a match */
938 if (HandleArray
->Events
& AFD_EVENT_ABORT
)
940 /* Check if it's not already set */
941 if (!FD_ISSET((SOCKET
)HandleArray
->Handle
, readfds
))
943 /* Increase Handles with an Event */
946 /* Set this handle */
947 FD_SET((SOCKET
)HandleArray
->Handle
, readfds
);
950 /* Check for a match */
951 if (HandleArray
->Events
& AFD_EVENT_CLOSE
)
953 /* Check if it's not already set */
954 if (!FD_ISSET((SOCKET
)HandleArray
->Handle
, readfds
))
956 /* Increase Handles with an Event */
959 /* Set this handle */
960 FD_SET((SOCKET
)HandleArray
->Handle
, readfds
);
964 /* Move to next entry */
970 /* Check if we should free the buffer */
971 if (PollInfo
&& (PollInfo
!= (PVOID
)PollBuffer
))
973 /* Free it from the heap */
974 RtlFreeHeap(SockPrivateHeap
, 0, PollInfo
);
977 /* Check for error */
978 if (ErrorCode
!= NO_ERROR
)
981 *lpErrno
= ErrorCode
;
985 /* Return the number of handles */