# Global Metrics

path: .metrics.nom.total
old: 7.0
new: 70.0
path: .metrics.nom.functions
old: 7.0
new: 70.0
path: .metrics.mi.mi_sei
old: -43.631138310451846
new: -63.905615257317294
path: .metrics.mi.mi_original
old: -7.687803775049673
new: -16.6284829577058
path: .metrics.halstead.level
old: 0.007418832119638429
new: 0.0184981684981685
path: .metrics.halstead.estimated_program_length
old: 3429.5188677682713
new: 2703.812403527932
path: .metrics.halstead.purity_ratio
old: 0.5078511576733705
new: 1.2245527189890997
path: .metrics.halstead.n2
old: 380.0
new: 303.0
path: .metrics.halstead.n1
old: 34.0
new: 39.0
path: .metrics.halstead.effort
old: 7913255.951511428
new: 1004781.5466005903
path: .metrics.halstead.time
old: 439625.33063952375
new: 55821.19703336613
path: .metrics.halstead.bugs
old: 13.236776033564936
new: 3.343950542543645
path: .metrics.halstead.vocabulary
old: 414.0
new: 342.0
path: .metrics.halstead.volume
old: 58707.11742399294
new: 18586.618352868063
path: .metrics.halstead.N1
old: 3740.0
new: 1368.0
path: .metrics.halstead.difficulty
old: 134.7921052631579
new: 54.05940594059406
path: .metrics.halstead.length
old: 6753.0
new: 2208.0
path: .metrics.halstead.N2
old: 3013.0
new: 840.0
path: .metrics.nargs.sum
old: 10.0
new: 49.0
path: .metrics.nargs.average
old: 1.4285714285714286
new: 0.7
path: .metrics.nexits.sum
old: 9.0
new: 73.0
path: .metrics.nexits.average
old: 1.2857142857142858
new: 1.042857142857143
path: .metrics.loc.lloc
old: 170.0
new: 144.0
path: .metrics.loc.cloc
old: 235.0
new: 69.0
path: .metrics.loc.ploc
old: 577.0
new: 521.0
path: .metrics.loc.sloc
old: 798.0
new: 742.0
path: .metrics.loc.blank
old: 0.0
new: 152.0
path: .metrics.cognitive.sum
old: 72.0
new: 47.0
path: .metrics.cognitive.average
old: 10.285714285714286
new: 0.6714285714285714
path: .metrics.cyclomatic.sum
old: 58.0
new: 128.0
path: .metrics.cyclomatic.average
old: 5.2727272727272725
new: 1.5609756097560976

# Spaces Data

## Minimal test - lines (71, 740)

path: .spaces[1].metrics.cyclomatic.average
old: 12.0
new: 1.575
path: .spaces[1].metrics.cyclomatic.sum
old: 12.0
new: 126.0
path: .spaces[1].metrics.halstead.difficulty
old: 19.86111111111111
new: 55.74381625441696
path: .spaces[1].metrics.halstead.effort
old: 11512.3136762615
new: 1004490.9266174488
path: .spaces[1].metrics.halstead.N1
old: 62.0
new: 1354.0
path: .spaces[1].metrics.halstead.purity_ratio
old: 1.0526868919811607
new: 1.1609195419588767
path: .spaces[1].metrics.halstead.vocabulary
old: 31.0
new: 322.0
path: .spaces[1].metrics.halstead.N2
old: 55.0
new: 809.0
path: .spaces[1].metrics.halstead.bugs
old: 0.16994973360299917
new: 3.34330571534562
path: .spaces[1].metrics.halstead.estimated_program_length
old: 123.1643663617958
new: 2511.0689692570504
path: .spaces[1].metrics.halstead.n2
old: 18.0
new: 283.0
path: .spaces[1].metrics.halstead.volume
old: 579.6409683152643
new: 18019.77320736192
path: .spaces[1].metrics.halstead.time
old: 639.5729820145277
new: 55805.05147874715
path: .spaces[1].metrics.halstead.length
old: 117.0
new: 2163.0
path: .spaces[1].metrics.halstead.level
old: 0.05034965034965035
new: 0.01793920953377072
path: .spaces[1].metrics.halstead.n1
old: 13.0
new: 39.0
path: .spaces[1].metrics.mi.mi_visual_studio
old: 51.14360368453085
new: 0.0
path: .spaces[1].metrics.mi.mi_sei
old: 51.69269234999679
new: -63.239551480398944
path: .spaces[1].metrics.mi.mi_original
old: 87.45556230054775
new: -14.353868657113082
path: .spaces[1].metrics.cognitive.average
old: 3.0
new: 0.6714285714285714
path: .spaces[1].metrics.cognitive.sum
old: 3.0
new: 47.0
path: .spaces[1].metrics.nom.functions
old: 1.0
new: 70.0
path: .spaces[1].metrics.nom.total
old: 1.0
new: 70.0
path: .spaces[1].metrics.loc.sloc
old: 19.0
new: 670.0
path: .spaces[1].metrics.loc.blank
old: 0.0
new: 138.0
path: .spaces[1].metrics.loc.cloc
old: 0.0
new: 49.0
path: .spaces[1].metrics.loc.ploc
old: 19.0
new: 483.0
path: .spaces[1].metrics.loc.lloc
old: 3.0
new: 144.0
path: .spaces[1].metrics.nexits.sum
old: 2.0
new: 73.0
path: .spaces[1].metrics.nexits.average
old: 2.0
new: 1.042857142857143
path: .spaces[1].metrics.nargs.average
old: 2.0
new: 0.7
path: .spaces[1].metrics.nargs.sum
old: 2.0
new: 49.0

### Code

    namespace mozilla {

    class WindowsError final {
     private:
      // HRESULT and NTSTATUS are both typedefs of LONG, so we cannot use
      // overloading to properly differentiate between the two. Instead we'll use
      // static functions to convert the various error types to HRESULTs before
      // instantiating.
      explicit constexpr WindowsError(HRESULT aHResult) : mHResult(aHResult) {}

     public:
      using UniqueString = UniquePtr;

      static constexpr WindowsError FromNtStatus(NTSTATUS aNtStatus) {
        if (aNtStatus == STATUS_SUCCESS) {
          // Special case: we don't want to set FACILITY_NT_BIT
          // (HRESULT_FROM_NT does not handle this case, unlike HRESULT_FROM_WIN32)
          return WindowsError(S_OK);
        }

        return WindowsError(HRESULT_FROM_NT(aNtStatus));
      }

      static constexpr WindowsError FromHResult(HRESULT aHResult) {
        return WindowsError(aHResult);
      }

      static constexpr WindowsError FromWin32Error(DWORD aWin32Err) {
        return WindowsError(HRESULT_FROM_WIN32(aWin32Err));
      }

      static WindowsError FromLastError() {
        return FromWin32Error(::GetLastError());
      }

      static WindowsError CreateSuccess() { return WindowsError(S_OK); }

      static WindowsError CreateGeneric() {
        return FromWin32Error(ERROR_UNIDENTIFIED_ERROR);
      }

      bool IsSuccess() const { return SUCCEEDED(mHResult); }

      bool IsFailure() const { return FAILED(mHResult); }

      bool IsAvailableAsWin32Error() const {
        return IsAvailableAsNtStatus() ||
               HRESULT_FACILITY(mHResult) == FACILITY_WIN32;
      }

      bool IsAvailableAsNtStatus() const {
        return mHResult == S_OK || (mHResult & FACILITY_NT_BIT);
      }

      bool IsAvailableAsHResult() const { return true; }

      UniqueString AsString() const {
        LPWSTR rawMsgBuf = nullptr;
        constexpr DWORD flags = FORMAT_MESSAGE_ALLOCATE_BUFFER |
                                FORMAT_MESSAGE_FROM_SYSTEM |
                                FORMAT_MESSAGE_IGNORE_INSERTS;
        DWORD result =
            ::FormatMessageW(flags, nullptr, mHResult, 0,
                             reinterpret_cast(&rawMsgBuf), 0, nullptr);
        if (!result) {
          return nullptr;
        }

        return UniqueString(rawMsgBuf);
      }

      HRESULT AsHResult() const { return mHResult; }

      // Not all HRESULTs are convertible to Win32 Errors, so we use Maybe
      Maybe AsWin32Error() const {
        if (mHResult == S_OK) {
          return Some(static_cast(ERROR_SUCCESS));
        }

        if (HRESULT_FACILITY(mHResult) == FACILITY_WIN32) {
          // This is the inverse of HRESULT_FROM_WIN32
          return Some(static_cast(HRESULT_CODE(mHResult)));
        }

        // The NTSTATUS facility is a special case and thus does not utilize the
        // HRESULT_FACILITY and HRESULT_CODE macros.
        if (mHResult & FACILITY_NT_BIT) {
          return Some(NtStatusToWin32Error(
              static_cast(mHResult & ~FACILITY_NT_BIT)));
        }

        return Nothing();
      }

      // Not all HRESULTs are convertible to NTSTATUS, so we use Maybe
      Maybe AsNtStatus() const {
        if (mHResult == S_OK) {
          return Some(STATUS_SUCCESS);
        }

        // The NTSTATUS facility is a special case and thus does not utilize the
        // HRESULT_FACILITY and HRESULT_CODE macros.
        if (mHResult & FACILITY_NT_BIT) {
          return Some(static_cast(mHResult & ~FACILITY_NT_BIT));
        }

        return Nothing();
      }

      constexpr bool operator==(const WindowsError& aOther) const {
        return mHResult == aOther.mHResult;
      }

      constexpr bool operator!=(const WindowsError& aOther) const {
        return mHResult != aOther.mHResult;
      }

      static DWORD NtStatusToWin32Error(NTSTATUS aNtStatus) {
        static const StaticDynamicallyLinkedFunctionPtr
            pRtlNtStatusToDosError(L"ntdll.dll", "RtlNtStatusToDosError");

        MOZ_ASSERT(!!pRtlNtStatusToDosError);
        if (!pRtlNtStatusToDosError) {
          return ERROR_UNIDENTIFIED_ERROR;
        }

        return pRtlNtStatusToDosError(aNtStatus);
      }

     private:
      // We store the error code as an HRESULT because they can encode both Win32
      // error codes and NTSTATUS codes.
      HRESULT mHResult;
    };

    namespace detail {
    template <>
    struct UnusedZero {
      using StorageType = WindowsError;

      static constexpr bool value = true;
      static constexpr StorageType nullValue = WindowsError::FromHResult(S_OK);

      static constexpr void AssertValid(StorageType aValue) {}
      static constexpr const WindowsError& Inspect(const StorageType& aValue) {
        return aValue;
      }
      static constexpr WindowsError Unwrap(StorageType aValue) { return aValue; }
      static constexpr StorageType Store(WindowsError aValue) { return aValue; }
    };
    }  // namespace detail

    enum DetourResultCode : uint32_t {
      RESULT_OK = 0,
      INTERCEPTOR_MOD_NULL,
      INTERCEPTOR_MOD_INACCESSIBLE,
      INTERCEPTOR_PROC_NULL,
      INTERCEPTOR_PROC_INACCESSIBLE,
      DETOUR_PATCHER_RESERVE_FOR_MODULE_PE_ERROR,
      DETOUR_PATCHER_RESERVE_FOR_MODULE_TEXT_ERROR,
      DETOUR_PATCHER_RESERVE_FOR_MODULE_RESERVE_ERROR,
      DETOUR_PATCHER_DO_RESERVE_ERROR,
      DETOUR_PATCHER_NEXT_TRAMPOLINE_ERROR,
      DETOUR_PATCHER_INVALID_TRAMPOLINE,
      DETOUR_PATCHER_WRITE_POINTER_ERROR,
      DETOUR_PATCHER_CREATE_TRAMPOLINE_ERROR,
      FUNCHOOKCROSSPROCESS_COPYSTUB_ERROR,
      MMPOLICY_RESERVE_INVALIDARG,
      MMPOLICY_RESERVE_ZERO_RESERVATIONSIZE,
      MMPOLICY_RESERVE_CREATEFILEMAPPING,
      MMPOLICY_RESERVE_MAPVIEWOFFILE,
      MMPOLICY_RESERVE_NOBOUND_RESERVE_ERROR,
      MMPOLICY_RESERVE_FINDREGION_INVALIDLEN,
      MMPOLICY_RESERVE_FINDREGION_INVALIDRANGE,
      MMPOLICY_RESERVE_FINDREGION_VIRTUALQUERY_ERROR,
      MMPOLICY_RESERVE_FINDREGION_NO_FREE_REGION,
      MMPOLICY_RESERVE_FINAL_RESERVE_ERROR,
    };

    #if defined(NIGHTLY_BUILD)
    struct DetourError {
      // We have a 16-bytes buffer, but only minimum bytes to detour per
      // architecture are copied.  See CreateTrampoline in PatcherDetour.h.
      DetourResultCode mErrorCode;
      uint8_t mOrigBytes[16];
      explicit DetourError(DetourResultCode aError)
          : mErrorCode(aError), mOrigBytes{} {}
      DetourError(DetourResultCode aError, DWORD aWin32Error)
          : mErrorCode(aError), mOrigBytes{} {
        static_assert(sizeof(mOrigBytes) >= sizeof(aWin32Error),
                      "Can't fit a DWORD in mOrigBytes");
        *reinterpret_cast(mOrigBytes) = aWin32Error;
      }
      operator WindowsError() const {
        return WindowsError::FromHResult(mErrorCode);
      }
    };
    #endif  // defined(NIGHTLY_BUILD)

    template
    using WindowsErrorResult = Result;

    struct LauncherError {
      LauncherError(const char* aFile, int aLine, WindowsError aWin32Error)
          : mFile(aFile), mLine(aLine), mError(aWin32Error) {}

    #if defined(NIGHTLY_BUILD)
      LauncherError(const char* aFile, int aLine,
                    const Maybe& aDetourError)
          : mFile(aFile),
            mLine(aLine),
            mError(aDetourError.isSome() ? aDetourError.value()
                                         : WindowsError::CreateGeneric()),
            mDetourError(aDetourError) {}
    #endif  // defined(NIGHTLY_BUILD)

      const char* mFile;
      int mLine;
      WindowsError mError;
    #if defined(NIGHTLY_BUILD)
      Maybe mDetourError;
    #endif  // defined(NIGHTLY_BUILD)

      bool operator==(const LauncherError& aOther) const {
        return mError == aOther.mError;
      }

      bool operator!=(const LauncherError& aOther) const {
        return mError != aOther.mError;
      }

      bool operator==(const WindowsError& aOther) const { return mError == aOther; }

      bool operator!=(const WindowsError& aOther) const { return mError != aOther; }
    };

    #if defined(MOZ_USE_LAUNCHER_ERROR)

    template
    using LauncherResult = Result;

    template
    using LauncherResultWithLineInfo = LauncherResult;

    using WindowsErrorType = LauncherError;

    #else

    template
    using LauncherResult = WindowsErrorResult;

    template
    using LauncherResultWithLineInfo = Result;

    using WindowsErrorType = WindowsError;

    #endif  // defined(MOZ_USE_LAUNCHER_ERROR)

    using LauncherVoidResult = LauncherResult;

    using LauncherVoidResultWithLineInfo = LauncherResultWithLineInfo;

    #if defined(MOZ_USE_LAUNCHER_ERROR)

    #  define LAUNCHER_ERROR_GENERIC()           \
        ::mozilla::Err(::mozilla::LauncherError( \
            __FILE__, __LINE__, ::mozilla::WindowsError::CreateGeneric()))

    #  if defined(NIGHTLY_BUILD)
    #    define LAUNCHER_ERROR_FROM_DETOUR_ERROR(err) \
          ::mozilla::Err(::mozilla::LauncherError(__FILE__, __LINE__, err))
    #  else
    #    define LAUNCHER_ERROR_FROM_DETOUR_ERROR(err) LAUNCHER_ERROR_GENERIC()
    #  endif  // defined(NIGHTLY_BUILD)

    #  define LAUNCHER_ERROR_FROM_WIN32(err)     \
        ::mozilla::Err(::mozilla::LauncherError( \
            __FILE__, __LINE__, ::mozilla::WindowsError::FromWin32Error(err)))

    #  define LAUNCHER_ERROR_FROM_LAST()         \
        ::mozilla::Err(::mozilla::LauncherError( \
            __FILE__, __LINE__, ::mozilla::WindowsError::FromLastError()))

    #  define LAUNCHER_ERROR_FROM_NTSTATUS(ntstatus) \
        ::mozilla::Err(::mozilla::LauncherError(     \
            __FILE__, __LINE__, ::mozilla::WindowsError::FromNtStatus(ntstatus)))

    #  define LAUNCHER_ERROR_FROM_HRESULT(hresult) \
        ::mozilla::Err(::mozilla::LauncherError(   \
            __FILE__, __LINE__, ::mozilla::WindowsError::FromHResult(hresult)))

    // This macro wraps the supplied WindowsError with a LauncherError
    #  define LAUNCHER_ERROR_FROM_MOZ_WINDOWS_ERROR(err) \
        ::mozilla::Err(::mozilla::LauncherError(__FILE__, __LINE__, err))

    #else

    #  define LAUNCHER_ERROR_GENERIC() \
        ::mozilla::Err(::mozilla::WindowsError::CreateGeneric())

    #  define LAUNCHER_ERROR_FROM_DETOUR_ERROR(err) LAUNCHER_ERROR_GENERIC()

    #  define LAUNCHER_ERROR_FROM_WIN32(err) \
        ::mozilla::Err(::mozilla::WindowsError::FromWin32Error(err))

    #  define LAUNCHER_ERROR_FROM_LAST() \
        ::mozilla::Err(::mozilla::WindowsError::FromLastError())

    #  define LAUNCHER_ERROR_FROM_NTSTATUS(ntstatus) \
        ::mozilla::Err(::mozilla::WindowsError::FromNtStatus(ntstatus))

    #  define LAUNCHER_ERROR_FROM_HRESULT(hresult) \
        ::mozilla::Err(::mozilla::WindowsError::FromHResult(hresult))

    #  define LAUNCHER_ERROR_FROM_MOZ_WINDOWS_ERROR(err) ::mozilla::Err(err)

    #endif  // defined(MOZ_USE_LAUNCHER_ERROR)

    // How long to wait for a created process to become available for input,
    // to prevent that process's windows being forced to the background.
    // This is used across update, restart, and the launcher.
    const DWORD kWaitForInputIdleTimeoutMS = 10 * 1000;

    /**
     * Wait for a child GUI process to become "idle." Idle means that the process
     * has created its message queue and has begun waiting for user input.
     *
     * Note that this must only be used when the child process is going to display
     * GUI! Otherwise you're going to be waiting for a very long time ;-)
     *
     * @return true if we successfully waited for input idle;
     *         false if we timed out or failed to wait.
     */
    inline bool WaitForInputIdle(HANDLE aProcess,
                                 DWORD aTimeoutMs = kWaitForInputIdleTimeoutMS) {
      const DWORD kSleepTimeMs = 10;
      const DWORD waitStart = aTimeoutMs == INFINITE ? 0 : ::GetTickCount();
      DWORD elapsed = 0;

      while (true) {
        if (aTimeoutMs != INFINITE) {
          elapsed = ::GetTickCount() - waitStart;
        }

        if (elapsed >= aTimeoutMs) {
          return false;
        }

        // ::WaitForInputIdle() doesn't always set the last-error code on failure
        ::SetLastError(ERROR_SUCCESS);

        DWORD waitResult = ::WaitForInputIdle(aProcess, aTimeoutMs - elapsed);
        if (!waitResult) {
          return true;
        }

        if (waitResult == WAIT_FAILED &&
            ::GetLastError() == ERROR_NOT_GUI_PROCESS) {
          ::Sleep(kSleepTimeMs);
          continue;
        }

        return false;
      }
    }

    enum class PathType {
      eNtPath,
      eDosPath,
    };

    class FileUniqueId final {
     public:
      explicit FileUniqueId(const wchar_t* aPath, PathType aPathType)
          : mId(FILE_ID_INFO()) {
        if (!aPath) {
          mId = LAUNCHER_ERROR_FROM_HRESULT(E_INVALIDARG);
          return;
        }

        nsAutoHandle file;

        switch (aPathType) {
          default:
            mId = LAUNCHER_ERROR_FROM_HRESULT(E_INVALIDARG);
            MOZ_ASSERT_UNREACHABLE("Unhandled PathType");
            return;

          case PathType::eNtPath: {
            UNICODE_STRING unicodeString;
            ::RtlInitUnicodeString(&unicodeString, aPath);
            OBJECT_ATTRIBUTES objectAttributes;
            InitializeObjectAttributes(&objectAttributes, &unicodeString,
                                       OBJ_CASE_INSENSITIVE, nullptr, nullptr);
            IO_STATUS_BLOCK ioStatus = {};
            HANDLE ntHandle;
            NTSTATUS status = ::NtOpenFile(
                &ntHandle, SYNCHRONIZE | FILE_READ_ATTRIBUTES, &objectAttributes,
                &ioStatus, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT);
            // We don't need to check |ntHandle| for INVALID_HANDLE_VALUE here,
            // as that value is set by the Win32 layer.
            if (!NT_SUCCESS(status)) {
              mId = LAUNCHER_ERROR_FROM_NTSTATUS(status);
              return;
            }

            file.own(ntHandle);
            break;
          }

          case PathType::eDosPath: {
            file.own(::CreateFileW(
                aPath, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr));
            if (file == INVALID_HANDLE_VALUE) {
              mId = LAUNCHER_ERROR_FROM_LAST();
              return;
            }

            break;
          }
        }

        GetId(file);
      }

      explicit FileUniqueId(const nsAutoHandle& aFile) : mId(FILE_ID_INFO()) {
        GetId(aFile);
      }

      ~FileUniqueId() = default;

      bool IsError() const { return mId.isErr(); }

      const WindowsErrorType& GetError() const { return mId.inspectErr(); }

      FileUniqueId(FileUniqueId&& aOther) = default;
      FileUniqueId& operator=(FileUniqueId&& aOther) = delete;

      bool operator==(const FileUniqueId& aOther) const {
        return mId.isOk() && aOther.mId.isOk() &&
               !memcmp(&mId.inspect(), &aOther.mId.inspect(), sizeof(FILE_ID_INFO));
      }

      bool operator!=(const FileUniqueId& aOther) const {
        return !((*this) == aOther);
      }

     private:
      void GetId(const nsAutoHandle& aFile) {
        FILE_ID_INFO fileIdInfo = {};
        if (IsWin8OrLater()) {
          if (::GetFileInformationByHandleEx(aFile.get(), FileIdInfo, &fileIdInfo,
                                             sizeof(fileIdInfo))) {
            mId = fileIdInfo;
            return;
          }
          // Only NTFS and ReFS support FileIdInfo. So we have to fallback if
          // GetFileInformationByHandleEx failed.
        }

        BY_HANDLE_FILE_INFORMATION info = {};
        if (!::GetFileInformationByHandle(aFile.get(), &info)) {
          mId = LAUNCHER_ERROR_FROM_LAST();
          return;
        }

        fileIdInfo.VolumeSerialNumber = info.dwVolumeSerialNumber;
        memcpy(&fileIdInfo.FileId.Identifier[0], &info.nFileIndexLow,
               sizeof(DWORD));
        memcpy(&fileIdInfo.FileId.Identifier[sizeof(DWORD)], &info.nFileIndexHigh,
               sizeof(DWORD));
        mId = fileIdInfo;
      }

     private:
      LauncherResult mId;
    };

    class MOZ_RAII AutoVirtualProtect final {
     public:
      AutoVirtualProtect(void* aAddress, size_t aLength, DWORD aProtFlags,
                         HANDLE aTargetProcess = ::GetCurrentProcess())
          : mAddress(aAddress),
            mLength(aLength),
            mTargetProcess(aTargetProcess),
            mPrevProt(0),
            mError(WindowsError::CreateSuccess()) {
        if (!::VirtualProtectEx(aTargetProcess, aAddress, aLength, aProtFlags,
                                &mPrevProt)) {
          mError = WindowsError::FromLastError();
        }
      }

      ~AutoVirtualProtect() {
        if (mError.IsFailure()) {
          return;
        }

        ::VirtualProtectEx(mTargetProcess, mAddress, mLength, mPrevProt,
                           &mPrevProt);
      }

      explicit operator bool() const { return mError.IsSuccess(); }

      WindowsError GetError() const { return mError; }

      DWORD PrevProt() const { return mPrevProt; }

      AutoVirtualProtect(const AutoVirtualProtect&) = delete;
      AutoVirtualProtect(AutoVirtualProtect&&) = delete;
      AutoVirtualProtect& operator=(const AutoVirtualProtect&) = delete;
      AutoVirtualProtect& operator=(AutoVirtualProtect&&) = delete;

     private:
      void* mAddress;
      size_t mLength;
      HANDLE mTargetProcess;
      DWORD mPrevProt;
      WindowsError mError;
    };

    inline UniquePtr GetFullModulePath(HMODULE aModule) {
      DWORD bufLen = MAX_PATH;
      mozilla::UniquePtr buf;
      DWORD retLen;

      while (true) {
        buf = mozilla::MakeUnique(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(retLen);
      if (wcscpy_s(result.get(), retLen, buf.get())) {
        return nullptr;
      }

      return result;
    }

    inline UniquePtr GetFullBinaryPath() {
      return GetFullModulePath(nullptr);
    }

    class ModuleVersion final {
     public:
      constexpr ModuleVersion() : mVersion(0ULL) {}

      explicit ModuleVersion(const VS_FIXEDFILEINFO& aFixedInfo)
          : mVersion((static_cast(aFixedInfo.dwFileVersionMS) << 32) |
                     static_cast(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 AsTuple() const {
        uint16_t major = static_cast((mVersion >> 48) & 0xFFFFU);
        uint16_t minor = static_cast((mVersion >> 32) & 0xFFFFU);
        uint16_t patch = static_cast((mVersion >> 16) & 0xFFFFU);
        uint16_t build = static_cast(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; }

      ModuleVersion& operator=(const uint64_t aIntVersion) {
        mVersion = aIntVersion;
        return *this;
      }

     private:
      uint64_t mVersion;
    };

    inline LauncherResult GetModuleVersion(
        const wchar_t* aModuleFullPath) {
      DWORD verInfoLen = ::GetFileVersionInfoSizeW(aModuleFullPath, nullptr);
      if (!verInfoLen) {
        return LAUNCHER_ERROR_FROM_LAST();
      }

      auto verInfoBuf = MakeUnique(verInfoLen);
      if (!::GetFileVersionInfoW(aModuleFullPath, 0, verInfoLen,
                                 verInfoBuf.get())) {
        return LAUNCHER_ERROR_FROM_LAST();
      }

      UINT fixedInfoLen;
      VS_FIXEDFILEINFO* fixedInfo = nullptr;
      if (!::VerQueryValueW(verInfoBuf.get(), L"\\",
                            reinterpret_cast(&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 LauncherResult GetModuleVersion(HMODULE aModule) {
      UniquePtr fullPath(GetFullModulePath(aModule));
      if (!fullPath) {
        return LAUNCHER_ERROR_GENERIC();
      }

      return GetModuleVersion(fullPath.get());
    }

    #if defined(MOZILLA_INTERNAL_API)
    inline LauncherResult GetModuleVersion(nsIFile* aFile) {
      if (!aFile) {
        return LAUNCHER_ERROR_FROM_HRESULT(E_INVALIDARG);
      }

      nsAutoString fullPath;
      nsresult rv = aFile->GetPath(fullPath);
      if (NS_FAILED(rv)) {
        return LAUNCHER_ERROR_GENERIC();
      }

      return GetModuleVersion(fullPath.get());
    }
    #endif  // defined(MOZILLA_INTERNAL_API)

    struct CoTaskMemFreeDeleter {
      void operator()(void* aPtr) { ::CoTaskMemFree(aPtr); }
    };

    inline LauncherResult GetElevationType(
        const nsAutoHandle& aToken) {
      DWORD retLen;
      TOKEN_ELEVATION_TYPE elevationType;
      if (!::GetTokenInformation(aToken.get(), TokenElevationType, &elevationType,
                                 sizeof(elevationType), &retLen)) {
        return LAUNCHER_ERROR_FROM_LAST();
      }

      return elevationType;
    }

    }  // namespace mozilla

## Minimal test - lines (41, 44)

path: .spaces[0].metrics.nargs.average
old: 1.0
new: null
path: .spaces[0].metrics.nargs.sum
old: 1.0
new: 0.0
path: .spaces[0].metrics.nexits.average
old: 0.0
new: null
path: .spaces[0].metrics.cognitive.average
old: 4.0
new: null
path: .spaces[0].metrics.cognitive.sum
old: 4.0
new: 0.0
path: .spaces[0].metrics.mi.mi_sei
old: 51.76455993612254
new: 115.02610035996176
path: .spaces[0].metrics.mi.mi_original
old: 74.03847250651805
new: 132.13127313109095
path: .spaces[0].metrics.mi.mi_visual_studio
old: 43.29735234299301
new: 77.26975036905904
path: .spaces[0].metrics.nom.functions
old: 1.0
new: 0.0
path: .spaces[0].metrics.nom.total
old: 1.0
new: 0.0
path: .spaces[0].metrics.cyclomatic.average
old: 3.0
new: 1.0
path: .spaces[0].metrics.cyclomatic.sum
old: 3.0
new: 1.0
path: .spaces[0].metrics.halstead.vocabulary
old: 52.0
new: 7.0
path: .spaces[0].metrics.halstead.volume
old: 1037.4800287016787
new: 22.458839376460833
path: .spaces[0].metrics.halstead.N2
old: 87.0
new: 4.0
path: .spaces[0].metrics.halstead.N1
old: 95.0
new: 4.0
path: .spaces[0].metrics.halstead.time
old: 1327.3641543683243
new: 1.871569948038403
path: .spaces[0].metrics.halstead.effort
old: 23892.55477862984
new: 33.68825906469125
path: .spaces[0].metrics.halstead.n1
old: 18.0
new: 3.0
path: .spaces[0].metrics.halstead.n2
old: 34.0
new: 4.0
path: .spaces[0].metrics.halstead.bugs
old: 0.2765161313707384
new: 0.003476944758806696
path: .spaces[0].metrics.halstead.estimated_program_length
old: 248.03238662847315
new: 12.754887502163468
path: .spaces[0].metrics.halstead.difficulty
old: 23.029411764705884
new: 1.5
path: .spaces[0].metrics.halstead.level
old: 0.043422733077905486
new: 0.6666666666666666
path: .spaces[0].metrics.halstead.length
old: 182.0
new: 8.0
path: .spaces[0].metrics.halstead.purity_ratio
old: 1.3628153111454568
new: 1.5943609377704335
path: .spaces[0].metrics.loc.ploc
old: 35.0
new: 4.0
path: .spaces[0].metrics.loc.lloc
old: 13.0
new: 0.0
path: .spaces[0].metrics.loc.cloc
old: 3.0
new: 0.0
path: .spaces[0].metrics.loc.blank
old: 3.0
new: 0.0
path: .spaces[0].metrics.loc.sloc
old: 41.0
new: 4.0

### Code

    typedef struct _FILE_ID_INFO {
      ULONGLONG VolumeSerialNumber;
      FILE_ID_128 FileId;
    } FILE_ID_INFO;