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