Annotation of q_a/samples/ddk/wshsmple/wshsmple.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1992 Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     WshTcpip.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This module contains necessary routines for the TCP/IP Windows Sockets
        !            12:     Helper DLL.  This DLL provides the transport-specific support necessary
        !            13:     for the Windows Sockets DLL to use TCP/IP as a transport.
        !            14: 
        !            15: Author:
        !            16: 
        !            17:     David Treadwell     19-Jul-1992
        !            18: 
        !            19: Revision History:
        !            20: 
        !            21:        Converted to use Win32 APIs.
        !            22: 
        !            23: --*/
        !            24: 
        !            25: #include <windows.h>
        !            26: #include <winerror.h>
        !            27: #include <winioctl.h>
        !            28: 
        !            29: #include <assert.h>
        !            30: #include <wchar.h>
        !            31: 
        !            32: typedef LONG NTSTATUS;
        !            33: /*lint -e624 */  // Don't complain about different typedefs.   // winnt
        !            34: typedef NTSTATUS *PNTSTATUS;
        !            35: /*lint +e624 */  // Resume checking for different typedefs.    // winnt
        !            36: 
        !            37: #include <tdi.h>
        !            38: 
        !            39: #include <winsock.h>
        !            40: 
        !            41: typedef struct _UNICODE_STRING {
        !            42:     USHORT Length;
        !            43:     USHORT MaximumLength;
        !            44: #ifdef MIDL_PASS
        !            45:     [size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer;
        !            46: #else // MIDL_PASS
        !            47:     PWSTR  Buffer;
        !            48: #endif // MIDL_PASS
        !            49: } UNICODE_STRING;
        !            50: typedef UNICODE_STRING *PUNICODE_STRING;
        !            51: #define UNICODE_NULL ((WCHAR)0) // winnt
        !            52: 
        !            53: #define RtlInitUnicodeString(s, b) \
        !            54:     do \
        !            55:     { \
        !            56:        PUNICODE_STRING string = (s); \
        !            57:        PWSTR   buffer = (b); \
        !            58:        int     length = 2 * wcslen(buffer); \
        !            59:  \
        !            60:        string->Length = length; \
        !            61:        string->MaximumLength = length; \
        !            62:        string->Buffer = buffer; \
        !            63:     } \
        !            64:     while ( 0 );
        !            65: 
        !            66: #include <wsahelp.h>
        !            67: 
        !            68: #include <sys\snet\stcp_opt.h>
        !            69: 
        !            70: //
        !            71: // Structure and variables to define the triples supported by TCP/IP. The
        !            72: // first entry of each array is considered the canonical triple for
        !            73: // that socket type; the other entries are synonyms for the first.
        !            74: //
        !            75: 
        !            76: typedef struct _MAPPING_TRIPLE {
        !            77:     INT AddressFamily;
        !            78:     INT SocketType;
        !            79:     INT Protocol;
        !            80: } MAPPING_TRIPLE, *PMAPPING_TRIPLE;
        !            81: 
        !            82: MAPPING_TRIPLE TcpMappingTriples[] = { AF_INET,   SOCK_STREAM, IPPROTO_TCP,
        !            83:                                       AF_INET,   SOCK_STREAM, 0,
        !            84:                                       AF_INET,   0,           IPPROTO_TCP,
        !            85:                                       AF_UNSPEC, 0,           IPPROTO_TCP,
        !            86:                                       AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP };
        !            87: 
        !            88: MAPPING_TRIPLE UdpMappingTriples[] = { AF_INET,   SOCK_DGRAM,  IPPROTO_UDP,
        !            89:                                       AF_INET,   SOCK_DGRAM,  0,
        !            90:                                       AF_INET,   0,           IPPROTO_UDP,
        !            91:                                       AF_UNSPEC, 0,           IPPROTO_UDP,
        !            92:                                       AF_UNSPEC, SOCK_DGRAM,  IPPROTO_UDP };
        !            93: 
        !            94: //
        !            95: // Forward declarations of internal routines.
        !            96: //
        !            97: 
        !            98: VOID
        !            99: WINAPI
        !           100: CompleteTdiActionApc (
        !           101:     DWORD dwErrorCode,
        !           102:     DWORD dwNumberOfBytesTransfered,
        !           103:     LPOVERLAPPED lpOverlapped
        !           104:     );
        !           105: 
        !           106: INT
        !           107: DoTdiAction (
        !           108:     IN HANDLE TdiConnectionObjectHandle,
        !           109:     IN INT OptionLevel,
        !           110:     IN INT OptionName,
        !           111:     IN INT OptionalData
        !           112:     );
        !           113: 
        !           114: BOOLEAN
        !           115: IsTripleInList (
        !           116:     IN PMAPPING_TRIPLE List,
        !           117:     IN ULONG ListLength,
        !           118:     IN INT AddressFamily,
        !           119:     IN INT SocketType,
        !           120:     IN INT Protocol
        !           121:     );
        !           122: 
        !           123: //
        !           124: // The socket context structure for this DLL.  Each open TCP/IP socket
        !           125: // will have one of these context structures, which is used to maintain
        !           126: // information about the socket.
        !           127: //
        !           128: 
        !           129: typedef struct _WSHTCPIP_SOCKET_CONTEXT {
        !           130:     INT AddressFamily;
        !           131:     INT SocketType;
        !           132:     INT Protocol;
        !           133:     INT ReceiveBufferSize;
        !           134:     BOOLEAN KeepAlive;
        !           135:     BOOLEAN DontRoute;
        !           136:     BOOLEAN NoDelay;
        !           137: } WSHTCPIP_SOCKET_CONTEXT, *PWSHTCPIP_SOCKET_CONTEXT;
        !           138: 
        !           139: #define DEFAULT_RECEIVE_BUFFER_SIZE 8192
        !           140: 
        !           141: 
        !           142: INT
        !           143: WINAPI
        !           144: WSHGetSockaddrType (
        !           145:     IN PSOCKADDR Sockaddr,
        !           146:     IN DWORD SockaddrLength,
        !           147:     OUT PSOCKADDR_INFO SockaddrInfo
        !           148:     )
        !           149: 
        !           150: /*++
        !           151: 
        !           152: Routine Description:
        !           153: 
        !           154:     This routine parses a sockaddr to determine the type of the
        !           155:     machine address and endpoint address portions of the sockaddr.
        !           156:     This is called by the winsock DLL whenever it needs to interpret
        !           157:     a sockaddr.
        !           158: 
        !           159: Arguments:
        !           160: 
        !           161:     Sockaddr - a pointer to the sockaddr structure to evaluate.
        !           162: 
        !           163:     SockaddrLength - the number of bytes in the sockaddr structure.
        !           164: 
        !           165:     SockaddrInfo - a pointer to a structure that will receive information
        !           166:        about the specified sockaddr.
        !           167: 
        !           168: 
        !           169: Return Value:
        !           170: 
        !           171:     INT - a winsock error code indicating the status of the operation, or
        !           172:        NO_ERROR if the operation succeeded.
        !           173: 
        !           174: --*/
        !           175: 
        !           176: {
        !           177:     UNALIGNED SOCKADDR_IN *sockaddr = (PSOCKADDR_IN)Sockaddr;
        !           178:     ULONG i;
        !           179: 
        !           180:     //
        !           181:     // Make sure that the address family is correct.
        !           182:     //
        !           183: 
        !           184:     if ( sockaddr->sin_family != AF_INET ) {
        !           185:        return WSAEAFNOSUPPORT;
        !           186:     }
        !           187: 
        !           188:     //
        !           189:     // Make sure that the length is correct.
        !           190:     //
        !           191: 
        !           192:     if ( SockaddrLength < sizeof(SOCKADDR_IN) ) {
        !           193:        return WSAEFAULT;
        !           194:     }
        !           195: 
        !           196:     //
        !           197:     // The address passed the tests, looks like a good address.
        !           198:     // Determine the type of the address portion of the sockaddr.
        !           199:     //
        !           200: 
        !           201:     if ( sockaddr->sin_addr.s_addr == INADDR_ANY ) {
        !           202:        SockaddrInfo->AddressInfo = SockaddrAddressInfoWildcard;
        !           203:     } else if ( sockaddr->sin_addr.s_addr == INADDR_BROADCAST ) {
        !           204:        SockaddrInfo->AddressInfo = SockaddrAddressInfoBroadcast;
        !           205:     } else if ( sockaddr->sin_addr.s_addr == INADDR_LOOPBACK ) {
        !           206:        SockaddrInfo->AddressInfo = SockaddrAddressInfoLoopback;
        !           207:     } else {
        !           208:        SockaddrInfo->AddressInfo = SockaddrAddressInfoNormal;
        !           209:     }
        !           210: 
        !           211:     //
        !           212:     // Determine the type of the port (endpoint) in the sockaddr.
        !           213:     //
        !           214: 
        !           215:     if ( sockaddr->sin_port == 0 ) {
        !           216:        SockaddrInfo->EndpointInfo = SockaddrEndpointInfoWildcard;
        !           217:     } else if ( ntohs( sockaddr->sin_port ) < 2000 ) {
        !           218:        SockaddrInfo->EndpointInfo = SockaddrEndpointInfoReserved;
        !           219:     } else {
        !           220:        SockaddrInfo->EndpointInfo = SockaddrEndpointInfoNormal;
        !           221:     }
        !           222: 
        !           223:     //
        !           224:     // Zero out the sin_zero part of the address.  We silently allow
        !           225:     // nonzero values in this field.
        !           226:     //
        !           227: 
        !           228:     for ( i = 0; i < sizeof(sockaddr->sin_zero); i++ ) {
        !           229:        sockaddr->sin_zero[i] = 0;
        !           230:     }
        !           231: 
        !           232:     return NO_ERROR;
        !           233: 
        !           234: } // WSHGetSockaddrType
        !           235: 
        !           236: 
        !           237: INT
        !           238: WINAPI
        !           239: WSHGetSocketInformation (
        !           240:     IN PVOID HelperDllSocketContext,
        !           241:     IN SOCKET SocketHandle,
        !           242:     IN HANDLE TdiAddressObjectHandle,
        !           243:     IN HANDLE TdiConnectionObjectHandle,
        !           244:     IN INT Level,
        !           245:     IN INT OptionName,
        !           246:     OUT PCHAR OptionValue,
        !           247:     OUT PINT OptionLength
        !           248:     )
        !           249: 
        !           250: /*++
        !           251: 
        !           252: Routine Description:
        !           253: 
        !           254:     This routine retrieves information about a socket for those socket
        !           255:     options supported in this helper DLL.  The options supported here
        !           256:     are SO_KEEPALIVE and SO_DONTROUTE.  This routine is called by
        !           257:     the winsock DLL when a level/option name combination is passed
        !           258:     to getsockopt() that the winsock DLL does not understand.
        !           259: 
        !           260: Arguments:
        !           261: 
        !           262:     HelperDllSocketContext - the context pointer returned from
        !           263:        WSHOpenSocket().
        !           264: 
        !           265:     SocketHandle - the handle of the socket for which we're getting
        !           266:        information.
        !           267: 
        !           268:     TdiAddressObjectHandle - the TDI address object of the socket, if
        !           269:        any.  If the socket is not yet bound to an address, then
        !           270:        it does not have a TDI address object and this parameter
        !           271:        will be NULL.
        !           272: 
        !           273:     TdiConnectionObjectHandle - the TDI connection object of the socket,
        !           274:        if any.  If the socket is not yet connected, then it does not
        !           275:        have a TDI connection object and this parameter will be NULL.
        !           276: 
        !           277:     Level - the level parameter passed to getsockopt().
        !           278: 
        !           279:     OptionName - the optname parameter passed to getsockopt().
        !           280: 
        !           281:     OptionValue - the optval parameter passed to getsockopt().
        !           282: 
        !           283:     OptionLength - the optlen parameter passed to getsockopt().
        !           284: 
        !           285: Return Value:
        !           286: 
        !           287:     INT - a winsock error code indicating the status of the operation, or
        !           288:        NO_ERROR if the operation succeeded.
        !           289: 
        !           290: --*/
        !           291: 
        !           292: {
        !           293:     PWSHTCPIP_SOCKET_CONTEXT context = HelperDllSocketContext;
        !           294: 
        !           295:     UNREFERENCED_PARAMETER( SocketHandle );
        !           296:     UNREFERENCED_PARAMETER( TdiAddressObjectHandle );
        !           297:     UNREFERENCED_PARAMETER( TdiConnectionObjectHandle );
        !           298: 
        !           299:     //
        !           300:     // Check if this is an internal request for context information.
        !           301:     //
        !           302: 
        !           303:     if ( Level == SOL_INTERNAL && OptionName == SO_CONTEXT ) {
        !           304: 
        !           305:        //
        !           306:        // The Windows Sockets DLL is requesting context information 
        !           307:        // from us.  If an output buffer was not supplied, the Windows 
        !           308:        // Sockets DLL is just requesting the size of our context 
        !           309:        // information.  
        !           310:        //
        !           311: 
        !           312:        if ( OptionValue != NULL ) {
        !           313: 
        !           314:            //
        !           315:            // Make sure that the buffer is sufficient to hold all the 
        !           316:            // context information.  
        !           317:            //
        !           318: 
        !           319:            if ( *OptionLength < sizeof(*context) ) {
        !           320:                return WSAEFAULT;
        !           321:            }
        !           322: 
        !           323:            //
        !           324:            // Copy in the context information.
        !           325:            //
        !           326: 
        !           327:            CopyMemory( OptionValue, context, sizeof(*context) );
        !           328:        }
        !           329: 
        !           330:        *OptionLength = sizeof(*context);
        !           331: 
        !           332:        return NO_ERROR;
        !           333:     }
        !           334: 
        !           335:     //
        !           336:     // The only other levels we support here are SOL_SOCKET and 
        !           337:     // IPPROTO_TCP.  
        !           338:     //
        !           339: 
        !           340:     if ( Level != SOL_SOCKET && Level != IPPROTO_TCP ) {
        !           341:        return WSAEINVAL;
        !           342:     }
        !           343: 
        !           344:     //
        !           345:     // Make sure that the output buffer is sufficiently large.
        !           346:     //
        !           347: 
        !           348:     if ( *OptionLength < sizeof(int) ) {
        !           349:        return WSAEFAULT;
        !           350:     }
        !           351: 
        !           352:     //
        !           353:     // Handle TCP-level options.
        !           354:     //
        !           355: 
        !           356:     if ( Level == IPPROTO_TCP ) {
        !           357:               
        !           358:        if ( OptionName != TCP_NODELAY ) {
        !           359:            return WSAEINVAL;
        !           360:        }
        !           361: 
        !           362:        if ( context->SocketType == SOCK_DGRAM ) {
        !           363:            return WSAENOPROTOOPT;
        !           364:        }
        !           365: 
        !           366:        ZeroMemory( OptionValue, *OptionLength );
        !           367: 
        !           368:        *OptionValue = context->NoDelay;
        !           369:        *OptionLength = sizeof(int);
        !           370: 
        !           371:        return NO_ERROR;
        !           372:     }
        !           373: 
        !           374:     //
        !           375:     // Handle socket-level options.
        !           376:     //
        !           377: 
        !           378:     switch ( OptionName ) {
        !           379: 
        !           380:     case SO_KEEPALIVE:
        !           381: 
        !           382:        if ( context->SocketType == SOCK_DGRAM ) {
        !           383:            return WSAENOPROTOOPT;
        !           384:        }
        !           385: 
        !           386:        ZeroMemory( OptionValue, *OptionLength );
        !           387: 
        !           388:        *OptionValue = context->KeepAlive;
        !           389:        *OptionLength = sizeof(int);
        !           390: 
        !           391:        break;
        !           392: 
        !           393:     case SO_DONTROUTE:
        !           394: 
        !           395:        ZeroMemory( OptionValue, *OptionLength );
        !           396: 
        !           397:        *OptionValue = context->DontRoute;
        !           398:        *OptionLength = sizeof(int);
        !           399: 
        !           400:        break;
        !           401: 
        !           402:     default:
        !           403: 
        !           404:        return WSAENOPROTOOPT;
        !           405:     }
        !           406: 
        !           407:     return NO_ERROR;
        !           408: 
        !           409: } // WSHGetSocketInformation
        !           410: 
        !           411: 
        !           412: INT
        !           413: WINAPI
        !           414: WSHGetWildcardSockaddr (
        !           415:     IN PVOID HelperDllSocketContext,
        !           416:     OUT PSOCKADDR Sockaddr,
        !           417:     OUT PINT SockaddrLength
        !           418:     )
        !           419: 
        !           420: /*++
        !           421: 
        !           422: Routine Description:
        !           423: 
        !           424:     This routine returns a wildcard socket address.  A wildcard address
        !           425:     is one which will bind the socket to an endpoint of the transport's
        !           426:     choosing.  For TCP/IP, a wildcard address has IP address ==
        !           427:     0.0.0.0 and port = 0.
        !           428: 
        !           429: Arguments:
        !           430: 
        !           431:     HelperDllSocketContext - the context pointer returned from
        !           432:        WSHOpenSocket() for the socket for which we need a wildcard
        !           433:        address.
        !           434: 
        !           435:     Sockaddr - points to a buffer which will receive the wildcard socket
        !           436:        address.
        !           437: 
        !           438:     SockaddrLength - receives the length of the wioldcard sockaddr.
        !           439: 
        !           440: Return Value:
        !           441: 
        !           442:     INT - a winsock error code indicating the status of the operation, or
        !           443:        NO_ERROR if the operation succeeded.
        !           444: 
        !           445: --*/
        !           446: 
        !           447: {
        !           448:     if ( *SockaddrLength < sizeof(SOCKADDR_IN) ) {
        !           449:        return WSAEFAULT;
        !           450:     }
        !           451: 
        !           452:     *SockaddrLength = sizeof(SOCKADDR_IN);
        !           453: 
        !           454:     //
        !           455:     // Just zero out the address and set the family to AF_INET--this is 
        !           456:     // a wildcard address for TCP/IP.  
        !           457:     //
        !           458: 
        !           459:     ZeroMemory( Sockaddr, sizeof(SOCKADDR_IN) );
        !           460: 
        !           461:     Sockaddr->sa_family = AF_INET;
        !           462: 
        !           463:     return NO_ERROR;
        !           464: 
        !           465: } // WSAGetWildcardSockaddr
        !           466: 
        !           467: 
        !           468: DWORD
        !           469: WINAPI
        !           470: WSHGetWinsockMapping (
        !           471:     OUT PWINSOCK_MAPPING Mapping,
        !           472:     IN DWORD MappingLength
        !           473:     )
        !           474: 
        !           475: /*++
        !           476: 
        !           477: Routine Description:
        !           478: 
        !           479:     Returns the list of address family/socket type/protocol triples
        !           480:     supported by this helper DLL.
        !           481: 
        !           482: Arguments:
        !           483: 
        !           484:     Mapping - receives a pointer to a WINSOCK_MAPPING structure that
        !           485:        describes the triples supported here.
        !           486: 
        !           487:     MappingLength - the length, in bytes, of the passed-in Mapping buffer.
        !           488: 
        !           489: Return Value:
        !           490: 
        !           491:     DWORD - the length, in bytes, of a WINSOCK_MAPPING structure for this
        !           492:        helper DLL.  If the passed-in buffer is too small, the return
        !           493:        value will indicate the size of a buffer needed to contain
        !           494:        the WINSOCK_MAPPING structure.
        !           495: 
        !           496: --*/
        !           497: 
        !           498: {
        !           499:     DWORD mappingLength;
        !           500: 
        !           501:     mappingLength = sizeof(WINSOCK_MAPPING) - sizeof(MAPPING_TRIPLE) +
        !           502:                        sizeof(TcpMappingTriples) + sizeof(UdpMappingTriples);
        !           503: 
        !           504:     //
        !           505:     // If the passed-in buffer is too small, return the length needed
        !           506:     // now without writing to the buffer.  The caller should allocate
        !           507:     // enough memory and call this routine again.
        !           508:     //
        !           509: 
        !           510:     if ( mappingLength > MappingLength ) {
        !           511:        return mappingLength;
        !           512:     }
        !           513: 
        !           514:     //
        !           515:     // Fill in the output mapping buffer with the list of triples
        !           516:     // supported in this helper DLL.
        !           517:     //
        !           518: 
        !           519:     Mapping->Rows = sizeof(TcpMappingTriples) / sizeof(TcpMappingTriples[0])
        !           520:                     + sizeof(UdpMappingTriples) / sizeof(UdpMappingTriples[0]);
        !           521:     Mapping->Columns = sizeof(MAPPING_TRIPLE) / sizeof(DWORD);
        !           522:     MoveMemory(
        !           523:        Mapping->Mapping,
        !           524:        TcpMappingTriples,
        !           525:        sizeof(TcpMappingTriples)
        !           526:        );
        !           527:     MoveMemory(
        !           528:        (PCHAR)Mapping->Mapping + sizeof(TcpMappingTriples),
        !           529:        UdpMappingTriples,
        !           530:        sizeof(UdpMappingTriples)
        !           531:        );
        !           532: 
        !           533:     //
        !           534:     // Return the number of bytes we wrote.
        !           535:     //
        !           536: 
        !           537:     return mappingLength;
        !           538: 
        !           539: } // WSHGetWinsockMapping
        !           540: 
        !           541: 
        !           542: INT
        !           543: WINAPI
        !           544: WSHOpenSocket (
        !           545:     IN OUT PINT AddressFamily,
        !           546:     IN OUT PINT SocketType,
        !           547:     IN OUT PINT Protocol,
        !           548:     OUT PUNICODE_STRING TransportDeviceName,
        !           549:     OUT PVOID *HelperDllSocketContext,
        !           550:     OUT PDWORD NotificationEvents
        !           551:     )
        !           552: 
        !           553: /*++
        !           554: 
        !           555: Routine Description:
        !           556: 
        !           557:     Does the necessary work for this helper DLL to open a socket and is
        !           558:     called by the winsock DLL in the socket() routine.  This routine
        !           559:     verifies that the specified triple is valid, determines the NT
        !           560:     device name of the TDI provider that will support that triple,
        !           561:     allocates space to hold the socket's context block, and
        !           562:     canonicalizes the triple.
        !           563: 
        !           564: Arguments:
        !           565: 
        !           566:     AddressFamily - on input, the address family specified in the
        !           567:        socket() call.  On output, the canonicalized value for the
        !           568:        address family.
        !           569: 
        !           570:     SocketType - on input, the socket type specified in the socket()
        !           571:        call.  On output, the canonicalized value for the socket type.
        !           572: 
        !           573:     Protocol - on input, the protocol specified in the socket() call.
        !           574:        On output, the canonicalized value for the protocol.
        !           575: 
        !           576:     TransportDeviceName - receives the name of the TDI provider that
        !           577:        will support the specified triple.
        !           578: 
        !           579:     HelperDllSocketContext - receives a context pointer that the winsock
        !           580:        DLL will return to this helper DLL on future calls involving
        !           581:        this socket.
        !           582: 
        !           583:     NotificationEvents - receives a bitmask of those state transitions
        !           584:        this helper DLL should be notified on.
        !           585: 
        !           586: Return Value:
        !           587: 
        !           588:     INT - a winsock error code indicating the status of the operation, or
        !           589:        NO_ERROR if the operation succeeded.
        !           590: 
        !           591: --*/
        !           592: 
        !           593: {
        !           594:     PWSHTCPIP_SOCKET_CONTEXT context;
        !           595: 
        !           596:     //
        !           597:     // Determine whether this is to be a TCP or UDP socket.
        !           598:     //
        !           599: 
        !           600:     if ( IsTripleInList(
        !           601:             TcpMappingTriples,
        !           602:             sizeof(TcpMappingTriples) / sizeof(TcpMappingTriples[0]),
        !           603:             *AddressFamily,
        !           604:             *SocketType,
        !           605:             *Protocol ) ) {
        !           606: 
        !           607:        //
        !           608:        // Return the canonical form of a TCP socket triple.
        !           609:        //
        !           610: 
        !           611:        *AddressFamily = TcpMappingTriples[0].AddressFamily;
        !           612:        *SocketType = TcpMappingTriples[0].SocketType;
        !           613:        *Protocol = TcpMappingTriples[0].Protocol;
        !           614: 
        !           615:        //
        !           616:        // Indicate the name of the TDI device that will service
        !           617:        // SOCK_STREAM sockets in the internet address family.
        !           618:        //
        !           619: 
        !           620:        RtlInitUnicodeString( TransportDeviceName, L"\\Device\\Streams\\Tcp" );
        !           621: 
        !           622:     } else if ( IsTripleInList(
        !           623:                    UdpMappingTriples,
        !           624:                    sizeof(UdpMappingTriples) / sizeof(UdpMappingTriples[0]),
        !           625:                    *AddressFamily,
        !           626:                    *SocketType,
        !           627:                    *Protocol ) ) {
        !           628: 
        !           629:        //
        !           630:        // Return the canonical form of a UDP socket triple.
        !           631:        //
        !           632: 
        !           633:        *AddressFamily = UdpMappingTriples[0].AddressFamily;
        !           634:        *SocketType = UdpMappingTriples[0].SocketType;
        !           635:        *Protocol = UdpMappingTriples[0].Protocol;
        !           636: 
        !           637:        //
        !           638:        // Indicate the name of the TDI device that will service
        !           639:        // SOCK_DGRAM sockets in the internet address family.
        !           640:        //
        !           641: 
        !           642:        RtlInitUnicodeString( TransportDeviceName, L"\\Device\\Streams\\Udp" );
        !           643: 
        !           644:     } else {
        !           645: 
        !           646:        //
        !           647:        // This should never happen if the registry information about this
        !           648:        // helper DLL is correct.  If somehow this did happen, just return
        !           649:        // an error.
        !           650:        //
        !           651: 
        !           652:        return WSAEINVAL;
        !           653:     }
        !           654: 
        !           655:     //
        !           656:     // Allocate context for this socket.  The Windows Sockets DLL will
        !           657:     // return this value to us when it asks us to get/set socket options.
        !           658:     //
        !           659: 
        !           660:     context = (PWSHTCPIP_SOCKET_CONTEXT) HeapAlloc(
        !           661:                                                                                 GetProcessHeap(),
        !           662:                                                                                 0,
        !           663:                                                                                 sizeof(*context)
        !           664:                                                                                 );
        !           665:     if ( context == NULL ) {
        !           666:        return WSAENOBUFS;
        !           667:     }
        !           668: 
        !           669:     //
        !           670:     // Initialize the context for the socket.
        !           671:     //
        !           672: 
        !           673:     context->AddressFamily = *AddressFamily;
        !           674:     context->SocketType = *SocketType;
        !           675:     context->Protocol = *Protocol;
        !           676:     context->ReceiveBufferSize = DEFAULT_RECEIVE_BUFFER_SIZE;
        !           677:     context->KeepAlive = FALSE;
        !           678:     context->DontRoute = FALSE;
        !           679:     context->NoDelay = FALSE;
        !           680: 
        !           681:     //
        !           682:     // Tell the Windows Sockets DLL which state transitions we're
        !           683:     // interested in being notified of.  The only time we need to be
        !           684:     // called is after a connect has completed so that we can turn on
        !           685:     // the sending of keepalives if SO_KEEPALIVE was set before the
        !           686:     // socket was connected.
        !           687:     //
        !           688: 
        !           689:     *NotificationEvents = WSH_NOTIFY_CONNECT | WSH_NOTIFY_CLOSE;
        !           690: 
        !           691:     //
        !           692:     // Everything worked, return success.
        !           693:     //
        !           694: 
        !           695:     *HelperDllSocketContext = context;
        !           696:     return NO_ERROR;
        !           697: 
        !           698: } // WSHOpenSocket
        !           699: 
        !           700: 
        !           701: INT
        !           702: WINAPI
        !           703: WSHNotify (
        !           704:     IN PVOID HelperDllSocketContext,
        !           705:     IN SOCKET SocketHandle,
        !           706:     IN HANDLE TdiAddressObjectHandle,
        !           707:     IN HANDLE TdiConnectionObjectHandle,
        !           708:     IN DWORD NotifyEvent
        !           709:     )
        !           710: 
        !           711: /*++
        !           712: 
        !           713: Routine Description:
        !           714: 
        !           715:     This routine is called by the winsock DLL after a state transition
        !           716:     of the socket.  Only state transitions returned in the
        !           717:     NotificationEvents parameter of WSHOpenSocket() are notified here.
        !           718:     This routine allows a winsock helper DLL to track the state of
        !           719:     socket and perform necessary actions corresponding to state
        !           720:     transitions.
        !           721: 
        !           722: Arguments:
        !           723: 
        !           724:     HelperDllSocketContext - the context pointer given to the winsock
        !           725:        DLL by WSHOpenSocket().
        !           726: 
        !           727:     SocketHandle - the handle for the socket.
        !           728: 
        !           729:     TdiAddressObjectHandle - the TDI address object of the socket, if
        !           730:        any.  If the socket is not yet bound to an address, then
        !           731:        it does not have a TDI address object and this parameter
        !           732:        will be NULL.
        !           733: 
        !           734:     TdiConnectionObjectHandle - the TDI connection object of the socket,
        !           735:        if any.  If the socket is not yet connected, then it does not
        !           736:        have a TDI connection object and this parameter will be NULL.
        !           737: 
        !           738:     NotifyEvent - indicates the state transition for which we're being
        !           739:        called.
        !           740: 
        !           741: Return Value:
        !           742: 
        !           743:     INT - a winsock error code indicating the status of the operation, or
        !           744:        NO_ERROR if the operation succeeded.
        !           745: 
        !           746: --*/
        !           747: 
        !           748: {
        !           749:     PWSHTCPIP_SOCKET_CONTEXT context = HelperDllSocketContext;
        !           750:     INT err;
        !           751: 
        !           752:     //
        !           753:     // We should only be called after a connect() completes or when the
        !           754:     // socket is being closed.
        !           755:     //
        !           756: 
        !           757:     if ( NotifyEvent == WSH_NOTIFY_CONNECT ) {
        !           758: 
        !           759:        //
        !           760:        // SO_KEEPALIVE or TCP_NODELAY was set before the socket was 
        !           761:        // connected.  Set it now.  
        !           762:        //
        !           763: 
        !           764:        if ( context->KeepAlive ) {
        !           765:            err = DoTdiAction(
        !           766:                      TdiConnectionObjectHandle,
        !           767:                      TOL_TLI,
        !           768:                      TO_KEEPALIVE,
        !           769:                      TRUE
        !           770:                      );
        !           771:            if ( err != NO_ERROR ) {
        !           772:                return err;
        !           773:            }
        !           774:        }
        !           775: 
        !           776:        if ( context->NoDelay ) {
        !           777:            err = DoTdiAction(
        !           778:                      TdiConnectionObjectHandle,
        !           779:                      TOL_TLI,
        !           780:                      TO_NODELAY,
        !           781:                      TRUE
        !           782:                      );
        !           783:            if ( err != NO_ERROR ) {
        !           784:                return err;
        !           785:            }
        !           786:        }
        !           787: 
        !           788:        if ( context->ReceiveBufferSize != DEFAULT_RECEIVE_BUFFER_SIZE ) {
        !           789:            err = DoTdiAction(
        !           790:                      TdiConnectionObjectHandle,
        !           791:                      TOL_RCVBUF,
        !           792:                      0,
        !           793:                      context->ReceiveBufferSize
        !           794:                      );
        !           795:            if ( err != NO_ERROR ) {
        !           796:                return err;
        !           797:            }
        !           798:        }
        !           799: 
        !           800:     } else if ( NotifyEvent == WSH_NOTIFY_CLOSE ) {
        !           801: 
        !           802:        //
        !           803:        // Just free the socket context.
        !           804:        //
        !           805: 
        !           806:        HeapFree( GetProcessHeap( ), 0, (LPSTR)HelperDllSocketContext );
        !           807: 
        !           808:     } else {
        !           809: 
        !           810:        return WSAEINVAL;
        !           811:     }
        !           812: 
        !           813: 
        !           814:     return NO_ERROR;
        !           815: 
        !           816: } // WSHNotify
        !           817: 
        !           818: 
        !           819: INT
        !           820: WINAPI
        !           821: WSHSetSocketInformation (
        !           822:     IN PVOID HelperDllSocketContext,
        !           823:     IN SOCKET SocketHandle,
        !           824:     IN HANDLE TdiAddressObjectHandle,
        !           825:     IN HANDLE TdiConnectionObjectHandle,
        !           826:     IN INT Level,
        !           827:     IN INT OptionName,
        !           828:     IN PCHAR OptionValue,
        !           829:     IN INT OptionLength
        !           830:     )
        !           831: 
        !           832: /*++
        !           833: 
        !           834: Routine Description:
        !           835: 
        !           836:     This routine sets information about a socket for those socket
        !           837:     options supported in this helper DLL.  The options supported here
        !           838:     are SO_KEEPALIVE and SO_DONTROUTE.  This routine is called by the
        !           839:     winsock DLL when a level/option name combination is passed to
        !           840:     setsockopt() that the winsock DLL does not understand.
        !           841: 
        !           842: Arguments:
        !           843: 
        !           844:     HelperDllSocketContext - the context pointer returned from
        !           845:        WSHOpenSocket().
        !           846: 
        !           847:     SocketHandle - the handle of the socket for which we're getting
        !           848:        information.
        !           849: 
        !           850:     TdiAddressObjectHandle - the TDI address object of the socket, if
        !           851:        any.  If the socket is not yet bound to an address, then
        !           852:        it does not have a TDI address object and this parameter
        !           853:        will be NULL.
        !           854: 
        !           855:     TdiConnectionObjectHandle - the TDI connection object of the socket,
        !           856:        if any.  If the socket is not yet connected, then it does not
        !           857:        have a TDI connection object and this parameter will be NULL.
        !           858: 
        !           859:     Level - the level parameter passed to setsockopt().
        !           860: 
        !           861:     OptionName - the optname parameter passed to setsockopt().
        !           862: 
        !           863:     OptionValue - the optval parameter passed to setsockopt().
        !           864: 
        !           865:     OptionLength - the optlen parameter passed to setsockopt().
        !           866: 
        !           867: Return Value:
        !           868: 
        !           869:     INT - a winsock error code indicating the status of the operation, or
        !           870:        NO_ERROR if the operation succeeded.
        !           871: 
        !           872: --*/
        !           873: 
        !           874: {
        !           875:     PWSHTCPIP_SOCKET_CONTEXT context = HelperDllSocketContext;
        !           876:     INT error;
        !           877:     INT optionValue;
        !           878: 
        !           879:     UNREFERENCED_PARAMETER( SocketHandle );
        !           880:     UNREFERENCED_PARAMETER( TdiAddressObjectHandle );
        !           881:     UNREFERENCED_PARAMETER( TdiConnectionObjectHandle );
        !           882: 
        !           883:     //
        !           884:     // Check if this is an internal request for context information.
        !           885:     //
        !           886: 
        !           887:     if ( Level == SOL_INTERNAL && OptionName == SO_CONTEXT ) {
        !           888: 
        !           889:        //
        !           890:        // The Windows Sockets DLL is requesting that we set context 
        !           891:        // information for a new socket.  If the new socket was 
        !           892:        // accept()'ed, then we have already been notified of the socket 
        !           893:        // and HelperDllSocketContext will be valid.  If the new socket 
        !           894:        // was inherited or duped into this process, then this is our 
        !           895:        // first notification of the socket and HelperDllSocketContext 
        !           896:        // will be equal to NULL.  
        !           897:        //
        !           898:        // Insure that the context information being passed to us is 
        !           899:        // sufficiently large.  
        !           900:        //
        !           901: 
        !           902:        if ( OptionLength < sizeof(*context) ) {
        !           903:            return WSAEINVAL;
        !           904:        }
        !           905: 
        !           906:        if ( HelperDllSocketContext == NULL ) {
        !           907:            
        !           908:            //
        !           909:            // This is our notification that a socket handle was 
        !           910:            // inherited or duped into this process.  Allocate a context 
        !           911:            // structure for the new socket.  
        !           912:            //
        !           913:     
        !           914:            context = (PWSHTCPIP_SOCKET_CONTEXT) HeapAlloc(
        !           915:                                                                                        GetProcessHeap(),
        !           916:                                                                                        0,
        !           917:                                                                                        sizeof(*context)
        !           918:                                                                                        );
        !           919:            if ( context == NULL ) {
        !           920:                return WSAENOBUFS;
        !           921:            }
        !           922:     
        !           923:            //
        !           924:            // Copy over information into the context block.
        !           925:            //
        !           926:     
        !           927:            CopyMemory( context, OptionValue, sizeof(*context) );
        !           928:     
        !           929:            //
        !           930:            // Tell the Windows Sockets DLL where our context information is 
        !           931:            // stored so that it can return the context pointer in future 
        !           932:            // calls.  
        !           933:            //
        !           934:     
        !           935:            *(PWSHTCPIP_SOCKET_CONTEXT *)OptionValue = context;
        !           936:     
        !           937:            return NO_ERROR;
        !           938: 
        !           939:        } else {
        !           940: 
        !           941:            PWSHTCPIP_SOCKET_CONTEXT parentContext;
        !           942:            INT one = 1;
        !           943: 
        !           944:            //
        !           945:            // The socket was accept()'ed and it needs to have the same 
        !           946:            // properties as it'sw parent.  The OptionValue buffer 
        !           947:            // contains the context information of this socket's parent.  
        !           948:            //
        !           949: 
        !           950:            parentContext = (PWSHTCPIP_SOCKET_CONTEXT)OptionValue;
        !           951: 
        !           952:            assert( context->AddressFamily == parentContext->AddressFamily );
        !           953:            assert( context->SocketType == parentContext->SocketType );
        !           954:            assert( context->Protocol == parentContext->Protocol );
        !           955: 
        !           956:            //
        !           957:            // Turn on in the child any options that have been set in
        !           958:            // the parent.
        !           959:            //
        !           960: 
        !           961:            if ( parentContext->KeepAlive ) {
        !           962: 
        !           963:                error = WSHSetSocketInformation(
        !           964:                            HelperDllSocketContext,
        !           965:                            SocketHandle,
        !           966:                            TdiAddressObjectHandle,
        !           967:                            TdiConnectionObjectHandle,
        !           968:                            SOL_SOCKET,
        !           969:                            SO_KEEPALIVE,
        !           970:                            (PCHAR)&one,
        !           971:                            sizeof(one)
        !           972:                            );
        !           973:                if ( error != NO_ERROR ) {
        !           974:                    return error;
        !           975:                }
        !           976:            }
        !           977: 
        !           978:            if ( parentContext->DontRoute ) {
        !           979: 
        !           980:                error = WSHSetSocketInformation(
        !           981:                            HelperDllSocketContext,
        !           982:                            SocketHandle,
        !           983:                            TdiAddressObjectHandle,
        !           984:                            TdiConnectionObjectHandle,
        !           985:                            SOL_SOCKET,
        !           986:                            SO_DONTROUTE,
        !           987:                            (PCHAR)&one,
        !           988:                            sizeof(one)
        !           989:                            );
        !           990:                if ( error != NO_ERROR ) {
        !           991:                    return error;
        !           992:                }
        !           993:            }
        !           994: 
        !           995:            if ( parentContext->NoDelay ) {
        !           996: 
        !           997:                error = WSHSetSocketInformation(
        !           998:                            HelperDllSocketContext,
        !           999:                            SocketHandle,
        !          1000:                            TdiAddressObjectHandle,
        !          1001:                            TdiConnectionObjectHandle,
        !          1002:                            IPPROTO_TCP,
        !          1003:                            TCP_NODELAY,
        !          1004:                            (PCHAR)&one,
        !          1005:                            sizeof(one)
        !          1006:                            );
        !          1007:                if ( error != NO_ERROR ) {
        !          1008:                    return error;
        !          1009:                }
        !          1010:            }
        !          1011: 
        !          1012:            if ( parentContext->ReceiveBufferSize != DEFAULT_RECEIVE_BUFFER_SIZE ) {
        !          1013: 
        !          1014:                error = WSHSetSocketInformation(
        !          1015:                            HelperDllSocketContext,
        !          1016:                            SocketHandle,
        !          1017:                            TdiAddressObjectHandle,
        !          1018:                            TdiConnectionObjectHandle,
        !          1019:                            SOL_SOCKET,
        !          1020:                            SO_RCVBUF,
        !          1021:                            (PCHAR)&parentContext->ReceiveBufferSize,
        !          1022:                            sizeof(parentContext->ReceiveBufferSize)
        !          1023:                            );
        !          1024:                if ( error != NO_ERROR ) {
        !          1025:                    return error;
        !          1026:                }
        !          1027:            }
        !          1028: 
        !          1029:            return NO_ERROR;
        !          1030:        }
        !          1031:     }
        !          1032: 
        !          1033:     //
        !          1034:     // The only other levels we support here are SOL_SOCKET and 
        !          1035:     // IPPROTO_TCP.  
        !          1036:     //
        !          1037: 
        !          1038:     if ( Level != SOL_SOCKET && Level != IPPROTO_TCP ) {
        !          1039:        return WSAEINVAL;
        !          1040:     }
        !          1041: 
        !          1042:     //
        !          1043:     // Make sure that the option length is sufficient.
        !          1044:     //
        !          1045: 
        !          1046:     if ( OptionLength < sizeof(int) ) {
        !          1047:        return WSAEFAULT;
        !          1048:     }
        !          1049: 
        !          1050:     optionValue = *(PINT)OptionValue;
        !          1051: 
        !          1052:     //
        !          1053:     // Handle TCP-level options.
        !          1054:     //
        !          1055: 
        !          1056:     if ( Level == IPPROTO_TCP ) {
        !          1057:               
        !          1058:        if ( OptionName != TCP_NODELAY ) {
        !          1059:            return WSAEINVAL;
        !          1060:        }
        !          1061: 
        !          1062:        if ( context->SocketType == SOCK_DGRAM ) {
        !          1063:            return WSAENOPROTOOPT;
        !          1064:        }
        !          1065: 
        !          1066:        //
        !          1067:        // Atempt to turn on or off Nagle's algorithm, as necessary.
        !          1068:        //
        !          1069: 
        !          1070:        if ( !context->NoDelay && optionValue != 0 ) {
        !          1071: 
        !          1072:            //
        !          1073:            // NoDelay is currently off and the application wants to 
        !          1074:            // turn it on.  If the TDI connection object handle is NULL, 
        !          1075:            // then the socket is not yet connected.  In this case we'll 
        !          1076:            // just remember that the no delay option was set and 
        !          1077:            // actually turn them on in WSHNotify() after a connect() 
        !          1078:            // has completed on the socket.  
        !          1079:            //
        !          1080: 
        !          1081:            if ( TdiConnectionObjectHandle != NULL ) {
        !          1082:                error = DoTdiAction(
        !          1083:                            TdiConnectionObjectHandle,
        !          1084:                            TOL_TLI,
        !          1085:                            TO_NODELAY,
        !          1086:                            TRUE
        !          1087:                            );
        !          1088:                if ( error != NO_ERROR ) {
        !          1089:                    return error;
        !          1090:                }
        !          1091:            }
        !          1092: 
        !          1093:            //
        !          1094:            // Remember that no delay is enabled for this socket.
        !          1095:            //
        !          1096: 
        !          1097:            context->NoDelay = TRUE;
        !          1098: 
        !          1099:        } else if ( context->NoDelay && optionValue == 0 ) {
        !          1100: 
        !          1101:            //
        !          1102:            // No delay is currently enabled and the application wants 
        !          1103:            // to turn it off.  If the TDI connection object is NULL, 
        !          1104:            // the socket is not yet connected.  In this case we'll just 
        !          1105:            // remember that nodelay is disabled.  
        !          1106:            //
        !          1107: 
        !          1108:            if ( TdiConnectionObjectHandle != NULL ) {
        !          1109:                error = DoTdiAction(
        !          1110:                            TdiConnectionObjectHandle,
        !          1111:                            TOL_TLI,
        !          1112:                            TO_NODELAY,
        !          1113:                            FALSE
        !          1114:                            );
        !          1115:                if ( error != NO_ERROR ) {
        !          1116:                    return error;
        !          1117:                }
        !          1118:            }
        !          1119: 
        !          1120:            //
        !          1121:            // Remember that no delay is disabled for this socket.
        !          1122:            //
        !          1123: 
        !          1124:            context->NoDelay = FALSE;
        !          1125:        }
        !          1126: 
        !          1127:        return NO_ERROR;
        !          1128:     }
        !          1129: 
        !          1130:     //
        !          1131:     // Handle socket-level options.
        !          1132:     //
        !          1133: 
        !          1134:     switch ( OptionName ) {
        !          1135: 
        !          1136:     case SO_KEEPALIVE:
        !          1137: 
        !          1138:        //
        !          1139:        // Atempt to turn on or off keepalive sending, as necessary.
        !          1140:        //
        !          1141: 
        !          1142:        if ( context->SocketType == SOCK_DGRAM ) {
        !          1143:            return WSAENOPROTOOPT;
        !          1144:        }
        !          1145: 
        !          1146:        if ( !context->KeepAlive && optionValue != 0 ) {
        !          1147: 
        !          1148:            //
        !          1149:            // Keepalives are currently off and the application wants to
        !          1150:            // turn them on.  If the TDI connection object handle is
        !          1151:            // NULL, then the socket is not yet connected.  In this case
        !          1152:            // we'll just remember that the keepalive option was set and
        !          1153:            // actually turn them on in WSHNotify() after a connect()
        !          1154:            // has completed on the socket.
        !          1155:            //
        !          1156: 
        !          1157:            if ( TdiConnectionObjectHandle != NULL ) {
        !          1158:                error = DoTdiAction(
        !          1159:                            TdiConnectionObjectHandle,
        !          1160:                            TOL_TLI,
        !          1161:                            TO_KEEPALIVE,
        !          1162:                            TRUE
        !          1163:                            );
        !          1164:                if ( error != NO_ERROR ) {
        !          1165:                    return error;
        !          1166:                }
        !          1167:            }
        !          1168: 
        !          1169:            //
        !          1170:            // Remember that keepalives are enabled for this socket.
        !          1171:            //
        !          1172: 
        !          1173:            context->KeepAlive = TRUE;
        !          1174: 
        !          1175:        } else if ( context->KeepAlive && optionValue == 0 ) {
        !          1176: 
        !          1177:            //
        !          1178:            // Keepalives are currently enabled and the application
        !          1179:            // wants to turn them off.  If the TDI connection object is
        !          1180:            // NULL, the socket is not yet connected.  In this case
        !          1181:            // we'll just remember that keepalives are disabled.
        !          1182:            //
        !          1183: 
        !          1184:            if ( TdiConnectionObjectHandle != NULL ) {
        !          1185:                error = DoTdiAction(
        !          1186:                            TdiConnectionObjectHandle,
        !          1187:                            TOL_TLI,
        !          1188:                            TO_KEEPALIVE,
        !          1189:                            FALSE
        !          1190:                            );
        !          1191:                if ( error != NO_ERROR ) {
        !          1192:                    return error;
        !          1193:                }
        !          1194:            }
        !          1195: 
        !          1196:            //
        !          1197:            // Remember that keepalives are disabled for this socket.
        !          1198:            //
        !          1199: 
        !          1200:            context->KeepAlive = FALSE;
        !          1201:        }
        !          1202: 
        !          1203:        break;
        !          1204: 
        !          1205:     case SO_DONTROUTE:
        !          1206: 
        !          1207:        //
        !          1208:        // We don't really support SO_DONTROUTE.  Just remember that the
        !          1209:        // option was set or unset.
        !          1210:        //
        !          1211: 
        !          1212:        if ( optionValue != 0 ) {
        !          1213:            context->DontRoute = TRUE;
        !          1214:        } else if ( optionValue == 0 ) {
        !          1215:            context->DontRoute = FALSE;
        !          1216:        }
        !          1217: 
        !          1218:        break;
        !          1219: 
        !          1220:     case SO_RCVBUF:
        !          1221: 
        !          1222:        //
        !          1223:        // If the receive buffer size is being changed, tell TCP about 
        !          1224:        // it.  Do nothing if this is a datagram.  
        !          1225:        //
        !          1226: 
        !          1227:        if ( context->ReceiveBufferSize == optionValue ||
        !          1228:                 context->SocketType == SOCK_DGRAM ) {
        !          1229:            break;
        !          1230:        }
        !          1231: 
        !          1232:        //
        !          1233:        // We need to pass the new receive buffer size to the TCP 
        !          1234:        // transport.  If the TDI connection object is NULL, the socket 
        !          1235:        // is not yet connected.  In this case we'll just remember the 
        !          1236:        // new buffer size and set it after the socket is connected.  
        !          1237:        //
        !          1238: 
        !          1239:        if ( TdiConnectionObjectHandle != NULL ) {
        !          1240:            error = DoTdiAction(
        !          1241:                        TdiConnectionObjectHandle,
        !          1242:                        TOL_RCVBUF,
        !          1243:                        0,
        !          1244:                        optionValue
        !          1245:                        );
        !          1246:            if ( error != NO_ERROR ) {
        !          1247:                return error;
        !          1248:            }
        !          1249:        }
        !          1250: 
        !          1251:        context->ReceiveBufferSize = optionValue;
        !          1252: 
        !          1253:        break;
        !          1254: 
        !          1255:     default:
        !          1256: 
        !          1257:        return WSAENOPROTOOPT;
        !          1258:     }
        !          1259: 
        !          1260:     return NO_ERROR;
        !          1261: 
        !          1262: } // WSHSetSocketInformation
        !          1263: 
        !          1264: 
        !          1265: BOOLEAN
        !          1266: IsTripleInList (
        !          1267:     IN PMAPPING_TRIPLE List,
        !          1268:     IN ULONG ListLength,
        !          1269:     IN INT AddressFamily,
        !          1270:     IN INT SocketType,
        !          1271:     IN INT Protocol
        !          1272:     )
        !          1273: 
        !          1274: /*++
        !          1275: 
        !          1276: Routine Description:
        !          1277: 
        !          1278:     Determines whether the specified triple has an exact match in the
        !          1279:     list of triples.
        !          1280: 
        !          1281: Arguments:
        !          1282: 
        !          1283:     List - a list of triples (address family/socket type/protocol) to
        !          1284:        search.
        !          1285: 
        !          1286:     ListLength - the number of triples in the list.
        !          1287: 
        !          1288:     AddressFamily - the address family to look for in the list.
        !          1289: 
        !          1290:     SocketType - the socket type to look for in the list.
        !          1291: 
        !          1292:     Protocol - the protocol to look for in the list.
        !          1293: 
        !          1294: Return Value:
        !          1295: 
        !          1296:     BOOLEAN - TRUE if the triple was found in the list, false if not.
        !          1297: 
        !          1298: --*/
        !          1299: 
        !          1300: {
        !          1301:     ULONG i;
        !          1302: 
        !          1303:     //
        !          1304:     // Walk through the list searching for an exact match.
        !          1305:     //
        !          1306: 
        !          1307:     for ( i = 0; i < ListLength; i++ ) {
        !          1308: 
        !          1309:        //
        !          1310:        // If all three elements of the triple match, return indicating
        !          1311:        // that the triple did exist in the list.
        !          1312:        //
        !          1313: 
        !          1314:        if ( AddressFamily == List[i].AddressFamily &&
        !          1315:             SocketType == List[i].SocketType &&
        !          1316:             Protocol == List[i].Protocol ) {
        !          1317:            return TRUE;
        !          1318:        }
        !          1319:     }
        !          1320: 
        !          1321:     //
        !          1322:     // The triple was not found in the list.
        !          1323:     //
        !          1324: 
        !          1325:     return FALSE;
        !          1326: 
        !          1327: } // IsTripleInList
        !          1328: 
        !          1329: 
        !          1330: INT
        !          1331: DoTdiAction (
        !          1332:     IN HANDLE TdiConnectionObjectHandle,
        !          1333:     IN INT OptionLevel,
        !          1334:     IN INT OptionName,
        !          1335:     IN INT OptionalData
        !          1336:     )
        !          1337: 
        !          1338: /*++
        !          1339: 
        !          1340: Routine Description:
        !          1341: 
        !          1342:     Performs a TDI action to the TCP/IP driver.  A TDI action translates
        !          1343:     into a streams T_OPTMGMT_REQ.
        !          1344: 
        !          1345: Arguments:
        !          1346: 
        !          1347:     TdiConnectionObjectHandle - a TDI connection object on which to perform
        !          1348:        the TDI action.
        !          1349: 
        !          1350:     OptionLevel - the opt_level to pass in the TOPT structure.
        !          1351: 
        !          1352:     OptionName - The TPI option to set.
        !          1353: 
        !          1354:     OptionalData - data to put in the opt_data field of the TOPT
        !          1355:        structure.
        !          1356: 
        !          1357: Return Value:
        !          1358: 
        !          1359:     INT - NO_ERROR, or a Windows Sockets error code.
        !          1360: 
        !          1361: --*/
        !          1362: 
        !          1363: {
        !          1364:     BOOLEAN deviceIoResult;
        !          1365:     PSTREAMS_TDI_ACTION tdiAction;
        !          1366:     ULONG tdiActionLength;
        !          1367:     TOPT *tpiOptions;
        !          1368:     ULONG outputLength;
        !          1369: 
        !          1370:     //
        !          1371:     // Allocate space to hold the TDI action buffer and the IO status
        !          1372:     // block.  These cannot be stack variables in case we must return
        !          1373:     // before the operation is complete.
        !          1374:     //
        !          1375: 
        !          1376:     tdiActionLength = sizeof(*tdiAction) + sizeof(*tpiOptions) -
        !          1377:                          sizeof(tdiAction->Buffer[0]);
        !          1378: 
        !          1379:     tdiAction = (PSTREAMS_TDI_ACTION) HeapAlloc(
        !          1380:                                                              GetProcessHeap( ),
        !          1381:                                                              0,
        !          1382:                                                              tdiActionLength
        !          1383:                                                              );
        !          1384:     if ( tdiAction == NULL ) {
        !          1385:        return WSAENOBUFS;
        !          1386:     }
        !          1387: 
        !          1388:     //
        !          1389:     // Initialize the TDI action buffer.
        !          1390:     //
        !          1391: 
        !          1392:     tdiAction->BufferLength = sizeof(*tpiOptions);
        !          1393: 
        !          1394:     tpiOptions = (TOPT *)tdiAction->Buffer;
        !          1395:     tpiOptions->opt_level = OptionLevel;
        !          1396:     tpiOptions->opt_name = OptionName;
        !          1397:     tpiOptions->opt_data[0] = OptionalData;
        !          1398: 
        !          1399:     //
        !          1400:     // Make the actual TDI action call.  The Streams TDI mapper will 
        !          1401:     // translate this into a TPI option management request for us and 
        !          1402:     // give it to TCP/IP.  
        !          1403:     //
        !          1404: 
        !          1405:     deviceIoResult = DeviceIoControl(
        !          1406:                                 TdiConnectionObjectHandle,
        !          1407:                                 IOCTL_TDI_ACTION,
        !          1408:                                 tdiAction,
        !          1409:                                 tdiActionLength,
        !          1410:                                 tdiAction,
        !          1411:                                 tdiActionLength,
        !          1412:                                 &outputLength,
        !          1413:                                 NULL
        !          1414:                                 );
        !          1415: 
        !          1416:     HeapFree( GetProcessHeap( ), 0, (LPSTR)tdiAction );
        !          1417: 
        !          1418:     return deviceIoResult ? NO_ERROR : WSAENOBUFS;
        !          1419: 
        !          1420: } // DoTdiAction

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.