Example #1
0
        internal static IEnumerable <AlternateDataStreamInfo> EnumerateStreamsInternal(bool?isFolder, KernelTransaction transaction, SafeFileHandle safeHandle, string path, string originalName, StreamType?streamType, bool?isFullPath)
        {
            string pathLp = null;

            bool callerHandle = safeHandle != null;

            if (!callerHandle)
            {
                pathLp = isFullPath == null
               ? path
               : (bool)isFullPath
                  ? Path.GetLongPathInternal(path, false, false, false, false)
                  : Path.GetFullPathInternal(transaction, path, true, false, false, true, false, true, false);

                if (isFolder == null)
                {
                    FileAttributes attrs = File.GetAttributesExInternal <FileAttributes>(transaction, pathLp, null);
                    isFolder = (attrs & FileAttributes.Directory) == FileAttributes.Directory;
                }

                safeHandle = File.CreateFileInternal(transaction, pathLp,
                                                     (bool)isFolder
                  ? ExtendedFileAttributes.BackupSemantics
                  : ExtendedFileAttributes.Normal, null,
                                                     FileMode.Open, FileSystemRights.Read, FileShare.ReadWrite, false, null);
            }
            else
            {
                NativeMethods.IsValidHandle(safeHandle);
            }


            try
            {
                using (new PrivilegeEnabler(Privilege.Backup))
                    using (SafeGlobalMemoryBufferHandle safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
                    {
                        Type   typeWin32Stream = typeof(NativeMethods.Win32StreamId);
                        uint   sizeOfType      = (uint)Marshal.SizeOf(typeWin32Stream);
                        uint   numberOfBytesRead;
                        IntPtr context;

                        bool doLoop = true;
                        while (doLoop)
                        {
                            if (!NativeMethods.BackupRead(safeHandle, safeBuffer, sizeOfType, out numberOfBytesRead, false, true, out context))
                            {
                                // Throws IOException.
                                NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp, true);
                            }

                            doLoop = numberOfBytesRead == sizeOfType;
                            if (doLoop)
                            {
                                string streamName       = null;
                                string streamSearchName = null;


                                // CA2001:AvoidCallingProblematicMethods

                                IntPtr buffer     = IntPtr.Zero;
                                bool   successRef = false;
                                safeBuffer.DangerousAddRef(ref successRef);

                                // MSDN: The DangerousGetHandle method poses a security risk because it can return a handle that is not valid.
                                if (successRef)
                                {
                                    buffer = safeBuffer.DangerousGetHandle();
                                }

                                safeBuffer.DangerousRelease();

                                if (buffer == IntPtr.Zero)
                                {
                                    NativeError.ThrowException(Resources.HandleDangerousRef);
                                }

                                // CA2001:AvoidCallingProblematicMethods


                                NativeMethods.Win32StreamId stream = Utils.MarshalPtrToStructure <NativeMethods.Win32StreamId>(0, buffer);

                                if (streamType == null || stream.StreamType == streamType)
                                {
                                    if (stream.StreamNameSize > 0)
                                    {
                                        if (!NativeMethods.BackupRead(safeHandle, safeBuffer, stream.StreamNameSize, out numberOfBytesRead, false, true, out context))
                                        {
                                            // Throws IOException.
                                            NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp, true);
                                        }


                                        // CA2001:AvoidCallingProblematicMethods

                                        buffer     = IntPtr.Zero;
                                        successRef = false;
                                        safeBuffer.DangerousAddRef(ref successRef);

                                        // MSDN: The DangerousGetHandle method poses a security risk because it can return a handle that is not valid.
                                        if (successRef)
                                        {
                                            buffer = safeBuffer.DangerousGetHandle();
                                        }

                                        safeBuffer.DangerousRelease();

                                        if (buffer == IntPtr.Zero)
                                        {
                                            NativeError.ThrowException(Resources.HandleDangerousRef);
                                        }

                                        // CA2001:AvoidCallingProblematicMethods


                                        streamName = Marshal.PtrToStringUni(buffer, (int)numberOfBytesRead / 2);

                                        // Returned stream name format: ":streamName:$DATA"
                                        streamSearchName = streamName.TrimStart(Path.StreamSeparatorChar).Replace(Path.StreamSeparator + "$DATA", string.Empty);
                                    }

                                    if (originalName == null || (streamSearchName != null && streamSearchName.Equals(originalName, StringComparison.OrdinalIgnoreCase)))
                                    {
                                        yield return(new AlternateDataStreamInfo(stream, transaction, pathLp ?? path, streamName, originalName ?? streamSearchName, isFolder, isFullPath));
                                    }
                                }

                                uint lo, hi;
                                doLoop = !NativeMethods.BackupSeek(safeHandle, uint.MinValue, uint.MaxValue, out lo, out hi, out context);
                            }
                        }

                        // MSDN: To release the memory used by the data structure,
                        // call BackupRead with the bAbort parameter set to TRUE when the backup operation is complete.
                        if (!NativeMethods.BackupRead(safeHandle, safeBuffer, 0, out numberOfBytesRead, true, false, out context))
                        {
                            // Throws IOException.
                            NativeError.ThrowException(Marshal.GetLastWin32Error(), pathLp, true);
                        }
                    }
            }
            finally
            {
                // Handle is ours, dispose.
                if (!callerHandle && safeHandle != null)
                {
                    safeHandle.Close();
                }
            }
        }
        internal static IEnumerable <FileIdBothDirectoryInfo> EnumerateFileIdBothDirectoryInfoInternal(KernelTransaction transaction, SafeFileHandle safeHandle, string path, FileShare shareMode, bool continueOnException, PathFormat pathFormat)
        {
            if (!NativeMethods.IsAtLeastWindowsVista)
            {
                throw new PlatformNotSupportedException(Resources.RequiresWindowsVistaOrHigher);
            }

            bool callerHandle = safeHandle != null;

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

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

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


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

                // 2014-10-16: Number of returned items depends on the size of the buffer.
                // That does not seem right, investigate.
                using (var safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
                {
                    NativeMethods.IsValidHandle(safeBuffer, Marshal.GetLastWin32Error());

                    long fileNameOffset = Marshal.OffsetOf(typeof(NativeMethods.FileIdBothDirInfo), "FileName").ToInt64();

                    while (NativeMethods.GetFileInformationByHandleEx(safeHandle, NativeMethods.FileInfoByHandleClass.FileIdBothDirectoryInfo, safeBuffer.DangerousGetHandle(), NativeMethods.DefaultFileBufferSize))
                    {
                        // CA2001:AvoidCallingProblematicMethods

                        IntPtr buffer     = IntPtr.Zero;
                        bool   successRef = false;
                        safeBuffer.DangerousAddRef(ref successRef);

                        // MSDN: The DangerousGetHandle method poses a security risk because it can return a handle that is not valid.
                        if (successRef)
                        {
                            buffer = safeBuffer.DangerousGetHandle();
                        }

                        safeBuffer.DangerousRelease();

                        if (buffer == IntPtr.Zero)
                        {
                            NativeError.ThrowException(Resources.HandleDangerousRef);
                        }

                        // CA2001:AvoidCallingProblematicMethods


                        while (buffer != IntPtr.Zero)
                        {
                            NativeMethods.FileIdBothDirInfo fibdi = Utils.MarshalPtrToStructure <NativeMethods.FileIdBothDirInfo>(0, buffer);

                            string fileName = Marshal.PtrToStringUni(new IntPtr(fileNameOffset + buffer.ToInt64()), (int)(fibdi.FileNameLength / 2));

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


                            buffer = fibdi.NextEntryOffset == 0
                        ? IntPtr.Zero
                        : new IntPtr(buffer.ToInt64() + fibdi.NextEntryOffset);
                        }
                    }

                    int lastError = Marshal.GetLastWin32Error();
                    switch ((uint)lastError)
                    {
                    case Win32Errors.ERROR_SUCCESS:
                    case Win32Errors.ERROR_NO_MORE_FILES:
                    case Win32Errors.ERROR_HANDLE_EOF:
                        yield break;

                    default:
                        NativeError.ThrowException(lastError, path);
                        break;
                    }
                }
            }
            finally
            {
                // Handle is ours, dispose.
                if (!callerHandle && safeHandle != null)
                {
                    safeHandle.Close();
                }
            }
        }
Example #3
0
File: Device.cs Project: CDEApp/CDE
        internal static LinkTargetInfo GetLinkTargetInfoInternal(SafeFileHandle safeHandle)
        {
            // Start with a large buffer to prevent a 2nd call.
            uint bytesReturned = NativeMethods.MaxPathUnicode;

            using (SafeGlobalMemoryBufferHandle safeBuffer = new SafeGlobalMemoryBufferHandle((int)bytesReturned))
            {
                do
                {
                    // Possible PInvoke signature bug: safeBuffer.Capacity and bytesReturned are always the same.
                    // Since a large buffer is used, we are not affected.

                    // DeviceIoControlMethod.Buffered = 0,
                    // DeviceIoControlFileDevice.FileSystem = 9
                    // FsctlGetReparsePoint = (DeviceIoControlFileDevice.FileSystem << 16) | (42 << 2) | DeviceIoControlMethod.Buffered | (0 << 14)

                    if (!NativeMethods.DeviceIoControl(safeHandle, ((9 << 16) | (42 << 2) | 0 | (0 << 14)), IntPtr.Zero, 0, safeBuffer, (uint)safeBuffer.Capacity, out bytesReturned, IntPtr.Zero))
                    {
                        int lastError = Marshal.GetLastWin32Error();
                        switch ((uint)lastError)
                        {
                        case Win32Errors.ERROR_MORE_DATA:
                        case Win32Errors.ERROR_INSUFFICIENT_BUFFER:
                            if (safeBuffer.Capacity < bytesReturned)
                            {
                                safeBuffer.Close();
                                break;
                            }

                            // Throws IOException.
                            NativeError.ThrowException(lastError, true);
                            break;
                        }
                    }
                    else
                    {
                        break;
                    }
                } while (true);



                // CA2001:AvoidCallingProblematicMethods

                IntPtr buffer     = IntPtr.Zero;
                bool   successRef = false;
                safeBuffer.DangerousAddRef(ref successRef);

                // MSDN: The DangerousGetHandle method poses a security risk because it can return a handle that is not valid.
                if (successRef)
                {
                    buffer = safeBuffer.DangerousGetHandle();
                }

                safeBuffer.DangerousRelease();

                if (buffer == IntPtr.Zero)
                {
                    NativeError.ThrowException(Resources.HandleDangerousRef);
                }

                // CA2001:AvoidCallingProblematicMethods


                Type   toMountPointReparseBuffer   = typeof(NativeMethods.MountPointReparseBuffer);
                Type   toReparseDataBufferHeader   = typeof(NativeMethods.ReparseDataBufferHeader);
                Type   toSymbolicLinkReparseBuffer = typeof(NativeMethods.SymbolicLinkReparseBuffer);
                IntPtr marshalReparseBuffer        = Marshal.OffsetOf(toReparseDataBufferHeader, "data");

                NativeMethods.ReparseDataBufferHeader header = Utils.MarshalPtrToStructure <NativeMethods.ReparseDataBufferHeader>(0, buffer);

                IntPtr dataPos;
                byte[] dataBuffer;

                switch (header.ReparseTag)
                {
                case ReparsePointTag.MountPoint:
                    NativeMethods.MountPointReparseBuffer mprb = Utils.MarshalPtrToStructure <NativeMethods.MountPointReparseBuffer>(0, new IntPtr(buffer.ToInt64() + marshalReparseBuffer.ToInt64()));

                    dataPos    = new IntPtr(marshalReparseBuffer.ToInt64() + Marshal.OffsetOf(toMountPointReparseBuffer, "data").ToInt64());
                    dataBuffer = new byte[bytesReturned - dataPos.ToInt64()];

                    Marshal.Copy(new IntPtr(buffer.ToInt64() + dataPos.ToInt64()), dataBuffer, 0, dataBuffer.Length);

                    return(new LinkTargetInfo(
                               Encoding.Unicode.GetString(dataBuffer, mprb.SubstituteNameOffset, mprb.SubstituteNameLength),
                               Encoding.Unicode.GetString(dataBuffer, mprb.PrintNameOffset, mprb.PrintNameLength)));


                case ReparsePointTag.SymLink:
                    NativeMethods.SymbolicLinkReparseBuffer slrb = Utils.MarshalPtrToStructure <NativeMethods.SymbolicLinkReparseBuffer>(0, new IntPtr(buffer.ToInt64() + marshalReparseBuffer.ToInt64()));

                    dataPos    = new IntPtr(marshalReparseBuffer.ToInt64() + Marshal.OffsetOf(toSymbolicLinkReparseBuffer, "data").ToInt64());
                    dataBuffer = new byte[bytesReturned - dataPos.ToInt64()];

                    Marshal.Copy(new IntPtr(buffer.ToInt64() + dataPos.ToInt64()), dataBuffer, 0, dataBuffer.Length);

                    return(new SymbolicLinkTargetInfo(
                               Encoding.Unicode.GetString(dataBuffer, slrb.SubstituteNameOffset, slrb.SubstituteNameLength),
                               Encoding.Unicode.GetString(dataBuffer, slrb.PrintNameOffset, slrb.PrintNameLength), slrb.Flags));


                default:
                    throw new UnrecognizedReparsePointException();
                }
            }
        }
Example #4
0
File: Device.cs Project: CDEApp/CDE
        internal static IEnumerable <DeviceInfo> EnumerateDevicesInternal(SafeHandle safeHandle, string hostName, DeviceGuid deviceInterfaceGuid)
        {
            bool callerHandle = safeHandle != null;
            Guid 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.LocalToUncInternal(Host.GetUncName(hostName), false, false, false, false), out safeMachineHandle);

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

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


                try
                {
                    uint memberInterfaceIndex = 0;
                    NativeMethods.SpDeviceInterfaceData 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.SpDeviceInfoData            deviceInfoData            = CreateDeviceInfoDataInstance();
                        NativeMethods.SpDeviceInterfaceDetailData 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.
                        DeviceInfo 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 (SafeGlobalMemoryBufferHandle 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);
                            }


                            // CA2001:AvoidCallingProblematicMethods

                            IntPtr buffer     = IntPtr.Zero;
                            bool   successRef = false;
                            safeBuffer.DangerousAddRef(ref successRef);

                            // MSDN: The DangerousGetHandle method poses a security risk because it can return a handle that is not valid.
                            if (successRef)
                            {
                                buffer = safeBuffer.DangerousGetHandle();
                            }

                            safeBuffer.DangerousRelease();

                            if (buffer == IntPtr.Zero)
                            {
                                NativeError.ThrowException(Resources.HandleDangerousRef);
                            }

                            // CA2001:AvoidCallingProblematicMethods


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

                        #region Get Registry Properties

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


                            // CA2001:AvoidCallingProblematicMethods

                            IntPtr buffer     = IntPtr.Zero;
                            bool   successRef = false;
                            safeBuffer.DangerousAddRef(ref successRef);

                            // MSDN: The DangerousGetHandle method poses a security risk because it can return a handle that is not valid.
                            if (successRef)
                            {
                                buffer = safeBuffer.DangerousGetHandle();
                            }

                            safeBuffer.DangerousRelease();

                            if (buffer == IntPtr.Zero)
                            {
                                NativeError.ThrowException(Resources.HandleDangerousRef);
                            }

                            // CA2001:AvoidCallingProblematicMethods


                            uint safeBufferCapacity = (uint)safeBuffer.Capacity;


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

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

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

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

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

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

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

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

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

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

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

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

                        #endregion // Get Registry Properties

                        yield return(deviceInfo);

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

         bool callerHandle = safeHandle != null;
         if (!callerHandle)
         {
            if (Utils.IsNullOrWhiteSpace(path))
               throw new ArgumentNullException("path");

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

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


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

            // 2014-10-16: Number of returned items depends on the size of the buffer.
            // That does not seem right, investigate.
            using (var safeBuffer = new SafeGlobalMemoryBufferHandle(NativeMethods.DefaultFileBufferSize))
            {
               NativeMethods.IsValidHandle(safeBuffer, Marshal.GetLastWin32Error());

               long fileNameOffset = Marshal.OffsetOf(typeof(NativeMethods.FileIdBothDirInfo), "FileName").ToInt64();

               while (NativeMethods.GetFileInformationByHandleEx(safeHandle, NativeMethods.FileInfoByHandleClass.FileIdBothDirectoryInfo, safeBuffer.DangerousGetHandle(), NativeMethods.DefaultFileBufferSize))
               {
                  // CA2001:AvoidCallingProblematicMethods

                  IntPtr buffer = IntPtr.Zero;
                  bool successRef = false;
                  safeBuffer.DangerousAddRef(ref successRef);

                  // MSDN: The DangerousGetHandle method poses a security risk because it can return a handle that is not valid.
                  if (successRef)
                     buffer = safeBuffer.DangerousGetHandle();

                  safeBuffer.DangerousRelease();

                  if (buffer == IntPtr.Zero)
                     NativeError.ThrowException(Resources.HandleDangerousRef);

                  // CA2001:AvoidCallingProblematicMethods


                  while (buffer != IntPtr.Zero)
                  {
                     NativeMethods.FileIdBothDirInfo fibdi = Utils.MarshalPtrToStructure<NativeMethods.FileIdBothDirInfo>(0, buffer);

                     string fileName = Marshal.PtrToStringUni(new IntPtr(fileNameOffset + buffer.ToInt64()), (int)(fibdi.FileNameLength / 2));

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


                     buffer = fibdi.NextEntryOffset == 0
                        ? IntPtr.Zero
                        : new IntPtr(buffer.ToInt64() + fibdi.NextEntryOffset);
                  }
               }

               int lastError = Marshal.GetLastWin32Error();
               switch ((uint)lastError)
               {
                  case Win32Errors.ERROR_SUCCESS:
                  case Win32Errors.ERROR_NO_MORE_FILES:
                  case Win32Errors.ERROR_HANDLE_EOF:
                     yield break;

                  default:
                     NativeError.ThrowException(lastError, path);
                     break;
               }
            }
         }
         finally
         {
            // Handle is ours, dispose.
            if (!callerHandle && safeHandle != null)
               safeHandle.Close();
         }
      }