windows-nt/Source/XPSP1/NT/admin/snapin/dfsadmin/dfsgui/mmcjp.cpp

1805 lines
49 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Module Name:
MmcJP.cpp
Abstract:
This module contains the implementation for CMmcDfsJP. This is an class
for MMC display related calls for the second level node(the Junction Point nodes)
--*/
#include "stdafx.h"
#include "Utils.h" // For the LoadStringFromResource method
#include "resource.h" // For the Resource ID for strings, etc.
#include "DfsGUI.h"
#include "MmcAdmin.h"
#include "MmcRoot.h"
#include "MmcRep.h"
#include "MenuEnum.h" // Contains the menu and toolbar command ids
#include "AddToDfs.h"
#include "AddRep.h"
#include "MmcJP.h"
#include "DfsNodes.h" // For Node GUIDs
#include "DfsEnums.h" // For DFS_TYPE_STANDALONE and other DfsRoot declarations
#include "NewFrs.h"
const int CMmcDfsJunctionPoint::m_iIMAGEINDEX = 12;
const int CMmcDfsJunctionPoint::m_iOPENIMAGEINDEX = 12;
CMmcDfsJunctionPoint::CMmcDfsJunctionPoint(
IN IDfsJunctionPoint* i_pDfsJPObject,
IN CMmcDfsRoot* i_pDfsParentRoot,
IN LPCONSOLENAMESPACE i_lpConsoleNameSpace
)
{
dfsDebugOut((_T("CMmcDfsJunctionPoint::CMmcDfsJunctionPoint this=%p\n"), this));
MMC_DISP_CTOR_RETURN_INVALIDARG_IF_NULL(i_pDfsJPObject);
MMC_DISP_CTOR_RETURN_INVALIDARG_IF_NULL(i_pDfsParentRoot);
MMC_DISP_CTOR_RETURN_INVALIDARG_IF_NULL(i_lpConsoleNameSpace);
HRESULT hr = S_OK;
m_pDfsJPObject = i_pDfsJPObject;
m_pDfsParentRoot = i_pDfsParentRoot;
hr = m_pDfsJPObject->get_EntryPath(&m_bstrEntryPath);
MMC_DISP_CTOR_RETURN_HR_IF_FAILED(hr);
hr = m_pDfsJPObject->get_JunctionName(FALSE, &m_bstrDisplayName);
MMC_DISP_CTOR_RETURN_HR_IF_FAILED(hr);
m_lJunctionState = DFS_JUNCTION_STATE_UNASSIGNED;
m_lpConsoleNameSpace = i_lpConsoleNameSpace; // The Callback used to do Scope Pane operations
m_lpConsole = m_pDfsParentRoot->m_lpConsole;
m_hScopeItem = NULL; // Scopeitem handle
m_CLSIDNodeType = s_guidDfsJPNodeType;
m_bstrDNodeType = s_tchDfsJPNodeType;
m_bShowFRS = FALSE;
m_bDirty = false;
}
CMmcDfsJunctionPoint :: ~CMmcDfsJunctionPoint(
)
{
// Silently close outstanding property sheet.
ClosePropertySheet(TRUE);
CleanResultChildren();
if ((IReplicaSet *)m_piReplicaSet)
m_piReplicaSet.Release();
dfsDebugOut((_T("CMmcDfsJunctionPoint::~CMmcDfsJunctionPoint this=%p\n"), this));
}
STDMETHODIMP
CMmcDfsJunctionPoint::AddMenuItems(
IN LPCONTEXTMENUCALLBACK i_lpContextMenuCallback,
IN LPLONG i_lpInsertionAllowed
)
/*++
Routine Description:
This routine adds the context menu for Junction point nodes using the ContextMenuCallback
provided.
Arguments:
lpContextMenuCallback - A callback(function pointer) that is used to add the menu items
lpInsertionAllowed - Specifies what menus can be added and where they can be added.
--*/
{
RETURN_INVALIDARG_IF_NULL(i_lpContextMenuCallback);
enum
{
IDM_CONTEXTMENU_COMMAND_MAX = IDM_JUNCTION_MAX,
IDM_CONTEXTMENU_COMMAND_MIN = IDM_JUNCTION_MIN
};
LONG lInsertionPoints [IDM_CONTEXTMENU_COMMAND_MAX - IDM_CONTEXTMENU_COMMAND_MIN + 1] = {
CCM_INSERTIONPOINTID_PRIMARY_TOP,
CCM_INSERTIONPOINTID_PRIMARY_TOP,
CCM_INSERTIONPOINTID_PRIMARY_TOP,
CCM_INSERTIONPOINTID_PRIMARY_TOP,
CCM_INSERTIONPOINTID_PRIMARY_TOP,
CCM_INSERTIONPOINTID_PRIMARY_TOP,
CCM_INSERTIONPOINTID_PRIMARY_TOP
};
BOOL bReplicaSetExist = FALSE;
HRESULT hr = m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
RETURN_IF_FAILED(hr);
// we start with the first menu command id and continue till the last.
for (int iCommandID = IDM_CONTEXTMENU_COMMAND_MIN, iMenuResource = IDS_MENUS_JUNCTION_TOP_NEW_DFS_REPLICA ;
iCommandID <= IDM_CONTEXTMENU_COMMAND_MAX;
iCommandID++,iMenuResource++)
{
CONTEXTMENUITEM ContextMenuItem;
ZeroMemory(&ContextMenuItem, sizeof(ContextMenuItem));
switch (iCommandID)
{
case IDM_JUNCTION_TOP_REPLICATION_TOPOLOGY:
{
if (bReplicaSetExist || (1 >= m_MmcRepList.size()) ||
(DFS_TYPE_STANDALONE == m_pDfsParentRoot->m_lDfsRootType))
continue;
break;
}
case IDM_JUNCTION_TOP_SHOW_REPLICATION:
{
if (!bReplicaSetExist || m_bShowFRS)
continue;
break;
}
case IDM_JUNCTION_TOP_HIDE_REPLICATION:
{
if (!bReplicaSetExist || !m_bShowFRS)
continue;
break;
}
case IDM_JUNCTION_TOP_STOP_REPLICATION:
{
if (!bReplicaSetExist)
continue;
break;
}
}
CComBSTR bstrMenuText;
CComBSTR bstrStatusBarText;
hr = GetMenuResourceStrings(iMenuResource, &bstrMenuText, NULL, &bstrStatusBarText);
RETURN_IF_FAILED(hr);
ContextMenuItem.strName = bstrMenuText;
ContextMenuItem.strStatusBarText = bstrStatusBarText;
ContextMenuItem.lInsertionPointID = lInsertionPoints[iCommandID - IDM_CONTEXTMENU_COMMAND_MIN];
ContextMenuItem.lCommandID = iCommandID;
LONG lInsertionFlag = 0;
switch(ContextMenuItem.lInsertionPointID)
{
case CCM_INSERTIONPOINTID_PRIMARY_TOP:
lInsertionFlag = CCM_INSERTIONALLOWED_TOP;
break;
case CCM_INSERTIONPOINTID_PRIMARY_NEW:
lInsertionFlag = CCM_INSERTIONALLOWED_NEW;
break;
case CCM_INSERTIONPOINTID_PRIMARY_TASK:
lInsertionFlag = CCM_INSERTIONALLOWED_TASK;
break;
case CCM_INSERTIONPOINTID_PRIMARY_VIEW:
lInsertionFlag = CCM_INSERTIONALLOWED_VIEW;
break;
default:
break;
}
if (*i_lpInsertionAllowed & lInsertionFlag)
{
hr = i_lpContextMenuCallback->AddItem(&ContextMenuItem);
RETURN_IF_FAILED(hr);
}
}
return hr;
}
STDMETHODIMP
CMmcDfsJunctionPoint::Command(
IN LONG i_lCommandID
)
/*++
Routine Description:
Action to be taken on a context menu selection or click is takes place.
Arguments:
lCommandID - The Command ID of the menu for which action has to be taken
--*/
{
HRESULT hr = S_OK;
switch (i_lCommandID)
{
case IDM_JUNCTION_TOP_NEW_DFS_REPLICA: // "Add a replica to the Dfs Junction Point"
hr = OnNewReplica();
break;
case IDM_JUNCTION_TOP_REMOVE_FROM_DFS: // "Delete the junction point"
hr = DoDelete();
break;
case IDM_JUNCTION_TOP_REPLICATION_TOPOLOGY:
hr = OnNewReplicaSet();
break;
case IDM_JUNCTION_TOP_SHOW_REPLICATION:
case IDM_JUNCTION_TOP_HIDE_REPLICATION:
m_bShowFRS = !m_bShowFRS;
hr = OnShowReplication();
break;
case IDM_JUNCTION_TOP_STOP_REPLICATION:
hr = OnStopReplication(TRUE);
if (FAILED(hr))
DisplayMessageBoxForHR(hr);
break;
case IDM_JUNCTION_TOP_CHECK_STATUS:
hr = OnCheckStatus();
break;
default:
hr = E_INVALIDARG;
break;
}
return hr;
}
HRESULT CMmcDfsJunctionPoint::_InitReplicaSet()
{
DFS_TYPE lDfsType = DFS_TYPE_UNASSIGNED;
HRESULT hr = GetDfsType((long *)&lDfsType);
RETURN_IF_FAILED(hr);
if (lDfsType != DFS_TYPE_FTDFS)
return S_FALSE; // no replica set associate with standalone root
BOOL bReplicaSetExist = FALSE;
CComBSTR bstrDC;
hr = m_pDfsJPObject->get_ReplicaSetExistEx(&bstrDC, &bReplicaSetExist);
RETURN_IF_FAILED(hr);
if (!bReplicaSetExist)
{
if ((IReplicaSet *)m_piReplicaSet)
m_piReplicaSet.Release();
return S_FALSE; // no replica set associate with it
}
if ((IReplicaSet *)m_piReplicaSet)
{
CComBSTR bstrTargetedDC;
hr = m_piReplicaSet->get_TargetedDC(&bstrTargetedDC);
if (FAILED(hr) || lstrcmpi(bstrTargetedDC, bstrDC))
{
// something is wrong or we're using a different DC, re-init m_piReplicaSet
m_piReplicaSet.Release();
}
}
//
// read info of the replica set from DS
//
if (!m_piReplicaSet)
{
CComBSTR bstrDomain;
hr = GetDomainName(&bstrDomain);
RETURN_IF_FAILED(hr);
CComBSTR bstrReplicaSetDN;
hr = m_pDfsJPObject->get_ReplicaSetDN(&bstrReplicaSetDN);
RETURN_IF_FAILED(hr);
hr = CoCreateInstance(CLSID_ReplicaSet, NULL, CLSCTX_INPROC_SERVER, IID_IReplicaSet, (void**) &m_piReplicaSet);
RETURN_IF_FAILED(hr);
hr = m_piReplicaSet->Initialize(bstrDomain, bstrReplicaSetDN);
if (FAILED(hr))
{
m_piReplicaSet.Release();
return hr;
}
}
return hr;
}
HRESULT
CMmcDfsJunctionPoint::OnNewReplicaSet()
{
//
// refresh to pick up possible namespace updates on targets by others
//
HRESULT hr = OnRefresh();
if (S_FALSE == hr)
{
// this link has been deleted by others, no more reference
DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
return hr;
}
CWaitCursor wait;
BOOL bReplicaSetExist = FALSE;
m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
if (bReplicaSetExist) // replica set exist, return
return S_OK;
CComBSTR bstrDomain;
hr = GetDomainName(&bstrDomain);
RETURN_IF_FAILED(hr);
CComBSTR bstrReplicaSetDN;
hr = m_pDfsJPObject->get_ReplicaSetDN(&bstrReplicaSetDN);
RETURN_IF_FAILED(hr);
CNewReplicaSet ReplicaSetInfo;
hr = ReplicaSetInfo.Initialize(bstrDomain, bstrReplicaSetDN, &m_MmcRepList);
RETURN_IF_FAILED(hr);
if (S_FALSE == hr) // more than one targets on the same computer
{
if (IDYES != DisplayMessageBox(::GetActiveWindow(), MB_YESNO, 0, IDS_MSG_TARGETS_ONSAMECOMPUTER))
return hr;
}
CNewReplicaSetPage0 WizPage0;
CNewReplicaSetPage1 WizPage1(&ReplicaSetInfo);
CNewReplicaSetPage2 WizPage2(&ReplicaSetInfo, IsNewSchema());
//CNewReplicaSetPage3 WizPage3(&ReplicaSetInfo);
CComPtr<IPropertySheetCallback> pPropSheetCallback; // MMC Callback used to add pages
hr = m_lpConsole->QueryInterface(IID_IPropertySheetCallback, reinterpret_cast<void**>(&pPropSheetCallback));
RETURN_IF_FAILED(hr);
CComPtr<IPropertySheetProvider> pPropSheetProvider; // MMC callback used to handle wizard
hr = m_lpConsole->QueryInterface(IID_IPropertySheetProvider, reinterpret_cast<void**>(&pPropSheetProvider));
RETURN_IF_FAILED(hr);
//
// Create the wizard
//
hr = pPropSheetProvider->CreatePropertySheet(
_T(""), // title
FALSE, // Wizard and not property sheet.
0, // Cookie
NULL, // IDataobject
MMC_PSO_NEWWIZARDTYPE); // Creation flags
RETURN_IF_FAILED(hr);
hr = pPropSheetCallback->AddPage(WizPage0.Create());
RETURN_IF_FAILED(hr);
hr = pPropSheetCallback->AddPage(WizPage1.Create());
RETURN_IF_FAILED(hr);
hr = pPropSheetCallback->AddPage(WizPage2.Create());
RETURN_IF_FAILED(hr);
/*hr = pPropSheetCallback->AddPage(WizPage3.Create());
RETURN_IF_FAILED(hr);*/
// Ask the provider to use the pages from the callback
hr = pPropSheetProvider->AddPrimaryPages(
//(IComponentData *)(m_pParent->m_pScopeManager),
NULL,
TRUE, // Don't create a notify handle
NULL,
TRUE // Scope pane (not result pane)
);
RETURN_IF_FAILED(hr);
//
// Display the wizard
//
HWND hwndParent = NULL;
hr = m_lpConsole->GetMainWindow(&hwndParent);
RETURN_IF_FAILED(hr);
hr = pPropSheetProvider->Show((LONG_PTR)hwndParent, 0);
RETURN_IF_FAILED(hr);
//
// handle th result
//
if (S_OK == ReplicaSetInfo.m_hr)
{
//
// store the interface pointer
//
m_piReplicaSet = ReplicaSetInfo.m_piReplicaSet;
m_pDfsJPObject->put_ReplicaSetExist(TRUE);
//
// update icon
//
SCOPEDATAITEM ScopeDataItem;
ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
ScopeDataItem.ID = m_hScopeItem;
hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);
RETURN_IF_FAILED(hr);
if (SUCCEEDED(hr))
{
ScopeDataItem.nImage += 4;
ScopeDataItem.nOpenImage += 4;
hr = m_lpConsoleNameSpace->SetItem(&ScopeDataItem);
}
m_lpConsole->SelectScopeItem(m_hScopeItem);
}
return hr;
}
HRESULT CMmcDfsJunctionPoint::OnShowReplication()
{
BOOL bShowFRS = m_bShowFRS; // save it because refresh will reset it to FALSE
//
// refresh to pick up possible namespace updates on targets by others
//
HRESULT hr = OnRefresh();
if (S_FALSE == hr)
{
// this link has been deleted by others, no more reference
DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
return hr;
}
CWaitCursor wait;
DFS_REPLICA_LIST::iterator i;
if (bShowFRS)
{
hr = _InitReplicaSet();
if (S_OK != hr) // no replica set, do nothing and return
return S_OK;
//
// fill in each alternate m_bstrFRSColumnText and m_bstrStatusText
//
for (i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
{
((*i)->pReplica)->ShowReplicationInfo(m_piReplicaSet);
}
m_bShowFRS = TRUE;
}
m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
m_lpConsole->SelectScopeItem(m_hScopeItem);
return hr;
}
HRESULT
CMmcDfsJunctionPoint::OnStopReplication(BOOL bConfirm /* = FALSE */)
{
//
// refresh to pick up possible namespace updates on targets by others
//
HRESULT hr = OnRefresh();
if (S_FALSE == hr)
{
// this link has been deleted by others, no more reference
DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
return hr;
}
CWaitCursor wait;
BOOL bReplicaSetExist = FALSE;
m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
if (!bReplicaSetExist) // replica set doesn't exist, return
return S_OK;
if (bConfirm)
{
hr = ConfirmOperationOnDfsLink(IDS_MSG_STOP_REPLICATION);
if (S_OK != hr) return hr;
}
//
// init m_piReplicaSet
//
hr = _InitReplicaSet();
if (S_OK != hr) // no replica set, return
return hr;
hr = m_piReplicaSet->Delete();
if (SUCCEEDED(hr))
{
m_piReplicaSet.Release();
hr = m_pDfsJPObject->put_ReplicaSetExist(FALSE);
SCOPEDATAITEM ScopeDataItem;
ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
ScopeDataItem.ID = m_hScopeItem;
hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);
if (SUCCEEDED(hr))
{
ScopeDataItem.nImage -= 4;
ScopeDataItem.nOpenImage -= 4;
m_lpConsoleNameSpace->SetItem(&ScopeDataItem);
}
m_lpConsole->SelectScopeItem(m_hScopeItem);
if (m_bShowFRS)
{
m_bShowFRS = FALSE;
OnShowReplication();
}
}
return hr;
}
STDMETHODIMP
CMmcDfsJunctionPoint::SetColumnHeader(
IN LPHEADERCTRL2 i_piHeaderControl
)
{
RETURN_INVALIDARG_IF_NULL(i_piHeaderControl);
CComBSTR bstrColumn0;
HRESULT hr = LoadStringFromResource(IDS_RESULT_COLUMN_REPLICA, &bstrColumn0);
RETURN_IF_FAILED(hr);
i_piHeaderControl->InsertColumn(0, bstrColumn0, LVCFMT_LEFT, DFS_NAME_COLUMN_WIDTH);
if (m_bShowFRS)
{
CComBSTR bstrColumn1;
hr = LoadStringFromResource(IDS_RESULT_COLUMN_FRS, &bstrColumn1);
RETURN_IF_FAILED(hr);
i_piHeaderControl->InsertColumn(1, bstrColumn1, LVCFMT_LEFT, MMCLV_AUTO);
}
return hr;
}
STDMETHODIMP
CMmcDfsJunctionPoint::GetResultDisplayInfo(
IN OUT LPRESULTDATAITEM io_pResultDataItem
)
/*++
Routine Description:
Returns the information required for MMC display for this item.
Arguments:
io_pResultDataItem - The ResultItem which specifies what display information is required
--*/
{
RETURN_INVALIDARG_IF_NULL(io_pResultDataItem);
if (RDI_IMAGE & io_pResultDataItem->mask)
io_pResultDataItem->nImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + m_lJunctionState;
if (RDI_STR & io_pResultDataItem->mask)
{
if (0 == io_pResultDataItem->nCol)
io_pResultDataItem->str = m_bstrDisplayName;
}
return S_OK;
}
STDMETHODIMP
CMmcDfsJunctionPoint::GetScopeDisplayInfo(
IN OUT LPSCOPEDATAITEM io_pScopeDataItem
)
/*++
Routine Description:
Returns the information required for MMC display for this item.
Arguments:
i_pScopeDataItem - The ScopeItem which specifies what display information is required
--*/
{
RETURN_INVALIDARG_IF_NULL(io_pScopeDataItem);
if (SDI_STR & io_pScopeDataItem->mask)
io_pScopeDataItem->displayname = m_bstrDisplayName;
if (SDI_IMAGE & io_pScopeDataItem->mask)
io_pScopeDataItem->nImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + m_lJunctionState;
if (SDI_OPENIMAGE & io_pScopeDataItem->mask)
io_pScopeDataItem->nOpenImage = CMmcDfsRoot::m_iOPENIMAGEINDEX + m_lJunctionState;
return S_OK;
};
STDMETHODIMP
CMmcDfsJunctionPoint::EnumerateScopePane(
IN LPCONSOLENAMESPACE i_lpConsoleNameSpace,
IN HSCOPEITEM i_hParent
)
{
return S_OK; // no scope pane children
}
STDMETHODIMP
CMmcDfsJunctionPoint::EnumerateResultPane(
IN OUT IResultData* io_pResultData
)
/*++
Routine Description:
To eumerate(add) items in the result pane. Replicas in this case
Arguments:
io_pResultData - The callback used to add items to the Result pane
--*/
{
RETURN_INVALIDARG_IF_NULL(io_pResultData);
HRESULT hr = S_OK;
if (m_MmcRepList.empty())
{
CComPtr<IEnumVARIANT> pRepEnum;
hr = m_pDfsJPObject->get__NewEnum ((IUnknown**) &pRepEnum);
RETURN_IF_FAILED(hr);
VARIANT varReplicaObject;
VariantInit(&varReplicaObject);
while ( S_OK == (hr = pRepEnum->Next(1, &varReplicaObject, NULL)) )
{
CComPtr<IDfsReplica> pReplicaObject;
pReplicaObject = (IDfsReplica*) varReplicaObject.pdispVal;
CMmcDfsReplica* pMMCReplicaObject = new CMmcDfsReplica(pReplicaObject, this);
if (!pMMCReplicaObject)
{
hr = E_OUTOFMEMORY;
} else
{
hr = pMMCReplicaObject->m_hrValueFromCtor;
if (SUCCEEDED(hr))
{
hr = pMMCReplicaObject->AddItemToResultPane(io_pResultData);
if (SUCCEEDED(hr))
{
REP_LIST_NODE* pRepNode = new REP_LIST_NODE(pMMCReplicaObject);
if (!pRepNode)
{
hr = E_OUTOFMEMORY;
} else
{
m_MmcRepList.push_back(pRepNode);
}
}
}
if (FAILED(hr))
delete pMMCReplicaObject;
}
VariantClear(&varReplicaObject);
if (FAILED(hr))
break;
}
}
else
{
// The replicas of this junction are already enumerated,
// and the list exists, just add result items.
for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
{
hr = ((*i)->pReplica)->AddItemToResultPane(io_pResultData);
BREAK_IF_FAILED(hr);
}
}
return hr;
}
STDMETHODIMP
CMmcDfsJunctionPoint::SetConsoleVerbs(
IN LPCONSOLEVERB i_lpConsoleVerb
)
/*++
Routine Description:
Routine used to set the console verb settings.
Sets all of them except Open off.
For all scope pane items, default verb is "open'. For result items,
it is "properties"
Arguments:
i_lpConsoleVerb - The callback used to handle console verbs
--*/
{
RETURN_INVALIDARG_IF_NULL(i_lpConsoleVerb);
i_lpConsoleVerb->SetVerbState(MMC_VERB_COPY, HIDDEN, TRUE);
i_lpConsoleVerb->SetVerbState(MMC_VERB_PASTE, HIDDEN, TRUE);
i_lpConsoleVerb->SetVerbState(MMC_VERB_RENAME, HIDDEN, TRUE);
i_lpConsoleVerb->SetVerbState(MMC_VERB_PRINT, HIDDEN, TRUE);
i_lpConsoleVerb->SetVerbState(MMC_VERB_DELETE, HIDDEN, TRUE);
i_lpConsoleVerb->SetVerbState(MMC_VERB_OPEN, HIDDEN, TRUE);
i_lpConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, ENABLED, TRUE);
i_lpConsoleVerb->SetVerbState(MMC_VERB_REFRESH, ENABLED, TRUE);
i_lpConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN); //For scope items, default verb is "open"
return S_OK;
}
/*
Case1: add to a n-targets-link (repOn or repOff) which has actually been deleted by another DfsGui instance
result: refresh the root (the whole namespace), put up the retry message
Case2: add to a n-targets-link (repOn) whose targets have been partly deleted and whose replication has been turned off by another DfsGui instance
result: refresh the link, add the new target, if (checked && #targets>1), invoke the RepCfg wizard
Case3: add to a n-targets-link (repOn) whose targets have been partly deleted and whose replication has still been kept on by another DfsGui instance
result: refresh the link, add the new target, if (checked && #targets>1), join the new target to replication set
Case4: add to a n-targets-link (repOn), no other DfsGui instances are involved
result: refresh the link, add the new target, if (checked && #targets>1), join the new target to replication set
Case5: add to a n-targets-link (repOff), no other DfsGui instances are involved
result: refresh the link, add the new target, if (checked && #targets>1), invoke the RepCfg wizard
*/
STDMETHODIMP
CMmcDfsJunctionPoint::OnNewReplica(
)
/*++
Routine Description:
Adds a new replica to the Junction Point.
--*/
{
HRESULT hr = S_OK;
CAddRep AddRepDlg;
CComBSTR bstrServerName;
CComBSTR bstrShareName;
CComBSTR bstrNetPath;
AddRepDlg.put_EntryPath(m_bstrEntryPath);
AddRepDlg.put_DfsType(m_pDfsParentRoot->m_lDfsRootType);
hr = AddRepDlg.DoModal();
if (S_OK != hr)
return hr;
AddRepDlg.get_Server(&bstrServerName);
AddRepDlg.get_Share(&bstrShareName);
AddRepDlg.get_NetPath(&bstrNetPath);
/* bug#290375: both UI and core should allow interlink to have multiple targets
// Is it a dfs based path? These are not allowed.
if (IsDfsPath(bstrNetPath))
{
DisplayMessageBoxWithOK( IDS_MSG_MID_JUNCTION, bstrNetPath);
return(S_OK);
}
*/
//
// refresh to pick up possible namespace updates on this link or link targets
//
hr = OnRefresh();
if (S_FALSE == hr)
{
//
// this link has been deleted by other means, scope pane has been refreshed,
// ask user to retry
//
DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
return hr;
}
CWaitCursor wait;
CComPtr<IDfsReplica> pReplicaObject;
CMmcDfsReplica* pMMCReplicaObject = NULL;
VARIANT varReplicaObject;
VariantInit(&varReplicaObject);
hr = m_pDfsJPObject->AddReplica(bstrServerName, bstrShareName, &varReplicaObject);
if (FAILED(hr))
{
DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_MSG_FAILED_TO_CREATE_REPLICA);
return hr;
}
// Get the IDfsReplica interface.
pReplicaObject = (IDfsReplica*) varReplicaObject.pdispVal;
// Create display object.
pMMCReplicaObject = new CMmcDfsReplica(pReplicaObject, this);
if (!pMMCReplicaObject)
return E_OUTOFMEMORY;
// Add item to replica list and update
// Result view.
AddResultPaneItem(pMMCReplicaObject);
m_bDirty = true;
//
// If requested and the link has more than 1 target, configure file replication
//
if (CAddRep::NORMAL_REPLICATION == AddRepDlg.get_ReplicationType() && (m_MmcRepList.size() > 1))
{
BOOL bReplicaSetExist = FALSE;
hr = m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
RETURN_IF_FAILED(hr);
if (!bReplicaSetExist)
{
if (IDYES == DisplayMessageBox(::GetActiveWindow(), MB_YESNO, 0, IDS_MSG_NEWFRS_NOW))
hr = OnNewReplicaSet();
} else
{
hr = pMMCReplicaObject->OnReplicate();
}
}
return hr;
}
STDMETHODIMP
CMmcDfsJunctionPoint::AddItemToScopePane(
IN HSCOPEITEM i_hParent
)
{
HRESULT hr = S_OK;
BOOL bReplicaSetExist = FALSE;
hr = m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
if (SUCCEEDED(hr))
{
SCOPEDATAITEM JPScopeDataItem;
memset (&JPScopeDataItem, 0, sizeof(SCOPEDATAITEM));
JPScopeDataItem.mask = SDI_PARENT | SDI_IMAGE | SDI_OPENIMAGE | SDI_PARAM | SDI_STR | SDI_CHILDREN;
JPScopeDataItem.relativeID = i_hParent; //ID of DfsRoot Node
JPScopeDataItem.nImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + (bReplicaSetExist ? 4 : 0);
JPScopeDataItem.nOpenImage = CMmcDfsJunctionPoint::m_iOPENIMAGEINDEX + (bReplicaSetExist ? 4 : 0);
JPScopeDataItem.lParam = reinterpret_cast<LPARAM> (this);
JPScopeDataItem.displayname = MMC_CALLBACK ;
hr = m_lpConsoleNameSpace->InsertItem(&JPScopeDataItem);
if (SUCCEEDED(hr))
m_hScopeItem = JPScopeDataItem.ID;
}
return hr;
}
STDMETHODIMP
CMmcDfsJunctionPoint :: OnRemoveJP (IN BOOL bConfirm)
/*++
Routine Description:
This internal method handles the removal of Junction Points.
--*/
{
// check outstanding property sheet.
HRESULT hr = ClosePropertySheet(!bConfirm);
if (bConfirm)
{
if (S_OK != hr) // open property page found, discontinue
return hr;
hr = ConfirmOperationOnDfsLink(IDS_MSG_REMOVE_JP);
if(S_OK != hr) // Error or User decided to abort the operation
return hr;
}
// 5/12/2001: no need to select the scope node when deleting link
//m_lpConsole->SelectScopeItem(m_hScopeItem);
CWaitCursor WaitCursor; // Display the wait cursor
// Delete the associated replica set
hr = _InitReplicaSet();
if (S_OK == hr)
{
m_piReplicaSet->Delete();
m_pDfsJPObject->put_ReplicaSetExist(FALSE);
m_piReplicaSet.Release();
}
// Remove the actual junction point(from DS)
hr = m_pDfsParentRoot->m_DfsRoot->DeleteJunctionPoint(m_bstrDisplayName);
RETURN_IF_FAILED(hr);
hr = m_pDfsParentRoot->DeleteMmcJPNode(this);
RETURN_IF_FAILED(hr);
// Remove it from MMC console
hr = m_lpConsoleNameSpace->DeleteItem(m_hScopeItem, TRUE);
RETURN_IF_FAILED(hr);
Release(); // Release (delete) this Object
return (hr);
}
HRESULT
CMmcDfsJunctionPoint::ClosePropertySheet(BOOL bSilent)
{
if (!m_PropPage.m_hWnd && !m_frsPropPage.m_hWnd)
return S_OK; // no outstanding property sheet, return S_OK;
CComPtr<IPropertySheetProvider> pPropSheetProvider;
HRESULT hr = m_lpConsole->QueryInterface(IID_IPropertySheetProvider, reinterpret_cast<void**>(&pPropSheetProvider));
if (FAILED(hr))
{
hr = S_OK; // ignore the QI failure
} else
{
//
// find the outstanding property sheet and bring it to foreground
//
hr = pPropSheetProvider->FindPropertySheet((MMC_COOKIE)m_hScopeItem, NULL, this);
if (S_OK == hr)
{
if (bSilent)
{
//
// silently close outstanding property sheet, and return S_OK to continue user's operation
//
if (m_PropPage.m_hWnd)
::SendMessage(m_PropPage.m_hWnd, WM_PARENT_NODE_CLOSING, 0, 0);
if (m_frsPropPage.m_hWnd)
::SendMessage(m_frsPropPage.m_hWnd, WM_PARENT_NODE_CLOSING, 0, 0);
} else
{
//
// ask user to close it, return S_FALSE to quit user's operation
//
DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_PROPERTYPAGE_NOTCLOSED);
return S_FALSE;
}
} else
{
hr = S_OK; // no outstanding property sheet, return S_OK
}
}
//
// reset HWND
//
m_PropPage.m_hWnd = NULL;
m_frsPropPage.m_hWnd = NULL;
return hr;
}
STDMETHODIMP
CMmcDfsJunctionPoint::ConfirmOperationOnDfsLink(int idString)
/*++
Routine Description:
Asks the user for confirmation of whether he really wants to remove the particular
Junction point.
Return value:
S_OK, if the user chooses YES,
S_FALSE, if the user chooses NO.
--*/
{
CComBSTR bstrAppName;
HRESULT hr = LoadStringFromResource (IDS_APPLICATION_NAME, &bstrAppName);
RETURN_IF_FAILED(hr);
CComBSTR bstrFormattedMessage;
hr = FormatResourceString(idString, m_bstrEntryPath, &bstrFormattedMessage);
RETURN_IF_FAILED(hr);
CThemeContextActivator activator;
if (IDNO == ::MessageBox(::GetActiveWindow(), bstrFormattedMessage, bstrAppName, MB_YESNO | MB_ICONEXCLAMATION | MB_APPLMODAL))
return S_FALSE;
return S_OK;
}
//
// Call the root's RemoveJP() method to:
// 1. refresh the root node to pick up possible namespace updates by others
// 2. then locate the appropriate link to actually perform the removal operation
//
STDMETHODIMP
CMmcDfsJunctionPoint::DoDelete(
)
{
HRESULT hr = m_pDfsParentRoot->RemoveJP(m_bstrDisplayName);
if(FAILED(hr))
DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_MSG_WIZ_DELETE_JP_FAILURE, m_bstrDisplayName);
return hr;
}
STDMETHODIMP
CMmcDfsJunctionPoint::QueryPagesFor(
)
/*++
Routine Description:
Used to decide whether the object wants to display property pages.
Returning S_OK typically results in a call to CreatePropertyPages.
--*/
{
//
// refresh to pick up possible namespace updates by others
//
HRESULT hr = OnRefresh();
if (S_FALSE == hr)
{
// this link has been deleted by others, no more reference
DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
return hr; // no property page
}
return S_OK; // yes, we want to display a propertysheet
}
// Creates and passes back the pages to be displayed
STDMETHODIMP
CMmcDfsJunctionPoint::CreatePropertyPages(
IN LPPROPERTYSHEETCALLBACK i_lpPropSheetCallback,
IN LONG_PTR i_lNotifyHandle
)
/*++
Routine Description:
Used to display the property sheet pages
Arguments:
i_lpPropSheetCallback - The callback used to create the propertysheet.
i_lNotifyHandle - Notify handle used by the property page
--*/
{
RETURN_INVALIDARG_IF_NULL(i_lpPropSheetCallback);
m_lpConsole->SelectScopeItem(m_hScopeItem);
CWaitCursor WaitCursor;
HRESULT hr = S_OK;
do {
hr = m_PropPage.Initialize(NULL, (IDfsJunctionPoint*)m_pDfsJPObject);
BREAK_IF_FAILED(hr);
// Create the page for the replica set.
// Pass it to the Callback
HPROPSHEETPAGE h_proppage = m_PropPage.Create();
if (!h_proppage)
{
hr = HRESULT_FROM_WIN32(::GetLastError());
break;
}
// Pass on the notify data to the Property Page
hr = m_PropPage.SetNotifyData(i_lNotifyHandle, (LPARAM)this);
BREAK_IF_FAILED (hr);
hr = i_lpPropSheetCallback->AddPage(h_proppage);
BREAK_IF_FAILED (hr);
//
// Add "Replica Set" page
//
hr = CreateFrsPropertyPage(i_lpPropSheetCallback, i_lNotifyHandle);
if (FAILED(hr))
{
DisplayMessageBox(::GetActiveWindow(), MB_OK, hr, IDS_REPPAGE_ERROR);
hr = S_OK; // allow the other tabs to be brought up
}
} while (0);
if (FAILED(hr))
DisplayMessageBoxForHR(hr);
return hr;
}
STDMETHODIMP
CMmcDfsJunctionPoint::CreateFrsPropertyPage
(
IN LPPROPERTYSHEETCALLBACK i_lpPropSheetCallback,
IN LONG_PTR i_lNotifyHandle
)
{
HRESULT hr = _InitReplicaSet();
if (S_OK != hr)
return hr;
CComBSTR bstrType;
hr = m_piReplicaSet->get_Type(&bstrType);
RETURN_IF_FAILED(hr);
if (lstrcmpi(bstrType, FRS_RSTYPE_DFS))
return hr;
//
// set initial values on the property page
//
hr = m_frsPropPage.Initialize(m_piReplicaSet);
RETURN_IF_FAILED(hr);
//
// create the property page
//
HPROPSHEETPAGE h_frsproppage = m_frsPropPage.Create();
if (!h_frsproppage)
return HRESULT_FROM_WIN32(::GetLastError());
//
// pass on the notify data to the Property Page
//
hr = m_frsPropPage.SetNotifyData(i_lNotifyHandle, (LPARAM)this);
RETURN_IF_FAILED(hr);
//
// AddPage
//
return i_lpPropSheetCallback->AddPage(h_frsproppage);
}
STDMETHODIMP
CMmcDfsJunctionPoint::PropertyChanged(
)
/*++
Routine Description:
Used to update the properties.
--*/
{
return S_OK;
}
HRESULT
CMmcDfsJunctionPoint::SetDescriptionBarText(
IN LPRESULTDATA i_lpResultData
)
/*++
Routine Description:
A routine used set the text in the Description bar above
the result view.
Arguments:
i_lpResultData - Pointer to the IResultData callback which is
used to set the description text
--*/
{
RETURN_INVALIDARG_IF_NULL(i_lpResultData);
CComBSTR bstrTextForDescriptionBar; // Text to be shown in the Result view Description bar
HRESULT hr = FormatResourceString(IDS_DESCRIPTION_BAR_TEXT_JUNCTIONPOINT, m_bstrEntryPath, &bstrTextForDescriptionBar);
RETURN_IF_FAILED(hr);
hr = i_lpResultData->SetDescBarText(bstrTextForDescriptionBar);
return hr;
}
HRESULT
CMmcDfsJunctionPoint::ToolbarSelect(
IN const LONG i_lArg,
IN IToolbar* i_pToolBar
)
/*++
Routine Description:
Handle a select event for a toolbar
Create a toolbar, it it doesn't exist.
Attach the toolbar and enable the buttons, if the event for a selection.
Disable the buttons, if the event was for a deselection
Arguments:
i_lArg - The argument passed to the actual method.
o_pToolBar - The Toolbar pointer.
--*/
{
RETURN_INVALIDARG_IF_NULL(i_pToolBar);
BOOL bSelect = (BOOL) HIWORD(i_lArg); // Is the event for selection?
EnableToolbarButtons(i_pToolBar, IDT_JP_MIN, IDT_JP_MAX, bSelect);
if (bSelect)
{
BOOL bReplicaSetExist = FALSE;
HRESULT hr = m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
RETURN_IF_FAILED(hr);
if (bReplicaSetExist || (1 >= m_MmcRepList.size()) ||
(DFS_TYPE_STANDALONE == m_pDfsParentRoot->m_lDfsRootType))
{
i_pToolBar->SetButtonState(IDT_JP_REPLICATION_TOPOLOGY, ENABLED, FALSE);
i_pToolBar->SetButtonState(IDT_JP_REPLICATION_TOPOLOGY, HIDDEN, TRUE);
}
if (!bReplicaSetExist)
{
i_pToolBar->SetButtonState(IDT_JP_SHOW_REPLICATION, ENABLED, FALSE);
i_pToolBar->SetButtonState(IDT_JP_SHOW_REPLICATION, HIDDEN, TRUE);
i_pToolBar->SetButtonState(IDT_JP_HIDE_REPLICATION, ENABLED, FALSE);
i_pToolBar->SetButtonState(IDT_JP_HIDE_REPLICATION, HIDDEN, TRUE);
i_pToolBar->SetButtonState(IDT_JP_STOP_REPLICATION, ENABLED, FALSE);
i_pToolBar->SetButtonState(IDT_JP_STOP_REPLICATION, HIDDEN, TRUE);
} else
{
if (m_bShowFRS)
{
i_pToolBar->SetButtonState(IDT_JP_SHOW_REPLICATION, ENABLED, FALSE);
i_pToolBar->SetButtonState(IDT_JP_SHOW_REPLICATION, HIDDEN, TRUE);
} else
{
i_pToolBar->SetButtonState(IDT_JP_HIDE_REPLICATION, ENABLED, FALSE);
i_pToolBar->SetButtonState(IDT_JP_HIDE_REPLICATION, HIDDEN, TRUE);
}
}
}
return S_OK;
}
HRESULT
CMmcDfsJunctionPoint::CreateToolbar(
IN const LPCONTROLBAR i_pControlbar,
IN const LPEXTENDCONTROLBAR i_lExtendControlbar,
OUT IToolbar** o_pToolBar
)
/*++
Routine Description:
Create the toolbar.
Involves the actual toolbar creation call, creating the bitmap and adding it
and finally adding the buttons to the toolbar
Arguments:
i_pControlbar - The controlbar used to create toolbar.
i_lExtendControlbar - The object implementing IExtendControlbar. This is
the class exposed to MMC.
--*/
{
RETURN_INVALIDARG_IF_NULL(i_pControlbar);
RETURN_INVALIDARG_IF_NULL(i_lExtendControlbar);
RETURN_INVALIDARG_IF_NULL(o_pToolBar);
HRESULT hr = E_FAIL;
CComBSTR bstrAllTheMenuText;
int iButtonPosition = 0; // The first button position
// Create the toolbar
hr = i_pControlbar->Create(TOOLBAR, i_lExtendControlbar, reinterpret_cast<LPUNKNOWN*>(o_pToolBar));
RETURN_IF_FAILED(hr);
// Add the bitmap to the toolbar
hr = AddBitmapToToolbar(*o_pToolBar, IDB_JP_TOOLBAR);
RETURN_IF_FAILED(hr);
for (int iCommandID = IDT_JP_MIN, iMenuResource = IDS_MENUS_JUNCTION_TOP_NEW_DFS_REPLICA;
iCommandID <= IDT_JP_MAX;
iCommandID++,iMenuResource++,iButtonPosition++)
{
CComBSTR bstrMenuText;
CComBSTR bstrToolTipText;
hr = GetMenuResourceStrings(iMenuResource, &bstrMenuText, &bstrToolTipText, NULL);
RETURN_IF_FAILED(hr);
MMCBUTTON ToolbarButton;
ZeroMemory(&ToolbarButton, sizeof ToolbarButton);
ToolbarButton.nBitmap = iButtonPosition;
ToolbarButton.idCommand = iCommandID;
ToolbarButton.fsState = TBSTATE_ENABLED;
ToolbarButton.fsType = TBSTYLE_BUTTON;
ToolbarButton.lpButtonText = bstrMenuText;
ToolbarButton.lpTooltipText = bstrToolTipText;
// Add the button to the toolbar
hr = (*o_pToolBar)->InsertButton(iButtonPosition, &ToolbarButton);
_ASSERTE(S_OK == hr); // Assert, but continue as we want to try other buttons
}
return S_OK;
}
STDMETHODIMP
CMmcDfsJunctionPoint::ToolbarClick(
IN const LPCONTROLBAR i_pControlbar,
IN const LPARAM i_lParam
)
/*++
Routine Description:
Action to take on a click on a toolbar
Arguments:
i_pControlbar - The controlbar used to create toolbar.
i_lParam - The lparam to the actual notify. This is the command id of
the button on which a click occurred.
Return value:
S_OK, if successful.
E_INVALID_ARG, if any of the arguments is null
Another other value returned from the called methods.
--*/
{
RETURN_INVALIDARG_IF_NULL(i_pControlbar);
HRESULT hr = S_OK;
switch(i_lParam) // What button did the user click on.
{
case IDT_JP_NEW_DFS_REPLICA: // "New Replica"
hr = OnNewReplica();
break;
case IDT_JP_REMOVE_FROM_DFS: // "Remove Junction Point"
hr = DoDelete();
break;
case IDT_JP_REPLICATION_TOPOLOGY: // "Replication Topology"
hr = OnNewReplicaSet();
break;
case IDT_JP_SHOW_REPLICATION:
case IDT_JP_HIDE_REPLICATION:
m_bShowFRS = !m_bShowFRS;
hr = OnShowReplication();
break;
case IDT_JP_STOP_REPLICATION:
hr = OnStopReplication(TRUE);
if (FAILED(hr))
DisplayMessageBoxForHR(hr);
break;
case IDT_JP_CHECK_STATUS: // "Check Status"
hr = OnCheckStatus ();
break;
default:
hr = E_INVALIDARG;
break;
};
return hr;
}
HRESULT
CMmcDfsJunctionPoint::OnRefresh(
)
/*++
Routine Description:
Refreshes the junction point.
--*/
{
// Select this node first
m_lpConsole->SelectScopeItem(m_hScopeItem);
CWaitCursor WaitCursor; // Display the wait cursor
HRESULT hr = S_OK;
// silently close outstanding property sheet.
ClosePropertySheet(TRUE);
// Re-Initialize!
BOOL bReplicaSetExist = FALSE;
CComBSTR bstrDC;
(void)m_pDfsJPObject->get_ReplicaSetExistEx(&bstrDC, &bReplicaSetExist);
CComBSTR bstrReplicaSetDN;
if (bReplicaSetExist)
{
(void)m_pDfsJPObject->get_ReplicaSetDN(&bstrReplicaSetDN);
}
m_bShowFRS = FALSE;
if ((IReplicaSet *)m_piReplicaSet)
m_piReplicaSet.Release();
CleanResultChildren();
hr = m_pDfsJPObject->Initialize((IUnknown *)(m_pDfsParentRoot->m_DfsRoot), m_bstrEntryPath, bReplicaSetExist, bstrReplicaSetDN);
if (S_OK != hr) // fail to init the link or no such link any more, refresh the whole root
{
m_pDfsParentRoot->OnRefresh();
return S_FALSE; // indicate the current m_pDfsJPObject should NOT be used any more
}
// set the link icon
if (m_lpConsoleNameSpace != NULL)
{
SCOPEDATAITEM ScopeDataItem;
ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
ScopeDataItem.ID = m_hScopeItem;
hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);
if (SUCCEEDED(hr))
{
ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
ScopeDataItem.nImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + (bReplicaSetExist ? 4 : 0);
ScopeDataItem.nOpenImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + (bReplicaSetExist ? 4 : 0);
m_lpConsoleNameSpace->SetItem(&ScopeDataItem);
}
}
// re-display the result pane
m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
// Set the selected item in scope pane to this node
m_lpConsole->SelectScopeItem(m_hScopeItem);
return S_OK;
}
STDMETHODIMP CMmcDfsJunctionPoint::CleanResultChildren(
)
{
if (!m_MmcRepList.empty())
{
// clean up display objects
for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
{
delete (*i);
}
m_MmcRepList.erase(m_MmcRepList.begin(), m_MmcRepList.end());
// delete result pane items
m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 0);
}
return(S_OK);
}
STDMETHODIMP
CMmcDfsJunctionPoint::OnCheckStatus(
)
/*++
Routine Description:
This method checks the state of the replica.
--*/
{
//
// refresh to pick up possible namespace updates on targets by others
//
HRESULT hr = OnRefresh();
if (S_FALSE == hr)
{
// this link has been deleted by others, no more reference
DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
return hr;
}
CWaitCursor wait;
UINT nTotal = m_MmcRepList.size();
_ASSERT(nTotal != 0);
UINT nMappingOn = 0;
UINT nMappingOff = 0;
UINT nUnreachable = 0;
// Update state of all replicas also.
for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
{
(*i)->pReplica->OnCheckStatus();
switch ((*i)->pReplica->m_lReplicaState)
{
case DFS_REPLICA_STATE_ONLINE:
nMappingOn++;
break;
case DFS_REPLICA_STATE_OFFLINE:
nMappingOff++;
break;
case DFS_REPLICA_STATE_UNREACHABLE:
nUnreachable++;
break;
default:
_ASSERT(FALSE);
break;
}
}
long lDfsState = DFS_STATE_REACHABLE;
hr = m_pDfsJPObject->get_State(&lDfsState);
RETURN_IF_FAILED(hr);
if (DFS_STATE_REACHABLE == lDfsState)
{
if (nTotal == nMappingOn)
{
m_lJunctionState = DFS_JUNCTION_STATE_ALL_REP_OK;
} else if (nTotal != (nMappingOff + nUnreachable))
{
m_lJunctionState = DFS_JUNCTION_STATE_NOT_ALL_REP_OK;
} else
{
m_lJunctionState = DFS_JUNCTION_STATE_UNREACHABLE;
}
} else
{
m_lJunctionState = DFS_JUNCTION_STATE_UNREACHABLE;
}
BOOL bReplicaSetExist = FALSE;
hr = m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
RETURN_IF_FAILED(hr);
if (m_lpConsoleNameSpace != NULL)
{
SCOPEDATAITEM ScopeDataItem;
ZeroMemory(&ScopeDataItem, sizeof(SCOPEDATAITEM));
ScopeDataItem.ID = m_hScopeItem;
hr = m_lpConsoleNameSpace->GetItem(&ScopeDataItem);
RETURN_IF_FAILED(hr);
ScopeDataItem.mask = SDI_IMAGE | SDI_OPENIMAGE;
ScopeDataItem.nImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + (bReplicaSetExist ? 4 : 0) + m_lJunctionState;
ScopeDataItem.nOpenImage = CMmcDfsJunctionPoint::m_iIMAGEINDEX + (bReplicaSetExist ? 4 : 0) + m_lJunctionState;
hr = m_lpConsoleNameSpace->SetItem(&ScopeDataItem);
RETURN_IF_FAILED(hr);
}
return hr;
}
STDMETHODIMP CMmcDfsJunctionPoint::ViewChange(
IResultData* i_pResultData,
LONG_PTR i_lHint
)
/*++
Routine Description:
This method handles the MMCN_VIEW_CHANGE notification.
This updates the result view for the scope node on which the
UpdateAllViews was called.
if (0 == i_lHint) clean result pane only.
--*/
{
RETURN_INVALIDARG_IF_NULL(i_pResultData);
i_pResultData->DeleteAllRsltItems();
// Re-display the view
if (i_lHint)
EnumerateResultPane(i_pResultData);
return(S_OK);
}
STDMETHODIMP CMmcDfsJunctionPoint::AddResultPaneItem(
CMmcDfsReplica* i_pReplicaDispObject
)
/*++
Routine Description:
This method adds a new replica object to the list of replicas displayed
in the result view.
Arguments:
i_pReplicaDispObject - The CMmcReplica display object pointer..
--*/
{
REP_LIST_NODE* pNewReplica = new REP_LIST_NODE(i_pReplicaDispObject);
if (!pNewReplica)
return E_OUTOFMEMORY;
// Sort isnert. Find insertion position.
for (DFS_REPLICA_LIST::iterator j = m_MmcRepList.begin(); j != m_MmcRepList.end(); j++)
{
if (lstrcmpi(pNewReplica->pReplica->m_bstrDisplayName, (*j)->pReplica->m_bstrDisplayName) <= 0)
break;
}
m_MmcRepList.insert(j, pNewReplica);
BOOL bReplicaSetExist = FALSE;
m_pDfsJPObject->get_ReplicaSetExist(&bReplicaSetExist);
if (bReplicaSetExist && m_bShowFRS)
{
i_pReplicaDispObject->ShowReplicationInfo(m_piReplicaSet);
}
// Re-display to display this item.
m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
return S_OK;
}
//
// This function is called when removing a target from the result pane
//
STDMETHODIMP CMmcDfsJunctionPoint::RemoveReplica(LPCTSTR i_pszDisplayName)
{
if (!i_pszDisplayName)
return E_INVALIDARG;
//
// refresh to pick up possible namespace updates on targets by other means
//
HRESULT hr = OnRefresh();
if (S_FALSE == hr)
{
// this link has already been deleted by others, no more reference
DisplayMessageBox(::GetActiveWindow(), MB_OK, 0, IDS_INVALID_LINK);
return hr;
}
CWaitCursor wait;
//
// locate the correct target to remove, then call back.
//
for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
{
if (!lstrcmpi((*i)->pReplica->m_bstrDisplayName, i_pszDisplayName))
{
hr = (*i)->pReplica->RemoveReplica();
break;
}
}
return hr;
}
STDMETHODIMP CMmcDfsJunctionPoint::RemoveResultPaneItem(
CMmcDfsReplica* i_pReplicaDispObject
)
/*++
Routine Description:
This method adds a new replica object to the list of replicas displayed
in the result view.
Arguments:
i_pReplicaDispObject - The CMmcReplica display object pointer..
--*/
{
dfsDebugOut((_T("CMmcDfsJunctionPoint::RemoveResultPaneItem replist=%d\n"), m_MmcRepList.size()));
// Remove item from list.
for (DFS_REPLICA_LIST::iterator i = m_MmcRepList.begin(); i != m_MmcRepList.end(); i++)
{
if ((*i)->pReplica == i_pReplicaDispObject)
{
delete (*i);
m_MmcRepList.erase(i);
break;
}
}
// Last node is removed.
if (m_MmcRepList.empty())
{
// silently close any open property sheet
ClosePropertySheet(TRUE);
// Delete the item from Scope Pane
HRESULT hr = m_lpConsoleNameSpace->DeleteItem(m_hScopeItem, TRUE);
RETURN_IF_FAILED(hr);
// Remove the actual junction point(from DS)
hr = m_pDfsParentRoot->m_DfsRoot->DeleteJunctionPoint(m_bstrDisplayName);
RETURN_IF_FAILED(hr);
// Delete it from the internal list
hr = m_pDfsParentRoot->DeleteMmcJPNode(this);
RETURN_IF_FAILED(hr);
Release(); // delete this CMmcDfsJunctionPoint object
}
else
{
// Re-display to remove this item.
m_lpConsole->UpdateAllViews((IDataObject*)this, 0, 1);
}
return S_OK;
}
HRESULT CMmcDfsJunctionPoint::GetIReplicaSetPtr(IReplicaSet** o_ppiReplicaSet)
{
RETURN_INVALIDARG_IF_NULL(o_ppiReplicaSet);
HRESULT hr = _InitReplicaSet();
if (S_OK == hr)
{
m_piReplicaSet->AddRef();
*o_ppiReplicaSet = m_piReplicaSet;
}
return hr;
}