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