mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-11-04 02:09:05 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			127 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			127 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | 
						|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
 | 
						|
/* This Source Code Form is subject to the terms of the Mozilla Public
 | 
						|
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 | 
						|
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | 
						|
 | 
						|
#include "FileUtilsWin.h"
 | 
						|
 | 
						|
#include <windows.h>
 | 
						|
#include <psapi.h>
 | 
						|
 | 
						|
#include "base/process_util.h"
 | 
						|
#include "mozilla/ProfilerLabels.h"
 | 
						|
#include "mozilla/ScopeExit.h"
 | 
						|
#include "mozilla/Unused.h"
 | 
						|
#include "nsWindowsHelpers.h"
 | 
						|
 | 
						|
namespace mozilla {
 | 
						|
 | 
						|
bool HandleToFilename(HANDLE aHandle, const LARGE_INTEGER& aOffset,
 | 
						|
                      nsAString& aFilename) {
 | 
						|
  AUTO_PROFILER_LABEL("HandletoFilename", OTHER);
 | 
						|
 | 
						|
  aFilename.Truncate();
 | 
						|
  // This implementation is nice because it uses fully documented APIs that
 | 
						|
  // are available on all Windows versions that we support.
 | 
						|
  nsAutoHandle fileMapping(
 | 
						|
      CreateFileMapping(aHandle, nullptr, PAGE_READONLY, 0, 1, nullptr));
 | 
						|
  if (!fileMapping) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  const auto view = MapViewOfFile(fileMapping, FILE_MAP_READ, aOffset.HighPart,
 | 
						|
                                  aOffset.LowPart, 1);
 | 
						|
  if (!view) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  const auto cleanup =
 | 
						|
      MakeScopeExit([&]() { mozilla::Unused << UnmapViewOfFile(view); });
 | 
						|
 | 
						|
  nsAutoString mappedFilename;
 | 
						|
  DWORD len = 0;
 | 
						|
  SetLastError(ERROR_SUCCESS);
 | 
						|
  do {
 | 
						|
    mappedFilename.SetLength(mappedFilename.Length() + MAX_PATH);
 | 
						|
    len = GetMappedFileNameW(GetCurrentProcess(), view, mappedFilename.get(),
 | 
						|
                             mappedFilename.Length());
 | 
						|
  } while (!len && GetLastError() == ERROR_INSUFFICIENT_BUFFER);
 | 
						|
  if (!len) {
 | 
						|
    return false;
 | 
						|
  }
 | 
						|
  mappedFilename.Truncate(len);
 | 
						|
  return NtPathToDosPath(mappedFilename, aFilename);
 | 
						|
}
 | 
						|
 | 
						|
template <class T>
 | 
						|
struct RVAMap {
 | 
						|
  RVAMap(HANDLE map, DWORD offset) {
 | 
						|
    SYSTEM_INFO info;
 | 
						|
    GetSystemInfo(&info);
 | 
						|
 | 
						|
    DWORD alignedOffset =
 | 
						|
        (offset / info.dwAllocationGranularity) * info.dwAllocationGranularity;
 | 
						|
 | 
						|
    MOZ_ASSERT(offset - alignedOffset < info.dwAllocationGranularity, "Wtf");
 | 
						|
 | 
						|
    mRealView = ::MapViewOfFile(map, FILE_MAP_READ, 0, alignedOffset,
 | 
						|
                                sizeof(T) + (offset - alignedOffset));
 | 
						|
 | 
						|
    mMappedView =
 | 
						|
        mRealView
 | 
						|
            ? reinterpret_cast<T*>((char*)mRealView + (offset - alignedOffset))
 | 
						|
            : nullptr;
 | 
						|
  }
 | 
						|
  ~RVAMap() {
 | 
						|
    if (mRealView) {
 | 
						|
      ::UnmapViewOfFile(mRealView);
 | 
						|
    }
 | 
						|
  }
 | 
						|
  operator const T*() const { return mMappedView; }
 | 
						|
  const T* operator->() const { return mMappedView; }
 | 
						|
 | 
						|
 private:
 | 
						|
  const T* mMappedView;
 | 
						|
  void* mRealView;
 | 
						|
};
 | 
						|
 | 
						|
uint32_t GetExecutableArchitecture(const wchar_t* aPath) {
 | 
						|
  nsAutoHandle file(::CreateFileW(aPath, GENERIC_READ, FILE_SHARE_READ, nullptr,
 | 
						|
                                  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
 | 
						|
                                  nullptr));
 | 
						|
  if (!file) {
 | 
						|
    return base::PROCESS_ARCH_INVALID;
 | 
						|
  }
 | 
						|
 | 
						|
  nsAutoHandle map(
 | 
						|
      ::CreateFileMappingW(file, nullptr, PAGE_READONLY, 0, 0, nullptr));
 | 
						|
  if (!map) {
 | 
						|
    return base::PROCESS_ARCH_INVALID;
 | 
						|
  }
 | 
						|
 | 
						|
  RVAMap<IMAGE_DOS_HEADER> peHeader(map, 0);
 | 
						|
  if (!peHeader) {
 | 
						|
    return base::PROCESS_ARCH_INVALID;
 | 
						|
  }
 | 
						|
 | 
						|
  RVAMap<IMAGE_NT_HEADERS> ntHeader(map, peHeader->e_lfanew);
 | 
						|
  if (!ntHeader) {
 | 
						|
    return base::PROCESS_ARCH_INVALID;
 | 
						|
  }
 | 
						|
 | 
						|
  switch (ntHeader->FileHeader.Machine) {
 | 
						|
    case IMAGE_FILE_MACHINE_I386:
 | 
						|
      return base::PROCESS_ARCH_I386;
 | 
						|
    case IMAGE_FILE_MACHINE_AMD64:
 | 
						|
      return base::PROCESS_ARCH_X86_64;
 | 
						|
    case IMAGE_FILE_MACHINE_ARM64:
 | 
						|
      return base::PROCESS_ARCH_ARM_64;
 | 
						|
    case IMAGE_FILE_MACHINE_ARM:
 | 
						|
    case IMAGE_FILE_MACHINE_ARMNT:
 | 
						|
    case IMAGE_FILE_MACHINE_THUMB:
 | 
						|
      return base::PROCESS_ARCH_ARM;
 | 
						|
    default:
 | 
						|
      return base::PROCESS_ARCH_INVALID;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
}  // namespace mozilla
 |