/**********************************************************************/ /** Microsoft Windows NT **/ /** Copyright(c) Microsoft Corp., 1993 **/ /**********************************************************************/ /* rpcsupp.c This module contains support routines for the FTP Service RPC interface. FILE HISTORY: KeithMo 23-Mar-1993 Created. */ #include "ftpdp.h" #pragma hdrstop #include "rpcutil.h" // // Private constants. // // // Private globals. // // // Private prototypes. // // // Public functions. // /******************************************************************* NAME: I_FtprEnumerateUsers SYNOPSIS: Enumerates the connected users. This is a server-side worker routine for RPC. ENTRY: pszServer - Target server (unused). pBuffer - Will receive the number of entries and a pointer to the enumeration buffer. RETURNS: NET_API_STATUS - Net status code, NERR_Success if OK. HISTORY: KeithMo 23-Mar-1993 Created. ********************************************************************/ NET_API_STATUS I_FtprEnumerateUsers( FTP_IMPERSONATE_HANDLE pszServer, LPFTP_USER_ENUM_STRUCT pBuffer ) { APIERR err; DWORD cbBuffer; FTPD_ASSERT( pBuffer != NULL ); UNREFERENCED_PARAMETER(pszServer); IF_DEBUG( RPC ) { FTPD_PRINT(( "in I_FtprEnumerateUsers\n" )); } // // Check for proper access. // err = ApiAccessCheck( FTPD_ENUMERATE_USERS ); if( err != NO_ERROR ) { IF_DEBUG( RPC ) { FTPD_PRINT(( "I_FtprEnumerateUsers failed access check, error %lu\n", err )); } return (NET_API_STATUS)err; } // // Lock the user database. // LockUserDatabase(); // // Determine the necessary buffer size. // pBuffer->EntriesRead = 0; pBuffer->Buffer = NULL; cbBuffer = 0; err = NERR_Success; EnumerateUsers( pBuffer, &cbBuffer ); if( cbBuffer > 0 ) { // // Allocate the buffer. Note that we *must* // use midl_user_allocate/midl_user_free. // pBuffer->Buffer = (FTP_USER_INFO *)MIDL_user_allocate( (unsigned int)cbBuffer ); if( pBuffer->Buffer == NULL ) { err = ERROR_NOT_ENOUGH_MEMORY; } else { // // Since we've got the user database locked, there // *should* be enough room in the buffer for the // user data. If there isn't, we've screwed up // somewhere. // FTPD_REQUIRE( EnumerateUsers( pBuffer, &cbBuffer ) ); } } // // Unlock the user database before returning. UnlockUserDatabase(); return (NET_API_STATUS)err; } // I_FtprEnumerateUsers /******************************************************************* NAME: I_FtprDisconnectUser SYNOPSIS: Disconnects a specified user. This is a server-side worker routine for RPC. ENTRY: pszServer - Target server (unused). idUser - Identifies the user to disconnect. If 0, then disconnect ALL users. RETURNS: NET_API_STATUS - Net status code, NERR_Success if OK. HISTORY: KeithMo 23-Mar-1993 Created. ********************************************************************/ NET_API_STATUS I_FtprDisconnectUser( FTP_IMPERSONATE_HANDLE pszServer, DWORD idUser ) { APIERR err = NERR_Success; UNREFERENCED_PARAMETER(pszServer); IF_DEBUG( RPC ) { FTPD_PRINT(( "in I_FtprDisconnectUser\n" )); } // // Check for proper access. // err = ApiAccessCheck( FTPD_DISCONNECT_USER ); if( err != NO_ERROR ) { IF_DEBUG( RPC ) { FTPD_PRINT(( "I_FtprDisconnectUser failed access check, error %lu\n", err )); } return (NET_API_STATUS)err; } // // Do it. // if( idUser == 0 ) { DisconnectAllUsers(); } else { if( !DisconnectUser( idUser ) ) { err = NERR_UserNotFound; } } return (NET_API_STATUS)err; } // I_FtprDisconnectUser /******************************************************************* NAME: I_FtprQueryVolumeSecurity SYNOPSIS: Returns the current volume security masks. This is a server-side worker routine for RPC. ENTRY: pszServer - Target server (unused). pdwReadAccess - Will receive the read access mask. pdwWriteAccess - Will receive the write access mask. RETURNS: NET_API_STATUS - Status code, NERR_Success if successful. HISTORY: KeithMo 23-Mar-1993 Created. ********************************************************************/ NET_API_STATUS I_FtprQueryVolumeSecurity( FTP_IMPERSONATE_HANDLE pszServer, LPDWORD pdwReadAccess, LPDWORD pdwWriteAccess ) { APIERR err; FTPD_ASSERT( pdwReadAccess != NULL ); FTPD_ASSERT( pdwWriteAccess != NULL ); UNREFERENCED_PARAMETER(pszServer); IF_DEBUG( RPC ) { FTPD_PRINT(( "in I_FtprQueryVolumeSecurity\n" )); } // // Check for proper access. // err = ApiAccessCheck( FTPD_QUERY_SECURITY ); if( err != NO_ERROR ) { IF_DEBUG( RPC ) { FTPD_PRINT(( "I_FtprQueryVolumeSecurity failed access check, error %lu\n", err )); } return (NET_API_STATUS)err; } // // Return the current access masks. // LockGlobals(); *pdwReadAccess = maskReadAccess; *pdwWriteAccess = maskWriteAccess; UnlockGlobals(); return NERR_Success; } // I_FtprQueryVolumeSecurity /******************************************************************* NAME: I_FtprSetVolumeSecurity SYNOPSIS: Sets the current volume security masks. This function is also responsible for disconnecting any users that no longer have read access to their current directory. This is a server-side worker routine for RPC. ENTRY: pszServer - Target server (unused). dwReadAccess - The new read access mask. dwWriteAccess - The new write access mask. RETURNS: NET_API_STATUS - Status code, NERR_Success if successful. HISTORY: KeithMo 23-Mar-1993 Created. ********************************************************************/ NET_API_STATUS I_FtprSetVolumeSecurity( FTP_IMPERSONATE_HANDLE pszServer, DWORD dwReadAccess, DWORD dwWriteAccess ) { APIERR err; DWORD maskInvalid = ~VALID_DOS_DRIVE_MASK; UNREFERENCED_PARAMETER(pszServer); IF_DEBUG( RPC ) { FTPD_PRINT(( "in I_FtprSetVolumeSecurity\n" )); } // // Validate the parameters. // if( ( dwReadAccess & maskInvalid ) || ( dwWriteAccess & maskInvalid ) ) { return ERROR_INVALID_PARAMETER; } // // Check for proper access. // err = ApiAccessCheck( FTPD_SET_SECURITY ); if( err != NO_ERROR ) { IF_DEBUG( RPC ) { FTPD_PRINT(( "I_FtprSetVolumeSecurity failed access check, error %lu\n", err )); } return (NET_API_STATUS)err; } // // Update the registry. // err = WriteRegistryDword( FTPD_READ_ACCESS_MASK, dwReadAccess ); if( err == NO_ERROR ) { err = WriteRegistryDword( FTPD_WRITE_ACCESS_MASK, dwWriteAccess ); } if( err != NO_ERROR ) { IF_DEBUG( RPC ) { FTPD_PRINT(( "cannot update access masks in registry, error %lu\n", err )); } return (NET_API_STATUS)err; } // // Update the local masks. // LockGlobals(); maskReadAccess = dwReadAccess; maskWriteAccess = dwWriteAccess; UpdateAccessMasks(); UnlockGlobals(); IF_DEBUG( RPC ) { FTPD_PRINT(( "maskReadAccess set to %08lX\n", maskReadAccess )); FTPD_PRINT(( "maskWriteAccess set to %08lX\n", maskWriteAccess )); } // // Blow away everyone that can no longer access their // current directory. // DisconnectUsersWithNoAccess(); return NERR_Success; } // I_FtprSetVolumeSecurity /******************************************************************* NAME: I_FtprQueryStatistics SYNOPSIS: Queries the current server statistics. This is a server-side worker routine for RPC. ENTRY: pszServer - Target server (unused). Level - Info level. Currently only level 0 is supported. pBuffer - Will receive a poitner to the statistics structure. RETURNS: NET_API_STATUS - Net status code, NERR_Success if OK. HISTORY: KeithMo 02-Jun-1993 Created. ********************************************************************/ NET_API_STATUS I_FtprQueryStatistics( FTP_IMPERSONATE_HANDLE pszServer, DWORD Level, LPSTATISTICS_INFO pBuffer ) { APIERR err; FTPD_ASSERT( pBuffer != NULL ); UNREFERENCED_PARAMETER(pszServer); IF_DEBUG( RPC ) { FTPD_PRINT(( "in I_FtprQueryStatistics, level %lu\n", Level )); } // // Check for proper access. // err = ApiAccessCheck( FTPD_QUERY_STATISTICS ); if( err != NO_ERROR ) { IF_DEBUG( RPC ) { FTPD_PRINT(( "I_FtprQueryStatistics failed access check, error %lu\n", err )); } return (NET_API_STATUS)err; } // // Return the proper statistics based on the infolevel. // switch( Level ) { case 0 : { LPFTP_STATISTICS_0 pstats0; pstats0 = (LPFTP_STATISTICS_0)MIDL_user_allocate( sizeof(FTP_STATISTICS_0) ); if( pstats0 == NULL ) { err = ERROR_NOT_ENOUGH_MEMORY; } else { LockStatistics(); RtlCopyMemory( pstats0, &FtpStats, sizeof(FTP_STATISTICS_0) ); UnlockStatistics(); pBuffer->FtpStats0 = pstats0; } } break; default : err = ERROR_INVALID_LEVEL; break; } return (NET_API_STATUS)err; } // I_FtprQueryStatistics /******************************************************************* NAME: I_FtprClearStatistics SYNOPSIS: Clears current server statistics. This is a server-side worker routine for RPC. ENTRY: pszServer - Target server (unused). RETURNS: NET_API_STATUS - Net status code, NERR_Success if OK. HISTORY: KeithMo 02-Jun-1993 Created. ********************************************************************/ NET_API_STATUS I_FtprClearStatistics( FTP_IMPERSONATE_HANDLE pszServer ) { APIERR err; UNREFERENCED_PARAMETER(pszServer); IF_DEBUG( RPC ) { FTPD_PRINT(( "in I_FtprClearStatistics\n" )); } // // Check for proper access. // err = ApiAccessCheck( FTPD_CLEAR_STATISTICS ); if( err != NO_ERROR ) { IF_DEBUG( RPC ) { FTPD_PRINT(( "I_FtprClearStatistics failed access check, error %lu\n", err )); } return (NET_API_STATUS)err; } // // Clear the statistics. // ClearStatistics(); return (NET_API_STATUS)err; } // I_FtprClearStatistics // // Private functions. //