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