예제 #1
0
        private static string GetDeviceInstanceId(SafeCmConnectMachineHandle safeMachineHandle, string hostName, NativeMethods.SP_DEVINFO_DATA diData)
        {
            uint ptrPrevious;

            var lastError = NativeMethods.CM_Get_Parent_Ex(out ptrPrevious, diData.DevInst, 0, safeMachineHandle);

            if (lastError != Win32Errors.CR_SUCCESS)
            {
                NativeError.ThrowException(lastError, hostName);
            }


            using (var safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize / 8)) // 512
            {
                lastError = NativeMethods.CM_Get_Device_ID_Ex(diData.DevInst, safeBuffer, (uint)safeBuffer.Capacity, 0, safeMachineHandle);

                if (lastError != Win32Errors.CR_SUCCESS)
                {
                    NativeError.ThrowException(lastError, hostName);
                }


                // Device InstanceID, such as: "USB\VID_8087&PID_0A2B\5&2EDA7E1E&0&7", "SCSI\DISK&VEN_SANDISK&PROD_X400\4&288ED25&0&000200", ...

                return(safeBuffer.PtrToStringUni());
            }
        }
예제 #2
0
        private static string GetDeviceRegistryProperty(SafeHandle safeHandle, NativeMethods.SP_DEVINFO_DATA infoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum property)
        {
            var bufferSize = NativeMethods.DefaultFileBufferSize / 8; // 512

            while (true)
            {
                using (var safeBuffer = new SafeGlobalMemoryBufferHandle(bufferSize))
                {
                    var success = NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref infoData, property, IntPtr.Zero, safeBuffer, (uint)safeBuffer.Capacity, IntPtr.Zero);

                    var lastError = Marshal.GetLastWin32Error();

                    if (success)
                    {
                        var value = safeBuffer.PtrToStringUni();

                        return(!Utils.IsNullOrWhiteSpace(value) ? value.Trim() : null);
                    }


                    // MSDN: SetupDiGetDeviceRegistryProperty returns ERROR_INVALID_DATA error code if
                    // the requested property does not exist for a device or if the property data is not valid.

                    if (lastError == Win32Errors.ERROR_INVALID_DATA)
                    {
                        return(null);
                    }


                    bufferSize = GetDoubledBufferSizeOrThrowException(lastError, safeBuffer, bufferSize, property.ToString());
                }
            }
        }
예제 #3
0
        public BackupStreamInfo ReadStreamInfo()
        {
            using (SafeGlobalMemoryBufferHandle hBuf = new SafeGlobalMemoryBufferHandle(Marshal.SizeOf(typeof(NativeMethods.WIN32_STREAM_ID))))
            {
                uint numberOfBytesRead;
                if (!NativeMethods.BackupRead(_safeFileHandle, hBuf, (uint)Marshal.SizeOf(typeof(NativeMethods.WIN32_STREAM_ID)), out numberOfBytesRead, false, mProcessSecurity, ref m_context))
                {
                    NativeError.ThrowException();
                }

                if (numberOfBytesRead == 0)
                {
                    return(null);
                }

                if (numberOfBytesRead < Marshal.SizeOf(typeof(NativeMethods.WIN32_STREAM_ID)))
                {
                    throw new IOException(Resources.IncompleteHeaderRead);
                }

                NativeMethods.WIN32_STREAM_ID streamID = hBuf.PtrToStructure <NativeMethods.WIN32_STREAM_ID>();

                uint nameLength = (uint)Math.Min(streamID.StreamNameSize, hBuf.Capacity);
                if (!NativeMethods.BackupRead(_safeFileHandle, hBuf, nameLength, out numberOfBytesRead, false, mProcessSecurity, ref m_context))
                {
                    NativeError.ThrowException();
                }

                string name = hBuf.PtrToStringUni((int)nameLength / 2);

                return(new BackupStreamInfo(streamID, name));
            }
        }
예제 #4
0
        public BackupStreamInfo ReadStreamInfo()
        {
            var sizeOf = Marshal.SizeOf(typeof(NativeMethods.WIN32_STREAM_ID));

            using (var hBuf = new SafeGlobalMemoryBufferHandle(sizeOf))
            {
                uint numberOfBytesRead;

                var success = NativeMethods.BackupRead(SafeFileHandle, hBuf, (uint)sizeOf, out numberOfBytesRead, false, _processSecurity, ref _context);

                var lastError = Marshal.GetLastWin32Error();
                if (!success)
                {
                    NativeError.ThrowException(lastError);
                }


                if (numberOfBytesRead == 0)
                {
                    return(null);
                }


                if (numberOfBytesRead < sizeOf)
                {
                    throw new IOException(Resources.Read_Incomplete_Header);
                }


                var streamID   = hBuf.PtrToStructure <NativeMethods.WIN32_STREAM_ID>(0);
                var nameLength = (uint)Math.Min(streamID.dwStreamNameSize, hBuf.Capacity);


                success = NativeMethods.BackupRead(SafeFileHandle, hBuf, nameLength, out numberOfBytesRead, false, _processSecurity, ref _context);

                lastError = Marshal.GetLastWin32Error();
                if (!success)
                {
                    NativeError.ThrowException(lastError);
                }


                var name = hBuf.PtrToStringUni(0, (int)nameLength / UnicodeEncoding.CharSize);

                return(new BackupStreamInfo(streamID, name));
            }
        }
예제 #5
0
        internal static IEnumerable <FileIdBothDirectoryInfo> EnumerateFileIdBothDirectoryInfoCore(KernelTransaction transaction, SafeFileHandle safeFileHandle, string path, FileShare shareMode, bool continueOnException, PathFormat pathFormat)
        {
            if (!NativeMethods.IsAtLeastWindowsVista)
            {
                throw new PlatformNotSupportedException(new Win32Exception((int)Win32Errors.ERROR_OLD_WIN_VERSION).Message);
            }


            var pathLp = path;

            var callerHandle = null != safeFileHandle;

            if (!callerHandle)
            {
                if (Utils.IsNullOrWhiteSpace(path))
                {
                    throw new ArgumentNullException("path");
                }

                pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck);

                safeFileHandle = File.CreateFileCore(transaction, pathLp, ExtendedFileAttributes.BackupSemantics, null, FileMode.Open, FileSystemRights.ReadData, shareMode, true, false, PathFormat.LongFullPath);
            }


            try
            {
                if (!NativeMethods.IsValidHandle(safeFileHandle, Marshal.GetLastWin32Error(), !continueOnException))
                {
                    yield break;
                }

                var fileNameOffset = (int)Marshal.OffsetOf(typeof(NativeMethods.FILE_ID_BOTH_DIR_INFO), "FileName");

                using (var safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
                {
                    while (true)
                    {
                        var success = NativeMethods.GetFileInformationByHandleEx(safeFileHandle, NativeMethods.FILE_INFO_BY_HANDLE_CLASS.FILE_ID_BOTH_DIR_INFO, safeBuffer, (uint)safeBuffer.Capacity);

                        var lastError = Marshal.GetLastWin32Error();
                        if (!success)
                        {
                            switch ((uint)lastError)
                            {
                            case Win32Errors.ERROR_SUCCESS:
                            case Win32Errors.ERROR_NO_MORE_FILES:
                            case Win32Errors.ERROR_HANDLE_EOF:
                                yield break;

                            case Win32Errors.ERROR_MORE_DATA:
                                continue;

                            default:
                                NativeError.ThrowException(lastError, pathLp);

                                // Keep the compiler happy as we never get here.
                                yield break;
                            }
                        }


                        var offset = 0;
                        NativeMethods.FILE_ID_BOTH_DIR_INFO fibdi;

                        do
                        {
                            fibdi = safeBuffer.PtrToStructure <NativeMethods.FILE_ID_BOTH_DIR_INFO>(offset);

                            var fileName = safeBuffer.PtrToStringUni(offset + fileNameOffset, (int)(fibdi.FileNameLength / UnicodeEncoding.CharSize));

                            offset += fibdi.NextEntryOffset;


                            if (File.IsDirectory(fibdi.FileAttributes) &&
                                (fileName.Equals(Path.CurrentDirectoryPrefix, StringComparison.Ordinal) ||
                                 fileName.Equals(Path.ParentDirectoryPrefix, StringComparison.Ordinal)))
                            {
                                continue;
                            }


                            yield return(new FileIdBothDirectoryInfo(fibdi, fileName));


                            //offset += fibdi.NextEntryOffset;
                        } while (fibdi.NextEntryOffset != 0);
                    }
                }
            }
            finally
            {
                // Handle is ours, dispose.
                if (!callerHandle && null != safeFileHandle)
                {
                    safeFileHandle.Close();
                }
            }
        }
예제 #6
0
        internal static IEnumerable <DeviceInfo> EnumerateDevicesCore(SafeHandle safeHandle, string hostName, DeviceGuid deviceInterfaceGuid)
        {
            bool callerHandle = safeHandle != null;
            var  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.LocalToUncCore(Host.GetUncName(hostName), false, false, false), out safeMachineHandle);

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

            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.Handle_Is_Invalid);
                }


                try
                {
                    uint memberInterfaceIndex = 0;
                    NativeMethods.SP_DEVICE_INTERFACE_DATA 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.SP_DEVINFO_DATA deviceInfoData = CreateDeviceInfoDataInstance();
                        NativeMethods.SP_DEVICE_INTERFACE_DETAIL_DATA 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.
                        var 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 (var 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);
                            }

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

                        #region Get Registry Properties

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


                            if (NativeMethods.SetupDiGetDeviceRegistryProperty(safeHandle, ref deviceInfoData, NativeMethods.SetupDiGetDeviceRegistryPropertyEnum.BaseContainerId, out regType, safeBuffer, safeBufferCapacity, IntPtr.Zero))
                            {
                                dataString = safeBuffer.PtrToStringUni();
                                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 = safeBuffer.PtrToStringUni();
                                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 = safeBuffer.PtrToStringUni();
                            }

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

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

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

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

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

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

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

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

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

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

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

                        #endregion // Get Registry Properties

                        yield return(deviceInfo);

                        // Get new structure instance.
                        deviceInterfaceData = CreateDeviceInterfaceDataInstance();
                    }
                }
                finally
                {
                    // Handle is ours, dispose.
                    if (!callerHandle && safeHandle != null)
                    {
                        safeHandle.Close();
                    }
                }
            }
        }
예제 #7
0
        internal static IEnumerable <FileIdBothDirectoryInfo> EnumerateFileIdBothDirectoryInfoCore(KernelTransaction transaction, SafeFileHandle safeHandle, string path, FileShare shareMode, bool continueOnException, PathFormat pathFormat)
        {
            if (!NativeMethods.IsAtLeastWindowsVista)
            {
                throw new PlatformNotSupportedException(Resources.Requires_Windows_Vista_Or_Higher);
            }

            bool callerHandle = safeHandle != null;

            if (!callerHandle)
            {
                if (Utils.IsNullOrWhiteSpace(path))
                {
                    throw new ArgumentNullException("path");
                }

                string pathLp = Path.GetExtendedLengthPathCore(transaction, path, pathFormat, GetFullPathOptions.RemoveTrailingDirectorySeparator | GetFullPathOptions.FullCheck);

                safeHandle = File.CreateFileCore(transaction, pathLp, ExtendedFileAttributes.BackupSemantics, null, FileMode.Open, FileSystemRights.ReadData, shareMode, true, PathFormat.LongFullPath);
            }


            try
            {
                if (!NativeMethods.IsValidHandle(safeHandle, Marshal.GetLastWin32Error(), !continueOnException))
                {
                    yield break;
                }

                var fileNameOffset = (int)Marshal.OffsetOf(typeof(NativeMethods.FILE_ID_BOTH_DIR_INFO), "FileName");

                using (var safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
                {
                    while (true)
                    {
                        if (!NativeMethods.GetFileInformationByHandleEx(safeHandle, NativeMethods.FileInfoByHandleClass.FileIdBothDirectoryInfo, safeBuffer, (uint)safeBuffer.Capacity))
                        {
                            uint lastError = (uint)Marshal.GetLastWin32Error();
                            switch (lastError)
                            {
                            case Win32Errors.ERROR_SUCCESS:
                            case Win32Errors.ERROR_NO_MORE_FILES:
                            case Win32Errors.ERROR_HANDLE_EOF:
                                yield break;

                            case Win32Errors.ERROR_MORE_DATA:
                                continue;

                            default:
                                NativeError.ThrowException(lastError, path);
                                yield break; // we should never get to this yield break.
                            }
                        }

                        int offset = 0;
                        NativeMethods.FILE_ID_BOTH_DIR_INFO fibdi;
                        do
                        {
                            fibdi = safeBuffer.PtrToStructure <NativeMethods.FILE_ID_BOTH_DIR_INFO>(offset);
                            string fileName = safeBuffer.PtrToStringUni(offset + fileNameOffset, (int)(fibdi.FileNameLength / 2));

                            if (!fileName.Equals(Path.CurrentDirectoryPrefix, StringComparison.OrdinalIgnoreCase) &&
                                !fileName.Equals(Path.ParentDirectoryPrefix, StringComparison.OrdinalIgnoreCase))
                            {
                                yield return(new FileIdBothDirectoryInfo(fibdi, fileName));
                            }

                            offset += fibdi.NextEntryOffset;
                        }while (fibdi.NextEntryOffset != 0);
                    }
                }
            }
            finally
            {
                // Handle is ours, dispose.
                if (!callerHandle && safeHandle != null)
                {
                    safeHandle.Close();
                }
            }
        }
예제 #8
0
      public BackupStreamInfo ReadStreamInfo()
      {
         using (SafeGlobalMemoryBufferHandle hBuf = new SafeGlobalMemoryBufferHandle(Marshal.SizeOf(typeof(NativeMethods.WIN32_STREAM_ID))))
         {
            uint numberOfBytesRead;
            if (!NativeMethods.BackupRead(_safeFileHandle, hBuf, (uint)Marshal.SizeOf(typeof(NativeMethods.WIN32_STREAM_ID)), out numberOfBytesRead, false, mProcessSecurity, ref m_context))
               NativeError.ThrowException();

            if (numberOfBytesRead == 0)
               return null;

            if (numberOfBytesRead < Marshal.SizeOf(typeof(NativeMethods.WIN32_STREAM_ID)))
               throw new IOException(Resources.IncompleteHeaderRead);

            NativeMethods.WIN32_STREAM_ID streamID = hBuf.PtrToStructure<NativeMethods.WIN32_STREAM_ID>();

            uint nameLength = (uint)Math.Min(streamID.StreamNameSize, hBuf.Capacity);
            if (!NativeMethods.BackupRead(_safeFileHandle, hBuf, nameLength, out numberOfBytesRead, false, mProcessSecurity, ref m_context))
               NativeError.ThrowException();

            string name = hBuf.PtrToStringUni((int)nameLength / 2);

            return new BackupStreamInfo(streamID, name);

         }
      }