Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

683 lines
16 KiB

/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 1993 **/
/**********************************************************************/
/*
globals.cxx
This module contains global variable definitions shared by the
various FTPD Service components.
Functions exported by this module:
InitializeGlobals
TerminateGlobals
ClearStatistics
ReadParamsFromRegistry
WriteParamsToRegistry
FILE HISTORY:
KeithMo 07-Mar-1993 Created.
MuraliK 11-April-1995 Created new global ftp server config object
*/
#include "ftpdp.hxx"
//
// Private constants.
//
#define DEFAULT_ALLOW_ANONYMOUS TRUE
#define DEFAULT_ALLOW_GUEST_ACCESS TRUE
#define DEFAULT_ANONYMOUS_ONLY FALSE
#define DEFAULT_DEBUG_FLAGS 0
#define DEFAULT_READ_ACCESS_MASK 0
#define DEFAULT_WRITE_ACCESS_MASK 0
#define DEFAULT_EXIT_MESSAGE "Goodbye."
#define DEFAULT_MAX_CLIENTS_MSG "Maximum clients reached, service unavailable."
#define DEFAULT_GREETING_MESSAGE NULL // NULL == no special greeting.
#define DEFAULT_LOWERCASE_FILES FALSE
#define DEFAULT_LISTEN_BACKLOG 5
#define DEFAULT_ENABLE_LICENSING FALSE
#define DEFAULT_DEFAULT_LOGON_DOMAIN NULL // NULL == use primary domain
//
// Socket transfer buffer size.
//
DWORD g_SocketBufferSize;
//
// Statistics.
//
//
// FTP Statistics structure.
//
FTP_STATISTICS_0 g_FtpStatistics;
//
// Statistics structure lock.
//
CRITICAL_SECTION g_StatisticsLock;
//
// Miscellaneous data.
//
//
// The current FTP Server version number.
//
LPSTR g_FtpVersionString;
//
// For FTP server configuration information
//
LPFTP_SERVER_CONFIG g_pFtpServerConfig;
//
// key for the registry to read parameters
//
HKEY g_hkeyParams = NULL;
//
// The global variable lock.
//
CRITICAL_SECTION g_GlobalLock;
#ifdef KEEP_COMMAND_STATS
//
// Lock protecting per-command statistics.
//
CRITICAL_SECTION g_CommandStatisticsLock;
#endif // KEEP_COMMAND_STATS
#if DBG
//
// Debug-specific data.
//
//
// Debug output control flags.
//
#endif // DBG
# if DBG
VOID
PrintConfiguration( VOID);
# endif
BOOL
GenDoubleNullStringFromMultiLine( IN LPCWSTR lpsz,
IN OUT LPWSTR * ppszz,
IN OUT LPDWORD pcchLen);
extern DWORD g_dwRfcDataPort;
//
// Public functions.
//
/*******************************************************************
NAME: InitializeGlobals
SYNOPSIS: Initializes global shared variables. Some values are
initialized with constants, others are read from the
configuration registry.
RETURNS: APIERR - NO_ERROR if successful, otherwise a Win32
error code.
NOTES: This routine may only be called by a single thread
of execution; it is not necessarily multi-thread safe.
Also, this routine is called before the event logging
routines have been initialized. Therefore, event
logging is not available.
HISTORY:
KeithMo 07-Mar-1993 Created.
MuraliK 05-April-1995 Added FTP server config object
********************************************************************/
APIERR
InitializeGlobals(
VOID
)
{
APIERR err = NO_ERROR;
DWORD dwDebugFlags;
//
// Setup the version string.
//
g_FtpVersionString = "Version 3.0";
//
// Create global locks.
//
InitializeCriticalSection( &g_GlobalLock );
InitializeCriticalSection( &g_StatisticsLock );
#ifdef KEEP_COMMAND_STATS
InitializeCriticalSection( &g_CommandStatisticsLock );
#endif // KEEP_COMMAND_STATS
//
// Create an FTP server config object and load values from registry.
//
g_pFtpServerConfig = new FTP_SERVER_CONFIG();
if ( g_pFtpServerConfig == NULL) {
SetLastError( ERROR_NOT_ENOUGH_MEMORY);
return ( ERROR_NOT_ENOUGH_MEMORY);
}
//
// Connect to the registry.
//
err = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
FTPD_PARAMETERS_KEY,
0,
KEY_ALL_ACCESS,
&g_hkeyParams );
if( err != NO_ERROR )
{
TCP_PRINT(( DBG_CONTEXT,
"cannot open registry key %s, error %lu\n",
FTPD_PARAMETERS_KEY,
err ));
//
// Load Default values
//
err = NO_ERROR;
}
# if DBG
dwDebugFlags = ReadRegistryDword( g_hkeyParams,
FTPD_DEBUG_FLAGS,
DEFAULT_DEBUG_FLAGS );
SET_DEBUG_FLAGS( dwDebugFlags);
# endif // DBG
err = g_pFtpServerConfig->InitFromRegistry( g_hkeyParams, FC_FTP_ALL);
if ( err != NO_ERROR ) {
//
// Initializing configuration parameters from registry failed.
//
DBGPRINTF( ( DBG_CONTEXT,
"Initialize Config From Registry for FTP server failed.",
" Error = %lu\n",
err));
} else {
TCP_ASSERT( g_pFtpServerConfig->IsValid());
//
// Clear server statistics. This must be performed
// *after* the global lock is created.
//
ClearStatistics();
}
g_dwRfcDataPort = CONN_PORT_TO_DATA_PORT( g_pTsvcInfo->QueryPort());
return ( err);
} // InitializeGlobals()
/*******************************************************************
NAME: TerminateGlobals
SYNOPSIS: Terminate global shared variables.
NOTES: This routine may only be called by a single thread
of execution; it is not necessarily multi-thread safe.
Also, this routine is called after the event logging
routines have been terminated. Therefore, event
logging is not available.
HISTORY:
KeithMo 07-Mar-1993 Created.
********************************************************************/
VOID
TerminateGlobals(
VOID
)
{
if ( g_pFtpServerConfig != NULL) {
delete ( g_pFtpServerConfig);
g_pFtpServerConfig = NULL;
}
if ( g_hkeyParams != NULL) {
RegCloseKey( g_hkeyParams);
g_hkeyParams = NULL;
}
} // TerminateGlobals
/*******************************************************************
NAME: ClearStatistics
SYNOPSIS: Clears server statistics.
HISTORY:
KeithMo 02-Jun-1993 Created.
********************************************************************/
VOID
ClearStatistics(
VOID
)
{
LockStatistics();
//
// Clear everything *except* CurrentAnonymousUsers and
// CurrentNonAnonymousUsers, and CurrentConnections since
// these reflect the current state of connected users
// and are not "normal" counters.
//
g_FtpStatistics.TotalBytesSent.QuadPart = 0;
g_FtpStatistics.TotalBytesReceived.QuadPart = 0;
g_FtpStatistics.TotalFilesSent = 0;
g_FtpStatistics.TotalFilesReceived = 0;
g_FtpStatistics.TotalAnonymousUsers = 0;
g_FtpStatistics.TotalNonAnonymousUsers = 0;
g_FtpStatistics.MaxAnonymousUsers = 0;
g_FtpStatistics.MaxNonAnonymousUsers = 0;
g_FtpStatistics.MaxConnections = 0;
g_FtpStatistics.ConnectionAttempts = 0;
g_FtpStatistics.LogonAttempts = 0;
#ifndef CHICAGO
g_FtpStatistics.TimeOfLastClear = GetCurrentTimeInSeconds();
#else
g_FtpStatistics.TimeOfLastClear = 0; //!!!
#endif
UnlockStatistics();
} // ClearStatistics
BOOL
WriteParamsToRegistry(
IN HKEY hkey,
LPFTP_CONFIG_INFO pConfig
)
/*++
This function writes parameters to the registry
Arguments:
hkey HKEY for registry entry of parameters of FTP server.
pConfig pointer to configuration information.
Returns:
TRUE on success and FALSE if there is any failure.
--*/
{
DWORD err = NO_ERROR;
BOOL fRet = TRUE;
if( hkey == NULL )
{
err = ERROR_INVALID_HANDLE;
SetLastError( err);
TCP_PRINT(( DBG_CONTEXT,
"Invalid Registry key given. error %lu\n",
err ));
return FALSE;
}
//
// Write the registry data.
//
if( !err && IsFieldSet( pConfig->FieldControl, FC_FTP_ALLOW_ANONYMOUS ) )
{
err = WriteRegistryDword( hkey,
FTPD_ALLOW_ANONYMOUS,
pConfig->fAllowAnonymous );
}
if( !err && IsFieldSet( pConfig->FieldControl, FC_FTP_ALLOW_GUEST_ACCESS ) )
{
err = WriteRegistryDword( hkey,
FTPD_ALLOW_GUEST_ACCESS,
pConfig->fAllowGuestAccess );
}
if( !err && IsFieldSet( pConfig->FieldControl, FC_FTP_ANNOTATE_DIRECTORIES ) )
{
err = WriteRegistryDword( hkey,
FTPD_ANNOTATE_DIRS,
pConfig->fAnnotateDirectories );
}
if( !err && IsFieldSet( pConfig->FieldControl, FC_FTP_ANONYMOUS_ONLY ) )
{
err = WriteRegistryDword( hkey,
FTPD_ANONYMOUS_ONLY,
pConfig->fAnonymousOnly );
}
if( !err && IsFieldSet( pConfig->FieldControl, FC_FTP_LISTEN_BACKLOG ) )
{
err = WriteRegistryDword( hkey,
FTPD_LISTEN_BACKLOG,
pConfig->dwListenBacklog );
}
if( !err && IsFieldSet( pConfig->FieldControl, FC_FTP_LOWERCASE_FILES ) )
{
err = WriteRegistryDword( hkey,
FTPD_LOWERCASE_FILES,
pConfig->fLowercaseFiles );
}
if( !err && IsFieldSet( pConfig->FieldControl, FC_FTP_MSDOS_DIR_OUTPUT ) )
{
err = WriteRegistryDword( hkey,
FTPD_MSDOS_DIR_OUTPUT,
pConfig->fMsdosDirOutput );
}
if( !err && IsFieldSet( pConfig->FieldControl, FC_FTP_EXIT_MESSAGE ) )
{
err = RegSetValueExW( hkey,
FTPD_EXIT_MESSAGE_W,
0,
REG_SZ,
(BYTE *)pConfig->lpszExitMessage,
( wcslen( pConfig->lpszExitMessage ) + 1 ) *
sizeof(WCHAR) );
}
if( !err && IsFieldSet( pConfig->FieldControl, FC_FTP_GREETING_MESSAGE ) )
{
LPWSTR pszzGreetingMessage = NULL;
DWORD cchLen = 0;
if (GenDoubleNullStringFromMultiLine( pConfig->lpszGreetingMessage,
&pszzGreetingMessage,
&cchLen)
) {
DBG_ASSERT( pszzGreetingMessage != NULL);
err = RegSetValueExW( hkey,
FTPD_GREETING_MESSAGE_W,
0,
REG_MULTI_SZ,
(BYTE *) pszzGreetingMessage,
cchLen * sizeof(WCHAR));
TCP_FREE( pszzGreetingMessage);
} else {
err = ERROR_NOT_ENOUGH_MEMORY;
}
}
if( !err && IsFieldSet( pConfig->FieldControl, FC_FTP_MAX_CLIENTS_MESSAGE ) )
{
err = RegSetValueExW( hkey,
FTPD_MAX_CLIENTS_MSG_W,
0,
REG_SZ,
(BYTE *)pConfig->lpszMaxClientsMessage,
( wcslen( pConfig->lpszMaxClientsMessage ) + 1 ) *
sizeof(WCHAR) );
}
if( err )
{
SetLastError( err );
return FALSE;
}
return TRUE;
} // WriteParamsToRegistry
//
// Private functions.
//
BOOL
GenDoubleNullStringFromMultiLine( IN LPCWSTR lpsz,
IN OUT LPWSTR * ppszz,
IN OUT LPDWORD pcchLen)
{
DWORD cchLen;
DWORD nLines;
LPWSTR pszNext;
LPCWSTR pszSrc;
DBG_ASSERT( lpsz != NULL && ppszz != NULL && pcchLen != NULL);
// Initialize
*ppszz = NULL;
*pcchLen = 0;
//
// 1. Find the length of the the complete message including new lines
// For each new line we may potentially need an extra blank char
// So allocate space = nLines + length + 2 terminating null chars.
//
cchLen = lstrlenW( lpsz);
for ( pszSrc = lpsz, nLines = 0; *pszSrc != L'\0'; pszSrc++) {
if ( *pszSrc == L'\n') { nLines++; }
} // for
// Allocate sufficient space for the string.
*ppszz = (LPWSTR ) TCP_ALLOC( (cchLen + nLines + 3) * sizeof(WCHAR));
if ( *ppszz == NULL) {
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return (FALSE);
}
//
// walk down the local copy and convert all the line feed characters to
// be null char
//
//
// Since the MULTI_SZ string cannot contain empty strings
// we convert empty lines (ones with just \n into " \0"
// i.e. with a blank character.
//
pszSrc = lpsz;
LPWSTR pszDst = *ppszz;
if ( *pszSrc == L'\n') {
// first line is a linefeed. insert a blank and proceed to next line.
*pszDst = L' ';
*(pszDst + 1) = L'\0';
// move forward
pszDst += 2;
pszSrc++;
}
for( ; *pszSrc != L'\0'; pszSrc++, pszDst++) {
if ( *pszSrc == L'\n') {
// we are at boundary of new line.
if ( pszSrc > lpsz && *(pszSrc - 1) == L'\n') {
// we detected an empty line. Store an additional blank.
*pszDst++ = L' ';
}
*pszDst = L'\0'; // put null char in place of line feed.
} else {
*pszDst = *pszSrc;
}
} // for
*pszDst++ = L'\0'; // terminate with 1st null chars.
*pszDst++ = L'\0'; // terminate with 2nd null chars.
*pcchLen = (pszDst - *ppszz);
DBG_ASSERT( *pcchLen <= cchLen + nLines + 3);
return ( TRUE);
} // GenDoubleNullStringFromMultiline()
# if DBG
VOID
PrintConfiguration( VOID)
{
IF_DEBUG( CONFIG )
{
TCP_PRINT(( DBG_CONTEXT,
"Configuration:\n" ));
READ_LOCK_TSVC();
TCP_PRINT(( DBG_CONTEXT,
" AnonymousUser = %s\n",
g_pTsvcInfo->QueryAnonUserName() ));
UNLOCK_TSVC();
TCP_PRINT(( DBG_CONTEXT,
" LogAnonymous = %s\n",
DisplayBool( g_pTsvcInfo->QueryLogAnonymous() ) ));
TCP_PRINT(( DBG_CONTEXT,
" LogNonAnonymous = %s\n",
DisplayBool( g_pTsvcInfo->QueryLogNonAnonymous() ) ));
TCP_PRINT(( DBG_CONTEXT,
" MaxConnections = %lu\n",
g_pTsvcInfo->QueryMaxConnections() ));
TCP_PRINT(( DBG_CONTEXT,
" ConnectionTimeout = %lu\n",
g_pTsvcInfo->QueryConnectionTimeout() ));
TCP_PRINT(( DBG_CONTEXT,
" %s = %08lX\n",
FTPD_DEBUG_FLAGS,
GET_DEBUG_FLAGS()));
READ_LOCK_TSVC();
TCP_PRINT(( DBG_CONTEXT,
" LogFileDirectory = %s\n",
g_pTsvcInfo->QueryLogFileDirectory() ));
UNLOCK_TSVC();
TCP_PRINT(( DBG_CONTEXT,
" LogFileAccess = %lu\n",
g_pTsvcInfo->QueryLogFileType() ));
if ( g_pFtpServerConfig != NULL) {
g_pFtpServerConfig->Print();
}
}
return;
} // PrintConfiguration()
# endif // DBG
/************************ End Of File ************************/