771 lines
12 KiB
C++
771 lines
12 KiB
C++
|
/*++
|
||
|
|
||
|
Copyright (c) 1994-1999 Microsoft Corporation
|
||
|
|
||
|
Module Name :
|
||
|
|
||
|
shts.cpp
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
IIS Property sheet classes
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Ronald Meijer (ronaldm)
|
||
|
|
||
|
Project:
|
||
|
|
||
|
Internet Services Manager (cluster edition)
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
#include "stdafx.h"
|
||
|
#include "common.h"
|
||
|
#include "inetprop.h"
|
||
|
#include "InetMgrApp.h"
|
||
|
#include "shts.h"
|
||
|
#include "mime.h"
|
||
|
#include "iisobj.h"
|
||
|
#include "shutdown.h"
|
||
|
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
#undef THIS_FILE
|
||
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
||
|
#endif
|
||
|
|
||
|
|
||
|
|
||
|
#define new DEBUG_NEW
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// CInetPropertySheet class
|
||
|
//
|
||
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||
|
|
||
|
|
||
|
|
||
|
IMPLEMENT_DYNAMIC(CInetPropertySheet, CPropertySheet)
|
||
|
|
||
|
|
||
|
|
||
|
CInetPropertySheet::CInetPropertySheet(
|
||
|
CComAuthInfo * pAuthInfo,
|
||
|
LPCTSTR lpszMetaPath,
|
||
|
CWnd * pParentWnd,
|
||
|
LPARAM lParam,
|
||
|
LONG_PTR handle,
|
||
|
UINT iSelectPage
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
IIS Property Sheet constructor
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CComAuthInfo * pAuthInfo : Authentication information
|
||
|
LPCTSTR lpszMetPath : Metabase path
|
||
|
CWnd * pParentWnd : Optional parent window
|
||
|
LPARAM lParam : MMC Console parameter
|
||
|
LONG_PTR handle : MMC Console handle
|
||
|
UINT iSelectPage : Initial page to be selected
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
N/A
|
||
|
|
||
|
--*/
|
||
|
: CPropertySheet(_T(""), pParentWnd, iSelectPage),
|
||
|
m_auth(pAuthInfo),
|
||
|
m_strMetaPath(lpszMetaPath),
|
||
|
m_dwInstance(0L),
|
||
|
m_bModeless(FALSE),
|
||
|
m_hConsole(handle),
|
||
|
m_lParam(lParam),
|
||
|
m_fHasAdminAccess(TRUE), // Assumed by default
|
||
|
m_pCap(NULL),
|
||
|
m_refcount(0),
|
||
|
m_fRestartRequired(FALSE),
|
||
|
m_fChanged(FALSE)
|
||
|
{
|
||
|
m_fIsMasterPath = CMetabasePath::IsMasterInstance(lpszMetaPath);
|
||
|
TRACEEOLID("Metabase path is master? " << m_fIsMasterPath);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
CInetPropertySheet::NotifyMMC()
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Notify MMC that changes have been made, so that the changes are
|
||
|
reflected.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
//
|
||
|
// Notify MMC to update changes.
|
||
|
//
|
||
|
if (m_hConsole != NULL)
|
||
|
{
|
||
|
ASSERT(m_lParam != 0L);
|
||
|
MMCPropertyChangeNotify(m_hConsole, m_lParam);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
CInetPropertySheet::~CInetPropertySheet()
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
IIS Property Sheet destructor
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
N/A
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
N/A
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
// At this moment we should have in m_pages only pages that were not activated
|
||
|
// in this session.
|
||
|
while (!m_pages.IsEmpty())
|
||
|
{
|
||
|
CInetPropertyPage * pPage = m_pages.RemoveHead();
|
||
|
delete pPage;
|
||
|
}
|
||
|
if (m_fChanged)
|
||
|
{
|
||
|
NotifyMMC();
|
||
|
}
|
||
|
if (m_hConsole != NULL)
|
||
|
{
|
||
|
MMCFreeNotifyHandle(m_hConsole);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
CInetPropertySheet::AttachPage(CInetPropertyPage * pPage)
|
||
|
{
|
||
|
m_pages.AddTail(pPage);
|
||
|
}
|
||
|
|
||
|
|
||
|
void
|
||
|
CInetPropertySheet::DetachPage(CInetPropertyPage * pPage)
|
||
|
{
|
||
|
POSITION pos = m_pages.Find(pPage);
|
||
|
ASSERT(pos != NULL);
|
||
|
if (pos != NULL)
|
||
|
{
|
||
|
m_fChanged |= pPage->IsDirty();
|
||
|
m_pages.RemoveAt(pos);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WORD
|
||
|
CInetPropertySheet::QueryMajorVersion() const
|
||
|
{
|
||
|
CIISMBNode * pNode = (CIISMBNode *)m_lParam;
|
||
|
ASSERT(pNode != NULL);
|
||
|
return pNode->QueryMajorVersion();
|
||
|
}
|
||
|
|
||
|
WORD
|
||
|
CInetPropertySheet::QueryMinorVersion() const
|
||
|
{
|
||
|
CIISMBNode * pNode = (CIISMBNode *)m_lParam;
|
||
|
ASSERT(pNode != NULL);
|
||
|
return pNode->QueryMinorVersion();
|
||
|
}
|
||
|
|
||
|
/* virtual */
|
||
|
HRESULT
|
||
|
CInetPropertySheet::LoadConfigurationParameters()
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Load configuration parameters information
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
HRESULT
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
//
|
||
|
// Load base values
|
||
|
//
|
||
|
CError err;
|
||
|
|
||
|
if (m_pCap == NULL)
|
||
|
{
|
||
|
TRACEEOLID("Determining path locations for " << m_strMetaPath);
|
||
|
|
||
|
//
|
||
|
// Capability info stored off the service path ("lm/w3svc").
|
||
|
//
|
||
|
ASSERT(m_strInfoPath.IsEmpty());
|
||
|
|
||
|
//
|
||
|
// Building path components
|
||
|
//
|
||
|
CMetabasePath::GetServiceInfoPath(m_strMetaPath, m_strInfoPath);
|
||
|
|
||
|
TRACEEOLID("Storing info path: " << m_strInfoPath);
|
||
|
|
||
|
//
|
||
|
// Split into instance and directory paths
|
||
|
//
|
||
|
if (IsMasterInstance())
|
||
|
{
|
||
|
m_strServicePath = m_strInstancePath = QueryMetaPath();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
VERIFY(CMetabasePath::GetInstancePath(
|
||
|
QueryMetaPath(),
|
||
|
m_strInstancePath,
|
||
|
&m_strDirectoryPath
|
||
|
));
|
||
|
|
||
|
VERIFY(CMetabasePath::GetServicePath(
|
||
|
QueryMetaPath(),
|
||
|
m_strServicePath
|
||
|
));
|
||
|
}
|
||
|
|
||
|
TRACEEOLID("Service path " << m_strServicePath);
|
||
|
TRACEEOLID("Instance path " << m_strInstancePath);
|
||
|
|
||
|
if (m_strDirectoryPath.IsEmpty() && !IsMasterInstance())
|
||
|
{
|
||
|
m_strDirectoryPath = CMetabasePath(FALSE, QueryMetaPath(), g_cszRoot);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
m_strDirectoryPath = QueryMetaPath();
|
||
|
}
|
||
|
|
||
|
TRACEEOLID("Directory path " << m_strDirectoryPath);
|
||
|
|
||
|
m_dwInstance = CMetabasePath::GetInstanceNumber(m_strMetaPath);
|
||
|
|
||
|
TRACEEOLID("Instance number " << m_dwInstance);
|
||
|
|
||
|
m_pCap = new CServerCapabilities(QueryAuthInfo(), m_strInfoPath);
|
||
|
|
||
|
if (!m_pCap)
|
||
|
{
|
||
|
err = ERROR_NOT_ENOUGH_MEMORY;
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
err = m_pCap->LoadData();
|
||
|
|
||
|
if (err.Succeeded())
|
||
|
{
|
||
|
err = DetermineAdminAccess();
|
||
|
}
|
||
|
}
|
||
|
return err;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* virtual */
|
||
|
void
|
||
|
CInetPropertySheet::FreeConfigurationParameters()
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Clean up configuration data
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
// ASSERT_PTR(m_pCap);
|
||
|
SAFE_DELETE(m_pCap);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
CInetPropertySheet::WinHelp(
|
||
|
IN DWORD dwData,
|
||
|
IN UINT nCmd
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
WinHelp override. We can't use the base class, because our
|
||
|
'sheet' doesn't usually have a window handle
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
DWORD dwData : Help data
|
||
|
UINT nCmd : Help command
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
TCHAR szBuffer[20];
|
||
|
_stprintf(szBuffer,_T("WinHelp:0x%x\n"),dwData);OutputDebugString(szBuffer);
|
||
|
#endif
|
||
|
|
||
|
if (m_hWnd == NULL)
|
||
|
{
|
||
|
/*
|
||
|
//
|
||
|
// Special case
|
||
|
//
|
||
|
::WinHelp(
|
||
|
HWND hWndMain,
|
||
|
LPCWSTR lpszHelp,
|
||
|
UINT uCommand,
|
||
|
DWORD dwData
|
||
|
);
|
||
|
*/
|
||
|
|
||
|
CWnd * pWnd = ::AfxGetMainWnd();
|
||
|
|
||
|
if (pWnd != NULL)
|
||
|
{
|
||
|
pWnd->WinHelp(dwData, nCmd);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
CPropertySheet::WinHelp(dwData, nCmd);
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Message Map
|
||
|
//
|
||
|
BEGIN_MESSAGE_MAP(CInetPropertySheet, CPropertySheet)
|
||
|
//{{AFX_MSG_MAP(CInetPropertySheet)
|
||
|
//}}AFX_MSG_MAP
|
||
|
END_MESSAGE_MAP()
|
||
|
|
||
|
|
||
|
//
|
||
|
// CInetPropertyPage class
|
||
|
//
|
||
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// CInetPropertyPage property page
|
||
|
//
|
||
|
IMPLEMENT_DYNAMIC(CInetPropertyPage, CPropertyPage)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
|
||
|
/* virtual */
|
||
|
void
|
||
|
CInetPropertyPage::AssertValid() const
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* virtual */
|
||
|
void
|
||
|
CInetPropertyPage::Dump(CDumpContext& dc) const
|
||
|
{
|
||
|
}
|
||
|
|
||
|
#endif // _DEBUG
|
||
|
|
||
|
|
||
|
|
||
|
CInetPropertyPage::CInetPropertyPage(
|
||
|
IN UINT nIDTemplate,
|
||
|
IN CInetPropertySheet * pSheet,
|
||
|
IN UINT nIDCaption,
|
||
|
IN BOOL fEnableEnhancedFonts OPTIONAL
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
IIS Property Page Constructor
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
UINT nIDTemplate : Resource template
|
||
|
CInetPropertySheet * pSheet : Associated property sheet
|
||
|
UINT nIDCaption : Caption ID
|
||
|
BOOL fEnableEnhancedFonts : Enable enhanced fonts
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
N/A
|
||
|
|
||
|
--*/
|
||
|
: CPropertyPage(nIDTemplate, nIDCaption),
|
||
|
m_nHelpContext(nIDTemplate + 0x20000),
|
||
|
m_fEnableEnhancedFonts(fEnableEnhancedFonts),
|
||
|
m_bChanged(FALSE),
|
||
|
m_pSheet(pSheet)
|
||
|
{
|
||
|
//{{AFX_DATA_INIT(CInetPropertyPage)
|
||
|
//}}AFX_DATA_INIT
|
||
|
|
||
|
m_psp.dwFlags |= PSP_HASHELP;
|
||
|
|
||
|
ASSERT(m_pSheet != NULL);
|
||
|
m_pSheet->AttachPage(this);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
CInetPropertyPage::~CInetPropertyPage()
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
IIS Property Page Destructor
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
N/A
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
N/A
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
CInetPropertyPage::DoDataExchange(
|
||
|
IN CDataExchange * pDX
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Initialise/Store control data
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
CDataExchange * pDX - DDX/DDV control structure
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
CPropertyPage::DoDataExchange(pDX);
|
||
|
|
||
|
//{{AFX_DATA_MAP(CInetPropertyPage)
|
||
|
//}}AFX_DATA_MAP
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/* virtual */
|
||
|
void
|
||
|
CInetPropertyPage::PostNcDestroy()
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
handle destruction of the window by freeing the this
|
||
|
pointer (as this modeless dialog must have been created
|
||
|
on the heap)
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None.
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
m_pSheet->Release(this);
|
||
|
delete this;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Message Map
|
||
|
//
|
||
|
BEGIN_MESSAGE_MAP(CInetPropertyPage, CPropertyPage)
|
||
|
//{{AFX_MSG_MAP(CInetPropertyPage)
|
||
|
ON_COMMAND(ID_HELP, OnHelp)
|
||
|
ON_WM_HELPINFO()
|
||
|
//}}AFX_MSG_MAP
|
||
|
END_MESSAGE_MAP()
|
||
|
|
||
|
|
||
|
|
||
|
//
|
||
|
// Message Handlers
|
||
|
//
|
||
|
// <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||
|
|
||
|
|
||
|
|
||
|
/* virtual */
|
||
|
BOOL
|
||
|
CInetPropertyPage::OnInitDialog()
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
WM_INITDIALOG handler. Initialize the dialog. Reset changed
|
||
|
status (sometimes gets set by e.g. spinboxes when the dialog is
|
||
|
constructed), so make sure the dialog is considered clean.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
TRUE if no focus is to be set automatically, FALSE if the focus
|
||
|
is already set.
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
m_bChanged = FALSE;
|
||
|
|
||
|
//
|
||
|
// Tell derived class to load its configuration parameters
|
||
|
//
|
||
|
CError err(LoadConfigurationParameters());
|
||
|
|
||
|
if (err.Succeeded())
|
||
|
{
|
||
|
err = FetchLoadedValues();
|
||
|
}
|
||
|
|
||
|
BOOL bResult = CPropertyPage::OnInitDialog();
|
||
|
|
||
|
err.MessageBoxOnFailure();
|
||
|
|
||
|
if (m_fEnableEnhancedFonts)
|
||
|
{
|
||
|
CFont * pFont = &m_fontBold;
|
||
|
|
||
|
if (CreateSpecialDialogFont(this, pFont))
|
||
|
{
|
||
|
ApplyFontToControls(this, pFont, IDC_ED_BOLD1, IDC_ED_BOLD5);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// We should call AddRef here, not in page constructor, because PostNCDestroy()
|
||
|
// is getting called only for pages that were activated, not for all created pages.
|
||
|
// OnInitDialog is also called for activated pages only -- so we will get parity
|
||
|
// and delete property sheet.
|
||
|
//
|
||
|
ASSERT(m_pSheet != NULL);
|
||
|
m_pSheet->AddRef();
|
||
|
|
||
|
return bResult;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
CInetPropertyPage::OnHelp()
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
'Help' button handler
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
ASSERT_PTR(m_pSheet);
|
||
|
|
||
|
#ifdef _DEBUG
|
||
|
TCHAR szBuffer[20];
|
||
|
_stprintf(szBuffer,_T("WinHelp:0x%x\n"),m_nHelpContext);OutputDebugString(szBuffer);
|
||
|
#endif
|
||
|
|
||
|
m_pSheet->WinHelp(m_nHelpContext);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CInetPropertyPage::OnHelpInfo(
|
||
|
IN HELPINFO * pHelpInfo
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Eat "help info" command
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
OnHelp();
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
BOOL
|
||
|
CInetPropertyPage::OnApply()
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Handle "OK" or "APPLY". Call the derived class to save its stuff,
|
||
|
and set the dirty state depending on whether saving succeeded or
|
||
|
failed.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
None
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
BOOL bSuccess = TRUE;
|
||
|
|
||
|
if (IsDirty())
|
||
|
{
|
||
|
CError err(SaveInfo());
|
||
|
|
||
|
if (err.MessageBoxOnFailure())
|
||
|
{
|
||
|
//
|
||
|
// Failed, sheet will not be dismissed.
|
||
|
//
|
||
|
// CODEWORK: This page should be activated.
|
||
|
//
|
||
|
bSuccess = FALSE;
|
||
|
}
|
||
|
|
||
|
SetModified(!bSuccess);
|
||
|
if (bSuccess && GetSheet()->RestartRequired())
|
||
|
{
|
||
|
// ask user about immediate restart
|
||
|
if (IDYES == ::AfxMessageBox(IDS_ASK_TO_RESTART, MB_YESNO | MB_ICONQUESTION))
|
||
|
{
|
||
|
// restart IIS
|
||
|
CIISMachine * pMachine = new CIISMachine(QueryAuthInfo());
|
||
|
if (pMachine != NULL)
|
||
|
{
|
||
|
CIISShutdownDlg dlg(pMachine, this);
|
||
|
dlg.PerformCommand(ISC_RESTART);
|
||
|
bSuccess = dlg.ServicesWereRestarted();
|
||
|
delete pMachine;
|
||
|
}
|
||
|
}
|
||
|
// mark restart required false to suppress it on other pages
|
||
|
GetSheet()->SetRestartRequired(FALSE);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return bSuccess;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
void
|
||
|
CInetPropertyPage::SetModified(
|
||
|
IN BOOL bChanged
|
||
|
)
|
||
|
/*++
|
||
|
|
||
|
Routine Description:
|
||
|
|
||
|
Keep private check on dirty state of the property page.
|
||
|
|
||
|
Arguments:
|
||
|
|
||
|
BOOL bChanged : Dirty flag
|
||
|
|
||
|
Return Value:
|
||
|
|
||
|
None
|
||
|
|
||
|
--*/
|
||
|
{
|
||
|
CPropertyPage::SetModified(bChanged);
|
||
|
m_bChanged = bChanged;
|
||
|
}
|
||
|
|
||
|
|