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