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