1872 lines
52 KiB
C++
1872 lines
52 KiB
C++
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1996-1999 Microsoft Corporation
|
|
//
|
|
// Module Name:
|
|
// ExtObj.cpp
|
|
//
|
|
// Abstract:
|
|
// Implementation of the CExtObject class, which implements the
|
|
// extension interfaces required by a Microsoft Windows NT Cluster
|
|
// Administrator Extension DLL.
|
|
//
|
|
// Author:
|
|
// David Potter (davidp) August 29, 1996
|
|
//
|
|
// Revision History:
|
|
//
|
|
// Notes:
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "stdafx.h"
|
|
#include "CluAdmX.h"
|
|
#include "ExtObj.h"
|
|
|
|
#include "GenApp.h"
|
|
#include "GenScript.h"
|
|
#include "GenSvc.h"
|
|
#include "NetName.h"
|
|
#include "Disks.h"
|
|
#include "PrtSpool.h"
|
|
#include "SmbShare.h"
|
|
#include "IpAddr.h"
|
|
#include "RegRepl.h"
|
|
#include "AclUtils.h"
|
|
#include "ClusPage.h"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Global Variables
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
const WCHAR g_wszResourceTypeNames[] =
|
|
RESTYPE_NAME_GENERIC_APP L"\0"
|
|
RESTYPE_NAME_GENERIC_SCRIPT L"\0"
|
|
RESTYPE_NAME_GENERIC_SERVICE L"\0"
|
|
RESTYPE_NAME_NETWORK_NAME L"\0"
|
|
RESTYPE_NAME_PHYS_DISK L"\0"
|
|
#ifdef SUPPORT_FT_SET
|
|
RESTYPE_NAME_FT_SET L"\0"
|
|
#endif // SUPPORT_FT_SET
|
|
RESTYPE_NAME_PRINT_SPOOLER L"\0"
|
|
RESTYPE_NAME_FILE_SHARE L"\0"
|
|
RESTYPE_NAME_IP_ADDRESS L"\0"
|
|
;
|
|
const DWORD g_cchResourceTypeNames = sizeof(g_wszResourceTypeNames) / sizeof(WCHAR);
|
|
|
|
static CRuntimeClass * g_rgprtcPSGenAppPages[] = {
|
|
RUNTIME_CLASS(CGenericAppParamsPage),
|
|
RUNTIME_CLASS(CRegReplParamsPage),
|
|
NULL
|
|
};
|
|
static CRuntimeClass * g_rgprtcPSGenScriptPages[] = {
|
|
RUNTIME_CLASS(CGenericScriptParamsPage),
|
|
NULL
|
|
};
|
|
static CRuntimeClass * g_rgprtcPSGenSvcPages[] = {
|
|
RUNTIME_CLASS(CGenericSvcParamsPage),
|
|
RUNTIME_CLASS(CRegReplParamsPage),
|
|
NULL
|
|
};
|
|
static CRuntimeClass * g_rgprtcPSNetNamePages[] = {
|
|
RUNTIME_CLASS(CNetworkNameParamsPage),
|
|
NULL
|
|
};
|
|
static CRuntimeClass * g_rgprtcPSPhysDiskPages[] = {
|
|
RUNTIME_CLASS(CPhysDiskParamsPage),
|
|
NULL
|
|
};
|
|
#ifdef SUPPORT_FT_SET
|
|
static CRuntimeClass * g_rgprtcPSFTSetPages[] = {
|
|
RUNTIME_CLASS(CPhysDiskParamsPage),
|
|
NULL
|
|
};
|
|
#endif // SUPPORT_FT_SET
|
|
static CRuntimeClass * g_rgprtcPSPrintSpoolerPages[] = {
|
|
RUNTIME_CLASS(CPrintSpoolerParamsPage),
|
|
NULL
|
|
};
|
|
static CRuntimeClass * g_rgprtcPSFileSharePages[] = {
|
|
RUNTIME_CLASS(CFileShareParamsPage),
|
|
NULL
|
|
};
|
|
static CRuntimeClass * g_rgprtcPSIpAddrPages[] = {
|
|
RUNTIME_CLASS(CIpAddrParamsPage),
|
|
NULL
|
|
};
|
|
|
|
static CRuntimeClass ** g_rgpprtcPSPages[] = {
|
|
g_rgprtcPSGenAppPages,
|
|
g_rgprtcPSGenScriptPages,
|
|
g_rgprtcPSGenSvcPages,
|
|
g_rgprtcPSNetNamePages,
|
|
g_rgprtcPSPhysDiskPages,
|
|
#ifdef SUPPORT_FT_SET
|
|
g_rgprtcPSFTSetPages,
|
|
#endif // SUPPORT_FT_SET
|
|
g_rgprtcPSPrintSpoolerPages,
|
|
g_rgprtcPSFileSharePages,
|
|
g_rgprtcPSIpAddrPages,
|
|
};
|
|
|
|
// Wizard pages and property sheet pages are the same.
|
|
static CRuntimeClass ** g_rgpprtcWizPages[] = {
|
|
g_rgprtcPSGenAppPages,
|
|
g_rgprtcPSGenScriptPages,
|
|
g_rgprtcPSGenSvcPages,
|
|
g_rgprtcPSNetNamePages,
|
|
g_rgprtcPSPhysDiskPages,
|
|
#ifdef SUPPORT_FT_SET
|
|
g_rgprtcPSFTSetPages,
|
|
#endif // SUPPORT_FT_SET
|
|
g_rgprtcPSPrintSpoolerPages,
|
|
g_rgprtcPSFileSharePages,
|
|
g_rgprtcPSIpAddrPages,
|
|
};
|
|
|
|
#ifdef _DEMO_CTX_MENUS
|
|
static WCHAR g_wszGenAppMenuItems[] = {
|
|
L"GenApp Item 1\0First Generic Application menu item\0"
|
|
L"GenApp Item 2\0Second Generic Application menu item\0"
|
|
L"GenApp Item 3\0Third Generic Application menu item\0"
|
|
L"\0"
|
|
};
|
|
static WCHAR g_wszGenSvcMenuItems[] = {
|
|
L"GenSvc Item 1\0First Generic Service menu item\0"
|
|
L"GenSvc Item 2\0Second Generic Service menu item\0"
|
|
L"GenSvc Item 3\0Third Generic Service menu item\0"
|
|
L"\0"
|
|
};
|
|
static WCHAR g_wszNetNameMenuItems[] = {
|
|
L"NetName Item 1\0First Network Name menu item\0"
|
|
L"NetName Item 2\0Second Network Name menu item\0"
|
|
L"NetName Item 3\0Third Network Name menu item\0"
|
|
L"\0"
|
|
};
|
|
static WCHAR g_wszPhysDiskMenuItems[] = {
|
|
L"PhysDisk Item 1\0First Physical Disk menu item\0"
|
|
L"PhysDisk Item 2\0Second Physical Disk menu item\0"
|
|
L"PhysDisk Item 3\0Third Physical Disk menu item\0"
|
|
L"\0"
|
|
};
|
|
static WCHAR g_wszFileShareMenuItems[] = {
|
|
L"FileShare Item 1\0First File Share menu item\0"
|
|
L"FileShare Item 2\0Second File Share menu item\0"
|
|
L"FileShare Item 3\0Third File Share menu item\0"
|
|
L"\0"
|
|
};
|
|
static WCHAR g_wszIpAddrMenuItems[] = {
|
|
L"IpAddr Item 1\0First IP Address menu item\0"
|
|
L"IpAddr Item 2\0Second IP Address menu item\0"
|
|
L"IpAddr Item 3\0Third IP Address menu item\0"
|
|
L"\0"
|
|
};
|
|
|
|
static LPWSTR g_rgpwszContextMenuItems[] = {
|
|
g_wszGenAppMenuItems,
|
|
g_wszGenSvcMenuItems,
|
|
g_wszNetNameMenuItems,
|
|
g_wszPhysDiskMenuItems,
|
|
g_wszFileShareMenuItems,
|
|
g_wszIpAddrMenuItems,
|
|
};
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CExtObject
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::CExtObject
|
|
//
|
|
// Routine Description:
|
|
// Default constructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CExtObject::CExtObject(void)
|
|
{
|
|
m_piData = NULL;
|
|
m_piWizardCallback = NULL;
|
|
m_bWizard = FALSE;
|
|
m_istrResTypeName = 0;
|
|
|
|
m_hcluster = NULL;
|
|
m_lcid = NULL;
|
|
m_hfont = NULL;
|
|
m_hicon = NULL;
|
|
m_podObjData = NULL;
|
|
m_pCvi = NULL;
|
|
|
|
} //*** CExtObject::CExtObject()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::~CExtObject
|
|
//
|
|
// Routine Description:
|
|
// Destructor.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// None.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
CExtObject::~CExtObject(void)
|
|
{
|
|
// Release the data interface.
|
|
if (PiData() != NULL)
|
|
{
|
|
PiData()->Release();
|
|
m_piData = NULL;
|
|
} // if: we have a data interface pointer
|
|
|
|
// Release the wizard callback interface.
|
|
if (PiWizardCallback() != NULL)
|
|
{
|
|
PiWizardCallback()->Release();
|
|
m_piWizardCallback = NULL;
|
|
} // if: we have a wizard callback interface pointer
|
|
|
|
// Delete the pages.
|
|
{
|
|
POSITION pos;
|
|
|
|
pos = Lpg().GetHeadPosition();
|
|
while (pos != NULL)
|
|
delete Lpg().GetNext(pos);
|
|
} // Delete the pages
|
|
|
|
delete m_podObjData;
|
|
delete m_pCvi;
|
|
|
|
} //*** CExtObject::~CExtObject()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// ISupportErrorInfo Implementation
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::InterfaceSupportsErrorInfo (ISupportErrorInfo)
|
|
//
|
|
// Routine Description:
|
|
// Indicates whether an interface suportes the IErrorInfo interface.
|
|
// This interface is provided by ATL.
|
|
//
|
|
// Arguments:
|
|
// riid Interface ID.
|
|
//
|
|
// Return Value:
|
|
// S_OK Interface supports IErrorInfo.
|
|
// S_FALSE Interface does not support IErrorInfo.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CExtObject::InterfaceSupportsErrorInfo(REFIID riid)
|
|
{
|
|
static const IID * rgiid[] =
|
|
{
|
|
&IID_IWEExtendPropertySheet,
|
|
&IID_IWEExtendWizard,
|
|
#ifdef _DEMO_CTX_MENUS
|
|
&IID_IWEExtendContextMenu,
|
|
#endif
|
|
};
|
|
int iiid;
|
|
|
|
for (iiid = 0 ; iiid < sizeof(rgiid) / sizeof(rgiid[0]) ; iiid++)
|
|
{
|
|
if (InlineIsEqualGUID(*rgiid[iiid], riid))
|
|
return S_OK;
|
|
}
|
|
return S_FALSE;
|
|
|
|
} //*** CExtObject::InterfaceSupportsErrorInfo()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// IWEExtendPropertySheet Implementation
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::CreatePropertySheetPages (IWEExtendPropertySheet)
|
|
//
|
|
// Routine Description:
|
|
// Create property sheet pages and add them to the sheet.
|
|
//
|
|
// Arguments:
|
|
// piData IUnkown pointer from which to obtain interfaces
|
|
// for obtaining data describing the object for
|
|
// which the sheet is being displayed.
|
|
// piCallback Pointer to an IWCPropertySheetCallback interface
|
|
// for adding pages to the sheet.
|
|
//
|
|
// Return Value:
|
|
// NOERROR Pages added successfully.
|
|
// E_INVALIDARG Invalid arguments to the function.
|
|
// E_OUTOFMEMORY Error allocating memory.
|
|
// E_FAIL Error creating a page.
|
|
// E_NOTIMPL Not implemented for this type of data.
|
|
// Any error codes from IDataObject::GetData() (through HrSaveData()).
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CExtObject::CreatePropertySheetPages(
|
|
IN IUnknown * piData,
|
|
IN IWCPropertySheetCallback * piCallback
|
|
)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
HPROPSHEETPAGE hpage = NULL;
|
|
CException exc(FALSE /*bAutoDelete*/);
|
|
CRuntimeClass ** pprtc = NULL;
|
|
int irtc;
|
|
CBasePropertyPage * ppage;
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
// Validate the parameters.
|
|
if ((piData == NULL) || (piCallback == NULL))
|
|
return E_INVALIDARG;
|
|
|
|
try
|
|
{
|
|
// Get info about displaying UI.
|
|
hr = HrGetUIInfo(piData);
|
|
if (hr != NOERROR)
|
|
throw &exc;
|
|
|
|
// Save the data.
|
|
hr = HrSaveData(piData);
|
|
if (hr != NOERROR)
|
|
throw &exc;
|
|
|
|
// Delete any previous pages.
|
|
{
|
|
POSITION pos;
|
|
|
|
pos = Lpg().GetHeadPosition();
|
|
while (pos != NULL)
|
|
delete Lpg().GetNext(pos);
|
|
Lpg().RemoveAll();
|
|
} // Delete any previous pages
|
|
|
|
// Create property pages.
|
|
ASSERT(PodObjData() != NULL);
|
|
switch (PodObjData()->m_cot)
|
|
{
|
|
case CLUADMEX_OT_CLUSTER:
|
|
{
|
|
CClusterSecurityPage *pClusterSecurityPage = new CClusterSecurityPage;
|
|
|
|
if ( pClusterSecurityPage != NULL )
|
|
{
|
|
// Add it to the list.
|
|
Lpg().AddTail( pClusterSecurityPage );
|
|
|
|
hr = pClusterSecurityPage->HrInit( this );
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = piCallback->AddPropertySheetPage(
|
|
(LONG *) pClusterSecurityPage->GetHPage() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
throw &exc;
|
|
}
|
|
}
|
|
break;
|
|
case CLUADMEX_OT_RESOURCE:
|
|
pprtc = g_rgpprtcPSPages[IstrResTypeName()];
|
|
break;
|
|
default:
|
|
hr = E_NOTIMPL;
|
|
throw &exc;
|
|
break;
|
|
} // switch: object type
|
|
|
|
if (pprtc)
|
|
{
|
|
// Create each page.
|
|
for (irtc = 0 ; pprtc[irtc] != NULL ; irtc++)
|
|
{
|
|
// Create the page.
|
|
ppage = (CBasePropertyPage *) pprtc[irtc]->CreateObject();
|
|
ASSERT(ppage->IsKindOf(pprtc[irtc]));
|
|
|
|
// Add it to the list.
|
|
Lpg().AddTail(ppage);
|
|
|
|
// Initialize the property page.
|
|
hr = ppage->HrInit(this);
|
|
if (FAILED(hr))
|
|
throw &exc;
|
|
|
|
// Create the page.
|
|
hpage = ::CreatePropertySheetPage(&ppage->m_psp);
|
|
if (hpage == NULL)
|
|
{
|
|
DWORD sc = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(sc);
|
|
throw &exc;
|
|
} // if: error creating the page
|
|
|
|
// Save the hpage in the page itself.
|
|
ppage->SetHpage(hpage);
|
|
|
|
// Add it to the property sheet.
|
|
hr = piCallback->AddPropertySheetPage((LONG *) hpage);
|
|
if (hr != NOERROR)
|
|
throw &exc;
|
|
} // for: each page in the list
|
|
} // if: pprtc is null
|
|
|
|
} // try
|
|
catch (CMemoryException * pme)
|
|
{
|
|
TRACE(_T("CExtObject::CreatePropetySheetPages() - Failed to add property page\n"));
|
|
pme->Delete();
|
|
hr = E_OUTOFMEMORY;
|
|
} // catch: anything
|
|
catch (CException * pe)
|
|
{
|
|
TRACE(_T("CExtObject::CreatePropetySheetPages() - Failed to add property page\n"));
|
|
pe->Delete();
|
|
if (hr == NOERROR)
|
|
hr = E_FAIL;
|
|
} // catch: anything
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
if (hpage != NULL)
|
|
::DestroyPropertySheetPage(hpage);
|
|
piData->Release();
|
|
m_piData = NULL;
|
|
} // if: error occurred
|
|
|
|
piCallback->Release();
|
|
return hr;
|
|
|
|
} //*** CExtObject::CreatePropertySheetPages()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// IWEExtendWizard Implementation
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::CreateWizardPages (IWEExtendWizard)
|
|
//
|
|
// Routine Description:
|
|
// Create property sheet pages and add them to the wizard.
|
|
//
|
|
// Arguments:
|
|
// piData IUnkown pointer from which to obtain interfaces
|
|
// for obtaining data describing the object for
|
|
// which the wizard is being displayed.
|
|
// piCallback Pointer to an IWCPropertySheetCallback interface
|
|
// for adding pages to the sheet.
|
|
//
|
|
// Return Value:
|
|
// NOERROR Pages added successfully.
|
|
// E_INVALIDARG Invalid arguments to the function.
|
|
// E_OUTOFMEMORY Error allocating memory.
|
|
// E_FAIL Error creating a page.
|
|
// E_NOTIMPL Not implemented for this type of data.
|
|
// Any error codes from IDataObject::GetData() (through HrSaveData()).
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CExtObject::CreateWizardPages(
|
|
IN IUnknown * piData,
|
|
IN IWCWizardCallback * piCallback
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
HPROPSHEETPAGE hpage = NULL;
|
|
CException exc(FALSE /*bAutoDelete*/);
|
|
int irtc;
|
|
CBasePropertyPage * ppage;
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
// Validate the parameters.
|
|
if ((piData == NULL) || (piCallback == NULL))
|
|
return E_INVALIDARG;
|
|
|
|
try
|
|
{
|
|
// Get info about displaying UI.
|
|
hr = HrGetUIInfo(piData);
|
|
if (hr != NOERROR)
|
|
throw &exc;
|
|
|
|
// Save the data.
|
|
hr = HrSaveData(piData);
|
|
if (hr != NOERROR)
|
|
throw &exc;
|
|
|
|
// Delete any previous pages.
|
|
{
|
|
POSITION pos;
|
|
|
|
pos = Lpg().GetHeadPosition();
|
|
while (pos != NULL)
|
|
delete Lpg().GetNext(pos);
|
|
Lpg().RemoveAll();
|
|
} // Delete any previous pages
|
|
|
|
m_piWizardCallback = piCallback;
|
|
m_bWizard = TRUE;
|
|
|
|
// Add each page for this type of resource.
|
|
for (irtc = 0 ; g_rgpprtcWizPages[IstrResTypeName()][irtc] != NULL ; irtc++)
|
|
{
|
|
// Create the property pages.
|
|
ppage = (CBasePropertyPage *) g_rgpprtcWizPages[IstrResTypeName()][irtc]->CreateObject();
|
|
ASSERT(ppage->IsKindOf(g_rgpprtcWizPages[IstrResTypeName()][irtc]));
|
|
|
|
// Add it to the list.
|
|
Lpg().AddTail(ppage);
|
|
|
|
// Initialize the property page.
|
|
hr = ppage->HrInit(this);
|
|
if (FAILED(hr))
|
|
throw &exc;
|
|
|
|
// Create the page.
|
|
hpage = ::CreatePropertySheetPage(&ppage->m_psp);
|
|
if (hpage == NULL)
|
|
{
|
|
DWORD sc = GetLastError();
|
|
hr = HRESULT_FROM_WIN32(sc);
|
|
throw &exc;
|
|
} // if: error creating the page
|
|
|
|
// Save the hpage in the page itself.
|
|
ppage->SetHpage(hpage);
|
|
|
|
// Add it to the property sheet.
|
|
hr = piCallback->AddWizardPage((LONG *) hpage);
|
|
if (hr != NOERROR)
|
|
throw &exc;
|
|
} // for: each page for the type of resource
|
|
} // try
|
|
catch (CMemoryException * pme)
|
|
{
|
|
TRACE(_T("CExtObject::CreateWizardPages: Failed to add wizard page (CMemoryException)\n"));
|
|
pme->Delete();
|
|
hr = E_OUTOFMEMORY;
|
|
} // catch: CMemoryException
|
|
catch (CException * pe)
|
|
{
|
|
TRACE(_T("CExtObject::CreateWizardPages: Failed to add wizard page (CException)\n"));
|
|
pe->Delete();
|
|
if (hr == NOERROR)
|
|
hr = E_FAIL;
|
|
} // catch: CException
|
|
// catch (...)
|
|
// {
|
|
// TRACE(_T("CExtObject::CreateWizardPages: Failed to add wizard page (...)\n"));
|
|
// } // catch: anything
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
if (hpage != NULL)
|
|
::DestroyPropertySheetPage(hpage);
|
|
piCallback->Release();
|
|
if ( m_piWizardCallback == piCallback )
|
|
{
|
|
m_piWizardCallback = NULL;
|
|
} // if: already saved interface pointer
|
|
piData->Release();
|
|
m_piData = NULL;
|
|
} // if: error occurred
|
|
|
|
return hr;
|
|
|
|
} //*** CExtObject::CreateWizardPages()
|
|
|
|
#ifdef _DEMO_CTX_MENUS
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// IWEExtendContextMenu Implementation
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::AddContextMenuItems (IWEExtendContextMenu)
|
|
//
|
|
// Routine Description:
|
|
// Add items to a context menu.
|
|
//
|
|
// Arguments:
|
|
// piData IUnkown pointer from which to obtain interfaces
|
|
// for obtaining data describing the object for
|
|
// which the context menu is being displayed.
|
|
// piCallback Pointer to an IWCContextMenuCallback interface
|
|
// for adding menu items to the context menu.
|
|
//
|
|
// Return Value:
|
|
// NOERROR Pages added successfully.
|
|
// E_INVALIDARG Invalid arguments to the function.
|
|
// E_FAIL Error adding context menu item.
|
|
// E_NOTIMPL Not implemented for this type of data.
|
|
// Any error codes returned by HrSaveData() or IWCContextMenuCallback::
|
|
// AddExtensionMenuItem().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
STDMETHODIMP CExtObject::AddContextMenuItems(
|
|
IN IUnknown * piData,
|
|
IN IWCContextMenuCallback * piCallback
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
CException exc(FALSE /*bAutoDelete*/);
|
|
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
// Validate the parameters.
|
|
if ((piData == NULL) || (piCallback == NULL))
|
|
return E_INVALIDARG;
|
|
|
|
try
|
|
{
|
|
// Save the data.
|
|
hr = HrSaveData(piData);
|
|
if (hr != NOERROR)
|
|
throw &exc;
|
|
|
|
// Add menu items specific to this resource type.
|
|
{
|
|
ULONG iCommandID;
|
|
LPWSTR pwsz = g_rgpwszContextMenuItems[IstrResTypeName()];
|
|
LPWSTR pwszName;
|
|
LPWSTR pwszStatusBarText;
|
|
|
|
for (iCommandID = 0 ; *pwsz != L'\0' ; iCommandID++)
|
|
{
|
|
pwszName = pwsz;
|
|
pwszStatusBarText = pwszName + (lstrlenW(pwszName) + 1);
|
|
hr = piCallback->AddExtensionMenuItem(
|
|
pwszName, // lpszName
|
|
pwszStatusBarText, // lpszStatusBarText
|
|
iCommandID, // lCommandID
|
|
0, // lSubCommandID
|
|
0 // uFlags
|
|
);
|
|
if (hr != NOERROR)
|
|
throw &exc;
|
|
pwsz = pwszStatusBarText + (lstrlenW(pwszStatusBarText) + 1);
|
|
} // while: more menu items to add
|
|
} // Add menu items specific to this resource type
|
|
} // try
|
|
catch (CException * pe)
|
|
{
|
|
TRACE(_T("CExtObject::CreatePropetySheetPages: Failed to add context menu item\n"));
|
|
pe->Delete();
|
|
if (hr == NOERROR)
|
|
hr = E_FAIL;
|
|
} // catch: anything
|
|
|
|
if (hr != NOERROR)
|
|
{
|
|
piData->Release();
|
|
m_piData = NULL;
|
|
} // if: error occurred
|
|
|
|
piCallback->Release();
|
|
return hr;
|
|
|
|
} //*** CExtObject::AddContextMenuItems()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// IWEInvokeCommand Implementation
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::InvokeCommand (IWEInvokeCommand)
|
|
//
|
|
// Routine Description:
|
|
// Invoke a command offered by a context menu.
|
|
//
|
|
// Arguments:
|
|
// lCommandID ID of the menu item to execute. This is the same
|
|
// ID passed to the IWCContextMenuCallback
|
|
// ::AddExtensionMenuItem() method.
|
|
// piData IUnkown pointer from which to obtain interfaces
|
|
// for obtaining data describing the object for
|
|
// which the command is to be invoked.
|
|
//
|
|
// Return Value:
|
|
// NOERROR Command invoked successfully.
|
|
// E_INVALIDARG Invalid arguments to the function.
|
|
// E_OUTOFMEMORY Error allocating memory.
|
|
// E_NOTIMPL Not implemented for this type of data.
|
|
// Any error codes from IDataObject::GetData() (through HrSaveData()).
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CExtObject::InvokeCommand(
|
|
IN ULONG nCommandID,
|
|
IN IUnknown * piData
|
|
)
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
// Find the item that was executed in our table.
|
|
hr = HrSaveData(piData);
|
|
if (hr == NOERROR)
|
|
{
|
|
ULONG iCommandID;
|
|
LPWSTR pwsz = g_rgpwszContextMenuItems[IstrResTypeName()];
|
|
LPWSTR pwszName;
|
|
LPWSTR pwszStatusBarText;
|
|
|
|
for (iCommandID = 0 ; *pwsz != L'\0' ; iCommandID++)
|
|
{
|
|
pwszName = pwsz;
|
|
pwszStatusBarText = pwszName + (lstrlenW(pwszName) + 1);
|
|
if (iCommandID == nCommandID)
|
|
break;
|
|
pwsz = pwszStatusBarText + (lstrlenW(pwszStatusBarText) + 1);
|
|
} // while: more menu items to add
|
|
if (iCommandID == nCommandID)
|
|
{
|
|
CString strMsg;
|
|
CString strName;
|
|
|
|
try
|
|
{
|
|
strName = pwszName;
|
|
strMsg.Format(_T("Item %s was executed"), strName);
|
|
AfxMessageBox(strMsg);
|
|
} // try
|
|
catch (CException * pe)
|
|
{
|
|
pe->Delete();
|
|
} // catch: CException
|
|
} // if: command ID found
|
|
} // if: no errors saving the data
|
|
|
|
piData->Release();
|
|
m_piData = NULL;
|
|
return NOERROR;
|
|
|
|
} //*** CExtObject::InvokeCommand()
|
|
#endif
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::HrGetUIInfo
|
|
//
|
|
// Routine Description:
|
|
// Get info about displaying UI.
|
|
//
|
|
// Arguments:
|
|
// piData IUnkown pointer from which to obtain interfaces
|
|
// for obtaining data describing the object.
|
|
//
|
|
// Return Value:
|
|
// NOERROR Data saved successfully.
|
|
// E_NOTIMPL Not implemented for this type of data.
|
|
// Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
|
|
// or HrGetResourceName().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CExtObject::HrGetUIInfo(IUnknown * piData)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
ASSERT(piData != NULL);
|
|
|
|
// Save info about all types of objects.
|
|
{
|
|
IGetClusterUIInfo * pi;
|
|
|
|
hr = piData->QueryInterface(IID_IGetClusterUIInfo, (LPVOID *) &pi);
|
|
if (hr != NOERROR)
|
|
return hr;
|
|
|
|
m_lcid = pi->GetLocale();
|
|
m_hfont = pi->GetFont();
|
|
m_hicon = pi->GetIcon();
|
|
|
|
pi->Release();
|
|
} // Save info about all types of objects
|
|
|
|
return hr;
|
|
|
|
} //*** CExtObject::HrGetUIInfo()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::HrSaveData
|
|
//
|
|
// Routine Description:
|
|
// Save data from the object so that it can be used for the life
|
|
// of the object.
|
|
//
|
|
// Arguments:
|
|
// piData IUnkown pointer from which to obtain interfaces
|
|
// for obtaining data describing the object.
|
|
//
|
|
// Return Value:
|
|
// NOERROR Data saved successfully.
|
|
// E_NOTIMPL Not implemented for this type of data.
|
|
// Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
|
|
// or HrGetResourceName().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CExtObject::HrSaveData(IUnknown * piData)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
ASSERT(piData != NULL);
|
|
|
|
if (piData != m_piData)
|
|
{
|
|
if (m_piData != NULL)
|
|
m_piData->Release();
|
|
m_piData = piData;
|
|
} // if: different data interface pointer
|
|
|
|
// Save info about all types of objects.
|
|
{
|
|
IGetClusterDataInfo * pi;
|
|
|
|
hr = piData->QueryInterface(IID_IGetClusterDataInfo, (LPVOID *) &pi);
|
|
if (hr != NOERROR)
|
|
return hr;
|
|
|
|
m_hcluster = pi->GetClusterHandle();
|
|
m_cobj = pi->GetObjectCount();
|
|
if (Cobj() != 1)
|
|
hr = E_NOTIMPL;
|
|
else
|
|
hr = HrGetClusterName(pi);
|
|
|
|
pi->Release();
|
|
if (hr != NOERROR)
|
|
return hr;
|
|
} // Save info about all types of objects
|
|
|
|
// Save info about this object.
|
|
hr = HrGetObjectInfo();
|
|
if (hr != NOERROR)
|
|
return hr;
|
|
|
|
return hr;
|
|
|
|
} //*** CExtObject::HrSaveData()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::HrGetObjectInfo
|
|
//
|
|
// Routine Description:
|
|
// Get information about the object.
|
|
//
|
|
// Arguments:
|
|
// None.
|
|
//
|
|
// Return Value:
|
|
// NOERROR Data saved successfully.
|
|
// E_OUTOFMEMORY Error allocating memory.
|
|
// E_NOTIMPL Not implemented for this type of data.
|
|
// Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
|
|
// or HrGetResourceName().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CExtObject::HrGetObjectInfo(void)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
IGetClusterObjectInfo * piGcoi;
|
|
CLUADMEX_OBJECT_TYPE cot = CLUADMEX_OT_NONE;
|
|
CException exc(FALSE /*bAutoDelete*/);
|
|
const CString * pstrResTypeName = NULL;
|
|
|
|
ASSERT(PiData() != NULL);
|
|
|
|
// Get object info.
|
|
{
|
|
// Get an IGetClusterObjectInfo interface pointer.
|
|
hr = PiData()->QueryInterface(IID_IGetClusterObjectInfo, (LPVOID *) &piGcoi);
|
|
if (hr != NOERROR)
|
|
return hr;
|
|
|
|
// Read the object data.
|
|
try
|
|
{
|
|
// Delete the previous object data.
|
|
delete m_podObjData;
|
|
m_podObjData = NULL;
|
|
|
|
// Get the type of the object.
|
|
cot = piGcoi->GetObjectType(0);
|
|
switch (cot)
|
|
{
|
|
case CLUADMEX_OT_CLUSTER:
|
|
m_podObjData = new CObjData;
|
|
if ( m_podObjData == NULL )
|
|
{
|
|
AfxThrowMemoryException();
|
|
}
|
|
break;
|
|
|
|
case CLUADMEX_OT_RESOURCE:
|
|
{
|
|
IGetClusterResourceInfo * pi;
|
|
|
|
m_podObjData = new CResData;
|
|
if ( m_podObjData == NULL )
|
|
{
|
|
AfxThrowMemoryException();
|
|
}
|
|
|
|
// Get an IGetClusterResourceInfo interface pointer.
|
|
hr = PiData()->QueryInterface(IID_IGetClusterResourceInfo, (LPVOID *) &pi);
|
|
if (hr != NOERROR)
|
|
{
|
|
throw &exc;
|
|
}
|
|
|
|
PrdResDataRW()->m_hresource = pi->GetResourceHandle(0);
|
|
ASSERT(PrdResDataRW()->m_hresource != NULL);
|
|
if (PrdResDataRW()->m_hresource == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
hr = HrGetResourceTypeName(pi);
|
|
}
|
|
|
|
pi->Release();
|
|
if (hr != NOERROR)
|
|
{
|
|
throw &exc;
|
|
}
|
|
|
|
pstrResTypeName = &PrdResDataRW()->m_strResTypeName;
|
|
} // if: object is a resource
|
|
break;
|
|
|
|
case CLUADMEX_OT_RESOURCETYPE:
|
|
m_podObjData = new CObjData;
|
|
if ( m_podObjData == NULL )
|
|
{
|
|
AfxThrowMemoryException();
|
|
}
|
|
pstrResTypeName = &PodObjDataRW()->m_strName;
|
|
break;
|
|
|
|
default:
|
|
hr = E_NOTIMPL;
|
|
throw &exc;
|
|
|
|
} // switch: object type
|
|
|
|
PodObjDataRW()->m_cot = cot;
|
|
hr = HrGetObjectName(piGcoi);
|
|
|
|
} // try
|
|
catch (CMemoryException * pme)
|
|
{
|
|
pme->Delete();
|
|
hr = E_OUTOFMEMORY;
|
|
} // catch: CMemoryException
|
|
catch (CException * pe)
|
|
{
|
|
pe->Delete();
|
|
} // catch: CException
|
|
|
|
piGcoi->Release();
|
|
if (hr != NOERROR)
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
} // Get object info
|
|
|
|
// If this is a resource or resource type, see if we know about this type.
|
|
if (((cot == CLUADMEX_OT_RESOURCE)
|
|
|| (cot == CLUADMEX_OT_RESOURCETYPE))
|
|
&& (hr == NOERROR))
|
|
{
|
|
LPCWSTR pwszResTypeName = NULL;
|
|
|
|
// Find the resource type name in our list.
|
|
// Save the index for use in other arrays.
|
|
for (m_istrResTypeName = 0, pwszResTypeName = g_wszResourceTypeNames
|
|
; *pwszResTypeName != L'\0'
|
|
; m_istrResTypeName++, pwszResTypeName += lstrlenW(pwszResTypeName) + 1
|
|
)
|
|
{
|
|
if (pstrResTypeName->CompareNoCase(pwszResTypeName) == 0)
|
|
{
|
|
break;
|
|
}
|
|
} // for: each resource type in the list
|
|
|
|
if (*pwszResTypeName == L'\0')
|
|
{
|
|
hr = E_NOTIMPL;
|
|
}
|
|
|
|
} // See if we know about this resource type
|
|
|
|
return hr;
|
|
|
|
} //*** CExtObject::HrGetObjectInfo()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::HrGetClusterName
|
|
//
|
|
// Routine Description:
|
|
// Get the name of the cluster.
|
|
//
|
|
// Arguments:
|
|
// piData IGetClusterDataInfo interface pointer for getting
|
|
// the object name.
|
|
//
|
|
// Return Value:
|
|
// NOERROR Data saved successfully.
|
|
// E_NOTIMPL Not implemented for this type of data.
|
|
// Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
|
|
// or HrGetResourceName().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CExtObject::HrGetClusterName(
|
|
IN OUT IGetClusterDataInfo * pi
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
WCHAR * pwszName = NULL;
|
|
LONG cchName;
|
|
|
|
ASSERT(pi != NULL);
|
|
|
|
hr = pi->GetClusterName(NULL, &cchName);
|
|
if (hr != NOERROR)
|
|
return hr;
|
|
|
|
try
|
|
{
|
|
pwszName = new WCHAR[cchName];
|
|
hr = pi->GetClusterName(pwszName, &cchName);
|
|
if (hr != NOERROR)
|
|
{
|
|
delete [] pwszName;
|
|
pwszName = NULL;
|
|
} // if: error getting cluster name
|
|
|
|
m_strClusterName = pwszName;
|
|
} // try
|
|
catch (CMemoryException * pme)
|
|
{
|
|
pme->Delete();
|
|
hr = E_OUTOFMEMORY;
|
|
} // catch: CMemoryException
|
|
|
|
delete [] pwszName;
|
|
return hr;
|
|
|
|
} //*** CExtObject::HrGetClusterName()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::HrGetObjectName
|
|
//
|
|
// Routine Description:
|
|
// Get the name of the object.
|
|
//
|
|
// Arguments:
|
|
// piData IGetClusterObjectInfo interface pointer for getting
|
|
// the object name.
|
|
//
|
|
// Return Value:
|
|
// NOERROR Data saved successfully.
|
|
// E_NOTIMPL Not implemented for this type of data.
|
|
// Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
|
|
// or HrGetResourceName().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CExtObject::HrGetObjectName(
|
|
IN OUT IGetClusterObjectInfo * pi
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
WCHAR * pwszName = NULL;
|
|
LONG cchName;
|
|
|
|
ASSERT(pi != NULL);
|
|
|
|
hr = pi->GetObjectName(0, NULL, &cchName);
|
|
if (hr != NOERROR)
|
|
return hr;
|
|
|
|
try
|
|
{
|
|
pwszName = new WCHAR[cchName];
|
|
hr = pi->GetObjectName(0, pwszName, &cchName);
|
|
if (hr != NOERROR)
|
|
{
|
|
delete [] pwszName;
|
|
pwszName = NULL;
|
|
} // if: error getting object name
|
|
|
|
PodObjDataRW()->m_strName = pwszName;
|
|
} // try
|
|
catch (CMemoryException * pme)
|
|
{
|
|
pme->Delete();
|
|
hr = E_OUTOFMEMORY;
|
|
} // catch: CMemoryException
|
|
|
|
delete [] pwszName;
|
|
return hr;
|
|
|
|
} //*** CExtObject::HrGetObjectName()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::HrGetClusterVersion
|
|
//
|
|
// Routine Description:
|
|
// Get the version of the cluster.
|
|
//
|
|
// Arguments:
|
|
// ppCvi [OUT] holds the Cluster version info.
|
|
//
|
|
// Return Value:
|
|
// NOERROR Data retrieved successfully.
|
|
// E_NOTIMPL Not implemented for this type of data.
|
|
// Any error codes from GetClusterInformation()
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CExtObject::HrGetClusterVersion(
|
|
OUT LPCLUSTERVERSIONINFO *ppCvi
|
|
)
|
|
{
|
|
ASSERT(ppCvi != NULL);
|
|
|
|
HRESULT hr = E_FAIL;
|
|
|
|
if (ppCvi != NULL)
|
|
{
|
|
if (m_pCvi == NULL)
|
|
{
|
|
LPWSTR pwszName = NULL;
|
|
DWORD cchName = 128;
|
|
CWaitCursor wc;
|
|
|
|
try
|
|
{
|
|
pwszName = new WCHAR[cchName];
|
|
m_pCvi = new CLUSTERVERSIONINFO;
|
|
|
|
m_pCvi->dwVersionInfoSize = sizeof( CLUSTERVERSIONINFO );
|
|
|
|
hr = GetClusterInformation(Hcluster(), pwszName, &cchName, m_pCvi);
|
|
if (hr == ERROR_MORE_DATA)
|
|
{
|
|
delete [] pwszName;
|
|
cchName++;
|
|
pwszName = new WCHAR[cchName];
|
|
hr = GetClusterInformation(Hcluster(), pwszName, &cchName, m_pCvi);
|
|
} // if: buffer is too small
|
|
|
|
delete [] pwszName;
|
|
*ppCvi = m_pCvi;
|
|
} // try
|
|
catch (CException *)
|
|
{
|
|
delete [] pwszName;
|
|
delete m_pCvi;
|
|
m_pCvi = NULL;
|
|
throw;
|
|
} // catch: CException
|
|
}
|
|
else
|
|
{
|
|
*ppCvi = m_pCvi;
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
|
|
} //*** CExtObject::HrGetClusterVersion()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::HrGetResourceTypeName
|
|
//
|
|
// Routine Description:
|
|
// Get the name of the resource's type.
|
|
//
|
|
// Arguments:
|
|
// piData IGetClusterResourceInfo interface pointer for getting
|
|
// the resource type name.
|
|
//
|
|
// Return Value:
|
|
// NOERROR Data saved successfully.
|
|
// E_NOTIMPL Not implemented for this type of data.
|
|
// Any error codes from IUnknown::QueryInterface(), HrGetObjectName(),
|
|
// or HrGetResourceName().
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
HRESULT CExtObject::HrGetResourceTypeName(
|
|
IN OUT IGetClusterResourceInfo * pi
|
|
)
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
WCHAR * pwszName = NULL;
|
|
LONG cchName;
|
|
|
|
ASSERT(pi != NULL);
|
|
|
|
hr = pi->GetResourceTypeName(0, NULL, &cchName);
|
|
if (hr != NOERROR)
|
|
return hr;
|
|
|
|
try
|
|
{
|
|
pwszName = new WCHAR[cchName];
|
|
hr = pi->GetResourceTypeName(0, pwszName, &cchName);
|
|
if (hr != NOERROR)
|
|
{
|
|
delete [] pwszName;
|
|
pwszName = NULL;
|
|
} // if: error getting resource type name
|
|
|
|
PrdResDataRW()->m_strResTypeName = pwszName;
|
|
} // try
|
|
catch (CMemoryException * pme)
|
|
{
|
|
pme->Delete();
|
|
hr = E_OUTOFMEMORY;
|
|
} // catch: CMemoryException
|
|
|
|
delete [] pwszName;
|
|
return hr;
|
|
|
|
} //*** CExtObject::HrGetResourceTypeName()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BGetResourceNetworkName
|
|
//
|
|
// Routine Description:
|
|
// Get the name of the resource's type.
|
|
//
|
|
// Arguments:
|
|
// lpszNetName [OUT] String in which to return the network name resource name.
|
|
// pcchNetName [IN OUT] Points to a variable that specifies the
|
|
// maximum size, in characters, of the buffer. This
|
|
// value shold be large enough to contain
|
|
// MAX_COMPUTERNAME_LENGTH + 1 characters. Upon
|
|
// return it contains the actual number of characters
|
|
// copied.
|
|
//
|
|
// Return Value:
|
|
// TRUE Resource is dependent on a network name resource.
|
|
// FALSE Resource is NOT dependent on a network name resource.
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BGetResourceNetworkName(
|
|
OUT WCHAR * lpszNetName,
|
|
IN OUT DWORD * pcchNetName
|
|
)
|
|
{
|
|
BOOL bSuccess;
|
|
IGetClusterResourceInfo * piGcri;
|
|
|
|
ASSERT(PiData() != NULL);
|
|
|
|
// Get an IGetClusterResourceInfo interface pointer.
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = PiData()->QueryInterface(IID_IGetClusterResourceInfo, (LPVOID *) &piGcri);
|
|
if (hr != NOERROR)
|
|
{
|
|
SetLastError(hr);
|
|
return FALSE;
|
|
} // if: error getting the interface
|
|
} // Get an IGetClusterResourceInfo interface pointer
|
|
|
|
// Get the resource network name.
|
|
bSuccess = piGcri->GetResourceNetworkName(0, lpszNetName, pcchNetName);
|
|
|
|
piGcri->Release();
|
|
|
|
return bSuccess;
|
|
|
|
} //*** CExtObject::BGetResourceNetworkName()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsClusterVersionMixed
|
|
//
|
|
// Routine Description:
|
|
// Is the cluster of mixed version? Meaning that a rolling upgrade is
|
|
// is in progress and not all nodes are up to the current version.
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE Cluster is mixed version
|
|
// FALSE Cluster is homogonous
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsClusterVersionMixed(
|
|
void
|
|
)
|
|
{
|
|
BOOL bRet = FALSE;
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
bRet = pCvi->dwFlags & CLUSTER_VERSION_FLAG_MIXED_MODE;
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsClusterVersionMixed()
|
|
|
|
#if 0
|
|
//SS: cant tell whether a cluster is a mixed mode sp4 and sp3 cluster or a pure sp3 cluster
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsClusterVersionNT4Sp3
|
|
//
|
|
// Routine Description:
|
|
// Is the cluster version NT4Sp3?
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE Cluster is version NT4Sp3
|
|
// FALSE Cluster is not version NT4Sp3
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsClusterVersionNT4Sp3(
|
|
void
|
|
)
|
|
{
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if ((CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT4_MAJOR_VERSION) &&
|
|
!(BIsClusterVersionMixed()))
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsClusterVersionNT4Sp3()
|
|
|
|
#endif//SS: cant tell whether a cluster is a mixed mode sp4 and sp3 cluster or a pure sp3 cluster
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsClusterVersionNT4Sp4
|
|
//
|
|
// Routine Description:
|
|
// Is the cluster version a pure NT4Sp4 cluster
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE Cluster is version NT4Sp4
|
|
// FALSE Cluster is not version NT4Sp4
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsClusterVersionNT4Sp4(
|
|
void
|
|
)
|
|
{
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if ((CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT4SP4_MAJOR_VERSION) &&
|
|
!(BIsClusterVersionMixed()))
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsClusterVersionNT4Sp4()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsClusterVersionNT5
|
|
//
|
|
// Routine Description:
|
|
// Is the cluster version a pure NT5 version?
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE Cluster is version NT5
|
|
// FALSE Cluster is not version NT5
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsClusterVersionNT5(
|
|
void
|
|
)
|
|
{
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if ((CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT5_MAJOR_VERSION) &&
|
|
!(BIsClusterVersionMixed()))
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsClusterVersionNT5()
|
|
|
|
#if 0
|
|
//SS: cant tell whether a cluster is a mixed mode sp4 and sp3 cluster
|
|
//or a pure sp3 cluster
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsClusterHighestVersionNT4Sp3
|
|
//
|
|
// Routine Description:
|
|
// Is the highest cluster version NT4Sp3?
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE highest cluster is version NT4Sp3
|
|
// FALSE highest cluster is not version NT4Sp3
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsClusterHighestVersionNT4Sp3(
|
|
void
|
|
)
|
|
{
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterLowestVersion) == NT4_MAJOR_VERSION)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsClusterHighestVersionNT4Sp3()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsClusterHighestVersionNT4Sp4
|
|
//
|
|
// Routine Description:
|
|
// Is the highest cluster version NT4Sp4?
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE highest cluster is version NT4Sp4
|
|
// FALSE highest cluster is not version NT4Sp4
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsClusterHighestVersionNT4Sp4(
|
|
void
|
|
)
|
|
{
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterLowestVersion) == NT4_MAJOR_VERSION)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsClusterHighestVersionNT4Sp4()
|
|
|
|
#endif //SS: cant tell whether a cluster is a mixed mode sp4 and sp3 cluster or a pure sp3 cluster
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsClusterHighestVersionNT5
|
|
//
|
|
// Routine Description:
|
|
// Is the highest cluster version NT5? Is the node with the
|
|
// highest version in the cluster an nt 5 node.
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE highest cluster is version NT5
|
|
// FALSE highest cluster is not version NT5
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsClusterHighestVersionNT5(
|
|
void
|
|
)
|
|
{
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterLowestVersion) == NT4SP4_MAJOR_VERSION)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsClusterHighestVersionNT5()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsClusterLowestVersionNT4Sp3
|
|
//
|
|
// Routine Description:
|
|
// Is the Lowest cluster version NT4Sp3? Is the node with the lowest
|
|
// version an nt4 sp3 node
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE Lowest cluster is version NT4Sp3
|
|
// FALSE Lowest cluster is not version NT4Sp3
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsClusterLowestVersionNT4Sp3(
|
|
void
|
|
)
|
|
{
|
|
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT4_MAJOR_VERSION)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsClusterLowestVersionNT4Sp3()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsClusterLowestVersionNT4Sp4
|
|
//
|
|
// Routine Description:
|
|
// Is the Lowest cluster version NT4Sp4?Is the node with the lowest
|
|
// version an nt4 sp4 node.
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE Lowest cluster is version NT4Sp4
|
|
// FALSE Lowest cluster is not version NT4Sp4
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsClusterLowestVersionNT4Sp4(
|
|
void
|
|
)
|
|
{
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT4SP4_MAJOR_VERSION)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsClusterLowestVersionNT4Sp4()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsClusterLowestVersionNT5
|
|
//
|
|
// Routine Description:
|
|
// Is the Lowest cluster version NT5?Is the node with the lowest
|
|
// version an nt5 node
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE Lowest cluster is version NT5
|
|
// FALSE Lowest cluster is not version NT5
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsClusterLowestVersionNT5(
|
|
void
|
|
)
|
|
{
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT5_MAJOR_VERSION)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsClusterLowestVersionNT5()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsAnyNodeVersionLowerThanNT5
|
|
//
|
|
// Routine Description:
|
|
// Is the Lowest cluster version NT5?Is the node with the lowest
|
|
// version an nt5 node
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE Lowest cluster is version NT5
|
|
// FALSE Lowest cluster is not version NT5
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsAnyNodeVersionLowerThanNT5(
|
|
void
|
|
)
|
|
{
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) < NT5_MAJOR_VERSION)
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsClusterLowestVersionNT5()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsNT5ClusterMember
|
|
//
|
|
// Routine Description:
|
|
// Is NT5 a cluster member?
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE NT5 is a cluster member
|
|
// FALSE NT5 is not a cluster member
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsNT5ClusterMember(
|
|
void
|
|
)
|
|
{
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if ((CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT5_MAJOR_VERSION)
|
|
|| (CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterLowestVersion) == NT4SP4_MAJOR_VERSION))
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsNT5ClusterMember()
|
|
|
|
#if 0
|
|
//SS: cant tell whether a cluster is a mixed mode sp4 and sp3 cluster
|
|
//or a pure sp3 cluster
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsNT4Sp3ClusterMember
|
|
//
|
|
// Routine Description:
|
|
// Is NT4Sp3 a cluster member?
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE NT4Sp3 is a cluster member
|
|
// FALSE NT4Sp3 is not a cluster member
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsNT4Sp3ClusterMember(
|
|
void
|
|
)
|
|
{
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if ((CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT4_MAJOR_VERSION))
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsNT4Sp3ClusterMember()
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//++
|
|
//
|
|
// CExtObject::BIsNT4Sp4ClusterMember
|
|
//
|
|
// Routine Description:
|
|
// Is NT4Sp4 a cluster member?
|
|
//
|
|
// Arguments:
|
|
// none.
|
|
//
|
|
// Return Value:
|
|
// TRUE NT4Sp4 is a cluster member
|
|
// FALSE NT4Sp4 is not a cluster member
|
|
//
|
|
//--
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
BOOL CExtObject::BIsNT4Sp4ClusterMember(
|
|
void
|
|
)
|
|
{
|
|
LPCLUSTERVERSIONINFO pCvi;
|
|
BOOL bRet = FALSE;
|
|
|
|
if (SUCCEEDED(HrGetClusterVersion(&pCvi)))
|
|
{
|
|
if ((CLUSTER_GET_MAJOR_VERSION(pCvi->dwClusterHighestVersion) == NT4SP4_MAJOR_VERSION))
|
|
{
|
|
bRet = TRUE;
|
|
}
|
|
}
|
|
|
|
return bRet;
|
|
|
|
} //*** CExtObject::BIsNT4Sp4ClusterMember()
|
|
|
|
#endif
|