/*++ Copyright (c) 1996 Microsoft Corporation Module Name: ftpinst.hxx Abstract: This module defines the FTP_IIS_SERVICE type Author: Johnson Apacible (johnsona) 04-Sep-1996 --*/ #ifndef _FTPINST_HXX_ #define _FTPINST_HXX_ #include "iistypes.hxx" #include "stats.hxx" #include "type.hxx" typedef LPUSER_DATA PICLIENT_CONNECTION; typedef BOOL (*PFN_CLIENT_CONNECTION_ENUM)( PICLIENT_CONNECTION pcc, LPVOID pContext); // specifies the size of cache block for padding ==> to avoid false sharing # define MAX_CACHE_BLOCK_SIZE ( 64) class FTP_IIS_SERVICE : public IIS_SERVICE { public: FTP_IIS_SERVICE( IN LPCTSTR lpszServiceName, IN LPCSTR lpszModuleName, IN LPCSTR lpszRegParamKey, IN DWORD dwServiceId, IN ULONGLONG SvcLocId, IN BOOL MultipleInstanceSupport, IN DWORD cbAcceptExRecvBuffer, IN ATQ_CONNECT_CALLBACK pfnConnect, IN ATQ_COMPLETION pfnConnectEx, IN ATQ_COMPLETION pfnIoCompletion ) :IIS_SERVICE( lpszServiceName, lpszModuleName, lpszRegParamKey, dwServiceId, SvcLocId, MultipleInstanceSupport, cbAcceptExRecvBuffer, pfnConnect, pfnConnectEx, pfnIoCompletion ) { InitializeListHead( & m_InstanceList ); INITIALIZE_CRITICAL_SECTION( &m_csInstanceLock); } ~FTP_IIS_SERVICE() { DeleteCriticalSection( &m_csInstanceLock); } VOID LockInstanceList( VOID) { EnterCriticalSection( &m_csInstanceLock); } VOID UnLockInstanceList( VOID) { LeaveCriticalSection( &m_csInstanceLock); } virtual DWORD GetServiceConfigInfoSize(IN DWORD dwLevel); virtual BOOL AddInstanceInfo( IN DWORD dwInstance, IN BOOL fMigrateRoots ); virtual DWORD DisconnectUsersByInstance( IN IIS_SERVER_INSTANCE * pInstance ); BOOL AggregateStatistics( IN PCHAR pDestination, IN PCHAR pSource ); BOOL GetGlobalStatistics( IN DWORD dwLevel, OUT PCHAR *pBuffer ); LIST_ENTRY m_InstanceList; CRITICAL_SECTION m_csInstanceLock; }; typedef FTP_IIS_SERVICE *PFTP_IIS_SERVICE; // // This is the FTP version of the instance. Will contain all the // FTP specific operations. // class FTP_SERVER_INSTANCE : public IIS_SERVER_INSTANCE { public: FTP_SERVER_INSTANCE( IN PFTP_IIS_SERVICE pService, IN DWORD dwInstanceId, IN USHORT sPort, IN LPCSTR lpszRegParamKey, IN LPWSTR lpwszAnonPasswordSecretName, IN LPWSTR lpwszRootPasswordSecretName, IN BOOL fMigrateVroots ) ; ~FTP_SERVER_INSTANCE(); // // Instance start & stop // virtual DWORD StartInstance(); virtual DWORD StopInstance(); // // VIRTUALS for service specific params/RPC admin // virtual BOOL SetServiceConfig(IN PCHAR pConfig ); virtual BOOL GetServiceConfig(IN OUT PCHAR pConfig,IN DWORD dwLevel); virtual BOOL GetStatistics( IN DWORD dwLevel, OUT PCHAR *pBuffer); virtual BOOL ClearStatistics( VOID ); virtual BOOL DisconnectUser( IN DWORD dwIdUser ); virtual BOOL EnumerateUsers( OUT PCHAR* pBuffer, OUT PDWORD nRead ); virtual VOID MDChangeNotify( MD_CHANGE_OBJECT * pco ); BOOL FreeAllocCachedClientConn(VOID); PICLIENT_CONNECTION AllocClientConnFromAllocCache(VOID); VOID FreeClientConnToAllocCache(IN PICLIENT_CONNECTION pClient); // // Initialize the configuration data from registry information // // Arguments // hkeyReg key to the registry entry for parameters // FieldsToRead bitmapped flags indicating which data to be read. // // Returns: // NO_ERROR on success // Win32 error code otherwise // DWORD InitFromRegistry( IN FIELD_CONTROL FieldsToRead); DWORD ReadAuthentInfo( IN BOOL ReadAll = TRUE, IN DWORD SingleItemToRead = 0 ); DWORD GetConfigInformation( OUT LPFTP_CONFIG_INFO pConfigInfo); DWORD SetConfigInformation( IN LPFTP_CONFIG_INFO pConfigInfo); BOOL IsValid( VOID) const { return ( m_fValid); } VOID LockConfig( VOID) { EnterCriticalSection( &m_csLock); } VOID UnLockConfig( VOID) { LeaveCriticalSection( &m_csLock); } VOID LockConnectionsList() { EnterCriticalSection(&m_csConnectionsList); } VOID UnlockConnectionsList() { LeaveCriticalSection(&m_csConnectionsList); } DWORD GetCurrentConnectionsCount( VOID) const { return m_cCurrentConnections; } DWORD GetMaxCurrentConnectionsCount( VOID) const { return m_cMaxCurrentConnections; } DWORD SetLocalHostName(IN LPCSTR pszHost); LPCSTR QueryLocalHostName(VOID) const { return (m_pszLocalHostName); } DWORD QueryUserFlags(VOID) const { return (m_dwUserFlags); } BOOL QueryLowercaseFiles(VOID) const { return (m_fLowercaseFiles); } BOOL AllowAnonymous(VOID) const { return (m_fAllowAnonymous); } BOOL AllowGuestAccess(VOID) const { return (m_fAllowGuestAccess); } BOOL IsAllowedUser(IN BOOL fAnonymous) { return ((fAnonymous && m_fAllowAnonymous) || (!fAnonymous && !m_fAllowAnonymous) || (!fAnonymous && !m_fAnonymousOnly)); } BOOL IsEnableDataConnTo3rdIP(VOID) const { return (m_fEnableDataConnTo3rdIP); } BOOL IsEnablePasvConnFrom3rdIP(VOID) const { return (m_fEnablePasvConnFrom3rdIP); }; DWORD NumListenBacklog(VOID) const { return (m_ListenBacklog); } // Following functions return pointers to strings which should be used // within locked sections of config // Marked by LockConfig() and UnLockConfig() LPCSTR QueryMaxClientsMsg(VOID) const { return (LPCSTR)m_MaxClientsMessage.QueryStr(); } LPCSTR QueryGreetingMsg(VOID) const { return (LPCSTR)m_GreetingMessage.QueryStr(); } LPCSTR QueryBannerMsg(VOID) const { return (LPCSTR)m_BannerMessage.QueryStr(); } LPCSTR QueryExitMsg(VOID) const { return (LPCSTR)m_ExitMessage.QueryStr(); } BOOL EnumerateConnection( IN PFN_CLIENT_CONNECTION_ENUM pfnConnEnum, IN LPVOID pContext, IN DWORD dwConnectionId); VOID DisconnectAllConnections( VOID); PICLIENT_CONNECTION AllocNewConnection(); VOID RemoveConnection( IN OUT PICLIENT_CONNECTION pcc); BOOL WriteParamsToRegistry( LPFTP_CONFIG_INFO pConfig ); VOID Print( VOID) const; METADATA_REF_HANDLER* QueryMetaDataRefHandler() { return &m_rfAccessCheck; } PTCP_AUTHENT_INFO QueryAuthentInfo() { return &m_TcpAuthentInfo; } PUSER_AUTHENT_INFO QueryADConnAuthentInfo() { return &m_ADConnAuthentInfo; } BOOL AllowReplaceOnRename( VOID ) const { return m_fAllowReplaceOnRename; } LPFTP_SERVER_STATISTICS QueryStatsObj( VOID ) { return m_pFTPStats; } DWORD QueryIsolationMode( VOID ) const { return m_UserIsolationMode; } LPAD_IO QueryAdIo( VOID ) const { return m_pAdIo; } inline DWORD QueryAnonymousHomeDir( STR & strTargetPath) { return m_pAdIo ? m_pAdIo->GetAnonymHomeDir( strTargetPath ) : ERROR_BAD_CONFIGURATION; } inline DWORD QueryUserHomeDir( const STR & strUser, const STR & strDomain, STR * pstrTarget, ADIO_ASYNC ** ppadioReqCtx, tpAdioAsyncCallback pfnCallback, HANDLE hCLientCtx) { return m_pAdIo ? m_pAdIo->GetUserHomeDir( strUser, strDomain, pstrTarget, ppadioReqCtx, pfnCallback, hCLientCtx) : ERROR_BAD_CONFIGURATION; } private: DWORD SetAdIoInfo( VOID ); // // Connections related data // // m_cMaxConnections: max connections permitted by config // m_cCurrentConnections: count of currently connected users // m_cMaxCurrentConnections: max connections seen in this session // Always m_cCurrentConnections // <= m_cMaxCurrentConnections // <= m_cMaxConnections; // // DWORD m_cMaxConnections; // replaced by TSVC_INFO::QueryMaxConnections() DWORD m_cCurrentConnections; DWORD m_cMaxCurrentConnections; BOOL m_fAllowAnonymous; BOOL m_fAllowGuestAccess; BOOL m_fAnnotateDirectories; // annotate dirs when dir changes BOOL m_fAnonymousOnly; BOOL m_fEnableDataConnTo3rdIP; BOOL m_fEnablePasvConnFrom3rdIP; // if m_LowercaseFiles is TRUE, then dir listings from non-case-preserving // filesystems will be mapped to lowercase. BOOL m_fLowercaseFiles; BOOL m_fMsdosDirOutput; // send msdos style dir listings BOOL m_fFourDigitYear; // send 4 digit year dir listings STR m_ExitMessage; STR m_MaxClientsMessage; TCP_AUTHENT_INFO m_TcpAuthentInfo; USER_AUTHENT_INFO m_ADConnAuthentInfo; // // Greeting Message can be a multiline message. // We maintain two copies of the message // 1) double null terminated seq. of strings with one line per string // 2) single null terminated string with \n characters interspersed. // // Representation 1 is used for sending data to clients // Representation 2 is used for RPC admin facility // We maintain the string as MULTI_SZ in the registry // MULTISZ m_GreetingMessage; LPTSTR m_pszGreetingMessageWithLineFeed; // // Same as for the greeting message, the banner could be multiline too. // Same handling. // MULTISZ m_BannerMessage; LPTSTR m_pszBannerMessageWithLineFeed; BOOL m_fEnableLicensing; DWORD m_ListenBacklog; CHAR * m_pszLocalHostName; // this machine name running ftp service DWORD m_dwUserFlags; // user flags established at start of conn // // For FTP server configuration information // // // TODO: merge configuration and instance object together // // LPFTP_SERVER_CONFIG m_pFtpServerConfig; HKEY m_hkeyParams; // // Other data related to configuration load and store // BOOL m_fValid; CRITICAL_SECTION m_csLock; // used for updating this object CHAR m_rgchCacheBlock[MAX_CACHE_BLOCK_SIZE]; // to avoid false sharing // we should avoid cache block conflict // Following set of data constitute the dynamic data for connections // ==> it will be good if they are closeby, within one cache block. CRITICAL_SECTION m_csConnectionsList; LIST_ENTRY m_ActiveConnectionsList; // list of all active connections LIST_ENTRY m_FreeConnectionsList; // free list for connection objects METADATA_REF_HANDLER m_rfAccessCheck; LPFTP_SERVER_STATISTICS m_pFTPStats; BOOL m_fAllowReplaceOnRename; DWORD m_UserIsolationMode; BOOL m_fLogInUtf8; LPAD_IO m_pAdIo; }; typedef FTP_SERVER_INSTANCE *PFTP_SERVER_INSTANCE; // // Class for managing port range allocations // class FTP_PASV_PORT { public: FTP_PASV_PORT() { m_dwRemainingRetries = m_dwNextPasvPort == 0 ? 0 : m_dwPasvPortRangeEnd - m_dwPasvPortRangeStart + 1; } ~FTP_PASV_PORT() {} static VOID Init() { INITIALIZE_CRITICAL_SECTION( &m_csPasvPortRange); } static VOID Terminate() { DeleteCriticalSection( &m_csPasvPortRange); } static BOOL Configure(); PORT GetPort() { LONG Port = 0; if (m_dwRemainingRetries > 0) { m_dwRemainingRetries--; EnterCriticalSection(&m_csPasvPortRange); Port = m_dwNextPasvPort; if (++m_dwNextPasvPort > m_dwPasvPortRangeEnd) { m_dwNextPasvPort = m_dwPasvPortRangeStart; } LeaveCriticalSection(&m_csPasvPortRange); } return (PORT)Port; } private: static CRITICAL_SECTION m_csPasvPortRange; static PORT m_dwPasvPortRangeStart; // configured range start static PORT m_dwPasvPortRangeEnd; // configured range end static LONG m_dwNextPasvPort; // next port to allocate DWORD m_dwRemainingRetries; }; #endif // _FTPINST_HXX_