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