Ejemplo n.º 1
0
        /// <summary>
        /// Opens a thread token.
        /// </summary>
        public static AccessToken OpenThreadToken(AccessTokenRights desiredAccess, bool openAsSelf)
        {
            if (!Imports.OpenThreadToken(ThreadMethods.Imports.GetCurrentThread(), desiredAccess, openAsSelf, out var threadToken))
            {
                WindowsError error = Errors.GetLastError();
                if (error != WindowsError.ERROR_NO_TOKEN)
                {
                    throw Errors.GetIoExceptionForError(error, desiredAccess.ToString());
                }

                using (AccessToken processToken = OpenProcessToken(AccessTokenRights.Duplicate))
                {
                    if (!Imports.DuplicateTokenEx(
                            processToken,
                            AccessTokenRights.Impersonate | AccessTokenRights.Query | AccessTokenRights.AdjustPrivileges,
                            IntPtr.Zero,
                            SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
                            TOKEN_TYPE.TokenImpersonation,
                            ref threadToken))
                    {
                        throw Errors.GetIoExceptionForLastError(desiredAccess.ToString());
                    }
                }
            }

            return(threadToken);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Opens a thread token.
        /// </summary>
        public static SafeTokenHandle OpenThreadToken(TokenRights desiredAccess, bool openAsSelf)
        {
            SafeTokenHandle threadToken;

            if (!Direct.OpenThreadToken(ThreadMethods.Direct.GetCurrentThread(), desiredAccess, openAsSelf, out threadToken))
            {
                WindowsError error = ErrorHelper.GetLastError();
                if (error != WindowsError.ERROR_NO_TOKEN)
                {
                    throw ErrorHelper.GetIoExceptionForError(error, desiredAccess.ToString());
                }

                SafeTokenHandle processToken = OpenProcessToken(TokenRights.TOKEN_DUPLICATE);
                if (!Direct.DuplicateTokenEx(
                        processToken,
                        TokenRights.TOKEN_IMPERSONATE | TokenRights.TOKEN_QUERY | TokenRights.TOKEN_ADJUST_PRIVILEGES,
                        IntPtr.Zero,
                        SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation,
                        TOKEN_TYPE.TokenImpersonation,
                        ref threadToken))
                {
                    throw ErrorHelper.GetIoExceptionForLastError(desiredAccess.ToString());
                }
            }

            return(threadToken);
        }
Ejemplo n.º 3
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 = Errors.GetLastError();
                    switch (error)
                    {
                    case WindowsError.ERROR_MORE_DATA:
                        buffer.EnsureByteCapacity(((MOUNTDEV_UNIQUE_ID *)buffer.VoidPointer)->UniqueIdLength + (ulong)sizeof(MOUNTDEV_UNIQUE_ID));
                        break;

                    default:
                        throw Errors.GetIoExceptionForError(error);
                    }
                }

                return ((MOUNTDEV_UNIQUE_ID *)buffer.VoidPointer)->UniqueId.ToArray();
            }));
        }
Ejemplo n.º 4
0
            private string FindFirstVolume()
            {
                // Need at least some length on initial call or we'll get ERROR_INVALID_PARAMETER
                _buffer.EnsureCharCapacity(400);

                _findHandle = Imports.FindFirstVolumeMountPointW(
                    _volumeName,
                    _buffer,
                    _buffer.CharCapacity);

                if (_findHandle.IsInvalid)
                {
                    WindowsError error = Error.GetLastError();
                    switch (error)
                    {
                    // Not positive on this case as I haven't been able to get this API
                    // to fully work correctly yet.
                    case WindowsError.ERROR_MORE_DATA:
                        _buffer.EnsureCharCapacity(_buffer.CharCapacity + 64);
                        return(FindFirstVolume());

                    case WindowsError.ERROR_NO_MORE_FILES:
                        _lastEntryFound = true;
                        return(null);

                    default:
                        throw error.GetException();
                    }
                }

                _buffer.SetLengthToFirstNull();
                return(_buffer.ToString());
            }
Ejemplo n.º 5
0
        /// <summary>
        /// This only works for types that aren't built in (e.g. defined in ClipboardFormat).
        /// </summary>
        /// <exception cref="ArgumentException">Thrown if passing in a built-in format type.</exception>
        public static string GetClipboardFormatName(uint format)
        {
            return(BufferHelper.CachedInvoke((StringBuffer buffer) =>
            {
                realloc:

                int count = Direct.GetClipboardFormatNameW(format, buffer, (int)buffer.CharCapacity);
                if (count == 0)
                {
                    WindowsError error = ErrorHelper.GetLastError();
                    switch (error)
                    {
                    case WindowsError.ERROR_INSUFFICIENT_BUFFER:
                        buffer.EnsureCharCapacity(buffer.CharCapacity + 50);
                        goto realloc;

                    default:
                        throw ErrorHelper.GetIoExceptionForError(error);
                    }
                }

                buffer.Length = (uint)count;
                return buffer.ToString();
            }));
        }
Ejemplo n.º 6
0
        private unsafe static string GetMountDevName(SafeHandle deviceHandle, ControlCode controlCode)
        {
            return(BufferHelper.BufferInvoke((HeapBuffer buffer) =>
            {
                buffer.EnsureByteCapacity((ulong)sizeof(MOUNTDEV_NAME));

                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_NAME *)buffer.VoidPointer)->NameLength + (ulong)sizeof(MOUNTDEV_NAME));
                        break;

                    default:
                        throw error.GetException();
                    }
                }

                return ((MOUNTDEV_NAME *)buffer.VoidPointer)->Name.CreateString();
            }));
        }
Ejemplo n.º 7
0
        public static IEnumerable <string> EnumerateLocalGroups(string server = null)
        {
            var groups = new List <string>();

            WindowsError result = Imports.NetLocalGroupEnum(
                servername: server,
                level: 0,
                bufptr: out var buffer,
                prefmaxlen: Imports.MAX_PREFERRED_LENGTH,
                entriesread: out uint entriesRead,
                totalentries: out uint totalEntries,
                resumehandle: IntPtr.Zero);

            if (result != WindowsError.NERR_Success)
            {
                throw Errors.GetIoExceptionForError(result, server);
            }

            foreach (IntPtr pointer in ReadStructsFromBuffer <IntPtr>(buffer, entriesRead))
            {
                groups.Add(Marshal.PtrToStringUni(pointer));
            }

            return(groups);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Returns the list of all paths where the given volume name is mounted.
        /// </summary>
        /// <param name="volumeName">A volume GUID path for the volume (\\?\Volume{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}\).</param>
        public static IEnumerable <string> GetVolumePathNamesForVolumeName(string volumeName)
        {
            return(BufferHelper.BufferInvoke((StringBuffer buffer) =>
            {
                uint returnLength = 0;

                // GetLogicalDriveStringsPrivate takes the buffer count in TCHARs, which is 2 bytes for Unicode (WCHAR)
                while (!Imports.GetVolumePathNamesForVolumeNameW(volumeName, buffer, buffer.CharCapacity, ref returnLength))
                {
                    WindowsError error = Errors.GetLastError();
                    switch (error)
                    {
                    case WindowsError.ERROR_MORE_DATA:
                        buffer.EnsureCharCapacity(returnLength);
                        break;

                    default:
                        throw Errors.GetIoExceptionForError(error, volumeName);
                    }
                }

                Debug.Assert(returnLength != 2, "this should never happen can't have a string array without at least 3 chars");

                // If the return length is 1 there were no mount points. The buffer should be '\0'.
                if (returnLength < 3)
                {
                    return Enumerable.Empty <string>();
                }

                // The return length will be the entire length of the buffer, including the final string's
                // null and the string list's second null. Example: "Foo\0Bar\0\0" would be 9.
                buffer.Length = returnLength - 2;
                return buffer.Split('\0');
            }));
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Gets the formats that are currently available on the clipboard.
        /// </summary>
        public unsafe static uint[] GetAvailableClipboardFormats()
        {
            uint  countOut;
            uint  countIn = 5;
            uint *array;

realloc:
            {
                uint *alloc = stackalloc uint[(int)countIn];

                array = alloc;
                if (!Direct.GetUpdatedClipboardFormats(array, countIn, &countOut))
                {
                    WindowsError error = ErrorHelper.GetLastError();
                    switch (error)
                    {
                    case WindowsError.ERROR_INSUFFICIENT_BUFFER:
                        countIn = countOut;
                        goto realloc;

                    default:
                        throw ErrorHelper.GetIoExceptionForError(error);
                    }
                }
            }

            uint[] result = new uint[countOut];
            BufferHelper.CopyUintArray(array, result);
            return(result);
        }
Ejemplo n.º 10
0
        public static IEnumerable <MemberInfo> EnumerateGroupUsers(string groupName, string server = null)
        {
            var members = new List <MemberInfo>();

            WindowsError result = Imports.NetLocalGroupGetMembers(
                servername: server,
                localgroupname: groupName,
                level: 1,
                bufptr: out var buffer,
                prefmaxlen: Imports.MAX_PREFERRED_LENGTH,
                entriesread: out uint entriesRead,
                totalentries: out uint totalEntries,
                resumehandle: IntPtr.Zero);

            if (result != WindowsError.NERR_Success)
            {
                throw Errors.GetIoExceptionForError(result, server);
            }

            foreach (Imports.LOCALGROUP_MEMBERS_INFO_1 info in ReadStructsFromBuffer <Imports.LOCALGROUP_MEMBERS_INFO_1>(buffer, entriesRead))
            {
                members.Add(new MemberInfo
                {
                    Name        = Marshal.PtrToStringUni(info.lgrmi1_name),
                    AccountType = (SidNameUse)info.lgrmi1_sidusage
                });
            }

            return(members);
        }
Ejemplo n.º 11
0
        public static IEnumerable <string> GetVolumePathNamesForVolumeName(string volumeName)
        {
            return(BufferHelper.CachedInvoke((StringBuffer buffer) =>
            {
                uint returnLength = 0;

                // GetLogicalDriveStringsPrivate takes the buffer count in TCHARs, which is 2 bytes for Unicode (WCHAR)
                while (!Direct.GetVolumePathNamesForVolumeNameW(volumeName, buffer, buffer.CharCapacity, ref returnLength))
                {
                    WindowsError error = ErrorHelper.GetLastError();
                    switch (error)
                    {
                    case WindowsError.ERROR_MORE_DATA:
                        buffer.EnsureCharCapacity(returnLength);
                        break;

                    default:
                        throw ErrorHelper.GetIoExceptionForError(error, volumeName);
                    }
                }

                buffer.Length = returnLength;
                return buffer.Split('\0');
            }));
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Get the list of data streams for the given handle.
        /// </summary>
        public unsafe static IEnumerable <StreamInformation> GetStreamInformation(SafeFileHandle fileHandle)
        {
            return(BufferHelper.BufferInvoke((HeapBuffer buffer) =>
            {
                unsafe
                {
                    while (!Imports.GetFileInformationByHandleEx(fileHandle, FileInfoClass.FileStreamInfo,
                                                                 buffer.VoidPointer, checked ((uint)buffer.ByteCapacity)))
                    {
                        WindowsError error = Error.GetLastError();
                        switch (error)
                        {
                        case WindowsError.ERROR_HANDLE_EOF:
                            // No streams
                            return Enumerable.Empty <StreamInformation>();

                        case WindowsError.ERROR_MORE_DATA:
                            buffer.EnsureByteCapacity(buffer.ByteCapacity * 2);
                            break;

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

                return StreamInformation.Create((FILE_STREAM_INFORMATION *)buffer.VoidPointer);
            }));
        }
Ejemplo n.º 13
0
 /// <summary>
 /// Throw a relevant exception if <paramref name="error"/> is a failure.
 /// </summary>
 /// <param name="path">Optional path or other input detail.</param>
 public static void ThrowIfFailed(this WindowsError error, string?path = null)
 {
     if (error != WindowsError.ERROR_SUCCESS)
     {
         error.Throw(path);
     }
 }
Ejemplo n.º 14
0
 public static void ThrowIfFailed(this WindowsError error, string path = null)
 {
     if (error != WindowsError.ERROR_SUCCESS)
     {
         throw error.GetException(path);
     }
 }
Ejemplo n.º 15
0
            private string FindNextVolume()
            {
                Debug.Assert(!(_findHandle is null));

                if (_buffer is null)
                {
                    throw new ObjectDisposedException(nameof(VolumeNamesEnumerator));
                }

                if (!Imports.FindNextVolumeW(_findHandle, _buffer, _buffer.CharCapacity))
                {
                    WindowsError error = Error.GetLastError();
                    switch (error)
                    {
                    case WindowsError.ERROR_FILENAME_EXCED_RANGE:
                        _buffer.EnsureCharCapacity(_buffer.CharCapacity + 64);
                        return(FindNextVolume());

                    case WindowsError.ERROR_NO_MORE_FILES:
                        _lastEntryFound = true;
                        return(string.Empty);

                    default:
                        throw error.GetException();
                    }
                }

                _buffer.SetLengthToFirstNull();
                return(_buffer.ToString());
            }
Ejemplo n.º 16
0
            private string FindFirstVolume()
            {
                if (_buffer is null)
                {
                    throw new ObjectDisposedException(nameof(VolumeNamesEnumerator));
                }

                _findHandle = Imports.FindFirstVolumeW(
                    _buffer,
                    _buffer.CharCapacity);

                if (_findHandle.IsInvalid)
                {
                    WindowsError error = Error.GetLastError();
                    if (error == WindowsError.ERROR_FILENAME_EXCED_RANGE)
                    {
                        _buffer.EnsureCharCapacity(_buffer.CharCapacity + 64);
                        return(FindFirstVolume());
                    }

                    throw error.GetException();
                }

                _buffer.SetLengthToFirstNull();
                return(_buffer.ToString());
            }
Ejemplo n.º 17
0
        private FindResult FindFirstFile()
        {
            WIN32_FIND_DATA findData;

            _findHandle = FileMethods.Direct.FindFirstFileExW(
                OriginalPath,
                GetAlternateName ? FINDEX_INFO_LEVELS.FindExInfoStandard : FINDEX_INFO_LEVELS.FindExInfoBasic,
                out findData,
                // FINDEX_SEARCH_OPS.FindExSearchNameMatch is what FindFirstFile calls Ex wtih
                DirectoriesOnly ? FINDEX_SEARCH_OPS.FindExSearchLimitToDirectories : FINDEX_SEARCH_OPS.FindExSearchNameMatch,
                IntPtr.Zero,
                FindFirstFileExFlags.FIND_FIRST_EX_LARGE_FETCH);

            if (_findHandle == (IntPtr)(-1))
            {
                _findHandle = IntPtr.Zero;
                WindowsError error = ErrorHelper.GetLastError();
                if (error == WindowsError.ERROR_FILE_NOT_FOUND)
                {
                    return(null);
                }

                throw ErrorHelper.GetIoExceptionForLastError(OriginalPath);
            }

            return(new FindResult(findData, OriginalPath));
        }
Ejemplo n.º 18
0
            private string FindNextVolume()
            {
                if (!Imports.FindNextVolumeMountPointW(_findHandle, _buffer, _buffer.CharCapacity))
                {
                    WindowsError error = Error.GetLastError();
                    switch (error)
                    {
                    // Not positive on this case as I haven't been able to get this API
                    // to fully work correctly yet.
                    case WindowsError.ERROR_MORE_DATA:
                        _buffer.EnsureCharCapacity(_buffer.CharCapacity + 64);
                        return(FindNextVolume());

                    case WindowsError.ERROR_NO_MORE_FILES:
                        _lastEntryFound = true;
                        return(null);

                    default:
                        throw error.GetException();
                    }
                }

                _buffer.SetLengthToFirstNull();
                return(_buffer.ToString());
            }
Ejemplo n.º 19
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 = Errors.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 Errors.GetIoExceptionForError(error);
                    }
                }

                return (((MOUNTDEV_SUGGESTED_LINK_NAME *)buffer.VoidPointer)->Name).CreateString();
            })));
        }
Ejemplo n.º 20
0
        /// <summary>
        /// Returns true if the current process is a Windows Store application (WinRT).
        /// </summary>
        public static bool IsWindowsStoreApplication()
        {
            if (s_isWinRT == -1)
            {
                BufferHelper.BufferInvoke((StringBuffer buffer) =>
                {
                    uint bufferSize = buffer.CharCapacity;
                    try
                    {
                        WindowsError result = Imports.GetCurrentApplicationUserModelId(ref bufferSize, buffer);
                        switch (result)
                        {
                        case WindowsError.APPMODEL_ERROR_NO_APPLICATION:
                            s_isWinRT = 0;
                            break;

                        case WindowsError.ERROR_SUCCESS:
                        case WindowsError.ERROR_INSUFFICIENT_BUFFER:
                            s_isWinRT = 1;
                            break;

                        default:
                            throw result.GetException();
                        }
                    }
                    catch (EntryPointNotFoundException)
                    {
                        s_isWinRT = 0;
                    }
                });
            }

            return(s_isWinRT == 1);
        }
Ejemplo n.º 21
0
        /// <summary>
        /// Gets the user name in the specified format. Returns null for
        /// formats that aren't mapped.
        /// </summary>
        public static string?GetUserName(ExtendedNameFormat format)
        {
            return(BufferHelper.BufferInvoke((StringBuffer buffer) =>
            {
                uint size = buffer.CharCapacity;
                while (!Imports.GetUserNameExW(format, buffer, ref size))
                {
                    WindowsError error = Error.GetLastError();
                    switch (error)
                    {
                    case WindowsError.ERROR_NONE_MAPPED:
                        return null;

                    case WindowsError.ERROR_MORE_DATA:
                        buffer.EnsureCharCapacity(size);
                        break;

                    default:
                        throw error.GetException();
                    }
                }

                buffer.Length = size;
                return buffer.ToString();
            }));
        }
Ejemplo n.º 22
0
        // Access to the MountPointManager is denied for store apps
        public static string QueryDosVolumePath(string volume)
        {
            var mountManager = FileManagement.FileMethods.CreateFile(
                @"\\?\MountPointManager", 0, ShareMode.FILE_SHARE_READWRITE, CreationDisposition.OPEN_EXISTING, FileAttributes.FILE_ATTRIBUTE_NORMAL);

            uint controlCode = DeviceMacros.CTL_CODE(ControlCodeDeviceType.MOUNTMGRCONTROLTYPE, 12, ControlCodeMethod.METHOD_BUFFERED, ControlCodeAccess.FILE_ANY_ACCESS);

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

            BufferHelper.CachedInvoke((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.CachedInvoke((StringBuffer outBuffer) =>
                {
                    // Give enough for roughly 50 characters for a start
                    outBuffer.EnsureCharCapacity(50);

                    uint bytesReturned;

                    while (!Direct.DeviceIoControl(
                               hDevice: mountManager.DangerousGetHandle(),
                               dwIoControlCode: controlCode,
                               lpInBuffer: inBuffer.DangerousGetHandle(),
                               nInBufferSize: checked ((uint)inBuffer.ByteCapacity),
                               lpOutBuffer: outBuffer.DangerousGetHandle(),
                               nOutBufferSize: checked ((uint)outBuffer.ByteCapacity),
                               lpBytesReturned: out bytesReturned,
                               lpOverlapped: IntPtr.Zero))
                    {
                        WindowsError error = ErrorHelper.GetLastError();
                        switch (error)
                        {
                        case WindowsError.ERROR_MORE_DATA:
                            outBuffer.EnsureByteCapacity(checked (outBuffer.ByteCapacity * 2));
                            break;

                        default:
                            throw ErrorHelper.GetIoExceptionForError(error, 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.
                    unsafe
                    {
                        dosVolumePath = new string(outBuffer.CharPointer + 2);
                    }
                });
            });

            return(dosVolumePath);
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Get the list of data streams for the given handle.
        /// </summary>
        public static IEnumerable <StreamInformation> GetStreamInformationByHandle(SafeFileHandle fileHandle)
        {
            // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364406.aspx

            // typedef struct _FILE_STREAM_INFO
            // {
            //     DWORD NextEntryOffset;
            //     DWORD StreamNameLength;
            //     LARGE_INTEGER StreamSize;
            //     LARGE_INTEGER StreamAllocationSize;
            //     WCHAR StreamName[1];
            // } FILE_STREAM_INFO, *PFILE_STREAM_INFO;

            return(BufferHelper.CachedInvoke <IEnumerable <StreamInformation>, HeapBuffer>((buffer) =>
            {
                unsafe
                {
                    while (!Direct.GetFileInformationByHandleEx(fileHandle, FILE_INFO_BY_HANDLE_CLASS.FileStreamInfo,
                                                                buffer.VoidPointer, checked ((uint)buffer.ByteCapacity)))
                    {
                        WindowsError error = ErrorHelper.GetLastError();
                        switch (error)
                        {
                        case WindowsError.ERROR_HANDLE_EOF:
                            // No streams
                            return Enumerable.Empty <StreamInformation>();

                        case WindowsError.ERROR_MORE_DATA:
                            buffer.EnsureByteCapacity(buffer.ByteCapacity * 2);
                            break;

                        default:
                            throw ErrorHelper.GetIoExceptionForError(error);
                        }
                    }
                }

                var infos = new List <StreamInformation>();
                var reader = new CheckedReader(buffer);
                uint offset = 0;

                do
                {
                    reader.ByteOffset = offset;
                    offset = reader.ReadUint();
                    uint nameLength = reader.ReadUint();
                    infos.Add(new StreamInformation
                    {
                        Size = reader.ReadUlong(),
                        AllocationSize = reader.ReadUlong(),
                        Name = reader.ReadString((int)(nameLength / 2))
                    });
                } while (offset != 0);

                return infos;
            }));
        }
Ejemplo n.º 24
0
        public static void NetApiBufferFree(IntPtr buffer)
        {
            WindowsError result = Imports.NetApiBufferFree(buffer);

            if (result != WindowsError.NERR_Success)
            {
                throw Errors.GetIoExceptionForError(result);
            }
        }
Ejemplo n.º 25
0
        public static void ThrowIfLastErrorNot(WindowsError error, string?path = null)
        {
            WindowsError lastError = Imports.GetLastError();

            if (lastError != error)
            {
                throw lastError.GetException(path);
            }
        }
Ejemplo n.º 26
0
        public static void ThrowIfLastErrorNot(WindowsError error, string path = null)
        {
            WindowsError lastError = GetLastError();

            if (lastError != error)
            {
                throw GetIoExceptionForError(lastError, path);
            }
        }
Ejemplo n.º 27
0
        /// <summary>
        ///  Returns true if the given value exists.
        /// </summary>
        public static unsafe bool QueryValueExists(RegistryKeyHandle key, string valueName)
        {
            WindowsError result = Imports.RegQueryValueExW(key, valueName, null, null, null, null);

            return(result switch
            {
                WindowsError.ERROR_SUCCESS => true,
                WindowsError.ERROR_FILE_NOT_FOUND => false,
                _ => throw result.GetException(),
            });
Ejemplo n.º 28
0
        /// <summary>
        /// Turns Windows errors into the appropriate exception (that maps with existing .NET behavior as much as possible).
        /// There are additional IOException derived errors for ease of client error handling.
        /// </summary>
        public static Exception GetIoExceptionForError(WindowsError error, string path = null)
        {
            // http://referencesource.microsoft.com/#mscorlib/system/io/__error.cs,142

            string message = path == null
                ? $"{LastErrorToString(error)}"
                : $"{LastErrorToString(error)} '{path}'";

            return(WindowsErrorToException(error, message, path));
        }
        public void FindFirstFileBehaviors()
        {
            using (var cleaner = new TestFileCleaner())
            {
                IntPtr result = FileMethods.Imports.FindFirstFileW(cleaner.TempFolder, out WIN32_FIND_DATA findData);
                try
                {
                    IsValid(result).Should().BeTrue("root location exists");
                }
                finally
                {
                    if (IsValid(result))
                    {
                        FileMethods.Imports.FindClose(result);
                    }
                }

                result = FileMethods.Imports.FindFirstFileW(cleaner.GetTestPath(), out findData);
                WindowsError error = Errors.GetLastError();

                try
                {
                    IsValid(result).Should().BeFalse("non-existant file");
                    error.Should().Be(WindowsError.ERROR_FILE_NOT_FOUND);
                }
                finally
                {
                    if (IsValid(result))
                    {
                        FileMethods.Imports.FindClose(result);
                    }
                }

                result = FileMethods.Imports.FindFirstFileW(Paths.Combine(cleaner.GetTestPath(), "NotHere"), out findData);
                error  = Errors.GetLastError();

                try
                {
                    IsValid(result).Should().BeFalse("non-existant subdir");
                    error.Should().Be(WindowsError.ERROR_PATH_NOT_FOUND);
                }
                finally
                {
                    if (IsValid(result))
                    {
                        FileMethods.Imports.FindClose(result);
                    }
                }
            }

            bool IsValid(IntPtr value)
            {
                return(value != IntPtr.Zero && value != (IntPtr)(-1));
            }
        }
Ejemplo n.º 30
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 = FileMethods.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 = Errors.GetLastError();
                        switch (error)
                        {
                        case WindowsError.ERROR_MORE_DATA:
                            outBuffer.EnsureByteCapacity(checked (outBuffer.ByteCapacity * 2));
                            break;

                        default:
                            throw Errors.GetIoExceptionForError(error, 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);
        }