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