Использование OpenVirtualDisk () возвращает код ошибки 2 «Файл не найден» Windows 10 - PullRequest
0 голосов
/ 16 мая 2018

Добрый вечер всем. Я надеюсь, что сообщество, возможно, сможет помочь в моей маленькой проблеме программирования на C #. Я скажу здесь, что я очень новичок в программировании на C # и что это очень крутая кривая обучения от Borland Pascal!

В настоящее время я пытаюсь использовать API виртуального диска (как указано на здесь на веб-сайте MSDN), переводя на c # (надеюсь, в рамках управляемого контекста).

Мне удалось заставить OpenVirtualDisk () принять первый параметр, но он не проходит по второму (путь к файлу указанного ISO, который я хотел бы открыть и присоединить.) Из многих исследований я объявляю параметр «Путь» в виде строки, чтобы CLR лучше соответствовал сигнатуре функции.

Приложение в настоящее время запускается с ограниченными правами (через Visual Studio 2017)

Вот мой dllImport:

        [DllImport("VirtDisk.dll", EntryPoint = "OpenVirtualDisk", CharSet = CharSet.Ansi, ThrowOnUnmappableChar = true ,SetLastError = true)]
        public extern static Int64 OpenVirtualDisk(
                                               [In] ref _VIRTUAL_STORAGE_TYPE PVIRTUAL_STORAGE_TYPE,
                                               string Path,
                                               _VIRTUAL_DISK_ACCESS_MASK LVIRTUAL_DISK_ACCESS_MASK,
                                               long OPEN_VIRTUAL_DISK_FLAG,
                                               [In, Optional] ref OPEN_VIRTUAL_DISK_PARAMTERS POPEN_VIRTUAL_DISK_PARAMTERS,
                                               ref IntPtr pHandle);

Все остальные константы, перечисления и структуры объявляются как предусмотрено VirtDisk.h, при необходимости могут быть предоставлены.

Вот весь код, который я использую для вызова OpenVirtualDisk (как вы можете видеть, я использую File.Exists (), чтобы убедиться, что файл существует до начала любой работы):

        private void button1_Click(object sender, EventArgs e)
        {
          IntPtr pHandle = IntPtr.Zero;
          Int64 RetVal = 0;
          string VirtualDiskPath = @"F:\Images\Windows10.ISO";
          _VIRTUAL_DISK_ACCESS_MASK VIRTUAL_DISK_ACCESS;
          Int64 VIRTUAL_DISK_FLAG;
          _VIRTUAL_STORAGE_TYPE VIRTUAL_STORAGE_TYPE;

        if (File.Exists(VirtualDiskPath))
        {

            VIRTUAL_DISK_ACCESS = _VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_ATTACH_ALL;
            VIRTUAL_DISK_FLAG = OPEN_VIRTUAL_DISK_FLAG_NONE;

            VIRTUAL_STORAGE_TYPE.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_ISO;
            VIRTUAL_STORAGE_TYPE.VendorId = VENDORMICROSOFT;

            IntPtr VirtualStorPtr = IntPtr.Zero;
            VirtualStorPtr = Marshal.AllocHGlobal(Marshal.SizeOf(VIRTUAL_STORAGE_TYPE));
            Marshal.StructureToPtr(VIRTUAL_STORAGE_TYPE, VirtualStorPtr, true);

            IntPtr VirtualDiskVer = IntPtr.Zero;
            OPEN_VIRTUAL_DISK_PARAMTERS OPEN_VIRTUAL_DISK_PARAM;
            OPEN_VIRTUAL_DISK_PARAM = new OPEN_VIRTUAL_DISK_PARAMTERS
            {
                version = OPEN_VIRTUAL_DISK_VERSION.OPEN_VIRTUAL_DISK_VERSION_1,
                version1 = new OPEN_VIRTUAL_DISK_PARAMTERS1
                {
                    RWDepth = 0
                }
            };

            VirtualDiskVer = Marshal.AllocHGlobal(Marshal.SizeOf(OPEN_VIRTUAL_DISK_PARAM));
            Marshal.StructureToPtr(OPEN_VIRTUAL_DISK_PARAM, VirtualDiskVer, true);

            RetVal = OpenVirtualDisk(ref VIRTUAL_STORAGE_TYPE,
                                     VirtualDiskPath,
                                     VIRTUAL_DISK_ACCESS,
                                     VIRTUAL_DISK_FLAG,
                                     ref OPEN_VIRTUAL_DISK_PARAM,
                                     ref pHandle);
            if ((RetVal == 0))
            {
                MessageBox.Show("OpenVirtualDisk() has succeded in opening the file: \r\n" +
                                VirtualDiskPath + "\r\nWith the file Handle: " + pHandle.ToString());
            }
            else
            {
                MessageBox.Show("OpenVirtualDisk() failed to open the file: " +
                                VirtualDiskPath + ",\r\nWith Error Code: " + Marshal.GetLastWin32Error().ToString() +
                                "\r\nReturn Value: " + RetVal.ToString());
            }
            Marshal.FreeHGlobal(VirtualStorPtr);

        }
    }

До сих пор каждая попытка имела либо RetVal 87 «Неверный параметр» с GetLastWin32Error, сообщающий 1008 «Неверный токен», либо RetVal 2 «Файл не найден» с GetLastWin32Error, сообщающий об одном и том же.

Может кто-нибудь определить, где я иду не так?

Заранее спасибо.

Richie

N.B. Это часть пакета восстановления, который я создавал в c # на основе Windows Imaging API (Wimgapi.h). Это позволяет установить Windows (любой версии, если она 64-битная), если это необходимо. Он будет работать на WinPE (Windows 10, .Net версии 5.4.2). Я даже пытался использовать FileIOPermssion, чтобы разрешить этому процессу полный доступ к файлу.

Ошибка была отсортирована, как показано ниже. FILE_ACCESS_MASK необходимо изменить на FILE_ACCESS_MASK_RO, но объявление DLLimport также необходимо адаптировать. DLLImport теперь читает:

[DllImport ("virtdisk.dll" CharSet = CharSet.UNICODE, ThrowOnUnmappableChar = true, SetLastError = true)] public extern static Int64 OpenVirtualDisk ( [In] ref _VIRTUAL_STORAGE_TYPE PVIRTUAL_STORAGE_TYPE, Путь строки, [In] _VIRTUAL_DISK_ACCESS_MASK LVIRTUAL_DISK_ACCESS_MASK, [В] длинном OPEN_VIRTUAL_DISK_FLAG, [In, Необязательно] ref OPEN_VIRTUAL_DISK_PARAMTERS POPEN_VIRTUAL_DISK_PARAMTERS, [In] ref IntPtr pHandle);

1 Ответ

0 голосов
/ 16 мая 2018

Я уже открывал виртуальные ISO-образы и выложу свой код для вас:

public static class NativeMethods
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule", Justification = "Warning is bogus.")]
    [DllImport("virtdisk.dll", CharSet = CharSet.Unicode)]
    public static extern Int32 OpenVirtualDisk(ref VIRTUAL_STORAGE_TYPE VirtualStorageType, 
        string Path, 
        VIRTUAL_DISK_ACCESS_MASK VirtualDiskAccessMask, 
        OPEN_VIRTUAL_DISK_FLAG Flags, 
        ref OPEN_VIRTUAL_DISK_PARAMETERS Parameters, 
        ref VirtualDiskSafeHandle Handle);

    public static readonly Guid VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT = new Guid("EC984AEC-A0F9-47e9-901F-71415A66345B");
    public const int OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT = 1;

    public const Int32 ERROR_SUCCESS = 0;
    public const Int32 ERROR_FILE_CORRUPT = 1392;
    public const Int32 ERROR_FILE_NOT_FOUND = 2;
    public const Int32 ERROR_PATH_NOT_FOUND = 3;
    public const Int32 ERROR_ACCESS_DENIED = 5;

    /// CD or DVD image file device type. (.iso file)
    /// </summary>
    public const int VIRTUAL_STORAGE_TYPE_DEVICE_ISO = 1;

    /// <summary>
    /// Device type is unknown or not valid.
    /// </summary>
    public const int VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN = 0;

    /// <summary>
    /// Virtual hard disk device type. (.vhd file)
    /// </summary>
    public const int VIRTUAL_STORAGE_TYPE_DEVICE_VHD = 2;

    /// <summary>
    /// VHDX format virtual hard disk device type. (.vhdx file)
    /// </summary>
    public const int VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 3;

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct VIRTUAL_STORAGE_TYPE
    {
        /// <summary>
        /// Device type identifier.
        /// </summary>
        public Int32 DeviceId; //ULONG

        /// <summary>
        /// Vendor-unique identifier.
        /// </summary>
        public Guid VendorId; //GUID
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct OPEN_VIRTUAL_DISK_PARAMETERS
    {
        /// <summary>
        /// An OPEN_VIRTUAL_DISK_VERSION enumeration that specifies the version of the OPEN_VIRTUAL_DISK_PARAMETERS structure being passed to or from the VHD functions.
        /// </summary>
        public OPEN_VIRTUAL_DISK_VERSION Version; //OPEN_VIRTUAL_DISK_VERSION

        /// <summary>
        /// A structure.
        /// </summary>
        public OPEN_VIRTUAL_DISK_PARAMETERS_Version1 Version1;
    }

    public enum OPEN_VIRTUAL_DISK_VERSION : int
    {
        /// <summary>
        /// </summary>
        OPEN_VIRTUAL_DISK_VERSION_UNSPECIFIED = 0,

        /// <summary>
        /// </summary>
        OPEN_VIRTUAL_DISK_VERSION_1 = 1
    }

    [Flags]
    public enum VirtualDiskAccessMask : int
    {
        /// <summary>
        /// Open the virtual disk for read-only attach access. The caller must have READ access to the virtual disk image file. If used in a request to open a virtual disk that is already open, the other handles must be limited to either VIRTUAL_DISK_ACCESS_DETACH or VIRTUAL_DISK_ACCESS_GET_INFO access, otherwise the open request with this flag will fail.
        /// </summary>
        AttachReadOnly = 0x00010000,
        /// <summary>
        /// Open the virtual disk for read-write attaching access. The caller must have (READ | WRITE) access to the virtual disk image file. If used in a request to open a virtual disk that is already open, the other handles must be limited to either VIRTUAL_DISK_ACCESS_DETACH or VIRTUAL_DISK_ACCESS_GET_INFO access, otherwise the open request with this flag will fail. If the virtual disk is part of a differencing chain, the disk for this request cannot be less than the RWDepth specified during the prior open request for that differencing chain.
        /// </summary>
        AttachReadWrite = 0x00020000,
        /// <summary>
        /// Open the virtual disk to allow detaching of an attached virtual disk. The caller must have (FILE_READ_ATTRIBUTES | FILE_READ_DATA) access to the virtual disk image file.
        /// </summary>
        Detach = 0x00040000,
        /// <summary>
        /// Information retrieval access to the VHD. The caller must have READ access to the virtual disk image file.
        /// </summary>
        GetInfo = 0x00080000,
        /// <summary>
        /// VHD creation access.
        /// </summary>
        Create = 0x00100000,
        /// <summary>
        /// Open the VHD to perform offline meta-operations. The caller must have (READ | WRITE) access to the virtual disk image file, up to RWDepth if working with a differencing chain. If the VHD is part of a differencing chain, the backing store (host volume) is opened in RW exclusive mode up to RWDepth.
        /// </summary>
        MetaOperations = 0x00200000,
        /// <summary>
        /// Allows unrestricted access to the VHD. The caller must have unrestricted access rights to the virtual disk image file.
        /// </summary>
        All = 0x003f0000,
    }

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct OPEN_VIRTUAL_DISK_PARAMETERS_Version1
    {
        /// <summary>
        /// Indicates the number of stores, beginning with the child, of the backing store chain to open as read/write. The remaining stores in the differencing chain will be opened read-only. This is necessary for merge operations to succeed.
        /// </summary>
        public Int32 RWDepth; //ULONG
    }

    public enum OPEN_VIRTUAL_DISK_FLAG : int
    {
        /// <summary>
        /// No flag specified.
        /// </summary>
        OPEN_VIRTUAL_DISK_FLAG_NONE = 0x00000000,

        /// <summary>
        /// Open the backing store without opening any differencing-chain parents. Used to correct broken parent links.
        /// </summary>
        OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS = 0x00000001,

        /// <summary>
        /// Reserved.
        /// </summary>
        OPEN_VIRTUAL_DISK_FLAG_BLANK_FILE = 0x00000002,

        /// <summary>
        /// Reserved.
        /// </summary>
        OPEN_VIRTUAL_DISK_FLAG_BOOT_DRIVE = 0x00000004
    }

    public enum VIRTUAL_DISK_ACCESS_MASK : int
    {
        /// <summary>
        /// Open the virtual disk for read-only attach access. The caller must have READ access to the virtual disk image file. If used in a request to open a virtual disk that is already open, the other handles must be limited to either VIRTUAL_DISK_ACCESS_DETACH or VIRTUAL_DISK_ACCESS_GET_INFO access, otherwise the open request with this flag will fail.
        /// </summary>
        VIRTUAL_DISK_ACCESS_ATTACH_RO = 0x00010000,

        /// <summary>
        /// Open the virtual disk for read-write attaching access. The caller must have (READ | WRITE) access to the virtual disk image file. If used in a request to open a virtual disk that is already open, the other handles must be limited to either VIRTUAL_DISK_ACCESS_DETACH or VIRTUAL_DISK_ACCESS_GET_INFO access, otherwise the open request with this flag will fail. If the virtual disk is part of a differencing chain, the disk for this request cannot be less than the RWDepth specified during the prior open request for that differencing chain.
        /// </summary>
        VIRTUAL_DISK_ACCESS_ATTACH_RW = 0x00020000,

        /// <summary>
        /// Open the virtual disk to allow detaching of an attached virtual disk. The caller must have (FILE_READ_ATTRIBUTES | FILE_READ_DATA) access to the virtual disk image file.
        /// </summary>
        VIRTUAL_DISK_ACCESS_DETACH = 0x00040000,

        /// <summary>
        /// Information retrieval access to the VHD. The caller must have READ access to the virtual disk image file.
        /// </summary>
        VIRTUAL_DISK_ACCESS_GET_INFO = 0x00080000,

        /// <summary>
        /// VHD creation access.
        /// </summary>
        VIRTUAL_DISK_ACCESS_CREATE = 0x00100000,

        /// <summary>
        /// Open the VHD to perform offline meta-operations. The caller must have (READ | WRITE) access to the virtual disk image file, up to RWDepth if working with a differencing chain. If the VHD is part of a differencing chain, the backing store (host volume) is opened in RW exclusive mode up to RWDepth.
        /// </summary>
        VIRTUAL_DISK_ACCESS_METAOPS = 0x00200000,

        /// <summary>
        /// Reserved.
        /// </summary>
        VIRTUAL_DISK_ACCESS_READ = 0x000d0000,

        /// <summary>
        /// Allows unrestricted access to the VHD. The caller must have unrestricted access rights to the virtual disk image file.
        /// </summary>
        VIRTUAL_DISK_ACCESS_ALL = 0x003f0000,

        /// <summary>
        /// Reserved.
        /// </summary>
        VIRTUAL_DISK_ACCESS_WRITABLE = 0x00320000
    }

}

[SecurityPermission(SecurityAction.Demand)]
public class VirtualDiskSafeHandle : SafeHandle
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule", Justification = "Warning is bogus.")]
    [DllImportAttribute("kernel32.dll", SetLastError = true)]
    [return: MarshalAsAttribute(UnmanagedType.Bool)]
    public static extern Boolean CloseHandle(IntPtr hObject);

    public VirtualDiskSafeHandle()
        : base(IntPtr.Zero, true)
    {
    }

    public override bool IsInvalid
    {
        get { return (this.IsClosed) || (base.handle == IntPtr.Zero); }
    }

    public override string ToString()
    {
        return this.handle.ToString();
    }

    protected override bool ReleaseHandle()
    {
        return CloseHandle(handle);
    }

    public IntPtr Handle
    {
        get { return handle; }
    }
}

Чтобы использовать его, создайте метод, подобный этому:

private VirtualDiskSafeHandle OpenIso(string fileName, NativeMethods.VirtualDiskAccessMask fileAccessMask)
{
    var parameters = new NativeMethods.OPEN_VIRTUAL_DISK_PARAMETERS();
    parameters.Version = NativeMethods.OPEN_VIRTUAL_DISK_VERSION.OPEN_VIRTUAL_DISK_VERSION_1;
    parameters.Version1.RWDepth = NativeMethods.OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT;

    var storageType = new NativeMethods.VIRTUAL_STORAGE_TYPE();
    storageType.DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_ISO;
    storageType.VendorId = NativeMethods.VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT;

    fileAccessMask = ((fileAccessMask & NativeMethods.VirtualDiskAccessMask.GetInfo) == NativeMethods.VirtualDiskAccessMask.GetInfo) ? NativeMethods.VirtualDiskAccessMask.GetInfo : 0;
    fileAccessMask |= NativeMethods.VirtualDiskAccessMask.AttachReadOnly;

    VirtualDiskSafeHandle handle = new VirtualDiskSafeHandle();

    int res = NativeMethods.OpenVirtualDisk(ref storageType, fileName,
        (NativeMethods.VIRTUAL_DISK_ACCESS_MASK) fileAccessMask,
        NativeMethods.OPEN_VIRTUAL_DISK_FLAG.OPEN_VIRTUAL_DISK_FLAG_NONE, ref parameters, ref handle);

    if (res == NativeMethods.ERROR_SUCCESS)
    {
        return handle;
    }
    else
    {
        handle.SetHandleAsInvalid();
        if ((res == NativeMethods.ERROR_FILE_NOT_FOUND) || (res == NativeMethods.ERROR_PATH_NOT_FOUND))
        {
            throw new FileNotFoundException("File not found.");
        }
        else if (res == NativeMethods.ERROR_ACCESS_DENIED)
        {
            throw new IOException("Access is denied.");
        }
        else if (res == NativeMethods.ERROR_FILE_CORRUPT)
        {
            throw new InvalidDataException("File type not recognized.");
        }
        else
        {
            throw new Win32Exception(res);
        }
    }
}

И затем во всей вашей программе вы просто можете сделать это:

VirtualDiskSafeHandle handle = OpenIso(@"c:\IsoLocation\Isoname.iso", NativeMethods.VirtualDiskAccessMask.All);
MessageBox.Show($"Handle = {handle.Handle}");

Надеюсь, это поможет !!

...