|
|
/*======================================================================================//
| Process Control //
| //
|Copyright (c) 1998 Sequent Computer Systems, Incorporated. All rights reserved. //
| //
|File Name: RootFolder.cpp //
| //
|Description: Class implemention for the root node //
| //
|Created: Paul Skoglund 07-1998 //
| //
|Rev History: //
| //
|=======================================================================================*/
#include "StdAfx.h"
#include "BaseNode.h"
#include "ProcConLibMsg.h"
#include "RootPages.h"
#include "Container.h"
using std::list<CBaseNode *>;
const GUID CRootFolder::m_GUID = {0xff9baf5f,0x064e,0x11d2,{0x80, 0x14,0x00,0x10,0x4b,0x9a,0x31,0x06} }; const TCHAR *const CRootFolder::m_szGUID = _T("{ff9baf5f-064e-11d2-8014-00104b9a3106}");
///////////////////////////////////////////////////////////////////////////
// CRootFolder
const CONTEXTMENUITEMBYID CRootFolder::TaskMenuItems[] = { { IDS_ROOT_CONNECT, ID_ROOT_CONNECT, ID_ROOT_CONNECT, CCM_INSERTIONPOINTID_PRIMARY_TOP }, { 0, 0, 0, 0 }, };
CRootFolder::CRootFolder() : CBaseNode(ROOT_NODE), m_ID(0), m_ParentID(0), m_NodeList(0), m_bUseLocalComputer(TRUE), m_bDirty(FALSE), m_hPC(0), m_PCLastError(0), m_ipConsole2(NULL) { LoadStringHelper(m_name, IDS_ROOT_FOLDER); m_longname = m_name;
//LoadStringHelper(m_TypeDescriptionStr, IDS_TYPE_DESCRIPTION);
LoadStringHelper(m_DescriptionStr, IDS_DESCRIPTION);
memset(m_Computer, 0, sizeof(m_Computer)); }
CRootFolder::~CRootFolder() { ATLTRACE( _T("~CRootFolder <%s>\n"), GetNodeName() );
FreeNodes(); if (m_hPC) VERIFY( PCClose(m_hPC) );
ATLTRACE( _T("~CRootFolder end\n")); }
void CRootFolder::FreeNodes() { ATLTRACE( _T("CRootFolder::FreeNodes()\n")); for (list<CBaseNode *>::iterator i = m_NodeList.begin(); i != m_NodeList.end(); ++i) { (*i)->Release(); //delete *i;
} m_NodeList.clear(); }
const PCid CRootFolder::GetPCid() { ASSERT(!GetParentNode());
/*
if ( // retry code now in the ProcConLib/service
m_PCLastError == ERROR_NO_DATA || m_PCLastError == ERROR_BROKEN_PIPE || m_PCLastError == ERROR_BAD_PIPE || m_PCLastError == ERROR_PIPE_NOT_CONNECTED || m_PCLastError == ERROR_NETNAME_DELETED ) { m_PCLastError = 0; if (m_hPC) VERIFY( PCClose(m_hPC)); m_hPC = 0; } */
if (m_hPC) return m_hPC;
ATLTRACE(_T("Opening %s.\n"), GetComputerDisplayName());
m_hPC = PCOpen(m_bUseLocalComputer ? NULL : GetComputerName(), NULL, COM_BUFFER_SIZE);
if (!m_hPC) { m_PCLastError = PCGetLastError(m_hPC); ATLTRACE(_T("Unable to open connection to %s, Error(0x%lX).\n"), GetComputerDisplayName(), m_PCLastError ); }
return m_hPC; }
BOOL CRootFolder::ReportPCError(PCULONG32 nLastError) { TCHAR *pMsgBuf = FormatErrorMessageIntoBuffer(nLastError);
if ( pMsgBuf ) { int ret = 0; ATLTRACE( (TCHAR *) pMsgBuf ); ATLTRACE( _T("\n") );
if (m_ipConsole2) m_ipConsole2->MessageBox(pMsgBuf, NULL, MB_OK | MB_ICONWARNING, &ret);
LocalFree(pMsgBuf);
return TRUE; }
ATLTRACE(_T("Message Problem: Error (0x%lX).\n"), nLastError );
return FALSE; }
BOOL CRootFolder::ReportPCError() { return ReportPCError( GetLastPCError() ); }
PCULONG32 CRootFolder::GetLastPCError() { if (m_hPC) // don't clear an open error...
m_PCLastError = PCGetLastError(m_hPC);
return m_PCLastError; }
void CRootFolder::GetComputerConnectionInfo(COMPUTER_CONNECTION_INFO &out) { out.bLocalComputer = m_bUseLocalComputer; memcpy(out.RemoteComputer, m_Computer, sizeof(m_Computer)); }
void CRootFolder::SetComputerName(TCHAR Computer[SNAPIN_MAX_COMPUTERNAME_LENGTH + 1]) { Config((Computer[0] == 0), Computer); }
void CRootFolder::Config(BOOL bUseLocal, TCHAR Computer[SNAPIN_MAX_COMPUTERNAME_LENGTH + 1]) { m_bDirty = TRUE;
m_bUseLocalComputer = bUseLocal; memset(m_Computer, 0, sizeof(m_Computer)); _tcsncpy(m_Computer, Computer, ARRAY_SIZE(m_Computer) - 1);
// change the node's display name...
m_longname = m_name; if (m_bUseLocalComputer) { ITEM_STR tempstr; LoadStringHelper(tempstr, IDS_LOCAL); m_machinedisplayname = tempstr; } else { m_machinedisplayname.reserve((SNAPIN_MAX_COMPUTERNAME_LENGTH + 3) * sizeof(TCHAR)); m_machinedisplayname = _T(" ("); m_machinedisplayname+= m_Computer; m_machinedisplayname+= _T(")"); } m_longname += m_machinedisplayname; // finish change node name...
if (m_hPC) VERIFY( PCClose(m_hPC)); m_hPC = 0; }
HRESULT CRootFolder::IsDirty() const { if (m_bDirty) return S_OK; return S_FALSE; }
HRESULT CRootFolder::Load(IStream *pStm) { if (!pStm) return E_POINTER;
ASSERT(sizeof(WCHAR) == sizeof(TCHAR)); // conversions need to go to single byte characters
ULONG BytesRead = 0; WCHAR sIn[SNAPIN_MAX_COMPUTERNAME_LENGTH + 1] = { 0 };
HRESULT hr = pStm->Read(sIn, sizeof(sIn), &BytesRead);
if (hr == S_OK && BytesRead) { SetComputerName(sIn); m_bDirty = FALSE; }
//pStm->Release();
return hr; }
HRESULT CRootFolder::Save(IStream *pStm, BOOL fClearDirty) { if (!pStm) return E_POINTER;
#ifndef _UNICODE
#error "need to convert output to unicode prior to writing to disk"
#endif
ULONG BytesWritten = 0;
HRESULT hr = pStm->Write(GetComputerName(), ((SNAPIN_MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR)), &BytesWritten);
if (hr == S_OK && fClearDirty) m_bDirty = FALSE; // pStm->Release();
return hr; }
HRESULT CRootFolder::GetSizeMax(ULARGE_INTEGER *pcbSize) { if (!pcbSize) return E_POINTER;
(*pcbSize).LowPart = (SNAPIN_MAX_COMPUTERNAME_LENGTH + 1) * sizeof(WCHAR); (*pcbSize).HighPart = 0;
return S_OK; }
LPCTSTR CRootFolder::GetNodeName() { if (!m_ParentID) return m_longname.c_str(); else return m_name; }
HRESULT CRootFolder::GetDisplayInfo(RESULTDATAITEM &ResultItem) { if (ResultItem.bScopeItem) { if( ResultItem.mask & RDI_STR ) { if (0 == ResultItem.nCol) ResultItem.str = const_cast<LPOLESTR>(GetNodeName()); //else if (m_ParentID && 1 == ResultItem.nCol)
// ResultItem.Str = m_TypeDescriptionStr;
else if (2 == ResultItem.nCol) ResultItem.str = m_DescriptionStr; else ResultItem.str = _T(""); } if (ResultItem.mask & RDI_IMAGE) ResultItem.nImage = sImage(); return S_OK; } return E_UNEXPECTED; }
LPCTSTR CRootFolder::GetComputerName() const { return m_Computer; }
LPCTSTR CRootFolder::GetComputerDisplayName() const { return m_machinedisplayname.c_str(); }
HRESULT CRootFolder::OnHelpCmd(IDisplayHelp *ipDisplayHelp) { if (!ipDisplayHelp) return E_UNEXPECTED; ipDisplayHelp->ShowTopic(const_cast<TCHAR *>(HELP_overview));
return S_OK; }
//IComponentData::Notify -- MNCN_EXPAND
HRESULT CRootFolder::OnParentExpand( BOOL bExpanded, // [in] TRUE is we are expanding
HSCOPEITEM hID, // [in] Points to the HSCOPEITEM
IConsoleNameSpace2 *ipConsoleNameSpace2 ) { ASSERT(ipConsoleNameSpace2);
if(!ipConsoleNameSpace2) return E_UNEXPECTED;
if (bExpanded) { ASSERT(m_NodeList.size() == 0); ASSERT(m_ID == 0);
m_ParentID = hID;
SCOPEDATAITEM sdi = {0}; sdi.mask = SDI_STR | SDI_PARAM | // lParam is valid
SDI_IMAGE | // nImage is valid
SDI_OPENIMAGE | // nOpenImage is valid
SDI_CHILDREN | // cChildren is valid
SDI_PARENT; sdi.displayname = (LPOLESTR)MMC_CALLBACK; sdi.nImage = sImage(); sdi.nOpenImage = sOpenImage(); sdi.cChildren = GetChildrenCount(); sdi.lParam = reinterpret_cast <LPARAM> (this); sdi.relativeID = hID; HRESULT hr = ipConsoleNameSpace2->InsertItem(&sdi); if (hr == S_OK) m_ID = sdi.ID; }
return S_OK; // return has no meaning to MMC
} // end OnParentExpand()
//IComponentData::Notify -- MNCN_EXPAND
HRESULT CRootFolder::OnExpand( BOOL bExpanded, // [in] TRUE is we are expanding
HSCOPEITEM hID, // [in] Points to the HSCOPEITEM
IConsoleNameSpace2 *ipConsoleNameSpace2 ) { ASSERT(ipConsoleNameSpace2);
if(!ipConsoleNameSpace2) return E_UNEXPECTED;
if (bExpanded) { ASSERT(m_NodeList.size() == 0); ASSERT(m_ID == 0 || m_ID == hID);
m_ID = hID; // Cache the root node handle
// 3/7/2001 (PAS)
// around 2410 MMC behavior changed and the proccon folder icon
// wasn't always displayed correctly...the root node image used to be
// handled differently (ISnapinAbout::GetStaticFolderImage()) but
// possibly is now handled like other scope items.
SCOPEDATAITEM sdi = {0}; sdi.mask = SDI_STR | SDI_IMAGE | // nImage is valid
SDI_OPENIMAGE; // nOpenImage is valid
sdi.ID = hID; sdi.displayname = (LPOLESTR)MMC_CALLBACK; sdi.nImage = sImage(); sdi.nOpenImage = sOpenImage();
VERIFY( S_OK == ipConsoleNameSpace2->SetItem(&sdi) ); VERIFY( S_OK == AddNodes(ipConsoleNameSpace2) ); }
return S_OK; // return has no meaning to MMC
} // end OnExpand()
HRESULT CRootFolder::AddNodes(IConsoleNameSpace2 *ipConsoleNameSpace2) { VERIFY( S_OK == AddNode(ipConsoleNameSpace2, new CRuleFolder(this) ) );
VERIFY( S_OK == AddNode(ipConsoleNameSpace2, new CProcessFolder(this) ) );
VERIFY( S_OK == AddNode(ipConsoleNameSpace2, new CJobFolder(this) ) );
return S_OK; }
HRESULT CRootFolder::AddNode(IConsoleNameSpace2 *ipConsoleNameSpace2, CBaseNode *pSubNode) { HRESULT hr = S_OK;
SCOPEDATAITEM sdi = {0};
if (!pSubNode) return E_OUTOFMEMORY; // Place folder into the scope pane
sdi.mask = SDI_STR | // Displayname is valid
SDI_PARAM | // lParam is valid
SDI_IMAGE | // nImage is valid
SDI_OPENIMAGE | // nOpenImage is valid
SDI_CHILDREN | // cChildren is valid
SDI_PARENT; sdi.displayname = (LPOLESTR)MMC_CALLBACK; sdi.nImage = pSubNode->sImage(); sdi.nOpenImage = pSubNode->sOpenImage(); //sdi.nState
sdi.cChildren = pSubNode->GetChildrenCount(); sdi.lParam = reinterpret_cast <LPARAM> (pSubNode); sdi.relativeID = m_ID; hr = ipConsoleNameSpace2->InsertItem( &sdi );
if (SUCCEEDED(hr)) { pSubNode->SetID(sdi.ID); m_NodeList.push_front( pSubNode ); } else { pSubNode->Release(); //delete pSubNode;
}
return hr; }
//IComponentData::Notify -- MNCN_REMOVE_CHILDREN
HRESULT CRootFolder::OnParentRemoveChildren(HSCOPEITEM hID) { ASSERT(hID == m_ParentID); if (hID == m_ParentID) return OnRemoveChildren(m_ID); return E_UNEXPECTED; }
HRESULT CRootFolder::OnRemoveChildren(HSCOPEITEM hID) { ASSERT(m_ID == hID);
FreeNodes(); m_ID = 0; return S_OK; }
HRESULT CRootFolder::AddMenuItems(LPCONTEXTMENUCALLBACK piCallback, long * pInsertionAllowed) { HRESULT hr = S_OK;
// 10/2/1998 PAS
// when the snapin is first loaded and the root node has not yet been expanded or
// selected than we haven't yet been able to save the ID.
// The right click context menu can be invoked when the node has no yet been expanded or
// selected, if we haven't yet gotten the ID we have no way to change the selection
// node so the menu command can't be supported yet.
if (!m_ID) return S_FALSE;
ITEM_STR name; ITEM_STR status; if( *pInsertionAllowed & CCM_INSERTIONALLOWED_TOP ) { CONTEXTMENUITEM m = { 0 }; for (const CONTEXTMENUITEMBYID *M = TaskMenuItems; M->lCommandID; M++) { m.strName = const_cast<TCHAR *>(LoadStringHelper(name, M->strNameID)); m.strStatusBarText = const_cast<TCHAR *>(LoadStringHelper(status, M->strStatusBarTextID)); m.lCommandID = M->lCommandID; m.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TOP; m.fFlags = MF_ENABLED; //m.fSpecialFlags = 0; // currently always 0, initialized to 0
if (m.lCommandID == ID_ROOT_CONNECT && m_ParentID) continue;
hr = piCallback->AddItem(&m);
if (FAILED(hr)) break; } }
if( *pInsertionAllowed & CCM_INSERTIONALLOWED_TASK ) { CONTEXTMENUITEM m = { 0 }; for (const CONTEXTMENUITEMBYID *M = TaskMenuItems; M->lCommandID; M++) { m.strName = const_cast<TCHAR *>(LoadStringHelper(name, M->strNameID)); m.strStatusBarText = const_cast<TCHAR *>(LoadStringHelper(status, M->strStatusBarTextID)); m.lCommandID = M->lCommandID; m.lInsertionPointID = CCM_INSERTIONPOINTID_PRIMARY_TASK; m.fFlags = MF_ENABLED; //m.fSpecialFlags = 0; // currently always 0, initialized to 0
if (m.lCommandID == ID_ROOT_CONNECT && m_ParentID) continue;
hr = piCallback->AddItem(&m);
if (FAILED(hr)) break; } } return hr; }
HRESULT CRootFolder::OnMenuCommand(IConsole2 *ipConsole2, long nCommandID ) { HRESULT hr = S_FALSE; switch(nCommandID) { case ID_ROOT_CONNECT: ATLTRACE(_T("CRootFolder(%s)-OnMenuCommand Connect to another computer\n"), GetNodeName()); hr = OnChangeComputerConnection(); break; default: ATLTRACE(_T("CRootFolder(%s)-OnMenuCommand Unrecognized command 0x%lX\n"), GetNodeName(), nCommandID); break; } return hr; }
HRESULT CRootFolder::OnMenuCommand(IConsole2 *ipConsole2, long nCommandID, LPARAM Cookie) { ATLTRACE(_T("CRootFolder(%s)-OnMenuCommand Unrecognized command 0x%lX\n"), GetNodeName(), nCommandID); return E_UNEXPECTED; }
HRESULT CRootFolder::OnChangeComputerConnection() { CRootWizard2 *pPage2 = new CRootWizard2(CRootWizard2::LASTANDONLY_PAGE, IDS_CONNECT_TITLE, this); if (!pPage2) return S_FALSE; PROPSHEETHEADER sheet; memset(&sheet, 0, sizeof(PROPSHEETHEADER)); sheet.dwSize = sizeof(PROPSHEETHEADER); sheet.dwFlags = PSH_WIZARD | PSH_WIZARDCONTEXTHELP; sheet.hwndParent = ::GetActiveWindow(); sheet.hInstance = _Module.GetResourceInstance(); sheet.pszIcon = 0; sheet.pszCaption = 0; sheet.nPages = 1; sheet.nStartPage = 0;
#if USE_WIZARD97_WATERMARKS
sheet.dwFlags |= PSH_WIZARD97 | PSH_WATERMARK; sheet.pszbmWatermark = MAKEINTRESOURCE(IDB_WATERMARK1); #endif
#if USE_WIZARD97_HEADERS
sheet.dwFlags |= PSH_WIZARD97 | PSH_HEADER; sheet.pszbmHeader = MAKEINTRESOURCE(IDB_HEADER1); #endif
HPROPSHEETPAGE hPages[1];
hPages[0] = pPage2->Create();
sheet.phpage = &hPages[0]; sheet.pfnCallback = NULL;
PropertySheet(&sheet); return S_OK; }
// folder selection...
HRESULT CRootFolder::OnSelect(BOOL bScope, BOOL bSelect, IConsoleVerb* ipConsoleVerb) { ASSERT(bScope);
if (bSelect) { // allow properties verb to work when context menu is used in scope or result pane
VERIFY( ipConsoleVerb->SetVerbState( MMC_VERB_PROPERTIES, ENABLED, TRUE ) == S_OK); if (!bScope) // incase the rules are changed again leave !bScope test
{ VERIFY( ipConsoleVerb->SetVerbState( MMC_VERB_OPEN, ENABLED, TRUE ) == S_OK); VERIFY( ipConsoleVerb->SetDefaultVerb( MMC_VERB_OPEN ) == S_OK ); } } return S_OK; }
HRESULT CRootFolder::OnSelect(BOOL bScope, BOOL bSelect, IConsoleVerb* ipConsoleVerb, LPARAM Cookie) { ASSERT(!bScope);
if (bSelect) { // allow properties verb to work when context menu is used in scope or result pane
VERIFY( ipConsoleVerb->SetVerbState( MMC_VERB_PROPERTIES, ENABLED, TRUE ) == S_OK);
// why this seems to be a meaningless test
// changes between MMC 1.1 vs MMC 1.2 (as least in the documentation)
// as to whether bScope mean scope pane or scope item
// leave this in for the time being
if (!bScope) // incase the rules are changed again leave !bScope test
{ VERIFY( ipConsoleVerb->SetVerbState( MMC_VERB_OPEN, ENABLED, TRUE ) == S_OK); VERIFY( ipConsoleVerb->SetDefaultVerb( MMC_VERB_OPEN ) == S_OK ); } } return S_OK; }
HRESULT CRootFolder::QueryPagesFor() { return S_OK; }
HRESULT CRootFolder::OnCreatePropertyPages( LPPROPERTYSHEETCALLBACK lpProvider, LONG_PTR handle, DATA_OBJECT_TYPES context) { if (context == CCT_SNAPIN_MANAGER) { CRootWizard1 *pPage1 = new CRootWizard1(CRootWizard1::FIRST_PAGE, IDS_ADDSNAPIN_TITLE); CRootWizard2 *pPage2 = new CRootWizard2(CRootWizard2::LAST_PAGE, IDS_ADDSNAPIN_TITLE, this); if (!pPage1 || !pPage2) return S_FALSE;
ASSERT(handle == NULL); // $$ behavior change, better see what's going on...
// previously context of CCT_SNAPIN_MANAGER, the handle was always null so
// ...access the the folder object directly was assumed to be a valid operation
VERIFY(lpProvider->AddPage(pPage1->Create()) == S_OK);
return lpProvider->AddPage(pPage2->Create()); } else { COMPUTER_CONNECTION_INFO ConnInfo; GetComputerConnectionInfo(ConnInfo);
CRootGeneralPage *pPage1 = new CRootGeneralPage(NULL); if (pPage1) lpProvider->AddPage(pPage1->Create());
CRootVersionPage *pPage2 = new CRootVersionPage(NULL); if (pPage2) lpProvider->AddPage(pPage2->Create());
PCSystemInfo sysInfo;
PCid hID = GetPCid();
if (PCGetServiceInfo( hID, &sysInfo, sizeof(sysInfo) )) { CServicePageContainer *pContainer = new CServicePageContainer(sysInfo.sysParms, this, handle, hID, ConnInfo, 0, TRUE, -1); if (pContainer) { CRootServicePage *pPage3 = new CRootServicePage(NULL, pContainer); if (pPage3) { pPage3->PCInfo = sysInfo; lpProvider->AddPage(pPage3->Create()); } pContainer->Release(); pContainer = NULL; } } else { VERIFY(S_OK == MMCFreeNotifyHandle(handle)); }
return S_OK; } return S_FALSE; }
HRESULT CRootFolder::OnPropertyChange(PROPERTY_CHANGE_HDR *pUpdate, IConsole2 *ipConsole2) { ATLTRACE(_T("Service Info updated via property page...\n")); return S_OK; }
|