windows-nt/Source/XPSP1/NT/admin/netui/ftpmgr/cpl/ftpmcpl.cxx
2020-09-26 16:20:57 +08:00

895 lines
25 KiB
C++

/**********************************************************************/
/** Microsoft Windows NT **/
/** Copyright(c) Microsoft Corp., 1993 **/
/**********************************************************************/
/*
ftpmcpl.cxx
This is the main module for the FTP Server Control Panel Applet.
It contains the "CplApplet" function.
FILE HISTORY:
YiHsinS 22-Mar-1993 Templated from Keithmo's srvmcpl.cxx.
JonN 26-Jun-2000 CPlApplet takes HWND, UINT, LPARAM, LPARAM
*/
#define INCL_NET
#define INCL_NETLIB
#define INCL_NETSERVICE
#define INCL_WINDOWS
#define INCL_WINDOWS_GDI
#define INCL_NETERRORS
#define INCL_DOSERRORS
#include <lmui.hxx>
#if defined(DEBUG)
static const CHAR szFileName[] = __FILE__;
#define _FILENAME_DEFINED_ONCE szFileName
#endif
#include <uiassert.hxx>
#include <uitrace.hxx>
#define INCL_BLT_WINDOW
#define INCL_BLT_DIALOG
#define INCL_BLT_CONTROL
#define INCL_BLT_CLIENT
#define INCL_BLT_MSGPOPUP
#define INCL_BLT_EVENT
#define INCL_BLT_MISC
#define INCL_BLT_TIMER
#define INCL_BLT_CC
#include <blt.hxx>
#include <dbgstr.hxx>
#include <uatom.hxx>
#include <regkey.hxx>
#include <lmoloc.hxx>
#include <srvsvc.hxx>
extern "C"
{
#include <cpl.h> // Multimedia CPL defs
#include <ftpmgr.h>
#include <ftpd.h>
}
extern "C"
{
//
// Control Panel Applet entry point.
//
LONG FAR PASCAL CPlApplet( HWND hwndCPl,
UINT nMsg,
LPARAM lParam1,
LPARAM lparam2 );
//
// DLL load/unload entry point.
//
BOOL FAR PASCAL FtpMgrDllInitialize( HINSTANCE hInstance,
DWORD nReason,
LPVOID pReserved );
//
// Globals.
//
HINSTANCE _hCplInstance = NULL;
} // extern "C"
#include <ftpmgr.hxx>
//
// This is the "type" for an applet startup function.
//
typedef APIERR (* PCPL_APPLET_FUNC)( HWND hWnd );
//
// We'll keep one of these structures for each applet in this DLL.
//
typedef struct _CPL_APPLET
{
int idIcon;
int idName;
int idInfo;
int idHelpFile;
DWORD dwHelpContext;
LONG lData;
PCPL_APPLET_FUNC pfnApplet;
} CPL_APPLET;
//
// Forward reference prototypes.
//
APIERR RunFtpSvcMgr( HWND hWnd );
//
// Our applet descriptors.
//
CPL_APPLET CplApplets[] = {
{ // FTP Server applet
IDI_FTPCPA_ICON,
IDS_FTPCPA_NAME_STRING,
IDS_FTPCPA_INFO_STRING,
IDS_CPL_HELPFILENAME,
HC_FTPSVCMGR_DIALOG,
0L,
&RunFtpSvcMgr
}
};
#define NUM_APPLETS ( sizeof(CplApplets) / sizeof(CplApplets[0]) )
/*******************************************************************
NAME: InitializeDll
SYNOPSIS: Perform DLL initialiazation functions on a
once-per-process basis.
ENTRY: hInstance - Program instance of the caller.
EXIT: If this is the first initialization request for this
process, then all necessary BLT initializers have
been invoked.
RETURNS: BOOL - TRUE = Initialization OK.
FALSE = Initialization failed.
HISTORY:
YiHsinS 22-Mar-1993 Templated from Keithmo's srvmcpl.cxx.
********************************************************************/
BOOL InitializeDll( HINSTANCE hInstance )
{
//
// Save the instance handle.
//
_hCplInstance = hInstance;
return TRUE;
} // InitializeDll
/*******************************************************************
NAME: TerminateDll
SYNOPSIS: Perform DLL termination functions on a
once-per-process basis.
EXIT: All necessary BLT terminators have been invoked.
HISTORY:
YiHsinS 22-Mar-1993 Templated from Keithmo's srvmcpl.cxx.
********************************************************************/
VOID TerminateDll( VOID )
{
//
// Just in case we try to do anything goofy.
//
_hCplInstance = NULL;
} // TerminateDll
/*******************************************************************
NAME: IsFtpServerInstalled
SYNOPSIS: Determines if the FTP Server service is installed.
This doesn't necessarily mean the service is actually
running, just that it is installed on the system.
RETURNS: BOOL - TRUE = FTP Server service is installed.
FALSE = FTP Server service isn't installed.
NOTES: We could perform this check by trying to open the
service via the Service Controller, but this would
cause a lot of extraneous code to get paged in.
Instead, we'll check for the presence of the registry
key that controls the service.
HISTORY:
KeithMo 09-Apr-1993 Created.
********************************************************************/
BOOL IsFtpServerInstalled( VOID )
{
BOOL fInstalled = FALSE; // until proven otherwise...
//
// Open the registry root.
//
REG_KEY RootKey( HKEY_LOCAL_MACHINE );
APIERR err = RootKey.QueryError();
if( err == NERR_Success )
{
//
// Open the FTPSVC registry key.
//
ALIAS_STR nlsKeyName( (TCHAR *)FTPD_PARAMETERS_KEY );
UIASSERT( !!nlsKeyName );
REG_KEY RegKey( RootKey, nlsKeyName );
err = RegKey.QueryError();
if( err == NERR_Success )
{
//
// Since we successfully opened the FTP Server's
// parameters key, we'll assume that the service
// is indeed installed.
//
fInstalled = TRUE;
}
}
return fInstalled;
} // IsFtpServerInstalled
/*******************************************************************
NAME: InitializeAllApplets
SYNOPSIS: Called before applet proper is run.
ENTRY: hWnd - Window handle of parent window.
RETURNS: BOOL - TRUE = Applet should be installed.
FALSE = Applet cannot be installed.
HISTORY:
YiHsinS 22-Mar-1993 Templated from Keithmo's srvmcpl.cxx.
KeithMo 09-Apr-1993 Don't init if service not installed.
JonN 05-Oct-1994 Added lParam parameters to CPL_INIT, CPL_TERM
JonN 22-Sep-1995 Only called when applet is run
********************************************************************/
BOOL InitializeAllApplets( HWND hWnd, LPARAM lParam1, LPARAM lParam2 )
{
TRACEEOL( "FTPMGR.CPL: InitializeAllApplets enter" );
//
// Before we do anything, check to see if the FTP Server service
// is installed. If it isn't there's not much point in running
// this applet.
//
if( !IsFtpServerInstalled() )
{
return FALSE;
}
//
// Initialize all of the NetUI goodies.
//
APIERR err = BLT::Init( _hCplInstance,
IDRSRC_FTPMGR_BASE, IDRSRC_FTPMGR_LAST,
IDS_UI_FTPMGR_BASE, IDS_UI_FTPMGR_LAST );
TRACEEOL( "FTPMGR.CPL: InitializeAllApplets BLT::Init returns " << err );
if( err == NERR_Success )
{
TRACEEOL( "FTPMGR.CPL: InitializeAllApplets BLT::_MASTER_TIMER::Init next" );
err = BLT_MASTER_TIMER::Init();
TRACEEOL( "FTPMGR.CPL: InitializeAllApplets BLT::_MASTER_TIMER::Init returns " << err );
if( err != NERR_Success )
{
//
// BLT initialized OK, but BLT_MASTER_TIMER
// failed. So, before we bag-out, we must
// deinitialize BLT.
//
BLT::Term( _hCplInstance );
}
}
if( err == NERR_Success )
{
err = BLT::RegisterHelpFile( _hCplInstance,
IDS_CPL_HELPFILENAME,
HC_UI_FTPMGR_BASE,
HC_UI_FTPMGR_LAST );
if( err != NERR_Success )
{
//
// This is the only place where we can safely
// invoke MsgPopup, since we *know* that all of
// the BLT goodies were initialized properly.
//
::MsgPopup( hWnd, err );
BLT::Term( _hCplInstance );
}
}
TRACEEOL( "FTPMGR.CPL: InitializeAllApplets exit" );
return err == NERR_Success;
} // InitializeAllApplets
/*******************************************************************
NAME: TerminateAllApplets
SYNOPSIS: Called after applet is run.
ENTRY: hWnd - Window handle of parent window.
HISTORY:
YiHsinS 22-Mar-1993 Templated from Keithmo's srvmcpl.cxx.
JonN 04-Oct-1994 Added lParam parameters to CPL_INIT, CPL_TERM
JonN 22-Sep-1995 Only called when applet is run
********************************************************************/
VOID TerminateAllApplets( HWND hWnd, LPARAM lParam1, LPARAM lParam2 )
{
UNREFERENCED( hWnd );
TRACEEOL( "FTPMGR.CPL: TerminateAllApplets enter" );
//
// Kill the NetUI goodies.
//
BLT::DeregisterHelpFile( _hCplInstance, 0 );
TRACEEOL( "FTPMGR.CPL: TerminateAllApplets BLT::_MASTER_TIMER::Term next" );
BLT_MASTER_TIMER::Term();
TRACEEOL( "FTPMGR.CPL: TerminateAllApplets BLT::_MASTER_TIMER::Term complete" );
BLT::Term( _hCplInstance );
TRACEEOL( "FTPMGR.CPL: TerminateAllApplets exit" );
} // TerminateAllApplets
/*******************************************************************
NAME: AutoStartFtpServer
SYNOPSIS: Check the state of the FTP Server service. If it
isn't started, ask the user if it should be started.
If the user wants us to start the service, start it.
ENTRY: hWnd - Window handle of parent window.
RETURNS: BOOL - TRUE == FTP Server service is running.
FALSE == FTP Server service isn't running.
This may indicate either an error
or the user didn't want the service
started. If an error occurs, this
routine is responsible for displaying
it to the user.
HISTORY:
KeithMo 09-Apr-1993 Created.
********************************************************************/
BOOL AutoStartFtpServer( HWND hWnd )
{
BOOL fStarted = FALSE; // until proven otherwise...
//
// Get the "display name" for the local machine.
//
LOCATION loc( LOC_TYPE_LOCAL );
NLS_STR nlsDisplayName;
APIERR err = loc.QueryError();
err = err ? err : nlsDisplayName.QueryError();
err = err ? err : loc.QueryDisplayName( &nlsDisplayName );
if( err == NERR_Success )
{
//
// Determine the state of the service.
//
GENERIC_SERVICE * psvc = new GENERIC_SERVICE( hWnd,
NULL,
nlsDisplayName,
(TCHAR *)FTPD_SERVICE_NAME );
err = ( psvc == NULL ) ? ERROR_NOT_ENOUGH_MEMORY
: psvc->QueryError();
if( err == NERR_Success )
{
fStarted = psvc->IsInstalled( &err );
if( !fStarted && ( err == NERR_Success ) )
{
//
// Service isn't started. See if the user wants us
// to start it.
//
if( ::MsgPopup( hWnd,
IDS_START_FTPSVC_NOW,
MPSEV_WARNING,
MP_YESNO,
MP_YES ) == IDYES )
{
err = psvc->Start();
if( err == NERR_ServiceInstalled )
{
//
// Somebody must have started the service
// behind our backs...
//
err = NERR_Success;
}
if( err == NERR_Success )
{
//
// Whew!
//
fStarted = TRUE;
}
}
}
}
delete psvc;
}
//
// If anything tragic occurred, tell the user.
//
if( err != NERR_Success )
{
::MsgPopup( hWnd, err );
}
return fStarted;
} // AutoStartFtpServer
/*******************************************************************
NAME: RunFtpSvcMgr
SYNOPSIS: Invoke the main dialog of the FTP Server Control
Panel Applet.
ENTRY: hWnd - Window handle of parent window.
RETURNS: APIERR
HISTORY:
YiHsinS 18-Mar-1993 Created
KeithMo 09-Apr-1993 Autostart FTP service.
********************************************************************/
APIERR RunFtpSvcMgr( HWND hWnd )
{
//
// If the service isn't started, ask the user if
// it should be started.
//
if( !AutoStartFtpServer( hWnd ) )
{
//
// The user doesn't want to play right now.
//
return NERR_Success;
}
AUTO_CURSOR autocur;
// In the control panel applet, we will only be focusing on
// the local machine.
POPUP::SetCaption( IDS_FTPCPA_CAPTION );
FTP_SVCMGR_DIALOG * pDlg = new FTP_SVCMGR_DIALOG( hWnd,
NULL ); // local computer
APIERR err = ( pDlg == NULL ) ? ERROR_NOT_ENOUGH_MEMORY
: pDlg->QueryError();
if ( err == NERR_Success )
err = pDlg->Process();
delete pDlg;
pDlg = NULL;
if( err != NERR_Success )
{
if ( err == RPC_S_SERVER_UNAVAILABLE )
err = IERR_FTP_SERVICE_UNAVAILABLE;
::MsgPopup( hWnd, err );
}
POPUP::ResetCaption();
return err;
} // RunFtpSvcMgr
BOOL strLoad( INT idString, WCHAR * pszBuffer, INT cchBuffer )
{
int result = ::LoadString( ::_hCplInstance,
idString,
pszBuffer,
cchBuffer );
return ( result > 0 ) && ( result < cchBuffer );
} // strLoad
/*******************************************************************
NAME: CPlApplet
SYNOPSIS: Exported function to start the FTP Server Control
Panel Applet.
ENTRY: hwndCPl - Window handle of parent.
nMsg - CPL user message (see CPL.H
in WINDOWS\SHELL\CONTROL\H).
lParam1 - Message-specific pointer.
lParam2 - Message-specific pointer.
RETURNS: LONG
HISTORY:
YiHsinS 22-Mar-1993 Templated from Keithmo's srvmcpl.cxx.
JonN 04-Oct-1994 Added lParam parameters to CPL_INIT, CPL_TERM
JonN 22-Sep-1995 BLT::Init only called when applet is run
JonN 26-Jun-2000 CPlApplet takes HWND, UINT, LPARAM, LPARAM
********************************************************************/
LONG FAR PASCAL CPlApplet( HWND hwndCPl,
UINT nMsg,
LPARAM lParam1,
LPARAM lParam2 )
{
LPCPLINFO pCplInfo;
LPNEWCPLINFO pNewInfo;
LONG nResult = 0;
switch( nMsg )
{
case CPL_INIT:
//
// This message is sent to indicate that CPlApplet() was found.
//
// lParam1 is not used, but we pass it anyway.
//
// lParam2 is -1 iff the DLL will be used only to confirm the
// number of applets.
//
// Return TRUE if applet should be installed, FALSE otherwise.
//
// Before we do anything, check to see if the FTP Server service
// is installed. If it isn't there's not much point in running
// this applet.
//
return IsFtpServerInstalled();
case CPL_GETCOUNT:
//
// This message is set to determine the number of applets contained
// in this DLL.
//
// lParam1 and lParam2 are not used.
//
// Return the number of applets contained in this DLL.
//
return NUM_APPLETS;
case CPL_INQUIRE:
//
// This message is sent once per applet to retrieve information
// about each applet.
//
// lParam1 is the applet number to register.
//
// lParam2 is a pointer to a CPLINFO structure. The CPLINFO
// structure's idIcon, idName, idInfo, and lData fields should
// be initialized as appropriate for the applet.
//
// There is no return value.
//
pCplInfo = (LPCPLINFO)lParam2;
if( lParam1 < NUM_APPLETS )
{
CPL_APPLET * pApplet = &CplApplets[lParam1];
pCplInfo->idIcon = pApplet->idIcon;
pCplInfo->idName = pApplet->idName;
pCplInfo->idInfo = pApplet->idInfo;
pCplInfo->lData = pApplet->lData;
}
break;
case CPL_SELECT:
//
// This message is sent when the applet's icon has been
// selected.
//
// lParam1 is the applet number that was selected.
//
// lParam2 is the applet's lData value.
//
// There is no return value.
//
break;
case CPL_DBLCLK:
//
// This message is sent when the applet's icon has been
// double-clicked. This message should initiate the
// applet's dialog box.
//
// lParam1 is the applet number that was selected.
//
// lParam2 is the applet's lData value.
//
// There is no return value.
//
if( lParam1 < NUM_APPLETS )
{
if ((LONG)InitializeAllApplets( hwndCPl, lParam1, lParam2 ))
{
(CplApplets[lParam1].pfnApplet)( hwndCPl );
TerminateAllApplets( hwndCPl, lParam1, lParam2 );
}
else
{
ASSERT( FALSE );
}
}
break;
case CPL_STOP:
//
// This message is sent once for each applet when the
// control panel is shutting down. This message should
// initiate applet specific cleanup.
//
// lParam1 is the applet number being stopped.
//
// lParam2 is the applet's lData value.
//
// There is no return value.
//
break;
case CPL_EXIT:
//
// This message is sent just before the control panel calls
// FreeLibrary. This message should initiate non applet
// specific cleanup.
//
// lParam1 is not used, but we pass it anyway.
//
// lParam2 is -1 iff the DLL was used only to confirm the
// number of applets.
//
// There is no return value.
//
break;
case CPL_NEWINQUIRE:
//
// This message is basically the same as CPL_INQUIRE, except
// lParam2 points to a NEWCPLINFO structure. This message will
// be sent *before* CPL_INQUIRE. If the applet returns a non
// zero value, then CPL_INQUIRE will not be sent.
//
// lParam1 is the applet number to register.
//
// lParam2 is a pointer to a NEWCPLINFO structure.
//
// Return TRUE this message was handled, otherwise return FALSE.
//
pNewInfo = (LPNEWCPLINFO)lParam2;
if( lParam1 < NUM_APPLETS )
{
CPL_APPLET * pApplet = &CplApplets[lParam1];
pNewInfo->dwSize = sizeof(*pNewInfo);
pNewInfo->dwFlags = 0;
pNewInfo->dwHelpContext = pApplet->dwHelpContext;
pNewInfo->lData = pApplet->lData;
pNewInfo->hIcon = ::LoadIcon( ::_hCplInstance,
MAKEINTRESOURCE( pApplet->idIcon ) );
if( ( pNewInfo->hIcon != NULL ) &&
strLoad( pApplet->idName,
pNewInfo->szName,
sizeof(pNewInfo->szName) ) &&
strLoad( pApplet->idInfo,
pNewInfo->szInfo,
sizeof(pNewInfo->szInfo) ) &&
strLoad( pApplet->idHelpFile,
pNewInfo->szHelpFile,
sizeof(pNewInfo->szHelpFile) ) )
{
nResult = TRUE;
}
}
break;
default:
//
// Who knows. Ignore it.
//
break;
}
return nResult;
} // CPlApplet
/*******************************************************************
NAME: FtpMgrDllInitialize
SYNOPSIS: This DLL entry point is called when processes & threads
are initialized and terminated, or upon calls to
LoadLibrary() and FreeLibrary().
ENTRY: hInstance - A handle to the DLL.
nReason - Indicates why the DLL entry
point is being called.
pReserved - Reserved.
RETURNS: BOOL - TRUE = DLL init was successful.
FALSE = DLL init failed.
NOTES: The return value is only relevant during processing of
DLL_PROCESS_ATTACH notifications.
HISTORY:
YiHsinS 22-Mar-1993 Templated from Keithmo's srvmcpl.cxx.
********************************************************************/
BOOL FAR PASCAL FtpMgrDllInitialize( HINSTANCE hInstance,
DWORD nReason,
LPVOID pReserved )
{
UNREFERENCED( pReserved );
BOOL fResult = TRUE;
switch( nReason )
{
case DLL_PROCESS_ATTACH:
//
// This notification indicates that the DLL is attaching to
// the address space of the current process. This is either
// the result of the process starting up, or after a call to
// LoadLibrary(). The DLL should us this as a hook to
// initialize any instance data or to allocate a TLS index.
//
// This call is made in the context of the thread that
// caused the process address space to change.
//
fResult = InitializeDll( hInstance );
break;
case DLL_PROCESS_DETACH:
//
// This notification indicates that the calling process is
// detaching the DLL from its address space. This is either
// due to a clean process exit or from a FreeLibrary() call.
// The DLL should use this opportunity to return any TLS
// indexes allocated and to free any thread local data.
//
// Note that this notification is posted only once per
// process. Individual threads do not invoke the
// DLL_THREAD_DETACH notification.
//
TerminateDll();
break;
case DLL_THREAD_ATTACH:
//
// This notfication indicates that a new thread is being
// created in the current process. All DLLs attached to
// the process at the time the thread starts will be
// notified. The DLL should use this opportunity to
// initialize a TLS slot for the thread.
//
// Note that the thread that posts the DLL_PROCESS_ATTACH
// notification will not post a DLL_THREAD_ATTACH.
//
// Note also that after a DLL is loaded with LoadLibrary,
// only threads created after the DLL is loaded will
// post this notification.
//
break;
case DLL_THREAD_DETACH:
//
// This notification indicates that a thread is exiting
// cleanly. The DLL should use this opportunity to
// free any data stored in TLS indices.
//
break;
default:
//
// Who knows? Just ignore it.
//
break;
}
return fResult;
} // FtpMgrDllInitialize