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