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