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