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