Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendllmain.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Ancillary Function Driver DLL 00004 * FILE: misc/dllmain.c 00005 * PURPOSE: DLL entry point 00006 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 00007 * Alex Ionescu (alex@relsoft.net) 00008 * REVISIONS: 00009 * CSH 01/09-2000 Created 00010 * Alex 16/07/2004 - Complete Rewrite 00011 */ 00012 00013 #include <msafd.h> 00014 00015 #if DBG 00016 //DWORD DebugTraceLevel = DEBUG_ULTRA; 00017 DWORD DebugTraceLevel = 0; 00018 #endif /* DBG */ 00019 00020 HANDLE GlobalHeap; 00021 WSPUPCALLTABLE Upcalls; 00022 LPWPUCOMPLETEOVERLAPPEDREQUEST lpWPUCompleteOverlappedRequest; 00023 PSOCKET_INFORMATION SocketListHead = NULL; 00024 CRITICAL_SECTION SocketListLock; 00025 LIST_ENTRY SockHelpersListHead = { NULL, NULL }; 00026 ULONG SockAsyncThreadRefCount; 00027 HANDLE SockAsyncHelperAfdHandle; 00028 HANDLE SockAsyncCompletionPort = NULL; 00029 BOOLEAN SockAsyncSelectCalled; 00030 00031 00032 00033 /* 00034 * FUNCTION: Creates a new socket 00035 * ARGUMENTS: 00036 * af = Address family 00037 * type = Socket type 00038 * protocol = Protocol type 00039 * lpProtocolInfo = Pointer to protocol information 00040 * g = Reserved 00041 * dwFlags = Socket flags 00042 * lpErrno = Address of buffer for error information 00043 * RETURNS: 00044 * Created socket, or INVALID_SOCKET if it could not be created 00045 */ 00046 SOCKET 00047 WSPAPI 00048 WSPSocket(int AddressFamily, 00049 int SocketType, 00050 int Protocol, 00051 LPWSAPROTOCOL_INFOW lpProtocolInfo, 00052 GROUP g, 00053 DWORD dwFlags, 00054 LPINT lpErrno) 00055 { 00056 OBJECT_ATTRIBUTES Object; 00057 IO_STATUS_BLOCK IOSB; 00058 USHORT SizeOfPacket; 00059 ULONG SizeOfEA; 00060 PAFD_CREATE_PACKET AfdPacket; 00061 HANDLE Sock; 00062 PSOCKET_INFORMATION Socket = NULL; 00063 PFILE_FULL_EA_INFORMATION EABuffer = NULL; 00064 PHELPER_DATA HelperData; 00065 PVOID HelperDLLContext; 00066 DWORD HelperEvents; 00067 UNICODE_STRING TransportName; 00068 UNICODE_STRING DevName; 00069 LARGE_INTEGER GroupData; 00070 INT Status; 00071 00072 AFD_DbgPrint(MAX_TRACE, ("Creating Socket, getting TDI Name\n")); 00073 AFD_DbgPrint(MAX_TRACE, ("AddressFamily (%d) SocketType (%d) Protocol (%d).\n", 00074 AddressFamily, SocketType, Protocol)); 00075 00076 /* Get Helper Data and Transport */ 00077 Status = SockGetTdiName (&AddressFamily, 00078 &SocketType, 00079 &Protocol, 00080 g, 00081 dwFlags, 00082 &TransportName, 00083 &HelperDLLContext, 00084 &HelperData, 00085 &HelperEvents); 00086 00087 /* Check for error */ 00088 if (Status != NO_ERROR) 00089 { 00090 AFD_DbgPrint(MID_TRACE,("SockGetTdiName: Status %x\n", Status)); 00091 goto error; 00092 } 00093 00094 /* AFD Device Name */ 00095 RtlInitUnicodeString(&DevName, L"\\Device\\Afd\\Endpoint"); 00096 00097 /* Set Socket Data */ 00098 Socket = HeapAlloc(GlobalHeap, 0, sizeof(*Socket)); 00099 if (!Socket) 00100 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); 00101 00102 RtlZeroMemory(Socket, sizeof(*Socket)); 00103 Socket->RefCount = 2; 00104 Socket->Handle = -1; 00105 Socket->SharedData.Listening = FALSE; 00106 Socket->SharedData.State = SocketOpen; 00107 Socket->SharedData.AddressFamily = AddressFamily; 00108 Socket->SharedData.SocketType = SocketType; 00109 Socket->SharedData.Protocol = Protocol; 00110 Socket->HelperContext = HelperDLLContext; 00111 Socket->HelperData = HelperData; 00112 Socket->HelperEvents = HelperEvents; 00113 Socket->LocalAddress = &Socket->WSLocalAddress; 00114 Socket->SharedData.SizeOfLocalAddress = HelperData->MaxWSAddressLength; 00115 Socket->RemoteAddress = &Socket->WSRemoteAddress; 00116 Socket->SharedData.SizeOfRemoteAddress = HelperData->MaxWSAddressLength; 00117 Socket->SharedData.UseDelayedAcceptance = HelperData->UseDelayedAcceptance; 00118 Socket->SharedData.CreateFlags = dwFlags; 00119 Socket->SharedData.CatalogEntryId = lpProtocolInfo->dwCatalogEntryId; 00120 Socket->SharedData.ServiceFlags1 = lpProtocolInfo->dwServiceFlags1; 00121 Socket->SharedData.ProviderFlags = lpProtocolInfo->dwProviderFlags; 00122 Socket->SharedData.GroupID = g; 00123 Socket->SharedData.GroupType = 0; 00124 Socket->SharedData.UseSAN = FALSE; 00125 Socket->SharedData.NonBlocking = FALSE; /* Sockets start blocking */ 00126 Socket->SanData = NULL; 00127 00128 /* Ask alex about this */ 00129 if( Socket->SharedData.SocketType == SOCK_DGRAM || 00130 Socket->SharedData.SocketType == SOCK_RAW ) 00131 { 00132 AFD_DbgPrint(MID_TRACE,("Connectionless socket\n")); 00133 Socket->SharedData.ServiceFlags1 |= XP1_CONNECTIONLESS; 00134 } 00135 00136 /* Packet Size */ 00137 SizeOfPacket = TransportName.Length + sizeof(AFD_CREATE_PACKET) + sizeof(WCHAR); 00138 00139 /* EA Size */ 00140 SizeOfEA = SizeOfPacket + sizeof(FILE_FULL_EA_INFORMATION) + AFD_PACKET_COMMAND_LENGTH; 00141 00142 /* Set up EA Buffer */ 00143 EABuffer = HeapAlloc(GlobalHeap, 0, SizeOfEA); 00144 if (!EABuffer) 00145 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); 00146 00147 RtlZeroMemory(EABuffer, SizeOfEA); 00148 EABuffer->NextEntryOffset = 0; 00149 EABuffer->Flags = 0; 00150 EABuffer->EaNameLength = AFD_PACKET_COMMAND_LENGTH; 00151 RtlCopyMemory (EABuffer->EaName, 00152 AfdCommand, 00153 AFD_PACKET_COMMAND_LENGTH + 1); 00154 EABuffer->EaValueLength = SizeOfPacket; 00155 00156 /* Set up AFD Packet */ 00157 AfdPacket = (PAFD_CREATE_PACKET)(EABuffer->EaName + EABuffer->EaNameLength + 1); 00158 AfdPacket->SizeOfTransportName = TransportName.Length; 00159 RtlCopyMemory (AfdPacket->TransportName, 00160 TransportName.Buffer, 00161 TransportName.Length + sizeof(WCHAR)); 00162 AfdPacket->GroupID = g; 00163 00164 /* Set up Endpoint Flags */ 00165 if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECTIONLESS) != 0) 00166 { 00167 if ((SocketType != SOCK_DGRAM) && (SocketType != SOCK_RAW)) 00168 { 00169 /* Only RAW or UDP can be Connectionless */ 00170 goto error; 00171 } 00172 AfdPacket->EndpointFlags |= AFD_ENDPOINT_CONNECTIONLESS; 00173 } 00174 00175 if ((Socket->SharedData.ServiceFlags1 & XP1_MESSAGE_ORIENTED) != 0) 00176 { 00177 if (SocketType == SOCK_STREAM) 00178 { 00179 if ((Socket->SharedData.ServiceFlags1 & XP1_PSEUDO_STREAM) == 0) 00180 { 00181 /* The Provider doesn't actually support Message Oriented Streams */ 00182 goto error; 00183 } 00184 } 00185 AfdPacket->EndpointFlags |= AFD_ENDPOINT_MESSAGE_ORIENTED; 00186 } 00187 00188 if (SocketType == SOCK_RAW) AfdPacket->EndpointFlags |= AFD_ENDPOINT_RAW; 00189 00190 if (dwFlags & (WSA_FLAG_MULTIPOINT_C_ROOT | 00191 WSA_FLAG_MULTIPOINT_C_LEAF | 00192 WSA_FLAG_MULTIPOINT_D_ROOT | 00193 WSA_FLAG_MULTIPOINT_D_LEAF)) 00194 { 00195 if ((Socket->SharedData.ServiceFlags1 & XP1_SUPPORT_MULTIPOINT) == 0) 00196 { 00197 /* The Provider doesn't actually support Multipoint */ 00198 goto error; 00199 } 00200 AfdPacket->EndpointFlags |= AFD_ENDPOINT_MULTIPOINT; 00201 00202 if (dwFlags & WSA_FLAG_MULTIPOINT_C_ROOT) 00203 { 00204 if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_CONTROL_PLANE) == 0) 00205 || ((dwFlags & WSA_FLAG_MULTIPOINT_C_LEAF) != 0)) 00206 { 00207 /* The Provider doesn't support Control Planes, or you already gave a leaf */ 00208 goto error; 00209 } 00210 AfdPacket->EndpointFlags |= AFD_ENDPOINT_C_ROOT; 00211 } 00212 00213 if (dwFlags & WSA_FLAG_MULTIPOINT_D_ROOT) 00214 { 00215 if (((Socket->SharedData.ServiceFlags1 & XP1_MULTIPOINT_DATA_PLANE) == 0) 00216 || ((dwFlags & WSA_FLAG_MULTIPOINT_D_LEAF) != 0)) 00217 { 00218 /* The Provider doesn't support Data Planes, or you already gave a leaf */ 00219 goto error; 00220 } 00221 AfdPacket->EndpointFlags |= AFD_ENDPOINT_D_ROOT; 00222 } 00223 } 00224 00225 /* Set up Object Attributes */ 00226 InitializeObjectAttributes (&Object, 00227 &DevName, 00228 OBJ_CASE_INSENSITIVE | OBJ_INHERIT, 00229 0, 00230 0); 00231 00232 /* Create the Socket as asynchronous. That means we have to block 00233 ourselves after every call to NtDeviceIoControlFile. This is 00234 because the kernel doesn't support overlapping synchronous I/O 00235 requests (made from multiple threads) at this time (Sep 2005) */ 00236 Status = NtCreateFile(&Sock, 00237 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 00238 &Object, 00239 &IOSB, 00240 NULL, 00241 0, 00242 FILE_SHARE_READ | FILE_SHARE_WRITE, 00243 FILE_OPEN_IF, 00244 0, 00245 EABuffer, 00246 SizeOfEA); 00247 00248 HeapFree(GlobalHeap, 0, EABuffer); 00249 00250 if (Status != STATUS_SUCCESS) 00251 { 00252 AFD_DbgPrint(MIN_TRACE, ("Failed to open socket\n")); 00253 00254 HeapFree(GlobalHeap, 0, Socket); 00255 00256 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL); 00257 } 00258 00259 /* Save Handle */ 00260 Socket->Handle = (SOCKET)Sock; 00261 00262 /* Save Group Info */ 00263 if (g != 0) 00264 { 00265 GetSocketInformation(Socket, AFD_INFO_GROUP_ID_TYPE, NULL, NULL, &GroupData); 00266 Socket->SharedData.GroupID = GroupData.u.LowPart; 00267 Socket->SharedData.GroupType = GroupData.u.HighPart; 00268 } 00269 00270 /* Get Window Sizes and Save them */ 00271 GetSocketInformation (Socket, 00272 AFD_INFO_SEND_WINDOW_SIZE, 00273 NULL, 00274 &Socket->SharedData.SizeOfSendBuffer, 00275 NULL); 00276 00277 GetSocketInformation (Socket, 00278 AFD_INFO_RECEIVE_WINDOW_SIZE, 00279 NULL, 00280 &Socket->SharedData.SizeOfRecvBuffer, 00281 NULL); 00282 00283 /* Save in Process Sockets List */ 00284 EnterCriticalSection(&SocketListLock); 00285 Socket->NextSocket = SocketListHead; 00286 SocketListHead = Socket; 00287 LeaveCriticalSection(&SocketListLock); 00288 00289 /* Create the Socket Context */ 00290 CreateContext(Socket); 00291 00292 /* Notify Winsock */ 00293 Upcalls.lpWPUModifyIFSHandle(1, (SOCKET)Sock, lpErrno); 00294 00295 /* Return Socket Handle */ 00296 AFD_DbgPrint(MID_TRACE,("Success %x\n", Sock)); 00297 00298 return (SOCKET)Sock; 00299 00300 error: 00301 AFD_DbgPrint(MID_TRACE,("Ending %x\n", Status)); 00302 00303 if( Socket ) 00304 HeapFree(GlobalHeap, 0, Socket); 00305 00306 if( lpErrno ) 00307 *lpErrno = Status; 00308 00309 return INVALID_SOCKET; 00310 } 00311 00312 INT 00313 TranslateNtStatusError(NTSTATUS Status) 00314 { 00315 switch (Status) 00316 { 00317 case STATUS_CANT_WAIT: 00318 return WSAEWOULDBLOCK; 00319 00320 case STATUS_TIMEOUT: 00321 return WSAETIMEDOUT; 00322 00323 case STATUS_SUCCESS: 00324 return NO_ERROR; 00325 00326 case STATUS_FILE_CLOSED: 00327 case STATUS_END_OF_FILE: 00328 return WSAESHUTDOWN; 00329 00330 case STATUS_PENDING: 00331 return WSA_IO_PENDING; 00332 00333 case STATUS_BUFFER_TOO_SMALL: 00334 case STATUS_BUFFER_OVERFLOW: 00335 DbgPrint("MSAFD: STATUS_BUFFER_TOO_SMALL/STATUS_BUFFER_OVERFLOW\n"); 00336 return WSAEMSGSIZE; 00337 00338 case STATUS_NO_MEMORY: 00339 case STATUS_INSUFFICIENT_RESOURCES: 00340 DbgPrint("MSAFD: STATUS_NO_MEMORY/STATUS_INSUFFICIENT_RESOURCES\n"); 00341 return WSAENOBUFS; 00342 00343 case STATUS_INVALID_CONNECTION: 00344 DbgPrint("MSAFD: STATUS_INVALID_CONNECTION\n"); 00345 return WSAEAFNOSUPPORT; 00346 00347 case STATUS_INVALID_ADDRESS: 00348 DbgPrint("MSAFD: STATUS_INVALID_ADDRESS\n"); 00349 return WSAEADDRNOTAVAIL; 00350 00351 case STATUS_REMOTE_NOT_LISTENING: 00352 DbgPrint("MSAFD: STATUS_REMOTE_NOT_LISTENING\n"); 00353 return WSAECONNREFUSED; 00354 00355 case STATUS_NETWORK_UNREACHABLE: 00356 DbgPrint("MSAFD: STATUS_NETWORK_UNREACHABLE\n"); 00357 return WSAENETUNREACH; 00358 00359 case STATUS_INVALID_PARAMETER: 00360 DbgPrint("MSAFD: STATUS_INVALID_PARAMETER\n"); 00361 return WSAEINVAL; 00362 00363 case STATUS_CANCELLED: 00364 DbgPrint("MSAFD: STATUS_CANCELLED\n"); 00365 return WSA_OPERATION_ABORTED; 00366 00367 case STATUS_ADDRESS_ALREADY_EXISTS: 00368 DbgPrint("MSAFD: STATUS_ADDRESS_ALREADY_EXISTS\n"); 00369 return WSAEADDRINUSE; 00370 00371 case STATUS_LOCAL_DISCONNECT: 00372 DbgPrint("MSAFD: STATUS_LOCAL_DISCONNECT\n"); 00373 return WSAECONNABORTED; 00374 00375 case STATUS_REMOTE_DISCONNECT: 00376 DbgPrint("MSAFD: STATUS_REMOTE_DISCONNECT\n"); 00377 return WSAECONNRESET; 00378 00379 default: 00380 DbgPrint("MSAFD: Unhandled NTSTATUS value: 0x%x\n", Status); 00381 return WSAENETDOWN; 00382 } 00383 } 00384 00385 /* 00386 * FUNCTION: Closes an open socket 00387 * ARGUMENTS: 00388 * s = Socket descriptor 00389 * lpErrno = Address of buffer for error information 00390 * RETURNS: 00391 * NO_ERROR, or SOCKET_ERROR if the socket could not be closed 00392 */ 00393 INT 00394 WSPAPI 00395 WSPCloseSocket(IN SOCKET Handle, 00396 OUT LPINT lpErrno) 00397 { 00398 IO_STATUS_BLOCK IoStatusBlock; 00399 PSOCKET_INFORMATION Socket = NULL, CurrentSocket; 00400 NTSTATUS Status; 00401 HANDLE SockEvent; 00402 AFD_DISCONNECT_INFO DisconnectInfo; 00403 SOCKET_STATE OldState; 00404 LONG LingerWait = -1; 00405 00406 /* Create the Wait Event */ 00407 Status = NtCreateEvent(&SockEvent, 00408 GENERIC_READ | GENERIC_WRITE, 00409 NULL, 00410 1, 00411 FALSE); 00412 00413 if(!NT_SUCCESS(Status)) 00414 return SOCKET_ERROR; 00415 00416 /* Get the Socket Structure associate to this Socket*/ 00417 Socket = GetSocketStructure(Handle); 00418 if (!Socket) 00419 { 00420 NtClose(SockEvent); 00421 *lpErrno = WSAENOTSOCK; 00422 return SOCKET_ERROR; 00423 } 00424 00425 if (Socket->HelperEvents & WSH_NOTIFY_CLOSE) 00426 { 00427 Status = Socket->HelperData->WSHNotify(Socket->HelperContext, 00428 Socket->Handle, 00429 Socket->TdiAddressHandle, 00430 Socket->TdiConnectionHandle, 00431 WSH_NOTIFY_CLOSE); 00432 00433 if (Status) 00434 { 00435 if (lpErrno) *lpErrno = Status; 00436 NtClose(SockEvent); 00437 return SOCKET_ERROR; 00438 } 00439 } 00440 00441 /* If a Close is already in Process, give up */ 00442 if (Socket->SharedData.State == SocketClosed) 00443 { 00444 NtClose(SockEvent); 00445 *lpErrno = WSAENOTSOCK; 00446 return SOCKET_ERROR; 00447 } 00448 00449 /* Set the state to close */ 00450 OldState = Socket->SharedData.State; 00451 Socket->SharedData.State = SocketClosed; 00452 00453 /* If SO_LINGER is ON and the Socket is connected, we need to disconnect */ 00454 /* FIXME: Should we do this on Datagram Sockets too? */ 00455 if ((OldState == SocketConnected) && (Socket->SharedData.LingerData.l_onoff)) 00456 { 00457 ULONG SendsInProgress; 00458 ULONG SleepWait; 00459 00460 /* We need to respect the timeout */ 00461 SleepWait = 100; 00462 LingerWait = Socket->SharedData.LingerData.l_linger * 1000; 00463 00464 /* Loop until no more sends are pending, within the timeout */ 00465 while (LingerWait) 00466 { 00467 /* Find out how many Sends are in Progress */ 00468 if (GetSocketInformation(Socket, 00469 AFD_INFO_SENDS_IN_PROGRESS, 00470 NULL, 00471 &SendsInProgress, 00472 NULL)) 00473 { 00474 /* Bail out if anything but NO_ERROR */ 00475 LingerWait = 0; 00476 break; 00477 } 00478 00479 /* Bail out if no more sends are pending */ 00480 if (!SendsInProgress) 00481 { 00482 LingerWait = -1; 00483 break; 00484 } 00485 00486 /* 00487 * We have to execute a sleep, so it's kind of like 00488 * a block. If the socket is Nonblock, we cannot 00489 * go on since asyncronous operation is expected 00490 * and we cannot offer it 00491 */ 00492 if (Socket->SharedData.NonBlocking) 00493 { 00494 NtClose(SockEvent); 00495 Socket->SharedData.State = OldState; 00496 *lpErrno = WSAEWOULDBLOCK; 00497 return SOCKET_ERROR; 00498 } 00499 00500 /* Now we can sleep, and decrement the linger wait */ 00501 /* 00502 * FIXME: It seems Windows does some funky acceleration 00503 * since the waiting seems to be longer and longer. I 00504 * don't think this improves performance so much, so we 00505 * wait a fixed time instead. 00506 */ 00507 Sleep(SleepWait); 00508 LingerWait -= SleepWait; 00509 } 00510 } 00511 00512 if (OldState == SocketConnected) 00513 { 00514 if (LingerWait <= 0) 00515 { 00516 DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(0); 00517 DisconnectInfo.DisconnectType = LingerWait < 0 ? AFD_DISCONNECT_SEND : AFD_DISCONNECT_ABORT; 00518 00519 if (((DisconnectInfo.DisconnectType & AFD_DISCONNECT_SEND) && (!Socket->SharedData.SendShutdown)) || 00520 ((DisconnectInfo.DisconnectType & AFD_DISCONNECT_ABORT) && (!Socket->SharedData.ReceiveShutdown))) 00521 { 00522 /* Send IOCTL */ 00523 Status = NtDeviceIoControlFile((HANDLE)Handle, 00524 SockEvent, 00525 NULL, 00526 NULL, 00527 &IoStatusBlock, 00528 IOCTL_AFD_DISCONNECT, 00529 &DisconnectInfo, 00530 sizeof(DisconnectInfo), 00531 NULL, 00532 0); 00533 00534 /* Wait for return */ 00535 if (Status == STATUS_PENDING) 00536 { 00537 WaitForSingleObject(SockEvent, INFINITE); 00538 Status = IoStatusBlock.Status; 00539 } 00540 } 00541 } 00542 } 00543 00544 /* Cleanup Time! */ 00545 Socket->HelperContext = NULL; 00546 Socket->SharedData.AsyncDisabledEvents = -1; 00547 NtClose(Socket->TdiAddressHandle); 00548 Socket->TdiAddressHandle = NULL; 00549 NtClose(Socket->TdiConnectionHandle); 00550 Socket->TdiConnectionHandle = NULL; 00551 00552 EnterCriticalSection(&SocketListLock); 00553 if (SocketListHead == Socket) 00554 { 00555 SocketListHead = SocketListHead->NextSocket; 00556 } 00557 else 00558 { 00559 CurrentSocket = SocketListHead; 00560 while (CurrentSocket->NextSocket) 00561 { 00562 if (CurrentSocket->NextSocket == Socket) 00563 { 00564 CurrentSocket->NextSocket = CurrentSocket->NextSocket->NextSocket; 00565 break; 00566 } 00567 00568 CurrentSocket = CurrentSocket->NextSocket; 00569 } 00570 } 00571 LeaveCriticalSection(&SocketListLock); 00572 00573 /* Close the handle */ 00574 NtClose((HANDLE)Handle); 00575 NtClose(SockEvent); 00576 00577 HeapFree(GlobalHeap, 0, Socket); 00578 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL); 00579 } 00580 00581 00582 /* 00583 * FUNCTION: Associates a local address with a socket 00584 * ARGUMENTS: 00585 * s = Socket descriptor 00586 * name = Pointer to local address 00587 * namelen = Length of name 00588 * lpErrno = Address of buffer for error information 00589 * RETURNS: 00590 * 0, or SOCKET_ERROR if the socket could not be bound 00591 */ 00592 INT 00593 WSPAPI 00594 WSPBind(SOCKET Handle, 00595 const struct sockaddr *SocketAddress, 00596 int SocketAddressLength, 00597 LPINT lpErrno) 00598 { 00599 IO_STATUS_BLOCK IOSB; 00600 PAFD_BIND_DATA BindData; 00601 PSOCKET_INFORMATION Socket = NULL; 00602 NTSTATUS Status; 00603 SOCKADDR_INFO SocketInfo; 00604 HANDLE SockEvent; 00605 00606 /* See below */ 00607 BindData = HeapAlloc(GlobalHeap, 0, 0xA + SocketAddressLength); 00608 if (!BindData) 00609 { 00610 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); 00611 } 00612 00613 Status = NtCreateEvent(&SockEvent, 00614 GENERIC_READ | GENERIC_WRITE, 00615 NULL, 00616 1, 00617 FALSE); 00618 00619 if (!NT_SUCCESS(Status)) 00620 { 00621 HeapFree(GlobalHeap, 0, BindData); 00622 return SOCKET_ERROR; 00623 } 00624 00625 /* Get the Socket Structure associate to this Socket*/ 00626 Socket = GetSocketStructure(Handle); 00627 if (!Socket) 00628 { 00629 HeapFree(GlobalHeap, 0, BindData); 00630 *lpErrno = WSAENOTSOCK; 00631 return SOCKET_ERROR; 00632 } 00633 00634 /* Set up Address in TDI Format */ 00635 BindData->Address.TAAddressCount = 1; 00636 BindData->Address.Address[0].AddressLength = SocketAddressLength - sizeof(SocketAddress->sa_family); 00637 BindData->Address.Address[0].AddressType = SocketAddress->sa_family; 00638 RtlCopyMemory (BindData->Address.Address[0].Address, 00639 SocketAddress->sa_data, 00640 SocketAddressLength - sizeof(SocketAddress->sa_family)); 00641 00642 /* Get Address Information */ 00643 Socket->HelperData->WSHGetSockaddrType ((PSOCKADDR)SocketAddress, 00644 SocketAddressLength, 00645 &SocketInfo); 00646 00647 /* Set the Share Type */ 00648 if (Socket->SharedData.ExclusiveAddressUse) 00649 { 00650 BindData->ShareType = AFD_SHARE_EXCLUSIVE; 00651 } 00652 else if (SocketInfo.EndpointInfo == SockaddrEndpointInfoWildcard) 00653 { 00654 BindData->ShareType = AFD_SHARE_WILDCARD; 00655 } 00656 else if (Socket->SharedData.ReuseAddresses) 00657 { 00658 BindData->ShareType = AFD_SHARE_REUSE; 00659 } 00660 else 00661 { 00662 BindData->ShareType = AFD_SHARE_UNIQUE; 00663 } 00664 00665 /* Send IOCTL */ 00666 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 00667 SockEvent, 00668 NULL, 00669 NULL, 00670 &IOSB, 00671 IOCTL_AFD_BIND, 00672 BindData, 00673 0xA + Socket->SharedData.SizeOfLocalAddress, /* Can't figure out a way to calculate this in C*/ 00674 BindData, 00675 0xA + Socket->SharedData.SizeOfLocalAddress); /* Can't figure out a way to calculate this C */ 00676 00677 /* Wait for return */ 00678 if (Status == STATUS_PENDING) 00679 { 00680 WaitForSingleObject(SockEvent, INFINITE); 00681 Status = IOSB.Status; 00682 } 00683 00684 NtClose( SockEvent ); 00685 HeapFree(GlobalHeap, 0, BindData); 00686 00687 if (Status != STATUS_SUCCESS) 00688 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); 00689 00690 /* Set up Socket Data */ 00691 Socket->SharedData.State = SocketBound; 00692 Socket->TdiAddressHandle = (HANDLE)IOSB.Information; 00693 00694 if (Socket->HelperEvents & WSH_NOTIFY_BIND) 00695 { 00696 Status = Socket->HelperData->WSHNotify(Socket->HelperContext, 00697 Socket->Handle, 00698 Socket->TdiAddressHandle, 00699 Socket->TdiConnectionHandle, 00700 WSH_NOTIFY_BIND); 00701 00702 if (Status) 00703 { 00704 if (lpErrno) *lpErrno = Status; 00705 return SOCKET_ERROR; 00706 } 00707 } 00708 00709 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); 00710 } 00711 00712 int 00713 WSPAPI 00714 WSPListen(SOCKET Handle, 00715 int Backlog, 00716 LPINT lpErrno) 00717 { 00718 IO_STATUS_BLOCK IOSB; 00719 AFD_LISTEN_DATA ListenData; 00720 PSOCKET_INFORMATION Socket = NULL; 00721 HANDLE SockEvent; 00722 NTSTATUS Status; 00723 00724 /* Get the Socket Structure associate to this Socket*/ 00725 Socket = GetSocketStructure(Handle); 00726 if (!Socket) 00727 { 00728 *lpErrno = WSAENOTSOCK; 00729 return SOCKET_ERROR; 00730 } 00731 00732 if (Socket->SharedData.Listening) 00733 return 0; 00734 00735 Status = NtCreateEvent(&SockEvent, 00736 GENERIC_READ | GENERIC_WRITE, 00737 NULL, 00738 1, 00739 FALSE); 00740 00741 if( !NT_SUCCESS(Status) ) 00742 return -1; 00743 00744 /* Set Up Listen Structure */ 00745 ListenData.UseSAN = FALSE; 00746 ListenData.UseDelayedAcceptance = Socket->SharedData.UseDelayedAcceptance; 00747 ListenData.Backlog = Backlog; 00748 00749 /* Send IOCTL */ 00750 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 00751 SockEvent, 00752 NULL, 00753 NULL, 00754 &IOSB, 00755 IOCTL_AFD_START_LISTEN, 00756 &ListenData, 00757 sizeof(ListenData), 00758 NULL, 00759 0); 00760 00761 /* Wait for return */ 00762 if (Status == STATUS_PENDING) 00763 { 00764 WaitForSingleObject(SockEvent, INFINITE); 00765 Status = IOSB.Status; 00766 } 00767 00768 NtClose( SockEvent ); 00769 00770 if (Status != STATUS_SUCCESS) 00771 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); 00772 00773 /* Set to Listening */ 00774 Socket->SharedData.Listening = TRUE; 00775 00776 if (Socket->HelperEvents & WSH_NOTIFY_LISTEN) 00777 { 00778 Status = Socket->HelperData->WSHNotify(Socket->HelperContext, 00779 Socket->Handle, 00780 Socket->TdiAddressHandle, 00781 Socket->TdiConnectionHandle, 00782 WSH_NOTIFY_LISTEN); 00783 00784 if (Status) 00785 { 00786 if (lpErrno) *lpErrno = Status; 00787 return SOCKET_ERROR; 00788 } 00789 } 00790 00791 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); 00792 } 00793 00794 00795 int 00796 WSPAPI 00797 WSPSelect(IN int nfds, 00798 IN OUT fd_set *readfds OPTIONAL, 00799 IN OUT fd_set *writefds OPTIONAL, 00800 IN OUT fd_set *exceptfds OPTIONAL, 00801 IN const struct timeval *timeout OPTIONAL, 00802 OUT LPINT lpErrno) 00803 { 00804 IO_STATUS_BLOCK IOSB; 00805 PAFD_POLL_INFO PollInfo; 00806 NTSTATUS Status; 00807 ULONG HandleCount; 00808 LONG OutCount = 0; 00809 ULONG PollBufferSize; 00810 PVOID PollBuffer; 00811 ULONG i, j = 0, x; 00812 HANDLE SockEvent; 00813 BOOL HandleCounted; 00814 LARGE_INTEGER Timeout; 00815 00816 /* Find out how many sockets we have, and how large the buffer needs 00817 * to be */ 00818 00819 HandleCount = ( readfds ? readfds->fd_count : 0 ) + 00820 ( writefds ? writefds->fd_count : 0 ) + 00821 ( exceptfds ? exceptfds->fd_count : 0 ); 00822 00823 if ( HandleCount == 0 ) 00824 { 00825 AFD_DbgPrint(MAX_TRACE,("HandleCount: %u. Return SOCKET_ERROR\n", 00826 HandleCount)); 00827 if (lpErrno) *lpErrno = WSAEINVAL; 00828 return SOCKET_ERROR; 00829 } 00830 00831 PollBufferSize = sizeof(*PollInfo) + ((HandleCount - 1) * sizeof(AFD_HANDLE)); 00832 00833 AFD_DbgPrint(MID_TRACE,("HandleCount: %u BufferSize: %u\n", 00834 HandleCount, PollBufferSize)); 00835 00836 /* Convert Timeout to NT Format */ 00837 if (timeout == NULL) 00838 { 00839 Timeout.u.LowPart = -1; 00840 Timeout.u.HighPart = 0x7FFFFFFF; 00841 AFD_DbgPrint(MAX_TRACE,("Infinite timeout\n")); 00842 } 00843 else 00844 { 00845 Timeout = RtlEnlargedIntegerMultiply 00846 ((timeout->tv_sec * 1000) + (timeout->tv_usec / 1000), -10000); 00847 /* Negative timeouts are illegal. Since the kernel represents an 00848 * incremental timeout as a negative number, we check for a positive 00849 * result. 00850 */ 00851 if (Timeout.QuadPart > 0) 00852 { 00853 if (lpErrno) *lpErrno = WSAEINVAL; 00854 return SOCKET_ERROR; 00855 } 00856 AFD_DbgPrint(MAX_TRACE,("Timeout: Orig %d.%06d kernel %d\n", 00857 timeout->tv_sec, timeout->tv_usec, 00858 Timeout.u.LowPart)); 00859 } 00860 00861 Status = NtCreateEvent(&SockEvent, 00862 GENERIC_READ | GENERIC_WRITE, 00863 NULL, 00864 1, 00865 FALSE); 00866 00867 if( !NT_SUCCESS(Status) ) 00868 return SOCKET_ERROR; 00869 00870 /* Allocate */ 00871 PollBuffer = HeapAlloc(GlobalHeap, 0, PollBufferSize); 00872 00873 if (!PollBuffer) 00874 { 00875 if (lpErrno) 00876 *lpErrno = WSAEFAULT; 00877 NtClose(SockEvent); 00878 return SOCKET_ERROR; 00879 } 00880 00881 PollInfo = (PAFD_POLL_INFO)PollBuffer; 00882 00883 RtlZeroMemory( PollInfo, PollBufferSize ); 00884 00885 /* Number of handles for AFD to Check */ 00886 PollInfo->Exclusive = FALSE; 00887 PollInfo->Timeout = Timeout; 00888 00889 if (readfds != NULL) { 00890 for (i = 0; i < readfds->fd_count; i++, j++) 00891 { 00892 PollInfo->Handles[j].Handle = readfds->fd_array[i]; 00893 PollInfo->Handles[j].Events = AFD_EVENT_RECEIVE | 00894 AFD_EVENT_DISCONNECT | 00895 AFD_EVENT_ABORT | 00896 AFD_EVENT_CLOSE | 00897 AFD_EVENT_ACCEPT; 00898 } 00899 } 00900 if (writefds != NULL) 00901 { 00902 for (i = 0; i < writefds->fd_count; i++, j++) 00903 { 00904 PollInfo->Handles[j].Handle = writefds->fd_array[i]; 00905 PollInfo->Handles[j].Events = AFD_EVENT_SEND | AFD_EVENT_CONNECT; 00906 } 00907 } 00908 if (exceptfds != NULL) 00909 { 00910 for (i = 0; i < exceptfds->fd_count; i++, j++) 00911 { 00912 PollInfo->Handles[j].Handle = exceptfds->fd_array[i]; 00913 PollInfo->Handles[j].Events = AFD_EVENT_OOB_RECEIVE | AFD_EVENT_CONNECT_FAIL; 00914 } 00915 } 00916 00917 PollInfo->HandleCount = j; 00918 PollBufferSize = FIELD_OFFSET(AFD_POLL_INFO, Handles) + PollInfo->HandleCount * sizeof(AFD_HANDLE); 00919 00920 /* Send IOCTL */ 00921 Status = NtDeviceIoControlFile((HANDLE)PollInfo->Handles[0].Handle, 00922 SockEvent, 00923 NULL, 00924 NULL, 00925 &IOSB, 00926 IOCTL_AFD_SELECT, 00927 PollInfo, 00928 PollBufferSize, 00929 PollInfo, 00930 PollBufferSize); 00931 00932 AFD_DbgPrint(MID_TRACE,("DeviceIoControlFile => %x\n", Status)); 00933 00934 /* Wait for Completition */ 00935 if (Status == STATUS_PENDING) 00936 { 00937 WaitForSingleObject(SockEvent, INFINITE); 00938 Status = IOSB.Status; 00939 } 00940 00941 /* Clear the Structures */ 00942 if( readfds ) 00943 FD_ZERO(readfds); 00944 if( writefds ) 00945 FD_ZERO(writefds); 00946 if( exceptfds ) 00947 FD_ZERO(exceptfds); 00948 00949 /* Loop through return structure */ 00950 HandleCount = PollInfo->HandleCount; 00951 00952 /* Return in FDSET Format */ 00953 for (i = 0; i < HandleCount; i++) 00954 { 00955 HandleCounted = FALSE; 00956 for(x = 1; x; x<<=1) 00957 { 00958 switch (PollInfo->Handles[i].Events & x) 00959 { 00960 case AFD_EVENT_RECEIVE: 00961 case AFD_EVENT_DISCONNECT: 00962 case AFD_EVENT_ABORT: 00963 case AFD_EVENT_ACCEPT: 00964 case AFD_EVENT_CLOSE: 00965 AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n", 00966 PollInfo->Handles[i].Events, 00967 PollInfo->Handles[i].Handle)); 00968 if (! HandleCounted) 00969 { 00970 OutCount++; 00971 HandleCounted = TRUE; 00972 } 00973 if( readfds ) 00974 FD_SET(PollInfo->Handles[i].Handle, readfds); 00975 break; 00976 case AFD_EVENT_SEND: 00977 case AFD_EVENT_CONNECT: 00978 AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n", 00979 PollInfo->Handles[i].Events, 00980 PollInfo->Handles[i].Handle)); 00981 if (! HandleCounted) 00982 { 00983 OutCount++; 00984 HandleCounted = TRUE; 00985 } 00986 if( writefds ) 00987 FD_SET(PollInfo->Handles[i].Handle, writefds); 00988 break; 00989 case AFD_EVENT_OOB_RECEIVE: 00990 case AFD_EVENT_CONNECT_FAIL: 00991 AFD_DbgPrint(MID_TRACE,("Event %x on handle %x\n", 00992 PollInfo->Handles[i].Events, 00993 PollInfo->Handles[i].Handle)); 00994 if (! HandleCounted) 00995 { 00996 OutCount++; 00997 HandleCounted = TRUE; 00998 } 00999 if( exceptfds ) 01000 FD_SET(PollInfo->Handles[i].Handle, exceptfds); 01001 break; 01002 } 01003 } 01004 } 01005 01006 HeapFree( GlobalHeap, 0, PollBuffer ); 01007 NtClose( SockEvent ); 01008 01009 if( lpErrno ) 01010 { 01011 switch( IOSB.Status ) 01012 { 01013 case STATUS_SUCCESS: 01014 case STATUS_TIMEOUT: 01015 *lpErrno = 0; 01016 break; 01017 default: 01018 *lpErrno = WSAEINVAL; 01019 break; 01020 } 01021 AFD_DbgPrint(MID_TRACE,("*lpErrno = %x\n", *lpErrno)); 01022 } 01023 01024 AFD_DbgPrint(MID_TRACE,("%d events\n", OutCount)); 01025 01026 return OutCount; 01027 } 01028 01029 SOCKET 01030 WSPAPI 01031 WSPAccept(SOCKET Handle, 01032 struct sockaddr *SocketAddress, 01033 int *SocketAddressLength, 01034 LPCONDITIONPROC lpfnCondition, 01035 DWORD dwCallbackData, 01036 LPINT lpErrno) 01037 { 01038 IO_STATUS_BLOCK IOSB; 01039 PAFD_RECEIVED_ACCEPT_DATA ListenReceiveData; 01040 AFD_ACCEPT_DATA AcceptData; 01041 AFD_DEFER_ACCEPT_DATA DeferData; 01042 AFD_PENDING_ACCEPT_DATA PendingAcceptData; 01043 PSOCKET_INFORMATION Socket = NULL; 01044 NTSTATUS Status; 01045 struct fd_set ReadSet; 01046 struct timeval Timeout; 01047 PVOID PendingData = NULL; 01048 ULONG PendingDataLength = 0; 01049 PVOID CalleeDataBuffer; 01050 WSABUF CallerData, CalleeID, CallerID, CalleeData; 01051 PSOCKADDR RemoteAddress = NULL; 01052 GROUP GroupID = 0; 01053 ULONG CallBack; 01054 WSAPROTOCOL_INFOW ProtocolInfo; 01055 SOCKET AcceptSocket; 01056 PSOCKET_INFORMATION AcceptSocketInfo; 01057 UCHAR ReceiveBuffer[0x1A]; 01058 HANDLE SockEvent; 01059 01060 Status = NtCreateEvent(&SockEvent, 01061 GENERIC_READ | GENERIC_WRITE, 01062 NULL, 01063 1, 01064 FALSE); 01065 01066 if( !NT_SUCCESS(Status) ) 01067 { 01068 MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 01069 return INVALID_SOCKET; 01070 } 01071 01072 /* Dynamic Structure...ugh */ 01073 ListenReceiveData = (PAFD_RECEIVED_ACCEPT_DATA)ReceiveBuffer; 01074 01075 /* Get the Socket Structure associate to this Socket*/ 01076 Socket = GetSocketStructure(Handle); 01077 if (!Socket) 01078 { 01079 NtClose(SockEvent); 01080 *lpErrno = WSAENOTSOCK; 01081 return INVALID_SOCKET; 01082 } 01083 01084 /* If this is non-blocking, make sure there's something for us to accept */ 01085 FD_ZERO(&ReadSet); 01086 FD_SET(Socket->Handle, &ReadSet); 01087 Timeout.tv_sec=0; 01088 Timeout.tv_usec=0; 01089 01090 if (WSPSelect(0, &ReadSet, NULL, NULL, &Timeout, lpErrno) == SOCKET_ERROR) 01091 { 01092 NtClose(SockEvent); 01093 return INVALID_SOCKET; 01094 } 01095 01096 if (ReadSet.fd_array[0] != Socket->Handle) 01097 { 01098 NtClose(SockEvent); 01099 *lpErrno = WSAEWOULDBLOCK; 01100 return INVALID_SOCKET; 01101 } 01102 01103 /* Send IOCTL */ 01104 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 01105 SockEvent, 01106 NULL, 01107 NULL, 01108 &IOSB, 01109 IOCTL_AFD_WAIT_FOR_LISTEN, 01110 NULL, 01111 0, 01112 ListenReceiveData, 01113 0xA + sizeof(*ListenReceiveData)); 01114 01115 /* Wait for return */ 01116 if (Status == STATUS_PENDING) 01117 { 01118 WaitForSingleObject(SockEvent, INFINITE); 01119 Status = IOSB.Status; 01120 } 01121 01122 if (!NT_SUCCESS(Status)) 01123 { 01124 NtClose( SockEvent ); 01125 MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 01126 return INVALID_SOCKET; 01127 } 01128 01129 if (lpfnCondition != NULL) 01130 { 01131 if ((Socket->SharedData.ServiceFlags1 & XP1_CONNECT_DATA) != 0) 01132 { 01133 /* Find out how much data is pending */ 01134 PendingAcceptData.SequenceNumber = ListenReceiveData->SequenceNumber; 01135 PendingAcceptData.ReturnSize = TRUE; 01136 01137 /* Send IOCTL */ 01138 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 01139 SockEvent, 01140 NULL, 01141 NULL, 01142 &IOSB, 01143 IOCTL_AFD_GET_PENDING_CONNECT_DATA, 01144 &PendingAcceptData, 01145 sizeof(PendingAcceptData), 01146 &PendingAcceptData, 01147 sizeof(PendingAcceptData)); 01148 01149 /* Wait for return */ 01150 if (Status == STATUS_PENDING) 01151 { 01152 WaitForSingleObject(SockEvent, INFINITE); 01153 Status = IOSB.Status; 01154 } 01155 01156 if (!NT_SUCCESS(Status)) 01157 { 01158 NtClose( SockEvent ); 01159 MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 01160 return INVALID_SOCKET; 01161 } 01162 01163 /* How much data to allocate */ 01164 PendingDataLength = IOSB.Information; 01165 01166 if (PendingDataLength) 01167 { 01168 /* Allocate needed space */ 01169 PendingData = HeapAlloc(GlobalHeap, 0, PendingDataLength); 01170 if (!PendingData) 01171 { 01172 MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL ); 01173 return INVALID_SOCKET; 01174 } 01175 01176 /* We want the data now */ 01177 PendingAcceptData.ReturnSize = FALSE; 01178 01179 /* Send IOCTL */ 01180 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 01181 SockEvent, 01182 NULL, 01183 NULL, 01184 &IOSB, 01185 IOCTL_AFD_GET_PENDING_CONNECT_DATA, 01186 &PendingAcceptData, 01187 sizeof(PendingAcceptData), 01188 PendingData, 01189 PendingDataLength); 01190 01191 /* Wait for return */ 01192 if (Status == STATUS_PENDING) 01193 { 01194 WaitForSingleObject(SockEvent, INFINITE); 01195 Status = IOSB.Status; 01196 } 01197 01198 if (!NT_SUCCESS(Status)) 01199 { 01200 NtClose( SockEvent ); 01201 MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 01202 return INVALID_SOCKET; 01203 } 01204 } 01205 } 01206 01207 if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED) != 0) 01208 { 01209 /* I don't support this yet */ 01210 } 01211 01212 /* Build Callee ID */ 01213 CalleeID.buf = (PVOID)Socket->LocalAddress; 01214 CalleeID.len = Socket->SharedData.SizeOfLocalAddress; 01215 01216 RemoteAddress = HeapAlloc(GlobalHeap, 0, sizeof(*RemoteAddress)); 01217 if (!RemoteAddress) 01218 { 01219 MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); 01220 return INVALID_SOCKET; 01221 } 01222 01223 /* Set up Address in SOCKADDR Format */ 01224 RtlCopyMemory (RemoteAddress, 01225 &ListenReceiveData->Address.Address[0].AddressType, 01226 sizeof(*RemoteAddress)); 01227 01228 /* Build Caller ID */ 01229 CallerID.buf = (PVOID)RemoteAddress; 01230 CallerID.len = sizeof(*RemoteAddress); 01231 01232 /* Build Caller Data */ 01233 CallerData.buf = PendingData; 01234 CallerData.len = PendingDataLength; 01235 01236 /* Check if socket supports Conditional Accept */ 01237 if (Socket->SharedData.UseDelayedAcceptance != 0) 01238 { 01239 /* Allocate Buffer for Callee Data */ 01240 CalleeDataBuffer = HeapAlloc(GlobalHeap, 0, 4096); 01241 if (!CalleeDataBuffer) { 01242 MsafdReturnWithErrno( STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL ); 01243 return INVALID_SOCKET; 01244 } 01245 CalleeData.buf = CalleeDataBuffer; 01246 CalleeData.len = 4096; 01247 } 01248 else 01249 { 01250 /* Nothing */ 01251 CalleeData.buf = 0; 01252 CalleeData.len = 0; 01253 } 01254 01255 /* Call the Condition Function */ 01256 CallBack = (lpfnCondition)(&CallerID, 01257 CallerData.buf == NULL ? NULL : &CallerData, 01258 NULL, 01259 NULL, 01260 &CalleeID, 01261 CalleeData.buf == NULL ? NULL : &CalleeData, 01262 &GroupID, 01263 dwCallbackData); 01264 01265 if (((CallBack == CF_ACCEPT) && GroupID) != 0) 01266 { 01267 /* TBD: Check for Validity */ 01268 } 01269 01270 if (CallBack == CF_ACCEPT) 01271 { 01272 if ((Socket->SharedData.ServiceFlags1 & XP1_QOS_SUPPORTED) != 0) 01273 { 01274 /* I don't support this yet */ 01275 } 01276 if (CalleeData.buf) 01277 { 01278 // SockSetConnectData Sockets(SocketID), IOCTL_AFD_SET_CONNECT_DATA, CalleeData.Buffer, CalleeData.BuffSize, 0 01279 } 01280 } 01281 else 01282 { 01283 /* Callback rejected. Build Defer Structure */ 01284 DeferData.SequenceNumber = ListenReceiveData->SequenceNumber; 01285 DeferData.RejectConnection = (CallBack == CF_REJECT); 01286 01287 /* Send IOCTL */ 01288 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 01289 SockEvent, 01290 NULL, 01291 NULL, 01292 &IOSB, 01293 IOCTL_AFD_DEFER_ACCEPT, 01294 &DeferData, 01295 sizeof(DeferData), 01296 NULL, 01297 0); 01298 01299 /* Wait for return */ 01300 if (Status == STATUS_PENDING) 01301 { 01302 WaitForSingleObject(SockEvent, INFINITE); 01303 Status = IOSB.Status; 01304 } 01305 01306 NtClose( SockEvent ); 01307 01308 if (!NT_SUCCESS(Status)) 01309 { 01310 MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 01311 return INVALID_SOCKET; 01312 } 01313 01314 if (CallBack == CF_REJECT ) 01315 { 01316 *lpErrno = WSAECONNREFUSED; 01317 return INVALID_SOCKET; 01318 } 01319 else 01320 { 01321 *lpErrno = WSAECONNREFUSED; 01322 return INVALID_SOCKET; 01323 } 01324 } 01325 } 01326 01327 /* Create a new Socket */ 01328 ProtocolInfo.dwCatalogEntryId = Socket->SharedData.CatalogEntryId; 01329 ProtocolInfo.dwServiceFlags1 = Socket->SharedData.ServiceFlags1; 01330 ProtocolInfo.dwProviderFlags = Socket->SharedData.ProviderFlags; 01331 01332 AcceptSocket = WSPSocket (Socket->SharedData.AddressFamily, 01333 Socket->SharedData.SocketType, 01334 Socket->SharedData.Protocol, 01335 &ProtocolInfo, 01336 GroupID, 01337 Socket->SharedData.CreateFlags, 01338 lpErrno); 01339 if (AcceptSocket == INVALID_SOCKET) 01340 return INVALID_SOCKET; 01341 01342 /* Set up the Accept Structure */ 01343 AcceptData.ListenHandle = (HANDLE)AcceptSocket; 01344 AcceptData.SequenceNumber = ListenReceiveData->SequenceNumber; 01345 01346 /* Send IOCTL to Accept */ 01347 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 01348 SockEvent, 01349 NULL, 01350 NULL, 01351 &IOSB, 01352 IOCTL_AFD_ACCEPT, 01353 &AcceptData, 01354 sizeof(AcceptData), 01355 NULL, 01356 0); 01357 01358 /* Wait for return */ 01359 if (Status == STATUS_PENDING) 01360 { 01361 WaitForSingleObject(SockEvent, INFINITE); 01362 Status = IOSB.Status; 01363 } 01364 01365 if (!NT_SUCCESS(Status)) 01366 { 01367 NtClose(SockEvent); 01368 WSPCloseSocket( AcceptSocket, lpErrno ); 01369 MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 01370 return INVALID_SOCKET; 01371 } 01372 01373 AcceptSocketInfo = GetSocketStructure(AcceptSocket); 01374 if (!AcceptSocketInfo) 01375 { 01376 NtClose(SockEvent); 01377 WSPCloseSocket( AcceptSocket, lpErrno ); 01378 MsafdReturnWithErrno( STATUS_INVALID_CONNECTION, lpErrno, 0, NULL ); 01379 return INVALID_SOCKET; 01380 } 01381 01382 AcceptSocketInfo->SharedData.State = SocketConnected; 01383 01384 /* Return Address in SOCKADDR FORMAT */ 01385 if( SocketAddress ) 01386 { 01387 RtlCopyMemory (SocketAddress, 01388 &ListenReceiveData->Address.Address[0].AddressType, 01389 sizeof(*RemoteAddress)); 01390 if( SocketAddressLength ) 01391 *SocketAddressLength = ListenReceiveData->Address.Address[0].AddressLength; 01392 } 01393 01394 NtClose( SockEvent ); 01395 01396 /* Re-enable Async Event */ 01397 SockReenableAsyncSelectEvent(Socket, FD_ACCEPT); 01398 01399 AFD_DbgPrint(MID_TRACE,("Socket %x\n", AcceptSocket)); 01400 01401 if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_ACCEPT)) 01402 { 01403 Status = Socket->HelperData->WSHNotify(Socket->HelperContext, 01404 Socket->Handle, 01405 Socket->TdiAddressHandle, 01406 Socket->TdiConnectionHandle, 01407 WSH_NOTIFY_ACCEPT); 01408 01409 if (Status) 01410 { 01411 if (lpErrno) *lpErrno = Status; 01412 return INVALID_SOCKET; 01413 } 01414 } 01415 01416 *lpErrno = 0; 01417 01418 /* Return Socket */ 01419 return AcceptSocket; 01420 } 01421 01422 int 01423 WSPAPI 01424 WSPConnect(SOCKET Handle, 01425 const struct sockaddr * SocketAddress, 01426 int SocketAddressLength, 01427 LPWSABUF lpCallerData, 01428 LPWSABUF lpCalleeData, 01429 LPQOS lpSQOS, 01430 LPQOS lpGQOS, 01431 LPINT lpErrno) 01432 { 01433 IO_STATUS_BLOCK IOSB; 01434 PAFD_CONNECT_INFO ConnectInfo = NULL; 01435 PSOCKET_INFORMATION Socket; 01436 NTSTATUS Status; 01437 INT Errno; 01438 ULONG ConnectDataLength; 01439 ULONG InConnectDataLength; 01440 INT BindAddressLength; 01441 PSOCKADDR BindAddress; 01442 HANDLE SockEvent; 01443 int SocketDataLength; 01444 01445 Status = NtCreateEvent(&SockEvent, 01446 GENERIC_READ | GENERIC_WRITE, 01447 NULL, 01448 1, 01449 FALSE); 01450 01451 if (!NT_SUCCESS(Status)) 01452 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL); 01453 01454 AFD_DbgPrint(MID_TRACE,("Called\n")); 01455 01456 /* Get the Socket Structure associate to this Socket*/ 01457 Socket = GetSocketStructure(Handle); 01458 if (!Socket) 01459 { 01460 NtClose(SockEvent); 01461 if (lpErrno) *lpErrno = WSAENOTSOCK; 01462 return SOCKET_ERROR; 01463 } 01464 01465 /* Bind us First */ 01466 if (Socket->SharedData.State == SocketOpen) 01467 { 01468 /* Get the Wildcard Address */ 01469 BindAddressLength = Socket->HelperData->MaxWSAddressLength; 01470 BindAddress = HeapAlloc(GetProcessHeap(), 0, BindAddressLength); 01471 if (!BindAddress) 01472 { 01473 NtClose(SockEvent); 01474 return MsafdReturnWithErrno(STATUS_INSUFFICIENT_RESOURCES, lpErrno, 0, NULL); 01475 } 01476 Socket->HelperData->WSHGetWildcardSockaddr (Socket->HelperContext, 01477 BindAddress, 01478 &BindAddressLength); 01479 /* Bind it */ 01480 if (WSPBind(Handle, BindAddress, BindAddressLength, lpErrno) == SOCKET_ERROR) 01481 return SOCKET_ERROR; 01482 } 01483 01484 /* Set the Connect Data */ 01485 if (lpCallerData != NULL) 01486 { 01487 ConnectDataLength = lpCallerData->len; 01488 Status = NtDeviceIoControlFile((HANDLE)Handle, 01489 SockEvent, 01490 NULL, 01491 NULL, 01492 &IOSB, 01493 IOCTL_AFD_SET_CONNECT_DATA, 01494 lpCallerData->buf, 01495 ConnectDataLength, 01496 NULL, 01497 0); 01498 /* Wait for return */ 01499 if (Status == STATUS_PENDING) 01500 { 01501 WaitForSingleObject(SockEvent, INFINITE); 01502 Status = IOSB.Status; 01503 } 01504 01505 if (Status != STATUS_SUCCESS) 01506 goto notify; 01507 } 01508 01509 /* Calculate the size of SocketAddress->sa_data */ 01510 SocketDataLength = SocketAddressLength - FIELD_OFFSET(struct sockaddr, sa_data); 01511 01512 /* Allocate a connection info buffer with SocketDataLength bytes of payload */ 01513 ConnectInfo = HeapAlloc(GetProcessHeap(), 0, 01514 FIELD_OFFSET(AFD_CONNECT_INFO, 01515 RemoteAddress.Address[0].Address[SocketDataLength])); 01516 if (!ConnectInfo) 01517 { 01518 Status = STATUS_INSUFFICIENT_RESOURCES; 01519 goto notify; 01520 } 01521 01522 /* Set up Address in TDI Format */ 01523 ConnectInfo->RemoteAddress.TAAddressCount = 1; 01524 ConnectInfo->RemoteAddress.Address[0].AddressLength = SocketDataLength; 01525 ConnectInfo->RemoteAddress.Address[0].AddressType = SocketAddress->sa_family; 01526 RtlCopyMemory(ConnectInfo->RemoteAddress.Address[0].Address, 01527 SocketAddress->sa_data, 01528 SocketDataLength); 01529 01530 /* 01531 * Disable FD_WRITE and FD_CONNECT 01532 * The latter fixes a race condition where the FD_CONNECT is re-enabled 01533 * at the end of this function right after the Async Thread disables it. 01534 * This should only happen at the *next* WSPConnect 01535 */ 01536 if (Socket->SharedData.AsyncEvents & FD_CONNECT) 01537 { 01538 Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT | FD_WRITE; 01539 } 01540 01541 /* Tell AFD that we want Connection Data back, have it allocate a buffer */ 01542 if (lpCalleeData != NULL) 01543 { 01544 InConnectDataLength = lpCalleeData->len; 01545 Status = NtDeviceIoControlFile((HANDLE)Handle, 01546 SockEvent, 01547 NULL, 01548 NULL, 01549 &IOSB, 01550 IOCTL_AFD_SET_CONNECT_DATA_SIZE, 01551 &InConnectDataLength, 01552 sizeof(InConnectDataLength), 01553 NULL, 01554 0); 01555 01556 /* Wait for return */ 01557 if (Status == STATUS_PENDING) 01558 { 01559 WaitForSingleObject(SockEvent, INFINITE); 01560 Status = IOSB.Status; 01561 } 01562 01563 if (Status != STATUS_SUCCESS) 01564 goto notify; 01565 } 01566 01567 /* AFD doesn't seem to care if these are invalid, but let's 0 them anyways */ 01568 ConnectInfo->Root = 0; 01569 ConnectInfo->UseSAN = FALSE; 01570 ConnectInfo->Unknown = 0; 01571 01572 /* FIXME: Handle Async Connect */ 01573 if (Socket->SharedData.NonBlocking) 01574 { 01575 AFD_DbgPrint(MIN_TRACE, ("Async Connect UNIMPLEMENTED!\n")); 01576 } 01577 01578 /* Send IOCTL */ 01579 Status = NtDeviceIoControlFile((HANDLE)Handle, 01580 SockEvent, 01581 NULL, 01582 NULL, 01583 &IOSB, 01584 IOCTL_AFD_CONNECT, 01585 ConnectInfo, 01586 0x22, 01587 NULL, 01588 0); 01589 /* Wait for return */ 01590 if (Status == STATUS_PENDING) 01591 { 01592 WaitForSingleObject(SockEvent, INFINITE); 01593 Status = IOSB.Status; 01594 } 01595 01596 if (Status != STATUS_SUCCESS) 01597 goto notify; 01598 01599 Socket->SharedData.State = SocketConnected; 01600 Socket->TdiConnectionHandle = (HANDLE)IOSB.Information; 01601 01602 /* Get any pending connect data */ 01603 if (lpCalleeData != NULL) 01604 { 01605 Status = NtDeviceIoControlFile((HANDLE)Handle, 01606 SockEvent, 01607 NULL, 01608 NULL, 01609 &IOSB, 01610 IOCTL_AFD_GET_CONNECT_DATA, 01611 NULL, 01612 0, 01613 lpCalleeData->buf, 01614 lpCalleeData->len); 01615 /* Wait for return */ 01616 if (Status == STATUS_PENDING) 01617 { 01618 WaitForSingleObject(SockEvent, INFINITE); 01619 Status = IOSB.Status; 01620 } 01621 } 01622 01623 AFD_DbgPrint(MID_TRACE,("Ending\n")); 01624 01625 notify: 01626 if (ConnectInfo) HeapFree(GetProcessHeap(), 0, ConnectInfo); 01627 01628 /* Re-enable Async Event */ 01629 SockReenableAsyncSelectEvent(Socket, FD_WRITE); 01630 01631 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ 01632 SockReenableAsyncSelectEvent(Socket, FD_CONNECT); 01633 01634 NtClose(SockEvent); 01635 01636 if (Status == STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT)) 01637 { 01638 Errno = Socket->HelperData->WSHNotify(Socket->HelperContext, 01639 Socket->Handle, 01640 Socket->TdiAddressHandle, 01641 Socket->TdiConnectionHandle, 01642 WSH_NOTIFY_CONNECT); 01643 01644 if (Errno) 01645 { 01646 if (lpErrno) *lpErrno = Errno; 01647 return SOCKET_ERROR; 01648 } 01649 } 01650 else if (Status != STATUS_SUCCESS && (Socket->HelperEvents & WSH_NOTIFY_CONNECT_ERROR)) 01651 { 01652 Errno = Socket->HelperData->WSHNotify(Socket->HelperContext, 01653 Socket->Handle, 01654 Socket->TdiAddressHandle, 01655 Socket->TdiConnectionHandle, 01656 WSH_NOTIFY_CONNECT_ERROR); 01657 01658 if (Errno) 01659 { 01660 if (lpErrno) *lpErrno = Errno; 01661 return SOCKET_ERROR; 01662 } 01663 } 01664 01665 return MsafdReturnWithErrno(Status, lpErrno, 0, NULL); 01666 } 01667 int 01668 WSPAPI 01669 WSPShutdown(SOCKET Handle, 01670 int HowTo, 01671 LPINT lpErrno) 01672 01673 { 01674 IO_STATUS_BLOCK IOSB; 01675 AFD_DISCONNECT_INFO DisconnectInfo; 01676 PSOCKET_INFORMATION Socket = NULL; 01677 NTSTATUS Status; 01678 HANDLE SockEvent; 01679 01680 Status = NtCreateEvent(&SockEvent, 01681 GENERIC_READ | GENERIC_WRITE, 01682 NULL, 01683 1, 01684 FALSE); 01685 01686 if( !NT_SUCCESS(Status) ) 01687 return -1; 01688 01689 AFD_DbgPrint(MID_TRACE,("Called\n")); 01690 01691 /* Get the Socket Structure associate to this Socket*/ 01692 Socket = GetSocketStructure(Handle); 01693 if (!Socket) 01694 { 01695 NtClose(SockEvent); 01696 *lpErrno = WSAENOTSOCK; 01697 return SOCKET_ERROR; 01698 } 01699 01700 /* Set AFD Disconnect Type */ 01701 switch (HowTo) 01702 { 01703 case SD_RECEIVE: 01704 DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV; 01705 Socket->SharedData.ReceiveShutdown = TRUE; 01706 break; 01707 case SD_SEND: 01708 DisconnectInfo.DisconnectType= AFD_DISCONNECT_SEND; 01709 Socket->SharedData.SendShutdown = TRUE; 01710 break; 01711 case SD_BOTH: 01712 DisconnectInfo.DisconnectType = AFD_DISCONNECT_RECV | AFD_DISCONNECT_SEND; 01713 Socket->SharedData.ReceiveShutdown = TRUE; 01714 Socket->SharedData.SendShutdown = TRUE; 01715 break; 01716 } 01717 01718 DisconnectInfo.Timeout = RtlConvertLongToLargeInteger(-1000000); 01719 01720 /* Send IOCTL */ 01721 Status = NtDeviceIoControlFile((HANDLE)Handle, 01722 SockEvent, 01723 NULL, 01724 NULL, 01725 &IOSB, 01726 IOCTL_AFD_DISCONNECT, 01727 &DisconnectInfo, 01728 sizeof(DisconnectInfo), 01729 NULL, 01730 0); 01731 01732 /* Wait for return */ 01733 if (Status == STATUS_PENDING) 01734 { 01735 WaitForSingleObject(SockEvent, INFINITE); 01736 Status = IOSB.Status; 01737 } 01738 01739 AFD_DbgPrint(MID_TRACE,("Ending\n")); 01740 01741 NtClose( SockEvent ); 01742 01743 return MsafdReturnWithErrno( Status, lpErrno, 0, NULL ); 01744 } 01745 01746 01747 INT 01748 WSPAPI 01749 WSPGetSockName(IN SOCKET Handle, 01750 OUT LPSOCKADDR Name, 01751 IN OUT LPINT NameLength, 01752 OUT LPINT lpErrno) 01753 { 01754 IO_STATUS_BLOCK IOSB; 01755 ULONG TdiAddressSize; 01756 PTDI_ADDRESS_INFO TdiAddress; 01757 PTRANSPORT_ADDRESS SocketAddress; 01758 PSOCKET_INFORMATION Socket = NULL; 01759 NTSTATUS Status; 01760 HANDLE SockEvent; 01761 01762 Status = NtCreateEvent(&SockEvent, 01763 GENERIC_READ | GENERIC_WRITE, 01764 NULL, 01765 1, 01766 FALSE); 01767 01768 if( !NT_SUCCESS(Status) ) 01769 return SOCKET_ERROR; 01770 01771 /* Get the Socket Structure associate to this Socket*/ 01772 Socket = GetSocketStructure(Handle); 01773 if (!Socket) 01774 { 01775 NtClose(SockEvent); 01776 *lpErrno = WSAENOTSOCK; 01777 return SOCKET_ERROR; 01778 } 01779 01780 if (!Name || !NameLength) 01781 { 01782 NtClose(SockEvent); 01783 *lpErrno = WSAEFAULT; 01784 return SOCKET_ERROR; 01785 } 01786 01787 /* Allocate a buffer for the address */ 01788 TdiAddressSize = 01789 sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfLocalAddress; 01790 TdiAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize); 01791 01792 if ( TdiAddress == NULL ) 01793 { 01794 NtClose( SockEvent ); 01795 *lpErrno = WSAENOBUFS; 01796 return SOCKET_ERROR; 01797 } 01798 01799 SocketAddress = &TdiAddress->Address; 01800 01801 /* Send IOCTL */ 01802 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 01803 SockEvent, 01804 NULL, 01805 NULL, 01806 &IOSB, 01807 IOCTL_AFD_GET_SOCK_NAME, 01808 NULL, 01809 0, 01810 TdiAddress, 01811 TdiAddressSize); 01812 01813 /* Wait for return */ 01814 if (Status == STATUS_PENDING) 01815 { 01816 WaitForSingleObject(SockEvent, INFINITE); 01817 Status = IOSB.Status; 01818 } 01819 01820 NtClose( SockEvent ); 01821 01822 if (NT_SUCCESS(Status)) 01823 { 01824 if (*NameLength >= Socket->SharedData.SizeOfLocalAddress) 01825 { 01826 Name->sa_family = SocketAddress->Address[0].AddressType; 01827 RtlCopyMemory (Name->sa_data, 01828 SocketAddress->Address[0].Address, 01829 SocketAddress->Address[0].AddressLength); 01830 *NameLength = Socket->SharedData.SizeOfLocalAddress; 01831 AFD_DbgPrint (MID_TRACE, ("NameLength %d Address: %x Port %x\n", 01832 *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr, 01833 ((struct sockaddr_in *)Name)->sin_port)); 01834 HeapFree(GlobalHeap, 0, TdiAddress); 01835 return 0; 01836 } 01837 else 01838 { 01839 HeapFree(GlobalHeap, 0, TdiAddress); 01840 *lpErrno = WSAEFAULT; 01841 return SOCKET_ERROR; 01842 } 01843 } 01844 01845 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); 01846 } 01847 01848 01849 INT 01850 WSPAPI 01851 WSPGetPeerName(IN SOCKET s, 01852 OUT LPSOCKADDR Name, 01853 IN OUT LPINT NameLength, 01854 OUT LPINT lpErrno) 01855 { 01856 IO_STATUS_BLOCK IOSB; 01857 ULONG TdiAddressSize; 01858 PTRANSPORT_ADDRESS SocketAddress; 01859 PSOCKET_INFORMATION Socket = NULL; 01860 NTSTATUS Status; 01861 HANDLE SockEvent; 01862 01863 Status = NtCreateEvent(&SockEvent, 01864 GENERIC_READ | GENERIC_WRITE, 01865 NULL, 01866 1, 01867 FALSE); 01868 01869 if( !NT_SUCCESS(Status) ) 01870 return SOCKET_ERROR; 01871 01872 /* Get the Socket Structure associate to this Socket*/ 01873 Socket = GetSocketStructure(s); 01874 if (!Socket) 01875 { 01876 NtClose(SockEvent); 01877 *lpErrno = WSAENOTSOCK; 01878 return SOCKET_ERROR; 01879 } 01880 01881 if (Socket->SharedData.State != SocketConnected) 01882 { 01883 NtClose(SockEvent); 01884 *lpErrno = WSAENOTCONN; 01885 return SOCKET_ERROR; 01886 } 01887 01888 if (!Name || !NameLength) 01889 { 01890 NtClose(SockEvent); 01891 *lpErrno = WSAEFAULT; 01892 return SOCKET_ERROR; 01893 } 01894 01895 /* Allocate a buffer for the address */ 01896 TdiAddressSize = sizeof(TRANSPORT_ADDRESS) + Socket->SharedData.SizeOfRemoteAddress; 01897 SocketAddress = HeapAlloc(GlobalHeap, 0, TdiAddressSize); 01898 01899 if ( SocketAddress == NULL ) 01900 { 01901 NtClose( SockEvent ); 01902 *lpErrno = WSAENOBUFS; 01903 return SOCKET_ERROR; 01904 } 01905 01906 /* Send IOCTL */ 01907 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 01908 SockEvent, 01909 NULL, 01910 NULL, 01911 &IOSB, 01912 IOCTL_AFD_GET_PEER_NAME, 01913 NULL, 01914 0, 01915 SocketAddress, 01916 TdiAddressSize); 01917 01918 /* Wait for return */ 01919 if (Status == STATUS_PENDING) 01920 { 01921 WaitForSingleObject(SockEvent, INFINITE); 01922 Status = IOSB.Status; 01923 } 01924 01925 NtClose( SockEvent ); 01926 01927 if (NT_SUCCESS(Status)) 01928 { 01929 if (*NameLength >= Socket->SharedData.SizeOfRemoteAddress) 01930 { 01931 Name->sa_family = SocketAddress->Address[0].AddressType; 01932 RtlCopyMemory (Name->sa_data, 01933 SocketAddress->Address[0].Address, 01934 SocketAddress->Address[0].AddressLength); 01935 *NameLength = Socket->SharedData.SizeOfRemoteAddress; 01936 AFD_DbgPrint (MID_TRACE, ("NameLength %d Address: %s Port %x\n", 01937 *NameLength, ((struct sockaddr_in *)Name)->sin_addr.s_addr, 01938 ((struct sockaddr_in *)Name)->sin_port)); 01939 HeapFree(GlobalHeap, 0, SocketAddress); 01940 return 0; 01941 } 01942 else 01943 { 01944 HeapFree(GlobalHeap, 0, SocketAddress); 01945 *lpErrno = WSAEFAULT; 01946 return SOCKET_ERROR; 01947 } 01948 } 01949 01950 return MsafdReturnWithErrno ( Status, lpErrno, 0, NULL ); 01951 } 01952 01953 INT 01954 WSPAPI 01955 WSPIoctl(IN SOCKET Handle, 01956 IN DWORD dwIoControlCode, 01957 IN LPVOID lpvInBuffer, 01958 IN DWORD cbInBuffer, 01959 OUT LPVOID lpvOutBuffer, 01960 IN DWORD cbOutBuffer, 01961 OUT LPDWORD lpcbBytesReturned, 01962 IN LPWSAOVERLAPPED lpOverlapped, 01963 IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine, 01964 IN LPWSATHREADID lpThreadId, 01965 OUT LPINT lpErrno) 01966 { 01967 PSOCKET_INFORMATION Socket = NULL; 01968 BOOLEAN NeedsCompletion; 01969 BOOLEAN NonBlocking; 01970 01971 /* Get the Socket Structure associate to this Socket*/ 01972 Socket = GetSocketStructure(Handle); 01973 if (!Socket) 01974 { 01975 *lpErrno = WSAENOTSOCK; 01976 return SOCKET_ERROR; 01977 } 01978 01979 *lpcbBytesReturned = 0; 01980 01981 switch( dwIoControlCode ) 01982 { 01983 case FIONBIO: 01984 if( cbInBuffer < sizeof(INT) || IS_INTRESOURCE(lpvInBuffer) ) 01985 { 01986 *lpErrno = WSAEFAULT; 01987 return SOCKET_ERROR; 01988 } 01989 NonBlocking = *((PULONG)lpvInBuffer) ? TRUE : FALSE; 01990 Socket->SharedData.NonBlocking = NonBlocking ? 1 : 0; 01991 *lpErrno = SetSocketInformation(Socket, AFD_INFO_BLOCKING_MODE, &NonBlocking, NULL, NULL); 01992 if (*lpErrno != NO_ERROR) 01993 return SOCKET_ERROR; 01994 else 01995 return NO_ERROR; 01996 case FIONREAD: 01997 if( cbOutBuffer < sizeof(INT) || IS_INTRESOURCE(lpvOutBuffer) ) 01998 { 01999 *lpErrno = WSAEFAULT; 02000 return SOCKET_ERROR; 02001 } 02002 *lpErrno = GetSocketInformation(Socket, AFD_INFO_RECEIVE_CONTENT_SIZE, NULL, (PULONG)lpvOutBuffer, NULL); 02003 if (*lpErrno != NO_ERROR) 02004 return SOCKET_ERROR; 02005 else 02006 { 02007 *lpcbBytesReturned = sizeof(ULONG); 02008 return NO_ERROR; 02009 } 02010 case SIO_GET_EXTENSION_FUNCTION_POINTER: 02011 *lpErrno = WSAEINVAL; 02012 return SOCKET_ERROR; 02013 default: 02014 *lpErrno = Socket->HelperData->WSHIoctl(Socket->HelperContext, 02015 Handle, 02016 Socket->TdiAddressHandle, 02017 Socket->TdiConnectionHandle, 02018 dwIoControlCode, 02019 lpvInBuffer, 02020 cbInBuffer, 02021 lpvOutBuffer, 02022 cbOutBuffer, 02023 lpcbBytesReturned, 02024 lpOverlapped, 02025 lpCompletionRoutine, 02026 (LPBOOL)&NeedsCompletion); 02027 02028 if (*lpErrno != NO_ERROR) 02029 return SOCKET_ERROR; 02030 else 02031 return NO_ERROR; 02032 } 02033 } 02034 02035 02036 INT 02037 WSPAPI 02038 WSPGetSockOpt(IN SOCKET Handle, 02039 IN INT Level, 02040 IN INT OptionName, 02041 OUT CHAR FAR* OptionValue, 02042 IN OUT LPINT OptionLength, 02043 OUT LPINT lpErrno) 02044 { 02045 PSOCKET_INFORMATION Socket = NULL; 02046 PVOID Buffer; 02047 INT BufferSize; 02048 BOOL BoolBuffer; 02049 02050 /* Get the Socket Structure associate to this Socket*/ 02051 Socket = GetSocketStructure(Handle); 02052 if (Socket == NULL) 02053 { 02054 *lpErrno = WSAENOTSOCK; 02055 return SOCKET_ERROR; 02056 } 02057 02058 AFD_DbgPrint(MID_TRACE, ("Called\n")); 02059 02060 switch (Level) 02061 { 02062 case SOL_SOCKET: 02063 switch (OptionName) 02064 { 02065 case SO_TYPE: 02066 Buffer = &Socket->SharedData.SocketType; 02067 BufferSize = sizeof(INT); 02068 break; 02069 02070 case SO_RCVBUF: 02071 Buffer = &Socket->SharedData.SizeOfRecvBuffer; 02072 BufferSize = sizeof(INT); 02073 break; 02074 02075 case SO_SNDBUF: 02076 Buffer = &Socket->SharedData.SizeOfSendBuffer; 02077 BufferSize = sizeof(INT); 02078 break; 02079 02080 case SO_ACCEPTCONN: 02081 BoolBuffer = Socket->SharedData.Listening; 02082 Buffer = &BoolBuffer; 02083 BufferSize = sizeof(BOOL); 02084 break; 02085 02086 case SO_BROADCAST: 02087 BoolBuffer = Socket->SharedData.Broadcast; 02088 Buffer = &BoolBuffer; 02089 BufferSize = sizeof(BOOL); 02090 break; 02091 02092 case SO_DEBUG: 02093 BoolBuffer = Socket->SharedData.Debug; 02094 Buffer = &BoolBuffer; 02095 BufferSize = sizeof(BOOL); 02096 break; 02097 02098 case SO_DONTLINGER: 02099 BoolBuffer = (Socket->SharedData.LingerData.l_onoff == 0); 02100 Buffer = &BoolBuffer; 02101 BufferSize = sizeof(BOOL); 02102 break; 02103 02104 case SO_LINGER: 02105 Buffer = &Socket->SharedData.LingerData; 02106 BufferSize = sizeof(struct linger); 02107 break; 02108 02109 /* case SO_CONDITIONAL_ACCEPT: */ 02110 case SO_DONTROUTE: 02111 case SO_ERROR: 02112 case SO_GROUP_ID: 02113 case SO_GROUP_PRIORITY: 02114 case SO_KEEPALIVE: 02115 case SO_MAX_MSG_SIZE: 02116 case SO_OOBINLINE: 02117 case SO_PROTOCOL_INFO: 02118 case SO_REUSEADDR: 02119 AFD_DbgPrint(MID_TRACE, ("Unimplemented option (%x)\n", 02120 OptionName)); 02121 02122 default: 02123 *lpErrno = WSAEINVAL; 02124 return SOCKET_ERROR; 02125 } 02126 02127 if (*OptionLength < BufferSize) 02128 { 02129 *lpErrno = WSAEFAULT; 02130 *OptionLength = BufferSize; 02131 return SOCKET_ERROR; 02132 } 02133 RtlCopyMemory(OptionValue, Buffer, BufferSize); 02134 02135 return 0; 02136 02137 case IPPROTO_TCP: /* FIXME */ 02138 default: 02139 *lpErrno = Socket->HelperData->WSHGetSocketInformation(Socket->HelperContext, 02140 Handle, 02141 Socket->TdiAddressHandle, 02142 Socket->TdiConnectionHandle, 02143 Level, 02144 OptionName, 02145 OptionValue, 02146 (LPINT)OptionLength); 02147 return (*lpErrno == 0) ? 0 : SOCKET_ERROR; 02148 } 02149 } 02150 02151 INT 02152 WSPAPI 02153 WSPSetSockOpt( 02154 IN SOCKET s, 02155 IN INT level, 02156 IN INT optname, 02157 IN CONST CHAR FAR* optval, 02158 IN INT optlen, 02159 OUT LPINT lpErrno) 02160 { 02161 PSOCKET_INFORMATION Socket; 02162 02163 /* Get the Socket Structure associate to this Socket*/ 02164 Socket = GetSocketStructure(s); 02165 if (Socket == NULL) 02166 { 02167 *lpErrno = WSAENOTSOCK; 02168 return SOCKET_ERROR; 02169 } 02170 02171 02172 /* FIXME: We should handle some more cases here */ 02173 if (level == SOL_SOCKET) 02174 { 02175 switch (optname) 02176 { 02177 case SO_BROADCAST: 02178 if (optlen < sizeof(BOOL)) 02179 { 02180 *lpErrno = WSAEFAULT; 02181 return SOCKET_ERROR; 02182 } 02183 Socket->SharedData.Broadcast = (*optval != 0) ? 1 : 0; 02184 return 0; 02185 02186 case SO_DONTLINGER: 02187 if (optlen < sizeof(BOOL)) 02188 { 02189 *lpErrno = WSAEFAULT; 02190 return SOCKET_ERROR; 02191 } 02192 Socket->SharedData.LingerData.l_onoff = (*optval != 0) ? 0 : 1; 02193 return 0; 02194 02195 case SO_LINGER: 02196 if (optlen < sizeof(struct linger)) 02197 { 02198 *lpErrno = WSAEFAULT; 02199 return SOCKET_ERROR; 02200 } 02201 RtlCopyMemory(&Socket->SharedData.LingerData, 02202 optval, 02203 sizeof(struct linger)); 02204 return 0; 02205 02206 case SO_SNDBUF: 02207 if (optlen < sizeof(DWORD)) 02208 { 02209 *lpErrno = WSAEFAULT; 02210 return SOCKET_ERROR; 02211 } 02212 02213 /* TODO: The total per-socket buffer space reserved for sends */ 02214 AFD_DbgPrint(MIN_TRACE,("Setting send buf to %x is not implemented yet\n", optval)); 02215 return 0; 02216 02217 default: 02218 AFD_DbgPrint(MIN_TRACE,("Unknown optname %x\n", optname)); 02219 break; 02220 } 02221 } 02222 02223 02224 *lpErrno = Socket->HelperData->WSHSetSocketInformation(Socket->HelperContext, 02225 s, 02226 Socket->TdiAddressHandle, 02227 Socket->TdiConnectionHandle, 02228 level, 02229 optname, 02230 (PCHAR)optval, 02231 optlen); 02232 return (*lpErrno == 0) ? 0 : SOCKET_ERROR; 02233 } 02234 02235 /* 02236 * FUNCTION: Initialize service provider for a client 02237 * ARGUMENTS: 02238 * wVersionRequested = Highest WinSock SPI version that the caller can use 02239 * lpWSPData = Address of WSPDATA structure to initialize 02240 * lpProtocolInfo = Pointer to structure that defines the desired protocol 02241 * UpcallTable = Pointer to upcall table of the WinSock DLL 02242 * lpProcTable = Address of procedure table to initialize 02243 * RETURNS: 02244 * Status of operation 02245 */ 02246 INT 02247 WSPAPI 02248 WSPStartup(IN WORD wVersionRequested, 02249 OUT LPWSPDATA lpWSPData, 02250 IN LPWSAPROTOCOL_INFOW lpProtocolInfo, 02251 IN WSPUPCALLTABLE UpcallTable, 02252 OUT LPWSPPROC_TABLE lpProcTable) 02253 02254 { 02255 NTSTATUS Status; 02256 02257 AFD_DbgPrint(MAX_TRACE, ("wVersionRequested (0x%X) \n", wVersionRequested)); 02258 Status = NO_ERROR; 02259 Upcalls = UpcallTable; 02260 02261 if (Status == NO_ERROR) 02262 { 02263 lpProcTable->lpWSPAccept = WSPAccept; 02264 lpProcTable->lpWSPAddressToString = WSPAddressToString; 02265 lpProcTable->lpWSPAsyncSelect = WSPAsyncSelect; 02266 lpProcTable->lpWSPBind = WSPBind; 02267 lpProcTable->lpWSPCancelBlockingCall = WSPCancelBlockingCall; 02268 lpProcTable->lpWSPCleanup = WSPCleanup; 02269 lpProcTable->lpWSPCloseSocket = WSPCloseSocket; 02270 lpProcTable->lpWSPConnect = WSPConnect; 02271 lpProcTable->lpWSPDuplicateSocket = WSPDuplicateSocket; 02272 lpProcTable->lpWSPEnumNetworkEvents = WSPEnumNetworkEvents; 02273 lpProcTable->lpWSPEventSelect = WSPEventSelect; 02274 lpProcTable->lpWSPGetOverlappedResult = WSPGetOverlappedResult; 02275 lpProcTable->lpWSPGetPeerName = WSPGetPeerName; 02276 lpProcTable->lpWSPGetSockName = WSPGetSockName; 02277 lpProcTable->lpWSPGetSockOpt = WSPGetSockOpt; 02278 lpProcTable->lpWSPGetQOSByName = WSPGetQOSByName; 02279 lpProcTable->lpWSPIoctl = WSPIoctl; 02280 lpProcTable->lpWSPJoinLeaf = WSPJoinLeaf; 02281 lpProcTable->lpWSPListen = WSPListen; 02282 lpProcTable->lpWSPRecv = WSPRecv; 02283 lpProcTable->lpWSPRecvDisconnect = WSPRecvDisconnect; 02284 lpProcTable->lpWSPRecvFrom = WSPRecvFrom; 02285 lpProcTable->lpWSPSelect = WSPSelect; 02286 lpProcTable->lpWSPSend = WSPSend; 02287 lpProcTable->lpWSPSendDisconnect = WSPSendDisconnect; 02288 lpProcTable->lpWSPSendTo = WSPSendTo; 02289 lpProcTable->lpWSPSetSockOpt = WSPSetSockOpt; 02290 lpProcTable->lpWSPShutdown = WSPShutdown; 02291 lpProcTable->lpWSPSocket = WSPSocket; 02292 lpProcTable->lpWSPStringToAddress = WSPStringToAddress; 02293 lpWSPData->wVersion = MAKEWORD(2, 2); 02294 lpWSPData->wHighVersion = MAKEWORD(2, 2); 02295 } 02296 02297 AFD_DbgPrint(MAX_TRACE, ("Status (%d).\n", Status)); 02298 02299 return Status; 02300 } 02301 02302 02303 /* 02304 * FUNCTION: Cleans up service provider for a client 02305 * ARGUMENTS: 02306 * lpErrno = Address of buffer for error information 02307 * RETURNS: 02308 * 0 if successful, or SOCKET_ERROR if not 02309 */ 02310 INT 02311 WSPAPI 02312 WSPCleanup(OUT LPINT lpErrno) 02313 02314 { 02315 AFD_DbgPrint(MAX_TRACE, ("\n")); 02316 AFD_DbgPrint(MAX_TRACE, ("Leaving.\n")); 02317 *lpErrno = NO_ERROR; 02318 02319 return 0; 02320 } 02321 02322 02323 02324 int 02325 GetSocketInformation(PSOCKET_INFORMATION Socket, 02326 ULONG AfdInformationClass, 02327 PBOOLEAN Boolean OPTIONAL, 02328 PULONG Ulong OPTIONAL, 02329 PLARGE_INTEGER LargeInteger OPTIONAL) 02330 { 02331 IO_STATUS_BLOCK IOSB; 02332 AFD_INFO InfoData; 02333 NTSTATUS Status; 02334 HANDLE SockEvent; 02335 02336 Status = NtCreateEvent(&SockEvent, 02337 GENERIC_READ | GENERIC_WRITE, 02338 NULL, 02339 1, 02340 FALSE); 02341 02342 if( !NT_SUCCESS(Status) ) 02343 return -1; 02344 02345 /* Set Info Class */ 02346 InfoData.InformationClass = AfdInformationClass; 02347 02348 /* Send IOCTL */ 02349 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 02350 SockEvent, 02351 NULL, 02352 NULL, 02353 &IOSB, 02354 IOCTL_AFD_GET_INFO, 02355 &InfoData, 02356 sizeof(InfoData), 02357 &InfoData, 02358 sizeof(InfoData)); 02359 02360 /* Wait for return */ 02361 if (Status == STATUS_PENDING) 02362 { 02363 WaitForSingleObject(SockEvent, INFINITE); 02364 Status = IOSB.Status; 02365 } 02366 02367 if (Status != STATUS_SUCCESS) 02368 return -1; 02369 02370 /* Return Information */ 02371 if (Ulong != NULL) 02372 { 02373 *Ulong = InfoData.Information.Ulong; 02374 } 02375 if (LargeInteger != NULL) 02376 { 02377 *LargeInteger = InfoData.Information.LargeInteger; 02378 } 02379 if (Boolean != NULL) 02380 { 02381 *Boolean = InfoData.Information.Boolean; 02382 } 02383 02384 NtClose( SockEvent ); 02385 02386 return 0; 02387 02388 } 02389 02390 02391 int 02392 SetSocketInformation(PSOCKET_INFORMATION Socket, 02393 ULONG AfdInformationClass, 02394 PBOOLEAN Boolean OPTIONAL, 02395 PULONG Ulong OPTIONAL, 02396 PLARGE_INTEGER LargeInteger OPTIONAL) 02397 { 02398 IO_STATUS_BLOCK IOSB; 02399 AFD_INFO InfoData; 02400 NTSTATUS Status; 02401 HANDLE SockEvent; 02402 02403 Status = NtCreateEvent(&SockEvent, 02404 GENERIC_READ | GENERIC_WRITE, 02405 NULL, 02406 1, 02407 FALSE); 02408 02409 if( !NT_SUCCESS(Status) ) 02410 return -1; 02411 02412 /* Set Info Class */ 02413 InfoData.InformationClass = AfdInformationClass; 02414 02415 /* Set Information */ 02416 if (Ulong != NULL) 02417 { 02418 InfoData.Information.Ulong = *Ulong; 02419 } 02420 if (LargeInteger != NULL) 02421 { 02422 InfoData.Information.LargeInteger = *LargeInteger; 02423 } 02424 if (Boolean != NULL) 02425 { 02426 InfoData.Information.Boolean = *Boolean; 02427 } 02428 02429 /* Send IOCTL */ 02430 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 02431 SockEvent, 02432 NULL, 02433 NULL, 02434 &IOSB, 02435 IOCTL_AFD_SET_INFO, 02436 &InfoData, 02437 sizeof(InfoData), 02438 NULL, 02439 0); 02440 02441 /* Wait for return */ 02442 if (Status == STATUS_PENDING) 02443 { 02444 WaitForSingleObject(SockEvent, INFINITE); 02445 Status = IOSB.Status; 02446 } 02447 02448 NtClose( SockEvent ); 02449 02450 return Status == STATUS_SUCCESS ? 0 : -1; 02451 02452 } 02453 02454 PSOCKET_INFORMATION 02455 GetSocketStructure(SOCKET Handle) 02456 { 02457 PSOCKET_INFORMATION CurrentSocket; 02458 02459 EnterCriticalSection(&SocketListLock); 02460 02461 CurrentSocket = SocketListHead; 02462 while (CurrentSocket) 02463 { 02464 if (CurrentSocket->Handle == Handle) 02465 { 02466 LeaveCriticalSection(&SocketListLock); 02467 return CurrentSocket; 02468 } 02469 02470 CurrentSocket = CurrentSocket->NextSocket; 02471 } 02472 02473 LeaveCriticalSection(&SocketListLock); 02474 02475 return NULL; 02476 } 02477 02478 int CreateContext(PSOCKET_INFORMATION Socket) 02479 { 02480 IO_STATUS_BLOCK IOSB; 02481 SOCKET_CONTEXT ContextData; 02482 NTSTATUS Status; 02483 HANDLE SockEvent; 02484 02485 Status = NtCreateEvent(&SockEvent, 02486 GENERIC_READ | GENERIC_WRITE, 02487 NULL, 02488 1, 02489 FALSE); 02490 02491 if( !NT_SUCCESS(Status) ) 02492 return -1; 02493 02494 /* Create Context */ 02495 ContextData.SharedData = Socket->SharedData; 02496 ContextData.SizeOfHelperData = 0; 02497 RtlCopyMemory (&ContextData.LocalAddress, 02498 Socket->LocalAddress, 02499 Socket->SharedData.SizeOfLocalAddress); 02500 RtlCopyMemory (&ContextData.RemoteAddress, 02501 Socket->RemoteAddress, 02502 Socket->SharedData.SizeOfRemoteAddress); 02503 02504 /* Send IOCTL */ 02505 Status = NtDeviceIoControlFile((HANDLE)Socket->Handle, 02506 SockEvent, 02507 NULL, 02508 NULL, 02509 &IOSB, 02510 IOCTL_AFD_SET_CONTEXT, 02511 &ContextData, 02512 sizeof(ContextData), 02513 NULL, 02514 0); 02515 02516 /* Wait for Completition */ 02517 if (Status == STATUS_PENDING) 02518 { 02519 WaitForSingleObject(SockEvent, INFINITE); 02520 Status = IOSB.Status; 02521 } 02522 02523 NtClose( SockEvent ); 02524 02525 return Status == STATUS_SUCCESS ? 0 : -1; 02526 } 02527 02528 BOOLEAN SockCreateOrReferenceAsyncThread(VOID) 02529 { 02530 HANDLE hAsyncThread; 02531 DWORD AsyncThreadId; 02532 HANDLE AsyncEvent; 02533 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; 02534 NTSTATUS Status; 02535 02536 /* Check if the Thread Already Exists */ 02537 if (SockAsyncThreadRefCount) 02538 { 02539 ASSERT(SockAsyncCompletionPort); 02540 return TRUE; 02541 } 02542 02543 /* Create the Completion Port */ 02544 if (!SockAsyncCompletionPort) 02545 { 02546 Status = NtCreateIoCompletion(&SockAsyncCompletionPort, 02547 IO_COMPLETION_ALL_ACCESS, 02548 NULL, 02549 2); // Allow 2 threads only 02550 if (!NT_SUCCESS(Status)) 02551 { 02552 AFD_DbgPrint(MID_TRACE,("Failed to create completion port\n")); 02553 return FALSE; 02554 } 02555 /* Protect Handle */ 02556 HandleFlags.ProtectFromClose = TRUE; 02557 HandleFlags.Inherit = FALSE; 02558 Status = NtSetInformationObject(SockAsyncCompletionPort, 02559 ObjectHandleFlagInformation, 02560 &HandleFlags, 02561 sizeof(HandleFlags)); 02562 } 02563 02564 /* Create the Async Event */ 02565 Status = NtCreateEvent(&AsyncEvent, 02566 EVENT_ALL_ACCESS, 02567 NULL, 02568 NotificationEvent, 02569 FALSE); 02570 02571 /* Create the Async Thread */ 02572 hAsyncThread = CreateThread(NULL, 02573 0, 02574 (LPTHREAD_START_ROUTINE)SockAsyncThread, 02575 NULL, 02576 0, 02577 &AsyncThreadId); 02578 02579 /* Close the Handle */ 02580 NtClose(hAsyncThread); 02581 02582 /* Increase the Reference Count */ 02583 SockAsyncThreadRefCount++; 02584 return TRUE; 02585 } 02586 02587 int SockAsyncThread(PVOID ThreadParam) 02588 { 02589 PVOID AsyncContext; 02590 PASYNC_COMPLETION_ROUTINE AsyncCompletionRoutine; 02591 IO_STATUS_BLOCK IOSB; 02592 NTSTATUS Status; 02593 02594 /* Make the Thread Higher Priority */ 02595 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); 02596 02597 /* Do a KQUEUE/WorkItem Style Loop, thanks to IoCompletion Ports */ 02598 do 02599 { 02600 Status = NtRemoveIoCompletion (SockAsyncCompletionPort, 02601 (PVOID*)&AsyncCompletionRoutine, 02602 &AsyncContext, 02603 &IOSB, 02604 NULL); 02605 /* Call the Async Function */ 02606 if (NT_SUCCESS(Status)) 02607 { 02608 (*AsyncCompletionRoutine)(AsyncContext, &IOSB); 02609 } 02610 else 02611 { 02612 /* It Failed, sleep for a second */ 02613 Sleep(1000); 02614 } 02615 } while ((Status != STATUS_TIMEOUT)); 02616 02617 /* The Thread has Ended */ 02618 return 0; 02619 } 02620 02621 BOOLEAN SockGetAsyncSelectHelperAfdHandle(VOID) 02622 { 02623 UNICODE_STRING AfdHelper; 02624 OBJECT_ATTRIBUTES ObjectAttributes; 02625 IO_STATUS_BLOCK IoSb; 02626 FILE_COMPLETION_INFORMATION CompletionInfo; 02627 OBJECT_HANDLE_ATTRIBUTE_INFORMATION HandleFlags; 02628 02629 /* First, make sure we're not already intialized */ 02630 if (SockAsyncHelperAfdHandle) 02631 { 02632 return TRUE; 02633 } 02634 02635 /* Set up Handle Name and Object */ 02636 RtlInitUnicodeString(&AfdHelper, L"\\Device\\Afd\\AsyncSelectHlp" ); 02637 InitializeObjectAttributes(&ObjectAttributes, 02638 &AfdHelper, 02639 OBJ_INHERIT | OBJ_CASE_INSENSITIVE, 02640 NULL, 02641 NULL); 02642 02643 /* Open the Handle to AFD */ 02644 NtCreateFile(&SockAsyncHelperAfdHandle, 02645 GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 02646 &ObjectAttributes, 02647 &IoSb, 02648 NULL, 02649 0, 02650 FILE_SHARE_READ | FILE_SHARE_WRITE, 02651 FILE_OPEN_IF, 02652 0, 02653 NULL, 02654 0); 02655 02656 /* 02657 * Now Set up the Completion Port Information 02658 * This means that whenever a Poll is finished, the routine will be executed 02659 */ 02660 CompletionInfo.Port = SockAsyncCompletionPort; 02661 CompletionInfo.Key = SockAsyncSelectCompletionRoutine; 02662 NtSetInformationFile(SockAsyncHelperAfdHandle, 02663 &IoSb, 02664 &CompletionInfo, 02665 sizeof(CompletionInfo), 02666 FileCompletionInformation); 02667 02668 02669 /* Protect the Handle */ 02670 HandleFlags.ProtectFromClose = TRUE; 02671 HandleFlags.Inherit = FALSE; 02672 NtSetInformationObject(SockAsyncCompletionPort, 02673 ObjectHandleFlagInformation, 02674 &HandleFlags, 02675 sizeof(HandleFlags)); 02676 02677 02678 /* Set this variable to true so that Send/Recv/Accept will know wether to renable disabled events */ 02679 SockAsyncSelectCalled = TRUE; 02680 return TRUE; 02681 } 02682 02683 VOID SockAsyncSelectCompletionRoutine(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock) 02684 { 02685 02686 PASYNC_DATA AsyncData = Context; 02687 PSOCKET_INFORMATION Socket; 02688 ULONG x; 02689 02690 /* Get the Socket */ 02691 Socket = AsyncData->ParentSocket; 02692 02693 /* Check if the Sequence Number Changed behind our back */ 02694 if (AsyncData->SequenceNumber != Socket->SharedData.SequenceNumber ) 02695 { 02696 return; 02697 } 02698 02699 /* Check we were manually called b/c of a failure */ 02700 if (!NT_SUCCESS(IoStatusBlock->Status)) 02701 { 02702 /* FIXME: Perform Upcall */ 02703 return; 02704 } 02705 02706 for (x = 1; x; x<<=1) 02707 { 02708 switch (AsyncData->AsyncSelectInfo.Handles[0].Events & x) 02709 { 02710 case AFD_EVENT_RECEIVE: 02711 if (0 != (Socket->SharedData.AsyncEvents & FD_READ) && 02712 0 == (Socket->SharedData.AsyncDisabledEvents & FD_READ)) 02713 { 02714 /* Make the Notifcation */ 02715 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd, 02716 Socket->SharedData.wMsg, 02717 Socket->Handle, 02718 WSAMAKESELECTREPLY(FD_READ, 0)); 02719 /* Disable this event until the next read(); */ 02720 Socket->SharedData.AsyncDisabledEvents |= FD_READ; 02721 } 02722 break; 02723 02724 case AFD_EVENT_OOB_RECEIVE: 02725 if (0 != (Socket->SharedData.AsyncEvents & FD_OOB) && 02726 0 == (Socket->SharedData.AsyncDisabledEvents & FD_OOB)) 02727 { 02728 /* Make the Notifcation */ 02729 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd, 02730 Socket->SharedData.wMsg, 02731 Socket->Handle, 02732 WSAMAKESELECTREPLY(FD_OOB, 0)); 02733 /* Disable this event until the next read(); */ 02734 Socket->SharedData.AsyncDisabledEvents |= FD_OOB; 02735 } 02736 break; 02737 02738 case AFD_EVENT_SEND: 02739 if (0 != (Socket->SharedData.AsyncEvents & FD_WRITE) && 02740 0 == (Socket->SharedData.AsyncDisabledEvents & FD_WRITE)) 02741 { 02742 /* Make the Notifcation */ 02743 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd, 02744 Socket->SharedData.wMsg, 02745 Socket->Handle, 02746 WSAMAKESELECTREPLY(FD_WRITE, 0)); 02747 /* Disable this event until the next write(); */ 02748 Socket->SharedData.AsyncDisabledEvents |= FD_WRITE; 02749 } 02750 break; 02751 02752 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ 02753 case AFD_EVENT_CONNECT: 02754 case AFD_EVENT_CONNECT_FAIL: 02755 if (0 != (Socket->SharedData.AsyncEvents & FD_CONNECT) && 02756 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CONNECT)) 02757 { 02758 /* Make the Notifcation */ 02759 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd, 02760 Socket->SharedData.wMsg, 02761 Socket->Handle, 02762 WSAMAKESELECTREPLY(FD_CONNECT, 0)); 02763 /* Disable this event forever; */ 02764 Socket->SharedData.AsyncDisabledEvents |= FD_CONNECT; 02765 } 02766 break; 02767 02768 case AFD_EVENT_ACCEPT: 02769 if (0 != (Socket->SharedData.AsyncEvents & FD_ACCEPT) && 02770 0 == (Socket->SharedData.AsyncDisabledEvents & FD_ACCEPT)) 02771 { 02772 /* Make the Notifcation */ 02773 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd, 02774 Socket->SharedData.wMsg, 02775 Socket->Handle, 02776 WSAMAKESELECTREPLY(FD_ACCEPT, 0)); 02777 /* Disable this event until the next accept(); */ 02778 Socket->SharedData.AsyncDisabledEvents |= FD_ACCEPT; 02779 } 02780 break; 02781 02782 case AFD_EVENT_DISCONNECT: 02783 case AFD_EVENT_ABORT: 02784 case AFD_EVENT_CLOSE: 02785 if (0 != (Socket->SharedData.AsyncEvents & FD_CLOSE) && 02786 0 == (Socket->SharedData.AsyncDisabledEvents & FD_CLOSE)) 02787 { 02788 /* Make the Notifcation */ 02789 (Upcalls.lpWPUPostMessage)(Socket->SharedData.hWnd, 02790 Socket->SharedData.wMsg, 02791 Socket->Handle, 02792 WSAMAKESELECTREPLY(FD_CLOSE, 0)); 02793 /* Disable this event forever; */ 02794 Socket->SharedData.AsyncDisabledEvents |= FD_CLOSE; 02795 } 02796 break; 02797 /* FIXME: Support QOS */ 02798 } 02799 } 02800 02801 /* Check if there are any events left for us to check */ 02802 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 ) 02803 { 02804 return; 02805 } 02806 02807 /* Keep Polling */ 02808 SockProcessAsyncSelect(Socket, AsyncData); 02809 return; 02810 } 02811 02812 VOID SockProcessAsyncSelect(PSOCKET_INFORMATION Socket, PASYNC_DATA AsyncData) 02813 { 02814 02815 ULONG lNetworkEvents; 02816 NTSTATUS Status; 02817 02818 /* Set up the Async Data Event Info */ 02819 AsyncData->AsyncSelectInfo.Timeout.HighPart = 0x7FFFFFFF; 02820 AsyncData->AsyncSelectInfo.Timeout.LowPart = 0xFFFFFFFF; 02821 AsyncData->AsyncSelectInfo.HandleCount = 1; 02822 AsyncData->AsyncSelectInfo.Exclusive = TRUE; 02823 AsyncData->AsyncSelectInfo.Handles[0].Handle = Socket->Handle; 02824 AsyncData->AsyncSelectInfo.Handles[0].Events = 0; 02825 02826 /* Remove unwanted events */ 02827 lNetworkEvents = Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents); 02828 02829 /* Set Events to wait for */ 02830 if (lNetworkEvents & FD_READ) 02831 { 02832 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_RECEIVE; 02833 } 02834 02835 if (lNetworkEvents & FD_WRITE) 02836 { 02837 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_SEND; 02838 } 02839 02840 if (lNetworkEvents & FD_OOB) 02841 { 02842 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_OOB_RECEIVE; 02843 } 02844 02845 if (lNetworkEvents & FD_ACCEPT) 02846 { 02847 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_ACCEPT; 02848 } 02849 02850 /* FIXME: THIS IS NOT RIGHT!!! HACK HACK HACK! */ 02851 if (lNetworkEvents & FD_CONNECT) 02852 { 02853 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_CONNECT | AFD_EVENT_CONNECT_FAIL; 02854 } 02855 02856 if (lNetworkEvents & FD_CLOSE) 02857 { 02858 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_DISCONNECT | AFD_EVENT_ABORT | AFD_EVENT_CLOSE; 02859 } 02860 02861 if (lNetworkEvents & FD_QOS) 02862 { 02863 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_QOS; 02864 } 02865 02866 if (lNetworkEvents & FD_GROUP_QOS) 02867 { 02868 AsyncData->AsyncSelectInfo.Handles[0].Events |= AFD_EVENT_GROUP_QOS; 02869 } 02870 02871 /* Send IOCTL */ 02872 Status = NtDeviceIoControlFile (SockAsyncHelperAfdHandle, 02873 NULL, 02874 NULL, 02875 AsyncData, 02876 &AsyncData->IoStatusBlock, 02877 IOCTL_AFD_SELECT, 02878 &AsyncData->AsyncSelectInfo, 02879 sizeof(AsyncData->AsyncSelectInfo), 02880 &AsyncData->AsyncSelectInfo, 02881 sizeof(AsyncData->AsyncSelectInfo)); 02882 02883 /* I/O Manager Won't call the completion routine, let's do it manually */ 02884 if (NT_SUCCESS(Status)) 02885 { 02886 return; 02887 } 02888 else 02889 { 02890 AsyncData->IoStatusBlock.Status = Status; 02891 SockAsyncSelectCompletionRoutine(AsyncData, &AsyncData->IoStatusBlock); 02892 } 02893 } 02894 02895 VOID SockProcessQueuedAsyncSelect(PVOID Context, PIO_STATUS_BLOCK IoStatusBlock) 02896 { 02897 PASYNC_DATA AsyncData = Context; 02898 BOOL FreeContext = TRUE; 02899 PSOCKET_INFORMATION Socket; 02900 02901 /* Get the Socket */ 02902 Socket = AsyncData->ParentSocket; 02903 02904 /* If someone closed it, stop the function */ 02905 if (Socket->SharedData.State != SocketClosed) 02906 { 02907 /* Check if the Sequence Number changed by now, in which case quit */ 02908 if (AsyncData->SequenceNumber == Socket->SharedData.SequenceNumber) 02909 { 02910 /* Do the actuall select, if needed */ 02911 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents))) 02912 { 02913 SockProcessAsyncSelect(Socket, AsyncData); 02914 FreeContext = FALSE; 02915 } 02916 } 02917 } 02918 02919 /* Free the Context */ 02920 if (FreeContext) 02921 { 02922 HeapFree(GetProcessHeap(), 0, AsyncData); 02923 } 02924 02925 return; 02926 } 02927 02928 VOID 02929 SockReenableAsyncSelectEvent (IN PSOCKET_INFORMATION Socket, 02930 IN ULONG Event) 02931 { 02932 PASYNC_DATA AsyncData; 02933 02934 /* Make sure the event is actually disabled */ 02935 if (!(Socket->SharedData.AsyncDisabledEvents & Event)) 02936 { 02937 return; 02938 } 02939 02940 /* Re-enable it */ 02941 Socket->SharedData.AsyncDisabledEvents &= ~Event; 02942 02943 /* Return if no more events are being polled */ 02944 if ((Socket->SharedData.AsyncEvents & (~Socket->SharedData.AsyncDisabledEvents)) == 0 ) 02945 { 02946 return; 02947 } 02948 02949 /* Wait on new events */ 02950 AsyncData = HeapAlloc(GetProcessHeap(), 0, sizeof(ASYNC_DATA)); 02951 if (!AsyncData) return; 02952 02953 /* Create the Asynch Thread if Needed */ 02954 SockCreateOrReferenceAsyncThread(); 02955 02956 /* Increase the sequence number to stop anything else */ 02957 Socket->SharedData.SequenceNumber++; 02958 02959 /* Set up the Async Data */ 02960 AsyncData->ParentSocket = Socket; 02961 AsyncData->SequenceNumber = Socket->SharedData.SequenceNumber; 02962 02963 /* Begin Async Select by using I/O Completion */ 02964 NtSetIoCompletion(SockAsyncCompletionPort, 02965 (PVOID)&SockProcessQueuedAsyncSelect, 02966 AsyncData, 02967 0, 02968 0); 02969 02970 /* All done */ 02971 return; 02972 } 02973 02974 BOOL 02975 WINAPI 02976 DllMain(HANDLE hInstDll, 02977 ULONG dwReason, 02978 PVOID Reserved) 02979 { 02980 02981 switch (dwReason) 02982 { 02983 case DLL_PROCESS_ATTACH: 02984 02985 AFD_DbgPrint(MAX_TRACE, ("Loading MSAFD.DLL \n")); 02986 02987 /* Don't need thread attach notifications 02988 so disable them to improve performance */ 02989 DisableThreadLibraryCalls(hInstDll); 02990 02991 /* List of DLL Helpers */ 02992 InitializeListHead(&SockHelpersListHead); 02993 02994 /* Heap to use when allocating */ 02995 GlobalHeap = GetProcessHeap(); 02996 02997 /* Initialize the lock that protects our socket list */ 02998 InitializeCriticalSection(&SocketListLock); 02999 03000 AFD_DbgPrint(MAX_TRACE, ("MSAFD.DLL has been loaded\n")); 03001 03002 break; 03003 03004 case DLL_THREAD_ATTACH: 03005 break; 03006 03007 case DLL_THREAD_DETACH: 03008 break; 03009 03010 case DLL_PROCESS_DETACH: 03011 03012 /* Delete the socket list lock */ 03013 DeleteCriticalSection(&SocketListLock); 03014 03015 break; 03016 } 03017 03018 AFD_DbgPrint(MAX_TRACE, ("DllMain of msafd.dll (leaving)\n")); 03019 03020 return TRUE; 03021 } 03022 03023 /* EOF */ 03024 03025 Generated on Fri May 25 2012 04:20:41 for ReactOS by
1.7.6.1
|