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