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