home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 39 / IOPROG_39.ISO / SOFT / sdkjava40.exe / data1.cab / fg_Samples / Samples / Profiler / heapmon / objview.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-04  |  46.4 KB  |  1,435 lines

  1. // objview.cpp
  2. //
  3. // Created 10/08/98
  4. //
  5. // (C)Copyright 1998-1999 Microsoft Corporation, All rights reserved.
  6. //
  7.  
  8. #include "pch.hpp"
  9. #pragma hdrstop
  10.  
  11. #include "objview.hpp"
  12. #include "hpmonmgr.hpp"
  13. #include "resource.h"
  14. #include "refsview.hpp"
  15. #include "ansibuf.hpp"
  16. #include "instview.hpp"
  17.  
  18.  
  19. BOOL ObjectViewer::s_fRegisteredClass = FALSE;
  20.  
  21.  
  22. BOOL ObjectViewer::MoveSlider (LPARAM lParam)
  23. {
  24.     if (GetCapture() == m_hwnd)
  25.     {
  26.         LONG x = (SHORT)LOWORD(lParam);
  27.         //LONG y = HIWORD(lParam);
  28.  
  29.         RECT rc;
  30.         GetClientRect(m_hwnd, &rc);
  31.  
  32.         if (x < 0)
  33.             x = 0;
  34.         if (x+m_sliderwid > rc.right)
  35.             x = rc.right-m_sliderwid;
  36.  
  37.         MoveWindow(m_htree, 0, 0, x, rc.bottom, TRUE);
  38.  
  39.         LONG textx = x+m_sliderwid;
  40.         MoveWindow(m_htext, textx, 0, rc.right-textx, rc.bottom, TRUE);
  41.  
  42.         return TRUE;
  43.     }
  44.  
  45.     return FALSE;
  46. }
  47.  
  48.  
  49. VOID ObjectViewer::ClearText ()
  50. {
  51.     SetWindowText(m_htext, "");
  52. }
  53.  
  54.  
  55. //static
  56. LRESULT CALLBACK ObjectViewer::_WndProc (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
  57. {
  58.     ObjectViewer *ov = (ObjectViewer*)GetWindowLong(wnd, GWL_USERDATA);
  59.     if (ov != NULL)
  60.         return ov->WndProc(wnd, msg, wParam, lParam);
  61.     return BaseWndProc(wnd, msg, wParam, lParam);
  62. }
  63.  
  64.  
  65. LRESULT CALLBACK ObjectViewer::WndProc (HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam)
  66. {
  67.     switch (msg)
  68.     {
  69.     case WM_SIZE:
  70.         {
  71.             LONG w = LOWORD(lParam);
  72.             LONG h = HIWORD(lParam);
  73.             if (w < m_sliderright)
  74.             {
  75.                 m_sliderright = w;
  76.                 m_sliderleft = w - m_sliderwid;
  77.             }
  78.             MoveWindow(m_htree, 0,                 0, m_sliderleft,    h, TRUE);
  79.             MoveWindow(m_htext, m_sliderright, 0, w-m_sliderright, h, TRUE);
  80.         }
  81.         break;
  82.  
  83.     case WM_LBUTTONDOWN:
  84.         SetCapture(wnd);
  85.         return 0;
  86.  
  87.     case WM_MOUSEMOVE:
  88.         if (MoveSlider(lParam))
  89.             return 0;
  90.         break;
  91.  
  92.     case WM_LBUTTONUP:
  93.         if (MoveSlider(lParam))
  94.         {
  95.             ReleaseCapture();
  96.             return 0;
  97.         }
  98.         break;
  99.  
  100.     case WM_NOTIFY:
  101.         {
  102.             LPNMHDR pnmh = (NMHDR*)lParam; 
  103.             switch (pnmh->code)
  104.             {
  105.             case TVN_SELCHANGED:
  106.                 {
  107.                     NM_TREEVIEW *pnmtv = (NM_TREEVIEW*)lParam;
  108.                     TV_ITEM *ptvi = &pnmtv->itemNew;
  109.                     if (ptvi->hItem != NULL)
  110.                     {
  111.                         ANSIStringBuffer buf;
  112.                         if (GetItemDetailText(ptvi->hItem, &buf))
  113.                         {
  114.                             SetWindowText(m_htext, buf.GetStr());
  115.                             return 0;
  116.                         }
  117.                     }
  118.                     SetWindowText(m_htext, "");
  119.                 }
  120.                 break;
  121.  
  122.             case NM_RCLICK:
  123.                 {
  124.                     TVHITTESTINFO tvhtti;
  125.                     
  126.                     DWORD screenpos = GetMessagePos();
  127.                     tvhtti.pt.x = LOWORD(screenpos);
  128.                     tvhtti.pt.y = HIWORD(screenpos);
  129.  
  130.                     RECT rc;
  131.                     GetWindowRect(m_htree, &rc);
  132.                     tvhtti.pt.x -= rc.left;
  133.                     tvhtti.pt.y -= rc.top;
  134.                     
  135.                     HTREEITEM htisel = TreeView_HitTest(m_htree, &tvhtti);
  136.                     if (htisel != NULL)
  137.                     {
  138.                         TreeView_Select(m_htree, htisel, TVGN_CARET);
  139.  
  140.                         TV_ITEM tvi;
  141.                         tvi.mask = TVIF_IMAGE | TVIF_PARAM;
  142.                         tvi.hItem = htisel;
  143.                         if (   TreeView_GetItem(m_htree, &tvi)
  144.                             && (tvi.mask & TVIF_PARAM))
  145.                         {
  146.                             ObjectID vmid = NULL;
  147.                             ID id = NULL;
  148.                             
  149.                             if (   !(tvi.mask & TVIF_IMAGE)
  150.                                 || (ObjectViewerTreeItemTypes)tvi.iImage == HVTII_OBJECT)
  151.                             {
  152.                                 vmid = tvi.lParam;
  153.                                 id = m_mgr->LookupID(vmid);
  154.                             }
  155.                             else if (tvi.iImage >= HVTII_OBJID && tvi.iImage <= HVTII_LAST_OBJID)
  156.                             {
  157.                                 id = (ID)tvi.lParam;
  158.                                 vmid = id->vmid;
  159.                             }
  160.                             else if (tvi.iImage >= HVTII_FIRST_ID)
  161.                             {
  162.                                 id = (ID)tvi.lParam;
  163.                                 if (id->type == ID_OBJECT && !(id->flags & OID_FL_DEAD))
  164.                                     vmid = id->vmid;
  165.                             }
  166.  
  167.                             if ((id || vmid) && OnRightClickItem(id, vmid, wnd, screenpos))
  168.                                 return 0;
  169.                         }
  170.                     }
  171.                 }
  172.                 break;
  173.  
  174.             case TVN_GETDISPINFO:
  175.                 {
  176.                     TV_DISPINFO *ptvdi = (TV_DISPINFO*)lParam;
  177.                     TV_ITEM *ptvi = &ptvdi->item;
  178.                     if (ptvi->mask & (TVIF_TEXT | TVIF_SELECTEDIMAGE))
  179.                     {
  180.                         if (ptvi->mask & TVIF_TEXT)
  181.                         {
  182.                             PSTR psz = ptvi->pszText;
  183.                             int cchTextMax = ptvi->cchTextMax;
  184.                             if (   ptvi->cchTextMax > 0
  185.                                 && GetItemText(ptvi->hItem, psz, cchTextMax))
  186.                             {
  187.                                 ;
  188.                             }
  189.                             else
  190.                             {
  191.                                 *ptvi->pszText = '\0';
  192.                             }
  193.                         }
  194.  
  195.                         if (ptvi->mask & TVIF_SELECTEDIMAGE)
  196.                         {
  197.                             TV_ITEM tvi;
  198.                             tvi.hItem = ptvi->hItem;
  199.                             tvi.mask = TVIF_IMAGE;
  200.                             if (TreeView_GetItem(m_htree, &tvi))
  201.                                 ptvi->iSelectedImage = tvi.iImage;
  202.                             else
  203.                                 break;
  204.                         }
  205.  
  206.                         return 0;
  207.                     }
  208.                 }
  209.                 break;
  210.  
  211.             case TVN_ITEMEXPANDING:
  212.                 {
  213.                     NMTREEVIEW *pnmtv = (NMTREEVIEW*)lParam;
  214.                     TV_ITEM *ptvi = &pnmtv->itemNew;
  215.                     if (pnmtv->action & TVE_EXPAND)
  216.                     {
  217.                         TV_ITEM tvi;
  218.  
  219.                         BOOL fIsObject = FALSE;
  220.  
  221.                         if (ptvi->mask & TVIF_IMAGE)
  222.                         {
  223.                             if (IsObjectType((ObjectViewerTreeItemTypes)ptvi->iImage))
  224.                             {
  225.                                 fIsObject = TRUE;
  226.  
  227.                                 if (!(ptvi->mask & TVIF_PARAM))
  228.                                 {
  229.                                     tvi.mask = TVIF_IMAGE | TVIF_PARAM;
  230.                                     tvi.hItem = ptvi->hItem;
  231.                                     
  232.                                     if (   TreeView_GetItem(m_htree, &tvi)
  233.                                         && (tvi.mask & (TVIF_IMAGE | TVIF_PARAM)) == (TVIF_IMAGE | TVIF_PARAM))
  234.                                     {
  235.                                         ptvi = &tvi;
  236.                                     }
  237.                                     else
  238.                                     {
  239.                                         fIsObject = FALSE;
  240.                                     }
  241.                                 }
  242.                             }
  243.                         }
  244.                         else
  245.                         {
  246.                             fIsObject = TRUE;
  247.  
  248.                             if (!(ptvi->mask & TVIF_PARAM))
  249.                             {
  250.                                 tvi.mask = TVIF_PARAM;
  251.                                 tvi.hItem = ptvi->hItem;
  252.                                 if (   TreeView_GetItem(m_htree, &tvi)
  253.                                     && (tvi.mask & TVIF_PARAM))
  254.                                 {
  255.                                     ptvi = &tvi;
  256.                                 }
  257.                                 else
  258.                                 {
  259.                                     fIsObject = FALSE;
  260.                                 }
  261.                             }
  262.                         }
  263.  
  264.                         if (fIsObject)
  265.                         {
  266.                             ASSERT(m_mgr->IsStopped());
  267.  
  268.                             ObjectID vmid;
  269.                             OBJID id;
  270.                         
  271.                             if (  !(ptvi->mask & TVIF_IMAGE)
  272.                                 || ptvi->iImage == HVTII_OBJECT)
  273.                             {
  274.                                 vmid = (ObjectID)ptvi->lParam;
  275.                                 id = NULL;
  276.                             }
  277.                             else
  278.                             {
  279.                                 id = (OBJID)ptvi->lParam;
  280.                                 vmid = id->vmid;
  281.                             }
  282.  
  283.                             AddReferencesInfo info;
  284.                             info.ov = this;
  285.                             info.hti = ptvi->hItem;
  286.                             
  287.                             HeapMonitorManager::ExpandObjectResults res;
  288.                             res = m_mgr->ExpandObject(vmid, &id, &AddObjectIDReferences, &AddOBJIDReferences, &info);
  289.                             if (res != HeapMonitorManager::EOR_FAILED)
  290.                             {
  291.                                 BOOL fHasReferences = res != HeapMonitorManager::EOR_NO_REFERENCES;
  292.                             
  293.                                 if (!fHasReferences)
  294.                                 {
  295.                                     tvi.mask = TVIF_CHILDREN;
  296.                                     tvi.hItem = ptvi->hItem;
  297.                                     tvi.cChildren = 0;
  298.                                     TreeView_SetItem(m_htree, &tvi);
  299.                                 }
  300.  
  301.                                 RedrawTree();
  302.  
  303.                                 return !fHasReferences;
  304.                             }
  305.                         }
  306.                     }
  307.                 }
  308.                 break;
  309.  
  310.             case TVN_ITEMEXPANDED:
  311.                 {
  312.                     NMTREEVIEW *pnmtv = (NMTREEVIEW*)lParam;
  313.                     TV_ITEM *ptvi = &pnmtv->itemNew;
  314.                     if (pnmtv->action & TVE_COLLAPSE)
  315.                     {
  316.                         ObjectViewerTreeItemTypes type;
  317.                         LPARAM tvilParam;
  318.                         
  319.                         if ((ptvi->mask & (TVIF_IMAGE | TVIF_PARAM)) == (TVIF_IMAGE | TVIF_PARAM))
  320.                         {
  321.                             type = (ObjectViewerTreeItemTypes)ptvi->iImage;
  322.                             tvilParam = ptvi->lParam;
  323.                         }
  324.                         else
  325.                         {
  326.                             TV_ITEM tvi;
  327.                             tvi.mask = (TVIF_IMAGE | TVIF_PARAM);
  328.                             tvi.hItem = ptvi->hItem;
  329.                             if (   TreeView_GetItem(m_htree, &tvi)
  330.                                 && (tvi.mask & TVIF_PARAM))
  331.                             {
  332.                                 if (!(tvi.mask & TVIF_IMAGE))
  333.                                     type = HVTII_OBJECT;
  334.                                 else
  335.                                     type = (ObjectViewerTreeItemTypes)tvi.iImage;
  336.                                 tvilParam = tvi.lParam;
  337.                             }
  338.                             else
  339.                             {
  340.                                 break;
  341.                             }
  342.                         }
  343.  
  344.                         if (IsObjectType(type))
  345.                         {
  346.                             for (;;)
  347.                             {
  348.                                 HTREEITEM htichild = TreeView_GetChild(m_htree, ptvi->hItem);
  349.                                 if (htichild == NULL)
  350.                                     break;
  351.                                 TreeView_DeleteItem(m_htree, htichild);
  352.                             }
  353.  
  354.                             TV_ITEM tvi;
  355.                             tvi.hItem = ptvi->hItem;
  356.                             tvi.mask = TVIF_CHILDREN;
  357.                             tvi.cChildren = 1;
  358.                             TreeView_SetItem(m_htree, &tvi);
  359.  
  360.                             return 0;
  361.                         }
  362.                     }
  363.                 }
  364.                 break;
  365.  
  366.             case TVN_BEGINLABELEDIT:
  367.                 {
  368.                     NMTVDISPINFO *ptvdi = (NMTVDISPINFO*)lParam;
  369.                     TVITEM tvi;
  370.                     tvi.hItem = ptvdi->item.hItem;
  371.                     tvi.mask = TVIF_PARAM | TVIF_IMAGE;
  372.                     if (   TreeView_GetItem(m_htree, &tvi)
  373.                         && (tvi.mask & TVIF_IMAGE))
  374.                     {
  375.                         switch ((ObjectViewerTreeItemTypes)tvi.iImage)
  376.                         {
  377.                         case HVTII_FOLDER:
  378.                         case HVTII_UNLOADED_CLASS:
  379.                         case HVTII_DEAD_THREAD:
  380.                             return TRUE;
  381.  
  382.                         default:
  383.                             if (tvi.iImage > HVTII_FIRST_ID)
  384.                                 return TRUE;
  385.                             break;
  386.                         }
  387.                     }
  388.                 }
  389.                 break;
  390.  
  391.             case TVN_ENDLABELEDIT:
  392.                 {
  393.                     NMTVDISPINFO *ptvdi = (NMTVDISPINFO*)lParam;
  394.  
  395.                     TVITEM tvi;
  396.                     tvi.hItem = ptvdi->item.hItem;
  397.                     tvi.mask = TVIF_PARAM | TVIF_IMAGE;
  398.                     if (   TreeView_GetItem(m_htree, &tvi)
  399.                         && (tvi.mask & TVIF_PARAM))
  400.                     {
  401.                         if (ptvdi->item.pszText != NULL)
  402.                         {
  403.                             OBJID id;
  404.                             if (!(tvi.mask & TVIF_IMAGE) || tvi.iImage == HVTII_OBJECT)
  405.                                 id = m_mgr->LookupObject((ObjectID)tvi.lParam);
  406.                             else if (IsObjectType((ObjectViewerTreeItemTypes)tvi.iImage))
  407.                                 id = (OBJID)tvi.lParam;
  408.                             else
  409.                                 break;
  410.  
  411.                             if (id != NULL)
  412.                                 m_mgr->SetObjectTag(id, ptvdi->item.pszText);
  413.                             
  414.                             return TRUE;
  415.                         }
  416.                     }
  417.                 }
  418.                 break;
  419.             }
  420.         }
  421.         break;
  422.  
  423.     case WM_OVEVENT_PERMIT_EXPANSION:
  424.         WalkTree(0, &PermitItemExpansionCB, this);
  425.         return 0;
  426.  
  427.     case WM_OVEVENT_CLEAR_TRANSIENTS:
  428.         WalkTree(0, &DeleteTransientItemsCB, this);
  429.         return 0;
  430.  
  431.     case WM_OVEVENT_OBJECT_CHANGE:
  432.         WalkTree(0, &UpdateObjectStatusCB, (PVOID)lParam);
  433.         return 0;
  434.     }
  435.  
  436.     return BaseWndProc(wnd, msg, wParam, lParam);
  437. }
  438.  
  439.  
  440. BOOL ObjectViewer::OnCreateWindow ()
  441. {
  442.     BOOL result;
  443.  
  444.     HINSTANCE hinst = m_mgr->GetInstance();
  445.  
  446.     RECT rc;
  447.  
  448.     GetClientRect(m_hwnd, &rc);
  449.  
  450.     m_sliderwid = GetSystemMetrics(SM_CXDLGFRAME);
  451.  
  452.     LONG sliderpos = rc.left+(rc.right-rc.left)/2;
  453.     m_sliderleft = sliderpos-m_sliderwid/2;
  454.     m_sliderright = m_sliderleft+m_sliderwid;
  455.  
  456.     result = (m_htree = CreateWindowEx(
  457.             0,
  458.             WC_TREEVIEW,
  459.             "tv",
  460.             WS_VISIBLE | WS_CHILD | WS_BORDER | WS_HSCROLL | WS_VSCROLL
  461.                 | TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS | TVS_EDITLABELS,
  462.             rc.left, rc.top, m_sliderleft, rc.bottom,
  463.             m_hwnd,
  464.             NULL,
  465.             hinst,
  466.             NULL)) != NULL;
  467.  
  468.     HIMAGELIST himages = NULL;
  469.  
  470.     if (result)
  471.     {
  472.         result = (himages = ImageList_LoadBitmap(hinst, MAKEINTRESOURCE(IDB_TREEIMAGES), 16, 0, CLR_NONE)) != NULL;
  473.     }
  474.  
  475.     if (result)
  476.     {
  477.         TreeView_SetImageList(m_htree, himages, TVSIL_NORMAL);
  478.  
  479.         result = (m_htext = CreateWindowEx(
  480.                 0,
  481.                 "Edit",
  482.                 "",
  483.                 WS_VISIBLE | WS_CHILD | WS_BORDER | WS_HSCROLL | WS_VSCROLL
  484.                     | ES_AUTOHSCROLL | ES_AUTOVSCROLL | ES_LEFT | ES_MULTILINE | ES_READONLY,
  485.                 m_sliderright, rc.top, rc.right-m_sliderright, rc.bottom,
  486.                 m_hwnd,
  487.                 NULL,
  488.                 hinst,
  489.                 NULL)) != NULL;
  490.     }
  491.  
  492.     return result;
  493. }
  494.  
  495.  
  496. BOOL ObjectViewer::OnRightClickItem (ID id, UniqueID vmid, HWND wnd, DWORD screenpos)
  497. {
  498.     if (!id && vmid || id && id->type == ID_OBJECT)
  499.     {
  500.         OBJID obj = (OBJID)id;
  501.                 
  502.         HMENU hpopup = LoadMenu(m_mgr->GetInstance(), MAKEINTRESOURCE(IDR_HEAPVIEW_OBJ_POPUP));
  503.         if (hpopup != NULL)
  504.         {
  505.             hpopup = GetSubMenu(hpopup, 0);
  506.             if (hpopup != NULL)
  507.             {
  508.                 if (obj != NULL)
  509.                 {
  510.                     if (obj->flags & OID_FL_DEAD)
  511.                     {
  512.                         MENUITEMINFO mii;
  513.                         mii.cbSize = sizeof(mii);
  514.                         mii.fMask = MIIM_STATE;
  515.                         mii.fState = MFS_DISABLED;
  516.                         SetMenuItemInfo(hpopup, IDM_OBJPOPUP_FINDREFERENCES, FALSE, &mii);
  517.                     }
  518.  
  519.                     if (obj->flags & OID_FL_TRACKED)
  520.                     {
  521.                         MENUITEMINFO mii;
  522.                         mii.cbSize = sizeof(mii);
  523.                         mii.fMask = MIIM_STATE;
  524.                         mii.fState = MFS_CHECKED;
  525.                         SetMenuItemInfo(hpopup, IDM_OBJPOPUP_TRACK, FALSE, &mii);
  526.                     }
  527.                 }
  528.  
  529.                 // Return value is really a menu item id if TPM_RETURNCMD is specified.
  530.                 WORD cmd = (WORD)TrackPopupMenu(
  531.                         hpopup,
  532.                         TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
  533.                         LOWORD(screenpos), HIWORD(screenpos),
  534.                         0,
  535.                         wnd,
  536.                         NULL);
  537.                 if (cmd != 0)
  538.                 {
  539.                     switch (cmd)
  540.                     {
  541.                     case IDM_OBJPOPUP_FINDREFERENCES:
  542.                         FindObjectReferences(vmid);
  543.                         return TRUE;
  544.  
  545.                     case IDM_OBJPOPUP_TRACK:
  546.                         ToggleObjectTracking(obj, vmid);
  547.                         return TRUE;
  548.  
  549.                     case IDM_OBJPOPUP_TAG:
  550.                         TagObject(vmid);
  551.                         return TRUE;
  552.                     }
  553.                 }
  554.             }
  555.         }
  556.     }
  557.     else if (id && id->type == ID_CLASS)
  558.     {
  559.         HMENU hpopup = LoadMenu(m_mgr->GetInstance(), MAKEINTRESOURCE(IDR_HEAPVIEW_CLS_POPUP));
  560.         if (hpopup != NULL)
  561.         {
  562.             hpopup = GetSubMenu(hpopup, 0);
  563.             if (hpopup != NULL)
  564.             {
  565.                 // Return value is really a menu item id if TPM_RETURNCMD is specified.
  566.                 WORD cmd = (WORD)TrackPopupMenu(
  567.                         hpopup,
  568.                         TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD,
  569.                         LOWORD(screenpos), HIWORD(screenpos),
  570.                         0,
  571.                         wnd,
  572.                         NULL);
  573.                 if (cmd != 0)
  574.                 {
  575.                     switch (cmd)
  576.                     {
  577.                     case IDM_CLSPOPUP_FINDINSTANCES:
  578.                         {
  579.                             ClassInstancesViewer *civ = new(ClassInstancesViewer());
  580.                             if (civ != NULL)
  581.                             {
  582.                                 civ->Initialize(m_mgr, (CLASSID)id);
  583.  
  584.                                 civ->Release();
  585.                             }
  586.                         }
  587.                         return TRUE;
  588.                     }
  589.                 }
  590.             }
  591.         }
  592.     }
  593.  
  594.     return FALSE;
  595. }
  596.  
  597.  
  598. BOOL ObjectViewer::GetItemText (HTREEITEM hti, PSTR &psztext, int &cchmaxtext)
  599. {
  600.     BOOL result;
  601.  
  602.     TV_ITEM tvi;
  603.     tvi.hItem = hti;
  604.     tvi.mask = TVIF_PARAM | TVIF_IMAGE;
  605.     result = (   TreeView_GetItem(m_htree, &tvi)
  606.               && (tvi.mask & (TVIF_PARAM | TVIF_IMAGE)) == (TVIF_PARAM | TVIF_IMAGE));
  607.     if (result)
  608.     {
  609.         ObjectViewerTreeItemTypes type = (ObjectViewerTreeItemTypes)tvi.iImage;
  610.  
  611.         switch (type)
  612.         {
  613.         case HVTII_OBJID:
  614.         case HVTII_MULTIREF_OBJID:
  615.         case HVTII_TRACKED_OBJID:
  616.         case HVTII_MULTIREF_TRACKED_OBJID:
  617.         case HVTII_OBJECT:
  618.         case HVTII_DEAD_OBJID:
  619.             {
  620.                 int needed = 8;
  621.                 if (type == HVTII_DEAD_OBJID)
  622.                     needed = 0;
  623.  
  624.                 result = (cchmaxtext > needed);
  625.                 if (result)
  626.                 {
  627.                     ObjectID vmid;
  628.                     OBJID id;
  629.                     if (type == HVTII_OBJECT)
  630.                     {
  631.                         vmid = (ObjectID)tvi.lParam;
  632.                         id = NULL;
  633.                     }
  634.                     else
  635.                     {
  636.                         id = (OBJID)tvi.lParam;
  637.                         vmid = id->vmid;
  638.                     }
  639.                         
  640.                     if (id == NULL || !(id->flags & OID_FL_TAGGED))
  641.                     {
  642.                         if (id == NULL || !(id->flags & OID_FL_DEAD))
  643.                         {
  644.                             wsprintf(psztext, "%08x", vmid);
  645.                             needed++;
  646.                         }
  647.  
  648.                         if (cchmaxtext > needed+1)
  649.                         {
  650.                             IJavaEventMonitorIDInfo2 *vminfo = m_mgr->GetVMInfoInterface();
  651.                         
  652.                             ClassID clsid;
  653.  
  654.                             if (id == NULL || !(id->flags & OID_FL_DEAD))
  655.                                 result = (vminfo->ObjectInformation(vmid, &clsid) == S_OK);
  656.                             else
  657.                                 clsid = m_mgr->GetClassOfDeadObject(id);
  658.  
  659.                             if (result)
  660.                             {
  661.                                 PSTR clsnameutf8;
  662.                                 result = (vminfo->ClassInformation(clsid, &clsnameutf8, NULL, NULL, NULL, NULL) == S_OK);
  663.                                 if (result)
  664.                                 {
  665.                                     // TODO: ANSI conversion
  666.                                     int len = min((unsigned)cchmaxtext-needed, strlen(clsnameutf8));
  667.                                     if (needed)
  668.                                         psztext[needed-1] = ' ';
  669.                                     CopyMemory(psztext+needed, clsnameutf8, len);
  670.                                     psztext[needed+len] = '\0';
  671.  
  672.                                     CoTaskMemFree(clsnameutf8);
  673.                                 }
  674.                             }
  675.  
  676.                             vminfo->Release();
  677.                         }
  678.                     }
  679.                     else
  680.                     {
  681.                         m_mgr->Enter();
  682.                         {
  683.                             PCSTR tag = m_mgr->GetObjectTag(id);
  684.                             ASSERT(tag != NULL);
  685.                             int len = min((unsigned)cchmaxtext, strlen(tag));
  686.                             CopyMemory(psztext, tag, len);
  687.                             psztext[len] = '\0';
  688.                         }
  689.                         m_mgr->Leave();
  690.                     }
  691.                 }
  692.             }
  693.             break;
  694.                 
  695.         default:
  696.             if (type >= HVTII_FIRST_ID)
  697.             {
  698.                 CHAR *p = psztext;
  699.                 BOOL fCoFree = FALSE;
  700.  
  701.                 ID id = (ID)tvi.lParam;
  702.                 PCSTR text = m_mgr->FetchIDFriendlyName(id);
  703.                 result = (text != NULL);
  704.                 if (!result)
  705.                 {
  706.                     switch (id->type)
  707.                     {
  708.                         CONTAINER_TYPE rt_type;
  709.  
  710.                     case ID_THREAD:
  711.                     case ID_GHOST_THREAD:
  712.  
  713.                         // TODO: use thread name (provided by JVM_EVENT_TYPE2_THREAD_SET_NAME)
  714.  
  715.                         if (cchmaxtext > 10)
  716.                         {
  717.                             IJavaEventMonitorIDInfo2 *vminfo = m_mgr->GetVMInfoInterface();
  718.  
  719.                             DWORD tid;
  720.                             if (vminfo->ThreadInformation(id->vmid, &tid) == S_OK)
  721.                             {
  722.                                 result = TRUE;
  723.  
  724.                                 wsprintf(psztext, "0x%08x", tid);
  725.                             }
  726.  
  727.                             vminfo->Release();
  728.                         }
  729.                         break;
  730.  
  731.                     case ID_STACKFRAME:
  732.                         if (cchmaxtext > 8)
  733.                         {
  734.                             result = TRUE;
  735.                             
  736.                             wsprintf(psztext, "%08x", id->vmid);
  737.                         
  738.                             if (cchmaxtext > 10)
  739.                             {
  740.                                 p[8] = ' ';
  741.                                 cchmaxtext -= 9;
  742.                                 p += 9;
  743.                             
  744.                                 STACKID stkid = (STACKID)id;
  745.                                 MethodID methodid = stkid->methodid;
  746.                                 if (methodid != NULL)
  747.                                 {
  748.                                     IJavaEventMonitorIDInfo2 *vminfo = m_mgr->GetVMInfoInterface();
  749.                                 
  750.                                     result = (vminfo->MethodInformation(methodid, (PSTR*)&text, NULL, NULL, NULL, NULL) == S_OK);
  751.                                     if (result)
  752.                                     {
  753.                                         // TODO: ANSI conversion
  754.                                         fCoFree = TRUE;
  755.                                     }
  756.  
  757.                                     vminfo->Release();
  758.                                 }
  759.                                 else
  760.                                 {
  761.                                     rt_type = stkid->frmtype;
  762.                                     goto describe_root;
  763.                                 }
  764.                             }
  765.                         }
  766.                         break;
  767.  
  768.                     case ID_ROOT:
  769.                         {
  770.                             rt_type = ((ROOTID)id)->roottype;
  771.  
  772.                 describe_root:
  773.                         
  774.                             text = m_mgr->GetVerboseContainerName(rt_type);
  775.                             result = (text != NULL);
  776.                         }
  777.                         break;
  778.                     }
  779.                 }
  780.  
  781.                 if (result && text != NULL)
  782.                 {
  783.                     int len = strlen(text);
  784.                     len = min(len, cchmaxtext-1);
  785.                     CopyMemory(p, text, len);
  786.                     p[len] = '\0';
  787.  
  788.                     if (fCoFree)
  789.                         CoTaskMemFree((PSTR)text);
  790.                 }
  791.             }
  792.             break;
  793.         }
  794.     }
  795.  
  796.     return result;
  797. }
  798.  
  799.  
  800. BOOL ObjectViewer::GetItemDetailText (HTREEITEM hti, ANSIStringBuffer *buf)
  801. {
  802.     BOOL ret = FALSE;
  803.  
  804.     if (m_mgr->IsStopped())
  805.     {
  806.         TV_ITEM tvi;
  807.  
  808.         tvi.hItem = hti;
  809.         tvi.mask = TVIF_IMAGE | TVIF_PARAM;
  810.         if (TreeView_GetItem(m_htree, &tvi))
  811.         {
  812.             TV_ITEM *ptvi= &tvi;
  813.             ObjectID objid;
  814.             if (  !(ptvi->mask & TVIF_IMAGE)
  815.                 || ptvi->iImage == HVTII_OBJECT)
  816.             {
  817.                 objid = (ObjectID)ptvi->lParam;
  818.             }
  819.             else
  820.             {
  821.                 ObjectViewerTreeItemTypes type = (ObjectViewerTreeItemTypes)ptvi->iImage;
  822.                 if (IsObjectType(type))
  823.                 {
  824.                     OBJID id = (OBJID)ptvi->lParam;
  825.                     if (id->flags & OID_FL_DEAD)
  826.                         return FALSE;
  827.                     objid = id->GetObjectID();
  828.                 }
  829.                 else if (type == (ObjectViewerTreeItemTypes)(HVTII_FIRST_ID + ID_STACKFRAME))
  830.                 {
  831.                     STACKID id = (STACKID)ptvi->lParam;
  832.                     PCSTR descr = m_mgr->GetVerboseContainerName(id->frmtype);
  833.                     if (descr != NULL)
  834.                     {
  835.                         buf->Append(descr);
  836.                         buf->Append("\r\n");
  837.                         return TRUE;
  838.                     }
  839.                     
  840.                     return FALSE;
  841.                 }
  842.                 else
  843.                 {
  844.                     return FALSE;
  845.                 }
  846.             }
  847.  
  848.             IJavaEventMonitorIDInfo2 *pvminfo = m_mgr->GetVMInfoInterface();
  849.             
  850.             ClassID clsid;
  851.             if (pvminfo->ObjectInformation(objid, &clsid) == S_OK)
  852.             {
  853.                 // Check if this is a special class that the vm can display better.
  854.  
  855.                 CLASSID cls = m_mgr->LookupClass(clsid);
  856.                 if (cls && (cls->flags & CID_FL_HAS_DESCRIPTION))
  857.                 {
  858.                     PWSTR descr;
  859.                     if (pvminfo->DescribeObject(objid, &descr) == S_OK)
  860.                     {
  861.                         buf->Append(descr);
  862.                         buf->Append("\r\n");
  863.                         ret = TRUE;
  864.                         
  865.                         CoTaskMemFree(descr);
  866.                     }
  867.                 }
  868.  
  869.                 DWORD objsize;
  870.                 if (pvminfo->GetObjectSize(objid, &objsize) == S_OK)
  871.                 {
  872.                     CHAR sizestr[16];
  873.                     wsprintf(sizestr, "%u", objsize);
  874.                     buf->Append("Object size: ");
  875.                     buf->Append(sizestr);
  876.                     buf->Append(" bytes\r\n");
  877.                 }
  878.  
  879.                 if (!ret && cls)
  880.                 {
  881.                     unsigned nfields = cls->flds->nfields;
  882.                     FieldInfo *flds = &cls->flds->fldinfo[0];
  883.                 
  884.                     for (unsigned i = 0; i < nfields; i++)
  885.                     {
  886.                         PSTR fldname = flds[i].name;
  887.                     
  888.                         buf->AppendUtf8(fldname);
  889.  
  890.                         __int64 value;
  891.                         if (pvminfo->GetObjectField(objid, flds[i].id, &value) == S_OK)
  892.                         {
  893.                             buf->Append(" = ");
  894.  
  895.                             char *fmt = NULL;
  896.  
  897.                             if (flds[i].flags & JVM_FIELD_OBJECTREF)
  898.                             {
  899.                                 if (value)
  900.                                 {
  901.                                     buf->Append("object 0x");
  902.                                     fmt = "%x";
  903.                                 }
  904.                                 else
  905.                                 {
  906.                                     buf->Append("null");
  907.                                 }
  908.                             }
  909.                             else if (strncmp(fldname, "long ", 5) == 0)
  910.                             {
  911.                                 char tmp[100];
  912.                                 sprintf(tmp, "%I64d", value);
  913.                                 buf->Append(tmp);
  914.                             }
  915.                             else if (strncmp(fldname, "float ", 6) == 0)
  916.                             {
  917.                                 union {
  918.                                     int i;
  919.                                     float f;
  920.                                 } v;
  921.                                 v.i = (int)value;
  922.                                 
  923.                                 char tmp[100];
  924.                                 sprintf(tmp, "%g", v.f);
  925.                                 buf->Append(tmp);
  926.                             }
  927.                             else if (strncmp(fldname, "double ", 7) == 0)
  928.                             {
  929.                                 union {
  930.                                     __int64 l;
  931.                                     double d;
  932.                                 } v;
  933.                                 v.l = value;
  934.                                 
  935.                                 char tmp[100];
  936.                                 sprintf(tmp, "%lg", v.d);
  937.                                 buf->Append(tmp);
  938.                             }
  939.                             else if (strncmp(fldname, "boolean ", 8) == 0)
  940.                             {
  941.                                 buf->Append(value ? "true" : "false");
  942.                             }
  943.                             else
  944.                             {
  945.                                 fmt = "%d";
  946.                             }
  947.  
  948.                             if (fmt)
  949.                             {
  950.                                 char tmp[9];
  951.                                 sprintf(tmp, fmt, (int)value);
  952.                                 buf->Append(tmp);
  953.                             }
  954.                         }
  955.  
  956.                         buf->Append("\r\n");
  957.                     }
  958.  
  959.                     ret = TRUE;
  960.                 }
  961.             }
  962.  
  963.             pvminfo->Release();
  964.         }
  965.     }
  966.  
  967.     return ret;
  968. }
  969.  
  970.  
  971. //static
  972. ObjectViewer::ObjectViewerTreeItemTypes ObjectViewer::GetTreeItemTypeForID (ID id)
  973. {
  974.     ObjectViewerTreeItemTypes type;
  975.     if (id->type != ID_OBJECT)
  976.     {
  977.         type = (ObjectViewerTreeItemTypes)(HVTII_FIRST_ID + id->type);
  978.     }
  979.     else
  980.     {
  981.         OBJID obj = (OBJID)id;
  982.  
  983.         if (!(obj->flags & OID_FL_DEAD))
  984.         {
  985.             if (obj->flags & OID_FL_MULTIPLE_REFERENCES)
  986.                 type = HVTII_MULTIREF_OBJID;
  987.             else
  988.                 type = HVTII_OBJID;
  989.  
  990.             if (obj->flags & OID_FL_TRACKED)
  991.                 type = (ObjectViewerTreeItemTypes)(type + 1);
  992.         }
  993.         else
  994.         {
  995.             type = HVTII_DEAD_OBJID;
  996.         }
  997.     }
  998.     return type;
  999. }
  1000.  
  1001.  
  1002. BOOL ObjectViewer::GetTreeItemTypeInfo (HTREEITEM hti, ObjectViewerTreeItemTypes *ptype, PVOID *ptoken)
  1003. {
  1004.     TV_ITEM tvi;
  1005.     tvi.mask = TVIF_IMAGE | TVIF_PARAM;
  1006.     tvi.hItem = hti;
  1007.     BOOL ret = (   TreeView_GetItem(m_htree, &tvi)
  1008.                 && (tvi.mask & TVIF_PARAM));
  1009.     if (ret)
  1010.     {
  1011.         ObjectViewerTreeItemTypes type = HVTII_OBJECT;
  1012.         if (tvi.mask & TVIF_IMAGE)
  1013.             type = (ObjectViewerTreeItemTypes)tvi.iImage;
  1014.         *ptype = type;
  1015.         *ptoken = (PVOID)tvi.lParam;
  1016.     }
  1017.     return ret;
  1018. }
  1019.  
  1020.  
  1021. HTREEITEM ObjectViewer::AddTreeItem (HTREEITEM htiParent, HTREEITEM htiafter, ObjectViewerTreeItemTypes type, PVOID token)
  1022. {
  1023.     TVINSERTSTRUCT tvis;
  1024.     ZeroMemory(&tvis, sizeof(tvis));
  1025.     tvis.hParent = htiParent;
  1026.     tvis.hInsertAfter = htiafter;
  1027.     tvis.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  1028.     tvis.item.iImage = type;
  1029.     tvis.item.iSelectedImage = I_IMAGECALLBACK;
  1030.     tvis.item.pszText = LPSTR_TEXTCALLBACK;
  1031.     tvis.item.lParam = (LPARAM)token;
  1032.  
  1033.     if (IsObjectType(type) && m_mgr->IsStopped())
  1034.     {
  1035.         tvis.item.mask |= TVIF_CHILDREN;
  1036.         tvis.item.cChildren = 1;
  1037.     }
  1038.  
  1039.     return TreeView_InsertItem(m_htree, &tvis);
  1040. }
  1041.  
  1042.  
  1043. HTREEITEM ObjectViewer::AddTreeItemForID (HTREEITEM htiParent, ID id, BOOL fPermitDuplicates)
  1044. {
  1045.     ASSERT(fPermitDuplicates || !FindChildItemForID(htiParent, id));
  1046.     return AddTreeItem(htiParent, GetTreeItemTypeForID(id), id);
  1047. }
  1048.  
  1049.  
  1050. HTREEITEM ObjectViewer::AddTreeItemForID (HTREEITEM htiParent, HTREEITEM htiAfter, ID id, BOOL fPermitDuplicates)
  1051. {
  1052.     ASSERT(fPermitDuplicates || !FindChildItemForID(htiParent, id));
  1053.     return AddTreeItem(htiParent, htiAfter, GetTreeItemTypeForID(id), id);
  1054. }
  1055.  
  1056.  
  1057. HTREEITEM ObjectViewer::AddTreeItemForReferencedID (HTREEITEM htiParent, ID id)
  1058. {
  1059.     return AddTreeItemForID(htiParent, id, TRUE);
  1060. }
  1061.  
  1062.  
  1063. HTREEITEM ObjectViewer::AddTreeItemForReferencedID (HTREEITEM htiParent, HTREEITEM htiAfter, ID id, BOOL fPermitDuplicates)
  1064. {
  1065.     return AddTreeItemForID(htiParent, htiAfter, id, TRUE);
  1066. }
  1067.  
  1068.  
  1069. HTREEITEM ObjectViewer::AddStaticTreeItem (HTREEITEM htiParent, PCSTR text, ObjectViewerTreeItemTypes img)
  1070. {
  1071.     TVINSERTSTRUCT tvis;
  1072.     ZeroMemory(&tvis, sizeof(tvis));
  1073.     tvis.hParent = htiParent;
  1074.     tvis.hInsertAfter = TVI_LAST;
  1075.     tvis.item.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE;
  1076.     tvis.item.pszText = (PSTR)text;
  1077.     tvis.item.iImage = img;
  1078.     tvis.item.iSelectedImage = I_IMAGECALLBACK;
  1079.  
  1080.     return TreeView_InsertItem(m_htree, &tvis);
  1081. }
  1082.  
  1083.  
  1084. HTREEITEM ObjectViewer::AddTreeItem (HTREEITEM htiParent, ObjectViewerTreeItemTypes type, PVOID token)
  1085. {
  1086.     return AddTreeItem(htiParent, TVI_LAST, type, token);
  1087. }
  1088.  
  1089.  
  1090. HTREEITEM ObjectViewer::AddTreeItemForObject (HTREEITEM htiParent, ObjectID vmid)
  1091. {
  1092.     TVINSERTSTRUCT tvis;
  1093.     ZeroMemory(&tvis, sizeof(tvis));
  1094.     tvis.hParent = htiParent;
  1095.     tvis.hInsertAfter = TVI_LAST;
  1096.     tvis.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_SELECTEDIMAGE;
  1097.     tvis.item.pszText = LPSTR_TEXTCALLBACK;
  1098.     tvis.item.lParam = (LPARAM)vmid;
  1099.     tvis.item.iSelectedImage = I_IMAGECALLBACK;
  1100.  
  1101.     if (m_mgr->IsStopped())
  1102.     {
  1103.         tvis.item.cChildren = 1;
  1104.         tvis.item.mask |= TVIF_CHILDREN;
  1105.     }
  1106.  
  1107.     return TreeView_InsertItem(m_htree, &tvis);
  1108. }
  1109.  
  1110.  
  1111. VOID ObjectViewer::DeleteTreeItem (HTREEITEM hti)
  1112. {
  1113.     EVAL(TreeView_DeleteItem(m_htree, hti));
  1114. }
  1115.  
  1116.  
  1117. BOOL ObjectViewer::WalkTree (DWORD flags, PWALKTREECBFN pfn, PVOID token)
  1118. {
  1119.     return ::WalkTree(m_htree, NULL, flags, pfn, token);
  1120. }
  1121.  
  1122.  
  1123. HTREEITEM ObjectViewer::FindChildItemForID (HTREEITEM htiParent, ID id)
  1124. {
  1125.     HTREEITEM htichild = TreeView_GetChild(m_htree, htiParent);
  1126.     return FindNextSiblingForID(htichild, id);
  1127. }
  1128.  
  1129.  
  1130. HTREEITEM ObjectViewer::FindNextSiblingForID (HTREEITEM htichild, ID id)
  1131. {
  1132.     while (htichild != NULL)
  1133.     {
  1134.         TV_ITEM tvi;
  1135.         tvi.mask = TVIF_PARAM | TVIF_IMAGE;
  1136.         tvi.hItem = htichild;
  1137.         if (   TreeView_GetItem(m_htree, &tvi)
  1138.             && (tvi.iImage >= HVTII_FIRST_ID || (tvi.iImage <= HVTII_DEAD_OBJID && tvi.iImage != HVTII_OBJECT))
  1139.             && tvi.lParam == (LPARAM)id)
  1140.         {
  1141.             break;
  1142.         }
  1143.         
  1144.         htichild = TreeView_GetNextSibling(m_htree, htichild);
  1145.     }
  1146.     return htichild;
  1147. }
  1148.  
  1149.  
  1150. HTREEITEM ObjectViewer::CreateRoot (HTREEITEM *proot, PCSTR name, ObjectViewerTreeItemTypes img)
  1151. {
  1152.     HTREEITEM root = AddStaticTreeItem(TVI_ROOT, name, img);
  1153.     if (root == NULL)
  1154.         root = TVI_ROOT;
  1155.     return *proot = root;
  1156. }
  1157.  
  1158.  
  1159. BOOL ObjectViewer::ShouldDeleteTransientObject (HTREEITEM hti, OBJID obj)
  1160. {
  1161.     return TRUE;
  1162. }
  1163.  
  1164.  
  1165. //static
  1166. int ObjectViewer::AddObjectIDReferences (ObjectID vmid, PVOID token)
  1167. {
  1168.     AddReferencesInfo *info = (AddReferencesInfo*)token;
  1169.  
  1170.     return info->ov->AddTreeItemForObject(info->hti, vmid) != NULL;
  1171. }
  1172.  
  1173.  
  1174. //static
  1175. int ObjectViewer::AddOBJIDReferences (OBJID id, PVOID token)
  1176. {
  1177.     AddReferencesInfo *info = (AddReferencesInfo*)token;
  1178.  
  1179.     return info->ov->AddTreeItem(info->hti, GetTreeItemTypeForID(id), id) != NULL;
  1180. }
  1181.  
  1182.  
  1183. //static
  1184. WalkTreeCBResults ObjectViewer::UpdateObjectStatusCB (HWND htree, HTREEITEM hti, PVOID token)
  1185. {
  1186.     OBJID obj = (OBJID)token;
  1187.  
  1188.     WalkTreeCBResults result = WTCB_CONTINUE;
  1189.  
  1190.     TV_ITEM tvi;
  1191.     tvi.mask = TVIF_IMAGE | TVIF_PARAM;
  1192.     tvi.hItem = hti;
  1193.     if (   TreeView_GetItem(htree, &tvi)
  1194.         && (tvi.mask & TVIF_PARAM))
  1195.     {
  1196.         BOOL fModified = FALSE;
  1197.  
  1198.         if (obj->flags & OID_FL_DEAD)
  1199.         {
  1200.             if (   (tvi.mask & TVIF_IMAGE)
  1201.                 && tvi.iImage == HVTII_DEAD_OBJID
  1202.                 && !(obj->flags & ALL_OID_NONTRANSIENT_FLAGS))
  1203.             {
  1204.                 result = WTCB_DELETE;
  1205.                 fModified = TRUE;
  1206.             }
  1207.         }
  1208.         else
  1209.         {
  1210.             if (   !(tvi.mask & TVIF_IMAGE)
  1211.                 || tvi.iImage == HVTII_OBJECT)
  1212.             {
  1213.                 if (tvi.lParam == (LPARAM)obj->GetObjectID())
  1214.                 {
  1215.                     tvi.mask = TVIF_IMAGE | TVIF_PARAM;
  1216.                     tvi.lParam = (LPARAM)obj;
  1217.                     tvi.iImage = GetTreeItemTypeForID(obj);
  1218.                     TreeView_SetItem(htree, &tvi);
  1219.                     fModified = TRUE;
  1220.                 }
  1221.             }
  1222.             else
  1223.             {
  1224.                 ObjectViewerTreeItemTypes newtype;;
  1225.         
  1226.                 if (   IsObjectType((ObjectViewerTreeItemTypes)tvi.iImage)
  1227.                     && (OBJID)tvi.lParam == obj
  1228.                     && tvi.iImage != (newtype = GetTreeItemTypeForID(obj)))
  1229.                 {
  1230.                     tvi.mask = TVIF_IMAGE;
  1231.                     tvi.iImage = newtype;
  1232.                     TreeView_SetItem(htree, &tvi);
  1233.                     fModified = TRUE;
  1234.                 }
  1235.             }
  1236.         }
  1237.  
  1238.         if (!fModified)
  1239.         {
  1240.             // Something changed, but we didn't need to do anything special.
  1241.             // Just force it to be repainted.
  1242.  
  1243.             RECT rc;
  1244.             if (TreeView_GetItemRect(htree, hti, &rc, FALSE))
  1245.             {
  1246.                 InvalidateRect(htree, &rc, TRUE);
  1247.             }
  1248.         }
  1249.     }
  1250.  
  1251.     return result;
  1252. }
  1253.  
  1254.  
  1255. BOOL ObjectViewer::FindObjectReferences (ObjectID vmid)
  1256. {
  1257.     ASSERT(vmid);
  1258.  
  1259.     BOOL result;
  1260.  
  1261.     ObjectReferencesViewer *orv = new(ObjectReferencesViewer());
  1262.     result = (orv != NULL);
  1263.     if (result)
  1264.     {
  1265.         result = orv->Initialize(m_mgr, vmid);
  1266.  
  1267.         orv->Release();
  1268.     }
  1269.  
  1270.     return result;
  1271. }
  1272.  
  1273.  
  1274. VOID ObjectViewer::ToggleObjectTracking (OBJID obj, ObjectID vmid)
  1275. {
  1276.     m_mgr->ToggleObjectTracking(obj, vmid);
  1277. }
  1278.  
  1279.  
  1280. VOID ObjectViewer::TagObject (ObjectID vmid)
  1281. {
  1282.     ASSERT(vmid);
  1283.  
  1284.     HTREEITEM htisel = TreeView_GetSelection(m_htree);
  1285.     if (EVAL(htisel))
  1286.         TreeView_EditLabel(m_htree, htisel);
  1287. }
  1288.  
  1289.  
  1290. //static
  1291. WalkTreeCBResults ObjectViewer::DeleteTransientItemsCB (HWND htree, HTREEITEM hti, PVOID token)
  1292. {
  1293.     WalkTreeCBResults result = WTCB_CONTINUE;
  1294.  
  1295.     TV_ITEM tvi;
  1296.     tvi.mask = TVIF_PARAM | TVIF_IMAGE;
  1297.     tvi.hItem = hti;
  1298.     if (TreeView_GetItem(htree, &tvi))
  1299.     {
  1300.         if (tvi.mask & TVIF_IMAGE)
  1301.         {
  1302.             ObjectViewerTreeItemTypes type = (ObjectViewerTreeItemTypes)tvi.iImage;
  1303.  
  1304.             for (;;)
  1305.             {
  1306.                 switch (type)
  1307.                 {
  1308.                 case HVTII_OBJECT:
  1309.                 case HVTII_OBJID:
  1310.                 case HVTII_MULTIREF_OBJID:
  1311.                 case HVTII_TRACKED_OBJID:
  1312.                 case HVTII_MULTIREF_TRACKED_OBJID:
  1313.                 case HVTII_DEAD_OBJID:
  1314.                     if (tvi.mask & TVIF_PARAM)
  1315.                     {
  1316.                         OBJID obj = (OBJID)tvi.lParam;
  1317.  
  1318.                         if (   (obj->flags & ALL_OID_NONTRANSIENT_FLAGS)
  1319.                             && !((ObjectViewer*)token)->ShouldDeleteTransientObject(hti, obj))
  1320.                         {
  1321.                             // This has the useful side-effect of causing a
  1322.                             // '+' to appear when PermitItemExpansionCB
  1323.                             // applies the "has children" status.
  1324.                             TreeView_Expand(htree, hti, TVE_COLLAPSE);
  1325.                         
  1326.                             tvi.mask = TVIF_CHILDREN;
  1327.                             tvi.cChildren = 0;
  1328.                             EVAL(TreeView_SetItem(htree, &tvi));
  1329.  
  1330.                             break;
  1331.                         }
  1332.                     }
  1333.                     // fall through
  1334.                 case HVTII_UNLOADED_CLASS:
  1335.                 case HVTII_DEAD_THREAD:
  1336.                     result = WTCB_DELETE;
  1337.                     break;
  1338.  
  1339.                 default:
  1340.                     if (type >= (HVTII_FIRST_ID + ID_FIRST_TRANSIENT))
  1341.                         result = WTCB_DELETE;
  1342.                     break;
  1343.                 }
  1344.  
  1345.                 break;
  1346.             }
  1347.         }
  1348.         else
  1349.         {
  1350.             result = WTCB_DELETE;
  1351.         }
  1352.     }
  1353.     else
  1354.     {
  1355.         ASSERT(!"huh?");
  1356.     }
  1357.  
  1358.     return result;
  1359. }
  1360.  
  1361.  
  1362. //static
  1363. WalkTreeCBResults ObjectViewer::PermitItemExpansionCB (HWND htree, HTREEITEM hti, PVOID token)
  1364. {
  1365.     TV_ITEM tvi;
  1366.     tvi.mask = TVIF_PARAM | TVIF_IMAGE;
  1367.     tvi.hItem = hti;
  1368.     if (TreeView_GetItem(htree, &tvi))
  1369.     {
  1370.         if (tvi.mask & TVIF_IMAGE)
  1371.         {
  1372.             ObjectViewerTreeItemTypes type = (ObjectViewerTreeItemTypes)tvi.iImage;
  1373.  
  1374.             switch (type)
  1375.             {
  1376.             case HVTII_OBJECT:
  1377.             case HVTII_OBJID:
  1378.             case HVTII_MULTIREF_OBJID:
  1379.             case HVTII_TRACKED_OBJID:
  1380.             case HVTII_MULTIREF_TRACKED_OBJID:
  1381.             case HVTII_DEAD_OBJID:
  1382.                 tvi.mask = TVIF_CHILDREN;
  1383.                 tvi.cChildren = 1;
  1384.                 EVAL(TreeView_SetItem(htree, &tvi));
  1385.                 break;
  1386.             }
  1387.         }
  1388.     }
  1389.  
  1390.     return WTCB_CONTINUE;
  1391. }
  1392.  
  1393.  
  1394. BOOL ObjectViewer::OVPreInitialize (HeapMonitorManager *mgr, PCSTR wndtitle)
  1395. {
  1396.     BOOL result = TRUE;
  1397.  
  1398.     if (!s_fRegisteredClass)
  1399.     {
  1400.         WNDCLASS wc;
  1401.         ZeroMemory(&wc, sizeof(wc));
  1402.         wc.lpfnWndProc = &_WndProc;
  1403.         wc.hInstance = mgr->GetInstance();
  1404.         wc.lpszClassName = WC_HEAPMONITOR_OBJVIEWER;
  1405.         wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  1406.         wc.hCursor = LoadCursor(NULL, IDC_SIZEWE);
  1407.         result = RegisterClass(&wc);
  1408.  
  1409.         s_fRegisteredClass = result;
  1410.     }
  1411.  
  1412.     if (result)
  1413.     {
  1414.         result = BasePreInitialize(mgr, WC_HEAPMONITOR_OBJVIEWER, wndtitle);
  1415.     }
  1416.  
  1417.     return result;
  1418. }
  1419.  
  1420.  
  1421. BOOL ObjectViewer::OVPostInitialize (HeapMonitorClientRegistrationInfo *preginfo)
  1422. {
  1423.     HeapMonitorClientRegistrationInfo reginfo;
  1424.     if (!preginfo)
  1425.     {
  1426.         ZeroMemory(®info, sizeof(reginfo));
  1427.         preginfo = ®info;
  1428.     }
  1429.  
  1430.     preginfo->StoppedEventMask |= HMC_OBJECT_EVENTS;
  1431.  
  1432.     return BasePostInitialize(preginfo);
  1433. }
  1434.  
  1435.