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