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