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