forked from mirrors/gecko-dev
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:
parent
960e4c47d4
commit
7acf7a06ca
3 changed files with 132 additions and 34 deletions
|
|
@ -21,6 +21,7 @@
|
||||||
# include "mozilla/Move.h"
|
# include "mozilla/Move.h"
|
||||||
# include "mozilla/UniquePtr.h"
|
# include "mozilla/UniquePtr.h"
|
||||||
# include "mozilla/Vector.h"
|
# include "mozilla/Vector.h"
|
||||||
|
# include "mozilla/WinHeaderOnlyUtils.h"
|
||||||
|
|
||||||
# include <wchar.h>
|
# include <wchar.h>
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
|
|
@ -359,39 +360,6 @@ inline UniquePtr<wchar_t[]> MakeCommandLine(int argc, wchar_t** argv,
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline UniquePtr<wchar_t[]> GetFullBinaryPath() {
|
|
||||||
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);
|
|
||||||
if (!retLen) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (retLen == bufLen && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
|
||||||
bufLen *= 2;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Upon success, retLen *excludes* the null character
|
|
||||||
++retLen;
|
|
||||||
|
|
||||||
// Since we're likely to have a bunch of unused space in buf, let's reallocate
|
|
||||||
// a string to the actual size of the file name.
|
|
||||||
auto result = mozilla::MakeUnique<wchar_t[]>(retLen);
|
|
||||||
if (wcscpy_s(result.get(), retLen, buf.get())) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool SetArgv0ToFullBinaryPath(wchar_t* aArgv[]) {
|
inline bool SetArgv0ToFullBinaryPath(wchar_t* aArgv[]) {
|
||||||
if (!aArgv) {
|
if (!aArgv) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,10 @@
|
||||||
#ifndef mozilla_LauncherRegistryInfo_h
|
#ifndef mozilla_LauncherRegistryInfo_h
|
||||||
#define mozilla_LauncherRegistryInfo_h
|
#define mozilla_LauncherRegistryInfo_h
|
||||||
|
|
||||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
|
||||||
#include "mozilla/LauncherResult.h"
|
#include "mozilla/LauncherResult.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
|
#include "mozilla/WinHeaderOnlyUtils.h"
|
||||||
#include "nsWindowsHelpers.h"
|
#include "nsWindowsHelpers.h"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
|
||||||
|
|
@ -12,15 +12,23 @@
|
||||||
#include <winnt.h>
|
#include <winnt.h>
|
||||||
#include <winternl.h>
|
#include <winternl.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/DynamicallyLinkedFunctionPtr.h"
|
#include "mozilla/DynamicallyLinkedFunctionPtr.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
#include "mozilla/Result.h"
|
#include "mozilla/Result.h"
|
||||||
|
#include "mozilla/Tuple.h"
|
||||||
#include "mozilla/UniquePtr.h"
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "mozilla/WindowsVersion.h"
|
#include "mozilla/WindowsVersion.h"
|
||||||
#include "nsWindowsHelpers.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
|
* 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
|
* Win32. It may be used outside of xul.dll, in places such as firefox.exe or
|
||||||
|
|
@ -402,6 +410,128 @@ class MOZ_RAII AutoVirtualProtect final {
|
||||||
WindowsError mError;
|
WindowsError mError;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
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(aModule, buf.get(), bufLen);
|
||||||
|
if (!retLen) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (retLen == bufLen && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||||
|
bufLen *= 2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Upon success, retLen *excludes* the null character
|
||||||
|
++retLen;
|
||||||
|
|
||||||
|
// Since we're likely to have a bunch of unused space in buf, let's reallocate
|
||||||
|
// a string to the actual size of the file name.
|
||||||
|
auto result = mozilla::MakeUnique<wchar_t[]>(retLen);
|
||||||
|
if (wcscpy_s(result.get(), retLen, buf.get())) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline UniquePtr<wchar_t[]> GetFullBinaryPath() {
|
||||||
|
return GetFullModulePath(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif // mozilla_WinHeaderOnlyUtils_h
|
#endif // mozilla_WinHeaderOnlyUtils_h
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue