using System; using System.Collections.Concurrent; using System.Drawing; using System.Runtime.InteropServices; using System.Windows.Forms; using DTS.Common.USBFramework; using DTS.Common.Utilities.Logging; namespace DTS.DASLib.DASFactory { internal abstract class WindowsNotification : DeviceHandling { protected FileIODeclarations.SECURITY_ATTRIBUTES Security; protected DeviceManagement MyDeviceManagement; protected Guid DeviceGuid = Guid.Empty; /// /// Handle of the window which receives messages from Windows. This will be a form. /// protected IntPtr RecipientHandle; protected IntPtr DeviceNotifyHandle; protected NotificationForm NotificationWindow; protected WindowsNotification(DASFactory _factory, UpdateFinishedEventHandler _SerialUpdateFinished, Guid _guid, BlockingCollection> queueActionPerDevice ) : base(_factory, _SerialUpdateFinished, queueActionPerDevice) { MyDeviceManagement = new DeviceManagement(); Security = new FileIODeclarations.SECURITY_ATTRIBUTES { lpSecurityDescriptor = 0, bInheritHandle = Convert.ToInt32(true) }; Security.nLength = Marshal.SizeOf(Security); DeviceGuid = _guid; NotificationWindow = new NotificationForm(NotificationWndProc); NotificationWindow.Show(); // will be hidden immediately DeviceNotifyHandle = IntPtr.Zero; RecipientHandle = NotificationWindow.Handle; if (!MyDeviceManagement.RegisterForDeviceNotifications(RecipientHandle, DeviceGuid, ref DeviceNotifyHandle)) { throw new Exception("DASFactory.WindowsNotification: Unable to register device"); } } public override void Dispose() { if (DeviceNotifyHandle != IntPtr.Zero) { MyDeviceManagement.StopReceivingDeviceNotifications(DeviceNotifyHandle); } try { /*if (null != NotificationWindow) { if (NotificationWindow.InvokeRequired) { NotificationWindow.Invoke(new Action(() => { if (NotificationWindow.IsHandleCreated) { NotificationWindow.Close(); NotificationWindow.Dispose(); NotificationWindow = null; } })); } else { if (NotificationWindow.IsHandleCreated) { NotificationWindow.Close(); NotificationWindow.Dispose(); NotificationWindow = null; } } }*/ /* Cross-thread operation not valid: Control 'NotificationForm' accessed from a thread other than the thread it was created on. */ //NotificationWindow.Close(); } catch (Exception ex) { APILogger.Log(ex.Message); } base.Dispose(); } /// /// This gets called whenever anything happens to WinUSB devices /// /// The windows message protected virtual void NotificationWndProc(ref Message m) { //we detect the media arrival event if (m.Msg != DeviceManagementDeclarations.WM_DEVICECHANGE) { return; } if (m.WParam.ToInt32() == DeviceManagementDeclarations.DBT_DEVICEARRIVAL) { if (Marshal.ReadInt32(m.LParam, 4) == DeviceManagementDeclarations.DBT_DEVTYP_DEVICEINTERFACE) { NotificationDeviceArrived(ref m); } } else { if (m.WParam.ToInt32() == DeviceManagementDeclarations.DBT_DEVICEREMOVECOMPLETE) { if (Marshal.ReadInt32(m.LParam, 4) == DeviceManagementDeclarations.DBT_DEVTYP_DEVICEINTERFACE) { NotificationDeviceRemoved(ref m); } } } } protected abstract void NotificationDeviceArrived(ref Message m); protected abstract void NotificationDeviceRemoved(ref Message m); /// /// Hidden Form which we use to receive Windows messages /// internal class NotificationForm : Form { public delegate void WinMsgProc(ref Message m); private Label label1; private readonly WinMsgProc mDetector; /// /// Set up the hidden form. /// /// DriveDetector object which will receive notification about USB drives, see WndProc public NotificationForm(WinMsgProc detector) { mDetector = detector; MinimizeBox = false; MaximizeBox = false; ShowInTaskbar = false; ShowIcon = false; FormBorderStyle = FormBorderStyle.FixedToolWindow; Load += Load_Form; Activated += Form_Activated; } private void Load_Form(object sender, EventArgs e) { // We don't really need this, just to display the label in designer ... InitializeComponent(); // Create really small form, invisible anyway. Size = new Size(5, 5); } private void Form_Activated(object sender, EventArgs e) { //this.Visible = false; } /// /// This function receives all the windows messages for this window (form). /// We call the DASFactory from here so that is can pick up the messages /// protected override void WndProc(ref Message m) { base.WndProc(ref m); if (mDetector != null) { mDetector(ref m); } } private void InitializeComponent() { label1 = new Label(); SuspendLayout(); // // label1 // label1.AutoSize = true; label1.Location = new Point(13, 30); label1.Name = "label1"; label1.Size = new Size(314, 13); label1.TabIndex = 0; label1.Text = @"This is an invisible form."; // // DetectorForm // ClientSize = new Size(360, 80); Controls.Add(label1); Name = "NotificationForm"; Opacity = 0; ResumeLayout(false); PerformLayout(); } } } }