Skip to content

Commit

Permalink
Added new filter to drive discovery
Browse files Browse the repository at this point in the history
Added the filter 'network' to 'drive.discovery' key.
Some code tidy.
Code fixed from NativeVolume class for avoid exceptions.
Improved code from NativeVolume class for better performance.
  • Loading branch information
Fabricio Godoy committed Apr 2, 2014
1 parent e805080 commit 0499703
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 69 deletions.
96 changes: 67 additions & 29 deletions zbxlld-win/Discovery/Drive.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class Drive : IArgHandler
const string ARG_DRIVE_NOMOUNT = ARG_DRIVE + ".nomount";
const string ARG_DRIVE_SWAP = ARG_DRIVE + ".swap";
const string ARG_DRIVE_NOSWAP = ARG_DRIVE + ".noswap";
const string ARG_DRIVE_NETWORK = ARG_DRIVE + ".network";
const string CLASS_FULL_PATH = "zbxlld.Windows.Discovery.Drive";

static Drive def = new Drive();
Expand All @@ -51,6 +52,42 @@ private Drive()
{
}

private bool TryGetVolumesViaWmi(out Supplement.IVolumeInfo[] vols)
{
vols = null;

try
{
vols = Supplement.Win32_Volume.GetAllVolumes();
}
catch (System.OutOfMemoryException e)
{
if (MainClass.DEBUG)
{
MainClass.WriteLogEntry(string.Format("{0}.GetOutput: Out of memory exception.", CLASS_FULL_PATH));
MainClass.WriteLogEntry("Exception:");
MainClass.WriteLogEntry(e.ToString());
}
// TODO: Make a proper exit
Console.WriteLine("You have insufficient permissions or insufficient memory.");
Environment.Exit((int)ErrorId.GetAllVolumesOutOfMemory);
}
catch (Exception e)
{
if (MainClass.DEBUG)
{
MainClass.WriteLogEntry(string.Format(
"{0}.GetOutput: Unexpected exception.", CLASS_FULL_PATH));
MainClass.WriteLogEntry("Exception:");
MainClass.WriteLogEntry(e.ToString());
}
vols = null;
return false;
}

return true;
}

#region IArgHandler implementation

public Supplement.JsonOutput GetOutput(string key)
Expand All @@ -61,6 +98,7 @@ public Supplement.JsonOutput GetOutput(string key)
bool nomount = false;
bool swap = false;
bool noswap = false;
bool onlyNative = false;

DriveType dtype;
switch (key) {
Expand Down Expand Up @@ -94,35 +132,34 @@ public Supplement.JsonOutput GetOutput(string key)
dtype = DriveType.Fixed;
noswap = true;
break;
case ARG_DRIVE_NETWORK:
dtype = DriveType.Network;
onlyNative = true;
break;
default:
return null;
}

Supplement.JsonOutput jout = new Supplement.JsonOutput ();

Supplement.IVolumeInfo[] vols = null;
try {
vols = Supplement.Win32_Volume.GetAllVolumes();
} catch (System.OutOfMemoryException e) {
if (MainClass.DEBUG)
{
MainClass.WriteLogEntry(string.Format("{0}.GetOutput: Out of memory exception.", CLASS_FULL_PATH));
MainClass.WriteLogEntry("Exception:");
MainClass.WriteLogEntry(e.ToString());
}
Console.WriteLine("You have insufficient permissions or insufficient memory.");
Environment.Exit((int)ErrorId.GetAllVolumesOutOfMemory);
} catch (Exception e) {
// Fallback to native method
if (MainClass.DEBUG)

if (onlyNative)
{
vols = Supplement.NativeVolume.GetVolumes();
}
else
{
if (!TryGetVolumesViaWmi(out vols))
{
MainClass.WriteLogEntry(string.Format(
"{0}.GetOutput: Fallback to native method.", CLASS_FULL_PATH));
MainClass.WriteLogEntry("Exception:");
MainClass.WriteLogEntry(e.ToString());
if (MainClass.DEBUG)
MainClass.WriteLogEntry(string.Format("{0}.GetOutput: Fallback to native method.", CLASS_FULL_PATH));

// Fallback to native method
vols = Supplement.NativeVolume.GetVolumes();
}
vols = Supplement.NativeVolume.GetVolumes();
}
}

if (MainClass.DEBUG)
{
MainClass.WriteLogEntry(string.Format("{0}.GetOutput: got volumes. " +
Expand All @@ -145,14 +182,14 @@ public Supplement.JsonOutput GetOutput(string key)
ismounted = v.IsMounted;
ismletter = (v.DriveLetter != null);

if (v.Automount &&
v.DriveType == dtype &&
(!mounted || ismounted) &&
(!mfolder || (ismounted && !ismletter)) &&
(!mletter || (ismounted && ismletter)) &&
(!nomount || !ismounted) &&
(!swap || v.PageFilePresent) &&
(!noswap || !v.PageFilePresent)) {
if (v.Automount && // Match to drives mounted automatically
v.DriveType == dtype && // Match drive type
(!mounted || ismounted) && // If defined to mounted drives, then match mounted drives
(!mfolder || (ismounted && !ismletter)) && // If defined to folder mounted drives, then match mounted and not has letter
(!mletter || (ismounted && ismletter)) && // If defined to letter mounted drives, then match mounted and has letter
(!nomount || !ismounted) && // If defined to not mounted drives, then match not mounted drives
(!swap || v.PageFilePresent) && // If defined to drives that has page files, then match to drives that has page file
(!noswap || !v.PageFilePresent)) { // If defined to drives that no page files, then match to drives that has no page file
Dictionary<string, string> item =
new Dictionary<string, string> (2);

Expand Down Expand Up @@ -185,7 +222,8 @@ string[] IArgHandler.GetAllowedArgs()
ARG_DRIVE_MLETTER,
ARG_DRIVE_NOMOUNT,
ARG_DRIVE_SWAP,
ARG_DRIVE_NOSWAP
ARG_DRIVE_NOSWAP,
ARG_DRIVE_NETWORK
};
}

Expand Down
4 changes: 2 additions & 2 deletions zbxlld-win/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ class MainClass
public const string PROGRAM_NAME = "zbxlld-win";
// Latest release: 0.6.1.22
// Major.Minor.Maintenance.Build
public const string PROGRAM_VERSION = "0.6.2.27";
public const string PROGRAM_VERSION_SIMPLE = "0.6.2";
public const string PROGRAM_VERSION = "0.7.0.30";
public const string PROGRAM_VERSION_SIMPLE = "0.7";
public const string PROGRAM_TITLE = PROGRAM_NAME + " " + PROGRAM_VERSION_SIMPLE + PROGRAM_TITLE_SUFFIX;
static Logger log = null;

Expand Down
106 changes: 71 additions & 35 deletions zbxlld-win/Supplement/NativeVolume.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Author:
// Fabricio Godoy <skarllot@gmail.com>
//
// Copyright (c) 2013 Fabricio Godoy
// Copyright (c) 2014 Fabricio Godoy
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -33,6 +33,7 @@ public class NativeVolume : IVolumeInfo
const string KEY_VALUE_PREFIX = @"\DosDevices\";
const string KEY_VALUE_GUID_PREFIX = @"\??\Volume";
DriveInfo dinfo;
Guid? volGuid;

public NativeVolume(DriveInfo dinfo)
{
Expand Down Expand Up @@ -89,9 +90,13 @@ public bool IsMounted {
}

public string Label {
get {
return dinfo.VolumeLabel;
}
get
{
if (dinfo.IsReady)
return dinfo.VolumeLabel;
else
return null;
}
}

public string Name {
Expand All @@ -107,46 +112,77 @@ public bool PageFilePresent {
}

public string VolumeFormat {
get {
return dinfo.DriveFormat;
}
get
{
if (dinfo.IsReady)
return dinfo.DriveFormat;
else
return null;
}
}

public Guid VolumeGuid {
get {
RegistryKey regKey = Registry.LocalMachine.OpenSubKey(KEY_MOUNTED_DEVICES);
object keyval;
try { keyval = regKey.GetValue(KEY_VALUE_PREFIX + DriveLetter); }
catch (Exception e)
Guid guid;
TryGetVolumeGuid(out guid);
return guid;
}
}

#endregion

private bool TryGetVolumeGuid(out Guid volGuid)
{
volGuid = Guid.Empty;

if (this.volGuid.HasValue)
{
if (this.volGuid.Value == Guid.Empty)
return false;

volGuid = this.volGuid.Value;
return true;
}

this.volGuid = Guid.Empty;
RegistryKey regKey = Registry.LocalMachine.OpenSubKey(KEY_MOUNTED_DEVICES);
if (regKey == null)
return false;

object keyval;
try { keyval = regKey.GetValue(KEY_VALUE_PREFIX + DriveLetter); }
catch (Exception e)
{
if (MainClass.DEBUG)
{
MainClass.WriteLogEntry(string.Format(
"{0}.get_VolumeGuid: Could not read value from registry key.", CLASS_FULL_PATH));
MainClass.WriteLogEntry("Exception:");
MainClass.WriteLogEntry(e.ToString());
}
return false;
}
byte[] header = (byte[])keyval;
string[] values = regKey.GetValueNames();
byte[] temp;
foreach (string item in values)
{
if (item.IndexOf(KEY_VALUE_GUID_PREFIX) == 0)
{
if (MainClass.DEBUG)
temp = (byte[])regKey.GetValue(item);
if (SequenceEqual<byte>(header, temp))
{
MainClass.WriteLogEntry(string.Format(
"{0}.get_VolumeGuid: Could not read value from registry key.", CLASS_FULL_PATH));
MainClass.WriteLogEntry("Exception:");
MainClass.WriteLogEntry(e.ToString());
regKey.Close();
volGuid = new Guid(item.Substring(item.IndexOf('{')));
this.volGuid = volGuid;
return true;
}
return Guid.Empty;
}
byte[] header = (byte[])keyval;
string[] values = regKey.GetValueNames();
byte[] temp;
foreach (string item in values) {
if (item.IndexOf(KEY_VALUE_GUID_PREFIX) == 0) {
temp = (byte[])regKey.GetValue(item);
if (SequenceEqual<byte>(header, temp)) {
regKey.Close();
return new Guid(item.Substring(item.IndexOf('{')));
}
}
};

regKey.Close();
return Guid.Empty;
}
}
};

#endregion
regKey.Close();
return false;
}

private static bool SequenceEqual<T>(T[] a1, T[] a2) where T : IComparable<T>
{
Expand Down
10 changes: 7 additions & 3 deletions zbxlld-win/Supplement/Win32_Volume.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
// Author:
// Fabricio Godoy <skarllot@gmail.com>
//
// Copyright (c) 2013 Fabricio Godoy
// Copyright (c) 2014 Fabricio Godoy
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -41,7 +41,9 @@ private Win32_Volume(ManagementObject mgtobj)
properties.Add(item.Name, item.Value);
}

/// <summary>
#region Properties

/// <summary>
/// If true, the volume is mounted to the file system automatically when the first I/O is issued. If false, the
/// volume is not mounted until explicitly mounted by using the Mount method, or by adding a drive letter or
/// mount point.
Expand Down Expand Up @@ -211,7 +213,9 @@ public DriveStatus StatusInfo {
}
}

public static Win32_Volume[] GetAllVolumes()
#endregion

public static Win32_Volume[] GetAllVolumes()
{
ManagementObjectCollection wmicol =
new ManagementObjectSearcher(WQL_VOLUME).Get();
Expand Down

0 comments on commit 0499703

Please sign in to comment.