Repository navigation
Expand file tree
/
Copy pathUSBDeviceNotification.cs
More file actions
140 lines (121 loc) · 5.77 KB
/
Copy pathUSBDeviceNotification.cs
File metadata and controls
140 lines (121 loc) · 5.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//*********************************************************************************************************************
// File Name: USBDeviceNotification.cs
// Description: Implementation of the USB device notification system
//
// Copyright (C) 2023 Mike Pullen
// Licensed under the MIT License. See the LICENSE file in the project root for full license information.
//
// Revision History:
//====================================================================================================================
// 2023/12/03 - Mike Pullen - Original implementation.
// 2026/09/04 - Mike Pullen - Released the notification filter buffer, reported registration failures and hardened
// the unregister path.
// 2026/09/04 - Mike Pullen - Relicensed under the MIT License.
// 2026/09/05 - Mike Pullen - Documented the public surface for XML documentation output.
//*********************************************************************************************************************
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
namespace DeviceInterfaces
{
/// <summary>
/// Registers a window for notifications about USB devices being connected and removed
/// </summary>
public static class USBDeviceNotification
{
#region Externals
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, int Flags);
[DllImport("user32.dll")]
private static extern bool UnregisterDeviceNotification(IntPtr Handle);
#endregion
#region Type definitions
/// <summary>
/// Structure for filling the notificationFilter parameter buffer for RegisterDeviceNotification
/// </summary>
[StructLayout(LayoutKind.Sequential)]
private struct NotificationFilterStr
{
internal int iSize;
internal int iDeviceType;
internal int iReserved;
internal Guid classGuid;
internal short iName;
}
#endregion
#region Methods
/// <summary>
/// Registers a window to receive notifications when USB devices are connected or removed
/// </summary>
/// <param name="pWindowHandle">IN - Handle to the window to be notified</param>
/// <returns>The notification handle, which must be passed to UnregisterUsbDeviceNotification</returns>
/// <exception cref="Win32Exception">Thrown when the window could not be registered for device notifications</exception>
public static IntPtr RegisterUsbDeviceNotification(IntPtr pWindowHandle)
{
// Populate the notification filter information
NotificationFilterStr notificationFilter = new NotificationFilterStr
{
iDeviceType = m_iINTERFACE_TYPE,
iReserved = 0,
classGuid = m_USB_GUID,
iName = 0
};
// Allocate the buffer to marshal the structure into
notificationFilter.iSize = Marshal.SizeOf(notificationFilter);
IntPtr pNotificationFilterBuffer = Marshal.AllocHGlobal(notificationFilter.iSize);
try
{
// Marshal the structure into the buffer. The buffer holds uninitialized memory, so there is no
// previously marshalled structure for StructureToPtr to release.
Marshal.StructureToPtr(notificationFilter, pNotificationFilterBuffer, false);
// Register the window for USB device events
IntPtr pNotificationHandle = RegisterDeviceNotification(pWindowHandle, pNotificationFilterBuffer, m_iDEVICE_NOTIFY_WINDOW_HANDLE);
if (pNotificationHandle == IntPtr.Zero)
{
throw new Win32Exception(Marshal.GetLastWin32Error());
}
// Return the notification handle
return pNotificationHandle;
}
finally
{
// Windows copies the filter during registration, so the buffer is no longer needed
Marshal.FreeHGlobal(pNotificationFilterBuffer);
}
}
/// <summary>
/// Unregisters the window for USB device notifications
/// </summary>
/// <param name="pNotificationHandle">IN - Notification handle returned by RegisterUsbDeviceNotification</param>
public static void UnregisterUsbDeviceNotification(IntPtr pNotificationHandle)
{
// Ignore a handle that was never registered
if (pNotificationHandle == IntPtr.Zero)
{
return;
}
// Unregister the window using the specified notification handle
UnregisterDeviceNotification(pNotificationHandle);
}
#endregion
#region Data Members
// Exposed constants
/// <summary>
/// Value of wParam on a WM_DEVICECHANGE message reporting that a device was connected
/// </summary>
public const int iDEVICE_CONNECTED = 0x8000;
/// <summary>
/// Value of wParam on a WM_DEVICECHANGE message reporting that a device was removed
/// </summary>
public const int iDEVICE_REMOVED = 0x8004;
/// <summary>
/// Window message raised when a device is connected or removed
/// </summary>
public const int iWM_DEVICECHANGE = 0x0219;
// Interface constants
private const int m_iDEVICE_NOTIFY_WINDOW_HANDLE = 0;
private const int m_iINTERFACE_TYPE = 5; // DBT_DEVTYP_DEVICEINTERFACE
private static readonly Guid m_USB_GUID = new Guid("A5DCBF10-6530-11D2-901F-00C04FB951ED");
#endregion
}
}