зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
960e4c47d4
Коммит
7acf7a06ca
|
@ -21,6 +21,7 @@
|
|||
# include "mozilla/Move.h"
|
||||
# include "mozilla/UniquePtr.h"
|
||||
# include "mozilla/Vector.h"
|
||||
# include "mozilla/WinHeaderOnlyUtils.h"
|
||||
|
||||
# include <wchar.h>
|
||||
# include <windows.h>
|
||||
|
@ -359,39 +360,6 @@ inline UniquePtr<wchar_t[]> MakeCommandLine(int argc, wchar_t** argv,
|
|||
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[]) {
|
||||
if (!aArgv) {
|
||||
return false;
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
#ifndef mozilla_LauncherRegistryInfo_h
|
||||
#define mozilla_LauncherRegistryInfo_h
|
||||
|
||||
#include "mozilla/CmdLineAndEnvUtils.h"
|
||||
#include "mozilla/LauncherResult.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/WinHeaderOnlyUtils.h"
|
||||
#include "nsWindowsHelpers.h"
|
||||
|
||||
#include <string>
|
||||
|
|
|
@ -12,15 +12,23 @@
|
|||
#include <winnt.h>
|
||||
#include <winternl.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.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 +410,128 @@ class MOZ_RAII AutoVirtualProtect final {
|
|||
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
|
||||
|
||||
#endif // mozilla_WinHeaderOnlyUtils_h
|
||||
|
|
Загрузка…
Ссылка в новой задаче