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