Bug 1563336: Add a common implementation of module version info extraction to WinHeaderOnlyUtils; r=mhowell

Differential Revision: https://phabricator.services.mozilla.com/D36817

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Aaron Klotz 2019-07-03 21:06:00 +00:00
Родитель eb50d28bc0
Коммит 286af53a60
2 изменённых файлов: 98 добавлений и 2 удалений

Просмотреть файл

@ -359,14 +359,14 @@ inline UniquePtr<wchar_t[]> MakeCommandLine(int argc, wchar_t** argv,
return s;
}
inline UniquePtr<wchar_t[]> GetFullBinaryPath() {
inline UniquePtr<wchar_t[]> GetFullModulePath(HMODULE aModule) {
DWORD bufLen = MAX_PATH;
mozilla::UniquePtr<wchar_t[]> buf;
DWORD retLen;
while (true) {
buf = mozilla::MakeUnique<wchar_t[]>(bufLen);
retLen = ::GetModuleFileNameW(nullptr, buf.get(), bufLen);
retLen = ::GetModuleFileNameW(aModule, buf.get(), bufLen);
if (!retLen) {
return nullptr;
}
@ -392,6 +392,10 @@ inline UniquePtr<wchar_t[]> GetFullBinaryPath() {
return result;
}
inline UniquePtr<wchar_t[]> GetFullBinaryPath() {
return GetFullModulePath(nullptr);
}
inline bool SetArgv0ToFullBinaryPath(wchar_t* aArgv[]) {
if (!aArgv) {
return false;

Просмотреть файл

@ -14,13 +14,20 @@
#include "mozilla/Assertions.h"
#include "mozilla/Attributes.h"
#include "mozilla/CmdLineAndEnvUtils.h"
#include "mozilla/DynamicallyLinkedFunctionPtr.h"
#include "mozilla/Maybe.h"
#include "mozilla/Result.h"
#include "mozilla/Tuple.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WindowsVersion.h"
#include "nsWindowsHelpers.h"
#if defined(MOZILLA_INTERNAL_API)
# include "nsIFile.h"
# include "nsString.h"
#endif // defined(MOZILLA_INTERNAL_API)
/**
* This header is intended for self-contained, header-only, utility code for
* Win32. It may be used outside of xul.dll, in places such as firefox.exe or
@ -402,6 +409,91 @@ class MOZ_RAII AutoVirtualProtect final {
WindowsError mError;
};
class ModuleVersion final {
public:
explicit ModuleVersion(const VS_FIXEDFILEINFO& aFixedInfo)
: mVersion((static_cast<uint64_t>(aFixedInfo.dwFileVersionMS) << 32) |
static_cast<uint64_t>(aFixedInfo.dwFileVersionLS)) {}
explicit ModuleVersion(const uint64_t aVersion) : mVersion(aVersion) {}
ModuleVersion(const ModuleVersion& aOther) : mVersion(aOther.mVersion) {}
uint64_t AsInteger() const { return mVersion; }
operator uint64_t() const { return AsInteger(); }
Tuple<uint16_t, uint16_t, uint16_t, uint16_t> AsTuple() const {
uint16_t major = static_cast<uint16_t>((mVersion >> 48) & 0xFFFFU);
uint16_t minor = static_cast<uint16_t>((mVersion >> 32) & 0xFFFFU);
uint16_t patch = static_cast<uint16_t>((mVersion >> 16) & 0xFFFFU);
uint16_t build = static_cast<uint16_t>(mVersion & 0xFFFFU);
return MakeTuple(major, minor, patch, build);
}
explicit operator bool() const { return !!mVersion; }
bool operator<(const ModuleVersion& aOther) const {
return mVersion < aOther.mVersion;
}
bool operator<(const uint64_t& aOther) const { return mVersion < aOther; }
private:
const uint64_t mVersion;
};
inline WindowsErrorResult<ModuleVersion> GetModuleVersion(
const wchar_t* aModuleFullPath) {
DWORD verInfoLen = ::GetFileVersionInfoSizeW(aModuleFullPath, nullptr);
if (!verInfoLen) {
return Err(WindowsError::FromLastError());
}
auto verInfoBuf = MakeUnique<BYTE[]>(verInfoLen);
if (!::GetFileVersionInfoW(aModuleFullPath, 0, verInfoLen,
verInfoBuf.get())) {
return Err(WindowsError::FromLastError());
}
UINT fixedInfoLen;
VS_FIXEDFILEINFO* fixedInfo = nullptr;
if (!::VerQueryValueW(verInfoBuf.get(), L"\\",
reinterpret_cast<LPVOID*>(&fixedInfo), &fixedInfoLen)) {
// VerQueryValue may fail if the resource does not exist. This is not an
// error; we'll return 0 in this case.
return ModuleVersion(0ULL);
}
return ModuleVersion(*fixedInfo);
}
inline WindowsErrorResult<ModuleVersion> GetModuleVersion(HMODULE aModule) {
UniquePtr<wchar_t[]> fullPath(GetFullModulePath(aModule));
if (!fullPath) {
return Err(WindowsError::CreateGeneric());
}
return GetModuleVersion(fullPath.get());
}
#if defined(MOZILLA_INTERNAL_API)
inline WindowsErrorResult<ModuleVersion> GetModuleVersion(nsIFile* aFile) {
if (!aFile) {
return Err(WindowsError::FromHResult(E_INVALIDARG));
}
nsAutoString fullPath;
nsresult rv = aFile->GetPath(fullPath);
if (NS_FAILED(rv)) {
return Err(WindowsError::CreateGeneric());
}
return GetModuleVersion(fullPath.get());
}
#endif // defined(MOZILLA_INTERNAL_API)
} // namespace mozilla
#endif // mozilla_WinHeaderOnlyUtils_h