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