1028 lines
27 KiB
C++
1028 lines
27 KiB
C++
/*++
|
|
Module Name:
|
|
|
|
MmcAdmin.cpp
|
|
|
|
Abstract:
|
|
|
|
This module contains the implementation for CMmcDfsAdmin. This is an class
|
|
for MMC display related calls for the static node(the DFS Admin root node)
|
|
|
|
--*/
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "DfsGUI.h"
|
|
#include "Utils.h" // For the LoadStringFromResource method
|
|
#include "resource.h" // Contains the menu and toolbar command ids
|
|
#include "MenuEnum.h" // Contains the menu command ids
|
|
#include "MmcRoot.h" // CMmcDfsRoot class
|
|
#include "MmcAdmin.h"
|
|
#include "DfsEnums.h" // for common enums, typedefs, etc
|
|
#include "DfsWiz.h" // For the wizard pages, CCreateDfsRootWizPage1, 2, ...
|
|
#include "DfsNodes.h" // For Node GUIDs
|
|
#include "DfsScope.h"
|
|
#include "mroots.h"
|
|
|
|
|
|
static const TCHAR s_szWhack[] = _T("\\");
|
|
static const TCHAR s_szWhackWhack[] = _T("\\\\");
|
|
|
|
|
|
|
|
CMmcDfsAdmin::CMmcDfsAdmin(
|
|
CDfsSnapinScopeManager* pScopeManager
|
|
)
|
|
:m_hItemParent(NULL), m_bDirty(false), m_lpConsole(NULL)
|
|
{
|
|
dfsDebugOut((_T("CMmcDfsAdmin::CMmcDfsAdmin this=%p\n"), this));
|
|
m_CLSIDNodeType = s_guidDfsAdminNodeType;
|
|
m_bstrDNodeType = s_tchDfsAdminNodeType;
|
|
m_pScopeManager = pScopeManager;
|
|
}
|
|
|
|
|
|
|
|
CMmcDfsAdmin::~CMmcDfsAdmin()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The dtor for CMmcDfsAdmin. This removes the list of DfsRoots being administered.
|
|
|
|
--*/
|
|
{
|
|
CleanScopeChildren();
|
|
|
|
dfsDebugOut((_T("CMmcDfsAdmin::~CMmcDfsAdmin this=%p\n"), this));
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::AddMenuItems(
|
|
IN LPCONTEXTMENUCALLBACK i_lpContextMenuCallback,
|
|
IN LPLONG i_lpInsertionAllowed
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine adds a context menu 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_STATIC_MAX,
|
|
IDM_CONTEXTMENU_COMMAND_MIN = IDM_STATIC_MIN
|
|
};
|
|
|
|
LONG lInsertionPoints [IDM_CONTEXTMENU_COMMAND_MAX - IDM_CONTEXTMENU_COMMAND_MIN + 1] = {
|
|
CCM_INSERTIONPOINTID_PRIMARY_TOP,
|
|
CCM_INSERTIONPOINTID_PRIMARY_TOP
|
|
};
|
|
|
|
HRESULT hr = S_OK;
|
|
for (int iCommandID = IDM_CONTEXTMENU_COMMAND_MIN, iMenuResource = IDS_MENUS_STATIC_TOP_NEW_DFSROOT;
|
|
iCommandID <= IDM_CONTEXTMENU_COMMAND_MAX;
|
|
iCommandID++,iMenuResource++)
|
|
{
|
|
CComBSTR bstrMenuText;
|
|
CComBSTR bstrStatusBarText;
|
|
hr = GetMenuResourceStrings(iMenuResource, &bstrMenuText, NULL, &bstrStatusBarText);
|
|
RETURN_IF_FAILED(hr);
|
|
|
|
CONTEXTMENUITEM ContextMenuItem; // The structure which contains menu information
|
|
ZeroMemory(&ContextMenuItem, sizeof(ContextMenuItem));
|
|
ContextMenuItem.strName = bstrMenuText;
|
|
ContextMenuItem.strStatusBarText = bstrStatusBarText;
|
|
ContextMenuItem.lInsertionPointID = lInsertionPoints[iCommandID - IDM_CONTEXTMENU_COMMAND_MIN];
|
|
ContextMenuItem.lCommandID = iCommandID;
|
|
|
|
LONG lInsertionFlag = 0; // Use to check if we have permission to add this menu.
|
|
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) // Add the menu item we have have the permission
|
|
{
|
|
hr = i_lpContextMenuCallback->AddItem(&ContextMenuItem);
|
|
RETURN_IF_FAILED(hr);
|
|
}
|
|
|
|
} // for
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::SetColumnHeader(
|
|
IN LPHEADERCTRL2 i_piHeaderControl
|
|
)
|
|
{
|
|
//
|
|
// the static node will dispay the messageview in the result pane
|
|
//
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::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_STATIC_TOP_CONNECTTO:
|
|
hr = OnConnectTo();
|
|
break;
|
|
case IDM_STATIC_TOP_NEW_DFSROOT:
|
|
hr = OnNewDfsRoot();
|
|
break;
|
|
default:
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
}
|
|
|
|
return hr;
|
|
};
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::OnConnectTo(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action to be taken on menu command "Connect To Dfs Root"
|
|
|
|
--*/
|
|
{
|
|
// Display the ConnectTo dialog
|
|
CConnectToDialog ConnectTo; // Connect To Dialog.
|
|
HRESULT hr = ConnectTo.DoModal();
|
|
|
|
::ShowCursor(FALSE);
|
|
SetCursor(::LoadCursor(NULL, IDC_ARROW));
|
|
::ShowCursor(TRUE);
|
|
|
|
if (hr != S_OK) // Mostly an error or cancel operation
|
|
return hr;
|
|
|
|
// Get the Dfs Root selected by the user
|
|
CComBSTR bstrUserEnteredText;
|
|
hr = ConnectTo.get_DfsRoot(&bstrUserEnteredText);
|
|
RETURN_IF_FAILED(hr);
|
|
|
|
CWaitCursor WaitCursor;
|
|
if (S_OK == CheckUNCPath(bstrUserEnteredText))
|
|
{
|
|
//
|
|
// user has entered the fully spelled out root entry path
|
|
// add it to scope pane directly
|
|
//
|
|
hr = AddDfsRoot(bstrUserEnteredText);
|
|
} else
|
|
{
|
|
//
|
|
// user has entered only a domain or server name, we need user to further
|
|
// determine the roots he wants to display in the scope pane
|
|
//
|
|
CComBSTR bstrScopeWithWhacks;
|
|
PTSTR pszScopeWithNoWhacks = NULL;
|
|
if (!mylstrncmpi(bstrUserEnteredText, _T("\\\\"), 2))
|
|
{
|
|
pszScopeWithNoWhacks = bstrUserEnteredText + 2;
|
|
bstrScopeWithWhacks = bstrUserEnteredText;
|
|
} else
|
|
{
|
|
pszScopeWithNoWhacks = bstrUserEnteredText;
|
|
bstrScopeWithWhacks = _T("\\\\");
|
|
bstrScopeWithWhacks += bstrUserEnteredText;
|
|
}
|
|
bstrScopeWithWhacks += _T("\\");
|
|
|
|
ROOTINFOLIST DfsRootList;
|
|
if (S_OK == GetMultiDfsRoots(&DfsRootList, pszScopeWithNoWhacks) && !DfsRootList.empty())
|
|
{
|
|
ROOTINFOLIST::iterator i = DfsRootList.begin();
|
|
CComBSTR bstrRoot;
|
|
if (1 == DfsRootList.size())
|
|
{
|
|
//
|
|
// this domain or server only hosts one root, add it to scope pane directly
|
|
//
|
|
bstrRoot = bstrScopeWithWhacks;
|
|
bstrRoot += (*i)->bstrRootName;
|
|
hr = AddDfsRoot(bstrRoot);
|
|
} else
|
|
{
|
|
//
|
|
// invoke the multi roots dialog
|
|
//
|
|
CMultiRoots mroots;
|
|
hr = mroots.Init(pszScopeWithNoWhacks, &DfsRootList);
|
|
if (SUCCEEDED(hr))
|
|
hr = mroots.DoModal();
|
|
|
|
if (S_OK == hr)
|
|
{
|
|
//
|
|
// user has OK'ed the dialog, add each selected root to scope pane
|
|
//
|
|
NETNAMELIST *pList = NULL;
|
|
mroots.get_SelectedRootList(&pList);
|
|
for (NETNAMELIST::iterator j = pList->begin(); j != pList->end(); j++)
|
|
{
|
|
bstrRoot = bstrScopeWithWhacks;
|
|
bstrRoot += (*j)->bstrNetName;
|
|
hr = AddDfsRoot(bstrRoot);
|
|
if (FAILED(hr))
|
|
break;
|
|
}
|
|
} else if (S_FALSE == hr)
|
|
{
|
|
//
|
|
// user has cancelled the dialog, reset it to S_OK to avoid msg popup
|
|
//
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
} else
|
|
{
|
|
//
|
|
// could be downlevel server, try to add it to scope pane
|
|
//
|
|
hr = AddDfsRoot(bstrUserEnteredText);
|
|
}
|
|
|
|
FreeRootInfoList(&DfsRootList);
|
|
}
|
|
|
|
if (S_FALSE == hr)
|
|
DisplayMessageBoxWithOK(IDS_DFSROOT_NOT_EXIST, NULL);
|
|
|
|
if (FAILED(hr))
|
|
DisplayMessageBoxForHR(hr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::EnumerateScopePane(
|
|
IN LPCONSOLENAMESPACE i_lpConsoleNameSpace,
|
|
IN HSCOPEITEM i_hItemParent
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
To eumerate(add) items in the scope pane. Dfs Roots in this case
|
|
|
|
Arguments:
|
|
|
|
i_lpConsoleNameSpace - The callback used to add items to the Scope pane
|
|
i_hItemParent - HSCOPEITEM of the parent under which all the items will be added.
|
|
|
|
--*/
|
|
{
|
|
RETURN_INVALIDARG_IF_NULL(i_hItemParent);
|
|
RETURN_INVALIDARG_IF_NULL(i_lpConsoleNameSpace);
|
|
|
|
m_hItemParent = i_hItemParent;
|
|
m_lpConsoleNameSpace = i_lpConsoleNameSpace;
|
|
|
|
CWaitCursor WaitCursor;
|
|
for (DFS_ROOT_LIST::iterator i = m_RootList.begin(); i != m_RootList.end(); i++)
|
|
{
|
|
(void)((*i)->m_pMmcDfsRoot)->AddItemToScopePane(m_lpConsoleNameSpace, m_hItemParent);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::AddDfsRoot(
|
|
IN BSTR i_bstrDfsRootName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Adds the DfsRoot to the internal list and to the Scope pane.
|
|
|
|
Arguments:
|
|
i_bstrDfsRootName - The full path(display name) of the DfsRoot to be created.
|
|
Example, ComputerName\\DfsRootName or DomainName\DfsRootName
|
|
|
|
--*/
|
|
{
|
|
RETURN_INVALIDARG_IF_NULL(i_bstrDfsRootName);
|
|
|
|
CWaitCursor wait;
|
|
|
|
// Create the IDfsRoot object
|
|
CComPtr<IDfsRoot> pDfsRoot;
|
|
HRESULT hr = CoCreateInstance (CLSID_DfsRoot, NULL, CLSCTX_INPROC_SERVER, IID_IDfsRoot, (void**) &pDfsRoot);
|
|
RETURN_IF_FAILED(hr);
|
|
|
|
hr = pDfsRoot->Initialize(i_bstrDfsRootName);
|
|
if (S_OK != hr)
|
|
return hr;
|
|
|
|
// Get the server hosting Dfs.
|
|
CComBSTR bstrDfsRootEntryPath;
|
|
hr = pDfsRoot->get_RootEntryPath(&bstrDfsRootEntryPath);
|
|
RETURN_IF_FAILED(hr);
|
|
|
|
// If already present in the list, just display a message and return
|
|
CMmcDfsRoot *pMmcDfsRoot = NULL;
|
|
hr = IsAlreadyInList(bstrDfsRootEntryPath, &pMmcDfsRoot);
|
|
if (S_OK == hr)
|
|
{
|
|
pMmcDfsRoot->OnRefresh(); // refresh to pick up other root replicas
|
|
return hr;
|
|
}
|
|
|
|
// Add the IDfsRoot object to the list and to Scope Pane
|
|
hr = AddDfsRootToList(pDfsRoot);
|
|
RETURN_IF_FAILED(hr);
|
|
|
|
m_bDirty = true; // Dirty is true as we now have a new node in the list
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::AddDfsRootToList(
|
|
IN IDfsRoot* i_pDfsRoot,
|
|
IN ULONG i_ulLinkFilterMaxLimit, // = FILTERDFSLINKS_MAXLIMIT_DEFAULT,
|
|
IN FILTERDFSLINKS_TYPE i_lLinkFilterType, // = FILTERDFSLINKS_TYPE_NO_FILTER,
|
|
IN BSTR i_bstrLinkFilterName // = NULL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
To add a new DFSRoot only to the list.
|
|
|
|
Arguments:
|
|
|
|
i_pDfsRoot - The IDfsRoot object being added to the list
|
|
|
|
--*/
|
|
{
|
|
RETURN_INVALIDARG_IF_NULL(i_pDfsRoot);
|
|
|
|
CMmcDfsRoot* pMmcDfsRoot = new CMmcDfsRoot(i_pDfsRoot, this, m_lpConsole,
|
|
i_ulLinkFilterMaxLimit, i_lLinkFilterType, i_bstrLinkFilterName);
|
|
RETURN_OUTOFMEMORY_IF_NULL(pMmcDfsRoot);
|
|
|
|
HRESULT hr = S_OK;
|
|
if ( FAILED(hr = pMmcDfsRoot->m_hrValueFromCtor) )
|
|
{
|
|
delete pMmcDfsRoot;
|
|
return hr;
|
|
}
|
|
|
|
CComBSTR bstrRootEntryPath;
|
|
hr = i_pDfsRoot->get_RootEntryPath(&bstrRootEntryPath);
|
|
if (FAILED(hr))
|
|
{
|
|
delete pMmcDfsRoot;
|
|
return hr;
|
|
}
|
|
|
|
// Create a new node for storing Dfs Root information.
|
|
DFS_ROOT_NODE* pNewDfsRootNode = new DFS_ROOT_NODE(pMmcDfsRoot, bstrRootEntryPath);
|
|
if (!pNewDfsRootNode || !pNewDfsRootNode->m_bstrRootEntryPath)
|
|
{
|
|
delete pMmcDfsRoot;
|
|
delete pNewDfsRootNode;
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
m_RootList.push_back(pNewDfsRootNode);
|
|
|
|
// Add this DfsRoot to scope pane. Need item parent to be non null
|
|
if (m_hItemParent)
|
|
{
|
|
hr = (pNewDfsRootNode->m_pMmcDfsRoot)->AddItemToScopePane(m_lpConsoleNameSpace, m_hItemParent);
|
|
RETURN_IF_FAILED(hr);
|
|
}
|
|
|
|
m_bDirty = true; // Dirty is true as we now have a new node in the list
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
// This method returns the pointer to the list containing information of all DfsRoots
|
|
// added to the Snapin. The caller SHOULD NOT free the list.
|
|
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::GetList(
|
|
OUT DFS_ROOT_LIST** o_pList
|
|
)
|
|
{
|
|
RETURN_INVALIDARG_IF_NULL(o_pList);
|
|
|
|
*o_pList = &m_RootList;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::IsAlreadyInList(
|
|
IN BSTR i_bstrDfsRootEntryPath,
|
|
OUT CMmcDfsRoot **o_ppMmcDfsRoot
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Routine used to check if the DfsRoot is already in the list
|
|
|
|
Arguments:
|
|
|
|
i_bstrDfsRootEntryPath - The Server name of the DfsRoot object
|
|
|
|
Return value:
|
|
|
|
S_OK, if node is present in the list.
|
|
S_FALSE, if the node doesn't exist in the list
|
|
--*/
|
|
{
|
|
for (DFS_ROOT_LIST::iterator i = m_RootList.begin(); i != m_RootList.end(); i++)
|
|
{
|
|
if (!lstrcmpi((*i)->m_bstrRootEntryPath, i_bstrDfsRootEntryPath))
|
|
{
|
|
if (o_ppMmcDfsRoot)
|
|
*o_ppMmcDfsRoot = (*i)->m_pMmcDfsRoot;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT
|
|
CMmcDfsAdmin::OnRefresh(
|
|
)
|
|
{
|
|
// Select this node first
|
|
m_lpConsole->SelectScopeItem(m_hItemParent);
|
|
|
|
CWaitCursor WaitCursor;
|
|
|
|
HRESULT hr = S_OK;
|
|
NETNAMELIST listRootEntryPaths;
|
|
if (!m_RootList.empty())
|
|
{
|
|
for (DFS_ROOT_LIST::iterator i = m_RootList.begin(); i != m_RootList.end(); i++)
|
|
{
|
|
// silently close all property pages
|
|
((*i)->m_pMmcDfsRoot)->CloseAllPropertySheets(TRUE);
|
|
|
|
NETNAME *pName = new NETNAME;
|
|
BREAK_OUTOFMEMORY_IF_NULL(pName, &hr);
|
|
|
|
pName->bstrNetName = (*i)->m_bstrRootEntryPath;
|
|
BREAK_OUTOFMEMORY_IF_NULL((BSTR)(pName->bstrNetName), &hr);
|
|
|
|
listRootEntryPaths.push_back(pName);
|
|
}
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
FreeNetNameList(&listRootEntryPaths);
|
|
return hr;
|
|
}
|
|
|
|
if (listRootEntryPaths.empty())
|
|
return hr;
|
|
|
|
|
|
CleanScopeChildren();
|
|
|
|
|
|
for (NETNAMELIST::iterator i = listRootEntryPaths.begin(); i != listRootEntryPaths.end(); i++)
|
|
{
|
|
(void)AddDfsRoot((*i)->bstrNetName);
|
|
}
|
|
|
|
FreeNetNameList(&listRootEntryPaths);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
CMmcDfsAdmin::OnAddImages(IImageList *pImageList, HSCOPEITEM hsi)
|
|
{
|
|
return S_OK; // no listview on the static node
|
|
}
|
|
|
|
|
|
// Delete the node from m_RootList
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::DeleteMmcRootNode(
|
|
IN CMmcDfsRoot* i_pMmcDfsRoot
|
|
)
|
|
{
|
|
RETURN_INVALIDARG_IF_NULL(i_pMmcDfsRoot);
|
|
|
|
dfsDebugOut((_T("CMmcDfsAdmin::DeleteMmcRootNode %p\n"), i_pMmcDfsRoot));
|
|
|
|
for (DFS_ROOT_LIST::iterator i = m_RootList.begin(); i != m_RootList.end(); i++)
|
|
{
|
|
if ((*i)->m_pMmcDfsRoot == i_pMmcDfsRoot)
|
|
{
|
|
m_RootList.erase(i);
|
|
m_bDirty = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::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_REFRESH, ENABLED, TRUE);
|
|
i_lpConsoleVerb->SetVerbState(MMC_VERB_PROPERTIES, HIDDEN, TRUE);
|
|
|
|
i_lpConsoleVerb->SetDefaultVerb(MMC_VERB_OPEN); //For scope items, default verb is "open"
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
Used by CMmcDfsAdmin::OnNewDfsRoot()
|
|
*/
|
|
class CMmcNewDfsWizard : public CMmcDfsAdmin
|
|
{
|
|
public:
|
|
|
|
CMmcNewDfsWizard( CDfsSnapinScopeManager* i_pScopeManager );
|
|
|
|
virtual ~CMmcNewDfsWizard();
|
|
|
|
// Checks whether the object has pages to display
|
|
STDMETHODIMP QueryPagesFor(
|
|
) { return S_OK; };
|
|
|
|
|
|
|
|
// Creates and passes back the pages to be displayed
|
|
STDMETHODIMP CreatePropertyPages(
|
|
IN LPPROPERTYSHEETCALLBACK i_lpPropSheetCallback,
|
|
IN LONG_PTR i_lNotifyHandle
|
|
);
|
|
|
|
};
|
|
|
|
CMmcNewDfsWizard::CMmcNewDfsWizard( CDfsSnapinScopeManager* i_pScopeManager )
|
|
: CMmcDfsAdmin( i_pScopeManager )
|
|
{
|
|
}
|
|
|
|
CMmcNewDfsWizard::~CMmcNewDfsWizard()
|
|
{
|
|
}
|
|
|
|
// Creates and passes back the pages to be displayed
|
|
STDMETHODIMP
|
|
CMmcNewDfsWizard::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);
|
|
|
|
return S_OK; // since we want to display a propertysheet
|
|
}
|
|
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::OnNewDfsRoot(
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Action to be taken on menu command "New Dfs Root".
|
|
Here is a wizard is used to guide the user through the process of creating a new
|
|
dfs root.
|
|
|
|
Arguments:
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CMmcNewDfsWizard* pNewDfsWizard = new CMmcNewDfsWizard( m_pScopeManager );
|
|
RETURN_OUTOFMEMORY_IF_NULL(pNewDfsWizard);
|
|
|
|
CComPtr<IDataObject> spDfsWizardDataObject = (IDataObject*)pNewDfsWizard;
|
|
|
|
CREATEDFSROOTWIZINFO CreateWizInfo;// 0 initializes all members to 0. Necessary
|
|
CreateWizInfo.pMMCAdmin = this;
|
|
|
|
CCreateDfsRootWizPage1 WizPage1(&CreateWizInfo); // Wizard pages
|
|
CCreateDfsRootWizPage2 WizPage2(&CreateWizInfo);
|
|
CCreateDfsRootWizPage3 WizPage3(&CreateWizInfo);
|
|
CCreateDfsRootWizPage4 WizPage4(&CreateWizInfo);
|
|
CCreateDfsRootWizPage6 WizPage6(&CreateWizInfo);
|
|
CCreateDfsRootWizPage5 WizPage5(&CreateWizInfo);
|
|
CCreateDfsRootWizPage7 WizPage7(&CreateWizInfo);
|
|
|
|
// Get the required interfaces from IConsole2.
|
|
CComPtr<IPropertySheetCallback> pPropSheetCallback; // MMC Callback used to add pages
|
|
HRESULT 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
|
|
// JonN 2/14/98 Currently MMC-based wizards don't work unless you call AddPrimaryPages.
|
|
hr = pPropSheetProvider->CreatePropertySheet(
|
|
_T(""), // Property sheet title. Should not be null so send empty string.
|
|
FALSE, // Wizard and not property sheet.
|
|
0, // Cookie
|
|
(LPDATAOBJECT)spDfsWizardDataObject, // IDataobject
|
|
MMC_PSO_NEWWIZARDTYPE); // Creation flags
|
|
|
|
RETURN_IF_FAILED(hr);
|
|
|
|
|
|
// Create the pages for the wizard. Use the handle return to add to our wizard
|
|
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);
|
|
hr = pPropSheetCallback->AddPage(WizPage4.Create());
|
|
RETURN_IF_FAILED(hr);
|
|
hr = pPropSheetCallback->AddPage(WizPage6.Create());
|
|
RETURN_IF_FAILED(hr);
|
|
hr = pPropSheetCallback->AddPage(WizPage5.Create());
|
|
RETURN_IF_FAILED(hr);
|
|
hr = pPropSheetCallback->AddPage(WizPage7.Create());
|
|
RETURN_IF_FAILED(hr);
|
|
|
|
// Ask the provider to use the pages from the callback
|
|
hr = pPropSheetProvider->AddPrimaryPages( (IComponentData *)(m_pScopeManager),
|
|
TRUE, // Don't create a notify handle
|
|
NULL,
|
|
TRUE // Scope pane (not result pane)
|
|
);
|
|
RETURN_IF_FAILED(hr);
|
|
|
|
HWND hwndMainWin = 0; // MMC main window. Used to make it modal
|
|
hr = m_lpConsole->GetMainWindow(&hwndMainWin); // Get the main MMC window
|
|
RETURN_IF_FAILED(hr);
|
|
|
|
// Display the wizard
|
|
hr = pPropSheetProvider->Show( (LONG_PTR)hwndMainWin, // Parent window of the wizard
|
|
0 // Starting page
|
|
);
|
|
RETURN_IF_FAILED(hr);
|
|
|
|
if (CreateWizInfo.bDfsSetupSuccess)
|
|
{
|
|
CComBSTR bstrRootEntryPath = _T("\\\\");
|
|
if (CreateWizInfo.DfsType == DFS_TYPE_FTDFS)
|
|
bstrRootEntryPath += CreateWizInfo.bstrSelectedDomain;
|
|
else
|
|
bstrRootEntryPath += CreateWizInfo.bstrSelectedServer;
|
|
bstrRootEntryPath += _T("\\");
|
|
bstrRootEntryPath += CreateWizInfo.bstrDfsRootName;
|
|
|
|
hr = AddDfsRoot(bstrRootEntryPath);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CMmcDfsAdmin::PutConsolePtr(
|
|
IN const LPCONSOLE2 i_lpConsole
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
A routine used just to set the lpconsole pointer.
|
|
This is used later by display object
|
|
|
|
Arguments:
|
|
i_lpConsole - Console pointer.
|
|
|
|
--*/
|
|
{
|
|
RETURN_INVALIDARG_IF_NULL(i_lpConsole);
|
|
|
|
m_lpConsole = i_lpConsole;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CMmcDfsAdmin::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;
|
|
HRESULT hr = LoadStringFromResource(IDS_DESCRIPTION_BAR_TEXT_ADMIN, &bstrTextForDescriptionBar);
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = i_lpResultData->SetDescBarText(bstrTextForDescriptionBar);
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CMmcDfsAdmin::ToolbarSelect(
|
|
IN const LONG i_lArg,
|
|
IN IToolbar* i_pToolBar
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle a select event for a toolbar
|
|
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_ADMIN_MIN, IDT_ADMIN_MAX, bSelect);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
CMmcDfsAdmin::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.
|
|
o_pToolBar - The Toolbar pointer.
|
|
|
|
--*/
|
|
{
|
|
RETURN_INVALIDARG_IF_NULL(i_pControlbar);
|
|
RETURN_INVALIDARG_IF_NULL(i_lExtendControlbar);
|
|
RETURN_INVALIDARG_IF_NULL(o_pToolBar);
|
|
|
|
// Create the toolbar
|
|
HRESULT 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_ADMIN_TOOLBAR);
|
|
RETURN_IF_FAILED(hr);
|
|
|
|
int iButtonPosition = 0; // The first button position
|
|
for (int iCommandID = IDT_ADMIN_MIN, iMenuResource = IDS_MENUS_STATIC_TOP_NEW_DFSROOT;
|
|
iCommandID <= IDT_ADMIN_MAX;
|
|
iCommandID++,iMenuResource++,iButtonPosition++)
|
|
{
|
|
CComBSTR bstrMenuText;
|
|
CComBSTR bstrToolTipText;
|
|
hr = GetMenuResourceStrings(iMenuResource, &bstrMenuText, &bstrToolTipText, NULL);
|
|
RETURN_IF_FAILED(hr);
|
|
|
|
// Add all the buttons to the toolbar
|
|
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);
|
|
RETURN_IF_FAILED(hr);
|
|
}
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
STDMETHODIMP
|
|
CMmcDfsAdmin::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_INVALIDARG_IF_NULL(i_pControlbar);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
switch(i_lParam) // What button did the user click on.
|
|
{
|
|
case IDT_ADMIN_CONNECTTO:
|
|
hr = OnConnectTo();
|
|
break;
|
|
case IDT_ADMIN_NEW_DFSROOT:
|
|
hr = OnNewDfsRoot();
|
|
break;
|
|
default:
|
|
hr = E_INVALIDARG;
|
|
break;
|
|
};
|
|
|
|
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CMmcDfsAdmin::CleanScopeChildren(
|
|
)
|
|
{
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Recursively deletes all Scope pane children display objects.
|
|
|
|
--*/
|
|
HRESULT hr = S_OK;
|
|
|
|
if (!m_RootList.empty())
|
|
{
|
|
// clean up display objects
|
|
for (DFS_ROOT_LIST::iterator i = m_RootList.begin(); i != m_RootList.end(); i++)
|
|
{
|
|
delete (*i);
|
|
}
|
|
|
|
m_RootList.erase(m_RootList.begin(), m_RootList.end());
|
|
|
|
// Delete all child items from scope pane
|
|
if (m_lpConsoleNameSpace)
|
|
{
|
|
HSCOPEITEM hChild = NULL;
|
|
MMC_COOKIE lCookie = 0;
|
|
while (SUCCEEDED(hr = m_lpConsoleNameSpace->GetChildItem(m_hItemParent, &hChild, &lCookie)) && hChild)
|
|
{
|
|
(void) m_lpConsoleNameSpace->DeleteItem(hChild, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|