Windows Storage Management API — VDS (Virtual Disk Service) Эквивалентный метод удаления диска

Поскольку VDS устаревает и его заменяет API управления хранилищем Windows, существуют ли какие-либо методы WMI, IOCTL, DeviceIoControl или API управления хранилищем Windows, эквивалентные методу VDS «UninstallDisks»?

Я не могу найти другого способа сделать то, что делает метод VDS «UninstallDisks».

Любая помощь будет оценена по достоинству.


person parkerflyz    schedule 14.09.2017    source источник


Ответы (1)


Сам разобрался с комбинацией кода других участников.

Ссылка: функция Win32 API для программного включения/отключения устройства

Основная кодовая база ниже:

using Microsoft.Win32.SafeHandles;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;

namespace WindowsStorageManagementAPI.Devices
{
    public class DeviceInfoData
    {
        public int Size { get; set; }
        public Guid ClassGuid { get; set; }
        public int DevInst { get; set; }
        public IntPtr Reserved { get; set; }
    }

    public class SetupApiWrapper
    {
        private const string SetupAPI = "setupapi.dll";
        private const string NewDevLib = "Newdev.dll";

        #region NATIVE ENUMS
        [Flags()]
        private enum SetupDiGetClassDevsFlags
        {
            Default = 1,
            Present = 2,
            AllClasses = (int)0x04,
            Profile = 8,
            DeviceInterface = (int)0x10
        }

        private enum DiFunction
        {
            SelectDevice = 1,
            InstallDevice = 2,
            AssignResources = 3,
            Properties = 4,
            Remove = 5,
            FirstTimeSetup = 6,
            FoundDevice = 7,
            SelectClassDrivers = 8,
            ValidateClassDrivers = 9,
            InstallClassDrivers = (int)0xa,
            CalcDiskSpace = (int)0xb,
            DestroyPrivateData = (int)0xc,
            ValidateDriver = (int)0xd,
            Detect = (int)0xf,
            InstallWizard = (int)0x10,
            DestroyWizardData = (int)0x11,
            PropertyChange = (int)0x12,
            EnableClass = (int)0x13,
            DetectVerify = (int)0x14,
            InstallDeviceFiles = (int)0x15,
            UnRemove = (int)0x16,
            SelectBestCompatDrv = (int)0x17,
            AllowInstall = (int)0x18,
            RegisterDevice = (int)0x19,
            NewDeviceWizardPreSelect = (int)0x1a,
            NewDeviceWizardSelect = (int)0x1b,
            NewDeviceWizardPreAnalyze = (int)0x1c,
            NewDeviceWizardPostAnalyze = (int)0x1d,
            NewDeviceWizardFinishInstall = (int)0x1e,
            Unused1 = (int)0x1f,
            InstallInterfaces = (int)0x20,
            DetectCancel = (int)0x21,
            RegisterCoInstallers = (int)0x22,
            AddPropertyPageAdvanced = (int)0x23,
            AddPropertyPageBasic = (int)0x24,
            Reserved1 = (int)0x25,
            Troubleshooter = (int)0x26,
            PowerMessageWake = (int)0x27,
            AddRemotePropertyPageAdvanced = (int)0x28,
            UpdateDriverUI = (int)0x29,
            Reserved2 = (int)0x30
        }

        private enum StateChangeAction
        {
            Enable = 1,
            Disable = 2,
            PropChange = 3,
            Start = 4,
            Stop = 5
        }

        [Flags()]
        private enum Scope
        {
            Global = 1,
            ConfigSpecific = 2,
            ConfigGeneral = 4
        }

        private enum SetupApiError
        {
            NoAssociatedClass = unchecked((int)0xe0000200),
            ClassMismatch = unchecked((int)0xe0000201),
            DuplicateFound = unchecked((int)0xe0000202),
            NoDriverSelected = unchecked((int)0xe0000203),
            KeyDoesNotExist = unchecked((int)0xe0000204),
            InvalidDevinstName = unchecked((int)0xe0000205),
            InvalidClass = unchecked((int)0xe0000206),
            DevinstAlreadyExists = unchecked((int)0xe0000207),
            DevinfoNotRegistered = unchecked((int)0xe0000208),
            InvalidRegProperty = unchecked((int)0xe0000209),
            NoInf = unchecked((int)0xe000020a),
            NoSuchHDevinst = unchecked((int)0xe000020b),
            CantLoadClassIcon = unchecked((int)0xe000020c),
            InvalidClassInstaller = unchecked((int)0xe000020d),
            DiDoDefault = unchecked((int)0xe000020e),
            DiNoFileCopy = unchecked((int)0xe000020f),
            InvalidHwProfile = unchecked((int)0xe0000210),
            NoDeviceSelected = unchecked((int)0xe0000211),
            DevinfolistLocked = unchecked((int)0xe0000212),
            DevinfodataLocked = unchecked((int)0xe0000213),
            DiBadPath = unchecked((int)0xe0000214),
            NoClassInstallParams = unchecked((int)0xe0000215),
            FileQueueLocked = unchecked((int)0xe0000216),
            BadServiceInstallSect = unchecked((int)0xe0000217),
            NoClassDriverList = unchecked((int)0xe0000218),
            NoAssociatedService = unchecked((int)0xe0000219),
            NoDefaultDeviceInterface = unchecked((int)0xe000021a),
            DeviceInterfaceActive = unchecked((int)0xe000021b),
            DeviceInterfaceRemoved = unchecked((int)0xe000021c),
            BadInterfaceInstallSect = unchecked((int)0xe000021d),
            NoSuchInterfaceClass = unchecked((int)0xe000021e),
            InvalidReferenceString = unchecked((int)0xe000021f),
            InvalidMachineName = unchecked((int)0xe0000220),
            RemoteCommFailure = unchecked((int)0xe0000221),
            MachineUnavailable = unchecked((int)0xe0000222),
            NoConfigMgrServices = unchecked((int)0xe0000223),
            InvalidPropPageProvider = unchecked((int)0xe0000224),
            NoSuchDeviceInterface = unchecked((int)0xe0000225),
            DiPostProcessingRequired = unchecked((int)0xe0000226),
            InvalidCOInstaller = unchecked((int)0xe0000227),
            NoCompatDrivers = unchecked((int)0xe0000228),
            NoDeviceIcon = unchecked((int)0xe0000229),
            InvalidInfLogConfig = unchecked((int)0xe000022a),
            DiDontInstall = unchecked((int)0xe000022b),
            InvalidFilterDriver = unchecked((int)0xe000022c),
            NonWindowsNTDriver = unchecked((int)0xe000022d),
            NonWindowsDriver = unchecked((int)0xe000022e),
            NoCatalogForOemInf = unchecked((int)0xe000022f),
            DevInstallQueueNonNative = unchecked((int)0xe0000230),
            NotDisableable = unchecked((int)0xe0000231),
            CantRemoveDevinst = unchecked((int)0xe0000232),
            InvalidTarget = unchecked((int)0xe0000233),
            DriverNonNative = unchecked((int)0xe0000234),
            InWow64 = unchecked((int)0xe0000235),
            SetSystemRestorePoint = unchecked((int)0xe0000236),
            IncorrectlyCopiedInf = unchecked((int)0xe0000237),
            SceDisabled = unchecked((int)0xe0000238),
            UnknownException = unchecked((int)0xe0000239),
            PnpRegistryError = unchecked((int)0xe000023a),
            RemoteRequestUnsupported = unchecked((int)0xe000023b),
            NotAnInstalledOemInf = unchecked((int)0xe000023c),
            InfInUseByDevices = unchecked((int)0xe000023d),
            DiFunctionObsolete = unchecked((int)0xe000023e),
            NoAuthenticodeCatalog = unchecked((int)0xe000023f),
            AuthenticodeDisallowed = unchecked((int)0xe0000240),
            AuthenticodeTrustedPublisher = unchecked((int)0xe0000241),
            AuthenticodeTrustNotEstablished = unchecked((int)0xe0000242),
            AuthenticodePublisherNotTrusted = unchecked((int)0xe0000243),
            SignatureOSAttributeMismatch = unchecked((int)0xe0000244),
            OnlyValidateViaAuthenticode = unchecked((int)0xe0000245),
            NoMoreItems = unchecked((int)0xe0000259),
            ElementNotFound = unchecked((int)0xe0001168),
            InvalidData = unchecked((int)0xe0000013),
        }
        #endregion

        #region NATIVE STRUCTS
        [StructLayout(LayoutKind.Sequential)]
        private struct DeviceInfoDataNative
        {
            public int Size;
            public Guid ClassGuid;
            public int DeviceInstance;
            public IntPtr Reserved;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct ClassInstallHeader
        {
            public int Size;
            public DiFunction InstallFunction;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct PropertyChangeParameters
        {
            public ClassInstallHeader ClassInstallHeader;

            public StateChangeAction StateChange;
            public Scope Scope;
            public int HwProfile;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct RemoveDeviceParameters
        {
            public ClassInstallHeader ClassInstallHeader;
            public Scope Scope;
            public int HwProfile;
        }

        [StructLayout(LayoutKind.Sequential)]
        private struct DevicePropertyKey
        {
            public Guid fmtId;
            public int pId;

            // from devpkey.h
            public static readonly DevicePropertyKey Device_Parent = new DevicePropertyKey { fmtId = new Guid("{4340A6C5-93FA-4706-972C-7B648008A5A7}"), pId = 8 };
            public static readonly DevicePropertyKey Device_Children = new DevicePropertyKey { fmtId = new Guid("{4340A6C5-93FA-4706-972C-7B648008A5A7}"), pId = 9 };
        }
        #endregion

        #region P/INVOKE
        [SuppressUnmanagedCodeSecurity()]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [DllImport(SetupAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetupDiDestroyDeviceInfoList(IntPtr deviceInfoSet);

        [DllImport(SetupAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetupDiCallClassInstaller(DiFunction installFunction, SafeDeviceInfoSetHandle deviceInfoSet, [In()] ref DeviceInfoDataNative deviceInfoData);

        [DllImport(SetupAPI, SetLastError = true)]
        private static extern bool SetupDiEnumDeviceInfo(SafeDeviceInfoSetHandle DeviceInfoSet, int MemberIndex, ref DeviceInfoDataNative DeviceInfoData);

        [DllImport(SetupAPI, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, SetLastError = true)]
        private static extern SafeDeviceInfoSetHandle SetupDiGetClassDevs(ref Guid ClassGuid, [MarshalAs(UnmanagedType.LPWStr)] string Enumerator, IntPtr HwndParent, SetupDiGetClassDevsFlags Flags);

        [DllImport(SetupAPI, SetLastError = true, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetupDiGetDeviceInstanceId(IntPtr deviceInfoSet, ref DeviceInfoDataNative did, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder DeviceInstanceId, int DeviceInstanceIdSize, out int RequiredSize);

        [DllImport(SetupAPI, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetupDiSetClassInstallParams(SafeDeviceInfoSetHandle deviceInfoSet, [In()] ref DeviceInfoDataNative deviceInfoData, [In()] ref RemoveDeviceParameters classInstallParams, int classInstallParamsSize);

        [DllImport("Newdev.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool DiUninstallDevice(IntPtr hwnd, [In()] SafeDeviceInfoSetHandle deviceInfoSet, [In()] ref DeviceInfoDataNative deviceInfoData, [In()] int flags, out bool NeedReboot);

        [DllImport(SetupAPI, SetLastError = true, EntryPoint = "SetupDiGetDevicePropertyW")]
        private static extern bool SetupDiGetDeviceProperty(SafeDeviceInfoSetHandle deviceInfoSet, ref DeviceInfoDataNative DeviceInfoData, ref DevicePropertyKey propertyKey, out int propertyType, IntPtr propertyBuffer, int propertyBufferSize, out int requiredSize, int flags);
        #endregion

        private class SafeDeviceInfoSetHandle : SafeHandleZeroOrMinusOneIsInvalid
        {

            private SafeDeviceInfoSetHandle() : base(true)
            {
            }

            protected override bool ReleaseHandle()
            {
                return SetupDiDestroyDeviceInfoList(this.handle);
            }
        }

        private static DeviceInfoDataNative GetDeviceInfoData(SafeDeviceInfoSetHandle handle)
        {
            DeviceInfoDataNative _data = new DeviceInfoDataNative();

            _data.Size = Marshal.SizeOf(_data);

            if (!SetupDiEnumDeviceInfo(handle, 0, ref _data))
            {
                int error = Marshal.GetLastWin32Error();

                if (error == (int)SetupApiError.NoMoreItems)                                    
                    return _data;

                throw new Win32Exception(error);
            }

            return _data;
        }

        private static DeviceInfoDataNative[] GetDevicesInfoData(SafeDeviceInfoSetHandle handle)
        {
            List<DeviceInfoDataNative> _data = new List<DeviceInfoDataNative>();
            DeviceInfoDataNative deviceInfoData = new DeviceInfoDataNative();

            int index = 0;
            int deviceInfoDataSize = Marshal.SizeOf(deviceInfoData);

            deviceInfoData.Size = deviceInfoDataSize;

            while (SetupDiEnumDeviceInfo(handle, index, ref deviceInfoData))
            {
                _data.Add(deviceInfoData);
                index += 1;
                deviceInfoData = new DeviceInfoDataNative();
                deviceInfoData.Size = deviceInfoDataSize;
            }

            return _data.ToArray();
        }

        private static int GetIndexOfInstance(SafeDeviceInfoSetHandle handle, DeviceInfoDataNative[] diData, string instanceId)
        {
            const int ERROR_INSUFFICIENT_BUFFER = 122;
            for (int index = 0; index <= diData.Length - 1; index++)
            {
                StringBuilder sb = new StringBuilder(1);
                int requiredSize = 0;
                bool result = SetupDiGetDeviceInstanceId(handle.DangerousGetHandle(), ref diData[index], sb, sb.Capacity, out requiredSize);
                if (result == false && Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
                {
                    sb.Capacity = requiredSize;
                    result = SetupDiGetDeviceInstanceId(handle.DangerousGetHandle(), ref diData[index], sb, sb.Capacity, out requiredSize);
                }
                if (result == false)
                    throw new Win32Exception();
                if (instanceId.Equals(sb.ToString()))
                {
                    return index;
                }
            }
            // not found
            return -1;
        }

        public static bool UninstallDevice(Guid classGuid, string instanceId)
        {
            SafeDeviceInfoSetHandle handle = null;
            bool result = false;

            try
            {
                // Get the handle to a device information set for all devices matching classGuid that are present on the system.
                handle = SetupDiGetClassDevs(ref classGuid, instanceId, IntPtr.Zero, SetupDiGetClassDevsFlags.AllClasses | SetupDiGetClassDevsFlags.DeviceInterface);

                if (handle.IsInvalid)
                    throw new Win32Exception(Marshal.GetLastWin32Error());

                // Get the device information data for each matching device.
                DeviceInfoDataNative data = GetDeviceInfoData(handle);

                // Find the index of our instance. i.e. the touchpad mouse - I have 3 mice attached...
                //int index = GetIndexOfInstance(handle, diData, instanceId);

                // TODO: Check the data structure first

                // Uninstall
                result = StartUninstallDevice(handle, data);
            }
            finally
            {
                if (handle != null)
                {
                    if (handle.IsClosed == false)
                    {
                        handle.Close();
                    }

                    handle.Dispose();
                }                
            }

            return result;
        }

        private static bool StartUninstallDevice(SafeDeviceInfoSetHandle handle, DeviceInfoDataNative data)
        {
            ClassInstallHeader header = new ClassInstallHeader();
            RemoveDeviceParameters removalParameters = new RemoveDeviceParameters();

            bool needsReboot;

            removalParameters.ClassInstallHeader.Size = Marshal.SizeOf(header);
            removalParameters.ClassInstallHeader.InstallFunction = DiFunction.Remove;
            removalParameters.Scope = Scope.Global;
            removalParameters.HwProfile = 0;

            bool result = SetupDiSetClassInstallParams(handle, ref data, ref removalParameters, Marshal.SizeOf(removalParameters));

            if (result == false)
                throw new Win32Exception();

            result = DiUninstallDevice(IntPtr.Zero, handle, ref data, 0, out needsReboot);

            // TODO: Check if need reboot

            if (result == false)
            {
                int error = Marshal.GetLastWin32Error();

                if (error == (int)SetupApiError.NotDisableable)
                    throw new ArgumentException("Device can't be disabled (programmatically or in Device Manager)");
                else if (error >= (int)SetupApiError.NoAssociatedClass && error <= (int)SetupApiError.OnlyValidateViaAuthenticode)
                    throw new Win32Exception("SetupAPI Error: " + ((SetupApiError)error).ToString());
                else
                    throw new Win32Exception();
            }

            return result;
        }

        public static void RemoveDevice(Guid classGuid, string instanceId)
        {
            SafeDeviceInfoSetHandle handle = null;

            try
            {
                // Get the handle to a device information set for all devices matching classGuid that are present on the system.
                handle = SetupDiGetClassDevs(ref classGuid, instanceId, IntPtr.Zero, SetupDiGetClassDevsFlags.AllClasses | SetupDiGetClassDevsFlags.DeviceInterface);

                if (handle.IsInvalid)
                    throw new Win32Exception(Marshal.GetLastWin32Error());

                // Get the device information data for each matching device.
                DeviceInfoDataNative data = GetDeviceInfoData(handle);

                // Find the index of our instance. i.e. the touchpad mouse - I have 3 mice attached...
                //int index = GetIndexOfInstance(handle, diData, instanceId);

                // Uninstall
                bool result = StartRemoveDevice(handle, data);
            }
            finally
            {
                if (handle != null)
                {
                    if (handle.IsClosed == false)
                    {
                        handle.Close();
                    }
                    handle.Dispose();
                }
            }
        }

        private static bool StartRemoveDevice(SafeDeviceInfoSetHandle handle, DeviceInfoDataNative data)
        {
            ClassInstallHeader header = new ClassInstallHeader();
            RemoveDeviceParameters removalParameters = new RemoveDeviceParameters();

            removalParameters.ClassInstallHeader.Size = Marshal.SizeOf(header);
            removalParameters.ClassInstallHeader.InstallFunction = DiFunction.Remove;
            removalParameters.Scope = Scope.Global;
            removalParameters.HwProfile = 0;

            bool result = SetupDiSetClassInstallParams(handle, ref data, ref removalParameters, Marshal.SizeOf(removalParameters));

            if (result == false)
                throw new Win32Exception();

            result = SetupDiCallClassInstaller(DiFunction.Remove, handle, ref data);

            if (result == false)
            {
                int error = Marshal.GetLastWin32Error();

                if (error == (int)SetupApiError.NotDisableable)
                    throw new ArgumentException("Device can't be disabled (programmatically or in Device Manager).");
                else if (error >= (int)SetupApiError.NoAssociatedClass && error <= (int)SetupApiError.OnlyValidateViaAuthenticode)
                    throw new Win32Exception("SetupAPI Error: " + ((SetupApiError)error).ToString());
                else
                    throw new Win32Exception();
            }

            return result;
        }
    }
}

Применение:

/////* CD-ROM as an example */////

// Found in the Device Manager under <Device> -> Properties -> Details -> Class Guid
Guid cdromClassGuid = new Guid("4d36e965-e325-11ce-bfc1-08002be10318");

// Found using WMI calls -> Disk -> Partitions -> LogicalDisks
// For the CD-ROM example: Device Manager under <Device> -> Properties -> Details -> Device Instance Path
string cdromInstancePath = @"SCSI\CDROM&VEN_MATSHITA&PROD_BD-RE_UJ260AF\4&315C1285&0&000000";

bool success = SetupApiWrapper.UninstallDevice(cdromClassGuid, cdromInstancePath);
person parkerflyz    schedule 19.09.2017
comment
К сожалению, если вы перенумеруете устройства (сканируете аппаратные изменения, повторно сканируете диски), устройство показывает резервную копию. Не совсем то поведение, которое я хочу. - person parkerflyz; 29.09.2017