mirror of https://github.com/lianthony/NT4.0
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.
613 lines
14 KiB
613 lines
14 KiB
/*++
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
gdconf.cxx
|
|
|
|
Abstract:
|
|
|
|
This module contains functions for Gopher Server configuration
|
|
class (GSERVER_CONFIG).
|
|
|
|
Author:
|
|
|
|
Murali R. Krishnan (MuraliK) 30-Sept-1994
|
|
|
|
Project:
|
|
Gopher Server DLL
|
|
|
|
Functions Exported:
|
|
|
|
GSERVER_CONFIG::GSERVER_CONFIG()
|
|
GSERVER_CONFIG::~GSERVER_CONFIG()
|
|
DWORD GSERVER_CONFIG::InitFromRegistry(
|
|
IN HKEY hkeyReg,
|
|
IN FIELD_CONTROL FieldsToRead
|
|
)
|
|
VOID GSERVER_CONFIG::PrintConfiguration( VOID)
|
|
VOID GSERVER_CONFIG::DisconnectAllConnections( VOID)
|
|
BOOL GSERVER_CONFIG::InsertNewConnection(
|
|
IN OUT ICLIENT_CONNECTION * pcc);
|
|
VOID GSERVER_CONFIG::RemoveConnection(
|
|
IN OUT ICLIENT_CONNECTION * pcc);
|
|
BOOL GSERVER_CONFIG::ConvertGrPathToFullPath(
|
|
IN OUT STR & strGrPath,
|
|
OUT STR * pstrFullPath,
|
|
OUT HANDLE * phImpersonation,
|
|
OUT LPDWORD lpdwFileSystem) const
|
|
|
|
DWORD ReadRegistryDword()
|
|
|
|
Revisions:
|
|
|
|
MuraliK 2/20/1995 Moved some configuration information to TSVC_INFO
|
|
object. Modified GSERVER_CONFIG for the same.
|
|
|
|
--*/
|
|
|
|
|
|
# include "gdpriv.h"
|
|
# include "gdglobal.hxx"
|
|
# include "gdconf.hxx"
|
|
# include "iclient.hxx"
|
|
|
|
# include <tchar.h>
|
|
|
|
|
|
/************************************************************
|
|
* Symbolic Constants
|
|
************************************************************/
|
|
|
|
//
|
|
// Administration related data
|
|
//
|
|
# define DEFAULT_SITE TEXT("GopherSite")
|
|
# define DEFAULT_ORGANIZATION TEXT("")
|
|
# define DEFAULT_LOCATION TEXT("")
|
|
# define DEFAULT_LANGUAGE TEXT("En_US")
|
|
# define DEFAULT_GEOGRAPHY TEXT("")
|
|
# define DEFAULT_CHECK_FOR_WAISDB (FALSE)
|
|
|
|
|
|
|
|
/************************************************************
|
|
* Member Functions of GSERVER_CONFIG.
|
|
************************************************************/
|
|
|
|
GSERVER_CONFIG::GSERVER_CONFIG( VOID)
|
|
/*++
|
|
|
|
Description:
|
|
|
|
Constructor Function for Gopher Server Configuration Object
|
|
( Initializes all members to be NULL)
|
|
|
|
--*/
|
|
: m_strSite (),
|
|
m_strOrganization (),
|
|
m_strLocation (),
|
|
m_strGeography (),
|
|
m_strLanguage (),
|
|
m_fCheckForWaisDb (DEFAULT_CHECK_FOR_WAISDB),
|
|
m_strLocalHostName ()
|
|
{
|
|
|
|
m_fValid = FALSE;
|
|
|
|
m_cCurrentConnections =
|
|
m_cMaxCurrentConnections = 0;
|
|
|
|
InitializeListHead( &m_ConnectionsList);
|
|
InitializeCriticalSection( &m_csLock);
|
|
|
|
return;
|
|
|
|
} /* GSERVER_CONFIG::GSERVER_CONFIG() */
|
|
|
|
|
|
|
|
|
|
GSERVER_CONFIG::~GSERVER_CONFIG( VOID)
|
|
/*++
|
|
Description:
|
|
|
|
Destructor function for gopher server config object.
|
|
( Frees all dynamically allocated storage space)
|
|
--*/
|
|
{
|
|
|
|
//
|
|
// The strings are automatically freed by a call to destructor
|
|
//
|
|
|
|
//
|
|
// Delete the critical section object
|
|
//
|
|
|
|
DeleteCriticalSection( &m_csLock);
|
|
|
|
} /* GSERVER_CONFIG::~GSERVER_CONFIG() */
|
|
|
|
|
|
|
|
|
|
|
|
DWORD
|
|
GSERVER_CONFIG::InitFromRegistry(
|
|
IN HKEY hkeyReg,
|
|
IN FIELD_CONTROL FieldsToRead)
|
|
/*++
|
|
Description:
|
|
Initializes server configuration data from registry for Gopher Service.
|
|
Some values are also initialized with constants.
|
|
If invalid registry key or load data from registry fails,
|
|
then use default values.
|
|
|
|
Arguments:
|
|
|
|
hkeyReg handle to registry key
|
|
|
|
FieldsToRead
|
|
bitmask indicating the fields to read from the registry.
|
|
This is useful when we try to read the new values after
|
|
modifying the registry information as a result of
|
|
SetAdminInfo call from the Admin UI
|
|
|
|
Returns:
|
|
|
|
NO_ERROR if there are no errors.
|
|
Win32 error codes otherwise
|
|
|
|
Limitations:
|
|
|
|
No validity check is performed on the data present in registry.
|
|
--*/
|
|
{
|
|
BOOL fSuccess = TRUE;
|
|
|
|
if ( hkeyReg == INVALID_HANDLE_VALUE) {
|
|
|
|
//
|
|
// Invalid Registry handle given
|
|
//
|
|
|
|
SetLastError( ERROR_INVALID_PARAMETER);
|
|
return ( FALSE);
|
|
}
|
|
|
|
LockConfig();
|
|
//
|
|
// Read registry data.
|
|
//
|
|
|
|
if ( fSuccess && IsFieldSet( FieldsToRead, GDA_CHECK_FOR_WAISDB)) {
|
|
|
|
m_fCheckForWaisDb = !!ReadRegistryDword( hkeyReg,
|
|
GOPHERD_CHECK_FOR_WAISDB,
|
|
DEFAULT_CHECK_FOR_WAISDB
|
|
);
|
|
}
|
|
|
|
if ( fSuccess && IsFieldSet( FieldsToRead, GDA_SITE)) {
|
|
|
|
fSuccess = ReadRegistryStr( hkeyReg,
|
|
m_strSite,
|
|
GOPHERD_SITE,
|
|
DEFAULT_SITE);
|
|
}
|
|
|
|
if ( fSuccess && IsFieldSet( FieldsToRead, GDA_ORGANIZATION)) {
|
|
|
|
fSuccess = ReadRegistryStr( hkeyReg,
|
|
m_strOrganization,
|
|
GOPHERD_ORGANIZATION,
|
|
DEFAULT_ORGANIZATION);
|
|
}
|
|
|
|
if ( fSuccess && IsFieldSet( FieldsToRead, GDA_LOCATION)) {
|
|
|
|
fSuccess = ReadRegistryStr( hkeyReg,
|
|
m_strLocation,
|
|
GOPHERD_LOCATION,
|
|
DEFAULT_LOCATION);
|
|
}
|
|
|
|
if ( fSuccess && IsFieldSet( FieldsToRead, GDA_GEOGRAPHY)) {
|
|
|
|
fSuccess = ReadRegistryStr( hkeyReg,
|
|
m_strGeography,
|
|
GOPHERD_GEOGRAPHY,
|
|
DEFAULT_GEOGRAPHY);
|
|
}
|
|
|
|
if ( fSuccess && IsFieldSet( FieldsToRead, GDA_LANGUAGE)) {
|
|
|
|
fSuccess = ReadRegistryStr( hkeyReg,
|
|
m_strLanguage,
|
|
GOPHERD_LANGUAGE,
|
|
DEFAULT_LANGUAGE);
|
|
}
|
|
|
|
if ( !fSuccess) {
|
|
|
|
//
|
|
// Error in reading registry information for atleast one of the strings
|
|
//
|
|
DWORD dwError = GetLastError();
|
|
|
|
DBG_CODE(
|
|
DBGPRINTF( ( DBG_CONTEXT,
|
|
"InitFromRegistry() failed. Error = %u\n",
|
|
dwError));
|
|
);
|
|
|
|
return ( dwError);
|
|
}
|
|
|
|
UnLockConfig();
|
|
|
|
DEBUG_IF( CONFIG, {
|
|
PrintConfiguration();
|
|
});
|
|
|
|
m_fValid = TRUE;
|
|
|
|
return ( NO_ERROR);
|
|
|
|
} /* GSERVER_CONFIG::InitFromRegistry() */
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
static BOOL
|
|
RemoveInvalidsInPath( IN OUT TCHAR * pszPath)
|
|
/*++
|
|
Eliminate path components consisting of '.' and '..'
|
|
to prevent security from being overridden
|
|
|
|
Arguments:
|
|
|
|
pszPath pointer to string containing path
|
|
|
|
Returns:
|
|
TRUE on success and
|
|
FALSE if there is any failure
|
|
--*/
|
|
{
|
|
int idest;
|
|
TCHAR * pszScan;
|
|
|
|
//
|
|
// Check and eliminate the invalid path components
|
|
//
|
|
|
|
for( pszScan = pszPath; *pszScan != TEXT( '\0'); pszScan++) {
|
|
|
|
if ( *pszScan == TEXT( '/')) {
|
|
|
|
//
|
|
// Check and kill invalid path components before next back-slash
|
|
//
|
|
if ( *(pszScan + 1) == TEXT( '.')) {
|
|
|
|
if ( *(pszScan +2) == TEXT('/')) {
|
|
|
|
pszScan += 2; // skip the /./ pattern
|
|
|
|
} else
|
|
if ( *(pszScan +2) == TEXT('.') &&
|
|
*(pszScan +3) == TEXT('/')) {
|
|
|
|
//
|
|
// We found the pattern /../, elimiate it
|
|
//
|
|
pszScan += 3;
|
|
}
|
|
|
|
*pszPath++ = *pszScan;
|
|
continue;
|
|
|
|
} // found a single /.
|
|
|
|
}
|
|
|
|
*pszPath++ = *pszScan;
|
|
|
|
} // for
|
|
|
|
*pszPath = TEXT( '\0');
|
|
|
|
return ( TRUE);
|
|
|
|
} // RemoveInvalidsInPath()
|
|
|
|
|
|
# endif // 0
|
|
|
|
|
|
BOOL
|
|
GSERVER_CONFIG::ConvertGrPathToFullPath(
|
|
IN OUT STR & strGrPath,
|
|
OUT STR * pstrFullPath,
|
|
OUT HANDLE * phImpersonation, // Optional
|
|
OUT LPDWORD lpdwFileSystem // Optional
|
|
) const
|
|
/*++
|
|
|
|
Convert the partial path received from a Gopher request into
|
|
full path relative to the virtual volume that matches
|
|
the given path. The new path is returned in pstrFullPath.
|
|
|
|
Arguments:
|
|
|
|
strGrPath string containing the Gopher request path
|
|
This is of the form <volume-name>\<path-within-volume>
|
|
|
|
pstrFullPath pointer to string to return the full path
|
|
|
|
phImpersonation - pointer to handle that contains the
|
|
impersonation token on return, if any.
|
|
|
|
lpdwFileSystem pointer to DWORD to store file system type
|
|
|
|
Returns:
|
|
|
|
TRUE on successful conversion
|
|
FALSE if there is any error and the error code can be retrieved using
|
|
GetLastError().
|
|
|
|
--*/
|
|
{
|
|
BOOL fReturn;
|
|
CHAR rgchRealPath[ MAX_PATH + 1];
|
|
DWORD cbSize;
|
|
BOOL fValid = FALSE;
|
|
|
|
if ( lpdwFileSystem != NULL) {
|
|
|
|
*lpdwFileSystem = FS_FAT;
|
|
}
|
|
|
|
rgchRealPath[0] = '\0';
|
|
cbSize = MAX_PATH;
|
|
|
|
fReturn = ( CanonURL( &strGrPath, &fValid) && fValid &&
|
|
TsLookupVirtualRoot( g_pTsvcInfo->GetTsvcCache(),
|
|
strGrPath.QueryStr(),
|
|
rgchRealPath,
|
|
&cbSize,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
phImpersonation,
|
|
NULL,
|
|
lpdwFileSystem) &&
|
|
pstrFullPath->Copy( rgchRealPath));
|
|
|
|
if ( !fReturn) {
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT, "Error %u in mapping virtual path (%s)\n",
|
|
GetLastError(),
|
|
strGrPath.QueryStr()));
|
|
}
|
|
|
|
return ( fReturn);
|
|
|
|
} // GSERVER_CONFIG::ConvertGrPathToFullPath()
|
|
|
|
|
|
|
|
|
|
# if DBG
|
|
|
|
VOID
|
|
GSERVER_CONFIG::PrintConfiguration( VOID)
|
|
/*++
|
|
|
|
Description:
|
|
|
|
Prints the configuration information for this server.
|
|
To be used in debugging mode for verification.
|
|
|
|
|
|
Returns:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
DBGPRINTF( ( DBG_CONTEXT, "\n Gopher Server Configuration \n"));
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT, " %20s= %s\n", GOPHERD_SITE,
|
|
m_strSite.QueryStr()));
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT, " %20s= %s\n", GOPHERD_ORGANIZATION,
|
|
m_strOrganization.QueryStr()));
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT, " %20s= %s\n", GOPHERD_LOCATION,
|
|
m_strLocation.QueryStr()));
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT, " %20s= %s\n", GOPHERD_LANGUAGE,
|
|
m_strLanguage.QueryStr()));
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT, " %20s= %s\n", GOPHERD_GEOGRAPHY,
|
|
m_strGeography.QueryStr()));
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT, " %20s= %s\n", "Current Connections",
|
|
m_cCurrentConnections));
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT, " %20s= %s\n", "Max(CurrentConnections)",
|
|
m_cMaxCurrentConnections));
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT, " %20s= %s\n", "CheckForWaisDb",
|
|
m_fCheckForWaisDb));
|
|
|
|
return;
|
|
|
|
} // GSERVER_CONFIG::PrintConfiguration()
|
|
|
|
|
|
# endif // DBG
|
|
|
|
|
|
|
|
|
|
BOOL
|
|
GSERVER_CONFIG::InsertNewConnection( IN OUT ICLIENT_CONNECTION * pcc)
|
|
/*++
|
|
|
|
Adds the new client connection to the list
|
|
of client connections and increments the count of
|
|
clients currently connected to server.
|
|
|
|
We enter a critical section to avoid race condition
|
|
among different threads.
|
|
|
|
If the count of max connections is exceeded, then the
|
|
new connection is rejected.
|
|
|
|
Arguments:
|
|
|
|
pcc pointer to client connection to be added
|
|
|
|
Returns:
|
|
TRUE on success and
|
|
FALSE if there is max Connections exceeded.
|
|
--*/
|
|
{
|
|
|
|
BOOL fAllowConnection = FALSE;
|
|
|
|
LockConfig();
|
|
|
|
if ( (m_cCurrentConnections + 1) <= g_pTsvcInfo->QueryMaxConnections()) {
|
|
|
|
//
|
|
// We can add this new connection
|
|
//
|
|
|
|
fAllowConnection = TRUE;
|
|
|
|
//
|
|
// Increment the count of connected users
|
|
//
|
|
m_cCurrentConnections++;
|
|
|
|
//
|
|
// Update the current maximum connections
|
|
//
|
|
if ( m_cCurrentConnections > m_cMaxCurrentConnections) {
|
|
|
|
m_cMaxCurrentConnections = m_cCurrentConnections;
|
|
}
|
|
|
|
//
|
|
// Insert into the list of connected users.
|
|
//
|
|
InsertHeadList( &m_ConnectionsList, &pcc->QueryListEntry());
|
|
}
|
|
|
|
UnLockConfig();
|
|
|
|
return ( fAllowConnection);
|
|
|
|
} // GSERVER_CONFIG::InsertNewConnection()
|
|
|
|
|
|
|
|
|
|
VOID
|
|
GSERVER_CONFIG::DisconnectAllConnections( VOID)
|
|
/*++
|
|
|
|
Disconnects all user connections.
|
|
|
|
--*/
|
|
{
|
|
int i;
|
|
PLIST_ENTRY pEntry;
|
|
|
|
DBGPRINTF( ( DBG_CONTEXT,
|
|
"Entering GSERVER_CONFIG::DisconnectAllConnections()\n"));
|
|
|
|
LockConfig();
|
|
|
|
//
|
|
// close down all the active sockets.
|
|
//
|
|
for( pEntry = m_ConnectionsList.Flink;
|
|
pEntry != &m_ConnectionsList;
|
|
pEntry = pEntry->Flink) {
|
|
|
|
PICLIENT_CONNECTION pConn =
|
|
CONTAINING_RECORD( pEntry, ICLIENT_CONNECTION, m_listEntry);
|
|
ASSERT( pConn != NULL);
|
|
|
|
IF_DEBUG( ERROR) {
|
|
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
" Disconnecting client %08x\n", pConn));
|
|
DBG_CODE(pConn->Print());
|
|
}
|
|
|
|
pConn->DisconnectClient( ERROR_SERVER_DISABLED); // CloseSocket();
|
|
}
|
|
|
|
UnLockConfig();
|
|
|
|
//
|
|
// Wait for the users to die.
|
|
// The connection objects should be automatically freed because the
|
|
// socket has been closed. Subsequent requests will fail
|
|
// and cause a blowaway of the connection objects.
|
|
// looping is used to get out as early as possible when m_cCurrentConn == 0
|
|
//
|
|
|
|
for( i = 0 ;
|
|
( i < GD_CLEANUP_RETRY_COUNT ) &&
|
|
( m_cCurrentConnections> 0 ) ;
|
|
i++ ) {
|
|
|
|
Sleep( GD_CLEANUP_CHECK_TIME);
|
|
|
|
} // for
|
|
|
|
return;
|
|
|
|
} // GSERVER_CONFIG::DisconnectAllConnections()
|
|
|
|
|
|
|
|
VOID
|
|
GSERVER_CONFIG::RemoveConnection( IN OUT ICLIENT_CONNECTION * pcc)
|
|
/*++
|
|
|
|
Removes the current connection from the list of conenctions
|
|
and decrements count of connected users
|
|
|
|
Arguments:
|
|
|
|
pcc pointer to client connection to be removed
|
|
|
|
--*/
|
|
{
|
|
LockConfig();
|
|
|
|
//
|
|
// Remove from list of connections
|
|
//
|
|
RemoveEntryList( &pcc->QueryListEntry());
|
|
|
|
//
|
|
// Decrement count of current users
|
|
//
|
|
m_cCurrentConnections--;
|
|
|
|
UnLockConfig();
|
|
|
|
} // GSERVER_CONFIG::RemoveConnection()
|
|
|
|
|
|
/*************************** End Of File ****************************/
|