2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver DLL
5 * PURPOSE: DLL entry point
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Alex Ionescu (alex@relsoft.net)
9 * CSH 01/09-2000 Created
10 * Alex 16/07/2004 - Complete Rewrite
18 //DWORD DebugTraceLevel = DEBUG_ULTRA;
19 DWORD DebugTraceLevel
= 0;
23 WSPUPCALLTABLE Upcalls
;
24 LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest
;
25 ULONG SocketCount
= 0;
26 PSOCKET_INFORMATION
*Sockets
= NULL
;
27 LIST_ENTRY SockHelpersListHead
= { NULL
, NULL
};
28 ULONG SockAsyncThreadRefCount
;
29 HANDLE SockAsyncHelperAfdHandle
;
30 HANDLE SockAsyncCompletionPort
;
31 BOOLEAN SockAsyncSelectCalled
;
36 * FUNCTION: Creates a new socket
40 * protocol = Protocol type
41 * lpProtocolInfo = Pointer to protocol information
43 * dwFlags = Socket flags
44 * lpErrno = Address of buffer for error information
46 * Created socket, or INVALID_SOCKET if it could not be created
50 WSPSocket(int AddressFamily
,
53 LPWSAPROTOCOL_INFOW lpProtocolInfo
,
58 OBJECT_ATTRIBUTES Object
;
62 PAFD_CREATE_PACKET AfdPacket
;
64 PSOCKET_INFORMATION Socket
= NULL
, PrevSocket
= NULL
;
65 PFILE_FULL_EA_INFORMATION EABuffer
= NULL
;
66 PHELPER_DATA HelperData
;
67 PVOID HelperDLLContext
;
69 UNICODE_STRING TransportName
;
70 UNICODE_STRING DevName
;
71 LARGE_INTEGER GroupData
;
74 AFD_DbgPrint(MAX_TRACE
, ("Creating Socket, getting TDI Name\n"));
75 AFD_DbgPrint(MAX_TRACE
, ("AddressFamily (%d) SocketType (%d) Protocol (%d).\n",
76 AddressFamily
, SocketType
, Protocol
));
78 /* Get Helper Data and Transport */
79 Status
= SockGetTdiName (&AddressFamily
,
90 if (Status
!= NO_ERROR
)
92 AFD_DbgPrint(MID_TRACE
,("SockGetTdiName: Status %x\n", Status
));
97 RtlInitUnicodeString(&DevName
, L
"\\Device\\Afd\\Endpoint");
100 Socket
= HeapAlloc(GlobalHeap
, 0, sizeof(*Socket
));
101 RtlZeroMemory(Socket
, sizeof(*Socket
));
102 Socket
->RefCount
= 2;
104 Socket
->SharedData
.Listening
= FALSE
;
105 Socket
->SharedData
.State
= SocketOpen
;
106 Socket
->SharedData
.AddressFamily
= AddressFamily
;
107 Socket
->SharedData
.SocketType
= SocketType
;
108 Socket
->SharedData
.Protocol
= Protocol
;
109 Socket
->HelperContext
= HelperDLLContext
;
110 Socket
->HelperData
= HelperData
;
111 Socket
->HelperEvents
= HelperEvents
;
112 Socket
->LocalAddress
= &Socket
->WSLocalAddress
;
113 Socket
->SharedData
.SizeOfLocalAddress
= HelperData
->MaxWSAddressLength
;
114 Socket
->RemoteAddress
= &Socket
->WSRemoteAddress
;
115 Socket
->SharedData
.SizeOfRemoteAddress
= HelperData
->MaxWSAddressLength
;
116 Socket
->SharedData
.UseDelayedAcceptance
= HelperData
->UseDelayedAcceptance
;
117 Socket
->SharedData
.CreateFlags
= dwFlags
;
118 Socket
->SharedData
.CatalogEntryId
= lpProtocolInfo
->dwCatalogEntryId
;
119 Socket
->SharedData
.ServiceFlags1
= lpProtocolInfo
->dwServiceFlags1
;
120 Socket
->SharedData
.ProviderFlags
= lpProtocolInfo
->dwProviderFlags
;
121 Socket
->SharedData
.GroupID
= g
;
122 Socket
->SharedData
.GroupType
= 0;
123 Socket
->SharedData
.UseSAN
= FALSE
;
124 Socket
->SharedData
.NonBlocking
= FALSE
; /* Sockets start blocking */
125 Socket
->SanData
= NULL
;
127 /* Ask alex about this */
128 if( Socket
->SharedData
.SocketType
== SOCK_DGRAM
||
129 Socket
->SharedData
.SocketType
== SOCK_RAW
)
131 AFD_DbgPrint(MID_TRACE
,("Connectionless socket\n"));
132 Socket
->SharedData
.ServiceFlags1
|= XP1_CONNECTIONLESS
;
136 SizeOfPacket
= TransportName
.Length
+ sizeof(AFD_CREATE_PACKET
) + sizeof(WCHAR
);
139 SizeOfEA
= SizeOfPacket
+ sizeof(FILE_FULL_EA_INFORMATION
) + AFD_PACKET_COMMAND_LENGTH
;
141 /* Set up EA Buffer */
142 EABuffer
= HeapAlloc(GlobalHeap
, 0, SizeOfEA
);
143 RtlZeroMemory(EABuffer
, SizeOfEA
);
144 EABuffer
->NextEntryOffset
= 0;
146 EABuffer
->EaNameLength
= AFD_PACKET_COMMAND_LENGTH
;
147 RtlCopyMemory (EABuffer
->EaName
,
149 AFD_PACKET_COMMAND_LENGTH
+ 1);
150 EABuffer
->EaValueLength
= SizeOfPacket
;
152 /* Set up AFD Packet */
153 AfdPacket
= (PAFD_CREATE_PACKET
)(EABuffer
->EaName
+ EABuffer
->EaNameLength
+ 1);
154 AfdPacket
->SizeOfTransportName
= TransportName
.Length
;
155 RtlCopyMemory (AfdPacket
->TransportName
,
156 TransportName
.Buffer
,
157 TransportName
.Length
+ sizeof(WCHAR
));
158 AfdPacket
->GroupID
= g
;
160 /* Set up Endpoint Flags */
161 if ((Socket
->SharedData
.ServiceFlags1
& XP1_CONNECTIONLESS
) != 0)
163 if ((SocketType
!= SOCK_DGRAM
) && (SocketType
!= SOCK_RAW
))
165 /* Only RAW or UDP can be Connectionless */
168 AfdPacket
->EndpointFlags
|= AFD_ENDPOINT_CONNECTIONLESS
;
171 if ((Socket
->SharedData
.ServiceFlags1
& XP1_MESSAGE_ORIENTED
) != 0)
173 if (SocketType
== SOCK_STREAM
)
175 if ((Socket
->SharedData
.ServiceFlags1
& XP1_PSEUDO_STREAM
) == 0)
177 /* The Provider doesn't actually support Message Oriented Streams */
181 AfdPacket
->EndpointFlags
|= AFD_ENDPOINT_MESSAGE_ORIENTED
;
184 if (SocketType
== SOCK_RAW
) AfdPacket
->EndpointFlags
|= AFD_ENDPOINT_RAW
;
186 if (dwFlags
& (WSA_FLAG_MULTIPOINT_C_ROOT
|
187 WSA_FLAG_MULTIPOINT_C_LEAF
|
188 WSA_FLAG_MULTIPOINT_D_ROOT
|
189 WSA_FLAG_MULTIPOINT_D_LEAF
))
191 if ((Socket
->SharedData
.ServiceFlags1
& XP1_SUPPORT_MULTIPOINT
) == 0)
193 /* The Provider doesn't actually support Multipoint */
196 AfdPacket
->EndpointFlags
|= AFD_ENDPOINT_MULTIPOINT
;
198 if (dwFlags
& WSA_FLAG_MULTIPOINT_C_ROOT
)
200 if (((Socket
->SharedData
.ServiceFlags1
& XP1_MULTIPOINT_CONTROL_PLANE
) == 0)
201 || ((dwFlags
& WSA_FLAG_MULTIPOINT_C_LEAF
) != 0))
203 /* The Provider doesn't support Control Planes, or you already gave a leaf */
206 AfdPacket
->EndpointFlags
|= AFD_ENDPOINT_C_ROOT
;
209 if (dwFlags
& WSA_FLAG_MULTIPOINT_D_ROOT
)
211 if (((Socket
->SharedData
.ServiceFlags1
& XP1_MULTIPOINT_DATA_PLANE
) == 0)
212 || ((dwFlags
& WSA_FLAG_MULTIPOINT_D_LEAF
) != 0))
214 /* The Provider doesn't support Data Planes, or you already gave a leaf */
217 AfdPacket
->EndpointFlags
|= AFD_ENDPOINT_D_ROOT
;
221 /* Set up Object Attributes */
222 InitializeObjectAttributes (&Object
,
224 OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
,
228 /* Create the Socket as asynchronous. That means we have to block
229 ourselves after every call to NtDeviceIoControlFile. This is
230 because the kernel doesn't support overlapping synchronous I/O
231 requests (made from multiple threads) at this time (Sep 2005) */
233 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
238 FILE_SHARE_READ
| FILE_SHARE_WRITE
, FILE_OPEN_IF
,
244 Socket
->Handle
= (SOCKET
)Sock
;
246 /* XXX See if there's a structure we can reuse -- We need to do this
248 PrevSocket
= GetSocketStructure( (SOCKET
)Sock
);
252 RtlCopyMemory( PrevSocket
, Socket
, sizeof(*Socket
) );
253 RtlFreeHeap( GlobalHeap
, 0, Socket
);
257 /* Save Group Info */
260 GetSocketInformation(Socket
, AFD_INFO_GROUP_ID_TYPE
, 0, &GroupData
);
261 Socket
->SharedData
.GroupID
= GroupData
.u
.LowPart
;
262 Socket
->SharedData
.GroupType
= GroupData
.u
.HighPart
;
265 /* Get Window Sizes and Save them */
266 GetSocketInformation (Socket
,
267 AFD_INFO_SEND_WINDOW_SIZE
,
268 &Socket
->SharedData
.SizeOfSendBuffer
,
271 GetSocketInformation (Socket
,
272 AFD_INFO_RECEIVE_WINDOW_SIZE
,
273 &Socket
->SharedData
.SizeOfRecvBuffer
,
276 /* Save in Process Sockets List */
277 Sockets
[SocketCount
] = Socket
;
280 /* Create the Socket Context */
281 CreateContext(Socket
);
284 Upcalls
.lpWPUModifyIFSHandle(1, (SOCKET
)Sock
, lpErrno
);
286 /* Return Socket Handle */
287 AFD_DbgPrint(MID_TRACE
,("Success %x\n", Sock
));
292 AFD_DbgPrint(MID_TRACE
,("Ending %x\n", Status
));
297 return INVALID_SOCKET
;
301 DWORD
MsafdReturnWithErrno(NTSTATUS Status
,
304 LPDWORD ReturnedBytes
)
312 case STATUS_CANT_WAIT
:
313 *Errno
= WSAEWOULDBLOCK
;
316 *Errno
= WSAETIMEDOUT
;
319 /* Return Number of bytes Read */
321 *ReturnedBytes
= Received
;
323 case STATUS_END_OF_FILE
:
324 *Errno
= WSAESHUTDOWN
;
327 *Errno
= WSA_IO_PENDING
;
329 case STATUS_BUFFER_TOO_SMALL
:
330 case STATUS_BUFFER_OVERFLOW
:
331 DbgPrint("MSAFD: STATUS_BUFFER_TOO_SMALL/STATUS_BUFFER_OVERFLOW\n");
332 *Errno
= WSAEMSGSIZE
;
334 case STATUS_NO_MEMORY
: /* Fall through to STATUS_INSUFFICIENT_RESOURCES */
335 case STATUS_INSUFFICIENT_RESOURCES
:
336 DbgPrint("MSAFD: STATUS_NO_MEMORY/STATUS_INSUFFICIENT_RESOURCES\n");
337 *Errno
= WSA_NOT_ENOUGH_MEMORY
;
339 case STATUS_INVALID_CONNECTION
:
340 DbgPrint("MSAFD: STATUS_INVALID_CONNECTION\n");
341 *Errno
= WSAEAFNOSUPPORT
;
343 case STATUS_REMOTE_NOT_LISTENING
:
344 DbgPrint("MSAFD: STATUS_REMOTE_NOT_LISTENING\n");
345 *Errno
= WSAECONNRESET
;
347 case STATUS_FILE_CLOSED
:
348 DbgPrint("MSAFD: STATUS_FILE_CLOSED\n");
349 *Errno
= WSAENOTSOCK
;
351 case STATUS_INVALID_PARAMETER
:
352 DbgPrint("MSAFD: STATUS_INVALID_PARAMETER\n");
355 case STATUS_CANCELLED
:
356 DbgPrint("MSAFD: STATUS_CANCELLED\n");
357 *Errno
= WSAENOTSOCK
;
360 DbgPrint("MSAFD: Error %x is unknown\n", Status
);
367 return Status
== STATUS_SUCCESS
? 0 : SOCKET_ERROR
;
371 * FUNCTION: Closes an open socket
373 * s = Socket descriptor
374 * lpErrno = Address of buffer for error information
376 * NO_ERROR, or SOCKET_ERROR if the socket could not be closed
380 WSPCloseSocket(IN SOCKET Handle
,
383 IO_STATUS_BLOCK IoStatusBlock
;
384 PSOCKET_INFORMATION Socket
= NULL
;
387 AFD_DISCONNECT_INFO DisconnectInfo
;
388 SOCKET_STATE OldState
;
390 /* Create the Wait Event */
391 Status
= NtCreateEvent(&SockEvent
,
392 GENERIC_READ
| GENERIC_WRITE
,
397 if(!NT_SUCCESS(Status
))
400 /* Get the Socket Structure associate to this Socket*/
401 Socket
= GetSocketStructure(Handle
);
403 /* If a Close is already in Process, give up */
404 if (Socket
->SharedData
.State
== SocketClosed
)
407 *lpErrno
= WSAENOTSOCK
;
411 /* Set the state to close */
412 OldState
= Socket
->SharedData
.State
;
413 Socket
->SharedData
.State
= SocketClosed
;
415 /* If SO_LINGER is ON and the Socket is connected, we need to disconnect */
416 /* FIXME: Should we do this on Datagram Sockets too? */
417 if ((OldState
== SocketConnected
) && (Socket
->SharedData
.LingerData
.l_onoff
))
420 ULONG SendsInProgress
;
423 /* We need to respect the timeout */
425 LingerWait
= Socket
->SharedData
.LingerData
.l_linger
* 1000;
427 /* Loop until no more sends are pending, within the timeout */
430 /* Find out how many Sends are in Progress */
431 if (GetSocketInformation(Socket
,
432 AFD_INFO_SENDS_IN_PROGRESS
,
436 /* Bail out if anything but NO_ERROR */
441 /* Bail out if no more sends are pending */
442 if (!SendsInProgress
)
445 * We have to execute a sleep, so it's kind of like
446 * a block. If the socket is Nonblock, we cannot
447 * go on since asyncronous operation is expected
448 * and we cannot offer it
450 if (Socket
->SharedData
.NonBlocking
)
453 Socket
->SharedData
.State
= OldState
;
454 *lpErrno
= WSAEWOULDBLOCK
;
458 /* Now we can sleep, and decrement the linger wait */
460 * FIXME: It seems Windows does some funky acceleration
461 * since the waiting seems to be longer and longer. I
462 * don't think this improves performance so much, so we
463 * wait a fixed time instead.
466 LingerWait
-= SleepWait
;
470 * We have reached the timeout or sends are over.
471 * Disconnect if the timeout has been reached.
475 DisconnectInfo
.Timeout
= RtlConvertLongToLargeInteger(0);
476 DisconnectInfo
.DisconnectType
= AFD_DISCONNECT_ABORT
;
479 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
484 IOCTL_AFD_DISCONNECT
,
486 sizeof(DisconnectInfo
),
490 /* Wait for return */
491 if (Status
== STATUS_PENDING
)
493 WaitForSingleObject(SockEvent
, INFINITE
);
498 /* FIXME: We should notify the Helper DLL of WSH_NOTIFY_CLOSE */
501 Socket
->HelperContext
= NULL
;
502 Socket
->SharedData
.AsyncDisabledEvents
= -1;
503 NtClose(Socket
->TdiAddressHandle
);
504 Socket
->TdiAddressHandle
= NULL
;
505 NtClose(Socket
->TdiConnectionHandle
);
506 Socket
->TdiConnectionHandle
= NULL
;
508 /* Close the handle */
509 NtClose((HANDLE
)Handle
);
517 * FUNCTION: Associates a local address with a socket
519 * s = Socket descriptor
520 * name = Pointer to local address
521 * namelen = Length of name
522 * lpErrno = Address of buffer for error information
524 * 0, or SOCKET_ERROR if the socket could not be bound
528 WSPBind(SOCKET Handle
,
529 const struct sockaddr
*SocketAddress
,
530 int SocketAddressLength
,
533 IO_STATUS_BLOCK IOSB
;
534 PAFD_BIND_DATA BindData
;
535 PSOCKET_INFORMATION Socket
= NULL
;
537 UCHAR BindBuffer
[0x1A];
538 SOCKADDR_INFO SocketInfo
;
541 Status
= NtCreateEvent(&SockEvent
,
542 GENERIC_READ
| GENERIC_WRITE
,
547 if( !NT_SUCCESS(Status
) )
550 /* Get the Socket Structure associate to this Socket*/
551 Socket
= GetSocketStructure(Handle
);
553 /* Dynamic Structure...ugh */
554 BindData
= (PAFD_BIND_DATA
)BindBuffer
;
556 /* Set up Address in TDI Format */
557 BindData
->Address
.TAAddressCount
= 1;
558 BindData
->Address
.Address
[0].AddressLength
= SocketAddressLength
- sizeof(SocketAddress
->sa_family
);
559 BindData
->Address
.Address
[0].AddressType
= SocketAddress
->sa_family
;
560 RtlCopyMemory (BindData
->Address
.Address
[0].Address
,
561 SocketAddress
->sa_data
,
562 SocketAddressLength
- sizeof(SocketAddress
->sa_family
));
564 /* Get Address Information */
565 Socket
->HelperData
->WSHGetSockaddrType ((PSOCKADDR
)SocketAddress
,
569 /* Set the Share Type */
570 if (Socket
->SharedData
.ExclusiveAddressUse
)
572 BindData
->ShareType
= AFD_SHARE_EXCLUSIVE
;
574 else if (SocketInfo
.EndpointInfo
== SockaddrEndpointInfoWildcard
)
576 BindData
->ShareType
= AFD_SHARE_WILDCARD
;
578 else if (Socket
->SharedData
.ReuseAddresses
)
580 BindData
->ShareType
= AFD_SHARE_REUSE
;
584 BindData
->ShareType
= AFD_SHARE_UNIQUE
;
588 Status
= NtDeviceIoControlFile((HANDLE
)Socket
->Handle
,
595 0xA + Socket
->SharedData
.SizeOfLocalAddress
, /* Can't figure out a way to calculate this in C*/
597 0xA + Socket
->SharedData
.SizeOfLocalAddress
); /* Can't figure out a way to calculate this C */
599 /* Wait for return */
600 if (Status
== STATUS_PENDING
)
602 WaitForSingleObject(SockEvent
, INFINITE
);
603 Status
= IOSB
.Status
;
606 /* Set up Socket Data */
607 Socket
->SharedData
.State
= SocketBound
;
608 Socket
->TdiAddressHandle
= (HANDLE
)IOSB
.Information
;
610 NtClose( SockEvent
);
612 return MsafdReturnWithErrno ( Status
, lpErrno
, 0, NULL
);
617 WSPListen(SOCKET Handle
,
621 IO_STATUS_BLOCK IOSB
;
622 AFD_LISTEN_DATA ListenData
;
623 PSOCKET_INFORMATION Socket
= NULL
;
627 /* Get the Socket Structure associate to this Socket*/
628 Socket
= GetSocketStructure(Handle
);
630 if (Socket
->SharedData
.Listening
)
633 Status
= NtCreateEvent(&SockEvent
,
634 GENERIC_READ
| GENERIC_WRITE
,
639 if( !NT_SUCCESS(Status
) )
642 /* Set Up Listen Structure */
643 ListenData
.UseSAN
= FALSE
;
644 ListenData
.UseDelayedAcceptance
= Socket
->SharedData
.UseDelayedAcceptance
;
645 ListenData
.Backlog
= Backlog
;
648 Status
= NtDeviceIoControlFile((HANDLE
)Socket
->Handle
,
653 IOCTL_AFD_START_LISTEN
,
659 /* Wait for return */
660 if (Status
== STATUS_PENDING
)
662 WaitForSingleObject(SockEvent
, INFINITE
);
663 Status
= IOSB
.Status
;
666 /* Set to Listening */
667 Socket
->SharedData
.Listening
= TRUE
;
669 NtClose( SockEvent
);
671 return MsafdReturnWithErrno ( Status
, lpErrno
, 0, NULL
);
681 struct timeval
*timeout
,
684 IO_STATUS_BLOCK IOSB
;
685 PAFD_POLL_INFO PollInfo
;
687 LONG HandleCount
, OutCount
= 0;
688 ULONG PollBufferSize
;
693 LARGE_INTEGER Timeout
;
695 /* Find out how many sockets we have, and how large the buffer needs
698 HandleCount
= ( readfds
? readfds
->fd_count
: 0 ) +
699 ( writefds
? writefds
->fd_count
: 0 ) +
700 ( exceptfds
? exceptfds
->fd_count
: 0 );
702 if( HandleCount
< 0 || nfds
!= 0 )
703 HandleCount
= nfds
* 3;
705 PollBufferSize
= sizeof(*PollInfo
) + (HandleCount
* sizeof(AFD_HANDLE
));
707 AFD_DbgPrint(MID_TRACE
,("HandleCount: %d BufferSize: %d\n",
708 HandleCount
, PollBufferSize
));
710 /* Convert Timeout to NT Format */
713 Timeout
.u
.LowPart
= -1;
714 Timeout
.u
.HighPart
= 0x7FFFFFFF;
715 AFD_DbgPrint(MAX_TRACE
,("Infinite timeout\n"));
719 Timeout
= RtlEnlargedIntegerMultiply
720 ((timeout
->tv_sec
* 1000) + (timeout
->tv_usec
/ 1000), -10000);
721 /* Negative timeouts are illegal. Since the kernel represents an
722 * incremental timeout as a negative number, we check for a positive
725 if (Timeout
.QuadPart
> 0)
727 if (lpErrno
) *lpErrno
= WSAEINVAL
;
730 AFD_DbgPrint(MAX_TRACE
,("Timeout: Orig %d.%06d kernel %d\n",
731 timeout
->tv_sec
, timeout
->tv_usec
,
735 Status
= NtCreateEvent(&SockEvent
,
736 GENERIC_READ
| GENERIC_WRITE
,
741 if( !NT_SUCCESS(Status
) )
745 PollBuffer
= HeapAlloc(GlobalHeap
, 0, PollBufferSize
);
750 *lpErrno
= WSAEFAULT
;
755 PollInfo
= (PAFD_POLL_INFO
)PollBuffer
;
757 RtlZeroMemory( PollInfo
, PollBufferSize
);
759 /* Number of handles for AFD to Check */
760 PollInfo
->Exclusive
= FALSE
;
761 PollInfo
->Timeout
= Timeout
;
763 if (readfds
!= NULL
) {
764 for (i
= 0; i
< readfds
->fd_count
; i
++, j
++)
766 PollInfo
->Handles
[j
].Handle
= readfds
->fd_array
[i
];
767 PollInfo
->Handles
[j
].Events
= AFD_EVENT_RECEIVE
|
768 AFD_EVENT_DISCONNECT
|
773 if (writefds
!= NULL
)
775 for (i
= 0; i
< writefds
->fd_count
; i
++, j
++)
777 PollInfo
->Handles
[j
].Handle
= writefds
->fd_array
[i
];
778 PollInfo
->Handles
[j
].Events
= AFD_EVENT_SEND
| AFD_EVENT_CONNECT
;
781 if (exceptfds
!= NULL
)
783 for (i
= 0; i
< exceptfds
->fd_count
; i
++, j
++)
785 PollInfo
->Handles
[j
].Handle
= exceptfds
->fd_array
[i
];
786 PollInfo
->Handles
[j
].Events
= AFD_EVENT_OOB_RECEIVE
| AFD_EVENT_CONNECT_FAIL
;
790 PollInfo
->HandleCount
= j
;
791 PollBufferSize
= ((PCHAR
)&PollInfo
->Handles
[j
+1]) - ((PCHAR
)PollInfo
);
794 Status
= NtDeviceIoControlFile((HANDLE
)PollInfo
->Handles
[0].Handle
,
805 AFD_DbgPrint(MID_TRACE
,("DeviceIoControlFile => %x\n", Status
));
807 /* Wait for Completition */
808 if (Status
== STATUS_PENDING
)
810 WaitForSingleObject(SockEvent
, INFINITE
);
813 /* Clear the Structures */
821 /* Loop through return structure */
822 HandleCount
= PollInfo
->HandleCount
;
824 /* Return in FDSET Format */
825 for (i
= 0; i
< HandleCount
; i
++)
827 HandleCounted
= FALSE
;
830 switch (PollInfo
->Handles
[i
].Events
& x
)
832 case AFD_EVENT_RECEIVE
:
833 case AFD_EVENT_DISCONNECT
:
834 case AFD_EVENT_ABORT
:
835 case AFD_EVENT_ACCEPT
:
836 case AFD_EVENT_CLOSE
:
837 AFD_DbgPrint(MID_TRACE
,("Event %x on handle %x\n",
838 PollInfo
->Handles
[i
].Events
,
839 PollInfo
->Handles
[i
].Handle
));
843 HandleCounted
= TRUE
;
846 FD_SET(PollInfo
->Handles
[i
].Handle
, readfds
);
849 case AFD_EVENT_CONNECT
:
850 AFD_DbgPrint(MID_TRACE
,("Event %x on handle %x\n",
851 PollInfo
->Handles
[i
].Events
,
852 PollInfo
->Handles
[i
].Handle
));
856 HandleCounted
= TRUE
;
859 FD_SET(PollInfo
->Handles
[i
].Handle
, writefds
);
861 case AFD_EVENT_OOB_RECEIVE
:
862 case AFD_EVENT_CONNECT_FAIL
:
863 AFD_DbgPrint(MID_TRACE
,("Event %x on handle %x\n",
864 PollInfo
->Handles
[i
].Events
,
865 PollInfo
->Handles
[i
].Handle
));
869 HandleCounted
= TRUE
;
872 FD_SET(PollInfo
->Handles
[i
].Handle
, exceptfds
);
878 HeapFree( GlobalHeap
, 0, PollBuffer
);
879 NtClose( SockEvent
);
883 switch( IOSB
.Status
)
890 *lpErrno
= WSAEINVAL
;
893 AFD_DbgPrint(MID_TRACE
,("*lpErrno = %x\n", *lpErrno
));
896 AFD_DbgPrint(MID_TRACE
,("%d events\n", OutCount
));
903 WSPAccept(SOCKET Handle
,
904 struct sockaddr
*SocketAddress
,
905 int *SocketAddressLength
,
906 LPCONDITIONPROC lpfnCondition
,
907 DWORD_PTR dwCallbackData
,
910 IO_STATUS_BLOCK IOSB
;
911 PAFD_RECEIVED_ACCEPT_DATA ListenReceiveData
;
912 AFD_ACCEPT_DATA AcceptData
;
913 AFD_DEFER_ACCEPT_DATA DeferData
;
914 AFD_PENDING_ACCEPT_DATA PendingAcceptData
;
915 PSOCKET_INFORMATION Socket
= NULL
;
917 struct fd_set ReadSet
;
918 struct timeval Timeout
;
919 PVOID PendingData
= NULL
;
920 ULONG PendingDataLength
= 0;
921 PVOID CalleeDataBuffer
;
922 WSABUF CallerData
, CalleeID
, CallerID
, CalleeData
;
923 PSOCKADDR RemoteAddress
= NULL
;
926 WSAPROTOCOL_INFOW ProtocolInfo
;
928 UCHAR ReceiveBuffer
[0x1A];
931 Status
= NtCreateEvent(&SockEvent
,
932 GENERIC_READ
| GENERIC_WRITE
,
937 if( !NT_SUCCESS(Status
) )
939 MsafdReturnWithErrno( Status
, lpErrno
, 0, NULL
);
940 return INVALID_SOCKET
;
943 /* Dynamic Structure...ugh */
944 ListenReceiveData
= (PAFD_RECEIVED_ACCEPT_DATA
)ReceiveBuffer
;
946 /* Get the Socket Structure associate to this Socket*/
947 Socket
= GetSocketStructure(Handle
);
949 /* If this is non-blocking, make sure there's something for us to accept */
951 FD_SET(Socket
->Handle
, &ReadSet
);
955 WSPSelect(0, &ReadSet
, NULL
, NULL
, &Timeout
, NULL
);
957 if (ReadSet
.fd_array
[0] != Socket
->Handle
)
964 Status
= NtDeviceIoControlFile((HANDLE
)Socket
->Handle
,
969 IOCTL_AFD_WAIT_FOR_LISTEN
,
973 0xA + sizeof(*ListenReceiveData
));
975 /* Wait for return */
976 if (Status
== STATUS_PENDING
)
978 WaitForSingleObject(SockEvent
, INFINITE
);
979 Status
= IOSB
.Status
;
982 if (!NT_SUCCESS(Status
))
984 NtClose( SockEvent
);
985 MsafdReturnWithErrno( Status
, lpErrno
, 0, NULL
);
986 return INVALID_SOCKET
;
989 if (lpfnCondition
!= NULL
)
991 if ((Socket
->SharedData
.ServiceFlags1
& XP1_CONNECT_DATA
) != 0)
993 /* Find out how much data is pending */
994 PendingAcceptData
.SequenceNumber
= ListenReceiveData
->SequenceNumber
;
995 PendingAcceptData
.ReturnSize
= TRUE
;
998 Status
= NtDeviceIoControlFile((HANDLE
)Socket
->Handle
,
1003 IOCTL_AFD_GET_PENDING_CONNECT_DATA
,
1005 sizeof(PendingAcceptData
),
1007 sizeof(PendingAcceptData
));
1009 /* Wait for return */
1010 if (Status
== STATUS_PENDING
)
1012 WaitForSingleObject(SockEvent
, INFINITE
);
1013 Status
= IOSB
.Status
;
1016 if (!NT_SUCCESS(Status
))
1018 NtClose( SockEvent
);
1019 MsafdReturnWithErrno( Status
, lpErrno
, 0, NULL
);
1020 return INVALID_SOCKET
;
1023 /* How much data to allocate */
1024 PendingDataLength
= IOSB
.Information
;
1026 if (PendingDataLength
)
1028 /* Allocate needed space */
1029 PendingData
= HeapAlloc(GlobalHeap
, 0, PendingDataLength
);
1031 /* We want the data now */
1032 PendingAcceptData
.ReturnSize
= FALSE
;
1035 Status
= NtDeviceIoControlFile((HANDLE
)Socket
->Handle
,
1040 IOCTL_AFD_GET_PENDING_CONNECT_DATA
,
1042 sizeof(PendingAcceptData
),
1046 /* Wait for return */
1047 if (Status
== STATUS_PENDING
)
1049 WaitForSingleObject(SockEvent
, INFINITE
);
1050 Status
= IOSB
.Status
;
1053 if (!NT_SUCCESS(Status
))
1055 NtClose( SockEvent
);
1056 MsafdReturnWithErrno( Status
, lpErrno
, 0, NULL
);
1057 return INVALID_SOCKET
;
1062 if ((Socket
->SharedData
.ServiceFlags1
& XP1_QOS_SUPPORTED
) != 0)
1064 /* I don't support this yet */
1067 /* Build Callee ID */
1068 CalleeID
.buf
= (PVOID
)Socket
->LocalAddress
;
1069 CalleeID
.len
= Socket
->SharedData
.SizeOfLocalAddress
;
1071 /* Set up Address in SOCKADDR Format */
1072 RtlCopyMemory (RemoteAddress
,
1073 &ListenReceiveData
->Address
.Address
[0].AddressType
,
1074 sizeof(*RemoteAddress
));
1076 /* Build Caller ID */
1077 CallerID
.buf
= (PVOID
)RemoteAddress
;
1078 CallerID
.len
= sizeof(*RemoteAddress
);
1080 /* Build Caller Data */
1081 CallerData
.buf
= PendingData
;
1082 CallerData
.len
= PendingDataLength
;
1084 /* Check if socket supports Conditional Accept */
1085 if (Socket
->SharedData
.UseDelayedAcceptance
!= 0)
1087 /* Allocate Buffer for Callee Data */
1088 CalleeDataBuffer
= HeapAlloc(GlobalHeap
, 0, 4096);
1089 CalleeData
.buf
= CalleeDataBuffer
;
1090 CalleeData
.len
= 4096;
1099 /* Call the Condition Function */
1100 CallBack
= (lpfnCondition
)(&CallerID
,
1101 CallerData
.buf
== NULL
? NULL
: &CallerData
,
1105 CalleeData
.buf
== NULL
? NULL
: &CalleeData
,
1109 if (((CallBack
== CF_ACCEPT
) && GroupID
) != 0)
1111 /* TBD: Check for Validity */
1114 if (CallBack
== CF_ACCEPT
)
1116 if ((Socket
->SharedData
.ServiceFlags1
& XP1_QOS_SUPPORTED
) != 0)
1118 /* I don't support this yet */
1122 // SockSetConnectData Sockets(SocketID), IOCTL_AFD_SET_CONNECT_DATA, CalleeData.Buffer, CalleeData.BuffSize, 0
1127 /* Callback rejected. Build Defer Structure */
1128 DeferData
.SequenceNumber
= ListenReceiveData
->SequenceNumber
;
1129 DeferData
.RejectConnection
= (CallBack
== CF_REJECT
);
1132 Status
= NtDeviceIoControlFile((HANDLE
)Socket
->Handle
,
1137 IOCTL_AFD_DEFER_ACCEPT
,
1143 /* Wait for return */
1144 if (Status
== STATUS_PENDING
)
1146 WaitForSingleObject(SockEvent
, INFINITE
);
1147 Status
= IOSB
.Status
;
1150 NtClose( SockEvent
);
1152 if (!NT_SUCCESS(Status
))
1154 MsafdReturnWithErrno( Status
, lpErrno
, 0, NULL
);
1155 return INVALID_SOCKET
;
1158 if (CallBack
== CF_REJECT
)
1160 *lpErrno
= WSAECONNREFUSED
;
1161 return INVALID_SOCKET
;
1165 *lpErrno
= WSAECONNREFUSED
;
1166 return INVALID_SOCKET
;
1171 /* Create a new Socket */
1172 ProtocolInfo
.dwCatalogEntryId
= Socket
->SharedData
.CatalogEntryId
;
1173 ProtocolInfo
.dwServiceFlags1
= Socket
->SharedData
.ServiceFlags1
;
1174 ProtocolInfo
.dwProviderFlags
= Socket
->SharedData
.ProviderFlags
;
1176 AcceptSocket
= WSPSocket (Socket
->SharedData
.AddressFamily
,
1177 Socket
->SharedData
.SocketType
,
1178 Socket
->SharedData
.Protocol
,
1181 Socket
->SharedData
.CreateFlags
,
1184 /* Set up the Accept Structure */
1185 AcceptData
.ListenHandle
= AcceptSocket
;
1186 AcceptData
.SequenceNumber
= ListenReceiveData
->SequenceNumber
;
1188 /* Send IOCTL to Accept */
1189 Status
= NtDeviceIoControlFile((HANDLE
)Socket
->Handle
,
1200 /* Wait for return */
1201 if (Status
== STATUS_PENDING
)
1203 WaitForSingleObject(SockEvent
, INFINITE
);
1204 Status
= IOSB
.Status
;
1207 if (!NT_SUCCESS(Status
))
1210 WSPCloseSocket( AcceptSocket
, lpErrno
);
1211 MsafdReturnWithErrno( Status
, lpErrno
, 0, NULL
);
1212 return INVALID_SOCKET
;
1215 /* Return Address in SOCKADDR FORMAT */
1218 RtlCopyMemory (SocketAddress
,
1219 &ListenReceiveData
->Address
.Address
[0].AddressType
,
1220 sizeof(*RemoteAddress
));
1221 if( SocketAddressLength
)
1222 *SocketAddressLength
= ListenReceiveData
->Address
.Address
[0].AddressLength
;
1225 NtClose( SockEvent
);
1227 /* Re-enable Async Event */
1228 SockReenableAsyncSelectEvent(Socket
, FD_ACCEPT
);
1230 AFD_DbgPrint(MID_TRACE
,("Socket %x\n", AcceptSocket
));
1235 return AcceptSocket
;
1240 WSPConnect(SOCKET Handle
,
1241 const struct sockaddr
* SocketAddress
,
1242 int SocketAddressLength
,
1243 LPWSABUF lpCallerData
,
1244 LPWSABUF lpCalleeData
,
1249 IO_STATUS_BLOCK IOSB
;
1250 PAFD_CONNECT_INFO ConnectInfo
;
1251 PSOCKET_INFORMATION Socket
= NULL
;
1253 UCHAR ConnectBuffer
[0x22];
1254 ULONG ConnectDataLength
;
1255 ULONG InConnectDataLength
;
1256 INT BindAddressLength
;
1257 PSOCKADDR BindAddress
;
1260 Status
= NtCreateEvent(&SockEvent
,
1261 GENERIC_READ
| GENERIC_WRITE
,
1266 if( !NT_SUCCESS(Status
) )
1269 AFD_DbgPrint(MID_TRACE
,("Called\n"));
1271 /* Get the Socket Structure associate to this Socket*/
1272 Socket
= GetSocketStructure(Handle
);
1275 if (Socket
->SharedData
.State
== SocketOpen
)
1277 /* Get the Wildcard Address */
1278 BindAddressLength
= Socket
->HelperData
->MaxWSAddressLength
;
1279 BindAddress
= HeapAlloc(GetProcessHeap(), 0, BindAddressLength
);
1280 Socket
->HelperData
->WSHGetWildcardSockaddr (Socket
->HelperContext
,
1282 &BindAddressLength
);
1284 WSPBind(Handle
, BindAddress
, BindAddressLength
, NULL
);
1287 /* Set the Connect Data */
1288 if (lpCallerData
!= NULL
)
1290 ConnectDataLength
= lpCallerData
->len
;
1291 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
1296 IOCTL_AFD_SET_CONNECT_DATA
,
1301 /* Wait for return */
1302 if (Status
== STATUS_PENDING
)
1304 WaitForSingleObject(SockEvent
, INFINITE
);
1305 Status
= IOSB
.Status
;
1309 /* Dynamic Structure...ugh */
1310 ConnectInfo
= (PAFD_CONNECT_INFO
)ConnectBuffer
;
1312 /* Set up Address in TDI Format */
1313 ConnectInfo
->RemoteAddress
.TAAddressCount
= 1;
1314 ConnectInfo
->RemoteAddress
.Address
[0].AddressLength
= SocketAddressLength
- sizeof(SocketAddress
->sa_family
);
1315 ConnectInfo
->RemoteAddress
.Address
[0].AddressType
= SocketAddress
->sa_family
;
1316 RtlCopyMemory (ConnectInfo
->RemoteAddress
.Address
[0].Address
,
1317 SocketAddress
->sa_data
,
1318 SocketAddressLength
- sizeof(SocketAddress
->sa_family
));
1321 * Disable FD_WRITE and FD_CONNECT
1322 * The latter fixes a race condition where the FD_CONNECT is re-enabled
1323 * at the end of this function right after the Async Thread disables it.
1324 * This should only happen at the *next* WSPConnect
1326 if (Socket
->SharedData
.AsyncEvents
& FD_CONNECT
)
1328 Socket
->SharedData
.AsyncDisabledEvents
|= FD_CONNECT
| FD_WRITE
;
1331 /* Tell AFD that we want Connection Data back, have it allocate a buffer */
1332 if (lpCalleeData
!= NULL
)
1334 InConnectDataLength
= lpCalleeData
->len
;
1335 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
1340 IOCTL_AFD_SET_CONNECT_DATA_SIZE
,
1341 &InConnectDataLength
,
1342 sizeof(InConnectDataLength
),
1346 /* Wait for return */
1347 if (Status
== STATUS_PENDING
)
1349 WaitForSingleObject(SockEvent
, INFINITE
);
1350 Status
= IOSB
.Status
;
1354 /* AFD doesn't seem to care if these are invalid, but let's 0 them anyways */
1355 ConnectInfo
->Root
= 0;
1356 ConnectInfo
->UseSAN
= FALSE
;
1357 ConnectInfo
->Unknown
= 0;
1359 /* FIXME: Handle Async Connect */
1360 if (Socket
->SharedData
.NonBlocking
)
1362 AFD_DbgPrint(MIN_TRACE
, ("Async Connect UNIMPLEMENTED!\n"));
1366 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
1376 /* Wait for return */
1377 if (Status
== STATUS_PENDING
)
1379 WaitForSingleObject(SockEvent
, INFINITE
);
1380 Status
= IOSB
.Status
;
1383 /* Get any pending connect data */
1384 if (lpCalleeData
!= NULL
)
1386 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
1391 IOCTL_AFD_GET_CONNECT_DATA
,
1396 /* Wait for return */
1397 if (Status
== STATUS_PENDING
)
1399 WaitForSingleObject(SockEvent
, INFINITE
);
1400 Status
= IOSB
.Status
;
1404 /* Re-enable Async Event */
1405 SockReenableAsyncSelectEvent(Socket
, FD_WRITE
);
1407 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
1408 SockReenableAsyncSelectEvent(Socket
, FD_CONNECT
);
1410 AFD_DbgPrint(MID_TRACE
,("Ending\n"));
1412 NtClose( SockEvent
);
1414 return MsafdReturnWithErrno( Status
, lpErrno
, 0, NULL
);
1418 WSPShutdown(SOCKET Handle
,
1423 IO_STATUS_BLOCK IOSB
;
1424 AFD_DISCONNECT_INFO DisconnectInfo
;
1425 PSOCKET_INFORMATION Socket
= NULL
;
1429 Status
= NtCreateEvent(&SockEvent
,
1430 GENERIC_READ
| GENERIC_WRITE
,
1435 if( !NT_SUCCESS(Status
) )
1438 AFD_DbgPrint(MID_TRACE
,("Called\n"));
1440 /* Get the Socket Structure associate to this Socket*/
1441 Socket
= GetSocketStructure(Handle
);
1443 /* Set AFD Disconnect Type */
1447 DisconnectInfo
.DisconnectType
= AFD_DISCONNECT_RECV
;
1448 Socket
->SharedData
.ReceiveShutdown
= TRUE
;
1451 DisconnectInfo
.DisconnectType
= AFD_DISCONNECT_SEND
;
1452 Socket
->SharedData
.SendShutdown
= TRUE
;
1455 DisconnectInfo
.DisconnectType
= AFD_DISCONNECT_RECV
| AFD_DISCONNECT_SEND
;
1456 Socket
->SharedData
.ReceiveShutdown
= TRUE
;
1457 Socket
->SharedData
.SendShutdown
= TRUE
;
1461 DisconnectInfo
.Timeout
= RtlConvertLongToLargeInteger(-1);
1464 Status
= NtDeviceIoControlFile((HANDLE
)Handle
,
1469 IOCTL_AFD_DISCONNECT
,
1471 sizeof(DisconnectInfo
),
1475 /* Wait for return */
1476 if (Status
== STATUS_PENDING
)
1478 WaitForSingleObject(SockEvent
, INFINITE
);
1479 Status
= IOSB
.Status
;
1482 AFD_DbgPrint(MID_TRACE
,("Ending\n"));
1484 NtClose( SockEvent
);
1486 return MsafdReturnWithErrno( Status
, lpErrno
, 0, NULL
);
1492 WSPGetSockName(IN SOCKET Handle
,
1493 OUT LPSOCKADDR Name
,
1494 IN OUT LPINT NameLength
,
1497 IO_STATUS_BLOCK IOSB
;
1498 ULONG TdiAddressSize
;
1499 PTDI_ADDRESS_INFO TdiAddress
;
1500 PTRANSPORT_ADDRESS SocketAddress
;
1501 PSOCKET_INFORMATION Socket
= NULL
;
1505 Status
= NtCreateEvent(&SockEvent
,
1506 GENERIC_READ
| GENERIC_WRITE
,
1511 if( !NT_SUCCESS(Status
) )
1512 return SOCKET_ERROR
;
1514 /* Get the Socket Structure associate to this Socket*/
1515 Socket
= GetSocketStructure(Handle
);
1517 /* Allocate a buffer for the address */
1519 sizeof(TRANSPORT_ADDRESS
) + Socket
->SharedData
.SizeOfLocalAddress
;
1520 TdiAddress
= HeapAlloc(GlobalHeap
, 0, TdiAddressSize
);
1522 if ( TdiAddress
== NULL
)
1524 NtClose( SockEvent
);
1525 *lpErrno
= WSAENOBUFS
;
1526 return SOCKET_ERROR
;
1529 SocketAddress
= &TdiAddress
->Address
;
1532 Status
= NtDeviceIoControlFile((HANDLE
)Socket
->Handle
,
1537 IOCTL_AFD_GET_SOCK_NAME
,
1543 /* Wait for return */
1544 if (Status
== STATUS_PENDING
)
1546 WaitForSingleObject(SockEvent
, INFINITE
);
1547 Status
= IOSB
.Status
;
1550 NtClose( SockEvent
);
1552 if (NT_SUCCESS(Status
))
1554 if (*NameLength
>= SocketAddress
->Address
[0].AddressLength
)
1556 Name
->sa_family
= SocketAddress
->Address
[0].AddressType
;
1557 RtlCopyMemory (Name
->sa_data
,
1558 SocketAddress
->Address
[0].Address
,
1559 SocketAddress
->Address
[0].AddressLength
);
1560 *NameLength
= 2 + SocketAddress
->Address
[0].AddressLength
;
1561 AFD_DbgPrint (MID_TRACE
, ("NameLength %d Address: %x Port %x\n",
1562 *NameLength
, ((struct sockaddr_in
*)Name
)->sin_addr
.s_addr
,
1563 ((struct sockaddr_in
*)Name
)->sin_port
));
1564 HeapFree(GlobalHeap
, 0, TdiAddress
);
1569 HeapFree(GlobalHeap
, 0, TdiAddress
);
1570 *lpErrno
= WSAEFAULT
;
1571 return SOCKET_ERROR
;
1575 return MsafdReturnWithErrno ( Status
, lpErrno
, 0, NULL
);
1581 WSPGetPeerName(IN SOCKET s
,
1582 OUT LPSOCKADDR Name
,
1583 IN OUT LPINT NameLength
,
1586 IO_STATUS_BLOCK IOSB
;
1587 ULONG TdiAddressSize
;
1588 PTRANSPORT_ADDRESS SocketAddress
;
1589 PSOCKET_INFORMATION Socket
= NULL
;
1593 Status
= NtCreateEvent(&SockEvent
,
1594 GENERIC_READ
| GENERIC_WRITE
,
1599 if( !NT_SUCCESS(Status
) )
1600 return SOCKET_ERROR
;
1602 /* Get the Socket Structure associate to this Socket*/
1603 Socket
= GetSocketStructure(s
);
1605 /* Allocate a buffer for the address */
1606 TdiAddressSize
= sizeof(TRANSPORT_ADDRESS
) + *NameLength
;
1607 SocketAddress
= HeapAlloc(GlobalHeap
, 0, TdiAddressSize
);
1609 if ( SocketAddress
== NULL
)
1611 NtClose( SockEvent
);
1612 *lpErrno
= WSAENOBUFS
;
1613 return SOCKET_ERROR
;
1617 Status
= NtDeviceIoControlFile((HANDLE
)Socket
->Handle
,
1622 IOCTL_AFD_GET_PEER_NAME
,
1628 /* Wait for return */
1629 if (Status
== STATUS_PENDING
)
1631 WaitForSingleObject(SockEvent
, INFINITE
);
1632 Status
= IOSB
.Status
;
1635 NtClose( SockEvent
);
1637 if (NT_SUCCESS(Status
))
1639 if (*NameLength
>= SocketAddress
->Address
[0].AddressLength
)
1641 Name
->sa_family
= SocketAddress
->Address
[0].AddressType
;
1642 RtlCopyMemory (Name
->sa_data
,
1643 SocketAddress
->Address
[0].Address
,
1644 SocketAddress
->Address
[0].AddressLength
);
1645 *NameLength
= 2 + SocketAddress
->Address
[0].AddressLength
;
1646 AFD_DbgPrint (MID_TRACE
, ("NameLength %d Address: %s Port %x\n",
1647 *NameLength
, ((struct sockaddr_in
*)Name
)->sin_addr
.s_addr
,
1648 ((struct sockaddr_in
*)Name
)->sin_port
));
1649 HeapFree(GlobalHeap
, 0, SocketAddress
);
1654 HeapFree(GlobalHeap
, 0, SocketAddress
);
1655 *lpErrno
= WSAEFAULT
;
1656 return SOCKET_ERROR
;
1660 return MsafdReturnWithErrno ( Status
, lpErrno
, 0, NULL
);
1665 WSPIoctl(IN SOCKET Handle
,
1666 IN DWORD dwIoControlCode
,
1667 IN LPVOID lpvInBuffer
,
1668 IN DWORD cbInBuffer
,
1669 OUT LPVOID lpvOutBuffer
,
1670 IN DWORD cbOutBuffer
,
1671 OUT LPDWORD lpcbBytesReturned
,
1672 IN LPWSAOVERLAPPED lpOverlapped
,
1673 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
,
1674 IN LPWSATHREADID lpThreadId
,
1677 PSOCKET_INFORMATION Socket
= NULL
;
1679 /* Get the Socket Structure associate to this Socket*/
1680 Socket
= GetSocketStructure(Handle
);
1682 switch( dwIoControlCode
)
1685 if( cbInBuffer
< sizeof(INT
) )
1686 return SOCKET_ERROR
;
1687 Socket
->SharedData
.NonBlocking
= *((PINT
)lpvInBuffer
) ? 1 : 0;
1688 AFD_DbgPrint(MID_TRACE
,("[%x] Set nonblocking %d\n", Handle
, Socket
->SharedData
.NonBlocking
));
1691 return GetSocketInformation(Socket
, AFD_INFO_RECEIVE_CONTENT_SIZE
, (PULONG
)lpvOutBuffer
, NULL
);
1693 *lpErrno
= WSAEINVAL
;
1694 return SOCKET_ERROR
;
1701 WSPGetSockOpt(IN SOCKET Handle
,
1704 OUT CHAR FAR
* OptionValue
,
1705 IN OUT LPINT OptionLength
,
1708 PSOCKET_INFORMATION Socket
= NULL
;
1713 /* Get the Socket Structure associate to this Socket*/
1714 Socket
= GetSocketStructure(Handle
);
1717 *lpErrno
= WSAENOTSOCK
;
1718 return SOCKET_ERROR
;
1721 AFD_DbgPrint(MID_TRACE
, ("Called\n"));
1729 Buffer
= &Socket
->SharedData
.SocketType
;
1730 BufferSize
= sizeof(INT
);
1734 Buffer
= &Socket
->SharedData
.SizeOfRecvBuffer
;
1735 BufferSize
= sizeof(INT
);
1739 Buffer
= &Socket
->SharedData
.SizeOfSendBuffer
;
1740 BufferSize
= sizeof(INT
);
1744 BoolBuffer
= Socket
->SharedData
.Listening
;
1745 Buffer
= &BoolBuffer
;
1746 BufferSize
= sizeof(BOOLEAN
);
1750 BoolBuffer
= Socket
->SharedData
.Broadcast
;
1751 Buffer
= &BoolBuffer
;
1752 BufferSize
= sizeof(BOOLEAN
);
1756 BoolBuffer
= Socket
->SharedData
.Debug
;
1757 Buffer
= &BoolBuffer
;
1758 BufferSize
= sizeof(BOOLEAN
);
1761 /* case SO_CONDITIONAL_ACCEPT: */
1766 case SO_GROUP_PRIORITY
:
1769 case SO_MAX_MSG_SIZE
:
1771 case SO_PROTOCOL_INFO
:
1773 AFD_DbgPrint(MID_TRACE
, ("Unimplemented option (%x)\n",
1777 *lpErrno
= WSAEINVAL
;
1778 return SOCKET_ERROR
;
1781 if (*OptionLength
< BufferSize
)
1783 *lpErrno
= WSAEFAULT
;
1784 *OptionLength
= BufferSize
;
1785 return SOCKET_ERROR
;
1787 RtlCopyMemory(OptionValue
, Buffer
, BufferSize
);
1791 case IPPROTO_TCP
: /* FIXME */
1793 *lpErrno
= WSAEINVAL
;
1794 return SOCKET_ERROR
;
1800 * FUNCTION: Initialize service provider for a client
1802 * wVersionRequested = Highest WinSock SPI version that the caller can use
1803 * lpWSPData = Address of WSPDATA structure to initialize
1804 * lpProtocolInfo = Pointer to structure that defines the desired protocol
1805 * UpcallTable = Pointer to upcall table of the WinSock DLL
1806 * lpProcTable = Address of procedure table to initialize
1808 * Status of operation
1812 WSPStartup(IN WORD wVersionRequested
,
1813 OUT LPWSPDATA lpWSPData
,
1814 IN LPWSAPROTOCOL_INFOW lpProtocolInfo
,
1815 IN WSPUPCALLTABLE UpcallTable
,
1816 OUT LPWSPPROC_TABLE lpProcTable
)
1821 AFD_DbgPrint(MAX_TRACE
, ("wVersionRequested (0x%X) \n", wVersionRequested
));
1823 Upcalls
= UpcallTable
;
1825 if (Status
== NO_ERROR
)
1827 lpProcTable
->lpWSPAccept
= WSPAccept
;
1828 lpProcTable
->lpWSPAddressToString
= WSPAddressToString
;
1829 lpProcTable
->lpWSPAsyncSelect
= WSPAsyncSelect
;
1830 lpProcTable
->lpWSPBind
= WSPBind
;
1831 lpProcTable
->lpWSPCancelBlockingCall
= WSPCancelBlockingCall
;
1832 lpProcTable
->lpWSPCleanup
= WSPCleanup
;
1833 lpProcTable
->lpWSPCloseSocket
= WSPCloseSocket
;
1834 lpProcTable
->lpWSPConnect
= WSPConnect
;
1835 lpProcTable
->lpWSPDuplicateSocket
= WSPDuplicateSocket
;
1836 lpProcTable
->lpWSPEnumNetworkEvents
= WSPEnumNetworkEvents
;
1837 lpProcTable
->lpWSPEventSelect
= WSPEventSelect
;
1838 lpProcTable
->lpWSPGetOverlappedResult
= WSPGetOverlappedResult
;
1839 lpProcTable
->lpWSPGetPeerName
= WSPGetPeerName
;
1840 lpProcTable
->lpWSPGetSockName
= WSPGetSockName
;
1841 lpProcTable
->lpWSPGetSockOpt
= WSPGetSockOpt
;
1842 lpProcTable
->lpWSPGetQOSByName
= WSPGetQOSByName
;
1843 lpProcTable
->lpWSPIoctl
= WSPIoctl
;
1844 lpProcTable
->lpWSPJoinLeaf
= WSPJoinLeaf
;
1845 lpProcTable
->lpWSPListen
= WSPListen
;
1846 lpProcTable
->lpWSPRecv
= WSPRecv
;
1847 lpProcTable
->lpWSPRecvDisconnect
= WSPRecvDisconnect
;
1848 lpProcTable
->lpWSPRecvFrom
= WSPRecvFrom
;
1849 lpProcTable
->lpWSPSelect
= WSPSelect
;
1850 lpProcTable
->lpWSPSend
= WSPSend
;
1851 lpProcTable
->lpWSPSendDisconnect
= WSPSendDisconnect
;
1852 lpProcTable
->lpWSPSendTo
= WSPSendTo
;
1853 lpProcTable
->lpWSPSetSockOpt
= WSPSetSockOpt
;
1854 lpProcTable
->lpWSPShutdown
= WSPShutdown
;
1855 lpProcTable
->lpWSPSocket
= WSPSocket
;
1856 lpProcTable
->lpWSPStringToAddress
= WSPStringToAddress
;
1857 lpWSPData
->wVersion
= MAKEWORD(2, 2);
1858 lpWSPData
->wHighVersion
= MAKEWORD(2, 2);
1861 AFD_DbgPrint(MAX_TRACE
, ("Status (%d).\n", Status
));
1868 * FUNCTION: Cleans up service provider for a client
1870 * lpErrno = Address of buffer for error information
1872 * 0 if successful, or SOCKET_ERROR if not
1876 WSPCleanup(OUT LPINT lpErrno
)
1879 AFD_DbgPrint(MAX_TRACE
, ("\n"));
1880 AFD_DbgPrint(MAX_TRACE
, ("Leaving.\n"));
1881 *lpErrno
= NO_ERROR
;
1889 GetSocketInformation(PSOCKET_INFORMATION Socket
,
1890 ULONG AfdInformationClass
,
1891 PULONG Ulong OPTIONAL
,
1892 PLARGE_INTEGER LargeInteger OPTIONAL
)
1894 IO_STATUS_BLOCK IOSB
;
1899 Status
= NtCreateEvent(&SockEvent
,
1900 GENERIC_READ
| GENERIC_WRITE
,
1905 if( !NT_SUCCESS(Status
) )
1908 /* Set Info Class */
1909 InfoData
.InformationClass
= AfdInformationClass
;
1912 Status
= NtDeviceIoControlFile((HANDLE
)Socket
->Handle
,
1923 /* Wait for return */
1924 if (Status
== STATUS_PENDING
)
1926 WaitForSingleObject(SockEvent
, INFINITE
);
1929 /* Return Information */
1930 *Ulong
= InfoData
.Information
.Ulong
;
1931 if (LargeInteger
!= NULL
)
1933 *LargeInteger
= InfoData
.Information
.LargeInteger
;
1936 NtClose( SockEvent
);
1944 SetSocketInformation(PSOCKET_INFORMATION Socket
,
1945 ULONG AfdInformationClass
,
1946 PULONG Ulong OPTIONAL
,
1947 PLARGE_INTEGER LargeInteger OPTIONAL
)
1949 IO_STATUS_BLOCK IOSB
;
1954 Status
= NtCreateEvent(&SockEvent
,
1955 GENERIC_READ
| GENERIC_WRITE
,
1960 if( !NT_SUCCESS(Status
) )
1963 /* Set Info Class */
1964 InfoData
.InformationClass
= AfdInformationClass
;
1966 /* Set Information */
1967 InfoData
.Information
.Ulong
= *Ulong
;
1968 if (LargeInteger
!= NULL
)
1970 InfoData
.Information
.LargeInteger
= *LargeInteger
;
1973 AFD_DbgPrint(MID_TRACE
,("XXX Info %x (Data %x)\n",
1974 AfdInformationClass
, *Ulong
));
1977 Status
= NtDeviceIoControlFile((HANDLE
)Socket
->Handle
,
1988 /* Wait for return */
1989 if (Status
== STATUS_PENDING
)
1991 WaitForSingleObject(SockEvent
, INFINITE
);
1994 NtClose( SockEvent
);
2001 GetSocketStructure(SOCKET Handle
)
2005 for (i
=0; i
<SocketCount
; i
++)
2007 if (Sockets
[i
]->Handle
== Handle
)
2015 int CreateContext(PSOCKET_INFORMATION Socket
)
2017 IO_STATUS_BLOCK IOSB
;
2018 SOCKET_CONTEXT ContextData
;
2022 Status
= NtCreateEvent(&SockEvent
,
2023 GENERIC_READ
| GENERIC_WRITE
,
2028 if( !NT_SUCCESS(Status
) )
2031 /* Create Context */
2032 ContextData
.SharedData
= Socket
->SharedData
;
2033 ContextData
.SizeOfHelperData
= 0;
2034 RtlCopyMemory (&ContextData
.LocalAddress
,
2035 Socket
->LocalAddress
,
2036 Socket
->SharedData
.SizeOfLocalAddress
);
2037 RtlCopyMemory (&ContextData
.RemoteAddress
,
2038 Socket
->RemoteAddress
,
2039 Socket
->SharedData
.SizeOfRemoteAddress
);
2042 Status
= NtDeviceIoControlFile((HANDLE
)Socket
->Handle
,
2047 IOCTL_AFD_SET_CONTEXT
,
2049 sizeof(ContextData
),
2053 /* Wait for Completition */
2054 if (Status
== STATUS_PENDING
)
2056 WaitForSingleObject(SockEvent
, INFINITE
);
2059 NtClose( SockEvent
);
2064 BOOLEAN
SockCreateOrReferenceAsyncThread(VOID
)
2066 HANDLE hAsyncThread
;
2067 DWORD AsyncThreadId
;
2069 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags
;
2072 /* Check if the Thread Already Exists */
2073 if (SockAsyncThreadRefCount
)
2078 /* Create the Completion Port */
2079 if (!SockAsyncCompletionPort
)
2081 Status
= NtCreateIoCompletion(&SockAsyncCompletionPort
,
2082 IO_COMPLETION_ALL_ACCESS
,
2084 2); // Allow 2 threads only
2086 /* Protect Handle */
2087 HandleFlags
.ProtectFromClose
= TRUE
;
2088 HandleFlags
.Inherit
= FALSE
;
2089 Status
= NtSetInformationObject(SockAsyncCompletionPort
,
2090 ObjectHandleFlagInformation
,
2092 sizeof(HandleFlags
));
2095 /* Create the Async Event */
2096 Status
= NtCreateEvent(&AsyncEvent
,
2102 /* Create the Async Thread */
2103 hAsyncThread
= CreateThread(NULL
,
2105 (LPTHREAD_START_ROUTINE
)SockAsyncThread
,
2110 /* Close the Handle */
2111 NtClose(hAsyncThread
);
2113 /* Increase the Reference Count */
2114 SockAsyncThreadRefCount
++;
2118 int SockAsyncThread(PVOID ThreadParam
)
2121 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine
;
2122 IO_STATUS_BLOCK IOSB
;
2125 /* Make the Thread Higher Priority */
2126 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL
);
2128 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
2131 Status
= NtRemoveIoCompletion (SockAsyncCompletionPort
,
2132 (PVOID
*)&AsyncCompletionRoutine
,
2136 /* Call the Async Function */
2137 if (NT_SUCCESS(Status
))
2139 (*AsyncCompletionRoutine
)(AsyncContext
, &IOSB
);
2143 /* It Failed, sleep for a second */
2146 } while ((Status
!= STATUS_TIMEOUT
));
2148 /* The Thread has Ended */
2152 BOOLEAN
SockGetAsyncSelectHelperAfdHandle(VOID
)
2154 UNICODE_STRING AfdHelper
;
2155 OBJECT_ATTRIBUTES ObjectAttributes
;
2156 IO_STATUS_BLOCK IoSb
;
2158 FILE_COMPLETION_INFORMATION CompletionInfo
;
2159 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags
;
2161 /* First, make sure we're not already intialized */
2162 if (SockAsyncHelperAfdHandle
)
2167 /* Set up Handle Name and Object */
2168 RtlInitUnicodeString(&AfdHelper
, L
"\\Device\\Afd\\AsyncSelectHlp" );
2169 InitializeObjectAttributes(&ObjectAttributes
,
2171 OBJ_INHERIT
| OBJ_CASE_INSENSITIVE
,
2175 /* Open the Handle to AFD */
2176 Status
= NtCreateFile(&SockAsyncHelperAfdHandle
,
2177 GENERIC_READ
| GENERIC_WRITE
| SYNCHRONIZE
,
2182 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2189 * Now Set up the Completion Port Information
2190 * This means that whenever a Poll is finished, the routine will be executed
2192 CompletionInfo
.Port
= SockAsyncCompletionPort
;
2193 CompletionInfo
.Key
= SockAsyncSelectCompletionRoutine
;
2194 Status
= NtSetInformationFile(SockAsyncHelperAfdHandle
,
2197 sizeof(CompletionInfo
),
2198 FileCompletionInformation
);
2201 /* Protect the Handle */
2202 HandleFlags
.ProtectFromClose
= TRUE
;
2203 HandleFlags
.Inherit
= FALSE
;
2204 Status
= NtSetInformationObject(SockAsyncCompletionPort
,
2205 ObjectHandleFlagInformation
,
2207 sizeof(HandleFlags
));
2210 /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
2211 SockAsyncSelectCalled
= TRUE
;
2215 VOID
SockAsyncSelectCompletionRoutine(PVOID Context
, PIO_STATUS_BLOCK IoStatusBlock
)
2218 PASYNC_DATA AsyncData
= Context
;
2219 PSOCKET_INFORMATION Socket
;
2222 /* Get the Socket */
2223 Socket
= AsyncData
->ParentSocket
;
2225 /* Check if the Sequence Number Changed behind our back */
2226 if (AsyncData
->SequenceNumber
!= Socket
->SharedData
.SequenceNumber
)
2231 /* Check we were manually called b/c of a failure */
2232 if (!NT_SUCCESS(IoStatusBlock
->Status
))
2234 /* FIXME: Perform Upcall */
2238 for (x
= 1; x
; x
<<=1)
2240 switch (AsyncData
->AsyncSelectInfo
.Handles
[0].Events
& x
)
2242 case AFD_EVENT_RECEIVE
:
2243 if (0 != (Socket
->SharedData
.AsyncEvents
& FD_READ
) &&
2244 0 == (Socket
->SharedData
.AsyncDisabledEvents
& FD_READ
))
2246 /* Make the Notifcation */
2247 (Upcalls
.lpWPUPostMessage
)(Socket
->SharedData
.hWnd
,
2248 Socket
->SharedData
.wMsg
,
2250 WSAMAKESELECTREPLY(FD_READ
, 0));
2251 /* Disable this event until the next read(); */
2252 Socket
->SharedData
.AsyncDisabledEvents
|= FD_READ
;
2256 case AFD_EVENT_OOB_RECEIVE
:
2257 if (0 != (Socket
->SharedData
.AsyncEvents
& FD_OOB
) &&
2258 0 == (Socket
->SharedData
.AsyncDisabledEvents
& FD_OOB
))
2260 /* Make the Notifcation */
2261 (Upcalls
.lpWPUPostMessage
)(Socket
->SharedData
.hWnd
,
2262 Socket
->SharedData
.wMsg
,
2264 WSAMAKESELECTREPLY(FD_OOB
, 0));
2265 /* Disable this event until the next read(); */
2266 Socket
->SharedData
.AsyncDisabledEvents
|= FD_OOB
;
2270 case AFD_EVENT_SEND
:
2271 if (0 != (Socket
->SharedData
.AsyncEvents
& FD_WRITE
) &&
2272 0 == (Socket
->SharedData
.AsyncDisabledEvents
& FD_WRITE
))
2274 /* Make the Notifcation */
2275 (Upcalls
.lpWPUPostMessage
)(Socket
->SharedData
.hWnd
,
2276 Socket
->SharedData
.wMsg
,
2278 WSAMAKESELECTREPLY(FD_WRITE
, 0));
2279 /* Disable this event until the next write(); */
2280 Socket
->SharedData
.AsyncDisabledEvents
|= FD_WRITE
;
2284 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
2285 case AFD_EVENT_CONNECT
:
2286 if (0 != (Socket
->SharedData
.AsyncEvents
& FD_CONNECT
) &&
2287 0 == (Socket
->SharedData
.AsyncDisabledEvents
& FD_CONNECT
))
2289 /* Make the Notifcation */
2290 (Upcalls
.lpWPUPostMessage
)(Socket
->SharedData
.hWnd
,
2291 Socket
->SharedData
.wMsg
,
2293 WSAMAKESELECTREPLY(FD_CONNECT
, 0));
2294 /* Disable this event forever; */
2295 Socket
->SharedData
.AsyncDisabledEvents
|= FD_CONNECT
;
2299 case AFD_EVENT_ACCEPT
:
2300 if (0 != (Socket
->SharedData
.AsyncEvents
& FD_ACCEPT
) &&
2301 0 == (Socket
->SharedData
.AsyncDisabledEvents
& FD_ACCEPT
))
2303 /* Make the Notifcation */
2304 (Upcalls
.lpWPUPostMessage
)(Socket
->SharedData
.hWnd
,
2305 Socket
->SharedData
.wMsg
,
2307 WSAMAKESELECTREPLY(FD_ACCEPT
, 0));
2308 /* Disable this event until the next accept(); */
2309 Socket
->SharedData
.AsyncDisabledEvents
|= FD_ACCEPT
;
2313 case AFD_EVENT_DISCONNECT
:
2314 case AFD_EVENT_ABORT
:
2315 case AFD_EVENT_CLOSE
:
2316 if (0 != (Socket
->SharedData
.AsyncEvents
& FD_CLOSE
) &&
2317 0 == (Socket
->SharedData
.AsyncDisabledEvents
& FD_CLOSE
))
2319 /* Make the Notifcation */
2320 (Upcalls
.lpWPUPostMessage
)(Socket
->SharedData
.hWnd
,
2321 Socket
->SharedData
.wMsg
,
2323 WSAMAKESELECTREPLY(FD_CLOSE
, 0));
2324 /* Disable this event forever; */
2325 Socket
->SharedData
.AsyncDisabledEvents
|= FD_CLOSE
;
2328 /* FIXME: Support QOS */
2332 /* Check if there are any events left for us to check */
2333 if ((Socket
->SharedData
.AsyncEvents
& (~Socket
->SharedData
.AsyncDisabledEvents
)) == 0 )
2339 SockProcessAsyncSelect(Socket
, AsyncData
);
2343 VOID
SockProcessAsyncSelect(PSOCKET_INFORMATION Socket
, PASYNC_DATA AsyncData
)
2346 ULONG lNetworkEvents
;
2349 /* Set up the Async Data Event Info */
2350 AsyncData
->AsyncSelectInfo
.Timeout
.HighPart
= 0x7FFFFFFF;
2351 AsyncData
->AsyncSelectInfo
.Timeout
.LowPart
= 0xFFFFFFFF;
2352 AsyncData
->AsyncSelectInfo
.HandleCount
= 1;
2353 AsyncData
->AsyncSelectInfo
.Exclusive
= TRUE
;
2354 AsyncData
->AsyncSelectInfo
.Handles
[0].Handle
= Socket
->Handle
;
2355 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
= 0;
2357 /* Remove unwanted events */
2358 lNetworkEvents
= Socket
->SharedData
.AsyncEvents
& (~Socket
->SharedData
.AsyncDisabledEvents
);
2360 /* Set Events to wait for */
2361 if (lNetworkEvents
& FD_READ
)
2363 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_RECEIVE
;
2366 if (lNetworkEvents
& FD_WRITE
)
2368 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_SEND
;
2371 if (lNetworkEvents
& FD_OOB
)
2373 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_OOB_RECEIVE
;
2376 if (lNetworkEvents
& FD_ACCEPT
)
2378 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_ACCEPT
;
2381 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
2382 if (lNetworkEvents
& FD_CONNECT
)
2384 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_CONNECT
| AFD_EVENT_CONNECT_FAIL
;
2387 if (lNetworkEvents
& FD_CLOSE
)
2389 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_DISCONNECT
| AFD_EVENT_ABORT
;
2392 if (lNetworkEvents
& FD_QOS
)
2394 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_QOS
;
2397 if (lNetworkEvents
& FD_GROUP_QOS
)
2399 AsyncData
->AsyncSelectInfo
.Handles
[0].Events
|= AFD_EVENT_GROUP_QOS
;
2403 Status
= NtDeviceIoControlFile (SockAsyncHelperAfdHandle
,
2407 &AsyncData
->IoStatusBlock
,
2409 &AsyncData
->AsyncSelectInfo
,
2410 sizeof(AsyncData
->AsyncSelectInfo
),
2411 &AsyncData
->AsyncSelectInfo
,
2412 sizeof(AsyncData
->AsyncSelectInfo
));
2414 /* I/O Manager Won't call the completion routine, let's do it manually */
2415 if (NT_SUCCESS(Status
))
2421 AsyncData
->IoStatusBlock
.Status
= Status
;
2422 SockAsyncSelectCompletionRoutine(AsyncData
, &AsyncData
->IoStatusBlock
);
2426 VOID
SockProcessQueuedAsyncSelect(PVOID Context
, PIO_STATUS_BLOCK IoStatusBlock
)
2428 PASYNC_DATA AsyncData
= Context
;
2429 BOOL FreeContext
= TRUE
;
2430 PSOCKET_INFORMATION Socket
;
2432 /* Get the Socket */
2433 Socket
= AsyncData
->ParentSocket
;
2435 /* If someone closed it, stop the function */
2436 if (Socket
->SharedData
.State
!= SocketClosed
)
2438 /* Check if the Sequence Number changed by now, in which case quit */
2439 if (AsyncData
->SequenceNumber
== Socket
->SharedData
.SequenceNumber
)
2441 /* Do the actuall select, if needed */
2442 if ((Socket
->SharedData
.AsyncEvents
& (~Socket
->SharedData
.AsyncDisabledEvents
)))
2444 SockProcessAsyncSelect(Socket
, AsyncData
);
2445 FreeContext
= FALSE
;
2450 /* Free the Context */
2453 HeapFree(GetProcessHeap(), 0, AsyncData
);
2460 SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket
,
2463 PASYNC_DATA AsyncData
;
2465 /* Make sure the event is actually disabled */
2466 if (!(Socket
->SharedData
.AsyncDisabledEvents
& Event
))
2472 Socket
->SharedData
.AsyncDisabledEvents
&= ~Event
;
2474 /* Return if no more events are being polled */
2475 if ((Socket
->SharedData
.AsyncEvents
& (~Socket
->SharedData
.AsyncDisabledEvents
)) == 0 )
2480 /* Wait on new events */
2481 AsyncData
= HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA
));
2483 /* Create the Asynch Thread if Needed */
2484 SockCreateOrReferenceAsyncThread();
2486 /* Increase the sequence number to stop anything else */
2487 Socket
->SharedData
.SequenceNumber
++;
2489 /* Set up the Async Data */
2490 AsyncData
->ParentSocket
= Socket
;
2491 AsyncData
->SequenceNumber
= Socket
->SharedData
.SequenceNumber
;
2493 /* Begin Async Select by using I/O Completion */
2494 NtSetIoCompletion(SockAsyncCompletionPort
,
2495 (PVOID
)&SockProcessQueuedAsyncSelect
,
2506 DllMain(HANDLE hInstDll
,
2513 case DLL_PROCESS_ATTACH
:
2515 AFD_DbgPrint(MAX_TRACE
, ("Loading MSAFD.DLL \n"));
2517 /* Don't need thread attach notifications
2518 so disable them to improve performance */
2519 DisableThreadLibraryCalls(hInstDll
);
2521 /* List of DLL Helpers */
2522 InitializeListHead(&SockHelpersListHead
);
2524 /* Heap to use when allocating */
2525 GlobalHeap
= GetProcessHeap();
2527 /* Allocate Heap for 1024 Sockets, can be expanded later */
2528 Sockets
= HeapAlloc(GetProcessHeap(), 0, sizeof(PSOCKET_INFORMATION
) * 1024);
2530 AFD_DbgPrint(MAX_TRACE
, ("MSAFD.DLL has been loaded\n"));
2534 case DLL_THREAD_ATTACH
:
2537 case DLL_THREAD_DETACH
:
2540 case DLL_PROCESS_DETACH
:
2544 AFD_DbgPrint(MAX_TRACE
, ("DllMain of msafd.dll (leaving)\n"));