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