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