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