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