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