Example #1
0
 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());
         }
     }
 }
Example #2
0
        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);
            }
        }
Example #3
0
        /// <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);
        }