예제 #1
0
        /// <summary>
        /// Get the suggested link name for the device in the "\DosDevices\" format.
        /// </summary>
        public unsafe static string QuerySuggestedLinkName(SafeHandle deviceHandle)
        {
            return(BufferHelper.BufferInvoke(((HeapBuffer buffer) =>
            {
                buffer.EnsureByteCapacity((ulong)sizeof(MOUNTDEV_SUGGESTED_LINK_NAME));
                ControlCode controlCode = ControlCodes.MountDevice.QuerySuggestedLinkName;

                while (!Imports.DeviceIoControl(
                           hDevice: deviceHandle,
                           dwIoControlCode: controlCode,
                           lpInBuffer: null,
                           nInBufferSize: 0,
                           lpOutBuffer: buffer.VoidPointer,
                           nOutBufferSize: checked ((uint)buffer.ByteCapacity),
                           lpBytesReturned: out _,
                           lpOverlapped: null))
                {
                    WindowsError error = Error.GetLastError();
                    switch (error)
                    {
                    case WindowsError.ERROR_MORE_DATA:
                        buffer.EnsureByteCapacity(((MOUNTDEV_SUGGESTED_LINK_NAME *)buffer.VoidPointer)->NameLength + (ulong)sizeof(MOUNTDEV_SUGGESTED_LINK_NAME));
                        break;

                    default:
                        throw error.GetException();
                    }
                }

                return (((MOUNTDEV_SUGGESTED_LINK_NAME *)buffer.VoidPointer)->Name).CreateString();
            })));
        }
예제 #2
0
        /// <summary>
        /// Get the unique ID as presented to the mount manager by a device.
        /// </summary>
        public unsafe static byte[] QueryUniqueId(SafeHandle deviceHandle)
        {
            return(BufferHelper.BufferInvoke((HeapBuffer buffer) =>
            {
                buffer.EnsureByteCapacity((ulong)sizeof(MOUNTDEV_UNIQUE_ID));
                ControlCode controlCode = ControlCodes.MountDevice.QueryUniqueId;

                while (!Imports.DeviceIoControl(
                           hDevice: deviceHandle,
                           dwIoControlCode: controlCode,
                           lpInBuffer: null,
                           nInBufferSize: 0,
                           lpOutBuffer: buffer.VoidPointer,
                           nOutBufferSize: checked ((uint)buffer.ByteCapacity),
                           lpBytesReturned: out _,
                           lpOverlapped: null))
                {
                    WindowsError error = Error.GetLastError();
                    switch (error)
                    {
                    case WindowsError.ERROR_MORE_DATA:
                        buffer.EnsureByteCapacity(((MOUNTDEV_UNIQUE_ID *)buffer.VoidPointer)->UniqueIdLength + (ulong)sizeof(MOUNTDEV_UNIQUE_ID));
                        break;

                    default:
                        throw error.GetException();
                    }
                }

                return ((MOUNTDEV_UNIQUE_ID *)buffer.VoidPointer)->UniqueId.ToArray();
            }));
        }
예제 #3
0
        /// <summary>
        /// Gets the DOS drive letter for the given volume if it has one.
        /// </summary>
        public unsafe static string QueryDosVolumePath(string volume)
        {
            var mountManager = Storage.Storage.CreateFile(
                @"\\?\MountPointManager", CreationDisposition.OpenExisting, 0);

            ControlCode controlCode = ControlCodes.MountManager.QueryDosVolumePath;

            // Read ulong then get string
            string dosVolumePath = null;

            BufferHelper.BufferInvoke((StringBuffer inBuffer) =>
            {
                // The input is MOUNTMGR_TARGET_NAME which is a short length in bytes followed by the unicode string
                // https://msdn.microsoft.com/en-us/library/windows/hardware/ff562289.aspx

                inBuffer.Append((char)(volume.Length * sizeof(char)));
                inBuffer.Append(volume);

                BufferHelper.BufferInvoke((StringBuffer outBuffer) =>
                {
                    // Give enough for roughly 50 characters for a start
                    outBuffer.EnsureCharCapacity(50);

                    while (!Imports.DeviceIoControl(
                               hDevice: mountManager,
                               dwIoControlCode: controlCode,
                               lpInBuffer: inBuffer.VoidPointer,
                               nInBufferSize: checked ((uint)inBuffer.ByteCapacity),
                               lpOutBuffer: outBuffer.VoidPointer,
                               nOutBufferSize: checked ((uint)outBuffer.ByteCapacity),
                               lpBytesReturned: out _,
                               lpOverlapped: null))
                    {
                        WindowsError error = Error.GetLastError();
                        switch (error)
                        {
                        case WindowsError.ERROR_MORE_DATA:
                            outBuffer.EnsureByteCapacity(checked (outBuffer.ByteCapacity * 2));
                            break;

                        default:
                            throw error.GetException(volume);
                        }
                    }

                    // MOUNTMGR_VOLUME_PATHS is a uint length followed by a multi string (double null terminated)
                    // we only care about the first string in this case (should only be one?) so we can skip beyond
                    // the 4 bytes and read to null.
                    dosVolumePath = new string(outBuffer.CharPointer + 2);
                });
            });

            return(dosVolumePath);
        }
예제 #4
0
        /// <summary>
        /// Gets reparse point names for symbolic links and mount points.
        /// </summary>
        /// <param name="fileHandle">Handle for the reparse point, must be opened with <see cref="FileAccessRights.ReadExtendedAttributes"/>.</param>
        public unsafe static (string printName, string substituteName, ReparseTag tag) GetReparsePointNames(SafeFileHandle fileHandle)
        {
            return(BufferHelper.BufferInvoke((HeapBuffer buffer) =>
            {
                ControlCode controlCode = ControlCodes.FileSystem.GetReparsePoint;
                buffer.EnsureByteCapacity(1024);

                while (!Imports.DeviceIoControl(
                           hDevice: fileHandle,
                           dwIoControlCode: controlCode,
                           lpInBuffer: null,
                           nInBufferSize: 0,
                           lpOutBuffer: buffer.VoidPointer,
                           nOutBufferSize: checked ((uint)buffer.ByteCapacity),
                           lpBytesReturned: out _,
                           lpOverlapped: null))
                {
                    WindowsError error = Error.GetLastError();
                    switch (error)
                    {
                    case WindowsError.ERROR_SUCCESS:
                        // This can happen if the handle isn't a reparse point.
                        break;

                    case WindowsError.ERROR_MORE_DATA:
                        buffer.EnsureByteCapacity(buffer.ByteCapacity + 1024);
                        break;

                    default:
                        throw error.GetException();
                    }
                }

                ReparseTag reparseTag = ((REPARSE_DATA_BUFFER *)buffer.VoidPointer)->ReparseTag;

                string printName = null;
                string substitutename = null;

                if (reparseTag == ReparseTag.MountPoint)
                {
                    printName = ((REPARSE_DATA_BUFFER *)buffer.VoidPointer)->MountPointData.PrintName.CreateString();
                    substitutename = ((REPARSE_DATA_BUFFER *)buffer.VoidPointer)->MountPointData.SubstituteName.CreateString();
                }
                else if (reparseTag == ReparseTag.SymbolicLink)
                {
                    printName = ((REPARSE_DATA_BUFFER *)buffer.VoidPointer)->SymbolicLinkData.PrintName.CreateString();
                    substitutename = ((REPARSE_DATA_BUFFER *)buffer.VoidPointer)->SymbolicLinkData.SubstituteName.CreateString();
                }

                return (printName, substitutename, reparseTag);
            }));
        }
예제 #5
0
        /// <summary>
        /// Get the stable Guid for the given device handle.
        /// </summary>
        public unsafe static Guid QueryStableGuid(SafeHandle deviceHandle)
        {
            ControlCode controlCode = ControlCodes.MountDevice.QueryStableGuid;
            Guid        guid        = new Guid();

            if (!Imports.DeviceIoControl(
                    hDevice: deviceHandle,
                    dwIoControlCode: controlCode,
                    lpInBuffer: null,
                    nInBufferSize: 0,
                    lpOutBuffer: &guid,
                    nOutBufferSize: (uint)sizeof(Guid),
                    lpBytesReturned: out _,
                    lpOverlapped: null))
            {
                throw Error.GetExceptionForLastError();
            }

            return(guid);
        }