windows-nt/Source/XPSP1/NT/inetsrv/iis/ui/admin/pws/pwsdoc.cpp
2020-09-26 16:20:57 +08:00

669 lines
20 KiB
C++

// pwsDoc.cpp : implementation of the CPwsDoc class
//
#include "stdafx.h"
#include "resource.h"
#include "pwsform.h"
#include "Title.h"
#include "HotLink.h"
#include "PWSChart.h"
#include "pwsDoc.h"
//#include "PwsForm.h"
#include "Tip.h"
#include "TipDlg.h"
#include "EdDir.h"
#include "FormMain.h"
#include "FormAdv.h"
#include <isvctrl.h>
#include "ServCntr.h"
#include "pwstray.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// location of the installation path in the registry
#define REG_INSTALL_PATH _T("Software\\Microsoft\\InetStp")
#define REG_PATH_VAL _T("InstallPath")
#define SZ_KEY_RUN_TRAY _T("software\\microsoft\\windows\\currentversion\\run")
#define SZ_KEY_RUN_VALUE _T("PWSTray")
#define SERVER_WINDOWCLASS_NAME TEXT(INET_SERVER_WINDOW_CLASS)
// globals
//extern CPwsForm* g_p_FormView;
CPwsDoc* g_p_Doc = NULL;
extern CFormMain* g_FormMain;
extern IMSAdminBase* g_pMBCom;
extern BOOL g_fShutdownMode;
#define REGKEY_STP _T("SOFTWARE\\Microsoft\\INetStp")
#define REGKEY_INSTALLKEY _T("InstallPath")
/////////////////////////////////////////////////////////////////////////////
// CPwsDoc
IMPLEMENT_DYNCREATE(CPwsDoc, CDocument)
BEGIN_MESSAGE_MAP(CPwsDoc, CDocument)
//{{AFX_MSG_MAP(CPwsDoc)
ON_COMMAND(ID_START, OnStart)
ON_COMMAND(ID_STOP, OnStop)
ON_UPDATE_COMMAND_UI(ID_START, OnUpdateStart)
ON_UPDATE_COMMAND_UI(ID_STOP, OnUpdateStop)
ON_COMMAND(ID_PAUSE, OnPause)
ON_UPDATE_COMMAND_UI(ID_PAUSE, OnUpdatePause)
ON_COMMAND(ID_SHOW_TIPS, OnShowTips)
ON_UPDATE_COMMAND_UI(ID_SHOW_TIPS, OnUpdateShowTips)
ON_COMMAND(ID_HELP_DOCUMENTATION, OnHelpDocumentation)
ON_COMMAND(ID_HELP_HELP_TROUBLESHOOTING, OnHelpHelpTroubleshooting)
ON_UPDATE_COMMAND_UI(ID_CONTINUE, OnUpdateContinue)
ON_COMMAND(ID_CONTINUE, OnContinue)
ON_UPDATE_COMMAND_UI(ID_TRAYICON, OnUpdateTrayicon)
ON_COMMAND(ID_TRAYICON, OnTrayicon)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BEGIN_DISPATCH_MAP(CPwsDoc, CDocument)
//{{AFX_DISPATCH_MAP(CPwsDoc)
// NOTE - the ClassWizard will add and remove mapping macros here.
// DO NOT EDIT what you see in these blocks of generated code!
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
static const IID IID_IPws =
{ 0x35c43e1, 0x8464, 0x11d0, { 0xa9, 0x2d, 0x8, 0x0, 0x2b, 0x2c, 0x6f, 0x32 } };
BEGIN_INTERFACE_MAP(CPwsDoc, CDocument)
INTERFACE_PART(CPwsDoc, IID_IPws, Dispatch)
END_INTERFACE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPwsDoc construction/destruction
//------------------------------------------------------------------
CPwsDoc::CPwsDoc():
m_ActionToDo( 0 ),
m_ExpectedResult( 0 ),
m_dwSinkCookie( 0 ),
m_pEventSink( NULL ),
m_pConnPoint( NULL ),
m_fIsPWSTrayAvailable( FALSE )
{
EnableAutomation();
AfxOleLockApp();
g_p_Doc = this;
OSVERSIONINFO info_os;
info_os.dwOSVersionInfoSize = sizeof(info_os);
// record what sort of operating system we are running on
m_fIsWinNT = FALSE;
if ( GetVersionEx( &info_os ) )
{
if ( info_os.dwPlatformId == VER_PLATFORM_WIN32_NT )
m_fIsWinNT = TRUE;
}
}
//------------------------------------------------------------------
CPwsDoc::~CPwsDoc()
{
TerminateSink();
g_p_Doc = NULL;
AfxOleUnlockApp();
}
//------------------------------------------------------------------
// builds something akin to "http://boydm"
BOOL CPwsDoc::BuildHomePageString( CString &cs )
{
CHAR nameBuf[MAX_PATH+1];
// if the server is not running, fail
CW3ServerControl serverController;
if ( serverController.GetServerState() != MD_SERVER_STATE_STARTED )
return FALSE;
// start it off with the mandatory http header
cs.LoadString( IDS_HTTP_HEADER );
// get the host name of the machine
gethostname( nameBuf, sizeof(nameBuf));
cs += nameBuf;
return TRUE;
}
//------------------------------------------------------------------
BOOL CPwsDoc::InitializeSink()
{
IConnectionPointContainer * pConnPointContainer = NULL;
HRESULT hRes;
BOOL fSinkConnected = FALSE;
// g_pMBCom is defined in wrapmb
IUnknown* pmb = (IUnknown*)g_pMBCom;
m_pEventSink = new CImpIMSAdminBaseSink();
if ( !m_pEventSink )
{
return FALSE;
}
//
// First query the object for its Connection Point Container. This
// essentially asks the object in the server if it is connectable.
//
hRes = pmb->QueryInterface( IID_IConnectionPointContainer,
(PVOID *)&pConnPointContainer);
if SUCCEEDED(hRes)
{
// Find the requested Connection Point. This AddRef's the
// returned pointer.
hRes = pConnPointContainer->FindConnectionPoint( IID_IMSAdminBaseSink,
&m_pConnPoint);
if (SUCCEEDED(hRes))
{
hRes = m_pConnPoint->Advise( (IUnknown *)m_pEventSink,
&m_dwSinkCookie);
if (SUCCEEDED(hRes))
{
fSinkConnected = TRUE;
}
}
if ( pConnPointContainer )
{
pConnPointContainer->Release();
pConnPointContainer = NULL;
}
}
if ( !fSinkConnected )
{
delete m_pEventSink;
}
return fSinkConnected;
}
//------------------------------------------------------------------
void CPwsDoc::TerminateSink()
{
HRESULT hRes;
if ( m_dwSinkCookie )
{
hRes = m_pConnPoint->Unadvise( m_dwSinkCookie );
}
// don't need to delete m_pEventSink because the Unadvise
// above decrements is reference count and that causes it
// to delete itself....
}
//------------------------------------------------------------------
BOOL CPwsDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
if (!FInitServerInfo())
return FALSE;
// start up the sink
InitializeSink();
// see if the pwstray executable is available
CString pathTray;
if ( GetPWSTrayPath(pathTray) )
{
m_fIsPWSTrayAvailable = (GetFileAttributes(pathTray) != 0xFFFFFFFF);
}
// return success
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// CPwsDoc serialization
//------------------------------------------------------------------
void CPwsDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
}
else
{
}
}
/////////////////////////////////////////////////////////////////////////////
// CPwsDoc diagnostics
#ifdef _DEBUG
//------------------------------------------------------------------
void CPwsDoc::AssertValid() const
{
CDocument::AssertValid();
}
//------------------------------------------------------------------
void CPwsDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// Access to the server methods
//------------------------------------------------------------------
// initialize the location of the server - it is stored in the registry
BOOL CPwsDoc::FInitServerInfo()
{
DWORD err;
HKEY hKey;
DWORD iType = REG_SZ;
DWORD cbPath = MAX_PATH+1;
LPTSTR pPath;
// open the registry key, if it exists
err = RegOpenKeyEx(
HKEY_LOCAL_MACHINE, // handle of open key
REG_INSTALL_PATH, // address of name of subkey to open
0, // reserved
KEY_READ, // security access mask
&hKey // address of handle of open key
);
// if we were not able to open the key, then there was an error in the installation
if ( err != ERROR_SUCCESS )
{
AfxMessageBox( IDS_INSTALL_ERROR );
return FALSE;
}
// set up the buffer
pPath = m_szServerPath.GetBuffer( cbPath );
// get the base installation path for the server executable
err = RegQueryValueEx( hKey, REG_PATH_VAL, NULL, &iType, (PUCHAR)pPath, &cbPath );
// release the name buffers
m_szServerPath.ReleaseBuffer();
// all done, close the key before leaving
RegCloseKey( hKey );
// check the error code and fail if necessary
if ( err != ERROR_SUCCESS )
AfxMessageBox( IDS_INSTALL_ERROR );
// return success
return (err == ERROR_SUCCESS);
}
//------------------------------------------------------------------
// updates the state of the server. Affects both the status strings and the
// avis. Can be called from either a change notify or OnIdle.
void CPwsDoc::UpdateServerState()
{
}
//------------------------------------------------------------------
BOOL CPwsDoc::LauchAppIfNecessary()
{
BOOL f;
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInfo;
TCHAR path[MAX_PATH+1];
// if this is running under NT, skip this part
OSVERSIONINFO osver;
osver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx( &osver );
if ( osver.dwPlatformId == VER_PLATFORM_WIN32_NT )
return TRUE;
// if the window is there, the exe is running and we don't have to do anything
if ( FindWindow(SERVER_WINDOWCLASS_NAME, NULL) )
return TRUE;
CString szExeName;
szExeName.LoadString( IDS_EXECUTABLE );
ZeroMemory(&startupInfo,sizeof(STARTUPINFO));
startupInfo.cb = sizeof(STARTUPINFO);
CString szAppl;
szAppl.LoadString( IDS_INETINFO_EXE );
_tcscpy(path, m_szServerPath);
_tcscat(path, _T("\\"));
_tcscat(path, szAppl);
//
// the app is not running. Attempt to start the executable
//
f = CreateProcess(
(LPCTSTR)path,
(LPTSTR)(LPCTSTR)szExeName,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&startupInfo,
&processInfo
);
if ( !f )
{
AfxMessageBox( IDS_ERROR_START );
// failure
return FALSE;
}
// success
return TRUE;
}
//------------------------------------------------------------------
void CPwsDoc::PerformAction( DWORD action, DWORD expected )
{
}
//------------------------------------------------------------------
// if the service is running, stop it. If it is stopped, start it
void CPwsDoc::ToggleService()
{
}
/////////////////////////////////////////////////////////////////////////////
// CPwsDoc commands
//------------------------------------------------------------------
void CPwsDoc::OnUpdateShowTips(CCmdUI* pCmdUI)
{
pCmdUI->Enable( TRUE );
}
//------------------------------------------------------------------
void CPwsDoc::OnUpdateStart(CCmdUI* pCmdUI)
{
CW3ServerControl serverController;
DWORD dwState = serverController.GetServerState();
pCmdUI->Enable( dwState == MD_SERVER_STATE_STOPPED );
}
//------------------------------------------------------------------
void CPwsDoc::OnUpdateStop(CCmdUI* pCmdUI)
{
CW3ServerControl serverController;
DWORD dwState = serverController.GetServerState();
pCmdUI->Enable( (dwState == MD_SERVER_STATE_STARTED) ||
(dwState == MD_SERVER_STATE_PAUSED) );
}
//------------------------------------------------------------------
void CPwsDoc::OnUpdatePause(CCmdUI* pCmdUI)
{
CW3ServerControl serverController;
DWORD dwState = serverController.GetServerState();
pCmdUI->Enable( dwState == MD_SERVER_STATE_STARTED );
}
//------------------------------------------------------------------
void CPwsDoc::OnUpdateContinue(CCmdUI* pCmdUI)
{
CW3ServerControl serverController;
DWORD dwState = serverController.GetServerState();
pCmdUI->Enable( dwState == MD_SERVER_STATE_PAUSED );
}
//------------------------------------------------------------------
void CPwsDoc::OnStart()
{
CW3ServerControl serverController;
serverController.StartServer();
}
//------------------------------------------------------------------
void CPwsDoc::OnStop()
{
CW3ServerControl serverController;
serverController.StopServer();
// if this is win95 and the main pane is showing, tell it to update
if ( !m_fIsWinNT && g_FormMain )
g_FormMain->UpdateServerState();
}
//------------------------------------------------------------------
void CPwsDoc::OnPause()
{
CW3ServerControl serverController;
serverController.PauseServer();
}
//------------------------------------------------------------------
void CPwsDoc::OnContinue()
{
CW3ServerControl serverController;
serverController.ContinueServer();
}
//------------------------------------------------------------------
void CPwsDoc::OnShowTips()
{
CTipDlg dlg;
dlg.DoModal();
}
/*
//------------------------------------------------------------------
void CPwsDoc::OnHelpFinder()
{
DWORD err;
// build the path to the help file
CString szPath;
szPath.LoadString( IDS_HELP_LOC );
szPath = m_szServerPath + szPath;
// use shellexecute to open the file
ShellExecute( NULL, NULL, (PCHAR)(LPCSTR)szPath, NULL, NULL, SW_SHOW );
err = GetLastError();
if ( err )
{
// just re-use szPath
szPath.LoadString(IDS_NO_HELP);
szPath.Format( "%s\nError = %d", szPath, err );
AfxMessageBox( szPath );
}
}
*/
//------------------------------------------------------------------
void CPwsDoc::OnHelpDocumentation()
{
// this documentation only works if it is served. Thus, if the local
// server is not running, we should tell that to the user.
CW3ServerControl serverController;
if ( g_fShutdownMode || (serverController.GetServerState() != MD_SERVER_STATE_STARTED) )
{
AfxMessageBox( IDS_HELPERR_REQUIRES_SERVER );
return;
}
// load the served help docs url
CString szHelpURL;
szHelpURL.LoadString( IDS_HELPLOC_DOCS );
// use shellexecute to access the help via the browser
ShellExecute(
NULL, // handle to parent window
NULL, // pointer to string that specifies operation to perform
szHelpURL, // pointer to filename or folder name string
NULL, // pointer to string that specifies executable-file parameters
NULL, // pointer to string that specifies default directory
SW_SHOW // whether file is shown when opened
);
}
//------------------------------------------------------------------
void CPwsDoc::OnHelpHelpTroubleshooting()
{
// load the relative file path for the troublshooting
CString szTroublePath;
szTroublePath.LoadString( IDS_HELPLOC_README );
// expand the path
CString szExpandedPath;
ExpandEnvironmentStrings(
szTroublePath, // pointer to string with environment variables
szExpandedPath.GetBuffer(MAX_PATH + 1), // pointer to string with expanded environment variables
MAX_PATH // maximum characters in expanded string
);
szExpandedPath.ReleaseBuffer();
// use shellexecute to access the help via the browser
ShellExecute(
NULL, // handle to parent window
NULL, // pointer to string that specifies operation to perform
szExpandedPath, // pointer to filename or folder name string
NULL, // pointer to string that specifies executable-file parameters
NULL, // pointer to string that specifies default directory
SW_SHOW // whether file is shown when opened
);
}
//------------------------------------------------------------------
void CPwsDoc::OnUpdateTrayicon(CCmdUI* pCmdUI)
{
// if the exe is available, show the right thing
if ( m_fIsPWSTrayAvailable )
{
pCmdUI->Enable( TRUE );
pCmdUI->SetCheck( (::FindWindow(PWS_TRAY_WINDOW_CLASS,NULL) != NULL) );
}
else
{
pCmdUI->Enable( FALSE );
pCmdUI->SetCheck( FALSE );
}
}
//------------------------------------------------------------------
void CPwsDoc::OnTrayicon()
{
HWND hwndTray = FindWindow(PWS_TRAY_WINDOW_CLASS,NULL);
CString sz;
// first, act directly on the application
if ( hwndTray != NULL )
{
PostMessage( hwndTray, WM_CLOSE, 0, 0 );
// make sure it doesn't start up again
}
// else start it up
else
{
if ( GetPWSTrayPath( sz ) )
{
ShellExecute(
NULL, // handle to parent window
NULL, // pointer to string that specifies operation to perform
sz, // pointer to filename or folder name string
NULL, // pointer to string that specifies executable-file parameters
NULL, // pointer to string that specifies default directory
0 // whether file is shown when opened
);
}
// make sure it starts up again
}
// now write the proper value to the registry so that pwstray does, or doesn't
// get launched the next time you log on to the system
sz.LoadString( IDS_PWSTRAY_EXE );
DWORD err;
HKEY hKey;
DWORD cbdata = sizeof(TCHAR) * (sz.GetLength() + 1);
// open the registry key, if it exists
err = RegOpenKeyEx(
HKEY_LOCAL_MACHINE, // handle of open key
SZ_KEY_RUN_TRAY, // address of name of subkey to open
0, // reserved
KEY_WRITE, // security access mask
&hKey // address of handle of open key
);
// if we did not open the key for any reason (say... it doesn't exist)
// then show the icon
if ( err != ERROR_SUCCESS )
return;
//do the right thing
if ( hwndTray )
{
// remove it
err = RegDeleteValue(
hKey, // handle of key
SZ_KEY_RUN_VALUE // address of value name
);
}
else
{
// add it
err = RegSetValueEx(
hKey, // handle of key to query
SZ_KEY_RUN_VALUE, // address of name of value to query
0, // reserved
REG_SZ, // address of buffer for value type
(LPBYTE)(LPCTSTR)sz, // address of data buffer
cbdata // address of data buffer size
);
}
// all done, close the key before leaving
RegCloseKey( hKey );
}
//------------------------------------------------------------------
BOOL CPwsDoc::GetPWSTrayPath( CString &sz )
{
if ( !GetSystemDirectory(sz.GetBuffer(MAX_PATH+1),MAX_PATH) )
return FALSE;
sz.ReleaseBuffer();
// add on the executable part
CString szExe;
szExe.LoadString( IDS_PWSTRAY_EXE );
sz += '\\';
sz += szExe;
return TRUE;
}