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