[MSAFD] Remove fixed CatalogEntryId. By Peter Hater. CORE-10440
[reactos.git] / reactos / dll / win32 / msafd / misc / dllmain.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Ancillary Function Driver DLL
4 * FILE: misc/dllmain.c
5 * PURPOSE: DLL entry point
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Alex Ionescu (alex@relsoft.net)
8 * REVISIONS:
9 * CSH 01/09-2000 Created
10 * Alex 16/07/2004 - Complete Rewrite
11 */
12
13 #include <msafd.h>
14
15 #include <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
2178 case SO_GROUP_ID:
2179 case SO_GROUP_PRIORITY:
2180 case SO_MAX_MSG_SIZE:
2181 case SO_PROTOCOL_INFO:
2182
2183 default:
2184 DbgPrint("MSAFD: Get unknown optname %x\n", OptionName);
2185 *lpErrno = WSAENOPROTOOPT;
2186 return SOCKET_ERROR;
2187 }
2188
2189 if (*OptionLength < BufferSize)
2190 {
2191 *lpErrno = WSAEFAULT;
2192 *OptionLength = BufferSize;
2193 return SOCKET_ERROR;
2194 }
2195 RtlCopyMemory(OptionValue, Buffer, BufferSize);
2196
2197 return 0;
2198
2199 default:
2200 break;
2201 }
2202
2203 SendToHelper:
2204 *lpErrno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
2205 Handle,
2206 Socket->TdiAddressHandle,
2207 Socket->TdiConnectionHandle,
2208 Level,
2209 OptionName,
2210 OptionValue,
2211 (LPINT)OptionLength);
2212 return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
2213 }
2214
2215 INT
2216 WSPAPI
2217 WSPSetSockOpt(
2218 IN SOCKET s,
2219 IN INT level,
2220 IN INT optname,
2221 IN CONST CHAR FAR* optval,
2222 IN INT optlen,
2223 OUT LPINT lpErrno)
2224 {
2225 PSOCKET_INFORMATION Socket;
2226
2227 /* Get the Socket Structure associate to this Socket*/
2228 Socket = GetSocketStructure(s);
2229 if (Socket == NULL)
2230 {
2231 *lpErrno = WSAENOTSOCK;
2232 return SOCKET_ERROR;
2233 }
2234
2235
2236 /* FIXME: We should handle some more cases here */
2237 if (level == SOL_SOCKET)
2238 {
2239 switch (optname)
2240 {
2241 case SO_BROADCAST:
2242 if (optlen < sizeof(BOOL))
2243 {
2244 *lpErrno = WSAEFAULT;
2245 return SOCKET_ERROR;
2246 }
2247 Socket->SharedData.Broadcast = (*optval != 0) ? 1 : 0;
2248 return 0;
2249
2250 case SO_DONTLINGER:
2251 if (optlen < sizeof(BOOL))
2252 {
2253 *lpErrno = WSAEFAULT;
2254 return SOCKET_ERROR;
2255 }
2256 Socket->SharedData.LingerData.l_onoff = (*optval != 0) ? 0 : 1;
2257 return 0;
2258
2259 case SO_REUSEADDR:
2260 if (optlen < sizeof(BOOL))
2261 {
2262 *lpErrno = WSAEFAULT;
2263 return SOCKET_ERROR;
2264 }
2265 Socket->SharedData.ReuseAddresses = (*optval != 0) ? 1 : 0;
2266 return 0;
2267
2268 case SO_EXCLUSIVEADDRUSE:
2269 if (optlen < sizeof(BOOL))
2270 {
2271 *lpErrno = WSAEFAULT;
2272 return SOCKET_ERROR;
2273 }
2274 Socket->SharedData.ExclusiveAddressUse = (*optval != 0) ? 1 : 0;
2275 return 0;
2276
2277 case SO_LINGER:
2278 if (optlen < sizeof(struct linger))
2279 {
2280 *lpErrno = WSAEFAULT;
2281 return SOCKET_ERROR;
2282 }
2283 RtlCopyMemory(&Socket->SharedData.LingerData,
2284 optval,
2285 sizeof(struct linger));
2286 return 0;
2287
2288 case SO_SNDBUF:
2289 if (optlen < sizeof(DWORD))
2290 {
2291 *lpErrno = WSAEFAULT;
2292 return SOCKET_ERROR;
2293 }
2294
2295 /* TODO: The total per-socket buffer space reserved for sends */
2296 ERR("Setting send buf to %x is not implemented yet\n", optval);
2297 return 0;
2298
2299 case SO_SNDTIMEO:
2300 if (optlen < sizeof(DWORD))
2301 {
2302 *lpErrno = WSAEFAULT;
2303 return SOCKET_ERROR;
2304 }
2305
2306 RtlCopyMemory(&Socket->SharedData.SendTimeout,
2307 optval,
2308 sizeof(DWORD));
2309 return 0;
2310
2311 case SO_RCVTIMEO:
2312 if (optlen < sizeof(DWORD))
2313 {
2314 *lpErrno = WSAEFAULT;
2315 return SOCKET_ERROR;
2316 }
2317
2318 RtlCopyMemory(&Socket->SharedData.RecvTimeout,
2319 optval,
2320 sizeof(DWORD));
2321 return 0;
2322
2323 case SO_KEEPALIVE:
2324 case SO_DONTROUTE:
2325 /* These go directly to the helper dll */
2326 goto SendToHelper;
2327
2328 default:
2329 /* Obviously this is a hack */
2330 ERR("MSAFD: Set unknown optname %x\n", optname);
2331 return 0;
2332 }
2333 }
2334
2335 SendToHelper:
2336 *lpErrno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext,
2337 s,
2338 Socket->TdiAddressHandle,
2339 Socket->TdiConnectionHandle,
2340 level,
2341 optname,
2342 (PCHAR)optval,
2343 optlen);
2344 return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
2345 }
2346
2347 /*
2348 * FUNCTION: Initialize service provider for a client
2349 * ARGUMENTS:
2350 * wVersionRequested = Highest WinSock SPI version that the caller can use
2351 * lpWSPData = Address of WSPDATA structure to initialize
2352 * lpProtocolInfo = Pointer to structure that defines the desired protocol
2353 * UpcallTable = Pointer to upcall table of the WinSock DLL
2354 * lpProcTable = Address of procedure table to initialize
2355 * RETURNS:
2356 * Status of operation
2357 */
2358 INT
2359 WSPAPI
2360 WSPStartup(IN WORD wVersionRequested,
2361 OUT LPWSPDATA lpWSPData,
2362 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
2363 IN WSPUPCALLTABLE UpcallTable,
2364 OUT LPWSPPROC_TABLE lpProcTable)
2365
2366 {
2367 NTSTATUS Status;
2368
2369 ERR("wVersionRequested (0x%X) \n", wVersionRequested);
2370 Status = NO_ERROR;
2371 Upcalls = UpcallTable;
2372
2373 if (Status == NO_ERROR)
2374 {
2375 lpProcTable->lpWSPAccept = WSPAccept;
2376 lpProcTable->lpWSPAddressToString = WSPAddressToString;
2377 lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
2378 lpProcTable->lpWSPBind = WSPBind;
2379 lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
2380 lpProcTable->lpWSPCleanup = WSPCleanup;
2381 lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
2382 lpProcTable->lpWSPConnect = WSPConnect;
2383 lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
2384 lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
2385 lpProcTable->lpWSPEventSelect = WSPEventSelect;
2386 lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
2387 lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
2388 lpProcTable->lpWSPGetSockName = WSPGetSockName;
2389 lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
2390 lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
2391 lpProcTable->lpWSPIoctl = WSPIoctl;
2392 lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
2393 lpProcTable->lpWSPListen = WSPListen;
2394 lpProcTable->lpWSPRecv = WSPRecv;
2395 lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
2396 lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
2397 lpProcTable->lpWSPSelect = WSPSelect;
2398 lpProcTable->lpWSPSend = WSPSend;
2399 lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
2400 lpProcTable->lpWSPSendTo = WSPSendTo;
2401 lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
2402 lpProcTable->lpWSPShutdown = WSPShutdown;
2403 lpProcTable->lpWSPSocket = WSPSocket;
2404 lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
2405 lpWSPData->wVersion = MAKEWORD(2, 2);
2406 lpWSPData->wHighVersion = MAKEWORD(2, 2);
2407 /* Save CatalogEntryId for all upcalls */
2408 CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
2409 }
2410
2411 TRACE("Status (%d).\n", Status);
2412 return Status;
2413 }
2414
2415
2416 /*
2417 * FUNCTION: Cleans up service provider for a client
2418 * ARGUMENTS:
2419 * lpErrno = Address of buffer for error information
2420 * RETURNS:
2421 * 0 if successful, or SOCKET_ERROR if not
2422 */
2423 INT
2424 WSPAPI
2425 WSPCleanup(OUT LPINT lpErrno)
2426
2427 {
2428 TRACE("Leaving.\n");
2429 *lpErrno = NO_ERROR;
2430
2431 return 0;
2432 }
2433
2434
2435
2436 int
2437 GetSocketInformation(PSOCKET_INFORMATION Socket,
2438 ULONG AfdInformationClass,
2439 PBOOLEAN Boolean OPTIONAL,
2440 PULONG Ulong OPTIONAL,
2441 PLARGE_INTEGER LargeInteger OPTIONAL)
2442 {
2443 IO_STATUS_BLOCK IOSB;
2444 AFD_INFO InfoData;
2445 NTSTATUS Status;
2446 HANDLE SockEvent;
2447
2448 Status = NtCreateEvent(&SockEvent,
2449 EVENT_ALL_ACCESS,
2450 NULL,
2451 1,
2452 FALSE);
2453
2454 if( !NT_SUCCESS(Status) )
2455 return -1;
2456
2457 /* Set Info Class */
2458 InfoData.InformationClass = AfdInformationClass;
2459
2460 /* Send IOCTL */
2461 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2462 SockEvent,
2463 NULL,
2464 NULL,
2465 &IOSB,
2466 IOCTL_AFD_GET_INFO,
2467 &InfoData,
2468 sizeof(InfoData),
2469 &InfoData,
2470 sizeof(InfoData));
2471
2472 /* Wait for return */
2473 if (Status == STATUS_PENDING)
2474 {
2475 WaitForSingleObject(SockEvent, INFINITE);
2476 Status = IOSB.Status;
2477 }
2478
2479 if (Status != STATUS_SUCCESS)
2480 return -1;
2481
2482 /* Return Information */
2483 if (Ulong != NULL)
2484 {
2485 *Ulong = InfoData.Information.Ulong;
2486 }
2487 if (LargeInteger != NULL)
2488 {
2489 *LargeInteger = InfoData.Information.LargeInteger;
2490 }
2491 if (Boolean != NULL)
2492 {
2493 *Boolean = InfoData.Information.Boolean;
2494 }
2495
2496 NtClose( SockEvent );
2497
2498 return 0;
2499
2500 }
2501
2502
2503 int
2504 SetSocketInformation(PSOCKET_INFORMATION Socket,
2505 ULONG AfdInformationClass,
2506 PBOOLEAN Boolean OPTIONAL,
2507 PULONG Ulong OPTIONAL,
2508 PLARGE_INTEGER LargeInteger OPTIONAL)
2509 {
2510 IO_STATUS_BLOCK IOSB;
2511 AFD_INFO InfoData;
2512 NTSTATUS Status;
2513 HANDLE SockEvent;
2514
2515 Status = NtCreateEvent(&SockEvent,
2516 EVENT_ALL_ACCESS,
2517 NULL,
2518 1,
2519 FALSE);
2520
2521 if( !NT_SUCCESS(Status) )
2522 return -1;
2523
2524 /* Set Info Class */
2525 InfoData.InformationClass = AfdInformationClass;
2526
2527 /* Set Information */
2528 if (Ulong != NULL)
2529 {
2530 InfoData.Information.Ulong = *Ulong;
2531 }
2532 if (LargeInteger != NULL)
2533 {
2534 InfoData.Information.LargeInteger = *LargeInteger;
2535 }
2536 if (Boolean != NULL)
2537 {
2538 InfoData.Information.Boolean = *Boolean;
2539 }
2540
2541 /* Send IOCTL */
2542 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2543 SockEvent,
2544 NULL,
2545 NULL,
2546 &IOSB,
2547 IOCTL_AFD_SET_INFO,
2548 &InfoData,
2549 sizeof(InfoData),
2550 NULL,
2551 0);
2552
2553 /* Wait for return */
2554 if (Status == STATUS_PENDING)
2555 {
2556 WaitForSingleObject(SockEvent, INFINITE);
2557 Status = IOSB.Status;
2558 }
2559
2560 NtClose( SockEvent );
2561
2562 return Status == STATUS_SUCCESS ? 0 : -1;
2563
2564 }
2565
2566 PSOCKET_INFORMATION
2567 GetSocketStructure(SOCKET Handle)
2568 {
2569 PSOCKET_INFORMATION CurrentSocket;
2570
2571 EnterCriticalSection(&SocketListLock);
2572
2573 CurrentSocket = SocketListHead;
2574 while (CurrentSocket)
2575 {
2576 if (CurrentSocket->Handle == Handle)
2577 {
2578 LeaveCriticalSection(&SocketListLock);
2579 return CurrentSocket;
2580 }
2581
2582 CurrentSocket = CurrentSocket->NextSocket;
2583 }
2584
2585 LeaveCriticalSection(&SocketListLock);
2586
2587 return NULL;
2588 }
2589
2590 int CreateContext(PSOCKET_INFORMATION Socket)
2591 {
2592 IO_STATUS_BLOCK IOSB;
2593 SOCKET_CONTEXT ContextData;
2594 NTSTATUS Status;
2595 HANDLE SockEvent;
2596
2597 Status = NtCreateEvent(&SockEvent,
2598 EVENT_ALL_ACCESS,
2599 NULL,
2600 1,
2601 FALSE);
2602
2603 if( !NT_SUCCESS(Status) )
2604 return -1;
2605
2606 /* Create Context */
2607 ContextData.SharedData = Socket->SharedData;
2608 ContextData.SizeOfHelperData = 0;
2609 RtlCopyMemory (&ContextData.LocalAddress,
2610 Socket->LocalAddress,
2611 Socket->SharedData.SizeOfLocalAddress);
2612 RtlCopyMemory (&ContextData.RemoteAddress,
2613 Socket->RemoteAddress,
2614 Socket->SharedData.SizeOfRemoteAddress);
2615
2616 /* Send IOCTL */
2617 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2618 SockEvent,
2619 NULL,
2620 NULL,
2621 &IOSB,
2622 IOCTL_AFD_SET_CONTEXT,
2623 &ContextData,
2624 sizeof(ContextData),
2625 NULL,
2626 0);
2627
2628 /* Wait for Completition */
2629 if (Status == STATUS_PENDING)
2630 {
2631 WaitForSingleObject(SockEvent, INFINITE);
2632 Status = IOSB.Status;
2633 }
2634
2635 NtClose( SockEvent );
2636
2637 return Status == STATUS_SUCCESS ? 0 : -1;
2638 }
2639
2640 BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
2641 {
2642 HANDLE hAsyncThread;
2643 DWORD AsyncThreadId;
2644 HANDLE AsyncEvent;
2645 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
2646 NTSTATUS Status;
2647
2648 /* Check if the Thread Already Exists */
2649 if (SockAsyncThreadRefCount)
2650 {
2651 ASSERT(SockAsyncCompletionPort);
2652 return TRUE;
2653 }
2654
2655 /* Create the Completion Port */
2656 if (!SockAsyncCompletionPort)
2657 {
2658 Status = NtCreateIoCompletion(&SockAsyncCompletionPort,
2659 IO_COMPLETION_ALL_ACCESS,
2660 NULL,
2661 2); // Allow 2 threads only
2662 if (!NT_SUCCESS(Status))
2663 {
2664 ERR("Failed to create completion port: 0x%08x\n", Status);
2665 return FALSE;
2666 }
2667 /* Protect Handle */
2668 HandleFlags.ProtectFromClose = TRUE;
2669 HandleFlags.Inherit = FALSE;
2670 Status = NtSetInformationObject(SockAsyncCompletionPort,
2671 ObjectHandleFlagInformation,
2672 &HandleFlags,
2673 sizeof(HandleFlags));
2674 }
2675
2676 /* Create the Async Event */
2677 Status = NtCreateEvent(&AsyncEvent,
2678 EVENT_ALL_ACCESS,
2679 NULL,
2680 NotificationEvent,
2681 FALSE);
2682
2683 /* Create the Async Thread */
2684 hAsyncThread = CreateThread(NULL,
2685 0,
2686 (LPTHREAD_START_ROUTINE)SockAsyncThread,
2687 NULL,
2688 0,
2689 &AsyncThreadId);
2690
2691 /* Close the Handle */
2692 NtClose(hAsyncThread);
2693
2694 /* Increase the Reference Count */
2695 SockAsyncThreadRefCount++;
2696 return TRUE;
2697 }
2698
2699 int SockAsyncThread(PVOID ThreadParam)
2700 {
2701 PVOID AsyncContext;
2702 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
2703 IO_STATUS_BLOCK IOSB;
2704 NTSTATUS Status;
2705
2706 /* Make the Thread Higher Priority */
2707 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
2708
2709 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
2710 do
2711 {
2712 Status = NtRemoveIoCompletion (SockAsyncCompletionPort,
2713 (PVOID*)&AsyncCompletionRoutine,
2714 &AsyncContext,
2715 &IOSB,
2716 NULL);
2717 /* Call the Async Function */
2718 if (NT_SUCCESS(Status))
2719 {
2720 (*AsyncCompletionRoutine)(AsyncContext, &IOSB);
2721 }
2722 else
2723 {
2724 /* It Failed, sleep for a second */
2725 Sleep(1000);
2726 }
2727 } while ((Status != STATUS_TIMEOUT));
2728
2729 /* The Thread has Ended */
2730 return 0;
2731 }
2732
2733 BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
2734 {
2735 UNICODE_STRING AfdHelper;
2736 OBJECT_ATTRIBUTES ObjectAttributes;
2737 IO_STATUS_BLOCK IoSb;
2738 FILE_COMPLETION_INFORMATION CompletionInfo;
2739 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
2740
2741 /* First, make sure we're not already intialized */
2742 if (SockAsyncHelperAfdHandle)
2743 {
2744 return TRUE;
2745 }
2746
2747 /* Set up Handle Name and Object */
2748 RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" );
2749 InitializeObjectAttributes(&ObjectAttributes,
2750 &AfdHelper,
2751 OBJ_INHERIT | OBJ_CASE_INSENSITIVE,
2752 NULL,
2753 NULL);
2754
2755 /* Open the Handle to AFD */
2756 NtCreateFile(&SockAsyncHelperAfdHandle,
2757 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
2758 &ObjectAttributes,
2759 &IoSb,
2760 NULL,
2761 0,
2762 FILE_SHARE_READ | FILE_SHARE_WRITE,
2763 FILE_OPEN_IF,
2764 0,
2765 NULL,
2766 0);
2767
2768 /*
2769 * Now Set up the Completion Port Information
2770 * This means that whenever a Poll is finished, the routine will be executed
2771 */
2772 CompletionInfo.Port = SockAsyncCompletionPort;
2773 CompletionInfo.Key = SockAsyncSelectCompletionRoutine;
2774 NtSetInformationFile(SockAsyncHelperAfdHandle,
2775 &IoSb,
2776 &CompletionInfo,
2777 sizeof(CompletionInfo),
2778 FileCompletionInformation);
2779
2780
2781 /* Protect the Handle */
2782 HandleFlags.ProtectFromClose = TRUE;
2783 HandleFlags.Inherit = FALSE;
2784 NtSetInformationObject(SockAsyncCompletionPort,
2785 ObjectHandleFlagInformation,
2786 &HandleFlags,
2787 sizeof(HandleFlags));
2788
2789
2790 /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
2791 SockAsyncSelectCalled = TRUE;
2792 return TRUE;
2793 }
2794
2795 VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
2796 {
2797
2798 PASYNC_DATA AsyncData = Context;
2799 PSOCKET_INFORMATION Socket;
2800 ULONG x;
2801
2802 /* Get the Socket */
2803 Socket = AsyncData->ParentSocket;
2804
2805 /* Check if the Sequence Number Changed behind our back */
2806 if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber )
2807 {
2808 return;
2809 }
2810
2811 /* Check we were manually called b/c of a failure */
2812 if (!NT_SUCCESS(IoStatusBlock->Status))
2813 {
2814 /* FIXME: Perform Upcall */
2815 return;
2816 }
2817
2818 for (x = 1; x; x<<=1)
2819 {
2820 switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x)
2821 {
2822 case AFD_EVENT_RECEIVE:
2823 if (0 != (Socket->SharedData.AsyncEvents & FD_READ) &&
2824 0 == (Socket->SharedData.AsyncDisabledEvents & FD_READ))
2825 {
2826 /* Make the Notifcation */
2827 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2828 Socket->SharedData.wMsg,
2829 Socket->Handle,
2830 WSAMAKESELECTREPLY(FD_READ, 0));
2831 /* Disable this event until the next read(); */
2832 Socket->SharedData.AsyncDisabledEvents |= FD_READ;
2833 }
2834 break;
2835
2836 case AFD_EVENT_OOB_RECEIVE:
2837 if (0 != (Socket->SharedData.AsyncEvents & FD_OOB) &&
2838 0 == (Socket->SharedData.AsyncDisabledEvents & FD_OOB))
2839 {
2840 /* Make the Notifcation */
2841 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2842 Socket->SharedData.wMsg,
2843 Socket->Handle,
2844 WSAMAKESELECTREPLY(FD_OOB, 0));
2845 /* Disable this event until the next read(); */
2846 Socket->SharedData.AsyncDisabledEvents |= FD_OOB;
2847 }
2848 break;
2849
2850 case AFD_EVENT_SEND:
2851 if (0 != (Socket->SharedData.AsyncEvents & FD_WRITE) &&
2852 0 == (Socket->SharedData.AsyncDisabledEvents & FD_WRITE))
2853 {
2854 /* Make the Notifcation */
2855 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2856 Socket->SharedData.wMsg,
2857 Socket->Handle,
2858 WSAMAKESELECTREPLY(FD_WRITE, 0));
2859 /* Disable this event until the next write(); */
2860 Socket->SharedData.AsyncDisabledEvents |= FD_WRITE;
2861 }
2862 break;
2863
2864 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
2865 case AFD_EVENT_CONNECT:
2866 case AFD_EVENT_CONNECT_FAIL:
2867 if (0 != (Socket->SharedData.AsyncEvents & FD_CONNECT) &&
2868 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CONNECT))
2869 {
2870 /* Make the Notifcation */
2871 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2872 Socket->SharedData.wMsg,
2873 Socket->Handle,
2874 WSAMAKESELECTREPLY(FD_CONNECT, 0));
2875 /* Disable this event forever; */
2876 Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT;
2877 }
2878 break;
2879
2880 case AFD_EVENT_ACCEPT:
2881 if (0 != (Socket->SharedData.AsyncEvents & FD_ACCEPT) &&
2882 0 == (Socket->SharedData.AsyncDisabledEvents & FD_ACCEPT))
2883 {
2884 /* Make the Notifcation */
2885 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2886 Socket->SharedData.wMsg,
2887 Socket->Handle,
2888 WSAMAKESELECTREPLY(FD_ACCEPT, 0));
2889 /* Disable this event until the next accept(); */
2890 Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT;
2891 }
2892 break;
2893
2894 case AFD_EVENT_DISCONNECT:
2895 case AFD_EVENT_ABORT:
2896 case AFD_EVENT_CLOSE:
2897 if (0 != (Socket->SharedData.AsyncEvents & FD_CLOSE) &&
2898 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CLOSE))
2899 {
2900 /* Make the Notifcation */
2901 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2902 Socket->SharedData.wMsg,
2903 Socket->Handle,
2904 WSAMAKESELECTREPLY(FD_CLOSE, 0));
2905 /* Disable this event forever; */
2906 Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE;
2907 }
2908 break;
2909 /* FIXME: Support QOS */
2910 }
2911 }
2912
2913 /* Check if there are any events left for us to check */
2914 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 )
2915 {
2916 return;
2917 }
2918
2919 /* Keep Polling */
2920 SockProcessAsyncSelect(Socket, AsyncData);
2921 return;
2922 }
2923
2924 VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData)
2925 {
2926
2927 ULONG lNetworkEvents;
2928 NTSTATUS Status;
2929
2930 /* Set up the Async Data Event Info */
2931 AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF;
2932 AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF;
2933 AsyncData->AsyncSelectInfo.HandleCount = 1;
2934 AsyncData->AsyncSelectInfo.Exclusive = TRUE;
2935 AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle;
2936 AsyncData->AsyncSelectInfo.Handles[0].Events = 0;
2937
2938 /* Remove unwanted events */
2939 lNetworkEvents = Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents);
2940
2941 /* Set Events to wait for */
2942 if (lNetworkEvents & FD_READ)
2943 {
2944 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE;
2945 }
2946
2947 if (lNetworkEvents & FD_WRITE)
2948 {
2949 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND;
2950 }
2951
2952 if (lNetworkEvents & FD_OOB)
2953 {
2954 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE;
2955 }
2956
2957 if (lNetworkEvents & FD_ACCEPT)
2958 {
2959 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT;
2960 }
2961
2962 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
2963 if (lNetworkEvents & FD_CONNECT)
2964 {
2965 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
2966 }
2967
2968 if (lNetworkEvents & FD_CLOSE)
2969 {
2970 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE;
2971 }
2972
2973 if (lNetworkEvents & FD_QOS)
2974 {
2975 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS;
2976 }
2977
2978 if (lNetworkEvents & FD_GROUP_QOS)
2979 {
2980 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS;
2981 }
2982
2983 /* Send IOCTL */
2984 Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle,
2985 NULL,
2986 NULL,
2987 AsyncData,
2988 &AsyncData->IoStatusBlock,
2989 IOCTL_AFD_SELECT,
2990 &AsyncData->AsyncSelectInfo,
2991 sizeof(AsyncData->AsyncSelectInfo),
2992 &AsyncData->AsyncSelectInfo,
2993 sizeof(AsyncData->AsyncSelectInfo));
2994
2995 /* I/O Manager Won't call the completion routine, let's do it manually */
2996 if (NT_SUCCESS(Status))
2997 {
2998 return;
2999 }
3000 else
3001 {
3002 AsyncData->IoStatusBlock.Status = Status;
3003 SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock);
3004 }
3005 }
3006
3007 VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
3008 {
3009 PASYNC_DATA AsyncData = Context;
3010 BOOL FreeContext = TRUE;
3011 PSOCKET_INFORMATION Socket;
3012
3013 /* Get the Socket */
3014 Socket = AsyncData->ParentSocket;
3015
3016 /* If someone closed it, stop the function */
3017 if (Socket->SharedData.State != SocketClosed)
3018 {
3019 /* Check if the Sequence Number changed by now, in which case quit */
3020 if (AsyncData->SequenceNumber == Socket->SharedData.SequenceNumber)
3021 {
3022 /* Do the actuall select, if needed */
3023 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)))
3024 {
3025 SockProcessAsyncSelect(Socket, AsyncData);
3026 FreeContext = FALSE;
3027 }
3028 }
3029 }
3030
3031 /* Free the Context */
3032 if (FreeContext)
3033 {
3034 HeapFree(GetProcessHeap(), 0, AsyncData);
3035 }
3036
3037 return;
3038 }
3039
3040 VOID
3041 SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket,
3042 IN ULONG Event)
3043 {
3044 PASYNC_DATA AsyncData;
3045
3046 /* Make sure the event is actually disabled */
3047 if (!(Socket->SharedData.AsyncDisabledEvents & Event))
3048 {
3049 return;
3050 }
3051
3052 /* Re-enable it */
3053 Socket->SharedData.AsyncDisabledEvents &= ~Event;
3054
3055 /* Return if no more events are being polled */
3056 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 )
3057 {
3058 return;
3059 }
3060
3061 /* Wait on new events */
3062 AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA));
3063 if (!AsyncData) return;
3064
3065 /* Create the Asynch Thread if Needed */
3066 SockCreateOrReferenceAsyncThread();
3067
3068 /* Increase the sequence number to stop anything else */
3069 Socket->SharedData.SequenceNumber++;
3070
3071 /* Set up the Async Data */
3072 AsyncData->ParentSocket = Socket;
3073 AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber;
3074
3075 /* Begin Async Select by using I/O Completion */
3076 NtSetIoCompletion(SockAsyncCompletionPort,
3077 (PVOID)&SockProcessQueuedAsyncSelect,
3078 AsyncData,
3079 0,
3080 0);
3081
3082 /* All done */
3083 return;
3084 }
3085
3086 BOOL
3087 WINAPI
3088 DllMain(HANDLE hInstDll,
3089 ULONG dwReason,
3090 PVOID Reserved)
3091 {
3092
3093 switch (dwReason)
3094 {
3095 case DLL_PROCESS_ATTACH:
3096
3097 TRACE("Loading MSAFD.DLL \n");
3098
3099 /* Don't need thread attach notifications
3100 so disable them to improve performance */
3101 DisableThreadLibraryCalls(hInstDll);
3102
3103 /* List of DLL Helpers */
3104 InitializeListHead(&SockHelpersListHead);
3105
3106 /* Heap to use when allocating */
3107 GlobalHeap = GetProcessHeap();
3108
3109 /* Initialize the lock that protects our socket list */
3110 InitializeCriticalSection(&SocketListLock);
3111
3112 TRACE("MSAFD.DLL has been loaded\n");
3113
3114 break;
3115
3116 case DLL_THREAD_ATTACH:
3117 break;
3118
3119 case DLL_THREAD_DETACH:
3120 break;
3121
3122 case DLL_PROCESS_DETACH:
3123
3124 /* Delete the socket list lock */
3125 DeleteCriticalSection(&SocketListLock);
3126
3127 break;
3128 }
3129
3130 TRACE("DllMain of msafd.dll (leaving)\n");
3131
3132 return TRUE;
3133 }
3134
3135 /* EOF */
3136
3137