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