int WSAAPI WSAEventSelect( IN SOCKET s, IN WSAEVENT hEventObject, IN long lNetworkEvents ) /*++ Routine Description: Specify an event object to be associated with the supplied set of FD_XXX network events. Arguments: s - A descriptor identifying the socket. hEventObject - A handle identifying the event object to be associated with the supplied set of FD_XXX network events. lNetworkEvents - A bitmask which specifies the combination of FD_XXX network events in which the application has interest. Returns: Zero on success else SOCKET_Error. The error code is stored with SetLastError(). --*/ { INT ReturnValue; INT ErrorCode; PDPROVIDER Provider; PDSOCKET Socket; ErrorCode = TURBO_PROLOG(); if (ErrorCode == ERROR_SUCCESS) { Socket = DSOCKET::GetCountedDSocketFromSocket(s); if(Socket != NULL){ Provider = Socket->GetDProvider(); ReturnValue = Provider->WSPEventSelect( s, hEventObject, lNetworkEvents, &ErrorCode); Socket->DropDSocketReference(); if (ReturnValue==ERROR_SUCCESS) return ReturnValue; assert (ErrorCode!=NO_ERROR); if (ErrorCode==NO_ERROR) ErrorCode = WSASYSCALLFAILURE; } else { ErrorCode = WSAENOTSOCK; } } SetLastError(ErrorCode); return SOCKET_ERROR; } //WSAEventSelect
int WSAAPI bind( IN SOCKET s, IN const struct sockaddr FAR *name, IN int namelen ) /*++ Routine Description: Associate a local address with a socket. Arguments: s - A descriptor identifying an unbound socket. name - The address to assign to the socket. namelen - The length of the name. Returns: Zero on success else SOCKET_ERROR. The error code is stored with SetLastError(). --*/ { INT ReturnValue; PDPROVIDER Provider; INT ErrorCode; PDSOCKET Socket; ErrorCode = TURBO_PROLOG(); if (ErrorCode==ERROR_SUCCESS) { Socket = DSOCKET::GetCountedDSocketFromSocket(s); if(Socket != NULL) { Provider = Socket->GetDProvider(); ReturnValue = Provider->WSPBind(s, name, namelen, &ErrorCode); Socket->DropDSocketReference(); if (ReturnValue==ERROR_SUCCESS) return ReturnValue; assert (ErrorCode!=NO_ERROR); if (ErrorCode==NO_ERROR) ErrorCode = WSASYSCALLFAILURE; } else { ErrorCode = WSAENOTSOCK; } } SetLastError(ErrorCode); return SOCKET_ERROR; }
int WSAAPI getsockname( IN SOCKET s, OUT struct sockaddr FAR *name, OUT int FAR * namelen ) /*++ Routine Description: Get the local name for a socket. Arguments: s - A descriptor identifying a bound socket. name - Receives the address (name) of the socket. namelen - The size of the name buffer. Returns: Zero on success else SOCKET_ERROR. The error code is stored with SetLastError(). --*/ { INT ReturnValue; INT ErrorCode; PDPROVIDER Provider; PDSOCKET Socket; ErrorCode = TURBO_PROLOG(); if (ErrorCode == ERROR_SUCCESS) { Socket = DSOCKET::GetCountedDSocketFromSocket(s); if(Socket != NULL) { Provider = Socket->GetDProvider(); ReturnValue = Provider->WSPGetSockName(s, name, namelen, &ErrorCode); Socket->DropDSocketReference(); if (ReturnValue==ERROR_SUCCESS) return ReturnValue; assert (ErrorCode!=NO_ERROR); if (ErrorCode==NO_ERROR) ErrorCode = WSASYSCALLFAILURE; } else { ErrorCode = WSAENOTSOCK; } } SetLastError(ErrorCode); return SOCKET_ERROR; }
int WSAAPI WSARecvDisconnect( IN SOCKET s, OUT LPWSABUF lpInboundDisconnectData ) /*++ Routine Description: Terminate reception on a socket, and retrieve the disconnect data if the socket is connection-oriented. Arguments: s - A descriptor identifying a socket. lpInboundDisconnectData - A pointer to the incoming disconnect data. Returns: Zero on success else SOCKET_ERROR. The error code is stored with SetErrorCode(). --*/ { PDPROCESS Process; PDTHREAD Thread; INT ErrorCode; PDSOCKET Socket; ErrorCode = PROLOG (&Process,&Thread); if (ErrorCode==ERROR_SUCCESS) { Socket = DSOCKET::GetCountedDSocketFromSocket(s); if(Socket != NULL){ INT ReturnValue; PDPROVIDER Provider; Provider = Socket->GetDProvider(); ReturnValue = Provider->WSPRecvDisconnect( s, lpInboundDisconnectData, &ErrorCode); Socket->DropDSocketReference(); if (ReturnValue==ERROR_SUCCESS) return ERROR_SUCCESS; } else { ErrorCode = WSAENOTSOCK; } } SetLastError(ErrorCode); return(SOCKET_ERROR); }
int WSAAPI WSAHtonl ( IN SOCKET s, IN u_long hostlong, OUT u_long FAR * lpnetlong ) /*++ Routine Description: Convert a u_long from a specified host byte order to network byte order. Arguments: s - A descriptor identifying a socket. hostlong - A 32-bit number in host byte order. lpnetlong - A pointer to a 32-bit number in network byte order. Returns: If no error occurs, WSAHtonl() returns 0. Otherwise, a value of SOCKET_ERROR is returned. --*/ { PDSOCKET Socket; INT ErrorCode; PPROTO_CATALOG_ITEM CatalogEntry; LPWSAPROTOCOL_INFOW ProtocolInfo; ErrorCode = TURBO_PROLOG(); if (ErrorCode==ERROR_SUCCESS) { if( lpnetlong == NULL ) { SetLastError( WSAEFAULT ); return(SOCKET_ERROR); } Socket = DSOCKET::GetCountedDSocketFromSocket(s); if(Socket != NULL){ CatalogEntry = Socket->GetCatalogItem(); ProtocolInfo = CatalogEntry->GetProtocolInfo(); __try { if (LITTLEENDIAN == ProtocolInfo->iNetworkByteOrder) { *lpnetlong = hostlong; } //if else { *lpnetlong = SWAP_LONG( hostlong ); } //else ErrorCode = ERROR_SUCCESS; } __except (WS2_EXCEPTION_FILTER()) { ErrorCode = WSAEFAULT; } Socket->DropDSocketReference(); if (ErrorCode==ERROR_SUCCESS) return ErrorCode; } //if else
int WSAAPI select ( IN int nfds, IN OUT fd_set FAR *readfds, IN OUT fd_set FAR *writefds, IN OUT fd_set FAR *exceptfds, IN const struct timeval FAR *timeout ) /*++ Routine Description: Determine the status of one or more sockets, waiting if necessary. Arguments: nfds - This argument is ignored and included only for the sake of compatibility. readfds - An optional pointer to a set of sockets to be checked for readability. writefds - An optional pointer to a set of sockets to be checked for writability. exceptfds - An optional pointer to a set of sockets to be checked for errors. timeout - The maximum time for select() to wait, or NULL for blocking operation. Returns: select() returns the total number of descriptors which are ready and contained in the fd_set structures, 0 if the time limit expired, or SOCKET_ERROR if an error occurred. If the return value is SOCKET_ERROR, The error code is stored with SetLastError(). --*/ { INT ReturnValue; INT ErrorCode; PDPROVIDER Provider; PDSOCKET Socket; SOCKET SocketID; BOOL FoundSocket=FALSE; ErrorCode = TURBO_PROLOG(); if (ErrorCode == ERROR_SUCCESS) { __try { // Look for a socket in the three fd_sets handed in. The first // socket found will be used to select the service provider to // service this call if (readfds && readfds->fd_count) { SocketID = readfds->fd_array[0]; FoundSocket = TRUE; } //if if (!FoundSocket && writefds && writefds->fd_count ) { SocketID = writefds->fd_array[0]; FoundSocket = TRUE; } //if if (!FoundSocket && exceptfds && exceptfds->fd_count ) { SocketID = exceptfds->fd_array[0]; FoundSocket = TRUE; } //if } __except (WS2_EXCEPTION_FILTER()) { ErrorCode = WSAEFAULT; goto ReturnError; } if (FoundSocket) { Socket = DSOCKET::GetCountedDSocketFromSocket(SocketID); if(Socket != NULL){ Provider = Socket->GetDProvider(); ReturnValue = Provider->WSPSelect( nfds, readfds, writefds, exceptfds, timeout, &ErrorCode); Socket->DropDSocketReference(); if (ReturnValue!=SOCKET_ERROR) return ReturnValue; assert (ErrorCode!=NO_ERROR); if (ErrorCode==NO_ERROR) ErrorCode = WSASYSCALLFAILURE; } //if else { ErrorCode = WSAENOTSOCK; } } //if else { ErrorCode = WSAEINVAL; } //else }
int WSAAPI WSAAsyncSelect( IN SOCKET s, IN HWND hWnd, IN u_int wMsg, IN long lEvent ) /*++ Routine Description: Request event notification for a socket. Arguments: s - A descriptor identifying the socket for which event notification is required. hWnd - A handle identifying the window which should receive a message when a network event occurs. wMsg - The message to be received when a network event occurs. lEvent - A bitmask which specifies a combination of network events in which the application is interested. Returns: The return value is 0 if the application's declaration of interest in the network event set was successful. Otherwise the value SOCKET_ERROR is returned, and a specific error number may be retrieved by calling WSAGetLastError(). --*/ { INT ReturnValue; INT ErrorCode; PDPROVIDER Provider; PDSOCKET Socket; ErrorCode = TURBO_PROLOG(); if (ErrorCode == ERROR_SUCCESS) { Socket = DSOCKET::GetCountedDSocketFromSocket(s); if(Socket != NULL){ Provider = Socket->GetDProvider(); ReturnValue = Provider->WSPAsyncSelect( s, hWnd, wMsg, lEvent, &ErrorCode); Socket->DropDSocketReference(); if (ReturnValue==ERROR_SUCCESS) return ReturnValue; assert (ErrorCode!=NO_ERROR); if (ErrorCode==NO_ERROR) ErrorCode = WSASYSCALLFAILURE; } else { ErrorCode = WSAENOTSOCK; } } SetLastError(ErrorCode); return SOCKET_ERROR; } //WSAAsyncSelect
int WSAAPI WSANtohs ( IN SOCKET s, IN u_short netshort, OUT u_short FAR * lphostshort ) /*++ Routine Description: Arguments: Returns: Zero on success else SOCKET_ERROR. The error code is stored with SetErrorCode(). --*/ { PDPROCESS Process; PDTHREAD Thread; PDSOCKET Socket; INT ErrorCode; INT ReturnCode; PPROTO_CATALOG_ITEM CatalogEntry; LPWSAPROTOCOL_INFOW ProtocolInfo; ReturnCode = PROLOG( &Process, &Thread, &ErrorCode); if (ERROR_SUCCESS != ReturnCode) { SetLastError(ErrorCode); return(SOCKET_ERROR); } //if if( lphostshort == NULL ) { SetLastError( WSAEFAULT ); return(SOCKET_ERROR); } ErrorCode = DSOCKET::GetCountedDSocketFromSocket( s, // SocketHandle & Socket); // DSocket if(ERROR_SUCCESS == ErrorCode){ CatalogEntry = Socket->GetCatalogItem(); // This is kind of a special case. We are done with the DSOCKET // object reference and we don't call through to the provider at // all. Socket->DropDSocketReference(); ProtocolInfo = CatalogEntry->GetProtocolInfo(); if (LITTLEENDIAN == ProtocolInfo->iNetworkByteOrder) { *lphostshort = netshort; } //if else { *lphostshort = SWAP_SHORT( netshort ); } //else } //if if (ErrorCode != ERROR_SUCCESS) { SetLastError(ErrorCode); ReturnCode = SOCKET_ERROR; } return(ReturnCode); }
int WSAAPI WSANtohl ( IN SOCKET s, IN u_long netlong, OUT u_long FAR * lphostlong ) /*++ Routine Description: Convert a u_long from network byte order to host byte order. Arguments: s - A descriptor identifying a socket. netlong - A 32-bit number in network byte order. lphostlong - A pointer to a 32-bit number in host byte order. Returns: If no error occurs, WSANtohs() returns 0. Otherwise, a value of SOCKET_ERROR is returned. --*/ { PDPROCESS Process; PDTHREAD Thread; PDSOCKET Socket; INT ErrorCode; INT ReturnCode; PPROTO_CATALOG_ITEM CatalogEntry; LPWSAPROTOCOL_INFOW ProtocolInfo; ReturnCode = PROLOG( &Process, &Thread, &ErrorCode); if (ERROR_SUCCESS != ReturnCode) { SetLastError(ErrorCode); return(SOCKET_ERROR); } //if if( lphostlong == NULL ) { SetLastError( WSAEFAULT ); return(SOCKET_ERROR); } ErrorCode = DSOCKET::GetCountedDSocketFromSocket( s, // SocketHandle & Socket); // DSocket if(ERROR_SUCCESS == ErrorCode){ CatalogEntry = Socket->GetCatalogItem(); // This is kind of a special case. We are done with the DSOCKET // object reference and we don't call through to the provider at // all. Socket->DropDSocketReference(); ProtocolInfo = CatalogEntry->GetProtocolInfo(); if (LITTLEENDIAN == ProtocolInfo->iNetworkByteOrder) { *lphostlong = netlong; } //if else { *lphostlong = SWAP_LONG( netlong ); } //else } //if if (ErrorCode != ERROR_SUCCESS) { SetLastError(ErrorCode); ReturnCode = SOCKET_ERROR; } return(ReturnCode); }
int WSAAPI getsockopt( IN SOCKET s, IN int level, IN int optname, OUT char FAR * optval, IN OUT int FAR *optlen ) /*++ Routine Description: Retrieve a socket option. Arguments: s - A descriptor identifying a socket. level - The level at which the option is defined; the supported levels include SOL_SOCKET and IPPROTO_TCP. (See annex for more protocol-specific levels.) optname - The socket option for which the value is to be retrieved. optval - A pointer to the buffer in which the value for the requested option is to be returned. optlen - A pointer to the size of the optval buffer. Returns: Zero on success else SOCKET_ERROR. The error code is stored with SetLastError(). --*/ { INT ReturnValue; PDPROCESS Process; PDTHREAD Thread; INT ErrorCode; PDPROVIDER Provider; PDSOCKET Socket; WSAPROTOCOL_INFOW ProtocolInfoW; char FAR * SavedOptionValue = NULL; int SavedOptionLen = 0; ErrorCode = PROLOG(&Process, &Thread); if (ErrorCode==ERROR_SUCCESS) { // // SO_OPENTYPE hack-o-rama. // if( level == SOL_SOCKET && optname == SO_OPENTYPE ) { __try { if( optlen == NULL || *optlen < sizeof(INT) ) { SetLastError( WSAEFAULT ); return SOCKET_ERROR; } *((LPINT)optval) = Thread->GetOpenType(); *optlen = sizeof(INT); return ERROR_SUCCESS; } __except (WS2_EXCEPTION_FILTER()) { SetLastError (WSAEFAULT); return SOCKET_ERROR; } } Socket = DSOCKET::GetCountedDSocketFromSocket(s); if(Socket != NULL) { Provider = Socket->GetDProvider(); // // If we managed to lookup the provider from the socket, and the // user is asking for the ANSI WSAPROTOCOL_INFOA information, // then validate their option length parameter, remember this fact, // and map the option name to SO_PROTOCOL_INFOW. // if( level == SOL_SOCKET && optname == SO_PROTOCOL_INFOA ) { __try { if( optval == NULL || optlen == NULL || *optlen < sizeof(WSAPROTOCOL_INFOA) ) { * optlen = sizeof(WSAPROTOCOL_INFOA); Socket->DropDSocketReference(); SetLastError (WSAEFAULT); return (SOCKET_ERROR); } SavedOptionLen = *optlen; *optlen = sizeof(WSAPROTOCOL_INFOW); SavedOptionValue = optval; optval = (char FAR *)&ProtocolInfoW; optname = SO_PROTOCOL_INFOW; } __except (WS2_EXCEPTION_FILTER()) { ErrorCode = WSAEFAULT; Socket->DropDSocketReference(); goto ErrorExit; } }
int WSAAPI connect( IN SOCKET s, IN const struct sockaddr FAR *name, IN int namelen ) /*++ Routine Description: Establish a connection to a peer. Arguments: s - A descriptor identifying an unconnected socket. name - The name of the peer to which the socket is to be connected. namelen - The length of the name. Returns: Zero on success else SOCKET_ERROR. The error code is stored with SetLastError(). --*/ { INT ReturnValue; PDPROCESS Process; PDTHREAD Thread; PDPROVIDER Provider; INT ErrorCode; PDSOCKET Socket; BOOL RetryConnect; INT SavedErrorCode; ErrorCode = PROLOG(&Process, &Thread); if (ErrorCode==ERROR_SUCCESS) { Socket = DSOCKET::GetCountedDSocketFromSocket(s); if(Socket != NULL) { Provider = Socket->GetDProvider(); #ifdef RASAUTODIAL RetryConnect = FALSE; retry: #endif // RASAUTODIAL ReturnValue = Provider->WSPConnect(s, name, namelen, NULL, NULL, NULL, NULL, &ErrorCode); #ifdef RASAUTODIAL if (ReturnValue == SOCKET_ERROR && (ErrorCode == WSAEHOSTUNREACH || ErrorCode == WSAENETUNREACH)) { if (!RetryConnect) { // // We preserve the original error // so we can return it in case the // second call to WSPConnect() fails // also. // SavedErrorCode = ErrorCode; // // Only one retry per connect attempt. // RetryConnect = TRUE; if (WSAttemptAutodialAddr(name, namelen)) goto retry; } else ErrorCode = SavedErrorCode; } #endif // RASAUTODIAL Socket->DropDSocketReference(); if (ReturnValue==ERROR_SUCCESS) return ReturnValue; assert (ErrorCode!=NO_ERROR); if (ErrorCode==NO_ERROR) ErrorCode = WSASYSCALLFAILURE; } else { ErrorCode = WSAENOTSOCK; } } // // If this is a 1.x application and the service provider // failed the request with WSAEALREADY, map the error code // to WSAEINVAL to be consistent with MS's WinSock 1.1 // implementations. // if( ErrorCode == WSAEALREADY && Process->GetMajorVersion() == 1 ) { ErrorCode = WSAEINVAL; } SetLastError(ErrorCode); return SOCKET_ERROR; }
int WSAAPI recv( IN SOCKET s, OUT char FAR * buf, IN int len, IN int flags ) /*++ Routine Description: Receive data from a socket. Arguments: s - A descriptor identifying a connected socket. buf - A buffer for the incoming data. len - The length of buf. flags - Specifies the way in which the call is made. Returns: The number of bytes received. If the connection has been gracefully closed, the return value is 0. Otherwise, a value of SOCKET_ERROR is returned, and a specific error code is stored with SetErrorCode(). --*/ { INT ErrorCode; PDSOCKET Socket; LPWSATHREADID ThreadId; ErrorCode = TURBO_PROLOG_OVLP(&ThreadId); if (ErrorCode==ERROR_SUCCESS) { Socket = DSOCKET::GetCountedDSocketFromSocket(s); if(Socket != NULL){ INT ReturnValue; PDPROVIDER Provider; DWORD BytesReceived; WSABUF Buffers; Buffers.len = len; Buffers.buf = buf; Provider = Socket->GetDProvider(); ReturnValue = Provider->WSPRecv(s, &Buffers, 1, &BytesReceived, (LPDWORD)&flags, NULL, // lpOverlapped NULL, // lpCompletionRoutine ThreadId, &ErrorCode); Socket->DropDSocketReference(); if (ReturnValue==ERROR_SUCCESS) { if ((flags & MSG_PARTIAL)==0) { return (INT)BytesReceived; } ErrorCode = WSAEMSGSIZE; } assert (ErrorCode!=NO_ERROR); if (ErrorCode==NO_ERROR) ErrorCode = WSASYSCALLFAILURE; } else { ErrorCode = WSAENOTSOCK; } } SetLastError(ErrorCode); return SOCKET_ERROR; }
int WSAAPI WSARecvFrom( IN SOCKET s, OUT LPWSABUF lpBuffers, IN DWORD dwBufferCount, OUT LPDWORD lpNumberOfBytesRecvd, IN OUT LPDWORD lpFlags, OUT struct sockaddr FAR * lpFrom, IN OUT LPINT lpFromlen, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) /*++ Routine Description: Receive a datagram and store the source address. Arguments: s - A descriptor identifying a socket lpBuffers - A pointer to an array of WSABUF structures. Each WSABUF structure contains a pointer to a buffer and the length of the buffer. dwBufferCount - The number of WSABUF structures in the lpBuffers array. lpNumberOfBytesRecvd - A pointer to the number of bytes received by this call if the receive operation completes immediately. lpFlags - A pointer to flags. lpFrom - An optional pointer to a buffer which will hold the source address upon the completion of the overlapped operation. lpFromlen - A pointer to the size of the from buffer, required only if lpFrom is specified. lpOverlapped - A pointer to a WSAOVERLAPPED structure (ignored for non- overlapped sockets). lpCompletionRoutine - A pointer to the completion routine called when the receive operation has been completed (ignored for non-overlapped sockets). Returns: Zero on success else SOCKET_ERROR. The error code is stored with SetErrorCode(). --*/ { INT ErrorCode; PDSOCKET Socket; LPWSATHREADID ThreadId; ErrorCode = TURBO_PROLOG_OVLP(&ThreadId); if (ErrorCode==ERROR_SUCCESS) { Socket = DSOCKET::GetCountedDSocketFromSocket(s); if(Socket != NULL){ INT ReturnValue; PDPROVIDER Provider; Provider = Socket->GetDProvider(); ReturnValue = Provider->WSPRecvFrom(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpFrom, lpFromlen, lpOverlapped, lpCompletionRoutine, ThreadId, &ErrorCode); Socket->DropDSocketReference(); if (ReturnValue==ERROR_SUCCESS) return ReturnValue; assert (ErrorCode!=NO_ERROR); if (ErrorCode==NO_ERROR) ErrorCode = WSASYSCALLFAILURE; } else { ErrorCode = WSAENOTSOCK; } } SetLastError(ErrorCode); return SOCKET_ERROR; }
int WSAAPI WSARecv( IN SOCKET s, OUT LPWSABUF lpBuffers, IN DWORD dwBufferCount, OUT LPDWORD lpNumberOfBytesRecvd, IN OUT LPDWORD lpFlags, IN LPWSAOVERLAPPED lpOverlapped, IN LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) /*++ Routine Description: Receive data from a socket. Arguments: s - A descriptor identifying a connected socket. lpBuffers - A pointer to an array of WSABUF structures. Each WSABUF structure contains a pointer to a buffer and the length of the buffer. dwBufferCount - The number of WSABUF structures in the lpBuffers array. lpNumberOfBytesRecvd - A pointer to the number of bytes received by this call if the receive operation completes immediately. lpFlags - A pointer to flags. lpOverlapped - A pointer to a WSAOVERLAPPED structure (ignored for non-overlapped sockets). lpCompletionRoutine - A pointer to the completion routine called when the receive operation has been completed (ignored for non-overlapped sockets). Returns: If no error occurs and the receive operation has completed immediately, WSARecv() returns the number of bytes received. If the connection has been closed, it returns 0. Otherwise, a value of SOCKET_ERROR is returned, and the specific error code is stored with SetErrorCode(). The error code WSA_IO_PENDING indicates that the overlapped operation has been successfully initiated and that completion will be indicated at a later time. Any other error code indicates that the overlapped operation was not successfully initiated and no completion indication will occur. If the MSG_INTERRUPT flag is set, the meaning of the return value is changed. A value of zero indicates success and is interpreted as described above. Otherwise, the return value will directly contain the appropriate error code as shown below. Note that this is applicable only to Win16 environments and only for protocols that have the XP1_INTERRUPT bit set in the WSAPROTOCOL_INFO struct. --*/ { INT ErrorCode; PDSOCKET Socket; LPWSATHREADID ThreadId; ErrorCode = TURBO_PROLOG_OVLP(&ThreadId); if (ErrorCode==ERROR_SUCCESS) { Socket = DSOCKET::GetCountedDSocketFromSocket(s); if(Socket != NULL){ INT ReturnValue; PDPROVIDER Provider; Provider = Socket->GetDProvider(); ReturnValue = Provider->WSPRecv(s, lpBuffers, dwBufferCount, lpNumberOfBytesRecvd, lpFlags, lpOverlapped, lpCompletionRoutine, ThreadId, &ErrorCode); Socket->DropDSocketReference(); if (ReturnValue==ERROR_SUCCESS) return ReturnValue; assert (ErrorCode!=NO_ERROR); if (ErrorCode==NO_ERROR) ErrorCode = WSASYSCALLFAILURE; } else { ErrorCode = WSAENOTSOCK; } } SetLastError(ErrorCode); return SOCKET_ERROR; }