Example #1
0
File: Device.cs Project: CDEApp/CDE
        internal static IEnumerable <DeviceInfo> EnumerateDevicesInternal(SafeHandle safeHandle, string hostName, DeviceGuid deviceInterfaceGuid)
        {
            bool callerHandle = safeHandle != null;
            Guid deviceGuid   = new Guid(Utils.GetEnumDescription(deviceInterfaceGuid));


            // CM_Connect_Machine()
            // MSDN Note: Beginning in Windows 8 and Windows Server 2012 functionality to access remote machines has been removed.
            // You cannot access remote machines when running on these versions of Windows.
            // http://msdn.microsoft.com/en-us/library/windows/hardware/ff537948%28v=vs.85%29.aspx

            SafeCmConnectMachineHandle safeMachineHandle;
            int lastError = NativeMethods.CM_Connect_Machine(Path.LocalToUncInternal(Host.GetUncName(hostName), false, false, false, false), out safeMachineHandle);

            if (safeMachineHandle.IsInvalid)
            {
                safeMachineHandle.Close();
                NativeError.ThrowException(lastError, Resources.HandleInvalid);
            }

            using (safeMachineHandle)
            {
                // Start at the "Root" of the device tree of the specified machine.
                if (!callerHandle)
                {
                    safeHandle = NativeMethods.SetupDiGetClassDevsEx(ref deviceGuid, IntPtr.Zero, IntPtr.Zero,
                                                                     NativeMethods.SetupDiGetClassDevsExFlags.Present |
                                                                     NativeMethods.SetupDiGetClassDevsExFlags.DeviceInterface,
                                                                     IntPtr.Zero, hostName, IntPtr.Zero);
                }

                if (safeHandle.IsInvalid)
                {
                    safeHandle.Close();
                    NativeError.ThrowException(Marshal.GetLastWin32Error(), Resources.HandleInvalid);
                }


                try
                {
                    uint memberInterfaceIndex = 0;
                    NativeMethods.SpDeviceInterfaceData deviceInterfaceData = CreateDeviceInterfaceDataInstance();

                    // Start enumerating Device Interfaces.
                    while (NativeMethods.SetupDiEnumDeviceInterfaces(safeHandle, IntPtr.Zero, ref deviceGuid, memberInterfaceIndex++, ref deviceInterfaceData))
                    {
                        lastError = Marshal.GetLastWin32Error();
                        if (lastError != Win32Errors.NO_ERROR)
                        {
                            NativeError.ThrowException(lastError, hostName);
                        }


                        NativeMethods.SpDeviceInfoData            deviceInfoData            = CreateDeviceInfoDataInstance();
                        NativeMethods.SpDeviceInterfaceDetailData deviceInterfaceDetailData = GetDeviceInterfaceDetailDataInstance(safeHandle, deviceInterfaceData, deviceInfoData);

                        // Get device interace details.
                        if (!NativeMethods.SetupDiGetDeviceInterfaceDetail(safeHandle, ref deviceInterfaceData, ref deviceInterfaceDetailData, NativeMethods.DefaultFileBufferSize, IntPtr.Zero, ref deviceInfoData))
                        {
                            lastError = Marshal.GetLastWin32Error();
                            if (lastError != Win32Errors.NO_ERROR)
                            {
                                NativeError.ThrowException(lastError, hostName);
                            }
                        }

                        // Create DeviceInfo instance.
                        // Set DevicePath property of DeviceInfo instance.
                        DeviceInfo deviceInfo = new DeviceInfo(hostName)
                        {
                            DevicePath = deviceInterfaceDetailData.DevicePath
                        };


                        // Current InstanceId is at the "USBSTOR" level, so we
                        // need up "move up" one level to get to the "USB" level.
                        uint ptrPrevious;

                        // CM_Get_Parent_Ex()
                        // Note: Using this function to access remote machines is not supported
                        // beginning with Windows 8 and Windows Server 2012, as this functionality has been removed.
                        // http://msdn.microsoft.com/en-us/library/windows/hardware/ff538615%28v=vs.85%29.aspx

                        lastError = NativeMethods.CM_Get_Parent_Ex(out ptrPrevious, deviceInfoData.DevInst, 0, safeMachineHandle);
                        if (lastError != Win32Errors.CR_SUCCESS)
                        {
                            NativeError.ThrowException(lastError, hostName);
                        }


                        // Now we get the InstanceID of the USB level device.
                        using (SafeGlobalMemoryBufferHandle safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
                        {
                            // CM_Get_Device_ID_Ex()
                            // Note: Using this function to access remote machines is not supported beginning with Windows 8 and Windows Server 2012,
                            // as this functionality has been removed.
                            // http://msdn.microsoft.com/en-us/library/windows/hardware/ff538411%28v=vs.85%29.aspx

                            lastError = NativeMethods.CM_Get_Device_ID_Ex(deviceInfoData.DevInst, safeBuffer, (uint)safeBuffer.Capacity, 0, safeMachineHandle);
                            if (lastError != Win32Errors.CR_SUCCESS)
                            {
                                NativeError.ThrowException(lastError, hostName);
                            }


                            // CA2001:AvoidCallingProblematicMethods

                            IntPtr buffer     = IntPtr.Zero;
                            bool   successRef = false;
                            safeBuffer.DangerousAddRef(ref successRef);

                            // MSDN: The DangerousGetHandle method poses a security risk because it can return a handle that is not valid.
                            if (successRef)
                            {
                                buffer = safeBuffer.DangerousGetHandle();
                            }

                            safeBuffer.DangerousRelease();

                            if (buffer == IntPtr.Zero)
                            {
                                NativeError.ThrowException(Resources.HandleDangerousRef);
                            }

                            // CA2001:AvoidCallingProblematicMethods


                            // Add to instance.
                            deviceInfo.InstanceId = Marshal.PtrToStringUni(buffer);
                        }

                        #region Get Registry Properties

                        using (SafeGlobalMemoryBufferHandle safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
                        {
                            uint   regType;
                            string dataString;


                            // CA2001:AvoidCallingProblematicMethods

                            IntPtr buffer     = IntPtr.Zero;
                            bool   successRef = false;
                            safeBuffer.DangerousAddRef(ref successRef);

                            // MSDN: The DangerousGetHandle method poses a security risk because it can return a handle that is not valid.
                            if (successRef)
                            {
                                buffer = safeBuffer.DangerousGetHandle();
                            }

                            safeBuffer.DangerousRelease();

                            if (buffer == IntPtr.Zero)
                            {
                                NativeError.ThrowException(Resources.HandleDangerousRef);
                            }

                            // CA2001:AvoidCallingProblematicMethods


                            uint safeBufferCapacity = (uint)safeBuffer.Capacity;


                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.BaseContainerId, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                dataString = Marshal.PtrToStringUni(buffer);
                                if (!Utils.IsNullOrWhiteSpace(dataString))
                                {
                                    deviceInfo.BaseContainerId = new Guid(dataString);
                                }
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.ClassGuid, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                dataString = Marshal.PtrToStringUni(buffer);
                                if (!Utils.IsNullOrWhiteSpace(dataString))
                                {
                                    deviceInfo.ClassGuid = new Guid(dataString);
                                }
                            }


                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.Class, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.Class = Marshal.PtrToStringUni(buffer);
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.CompatibleIds, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.CompatibleIds = Marshal.PtrToStringUni(buffer);
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.DeviceDescription, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.DeviceDescription = Marshal.PtrToStringUni(buffer);
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.Driver, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.Driver = Marshal.PtrToStringUni(buffer);
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.EnumeratorName, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.EnumeratorName = Marshal.PtrToStringUni(buffer);
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.FriendlyName, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.FriendlyName = Marshal.PtrToStringUni(buffer);
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.HardwareId, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.HardwareId = Marshal.PtrToStringUni(buffer);
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.LocationInformation, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.LocationInformation = Marshal.PtrToStringUni(buffer);
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.LocationPaths, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.LocationPaths = Marshal.PtrToStringUni(buffer);
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.Manufacturer, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.Manufacturer = Marshal.PtrToStringUni(buffer);
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.PhysicalDeviceObjectName, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.PhysicalDeviceObjectName = Marshal.PtrToStringUni(buffer);
                            }

                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.Service, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                deviceInfo.Service = Marshal.PtrToStringUni(buffer);
                            }
                        }

                        #endregion // Get Registry Properties

                        yield return(deviceInfo);

                        // Get new structure instance.
                        deviceInterfaceData = CreateDeviceInterfaceDataInstance();
                    }
                }
                finally
                {
                    // Handle is ours, dispose.
                    if (!callerHandle && safeHandle != null)
                    {
                        safeHandle.Close();
                    }
                }
            }
        }
Example #2
0
        internal static IEnumerable <DeviceInfo> EnumerateDevicesCore(string hostName, DeviceGuid deviceGuid, bool getAllProperties)
        {
            if (Utils.IsNullOrWhiteSpace(hostName))
            {
                hostName = Environment.MachineName;
            }


            // CM_Connect_Machine()
            // MSDN Note: Beginning in Windows 8 and Windows Server 2012 functionality to access remote machines has been removed.
            // You cannot access remote machines when running on these versions of Windows.
            // http://msdn.microsoft.com/en-us/library/windows/hardware/ff537948%28v=vs.85%29.aspx


            SafeCmConnectMachineHandle safeMachineHandle;

            var lastError = NativeMethods.CM_Connect_Machine(Host.GetUncName(hostName), out safeMachineHandle);

            NativeMethods.IsValidHandle(safeMachineHandle, lastError);


            var classGuid = new Guid(Utils.GetEnumDescription(deviceGuid));


            // Start at the "Root" of the device tree of the specified machine.

            using (safeMachineHandle)
                using (var safeHandle = NativeMethods.SetupDiGetClassDevsEx(ref classGuid, IntPtr.Zero, IntPtr.Zero, NativeMethods.SetupDiGetClassDevsExFlags.Present | NativeMethods.SetupDiGetClassDevsExFlags.DeviceInterface, IntPtr.Zero, hostName, IntPtr.Zero))
                {
                    NativeMethods.IsValidHandle(safeHandle, Marshal.GetLastWin32Error());

                    uint memberInterfaceIndex = 0;
                    var  interfaceStructSize  = (uint)Marshal.SizeOf(typeof(NativeMethods.SP_DEVICE_INTERFACE_DATA));
                    var  dataStructSize       = (uint)Marshal.SizeOf(typeof(NativeMethods.SP_DEVINFO_DATA));


                    // Start enumerating device interfaces.

                    while (true)
                    {
                        var interfaceData = new NativeMethods.SP_DEVICE_INTERFACE_DATA {
                            cbSize = interfaceStructSize
                        };

                        var success = NativeMethods.SetupDiEnumDeviceInterfaces(safeHandle, IntPtr.Zero, ref classGuid, memberInterfaceIndex++, ref interfaceData);

                        lastError = Marshal.GetLastWin32Error();

                        if (!success)
                        {
                            if (lastError != Win32Errors.NO_ERROR && lastError != Win32Errors.ERROR_NO_MORE_ITEMS)
                            {
                                NativeError.ThrowException(lastError, hostName);
                            }

                            break;
                        }


                        // Create DeviceInfo instance.

                        var diData = new NativeMethods.SP_DEVINFO_DATA {
                            cbSize = dataStructSize
                        };

                        var deviceInfo = new DeviceInfo(hostName)
                        {
                            DevicePath = GetDeviceInterfaceDetail(safeHandle, ref interfaceData, ref diData).DevicePath
                        };


                        if (getAllProperties)
                        {
                            deviceInfo.InstanceId = GetDeviceInstanceId(safeMachineHandle, hostName, diData);

                            SetDeviceProperties(safeHandle, deviceInfo, diData);
                        }

                        else
                        {
                            SetMinimalDeviceProperties(safeHandle, deviceInfo, diData);
                        }


                        yield return(deviceInfo);
                    }
                }
        }