5062 lines
88 KiB
C++
5062 lines
88 KiB
C++
/*++
|
|
|
|
Copyright (c) 1994-1998 Microsoft Corporation
|
|
|
|
Module Name :
|
|
|
|
iisobj.cpp
|
|
|
|
Abstract:
|
|
|
|
IIS Objects
|
|
|
|
Author:
|
|
|
|
Ronald Meijer (ronaldm)
|
|
|
|
Project:
|
|
|
|
Internet Services Manager
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
|
|
//
|
|
// Include Files
|
|
//
|
|
#include "stdafx.h"
|
|
#include "comprop.h"
|
|
#include "inetmgr.h"
|
|
#include "iisobj.h"
|
|
#include "machine.h"
|
|
#include <shlwapi.h>
|
|
#include "guids.h"
|
|
|
|
#ifdef _DEBUG
|
|
#undef THIS_FILE
|
|
static char BASED_CODE THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
|
|
//
|
|
// Static initialization
|
|
//
|
|
BOOL CIISObject::m_fIsExtension = FALSE;
|
|
CString CIISObject::s_strProperties;
|
|
CString CIISObject::s_strRunning;
|
|
CString CIISObject::s_strPaused;
|
|
CString CIISObject::s_strStopped;
|
|
CString CIISObject::s_strUnknown;
|
|
CString CIISObject::s_strYes;
|
|
CString CIISObject::s_strNo;
|
|
CString CIISObject::s_strTCPIP;
|
|
CString CIISObject::s_strNetBIOS;
|
|
CString CIISObject::s_strDefaultIP;
|
|
CString CIISObject::s_strRedirect;
|
|
time_t CIISObject::s_lExpirationTime = (5L * 60L); // 5 Minutes
|
|
LPCONSOLENAMESPACE CIISObject::s_lpcnsScopeView = NULL;
|
|
|
|
|
|
|
|
//
|
|
// Backup/restore taskpad gif resource
|
|
//
|
|
#define RES_TASKPAD_BACKUP _T("/img\\backup.gif")
|
|
|
|
|
|
|
|
LPCTSTR
|
|
PrependParentPath(
|
|
IN OUT CString & strPath,
|
|
IN LPCTSTR lpszParent,
|
|
IN TCHAR chSep
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper function to prepend a new parent to the given path
|
|
|
|
Arguments:
|
|
|
|
CString & strPath : Current path
|
|
LPCTSTR lpszParent : Parent to be prepended
|
|
TCHAR chSep : Separator character
|
|
|
|
Return Value:
|
|
|
|
Pointer to the path
|
|
|
|
--*/
|
|
{
|
|
if (strPath.IsEmpty())
|
|
{
|
|
strPath = lpszParent;
|
|
}
|
|
else
|
|
{
|
|
CString strTail(strPath);
|
|
strPath = lpszParent;
|
|
strPath += chSep;
|
|
strPath += strTail;
|
|
}
|
|
|
|
TRACEEOLID("PrependParentPath: " << strPath);
|
|
|
|
return strPath;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
ShellExecuteDirectory(
|
|
IN LPCTSTR lpszCommand,
|
|
IN LPCTSTR lpszOwner,
|
|
IN LPCTSTR lpszDirectory
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Shell Open or explore on a given directory path
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpszCommand : "open" or "explore"
|
|
LPCTSTR lpszOwner : Owner server
|
|
LPCTSTR lpszDirectory : Directory path
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
CString strDir;
|
|
|
|
if (::IsServerLocal(lpszOwner) || ::IsUNCName(lpszDirectory))
|
|
{
|
|
//
|
|
// Local directory, or already a unc path
|
|
//
|
|
strDir = lpszDirectory;
|
|
}
|
|
else
|
|
{
|
|
::MakeUNCPath(strDir, lpszOwner, lpszDirectory);
|
|
}
|
|
|
|
TRACEEOLID("Attempting to " << lpszCommand << " Path: " << strDir);
|
|
|
|
CError err;
|
|
{
|
|
//
|
|
// AFX_MANAGE_STATE required for wait cursor
|
|
//
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
|
|
CWaitCursor wait;
|
|
|
|
if (::ShellExecute(
|
|
NULL,
|
|
lpszCommand,
|
|
strDir,
|
|
NULL,
|
|
_T(""),
|
|
SW_SHOW
|
|
) <= (HINSTANCE)32)
|
|
{
|
|
err.GetLastWinError();
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
void
|
|
CIISObject::BuildResultView(
|
|
IN LPHEADERCTRL pHeader,
|
|
IN int cColumns,
|
|
IN int * pnIDS,
|
|
IN int * pnWidths
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build the result view columns
|
|
|
|
Routine Description:
|
|
|
|
LPHEADERCTRL pHeader : Header control
|
|
int cColumns : Number of columns
|
|
int * pnIDS : Array of column header strings
|
|
int * pnWidths : Array of column widths
|
|
|
|
Routine Description:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
ASSERT(pHeader != NULL);
|
|
|
|
//
|
|
// Needed for loadstring
|
|
//
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
CString str;
|
|
|
|
for (int n = 0; n < cColumns; ++n)
|
|
{
|
|
VERIFY(str.LoadString(pnIDS[n]));
|
|
pHeader->InsertColumn(n, str, LVCFMT_LEFT, pnWidths[n]);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
BOOL
|
|
CIISObject::CanAddInstance(
|
|
IN LPCTSTR lpszMachineName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Helper function to determine if instances may be added on
|
|
this machine
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpszMachineName : Machine name
|
|
|
|
Return Value:
|
|
|
|
TRUE if instances can be added
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Assume W3svc and ftpsvc have the same capabilities.
|
|
//
|
|
CServerCapabilities * pcap;
|
|
|
|
pcap = new CServerCapabilities(lpszMachineName, SZ_MBN_WEB);
|
|
|
|
if (!pcap)
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
if (FAILED(pcap->LoadData()))
|
|
{
|
|
//
|
|
// Try ftp
|
|
//
|
|
delete pcap;
|
|
pcap = new CServerCapabilities(lpszMachineName, SZ_MBN_FTP);
|
|
}
|
|
|
|
if (!pcap || FAILED(pcap->LoadData()))
|
|
{
|
|
if (pcap)
|
|
{
|
|
delete pcap;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL fCanAdd = pcap->HasMultipleSites();
|
|
|
|
delete pcap;
|
|
|
|
return fCanAdd;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
CIISObject::IsScopeSelected()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return TRUE if the scope is currently selected
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if the item is currently selected, FALSE otherwise
|
|
|
|
--*/
|
|
{
|
|
ASSERT(s_lpcnsScopeView != NULL);
|
|
|
|
HSCOPEITEM hItem = GetScopeHandle();
|
|
ASSERT(hItem != NULL);
|
|
|
|
if (hItem != NULL)
|
|
{
|
|
SCOPEDATAITEM item;
|
|
::ZeroMemory(&item, sizeof(SCOPEDATAITEM));
|
|
item.mask = SDI_STATE;
|
|
item.nState = MMC_SCOPE_ITEM_STATE_EXPANDEDONCE;
|
|
item.ID = hItem;
|
|
|
|
HRESULT hr = s_lpcnsScopeView->GetItem(&item);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
return (item.nState & MMC_SCOPE_ITEM_STATE_EXPANDEDONCE) != 0;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CIISObject::RefreshDisplayInfo()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Refresh the display info parameters in the scope view
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
if (IsLeafNode())
|
|
{
|
|
//
|
|
// Not supported on result items
|
|
//
|
|
return;
|
|
}
|
|
|
|
ASSERT(s_lpcnsScopeView != NULL);
|
|
|
|
HSCOPEITEM hItem = GetScopeHandle();
|
|
ASSERT(hItem != NULL);
|
|
|
|
SCOPEDATAITEM item;
|
|
::ZeroMemory(&item, sizeof(SCOPEDATAITEM));
|
|
|
|
//
|
|
// Since we're using a callback, this is
|
|
// all we need to do here
|
|
//
|
|
item.mask = SDI_STR | SDI_IMAGE | SDI_OPENIMAGE;
|
|
item.displayname = MMC_CALLBACK;
|
|
item.nOpenImage = item.nImage = QueryBitmapIndex();
|
|
item.ID = hItem;
|
|
|
|
s_lpcnsScopeView->SetItem(&item);
|
|
}
|
|
|
|
|
|
|
|
CIISObject::CIISObject(
|
|
IN const GUID guid,
|
|
IN LPCTSTR lpszNodeName, OPTIONAL
|
|
IN LPCTSTR lpszPhysicalPath OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for CIISObject. Initialise static member functions
|
|
if not yet initialized. This is a protected constructor of
|
|
an abstract base class.
|
|
|
|
Arguments:
|
|
|
|
const GUID guid : GUID of the object
|
|
LPCTSTR lpszNodeName : Node name
|
|
LPCTSTR lpszPhysicalPath : Physical path (or empty)
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: m_hScopeItem(NULL),
|
|
m_guid(guid),
|
|
m_strNodeName(lpszNodeName),
|
|
m_strPhysicalPath(lpszPhysicalPath),
|
|
m_strRedirPath(),
|
|
m_fChildOnlyRedir(FALSE),
|
|
m_fIsParentScope(FALSE),
|
|
m_tmChildrenExpanded(0L)
|
|
{
|
|
//
|
|
// Initialize static members
|
|
//
|
|
if (CIISObject::s_strRunning.IsEmpty())
|
|
{
|
|
//
|
|
// AFX_MANAGE_STATE required for resource load
|
|
//
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
TRACEEOLID("Initializing static strings");
|
|
|
|
VERIFY(CIISObject::s_strRunning.LoadString(IDS_RUNNING));
|
|
VERIFY(CIISObject::s_strPaused.LoadString(IDS_PAUSED));
|
|
VERIFY(CIISObject::s_strStopped.LoadString(IDS_STOPPED));
|
|
VERIFY(CIISObject::s_strUnknown.LoadString(IDS_UNKNOWN));
|
|
VERIFY(CIISObject::s_strProperties.LoadString(IDS_MENU_PROPERTIES));
|
|
VERIFY(CIISObject::s_strYes.LoadString(IDS_YES));
|
|
VERIFY(CIISObject::s_strNo.LoadString(IDS_NO));
|
|
VERIFY(CIISObject::s_strTCPIP.LoadString(IDS_TCPIP));
|
|
VERIFY(CIISObject::s_strNetBIOS.LoadString(IDS_NETBIOS));
|
|
VERIFY(CIISObject::s_strDefaultIP.LoadString(IDS_DEFAULT_IP));
|
|
VERIFY(CIISObject::s_strRedirect.LoadString(IDS_REDIRECTED));
|
|
}
|
|
}
|
|
|
|
BOOL CIISObject::IsValidObject() const
|
|
{
|
|
// CIISObject could have only one of the following GUIDs
|
|
GUID guid = QueryGUID();
|
|
if ( guid == cInternetRootNode
|
|
|| guid == cMachineNode
|
|
|| guid == cServiceCollectorNode
|
|
|| guid == cInstanceCollectorNode
|
|
|| guid == cInstanceNode
|
|
|| guid == cChildNode
|
|
|| guid == cFileNode
|
|
)
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
CIISObject::operator LPCTSTR()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Typecast operator to call out the display text
|
|
|
|
Arguments:
|
|
|
|
N/A
|
|
|
|
Return Value:
|
|
|
|
Display text
|
|
|
|
--*/
|
|
{
|
|
static CString strText;
|
|
|
|
return GetDisplayText(strText);
|
|
}
|
|
|
|
//
|
|
// Separator menu item definition
|
|
//
|
|
CONTEXTMENUITEM menuSep =
|
|
{
|
|
NULL,
|
|
NULL,
|
|
-1,
|
|
CCM_INSERTIONPOINTID_PRIMARY_TOP,
|
|
0,
|
|
CCM_SPECIAL_SEPARATOR
|
|
};
|
|
|
|
|
|
|
|
//
|
|
// Menu item definition that uses resource definitions, and
|
|
// provides some additional information for taskpads.
|
|
//
|
|
typedef struct tagCONTEXTMENUITEM_RC
|
|
{
|
|
UINT nNameID;
|
|
UINT nStatusID;
|
|
UINT nDescriptionID;
|
|
LONG lCmdID;
|
|
LONG lInsertionPointID;
|
|
LONG fSpecialFlags;
|
|
LPCTSTR lpszMouseOverBitmap;
|
|
LPCTSTR lpszMouseOffBitmap;
|
|
} CONTEXTMENUITEM_RC;
|
|
|
|
|
|
|
|
//
|
|
// Important! The array indices below must ALWAYS be one
|
|
// less than the menu ID -- keep in sync with enumeration
|
|
// in inetmgr.h!!!!
|
|
//
|
|
static CONTEXTMENUITEM_RC menuItemDefs[] =
|
|
{
|
|
//
|
|
// Menu Commands in toolbar order
|
|
//
|
|
{ IDS_MENU_CONNECT, IDS_MENU_TT_CONNECT, -1, IDM_CONNECT, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
|
|
{ IDS_MENU_DISCOVER, IDS_MENU_TT_DISCOVER, -1, IDM_DISCOVER, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
|
|
{ IDS_MENU_START, IDS_MENU_TT_START, -1, IDM_START, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
|
|
{ IDS_MENU_STOP, IDS_MENU_TT_STOP, -1, IDM_STOP, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
|
|
{ IDS_MENU_PAUSE, IDS_MENU_TT_PAUSE, -1, IDM_PAUSE, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
|
|
//
|
|
// These are menu commands that do not show up in the toolbar
|
|
//
|
|
{ IDS_MENU_EXPLORE, IDS_MENU_TT_EXPLORE, -1, IDM_EXPLORE, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
|
|
{ IDS_MENU_OPEN, IDS_MENU_TT_OPEN, -1, IDM_OPEN, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
|
|
{ IDS_MENU_BROWSE, IDS_MENU_TT_BROWSE, -1, IDM_BROWSE, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
|
|
{ IDS_MENU_PROPERTIES, IDS_MENU_TT_PROPERTIES, -1, IDM_CONFIGURE, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
|
|
{ IDS_MENU_DISCONNECT, IDS_MENU_TT_DISCONNECT, -1, IDM_DISCONNECT, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
|
|
{ IDS_MENU_BACKUP, IDS_MENU_TT_BACKUP, IDS_MENU_TT_BACKUP, IDM_METABACKREST, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
|
|
{ IDS_MENU_SHUTDOWN_IIS, IDS_MENU_TT_SHUTDOWN_IIS, -1, IDM_SHUTDOWN, CCM_INSERTIONPOINTID_PRIMARY_TOP, 0, NULL, NULL, },
|
|
{ IDS_MENU_NEWVROOT, IDS_MENU_TT_NEWVROOT, IDS_MENU_DS_NEWVROOT, IDM_NEW_VROOT, CCM_INSERTIONPOINTID_PRIMARY_NEW, 0, RES_TASKPAD_NEWVROOT, RES_TASKPAD_NEWVROOT, },
|
|
{ IDS_MENU_NEWINSTANCE, IDS_MENU_TT_NEWINSTANCE, IDS_MENU_DS_NEWINSTANCE, IDM_NEW_INSTANCE, CCM_INSERTIONPOINTID_PRIMARY_NEW, 0, RES_TASKPAD_NEWSITE, RES_TASKPAD_NEWSITE, },
|
|
{ IDS_MENU_TASKPAD, IDS_MENU_TT_TASKPAD, -1, IDM_VIEW_TASKPAD, CCM_INSERTIONPOINTID_PRIMARY_VIEW, 0, NULL, NULL, },
|
|
{ IDS_MENU_SECURITY_WIZARD, IDS_MENU_TT_SECURITY_WIZARD, IDS_MENU_TT_SECURITY_WIZARD, IDM_TASK_SECURITY_WIZARD, CCM_INSERTIONPOINTID_PRIMARY_TASK, 0, RES_TASKPAD_SECWIZ, RES_TASKPAD_SECWIZ, },
|
|
};
|
|
|
|
|
|
|
|
/* static */
|
|
HRESULT
|
|
CIISObject::AddMenuItemByCommand(
|
|
IN LPCONTEXTMENUCALLBACK lpContextMenuCallback,
|
|
IN LONG lCmdID,
|
|
|
|
IN LONG fFlags
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add menu item by command
|
|
|
|
Arguments:
|
|
|
|
LPCONTEXTMENUCALLBACK lpContextMenuCallback : Callback pointer
|
|
LONG lCmdID : Command ID
|
|
LONG fFlags : Flags
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
ASSERT(lpContextMenuCallback != NULL);
|
|
|
|
//
|
|
// Offset 1 menu commands
|
|
//
|
|
LONG l = lCmdID -1;
|
|
|
|
CString strName;
|
|
CString strStatus;
|
|
|
|
{
|
|
//
|
|
// AFX_MANAGE_STATE required for resource load
|
|
//
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
|
|
VERIFY(strName.LoadString(menuItemDefs[l].nNameID));
|
|
VERIFY(strStatus.LoadString(menuItemDefs[l].nStatusID));
|
|
}
|
|
|
|
CONTEXTMENUITEM cmi;
|
|
cmi.strName = strName.GetBuffer(0);
|
|
cmi.strStatusBarText = strStatus.GetBuffer(0);
|
|
cmi.lCommandID = menuItemDefs[l].lCmdID;
|
|
cmi.lInsertionPointID = menuItemDefs[l].lInsertionPointID;
|
|
cmi.fFlags = fFlags;
|
|
cmi.fSpecialFlags = menuItemDefs[l].fSpecialFlags;
|
|
|
|
return lpContextMenuCallback->AddItem(&cmi);
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
HRESULT
|
|
CIISObject::AddTaskpadItemByInfo(
|
|
OUT MMC_TASK * pTask,
|
|
IN LONG lCommandID,
|
|
IN LPCTSTR lpszMouseOn,
|
|
IN LPCTSTR lpszMouseOff,
|
|
IN LPCTSTR lpszText,
|
|
IN LPCTSTR lpszHelpString
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add taskpad item from the information given
|
|
|
|
Arguments:
|
|
|
|
MMC_TASK * pTask : Task info
|
|
LPCTSTR lpszMouseOn : Mouse on URL
|
|
LPCTSTR lpszMouseOff : Mouse off URL
|
|
LPCTSTR lpszText : Text to be displayed
|
|
LPCTSTR lpszHelpString : Help string
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
TRACEEOLID(lpszMouseOn);
|
|
TRACEEOLID(lpszMouseOff);
|
|
|
|
pTask->sDisplayObject.eDisplayType = MMC_TASK_DISPLAY_TYPE_VANILLA_GIF;
|
|
|
|
pTask->sDisplayObject.uBitmap.szMouseOverBitmap
|
|
= CoTaskDupString((LPCOLESTR)lpszMouseOn);
|
|
pTask->sDisplayObject.uBitmap.szMouseOffBitmap
|
|
= CoTaskDupString((LPCOLESTR)lpszMouseOff);
|
|
pTask->szText = CoTaskDupString((LPCOLESTR)lpszText);
|
|
pTask->szHelpString = CoTaskDupString((LPCOLESTR)lpszHelpString);
|
|
|
|
if (pTask->sDisplayObject.uBitmap.szMouseOverBitmap
|
|
&& pTask->sDisplayObject.uBitmap.szMouseOffBitmap
|
|
&& pTask->szText
|
|
&& pTask->szHelpString
|
|
)
|
|
{
|
|
//
|
|
// Add action
|
|
//
|
|
pTask->eActionType = MMC_ACTION_ID;
|
|
pTask->nCommandID = lCommandID;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Failed
|
|
//
|
|
CoTaskStringFree(pTask->sDisplayObject.uBitmap.szMouseOverBitmap);
|
|
CoTaskStringFree(pTask->sDisplayObject.uBitmap.szMouseOffBitmap);
|
|
CoTaskStringFree(pTask->szText);
|
|
CoTaskStringFree(pTask->szHelpString);
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
HRESULT
|
|
CIISObject::AddTaskpadItemByCommand(
|
|
IN LONG lCmdID,
|
|
OUT MMC_TASK * pTask,
|
|
IN HINSTANCE hInstance OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add taskpad item by command
|
|
|
|
Arguments:
|
|
|
|
LONG lCmdID : Command ID
|
|
CString & strResURL : Resource ID
|
|
MMC_TASK * pTask : Task structure to be filled in
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
ASSERT(pTask != NULL);
|
|
|
|
//
|
|
// Offset 1 menu commands
|
|
//
|
|
LONG l = lCmdID -1;
|
|
|
|
CString strName;
|
|
CString strStatus;
|
|
|
|
CString strResURL;
|
|
HRESULT hr = BuildResURL(strResURL, hInstance);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
{
|
|
//
|
|
// AFX_MANAGE_STATE required for resource load
|
|
//
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
|
|
VERIFY(strName.LoadString(menuItemDefs[l].nStatusID));
|
|
VERIFY(strStatus.LoadString(menuItemDefs[l].nDescriptionID));
|
|
}
|
|
|
|
//
|
|
// Make sure this menu command was intended to go onto a taskpad
|
|
//
|
|
ASSERT(menuItemDefs[l].lpszMouseOverBitmap != NULL);
|
|
ASSERT(menuItemDefs[l].lpszMouseOffBitmap != NULL);
|
|
|
|
//
|
|
// Fill out bitmap URL (use defaults if nothing provided)
|
|
//
|
|
CString strMouseOn(strResURL);
|
|
CString strMouseOff(strResURL);
|
|
|
|
strMouseOn += menuItemDefs[l].lpszMouseOverBitmap;
|
|
strMouseOff += menuItemDefs[l].lpszMouseOffBitmap;
|
|
|
|
return AddTaskpadItemByInfo(
|
|
pTask,
|
|
menuItemDefs[l].lCmdID,
|
|
strMouseOn,
|
|
strMouseOff,
|
|
strName,
|
|
strStatus
|
|
);
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISObject::AddMenuItems(
|
|
IN LPCONTEXTMENUCALLBACK lpContextMenuCallback
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add menu items to the context that are valid for this
|
|
object
|
|
|
|
Arguments:
|
|
|
|
LPCONTEXTMENUCALLBACK lpContextMenuCallback : Callback
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
if (IsConnectable() && !m_fIsExtension)
|
|
{
|
|
AddMenuItemByCommand(lpContextMenuCallback, IDM_CONNECT);
|
|
AddMenuItemByCommand(lpContextMenuCallback, IDM_DISCONNECT);
|
|
}
|
|
|
|
if (IsExplorable())
|
|
{
|
|
lpContextMenuCallback->AddItem(&menuSep);
|
|
AddMenuItemByCommand(lpContextMenuCallback, IDM_EXPLORE);
|
|
}
|
|
|
|
if (IsOpenable())
|
|
{
|
|
AddMenuItemByCommand(lpContextMenuCallback, IDM_OPEN);
|
|
}
|
|
|
|
if (IsBrowsable())
|
|
{
|
|
AddMenuItemByCommand(lpContextMenuCallback, IDM_BROWSE);
|
|
}
|
|
|
|
if (IsControllable())
|
|
{
|
|
lpContextMenuCallback->AddItem(&menuSep);
|
|
|
|
UINT nPauseFlags = IsPausable() ? 0 : MF_GRAYED;
|
|
|
|
if (IsPaused())
|
|
{
|
|
nPauseFlags |= MF_CHECKED;
|
|
}
|
|
|
|
AddMenuItemByCommand(lpContextMenuCallback, IDM_START, IsStartable() ? 0 : MF_GRAYED);
|
|
AddMenuItemByCommand(lpContextMenuCallback, IDM_STOP, IsStoppable() ? 0 : MF_GRAYED);
|
|
AddMenuItemByCommand(lpContextMenuCallback, IDM_PAUSE, nPauseFlags);
|
|
}
|
|
|
|
#ifdef MMC_PAGES
|
|
|
|
//
|
|
// Bring up private config menu item only if not
|
|
// configurable through MMC
|
|
//
|
|
if (IsConfigurable() && !IsMMCConfigurable())
|
|
{
|
|
lpContextMenuCallback->AddItem(&menuSep);
|
|
AddMenuItemByCommand(lpContextMenuCallback, IDM_CONFIGURE);
|
|
}
|
|
|
|
#else
|
|
|
|
if (IsConfigurable())
|
|
{
|
|
lpContextMenuCallback->AddItem(&menuSep);
|
|
AddMenuItemByCommand(lpContextMenuCallback, IDM_CONFIGURE);
|
|
}
|
|
|
|
#endif // MMC_PAGES
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISObject::AddNextTaskpadItem(
|
|
OUT MMC_TASK * pTask
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add next taskpad item
|
|
|
|
Arguments:
|
|
|
|
MMC_TASK * pTask : Task structure to fill in
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// CODEWORK: Because of enumeration, this isn't easy
|
|
// to handle the way menu items are handled
|
|
//
|
|
ASSERT(FALSE);
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
CIISObject *
|
|
CIISObject::GetParentObject() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the parent object (in the scope view) of this object.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Pointer to the parent object, or NULL if not found
|
|
|
|
--*/
|
|
{
|
|
MMC_COOKIE cookie;
|
|
HSCOPEITEM hParent;
|
|
|
|
HRESULT hr = GetScopeView()->GetParentItem(
|
|
GetScopeHandle(),
|
|
&hParent,
|
|
&cookie
|
|
);
|
|
|
|
if (hParent == NULL || cookie == 0L || FAILED(hr))
|
|
{
|
|
//
|
|
// None found
|
|
//
|
|
return NULL;
|
|
}
|
|
|
|
return (CIISObject *)cookie;
|
|
}
|
|
|
|
|
|
|
|
LPCTSTR
|
|
CIISObject::BuildParentPath(
|
|
OUT CString & strParent,
|
|
IN BOOL fMetabasePath
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Walk up the parent nodes to build either a metabase path,
|
|
or a physical path to the parent of this node.
|
|
|
|
Arguments:
|
|
|
|
CString & strParent : Returns the parent path
|
|
BOOL fMetabasePath : If TRUE want full metabse path
|
|
If FALSE, relative path from the instance only
|
|
|
|
Return Value:
|
|
|
|
Pointer to the path
|
|
|
|
--*/
|
|
{
|
|
const CIISObject * pObject = this;
|
|
|
|
//
|
|
// Walk up the tree to build a proper parent path
|
|
//
|
|
for (;;)
|
|
{
|
|
if (pObject->IsTerminalPoint(fMetabasePath))
|
|
{
|
|
break;
|
|
}
|
|
|
|
pObject = pObject->GetParentObject();
|
|
|
|
if (pObject == NULL)
|
|
{
|
|
//
|
|
// Should have stopped before this.
|
|
//
|
|
ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
PrependParentPath(
|
|
strParent,
|
|
pObject->QueryNodeName(fMetabasePath),
|
|
g_chSep
|
|
);
|
|
|
|
//
|
|
// Keep looking
|
|
//
|
|
}
|
|
|
|
TRACEEOLID("BuildParentPath: " << strParent);
|
|
|
|
return strParent;
|
|
}
|
|
|
|
|
|
|
|
LPCTSTR
|
|
CIISObject::BuildFullPath(
|
|
OUT CString & strPath,
|
|
IN BOOL fMetabasePath
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build complete path for the current object. Either a metabase path or
|
|
a directory path.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
Pointer to the path
|
|
|
|
--*/
|
|
{
|
|
strPath = QueryNodeName(fMetabasePath);
|
|
BuildParentPath(strPath, fMetabasePath);
|
|
TRACEEOLID("CIISObject::BuildFullPath:" << strPath);
|
|
|
|
return strPath;
|
|
}
|
|
|
|
|
|
|
|
LPCTSTR
|
|
CIISObject::BuildPhysicalPath(
|
|
OUT CString & strPhysicalPath
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build a physical path for the current node. Starting with the current
|
|
node, walk up the tree appending node names until a virtual directory
|
|
with a real physical path is found
|
|
|
|
Arguments:
|
|
|
|
CString & strPhysicalPath : Returns file path
|
|
|
|
Return Value:
|
|
|
|
Pointer to path
|
|
|
|
--*/
|
|
{
|
|
const CIISObject * pObject = this;
|
|
|
|
//
|
|
// Walk up the tree to build a physical path
|
|
//
|
|
for (;;)
|
|
{
|
|
if (pObject->IsVirtualDirectory())
|
|
{
|
|
//
|
|
// Path is properly terminated here
|
|
//
|
|
PrependParentPath(
|
|
strPhysicalPath,
|
|
pObject->QueryPhysicalPath(),
|
|
_T('\\')
|
|
);
|
|
break;
|
|
}
|
|
|
|
PrependParentPath(
|
|
strPhysicalPath,
|
|
pObject->QueryNodeName(),
|
|
_T('\\')
|
|
);
|
|
|
|
pObject = pObject->GetParentObject();
|
|
|
|
if (pObject == NULL)
|
|
{
|
|
//
|
|
// Should have stopped before this.
|
|
//
|
|
ASSERT(FALSE);
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Keep looking
|
|
//
|
|
}
|
|
|
|
TRACEEOLID("BuildPhysicalPath: " << strPhysicalPath);
|
|
|
|
return strPhysicalPath;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
CIISObject::QueryInstanceID()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return the ID of the owner instance
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Owner instance ID or 0xffffffff
|
|
|
|
--*/
|
|
{
|
|
CIISInstance * pInstance = FindOwnerInstance();
|
|
|
|
return pInstance ? pInstance->QueryID() : 0xffffffff;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISObject::Open()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Open the physical path of the current node in the explorer
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
CString strPath;
|
|
BuildPhysicalPath(strPath);
|
|
|
|
return ShellExecuteDirectory(_T("open"), GetMachineName(), strPath);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISObject::Explore()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
"explore" the physical path of the current node
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
CString strPath;
|
|
BuildPhysicalPath(strPath);
|
|
|
|
return ShellExecuteDirectory(_T("explore"), GetMachineName(), strPath);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISObject::Browse()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Bring up the current path in the browser.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
CString strPath;
|
|
|
|
BuildFullPath(strPath, FALSE);
|
|
|
|
CIISInstance * pInstance = FindOwnerInstance();
|
|
|
|
if (pInstance == NULL)
|
|
{
|
|
ASSERT(FALSE);
|
|
|
|
return CError::HResult(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
return pInstance->ShellBrowsePath(strPath);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Machine pages
|
|
//
|
|
CObListPlus * CIISMachine::s_poblNewInstanceCmds = NULL;
|
|
CString CIISMachine::s_strLocalMachine;
|
|
|
|
|
|
|
|
//
|
|
// Define result view for machine objects
|
|
//
|
|
int CIISMachine::rgnLabels[COL_TOTAL] =
|
|
{
|
|
IDS_RESULT_COMPUTER_NAME,
|
|
IDS_RESULT_COMPUTER_LOCAL,
|
|
IDS_RESULT_COMPUTER_CONNECTION_TYPE,
|
|
IDS_RESULT_STATUS,
|
|
};
|
|
|
|
|
|
|
|
int CIISMachine::rgnWidths[COL_TOTAL] =
|
|
{
|
|
200,
|
|
50,
|
|
100,
|
|
200,
|
|
};
|
|
|
|
|
|
|
|
/* static */
|
|
void
|
|
CIISMachine::InitializeHeaders(
|
|
IN LPHEADERCTRL pHeader
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the result view headers for a machine object
|
|
|
|
Arguments:
|
|
|
|
LPHEADERCTRL pHeader : Pointer to header control
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
CIISObject::BuildResultView(pHeader, COL_TOTAL, rgnLabels, rgnWidths);
|
|
}
|
|
|
|
|
|
|
|
CIISMachine::CIISMachine(
|
|
IN LPCTSTR lpszMachineName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for machine object
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpszMachineName : Machine name
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: CIISObject(cMachineNode),
|
|
m_strMachineName(lpszMachineName),
|
|
m_fLocal(::IsServerLocal(lpszMachineName))
|
|
{
|
|
ASSERT(lpszMachineName != NULL);
|
|
|
|
VERIFY(m_strDisplayName.LoadString(IDS_NODENAME));
|
|
|
|
//
|
|
// Initialize static members
|
|
//
|
|
if (CIISMachine::s_strLocalMachine.IsEmpty())
|
|
{
|
|
//
|
|
// AFX_MANAGE_STATE required for resource load
|
|
//
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
TRACEEOLID("Initializing static strings");
|
|
VERIFY(CIISMachine::s_strLocalMachine.LoadString(IDS_LOCAL_COMPUTER));
|
|
}
|
|
// Determine if current user is administrator
|
|
CMetaKey key(lpszMachineName);
|
|
if (key.Succeeded())
|
|
{
|
|
DWORD err = DetermineIfAdministrator(
|
|
&key,
|
|
_T("w3svc"),
|
|
0,
|
|
&m_fIsAdministrator);
|
|
if (err != ERROR_SUCCESS)
|
|
{
|
|
err = DetermineIfAdministrator(
|
|
&key,
|
|
_T("msftpsvc"),
|
|
0,
|
|
&m_fIsAdministrator);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
BOOL
|
|
CIISMachine::IsConfigurable() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine if the machine is configurable, that is at least
|
|
one property page handler was registered for it.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if the machine is configurable, FALSE otherwise
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Codework: do a metabase check here
|
|
//
|
|
return m_fIsAdministrator;
|
|
//return CIISMachine::s_poblISMMachinePages != NULL
|
|
// && CIISMachine::s_poblISMMachinePages->GetCount() > 0;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISMachine::Configure(
|
|
IN CWnd * pParent OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Configure the machine object. In order for the machine object to
|
|
be configurable, at least one property page add-on function must
|
|
be defined.
|
|
|
|
Arguments:
|
|
|
|
CWnd * pParent : Parent window handle
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
|
|
|
|
CError err;
|
|
|
|
/*
|
|
try
|
|
{
|
|
CString strTitle, str;
|
|
|
|
VERIFY(str.LoadString(IDS_MACHINE_PROPERTIES));
|
|
|
|
strTitle.Format(str, GetMachineName());
|
|
|
|
PROPSHEETHEADER psh;
|
|
psh.dwSize = sizeof(psh);
|
|
psh.dwFlags = PSH_DEFAULT | PSH_HASHELP;
|
|
psh.hwndParent = pParent ? pParent->m_hWnd : NULL;
|
|
psh.hInstance = NULL;
|
|
psh.pszIcon = NULL;
|
|
psh.pszCaption = (LPTSTR)(LPCTSTR)strTitle;
|
|
psh.nStartPage = 0;
|
|
psh.nPages = 0;
|
|
psh.phpage = NULL;
|
|
psh.pfnCallback = NULL;
|
|
|
|
ASSERT(CIISMachine::s_poblISMMachinePages != NULL);
|
|
CObListIter obli(*CIISMachine::s_poblISMMachinePages);
|
|
CISMMachinePageExt * pipe;
|
|
while (pipe = (CISMMachinePageExt *)obli.Next())
|
|
{
|
|
DWORD errDLL = pipe->Load();
|
|
if (errDLL == ERROR_SUCCESS)
|
|
{
|
|
errDLL = pipe->AddPages(GetMachineName(), &psh);
|
|
}
|
|
|
|
if (errDLL != ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Unable to load, display error message
|
|
// with the name of the DLL. This does not
|
|
// necessarily pose problems for the rest
|
|
// of the property sheet.
|
|
//
|
|
::DisplayFmtMessage(
|
|
IDS_ERR_NO_LOAD,
|
|
MB_OK,
|
|
0,
|
|
(LPCTSTR)*pipe,
|
|
::GetSystemMessage(errDLL)
|
|
);
|
|
}
|
|
}
|
|
|
|
if (psh.nPages > 0)
|
|
{
|
|
//
|
|
// Display the property sheet
|
|
//
|
|
PropertySheet(&psh);
|
|
|
|
//
|
|
// Now clean up the property sheet structure
|
|
//
|
|
// FreeMem(psh.phpage);
|
|
}
|
|
|
|
//
|
|
// Unload the extentions
|
|
//
|
|
obli.Reset();
|
|
while (pipe = (CISMMachinePageExt *)obli.Next())
|
|
{
|
|
if ((HINSTANCE)*pipe)
|
|
{
|
|
VERIFY(pipe->UnLoad());
|
|
}
|
|
}
|
|
}
|
|
catch(CMemoryException * e)
|
|
{
|
|
err = ERROR_NOT_ENOUGH_MEMORY;
|
|
e->Delete();
|
|
}
|
|
*/
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISMachine::ConfigureMMC(
|
|
IN LPPROPERTYSHEETCALLBACK lpProvider,
|
|
IN LPARAM param,
|
|
IN LONG_PTR handle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Configure using MMC property sheets
|
|
|
|
Arguments:
|
|
|
|
LPPROPERTYSHEETCALLBACK lpProvider : Prop sheet provider
|
|
LPARAM param : Prop parameter
|
|
LONG_PTR handle : console handle
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
HINSTANCE hOld = AfxGetResourceHandle();
|
|
AfxSetResourceHandle(GetModuleHandle(COMPROP_DLL_NAME));
|
|
|
|
HINSTANCE hInstance = AfxGetInstanceHandle();
|
|
CIISMachinePage * ppgMachine = new CIISMachinePage(
|
|
GetMachineName(),
|
|
hInstance
|
|
);
|
|
|
|
AfxSetResourceHandle(hOld);
|
|
|
|
if (ppgMachine)
|
|
{
|
|
CError err(ppgMachine->QueryResult());
|
|
|
|
if (err.Failed())
|
|
{
|
|
if (err == REGDB_E_CLASSNOTREG)
|
|
{
|
|
//
|
|
// There isn't a metabase -- fail gracefully
|
|
//
|
|
::AfxMessageBox(IDS_NO_MACHINE_PROPS);
|
|
err.Reset();
|
|
}
|
|
|
|
delete ppgMachine;
|
|
|
|
return err;
|
|
}
|
|
|
|
//
|
|
// Patch MFC property page class.
|
|
//
|
|
ppgMachine->m_psp.dwFlags |= PSP_HASHELP;
|
|
MMCPropPageCallback(&ppgMachine->m_psp);
|
|
|
|
HPROPSHEETPAGE hPage = CreatePropertySheetPage(
|
|
(LPCPROPSHEETPAGE)&ppgMachine->m_psp
|
|
);
|
|
|
|
if (hPage != NULL)
|
|
{
|
|
lpProvider->AddPage(hPage);
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISMachine::AddMenuItems(
|
|
IN LPCONTEXTMENUCALLBACK lpContextMenuCallback
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add menu items for machine object
|
|
|
|
Arguments:
|
|
|
|
LPCONTEXTMENUCALLBACK pContextMenuCallback : Context menu items callback
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
CIISObject::AddMenuItems(lpContextMenuCallback);
|
|
|
|
//
|
|
// Add metabase backup/restore
|
|
//
|
|
lpContextMenuCallback->AddItem(&menuSep);
|
|
AddMenuItemByCommand(lpContextMenuCallback, IDM_METABACKREST);
|
|
|
|
//
|
|
// Add 'IIS shutdown' command
|
|
//
|
|
// ISSUE: Should there be a capability bit?
|
|
//
|
|
AddMenuItemByCommand(lpContextMenuCallback, IDM_SHUTDOWN);
|
|
|
|
if (!CanAddInstance(GetMachineName()))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Add one 'new instance' for every service that supports
|
|
// instances
|
|
//
|
|
ASSERT(CIISMachine::s_poblNewInstanceCmds);
|
|
|
|
POSITION pos = CIISMachine::s_poblNewInstanceCmds->GetHeadPosition();
|
|
|
|
int lCommandID = IDM_NEW_EX_INSTANCE;
|
|
HRESULT hr;
|
|
|
|
while(pos)
|
|
{
|
|
CNewInstanceCmd * pcmd =
|
|
(CNewInstanceCmd *)s_poblNewInstanceCmds->GetNext(pos);
|
|
ASSERT(pcmd != NULL);
|
|
|
|
CONTEXTMENUITEM cmi;
|
|
cmi.strName = pcmd->GetMenuCommand().GetBuffer(0);
|
|
cmi.strStatusBarText = pcmd->GetTTText().GetBuffer(0);
|
|
cmi.lCommandID = lCommandID++;
|
|
cmi.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_NEW;
|
|
cmi.fFlags = 0;
|
|
cmi.fSpecialFlags = 0;
|
|
|
|
hr = lpContextMenuCallback->AddItem(&cmi);
|
|
ASSERT(SUCCEEDED(hr));
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISMachine::AddNextTaskpadItem(
|
|
OUT MMC_TASK * pTask
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add next taskpad item
|
|
|
|
Arguments:
|
|
|
|
MMC_TASK * pTask : Task structure to fill in
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Add one 'new instance' for every service that supports
|
|
// instances
|
|
//
|
|
ASSERT(CIISMachine::s_poblNewInstanceCmds);
|
|
|
|
static POSITION pos = NULL;
|
|
static BOOL fShownBackup = FALSE;
|
|
static int lCommandID = -1;
|
|
|
|
HRESULT hr;
|
|
|
|
CString strName, strStatus, strMouseOn, strMouseOff;
|
|
long lCmdID;
|
|
|
|
//
|
|
// Metabase backup/restore
|
|
//
|
|
if (!fShownBackup)
|
|
{
|
|
//
|
|
// AFX_MANAGE_STATE required for resource load
|
|
//
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
|
|
|
|
CString strResURL;
|
|
hr = BuildResURL(strResURL);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
VERIFY(strName.LoadString(IDS_MENU_BACKUP));
|
|
VERIFY(strStatus.LoadString(IDS_MENU_TT_BACKUP));
|
|
|
|
strMouseOn = strResURL + RES_TASKPAD_BACKUP;
|
|
strMouseOff = strMouseOn;
|
|
lCmdID = IDM_METABACKREST;
|
|
|
|
++fShownBackup;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Display the new instance commands for each service that
|
|
// supports it.
|
|
//
|
|
if (lCommandID == -1)
|
|
{
|
|
//
|
|
// Initialize (use lCommandID == -1 as a flag
|
|
// to indicate we're at the beginning of the list)
|
|
//
|
|
if (CanAddInstance(GetMachineName()))
|
|
{
|
|
pos = CIISMachine::s_poblNewInstanceCmds->GetHeadPosition();
|
|
lCommandID = IDM_NEW_EX_INSTANCE;
|
|
}
|
|
else
|
|
{
|
|
return S_FALSE;
|
|
}
|
|
}
|
|
|
|
if (pos == NULL)
|
|
{
|
|
//
|
|
// No more items remain in the list.
|
|
//
|
|
lCommandID = -1;
|
|
fShownBackup = FALSE;
|
|
|
|
return S_FALSE;
|
|
}
|
|
|
|
CNewInstanceCmd * pcmd =
|
|
(CNewInstanceCmd *)s_poblNewInstanceCmds->GetNext(pos);
|
|
ASSERT(pcmd != NULL);
|
|
|
|
CString strResURL;
|
|
hr = BuildResURL(strResURL, pcmd->QueryInstanceHandle());
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// AFX_MANAGE_STATE required for resource load
|
|
//
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState());
|
|
VERIFY(strStatus.LoadString(IDS_MENU_DS_NEWINSTANCE));
|
|
|
|
strMouseOn = strResURL + RES_TASKPAD_NEWSITE;
|
|
strMouseOff = strMouseOn;
|
|
strName = pcmd->GetTTText();
|
|
|
|
lCmdID = lCommandID++;
|
|
}
|
|
|
|
return AddTaskpadItemByInfo(
|
|
pTask,
|
|
lCmdID,
|
|
strMouseOn,
|
|
strMouseOff,
|
|
strName,
|
|
strStatus
|
|
);
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
LPCTSTR
|
|
CIISMachine::GetDisplayText(
|
|
OUT CString & strText
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the display text of this object
|
|
|
|
Arguments:
|
|
|
|
CString & strText : String in which display text is to be returned
|
|
|
|
Return Value:
|
|
|
|
Pointer to the string
|
|
|
|
--*/
|
|
{
|
|
try
|
|
{
|
|
if (m_fIsExtension)
|
|
{
|
|
//
|
|
// This is an extension
|
|
//
|
|
strText = m_strDisplayName;
|
|
}
|
|
else
|
|
{
|
|
if (IsLocalMachine())
|
|
{
|
|
ASSERT(!s_strLocalMachine.IsEmpty());
|
|
strText.Format(s_strLocalMachine, m_strMachineName);
|
|
}
|
|
else
|
|
{
|
|
strText = m_strMachineName;
|
|
}
|
|
}
|
|
}
|
|
catch(CMemoryException * e)
|
|
{
|
|
TRACEEOLID("!!!exception in GetDisplayText");
|
|
e->ReportError();
|
|
e->Delete();
|
|
}
|
|
|
|
return strText;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
int
|
|
CIISMachine::QueryBitmapIndex() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine the bitmap index that represents the current item
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Index into the bitmap strip
|
|
|
|
--*/
|
|
{
|
|
if (m_fIsExtension)
|
|
{
|
|
return BMP_INETMGR;
|
|
}
|
|
|
|
return IsLocalMachine() ? BMP_LOCAL_COMPUTER : BMP_COMPUTER;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
void
|
|
CIISMachine::GetResultDisplayInfo(
|
|
IN int nCol,
|
|
OUT CString & str,
|
|
OUT int & nImage
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get result data item display information.
|
|
|
|
Arguments:
|
|
|
|
int nCol : Column number
|
|
CString & str : String data
|
|
int & nImage : Image number
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// Need different icon for extension...
|
|
//
|
|
nImage = QueryBitmapIndex();
|
|
|
|
str.Empty();
|
|
|
|
switch(nCol)
|
|
{
|
|
case COL_NAME: // Computer Name
|
|
GetDisplayText(str);
|
|
break;
|
|
|
|
case COL_LOCAL: // Local
|
|
if (m_fIsExtension)
|
|
{
|
|
//
|
|
// If we're an extension, display the type
|
|
//
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
VERIFY(str.LoadString(IDS_SNAPIN_TYPE));
|
|
}
|
|
else
|
|
{
|
|
//
|
|
//
|
|
str = IsLocalMachine()
|
|
? CIISObject::s_strYes
|
|
: CIISObject::s_strNo;
|
|
}
|
|
break;
|
|
|
|
case COL_TYPE: // Connection Type
|
|
if (m_fIsExtension)
|
|
{
|
|
//
|
|
// If we're an extension snap-in we should display
|
|
// the snap-in description in this column
|
|
//
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
VERIFY(str.LoadString(IDS_SNAPIN_DESC));
|
|
}
|
|
else
|
|
{
|
|
str = IS_NETBIOS_NAME(GetMachineName())
|
|
? CIISObject::s_strNetBIOS
|
|
: CIISObject::s_strTCPIP;
|
|
}
|
|
break;
|
|
|
|
case COL_STATUS:
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// No other columns current supported
|
|
//
|
|
ASSERT(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
int
|
|
CIISMachine::Compare(
|
|
IN int nCol,
|
|
IN CIISObject * pObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compare against another CIISObject
|
|
|
|
Arguments:
|
|
|
|
int nCol : Compare on this column
|
|
CIISObject * pObject : Compare against this object
|
|
|
|
Routine Description:
|
|
|
|
Comparison Return Value
|
|
|
|
--*/
|
|
{
|
|
ASSERT(QueryGUID() == pObject->QueryGUID());
|
|
if (QueryGUID() != pObject->QueryGUID())
|
|
{
|
|
//
|
|
// Invalid comparison
|
|
//
|
|
return +1;
|
|
}
|
|
|
|
CString str1, str2;
|
|
int n1, n2;
|
|
|
|
CIISMachine * pMachine = (CIISMachine *)pObject;
|
|
|
|
switch(nCol)
|
|
{
|
|
case COL_NAME: // Computer Name
|
|
GetDisplayText(str1);
|
|
pMachine->GetDisplayText(str2);
|
|
return str1.CompareNoCase(str2);
|
|
|
|
case COL_LOCAL: // Local
|
|
n1 = IsLocalMachine();
|
|
n2 = pMachine->IsLocalMachine();
|
|
return n1 - n2;
|
|
|
|
case COL_TYPE: // Connection Type
|
|
n1 = IS_NETBIOS_NAME(GetMachineName());
|
|
n2 = IS_NETBIOS_NAME(pMachine->GetMachineName());
|
|
return n1 - n2;
|
|
|
|
case COL_STATUS:
|
|
return 0;
|
|
|
|
default:
|
|
//
|
|
// No other columns current supported
|
|
//
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CIISMachine::InitializeChildHeaders(
|
|
IN LPHEADERCTRL pHeader
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Build result view underneath
|
|
|
|
Arguments:
|
|
|
|
LPHEADERCTRL pHeader : Header control
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CIISInstance::InitializeHeaders(pHeader);
|
|
}
|
|
|
|
|
|
|
|
//
|
|
// Static Initialization
|
|
//
|
|
CString CIISInstance::s_strFormatState;
|
|
BOOL CIISInstance::s_fServerView = TRUE;
|
|
BOOL CIISInstance::s_fAppendState = TRUE;
|
|
|
|
|
|
|
|
//
|
|
// Instance Result View definition
|
|
//
|
|
int CIISInstance::rgnLabels[COL_TOTAL] =
|
|
{
|
|
IDS_RESULT_SERVICE_DESCRIPTION,
|
|
IDS_RESULT_SERVICE_STATE,
|
|
IDS_RESULT_SERVICE_DOMAIN_NAME,
|
|
IDS_RESULT_SERVICE_IP_ADDRESS,
|
|
IDS_RESULT_SERVICE_TCP_PORT,
|
|
IDS_RESULT_STATUS,
|
|
};
|
|
|
|
|
|
|
|
int CIISInstance::rgnWidths[COL_TOTAL] =
|
|
{
|
|
180,
|
|
70,
|
|
120,
|
|
105,
|
|
40,
|
|
200,
|
|
};
|
|
|
|
|
|
|
|
/* static */
|
|
void
|
|
CIISInstance::InitializeStrings()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Static method to initialize the strings.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
if (!IsInitialized())
|
|
{
|
|
TRACEEOLID("Initializing static strings");
|
|
|
|
//
|
|
// iisui.dll is an extension DLL, and this should
|
|
// load automatically, but doesn't -- why?
|
|
//
|
|
HINSTANCE hOld = AfxGetResourceHandle();
|
|
AfxSetResourceHandle(GetModuleHandle(COMPROP_DLL_NAME));
|
|
VERIFY(CIISInstance::s_strFormatState.LoadString(IDS_INSTANCE_STATE_FMT));
|
|
AfxSetResourceHandle(hOld);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
void
|
|
CIISInstance::InitializeHeaders(
|
|
IN LPHEADERCTRL pHeader
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the result headers
|
|
|
|
Arguments:
|
|
|
|
LPHEADERCTRL pHeader : Header control
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CIISObject::BuildResultView(pHeader, COL_TOTAL, rgnLabels, rgnWidths);
|
|
}
|
|
|
|
|
|
|
|
CIISInstance::CIISInstance(
|
|
IN CServerInfo * pServerInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for instance object without instance ID code. In other
|
|
words, this is a wrapper for a plain-old down-level CServerInfo
|
|
object.
|
|
|
|
Arguments:
|
|
|
|
CServerInfo * pServerInfo : Controlling server info
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: CIISObject(cInstanceNode),
|
|
m_fDownLevel(TRUE),
|
|
m_fDeletable(FALSE),
|
|
m_fClusterEnabled(FALSE),
|
|
m_fLocalMachine(FALSE),
|
|
m_hrError(S_OK),
|
|
m_sPort(0),
|
|
m_dwIPAddress(0L),
|
|
m_strHostHeaderName(),
|
|
m_strComment(),
|
|
m_strMachine(),
|
|
m_pServerInfo(pServerInfo)
|
|
{
|
|
if (!IsInitialized())
|
|
{
|
|
CIISInstance::InitializeStrings();
|
|
}
|
|
|
|
//
|
|
// Some service types do not support instances, but
|
|
// still understand the instance codes
|
|
//
|
|
ASSERT(m_pServerInfo != NULL);
|
|
m_dwID = 0L;
|
|
m_strMachine = m_pServerInfo->QueryServerName();
|
|
m_fLocalMachine = ::IsServerLocal(m_strMachine);
|
|
}
|
|
|
|
|
|
|
|
CIISInstance::CIISInstance(
|
|
IN ISMINSTANCEINFO * pii,
|
|
IN CServerInfo * pServerInfo
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize IIS Instance from ISMINSTANCEINFO structure
|
|
|
|
Arguments:
|
|
|
|
ISMINSTANCEINFO * pii : Pointer to ISMINSTANCEINFO structure
|
|
CServerInfo * pServerInfo : Server info structure
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: CIISObject(cInstanceNode),
|
|
m_fDownLevel(FALSE),
|
|
m_fLocalMachine(),
|
|
m_strMachine(),
|
|
m_pServerInfo(pServerInfo)
|
|
{
|
|
InitializeFromStruct(pii);
|
|
|
|
if (!IsInitialized())
|
|
{
|
|
CIISInstance::InitializeStrings();
|
|
}
|
|
|
|
ASSERT(m_pServerInfo != NULL);
|
|
m_strMachine = m_pServerInfo->QueryServerName();
|
|
m_fLocalMachine = ::IsServerLocal(m_strMachine);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CIISInstance::InitializeFromStruct(
|
|
IN ISMINSTANCEINFO * pii
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize data from ISMINSTANCEINFO structure
|
|
|
|
Arguments:
|
|
|
|
ISMINSTANCEINFO * pii : Pointer to ISMINSTANCEINFO structure
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(pii);
|
|
|
|
m_dwID = pii->dwID;
|
|
m_strHostHeaderName = pii->szServerName;
|
|
m_strComment = pii->szComment;
|
|
m_nState = pii->nState;
|
|
m_dwIPAddress = pii->dwIPAddress;
|
|
m_sPort = pii->sPort;
|
|
m_fDeletable = pii->fDeletable;
|
|
m_fClusterEnabled = pii->fClusterEnabled;
|
|
|
|
CError err(pii->dwError);
|
|
m_hrError = err;
|
|
|
|
m_strRedirPath = pii->szRedirPath;
|
|
m_fChildOnlyRedir = pii->fChildOnlyRedir;
|
|
|
|
//
|
|
// Home directory path should exist unless someone's been
|
|
// messing up the metabase.
|
|
//
|
|
m_strPhysicalPath = pii->szPath;
|
|
|
|
m_strNodeName.Format(_T("%s%c%s%c%ld%c%s"),
|
|
g_cszMachine,
|
|
g_chSep,
|
|
GetServerInfo()->GetMetabaseName(),
|
|
g_chSep,
|
|
m_dwID,
|
|
g_chSep,
|
|
g_cszRoot
|
|
);
|
|
|
|
TRACEEOLID(m_strNodeName);
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
BOOL
|
|
CIISInstance::IsRunning() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Check to see if this instance is currently running.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE if currently running
|
|
|
|
Notes:
|
|
|
|
On a down-level (v3) version, this applies to the service, not
|
|
the instance
|
|
|
|
--*/
|
|
{
|
|
if (IsDownLevel())
|
|
{
|
|
ASSERT(m_pServerInfo != NULL);
|
|
return m_pServerInfo->IsServiceRunning();
|
|
}
|
|
|
|
return m_nState == INetServiceRunning;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
BOOL
|
|
CIISInstance::IsStopped() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Check to see if this instance is currently stopped.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE if currently stopped
|
|
|
|
Notes:
|
|
|
|
On a down-level (v3) version, this applies to the server, not
|
|
the instance
|
|
|
|
--*/
|
|
{
|
|
if (IsDownLevel())
|
|
{
|
|
ASSERT(m_pServerInfo != NULL);
|
|
return m_pServerInfo->IsServiceStopped();
|
|
}
|
|
|
|
return m_nState == INetServiceStopped;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
BOOL
|
|
CIISInstance::IsPaused() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Check to see if this instance is currently paused.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE if currently paused
|
|
|
|
Notes:
|
|
|
|
On a down-level (v3) version, this applies to the server, not
|
|
the instance
|
|
|
|
--*/
|
|
{
|
|
if (IsDownLevel())
|
|
{
|
|
ASSERT(m_pServerInfo != NULL);
|
|
|
|
return m_pServerInfo->IsServicePaused();
|
|
}
|
|
|
|
return m_nState == INetServicePaused;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
int
|
|
CIISInstance::QueryState() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the ISM state of the instance
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
The ISM (INet*) state of the instance
|
|
|
|
Notes:
|
|
|
|
On a down-level (v3) version, this applies to the server, not
|
|
the instance
|
|
|
|
--*/
|
|
{
|
|
if (IsDownLevel())
|
|
{
|
|
return m_pServerInfo->QueryServiceState();
|
|
}
|
|
|
|
return m_nState;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISInstance::ChangeState(
|
|
IN int nNewState
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Change the ISM state of the instance
|
|
|
|
Arguments:
|
|
|
|
int nNewState
|
|
|
|
Return Value:
|
|
|
|
Error Return Code
|
|
|
|
Notes:
|
|
|
|
On a down-level (v3) version, this applies to the server, not
|
|
the instance
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pServerInfo != NULL);
|
|
|
|
int * pnCurrentState;
|
|
DWORD dwID;
|
|
|
|
if (IsClusterEnabled())
|
|
{
|
|
//
|
|
// Not supported on cluster server
|
|
//
|
|
return ERROR_BAD_DEV_TYPE;
|
|
}
|
|
|
|
if (IsDownLevel())
|
|
{
|
|
dwID = 0;
|
|
pnCurrentState = m_pServerInfo->GetServiceStatePtr();
|
|
}
|
|
else
|
|
{
|
|
dwID = QueryID();
|
|
pnCurrentState = &m_nState;
|
|
}
|
|
|
|
return m_pServerInfo->ChangeServiceState(nNewState, pnCurrentState, dwID);
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISInstance::Configure(
|
|
IN CWnd * pParent OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Configure the instance object
|
|
|
|
Arguments:
|
|
|
|
CWnd * pParent : Optional parent window
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
|
|
ASSERT(m_pServerInfo != NULL);
|
|
|
|
//
|
|
// Set help file
|
|
//
|
|
theApp.SetHelpPath(m_pServerInfo);
|
|
|
|
CError err(m_pServerInfo->ConfigureServer(pParent->m_hWnd, QueryID()));
|
|
|
|
//
|
|
// Restore help path
|
|
//
|
|
theApp.SetHelpPath();
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
RefreshData();
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISInstance::RefreshData()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Refresh internal data
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
CError err;
|
|
|
|
if (!IsDownLevel())
|
|
{
|
|
ISMINSTANCEINFO ii;
|
|
err = m_pServerInfo->QueryInstanceInfo(
|
|
WITHOUT_INHERITANCE,
|
|
&ii,
|
|
QueryID()
|
|
);
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
InitializeFromStruct(&ii);
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISInstance::ConfigureMMC(
|
|
IN LPPROPERTYSHEETCALLBACK lpProvider,
|
|
IN LPARAM param,
|
|
IN LONG_PTR handle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Configure using MMC property sheets
|
|
|
|
Arguments:
|
|
|
|
LPPROPERTYSHEETCALLBACK lpProvider : Prop sheet provider
|
|
LPARAM param : Prop parameter
|
|
LONG_PTR handle : console handle
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pServerInfo != NULL);
|
|
|
|
return m_pServerInfo->MMMCConfigureServer(
|
|
lpProvider,
|
|
param,
|
|
handle,
|
|
QueryID()
|
|
);
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
LPCTSTR
|
|
CIISInstance::GetStateText() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return text representation of current state (running/paused/stopped).
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Pointer to the string
|
|
|
|
--*/
|
|
{
|
|
ASSERT(!CIISObject::s_strRunning.IsEmpty());
|
|
|
|
return IsStopped()
|
|
? CIISObject::s_strStopped
|
|
: IsPaused()
|
|
? CIISObject::s_strPaused
|
|
: IsRunning()
|
|
? CIISObject::s_strRunning
|
|
: CIISObject::s_strUnknown;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
LPCTSTR
|
|
CIISInstance::GetDisplayText(
|
|
OUT CString & strText
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the display text of this object
|
|
|
|
Arguments:
|
|
|
|
CString & strText : String in which display text is to be returned
|
|
|
|
Return Value:
|
|
|
|
Pointer to the string
|
|
|
|
--*/
|
|
{
|
|
try
|
|
{
|
|
if (m_fDownLevel)
|
|
{
|
|
ASSERT(m_pServerInfo != NULL);
|
|
|
|
if (CIISInstance::s_fServerView)
|
|
{
|
|
strText = m_pServerInfo->GetServiceName();
|
|
}
|
|
else
|
|
{
|
|
strText = m_pServerInfo->QueryServerName();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// GetDisplayText loads from resources
|
|
//
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
|
|
|
|
CIPAddress ia(m_dwIPAddress);
|
|
|
|
CInstanceProps::GetDisplayText(
|
|
strText,
|
|
GetComment(),
|
|
GetHostHeaderName(),
|
|
m_pServerInfo->GetServiceName(),
|
|
ia,
|
|
m_sPort,
|
|
m_dwID
|
|
);
|
|
}
|
|
|
|
//
|
|
// Append state (paused, etc) if not running
|
|
//
|
|
if (CIISInstance::s_fAppendState && !IsRunning())
|
|
{
|
|
CString strState;
|
|
strState.Format(CIISInstance::s_strFormatState, GetStateText());
|
|
strText += strState;
|
|
}
|
|
}
|
|
catch(CMemoryException * e)
|
|
{
|
|
TRACEEOLID("!!!exception in GetDisplayText");
|
|
e->ReportError();
|
|
e->Delete();
|
|
}
|
|
|
|
return strText;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISInstance::AddChildNode(
|
|
IN OUT CIISChildNode *& pChild
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add child node under current node
|
|
|
|
Arguments:
|
|
|
|
CIISChildNode *& pChild : Child node to be added
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
pChild = NULL;
|
|
|
|
ISMCHILDINFO ii;
|
|
CString strParent(g_cszRoot);
|
|
CError err(GetServerInfo()->AddChild(
|
|
&ii,
|
|
sizeof(ii),
|
|
QueryID(),
|
|
strParent
|
|
));
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
pChild = new CIISChildNode(&ii, this);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
BOOL
|
|
CIISInstance::ChildrenExpanded() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Determine if the child items of this node have already been expanded
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
TRUE if the items do not need expansion, FALSE if they do.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pServerInfo != NULL);
|
|
|
|
if (m_pServerInfo->SupportsChildren())
|
|
{
|
|
//
|
|
// Note: timestamps ignored, because MMC will never send me another
|
|
// expansion notification, so we can't refresh after a certain time.
|
|
//
|
|
return m_tmChildrenExpanded > 0L;
|
|
}
|
|
|
|
//
|
|
// Can't drill down any lower than this.
|
|
//
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISInstance::ExpandChildren(
|
|
IN HSCOPEITEM pParent
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Mark the children as being expanded.
|
|
|
|
Arguments:
|
|
|
|
HSCOPEITEM pParent : Parent scope item
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pServerInfo != NULL);
|
|
|
|
if (m_pServerInfo->SupportsChildren() )
|
|
{
|
|
//
|
|
// Mark the last epxansion time as being now.
|
|
//
|
|
time(&m_tmChildrenExpanded);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//
|
|
// Can't drill down any lower than this.
|
|
//
|
|
return CError::HResult(ERROR_INVALID_FUNCTION);
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
int
|
|
CIISInstance::QueryBitmapIndex() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the bitmap index of the object. This varies with the state
|
|
of the view
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Bitmap index
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pServerInfo != NULL);
|
|
|
|
/*
|
|
return OK()
|
|
? m_pServerInfo->QueryBitmapIndex()
|
|
: BMP_ERROR;
|
|
*/
|
|
|
|
return m_pServerInfo->QueryBitmapIndex();
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISInstance::AddMenuItems(
|
|
IN LPCONTEXTMENUCALLBACK pContextMenuCallback
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add context menu items for the instance
|
|
|
|
Arguments:
|
|
|
|
LPCONTEXTMENUCALLBACK pContextMenuCallback : Context menu callback
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
CIISObject::AddMenuItems(pContextMenuCallback);
|
|
|
|
if (SupportsInstances() && CanAddInstance(GetMachineName()))
|
|
{
|
|
AddMenuItemByCommand(pContextMenuCallback, IDM_NEW_INSTANCE);
|
|
}
|
|
|
|
if (SupportsChildren())
|
|
{
|
|
AddMenuItemByCommand(pContextMenuCallback, IDM_NEW_VROOT);
|
|
}
|
|
|
|
if (SupportsSecurityWizard())
|
|
{
|
|
AddMenuItemByCommand(pContextMenuCallback, IDM_TASK_SECURITY_WIZARD);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISInstance::AddNextTaskpadItem(
|
|
OUT MMC_TASK * pTask
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add next taskpad item
|
|
|
|
Arguments:
|
|
|
|
MMC_TASK * pTask : Task structure to fill in
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// CODEWORK: Ideally I would call the base class here, but that's
|
|
// a pain with enumeration
|
|
//
|
|
static int iIndex = 0;
|
|
|
|
//
|
|
// Fall through on the switch until an applicable command is found
|
|
//
|
|
UINT nID;
|
|
switch(iIndex)
|
|
{
|
|
case 0:
|
|
if (SupportsInstances() && CanAddInstance(GetMachineName()))
|
|
{
|
|
nID = IDM_NEW_INSTANCE;
|
|
break;
|
|
}
|
|
|
|
++iIndex;
|
|
|
|
//
|
|
// Fall through
|
|
//
|
|
|
|
case 1:
|
|
if (SupportsChildren())
|
|
{
|
|
nID = IDM_NEW_VROOT;
|
|
break;
|
|
}
|
|
|
|
++iIndex;
|
|
|
|
//
|
|
// Fall through
|
|
//
|
|
|
|
case 2:
|
|
if (SupportsSecurityWizard())
|
|
{
|
|
nID = IDM_TASK_SECURITY_WIZARD;
|
|
break;
|
|
}
|
|
|
|
++iIndex;
|
|
|
|
//
|
|
// Fall through
|
|
//
|
|
|
|
default:
|
|
//
|
|
// All done
|
|
//
|
|
iIndex = 0;
|
|
return S_FALSE;
|
|
}
|
|
|
|
|
|
HRESULT hr = AddTaskpadItemByCommand(
|
|
nID,
|
|
pTask,
|
|
GetServerInfo()->QueryInstanceHandle()
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
++iIndex;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISInstance::Delete()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Handle deletion of the current item
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pServerInfo != NULL);
|
|
|
|
return m_pServerInfo->DeleteInstance(m_dwID);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISInstance::SecurityWizard()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Launch the security wizard on this instance
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pServerInfo != NULL);
|
|
ASSERT(m_pServerInfo->SupportsSecurityWizard());
|
|
|
|
CString strPhysicalPath;
|
|
BuildPhysicalPath(strPhysicalPath);
|
|
|
|
return m_pServerInfo->ISMSecurityWizard(m_dwID, _T(""), g_cszRoot);
|
|
}
|
|
|
|
|
|
|
|
int
|
|
CIISInstance::Compare(
|
|
IN int nCol,
|
|
IN CIISObject * pObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compare against another CIISObject
|
|
|
|
Arguments:
|
|
|
|
int nCol : Compare on this column
|
|
CIISObject * pObject : Compare against this object
|
|
|
|
Routine Description:
|
|
|
|
Comparison Return Value
|
|
|
|
--*/
|
|
{
|
|
ASSERT(QueryGUID() == pObject->QueryGUID());
|
|
|
|
if (QueryGUID() != pObject->QueryGUID())
|
|
{
|
|
//
|
|
// Invalid comparison
|
|
//
|
|
return +1;
|
|
}
|
|
|
|
CString str1, str2;
|
|
CIPAddress ia1, ia2;
|
|
DWORD dw1, dw2;
|
|
int n1, n2;
|
|
CIISInstance * pInstance = (CIISInstance *)pObject;
|
|
|
|
switch(nCol)
|
|
{
|
|
case COL_DESCRIPTION: // Description
|
|
GetDisplayText(str1);
|
|
pInstance->GetDisplayText(str2);
|
|
return str1.CompareNoCase(str2);
|
|
|
|
case COL_STATE: // State
|
|
str1 = GetStateText();
|
|
str2 = pInstance->GetStateText();
|
|
return str1.CompareNoCase(str2);
|
|
|
|
case COL_DOMAIN_NAME: // Domain name
|
|
str1 = GetHostHeaderName();
|
|
str2 = pInstance->GetHostHeaderName();
|
|
return str1.CompareNoCase(str2);
|
|
|
|
case COL_IP_ADDRESS: // IP Address
|
|
ia1 = GetIPAddress();
|
|
ia2 = pInstance->GetIPAddress();
|
|
return ia1.CompareItem(ia2);
|
|
|
|
case COL_TCP_PORT: // Port
|
|
n1 = GetPort();
|
|
n2 = pInstance->GetPort();
|
|
return n1 - n2;
|
|
|
|
case COL_STATUS:
|
|
dw1 = m_hrError;
|
|
dw2 = pInstance->QueryError();
|
|
return dw1 > dw2 ? +1 : dw1==dw2 ? 0 : -1;
|
|
|
|
default:
|
|
//
|
|
// No other columns current supported
|
|
//
|
|
ASSERT(FALSE);
|
|
return 0;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
void
|
|
CIISInstance::GetResultDisplayInfo(
|
|
IN int nCol,
|
|
OUT CString & str,
|
|
OUT int & nImage
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get result data item display information.
|
|
|
|
Arguments:
|
|
|
|
int nCol : Column number
|
|
CString & str : String data
|
|
int & nImage : Image number
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
nImage = QueryBitmapIndex();
|
|
CIPAddress ia;
|
|
|
|
str.Empty();
|
|
switch(nCol)
|
|
{
|
|
case COL_DESCRIPTION: // Description
|
|
GetDisplayText(str);
|
|
break;
|
|
|
|
case COL_STATE: // State
|
|
if (OK())
|
|
{
|
|
str = GetStateText();
|
|
}
|
|
break;
|
|
|
|
case COL_DOMAIN_NAME: // Domain name
|
|
if (OK())
|
|
{
|
|
str = GetHostHeaderName();
|
|
}
|
|
break;
|
|
|
|
case COL_IP_ADDRESS: // IP Address
|
|
if (!IsDownLevel() && OK())
|
|
{
|
|
ia = GetIPAddress();
|
|
if (ia.IsZeroValue())
|
|
{
|
|
str = CIISObject::s_strDefaultIP;
|
|
}
|
|
else
|
|
{
|
|
ia.QueryIPAddress(str);
|
|
}
|
|
}
|
|
break;
|
|
|
|
case COL_TCP_PORT: // Port
|
|
if (OK())
|
|
{
|
|
if (GetPort())
|
|
{
|
|
str.Format(_T("%u"), GetPort());
|
|
}
|
|
else
|
|
{
|
|
str.Empty();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case COL_STATUS:
|
|
if (!OK())
|
|
{
|
|
CError::TextFromHRESULT(QueryErrorCode(), str);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// No other columns current supported
|
|
//
|
|
ASSERT(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
LPCTSTR
|
|
CIISInstance::GetComment() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the comment string
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Pointer to the comment string
|
|
|
|
--*/
|
|
{
|
|
if (IsDownLevel())
|
|
{
|
|
ASSERT(m_pServerInfo != NULL);
|
|
return m_pServerInfo->GetServerComment();
|
|
}
|
|
|
|
return m_strComment;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISInstance::ShellBrowsePath(
|
|
IN LPCTSTR lpszPath
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Generate an URL from the instance and path information given, and
|
|
attempt to resolve that URL
|
|
|
|
Arguments:
|
|
|
|
IN LPCTSTR lpszPath : Path
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
CString strDir;
|
|
CString strOwner;
|
|
|
|
ASSERT(IsBrowsable());
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Try to build an URL. Use in order of priority:
|
|
//
|
|
// Domain name:port/root
|
|
// ip address:port/root
|
|
// computer name:port/root
|
|
//
|
|
if (HasHostHeaderName())
|
|
{
|
|
strOwner = GetHostHeaderName();
|
|
}
|
|
else if (HasIPAddress())
|
|
{
|
|
CIPAddress ia(GetIPAddress());
|
|
ia.QueryIPAddress(strOwner);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Use the computer name (w/o backslashes)
|
|
//
|
|
if (IsLocalMachine())
|
|
{
|
|
strOwner = _T("localhost");
|
|
}
|
|
else
|
|
{
|
|
LPCTSTR lpOwner = GetMachineName();
|
|
strOwner = PURE_COMPUTER_NAME(lpOwner);
|
|
}
|
|
}
|
|
|
|
int nPort = GetPort();
|
|
|
|
LPCTSTR lpProtocol = GetServerInfo()->GetProtocol();
|
|
|
|
if (lpProtocol == NULL)
|
|
{
|
|
return CError::HResult(ERROR_INVALID_PARAMETER);
|
|
}
|
|
|
|
//
|
|
// "Root" is a metabase concept which has no place in the
|
|
// path.
|
|
//
|
|
TRACEEOLID(lpszPath);
|
|
lpszPath += lstrlen(g_cszRoot);
|
|
strDir.Format(
|
|
_T("%s://%s:%u%s"),
|
|
lpProtocol,
|
|
(LPCTSTR)strOwner,
|
|
nPort,
|
|
lpszPath
|
|
);
|
|
|
|
TRACEEOLID("Attempting to open URL: " << strDir);
|
|
|
|
CError err;
|
|
{
|
|
//
|
|
// AFX_MANAGE_STATE required for wait cursor
|
|
//
|
|
AFX_MANAGE_STATE(AfxGetStaticModuleState());
|
|
CWaitCursor wait;
|
|
|
|
if (::ShellExecute(
|
|
NULL,
|
|
_T("open"),
|
|
strDir,
|
|
NULL,
|
|
_T(""),
|
|
SW_SHOW
|
|
) <= (HINSTANCE)32)
|
|
{
|
|
err.GetLastWinError();
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CIISInstance::InitializeChildHeaders(
|
|
IN LPHEADERCTRL pHeader
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the result headers
|
|
|
|
Arguments:
|
|
|
|
LPHEADERCTRL pHeader : Header control
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CIISChildNode::InitializeHeaders(pHeader);
|
|
}
|
|
|
|
|
|
|
|
int CIISChildNode::rgnLabels[COL_TOTAL] =
|
|
{
|
|
IDS_RESULT_VDIR_ALIAS,
|
|
IDS_RESULT_PATH,
|
|
IDS_RESULT_STATUS,
|
|
};
|
|
|
|
|
|
|
|
int CIISChildNode::rgnWidths[COL_TOTAL] =
|
|
{
|
|
120,
|
|
300,
|
|
200,
|
|
};
|
|
|
|
|
|
|
|
/* static */
|
|
void
|
|
CIISChildNode::InitializeHeaders(
|
|
IN LPHEADERCTRL pHeader
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the result headers
|
|
|
|
Arguments:
|
|
|
|
LPHEADERCTRL pHeader : Header control
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CIISObject::BuildResultView(pHeader, COL_TOTAL, rgnLabels, rgnWidths);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CIISChildNode::InitializeChildHeaders(
|
|
LPHEADERCTRL pHeader
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the result headers for a child item
|
|
|
|
Arguments:
|
|
|
|
LPHEADERCTRL pHeader : Header control
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
InitializeHeaders(pHeader);
|
|
}
|
|
|
|
|
|
|
|
|
|
CIISChildNode::CIISChildNode(
|
|
IN ISMCHILDINFO * pii,
|
|
IN CIISInstance * pOwner
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize child node object from ISMCHILDINFO structure information
|
|
|
|
Arguments:
|
|
|
|
ISMCHILDINFO * pii : Pointer to ISMCHILDINFO structure
|
|
CIISInstance * pOwner : Owner instance
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: CIISObject(cChildNode),
|
|
m_pOwner(pOwner)
|
|
{
|
|
InitializeFromStruct(pii);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CIISChildNode::InitializeFromStruct(
|
|
IN ISMCHILDINFO * pii
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize data from ISMCHILDINFO structure
|
|
|
|
Arguments:
|
|
|
|
ISMCHILDINFO * pii : Pointer to ISMCHILDINFO structure
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
ASSERT(pii);
|
|
ASSERT(pii->szAlias);
|
|
ASSERT(pii->szPath);
|
|
|
|
try
|
|
{
|
|
m_fEnabledApplication = pii->fEnabledApplication;
|
|
CError err(pii->dwError);
|
|
m_hrError = err;
|
|
m_strRedirPath = pii->szRedirPath;
|
|
m_fChildOnlyRedir = pii->fChildOnlyRedir;
|
|
|
|
//
|
|
// Initialize base objects
|
|
//
|
|
m_strNodeName = pii->szAlias;
|
|
m_strPhysicalPath = pii->szPath;
|
|
}
|
|
catch(CMemoryException * e)
|
|
{
|
|
e->ReportError();
|
|
e->Delete();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
int
|
|
CIISChildNode::QueryBitmapIndex() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the bitmap index of the object. This varies with the state
|
|
of the view
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Bitmap index
|
|
|
|
--*/
|
|
{
|
|
if (!OK())
|
|
{
|
|
return BMP_ERROR;
|
|
}
|
|
|
|
if (IsEnabledApplication())
|
|
{
|
|
return BMP_APPLICATION;
|
|
}
|
|
|
|
if (IsVirtualDirectory())
|
|
{
|
|
ASSERT(m_pOwner != NULL);
|
|
|
|
return m_pOwner->GetServerInfo()->QueryChildBitmapIndex();
|
|
}
|
|
|
|
return BMP_DIRECTORY;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
LPCTSTR
|
|
CIISChildNode::GetDisplayText(
|
|
OUT CString & strText
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the display text of this object
|
|
|
|
Arguments:
|
|
|
|
CString & strText : String in which display text is to be returned
|
|
|
|
Return Value:
|
|
|
|
Pointer to the string
|
|
|
|
--*/
|
|
{
|
|
strText = m_strNodeName;
|
|
|
|
return strText;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISChildNode::AddMenuItems(
|
|
IN LPCONTEXTMENUCALLBACK pContextMenuCallback
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add context menu items relevant to this node
|
|
|
|
Arguments:
|
|
|
|
LPCONTEXTMENUCALLBACK pContextMenuCallback
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
CIISObject::AddMenuItems(pContextMenuCallback);
|
|
|
|
AddMenuItemByCommand(pContextMenuCallback, IDM_NEW_VROOT);
|
|
|
|
if (SupportsSecurityWizard())
|
|
{
|
|
AddMenuItemByCommand(pContextMenuCallback, IDM_TASK_SECURITY_WIZARD);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISChildNode::AddNextTaskpadItem(
|
|
OUT MMC_TASK * pTask
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add next taskpad item
|
|
|
|
Arguments:
|
|
|
|
MMC_TASK * pTask : Task structure to fill in
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// CODEWORK: Ideally I would call the base class here, but that's
|
|
// a pain with enumeration
|
|
//
|
|
static int iIndex = 0;
|
|
|
|
//
|
|
// Fall through on the switch until an applicable command is found
|
|
//
|
|
UINT nID;
|
|
switch(iIndex)
|
|
{
|
|
case 0:
|
|
nID = IDM_NEW_VROOT;
|
|
break;
|
|
|
|
case 1:
|
|
if (SupportsSecurityWizard())
|
|
{
|
|
nID = IDM_TASK_SECURITY_WIZARD;
|
|
break;
|
|
}
|
|
|
|
++iIndex;
|
|
|
|
//
|
|
// Fall through
|
|
//
|
|
|
|
default:
|
|
//
|
|
// All done
|
|
//
|
|
iIndex = 0;
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT hr = AddTaskpadItemByCommand(
|
|
nID,
|
|
pTask,
|
|
GetServerInfo()->QueryInstanceHandle()
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
++iIndex;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
CIISChildNode::Compare(
|
|
IN int nCol,
|
|
IN CIISObject * pObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compare against another CIISObject
|
|
|
|
Arguments:
|
|
|
|
int nCol : Compare on this column
|
|
CIISObject * pObject : Compare against this object
|
|
|
|
Routine Description:
|
|
|
|
Comparison Return Value
|
|
|
|
--*/
|
|
{
|
|
ASSERT(QueryGUID() == pObject->QueryGUID());
|
|
if (QueryGUID() != pObject->QueryGUID())
|
|
{
|
|
//
|
|
// Invalid comparison
|
|
//
|
|
return +1;
|
|
}
|
|
|
|
DWORD dw1, dw2;
|
|
|
|
CIISChildNode * pChild = (CIISChildNode *)pObject;
|
|
|
|
switch(nCol)
|
|
{
|
|
case COL_ALIAS: // Alias
|
|
return m_strNodeName.CompareNoCase(pChild->m_strNodeName);
|
|
|
|
case COL_PATH: // Path
|
|
dw1 = IsRedirected();
|
|
dw2 = pChild->IsRedirected();
|
|
if (dw1 != dw2)
|
|
{
|
|
return dw1 > dw2 ? +1 : -1;
|
|
}
|
|
|
|
return GetPhysicalPath().CompareNoCase(pChild->GetPhysicalPath());
|
|
|
|
case COL_STATUS:
|
|
dw1 = m_hrError;
|
|
dw2 = pChild->QueryError();
|
|
return dw1 > dw2 ? +1 : dw1==dw2 ? 0 : -1;
|
|
|
|
default:
|
|
//
|
|
// No other columns current supported
|
|
//
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
void
|
|
CIISChildNode::GetResultDisplayInfo(
|
|
IN int nCol,
|
|
OUT CString & str,
|
|
OUT int & nImage
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get result data item display information.
|
|
|
|
Arguments:
|
|
|
|
int nCol : Column number
|
|
CString & str : String data
|
|
int & nImage : Image number
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
nImage = QueryBitmapIndex();
|
|
|
|
str.Empty();
|
|
switch(nCol)
|
|
{
|
|
case COL_ALIAS: // Alias
|
|
str = m_strNodeName;
|
|
break;
|
|
|
|
case COL_PATH: // Path
|
|
if (IsRedirected())
|
|
{
|
|
str.Format(s_strRedirect, m_strRedirPath);
|
|
}
|
|
else
|
|
{
|
|
str = m_strPhysicalPath;
|
|
}
|
|
break;
|
|
|
|
case COL_STATUS:
|
|
if (!OK())
|
|
{
|
|
CError::TextFromHRESULT(QueryErrorCode(), str);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// No other columns current supported
|
|
//
|
|
ASSERT(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISChildNode::Configure(
|
|
IN CWnd * pParent
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Configure the child node object
|
|
|
|
Arguments:
|
|
|
|
CWnd * pParent : Parent window handle
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
|
|
{
|
|
ASSERT(m_pOwner != NULL);
|
|
|
|
//
|
|
// Ok, build a metabase path on the fly now by getting
|
|
// the nodes of the parents up until the owning instance.
|
|
//
|
|
CString strParent;
|
|
BuildParentPath(strParent, FALSE);
|
|
|
|
//
|
|
// Set help file
|
|
//
|
|
theApp.SetHelpPath(GetServerInfo());
|
|
|
|
CError err(GetServerInfo()->ConfigureChild(
|
|
pParent->m_hWnd,
|
|
FILE_ATTRIBUTE_VIRTUAL_DIRECTORY,
|
|
m_pOwner->QueryID(),
|
|
strParent,
|
|
m_strNodeName
|
|
));
|
|
|
|
//
|
|
// Set help file
|
|
//
|
|
theApp.SetHelpPath();
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
RefreshData();
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISChildNode::RefreshData()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Refresh internal data
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
ISMCHILDINFO ii;
|
|
|
|
CString strParent;
|
|
BuildParentPath(strParent, FALSE);
|
|
|
|
CError err(GetServerInfo()->QueryChildInfo(
|
|
WITH_INHERITANCE,
|
|
&ii,
|
|
m_pOwner->QueryID(),
|
|
strParent,
|
|
m_strNodeName
|
|
));
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
InitializeFromStruct(&ii);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISChildNode::ConfigureMMC(
|
|
IN LPPROPERTYSHEETCALLBACK lpProvider,
|
|
IN LPARAM param,
|
|
IN LONG_PTR handle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Configure using MMC property sheets
|
|
|
|
Arguments:
|
|
|
|
LPPROPERTYSHEETCALLBACK lpProvider : Prop sheet provider
|
|
LPARAM param : Prop parameter
|
|
LONG_PTR handle : console handle
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pOwner != NULL);
|
|
|
|
CString strParent;
|
|
BuildParentPath(strParent, FALSE);
|
|
|
|
return GetServerInfo()->MMCConfigureChild(lpProvider,
|
|
param,
|
|
handle,
|
|
FILE_ATTRIBUTE_VIRTUAL_DIRECTORY,
|
|
m_pOwner->QueryID(),
|
|
strParent,
|
|
m_strNodeName
|
|
);
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISChildNode::AddChildNode(
|
|
CIISChildNode *& pChild
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add child node under current node
|
|
|
|
Arguments:
|
|
|
|
CIISChildNode *& pChild : Child node to be added
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pOwner != NULL);
|
|
ISMCHILDINFO ii;
|
|
|
|
CString strPath;
|
|
BuildFullPath(strPath, FALSE);
|
|
|
|
pChild = NULL;
|
|
CError err(GetServerInfo()->AddChild(
|
|
&ii,
|
|
sizeof(ii),
|
|
m_pOwner->QueryID(),
|
|
strPath
|
|
));
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
pChild = new CIISChildNode(&ii, m_pOwner);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISChildNode::Rename(
|
|
IN LPCTSTR lpszNewName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Rename the current node
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpszNewName : New name
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pOwner != NULL);
|
|
|
|
CString strPath;
|
|
BuildParentPath(strPath, FALSE);
|
|
|
|
CError err(GetServerInfo()->RenameChild(
|
|
m_pOwner->QueryID(),
|
|
strPath,
|
|
m_strNodeName,
|
|
lpszNewName
|
|
));
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
m_strNodeName = lpszNewName;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISChildNode::Delete()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete the current node
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pOwner != NULL);
|
|
|
|
CString strParent;
|
|
BuildParentPath(strParent, FALSE);
|
|
|
|
return GetServerInfo()->DeleteChild(
|
|
m_pOwner->QueryID(),
|
|
strParent,
|
|
m_strNodeName
|
|
);
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISChildNode::SecurityWizard()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Launch the security wizard on this child node
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pOwner != NULL);
|
|
|
|
CString strParent;
|
|
BuildParentPath(strParent, FALSE);
|
|
|
|
return GetServerInfo()->ISMSecurityWizard(
|
|
m_pOwner->QueryID(),
|
|
strParent,
|
|
m_strNodeName
|
|
);
|
|
}
|
|
|
|
|
|
|
|
int CIISFileNode::rgnLabels[COL_TOTAL] =
|
|
{
|
|
IDS_RESULT_VDIR_ALIAS,
|
|
IDS_RESULT_PATH,
|
|
IDS_RESULT_STATUS,
|
|
};
|
|
|
|
|
|
|
|
int CIISFileNode::rgnWidths[COL_TOTAL] =
|
|
{
|
|
120,
|
|
300,
|
|
200,
|
|
};
|
|
|
|
|
|
|
|
/* static */
|
|
void
|
|
CIISFileNode::InitializeHeaders(
|
|
IN LPHEADERCTRL pHeader
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the result headers
|
|
|
|
Arguments:
|
|
|
|
LPHEADERCTRL pHeader : Header control
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
CIISObject::BuildResultView(pHeader, COL_TOTAL, rgnLabels, rgnWidths);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
CIISFileNode::InitializeChildHeaders(
|
|
IN LPHEADERCTRL pHeader
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize the result headers
|
|
|
|
Arguments:
|
|
|
|
LPHEADERCTRL pHeader : Header control
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
InitializeHeaders(pHeader);
|
|
}
|
|
|
|
|
|
|
|
CIISFileNode::CIISFileNode(
|
|
IN LPCTSTR lpszAlias,
|
|
IN DWORD dwAttributes,
|
|
IN CIISInstance * pOwner,
|
|
IN LPCTSTR lpszRedirect,
|
|
IN BOOL fDir OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Constructor for file object
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpszPath : Path name
|
|
DWORD dwAttributes : Attributes
|
|
CIISInstance * pOwner : Owner instance
|
|
BOOL fDir : TRUE for directory, FALSE for file
|
|
|
|
Return Value:
|
|
|
|
N/A
|
|
|
|
--*/
|
|
: CIISObject(cFileNode, lpszAlias),
|
|
m_dwAttributes(dwAttributes),
|
|
m_pOwner(pOwner),
|
|
m_fEnabledApplication(FALSE),
|
|
m_fDir(fDir)
|
|
{
|
|
m_strRedirPath = lpszRedirect;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
int
|
|
CIISFileNode::QueryBitmapIndex() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the bitmap index of the object. This varies with the state
|
|
of the view
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Bitmap index
|
|
|
|
--*/
|
|
{
|
|
if (IsEnabledApplication())
|
|
{
|
|
return BMP_APPLICATION;
|
|
}
|
|
|
|
return IsDirectory() ? BMP_DIRECTORY : BMP_FILE;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
LPCTSTR
|
|
CIISFileNode::GetDisplayText(
|
|
OUT CString & strText
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the display text of this object
|
|
|
|
Arguments:
|
|
|
|
CString & strText : String in which display text is to be returned
|
|
|
|
Return Value:
|
|
|
|
Pointer to the string
|
|
|
|
--*/
|
|
{
|
|
strText = m_strNodeName;
|
|
|
|
return strText;
|
|
}
|
|
|
|
|
|
|
|
int
|
|
CIISFileNode::Compare(
|
|
IN int nCol,
|
|
IN CIISObject * pObject
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Compare against another CIISObject
|
|
|
|
Arguments:
|
|
|
|
int nCol : Compare on this column
|
|
CIISObject * pObject : Compare against this object
|
|
|
|
Routine Description:
|
|
|
|
Comparison Return Value
|
|
|
|
--*/
|
|
{
|
|
ASSERT(QueryGUID() == pObject->QueryGUID());
|
|
if (QueryGUID() != pObject->QueryGUID())
|
|
{
|
|
//
|
|
// Invalid comparison
|
|
//
|
|
return +1;
|
|
}
|
|
|
|
return m_strNodeName.CompareNoCase(pObject->GetNodeName());
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
void
|
|
CIISFileNode::GetResultDisplayInfo(
|
|
IN int nCol,
|
|
OUT CString & str,
|
|
OUT int & nImage
|
|
) const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get result data item display information.
|
|
|
|
Arguments:
|
|
|
|
int nCol : Column number
|
|
CString & str : String data
|
|
int & nImage : Image number
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
nImage = QueryBitmapIndex();
|
|
str.Empty();
|
|
|
|
switch(nCol)
|
|
{
|
|
case COL_ALIAS:
|
|
str = m_strNodeName;
|
|
break;
|
|
|
|
case COL_PATH: // Path
|
|
if (IsRedirected())
|
|
{
|
|
str.Format(s_strRedirect, m_strRedirPath);
|
|
}
|
|
else
|
|
{
|
|
str.Empty();
|
|
}
|
|
break;
|
|
|
|
case COL_STATUS:
|
|
if (!OK())
|
|
{
|
|
CError::TextFromHRESULT(QueryErrorCode(), str);
|
|
}
|
|
break;
|
|
|
|
default:
|
|
//
|
|
// No other columns current supported
|
|
//
|
|
ASSERT(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
CIISObject *
|
|
CIISFileNode::GetParentObject() const
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get the parent object (in the scope view) of this object.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Pointer to the parent object, or NULL if not found
|
|
|
|
--*/
|
|
{
|
|
if (!IsDir())
|
|
{
|
|
//
|
|
// File nodes exist on the result side only, and the scope
|
|
// item handle they have points to their _parent_ not to
|
|
// themselves.
|
|
//
|
|
SCOPEDATAITEM sdi;
|
|
sdi.mask = SDI_PARAM;
|
|
sdi.ID = GetScopeHandle();
|
|
HRESULT hr = GetScopeView()->GetItem(&sdi);
|
|
|
|
return (CIISObject *)sdi.lParam;
|
|
}
|
|
|
|
//
|
|
// Directory nodes work like anyone else
|
|
//
|
|
return CIISObject::GetParentObject();
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISFileNode::Configure(
|
|
IN CWnd * pParent
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Configure using private property sheet provider
|
|
|
|
Arguments:
|
|
|
|
CWnd * pParent : Parent window
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pOwner != NULL);
|
|
|
|
CString strParent;
|
|
BuildParentPath(strParent, FALSE);
|
|
|
|
//
|
|
// Set help file
|
|
//
|
|
theApp.SetHelpPath(GetServerInfo());
|
|
|
|
CError err(GetServerInfo()->ConfigureChild(
|
|
pParent->m_hWnd,
|
|
m_dwAttributes,
|
|
m_pOwner->QueryID(),
|
|
strParent,
|
|
m_strNodeName
|
|
));
|
|
|
|
//
|
|
// Restore help file
|
|
//
|
|
theApp.SetHelpPath();
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
RefreshData();
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISFileNode::Rename(
|
|
IN LPCTSTR lpszNewName
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Rename the current node
|
|
|
|
Arguments:
|
|
|
|
LPCTSTR lpszNewName : New name
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pOwner != NULL);
|
|
ASSERT(lpszNewName != NULL);
|
|
|
|
// We need to check if this new name is OK
|
|
LPTSTR p = (LPTSTR)lpszNewName;
|
|
if (*p == 0)
|
|
{
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
|
|
::AfxMessageBox(IDS_ERR_EMPTY_FILENAME, MB_ICONSTOP);
|
|
return ERROR_BAD_PATHNAME;
|
|
}
|
|
|
|
while (*p != 0)
|
|
{
|
|
UINT type = PathGetCharType(*p);
|
|
if (type & (GCT_LFNCHAR | GCT_SHORTCHAR))
|
|
{
|
|
p++;
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
|
|
::AfxMessageBox(IDS_ERR_INVALID_CHAR, MB_ICONSTOP);
|
|
return ERROR_BAD_PATHNAME;
|
|
}
|
|
}
|
|
|
|
CString strPath, strPhysicalPath, strDir, strNewName;
|
|
BuildPhysicalPath(strPhysicalPath);
|
|
BuildParentPath(strPath, FALSE);
|
|
|
|
//
|
|
// First make sure there's no conflicting name in the metabase
|
|
//
|
|
ISMCHILDINFO ii;
|
|
ii.dwSize = sizeof(ii);
|
|
|
|
CError err(GetServerInfo()->QueryChildInfo(
|
|
WITHOUT_INHERITANCE,
|
|
&ii,
|
|
m_pOwner->QueryID(),
|
|
strPath,
|
|
lpszNewName
|
|
));
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
//
|
|
// That won't do -- the name already exists in the metabase
|
|
// We handle the UI for this message
|
|
//
|
|
AFX_MANAGE_STATE(::AfxGetStaticModuleState() );
|
|
::AfxMessageBox(IDS_ERR_DUP_METABASE);
|
|
|
|
return ERROR_ALREADY_EXISTS;
|
|
}
|
|
|
|
if (IsLocalMachine() || ::IsUNCName(strPhysicalPath))
|
|
{
|
|
//
|
|
// Local directory, or already a unc path
|
|
//
|
|
strDir = strPhysicalPath;
|
|
}
|
|
else
|
|
{
|
|
::MakeUNCPath(strDir, GetMachineName(), strPhysicalPath);
|
|
}
|
|
|
|
//
|
|
// Have to make a fully qualified destination name
|
|
//
|
|
strNewName = strDir;
|
|
int iPos = strNewName.ReverseFind(_T('\\'));
|
|
|
|
if (iPos <= 0)
|
|
{
|
|
//
|
|
// Bogus file name path!
|
|
//
|
|
ASSERT(FALSE);
|
|
return ERROR_INVALID_PARAMETER;
|
|
}
|
|
|
|
strNewName.ReleaseBuffer(iPos + 1);
|
|
strNewName += lpszNewName;
|
|
|
|
TRACEEOLID("Attempting to rename file/directory: " << strDir);
|
|
TRACEEOLID("To " << strNewName);
|
|
|
|
//
|
|
// Convert to double-null terminated list of null terminated
|
|
// strings
|
|
//
|
|
TCHAR szPath[MAX_PATH + 1];
|
|
TCHAR szDest[MAX_PATH + 1];
|
|
ZeroMemory(szPath, sizeof(szPath));
|
|
ZeroMemory(szDest, sizeof(szDest));
|
|
_tcscpy(szPath, strDir);
|
|
_tcscpy(szDest, strNewName);
|
|
|
|
CWnd * pWnd = AfxGetMainWnd();
|
|
|
|
//
|
|
// Attempt to delete using shell APIs
|
|
//
|
|
SHFILEOPSTRUCT sos;
|
|
ZeroMemory(&sos, sizeof(sos));
|
|
sos.hwnd = pWnd ? pWnd->m_hWnd : NULL;
|
|
sos.wFunc = FO_RENAME;
|
|
sos.pFrom = szPath;
|
|
sos.pTo = szDest;
|
|
sos.fFlags = FOF_ALLOWUNDO;
|
|
|
|
int iReturn = SHFileOperation(&sos);
|
|
|
|
if (sos.fAnyOperationsAborted)
|
|
{
|
|
err = ERROR_CANCELLED;
|
|
}
|
|
|
|
err = iReturn;
|
|
|
|
if (!iReturn && !sos.fAnyOperationsAborted)
|
|
{
|
|
//
|
|
// Successful rename -- now handle the metabase
|
|
// rename as well.
|
|
//
|
|
err = GetServerInfo()->RenameChild(
|
|
m_pOwner->QueryID(),
|
|
strPath,
|
|
m_strNodeName,
|
|
lpszNewName
|
|
);
|
|
|
|
if (err.Win32Error() == ERROR_PATH_NOT_FOUND
|
|
|| err.Win32Error() == ERROR_FILE_NOT_FOUND
|
|
)
|
|
{
|
|
//
|
|
// Harmless
|
|
//
|
|
err.Reset();
|
|
}
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
m_strNodeName = lpszNewName;
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISFileNode::Delete()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Delete the current node
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
CString strPhysicalPath, strDir;
|
|
BuildPhysicalPath(strPhysicalPath);
|
|
|
|
if (IsLocalMachine() || ::IsUNCName(strPhysicalPath))
|
|
{
|
|
//
|
|
// Local directory, or already a unc path
|
|
//
|
|
strDir = strPhysicalPath;
|
|
}
|
|
else
|
|
{
|
|
::MakeUNCPath(strDir, GetMachineName(), strPhysicalPath);
|
|
}
|
|
|
|
TRACEEOLID("Attempting to remove file/directory: " << strDir);
|
|
|
|
//
|
|
// Convert to double-null terminated list of null terminated
|
|
// strings
|
|
//
|
|
TCHAR szPath[MAX_PATH + 1];
|
|
ZeroMemory(szPath, sizeof(szPath));
|
|
_tcscpy(szPath, strDir);
|
|
|
|
CWnd * pWnd = AfxGetMainWnd();
|
|
|
|
//
|
|
// Attempt to delete using shell APIs
|
|
//
|
|
SHFILEOPSTRUCT sos;
|
|
ZeroMemory(&sos, sizeof(sos));
|
|
sos.hwnd = pWnd ? pWnd->m_hWnd : NULL;
|
|
sos.wFunc = FO_DELETE;
|
|
sos.pFrom = szPath;
|
|
sos.fFlags = FOF_ALLOWUNDO;
|
|
|
|
CError err;
|
|
// Use assignment to avoid conversion and wrong constructor call
|
|
err = ::SHFileOperation(&sos);
|
|
|
|
if (sos.fAnyOperationsAborted)
|
|
{
|
|
err = ERROR_CANCELLED;
|
|
}
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
//
|
|
// Successful deletion -- now delete metabase properties
|
|
ASSERT(m_pOwner != NULL);
|
|
|
|
CString strParent;
|
|
BuildParentPath(strParent, FALSE);
|
|
|
|
err = GetServerInfo()->DeleteChild(
|
|
m_pOwner->QueryID(),
|
|
strParent,
|
|
m_strNodeName
|
|
);
|
|
|
|
if (err.Win32Error() == ERROR_PATH_NOT_FOUND
|
|
|| err.Win32Error() == ERROR_FILE_NOT_FOUND
|
|
)
|
|
{
|
|
//
|
|
// Harmless
|
|
//
|
|
err.Reset();
|
|
}
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISFileNode::FetchMetaInformation(
|
|
IN CString & strParent,
|
|
OUT BOOL * pfVirtualDirectory OPTIONAL
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Fetch metabase information on this item.
|
|
|
|
Arguments:
|
|
|
|
CString & strParent : Parent path
|
|
BOOL * pfVirtualDirectory : Directory
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
ISMCHILDINFO ii;
|
|
|
|
CError err(GetServerInfo()->QueryChildInfo(
|
|
WITH_INHERITANCE,
|
|
&ii,
|
|
m_pOwner->QueryID(),
|
|
strParent,
|
|
m_strNodeName
|
|
));
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
//
|
|
// Exists in the metabase
|
|
//
|
|
m_fEnabledApplication = ii.fEnabledApplication;
|
|
m_strRedirPath = ii.szRedirPath;
|
|
m_fChildOnlyRedir = ii.fChildOnlyRedir;
|
|
|
|
if (pfVirtualDirectory)
|
|
{
|
|
*pfVirtualDirectory = !ii.fInheritedPath;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// No entry for this in the metabase
|
|
//
|
|
m_fEnabledApplication = FALSE;
|
|
m_strRedirPath.Empty();
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISFileNode::RefreshData()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Refresh internal data
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
CString strParent;
|
|
BuildParentPath(strParent, FALSE);
|
|
|
|
return FetchMetaInformation(strParent);
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISFileNode::ConfigureMMC(
|
|
IN LPPROPERTYSHEETCALLBACK lpProvider,
|
|
IN LPARAM param,
|
|
IN LONG_PTR handle
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Configure using MMC property sheet provider
|
|
|
|
Arguments:
|
|
|
|
LPPROPERTYSHEETCALLBACK lpProvider : Property sheet provider
|
|
LPARAM param : Parameter
|
|
LONG_PTR handle : Handle
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pOwner != NULL);
|
|
|
|
CString strParent;
|
|
BuildParentPath(strParent, FALSE);
|
|
|
|
return GetServerInfo()->MMCConfigureChild(
|
|
lpProvider,
|
|
param,
|
|
handle,
|
|
m_dwAttributes,
|
|
m_pOwner->QueryID(),
|
|
strParent,
|
|
m_strNodeName
|
|
);
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISFileNode::AddMenuItems(
|
|
IN LPCONTEXTMENUCALLBACK pContextMenuCallback
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add context menu items relevant to this node
|
|
|
|
Arguments:
|
|
|
|
LPCONTEXTMENUCALLBACK pContextMenuCallback
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
CIISObject::AddMenuItems(pContextMenuCallback);
|
|
|
|
if (IsDir())
|
|
{
|
|
AddMenuItemByCommand(pContextMenuCallback, IDM_NEW_VROOT);
|
|
}
|
|
|
|
if (SupportsSecurityWizard())
|
|
{
|
|
AddMenuItemByCommand(pContextMenuCallback, IDM_TASK_SECURITY_WIZARD);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISFileNode::AddNextTaskpadItem(
|
|
OUT MMC_TASK * pTask
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add next taskpad item
|
|
|
|
Arguments:
|
|
|
|
MMC_TASK * pTask : Task structure to fill in
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
//
|
|
// CODEWORK: Ideally I would call be the base class here, but that's
|
|
// a pain with enumeration
|
|
//
|
|
static int iIndex = 0;
|
|
|
|
//
|
|
// Fall through on the switch until an applicable command is found
|
|
//
|
|
UINT nID;
|
|
|
|
switch(iIndex)
|
|
{
|
|
case 0:
|
|
if (IsDir())
|
|
{
|
|
nID = IDM_NEW_VROOT;
|
|
break;
|
|
}
|
|
|
|
default:
|
|
//
|
|
// All done
|
|
//
|
|
iIndex = 0;
|
|
return S_FALSE;
|
|
}
|
|
|
|
HRESULT hr = AddTaskpadItemByCommand(
|
|
nID,
|
|
pTask,
|
|
GetServerInfo()->QueryInstanceHandle()
|
|
);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
++iIndex;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
/* virtual */
|
|
HRESULT
|
|
CIISFileNode::AddChildNode(
|
|
IN CIISChildNode *& pChild
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Add child node under current node
|
|
|
|
Arguments:
|
|
|
|
CIISChildNode *& pChild : Child node to be added
|
|
|
|
Return Value:
|
|
|
|
Error return code.
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pOwner != NULL);
|
|
ISMCHILDINFO ii;
|
|
|
|
CString strPath;
|
|
BuildFullPath(strPath, FALSE);
|
|
|
|
pChild = NULL;
|
|
CError err(GetServerInfo()->AddChild(
|
|
&ii,
|
|
sizeof(ii),
|
|
m_pOwner->QueryID(),
|
|
strPath
|
|
));
|
|
|
|
if (err.Succeeded())
|
|
{
|
|
pChild = new CIISChildNode(
|
|
&ii,
|
|
m_pOwner
|
|
);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
|
|
|
|
HRESULT
|
|
CIISFileNode::SecurityWizard()
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Launch the security wizard on this file node
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
Error return code
|
|
|
|
--*/
|
|
{
|
|
ASSERT(m_pOwner != NULL);
|
|
ASSERT(SupportsSecurityWizard());
|
|
|
|
CString strParent;
|
|
BuildParentPath(strParent, FALSE);
|
|
|
|
return GetServerInfo()->ISMSecurityWizard(
|
|
m_pOwner->QueryID(),
|
|
strParent,
|
|
m_strNodeName
|
|
);
|
|
}
|