зеркало из https://github.com/mozilla/gecko-dev.git
128 строки
3.7 KiB
C++
128 строки
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
|