[MSAFD] Implement WSPDuplicateSocket. By Peter Hater. CORE-12092
[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( cbOutBuffer < sizeof(INT) || IS_INTRESOURCE(lpvOutBuffer) )
2193 {
2194 *lpErrno = WSAEFAULT;
2195 return SOCKET_ERROR;
2196 }
2197 *lpErrno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, NULL, (PULONG)lpvOutBuffer, NULL);
2198 if (*lpErrno != NO_ERROR)
2199 return SOCKET_ERROR;
2200 else
2201 {
2202 *lpcbBytesReturned = sizeof(ULONG);
2203 return NO_ERROR;
2204 }
2205 case SIOCATMARK:
2206 if (cbOutBuffer < sizeof(BOOL) || IS_INTRESOURCE(lpvOutBuffer))
2207 {
2208 *lpErrno = WSAEFAULT;
2209 return SOCKET_ERROR;
2210 }
2211
2212 /* FIXME: Return false for now */
2213 *(BOOL*)lpvOutBuffer = FALSE;
2214
2215 *lpcbBytesReturned = sizeof(BOOL);
2216 *lpErrno = NO_ERROR;
2217 return NO_ERROR;
2218 case SIO_GET_EXTENSION_FUNCTION_POINTER:
2219 *lpErrno = WSAEINVAL;
2220 return SOCKET_ERROR;
2221
2222 case SIO_ADDRESS_LIST_QUERY:
2223 if (cbOutBuffer < (sizeof(SOCKET_ADDRESS_LIST) + sizeof(Socket->SharedData->WSLocalAddress)) || IS_INTRESOURCE(lpvOutBuffer))
2224 {
2225 *lpErrno = WSAEINVAL;
2226 return SOCKET_ERROR;
2227 }
2228
2229 *lpcbBytesReturned = sizeof(SOCKET_ADDRESS_LIST) +
2230 sizeof(Socket->SharedData->WSLocalAddress);
2231
2232 ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->iAddressCount = 1;
2233 ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].iSockaddrLength = sizeof(Socket->SharedData->WSLocalAddress);
2234 ((SOCKET_ADDRESS_LIST*)lpvOutBuffer)->Address[0].lpSockaddr = &Socket->SharedData->WSLocalAddress;
2235
2236 *lpErrno = NO_ERROR;
2237 return NO_ERROR;
2238
2239 default:
2240 *lpErrno = Socket->HelperData->WSHIoctl(Socket->HelperContext,
2241 Handle,
2242 Socket->TdiAddressHandle,
2243 Socket->TdiConnectionHandle,
2244 dwIoControlCode,
2245 lpvInBuffer,
2246 cbInBuffer,
2247 lpvOutBuffer,
2248 cbOutBuffer,
2249 lpcbBytesReturned,
2250 lpOverlapped,
2251 lpCompletionRoutine,
2252 (LPBOOL)&NeedsCompletion);
2253
2254 if (*lpErrno != NO_ERROR)
2255 return SOCKET_ERROR;
2256 else
2257 return NO_ERROR;
2258 }
2259 }
2260
2261
2262 INT
2263 WSPAPI
2264 WSPGetSockOpt(IN SOCKET Handle,
2265 IN INT Level,
2266 IN INT OptionName,
2267 OUT CHAR FAR* OptionValue,
2268 IN OUT LPINT OptionLength,
2269 OUT LPINT lpErrno)
2270 {
2271 PSOCKET_INFORMATION Socket = NULL;
2272 PVOID Buffer;
2273 INT BufferSize;
2274 BOOL BoolBuffer;
2275 INT IntBuffer;
2276
2277 /* Get the Socket Structure associate to this Socket*/
2278 Socket = GetSocketStructure(Handle);
2279 if (Socket == NULL)
2280 {
2281 *lpErrno = WSAENOTSOCK;
2282 return SOCKET_ERROR;
2283 }
2284
2285 TRACE("Called\n");
2286
2287 switch (Level)
2288 {
2289 case SOL_SOCKET:
2290 switch (OptionName)
2291 {
2292 case SO_TYPE:
2293 Buffer = &Socket->SharedData->SocketType;
2294 BufferSize = sizeof(INT);
2295 break;
2296
2297 case SO_RCVBUF:
2298 Buffer = &Socket->SharedData->SizeOfRecvBuffer;
2299 BufferSize = sizeof(INT);
2300 break;
2301
2302 case SO_SNDBUF:
2303 Buffer = &Socket->SharedData->SizeOfSendBuffer;
2304 BufferSize = sizeof(INT);
2305 break;
2306
2307 case SO_ACCEPTCONN:
2308 BoolBuffer = Socket->SharedData->Listening;
2309 Buffer = &BoolBuffer;
2310 BufferSize = sizeof(BOOL);
2311 break;
2312
2313 case SO_BROADCAST:
2314 BoolBuffer = Socket->SharedData->Broadcast;
2315 Buffer = &BoolBuffer;
2316 BufferSize = sizeof(BOOL);
2317 break;
2318
2319 case SO_DEBUG:
2320 BoolBuffer = Socket->SharedData->Debug;
2321 Buffer = &BoolBuffer;
2322 BufferSize = sizeof(BOOL);
2323 break;
2324
2325 case SO_DONTLINGER:
2326 BoolBuffer = (Socket->SharedData->LingerData.l_onoff == 0);
2327 Buffer = &BoolBuffer;
2328 BufferSize = sizeof(BOOL);
2329 break;
2330
2331 case SO_LINGER:
2332 if (Socket->SharedData->SocketType == SOCK_DGRAM)
2333 {
2334 *lpErrno = WSAENOPROTOOPT;
2335 return SOCKET_ERROR;
2336 }
2337 Buffer = &Socket->SharedData->LingerData;
2338 BufferSize = sizeof(struct linger);
2339 break;
2340
2341 case SO_OOBINLINE:
2342 BoolBuffer = (Socket->SharedData->OobInline != 0);
2343 Buffer = &BoolBuffer;
2344 BufferSize = sizeof(BOOL);
2345 break;
2346
2347 case SO_KEEPALIVE:
2348 case SO_DONTROUTE:
2349 /* These guys go directly to the helper */
2350 goto SendToHelper;
2351
2352 case SO_CONDITIONAL_ACCEPT:
2353 BoolBuffer = (Socket->SharedData->UseDelayedAcceptance != 0);
2354 Buffer = &BoolBuffer;
2355 BufferSize = sizeof(BOOL);
2356 break;
2357
2358 case SO_REUSEADDR:
2359 BoolBuffer = (Socket->SharedData->ReuseAddresses != 0);
2360 Buffer = &BoolBuffer;
2361 BufferSize = sizeof(BOOL);
2362 break;
2363
2364 case SO_EXCLUSIVEADDRUSE:
2365 BoolBuffer = (Socket->SharedData->ExclusiveAddressUse != 0);
2366 Buffer = &BoolBuffer;
2367 BufferSize = sizeof(BOOL);
2368 break;
2369
2370 case SO_ERROR:
2371 /* HACK: This needs to be properly tracked */
2372 IntBuffer = 0;
2373 DbgPrint("MSAFD: Hacked SO_ERROR returning error %d\n", IntBuffer);
2374
2375 Buffer = &IntBuffer;
2376 BufferSize = sizeof(INT);
2377 break;
2378 case SO_SNDTIMEO:
2379 Buffer = &Socket->SharedData->SendTimeout;
2380 BufferSize = sizeof(DWORD);
2381 break;
2382 case SO_RCVTIMEO:
2383 Buffer = &Socket->SharedData->RecvTimeout;
2384 BufferSize = sizeof(DWORD);
2385 break;
2386 case SO_PROTOCOL_INFOW:
2387 Buffer = &Socket->ProtocolInfo;
2388 BufferSize = sizeof(Socket->ProtocolInfo);
2389 break;
2390
2391 case SO_GROUP_ID:
2392 case SO_GROUP_PRIORITY:
2393 case SO_MAX_MSG_SIZE:
2394
2395 default:
2396 DbgPrint("MSAFD: Get unknown optname %x\n", OptionName);
2397 *lpErrno = WSAENOPROTOOPT;
2398 return SOCKET_ERROR;
2399 }
2400
2401 if (*OptionLength < BufferSize)
2402 {
2403 *lpErrno = WSAEFAULT;
2404 *OptionLength = BufferSize;
2405 return SOCKET_ERROR;
2406 }
2407 RtlCopyMemory(OptionValue, Buffer, BufferSize);
2408
2409 return 0;
2410
2411 default:
2412 *lpErrno = WSAEINVAL;
2413 return SOCKET_ERROR;
2414 }
2415
2416 SendToHelper:
2417 *lpErrno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext,
2418 Handle,
2419 Socket->TdiAddressHandle,
2420 Socket->TdiConnectionHandle,
2421 Level,
2422 OptionName,
2423 OptionValue,
2424 (LPINT)OptionLength);
2425 return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
2426 }
2427
2428 INT
2429 WSPAPI
2430 WSPSetSockOpt(
2431 IN SOCKET s,
2432 IN INT level,
2433 IN INT optname,
2434 IN CONST CHAR FAR* optval,
2435 IN INT optlen,
2436 OUT LPINT lpErrno)
2437 {
2438 PSOCKET_INFORMATION Socket;
2439
2440 /* Get the Socket Structure associate to this Socket*/
2441 Socket = GetSocketStructure(s);
2442 if (Socket == NULL)
2443 {
2444 *lpErrno = WSAENOTSOCK;
2445 return SOCKET_ERROR;
2446 }
2447
2448
2449 /* FIXME: We should handle some more cases here */
2450 if (level == SOL_SOCKET)
2451 {
2452 switch (optname)
2453 {
2454 case SO_BROADCAST:
2455 if (optlen < sizeof(BOOL))
2456 {
2457 *lpErrno = WSAEFAULT;
2458 return SOCKET_ERROR;
2459 }
2460 Socket->SharedData->Broadcast = (*optval != 0) ? 1 : 0;
2461 return 0;
2462
2463 case SO_DONTLINGER:
2464 if (optlen < sizeof(BOOL))
2465 {
2466 *lpErrno = WSAEFAULT;
2467 return SOCKET_ERROR;
2468 }
2469 Socket->SharedData->LingerData.l_onoff = (*optval != 0) ? 0 : 1;
2470 return 0;
2471
2472 case SO_REUSEADDR:
2473 if (optlen < sizeof(BOOL))
2474 {
2475 *lpErrno = WSAEFAULT;
2476 return SOCKET_ERROR;
2477 }
2478 Socket->SharedData->ReuseAddresses = (*optval != 0) ? 1 : 0;
2479 return 0;
2480
2481 case SO_EXCLUSIVEADDRUSE:
2482 if (optlen < sizeof(BOOL))
2483 {
2484 *lpErrno = WSAEFAULT;
2485 return SOCKET_ERROR;
2486 }
2487 Socket->SharedData->ExclusiveAddressUse = (*optval != 0) ? 1 : 0;
2488 return 0;
2489
2490 case SO_LINGER:
2491 if (optlen < sizeof(struct linger))
2492 {
2493 *lpErrno = WSAEFAULT;
2494 return SOCKET_ERROR;
2495 }
2496 RtlCopyMemory(&Socket->SharedData->LingerData,
2497 optval,
2498 sizeof(struct linger));
2499 return 0;
2500
2501 case SO_SNDBUF:
2502 if (optlen < sizeof(DWORD))
2503 {
2504 *lpErrno = WSAEFAULT;
2505 return SOCKET_ERROR;
2506 }
2507
2508 /* TODO: The total per-socket buffer space reserved for sends */
2509 ERR("Setting send buf to %x is not implemented yet\n", optval);
2510 return 0;
2511
2512 case SO_SNDTIMEO:
2513 if (optlen < sizeof(DWORD))
2514 {
2515 *lpErrno = WSAEFAULT;
2516 return SOCKET_ERROR;
2517 }
2518
2519 RtlCopyMemory(&Socket->SharedData->SendTimeout,
2520 optval,
2521 sizeof(DWORD));
2522 return 0;
2523
2524 case SO_RCVTIMEO:
2525 if (optlen < sizeof(DWORD))
2526 {
2527 *lpErrno = WSAEFAULT;
2528 return SOCKET_ERROR;
2529 }
2530
2531 RtlCopyMemory(&Socket->SharedData->RecvTimeout,
2532 optval,
2533 sizeof(DWORD));
2534 return 0;
2535
2536 case SO_KEEPALIVE:
2537 case SO_DONTROUTE:
2538 /* These go directly to the helper dll */
2539 goto SendToHelper;
2540
2541 default:
2542 /* Obviously this is a hack */
2543 ERR("MSAFD: Set unknown optname %x\n", optname);
2544 return 0;
2545 }
2546 }
2547
2548 SendToHelper:
2549 *lpErrno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext,
2550 s,
2551 Socket->TdiAddressHandle,
2552 Socket->TdiConnectionHandle,
2553 level,
2554 optname,
2555 (PCHAR)optval,
2556 optlen);
2557 return (*lpErrno == 0) ? 0 : SOCKET_ERROR;
2558 }
2559
2560 /*
2561 * FUNCTION: Initialize service provider for a client
2562 * ARGUMENTS:
2563 * wVersionRequested = Highest WinSock SPI version that the caller can use
2564 * lpWSPData = Address of WSPDATA structure to initialize
2565 * lpProtocolInfo = Pointer to structure that defines the desired protocol
2566 * UpcallTable = Pointer to upcall table of the WinSock DLL
2567 * lpProcTable = Address of procedure table to initialize
2568 * RETURNS:
2569 * Status of operation
2570 */
2571 INT
2572 WSPAPI
2573 WSPStartup(IN WORD wVersionRequested,
2574 OUT LPWSPDATA lpWSPData,
2575 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
2576 IN WSPUPCALLTABLE UpcallTable,
2577 OUT LPWSPPROC_TABLE lpProcTable)
2578
2579 {
2580 NTSTATUS Status;
2581
2582 if (((LOBYTE(wVersionRequested) == 2) && (HIBYTE(wVersionRequested) < 2)) ||
2583 (LOBYTE(wVersionRequested) < 2))
2584 {
2585 ERR("WSPStartup NOT SUPPORTED for version 0x%X\n", wVersionRequested);
2586 return WSAVERNOTSUPPORTED;
2587 }
2588 else
2589 Status = NO_ERROR;
2590 /* FIXME: Enable all cases of WSPStartup status */
2591 Upcalls = UpcallTable;
2592
2593 if (Status == NO_ERROR)
2594 {
2595 lpProcTable->lpWSPAccept = WSPAccept;
2596 lpProcTable->lpWSPAddressToString = WSPAddressToString;
2597 lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect;
2598 lpProcTable->lpWSPBind = WSPBind;
2599 lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall;
2600 lpProcTable->lpWSPCleanup = WSPCleanup;
2601 lpProcTable->lpWSPCloseSocket = WSPCloseSocket;
2602 lpProcTable->lpWSPConnect = WSPConnect;
2603 lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket;
2604 lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents;
2605 lpProcTable->lpWSPEventSelect = WSPEventSelect;
2606 lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult;
2607 lpProcTable->lpWSPGetPeerName = WSPGetPeerName;
2608 lpProcTable->lpWSPGetSockName = WSPGetSockName;
2609 lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt;
2610 lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName;
2611 lpProcTable->lpWSPIoctl = WSPIoctl;
2612 lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf;
2613 lpProcTable->lpWSPListen = WSPListen;
2614 lpProcTable->lpWSPRecv = WSPRecv;
2615 lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect;
2616 lpProcTable->lpWSPRecvFrom = WSPRecvFrom;
2617 lpProcTable->lpWSPSelect = WSPSelect;
2618 lpProcTable->lpWSPSend = WSPSend;
2619 lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect;
2620 lpProcTable->lpWSPSendTo = WSPSendTo;
2621 lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt;
2622 lpProcTable->lpWSPShutdown = WSPShutdown;
2623 lpProcTable->lpWSPSocket = WSPSocket;
2624 lpProcTable->lpWSPStringToAddress = WSPStringToAddress;
2625 lpWSPData->wVersion = MAKEWORD(2, 2);
2626 lpWSPData->wHighVersion = MAKEWORD(2, 2);
2627 /* Save CatalogEntryId for all upcalls */
2628 CatalogEntryId = lpProtocolInfo->dwCatalogEntryId;
2629 }
2630
2631 TRACE("Status (%d).\n", Status);
2632 return Status;
2633 }
2634
2635
2636 INT
2637 WSPAPI
2638 WSPAddressToString(IN LPSOCKADDR lpsaAddress,
2639 IN DWORD dwAddressLength,
2640 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
2641 OUT LPWSTR lpszAddressString,
2642 IN OUT LPDWORD lpdwAddressStringLength,
2643 OUT LPINT lpErrno)
2644 {
2645 DWORD size;
2646 WCHAR buffer[54]; /* 32 digits + 7':' + '[' + '%" + 5 digits + ']:' + 5 digits + '\0' */
2647 WCHAR *p;
2648
2649 if (!lpsaAddress || !lpszAddressString || !lpdwAddressStringLength)
2650 {
2651 *lpErrno = WSAEFAULT;
2652 return SOCKET_ERROR;
2653 }
2654
2655 switch (lpsaAddress->sa_family)
2656 {
2657 case AF_INET:
2658 if (dwAddressLength < sizeof(SOCKADDR_IN))
2659 {
2660 *lpErrno = WSAEINVAL;
2661 return SOCKET_ERROR;
2662 }
2663 swprintf(buffer,
2664 L"%u.%u.%u.%u:%u",
2665 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 24 & 0xff),
2666 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 16 & 0xff),
2667 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) >> 8 & 0xff),
2668 (unsigned int)(ntohl(((SOCKADDR_IN *)lpsaAddress)->sin_addr.s_addr) & 0xff),
2669 ntohs(((SOCKADDR_IN *)lpsaAddress)->sin_port));
2670
2671 p = wcschr(buffer, L':');
2672 if (!((SOCKADDR_IN *)lpsaAddress)->sin_port)
2673 {
2674 *p = 0;
2675 }
2676 break;
2677 default:
2678 *lpErrno = WSAEINVAL;
2679 return SOCKET_ERROR;
2680 }
2681
2682 size = wcslen(buffer) + 1;
2683
2684 if (*lpdwAddressStringLength < size)
2685 {
2686 *lpdwAddressStringLength = size;
2687 *lpErrno = WSAENOBUFS;
2688 return SOCKET_ERROR;
2689 }
2690
2691 *lpdwAddressStringLength = size;
2692 wcscpy(lpszAddressString, buffer);
2693 return 0;
2694 }
2695
2696 INT
2697 WSPAPI
2698 WSPStringToAddress(IN LPWSTR AddressString,
2699 IN INT AddressFamily,
2700 IN LPWSAPROTOCOL_INFOW lpProtocolInfo,
2701 OUT LPSOCKADDR lpAddress,
2702 IN OUT LPINT lpAddressLength,
2703 OUT LPINT lpErrno)
2704 {
2705 int pos = 0;
2706 LONG inetaddr = 0;
2707 LPWSTR *bp = NULL;
2708 SOCKADDR_IN *sockaddr;
2709
2710 if (!lpAddressLength || !lpAddress || !AddressString)
2711 {
2712 *lpErrno = WSAEINVAL;
2713 return SOCKET_ERROR;
2714 }
2715
2716 sockaddr = (SOCKADDR_IN *)lpAddress;
2717
2718 /* Set right address family */
2719 if (lpProtocolInfo != NULL)
2720 {
2721 sockaddr->sin_family = lpProtocolInfo->iAddressFamily;
2722 }
2723 else
2724 {
2725 sockaddr->sin_family = AddressFamily;
2726 }
2727
2728 /* Report size */
2729 if (AddressFamily == AF_INET)
2730 {
2731 if (*lpAddressLength < (INT)sizeof(SOCKADDR_IN))
2732 {
2733 *lpAddressLength = sizeof(SOCKADDR_IN);
2734 *lpErrno = WSAEFAULT;
2735 }
2736 else
2737 {
2738 // translate ip string to ip
2739
2740 /* rest sockaddr.sin_addr.s_addr
2741 for we need to be sure it is zero when we come to while */
2742 memset(lpAddress, 0, sizeof(SOCKADDR_IN));
2743
2744 /* Set right adress family */
2745 sockaddr->sin_family = AF_INET;
2746
2747 /* Get port number */
2748 pos = wcscspn(AddressString, L":") + 1;
2749
2750 if (pos < (int)wcslen(AddressString))
2751 {
2752 sockaddr->sin_port = wcstol(&AddressString[pos], bp, 10);
2753 }
2754 else
2755 {
2756 sockaddr->sin_port = 0;
2757 }
2758
2759 /* Get ip number */
2760 pos = 0;
2761 inetaddr = 0;
2762
2763 while (pos < (int)wcslen(AddressString))
2764 {
2765 inetaddr = (inetaddr << 8) +
2766 ((UCHAR)wcstol(&AddressString[pos], bp, 10));
2767
2768 pos += wcscspn(&AddressString[pos], L".") + 1;
2769 }
2770
2771 *lpErrno = 0;
2772 sockaddr->sin_addr.s_addr = inetaddr;
2773
2774 }
2775 }
2776
2777 if (!*lpErrno)
2778 {
2779 return 0;
2780 }
2781
2782 return SOCKET_ERROR;
2783 }
2784
2785 /*
2786 * FUNCTION: Cleans up service provider for a client
2787 * ARGUMENTS:
2788 * lpErrno = Address of buffer for error information
2789 * RETURNS:
2790 * 0 if successful, or SOCKET_ERROR if not
2791 */
2792 INT
2793 WSPAPI
2794 WSPCleanup(OUT LPINT lpErrno)
2795
2796 {
2797 TRACE("Leaving.\n");
2798 *lpErrno = NO_ERROR;
2799
2800 return 0;
2801 }
2802
2803
2804
2805 int
2806 GetSocketInformation(PSOCKET_INFORMATION Socket,
2807 ULONG AfdInformationClass,
2808 PBOOLEAN Boolean OPTIONAL,
2809 PULONG Ulong OPTIONAL,
2810 PLARGE_INTEGER LargeInteger OPTIONAL)
2811 {
2812 IO_STATUS_BLOCK IOSB;
2813 AFD_INFO InfoData;
2814 NTSTATUS Status;
2815 HANDLE SockEvent;
2816
2817 Status = NtCreateEvent(&SockEvent,
2818 EVENT_ALL_ACCESS,
2819 NULL,
2820 1,
2821 FALSE);
2822
2823 if( !NT_SUCCESS(Status) )
2824 return -1;
2825
2826 /* Set Info Class */
2827 InfoData.InformationClass = AfdInformationClass;
2828
2829 /* Send IOCTL */
2830 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2831 SockEvent,
2832 NULL,
2833 NULL,
2834 &IOSB,
2835 IOCTL_AFD_GET_INFO,
2836 &InfoData,
2837 sizeof(InfoData),
2838 &InfoData,
2839 sizeof(InfoData));
2840
2841 /* Wait for return */
2842 if (Status == STATUS_PENDING)
2843 {
2844 WaitForSingleObject(SockEvent, INFINITE);
2845 Status = IOSB.Status;
2846 }
2847
2848 if (Status != STATUS_SUCCESS)
2849 return -1;
2850
2851 /* Return Information */
2852 if (Ulong != NULL)
2853 {
2854 *Ulong = InfoData.Information.Ulong;
2855 }
2856 if (LargeInteger != NULL)
2857 {
2858 *LargeInteger = InfoData.Information.LargeInteger;
2859 }
2860 if (Boolean != NULL)
2861 {
2862 *Boolean = InfoData.Information.Boolean;
2863 }
2864
2865 NtClose( SockEvent );
2866
2867 return 0;
2868
2869 }
2870
2871
2872 int
2873 SetSocketInformation(PSOCKET_INFORMATION Socket,
2874 ULONG AfdInformationClass,
2875 PBOOLEAN Boolean OPTIONAL,
2876 PULONG Ulong OPTIONAL,
2877 PLARGE_INTEGER LargeInteger OPTIONAL)
2878 {
2879 IO_STATUS_BLOCK IOSB;
2880 AFD_INFO InfoData;
2881 NTSTATUS Status;
2882 HANDLE SockEvent;
2883
2884 Status = NtCreateEvent(&SockEvent,
2885 EVENT_ALL_ACCESS,
2886 NULL,
2887 1,
2888 FALSE);
2889
2890 if( !NT_SUCCESS(Status) )
2891 return -1;
2892
2893 /* Set Info Class */
2894 InfoData.InformationClass = AfdInformationClass;
2895
2896 /* Set Information */
2897 if (Ulong != NULL)
2898 {
2899 InfoData.Information.Ulong = *Ulong;
2900 }
2901 if (LargeInteger != NULL)
2902 {
2903 InfoData.Information.LargeInteger = *LargeInteger;
2904 }
2905 if (Boolean != NULL)
2906 {
2907 InfoData.Information.Boolean = *Boolean;
2908 }
2909
2910 /* Send IOCTL */
2911 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2912 SockEvent,
2913 NULL,
2914 NULL,
2915 &IOSB,
2916 IOCTL_AFD_SET_INFO,
2917 &InfoData,
2918 sizeof(InfoData),
2919 NULL,
2920 0);
2921
2922 /* Wait for return */
2923 if (Status == STATUS_PENDING)
2924 {
2925 WaitForSingleObject(SockEvent, INFINITE);
2926 Status = IOSB.Status;
2927 }
2928
2929 NtClose( SockEvent );
2930
2931 return Status == STATUS_SUCCESS ? 0 : -1;
2932
2933 }
2934
2935 PSOCKET_INFORMATION
2936 GetSocketStructure(SOCKET Handle)
2937 {
2938 PSOCKET_INFORMATION CurrentSocket;
2939
2940 EnterCriticalSection(&SocketListLock);
2941
2942 CurrentSocket = SocketListHead;
2943 while (CurrentSocket)
2944 {
2945 if (CurrentSocket->Handle == Handle)
2946 {
2947 LeaveCriticalSection(&SocketListLock);
2948 return CurrentSocket;
2949 }
2950
2951 CurrentSocket = CurrentSocket->NextSocket;
2952 }
2953
2954 LeaveCriticalSection(&SocketListLock);
2955
2956 return NULL;
2957 }
2958
2959 int CreateContext(PSOCKET_INFORMATION Socket)
2960 {
2961 IO_STATUS_BLOCK IOSB;
2962 SOCKET_CONTEXT ContextData;
2963 NTSTATUS Status;
2964 HANDLE SockEvent;
2965
2966 Status = NtCreateEvent(&SockEvent,
2967 EVENT_ALL_ACCESS,
2968 NULL,
2969 1,
2970 FALSE);
2971
2972 if( !NT_SUCCESS(Status) )
2973 return -1;
2974
2975 /* Create Context */
2976 ContextData.SharedData = *Socket->SharedData;
2977 ContextData.SizeOfHelperData = 0;
2978 RtlCopyMemory (&ContextData.LocalAddress,
2979 Socket->LocalAddress,
2980 Socket->SharedData->SizeOfLocalAddress);
2981 RtlCopyMemory (&ContextData.RemoteAddress,
2982 Socket->RemoteAddress,
2983 Socket->SharedData->SizeOfRemoteAddress);
2984
2985 /* Send IOCTL */
2986 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle,
2987 SockEvent,
2988 NULL,
2989 NULL,
2990 &IOSB,
2991 IOCTL_AFD_SET_CONTEXT,
2992 &ContextData,
2993 sizeof(ContextData),
2994 NULL,
2995 0);
2996
2997 /* Wait for Completition */
2998 if (Status == STATUS_PENDING)
2999 {
3000 WaitForSingleObject(SockEvent, INFINITE);
3001 Status = IOSB.Status;
3002 }
3003
3004 NtClose( SockEvent );
3005
3006 return Status == STATUS_SUCCESS ? 0 : -1;
3007 }
3008
3009 BOOLEAN SockCreateOrReferenceAsyncThread(VOID)
3010 {
3011 HANDLE hAsyncThread;
3012 DWORD AsyncThreadId;
3013 HANDLE AsyncEvent;
3014 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
3015 NTSTATUS Status;
3016
3017 /* Check if the Thread Already Exists */
3018 if (SockAsyncThreadRefCount)
3019 {
3020 ASSERT(SockAsyncCompletionPort);
3021 return TRUE;
3022 }
3023
3024 /* Create the Completion Port */
3025 if (!SockAsyncCompletionPort)
3026 {
3027 Status = NtCreateIoCompletion(&SockAsyncCompletionPort,
3028 IO_COMPLETION_ALL_ACCESS,
3029 NULL,
3030 2); // Allow 2 threads only
3031 if (!NT_SUCCESS(Status))
3032 {
3033 ERR("Failed to create completion port: 0x%08x\n", Status);
3034 return FALSE;
3035 }
3036 /* Protect Handle */
3037 HandleFlags.ProtectFromClose = TRUE;
3038 HandleFlags.Inherit = FALSE;
3039 Status = NtSetInformationObject(SockAsyncCompletionPort,
3040 ObjectHandleFlagInformation,
3041 &HandleFlags,
3042 sizeof(HandleFlags));
3043 }
3044
3045 /* Create the Async Event */
3046 Status = NtCreateEvent(&AsyncEvent,
3047 EVENT_ALL_ACCESS,
3048 NULL,
3049 NotificationEvent,
3050 FALSE);
3051
3052 /* Create the Async Thread */
3053 hAsyncThread = CreateThread(NULL,
3054 0,
3055 (LPTHREAD_START_ROUTINE)SockAsyncThread,
3056 NULL,
3057 0,
3058 &AsyncThreadId);
3059
3060 /* Close the Handle */
3061 NtClose(hAsyncThread);
3062
3063 /* Increase the Reference Count */
3064 SockAsyncThreadRefCount++;
3065 return TRUE;
3066 }
3067
3068 int SockAsyncThread(PVOID ThreadParam)
3069 {
3070 PVOID AsyncContext;
3071 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine;
3072 IO_STATUS_BLOCK IOSB;
3073 NTSTATUS Status;
3074
3075 /* Make the Thread Higher Priority */
3076 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
3077
3078 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */
3079 do
3080 {
3081 Status = NtRemoveIoCompletion (SockAsyncCompletionPort,
3082 (PVOID*)&AsyncCompletionRoutine,
3083 &AsyncContext,
3084 &IOSB,
3085 NULL);
3086 /* Call the Async Function */
3087 if (NT_SUCCESS(Status))
3088 {
3089 (*AsyncCompletionRoutine)(AsyncContext, &IOSB);
3090 }
3091 else
3092 {
3093 /* It Failed, sleep for a second */
3094 Sleep(1000);
3095 }
3096 } while ((Status != STATUS_TIMEOUT));
3097
3098 /* The Thread has Ended */
3099 return 0;
3100 }
3101
3102 BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID)
3103 {
3104 UNICODE_STRING AfdHelper;
3105 OBJECT_ATTRIBUTES ObjectAttributes;
3106 IO_STATUS_BLOCK IoSb;
3107 FILE_COMPLETION_INFORMATION CompletionInfo;
3108 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags;
3109
3110 /* First, make sure we're not already intialized */
3111 if (SockAsyncHelperAfdHandle)
3112 {
3113 return TRUE;
3114 }
3115
3116 /* Set up Handle Name and Object */
3117 RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" );
3118 InitializeObjectAttributes(&ObjectAttributes,
3119 &AfdHelper,
3120 OBJ_INHERIT | OBJ_CASE_INSENSITIVE,
3121 NULL,
3122 NULL);
3123
3124 /* Open the Handle to AFD */
3125 NtCreateFile(&SockAsyncHelperAfdHandle,
3126 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
3127 &ObjectAttributes,
3128 &IoSb,
3129 NULL,
3130 0,
3131 FILE_SHARE_READ | FILE_SHARE_WRITE,
3132 FILE_OPEN_IF,
3133 0,
3134 NULL,
3135 0);
3136
3137 /*
3138 * Now Set up the Completion Port Information
3139 * This means that whenever a Poll is finished, the routine will be executed
3140 */
3141 CompletionInfo.Port = SockAsyncCompletionPort;
3142 CompletionInfo.Key = SockAsyncSelectCompletionRoutine;
3143 NtSetInformationFile(SockAsyncHelperAfdHandle,
3144 &IoSb,
3145 &CompletionInfo,
3146 sizeof(CompletionInfo),
3147 FileCompletionInformation);
3148
3149
3150 /* Protect the Handle */
3151 HandleFlags.ProtectFromClose = TRUE;
3152 HandleFlags.Inherit = FALSE;
3153 NtSetInformationObject(SockAsyncCompletionPort,
3154 ObjectHandleFlagInformation,
3155 &HandleFlags,
3156 sizeof(HandleFlags));
3157
3158
3159 /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */
3160 SockAsyncSelectCalled = TRUE;
3161 return TRUE;
3162 }
3163
3164 VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
3165 {
3166
3167 PASYNC_DATA AsyncData = Context;
3168 PSOCKET_INFORMATION Socket;
3169 ULONG x;
3170
3171 /* Get the Socket */
3172 Socket = AsyncData->ParentSocket;
3173
3174 /* Check if the Sequence Number Changed behind our back */
3175 if (AsyncData->SequenceNumber != Socket->SharedData->SequenceNumber )
3176 {
3177 return;
3178 }
3179
3180 /* Check we were manually called b/c of a failure */
3181 if (!NT_SUCCESS(IoStatusBlock->Status))
3182 {
3183 /* FIXME: Perform Upcall */
3184 return;
3185 }
3186
3187 for (x = 1; x; x<<=1)
3188 {
3189 switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x)
3190 {
3191 case AFD_EVENT_RECEIVE:
3192 if (0 != (Socket->SharedData->AsyncEvents & FD_READ) &&
3193 0 == (Socket->SharedData->AsyncDisabledEvents & FD_READ))
3194 {
3195 /* Make the Notifcation */
3196 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3197 Socket->SharedData->wMsg,
3198 Socket->Handle,
3199 WSAMAKESELECTREPLY(FD_READ, 0));
3200 /* Disable this event until the next read(); */
3201 Socket->SharedData->AsyncDisabledEvents |= FD_READ;
3202 }
3203 break;
3204
3205 case AFD_EVENT_OOB_RECEIVE:
3206 if (0 != (Socket->SharedData->AsyncEvents & FD_OOB) &&
3207 0 == (Socket->SharedData->AsyncDisabledEvents & FD_OOB))
3208 {
3209 /* Make the Notifcation */
3210 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3211 Socket->SharedData->wMsg,
3212 Socket->Handle,
3213 WSAMAKESELECTREPLY(FD_OOB, 0));
3214 /* Disable this event until the next read(); */
3215 Socket->SharedData->AsyncDisabledEvents |= FD_OOB;
3216 }
3217 break;
3218
3219 case AFD_EVENT_SEND:
3220 if (0 != (Socket->SharedData->AsyncEvents & FD_WRITE) &&
3221 0 == (Socket->SharedData->AsyncDisabledEvents & FD_WRITE))
3222 {
3223 /* Make the Notifcation */
3224 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3225 Socket->SharedData->wMsg,
3226 Socket->Handle,
3227 WSAMAKESELECTREPLY(FD_WRITE, 0));
3228 /* Disable this event until the next write(); */
3229 Socket->SharedData->AsyncDisabledEvents |= FD_WRITE;
3230 }
3231 break;
3232
3233 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
3234 case AFD_EVENT_CONNECT:
3235 case AFD_EVENT_CONNECT_FAIL:
3236 if (0 != (Socket->SharedData->AsyncEvents & FD_CONNECT) &&
3237 0 == (Socket->SharedData->AsyncDisabledEvents & FD_CONNECT))
3238 {
3239 /* Make the Notifcation */
3240 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3241 Socket->SharedData->wMsg,
3242 Socket->Handle,
3243 WSAMAKESELECTREPLY(FD_CONNECT, 0));
3244 /* Disable this event forever; */
3245 Socket->SharedData->AsyncDisabledEvents |= FD_CONNECT;
3246 }
3247 break;
3248
3249 case AFD_EVENT_ACCEPT:
3250 if (0 != (Socket->SharedData->AsyncEvents & FD_ACCEPT) &&
3251 0 == (Socket->SharedData->AsyncDisabledEvents & FD_ACCEPT))
3252 {
3253 /* Make the Notifcation */
3254 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3255 Socket->SharedData->wMsg,
3256 Socket->Handle,
3257 WSAMAKESELECTREPLY(FD_ACCEPT, 0));
3258 /* Disable this event until the next accept(); */
3259 Socket->SharedData->AsyncDisabledEvents |= FD_ACCEPT;
3260 }
3261 break;
3262
3263 case AFD_EVENT_DISCONNECT:
3264 case AFD_EVENT_ABORT:
3265 case AFD_EVENT_CLOSE:
3266 if (0 != (Socket->SharedData->AsyncEvents & FD_CLOSE) &&
3267 0 == (Socket->SharedData->AsyncDisabledEvents & FD_CLOSE))
3268 {
3269 /* Make the Notifcation */
3270 (Upcalls.lpWPUPostMessage)(Socket->SharedData->hWnd,
3271 Socket->SharedData->wMsg,
3272 Socket->Handle,
3273 WSAMAKESELECTREPLY(FD_CLOSE, 0));
3274 /* Disable this event forever; */
3275 Socket->SharedData->AsyncDisabledEvents |= FD_CLOSE;
3276 }
3277 break;
3278 /* FIXME: Support QOS */
3279 }
3280 }
3281
3282 /* Check if there are any events left for us to check */
3283 if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0 )
3284 {
3285 return;
3286 }
3287
3288 /* Keep Polling */
3289 SockProcessAsyncSelect(Socket, AsyncData);
3290 return;
3291 }
3292
3293 VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData)
3294 {
3295
3296 ULONG lNetworkEvents;
3297 NTSTATUS Status;
3298
3299 /* Set up the Async Data Event Info */
3300 AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF;
3301 AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF;
3302 AsyncData->AsyncSelectInfo.HandleCount = 1;
3303 AsyncData->AsyncSelectInfo.Exclusive = TRUE;
3304 AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle;
3305 AsyncData->AsyncSelectInfo.Handles[0].Events = 0;
3306
3307 /* Remove unwanted events */
3308 lNetworkEvents = Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents);
3309
3310 /* Set Events to wait for */
3311 if (lNetworkEvents & FD_READ)
3312 {
3313 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE;
3314 }
3315
3316 if (lNetworkEvents & FD_WRITE)
3317 {
3318 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND;
3319 }
3320
3321 if (lNetworkEvents & FD_OOB)
3322 {
3323 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE;
3324 }
3325
3326 if (lNetworkEvents & FD_ACCEPT)
3327 {
3328 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT;
3329 }
3330
3331 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */
3332 if (lNetworkEvents & FD_CONNECT)
3333 {
3334 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL;
3335 }
3336
3337 if (lNetworkEvents & FD_CLOSE)
3338 {
3339 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE;
3340 }
3341
3342 if (lNetworkEvents & FD_QOS)
3343 {
3344 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS;
3345 }
3346
3347 if (lNetworkEvents & FD_GROUP_QOS)
3348 {
3349 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS;
3350 }
3351
3352 /* Send IOCTL */
3353 Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle,
3354 NULL,
3355 NULL,
3356 AsyncData,
3357 &AsyncData->IoStatusBlock,
3358 IOCTL_AFD_SELECT,
3359 &AsyncData->AsyncSelectInfo,
3360 sizeof(AsyncData->AsyncSelectInfo),
3361 &AsyncData->AsyncSelectInfo,
3362 sizeof(AsyncData->AsyncSelectInfo));
3363
3364 /* I/O Manager Won't call the completion routine, let's do it manually */
3365 if (NT_SUCCESS(Status))
3366 {
3367 return;
3368 }
3369 else
3370 {
3371 AsyncData->IoStatusBlock.Status = Status;
3372 SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock);
3373 }
3374 }
3375
3376 VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock)
3377 {
3378 PASYNC_DATA AsyncData = Context;
3379 BOOL FreeContext = TRUE;
3380 PSOCKET_INFORMATION Socket;
3381
3382 /* Get the Socket */
3383 Socket = AsyncData->ParentSocket;
3384
3385 /* If someone closed it, stop the function */
3386 if (Socket->SharedData->State != SocketClosed)
3387 {
3388 /* Check if the Sequence Number changed by now, in which case quit */
3389 if (AsyncData->SequenceNumber == Socket->SharedData->SequenceNumber)
3390 {
3391 /* Do the actuall select, if needed */
3392 if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)))
3393 {
3394 SockProcessAsyncSelect(Socket, AsyncData);
3395 FreeContext = FALSE;
3396 }
3397 }
3398 }
3399
3400 /* Free the Context */
3401 if (FreeContext)
3402 {
3403 HeapFree(GetProcessHeap(), 0, AsyncData);
3404 }
3405
3406 return;
3407 }
3408
3409 VOID
3410 SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket,
3411 IN ULONG Event)
3412 {
3413 PASYNC_DATA AsyncData;
3414
3415 /* Make sure the event is actually disabled */
3416 if (!(Socket->SharedData->AsyncDisabledEvents & Event))
3417 {
3418 return;
3419 }
3420
3421 /* Re-enable it */
3422 Socket->SharedData->AsyncDisabledEvents &= ~Event;
3423
3424 /* Return if no more events are being polled */
3425 if ((Socket->SharedData->AsyncEvents & (~Socket->SharedData->AsyncDisabledEvents)) == 0 )
3426 {
3427 return;
3428 }
3429
3430 /* Wait on new events */
3431 AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA));
3432 if (!AsyncData) return;
3433
3434 /* Create the Asynch Thread if Needed */
3435 SockCreateOrReferenceAsyncThread();
3436
3437 /* Increase the sequence number to stop anything else */
3438 Socket->SharedData->SequenceNumber++;
3439
3440 /* Set up the Async Data */
3441 AsyncData->ParentSocket = Socket;
3442 AsyncData->SequenceNumber = Socket->SharedData->SequenceNumber;
3443
3444 /* Begin Async Select by using I/O Completion */
3445 NtSetIoCompletion(SockAsyncCompletionPort,
3446 (PVOID)&SockProcessQueuedAsyncSelect,
3447 AsyncData,
3448 0,
3449 0);
3450
3451 /* All done */
3452 return;
3453 }
3454
3455 BOOL
3456 WINAPI
3457 DllMain(HANDLE hInstDll,
3458 ULONG dwReason,
3459 PVOID Reserved)
3460 {
3461
3462 switch (dwReason)
3463 {
3464 case DLL_PROCESS_ATTACH:
3465
3466 TRACE("Loading MSAFD.DLL \n");
3467
3468 /* Don't need thread attach notifications
3469 so disable them to improve performance */
3470 DisableThreadLibraryCalls(hInstDll);
3471
3472 /* List of DLL Helpers */
3473 InitializeListHead(&SockHelpersListHead);
3474
3475 /* Heap to use when allocating */
3476 GlobalHeap = GetProcessHeap();
3477
3478 /* Initialize the lock that protects our socket list */
3479 InitializeCriticalSection(&SocketListLock);
3480
3481 TRACE("MSAFD.DLL has been loaded\n");
3482
3483 break;
3484
3485 case DLL_THREAD_ATTACH:
3486 break;
3487
3488 case DLL_THREAD_DETACH:
3489 break;
3490
3491 case DLL_PROCESS_DETACH:
3492
3493 /* Delete the socket list lock */
3494 DeleteCriticalSection(&SocketListLock);
3495
3496 break;
3497 }
3498
3499 TRACE("DllMain of msafd.dll (leaving)\n");
3500
3501 return TRUE;
3502 }
3503
3504 /* EOF */
3505
3506