public BackupStreamInfo ReadStreamInfo() { using (SafeGlobalMemoryBufferHandle hBuf = new SafeGlobalMemoryBufferHandle(Marshal.SizeOf(typeof(NativeMethods.WIN32_STREAM_ID)))) { uint numberOfBytesRead; if (!NativeMethods.BackupRead(mFileHandle, hBuf, (uint)Marshal.SizeOf(typeof(NativeMethods.WIN32_STREAM_ID)), out numberOfBytesRead, false, mProcessSecurity, ref mContext)) { NativeError.ThrowException(); } if (numberOfBytesRead == 0) { return(null); } if (numberOfBytesRead < Marshal.SizeOf(typeof(NativeMethods.WIN32_STREAM_ID))) { throw new System.IO.IOException(Resources.IncompleteHeaderRead); } NativeMethods.WIN32_STREAM_ID streamID = (NativeMethods.WIN32_STREAM_ID)Marshal.PtrToStructure(hBuf.DangerousGetHandle(), typeof(NativeMethods.WIN32_STREAM_ID)); uint nameLength = (uint)Math.Min(streamID.dwStreamNameSize, hBuf.Capacity); if (!NativeMethods.BackupRead(mFileHandle, hBuf, nameLength, out numberOfBytesRead, false, mProcessSecurity, ref mContext)) { NativeError.ThrowException(); } string name = Marshal.PtrToStringUni(hBuf.DangerousGetHandle(), (int)nameLength / 2); return(new BackupStreamInfo(streamID, name)); } }
private static NativeMethods.RemoteNameInfo GetMappedInfoInternal(string path) { if (path == null) { throw new ArgumentNullException("path", "The specified path cannot be NULL."); } if (IsLongPath(path)) { throw new ArgumentException("Long paths are not supported but this method."); } if (path.Length > NativeMethods.MAX_PATH) { throw new System.IO.PathTooLongException(); } int bufferSize = 0; SafeGlobalMemoryBufferHandle safeBuffer = new SafeGlobalMemoryBufferHandle(bufferSize); try { uint retVal; // first call is to get correct buffer size to store results. if ((retVal = NativeMethods.WNetGetUniversalName(path, NativeMethods.REMOTE_NAME_INFO_LEVEL, safeBuffer, ref bufferSize)) != Win32Errors.ERROR_MORE_DATA) { NativeError.ThrowException(retVal); } safeBuffer.Dispose(); safeBuffer = null; safeBuffer = new SafeGlobalMemoryBufferHandle(bufferSize); if ((retVal = NativeMethods.WNetGetUniversalName(path, NativeMethods.REMOTE_NAME_INFO_LEVEL, safeBuffer, ref bufferSize)) != Win32Errors.NO_ERROR) { NativeError.ThrowException(retVal); } return((NativeMethods.RemoteNameInfo)Marshal.PtrToStructure(safeBuffer.DangerousGetHandle(), typeof(NativeMethods.RemoteNameInfo))); } finally { if (safeBuffer != null) { safeBuffer.Dispose(); } } }
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(); } } }
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 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(); } } }
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(); } }