- Check that AFD succeeded the create request
[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_PTR 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) )
1739 return SOCKET_ERROR;
1740 Socket->SharedData.NonBlocking = *((PINT)lpvInBuffer) ? 1 : 0;
1741 AFD_DbgPrint(MID_TRACE,("[%x] Set nonblocking %d\n", Handle, Socket->SharedData.NonBlocking));
1742 return 0;
1743 case FIONREAD:
1744 return GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, (PULONG)lpvOutBuffer, NULL);
1745 default:
1746 *lpErrno = WSAEINVAL;
1747 return SOCKET_ERROR;
1748 }
1749 }
1750
1751
1752 INT
1753 WSPAPI
1754 WSPGetSockOpt(IN SOCKET Handle,
1755 IN INT Level,
1756 IN INT OptionName,
1757 OUT CHAR FAR* OptionValue,
1758 IN OUT LPINT OptionLength,
1759 OUT LPINT lpErrno)
1760 {
1761 PSOCKET_INFORMATION Socket = NULL;
1762 PVOID Buffer;
1763 INT BufferSize;
1764 BOOLEAN BoolBuffer;
1765
1766 /* Get the Socket Structure associate to this Socket*/
1767 Socket = GetSocketStructure(Handle);
1768 if (Socket == NULL)
1769 {
1770 *lpErrno = WSAENOTSOCK;
1771 return SOCKET_ERROR;
1772 }
1773
1774 AFD_DbgPrint(MID_TRACE, ("Called\n"));
1775
1776 switch (Level)
1777 {
1778 case SOL_SOCKET:
1779 switch (OptionName)
1780 {
1781 case SO_TYPE:
1782 Buffer = &Socket->SharedData.SocketType;
1783 BufferSize = sizeof(INT);
1784 break;
1785
1786 case SO_RCVBUF:
1787 Buffer = &Socket->SharedData.SizeOfRecvBuffer;
1788 BufferSize = sizeof(INT);
1789 break;
1790
1791 case SO_SNDBUF:
1792 Buffer = &Socket->SharedData.SizeOfSendBuffer;
1793 BufferSize = sizeof(INT);
1794 break;
1795
1796 case SO_ACCEPTCONN:
1797 BoolBuffer = Socket->SharedData.Listening;
1798 Buffer = &BoolBuffer;
1799 BufferSize = sizeof(BOOLEAN);
1800 break;
1801
1802 case SO_BROADCAST:
1803 BoolBuffer = Socket->SharedData.Broadcast;
1804 Buffer = &BoolBuffer;
1805 BufferSize = sizeof(BOOLEAN);
1806 break;
1807
1808 case SO_DEBUG:
1809 BoolBuffer = Socket->SharedData.Debug;
1810 Buffer = &BoolBuffer;
1811 BufferSize = sizeof(BOOLEAN);
1812 break;
1813
1814 /* case SO_CONDITIONAL_ACCEPT: */
1815 case SO_DONTLINGER:
1816 case SO_DONTROUTE:
1817 case SO_ERROR:
1818 case SO_GROUP_ID:
1819 case SO_GROUP_PRIORITY:
1820 case SO_KEEPALIVE:
1821 case SO_LINGER:
1822 case SO_MAX_MSG_SIZE:
1823 case SO_OOBINLINE:
1824 case SO_PROTOCOL_INFO:
1825 case SO_REUSEADDR:
1826 AFD_DbgPrint(MID_TRACE, ("Unimplemented option (%x)\n",
1827 OptionName));
1828
1829 default:
1830 *lpErrno = WSAEINVAL;
1831 return SOCKET_ERROR;
1832 }
1833
1834 if (*OptionLength < BufferSize)
1835 {
1836 *lpErrno = WSAEFAULT;
1837 *OptionLength = BufferSize;
1838 return SOCKET_ERROR;
1839 }
1840 RtlCopyMemory(OptionValue, Buffer, BufferSize);
1841
1842 return 0;
1843
1844 case IPPROTO_TCP: /* FIXME */
1845 default:
1846 *lpErrno = WSAEINVAL;
1847 return SOCKET_ERROR;
1848 }
1849 }
1850
1851
1852 /*
1853 * FUNCTION: Initialize service provider for a client
1854 * ARGUMENTS:
1855 * wVersionRequested = Highest WinSock SPI version that the caller can use
1856 * lpWSPData = Address of WSPDATA structure to initialize
1857 * lpProtocolInfo = Pointer to structure that defines the desired protocol
1858 * UpcallTable = Pointer to upcall table of the WinSock DLL
1859 * lpProcTable = Address of procedure table to initialize
1860 * RETURNS:
1861 * Status of operation
1862 */
1863 INT
1864 WSPAPI
1865 WSPStartup(IN WORD wVersionRequested,
1866 OUT LPWSPDATA lpWSPData,
1867 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
1868 IN WSPUPCALLTABLE UpcallTable,
1869 OUT LPWSPPROC_TABLE lpProcTable)
1870
1871 {
1872 NTSTATUS Status;
1873
1874 AFD_DbgPrint(MAX_TRACE, ("wVersionRequested (0x%X) \n", wVersionRequested));
1875 Status = NO_ERROR;
1876 Upcalls = UpcallTable;
1877
1878 if (Status == NO_ERROR)
1879 {
1880 lpProcTable->lpWSPAccept = WSPAccept;
1881 lpProcTable->lpWSPAddressToString = WSPAddressToString;
1882 lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
1883 lpProcTable->lpWSPBind = WSPBind;
1884 lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
1885 lpProcTable->lpWSPCleanup = WSPCleanup;
1886 lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
1887 lpProcTable->lpWSPConnect = WSPConnect;
1888 lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
1889 lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
1890 lpProcTable->lpWSPEventSelect = WSPEventSelect;
1891 lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
1892 lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
1893 lpProcTable->lpWSPGetSockName = WSPGetSockName;
1894 lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
1895 lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
1896 lpProcTable->lpWSPIoctl = WSPIoctl;
1897 lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
1898 lpProcTable->lpWSPListen = WSPListen;
1899 lpProcTable->lpWSPRecv = WSPRecv;
1900 lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
1901 lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
1902 lpProcTable->lpWSPSelect = WSPSelect;
1903 lpProcTable->lpWSPSend = WSPSend;
1904 lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
1905 lpProcTable->lpWSPSendTo = WSPSendTo;
1906 lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
1907 lpProcTable->lpWSPShutdown = WSPShutdown;
1908 lpProcTable->lpWSPSocket = WSPSocket;
1909 lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
1910 lpWSPData->wVersion = MAKEWORD(2, 2);
1911 lpWSPData->wHighVersion = MAKEWORD(2, 2);
1912 }
1913
1914 AFD_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status));
1915
1916 return Status;
1917 }
1918
1919
1920 /*
1921 * FUNCTION: Cleans up service provider for a client
1922 * ARGUMENTS:
1923 * lpErrno = Address of buffer for error information
1924 * RETURNS:
1925 * 0 if successful, or SOCKET_ERROR if not
1926 */
1927 INT
1928 WSPAPI
1929 WSPCleanup(OUT LPINT lpErrno)
1930
1931 {
1932 AFD_DbgPrint(MAX_TRACE, ("\n"));
1933 AFD_DbgPrint(MAX_TRACE, ("Leaving.\n"));
1934 *lpErrno = NO_ERROR;
1935
1936 return 0;
1937 }
1938
1939
1940
1941 int
1942 GetSocketInformation(PSOCKET_INFORMATION Socket,
1943 ULONG AfdInformationClass,
1944 PULONG Ulong OPTIONAL,
1945 PLARGE_INTEGER LargeInteger OPTIONAL)
1946 {
1947 IO_STATUS_BLOCK IOSB;
1948 AFD_INFO InfoData;
1949 NTSTATUS Status;
1950 HANDLE SockEvent;
1951
1952 Status = NtCreateEvent(&SockEvent,
1953 GENERIC_READ | GENERIC_WRITE,
1954 NULL,
1955 1,
1956 FALSE);
1957
1958 if( !NT_SUCCESS(Status) )
1959 return -1;
1960
1961 /* Set Info Class */
1962 InfoData.InformationClass = AfdInformationClass;
1963
1964 /* Send IOCTL */
1965 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
1966 SockEvent,
1967 NULL,
1968 NULL,
1969 &IOSB,
1970 IOCTL_AFD_GET_INFO,
1971 &InfoData,
1972 sizeof(InfoData),
1973 &InfoData,
1974 sizeof(InfoData));
1975
1976 /* Wait for return */
1977 if (Status == STATUS_PENDING)
1978 {
1979 WaitForSingleObject(SockEvent, INFINITE);
1980 }
1981
1982 /* Return Information */
1983 if (Ulong != NULL)
1984 {
1985 *Ulong = InfoData.Information.Ulong;
1986 }
1987 if (LargeInteger != NULL)
1988 {
1989 *LargeInteger = InfoData.Information.LargeInteger;
1990 }
1991
1992 NtClose( SockEvent );
1993
1994 return 0;
1995
1996 }
1997
1998
1999 int
2000 SetSocketInformation(PSOCKET_INFORMATION Socket,
2001 ULONG AfdInformationClass,
2002 PULONG Ulong OPTIONAL,
2003 PLARGE_INTEGER LargeInteger OPTIONAL)
2004 {
2005 IO_STATUS_BLOCK IOSB;
2006 AFD_INFO InfoData;
2007 NTSTATUS Status;
2008 HANDLE SockEvent;
2009
2010 Status = NtCreateEvent(&SockEvent,
2011 GENERIC_READ | GENERIC_WRITE,
2012 NULL,
2013 1,
2014 FALSE);
2015
2016 if( !NT_SUCCESS(Status) )
2017 return -1;
2018
2019 /* Set Info Class */
2020 InfoData.InformationClass = AfdInformationClass;
2021
2022 /* Set Information */
2023 if (Ulong != NULL)
2024 {
2025 InfoData.Information.Ulong = *Ulong;
2026 }
2027 if (LargeInteger != NULL)
2028 {
2029 InfoData.Information.LargeInteger = *LargeInteger;
2030 }
2031
2032 AFD_DbgPrint(MID_TRACE,("XXX Info %x (Data %x)\n",
2033 AfdInformationClass, *Ulong));
2034
2035 /* Send IOCTL */
2036 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2037 SockEvent,
2038 NULL,
2039 NULL,
2040 &IOSB,
2041 IOCTL_AFD_SET_INFO,
2042 &InfoData,
2043 sizeof(InfoData),
2044 NULL,
2045 0);
2046
2047 /* Wait for return */
2048 if (Status == STATUS_PENDING)
2049 {
2050 WaitForSingleObject(SockEvent, INFINITE);
2051 }
2052
2053 NtClose( SockEvent );
2054
2055 return 0;
2056
2057 }
2058
2059 PSOCKET_INFORMATION
2060 GetSocketStructure(SOCKET Handle)
2061 {
2062 ULONG i;
2063
2064 for (i=0; i<SocketCount; i++)
2065 {
2066 if (Sockets[i]->Handle == Handle)
2067 {
2068 return Sockets[i];
2069 }
2070 }
2071 return 0;
2072 }
2073
2074 int CreateContext(PSOCKET_INFORMATION Socket)
2075 {
2076 IO_STATUS_BLOCK IOSB;
2077 SOCKET_CONTEXT ContextData;
2078 NTSTATUS Status;
2079 HANDLE SockEvent;
2080
2081 Status = NtCreateEvent(&SockEvent,
2082 GENERIC_READ | GENERIC_WRITE,
2083 NULL,
2084 1,
2085 FALSE);
2086
2087 if( !NT_SUCCESS(Status) )
2088 return -1;
2089
2090 /* Create Context */
2091 ContextData.SharedData = Socket->SharedData;
2092 ContextData.SizeOfHelperData = 0;
2093 RtlCopyMemory (&ContextData.LocalAddress,
2094 Socket->LocalAddress,
2095 Socket->SharedData.SizeOfLocalAddress);
2096 RtlCopyMemory (&ContextData.RemoteAddress,
2097 Socket->RemoteAddress,
2098 Socket->SharedData.SizeOfRemoteAddress);
2099
2100 /* Send IOCTL */
2101 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2102 SockEvent,
2103 NULL,
2104 NULL,
2105 &IOSB,
2106 IOCTL_AFD_SET_CONTEXT,
2107 &ContextData,
2108 sizeof(ContextData),
2109 NULL,
2110 0);
2111
2112 /* Wait for Completition */
2113 if (Status == STATUS_PENDING)
2114 {
2115 WaitForSingleObject(SockEvent, INFINITE);
2116 }
2117
2118 NtClose( SockEvent );
2119
2120 return 0;
2121 }
2122
2123 BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
2124 {
2125 HANDLE hAsyncThread;
2126 DWORD AsyncThreadId;
2127 HANDLE AsyncEvent;
2128 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
2129 NTSTATUS Status;
2130
2131 /* Check if the Thread Already Exists */
2132 if (SockAsyncThreadRefCount)
2133 {
2134 return TRUE;
2135 }
2136
2137 /* Create the Completion Port */
2138 if (!SockAsyncCompletionPort)
2139 {
2140 Status = NtCreateIoCompletion(&SockAsyncCompletionPort,
2141 IO_COMPLETION_ALL_ACCESS,
2142 NULL,
2143 2); // Allow 2 threads only
2144
2145 /* Protect Handle */
2146 HandleFlags.ProtectFromClose = TRUE;
2147 HandleFlags.Inherit = FALSE;
2148 Status = NtSetInformationObject(SockAsyncCompletionPort,
2149 ObjectHandleFlagInformation,
2150 &HandleFlags,
2151 sizeof(HandleFlags));
2152 }
2153
2154 /* Create the Async Event */
2155 Status = NtCreateEvent(&AsyncEvent,
2156 EVENT_ALL_ACCESS,
2157 NULL,
2158 NotificationEvent,
2159 FALSE);
2160
2161 /* Create the Async Thread */
2162 hAsyncThread = CreateThread(NULL,
2163 0,
2164 (LPTHREAD_START_ROUTINE)SockAsyncThread,
2165 NULL,
2166 0,
2167 &AsyncThreadId);
2168
2169 /* Close the Handle */
2170 NtClose(hAsyncThread);
2171
2172 /* Increase the Reference Count */
2173 SockAsyncThreadRefCount++;
2174 return TRUE;
2175 }
2176
2177 int SockAsyncThread(PVOID ThreadParam)
2178 {
2179 PVOID AsyncContext;
2180 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
2181 IO_STATUS_BLOCK IOSB;
2182 NTSTATUS Status;
2183
2184 /* Make the Thread Higher Priority */
2185 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
2186
2187 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
2188 do
2189 {
2190 Status = NtRemoveIoCompletion (SockAsyncCompletionPort,
2191 (PVOID*)&AsyncCompletionRoutine,
2192 &AsyncContext,
2193 &IOSB,
2194 NULL);
2195 /* Call the Async Function */
2196 if (NT_SUCCESS(Status))
2197 {
2198 (*AsyncCompletionRoutine)(AsyncContext, &IOSB);
2199 }
2200 else
2201 {
2202 /* It Failed, sleep for a second */
2203 Sleep(1000);
2204 }
2205 } while ((Status != STATUS_TIMEOUT));
2206
2207 /* The Thread has Ended */
2208 return 0;
2209 }
2210
2211 BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
2212 {
2213 UNICODE_STRING AfdHelper;
2214 OBJECT_ATTRIBUTES ObjectAttributes;
2215 IO_STATUS_BLOCK IoSb;
2216 NTSTATUS Status;
2217 FILE_COMPLETION_INFORMATION CompletionInfo;
2218 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
2219
2220 /* First, make sure we're not already intialized */
2221 if (SockAsyncHelperAfdHandle)
2222 {
2223 return TRUE;
2224 }
2225
2226 /* Set up Handle Name and Object */
2227 RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" );
2228 InitializeObjectAttributes(&ObjectAttributes,
2229 &AfdHelper,
2230 OBJ_INHERIT | OBJ_CASE_INSENSITIVE,
2231 NULL,
2232 NULL);
2233
2234 /* Open the Handle to AFD */
2235 Status = NtCreateFile(&SockAsyncHelperAfdHandle,
2236 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
2237 &ObjectAttributes,
2238 &IoSb,
2239 NULL,
2240 0,
2241 FILE_SHARE_READ | FILE_SHARE_WRITE,
2242 FILE_OPEN_IF,
2243 0,
2244 NULL,
2245 0);
2246
2247 /*
2248 * Now Set up the Completion Port Information
2249 * This means that whenever a Poll is finished, the routine will be executed
2250 */
2251 CompletionInfo.Port = SockAsyncCompletionPort;
2252 CompletionInfo.Key = SockAsyncSelectCompletionRoutine;
2253 Status = NtSetInformationFile(SockAsyncHelperAfdHandle,
2254 &IoSb,
2255 &CompletionInfo,
2256 sizeof(CompletionInfo),
2257 FileCompletionInformation);
2258
2259
2260 /* Protect the Handle */
2261 HandleFlags.ProtectFromClose = TRUE;
2262 HandleFlags.Inherit = FALSE;
2263 Status = NtSetInformationObject(SockAsyncCompletionPort,
2264 ObjectHandleFlagInformation,
2265 &HandleFlags,
2266 sizeof(HandleFlags));
2267
2268
2269 /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
2270 SockAsyncSelectCalled = TRUE;
2271 return TRUE;
2272 }
2273
2274 VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
2275 {
2276
2277 PASYNC_DATA AsyncData = Context;
2278 PSOCKET_INFORMATION Socket;
2279 ULONG x;
2280
2281 /* Get the Socket */
2282 Socket = AsyncData->ParentSocket;
2283
2284 /* Check if the Sequence Number Changed behind our back */
2285 if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber )
2286 {
2287 return;
2288 }
2289
2290 /* Check we were manually called b/c of a failure */
2291 if (!NT_SUCCESS(IoStatusBlock->Status))
2292 {
2293 /* FIXME: Perform Upcall */
2294 return;
2295 }
2296
2297 for (x = 1; x; x<<=1)
2298 {
2299 switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x)
2300 {
2301 case AFD_EVENT_RECEIVE:
2302 if (0 != (Socket->SharedData.AsyncEvents & FD_READ) &&
2303 0 == (Socket->SharedData.AsyncDisabledEvents & FD_READ))
2304 {
2305 /* Make the Notifcation */
2306 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2307 Socket->SharedData.wMsg,
2308 Socket->Handle,
2309 WSAMAKESELECTREPLY(FD_READ, 0));
2310 /* Disable this event until the next read(); */
2311 Socket->SharedData.AsyncDisabledEvents |= FD_READ;
2312 }
2313 break;
2314
2315 case AFD_EVENT_OOB_RECEIVE:
2316 if (0 != (Socket->SharedData.AsyncEvents & FD_OOB) &&
2317 0 == (Socket->SharedData.AsyncDisabledEvents & FD_OOB))
2318 {
2319 /* Make the Notifcation */
2320 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2321 Socket->SharedData.wMsg,
2322 Socket->Handle,
2323 WSAMAKESELECTREPLY(FD_OOB, 0));
2324 /* Disable this event until the next read(); */
2325 Socket->SharedData.AsyncDisabledEvents |= FD_OOB;
2326 }
2327 break;
2328
2329 case AFD_EVENT_SEND:
2330 if (0 != (Socket->SharedData.AsyncEvents & FD_WRITE) &&
2331 0 == (Socket->SharedData.AsyncDisabledEvents & FD_WRITE))
2332 {
2333 /* Make the Notifcation */
2334 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2335 Socket->SharedData.wMsg,
2336 Socket->Handle,
2337 WSAMAKESELECTREPLY(FD_WRITE, 0));
2338 /* Disable this event until the next write(); */
2339 Socket->SharedData.AsyncDisabledEvents |= FD_WRITE;
2340 }
2341 break;
2342
2343 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
2344 case AFD_EVENT_CONNECT:
2345 case AFD_EVENT_CONNECT_FAIL:
2346 if (0 != (Socket->SharedData.AsyncEvents & FD_CONNECT) &&
2347 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CONNECT))
2348 {
2349 /* Make the Notifcation */
2350 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2351 Socket->SharedData.wMsg,
2352 Socket->Handle,
2353 WSAMAKESELECTREPLY(FD_CONNECT, 0));
2354 /* Disable this event forever; */
2355 Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT;
2356 }
2357 break;
2358
2359 case AFD_EVENT_ACCEPT:
2360 if (0 != (Socket->SharedData.AsyncEvents & FD_ACCEPT) &&
2361 0 == (Socket->SharedData.AsyncDisabledEvents & FD_ACCEPT))
2362 {
2363 /* Make the Notifcation */
2364 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2365 Socket->SharedData.wMsg,
2366 Socket->Handle,
2367 WSAMAKESELECTREPLY(FD_ACCEPT, 0));
2368 /* Disable this event until the next accept(); */
2369 Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT;
2370 }
2371 break;
2372
2373 case AFD_EVENT_DISCONNECT:
2374 case AFD_EVENT_ABORT:
2375 case AFD_EVENT_CLOSE:
2376 if (0 != (Socket->SharedData.AsyncEvents & FD_CLOSE) &&
2377 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CLOSE))
2378 {
2379 /* Make the Notifcation */
2380 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd,
2381 Socket->SharedData.wMsg,
2382 Socket->Handle,
2383 WSAMAKESELECTREPLY(FD_CLOSE, 0));
2384 /* Disable this event forever; */
2385 Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE;
2386 }
2387 break;
2388 /* FIXME: Support QOS */
2389 }
2390 }
2391
2392 /* Check if there are any events left for us to check */
2393 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 )
2394 {
2395 return;
2396 }
2397
2398 /* Keep Polling */
2399 SockProcessAsyncSelect(Socket, AsyncData);
2400 return;
2401 }
2402
2403 VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData)
2404 {
2405
2406 ULONG lNetworkEvents;
2407 NTSTATUS Status;
2408
2409 /* Set up the Async Data Event Info */
2410 AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF;
2411 AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF;
2412 AsyncData->AsyncSelectInfo.HandleCount = 1;
2413 AsyncData->AsyncSelectInfo.Exclusive = TRUE;
2414 AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle;
2415 AsyncData->AsyncSelectInfo.Handles[0].Events = 0;
2416
2417 /* Remove unwanted events */
2418 lNetworkEvents = Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents);
2419
2420 /* Set Events to wait for */
2421 if (lNetworkEvents & FD_READ)
2422 {
2423 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE;
2424 }
2425
2426 if (lNetworkEvents & FD_WRITE)
2427 {
2428 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND;
2429 }
2430
2431 if (lNetworkEvents & FD_OOB)
2432 {
2433 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE;
2434 }
2435
2436 if (lNetworkEvents & FD_ACCEPT)
2437 {
2438 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT;
2439 }
2440
2441 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
2442 if (lNetworkEvents & FD_CONNECT)
2443 {
2444 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
2445 }
2446
2447 if (lNetworkEvents & FD_CLOSE)
2448 {
2449 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE;
2450 }
2451
2452 if (lNetworkEvents & FD_QOS)
2453 {
2454 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS;
2455 }
2456
2457 if (lNetworkEvents & FD_GROUP_QOS)
2458 {
2459 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS;
2460 }
2461
2462 /* Send IOCTL */
2463 Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle,
2464 NULL,
2465 NULL,
2466 AsyncData,
2467 &AsyncData->IoStatusBlock,
2468 IOCTL_AFD_SELECT,
2469 &AsyncData->AsyncSelectInfo,
2470 sizeof(AsyncData->AsyncSelectInfo),
2471 &AsyncData->AsyncSelectInfo,
2472 sizeof(AsyncData->AsyncSelectInfo));
2473
2474 /* I/O Manager Won't call the completion routine, let's do it manually */
2475 if (NT_SUCCESS(Status))
2476 {
2477 return;
2478 }
2479 else
2480 {
2481 AsyncData->IoStatusBlock.Status = Status;
2482 SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock);
2483 }
2484 }
2485
2486 VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
2487 {
2488 PASYNC_DATA AsyncData = Context;
2489 BOOL FreeContext = TRUE;
2490 PSOCKET_INFORMATION Socket;
2491
2492 /* Get the Socket */
2493 Socket = AsyncData->ParentSocket;
2494
2495 /* If someone closed it, stop the function */
2496 if (Socket->SharedData.State != SocketClosed)
2497 {
2498 /* Check if the Sequence Number changed by now, in which case quit */
2499 if (AsyncData->SequenceNumber == Socket->SharedData.SequenceNumber)
2500 {
2501 /* Do the actuall select, if needed */
2502 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)))
2503 {
2504 SockProcessAsyncSelect(Socket, AsyncData);
2505 FreeContext = FALSE;
2506 }
2507 }
2508 }
2509
2510 /* Free the Context */
2511 if (FreeContext)
2512 {
2513 HeapFree(GetProcessHeap(), 0, AsyncData);
2514 }
2515
2516 return;
2517 }
2518
2519 VOID
2520 SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket,
2521 IN ULONG Event)
2522 {
2523 PASYNC_DATA AsyncData;
2524
2525 /* Make sure the event is actually disabled */
2526 if (!(Socket->SharedData.AsyncDisabledEvents & Event))
2527 {
2528 return;
2529 }
2530
2531 /* Re-enable it */
2532 Socket->SharedData.AsyncDisabledEvents &= ~Event;
2533
2534 /* Return if no more events are being polled */
2535 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 )
2536 {
2537 return;
2538 }
2539
2540 /* Wait on new events */
2541 AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA));
2542 if (!AsyncData) return;
2543
2544 /* Create the Asynch Thread if Needed */
2545 SockCreateOrReferenceAsyncThread();
2546
2547 /* Increase the sequence number to stop anything else */
2548 Socket->SharedData.SequenceNumber++;
2549
2550 /* Set up the Async Data */
2551 AsyncData->ParentSocket = Socket;
2552 AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber;
2553
2554 /* Begin Async Select by using I/O Completion */
2555 NtSetIoCompletion(SockAsyncCompletionPort,
2556 (PVOID)&SockProcessQueuedAsyncSelect,
2557 AsyncData,
2558 0,
2559 0);
2560
2561 /* All done */
2562 return;
2563 }
2564
2565 BOOL
2566 WINAPI
2567 DllMain(HANDLE hInstDll,
2568 ULONG dwReason,
2569 PVOID Reserved)
2570 {
2571
2572 switch (dwReason)
2573 {
2574 case DLL_PROCESS_ATTACH:
2575
2576 AFD_DbgPrint(MAX_TRACE, ("Loading MSAFD.DLL \n"));
2577
2578 /* Don't need thread attach notifications
2579 so disable them to improve performance */
2580 DisableThreadLibraryCalls(hInstDll);
2581
2582 /* List of DLL Helpers */
2583 InitializeListHead(&SockHelpersListHead);
2584
2585 /* Heap to use when allocating */
2586 GlobalHeap = GetProcessHeap();
2587
2588 /* Allocate Heap for 1024 Sockets, can be expanded later */
2589 Sockets = HeapAlloc(GetProcessHeap(), 0, sizeof(PSOCKET_INFORMATION) * 1024);
2590 if (!Sockets) return FALSE;
2591
2592 AFD_DbgPrint(MAX_TRACE, ("MSAFD.DLL has been loaded\n"));
2593
2594 break;
2595
2596 case DLL_THREAD_ATTACH:
2597 break;
2598
2599 case DLL_THREAD_DETACH:
2600 break;
2601
2602 case DLL_PROCESS_DETACH:
2603 break;
2604 }
2605
2606 AFD_DbgPrint(MAX_TRACE, ("DllMain of msafd.dll (leaving)\n"));
2607
2608 return TRUE;
2609 }
2610
2611 /* EOF */
2612
2613