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