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