Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

964 lines
28 KiB

  1. /*******************************************************************************
  2. *
  3. * apptree.cpp
  4. *
  5. * implementation of the CAppTreeView class
  6. *
  7. * copyright notice: Copyright 1997, Citrix Systems Inc.
  8. * Copyright (c) 1998 - 1999 Microsoft Corporation
  9. *
  10. * $Author: donm $ Don Messerli
  11. *
  12. * $Log: N:\nt\private\utils\citrix\winutils\tsadmin\VCS\apptree.cpp $
  13. *
  14. * Rev 1.2 16 Feb 1998 16:00:06 donm
  15. * modifications to support pICAsso extension
  16. *
  17. * Rev 1.1 03 Nov 1997 15:21:24 donm
  18. * update
  19. *
  20. * Rev 1.0 13 Oct 1997 22:31:20 donm
  21. * Initial revision.
  22. *
  23. *******************************************************************************/
  24. #include "stdafx.h"
  25. #include "winadmin.h"
  26. #include "admindoc.h"
  27. #include "apptree.h"
  28. #ifdef _DEBUG
  29. #define new DEBUG_NEW
  30. #undef THIS_FILE
  31. static char THIS_FILE[] = __FILE__;
  32. #endif
  33. /////////////////////////////
  34. // MESSAGE MAP: CAppTreeView
  35. //
  36. IMPLEMENT_DYNCREATE(CAppTreeView, CBaseTreeView)
  37. BEGIN_MESSAGE_MAP(CAppTreeView, CBaseTreeView)
  38. //{{AFX_MSG_MAP(CAppTreeView)
  39. ON_MESSAGE(WM_EXT_ADD_APPLICATION, OnExtAddApplication)
  40. ON_MESSAGE(WM_EXT_REMOVE_APPLICATION, OnExtRemoveApplication)
  41. ON_MESSAGE(WM_EXT_APP_CHANGED, OnExtAppChanged)
  42. ON_MESSAGE(WM_EXT_ADD_APP_SERVER, OnExtAddAppServer)
  43. ON_MESSAGE(WM_EXT_REMOVE_APP_SERVER, OnExtRemoveAppServer)
  44. ON_MESSAGE(WM_ADMIN_VIEWS_READY, OnAdminViewsReady)
  45. ON_MESSAGE(WM_ADMIN_UPDATE_SERVER, OnAdminUpdateServer)
  46. ON_MESSAGE(WM_ADMIN_ADD_WINSTATION, OnAdminAddWinStation)
  47. ON_MESSAGE(WM_ADMIN_REMOVE_WINSTATION, OnAdminRemoveWinStation)
  48. ON_MESSAGE(WM_ADMIN_UPDATE_WINSTATION, OnAdminUpdateWinStation)
  49. ON_WM_CONTEXTMENU()
  50. ON_NOTIFY(NM_RCLICK, AFX_IDW_PANE_FIRST, OnRClick)
  51. ON_NOTIFY(NM_RCLICK, 1, OnRClick)
  52. ON_WM_LBUTTONDOWN()
  53. //}}AFX_MSG_MAP
  54. END_MESSAGE_MAP()
  55. //////////////////////////
  56. // CAppTreeView ctor
  57. //
  58. CAppTreeView::CAppTreeView()
  59. {
  60. } // end CAppTreeView ctor
  61. //////////////////////////
  62. // CAppTreeView dtor
  63. //
  64. CAppTreeView::~CAppTreeView()
  65. {
  66. } // end CAppTreeView dtor
  67. #ifdef _DEBUG
  68. //////////////////////////////////
  69. // CAppTreeView::AssertValid
  70. //
  71. void CAppTreeView::AssertValid() const
  72. {
  73. CBaseTreeView::AssertValid();
  74. } // end CAppTreeView::AssertValid
  75. ///////////////////////////
  76. // CAppTreeView::Dump
  77. //
  78. void CAppTreeView::Dump(CDumpContext& dc) const
  79. {
  80. CBaseTreeView::Dump(dc);
  81. } // end CAppTreeView::Dump
  82. #endif
  83. /////////////////////////////////////
  84. // CAppTreeView::BuildImageList
  85. //
  86. // - calls m_imageList.Create(..) to create the image list
  87. // - calls AddIconToImageList(..) to add the icons themselves and save
  88. // off their indices
  89. // - attaches the image list to the CTreeCtrl
  90. //
  91. void CAppTreeView::BuildImageList()
  92. {
  93. m_ImageList.Create(16, 16, TRUE, 7, 0);
  94. m_idxApps = AddIconToImageList(IDI_APPS);
  95. m_idxGenericApp = AddIconToImageList(IDI_GENERIC_APP);
  96. m_idxServer = AddIconToImageList(IDI_SERVER);
  97. m_idxNotSign = AddIconToImageList(IDI_NOTSIGN);
  98. m_idxQuestion = AddIconToImageList(IDI_QUESTIONMARK);
  99. m_idxUser = AddIconToImageList(IDI_USER);
  100. m_idxCurrentServer = AddIconToImageList(IDI_CURRENT_SERVER);
  101. m_idxCurrentUser = AddIconToImageList(IDI_CURRENT_USER);
  102. m_idxServerNotConnected = AddIconToImageList(IDI_SERVER_NOT_CONNECTED);
  103. // Overlay for Servers we can't talk to
  104. m_ImageList.SetOverlayImage(m_idxNotSign, 1);
  105. // Overlay for Servers we are currently gathering information about
  106. m_ImageList.SetOverlayImage(m_idxQuestion, 2);
  107. GetTreeCtrl().SetImageList(&m_ImageList, TVSIL_NORMAL);
  108. } // end CAppTreeView::BuildImageList
  109. //////////////////////////////////
  110. // CAppTreeView::OnAdminViewsReady
  111. //
  112. LRESULT CAppTreeView::OnAdminViewsReady(WPARAM wParam, LPARAM lParam)
  113. {
  114. LockTreeControl();
  115. // Get a pointer to our document
  116. CWinAdminDoc *doc = (CWinAdminDoc*)GetDocument();
  117. // add the root to the tree
  118. CString citrix;
  119. citrix.LoadString(IDS_PUBLISHED_APPS);
  120. CTreeNode* pRootNode = new CTreeNode(NODE_PUBLISHED_APPS, NULL);
  121. if(pRootNode) {
  122. HTREEITEM hRoot = AddItemToTree(NULL, citrix, TVI_ROOT, m_idxApps, (DWORD)pRootNode);
  123. if(!hRoot) delete pRootNode;
  124. }
  125. UnlockTreeControl();
  126. return 0;
  127. } // end CAppTreeView::OnAdminViewsReady
  128. ////////////////////////////////
  129. // CAppTreeView::OnExtAddApplication
  130. //
  131. // Message Handler to add a published application to the tree
  132. // Pointer to ExtAddTreeNode is in wParam
  133. // Pointer to CPublishedApp is in lParam
  134. //
  135. LRESULT CAppTreeView::OnExtAddApplication(WPARAM wParam, LPARAM lParam)
  136. {
  137. LockTreeControl();
  138. ExtAddTreeNode *pExtAddTreeNode = (ExtAddTreeNode*)wParam;
  139. // First make sure the application isn't already in the tree
  140. HTREEITEM hRoot = GetTreeCtrl().GetRootItem();
  141. // Get the first application
  142. HTREEITEM hItem = GetTreeCtrl().GetNextItem(hRoot, TVGN_CHILD);
  143. while(hItem) {
  144. // Get the data attached to the tree item
  145. CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hItem);
  146. // Is this the application we want to add?
  147. if((CObject*)node->GetTreeObject() == pExtAddTreeNode->pObject) return 0;
  148. hItem = GetTreeCtrl().GetNextItem(hItem, TVGN_NEXT);
  149. }
  150. // Add the published application to the tree
  151. // Create a CTreeNode object with info about this tree node
  152. CTreeNode* pNode = new CTreeNode(NODE_APPLICATION, pExtAddTreeNode->pObject);
  153. if(pNode) {
  154. HTREEITEM hApplication = AddItemToTree(hRoot, pExtAddTreeNode->Name, TVI_SORT,
  155. m_idxGenericApp, (DWORD)pNode);
  156. if(!hApplication) delete pNode;
  157. if(!((CPublishedApp*)pExtAddTreeNode->pObject)->IsState(PAS_GOOD))
  158. GetTreeCtrl().SetItemState(hApplication, STATE_QUESTION, 0x0F00);
  159. ((CPublishedApp*)pExtAddTreeNode->pObject)->SetTreeItem(hApplication);
  160. }
  161. UnlockTreeControl();
  162. return 0;
  163. } // end CAppTreeView::OnExtAddApplication
  164. ////////////////////////////////
  165. // CAppTreeView::OnExtRemoveApplication
  166. //
  167. // Message Handler to remove a published application from the tree
  168. // Pointer to CPublishedApp is in lParam
  169. //
  170. LRESULT CAppTreeView::OnExtRemoveApplication(WPARAM wParam, LPARAM lParam)
  171. {
  172. ASSERT(lParam);
  173. CPublishedApp *pApplication = (CPublishedApp*)lParam;
  174. HTREEITEM hApplication = pApplication->GetTreeItem();
  175. if(!hApplication) return 0;
  176. LockTreeControl();
  177. // Get the data attached to this tree node
  178. CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hApplication);
  179. if(node) {
  180. // Is this the application we want to remove
  181. CPublishedApp *pTreeApp = (CPublishedApp*)node->GetTreeObject();
  182. // Make sure the tree node is correct
  183. if(pTreeApp != pApplication) {
  184. UnlockTreeControl();
  185. return 0;
  186. }
  187. }
  188. else {
  189. UnlockTreeControl();
  190. return 0;
  191. }
  192. // Loop through it's children and delete their data
  193. HTREEITEM hAppServer = GetTreeCtrl().GetNextItem(hApplication, TVGN_CHILD);
  194. while(hAppServer) {
  195. CTreeNode *pTreeNode = (CTreeNode*)GetTreeCtrl().GetItemData(hAppServer);
  196. if(pTreeNode) {
  197. delete pTreeNode;
  198. }
  199. // Loop through the users nodes under the AppServer in the tree
  200. HTREEITEM hUser = GetTreeCtrl().GetNextItem(hAppServer, TVGN_CHILD);
  201. while(hUser) {
  202. CTreeNode *pTreeNode = (CTreeNode*)GetTreeCtrl().GetItemData(hUser);
  203. if(pTreeNode) {
  204. CWinStation *pWinStation = (CWinStation*)pTreeNode->GetTreeObject();
  205. if(pWinStation)
  206. pWinStation->SetAppTreeItem(NULL);
  207. delete pTreeNode;
  208. }
  209. }
  210. hAppServer = GetTreeCtrl().GetNextItem(hAppServer, TVGN_NEXT);
  211. }
  212. // Delete the data attached to the tree item
  213. delete node;
  214. // Let the application know he is no longer in the tree
  215. pApplication->SetTreeItem(NULL);
  216. // Remove the application from the tree
  217. // This SHOULD remove all it's children
  218. GetTreeCtrl().DeleteItem(hApplication);
  219. UnlockTreeControl();
  220. return 0;
  221. } // end CAppTreeView::OnExtRemoveApplication
  222. /////////////////////////////////////////
  223. // CAppTreeView::OnExtAppChanged
  224. //
  225. LRESULT CAppTreeView::OnExtAppChanged(WPARAM wParam, LPARAM lParam)
  226. {
  227. ASSERT(lParam);
  228. // we only care if it is a state change
  229. if(wParam & ACF_STATE) {
  230. CPublishedApp *pApplication = (CPublishedApp*)lParam;
  231. HTREEITEM hApplication = pApplication->GetTreeItem();
  232. if(!hApplication) return 0;
  233. LockTreeControl();
  234. // Get the data attached to this tree node
  235. CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hApplication);
  236. if(node) {
  237. // Is this the app we want to update?
  238. CPublishedApp *pTreeApp = (CPublishedApp*)node->GetTreeObject();
  239. // Make sure the tree node is correct
  240. if(pTreeApp != pApplication) {
  241. UnlockTreeControl();
  242. return 0;
  243. }
  244. } else {
  245. UnlockTreeControl();
  246. return 0;
  247. }
  248. USHORT NewState;
  249. // Remember the previous state
  250. USHORT PreviousState = GetTreeCtrl().GetItemState(hApplication, 0x0F00);
  251. // Change the icon/overlay for the app
  252. // If we aren't done getting all the information about this app,
  253. // put a question mark over the icon
  254. if(pApplication->IsState(PAS_GETTING_INFORMATION)) NewState = STATE_QUESTION;
  255. // If it is fine, we want to remove any overlays from the icon
  256. else NewState = STATE_NORMAL;
  257. // Set the tree item to the new state
  258. GetTreeCtrl().SetItemState(hApplication, NewState, 0x0F00);
  259. }
  260. return 0;
  261. } // end CAppTreeView::OnExtAppChanged
  262. /////////////////////////////////////////
  263. // CAppTreeView::DetermineServerIcon
  264. //
  265. // determines which icon to display for a Server
  266. // in the tree
  267. //
  268. int CAppTreeView::DetermineServerIcon(CServer *pServer)
  269. {
  270. if(!pServer) return m_idxServerNotConnected;
  271. int WhichIcon = m_idxServer;
  272. // Is this the current server?
  273. if(pServer->IsCurrentServer()) {
  274. if(pServer->IsState(SS_NONE) || pServer->IsState(SS_NOT_CONNECTED))
  275. WhichIcon = m_idxServerNotConnected;
  276. else
  277. WhichIcon = m_idxCurrentServer;
  278. } else { // not the current server
  279. if(pServer->IsState(SS_NONE) || pServer->IsState(SS_NOT_CONNECTED))
  280. WhichIcon = m_idxServerNotConnected;
  281. }
  282. return WhichIcon;
  283. } // end CAooTreeView::DetermineServerIcon
  284. ////////////////////////////////
  285. // CAppTreeView::OnExtAddAppServer
  286. //
  287. // Message Handler to add a server beneath a published application
  288. // Pointer to ExtAddTreeNode is in wParam
  289. // Pointer to CAppServer is in lParam
  290. //
  291. LRESULT CAppTreeView::OnExtAddAppServer(WPARAM wParam, LPARAM lParam)
  292. {
  293. ExtAddTreeNode *pExtAddTreeNode = (ExtAddTreeNode*)wParam;
  294. HTREEITEM hParent = pExtAddTreeNode->hParent;
  295. if(!hParent) return 0;
  296. CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
  297. CServer *pServer = pDoc->FindServerByName(pExtAddTreeNode->Name);
  298. LockTreeControl();
  299. CTreeCtrl &tree = GetTreeCtrl();
  300. // First make sure the server isn't already in the tree
  301. // Get the first server under the application
  302. HTREEITEM hItem = tree.GetNextItem(hParent, TVGN_CHILD);
  303. while(hItem) {
  304. // Get the data attached to the tree item
  305. CTreeNode *node = (CTreeNode*)tree.GetItemData(hItem);
  306. if(node) {
  307. // Is this the server we want to add
  308. CAppServer *pAppServer = (CAppServer*)node->GetTreeObject();
  309. if(pAppServer == (CAppServer*)pExtAddTreeNode->pObject) {
  310. UnlockTreeControl();
  311. return 0;
  312. }
  313. }
  314. hItem = tree.GetNextItem(hItem, TVGN_NEXT);
  315. }
  316. CTreeNode* pNode = new CTreeNode(NODE_APP_SERVER, pExtAddTreeNode->pObject);
  317. if(pNode) {
  318. HTREEITEM hServer = AddItemToTree(hParent, pExtAddTreeNode->Name, TVI_SORT,
  319. DetermineServerIcon(pServer), (DWORD)pNode);
  320. if(!hServer) delete pNode;
  321. ((CAppServer*)pExtAddTreeNode->pObject)->SetTreeItem(hServer);
  322. if(pServer) {
  323. // If the server isn't sane, put a not sign over the icon
  324. if(!pServer->IsServerSane()) tree.SetItemState(hServer, STATE_NOT, 0x0F00);
  325. // If we aren't done getting all the information about this server,
  326. // put a question mark over the icon
  327. else if(pServer->IsState(SS_GETTING_INFO)) tree.SetItemState(hServer, STATE_QUESTION, 0x0F00);
  328. }
  329. }
  330. UnlockTreeControl();
  331. return 0;
  332. } // end CAppTreeView::OnExtAddAppServer
  333. ////////////////////////////////
  334. // CAppTreeView::OnExtRemoveAppServer
  335. //
  336. // Message Handler to remove a server from beneath a published application
  337. // Pointer to CPublishedApp is in wParam
  338. // Pointer to CAppServer is in lParam
  339. //
  340. LRESULT CAppTreeView::OnExtRemoveAppServer(WPARAM wParam, LPARAM lParam)
  341. {
  342. ASSERT(wParam);
  343. ASSERT(lParam);
  344. HTREEITEM hServer = ((CAppServer*)lParam)->GetTreeItem();
  345. if(!hServer) return 0;
  346. LockTreeControl();
  347. CTreeCtrl &tree = GetTreeCtrl();
  348. CTreeNode *ServerNode = (CTreeNode*)tree.GetItemData(hServer);
  349. // Remove the Users underneath this server in the tree
  350. HTREEITEM hUser = tree.GetNextItem(hServer, TVGN_CHILD);
  351. while(hUser) {
  352. // Get the data attached to the tree item
  353. CTreeNode *node = (CTreeNode*)tree.GetItemData(hUser);
  354. if(node) {
  355. CWinStation *pWinStation = (CWinStation*)node->GetTreeObject();
  356. pWinStation->SetAppTreeItem(NULL);
  357. delete node;
  358. }
  359. hUser = tree.GetNextItem(hUser, TVGN_NEXT);
  360. }
  361. // Delete the data attached to the tree item
  362. delete ServerNode;
  363. // Let the AppServer know he is no longer in the tree
  364. ((CAppServer*)lParam)->SetTreeItem(NULL);
  365. // Remove the AppServer from the tree
  366. // This SHOULD remove all it's children
  367. GetTreeCtrl().DeleteItem(hServer);
  368. UnlockTreeControl();
  369. return 0;
  370. } // end CAppTreeView::OnExtRemoveAppServer
  371. /////////////////////////////////////////
  372. // CAppTreeView::AddServerChildren
  373. //
  374. // Adds the Users running the published app on a given Server
  375. // to the tree
  376. //
  377. void CAppTreeView::AddServerChildren(HTREEITEM hServer, CServer *pServer)
  378. {
  379. ASSERT(hServer);
  380. ASSERT(pServer);
  381. if(pServer->IsServerSane()) {
  382. LockTreeControl();
  383. HTREEITEM hParent = GetTreeCtrl().GetParentItem(hServer);
  384. HTREEITEM hLastNode = hServer;
  385. CTreeNode *pParentNode = (CTreeNode*)GetTreeCtrl().GetItemData(hParent);
  386. CPublishedApp *pApplication = (CPublishedApp*)pParentNode->GetTreeObject();
  387. pServer->LockWinStationList();
  388. // Get a pointer to the server's list of WinStations
  389. CObList *pWinStationList = pServer->GetWinStationList();
  390. // Iterate through the WinStation list
  391. POSITION pos = pWinStationList->GetHeadPosition();
  392. while(pos) {
  393. CWinStation *pWinStation = (CWinStation*)pWinStationList->GetNext(pos);
  394. // We only care if the user is running this published app
  395. if(pWinStation->GetState() == State_Active
  396. && pWinStation->HasUser()
  397. && pWinStation->IsRunningPublishedApp()
  398. && pWinStation->IsRunningPublishedApp(pApplication->GetName())) {
  399. // Figure out what text to display
  400. CString UserString;
  401. if(wcslen(pWinStation->GetUserName())) {
  402. UserString.Format(TEXT("%s (%s)"), pWinStation->GetName(), pWinStation->GetUserName());
  403. }
  404. else UserString.Format(TEXT("%s"), pWinStation->GetName());
  405. CTreeNode *pNode = new CTreeNode(NODE_WINSTATION, pWinStation);
  406. if(pNode) {
  407. pNode->SetSortOrder(pWinStation->GetSortOrder());
  408. hLastNode = AddItemToTree(hServer, UserString, TVI_SORT,
  409. pWinStation->IsCurrentUser() ? m_idxCurrentUser : m_idxUser, (DWORD)pNode);
  410. if(!hLastNode) delete pNode;
  411. }
  412. // The WinStation wants to know his tree item handle
  413. pWinStation->SetAppTreeItem(hLastNode);
  414. }
  415. }
  416. pServer->UnlockWinStationList();
  417. UnlockTreeControl();
  418. } // end if(pServer->IsServerSane())
  419. } // end CAppTreeView::AddServerChildren
  420. ////////////////////////////////
  421. // CAppTreeView::OnAdminUpdateServer
  422. //
  423. // Message handler to update a Server in the tree
  424. // Pointer to CServer to update is in lParam
  425. //
  426. LRESULT CAppTreeView::OnAdminUpdateServer(WPARAM wParam, LPARAM lParam)
  427. {
  428. ASSERT(lParam);
  429. CServer *pServer = (CServer*)lParam;
  430. if(!pServer) return 0;
  431. LockTreeControl();
  432. // The server can be in the tree more than one place
  433. UINT itemCount = GetTreeCtrl().GetCount();
  434. HTREEITEM hTreeItem = GetTreeCtrl().GetRootItem();
  435. for(UINT i = 0; i < itemCount; i++) {
  436. CTreeNode *node = ((CTreeNode*)GetTreeCtrl().GetItemData(hTreeItem));
  437. if(node) {
  438. // we only care about app servers
  439. if(node->GetNodeType() == NODE_APP_SERVER) {
  440. CAppServer *pAppServer = (CAppServer*)node->GetTreeObject();
  441. // Is it the same server?
  442. if(0 == wcscmp(pAppServer->GetName(), pServer->GetName())) {
  443. USHORT NewState;
  444. // Remember the previous state
  445. USHORT PreviousState = GetTreeCtrl().GetItemState(hTreeItem, 0x0F00);
  446. // Change the icon/overlay for the server
  447. // If the server isn't sane, put a not sign over the icon
  448. if(!pServer->IsServerSane()) NewState = STATE_NOT;
  449. // If we aren't done getting all the information about this server,
  450. // put a question mark over the icon
  451. else if(pServer->IsState(SS_GETTING_INFO)) NewState = STATE_QUESTION;
  452. // If it is fine, we want to remove any overlays from the icon
  453. else NewState = STATE_NORMAL;
  454. // Set the tree item to the new state
  455. GetTreeCtrl().SetItemState(hTreeItem, NewState, 0x0F00);
  456. // If this Server was not opened and now is GOOD,
  457. // add it's children to the tree
  458. if(PreviousState != STATE_NORMAL && pServer->IsState(SS_GOOD)) {
  459. int ServerIcon = DetermineServerIcon(pServer);
  460. GetTreeCtrl().SetItemImage(hTreeItem, ServerIcon, ServerIcon);
  461. AddServerChildren(hTreeItem, pServer);
  462. }
  463. else if(pServer->GetPreviousState() == SS_DISCONNECTING && pServer->IsState(SS_NOT_CONNECTED)) {
  464. int ServerIcon = DetermineServerIcon(pServer);
  465. GetTreeCtrl().SetItemImage(hTreeItem, ServerIcon, ServerIcon);
  466. }
  467. // If we changed the state of this server and it is the currently
  468. // selected node in the tree, we need to send a message to change
  469. // the view
  470. // We also need to make sure this is the currently selected tree
  471. CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
  472. if(NewState != PreviousState && hTreeItem == GetTreeCtrl().GetSelectedItem()
  473. && pDoc->GetCurrentTree() == TREEVIEW_APPS) {
  474. #if 0
  475. LONG Result;
  476. OnSelChange(NULL, &Result);
  477. #endif
  478. ForceSelChange();
  479. }
  480. }
  481. }
  482. }
  483. hTreeItem = GetNextItem(hTreeItem);
  484. }
  485. UnlockTreeControl();
  486. return 0;
  487. } // end CAppTreeView::OnAdminUpdateServer
  488. ////////////////////////////////
  489. // CAppTreeView::AddUser
  490. //
  491. HTREEITEM CAppTreeView::AddUser(CWinStation *pWinStation)
  492. {
  493. ASSERT(pWinStation);
  494. HTREEITEM hWinStation = NULL;
  495. // Find the published app that this WinStation is running in our tree
  496. CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
  497. CPublishedApp *pApplication = pDoc->FindPublishedAppByName(pWinStation->GetPublishedAppName());
  498. CServer *pServer = pWinStation->GetServer();
  499. if(!pApplication) return NULL;
  500. HTREEITEM hApplication = pApplication->GetTreeItem();
  501. if(!hApplication) return NULL;
  502. CTreeCtrl &tree = LockTreeControl();
  503. // Find this WinStation's server under the published application in the tree
  504. HTREEITEM hServer = NULL;
  505. hServer = tree.GetChildItem(hApplication);
  506. while(hServer) {
  507. CTreeNode *pNode = (CTreeNode*)GetTreeCtrl().GetItemData(hServer);
  508. CAppServer *pAppServer = (CAppServer*)pNode->GetTreeObject();
  509. if(0 == wcscmp(pAppServer->GetName(), pServer->GetName())) {
  510. // Figure out what text to display
  511. CString UserString;
  512. if(wcslen(pWinStation->GetUserName())) {
  513. UserString.Format(TEXT("%s (%s)"), pWinStation->GetName(), pWinStation->GetUserName());
  514. }
  515. else UserString.Format(TEXT("%s"), pWinStation->GetName());
  516. CTreeNode *pNewNode = new CTreeNode(NODE_WINSTATION, pWinStation);
  517. if(pNewNode) {
  518. hWinStation = AddItemToTree(hServer, UserString, TVI_SORT,
  519. pWinStation->IsCurrentUser() ? m_idxCurrentUser : m_idxUser, (DWORD)pNewNode);
  520. if(!hWinStation) delete pNewNode;
  521. // The WinStation wants to know his tree item handle
  522. pWinStation->SetAppTreeItem(hWinStation);
  523. }
  524. }
  525. hServer = tree.GetNextSiblingItem(hServer);
  526. }
  527. UnlockTreeControl();
  528. return hWinStation;
  529. }
  530. ////////////////////////////////
  531. // CAppTreeView::OnAdminAddWinStation
  532. //
  533. // Message handler to add a WinStation to the tree
  534. // lParam = pointer to CWinStation to add
  535. // wParam is TRUE if this is replacing a WinStation that was currently selected
  536. //
  537. LRESULT CAppTreeView::OnAdminAddWinStation(WPARAM wParam, LPARAM lParam)
  538. {
  539. ASSERT(lParam);
  540. CWinStation *pWinStation = (CWinStation*)lParam;
  541. if(!pWinStation) return 0;
  542. // If this WinStation isn't running a published App, we
  543. // don't give a damn
  544. if(!pWinStation->IsState(State_Active) || !pWinStation->IsRunningPublishedApp())
  545. return 0;
  546. AddUser(pWinStation);
  547. return 0;
  548. } // end CAppTreeView::OnAdminAddWinStation
  549. ////////////////////////////////
  550. // CAppTreeView::OnAdminUpdateWinStation
  551. //
  552. // Message handler to update a WinStation in the tree
  553. // lParam = pointer to CWinStation to update
  554. //
  555. LRESULT CAppTreeView::OnAdminUpdateWinStation(WPARAM wParam, LPARAM lParam)
  556. {
  557. ASSERT(lParam);
  558. CWinStation *pWinStation = (CWinStation*)lParam;
  559. if(!pWinStation) return 0;
  560. // If this WinStation isn't running a published App, we
  561. // don't give a damn
  562. if(!pWinStation->IsState(State_Active) || !pWinStation->IsRunningPublishedApp())
  563. return 0;
  564. // If this WinStation is already in the tree, we don't want to
  565. // add it again
  566. if(pWinStation->GetAppTreeItem())
  567. return 0;
  568. AddUser(pWinStation);
  569. return 0;
  570. } // end CAppTreeView::OnAdminUpdateWinStation
  571. ////////////////////////////////
  572. // CAppTreeView::OnAdminRemoveWinStation
  573. //
  574. // Message handler to remove a WinStation from the tree
  575. // lParam = pointer to CWinStation to remove
  576. LRESULT CAppTreeView::OnAdminRemoveWinStation(WPARAM wParam, LPARAM lParam)
  577. {
  578. ASSERT(lParam);
  579. BOOL CurrentInTree = FALSE;
  580. CWinStation *pWinStation = (CWinStation*)lParam;
  581. if(!pWinStation) return 0;
  582. HTREEITEM hWinStation = pWinStation->GetAppTreeItem();
  583. if(!hWinStation) return 0;
  584. LockTreeControl();
  585. // Get the data attached to this tree node
  586. CTreeNode *node = (CTreeNode*)GetTreeCtrl().GetItemData(hWinStation);
  587. if(node) {
  588. // Is this the WinStation we want to update
  589. CWinStation *pTreeWinStation = (CWinStation*)node->GetTreeObject();
  590. // Make sure the tree node is correct
  591. if(pTreeWinStation != pWinStation) {
  592. UnlockTreeControl();
  593. return 0;
  594. }
  595. } else {
  596. UnlockTreeControl();
  597. return 0;
  598. }
  599. // Delete the data attached to the tree item
  600. delete node;
  601. // Let the WinStation know he is no longer in the tree
  602. pWinStation->SetAppTreeItem(NULL);
  603. // Is this WinStation currently selected in the tree?
  604. CurrentInTree = (GetTreeCtrl().GetSelectedItem() == hWinStation);
  605. // Remove the WinStation from the tree
  606. GetTreeCtrl().DeleteItem(hWinStation);
  607. // If this WinStation is the currently selected node in the tree,
  608. // make it not so
  609. // This may not be necessary!
  610. CWinAdminDoc *pDoc = (CWinAdminDoc*)((CWinAdminApp*)AfxGetApp())->GetDocument();
  611. if(CurrentInTree && pDoc->GetCurrentTree() == TREEVIEW_APPS)
  612. ((CWinAdminDoc*)GetDocument())->SetCurrentView(VIEW_CHANGING);
  613. UnlockTreeControl();
  614. return 0;
  615. } // end CAppTreeView::OnAdminRemoveWinStation
  616. ////////////////////////////////
  617. // CAppTreeView::OnContextMenu
  618. //
  619. // Message handler called when user wants a context menu
  620. // This happens when the user clicks the right mouse button,
  621. // presses Shift-F10, or presses the menu key on a Windows keyboard
  622. //
  623. void CAppTreeView::OnContextMenu(CWnd* pWnd, CPoint ptScreen)
  624. {
  625. CTreeCtrl &tree = GetTreeCtrl();
  626. UINT flags;
  627. HTREEITEM hItem;
  628. CPoint ptClient = ptScreen;
  629. ScreenToClient(&ptClient);
  630. // If we got here from the keyboard,
  631. if(ptScreen.x == -1 && ptScreen.y == -1) {
  632. hItem = tree.GetSelectedItem();
  633. RECT rect;
  634. tree.GetItemRect(hItem, &rect, 0);
  635. ptScreen.x = rect.left + (rect.right - rect.left)/2;
  636. ptScreen.y = rect.top + (rect.bottom - rect.top)/2;
  637. ClientToScreen(&ptScreen);
  638. }
  639. else {
  640. hItem = tree.HitTest(ptClient, &flags);
  641. if((NULL == hItem) || !(TVHT_ONITEM & flags))
  642. return;
  643. }
  644. // Pop-up the menu
  645. CTreeNode *pNode = (CTreeNode*)tree.GetItemData(hItem);
  646. CWinAdminDoc *pDoc = (CWinAdminDoc*)GetDocument();
  647. pDoc->SetTreeTemp(pNode->GetTreeObject(), (pNode->GetNodeType()));
  648. if(pNode) {
  649. CMenu menu;
  650. UINT nIDResource = 0;
  651. switch(pNode->GetNodeType()) {
  652. case NODE_APP_SERVER:
  653. {
  654. CAppServer *pAppServer = (CAppServer*)pNode->GetTreeObject();
  655. CServer *pServer = ((CWinAdminDoc*)GetDocument())->FindServerByName(pAppServer->GetName());
  656. if(pServer) {
  657. pDoc->SetTreeTemp(pServer, NODE_SERVER);
  658. } else return;
  659. nIDResource = IDR_SERVER_POPUP;
  660. }
  661. break;
  662. case NODE_WINSTATION:
  663. nIDResource = IDR_WINSTATION_TREE_POPUP;
  664. break;
  665. }
  666. if(nIDResource) {
  667. if(menu.LoadMenu(nIDResource)) {
  668. menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON |
  669. TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, AfxGetMainWnd());
  670. }
  671. }
  672. } // end if(pNode)
  673. } // end CAppTreeView::OnContextMenu
  674. ////////////////////////////////
  675. // CAppTreeView::OnRClick
  676. //
  677. // The Tree Common Control sends a WM_NOTIFY of NM_RCLICK when
  678. // the user presses the right mouse button in the tree
  679. //
  680. void CAppTreeView::OnRClick(NMHDR* pNMHDR, LRESULT* pResult)
  681. {
  682. CPoint ptScreen(::GetMessagePos());
  683. LockTreeControl();
  684. // Get a pointer to our document
  685. CWinAdminDoc *doc = (CWinAdminDoc*)GetDocument();
  686. CTreeCtrl &tree = GetTreeCtrl();
  687. UINT flags;
  688. HTREEITEM hItem;
  689. CPoint ptClient = ptScreen;
  690. ScreenToClient(&ptClient);
  691. hItem = tree.HitTest(ptClient, &flags);
  692. if((NULL == hItem) || !(TVHT_ONITEM & flags)) {
  693. UnlockTreeControl();
  694. return;
  695. }
  696. // Pop-up the menu
  697. CTreeNode *pNode = (CTreeNode*)tree.GetItemData(hItem);
  698. CWinAdminDoc *pDoc = (CWinAdminDoc*)GetDocument();
  699. pDoc->SetTreeTemp(pNode->GetTreeObject(), (pNode->GetNodeType()));
  700. if(pNode) {
  701. CMenu menu;
  702. UINT nIDResource = 0;
  703. switch(pNode->GetNodeType()) {
  704. case NODE_APP_SERVER:
  705. {
  706. CAppServer *pAppServer = (CAppServer*)pNode->GetTreeObject();
  707. CServer *pServer = ((CWinAdminDoc*)GetDocument())->FindServerByName(pAppServer->GetName());
  708. if(pServer) {
  709. pDoc->SetTreeTemp(pServer, NODE_SERVER);
  710. } else return;
  711. nIDResource = IDR_SERVER_POPUP;
  712. }
  713. break;
  714. case NODE_WINSTATION:
  715. nIDResource = IDR_WINSTATION_TREE_POPUP;
  716. break;
  717. }
  718. if(nIDResource) {
  719. if(menu.LoadMenu(nIDResource)) {
  720. menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON |
  721. TPM_RIGHTBUTTON, ptScreen.x, ptScreen.y, AfxGetMainWnd());
  722. }
  723. }
  724. } // end if(pNode)
  725. UnlockTreeControl();
  726. } // end CAppTreeView::OnRClick
  727. ////////////////////////////////
  728. // CAppTreeView::OnLButtonDown
  729. //
  730. void CAppTreeView::OnLButtonDown(UINT nFlags, CPoint ptClient)
  731. {
  732. // Figure out what they clicked on
  733. LockTreeControl();
  734. CTreeCtrl &tree = GetTreeCtrl();
  735. UINT flags;
  736. HTREEITEM hItem;
  737. hItem = tree.HitTest(ptClient, &flags);
  738. if((NULL == hItem) || !(TVHT_ONITEM & flags)) {
  739. UnlockTreeControl();
  740. CTreeView::OnLButtonDown(nFlags, ptClient);
  741. return;
  742. }
  743. // We only care about servers
  744. CTreeNode *pNode = (CTreeNode*)tree.GetItemData(hItem);
  745. if(pNode && pNode->GetNodeType() == NODE_APP_SERVER) {
  746. // Is it the same item as is selected
  747. if(hItem == tree.GetSelectedItem()) {
  748. CAppServer *pAppServer = (CAppServer*)pNode->GetTreeObject();
  749. CServer *pServer = ((CWinAdminDoc*)GetDocument())->FindServerByName(pAppServer->GetName());
  750. // Is this server in the "just disconnected" state
  751. // If both previous state and state are SS_NOT_CONNECTED,
  752. // we know the user just disconnected from this server
  753. if(pServer && pServer->IsState(SS_NOT_CONNECTED)) {
  754. UnlockTreeControl();
  755. LONG Result;
  756. OnSelChange(NULL, &Result);
  757. return;
  758. }
  759. }
  760. }
  761. UnlockTreeControl();
  762. CTreeView::OnLButtonDown(nFlags, ptClient);
  763. } // CAppTreeView::OnLButtonDown