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