965 lines
28 KiB
C++
965 lines
28 KiB
C++
/*******************************************************************************
|
|
*
|
|
* apptree.cpp
|
|
*
|
|
* implementation of the CAppTreeView class
|
|
*
|
|
* copyright notice: Copyright 1997, Citrix Systems Inc.
|
|
* Copyright (c) 1998 - 1999 Microsoft Corporation
|
|
*
|
|
* $Author: donm $ Don Messerli
|
|
*
|
|
* $Log: N:\nt\private\utils\citrix\winutils\tsadmin\VCS\apptree.cpp $
|
|
*
|
|
* Rev 1.2 16 Feb 1998 16:00:06 donm
|
|
* modifications to support pICAsso extension
|
|
*
|
|
* Rev 1.1 03 Nov 1997 15:21:24 donm
|
|
* update
|
|
*
|
|
* Rev 1.0 13 Oct 1997 22:31:20 donm
|
|
* Initial revision.
|
|
*
|
|
*******************************************************************************/
|
|
|
|
#include "stdafx.h"
|
|
#include "winadmin.h"
|
|
#include "admindoc.h"
|
|
#include "apptree.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
|
|
/////////////////////////////
|
|
// MESSAGE MAP: CAppTreeView
|
|
//
|
|
IMPLEMENT_DYNCREATE(CAppTreeView, CBaseTreeView)
|
|
|
|
BEGIN_MESSAGE_MAP(CAppTreeView, CBaseTreeView)
|
|
//{{AFX_MSG_MAP(CAppTreeView)
|
|
ON_MESSAGE(WM_EXT_ADD_APPLICATION, OnExtAddApplication)
|
|
ON_MESSAGE(WM_EXT_REMOVE_APPLICATION, OnExtRemoveApplication)
|
|
ON_MESSAGE(WM_EXT_APP_CHANGED, OnExtAppChanged)
|
|
ON_MESSAGE(WM_EXT_ADD_APP_SERVER, OnExtAddAppServer)
|
|
ON_MESSAGE(WM_EXT_REMOVE_APP_SERVER, OnExtRemoveAppServer)
|
|
ON_MESSAGE(WM_ADMIN_VIEWS_READY, OnAdminViewsReady)
|
|
ON_MESSAGE(WM_ADMIN_UPDATE_SERVER, OnAdminUpdateServer)
|
|
ON_MESSAGE(WM_ADMIN_ADD_WINSTATION, OnAdminAddWinStation)
|
|
ON_MESSAGE(WM_ADMIN_REMOVE_WINSTATION, OnAdminRemoveWinStation)
|
|
ON_MESSAGE(WM_ADMIN_UPDATE_WINSTATION, OnAdminUpdateWinStation)
|
|
ON_WM_CONTEXTMENU()
|
|
ON_NOTIFY(NM_RCLICK, AFX_IDW_PANE_FIRST, OnRClick)
|
|
ON_NOTIFY(NM_RCLICK, 1, OnRClick)
|
|
ON_WM_LBUTTONDOWN()
|
|
//}}AFX_MSG_MAP
|
|
END_MESSAGE_MAP()
|
|
|
|
//////////////////////////
|
|
// CAppTreeView ctor
|
|
//
|
|
CAppTreeView::CAppTreeView()
|
|
{
|
|
|
|
} // end CAppTreeView ctor
|
|
|
|
|
|
//////////////////////////
|
|
// CAppTreeView dtor
|
|
//
|
|
CAppTreeView::~CAppTreeView()
|
|
{
|
|
|
|
} // end CAppTreeView dtor
|
|
|
|
|
|
#ifdef _DEBUG
|
|
//////////////////////////////////
|
|
// CAppTreeView::AssertValid
|
|
//
|
|
void CAppTreeView::AssertValid() const
|
|
{
|
|
CBaseTreeView::AssertValid();
|
|
|
|
} // end CAppTreeView::AssertValid
|
|
|
|
|
|
///////////////////////////
|
|
// CAppTreeView::Dump
|
|
//
|
|
void CAppTreeView::Dump(CDumpContext& dc) const
|
|
{
|
|
CBaseTreeView::Dump(dc);
|
|
|
|
} // end CAppTreeView::Dump
|
|
#endif
|
|
|
|
|
|
/////////////////////////////////////
|
|
// CAppTreeView::BuildImageList
|
|
//
|
|
// - calls m_imageList.Create(..) to create the image list
|
|
// - calls AddIconToImageList(..) to add the icons themselves and save
|
|
// off their indices
|
|
// - attaches the image list to the CTreeCtrl
|
|
//
|
|
void CAppTreeView::BuildImageList()
|
|
{
|
|
m_ImageList.Create(16, 16, TRUE, 7, 0);
|
|
|
|
m_idxApps = AddIconToImageList(IDI_APPS);
|
|
m_idxGenericApp = AddIconToImageList(IDI_GENERIC_APP);
|
|
m_idxServer = AddIconToImageList(IDI_SERVER);
|
|
m_idxNotSign = AddIconToImageList(IDI_NOTSIGN);
|
|
m_idxQuestion = AddIconToImageList(IDI_QUESTIONMARK);
|
|
m_idxUser = AddIconToImageList(IDI_USER);
|
|
m_idxCurrentServer = AddIconToImageList(IDI_CURRENT_SERVER);
|
|
m_idxCurrentUser = AddIconToImageList(IDI_CURRENT_USER);
|
|
m_idxServerNotConnected = AddIconToImageList(IDI_SERVER_NOT_CONNECTED);
|
|
|
|
// Overlay for Servers we can't talk to
|
|
m_ImageList.SetOverlayImage(m_idxNotSign, 1);
|
|
// Overlay for Servers we are currently gathering information about
|
|
m_ImageList.SetOverlayImage(m_idxQuestion, 2);
|
|
|
|
GetTreeCtrl().SetImageList(&m_ImageList, TVSIL_NORMAL);
|
|
|
|
} // end CAppTreeView::BuildImageList
|
|
|
|
|
|
//////////////////////////////////
|
|
// CAppTreeView::OnAdminViewsReady
|
|
//
|
|
LRESULT CAppTreeView::OnAdminViewsReady(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LockTreeControl();
|
|
|
|
// Get a pointer to our document
|
|
CWinAdminDoc *doc = (CWinAdminDoc*)GetDocument();
|
|
|
|
// add the root to the tree
|
|
CString citrix;
|
|
citrix.LoadString(IDS_PUBLISHED_APPS);
|
|
CTreeNode* pRootNode = new CTreeNode(NODE_PUBLISHED_APPS, NULL);
|
|
if(pRootNode) {
|
|
HTREEITEM hRoot = AddItemToTree(NULL, citrix, TVI_ROOT, m_idxApps, (DWORD)pRootNode);
|
|
if(!hRoot) delete pRootNode;
|
|
}
|
|
|
|
UnlockTreeControl();
|
|
|
|
return 0;
|
|
|
|
} // end CAppTreeView::OnAdminViewsReady
|
|
|
|
|
|
////////////////////////////////
|
|
// CAppTreeView::OnExtAddApplication
|
|
//
|
|
// Message Handler to add a published application to the tree
|
|
// Pointer to ExtAddTreeNode is in wParam
|
|
// Pointer to CPublishedApp is in lParam
|
|
//
|
|
LRESULT CAppTreeView::OnExtAddApplication(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LockTreeControl();
|
|
|
|
ExtAddTreeNode *pExtAddTreeNode = (ExtAddTreeNode*)wParam;
|
|
|
|
// First make sure the application isn't already in the tree
|
|
HTREEITEM hRoot = GetTreeCtrl().GetRootItem();
|
|
// Get the first application
|
|
HTREEITEM hItem = GetTreeCtrl().GetNextItem(hRoot, TVGN_CHILD);
|
|
while(hItem) {
|
|
// Get the data attached to the tree item
|
|
CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hItem);
|
|
// Is this the application we want to add?
|
|
if((CObject*)node->GetTreeObject() == pExtAddTreeNode->pObject) return 0;
|
|
hItem = GetTreeCtrl().GetNextItem(hItem, TVGN_NEXT);
|
|
}
|
|
|
|
// Add the published application to the tree
|
|
// Create a CTreeNode object with info about this tree node
|
|
CTreeNode* pNode = new CTreeNode(NODE_APPLICATION, pExtAddTreeNode->pObject);
|
|
if(pNode) {
|
|
HTREEITEM hApplication = AddItemToTree(hRoot, pExtAddTreeNode->Name, TVI_SORT,
|
|
m_idxGenericApp, (DWORD)pNode);
|
|
|
|
if(!hApplication) delete pNode;
|
|
|
|
if(!((CPublishedApp*)pExtAddTreeNode->pObject)->IsState(PAS_GOOD))
|
|
GetTreeCtrl().SetItemState(hApplication, STATE_QUESTION, 0x0F00);
|
|
|
|
((CPublishedApp*)pExtAddTreeNode->pObject)->SetTreeItem(hApplication);
|
|
}
|
|
|
|
UnlockTreeControl();
|
|
|
|
return 0;
|
|
|
|
} // end CAppTreeView::OnExtAddApplication
|
|
|
|
|
|
////////////////////////////////
|
|
// CAppTreeView::OnExtRemoveApplication
|
|
//
|
|
// Message Handler to remove a published application from the tree
|
|
// Pointer to CPublishedApp is in lParam
|
|
//
|
|
LRESULT CAppTreeView::OnExtRemoveApplication(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
ASSERT(lParam);
|
|
|
|
CPublishedApp *pApplication = (CPublishedApp*)lParam;
|
|
|
|
HTREEITEM hApplication = pApplication->GetTreeItem();
|
|
if(!hApplication) return 0;
|
|
|
|
LockTreeControl();
|
|
|
|
// Get the data attached to this tree node
|
|
CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hApplication);
|
|
if(node) {
|
|
// Is this the application we want to remove
|
|
CPublishedApp *pTreeApp = (CPublishedApp*)node->GetTreeObject();
|
|
// Make sure the tree node is correct
|
|
if(pTreeApp != pApplication) {
|
|
UnlockTreeControl();
|
|
return 0;
|
|
}
|
|
}
|
|
else {
|
|
UnlockTreeControl();
|
|
return 0;
|
|
}
|
|
|
|
// Loop through it's children and delete their data
|
|
HTREEITEM hAppServer = GetTreeCtrl().GetNextItem(hApplication, TVGN_CHILD);
|
|
while(hAppServer) {
|
|
CTreeNode *pTreeNode = (CTreeNode*)GetTreeCtrl().GetItemData(hAppServer);
|
|
if(pTreeNode) {
|
|
delete pTreeNode;
|
|
}
|
|
// Loop through the users nodes under the AppServer in the tree
|
|
HTREEITEM hUser = GetTreeCtrl().GetNextItem(hAppServer, TVGN_CHILD);
|
|
while(hUser) {
|
|
CTreeNode *pTreeNode = (CTreeNode*)GetTreeCtrl().GetItemData(hUser);
|
|
if(pTreeNode) {
|
|
CWinStation *pWinStation = (CWinStation*)pTreeNode->GetTreeObject();
|
|
if(pWinStation)
|
|
pWinStation->SetAppTreeItem(NULL);
|
|
delete pTreeNode;
|
|
}
|
|
}
|
|
|
|
hAppServer = GetTreeCtrl().GetNextItem(hAppServer, TVGN_NEXT);
|
|
}
|
|
|
|
// Delete the data attached to the tree item
|
|
delete node;
|
|
// Let the application know he is no longer in the tree
|
|
pApplication->SetTreeItem(NULL);
|
|
// Remove the application from the tree
|
|
// This SHOULD remove all it's children
|
|
GetTreeCtrl().DeleteItem(hApplication);
|
|
|
|
UnlockTreeControl();
|
|
|
|
return 0;
|
|
|
|
} // end CAppTreeView::OnExtRemoveApplication
|
|
|
|
|
|
/////////////////////////////////////////
|
|
// CAppTreeView::OnExtAppChanged
|
|
//
|
|
LRESULT CAppTreeView::OnExtAppChanged(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
ASSERT(lParam);
|
|
|
|
// we only care if it is a state change
|
|
if(wParam & ACF_STATE) {
|
|
|
|
CPublishedApp *pApplication = (CPublishedApp*)lParam;
|
|
|
|
HTREEITEM hApplication = pApplication->GetTreeItem();
|
|
if(!hApplication) return 0;
|
|
|
|
LockTreeControl();
|
|
|
|
// Get the data attached to this tree node
|
|
CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hApplication);
|
|
if(node) {
|
|
// Is this the app we want to update?
|
|
CPublishedApp *pTreeApp = (CPublishedApp*)node->GetTreeObject();
|
|
// Make sure the tree node is correct
|
|
if(pTreeApp != pApplication) {
|
|
UnlockTreeControl();
|
|
return 0;
|
|
}
|
|
} else {
|
|
UnlockTreeControl();
|
|
return 0;
|
|
}
|
|
|
|
USHORT NewState;
|
|
// Remember the previous state
|
|
USHORT PreviousState = GetTreeCtrl().GetItemState(hApplication, 0x0F00);
|
|
// Change the icon/overlay for the app
|
|
// If we aren't done getting all the information about this app,
|
|
// put a question mark over the icon
|
|
if(pApplication->IsState(PAS_GETTING_INFORMATION)) NewState = STATE_QUESTION;
|
|
// If it is fine, we want to remove any overlays from the icon
|
|
else NewState = STATE_NORMAL;
|
|
|
|
// Set the tree item to the new state
|
|
GetTreeCtrl().SetItemState(hApplication, NewState, 0x0F00);
|
|
}
|
|
|
|
return 0;
|
|
|
|
} // end CAppTreeView::OnExtAppChanged
|
|
|
|
|
|
/////////////////////////////////////////
|
|
// CAppTreeView::DetermineServerIcon
|
|
//
|
|
// determines which icon to display for a Server
|
|
// in the tree
|
|
//
|
|
int CAppTreeView::DetermineServerIcon(CServer *pServer)
|
|
{
|
|
if(!pServer) return m_idxServerNotConnected;
|
|
|
|
int WhichIcon = m_idxServer;
|
|
|
|
// Is this the current server?
|
|
if(pServer->IsCurrentServer()) {
|
|
if(pServer->IsState(SS_NONE) || pServer->IsState(SS_NOT_CONNECTED))
|
|
WhichIcon = m_idxServerNotConnected;
|
|
else
|
|
WhichIcon = m_idxCurrentServer;
|
|
} else { // not the current server
|
|
if(pServer->IsState(SS_NONE) || pServer->IsState(SS_NOT_CONNECTED))
|
|
WhichIcon = m_idxServerNotConnected;
|
|
}
|
|
|
|
return WhichIcon;
|
|
|
|
} // end CAooTreeView::DetermineServerIcon
|
|
|
|
|
|
////////////////////////////////
|
|
// CAppTreeView::OnExtAddAppServer
|
|
//
|
|
// Message Handler to add a server beneath a published application
|
|
// Pointer to ExtAddTreeNode is in wParam
|
|
// Pointer to CAppServer is in lParam
|
|
//
|
|
LRESULT CAppTreeView::OnExtAddAppServer(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
ExtAddTreeNode *pExtAddTreeNode = (ExtAddTreeNode*)wParam;
|
|
|
|
HTREEITEM hParent = pExtAddTreeNode->hParent;
|
|
if(!hParent) return 0;
|
|
|
|
CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
|
|
CServer *pServer = pDoc->FindServerByName(pExtAddTreeNode->Name);
|
|
|
|
LockTreeControl();
|
|
CTreeCtrl &tree = GetTreeCtrl();
|
|
|
|
// First make sure the server isn't already in the tree
|
|
// Get the first server under the application
|
|
HTREEITEM hItem = tree.GetNextItem(hParent, TVGN_CHILD);
|
|
while(hItem) {
|
|
// Get the data attached to the tree item
|
|
CTreeNode *node = (CTreeNode*)tree.GetItemData(hItem);
|
|
if(node) {
|
|
// Is this the server we want to add
|
|
CAppServer *pAppServer = (CAppServer*)node->GetTreeObject();
|
|
if(pAppServer == (CAppServer*)pExtAddTreeNode->pObject) {
|
|
UnlockTreeControl();
|
|
return 0;
|
|
}
|
|
}
|
|
hItem = tree.GetNextItem(hItem, TVGN_NEXT);
|
|
}
|
|
|
|
CTreeNode* pNode = new CTreeNode(NODE_APP_SERVER, pExtAddTreeNode->pObject);
|
|
if(pNode) {
|
|
|
|
HTREEITEM hServer = AddItemToTree(hParent, pExtAddTreeNode->Name, TVI_SORT,
|
|
DetermineServerIcon(pServer), (DWORD)pNode);
|
|
if(!hServer) delete pNode;
|
|
((CAppServer*)pExtAddTreeNode->pObject)->SetTreeItem(hServer);
|
|
|
|
if(pServer) {
|
|
// If the server isn't sane, put a not sign over the icon
|
|
if(!pServer->IsServerSane()) tree.SetItemState(hServer, STATE_NOT, 0x0F00);
|
|
// If we aren't done getting all the information about this server,
|
|
// put a question mark over the icon
|
|
else if(pServer->IsState(SS_GETTING_INFO)) tree.SetItemState(hServer, STATE_QUESTION, 0x0F00);
|
|
}
|
|
|
|
}
|
|
|
|
UnlockTreeControl();
|
|
return 0;
|
|
|
|
} // end CAppTreeView::OnExtAddAppServer
|
|
|
|
|
|
////////////////////////////////
|
|
// CAppTreeView::OnExtRemoveAppServer
|
|
//
|
|
// Message Handler to remove a server from beneath a published application
|
|
// Pointer to CPublishedApp is in wParam
|
|
// Pointer to CAppServer is in lParam
|
|
//
|
|
LRESULT CAppTreeView::OnExtRemoveAppServer(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
ASSERT(wParam);
|
|
ASSERT(lParam);
|
|
|
|
HTREEITEM hServer = ((CAppServer*)lParam)->GetTreeItem();
|
|
if(!hServer) return 0;
|
|
|
|
LockTreeControl();
|
|
CTreeCtrl &tree = GetTreeCtrl();
|
|
|
|
CTreeNode *ServerNode = (CTreeNode*)tree.GetItemData(hServer);
|
|
|
|
// Remove the Users underneath this server in the tree
|
|
HTREEITEM hUser = tree.GetNextItem(hServer, TVGN_CHILD);
|
|
while(hUser) {
|
|
// Get the data attached to the tree item
|
|
CTreeNode *node = (CTreeNode*)tree.GetItemData(hUser);
|
|
if(node) {
|
|
CWinStation *pWinStation = (CWinStation*)node->GetTreeObject();
|
|
pWinStation->SetAppTreeItem(NULL);
|
|
delete node;
|
|
}
|
|
|
|
hUser = tree.GetNextItem(hUser, TVGN_NEXT);
|
|
}
|
|
|
|
// Delete the data attached to the tree item
|
|
delete ServerNode;
|
|
// Let the AppServer know he is no longer in the tree
|
|
((CAppServer*)lParam)->SetTreeItem(NULL);
|
|
// Remove the AppServer from the tree
|
|
// This SHOULD remove all it's children
|
|
GetTreeCtrl().DeleteItem(hServer);
|
|
|
|
UnlockTreeControl();
|
|
return 0;
|
|
|
|
} // end CAppTreeView::OnExtRemoveAppServer
|
|
|
|
|
|
/////////////////////////////////////////
|
|
// CAppTreeView::AddServerChildren
|
|
//
|
|
// Adds the Users running the published app on a given Server
|
|
// to the tree
|
|
//
|
|
void CAppTreeView::AddServerChildren(HTREEITEM hServer, CServer *pServer)
|
|
{
|
|
ASSERT(hServer);
|
|
ASSERT(pServer);
|
|
|
|
if(pServer->IsServerSane()) {
|
|
|
|
LockTreeControl();
|
|
|
|
HTREEITEM hParent = GetTreeCtrl().GetParentItem(hServer);
|
|
|
|
HTREEITEM hLastNode = hServer;
|
|
|
|
CTreeNode *pParentNode = (CTreeNode*)GetTreeCtrl().GetItemData(hParent);
|
|
CPublishedApp *pApplication = (CPublishedApp*)pParentNode->GetTreeObject();
|
|
|
|
pServer->LockWinStationList();
|
|
// Get a pointer to the server's list of WinStations
|
|
CObList *pWinStationList = pServer->GetWinStationList();
|
|
|
|
// Iterate through the WinStation list
|
|
POSITION pos = pWinStationList->GetHeadPosition();
|
|
|
|
while(pos) {
|
|
CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
|
|
|
|
// We only care if the user is running this published app
|
|
if(pWinStation->GetState() == State_Active
|
|
&& pWinStation->HasUser()
|
|
&& pWinStation->IsRunningPublishedApp()
|
|
&& pWinStation->IsRunningPublishedApp(pApplication->GetName())) {
|
|
|
|
// Figure out what text to display
|
|
CString UserString;
|
|
if(wcslen(pWinStation->GetUserName())) {
|
|
UserString.Format(TEXT("%s (%s)"), pWinStation->GetName(), pWinStation->GetUserName());
|
|
}
|
|
else UserString.Format(TEXT("%s"), pWinStation->GetName());
|
|
|
|
CTreeNode *pNode = new CTreeNode(NODE_WINSTATION, pWinStation);
|
|
if(pNode) {
|
|
pNode->SetSortOrder(pWinStation->GetSortOrder());
|
|
hLastNode = AddItemToTree(hServer, UserString, TVI_SORT,
|
|
pWinStation->IsCurrentUser() ? m_idxCurrentUser : m_idxUser, (DWORD)pNode);
|
|
if(!hLastNode) delete pNode;
|
|
}
|
|
|
|
// The WinStation wants to know his tree item handle
|
|
pWinStation->SetAppTreeItem(hLastNode);
|
|
}
|
|
}
|
|
|
|
pServer->UnlockWinStationList();
|
|
|
|
UnlockTreeControl();
|
|
|
|
} // end if(pServer->IsServerSane())
|
|
|
|
|
|
} // end CAppTreeView::AddServerChildren
|
|
|
|
|
|
////////////////////////////////
|
|
// CAppTreeView::OnAdminUpdateServer
|
|
//
|
|
// Message handler to update a Server in the tree
|
|
// Pointer to CServer to update is in lParam
|
|
//
|
|
LRESULT CAppTreeView::OnAdminUpdateServer(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
ASSERT(lParam);
|
|
|
|
CServer *pServer = (CServer*)lParam;
|
|
if(!pServer) return 0;
|
|
|
|
LockTreeControl();
|
|
|
|
// The server can be in the tree more than one place
|
|
UINT itemCount = GetTreeCtrl().GetCount();
|
|
|
|
HTREEITEM hTreeItem = GetTreeCtrl().GetRootItem();
|
|
for(UINT i = 0; i < itemCount; i++) {
|
|
CTreeNode *node = ((CTreeNode*)GetTreeCtrl().GetItemData(hTreeItem));
|
|
if(node) {
|
|
// we only care about app servers
|
|
if(node->GetNodeType() == NODE_APP_SERVER) {
|
|
CAppServer *pAppServer = (CAppServer*)node->GetTreeObject();
|
|
// Is it the same server?
|
|
if(0 == wcscmp(pAppServer->GetName(), pServer->GetName())) {
|
|
USHORT NewState;
|
|
// Remember the previous state
|
|
USHORT PreviousState = GetTreeCtrl().GetItemState(hTreeItem, 0x0F00);
|
|
// Change the icon/overlay for the server
|
|
// If the server isn't sane, put a not sign over the icon
|
|
if(!pServer->IsServerSane()) NewState = STATE_NOT;
|
|
// If we aren't done getting all the information about this server,
|
|
// put a question mark over the icon
|
|
else if(pServer->IsState(SS_GETTING_INFO)) NewState = STATE_QUESTION;
|
|
// If it is fine, we want to remove any overlays from the icon
|
|
else NewState = STATE_NORMAL;
|
|
|
|
// Set the tree item to the new state
|
|
GetTreeCtrl().SetItemState(hTreeItem, NewState, 0x0F00);
|
|
|
|
// If this Server was not opened and now is GOOD,
|
|
// add it's children to the tree
|
|
if(PreviousState != STATE_NORMAL && pServer->IsState(SS_GOOD)) {
|
|
int ServerIcon = DetermineServerIcon(pServer);
|
|
GetTreeCtrl().SetItemImage(hTreeItem, ServerIcon, ServerIcon);
|
|
AddServerChildren(hTreeItem, pServer);
|
|
}
|
|
else if(pServer->GetPreviousState() == SS_DISCONNECTING && pServer->IsState(SS_NOT_CONNECTED)) {
|
|
int ServerIcon = DetermineServerIcon(pServer);
|
|
GetTreeCtrl().SetItemImage(hTreeItem, ServerIcon, ServerIcon);
|
|
}
|
|
|
|
// If we changed the state of this server and it is the currently
|
|
// selected node in the tree, we need to send a message to change
|
|
// the view
|
|
// We also need to make sure this is the currently selected tree
|
|
CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
|
|
if(NewState != PreviousState && hTreeItem == GetTreeCtrl().GetSelectedItem()
|
|
&& pDoc->GetCurrentTree() == TREEVIEW_APPS) {
|
|
#if 0
|
|
LONG Result;
|
|
OnSelChange(NULL, &Result);
|
|
#endif
|
|
ForceSelChange();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
hTreeItem = GetNextItem(hTreeItem);
|
|
}
|
|
|
|
UnlockTreeControl();
|
|
|
|
return 0;
|
|
|
|
} // end CAppTreeView::OnAdminUpdateServer
|
|
|
|
|
|
////////////////////////////////
|
|
// CAppTreeView::AddUser
|
|
//
|
|
HTREEITEM CAppTreeView::AddUser(CWinStation *pWinStation)
|
|
{
|
|
ASSERT(pWinStation);
|
|
|
|
HTREEITEM hWinStation = NULL;
|
|
|
|
// Find the published app that this WinStation is running in our tree
|
|
CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
|
|
CPublishedApp *pApplication = pDoc->FindPublishedAppByName(pWinStation->GetPublishedAppName());
|
|
CServer *pServer = pWinStation->GetServer();
|
|
|
|
if(!pApplication) return NULL;
|
|
|
|
HTREEITEM hApplication = pApplication->GetTreeItem();
|
|
if(!hApplication) return NULL;
|
|
|
|
CTreeCtrl &tree = LockTreeControl();
|
|
|
|
// Find this WinStation's server under the published application in the tree
|
|
HTREEITEM hServer = NULL;
|
|
|
|
hServer = tree.GetChildItem(hApplication);
|
|
|
|
while(hServer) {
|
|
CTreeNode *pNode = (CTreeNode*)GetTreeCtrl().GetItemData(hServer);
|
|
CAppServer *pAppServer = (CAppServer*)pNode->GetTreeObject();
|
|
if(0 == wcscmp(pAppServer->GetName(), pServer->GetName())) {
|
|
// Figure out what text to display
|
|
CString UserString;
|
|
if(wcslen(pWinStation->GetUserName())) {
|
|
UserString.Format(TEXT("%s (%s)"), pWinStation->GetName(), pWinStation->GetUserName());
|
|
}
|
|
else UserString.Format(TEXT("%s"), pWinStation->GetName());
|
|
|
|
CTreeNode *pNewNode = new CTreeNode(NODE_WINSTATION, pWinStation);
|
|
if(pNewNode) {
|
|
hWinStation = AddItemToTree(hServer, UserString, TVI_SORT,
|
|
pWinStation->IsCurrentUser() ? m_idxCurrentUser : m_idxUser, (DWORD)pNewNode);
|
|
if(!hWinStation) delete pNewNode;
|
|
// The WinStation wants to know his tree item handle
|
|
pWinStation->SetAppTreeItem(hWinStation);
|
|
}
|
|
}
|
|
|
|
hServer = tree.GetNextSiblingItem(hServer);
|
|
}
|
|
|
|
UnlockTreeControl();
|
|
|
|
return hWinStation;
|
|
|
|
}
|
|
|
|
|
|
////////////////////////////////
|
|
// CAppTreeView::OnAdminAddWinStation
|
|
//
|
|
// Message handler to add a WinStation to the tree
|
|
// lParam = pointer to CWinStation to add
|
|
// wParam is TRUE if this is replacing a WinStation that was currently selected
|
|
//
|
|
LRESULT CAppTreeView::OnAdminAddWinStation(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
ASSERT(lParam);
|
|
|
|
CWinStation *pWinStation = (CWinStation*)lParam;
|
|
if(!pWinStation) return 0;
|
|
|
|
// If this WinStation isn't running a published App, we
|
|
// don't give a damn
|
|
if(!pWinStation->IsState(State_Active) || !pWinStation->IsRunningPublishedApp())
|
|
return 0;
|
|
|
|
AddUser(pWinStation);
|
|
|
|
return 0;
|
|
|
|
} // end CAppTreeView::OnAdminAddWinStation
|
|
|
|
|
|
////////////////////////////////
|
|
// CAppTreeView::OnAdminUpdateWinStation
|
|
//
|
|
// Message handler to update a WinStation in the tree
|
|
// lParam = pointer to CWinStation to update
|
|
//
|
|
LRESULT CAppTreeView::OnAdminUpdateWinStation(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
ASSERT(lParam);
|
|
|
|
CWinStation *pWinStation = (CWinStation*)lParam;
|
|
if(!pWinStation) return 0;
|
|
|
|
// If this WinStation isn't running a published App, we
|
|
// don't give a damn
|
|
if(!pWinStation->IsState(State_Active) || !pWinStation->IsRunningPublishedApp())
|
|
return 0;
|
|
|
|
// If this WinStation is already in the tree, we don't want to
|
|
// add it again
|
|
if(pWinStation->GetAppTreeItem())
|
|
return 0;
|
|
|
|
AddUser(pWinStation);
|
|
|
|
return 0;
|
|
|
|
} // end CAppTreeView::OnAdminUpdateWinStation
|
|
|
|
|
|
////////////////////////////////
|
|
// CAppTreeView::OnAdminRemoveWinStation
|
|
//
|
|
// Message handler to remove a WinStation from the tree
|
|
// lParam = pointer to CWinStation to remove
|
|
LRESULT CAppTreeView::OnAdminRemoveWinStation(WPARAM wParam, LPARAM lParam)
|
|
{
|
|
ASSERT(lParam);
|
|
|
|
BOOL CurrentInTree = FALSE;
|
|
|
|
CWinStation *pWinStation = (CWinStation*)lParam;
|
|
if(!pWinStation) return 0;
|
|
|
|
HTREEITEM hWinStation = pWinStation->GetAppTreeItem();
|
|
if(!hWinStation) return 0;
|
|
|
|
LockTreeControl();
|
|
|
|
// Get the data attached to this tree node
|
|
CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hWinStation);
|
|
if(node) {
|
|
// Is this the WinStation we want to update
|
|
CWinStation *pTreeWinStation = (CWinStation*)node->GetTreeObject();
|
|
// Make sure the tree node is correct
|
|
if(pTreeWinStation != pWinStation) {
|
|
UnlockTreeControl();
|
|
return 0;
|
|
}
|
|
} else {
|
|
UnlockTreeControl();
|
|
return 0;
|
|
}
|
|
|
|
// Delete the data attached to the tree item
|
|
delete node;
|
|
// Let the WinStation know he is no longer in the tree
|
|
pWinStation->SetAppTreeItem(NULL);
|
|
// Is this WinStation currently selected in the tree?
|
|
CurrentInTree = (GetTreeCtrl().GetSelectedItem() == hWinStation);
|
|
// Remove the WinStation from the tree
|
|
GetTreeCtrl().DeleteItem(hWinStation);
|
|
|
|
// If this WinStation is the currently selected node in the tree,
|
|
// make it not so
|
|
// This may not be necessary!
|
|
CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
|
|
if(CurrentInTree && pDoc->GetCurrentTree() == TREEVIEW_APPS)
|
|
((CWinAdminDoc*)GetDocument())->SetCurrentView(VIEW_CHANGING);
|
|
|
|
UnlockTreeControl();
|
|
|
|
return 0;
|
|
|
|
} // end CAppTreeView::OnAdminRemoveWinStation
|
|
|
|
|
|
////////////////////////////////
|
|
// CAppTreeView::OnContextMenu
|
|
//
|
|
// Message handler called when user wants a context menu
|
|
// This happens when the user clicks the right mouse button,
|
|
// presses Shift-F10, or presses the menu key on a Windows keyboard
|
|
//
|
|
void CAppTreeView::OnContextMenu(CWnd* pWnd, CPoint ptScreen)
|
|
{
|
|
CTreeCtrl &tree = GetTreeCtrl();
|
|
|
|
UINT flags;
|
|
HTREEITEM hItem;
|
|
CPoint ptClient = ptScreen;
|
|
ScreenToClient(&ptClient);
|
|
|
|
// If we got here from the keyboard,
|
|
if(ptScreen.x == -1 && ptScreen.y == -1) {
|
|
hItem = tree.GetSelectedItem();
|
|
RECT rect;
|
|
tree.GetItemRect(hItem, &rect, 0);
|
|
ptScreen.x = rect.left + (rect.right - rect.left)/2;
|
|
ptScreen.y = rect.top + (rect.bottom - rect.top)/2;
|
|
ClientToScreen(&ptScreen);
|
|
}
|
|
else {
|
|
hItem = tree.HitTest(ptClient, &flags);
|
|
if((NULL == hItem) || !(TVHT_ONITEM & flags))
|
|
return;
|
|
}
|
|
|
|
// Pop-up the menu
|
|
CTreeNode *pNode = (CTreeNode*)tree.GetItemData(hItem);
|
|
CWinAdminDoc *pDoc = (CWinAdminDoc*)GetDocument();
|
|
pDoc->SetTreeTemp(pNode->GetTreeObject(), (pNode->GetNodeType()));
|
|
|
|
if(pNode) {
|
|
CMenu menu;
|
|
UINT nIDResource = 0;
|
|
|
|
switch(pNode->GetNodeType()) {
|
|
case NODE_APP_SERVER:
|
|
{
|
|
CAppServer *pAppServer = (CAppServer*)pNode->GetTreeObject();
|
|
CServer *pServer = ((CWinAdminDoc*)GetDocument())->FindServerByName(pAppServer->GetName());
|
|
if(pServer) {
|
|
pDoc->SetTreeTemp(pServer, NODE_SERVER);
|
|
} else return;
|
|
nIDResource = IDR_SERVER_POPUP;
|
|
}
|
|
break;
|
|
|
|
case NODE_WINSTATION:
|
|
nIDResource = IDR_WINSTATION_TREE_POPUP;
|
|
break;
|
|
}
|
|
|
|
if(nIDResource) {
|
|
if(menu.LoadMenu(nIDResource)) {
|
|
menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON |
|
|
TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, AfxGetMainWnd());
|
|
}
|
|
}
|
|
|
|
} // end if(pNode)
|
|
|
|
} // end CAppTreeView::OnContextMenu
|
|
|
|
|
|
////////////////////////////////
|
|
// CAppTreeView::OnRClick
|
|
//
|
|
// The Tree Common Control sends a WM_NOTIFY of NM_RCLICK when
|
|
// the user presses the right mouse button in the tree
|
|
//
|
|
void CAppTreeView::OnRClick(NMHDR* pNMHDR, LRESULT* pResult)
|
|
{
|
|
CPoint ptScreen(::GetMessagePos());
|
|
|
|
LockTreeControl();
|
|
|
|
// Get a pointer to our document
|
|
CWinAdminDoc *doc = (CWinAdminDoc*)GetDocument();
|
|
|
|
CTreeCtrl &tree = GetTreeCtrl();
|
|
|
|
UINT flags;
|
|
HTREEITEM hItem;
|
|
CPoint ptClient = ptScreen;
|
|
ScreenToClient(&ptClient);
|
|
|
|
hItem = tree.HitTest(ptClient, &flags);
|
|
if((NULL == hItem) || !(TVHT_ONITEM & flags)) {
|
|
UnlockTreeControl();
|
|
return;
|
|
}
|
|
|
|
// Pop-up the menu
|
|
CTreeNode *pNode = (CTreeNode*)tree.GetItemData(hItem);
|
|
CWinAdminDoc *pDoc = (CWinAdminDoc*)GetDocument();
|
|
pDoc->SetTreeTemp(pNode->GetTreeObject(), (pNode->GetNodeType()));
|
|
|
|
if(pNode) {
|
|
CMenu menu;
|
|
UINT nIDResource = 0;
|
|
|
|
switch(pNode->GetNodeType()) {
|
|
case NODE_APP_SERVER:
|
|
{
|
|
CAppServer *pAppServer = (CAppServer*)pNode->GetTreeObject();
|
|
CServer *pServer = ((CWinAdminDoc*)GetDocument())->FindServerByName(pAppServer->GetName());
|
|
if(pServer) {
|
|
pDoc->SetTreeTemp(pServer, NODE_SERVER);
|
|
} else return;
|
|
nIDResource = IDR_SERVER_POPUP;
|
|
}
|
|
break;
|
|
|
|
case NODE_WINSTATION:
|
|
nIDResource = IDR_WINSTATION_TREE_POPUP;
|
|
break;
|
|
}
|
|
|
|
if(nIDResource) {
|
|
if(menu.LoadMenu(nIDResource)) {
|
|
menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON |
|
|
TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, AfxGetMainWnd());
|
|
}
|
|
}
|
|
|
|
} // end if(pNode)
|
|
|
|
UnlockTreeControl();
|
|
|
|
} // end CAppTreeView::OnRClick
|
|
|
|
|
|
////////////////////////////////
|
|
// CAppTreeView::OnLButtonDown
|
|
//
|
|
void CAppTreeView::OnLButtonDown(UINT nFlags, CPoint ptClient)
|
|
{
|
|
// Figure out what they clicked on
|
|
LockTreeControl();
|
|
|
|
CTreeCtrl &tree = GetTreeCtrl();
|
|
|
|
UINT flags;
|
|
HTREEITEM hItem;
|
|
|
|
hItem = tree.HitTest(ptClient, &flags);
|
|
if((NULL == hItem) || !(TVHT_ONITEM & flags)) {
|
|
UnlockTreeControl();
|
|
CTreeView::OnLButtonDown(nFlags, ptClient);
|
|
return;
|
|
}
|
|
|
|
// We only care about servers
|
|
CTreeNode *pNode = (CTreeNode*)tree.GetItemData(hItem);
|
|
if(pNode && pNode->GetNodeType() == NODE_APP_SERVER) {
|
|
// Is it the same item as is selected
|
|
if(hItem == tree.GetSelectedItem()) {
|
|
CAppServer *pAppServer = (CAppServer*)pNode->GetTreeObject();
|
|
CServer *pServer = ((CWinAdminDoc*)GetDocument())->FindServerByName(pAppServer->GetName());
|
|
// Is this server in the "just disconnected" state
|
|
// If both previous state and state are SS_NOT_CONNECTED,
|
|
// we know the user just disconnected from this server
|
|
if(pServer && pServer->IsState(SS_NOT_CONNECTED)) {
|
|
UnlockTreeControl();
|
|
LONG Result;
|
|
OnSelChange(NULL, &Result);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
UnlockTreeControl();
|
|
|
|
CTreeView::OnLButtonDown(nFlags, ptClient);
|
|
|
|
} // CAppTreeView::OnLButtonDown
|
|
|
|
|