public static MachineType GetMachineType(string path) { // Open the PE File as a binary file, and parse just enough information to determine the // machine type. //http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx using (SafeFileHandle safeHandle = NativeMethods.CreateFile( path, NativeAccessFlags.GenericRead, FileShare.Read, IntPtr.Zero, FileMode.Open, FileAttributes.Normal, IntPtr.Zero)) { FileStream fs = new FileStream(safeHandle, FileAccess.Read); using (BinaryReader br = new BinaryReader(fs)) { fs.Seek(0x3c, SeekOrigin.Begin); Int32 peOffset = br.ReadInt32(); fs.Seek(peOffset, SeekOrigin.Begin); UInt32 peHead = br.ReadUInt32(); if (peHead != 0x00004550) // "PE\0\0", little-endian { throw new Exception("Can't find PE header"); } return((MachineType)br.ReadUInt16()); } } }
private static SafeHeapBlockHandle ReadFileWorker(FullPath path, long fileSize, int trailingByteCount) { using ( var fileHandle = NativeMethods.CreateFile(path.Value, NativeAccessFlags.GenericRead, FileShare.ReadWrite | FileShare.Delete, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero)) { if (fileHandle.IsInvalid) { throw new Win32Exception(); } // Note: We are limited to 2GB files by design. var maxLen = int.MaxValue - trailingByteCount; if (fileSize >= maxLen) { Logger.LogWarn("File too big, truncated to {0} bytes", maxLen); } var len = (int)Math.Min(maxLen, fileSize); var heap = HeapAllocStatic.Alloc(len + trailingByteCount); try { var bytesRead = new int[1]; if (!NativeMethods.ReadFile(fileHandle, heap.Pointer, len, bytesRead, null)) { throw new Win32Exception(); } if (bytesRead[0] != len) { throw new Exception("File read operation didn't read the whole file"); } } catch (Exception) { heap.Dispose(); throw; } return(heap); } }
/// <summary> /// Note: For testability, this function should be called through <see cref="IFileSystem"/>. /// </summary> public static unsafe List <DirectoryEntry> GetDirectoryEntries(string path) { var directoryEntries = new List <DirectoryEntry>(); // Open the file with the special FILE_LIST_DIRECTORY access to enable reading // the contents of the directory file (i.e. the list of directory entries). // Note that the FILE_FLAG_BACKUP_SEMANTICS is also important to ensure this // call succeeds. var fileHandle = NativeMethods.CreateFile(path, NativeAccessFlags.FILE_LIST_DIRECTORY, FileShare.Read | FileShare.Write | FileShare.Delete, IntPtr.Zero, FileMode.Open, NativeMethods.FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero); if (fileHandle.IsInvalid) { var lastWin32Error = Marshal.GetLastWin32Error(); if (lastWin32Error != (int)Win32Errors.ERROR_FILE_NOT_FOUND && lastWin32Error != (int)Win32Errors.ERROR_PATH_NOT_FOUND && lastWin32Error != (int)Win32Errors.ERROR_ACCESS_DENIED) { throw new LastWin32ErrorException(lastWin32Error, string.Format("Error enumerating files at \"{0}\".", path)); } // Skip this directory return(directoryEntries); } using (fileHandle) { // 8KB is large enough to hold about 80 entries of average size (the size depends on the // length of the filename), which is a reasonable compromise in terms of stack usages // vs # of calls to the API. const int bufferSize = 8192; byte * bufferAddress = stackalloc byte[bufferSize]; // Invoke NtQueryDirectoryFile to fill the initial buffer NTSTATUS status = InvokeNtQueryDirectoryFile(fileHandle, bufferAddress, bufferSize); if (!NativeMethods.NT_SUCCESS(status)) { // On the first invokcation, NtQueryDirectoryFile returns STATUS_INVALID_PARAMETER when // asked to enumerate an invalid directory (ie it is a file // instead of a directory). Verify that is the actual cause // of the error. if (status == NTSTATUS.STATUS_INVALID_PARAMETER) { FileAttributes attributes = NativeMethods.GetFileAttributes(path); if ((attributes & FileAttributes.Directory) == 0) { status = NTSTATUS.STATUS_NOT_A_DIRECTORY; } } throw ThrowInvokeNtQueryDirectoryFileError(path, status); } // Process entries from the buffer, and invoke NtQueryDirectoryFile as long as there are // more entries to enumerate. while (true) { ProcessFileInformationBuffer(directoryEntries, bufferAddress, bufferSize); status = InvokeNtQueryDirectoryFile(fileHandle, bufferAddress, bufferSize); if (!NativeMethods.NT_SUCCESS(status)) { if (status == NTSTATUS.STATUS_NO_MORE_FILES) { // Success, enumeration finished break; } else { throw ThrowInvokeNtQueryDirectoryFileError(path, status); } } } } // using fileHandle return(directoryEntries); }