using System;
using Systemm = System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using Trigger.Classes.System;
using Trigger.Classes.Device;
namespace Trigger.Events
{
///
/// A that provides events for Devices
/// It catches arriving and removed devices as well as inserted media and new network volumes
///
public class Device : EventPlugin
{
#region Constants, Structs & Enums
internal enum EventType : byte
{
DeviceArrived,
DeviceRemoved,
}
#endregion
#region Properties
internal static Main Main;
internal Dictionary oldValues = new Dictionary();
internal static Dictionary oldStaticValues = new Dictionary();
#region Register Parent Events
internal static byte deviceChangedEnabled;
internal static bool DeviceChangedEnabled
{
get
{
return deviceChangedEnabled > 0;
}
set
{
if (value)
deviceChangedEnabled++;
else
deviceChangedEnabled--;
if (value && deviceChangedEnabled == 1)
{
Main.RegisterEventForMessage(Classes.System.WindowsMessages.WM_DEVICECHANGE);
Main.MessageReceived += Main_MessageReceived;
}
else if (deviceChangedEnabled == 0)
{
Main.UnregisterEventForMessage(Classes.System.WindowsMessages.WM_DEVICECHANGE);
Main.MessageReceived -= Main_MessageReceived;
}
}
}
#endregion
#region Events
#region DeviceArrived
internal static EventPlugin.EventValue OnDeviceArrived;
/// A device (no media) has been inserted and becomes available.
public event EventPlugin.EventValue DeviceArrived
{
add
{
OnDeviceArrived += value;
DeviceChangedEnabled = true;
}
remove
{
OnDeviceArrived -= value;
DeviceChangedEnabled = false;
}
}
#endregion
#region DeviceQueryRemove
internal static EventPlugin.EventValue OnDeviceQueryRemove;
/// The system broadcasts the DBT_DEVICEQUERYREMOVE device event to request permission to remove a device or piece of media. This message is the last chance for applications and drivers to prepare for this removal. However, any application can deny this request and cancel the operation.
public event EventPlugin.EventValue DeviceQueryRemove
{
add
{
OnDeviceQueryRemove += value;
DeviceChangedEnabled = true;
}
remove
{
OnDeviceQueryRemove -= value;
DeviceChangedEnabled = false;
}
}
#endregion
#region DeviceQueryRemoveFailed
internal static EventPlugin.EventValue OnDeviceQueryRemoveFailed;
/// A request to remove a device or piece of media has been canceled.
public event EventPlugin.EventValue DeviceQueryRemoveFailed
{
add
{
OnDeviceQueryRemoveFailed += value;
DeviceChangedEnabled = true;
}
remove
{
OnDeviceQueryRemoveFailed -= value;
DeviceChangedEnabled = false;
}
}
#endregion
#region DeviceRemoved
internal static EventPlugin.EventValue OnDeviceRemoved;
/// A device or piece of media has been physically removed.
public event EventPlugin.EventValue DeviceRemoved
{
add
{
if (!oldStaticValues.ContainsKey(EventType.DeviceRemoved))
oldStaticValues[EventType.DeviceRemoved] = Status.Device.AvailableDisks;
OnDeviceRemoved += value;
DeviceChangedEnabled = true;
}
remove
{
OnDeviceRemoved -= value;
DeviceChangedEnabled = false;
}
}
#endregion
#region DeviceRemovePending
internal static EventPlugin.EventValue OnDeviceRemovePending;
/// A device or piece of media is being removed and is no longer available for use.
public event EventPlugin.EventValue DeviceRemovePending
{
add
{
OnDeviceRemovePending += value;
DeviceChangedEnabled = true;
}
remove
{
OnDeviceRemovePending -= value;
DeviceChangedEnabled = false;
}
}
#endregion
#region MediaInserted
internal static EventPlugin.EventValue OnMediaInserted;
/// A piece of media (CD, DVD, ...) has been inserted and becomes available
public event EventPlugin.EventValue MediaInserted
{
add
{
OnMediaInserted += value;
DeviceChangedEnabled = true;
}
remove
{
OnMediaInserted -= value;
DeviceChangedEnabled = false;
}
}
#endregion
#region NetworkVolumeArrived
internal static EventPlugin.EventValue OnNetworkVolumeArrived;
/// A piece of media (CD, DVD, ...) has been inserted and becomes available
public event EventPlugin.EventValue NetworkVolumeArrived
{
add
{
OnNetworkVolumeArrived += value;
DeviceChangedEnabled = true;
}
remove
{
OnNetworkVolumeArrived -= value;
DeviceChangedEnabled = false;
}
}
#endregion
#endregion
#endregion
#region Constructor & Destructor
///
/// Creates an instance of this class
///
///
public Device(Main main)
{
Main = main;
}
///
/// Disables all SystemEvents because they are static
///
/// http://msdn.microsoft.com/en-us/library/microsoft.win32.systemevents.displaysettingschanged%28v=vs.110%29.aspx
~Device()
{
if (DeviceChangedEnabled)
{
Main.UnregisterEventForMessage(Classes.System.WindowsMessages.WM_DEVICECHANGE);
Main.MessageReceived -= Main_MessageReceived;
}
}
#endregion
#region Methods
///
/// Get all events that are provided
///
///
public override EventList EventNames()
{
EventList list = new EventList();
EventListRow row = list.NewEventListRow();
return list;
}
///
/// Get the current status of this
///
///
public override TreeNode GetStatus()
{
TreeNode tnMain = new TreeNode("Device");
TreeNode tnEvents = tnMain.Nodes.Add("Registered events");
if (DeviceChangedEnabled)
{
TreeNode tnEvent = tnEvents.Nodes.Add("DeviceChanged");
tnEvent.ToolTipText = "Registered in Win32 message service (WM_DEVICECHANGED)";
}
return tnMain;
}
#endregion
#region Event Handler
internal static void Main_MessageReceived(object sender, EventArgsValue e)
{
if (e.Value.Msg != (int)WindowsMessages.WM_DEVICECHANGE || e.Value.LParam == IntPtr.Zero)
return;
DEV_BROADCAST_VOLUME dbcv = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(e.Value.LParam, typeof(DEV_BROADCAST_VOLUME));
if (dbcv.dbcv_devicetype != (int)DBT.DEVTYP_VOLUME)
return; // we were not even allowed to transform to DEV_BROADCAST_VOLUME =) But who cares...
switch ((DBT)((int)e.Value.WParam))
{
#region case DBT.DEVICEARRIVLE:
case DBT.DEVICEARRIVAL:
StorageDisk device = StorageDisk.FromUnitMask(dbcv.dbcv_unitmask); // Bug: unitmask = 0 when media inserted, flags passen auch nicht
((List)oldStaticValues[EventType.DeviceRemoved]).Add(device);
if ((dbcv.dbcv_flags & 1 /*DBFT_MEDIA*/) == 1)
{
if (OnMediaInserted != null)
OnMediaInserted(null, new EventArgsValue(device));
}
else if ((dbcv.dbcv_flags & 2 /*DBFT_NET*/) == 2)
{
if (OnNetworkVolumeArrived != null)
OnNetworkVolumeArrived(null, new EventArgsValue(device));
}
else
{
if (OnDeviceArrived != null)
OnDeviceArrived(null, new EventArgsValue(device));
}
break;
#endregion
#region case DBT.DEVICEQUERYREMOVE:
case DBT.DEVICEQUERYREMOVE:
throw new NotImplementedException("\"Device Query remove\" is not implemented");
#endregion
#region case DBT.DEVICEQUERYREMOVEFAILED:
case DBT.DEVICEQUERYREMOVEFAILED:
throw new NotImplementedException("\"Device Query remove failed\" is not implemented");
#endregion
#region case DBT.DEVICEREMOVECOMPLETE:
case DBT.DEVICEREMOVECOMPLETE:
if (OnDeviceRemoved == null)
break;
char removedDiskLetter = StorageDisk.FirstDriveFromMask(dbcv.dbcv_unitmask);
List oldDisks = (List)oldStaticValues[EventType.DeviceRemoved];
foreach (StorageDisk oldDisk in oldDisks)
{
if (oldDisk.DriveLetters.Contains(removedDiskLetter))
{
OnDeviceRemoved(null, new EventArgsValue(oldDisk));
oldDisks.Remove(oldDisk);
return;
}
StorageDisk unknownDisk = StorageDisk.FromUnitMask(dbcv.dbcv_unitmask);
OnDeviceRemoved(null, new EventArgsValue(unknownDisk));
}
break;
#endregion
}
}
#endregion
}
}