Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

372 lines
11 KiB

/*++
Copyright (c) 1996 Microsoft Corporation
Module Name :
rnr.cxx (ripped out of tsvcinfo.cxx)
Abstract:
Defines the functions for TCP services Info class.
This module is intended to capture the common scheduler
code for the tcp services ( especially internet services)
which involves the Service Controller dispatch functions.
Also this class provides an interface for common dll of servers.
Author:
Murali R. Krishnan ( MuraliK ) 15-Nov-1994
Project:
Internet Servers Common DLL
--*/
#include "tcpdllp.hxx"
#include <tsunami.hxx>
#include <iistypes.hxx>
#define MAX_SOCKETS ( 20)
#if 0
inline
BOOL
IsConnectionOriented(
IN PPROTOCOL_INFO pProtocolInfo
)
{
return ( ( pProtocolInfo->dwServiceFlags & XP_CONNECTIONLESS) == 0);
} // IsConnectionOriented()
inline
BOOL
IsReliable(
IN PPROTOCOL_INFO pProtocolInfo
)
/*++
This should be a protocol which delivers all packets and in order in which
they are sent.
--*/
{
return ( ( pProtocolInfo->dwServiceFlags & XP_GUARANTEED_DELIVERY) &&
( pProtocolInfo->dwServiceFlags & XP_GUARANTEED_ORDER) &&
IsConnectionOriented( pProtocolInfo));
} // IsReliable()
INT
GetValidListenAddresses( IN LPCTSTR pszServiceName,
IN LPGUID lpServiceGuid,
IN PCSADDR_INFO pcsAddrInfo,
IN OUT LPDWORD lpcbAddrInfo )
/*++
This function obtains the list of valid listen addresses for the service
specified. It uses the RNR API set to enumerate the list of protocols
installed in a machine and queries using GetAddressByName() to obtain
the list of valid addresses that can be used for establishing a listen
socket.
Arguments:
pszServiceName pointer to null-terminated string containing service name.
lpServiceGuid pointer to GUID for the service.
pcsAddrInfo pointer to an array of CSADDR_INFO structures which
on successful return contains the address information.
lpcbAddInfo pointer to a DWORD containing the count of bytes
available under pcsAddrInfo. When this function is
called, it contains the number of bytes pointed to by
pcsAddrInfo. On return contains the number of
bytes required.
Returns:
count of valid CSADDR_INFO structures found for the given service to
establish a listen socket.
On error returns a value <= 0.
--*/
{
int nAddresses = 0; // assume a safe value == failure.
DWORD cbBuffer;
int cProtocols;
PPROTOCOL_INFO pProtocolInfo;
int rgProtocols[ MAX_SOCKETS + 1];
int * pProtocol;
int i;
BUFFER buff;
#define ENUM_PROTO_BUFF_SIZE 49152
//
// First Look up the protocols installed on this machine. The
// EnumProtocols() API returns about all the windows sockets protocols
// loaded on this machine. We will use this information to identify the
// protocols which provide the necessary semantics.
//
if ( !buff.Resize( ENUM_PROTO_BUFF_SIZE )) {
return 0;
}
cbBuffer = buff.QuerySize();
cProtocols = EnumProtocols( NULL, buff.QueryPtr(), &cbBuffer);
if ( cProtocols < 0) {
return 0;
}
//
// Walk through the available protocols and pick out the ones that
// support the desired characteristics.
//
for( pProtocolInfo = (PPROTOCOL_INFO ) buff.QueryPtr(),
pProtocol = rgProtocols,
i = 0;
( i < cProtocols &&
( pProtocol < rgProtocols + MAX_SOCKETS));
pProtocolInfo++, i++ ) {
if ( IsReliable( pProtocolInfo)) {
//
// This protocol matches our requirement of being reliable.
// Make a note of the protocol.
//
IF_DEBUG( DLL_SERVICE_INFO) {
DBGPRINTF( ( DBG_CONTEXT,
" Protocol %d ( %s) matches condition\n",
pProtocolInfo->iProtocol,
pProtocolInfo->lpProtocol));
}
*pProtocol++ = pProtocolInfo->iProtocol;
}
} // for() : Protocol filter ()
IF_DEBUG( DLL_SERVICE_INFO) {
DBGPRINTF( ( DBG_CONTEXT, " Filtering yields %d of %d protocols. \n",
( pProtocol - rgProtocols), cProtocols));
}
// terminate the protocols array.
*pProtocol = 0;
cProtocols = ( pProtocol - rgProtocols);
//
// Make sure we found at least one acceptable protocol.
// If there is no protocol on this machine, which suit our condition,
// this function fails.
//
if ( cProtocols > 0) {
//
// Use GetAddressByName() to get addresses for chosen protocols.
// We restrict the scope of the search to those protocols of interest
// by passing the protocols array we generated. The function
// returns socket addresses only for the protocols we can support.
//
nAddresses = GetAddressByName(
NS_DEFAULT, // lpszNameSpace
lpServiceGuid,
(char *) pszServiceName,
rgProtocols,
RES_SERVICE | RES_FIND_MULTIPLE,
NULL, // lpServiceAsyncInfo
(PVOID )pcsAddrInfo,
lpcbAddrInfo,
NULL, // lpAliasBuffer
NULL // lpdwAliasBufferLen
);
IF_DEBUG( DLL_SERVICE_INFO) {
// take a copy of error code and set it back, to avoid lost errors
DWORD dwError = GetLastError();
DBGPRINTF( ( DBG_CONTEXT,
" GetAddressByName() returned %d."
" Bytes Written=%d. Error = %ld\n",
nAddresses, *lpcbAddrInfo,
( nAddresses <= 0) ? dwError: NO_ERROR));
if ( nAddresses <= 0) { SetLastError( dwError); }
}
}
return ( nAddresses);
} // GetValidListenAddress()
#endif
BOOL
RegisterServiceForAdvertising(
IN LPCTSTR pszServiceName,
IN LPGUID lpServiceGuid,
IN SOCKET s,
IN BOOL fRegister
)
/*++
This function registers a service for the purpose of advertising.
By registering using RnR apis, we advertise the fact that this particular
service is running on the protocols designated. Hence RnR compliant
clients can get access to the same.
Arguments:
pszService name of the service
lpServiceGuid pointer to GUID for the service.
s socket whose address needs to be advertised.
fRegister whether to register to deregister
Returns:
TRUE on success and FALSE if there is any failure.
Use GetLastError() for further details on failure.
--*/
{
BOOL fReturn = TRUE;
#if 0
BYTE * pbAddressBuffer;
DWORD cbAddressBuffer;
INT err;
SERVICE_INFO serviceInfo;
SERVICE_ADDRESSES * pServiceAddress;
DBG_ASSERT( pszServiceName && lpServiceGuid );
DBG_ASSERT( s != INVALID_SOCKET );
/*++
Advertising service involves following steps:
1. Set up a service info structure.
2. Allocate memory for service addresses for as many sockets need to
be advertised.
3. Fill in the information containing the socket addresses
4. Execute call for advertising the service (use SetService( REGISTER)).
--*/
//
// Alloc space for SERVICE_ADDRESSES and n-1 SERVICE_ADDRESS structures.
//
pServiceAddress = ( ( SERVICE_ADDRESSES *)
TCP_ALLOC( sizeof( SERVICE_ADDRESSES) )
);
// Alloc space for SOCKADDR addresses returned.
cbAddressBuffer = sizeof(SOCKADDR);
pbAddressBuffer = (BYTE *) TCP_ALLOC(cbAddressBuffer);
if ( pServiceAddress == NULL || pbAddressBuffer == NULL) {
if ( pServiceAddress != NULL) { TCP_FREE( pServiceAddress); }
if ( pbAddressBuffer != NULL) { TCP_FREE( pbAddressBuffer); }
SetLastError( ERROR_NOT_ENOUGH_MEMORY);
return (FALSE);
}
//
// set up service info structure.
// Here the interesting fields are lpServiceType, lpServiceName,
// and lpServiceAddress fields.
//
serviceInfo.lpServiceType = lpServiceGuid ;
// surprisingly enough! RNR structures dont like constants
serviceInfo.lpServiceName = (LPTSTR ) pszServiceName ;
// do we need better comment ? NYI
serviceInfo.lpComment = "Microsoft Internet Services";
serviceInfo.lpLocale = NULL;
serviceInfo.lpMachineName = NULL ;
serviceInfo.dwVersion = 1;
serviceInfo.dwDisplayHint = 0;
serviceInfo.dwTime = 0;
serviceInfo.lpServiceAddress = pServiceAddress;
serviceInfo.ServiceSpecificInfo.cbSize = 0 ;
serviceInfo.ServiceSpecificInfo.pBlobData = NULL ;
//
// For each socket, get its local association and store the same.
//
PSOCKADDR pSockAddr = (PSOCKADDR ) pbAddressBuffer;
int size = (int) cbAddressBuffer;
//
// Call getsockname() to get the local association for the socket.
//
if ( getsockname( s, pSockAddr, &size) == 0 ) {
//
// Now setup the Addressing information for this socket.
// Only the dwAddressType, dwAddressLength and lpAddress
// is of any interest in this example.
//
pServiceAddress->Addresses[0].dwAddressType = pSockAddr->sa_family;
pServiceAddress->Addresses[0].dwAddressFlags = 0;
pServiceAddress->Addresses[0].dwAddressLength = size ;
pServiceAddress->Addresses[0].dwPrincipalLength= 0 ;
pServiceAddress->Addresses[0].lpAddress = (LPBYTE) pSockAddr;
pServiceAddress->Addresses[0].lpPrincipal = NULL ;
//
// Advance pointer and adjust buffer size. Assumes that
// the structures are aligned. Unaligned accesses !! NYI
//
cbAddressBuffer -= size;
pSockAddr = (PSOCKADDR) ((BYTE*)pSockAddr + size);
pServiceAddress->dwAddressCount = 1;
//
// If we got at least one address, go ahead and advertise it.
//
DWORD dwStatusFlags;
err = SetService(
NS_DEFAULT, // for all default name spaces
fRegister ? SERVICE_REGISTER : SERVICE_DEREGISTER,
0, // no flags specified
&serviceInfo, // SERVICE_INFO structure
NULL, // no async support yet
&dwStatusFlags) ; // returns status flags
IF_DEBUG( DLL_CONNECTION ) {
DBGPRINTF(( DBG_CONTEXT, " SetService(%s, NS_DEFAULT, Register=%d)"
" returns Status = %08x,"
" err = %d\n",
pszServiceName, fRegister,
dwStatusFlags, err));
}
} else {
SetLastError( ERROR_INVALID_PARAMETER);
fReturn = FALSE;
}
TCP_FREE( pbAddressBuffer);
TCP_FREE( pServiceAddress);
#endif
return ( fReturn);
} // RegisterServiceForAdvertising()