Esempio n. 1
0
        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..]
Esempio n. 2
0
        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();
        }
Esempio n. 5
0
        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);
        }