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