public static void ResolveSymlinkWinApi(ref FileInfo info) { if (!IsSymbolicLink(info)) { return; } // If we follow the symbolic link, we need to resolve it. using Kernel32.SafeHFILE handle = Kernel32 .CreateFile(info.FullName, 0, 0, null, FileMode.Open, FileFlagsAndAttributes.FILE_ATTRIBUTE_NORMAL); if (handle == HFILE.INVALID_HANDLE_VALUE) { Kernel32.GetLastError().ThrowIfFailed(); } var fullPath = new StringBuilder(Kernel32.MAX_PATH + 1); Kernel32.GetFinalPathNameByHandle(handle, fullPath, Kernel32.MAX_PATH, Kernel32.FinalPathNameOptions.FILE_NAME_NORMALIZED); Kernel32.GetLastError().ThrowIfFailed(); string filePath = fullPath.ToString(); info = new FileInfo(filePath.StartsWith(@"\\?\") ? filePath[@"\\?\".Length..]
public static bool EjectDevice(string Path) { if (string.IsNullOrEmpty(Path) || string.IsNullOrEmpty(System.IO.Path.GetPathRoot(Path))) { throw new ArgumentNullException(nameof(Path), "Argument is not legal"); } try { int DeviceNumber = 0; using (Kernel32.SafeHFILE hVolume = Kernel32.CreateFile($@"\\.\{Path.Substring(0, 2)}", 0, FileShare.ReadWrite, null, FileMode.Open, FileFlagsAndAttributes.SECURITY_ANONYMOUS)) { if (hVolume.IsNull || hVolume.IsInvalid) { return(false); } DeviceNumber = GetDeviceNumber(hVolume); } if (DeviceNumber >= 0) { uint DevInst = GetDrivesDevInstByDeviceNumber(DeviceNumber, Kernel32.GetDriveType(Path)); if (DevInst == 0) { return(false); } uint DevInstParent = 0; if (CM_Get_Parent(ref DevInstParent, DevInst, 0) == CR_SUCCESS) { for (int i = 0; i < 5; i++) { if (CM_Request_Device_Eject(DevInstParent, out PNP_VETO_TYPE Result, null, 0, 0) == CR_SUCCESS) { return(true); } else { Debug.WriteLine($"Could not reject the USB device, PNP_VETO reason: {Enum.GetName(typeof(PNP_VETO_TYPE), Result)}"); } Thread.Sleep(300); } } }
public int Read(FileInfo info, string name, ref Span <byte> data) { using Kernel32.SafeHFILE handle = Kernel32.CreateFile($"{info.FullName}:tsuku.{name}", Kernel32.FileAccess.FILE_GENERIC_READ, FileShare.Read, null, FileMode.Open, FileFlagsAndAttributes.FILE_ATTRIBUTE_NORMAL); if (handle == HFILE.INVALID_HANDLE_VALUE) { Kernel32.GetLastError().ThrowIfFailed(); } int maxRead = Math.Min(data.Length, Tsuku.MAX_ATTR_SIZE); // Kernel32.SafeHFILE should close after on dispose. using var stream = new FileStream(new SafeFileHandle(handle.DangerousGetHandle(), false), FileAccess.Read); return(stream.Read(data[..maxRead]));
public void Write(FileInfo info, string name, ReadOnlySpan <byte> data) { using Kernel32.SafeHFILE handle = Kernel32.CreateFile($"{info.FullName}:tsuku.{name}", Kernel32.FileAccess.FILE_GENERIC_WRITE, FileShare.Write, null, FileMode.OpenOrCreate, FileFlagsAndAttributes.FILE_ATTRIBUTE_NORMAL); if (handle == HFILE.INVALID_HANDLE_VALUE) { Kernel32.GetLastError().ThrowIfFailed(); } // Kernel32.SafeHFILE should close after on dispose. using var stream = new FileStream(new SafeFileHandle(handle.DangerousGetHandle(), false), FileAccess.ReadWrite); stream.Write(data); stream.Flush(); }
private static uint GetDrivesDevInstByDeviceNumber(long DeviceNumber, Kernel32.DRIVE_TYPE DriveType) { Guid Type_Guid; switch (DriveType) { case Kernel32.DRIVE_TYPE.DRIVE_REMOVABLE: case Kernel32.DRIVE_TYPE.DRIVE_FIXED: { Type_Guid = new Guid(GUID_DEVINTERFACE_DISK); break; } case Kernel32.DRIVE_TYPE.DRIVE_CDROM: { Type_Guid = new Guid(GUID_DEVINTERFACE_CDROM); break; } default: { throw new ArgumentException("Parameter is invalid", nameof(DriveType)); } } using (SetupAPI.SafeHDEVINFO hDevInfo = SetupAPI.SetupDiGetClassDevs(Type_Guid, Flags: SetupAPI.DIGCF.DIGCF_PRESENT | SetupAPI.DIGCF.DIGCF_DEVICEINTERFACE)) { if (hDevInfo.IsInvalid || hDevInfo.IsNull) { throw new Win32Exception(Marshal.GetLastWin32Error()); } for (uint Index = 0; ; Index++) { SetupAPI.SP_DEVICE_INTERFACE_DATA Interface_Data = new SetupAPI.SP_DEVICE_INTERFACE_DATA { cbSize = Convert.ToUInt32(Marshal.SizeOf(typeof(SetupAPI.SP_DEVICE_INTERFACE_DATA))) }; if (!SetupAPI.SetupDiEnumDeviceInterfaces(hDevInfo, IntPtr.Zero, Type_Guid, Index, ref Interface_Data)) { int Error = Marshal.GetLastWin32Error(); if (Error != Win32Error.ERROR_NO_MORE_ITEMS) { throw new Win32Exception(Error); } break; } SetupAPI.SP_DEVINFO_DATA devData = new SetupAPI.SP_DEVINFO_DATA { cbSize = Convert.ToUInt32(Marshal.SizeOf(typeof(SetupAPI.SP_DEVINFO_DATA))) }; if (!SetupAPI.SetupDiGetDeviceInterfaceDetail(hDevInfo, Interface_Data, IntPtr.Zero, 0, out uint Size, ref devData)) { int Error = Marshal.GetLastWin32Error(); if (Error != Win32Error.ERROR_INSUFFICIENT_BUFFER) { throw new Win32Exception(Error); } } IntPtr Buffer = Marshal.AllocHGlobal(Convert.ToInt32(Size)); try { SetupAPI.SP_DEVICE_INTERFACE_DETAIL_DATA Interface_Detail_Data = new SetupAPI.SP_DEVICE_INTERFACE_DETAIL_DATA { cbSize = Convert.ToUInt32(Marshal.SizeOf(typeof(SetupAPI.SP_DEVICE_INTERFACE_DETAIL_DATA))) }; Marshal.StructureToPtr(Interface_Detail_Data, Buffer, false); if (!SetupAPI.SetupDiGetDeviceInterfaceDetail(hDevInfo, Interface_Data, Buffer, Size, out _, ref devData)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } string DevicePath = Marshal.PtrToStringAuto((IntPtr)(Buffer.ToInt64() + Marshal.SizeOf(typeof(int)))); using (Kernel32.SafeHFILE hDrive = Kernel32.CreateFile(DevicePath, 0, FileShare.ReadWrite, null, FileMode.Open, FileFlagsAndAttributes.SECURITY_ANONYMOUS)) { if (!hDrive.IsInvalid && !hDrive.IsNull && DeviceNumber == GetDeviceNumber(hDrive)) { return(devData.DevInst); } } } finally { Marshal.FreeHGlobal(Buffer); } } } return(0); }