// Copyright (c) 2010-2014 SharpDX - Alexandre Mutel
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace SharpDX.IO
{
///
/// Windows File Helper.
///
public static class NativeFile
{
#if WINDOWS_UWP
private const string KERNEL_FILE = "api-ms-win-core-file-l1-2-0.dll";
#else
private const string KERNEL_FILE = "kernel32.dll";
#endif
///
/// Checks if the specified file path exists.
///
/// The file path.
/// true if the specified file path exists, false otherwise
public static bool Exists(string filePath)
{
try
{
WIN32_FILE_ATTRIBUTE_DATA data;
if (GetFileAttributesEx(filePath, 0, out data))
{
return true;
}
} catch {}
return false;
}
///
/// Opens a binary file, reads the contents of the file into a byte array, and then closes the file.
///
/// The file to open for reading.
/// A byte array containing the contents of the file.
public static byte[] ReadAllBytes(string path)
{
byte[] buffer;
using (var stream = new NativeFileStream(path, NativeFileMode.Open, NativeFileAccess.Read))
{
int offset = 0;
long length = stream.Length;
if (length > 0x7fffffffL)
{
throw new IOException("File too long");
}
int count = (int)length;
buffer = new byte[count];
while (count > 0)
{
int num4 = stream.Read(buffer, offset, count);
if (num4 == 0)
{
throw new EndOfStreamException();
}
offset += num4;
count -= num4;
}
}
return buffer;
}
///
/// Opens a text file, reads all lines of the file, and then closes the file.
///
/// The file to open for reading.
/// A string containing all lines of the file.
public static string ReadAllText(string path)
{
return ReadAllText(path, Encoding.UTF8);
}
///
/// Opens a text file, reads all lines of the file, and then closes the file.
///
/// The file to open for reading.
/// The encoding.
/// The sharing.
/// A string containing all lines of the file.
public static string ReadAllText(string path, Encoding encoding, NativeFileShare sharing = NativeFileShare.Read)
{
using (var stream = new NativeFileStream(path, NativeFileMode.Open, NativeFileAccess.Read, sharing))
{
using (StreamReader reader = new StreamReader(stream, encoding, true, 0x400))
{
return reader.ReadToEnd();
}
}
}
#if WINDOWS_UWP
internal struct CREATEFILE2_EXTENDED_PARAMETERS
{
public uint dwSize;
public uint dwFileAttributes;
public uint dwFileFlags;
public uint dwSecurityQosFlags;
public IntPtr lpSecurityAttributes;
public IntPtr hTemplateFile;
};
private enum FILE_INFO_BY_HANDLE_CLASS : int
{
FileBasicInfo = 0,
FileStandardInfo = 1,
FileNameInfo = 2,
FileRenameInfo = 3,
FileDispositionInfo = 4,
FileAllocationInfo = 5,
FileEndOfFileInfo = 6,
FileStreamInfo = 7,
FileCompressionInfo = 8,
FileAttributeTagInfo = 9,
FileIdBothDirectoryInfo = 10, // 0xA
FileIdBothDirectoryRestartInfo = 11, // 0xB
FileIoPriorityHintInfo = 12, // 0xC
FileRemoteProtocolInfo = 13, // 0xD
FileFullDirectoryInfo = 14, // 0xE
FileFullDirectoryRestartInfo = 15, // 0xF
FileStorageInfo = 16, // 0x10
FileAlignmentInfo = 17, // 0x11
MaximumFileInfoByHandlesClass
};
[StructLayout(LayoutKind.Sequential)]
private struct FILE_STANDARD_INFO
{
public long AllocationSize;
public long EndOfFile;
public int NumberOfLinks;
public int DeletePending;
public int Directory;
};
///
/// Gets the size of the file.
///
/// The handle.
/// Size of the file.
///
/// GetFileSizeEx
internal static bool GetFileSizeEx(IntPtr handle, out long fileSize)
{
FILE_STANDARD_INFO info;
unsafe
{
var result = GetFileInformationByHandleEx(handle, FILE_INFO_BY_HANDLE_CLASS.FileStandardInfo, new IntPtr(&info), Utilities.SizeOf());
fileSize = info.EndOfFile;
return result;
}
}
#endif
[StructLayout(LayoutKind.Sequential)]
internal struct FILETIME
{
public uint DateTimeLow;
public uint DateTimeHigh;
public DateTime ToDateTime()
{
return DateTime.FromFileTimeUtc((((long)DateTimeHigh) << 32) | ((uint)DateTimeLow));
}
}
[StructLayout(LayoutKind.Sequential)]
internal struct WIN32_FILE_ATTRIBUTE_DATA
{
public uint FileAttributes;
public FILETIME CreationTime;
public FILETIME LastAccessTime;
public FILETIME LastWriteTime;
public uint FileSizeHigh;
public uint FileSizeLow;
}
///
/// Gets the last write time access for the specified path.
///
/// The path.
/// The last write time access
public static DateTime GetLastWriteTime(string path)
{
WIN32_FILE_ATTRIBUTE_DATA data;
if (GetFileAttributesEx(path, 0, out data))
{
return data.LastWriteTime.ToDateTime().ToLocalTime();
}
return new DateTime(0);
}
///
/// Reads to a file.
///
/// The file handle.
/// The buffer.
/// The number of bytes to read.
/// The number of bytes read.
/// The overlapped.
/// A Result
/// ReadFile
[DllImport(KERNEL_FILE, EntryPoint = "ReadFile", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool ReadFile(IntPtr fileHandle, IntPtr buffer, int numberOfBytesToRead, out int numberOfBytesRead, IntPtr overlapped);
[DllImport(KERNEL_FILE, EntryPoint = "FlushFileBuffers", SetLastError = true)]
internal static extern bool FlushFileBuffers(IntPtr hFile);
///
/// Writes to a file.
///
/// The file handle.
/// The buffer.
/// The number of bytes to read.
/// The number of bytes read.
/// The overlapped.
/// A Result
/// WriteFile
[DllImport(KERNEL_FILE, EntryPoint = "WriteFile", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool WriteFile(IntPtr fileHandle, IntPtr buffer, int numberOfBytesToRead, out int numberOfBytesRead, IntPtr overlapped);
///
/// Sets the file pointer.
///
/// The handle.
/// The distance to move.
/// The distance to move high.
/// The seek origin.
///
/// SetFilePointerEx
[DllImport(KERNEL_FILE, EntryPoint = "SetFilePointerEx", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool SetFilePointerEx(IntPtr handle, long distanceToMove, out long distanceToMoveHigh, SeekOrigin seekOrigin);
///
/// Sets the end of file.
///
/// The handle.
///
/// SetEndOfFile
[DllImport(KERNEL_FILE, EntryPoint = "SetEndOfFile", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool SetEndOfFile(IntPtr handle);
[DllImport(KERNEL_FILE, EntryPoint = "GetFileAttributesExW", CharSet = CharSet.Unicode, SetLastError = true)]
internal static extern bool GetFileAttributesEx(string name, int fileInfoLevel, out WIN32_FILE_ATTRIBUTE_DATA lpFileInformation);
#if WINDOWS_UWP
///
/// Creates the file.
///
/// Name of the file.
/// The desired access.
/// The share mode.
/// The creation disposition.
/// The extended parameters.
/// A handle to the created file. IntPtr.Zero if failed.
/// CreateFile2
[DllImport(KERNEL_FILE, EntryPoint = "CreateFile2", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr Create(
string fileName,
NativeFileAccess desiredAccess,
NativeFileShare shareMode,
NativeFileMode mode,
IntPtr extendedParameters);
[DllImport("api-ms-win-core-file-l2-1-0.dll", EntryPoint = "GetFileInformationByHandleEx", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool GetFileInformationByHandleEx(IntPtr handle, FILE_INFO_BY_HANDLE_CLASS FileInformationClass, IntPtr lpFileInformation, int dwBufferSize);
#else
///
/// Creates the file.
///
/// Name of the file.
/// The desired access.
/// The share mode.
/// The security attributes.
/// The creation disposition.
/// The flags and attributes.
/// The template file.
/// A handle to the created file. IntPtr.Zero if failed.
/// CreateFile
[DllImport("kernel32.dll", EntryPoint = "CreateFile", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern IntPtr Create(
string fileName,
NativeFileAccess desiredAccess,
NativeFileShare shareMode,
IntPtr securityAttributes,
NativeFileMode mode,
NativeFileOptions flagsAndOptions,
IntPtr templateFile);
///
/// Gets the size of the file.
///
/// The handle.
/// Size of the file.
///
/// GetFileSizeEx
[DllImport("kernel32.dll", EntryPoint = "GetFileSizeEx", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool GetFileSizeEx(IntPtr handle, out long fileSize);
#endif
}
}