[MSAFD]: Addendum to r73203.
[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 DWORD
1324 GetCurrentTimeInSeconds()
1325 {
1326 FILETIME Time;
1327 FILETIME Adjustment;
1328 ULARGE_INTEGER lTime, lAdj;
1329 SYSTEMTIME st = { 1970,1,0,1,0,0,0 };
1330 SystemTimeToFileTime(&st, &Adjustment);
1331 memcpy(&lAdj, &Adjustment, sizeof(lAdj));
1332 GetSystemTimeAsFileTime(&Time);
1333 memcpy(&lTime, &Time, sizeof(lTime));
1334 lTime.QuadPart -= lAdj.QuadPart;
1335 return (DWORD)(lTime.QuadPart / 10000000LLU);
1336 }
1337
1338 SOCKET
1339 WSPAPI
1340 WSPAccept(SOCKET Handle,
1341 struct sockaddr *SocketAddress,
1342 int *SocketAddressLength,
1343 LPCONDITIONPROC lpfnCondition,
1344 DWORD dwCallbackData,
1345 LPINT lpErrno)
1346 {
1347 IO_STATUS_BLOCK IOSB;
1348 PAFD_RECEIVED_ACCEPT_DATA ListenReceiveData;
1349 AFD_ACCEPT_DATA AcceptData;
1350 AFD_DEFER_ACCEPT_DATA DeferData;
1351 AFD_PENDING_ACCEPT_DATA PendingAcceptData;
1352 PSOCKET_INFORMATION Socket = NULL;
1353 NTSTATUS Status;
1354 struct fd_set ReadSet;
1355 struct timeval Timeout;
1356 PVOID PendingData = NULL;
1357 ULONG PendingDataLength = 0;
1358 PVOID CalleeDataBuffer;
1359 WSABUF CallerData, CalleeID, CallerID, CalleeData;
1360 PSOCKADDR RemoteAddress = NULL;
1361 GROUP GroupID = 0;
1362 ULONG CallBack;
1363 SOCKET AcceptSocket;
1364 PSOCKET_INFORMATION AcceptSocketInfo;
1365 UCHAR ReceiveBuffer[0x1A];
1366 HANDLE SockEvent;
1367
1368 /* Get the Socket Structure associate to this Socket*/
1369 Socket = GetSocketStructure(Handle);
1370 if (!Socket)
1371 {
1372 if (lpErrno) *lpErrno = WSAENOTSOCK;
1373 return SOCKET_ERROR;
1374 }
1375 if ((SocketAddress && !SocketAddressLength) ||
1376 (SocketAddressLength && !SocketAddress) ||
1377 (SocketAddressLength && *SocketAddressLength < sizeof(SOCKADDR)))
1378 {
1379 if (lpErrno) *lpErrno = WSAEFAULT;
1380 return INVALID_SOCKET;
1381 }
1382
1383 Status = NtCreateEvent(&SockEvent,
1384 EVENT_ALL_ACCESS,
1385 NULL,
1386 1,
1387 FALSE);
1388
1389 if( !NT_SUCCESS(Status) )
1390 {
1391 return SOCKET_ERROR;
1392 }
1393
1394 /* Dynamic Structure...ugh */
1395 ListenReceiveData = (PAFD_RECEIVED_ACCEPT_DATA)ReceiveBuffer;
1396
1397 /* If this is non-blocking, make sure there's something for us to accept */
1398 FD_ZERO(&ReadSet);
1399 FD_SET(Socket->Handle, &ReadSet);
1400 Timeout.tv_sec=0;
1401 Timeout.tv_usec=0;
1402
1403 if (WSPSelect(0, &ReadSet, NULL, NULL, &Timeout, lpErrno) == SOCKET_ERROR)
1404 {
1405 NtClose(SockEvent);
1406 return SOCKET_ERROR;
1407 }
1408
1409 if (ReadSet.fd_array[0] != Socket->Handle)
1410 {
1411 NtClose(SockEvent);
1412 if (lpErrno) *lpErrno = WSAEWOULDBLOCK;
1413 return SOCKET_ERROR;
1414 }
1415
1416 /* Send IOCTL */
1417 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1418 SockEvent,
1419 NULL,
1420 NULL,
1421 &IOSB,
1422 IOCTL_AFD_WAIT_FOR_LISTEN,
1423 NULL,
1424 0,
1425 ListenReceiveData,
1426 0xA + sizeof(*ListenReceiveData));
1427
1428 /* Wait for return */
1429 if (Status == STATUS_PENDING)
1430 {
1431 WaitForSingleObject(SockEvent, INFINITE);
1432 Status = IOSB.Status;
1433 }
1434
1435 if (!NT_SUCCESS(Status))
1436 {
1437 NtClose( SockEvent );
1438 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1439 }
1440
1441 if (lpfnCondition != NULL)
1442 {
1443 if ((Socket->SharedData->ServiceFlags1 & XP1_CONNECT_DATA) != 0)
1444 {
1445 /* Find out how much data is pending */
1446 PendingAcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
1447 PendingAcceptData.ReturnSize = TRUE;
1448
1449 /* Send IOCTL */
1450 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1451 SockEvent,
1452 NULL,
1453 NULL,
1454 &IOSB,
1455 IOCTL_AFD_GET_PENDING_CONNECT_DATA,
1456 &PendingAcceptData,
1457 sizeof(PendingAcceptData),
1458 &PendingAcceptData,
1459 sizeof(PendingAcceptData));
1460
1461 /* Wait for return */
1462 if (Status == STATUS_PENDING)
1463 {
1464 WaitForSingleObject(SockEvent, INFINITE);
1465 Status = IOSB.Status;
1466 }
1467
1468 if (!NT_SUCCESS(Status))
1469 {
1470 NtClose( SockEvent );
1471 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1472 }
1473
1474 /* How much data to allocate */
1475 PendingDataLength = IOSB.Information;
1476
1477 if (PendingDataLength)
1478 {
1479 /* Allocate needed space */
1480 PendingData = HeapAlloc(GlobalHeap, 0, PendingDataLength);
1481 if (!PendingData)
1482 {
1483 return MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
1484 }
1485
1486 /* We want the data now */
1487 PendingAcceptData.ReturnSize = FALSE;
1488
1489 /* Send IOCTL */
1490 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1491 SockEvent,
1492 NULL,
1493 NULL,
1494 &IOSB,
1495 IOCTL_AFD_GET_PENDING_CONNECT_DATA,
1496 &PendingAcceptData,
1497 sizeof(PendingAcceptData),
1498 PendingData,
1499 PendingDataLength);
1500
1501 /* Wait for return */
1502 if (Status == STATUS_PENDING)
1503 {
1504 WaitForSingleObject(SockEvent, INFINITE);
1505 Status = IOSB.Status;
1506 }
1507
1508 if (!NT_SUCCESS(Status))
1509 {
1510 NtClose( SockEvent );
1511 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1512 }
1513 }
1514 }
1515
1516 if ((Socket->SharedData->ServiceFlags1 & XP1_QOS_SUPPORTED) != 0)
1517 {
1518 /* I don't support this yet */
1519 }
1520
1521 /* Build Callee ID */
1522 CalleeID.buf = (PVOID)Socket->LocalAddress;
1523 CalleeID.len = Socket->SharedData->SizeOfLocalAddress;
1524
1525 RemoteAddress = HeapAlloc(GlobalHeap, 0, sizeof(*RemoteAddress));
1526 if (!RemoteAddress)
1527 {
1528 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
1529 }
1530
1531 /* Set up Address in SOCKADDR Format */
1532 RtlCopyMemory (RemoteAddress,
1533 &ListenReceiveData->Address.Address[0].AddressType,
1534 sizeof(*RemoteAddress));
1535
1536 /* Build Caller ID */
1537 CallerID.buf = (PVOID)RemoteAddress;
1538 CallerID.len = sizeof(*RemoteAddress);
1539
1540 /* Build Caller Data */
1541 CallerData.buf = PendingData;
1542 CallerData.len = PendingDataLength;
1543
1544 /* Check if socket supports Conditional Accept */
1545 if (Socket->SharedData->UseDelayedAcceptance != 0)
1546 {
1547 /* Allocate Buffer for Callee Data */
1548 CalleeDataBuffer = HeapAlloc(GlobalHeap, 0, 4096);
1549 if (!CalleeDataBuffer) {
1550 return MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL );
1551 }
1552 CalleeData.buf = CalleeDataBuffer;
1553 CalleeData.len = 4096;
1554 }
1555 else
1556 {
1557 /* Nothing */
1558 CalleeData.buf = 0;
1559 CalleeData.len = 0;
1560 }
1561
1562 /* Call the Condition Function */
1563 CallBack = (lpfnCondition)(&CallerID,
1564 CallerData.buf == NULL ? NULL : &CallerData,
1565 NULL,
1566 NULL,
1567 &CalleeID,
1568 CalleeData.buf == NULL ? NULL : &CalleeData,
1569 &GroupID,
1570 dwCallbackData);
1571
1572 if (((CallBack == CF_ACCEPT) && GroupID) != 0)
1573 {
1574 /* TBD: Check for Validity */
1575 }
1576
1577 if (CallBack == CF_ACCEPT)
1578 {
1579 if ((Socket->SharedData->ServiceFlags1 & XP1_QOS_SUPPORTED) != 0)
1580 {
1581 /* I don't support this yet */
1582 }
1583 if (CalleeData.buf)
1584 {
1585 // SockSetConnectData Sockets(SocketID), IOCTL_AFD_SET_CONNECT_DATA, CalleeData.Buffer, CalleeData.BuffSize, 0
1586 }
1587 }
1588 else
1589 {
1590 /* Callback rejected. Build Defer Structure */
1591 DeferData.SequenceNumber = ListenReceiveData->SequenceNumber;
1592 DeferData.RejectConnection = (CallBack == CF_REJECT);
1593
1594 /* Send IOCTL */
1595 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1596 SockEvent,
1597 NULL,
1598 NULL,
1599 &IOSB,
1600 IOCTL_AFD_DEFER_ACCEPT,
1601 &DeferData,
1602 sizeof(DeferData),
1603 NULL,
1604 0);
1605
1606 /* Wait for return */
1607 if (Status == STATUS_PENDING)
1608 {
1609 WaitForSingleObject(SockEvent, INFINITE);
1610 Status = IOSB.Status;
1611 }
1612
1613 NtClose( SockEvent );
1614
1615 if (!NT_SUCCESS(Status))
1616 {
1617 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1618 }
1619
1620 if (CallBack == CF_REJECT )
1621 {
1622 if (lpErrno) *lpErrno = WSAECONNREFUSED;
1623 return SOCKET_ERROR;
1624 }
1625 else
1626 {
1627 if (lpErrno) *lpErrno = WSAECONNREFUSED;
1628 return SOCKET_ERROR;
1629 }
1630 }
1631 }
1632
1633 /* Create a new Socket */
1634 AcceptSocket = WSPSocket (Socket->SharedData->AddressFamily,
1635 Socket->SharedData->SocketType,
1636 Socket->SharedData->Protocol,
1637 &Socket->ProtocolInfo,
1638 GroupID,
1639 Socket->SharedData->CreateFlags,
1640 lpErrno);
1641 if (AcceptSocket == INVALID_SOCKET)
1642 return SOCKET_ERROR;
1643
1644 /* Set up the Accept Structure */
1645 AcceptData.ListenHandle = (HANDLE)AcceptSocket;
1646 AcceptData.SequenceNumber = ListenReceiveData->SequenceNumber;
1647
1648 /* Send IOCTL to Accept */
1649 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1650 SockEvent,
1651 NULL,
1652 NULL,
1653 &IOSB,
1654 IOCTL_AFD_ACCEPT,
1655 &AcceptData,
1656 sizeof(AcceptData),
1657 NULL,
1658 0);
1659
1660 /* Wait for return */
1661 if (Status == STATUS_PENDING)
1662 {
1663 WaitForSingleObject(SockEvent, INFINITE);
1664 Status = IOSB.Status;
1665 }
1666
1667 Socket->SharedData->SocketLastError = TranslateNtStatusError(Status);
1668 if (!NT_SUCCESS(Status))
1669 {
1670 NtClose(SockEvent);
1671 WSPCloseSocket( AcceptSocket, lpErrno );
1672 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
1673 }
1674
1675 AcceptSocketInfo = GetSocketStructure(AcceptSocket);
1676 if (!AcceptSocketInfo)
1677 {
1678 NtClose(SockEvent);
1679 WSPCloseSocket( AcceptSocket, lpErrno );
1680 return MsafdReturnWithErrno( STATUS_PROTOCOL_NOT_SUPPORTED, lpErrno, 0, NULL );
1681 }
1682
1683 AcceptSocketInfo->SharedData->State = SocketConnected;
1684 AcceptSocketInfo->SharedData->ConnectTime = GetCurrentTimeInSeconds();
1685
1686 /* Return Address in SOCKADDR FORMAT */
1687 if( SocketAddress )
1688 {
1689 RtlCopyMemory (SocketAddress,
1690 &ListenReceiveData->Address.Address[0].AddressType,
1691 sizeof(*RemoteAddress));
1692 if( SocketAddressLength )
1693 *SocketAddressLength = sizeof(*RemoteAddress);
1694 }
1695
1696 NtClose( SockEvent );
1697
1698 /* Re-enable Async Event */
1699 SockReenableAsyncSelectEvent(Socket, FD_ACCEPT);
1700
1701 TRACE("Socket %x\n", AcceptSocket);
1702
1703 if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_ACCEPT))
1704 {
1705 Status = Socket->HelperData->WSHNotify(Socket->HelperContext,
1706 Socket->Handle,
1707 Socket->TdiAddressHandle,
1708 Socket->TdiConnectionHandle,
1709 WSH_NOTIFY_ACCEPT);
1710
1711 if (Status)
1712 {
1713 if (lpErrno) *lpErrno = Status;
1714 return SOCKET_ERROR;
1715 }
1716 }
1717
1718 if (lpErrno) *lpErrno = NO_ERROR;
1719
1720 /* Return Socket */
1721 return AcceptSocket;
1722 }
1723
1724 int
1725 WSPAPI
1726 WSPConnect(SOCKET Handle,
1727 const struct sockaddr * SocketAddress,
1728 int SocketAddressLength,
1729 LPWSABUF lpCallerData,
1730 LPWSABUF lpCalleeData,
1731 LPQOS lpSQOS,
1732 LPQOS lpGQOS,
1733 LPINT lpErrno)
1734 {
1735 IO_STATUS_BLOCK IOSB;
1736 PAFD_CONNECT_INFO ConnectInfo = NULL;
1737 PSOCKET_INFORMATION Socket;
1738 NTSTATUS Status;
1739 INT Errno;
1740 ULONG ConnectDataLength;
1741 ULONG InConnectDataLength;
1742 INT BindAddressLength;
1743 PSOCKADDR BindAddress;
1744 HANDLE SockEvent;
1745 int SocketDataLength;
1746
1747 TRACE("Called (%lx) %lx:%d\n", Handle, ((const struct sockaddr_in *)SocketAddress)->sin_addr, ((const struct sockaddr_in *)SocketAddress)->sin_port);
1748
1749 /* Get the Socket Structure associate to this Socket*/
1750 Socket = GetSocketStructure(Handle);
1751 if (!Socket)
1752 {
1753 if (lpErrno) *lpErrno = WSAENOTSOCK;
1754 return SOCKET_ERROR;
1755 }
1756
1757 Status = NtCreateEvent(&SockEvent,
1758 EVENT_ALL_ACCESS,
1759 NULL,
1760 1,
1761 FALSE);
1762
1763 if (!NT_SUCCESS(Status))
1764 return SOCKET_ERROR;
1765
1766 /* Bind us First */
1767 if (Socket->SharedData->State == SocketOpen)
1768 {
1769 /* Get the Wildcard Address */
1770 BindAddressLength = Socket->HelperData->MaxWSAddressLength;
1771 BindAddress = HeapAlloc(GetProcessHeap(), 0, BindAddressLength);
1772 if (!BindAddress)
1773 {
1774 NtClose(SockEvent);
1775 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL);
1776 }
1777 Socket->HelperData->WSHGetWildcardSockaddr (Socket->HelperContext,
1778 BindAddress,
1779 &BindAddressLength);
1780 /* Bind it */
1781 if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR)
1782 return SOCKET_ERROR;
1783 }
1784
1785 /* Set the Connect Data */
1786 if (lpCallerData != NULL)
1787 {
1788 ConnectDataLength = lpCallerData->len;
1789 Status = NtDeviceIoControlFile((HANDLE)Handle,
1790 SockEvent,
1791 NULL,
1792 NULL,
1793 &IOSB,
1794 IOCTL_AFD_SET_CONNECT_DATA,
1795 lpCallerData->buf,
1796 ConnectDataLength,
1797 NULL,
1798 0);
1799 /* Wait for return */
1800 if (Status == STATUS_PENDING)
1801 {
1802 WaitForSingleObject(SockEvent, INFINITE);
1803 Status = IOSB.Status;
1804 }
1805
1806 if (Status != STATUS_SUCCESS)
1807 goto notify;
1808 }
1809
1810 /* Calculate the size of SocketAddress->sa_data */
1811 SocketDataLength = SocketAddressLength - FIELD_OFFSET(struct sockaddr, sa_data);
1812
1813 /* Allocate a connection info buffer with SocketDataLength bytes of payload */
1814 ConnectInfo = HeapAlloc(GetProcessHeap(), 0,
1815 FIELD_OFFSET(AFD_CONNECT_INFO,
1816 RemoteAddress.Address[0].Address[SocketDataLength]));
1817 if (!ConnectInfo)
1818 {
1819 Status = STATUS_INSUFFICIENT_RESOURCES;
1820 goto notify;
1821 }
1822
1823 /* Set up Address in TDI Format */
1824 ConnectInfo->RemoteAddress.TAAddressCount = 1;
1825 ConnectInfo->RemoteAddress.Address[0].AddressLength = SocketDataLength;
1826 ConnectInfo->RemoteAddress.Address[0].AddressType = SocketAddress->sa_family;
1827 RtlCopyMemory(ConnectInfo->RemoteAddress.Address[0].Address,
1828 SocketAddress->sa_data,
1829 SocketDataLength);
1830
1831 /*
1832 * Disable FD_WRITE and FD_CONNECT
1833 * The latter fixes a race condition where the FD_CONNECT is re-enabled
1834 * at the end of this function right after the Async Thread disables it.
1835 * This should only happen at the *next* WSPConnect
1836 */
1837 if (Socket->SharedData->AsyncEvents & FD_CONNECT)
1838 {
1839 Socket->SharedData->AsyncDisabledEvents |= FD_CONNECT | FD_WRITE;
1840 }
1841
1842 /* Tell AFD that we want Connection Data back, have it allocate a buffer */
1843 if (lpCalleeData != NULL)
1844 {
1845 InConnectDataLength = lpCalleeData->len;
1846 Status = NtDeviceIoControlFile((HANDLE)Handle,
1847 SockEvent,
1848 NULL,
1849 NULL,
1850 &IOSB,
1851 IOCTL_AFD_SET_CONNECT_DATA_SIZE,
1852 &InConnectDataLength,
1853 sizeof(InConnectDataLength),
1854 NULL,
1855 0);
1856
1857 /* Wait for return */
1858 if (Status == STATUS_PENDING)
1859 {
1860 WaitForSingleObject(SockEvent, INFINITE);
1861 Status = IOSB.Status;
1862 }
1863
1864 if (Status != STATUS_SUCCESS)
1865 goto notify;
1866 }
1867
1868 /* AFD doesn't seem to care if these are invalid, but let's 0 them anyways */
1869 ConnectInfo->Root = 0;
1870 ConnectInfo->UseSAN = FALSE;
1871 ConnectInfo->Unknown = 0;
1872
1873 /* FIXME: Handle Async Connect */
1874 if (Socket->SharedData->NonBlocking)
1875 {
1876 ERR("Async Connect UNIMPLEMENTED!\n");
1877 }
1878
1879 /* Send IOCTL */
1880 Status = NtDeviceIoControlFile((HANDLE)Handle,
1881 SockEvent,
1882 NULL,
1883 NULL,
1884 &IOSB,
1885 IOCTL_AFD_CONNECT,
1886 ConnectInfo,
1887 0x22,
1888 NULL,
1889 0);
1890 /* Wait for return */
1891 if (Status == STATUS_PENDING)
1892 {
1893 WaitForSingleObject(SockEvent, INFINITE);
1894 Status = IOSB.Status;
1895 }
1896
1897 Socket->SharedData->SocketLastError = TranslateNtStatusError(Status);
1898 if (Status != STATUS_SUCCESS)
1899 goto notify;
1900
1901 Socket->SharedData->State = SocketConnected;
1902 Socket->TdiConnectionHandle = (HANDLE)IOSB.Information;
1903 Socket->SharedData->ConnectTime = GetCurrentTimeInSeconds();
1904
1905 /* Get any pending connect data */
1906 if (lpCalleeData != NULL)
1907 {
1908 Status = NtDeviceIoControlFile((HANDLE)Handle,
1909 SockEvent,
1910 NULL,
1911 NULL,
1912 &IOSB,
1913 IOCTL_AFD_GET_CONNECT_DATA,
1914 NULL,
1915 0,
1916 lpCalleeData->buf,
1917 lpCalleeData->len);
1918 /* Wait for return */
1919 if (Status == STATUS_PENDING)
1920 {
1921 WaitForSingleObject(SockEvent, INFINITE);
1922 Status = IOSB.Status;
1923 }
1924 }
1925
1926 TRACE("Ending %lx\n", IOSB.Status);
1927
1928 notify:
1929 if (ConnectInfo) HeapFree(GetProcessHeap(), 0, ConnectInfo);
1930
1931 /* Re-enable Async Event */
1932 SockReenableAsyncSelectEvent(Socket, FD_WRITE);
1933
1934 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
1935 SockReenableAsyncSelectEvent(Socket, FD_CONNECT);
1936
1937 NtClose(SockEvent);
1938
1939 if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT))
1940 {
1941 Errno = Socket->HelperData->WSHNotify(Socket->HelperContext,
1942 Socket->Handle,
1943 Socket->TdiAddressHandle,
1944 Socket->TdiConnectionHandle,
1945 WSH_NOTIFY_CONNECT);
1946
1947 if (Errno)
1948 {
1949 if (lpErrno) *lpErrno = Errno;
1950 return SOCKET_ERROR;
1951 }
1952 }
1953 else if (Status != STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR))
1954 {
1955 Errno = Socket->HelperData->WSHNotify(Socket->HelperContext,
1956 Socket->Handle,
1957 Socket->TdiAddressHandle,
1958 Socket->TdiConnectionHandle,
1959 WSH_NOTIFY_CONNECT_ERROR);
1960
1961 if (Errno)
1962 {
1963 if (lpErrno) *lpErrno = Errno;
1964 return SOCKET_ERROR;
1965 }
1966 }
1967
1968 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL);
1969 }
1970 int
1971 WSPAPI
1972 WSPShutdown(SOCKET Handle,
1973 int HowTo,
1974 LPINT lpErrno)
1975
1976 {
1977 IO_STATUS_BLOCK IOSB;
1978 AFD_DISCONNECT_INFO DisconnectInfo;
1979 PSOCKET_INFORMATION Socket = NULL;
1980 NTSTATUS Status;
1981 HANDLE SockEvent;
1982
1983 TRACE("Called\n");
1984
1985 /* Get the Socket Structure associate to this Socket*/
1986 Socket = GetSocketStructure(Handle);
1987 if (!Socket)
1988 {
1989 if (lpErrno) *lpErrno = WSAENOTSOCK;
1990 return SOCKET_ERROR;
1991 }
1992
1993 Status = NtCreateEvent(&SockEvent,
1994 EVENT_ALL_ACCESS,
1995 NULL,
1996 1,
1997 FALSE);
1998
1999 if( !NT_SUCCESS(Status) )
2000 return SOCKET_ERROR;
2001
2002 /* Set AFD Disconnect Type */
2003 switch (HowTo)
2004 {
2005 case SD_RECEIVE:
2006 DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV;
2007 Socket->SharedData->ReceiveShutdown = TRUE;
2008 break;
2009 case SD_SEND:
2010 DisconnectInfo.DisconnectType= AFD_DISCONNECT_SEND;
2011 Socket->SharedData->SendShutdown = TRUE;
2012 break;
2013 case SD_BOTH:
2014 DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND;
2015 Socket->SharedData->ReceiveShutdown = TRUE;
2016 Socket->SharedData->SendShutdown = TRUE;
2017 break;
2018 }
2019
2020 DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1000000);
2021
2022 /* Send IOCTL */
2023 Status = NtDeviceIoControlFile((HANDLE)Handle,
2024 SockEvent,
2025 NULL,
2026 NULL,
2027 &IOSB,
2028 IOCTL_AFD_DISCONNECT,
2029 &DisconnectInfo,
2030 sizeof(DisconnectInfo),
2031 NULL,
2032 0);
2033
2034 /* Wait for return */
2035 if (Status == STATUS_PENDING)
2036 {
2037 WaitForSingleObject(SockEvent, INFINITE);
2038 Status = IOSB.Status;
2039 }
2040
2041 TRACE("Ending\n");
2042
2043 NtClose( SockEvent );
2044
2045 Socket->SharedData->SocketLastError = TranslateNtStatusError(Status);
2046 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL );
2047 }
2048
2049
2050 INT
2051 WSPAPI
2052 WSPGetSockName(IN SOCKET Handle,
2053 OUT LPSOCKADDR Name,
2054 IN OUT LPINT NameLength,
2055 OUT LPINT lpErrno)
2056 {
2057 IO_STATUS_BLOCK IOSB;
2058 ULONG TdiAddressSize;
2059 PTDI_ADDRESS_INFO TdiAddress;
2060 PTRANSPORT_ADDRESS SocketAddress;
2061 PSOCKET_INFORMATION Socket = NULL;
2062 NTSTATUS Status;
2063 HANDLE SockEvent;
2064
2065 /* Get the Socket Structure associate to this Socket*/
2066 Socket = GetSocketStructure(Handle);
2067 if (!Socket)
2068 {
2069 if (lpErrno) *lpErrno = WSAENOTSOCK;
2070 return SOCKET_ERROR;
2071 }
2072
2073 if (!Name || !NameLength)
2074 {
2075 if (lpErrno) *lpErrno = WSAEFAULT;
2076 return SOCKET_ERROR;
2077 }
2078
2079 Status = NtCreateEvent(&SockEvent,
2080 EVENT_ALL_ACCESS,
2081 NULL,
2082 1,
2083 FALSE);
2084
2085 if( !NT_SUCCESS(Status) )
2086 return SOCKET_ERROR;
2087
2088 /* Allocate a buffer for the address */
2089 TdiAddressSize =
2090 sizeof(TRANSPORT_ADDRESS) + Socket->SharedData->SizeOfLocalAddress;
2091 TdiAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize);
2092
2093 if ( TdiAddress == NULL )
2094 {
2095 NtClose( SockEvent );
2096 if (lpErrno) *lpErrno = WSAENOBUFS;
2097 return SOCKET_ERROR;
2098 }
2099
2100 SocketAddress = &TdiAddress->Address;
2101
2102 /* Send IOCTL */
2103 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2104 SockEvent,
2105 NULL,
2106 NULL,
2107 &IOSB,
2108 IOCTL_AFD_GET_SOCK_NAME,
2109 NULL,
2110 0,
2111 TdiAddress,
2112 TdiAddressSize);
2113
2114 /* Wait for return */
2115 if (Status == STATUS_PENDING)
2116 {
2117 WaitForSingleObject(SockEvent, INFINITE);
2118 Status = IOSB.Status;
2119 }
2120
2121 NtClose( SockEvent );
2122
2123 if (NT_SUCCESS(Status))
2124 {
2125 if (*NameLength >= Socket->SharedData->SizeOfLocalAddress)
2126 {
2127 Name->sa_family = SocketAddress->Address[0].AddressType;
2128 RtlCopyMemory (Name->sa_data,
2129 SocketAddress->Address[0].Address,
2130 SocketAddress->Address[0].AddressLength);
2131 *NameLength = Socket->SharedData->SizeOfLocalAddress;
2132 TRACE("NameLength %d Address: %x Port %x\n",
2133 *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr,
2134 ((struct sockaddr_in *)Name)->sin_port);
2135 HeapFree(GlobalHeap, 0, TdiAddress);
2136 return 0;
2137 }
2138 else
2139 {
2140 HeapFree(GlobalHeap, 0, TdiAddress);
2141 if (lpErrno) *lpErrno = WSAEFAULT;
2142 return SOCKET_ERROR;
2143 }
2144 }
2145
2146 HeapFree(GlobalHeap, 0, TdiAddress);
2147
2148 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
2149 }
2150
2151
2152 INT
2153 WSPAPI
2154 WSPGetPeerName(IN SOCKET s,
2155 OUT LPSOCKADDR Name,
2156 IN OUT LPINT NameLength,
2157 OUT LPINT lpErrno)
2158 {
2159 IO_STATUS_BLOCK IOSB;
2160 ULONG TdiAddressSize;
2161 PTRANSPORT_ADDRESS SocketAddress;
2162 PSOCKET_INFORMATION Socket = NULL;
2163 NTSTATUS Status;
2164 HANDLE SockEvent;
2165
2166 /* Get the Socket Structure associate to this Socket*/
2167 Socket = GetSocketStructure(s);
2168 if (!Socket)
2169 {
2170 if (lpErrno) *lpErrno = WSAENOTSOCK;
2171 return SOCKET_ERROR;
2172 }
2173
2174 if (Socket->SharedData->State != SocketConnected)
2175 {
2176 if (lpErrno) *lpErrno = WSAENOTCONN;
2177 return SOCKET_ERROR;
2178 }
2179
2180 if (!Name || !NameLength)
2181 {
2182 if (lpErrno) *lpErrno = WSAEFAULT;
2183 return SOCKET_ERROR;
2184 }
2185
2186 Status = NtCreateEvent(&SockEvent,
2187 EVENT_ALL_ACCESS,
2188 NULL,
2189 1,
2190 FALSE);
2191
2192 if( !NT_SUCCESS(Status) )
2193 return SOCKET_ERROR;
2194
2195 /* Allocate a buffer for the address */
2196 TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + Socket->SharedData->SizeOfRemoteAddress;
2197 SocketAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize);
2198
2199 if ( SocketAddress == NULL )
2200 {
2201 NtClose( SockEvent );
2202 if (lpErrno) *lpErrno = WSAENOBUFS;
2203 return SOCKET_ERROR;
2204 }
2205
2206 /* Send IOCTL */
2207 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2208 SockEvent,
2209 NULL,
2210 NULL,
2211 &IOSB,
2212 IOCTL_AFD_GET_PEER_NAME,
2213 NULL,
2214 0,
2215 SocketAddress,
2216 TdiAddressSize);
2217
2218 /* Wait for return */
2219 if (Status == STATUS_PENDING)
2220 {
2221 WaitForSingleObject(SockEvent, INFINITE);
2222 Status = IOSB.Status;
2223 }
2224
2225 NtClose( SockEvent );
2226
2227 if (NT_SUCCESS(Status))
2228 {
2229 if (*NameLength >= Socket->SharedData->SizeOfRemoteAddress)
2230 {
2231 Name->sa_family = SocketAddress->Address[0].AddressType;
2232 RtlCopyMemory (Name->sa_data,
2233 SocketAddress->Address[0].Address,
2234 SocketAddress->Address[0].AddressLength);
2235 *NameLength = Socket->SharedData->SizeOfRemoteAddress;
2236 TRACE("NameLength %d Address: %x Port %x\n",
2237 *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr,
2238 ((struct sockaddr_in *)Name)->sin_port);
2239 HeapFree(GlobalHeap, 0, SocketAddress);
2240 return 0;
2241 }
2242 else
2243 {
2244 HeapFree(GlobalHeap, 0, SocketAddress);
2245 if (lpErrno) *lpErrno = WSAEFAULT;
2246 return SOCKET_ERROR;
2247 }
2248 }
2249
2250 HeapFree(GlobalHeap, 0, SocketAddress);
2251
2252 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL );
2253 }
2254
2255 INT
2256 WSPAPI
2257 WSPIoctl(IN SOCKET Handle,
2258 IN DWORD dwIoControlCode,
2259 IN LPVOID lpvInBuffer,
2260 IN DWORD cbInBuffer,
2261 OUT LPVOID lpvOutBuffer,
2262 IN DWORD cbOutBuffer,
2263 OUT LPDWORD lpcbBytesReturned,
2264 IN LPWSAOVERLAPPED lpOverlapped,
2265 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine,
2266 IN LPWSATHREADID lpThreadId,
2267 OUT LPINT lpErrno)
2268 {
2269 PSOCKET_INFORMATION Socket = NULL;
2270 BOOL NeedsCompletion = lpOverlapped != NULL;
2271 BOOLEAN NonBlocking;
2272 INT Errno = NO_ERROR, Ret = SOCKET_ERROR;
2273 DWORD cbRet = 0;
2274
2275 /* Get the Socket Structure associate to this Socket*/
2276 Socket = GetSocketStructure(Handle);
2277 if (!Socket)
2278 {
2279 if(lpErrno)
2280 *lpErrno = WSAENOTSOCK;
2281 return SOCKET_ERROR;
2282 }
2283
2284 if (!lpcbBytesReturned && !lpOverlapped)
2285 {
2286 if(lpErrno)
2287 *lpErrno = WSAEFAULT;
2288 return SOCKET_ERROR;
2289 }
2290
2291 switch( dwIoControlCode )
2292 {
2293 case FIONBIO:
2294 if( cbInBuffer < sizeof(INT) || IS_INTRESOURCE(lpvInBuffer) )
2295 {
2296 Errno = WSAEFAULT;
2297 break;
2298 }
2299 NonBlocking = *((PULONG)lpvInBuffer) ? TRUE : FALSE;
2300 /* Don't allow to go in blocking mode if WSPAsyncSelect or WSPEventSelect is pending */
2301 if (!NonBlocking)
2302 {
2303 /* If there is an WSPAsyncSelect pending, fail with WSAEINVAL */
2304 if (Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents))
2305 {
2306 Errno = WSAEINVAL;
2307 break;
2308 }
2309 /* If there is an WSPEventSelect pending, fail with WSAEINVAL */
2310 if (Socket->NetworkEvents)
2311 {
2312 Errno = WSAEINVAL;
2313 break;
2314 }
2315 }
2316 Socket->SharedData->NonBlocking = NonBlocking ? 1 : 0;
2317 NeedsCompletion = FALSE;
2318 Errno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &NonBlocking, NULL, NULL, lpOverlapped, lpCompletionRoutine);
2319 if (Errno == NO_ERROR)
2320 Ret = NO_ERROR;
2321 break;
2322 case FIONREAD:
2323 if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0)
2324 {
2325 cbRet = sizeof(ULONG);
2326 Errno = WSAEFAULT;
2327 break;
2328 }
2329 if (cbOutBuffer < sizeof(ULONG))
2330 {
2331 Errno = WSAEINVAL;
2332 break;
2333 }
2334 NeedsCompletion = FALSE;
2335 Errno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, NULL, (PULONG)lpvOutBuffer, NULL, lpOverlapped, lpCompletionRoutine);
2336 if (Errno == NO_ERROR)
2337 {
2338 cbRet = sizeof(ULONG);
2339 Ret = NO_ERROR;
2340 }
2341 break;
2342 case SIOCATMARK:
2343 if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0)
2344 {
2345 cbRet = sizeof(BOOL);
2346 Errno = WSAEFAULT;
2347 break;
2348 }
2349 if (cbOutBuffer < sizeof(BOOL))
2350 {
2351 Errno = WSAEINVAL;
2352 break;
2353 }
2354 if (Socket->SharedData->SocketType != SOCK_STREAM)
2355 {
2356 Errno = WSAEINVAL;
2357 break;
2358 }
2359
2360 /* FIXME: Return false if OOBINLINE is true for now
2361 We should MSG_PEEK|MSG_OOB check with driver
2362 */
2363 *(BOOL*)lpvOutBuffer = !Socket->SharedData->OobInline;
2364
2365 cbRet = sizeof(BOOL);
2366 Errno = NO_ERROR;
2367 Ret = NO_ERROR;
2368 break;
2369 case SIO_GET_EXTENSION_FUNCTION_POINTER:
2370 Errno = WSAEINVAL;
2371 break;
2372 case SIO_ADDRESS_LIST_QUERY:
2373 if (IS_INTRESOURCE(lpvOutBuffer) || cbOutBuffer == 0)
2374 {
2375 cbRet = sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress);
2376 Errno = WSAEFAULT;
2377 break;
2378 }
2379 if (cbOutBuffer < sizeof(INT))
2380 {
2381 Errno = WSAEINVAL;
2382 break;
2383 }
2384
2385 cbRet = sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress);
2386
2387 ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->iAddressCount = 1;
2388
2389 if (cbOutBuffer < (sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress)))
2390 {
2391 Errno = WSAEFAULT;
2392 break;
2393 }
2394
2395 ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].iSockaddrLength = sizeof(Socket->SharedData->WSLocalAddress);
2396 ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].lpSockaddr = &Socket->SharedData->WSLocalAddress;
2397
2398 Errno = NO_ERROR;
2399 Ret = NO_ERROR;
2400 break;
2401 default:
2402 Errno = Socket->HelperData->WSHIoctl(Socket->HelperContext,
2403 Handle,
2404 Socket->TdiAddressHandle,
2405 Socket->TdiConnectionHandle,
2406 dwIoControlCode,
2407 lpvInBuffer,
2408 cbInBuffer,
2409 lpvOutBuffer,
2410 cbOutBuffer,
2411 &cbRet,
2412 lpOverlapped,
2413 lpCompletionRoutine,
2414 &NeedsCompletion);
2415
2416 if (Errno == NO_ERROR)
2417 Ret = NO_ERROR;
2418 break;
2419 }
2420 if (lpOverlapped && NeedsCompletion)
2421 {
2422 lpOverlapped->Internal = Errno;
2423 lpOverlapped->InternalHigh = cbRet;
2424 if (lpCompletionRoutine != NULL)
2425 {
2426 lpCompletionRoutine(Errno, cbRet, lpOverlapped, 0);
2427 }
2428 if (lpOverlapped->hEvent)
2429 SetEvent(lpOverlapped->hEvent);
2430 if (!PostQueuedCompletionStatus((HANDLE)Handle, cbRet, 0, lpOverlapped))
2431 {
2432 ERR("PostQueuedCompletionStatus failed %d\n", GetLastError());
2433 }
2434 return NO_ERROR;
2435 }
2436 if (lpErrno)
2437 *lpErrno = Errno;
2438 if (lpcbBytesReturned)
2439 *lpcbBytesReturned = cbRet;
2440 return Ret;
2441 }
2442
2443
2444 INT
2445 WSPAPI
2446 WSPGetSockOpt(IN SOCKET Handle,
2447 IN INT Level,
2448 IN INT OptionName,
2449 OUT CHAR FAR* OptionValue,
2450 IN OUT LPINT OptionLength,
2451 OUT LPINT lpErrno)
2452 {
2453 PSOCKET_INFORMATION Socket = NULL;
2454 PVOID Buffer;
2455 INT BufferSize;
2456 BOOL BoolBuffer;
2457 DWORD DwordBuffer;
2458 INT Errno;
2459
2460 TRACE("Called\n");
2461
2462 /* Get the Socket Structure associate to this Socket*/
2463 Socket = GetSocketStructure(Handle);
2464 if (Socket == NULL)
2465 {
2466 if (lpErrno) *lpErrno = WSAENOTSOCK;
2467 return SOCKET_ERROR;
2468 }
2469 if (!OptionLength || !OptionValue)
2470 {
2471 if (lpErrno) *lpErrno = WSAEFAULT;
2472 return SOCKET_ERROR;
2473 }
2474
2475 switch (Level)
2476 {
2477 case SOL_SOCKET:
2478 switch (OptionName)
2479 {
2480 case SO_TYPE:
2481 Buffer = &Socket->SharedData->SocketType;
2482 BufferSize = sizeof(INT);
2483 break;
2484
2485 case SO_RCVBUF:
2486 Buffer = &Socket->SharedData->SizeOfRecvBuffer;
2487 BufferSize = sizeof(INT);
2488 break;
2489
2490 case SO_SNDBUF:
2491 Buffer = &Socket->SharedData->SizeOfSendBuffer;
2492 BufferSize = sizeof(INT);
2493 break;
2494
2495 case SO_ACCEPTCONN:
2496 BoolBuffer = Socket->SharedData->Listening;
2497 Buffer = &BoolBuffer;
2498 BufferSize = sizeof(BOOL);
2499 break;
2500
2501 case SO_BROADCAST:
2502 BoolBuffer = Socket->SharedData->Broadcast;
2503 Buffer = &BoolBuffer;
2504 BufferSize = sizeof(BOOL);
2505 break;
2506
2507 case SO_DEBUG:
2508 BoolBuffer = Socket->SharedData->Debug;
2509 Buffer = &BoolBuffer;
2510 BufferSize = sizeof(BOOL);
2511 break;
2512
2513 case SO_DONTLINGER:
2514 BoolBuffer = (Socket->SharedData->LingerData.l_onoff == 0);
2515 Buffer = &BoolBuffer;
2516 BufferSize = sizeof(BOOL);
2517 break;
2518
2519 case SO_LINGER:
2520 if (Socket->SharedData->SocketType == SOCK_DGRAM)
2521 {
2522 if (lpErrno) *lpErrno = WSAENOPROTOOPT;
2523 return SOCKET_ERROR;
2524 }
2525 Buffer = &Socket->SharedData->LingerData;
2526 BufferSize = sizeof(struct linger);
2527 break;
2528
2529 case SO_OOBINLINE:
2530 BoolBuffer = (Socket->SharedData->OobInline != 0);
2531 Buffer = &BoolBuffer;
2532 BufferSize = sizeof(BOOL);
2533 break;
2534
2535 case SO_KEEPALIVE:
2536 case SO_DONTROUTE:
2537 /* These guys go directly to the helper */
2538 goto SendToHelper;
2539
2540 case SO_CONDITIONAL_ACCEPT:
2541 BoolBuffer = (Socket->SharedData->UseDelayedAcceptance != 0);
2542 Buffer = &BoolBuffer;
2543 BufferSize = sizeof(BOOL);
2544 break;
2545
2546 case SO_REUSEADDR:
2547 BoolBuffer = (Socket->SharedData->ReuseAddresses != 0);
2548 Buffer = &BoolBuffer;
2549 BufferSize = sizeof(BOOL);
2550 break;
2551
2552 case SO_EXCLUSIVEADDRUSE:
2553 BoolBuffer = (Socket->SharedData->ExclusiveAddressUse != 0);
2554 Buffer = &BoolBuffer;
2555 BufferSize = sizeof(BOOL);
2556 break;
2557
2558 case SO_ERROR:
2559 Buffer = &Socket->SharedData->SocketLastError;
2560 BufferSize = sizeof(INT);
2561 break;
2562
2563 case SO_CONNECT_TIME:
2564 DwordBuffer = GetCurrentTimeInSeconds() - Socket->SharedData->ConnectTime;
2565 Buffer = &DwordBuffer;
2566 BufferSize = sizeof(DWORD);
2567 break;
2568
2569 case SO_SNDTIMEO:
2570 Buffer = &Socket->SharedData->SendTimeout;
2571 BufferSize = sizeof(DWORD);
2572 break;
2573 case SO_RCVTIMEO:
2574 Buffer = &Socket->SharedData->RecvTimeout;
2575 BufferSize = sizeof(DWORD);
2576 break;
2577 case SO_PROTOCOL_INFOW:
2578 Buffer = &Socket->ProtocolInfo;
2579 BufferSize = sizeof(Socket->ProtocolInfo);
2580 break;
2581
2582 case SO_GROUP_ID:
2583 case SO_GROUP_PRIORITY:
2584 case SO_MAX_MSG_SIZE:
2585
2586 default:
2587 DbgPrint("MSAFD: Get unknown optname %x\n", OptionName);
2588 if (lpErrno) *lpErrno = WSAENOPROTOOPT;
2589 return SOCKET_ERROR;
2590 }
2591
2592 if (*OptionLength < BufferSize)
2593 {
2594 if (lpErrno) *lpErrno = WSAEFAULT;
2595 *OptionLength = BufferSize;
2596 return SOCKET_ERROR;
2597 }
2598 RtlCopyMemory(OptionValue, Buffer, BufferSize);
2599
2600 return 0;
2601
2602 default:
2603 if (lpErrno) *lpErrno = WSAEINVAL;
2604 return SOCKET_ERROR;
2605 }
2606
2607 SendToHelper:
2608 Errno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
2609 Handle,
2610 Socket->TdiAddressHandle,
2611 Socket->TdiConnectionHandle,
2612 Level,
2613 OptionName,
2614 OptionValue,
2615 (LPINT)OptionLength);
2616 if (lpErrno) *lpErrno = Errno;
2617 return (Errno == NO_ERROR) ? NO_ERROR : SOCKET_ERROR;
2618 }
2619
2620 INT
2621 WSPAPI
2622 WSPSetSockOpt(
2623 IN SOCKET s,
2624 IN INT level,
2625 IN INT optname,
2626 IN CONST CHAR FAR* optval,
2627 IN INT optlen,
2628 OUT LPINT lpErrno)
2629 {
2630 PSOCKET_INFORMATION Socket;
2631 INT Errno;
2632
2633 /* Get the Socket Structure associate to this Socket*/
2634 Socket = GetSocketStructure(s);
2635 if (Socket == NULL)
2636 {
2637 if (lpErrno) *lpErrno = WSAENOTSOCK;
2638 return SOCKET_ERROR;
2639 }
2640 if (!optval)
2641 {
2642 if (lpErrno) *lpErrno = WSAEFAULT;
2643 return SOCKET_ERROR;
2644 }
2645
2646
2647 /* FIXME: We should handle some more cases here */
2648 if (level == SOL_SOCKET)
2649 {
2650 switch (optname)
2651 {
2652 case SO_BROADCAST:
2653 if (optlen < sizeof(BOOL))
2654 {
2655 if (lpErrno) *lpErrno = WSAEFAULT;
2656 return SOCKET_ERROR;
2657 }
2658 Socket->SharedData->Broadcast = (*optval != 0) ? 1 : 0;
2659 return NO_ERROR;
2660
2661 case SO_OOBINLINE:
2662 if (optlen < sizeof(BOOL))
2663 {
2664 if (lpErrno) *lpErrno = WSAEFAULT;
2665 return SOCKET_ERROR;
2666 }
2667 Socket->SharedData->OobInline = (*optval != 0) ? 1 : 0;
2668 return NO_ERROR;
2669
2670 case SO_DONTLINGER:
2671 if (optlen < sizeof(BOOL))
2672 {
2673 if (lpErrno) *lpErrno = WSAEFAULT;
2674 return SOCKET_ERROR;
2675 }
2676 Socket->SharedData->LingerData.l_onoff = (*optval != 0) ? 0 : 1;
2677 return NO_ERROR;
2678
2679 case SO_REUSEADDR:
2680 if (optlen < sizeof(BOOL))
2681 {
2682 if (lpErrno) *lpErrno = WSAEFAULT;
2683 return SOCKET_ERROR;
2684 }
2685 Socket->SharedData->ReuseAddresses = (*optval != 0) ? 1 : 0;
2686 return NO_ERROR;
2687
2688 case SO_EXCLUSIVEADDRUSE:
2689 if (optlen < sizeof(BOOL))
2690 {
2691 if (lpErrno) *lpErrno = WSAEFAULT;
2692 return SOCKET_ERROR;
2693 }
2694 Socket->SharedData->ExclusiveAddressUse = (*optval != 0) ? 1 : 0;
2695 return NO_ERROR;
2696
2697 case SO_LINGER:
2698 if (optlen < sizeof(struct linger))
2699 {
2700 if (lpErrno) *lpErrno = WSAEFAULT;
2701 return SOCKET_ERROR;
2702 }
2703 RtlCopyMemory(&Socket->SharedData->LingerData,
2704 optval,
2705 sizeof(struct linger));
2706 return NO_ERROR;
2707
2708 case SO_SNDBUF:
2709 if (optlen < sizeof(DWORD))
2710 {
2711 if (lpErrno) *lpErrno = WSAEFAULT;
2712 return SOCKET_ERROR;
2713 }
2714
2715 /* TODO: The total per-socket buffer space reserved for sends */
2716 ERR("Setting send buf to %x is not implemented yet\n", optval);
2717 return NO_ERROR;
2718
2719 case SO_ERROR:
2720 if (optlen < sizeof(INT))
2721 {
2722 if (lpErrno) *lpErrno = WSAEFAULT;
2723 return SOCKET_ERROR;
2724 }
2725
2726 RtlCopyMemory(&Socket->SharedData->SocketLastError,
2727 optval,
2728 sizeof(INT));
2729 return NO_ERROR;
2730
2731 case SO_SNDTIMEO:
2732 if (optlen < sizeof(DWORD))
2733 {
2734 if (lpErrno) *lpErrno = WSAEFAULT;
2735 return SOCKET_ERROR;
2736 }
2737
2738 RtlCopyMemory(&Socket->SharedData->SendTimeout,
2739 optval,
2740 sizeof(DWORD));
2741 return NO_ERROR;
2742
2743 case SO_RCVTIMEO:
2744 if (optlen < sizeof(DWORD))
2745 {
2746 if (lpErrno) *lpErrno = WSAEFAULT;
2747 return SOCKET_ERROR;
2748 }
2749
2750 RtlCopyMemory(&Socket->SharedData->RecvTimeout,
2751 optval,
2752 sizeof(DWORD));
2753 return NO_ERROR;
2754
2755 case SO_KEEPALIVE:
2756 case SO_DONTROUTE:
2757 /* These go directly to the helper dll */
2758 goto SendToHelper;
2759
2760 default:
2761 /* Obviously this is a hack */
2762 ERR("MSAFD: Set unknown optname %x\n", optname);
2763 return NO_ERROR;
2764 }
2765 }
2766
2767 SendToHelper:
2768 Errno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext,
2769 s,
2770 Socket->TdiAddressHandle,
2771 Socket->TdiConnectionHandle,
2772 level,
2773 optname,
2774 (PCHAR)optval,
2775 optlen);
2776 if (lpErrno) *lpErrno = Errno;
2777 return (Errno == NO_ERROR) ? NO_ERROR : SOCKET_ERROR;
2778 }
2779
2780 /*
2781 * FUNCTION: Initialize service provider for a client
2782 * ARGUMENTS:
2783 * wVersionRequested = Highest WinSock SPI version that the caller can use
2784 * lpWSPData = Address of WSPDATA structure to initialize
2785 * lpProtocolInfo = Pointer to structure that defines the desired protocol
2786 * UpcallTable = Pointer to upcall table of the WinSock DLL
2787 * lpProcTable = Address of procedure table to initialize
2788 * RETURNS:
2789 * Status of operation
2790 */
2791 INT
2792 WSPAPI
2793 WSPStartup(IN WORD wVersionRequested,
2794 OUT LPWSPDATA lpWSPData,
2795 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
2796 IN WSPUPCALLTABLE UpcallTable,
2797 OUT LPWSPPROC_TABLE lpProcTable)
2798
2799 {
2800 NTSTATUS Status;
2801
2802 if (((LOBYTE(wVersionRequested) == 2) && (HIBYTE(wVersionRequested) < 2)) ||
2803 (LOBYTE(wVersionRequested) < 2))
2804 {
2805 ERR("WSPStartup NOT SUPPORTED for version 0x%X\n", wVersionRequested);
2806 return WSAVERNOTSUPPORTED;
2807 }
2808 else
2809 Status = NO_ERROR;
2810 /* FIXME: Enable all cases of WSPStartup status */
2811 Upcalls = UpcallTable;
2812
2813 if (Status == NO_ERROR)
2814 {
2815 lpProcTable->lpWSPAccept = WSPAccept;
2816 lpProcTable->lpWSPAddressToString = WSPAddressToString;
2817 lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
2818 lpProcTable->lpWSPBind = WSPBind;
2819 lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
2820 lpProcTable->lpWSPCleanup = WSPCleanup;
2821 lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
2822 lpProcTable->lpWSPConnect = WSPConnect;
2823 lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
2824 lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
2825 lpProcTable->lpWSPEventSelect = WSPEventSelect;
2826 lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
2827 lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
2828 lpProcTable->lpWSPGetSockName = WSPGetSockName;
2829 lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
2830 lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
2831 lpProcTable->lpWSPIoctl = WSPIoctl;
2832 lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
2833 lpProcTable->lpWSPListen = WSPListen;
2834 lpProcTable->lpWSPRecv = WSPRecv;
2835 lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
2836 lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
2837 lpProcTable->lpWSPSelect = WSPSelect;
2838 lpProcTable->lpWSPSend = WSPSend;
2839 lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
2840 lpProcTable->lpWSPSendTo = WSPSendTo;
2841 lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
2842 lpProcTable->lpWSPShutdown = WSPShutdown;
2843 lpProcTable->lpWSPSocket = WSPSocket;
2844 lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
2845 lpWSPData->wVersion = MAKEWORD(2, 2);
2846 lpWSPData->wHighVersion = MAKEWORD(2, 2);
2847 /* Save CatalogEntryId for all upcalls */
2848 CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
2849 }
2850
2851 TRACE("Status (%d).\n", Status);
2852 return Status;
2853 }
2854
2855
2856 INT
2857 WSPAPI
2858 WSPAddressToString(IN LPSOCKADDR lpsaAddress,
2859 IN DWORD dwAddressLength,
2860 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
2861 OUT LPWSTR lpszAddressString,
2862 IN OUT LPDWORD lpdwAddressStringLength,
2863 OUT LPINT lpErrno)
2864 {
2865 DWORD size;
2866 WCHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
2867 WCHAR *p;
2868
2869 if (!lpsaAddress || !lpszAddressString || !lpdwAddressStringLength)
2870 {
2871 if (lpErrno) *lpErrno = WSAEFAULT;
2872 return SOCKET_ERROR;
2873 }
2874
2875 switch (lpsaAddress->sa_family)
2876 {
2877 case AF_INET:
2878 if (dwAddressLength < sizeof(SOCKADDR_IN))
2879 {
2880 if (lpErrno) *lpErrno = WSAEINVAL;
2881 return SOCKET_ERROR;
2882 }
2883 swprintf(buffer,
2884 L"%u.%u.%u.%u:%u",
2885 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 24 & 0xff),
2886 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 16 & 0xff),
2887 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 8 & 0xff),
2888 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) & 0xff),
2889 ntohs(((SOCKADDR_IN *)lpsaAddress)->sin_port));
2890
2891 p = wcschr(buffer, L':');
2892 if (!((SOCKADDR_IN *)lpsaAddress)->sin_port)
2893 {
2894 *p = 0;
2895 }
2896 break;
2897 default:
2898 if (lpErrno) *lpErrno = WSAEINVAL;
2899 return SOCKET_ERROR;
2900 }
2901
2902 size = wcslen(buffer) + 1;
2903
2904 if (*lpdwAddressStringLength < size)
2905 {
2906 *lpdwAddressStringLength = size;
2907 if (lpErrno) *lpErrno = WSAEFAULT;
2908 return SOCKET_ERROR;
2909 }
2910
2911 *lpdwAddressStringLength = size;
2912 wcscpy(lpszAddressString, buffer);
2913 return 0;
2914 }
2915
2916 INT
2917 WSPAPI
2918 WSPStringToAddress(IN LPWSTR AddressString,
2919 IN INT AddressFamily,
2920 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
2921 OUT LPSOCKADDR lpAddress,
2922 IN OUT LPINT lpAddressLength,
2923 OUT LPINT lpErrno)
2924 {
2925 int numdots = 0;
2926 USHORT port;
2927 LONG inetaddr = 0, ip_part;
2928 LPWSTR *bp = NULL;
2929 SOCKADDR_IN *sockaddr;
2930
2931 if (!lpAddressLength || !lpAddress || !AddressString)
2932 {
2933 if (lpErrno) *lpErrno = WSAEINVAL;
2934 return SOCKET_ERROR;
2935 }
2936
2937 sockaddr = (SOCKADDR_IN *)lpAddress;
2938
2939 /* Set right address family */
2940 if (lpProtocolInfo != NULL)
2941 {
2942 sockaddr->sin_family = lpProtocolInfo->iAddressFamily;
2943 }
2944 else
2945 {
2946 sockaddr->sin_family = AddressFamily;
2947 }
2948
2949 /* Report size */
2950 if (AddressFamily == AF_INET)
2951 {
2952 if (*lpAddressLength < (INT)sizeof(SOCKADDR_IN))
2953 {
2954 if (lpErrno) *lpErrno = WSAEFAULT;
2955 }
2956 else
2957 {
2958 // translate ip string to ip
2959
2960 /* Get ip number */
2961 bp = &AddressString;
2962 inetaddr = 0;
2963
2964 while (*bp < &AddressString[wcslen(AddressString)])
2965 {
2966 ip_part = wcstol(*bp, bp, 10);
2967 /* ip part number should be in range 0-255 */
2968 if (ip_part < 0 || ip_part > 255)
2969 {
2970 if (lpErrno) *lpErrno = WSAEINVAL;
2971 return SOCKET_ERROR;
2972 }
2973 inetaddr = (inetaddr << 8) + ip_part;
2974 /* we end on string end or port separator */
2975 if ((*bp)[0] == 0 || (*bp)[0] == L':')
2976 break;
2977 /* ip parts are dot separated. verify it */
2978 if ((*bp)[0] != L'.')
2979 {
2980 if (lpErrno) *lpErrno = WSAEINVAL;
2981 return SOCKET_ERROR;
2982 }
2983 /* count the dots */
2984 numdots++;
2985 /* move over the dot to next ip part */
2986 (*bp)++;
2987 }
2988
2989 /* check dots count */
2990 if (numdots != 3)
2991 {
2992 if (lpErrno) *lpErrno = WSAEINVAL;
2993 return SOCKET_ERROR;
2994 }
2995
2996 /* Get port number */
2997 if ((*bp)[0] == L':')
2998 {
2999 /* move over the column to port part */
3000 (*bp)++;
3001 /* next char should be numeric */
3002 if ((*bp)[0] < L'0' || (*bp)[0] > L'9')
3003 {
3004 if (lpErrno) *lpErrno = WSAEINVAL;
3005 return SOCKET_ERROR;
3006 }
3007 port = wcstol(*bp, bp, 10);
3008 }
3009 else
3010 {
3011 port = 0;
3012 }
3013
3014 if (lpErrno) *lpErrno = NO_ERROR;
3015 /* rest sockaddr.sin_addr.s_addr
3016 for we need to be sure it is zero when we come to while */
3017 *lpAddressLength = sizeof(*sockaddr);
3018 memset(lpAddress, 0, sizeof(*sockaddr));
3019 sockaddr->sin_family = AF_INET;
3020 sockaddr->sin_addr.s_addr = inetaddr;
3021 sockaddr->sin_port = port;
3022 }
3023 }
3024
3025 if (lpErrno && !*lpErrno)
3026 {
3027 return 0;
3028 }
3029
3030 return SOCKET_ERROR;
3031 }
3032
3033 /*
3034 * FUNCTION: Cleans up service provider for a client
3035 * ARGUMENTS:
3036 * lpErrno = Address of buffer for error information
3037 * RETURNS:
3038 * 0 if successful, or SOCKET_ERROR if not
3039 */
3040 INT
3041 WSPAPI
3042 WSPCleanup(OUT LPINT lpErrno)
3043
3044 {
3045 TRACE("Leaving.\n");
3046
3047 if (lpErrno) *lpErrno = NO_ERROR;
3048
3049 return 0;
3050 }
3051
3052 VOID
3053 NTAPI
3054 AfdInfoAPC(PVOID ApcContext,
3055 PIO_STATUS_BLOCK IoStatusBlock,
3056 ULONG Reserved)
3057 {
3058 PAFDAPCCONTEXT Context = ApcContext;
3059
3060 Context->lpCompletionRoutine(IoStatusBlock->Status, IoStatusBlock->Information, Context->lpOverlapped, 0);
3061 HeapFree(GlobalHeap, 0, ApcContext);
3062 }
3063
3064 int
3065 GetSocketInformation(PSOCKET_INFORMATION Socket,
3066 ULONG AfdInformationClass,
3067 PBOOLEAN Boolean OPTIONAL,
3068 PULONG Ulong OPTIONAL,
3069 PLARGE_INTEGER LargeInteger OPTIONAL,
3070 LPWSAOVERLAPPED Overlapped OPTIONAL,
3071 LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine OPTIONAL)
3072 {
3073 PIO_STATUS_BLOCK IOSB;
3074 IO_STATUS_BLOCK DummyIOSB;
3075 AFD_INFO InfoData;
3076 NTSTATUS Status;
3077 PAFDAPCCONTEXT APCContext;
3078 PIO_APC_ROUTINE APCFunction;
3079 HANDLE Event = NULL;
3080 HANDLE SockEvent;
3081
3082 Status = NtCreateEvent(&SockEvent,
3083 EVENT_ALL_ACCESS,
3084 NULL,
3085 1,
3086 FALSE);
3087
3088 if( !NT_SUCCESS(Status) )
3089 return SOCKET_ERROR;
3090
3091 /* Set Info Class */
3092 InfoData.InformationClass = AfdInformationClass;
3093
3094 /* Verify if we should use APC */
3095 if (Overlapped == NULL)
3096 {
3097 /* Not using Overlapped structure, so use normal blocking on event */
3098 APCContext = NULL;
3099 APCFunction = NULL;
3100 Event = SockEvent;
3101 IOSB = &DummyIOSB;
3102 }
3103 else
3104 {
3105 /* Overlapped request for non overlapped opened socket */
3106 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
3107 {
3108 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
3109 return 0;
3110 }
3111 if (CompletionRoutine == NULL)
3112 {
3113 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
3114 APCContext = (PAFDAPCCONTEXT)Overlapped;
3115 APCFunction = NULL;
3116 Event = Overlapped->hEvent;
3117 }
3118 else
3119 {
3120 /* Using Overlapped Structure and a Completition Routine, so use an APC */
3121 APCFunction = &AfdInfoAPC; // should be a private io completition function inside us
3122 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
3123 if (!APCContext)
3124 {
3125 ERR("Not enough memory for APC Context\n");
3126 return WSAEFAULT;
3127 }
3128 APCContext->lpCompletionRoutine = CompletionRoutine;
3129 APCContext->lpOverlapped = Overlapped;
3130 APCContext->lpSocket = Socket;
3131 }
3132
3133 IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal;
3134 }
3135
3136 IOSB->Status = STATUS_PENDING;
3137
3138 /* Send IOCTL */
3139 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
3140 Event,
3141 APCFunction,
3142 APCContext,
3143 IOSB,
3144 IOCTL_AFD_GET_INFO,
3145 &InfoData,
3146 sizeof(InfoData),
3147 &InfoData,
3148 sizeof(InfoData));
3149
3150 /* Wait for return */
3151 if (Status == STATUS_PENDING && Overlapped == NULL)
3152 {
3153 WaitForSingleObject(SockEvent, INFINITE);
3154 Status = IOSB->Status;
3155 }
3156
3157 TRACE("Status %x Information %d\n", Status, IOSB->Information);
3158
3159 if (Status == STATUS_PENDING)
3160 {
3161 TRACE("Leaving (Pending)\n");
3162 return WSA_IO_PENDING;
3163 }
3164
3165 if (Status != STATUS_SUCCESS)
3166 return SOCKET_ERROR;
3167
3168 /* Return Information */
3169 if (Ulong != NULL)
3170 {
3171 *Ulong = InfoData.Information.Ulong;
3172 }
3173 if (LargeInteger != NULL)
3174 {
3175 *LargeInteger = InfoData.Information.LargeInteger;
3176 }
3177 if (Boolean != NULL)
3178 {
3179 *Boolean = InfoData.Information.Boolean;
3180 }
3181
3182 NtClose( SockEvent );
3183
3184 return NO_ERROR;
3185
3186 }
3187
3188
3189 int
3190 SetSocketInformation(PSOCKET_INFORMATION Socket,
3191 ULONG AfdInformationClass,
3192 PBOOLEAN Boolean OPTIONAL,
3193 PULONG Ulong OPTIONAL,
3194 PLARGE_INTEGER LargeInteger OPTIONAL,
3195 LPWSAOVERLAPPED Overlapped OPTIONAL,
3196 LPWSAOVERLAPPED_COMPLETION_ROUTINE CompletionRoutine OPTIONAL)
3197 {
3198 PIO_STATUS_BLOCK IOSB;
3199 IO_STATUS_BLOCK DummyIOSB;
3200 AFD_INFO InfoData;
3201 NTSTATUS Status;
3202 PAFDAPCCONTEXT APCContext;
3203 PIO_APC_ROUTINE APCFunction;
3204 HANDLE Event = NULL;
3205 HANDLE SockEvent;
3206
3207 Status = NtCreateEvent(&SockEvent,
3208 EVENT_ALL_ACCESS,
3209 NULL,
3210 1,
3211 FALSE);
3212
3213 if( !NT_SUCCESS(Status) )
3214 return SOCKET_ERROR;
3215
3216 /* Set Info Class */
3217 InfoData.InformationClass = AfdInformationClass;
3218
3219 /* Set Information */
3220 if (Ulong != NULL)
3221 {
3222 InfoData.Information.Ulong = *Ulong;
3223 }
3224 if (LargeInteger != NULL)
3225 {
3226 InfoData.Information.LargeInteger = *LargeInteger;
3227 }
3228 if (Boolean != NULL)
3229 {
3230 InfoData.Information.Boolean = *Boolean;
3231 }
3232
3233 /* Verify if we should use APC */
3234 if (Overlapped == NULL)
3235 {
3236 /* Not using Overlapped structure, so use normal blocking on event */
3237 APCContext = NULL;
3238 APCFunction = NULL;
3239 Event = SockEvent;
3240 IOSB = &DummyIOSB;
3241 }
3242 else
3243 {
3244 /* Overlapped request for non overlapped opened socket */
3245 if ((Socket->SharedData->CreateFlags & SO_SYNCHRONOUS_NONALERT) != 0)
3246 {
3247 TRACE("Opened without flag WSA_FLAG_OVERLAPPED. Do nothing.\n");
3248 return 0;
3249 }
3250 if (CompletionRoutine == NULL)
3251 {
3252 /* Using Overlapped Structure, but no Completition Routine, so no need for APC */
3253 APCContext = (PAFDAPCCONTEXT)Overlapped;
3254 APCFunction = NULL;
3255 Event = Overlapped->hEvent;
3256 }
3257 else
3258 {
3259 /* Using Overlapped Structure and a Completition Routine, so use an APC */
3260 APCFunction = &AfdInfoAPC; // should be a private io completition function inside us
3261 APCContext = HeapAlloc(GlobalHeap, 0, sizeof(AFDAPCCONTEXT));
3262 if (!APCContext)
3263 {
3264 ERR("Not enough memory for APC Context\n");
3265 return WSAEFAULT;
3266 }
3267 APCContext->lpCompletionRoutine = CompletionRoutine;
3268 APCContext->lpOverlapped = Overlapped;
3269 APCContext->lpSocket = Socket;
3270 }
3271
3272 IOSB = (PIO_STATUS_BLOCK)&Overlapped->Internal;
3273 }
3274
3275 IOSB->Status = STATUS_PENDING;
3276
3277 /* Send IOCTL */
3278 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
3279 Event,
3280 APCFunction,
3281 APCContext,
3282 IOSB,
3283 IOCTL_AFD_SET_INFO,
3284 &InfoData,
3285 sizeof(InfoData),
3286 NULL,
3287 0);
3288
3289 /* Wait for return */
3290 if (Status == STATUS_PENDING && Overlapped == NULL)
3291 {
3292 WaitForSingleObject(SockEvent, INFINITE);
3293 Status = IOSB->Status;
3294 }
3295
3296 NtClose( SockEvent );
3297
3298 TRACE("Status %x Information %d\n", Status, IOSB->Information);
3299
3300 if (Status == STATUS_PENDING)
3301 {
3302 TRACE("Leaving (Pending)\n");
3303 return WSA_IO_PENDING;
3304 }
3305
3306 return Status == STATUS_SUCCESS ? NO_ERROR : SOCKET_ERROR;
3307
3308 }
3309
3310 PSOCKET_INFORMATION
3311 GetSocketStructure(SOCKET Handle)
3312 {
3313 PSOCKET_INFORMATION CurrentSocket;
3314
3315 EnterCriticalSection(&SocketListLock);
3316
3317 CurrentSocket = SocketListHead;
3318 while (CurrentSocket)
3319 {
3320 if (CurrentSocket->Handle == Handle)
3321 {
3322 LeaveCriticalSection(&SocketListLock);
3323 return CurrentSocket;
3324 }
3325
3326 CurrentSocket = CurrentSocket->NextSocket;
3327 }
3328
3329 LeaveCriticalSection(&SocketListLock);
3330
3331 return NULL;
3332 }
3333
3334 int CreateContext(PSOCKET_INFORMATION Socket)
3335 {
3336 IO_STATUS_BLOCK IOSB;
3337 SOCKET_CONTEXT ContextData;
3338 NTSTATUS Status;
3339 HANDLE SockEvent;
3340
3341 Status = NtCreateEvent(&SockEvent,
3342 EVENT_ALL_ACCESS,
3343 NULL,
3344 1,
3345 FALSE);
3346
3347 if( !NT_SUCCESS(Status) )
3348 return SOCKET_ERROR;
3349
3350 /* Create Context */
3351 ContextData.SharedData = *Socket->SharedData;
3352 ContextData.SizeOfHelperData = 0;
3353 RtlCopyMemory (&ContextData.LocalAddress,
3354 Socket->LocalAddress,
3355 Socket->SharedData->SizeOfLocalAddress);
3356 RtlCopyMemory (&ContextData.RemoteAddress,
3357 Socket->RemoteAddress,
3358 Socket->SharedData->SizeOfRemoteAddress);
3359
3360 /* Send IOCTL */
3361 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
3362 SockEvent,
3363 NULL,
3364 NULL,
3365 &IOSB,
3366 IOCTL_AFD_SET_CONTEXT,
3367 &ContextData,
3368 sizeof(ContextData),
3369 NULL,
3370 0);
3371
3372 /* Wait for Completition */
3373 if (Status == STATUS_PENDING)
3374 {
3375 WaitForSingleObject(SockEvent, INFINITE);
3376 Status = IOSB.Status;
3377 }
3378
3379 NtClose( SockEvent );
3380
3381 return Status == STATUS_SUCCESS ? NO_ERROR : SOCKET_ERROR;
3382 }
3383
3384 BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
3385 {
3386 HANDLE hAsyncThread;
3387 DWORD AsyncThreadId;
3388 HANDLE AsyncEvent;
3389 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
3390 NTSTATUS Status;
3391
3392 /* Check if the Thread Already Exists */
3393 if (SockAsyncThreadRefCount)
3394 {
3395 ASSERT(SockAsyncCompletionPort);
3396 return TRUE;
3397 }
3398
3399 /* Create the Completion Port */
3400 if (!SockAsyncCompletionPort)
3401 {
3402 Status = NtCreateIoCompletion(&SockAsyncCompletionPort,
3403 IO_COMPLETION_ALL_ACCESS,
3404 NULL,
3405 2); // Allow 2 threads only
3406 if (!NT_SUCCESS(Status))
3407 {
3408 ERR("Failed to create completion port: 0x%08x\n", Status);
3409 return FALSE;
3410 }
3411 /* Protect Handle */
3412 HandleFlags.ProtectFromClose = TRUE;
3413 HandleFlags.Inherit = FALSE;
3414 Status = NtSetInformationObject(SockAsyncCompletionPort,
3415 ObjectHandleFlagInformation,
3416 &HandleFlags,
3417 sizeof(HandleFlags));
3418 }
3419
3420 /* Create the Async Event */
3421 Status = NtCreateEvent(&AsyncEvent,
3422 EVENT_ALL_ACCESS,
3423 NULL,
3424 NotificationEvent,
3425 FALSE);
3426
3427 /* Create the Async Thread */
3428 hAsyncThread = CreateThread(NULL,
3429 0,
3430 (LPTHREAD_START_ROUTINE)SockAsyncThread,
3431 NULL,
3432 0,
3433 &AsyncThreadId);
3434
3435 /* Close the Handle */
3436 NtClose(hAsyncThread);
3437
3438 /* Increase the Reference Count */
3439 SockAsyncThreadRefCount++;
3440 return TRUE;
3441 }
3442
3443 int SockAsyncThread(PVOID ThreadParam)
3444 {
3445 PVOID AsyncContext;
3446 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
3447 IO_STATUS_BLOCK IOSB;
3448 NTSTATUS Status;
3449
3450 /* Make the Thread Higher Priority */
3451 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
3452
3453 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
3454 do
3455 {
3456 Status = NtRemoveIoCompletion (SockAsyncCompletionPort,
3457 (PVOID*)&AsyncCompletionRoutine,
3458 &AsyncContext,
3459 &IOSB,
3460 NULL);
3461 /* Call the Async Function */
3462 if (NT_SUCCESS(Status))
3463 {
3464 (*AsyncCompletionRoutine)(AsyncContext, &IOSB);
3465 }
3466 else
3467 {
3468 /* It Failed, sleep for a second */
3469 Sleep(1000);
3470 }
3471 } while ((Status != STATUS_TIMEOUT));
3472
3473 /* The Thread has Ended */
3474 return 0;
3475 }
3476
3477 BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
3478 {
3479 UNICODE_STRING AfdHelper;
3480 OBJECT_ATTRIBUTES ObjectAttributes;
3481 IO_STATUS_BLOCK IoSb;
3482 FILE_COMPLETION_INFORMATION CompletionInfo;
3483 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
3484
3485 /* First, make sure we're not already intialized */
3486 if (SockAsyncHelperAfdHandle)
3487 {
3488 return TRUE;
3489 }
3490
3491 /* Set up Handle Name and Object */
3492 RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" );
3493 InitializeObjectAttributes(&ObjectAttributes,
3494 &AfdHelper,
3495 OBJ_INHERIT | OBJ_CASE_INSENSITIVE,
3496 NULL,
3497 NULL);
3498
3499 /* Open the Handle to AFD */
3500 NtCreateFile(&SockAsyncHelperAfdHandle,
3501 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
3502 &ObjectAttributes,
3503 &IoSb,
3504 NULL,
3505 0,
3506 FILE_SHARE_READ | FILE_SHARE_WRITE,
3507 FILE_OPEN_IF,
3508 0,
3509 NULL,
3510 0);
3511
3512 /*
3513 * Now Set up the Completion Port Information
3514 * This means that whenever a Poll is finished, the routine will be executed
3515 */
3516 CompletionInfo.Port = SockAsyncCompletionPort;
3517 CompletionInfo.Key = SockAsyncSelectCompletionRoutine;
3518 NtSetInformationFile(SockAsyncHelperAfdHandle,
3519 &IoSb,
3520 &CompletionInfo,
3521 sizeof(CompletionInfo),
3522 FileCompletionInformation);
3523
3524
3525 /* Protect the Handle */
3526 HandleFlags.ProtectFromClose = TRUE;
3527 HandleFlags.Inherit = FALSE;
3528 NtSetInformationObject(SockAsyncCompletionPort,
3529 ObjectHandleFlagInformation,
3530 &HandleFlags,
3531 sizeof(HandleFlags));
3532
3533
3534 /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
3535 SockAsyncSelectCalled = TRUE;
3536 return TRUE;
3537 }
3538
3539 VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
3540 {
3541
3542 PASYNC_DATA AsyncData = Context;
3543 PSOCKET_INFORMATION Socket;
3544 ULONG x;
3545
3546 /* Get the Socket */
3547 Socket = AsyncData->ParentSocket;
3548
3549 /* Check if the Sequence Number Changed behind our back */
3550 if (AsyncData->SequenceNumber != Socket->SharedData->SequenceNumber )
3551 {
3552 return;
3553 }
3554
3555 /* Check we were manually called b/c of a failure */
3556 if (!NT_SUCCESS(IoStatusBlock->Status))
3557 {
3558 /* FIXME: Perform Upcall */
3559 return;
3560 }
3561
3562 for (x = 1; x; x<<=1)
3563 {
3564 switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x)
3565 {
3566 case AFD_EVENT_RECEIVE:
3567 if (0 != (Socket->SharedData->AsyncEvents & FD_READ) &&
3568 0 == (Socket->SharedData->AsyncDisabledEvents & FD_READ))
3569 {
3570 /* Make the Notifcation */
3571 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3572 Socket->SharedData->wMsg,
3573 Socket->Handle,
3574 WSAMAKESELECTREPLY(FD_READ, 0));
3575 /* Disable this event until the next read(); */
3576 Socket->SharedData->AsyncDisabledEvents |= FD_READ;
3577 }
3578 break;
3579
3580 case AFD_EVENT_OOB_RECEIVE:
3581 if (0 != (Socket->SharedData->AsyncEvents & FD_OOB) &&
3582 0 == (Socket->SharedData->AsyncDisabledEvents & FD_OOB))
3583 {
3584 /* Make the Notifcation */
3585 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3586 Socket->SharedData->wMsg,
3587 Socket->Handle,
3588 WSAMAKESELECTREPLY(FD_OOB, 0));
3589 /* Disable this event until the next read(); */
3590 Socket->SharedData->AsyncDisabledEvents |= FD_OOB;
3591 }
3592 break;
3593
3594 case AFD_EVENT_SEND:
3595 if (0 != (Socket->SharedData->AsyncEvents & FD_WRITE) &&
3596 0 == (Socket->SharedData->AsyncDisabledEvents & FD_WRITE))
3597 {
3598 /* Make the Notifcation */
3599 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3600 Socket->SharedData->wMsg,
3601 Socket->Handle,
3602 WSAMAKESELECTREPLY(FD_WRITE, 0));
3603 /* Disable this event until the next write(); */
3604 Socket->SharedData->AsyncDisabledEvents |= FD_WRITE;
3605 }
3606 break;
3607
3608 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
3609 case AFD_EVENT_CONNECT:
3610 case AFD_EVENT_CONNECT_FAIL:
3611 if (0 != (Socket->SharedData->AsyncEvents & FD_CONNECT) &&
3612 0 == (Socket->SharedData->AsyncDisabledEvents & FD_CONNECT))
3613 {
3614 /* Make the Notifcation */
3615 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3616 Socket->SharedData->wMsg,
3617 Socket->Handle,
3618 WSAMAKESELECTREPLY(FD_CONNECT, 0));
3619 /* Disable this event forever; */
3620 Socket->SharedData->AsyncDisabledEvents |= FD_CONNECT;
3621 }
3622 break;
3623
3624 case AFD_EVENT_ACCEPT:
3625 if (0 != (Socket->SharedData->AsyncEvents & FD_ACCEPT) &&
3626 0 == (Socket->SharedData->AsyncDisabledEvents & FD_ACCEPT))
3627 {
3628 /* Make the Notifcation */
3629 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3630 Socket->SharedData->wMsg,
3631 Socket->Handle,
3632 WSAMAKESELECTREPLY(FD_ACCEPT, 0));
3633 /* Disable this event until the next accept(); */
3634 Socket->SharedData->AsyncDisabledEvents |= FD_ACCEPT;
3635 }
3636 break;
3637
3638 case AFD_EVENT_DISCONNECT:
3639 case AFD_EVENT_ABORT:
3640 case AFD_EVENT_CLOSE:
3641 if (0 != (Socket->SharedData->AsyncEvents & FD_CLOSE) &&
3642 0 == (Socket->SharedData->AsyncDisabledEvents & FD_CLOSE))
3643 {
3644 /* Make the Notifcation */
3645 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3646 Socket->SharedData->wMsg,
3647 Socket->Handle,
3648 WSAMAKESELECTREPLY(FD_CLOSE, 0));
3649 /* Disable this event forever; */
3650 Socket->SharedData->AsyncDisabledEvents |= FD_CLOSE;
3651 }
3652 break;
3653 /* FIXME: Support QOS */
3654 }
3655 }
3656
3657 /* Check if there are any events left for us to check */
3658 if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0 )
3659 {
3660 return;
3661 }
3662
3663 /* Keep Polling */
3664 SockProcessAsyncSelect(Socket, AsyncData);
3665 return;
3666 }
3667
3668 VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData)
3669 {
3670
3671 ULONG lNetworkEvents;
3672 NTSTATUS Status;
3673
3674 /* Set up the Async Data Event Info */
3675 AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF;
3676 AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF;
3677 AsyncData->AsyncSelectInfo.HandleCount = 1;
3678 AsyncData->AsyncSelectInfo.Exclusive = TRUE;
3679 AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle;
3680 AsyncData->AsyncSelectInfo.Handles[0].Events = 0;
3681
3682 /* Remove unwanted events */
3683 lNetworkEvents = Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents);
3684
3685 /* Set Events to wait for */
3686 if (lNetworkEvents & FD_READ)
3687 {
3688 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE;
3689 }
3690
3691 if (lNetworkEvents & FD_WRITE)
3692 {
3693 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND;
3694 }
3695
3696 if (lNetworkEvents & FD_OOB)
3697 {
3698 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE;
3699 }
3700
3701 if (lNetworkEvents & FD_ACCEPT)
3702 {
3703 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT;
3704 }
3705
3706 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
3707 if (lNetworkEvents & FD_CONNECT)
3708 {
3709 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
3710 }
3711
3712 if (lNetworkEvents & FD_CLOSE)
3713 {
3714 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE;
3715 }
3716
3717 if (lNetworkEvents & FD_QOS)
3718 {
3719 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS;
3720 }
3721
3722 if (lNetworkEvents & FD_GROUP_QOS)
3723 {
3724 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS;
3725 }
3726
3727 /* Send IOCTL */
3728 Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle,
3729 NULL,
3730 NULL,
3731 AsyncData,
3732 &AsyncData->IoStatusBlock,
3733 IOCTL_AFD_SELECT,
3734 &AsyncData->AsyncSelectInfo,
3735 sizeof(AsyncData->AsyncSelectInfo),
3736 &AsyncData->AsyncSelectInfo,
3737 sizeof(AsyncData->AsyncSelectInfo));
3738
3739 /* I/O Manager Won't call the completion routine, let's do it manually */
3740 if (NT_SUCCESS(Status))
3741 {
3742 return;
3743 }
3744 else
3745 {
3746 AsyncData->IoStatusBlock.Status = Status;
3747 SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock);
3748 }
3749 }
3750
3751 VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
3752 {
3753 PASYNC_DATA AsyncData = Context;
3754 BOOL FreeContext = TRUE;
3755 PSOCKET_INFORMATION Socket;
3756
3757 /* Get the Socket */
3758 Socket = AsyncData->ParentSocket;
3759
3760 /* If someone closed it, stop the function */
3761 if (Socket->SharedData->State != SocketClosed)
3762 {
3763 /* Check if the Sequence Number changed by now, in which case quit */
3764 if (AsyncData->SequenceNumber == Socket->SharedData->SequenceNumber)
3765 {
3766 /* Do the actuall select, if needed */
3767 if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)))
3768 {
3769 SockProcessAsyncSelect(Socket, AsyncData);
3770 FreeContext = FALSE;
3771 }
3772 }
3773 }
3774
3775 /* Free the Context */
3776 if (FreeContext)
3777 {
3778 HeapFree(GetProcessHeap(), 0, AsyncData);
3779 }
3780
3781 return;
3782 }
3783
3784 VOID
3785 SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket,
3786 IN ULONG Event)
3787 {
3788 PASYNC_DATA AsyncData;
3789
3790 /* Make sure the event is actually disabled */
3791 if (!(Socket->SharedData->AsyncDisabledEvents & Event))
3792 {
3793 return;
3794 }
3795
3796 /* Re-enable it */
3797 Socket->SharedData->AsyncDisabledEvents &= ~Event;
3798
3799 /* Return if no more events are being polled */
3800 if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0 )
3801 {
3802 return;
3803 }
3804
3805 /* Wait on new events */
3806 AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA));
3807 if (!AsyncData) return;
3808
3809 /* Create the Asynch Thread if Needed */
3810 SockCreateOrReferenceAsyncThread();
3811
3812 /* Increase the sequence number to stop anything else */
3813 Socket->SharedData->SequenceNumber++;
3814
3815 /* Set up the Async Data */
3816 AsyncData->ParentSocket = Socket;
3817 AsyncData->SequenceNumber = Socket->SharedData->SequenceNumber;
3818
3819 /* Begin Async Select by using I/O Completion */
3820 NtSetIoCompletion(SockAsyncCompletionPort,
3821 (PVOID)&SockProcessQueuedAsyncSelect,
3822 AsyncData,
3823 0,
3824 0);
3825
3826 /* All done */
3827 return;
3828 }
3829
3830 BOOL
3831 WINAPI
3832 DllMain(HANDLE hInstDll,
3833 ULONG dwReason,
3834 PVOID Reserved)
3835 {
3836
3837 switch (dwReason)
3838 {
3839 case DLL_PROCESS_ATTACH:
3840
3841 TRACE("Loading MSAFD.DLL \n");
3842
3843 /* Don't need thread attach notifications
3844 so disable them to improve performance */
3845 DisableThreadLibraryCalls(hInstDll);
3846
3847 /* List of DLL Helpers */
3848 InitializeListHead(&SockHelpersListHead);
3849
3850 /* Heap to use when allocating */
3851 GlobalHeap = GetProcessHeap();
3852
3853 /* Initialize the lock that protects our socket list */
3854 InitializeCriticalSection(&SocketListLock);
3855
3856 TRACE("MSAFD.DLL has been loaded\n");
3857
3858 break;
3859
3860 case DLL_THREAD_ATTACH:
3861 break;
3862
3863 case DLL_THREAD_DETACH:
3864 break;
3865
3866 case DLL_PROCESS_DETACH:
3867
3868 /* Delete the socket list lock */
3869 DeleteCriticalSection(&SocketListLock);
3870
3871 break;
3872 }
3873
3874 TRACE("DllMain of msafd.dll (leaving)\n");
3875
3876 return TRUE;
3877 }
3878
3879 /* EOF */