- Update to trunk
[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 BOOLEAN NeedsCompletion;
1914
1915 /* Get the Socket Structure associate to this Socket*/
1916 Socket = GetSocketStructure(Handle);
1917 if (!Socket)
1918 {
1919 *lpErrno = WSAENOTSOCK;
1920 return SOCKET_ERROR;
1921 }
1922
1923 *lpcbBytesReturned = 0;
1924
1925 switch( dwIoControlCode )
1926 {
1927 case FIONBIO:
1928 if( cbInBuffer < sizeof(INT) || IS_INTRESOURCE(lpvInBuffer) )
1929 {
1930 *lpErrno = WSAEFAULT;
1931 return SOCKET_ERROR;
1932 }
1933 Socket->SharedData.NonBlocking = *((PULONG)lpvInBuffer) ? 1 : 0;
1934 *lpErrno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, (PULONG)lpvInBuffer, NULL);
1935 if (*lpErrno != NO_ERROR)
1936 return SOCKET_ERROR;
1937 else
1938 return NO_ERROR;
1939 case FIONREAD:
1940 if( cbOutBuffer < sizeof(INT) || IS_INTRESOURCE(lpvOutBuffer) )
1941 {
1942 *lpErrno = WSAEFAULT;
1943 return SOCKET_ERROR;
1944 }
1945 *lpErrno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, (PULONG)lpvOutBuffer, NULL);
1946 if (*lpErrno != NO_ERROR)
1947 return SOCKET_ERROR;
1948 else
1949 {
1950 *lpcbBytesReturned = sizeof(ULONG);
1951 return NO_ERROR;
1952 }
1953 default:
1954 *lpErrno = Socket->HelperData->WSHIoctl(Socket->HelperContext,
1955 Handle,
1956 Socket->TdiAddressHandle,
1957 Socket->TdiConnectionHandle,
1958 dwIoControlCode,
1959 lpvInBuffer,
1960 cbInBuffer,
1961 lpvOutBuffer,
1962 cbOutBuffer,
1963 lpcbBytesReturned,
1964 lpOverlapped,
1965 lpCompletionRoutine,
1966 (LPBOOL)&NeedsCompletion);
1967
1968 if (*lpErrno != NO_ERROR)
1969 return SOCKET_ERROR;
1970 else
1971 return NO_ERROR;
1972 }
1973 }
1974
1975
1976 INT
1977 WSPAPI
1978 WSPGetSockOpt(IN SOCKET Handle,
1979 IN INT Level,
1980 IN INT OptionName,
1981 OUT CHAR FAR* OptionValue,
1982 IN OUT LPINT OptionLength,
1983 OUT LPINT lpErrno)
1984 {
1985 PSOCKET_INFORMATION Socket = NULL;
1986 PVOID Buffer;
1987 INT BufferSize;
1988 BOOLEAN BoolBuffer;
1989
1990 /* Get the Socket Structure associate to this Socket*/
1991 Socket = GetSocketStructure(Handle);
1992 if (Socket == NULL)
1993 {
1994 *lpErrno = WSAENOTSOCK;
1995 return SOCKET_ERROR;
1996 }
1997
1998 AFD_DbgPrint(MID_TRACE, ("Called\n"));
1999
2000 switch (Level)
2001 {
2002 case SOL_SOCKET:
2003 switch (OptionName)
2004 {
2005 case SO_TYPE:
2006 Buffer = &Socket->SharedData.SocketType;
2007 BufferSize = sizeof(INT);
2008 break;
2009
2010 case SO_RCVBUF:
2011 Buffer = &Socket->SharedData.SizeOfRecvBuffer;
2012 BufferSize = sizeof(INT);
2013 break;
2014
2015 case SO_SNDBUF:
2016 Buffer = &Socket->SharedData.SizeOfSendBuffer;
2017 BufferSize = sizeof(INT);
2018 break;
2019
2020 case SO_ACCEPTCONN:
2021 BoolBuffer = Socket->SharedData.Listening;
2022 Buffer = &BoolBuffer;
2023 BufferSize = sizeof(BOOLEAN);
2024 break;
2025
2026 case SO_BROADCAST:
2027 BoolBuffer = Socket->SharedData.Broadcast;
2028 Buffer = &BoolBuffer;
2029 BufferSize = sizeof(BOOLEAN);
2030 break;
2031
2032 case SO_DEBUG:
2033 BoolBuffer = Socket->SharedData.Debug;
2034 Buffer = &BoolBuffer;
2035 BufferSize = sizeof(BOOLEAN);
2036 break;
2037
2038 /* case SO_CONDITIONAL_ACCEPT: */
2039 case SO_DONTLINGER:
2040 case SO_DONTROUTE:
2041 case SO_ERROR:
2042 case SO_GROUP_ID:
2043 case SO_GROUP_PRIORITY:
2044 case SO_KEEPALIVE:
2045 case SO_LINGER:
2046 case SO_MAX_MSG_SIZE:
2047 case SO_OOBINLINE:
2048 case SO_PROTOCOL_INFO:
2049 case SO_REUSEADDR:
2050 AFD_DbgPrint(MID_TRACE, ("Unimplemented option (%x)\n",
2051 OptionName));
2052
2053 default:
2054 *lpErrno = WSAEINVAL;
2055 return SOCKET_ERROR;
2056 }
2057
2058 if (*OptionLength < BufferSize)
2059 {
2060 *lpErrno = WSAEFAULT;
2061 *OptionLength = BufferSize;
2062 return SOCKET_ERROR;
2063 }
2064 RtlCopyMemory(OptionValue, Buffer, BufferSize);
2065
2066 return 0;
2067
2068 case IPPROTO_TCP: /* FIXME */
2069 default:
2070 *lpErrno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
2071 Handle,
2072 Socket->TdiAddressHandle,
2073 Socket->TdiConnectionHandle,
2074 Level,
2075 OptionName,
2076 OptionValue,
2077 (LPINT)OptionLength);
2078 return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
2079 }
2080 }
2081
2082 INT
2083 WSPAPI
2084 WSPSetSockOpt(
2085 IN SOCKET s,
2086 IN INT level,
2087 IN INT optname,
2088 IN CONST CHAR FAR* optval,
2089 IN INT optlen,
2090 OUT LPINT lpErrno)
2091 {
2092 PSOCKET_INFORMATION Socket;
2093
2094 /* Get the Socket Structure associate to this Socket*/
2095 Socket = GetSocketStructure(s);
2096 if (Socket == NULL)
2097 {
2098 *lpErrno = WSAENOTSOCK;
2099 return SOCKET_ERROR;
2100 }
2101
2102
2103 /* FIXME: We should handle some more cases here */
2104 if (level == SOL_SOCKET)
2105 {
2106 switch (optname)
2107 {
2108 case SO_BROADCAST:
2109 Socket->SharedData.Broadcast = (*optval != 0) ? 1 : 0;
2110 return 0;
2111 }
2112 }
2113
2114
2115 *lpErrno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext,
2116 s,
2117 Socket->TdiAddressHandle,
2118 Socket->TdiConnectionHandle,
2119 level,
2120 optname,
2121 (PCHAR)optval,
2122 optlen);
2123 return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
2124 }
2125
2126 /*
2127 * FUNCTION: Initialize service provider for a client
2128 * ARGUMENTS:
2129 * wVersionRequested = Highest WinSock SPI version that the caller can use
2130 * lpWSPData = Address of WSPDATA structure to initialize
2131 * lpProtocolInfo = Pointer to structure that defines the desired protocol
2132 * UpcallTable = Pointer to upcall table of the WinSock DLL
2133 * lpProcTable = Address of procedure table to initialize
2134 * RETURNS:
2135 * Status of operation
2136 */
2137 INT
2138 WSPAPI
2139 WSPStartup(IN WORD wVersionRequested,
2140 OUT LPWSPDATA lpWSPData,
2141 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
2142 IN WSPUPCALLTABLE UpcallTable,
2143 OUT LPWSPPROC_TABLE lpProcTable)
2144
2145 {
2146 NTSTATUS Status;
2147
2148 AFD_DbgPrint(MAX_TRACE, ("wVersionRequested (0x%X) \n", wVersionRequested));
2149 Status = NO_ERROR;
2150 Upcalls = UpcallTable;
2151
2152 if (Status == NO_ERROR)
2153 {
2154 lpProcTable->lpWSPAccept = WSPAccept;
2155 lpProcTable->lpWSPAddressToString = WSPAddressToString;
2156 lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
2157 lpProcTable->lpWSPBind = WSPBind;
2158 lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
2159 lpProcTable->lpWSPCleanup = WSPCleanup;
2160 lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
2161 lpProcTable->lpWSPConnect = WSPConnect;
2162 lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
2163 lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
2164 lpProcTable->lpWSPEventSelect = WSPEventSelect;
2165 lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
2166 lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
2167 lpProcTable->lpWSPGetSockName = WSPGetSockName;
2168 lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
2169 lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
2170 lpProcTable->lpWSPIoctl = WSPIoctl;
2171 lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
2172 lpProcTable->lpWSPListen = WSPListen;
2173 lpProcTable->lpWSPRecv = WSPRecv;
2174 lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
2175 lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
2176 lpProcTable->lpWSPSelect = WSPSelect;
2177 lpProcTable->lpWSPSend = WSPSend;
2178 lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
2179 lpProcTable->lpWSPSendTo = WSPSendTo;
2180 lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
2181 lpProcTable->lpWSPShutdown = WSPShutdown;
2182 lpProcTable->lpWSPSocket = WSPSocket;
2183 lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
2184 lpWSPData->wVersion = MAKEWORD(2, 2);
2185 lpWSPData->wHighVersion = MAKEWORD(2, 2);
2186 }
2187
2188 AFD_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status));
2189
2190 return Status;
2191 }
2192
2193
2194 /*
2195 * FUNCTION: Cleans up service provider for a client
2196 * ARGUMENTS:
2197 * lpErrno = Address of buffer for error information
2198 * RETURNS:
2199 * 0 if successful, or SOCKET_ERROR if not
2200 */
2201 INT
2202 WSPAPI
2203 WSPCleanup(OUT LPINT lpErrno)
2204
2205 {
2206 AFD_DbgPrint(MAX_TRACE, ("\n"));
2207 AFD_DbgPrint(MAX_TRACE, ("Leaving.\n"));
2208 *lpErrno = NO_ERROR;
2209
2210 return 0;
2211 }
2212
2213
2214
2215 int
2216 GetSocketInformation(PSOCKET_INFORMATION Socket,
2217 ULONG AfdInformationClass,
2218 PULONG Ulong OPTIONAL,
2219 PLARGE_INTEGER LargeInteger OPTIONAL)
2220 {
2221 IO_STATUS_BLOCK IOSB;
2222 AFD_INFO InfoData;
2223 NTSTATUS Status;
2224 HANDLE SockEvent;
2225
2226 Status = NtCreateEvent(&SockEvent,
2227 GENERIC_READ | GENERIC_WRITE,
2228 NULL,
2229 1,
2230 FALSE);
2231
2232 if( !NT_SUCCESS(Status) )
2233 return -1;
2234
2235 /* Set Info Class */
2236 InfoData.InformationClass = AfdInformationClass;
2237
2238 /* Send IOCTL */
2239 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2240 SockEvent,
2241 NULL,
2242 NULL,
2243 &IOSB,
2244 IOCTL_AFD_GET_INFO,
2245 &InfoData,
2246 sizeof(InfoData),
2247 &InfoData,
2248 sizeof(InfoData));
2249
2250 /* Wait for return */
2251 if (Status == STATUS_PENDING)
2252 {
2253 WaitForSingleObject(SockEvent, INFINITE);
2254 Status = IOSB.Status;
2255 }
2256
2257 if (Status != STATUS_SUCCESS)
2258 return -1;
2259
2260 /* Return Information */
2261 if (Ulong != NULL)
2262 {
2263 *Ulong = InfoData.Information.Ulong;
2264 }
2265 if (LargeInteger != NULL)
2266 {
2267 *LargeInteger = InfoData.Information.LargeInteger;
2268 }
2269
2270 NtClose( SockEvent );
2271
2272 return 0;
2273
2274 }
2275
2276
2277 int
2278 SetSocketInformation(PSOCKET_INFORMATION Socket,
2279 ULONG AfdInformationClass,
2280 PULONG Ulong OPTIONAL,
2281 PLARGE_INTEGER LargeInteger OPTIONAL)
2282 {
2283 IO_STATUS_BLOCK IOSB;
2284 AFD_INFO InfoData;
2285 NTSTATUS Status;
2286 HANDLE SockEvent;
2287
2288 Status = NtCreateEvent(&SockEvent,
2289 GENERIC_READ | GENERIC_WRITE,
2290 NULL,
2291 1,
2292 FALSE);
2293
2294 if( !NT_SUCCESS(Status) )
2295 return -1;
2296
2297 /* Set Info Class */
2298 InfoData.InformationClass = AfdInformationClass;
2299
2300 /* Set Information */
2301 if (Ulong != NULL)
2302 {
2303 InfoData.Information.Ulong = *Ulong;
2304 }
2305 if (LargeInteger != NULL)
2306 {
2307 InfoData.Information.LargeInteger = *LargeInteger;
2308 }
2309
2310 AFD_DbgPrint(MID_TRACE,("XXX Info %x (Data %x)\n",
2311 AfdInformationClass, *Ulong));
2312
2313 /* Send IOCTL */
2314 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2315 SockEvent,
2316 NULL,
2317 NULL,
2318 &IOSB,
2319 IOCTL_AFD_SET_INFO,
2320 &InfoData,
2321 sizeof(InfoData),
2322 NULL,
2323 0);
2324
2325 /* Wait for return */
2326 if (Status == STATUS_PENDING)
2327 {
2328 WaitForSingleObject(SockEvent, INFINITE);
2329 Status = IOSB.Status;
2330 }
2331
2332 NtClose( SockEvent );
2333
2334 return Status == STATUS_SUCCESS ? 0 : -1;
2335
2336 }
2337
2338 PSOCKET_INFORMATION
2339 GetSocketStructure(SOCKET Handle)
2340 {
2341 PSOCKET_INFORMATION CurrentSocket;
2342
2343 EnterCriticalSection(&SocketListLock);
2344
2345 CurrentSocket = SocketListHead;
2346 while (CurrentSocket)
2347 {
2348 if (CurrentSocket->Handle == Handle)
2349 {
2350 LeaveCriticalSection(&SocketListLock);
2351 return CurrentSocket;
2352 }
2353
2354 CurrentSocket = CurrentSocket->NextSocket;
2355 }
2356
2357 LeaveCriticalSection(&SocketListLock);
2358
2359 return NULL;
2360 }
2361
2362 int CreateContext(PSOCKET_INFORMATION Socket)
2363 {
2364 IO_STATUS_BLOCK IOSB;
2365 SOCKET_CONTEXT ContextData;
2366 NTSTATUS Status;
2367 HANDLE SockEvent;
2368
2369 Status = NtCreateEvent(&SockEvent,
2370 GENERIC_READ | GENERIC_WRITE,
2371 NULL,
2372 1,
2373 FALSE);
2374
2375 if( !NT_SUCCESS(Status) )
2376 return -1;
2377
2378 /* Create Context */
2379 ContextData.SharedData = Socket->SharedData;
2380 ContextData.SizeOfHelperData = 0;
2381 RtlCopyMemory (&ContextData.LocalAddress,
2382 Socket->LocalAddress,
2383 Socket->SharedData.SizeOfLocalAddress);
2384 RtlCopyMemory (&ContextData.RemoteAddress,
2385 Socket->RemoteAddress,
2386 Socket->SharedData.SizeOfRemoteAddress);
2387
2388 /* Send IOCTL */
2389 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2390 SockEvent,
2391 NULL,
2392 NULL,
2393 &IOSB,
2394 IOCTL_AFD_SET_CONTEXT,
2395 &ContextData,
2396 sizeof(ContextData),
2397 NULL,
2398 0);
2399
2400 /* Wait for Completition */
2401 if (Status == STATUS_PENDING)
2402 {
2403 WaitForSingleObject(SockEvent, INFINITE);
2404 Status = IOSB.Status;
2405 }
2406
2407 NtClose( SockEvent );
2408
2409 return Status == STATUS_SUCCESS ? 0 : -1;
2410 }
2411
2412 BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
2413 {
2414 HANDLE hAsyncThread;
2415 DWORD AsyncThreadId;
2416 HANDLE AsyncEvent;
2417 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
2418 NTSTATUS Status;
2419
2420 /* Check if the Thread Already Exists */
2421 if (SockAsyncThreadRefCount)
2422 {
2423 return TRUE;
2424 }
2425
2426 /* Create the Completion Port */
2427 if (!SockAsyncCompletionPort)
2428 {
2429 Status = NtCreateIoCompletion(&SockAsyncCompletionPort,
2430 IO_COMPLETION_ALL_ACCESS,
2431 NULL,
2432 2); // Allow 2 threads only
2433
2434 /* Protect Handle */
2435 HandleFlags.ProtectFromClose = TRUE;
2436 HandleFlags.Inherit = FALSE;
2437 Status = NtSetInformationObject(SockAsyncCompletionPort,
2438 ObjectHandleFlagInformation,
2439 &HandleFlags,
2440 sizeof(HandleFlags));
2441 }
2442
2443 /* Create the Async Event */
2444 Status = NtCreateEvent(&AsyncEvent,
2445 EVENT_ALL_ACCESS,
2446 NULL,
2447 NotificationEvent,
2448 FALSE);
2449
2450 /* Create the Async Thread */
2451 hAsyncThread = CreateThread(NULL,
2452 0,
2453 (LPTHREAD_START_ROUTINE)SockAsyncThread,
2454 NULL,
2455 0,
2456 &AsyncThreadId);
2457
2458 /* Close the Handle */
2459 NtClose(hAsyncThread);
2460
2461 /* Increase the Reference Count */
2462 SockAsyncThreadRefCount++;
2463 return TRUE;
2464 }
2465
2466 int SockAsyncThread(PVOID ThreadParam)
2467 {
2468 PVOID AsyncContext;
2469 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
2470 IO_STATUS_BLOCK IOSB;
2471 NTSTATUS Status;
2472
2473 /* Make the Thread Higher Priority */
2474 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
2475
2476 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
2477 do
2478 {
2479 Status = NtRemoveIoCompletion (SockAsyncCompletionPort,
2480 (PVOID*)&AsyncCompletionRoutine,
2481 &AsyncContext,
2482 &IOSB,
2483 NULL);
2484 /* Call the Async Function */
2485 if (NT_SUCCESS(Status))
2486 {
2487 (*AsyncCompletionRoutine)(AsyncContext, &IOSB);
2488 }
2489 else
2490 {
2491 /* It Failed, sleep for a second */
2492 Sleep(1000);
2493 }
2494 } while ((Status != STATUS_TIMEOUT));
2495
2496 /* The Thread has Ended */
2497 return 0;
2498 }
2499
2500 BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
2501 {
2502 UNICODE_STRING AfdHelper;
2503 OBJECT_ATTRIBUTES ObjectAttributes;
2504 IO_STATUS_BLOCK IoSb;
2505 NTSTATUS Status;
2506 FILE_COMPLETION_INFORMATION CompletionInfo;
2507 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
2508
2509 /* First, make sure we're not already intialized */
2510 if (SockAsyncHelperAfdHandle)
2511 {
2512 return TRUE;
2513 }
2514
2515 /* Set up Handle Name and Object */
2516 RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" );
2517 InitializeObjectAttributes(&ObjectAttributes,
2518 &AfdHelper,
2519 OBJ_INHERIT | OBJ_CASE_INSENSITIVE,
2520 NULL,
2521 NULL);
2522
2523 /* Open the Handle to AFD */
2524 Status = NtCreateFile(&SockAsyncHelperAfdHandle,
2525 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
2526 &ObjectAttributes,
2527 &IoSb,
2528 NULL,
2529 0,
2530 FILE_SHARE_READ | FILE_SHARE_WRITE,
2531 FILE_OPEN_IF,
2532 0,
2533 NULL,
2534 0);
2535
2536 /*
2537 * Now Set up the Completion Port Information
2538 * This means that whenever a Poll is finished, the routine will be executed
2539 */
2540 CompletionInfo.Port = SockAsyncCompletionPort;
2541 CompletionInfo.Key = SockAsyncSelectCompletionRoutine;
2542 Status = NtSetInformationFile(SockAsyncHelperAfdHandle,
2543 &IoSb,
2544 &CompletionInfo,
2545 sizeof(CompletionInfo),
2546 FileCompletionInformation);
2547
2548
2549 /* Protect the Handle */
2550 HandleFlags.ProtectFromClose = TRUE;
2551 HandleFlags.Inherit = FALSE;
2552 Status = NtSetInformationObject(SockAsyncCompletionPort,
2553 ObjectHandleFlagInformation,
2554 &HandleFlags,
2555 sizeof(HandleFlags));
2556
2557
2558 /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
2559 SockAsyncSelectCalled = TRUE;
2560 return TRUE;
2561 }
2562
2563 VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
2564 {
2565
2566 PASYNC_DATA AsyncData = Context;
2567 PSOCKET_INFORMATION Socket;
2568 ULONG x;
2569
2570 /* Get the Socket */
2571 Socket = AsyncData->ParentSocket;
2572
2573 /* Check if the Sequence Number Changed behind our back */
2574 if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber )
2575 {
2576 return;
2577 }
2578
2579 /* Check we were manually called b/c of a failure */
2580 if (!NT_SUCCESS(IoStatusBlock->Status))
2581 {
2582 /* FIXME: Perform Upcall */
2583 return;
2584 }
2585
2586 for (x = 1; x; x<<=1)
2587 {
2588 switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x)
2589 {
2590 case AFD_EVENT_RECEIVE:
2591 if (0 != (Socket->SharedData.AsyncEvents & FD_READ) &&
2592 0 == (Socket->SharedData.AsyncDisabledEvents & FD_READ))
2593 {
2594 /* Make the Notifcation */
2595 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2596 Socket->SharedData.wMsg,
2597 Socket->Handle,
2598 WSAMAKESELECTREPLY(FD_READ, 0));
2599 /* Disable this event until the next read(); */
2600 Socket->SharedData.AsyncDisabledEvents |= FD_READ;
2601 }
2602 break;
2603
2604 case AFD_EVENT_OOB_RECEIVE:
2605 if (0 != (Socket->SharedData.AsyncEvents & FD_OOB) &&
2606 0 == (Socket->SharedData.AsyncDisabledEvents & FD_OOB))
2607 {
2608 /* Make the Notifcation */
2609 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2610 Socket->SharedData.wMsg,
2611 Socket->Handle,
2612 WSAMAKESELECTREPLY(FD_OOB, 0));
2613 /* Disable this event until the next read(); */
2614 Socket->SharedData.AsyncDisabledEvents |= FD_OOB;
2615 }
2616 break;
2617
2618 case AFD_EVENT_SEND:
2619 if (0 != (Socket->SharedData.AsyncEvents & FD_WRITE) &&
2620 0 == (Socket->SharedData.AsyncDisabledEvents & FD_WRITE))
2621 {
2622 /* Make the Notifcation */
2623 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2624 Socket->SharedData.wMsg,
2625 Socket->Handle,
2626 WSAMAKESELECTREPLY(FD_WRITE, 0));
2627 /* Disable this event until the next write(); */
2628 Socket->SharedData.AsyncDisabledEvents |= FD_WRITE;
2629 }
2630 break;
2631
2632 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
2633 case AFD_EVENT_CONNECT:
2634 case AFD_EVENT_CONNECT_FAIL:
2635 if (0 != (Socket->SharedData.AsyncEvents & FD_CONNECT) &&
2636 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CONNECT))
2637 {
2638 /* Make the Notifcation */
2639 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2640 Socket->SharedData.wMsg,
2641 Socket->Handle,
2642 WSAMAKESELECTREPLY(FD_CONNECT, 0));
2643 /* Disable this event forever; */
2644 Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT;
2645 }
2646 break;
2647
2648 case AFD_EVENT_ACCEPT:
2649 if (0 != (Socket->SharedData.AsyncEvents & FD_ACCEPT) &&
2650 0 == (Socket->SharedData.AsyncDisabledEvents & FD_ACCEPT))
2651 {
2652 /* Make the Notifcation */
2653 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2654 Socket->SharedData.wMsg,
2655 Socket->Handle,
2656 WSAMAKESELECTREPLY(FD_ACCEPT, 0));
2657 /* Disable this event until the next accept(); */
2658 Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT;
2659 }
2660 break;
2661
2662 case AFD_EVENT_DISCONNECT:
2663 case AFD_EVENT_ABORT:
2664 case AFD_EVENT_CLOSE:
2665 if (0 != (Socket->SharedData.AsyncEvents & FD_CLOSE) &&
2666 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CLOSE))
2667 {
2668 /* Make the Notifcation */
2669 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2670 Socket->SharedData.wMsg,
2671 Socket->Handle,
2672 WSAMAKESELECTREPLY(FD_CLOSE, 0));
2673 /* Disable this event forever; */
2674 Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE;
2675 }
2676 break;
2677 /* FIXME: Support QOS */
2678 }
2679 }
2680
2681 /* Check if there are any events left for us to check */
2682 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 )
2683 {
2684 return;
2685 }
2686
2687 /* Keep Polling */
2688 SockProcessAsyncSelect(Socket, AsyncData);
2689 return;
2690 }
2691
2692 VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData)
2693 {
2694
2695 ULONG lNetworkEvents;
2696 NTSTATUS Status;
2697
2698 /* Set up the Async Data Event Info */
2699 AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF;
2700 AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF;
2701 AsyncData->AsyncSelectInfo.HandleCount = 1;
2702 AsyncData->AsyncSelectInfo.Exclusive = TRUE;
2703 AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle;
2704 AsyncData->AsyncSelectInfo.Handles[0].Events = 0;
2705
2706 /* Remove unwanted events */
2707 lNetworkEvents = Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents);
2708
2709 /* Set Events to wait for */
2710 if (lNetworkEvents & FD_READ)
2711 {
2712 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE;
2713 }
2714
2715 if (lNetworkEvents & FD_WRITE)
2716 {
2717 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND;
2718 }
2719
2720 if (lNetworkEvents & FD_OOB)
2721 {
2722 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE;
2723 }
2724
2725 if (lNetworkEvents & FD_ACCEPT)
2726 {
2727 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT;
2728 }
2729
2730 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
2731 if (lNetworkEvents & FD_CONNECT)
2732 {
2733 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
2734 }
2735
2736 if (lNetworkEvents & FD_CLOSE)
2737 {
2738 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE;
2739 }
2740
2741 if (lNetworkEvents & FD_QOS)
2742 {
2743 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS;
2744 }
2745
2746 if (lNetworkEvents & FD_GROUP_QOS)
2747 {
2748 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS;
2749 }
2750
2751 /* Send IOCTL */
2752 Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle,
2753 NULL,
2754 NULL,
2755 AsyncData,
2756 &AsyncData->IoStatusBlock,
2757 IOCTL_AFD_SELECT,
2758 &AsyncData->AsyncSelectInfo,
2759 sizeof(AsyncData->AsyncSelectInfo),
2760 &AsyncData->AsyncSelectInfo,
2761 sizeof(AsyncData->AsyncSelectInfo));
2762
2763 /* I/O Manager Won't call the completion routine, let's do it manually */
2764 if (NT_SUCCESS(Status))
2765 {
2766 return;
2767 }
2768 else
2769 {
2770 AsyncData->IoStatusBlock.Status = Status;
2771 SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock);
2772 }
2773 }
2774
2775 VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
2776 {
2777 PASYNC_DATA AsyncData = Context;
2778 BOOL FreeContext = TRUE;
2779 PSOCKET_INFORMATION Socket;
2780
2781 /* Get the Socket */
2782 Socket = AsyncData->ParentSocket;
2783
2784 /* If someone closed it, stop the function */
2785 if (Socket->SharedData.State != SocketClosed)
2786 {
2787 /* Check if the Sequence Number changed by now, in which case quit */
2788 if (AsyncData->SequenceNumber == Socket->SharedData.SequenceNumber)
2789 {
2790 /* Do the actuall select, if needed */
2791 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)))
2792 {
2793 SockProcessAsyncSelect(Socket, AsyncData);
2794 FreeContext = FALSE;
2795 }
2796 }
2797 }
2798
2799 /* Free the Context */
2800 if (FreeContext)
2801 {
2802 HeapFree(GetProcessHeap(), 0, AsyncData);
2803 }
2804
2805 return;
2806 }
2807
2808 VOID
2809 SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket,
2810 IN ULONG Event)
2811 {
2812 PASYNC_DATA AsyncData;
2813
2814 /* Make sure the event is actually disabled */
2815 if (!(Socket->SharedData.AsyncDisabledEvents & Event))
2816 {
2817 return;
2818 }
2819
2820 /* Re-enable it */
2821 Socket->SharedData.AsyncDisabledEvents &= ~Event;
2822
2823 /* Return if no more events are being polled */
2824 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 )
2825 {
2826 return;
2827 }
2828
2829 /* Wait on new events */
2830 AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA));
2831 if (!AsyncData) return;
2832
2833 /* Create the Asynch Thread if Needed */
2834 SockCreateOrReferenceAsyncThread();
2835
2836 /* Increase the sequence number to stop anything else */
2837 Socket->SharedData.SequenceNumber++;
2838
2839 /* Set up the Async Data */
2840 AsyncData->ParentSocket = Socket;
2841 AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber;
2842
2843 /* Begin Async Select by using I/O Completion */
2844 NtSetIoCompletion(SockAsyncCompletionPort,
2845 (PVOID)&SockProcessQueuedAsyncSelect,
2846 AsyncData,
2847 0,
2848 0);
2849
2850 /* All done */
2851 return;
2852 }
2853
2854 BOOL
2855 WINAPI
2856 DllMain(HANDLE hInstDll,
2857 ULONG dwReason,
2858 PVOID Reserved)
2859 {
2860
2861 switch (dwReason)
2862 {
2863 case DLL_PROCESS_ATTACH:
2864
2865 AFD_DbgPrint(MAX_TRACE, ("Loading MSAFD.DLL \n"));
2866
2867 /* Don't need thread attach notifications
2868 so disable them to improve performance */
2869 DisableThreadLibraryCalls(hInstDll);
2870
2871 /* List of DLL Helpers */
2872 InitializeListHead(&SockHelpersListHead);
2873
2874 /* Heap to use when allocating */
2875 GlobalHeap = GetProcessHeap();
2876
2877 /* Initialize the lock that protects our socket list */
2878 InitializeCriticalSection(&SocketListLock);
2879
2880 AFD_DbgPrint(MAX_TRACE, ("MSAFD.DLL has been loaded\n"));
2881
2882 break;
2883
2884 case DLL_THREAD_ATTACH:
2885 break;
2886
2887 case DLL_THREAD_DETACH:
2888 break;
2889
2890 case DLL_PROCESS_DETACH:
2891
2892 /* Delete the socket list lock */
2893 DeleteCriticalSection(&SocketListLock);
2894
2895 break;
2896 }
2897
2898 AFD_DbgPrint(MAX_TRACE, ("DllMain of msafd.dll (leaving)\n"));
2899
2900 return TRUE;
2901 }
2902
2903 /* EOF */
2904
2905