namespace Microsoft.VSDesigner.WMI
{
using System;
using System.Management;
using System.Windows.Forms;
using System.Net;
using System.Collections;
using System.Drawing;
using System.Threading;
internal enum ClassFilters
{
ConcreteData,
ConcreteOrHavingConcreteSubclasses,
ExtrinsicEvents,
All
}
// A delegate type for hooking up NS expansion start notifications.
public delegate void NSExpandStartedEventHandler(string nsPath);
// A delegate type for hooking up NS expansion end notifications.
public delegate void NSExpandCompleteEventHandler(string nsPath);
internal class WMIClassTreeView : TreeView
{
class ClassTreeNode : TreeNode
{
public ClassTreeNode (string serverName,
string nsName,
string wmiClass,
string nodeLabel) :
base(nodeLabel)
{
server = serverName;
className = wmiClass;
ns = nsName;
if (nodeLabel == "")
{
base.Text = className;
}
}
private string className = "";
private string server = "";
private string ns = "";
public string ClassName
{
get
{
return className;
}
set
{
className = value;
}
}
public string Server
{
get
{
return server;
}
set
{
server = value;
}
}
public string Namespace
{
get
{
return ns;
}
set
{
ns = value;
}
}
}
private string server = string.Empty;
private string connectAs = null;
private string password = null;
public event NSExpandStartedEventHandler NSExpandStarted;
public event NSExpandCompleteEventHandler NSExpandComplete;
private TreeCancelDialog cancelDlg = null;
private bool bCancelled = false;
private SortedList curClassList = new SortedList(100);
private TreeNode curNSExpanded = null;
private ClassFilters currentFilters;
public WMIClassTreeView(string serverIn,
string user,
string pw,
ClassFilters filters,
string[] expandedNS)
{
server = serverIn;
connectAs = user;
password = pw;
currentFilters = filters;
this.Location = new Point(16, 63);
this.Size = (Size) new Point(200, 270);
this.ShowPlusMinus = true;
this.ShowLines = true;
this.BeforeExpand += (new TreeViewCancelEventHandler(this.BeforeNodeExpand));
this.HideSelection = false;
this.FullRowSelect = true;
this.Sorted = true;
EnumNamespaces("root", 0);
}
public string SelectedClass
{
get
{
if (this.SelectedNode.Parent == null)
{
//ns selected
return string.Empty;
}
return this.SelectedNode.Text;
}
}
public string SelectedNS
{
get
{
if (this.SelectedNode.Parent == null)
{
//ns selected
return this.SelectedNode.Text;
}
else
{
return this.SelectedNode.Parent.Text;
}
}
}
public ClassFilters CurrentFilters
{
get
{
return currentFilters;
}
set
{
if (value == currentFilters)
{
return;
}
currentFilters = value;
//collapse namespaces and delete existing child nodes
//put one dummy node under each NS instead
this.Nodes.Clear();
EnumNamespaces("root", 0);
this.curClassList.Clear();
this.curNSExpanded = null;
}
}
// Invoke the NSExpandStarted event
protected virtual void OnNSExpandStarted(string nsPath)
{
if (NSExpandStarted != null)
NSExpandStarted(nsPath);
}
// Invoke the NSExpandComplete event
protected virtual void OnNSExpandComplete(string nsPath)
{
if (NSExpandComplete != null)
NSExpandComplete(nsPath);
}
protected virtual void BeforeNodeExpand(Object sender, TreeViewCancelEventArgs args)
{
TreeNode curNode = args.Node;
this.OnNSExpandStarted(curNode.Text);
//check that this is a namespace
if (curNode.Parent != null)
{
return;
}
if ((curNode.Nodes.Count == 1 && curNode.Nodes[0].Text == "")) //list is empty
{
ShowClasses( args.Node);
}
}
internal bool ShowClasses(TreeNode curNode)
{
try
{
//check that this is a namespace:
if (curNode.Parent != null)
{
return false;
}
this.Cursor = Cursors.WaitCursor;
curNode.Nodes.Clear();
curNSExpanded = curNode;
curClassList.Clear();
//spawn a thread that would handle cancel dialog
//Thread cancelDlgThread = new Thread (new ThreadStart(CancelDlgThread));
//cancelDlgThread.Start();
string nsPath = WmiHelper.MakeNSPath(server, curNSExpanded.Text);
ConnectionOptions connectOpts = new ConnectionOptions(
"", //locale
this.connectAs, //username
this.password, //password
"", //authority
ImpersonationLevel.Impersonate,
AuthenticationLevel.Connect,
true, //enablePrivileges
null //context
);
ManagementScope scope = (this.server == WmiHelper.DNS2UNC(Dns.GetHostName())) ?
new ManagementScope(nsPath):
new ManagementScope(nsPath, connectOpts);
QueryOptions enumOpts = new QueryOptions(null, //context
new TimeSpan(Int64.MaxValue), //timeout
50, //block size
false, //non-rewindable
true, //return immediately
true, //use amended quals
true, //ensure locatable
false, //prototype only
false //direct read
);
ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope,
new ObjectQuery("select * from meta_class"),
enumOpts);
ManagementObjectCollection objs = searcher.Get();
ManagementObjectCollection.ManagementObjectEnumerator objEnum = objs.GetEnumerator();
while (objEnum.MoveNext() && !bCancelled)
{
ManagementClass obj = (ManagementClass)objEnum.Current;
if (FilterPass(obj))
{
TreeNode child = new TreeNode(obj.Path.RelativePath);
curNSExpanded.Nodes.Add(child);
//curClassList.Add(obj.Path.RelativePath, obj.Path.RelativePath);
}
}
if (!bCancelled)
{
/*
for (int i = 0; i < curClassList.Count; i++)
{
//TreeNode child = new TreeNode(curClassList.GetByIndex(i).ToString());
//curNSExpanded.Nodes.Add(child);
}
cancelDlg.DialogResult = DialogResult.None;
cancelDlg.Hide();
cancelDlg.Dispose();
cancelDlg = null;
*/
}
else
{
curClassList.Clear();
//re-set NS node:
curNSExpanded.Nodes.Clear();
//show the node
TreeNode dummy = new TreeNode("");
curNSExpanded.Nodes.Add(dummy);
curNSExpanded.Collapse();
}
this.OnNSExpandComplete(curNode.Text);
this.Cursor = Cursors.Default;
return true;
}
catch (Exception e)
{
MessageBox.Show(WMISys.GetString("WMISE_Exception", e.Message, e.StackTrace));
this.Cursor = Cursors.Default;
return false;
}
}
private void CancelDlgThread ()
{
try
{
if (cancelDlg != null)
{
cancelDlg.Hide();
cancelDlg.Dispose();
cancelDlg = null;
}
cancelDlg = new TreeCancelDialog(WMISys.GetString("WMISE_PleaseWait", curNSExpanded.Text),
this.Location.X + 40,
this.Location.Y + 40);
DialogResult res = cancelDlg.ShowDialog();
if (res == DialogResult.Cancel)
{
bCancelled = true;
}
}
catch (Exception e)
{
MessageBox.Show(WMISys.GetString("WMISE_Exception", e.Message, e.StackTrace));
}
}
private bool EnumNamespaces(string parent, int num)
//recursively adds namespaces to the drop-down box
{
try
{
//show the node
TreeNode dummy = new TreeNode("");
TreeNode[] children = new TreeNode[] {dummy};
TreeNode nsNode = new TreeNode(parent,
//(int)schema_icons.SCHEMA_NS_CLOSED,
//(int)schema_icons.SCHEMA_NS_CLOSED,
children);
nsNode.Collapse();
this.Nodes.Insert(num, nsNode);
string nsPath = WmiHelper.MakeClassPath(server, parent, "__NAMESPACE");
string nsScopePath = WmiHelper.MakeNSPath(server, parent);
ConnectionOptions connectOpts = new ConnectionOptions("", //locale
this.connectAs, //username
this.password, //password
"", //authority
ImpersonationLevel.Impersonate,
AuthenticationLevel.Connect,
true, //enablePrivileges
null //context
);
ManagementScope scope = (this.server == WmiHelper.DNS2UNC(Dns.GetHostName())) ?
new ManagementScope(nsScopePath):
new ManagementScope(nsScopePath, connectOpts);
ManagementClass nsClass = new ManagementClass(scope,
new ManagementPath(nsPath),
new ObjectGetOptions(null, true));
ManagementObjectCollection subNSCollection = nsClass.GetInstances();
IEnumerator eInstances = ((IEnumerable)subNSCollection).GetEnumerator();
while(eInstances.MoveNext())
{
num++;
ManagementObject obj = (ManagementObject)eInstances.Current;
PropertyCollection props = (PropertyCollection)obj.Properties;
string NameOut = "";
string curName = props["Name"].Value.ToString();
//skip localized namespace
//NOTE: this assumes that localized namespaces are always leaf
if (curName.ToUpper().IndexOf("MS_", 0) == 0)
{
continue;
}
//skip root\security namespace (we don't want to expose it)
if (curName.ToUpper() == "SECURITY" && parent.ToUpper() == "ROOT")
{
continue;
}
//skip root\directory\ldap namespace (BUGBUG: change this in Beta2 when we can do asynchronous class enumerations)
if (curName.ToUpper() == "LDAP" && parent.ToUpper() == "ROOT\\DIRECTORY")
{
continue;
}
if (parent != "")
{
NameOut = parent + "\\" + curName;
}
else
{
NameOut = curName;
}
EnumNamespaces(NameOut, num);
}
return true;
}
catch (Exception e)
{
MessageBox.Show(WMISys.GetString("WMISE_Exception", e.Message, e.StackTrace));
return false;
}
}
///
/// This returns false if the object should be filtered out according to currentFilters value
///
///
private bool FilterPass (ManagementClass obj)
{
switch (currentFilters)
{
case (ClassFilters.ConcreteData) :
{
if (!WmiHelper.IsAbstract(obj) &&
!WmiHelper.IsAssociation(obj))
return true;
else
return false;
}
case (ClassFilters.ConcreteOrHavingConcreteSubclasses) :
{
if(!WmiHelper.IsAbstract(obj) ||
WmiHelper.HasNonAbstractChildren(obj))
return true;
else
return false;
}
case (ClassFilters.ExtrinsicEvents) :
{
if (WmiHelper.IsEvent(obj))
return true;
else
return false;
}
case (ClassFilters.All) :
{
return true;
}
default :
break;
}
return true;
}
}
internal class TreeCancelDialog : Form
{
private Button cancelBtn = new Button();
private Label text = new Label();
private void InitializeComponent ()
{
this.ClientSize = (Size)new Point(250, 100);
this.ShowInTaskbar = false;
this.MinimizeBox = false;
this.MaximizeBox = false;
this.AcceptButton = cancelBtn;
this.BorderStyle = FormBorderStyle.FixedSingle;
this.AutoScaleBaseSize = (Size) new Point(5, 13);
text.Location = new Point(15, 15);
text.TabStop = false;
text.Size = (Size) new Point(200, 25);
cancelBtn.Location = new Point(95, 70);
cancelBtn.DialogResult = DialogResult.Cancel;
cancelBtn.Text = WMISys.GetString("WMISE_Cancel");
cancelBtn.TabStop = true;
}
public TreeCancelDialog(string textIn, int x, int y)
{
InitializeComponent();
text.Text = textIn;
this.Location = new Point(x, y);
this.Controls.Add(cancelBtn);
this.Controls.Add(text);
}
}
}