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