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