summaryrefslogtreecommitdiffstats
path: root/browser/app/winlauncher/freestanding/ModuleLoadFrame.cpp
blob: 3aa043b8c7aa897ec9854563a48f1e0da1ed291d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/* -*- 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 https://mozilla.org/MPL/2.0/. */

#include "ModuleLoadFrame.h"

#include "LoaderPrivateAPI.h"

namespace mozilla {
namespace freestanding {

ModuleLoadFrame::ModuleLoadFrame(PCUNICODE_STRING aRequestedDllName)
    : mPrev(sTopFrame.get()),
      mContext(nullptr),
      mLSPSubstitutionRequired(false),
      mLoadNtStatus(STATUS_UNSUCCESSFUL),
      mLoadInfo(aRequestedDllName) {
  EnsureInitialized();
  sTopFrame.set(this);

  gLoaderPrivateAPI.NotifyBeginDllLoad(mLoadInfo, &mContext, aRequestedDllName);
}

ModuleLoadFrame::ModuleLoadFrame(nt::AllocatedUnicodeString&& aSectionName,
                                 const void* aMapBaseAddr, NTSTATUS aNtStatus,
                                 ModuleLoadInfo::Status aLoadStatus,
                                 bool aIsDependent)
    : mPrev(sTopFrame.get()),
      mContext(nullptr),
      mLSPSubstitutionRequired(false),
      mLoadNtStatus(aNtStatus),
      mLoadInfo(std::move(aSectionName), aMapBaseAddr, aLoadStatus,
                aIsDependent) {
  sTopFrame.set(this);

  gLoaderPrivateAPI.NotifyBeginDllLoad(&mContext, mLoadInfo.mSectionName);
}

ModuleLoadFrame::~ModuleLoadFrame() {
  gLoaderPrivateAPI.NotifyEndDllLoad(mContext, mLoadNtStatus,
                                     std::move(mLoadInfo));
  sTopFrame.set(mPrev);
}

/* static */
void ModuleLoadFrame::NotifyLSPSubstitutionRequired(
    PCUNICODE_STRING aLeafName) {
  ModuleLoadFrame* topFrame = sTopFrame.get();
  if (!topFrame) {
    return;
  }

  topFrame->SetLSPSubstitutionRequired(aLeafName);
}

void ModuleLoadFrame::SetLSPSubstitutionRequired(PCUNICODE_STRING aLeafName) {
  MOZ_ASSERT(!mLoadInfo.mBaseAddr);
  if (mLoadInfo.mBaseAddr) {
    // If mBaseAddr is not null then |this| has already seen a module load. This
    // should not be the case for a LSP substitution, so we bail.
    return;
  }

  // Save aLeafName, as it will be used by SetLoadStatus when invoking
  // SubstituteForLSP
  mLoadInfo.mRequestedDllName = aLeafName;
  mLSPSubstitutionRequired = true;
}

/* static */
void ModuleLoadFrame::NotifySectionMap(
    nt::AllocatedUnicodeString&& aSectionName, const void* aMapBaseAddr,
    NTSTATUS aMapNtStatus, ModuleLoadInfo::Status aLoadStatus,
    bool aIsDependent) {
  ModuleLoadFrame* topFrame = sTopFrame.get();
  if (!topFrame) {
    // The only time that this data is useful is during initial mapping of
    // the executable's dependent DLLs. If mozglue is present then
    // IsDefaultObserver will return false, indicating that we are beyond
    // initial process startup.
    if (gLoaderPrivateAPI.IsDefaultObserver()) {
      OnBareSectionMap(std::move(aSectionName), aMapBaseAddr, aMapNtStatus,
                       aLoadStatus, aIsDependent);
    }
    return;
  }

  topFrame->OnSectionMap(std::move(aSectionName), aMapBaseAddr, aMapNtStatus,
                         aLoadStatus, aIsDependent);
}

/* static */
bool ModuleLoadFrame::ExistsTopFrame() { return !!sTopFrame.get(); }

void ModuleLoadFrame::OnSectionMap(nt::AllocatedUnicodeString&& aSectionName,
                                   const void* aMapBaseAddr,
                                   NTSTATUS aMapNtStatus,
                                   ModuleLoadInfo::Status aLoadStatus,
                                   bool aIsDependent) {
  if (mLoadInfo.mBaseAddr) {
    // If mBaseAddr is not null then |this| has already seen a module load. This
    // means that we are witnessing a bare section map.
    OnBareSectionMap(std::move(aSectionName), aMapBaseAddr, aMapNtStatus,
                     aLoadStatus, aIsDependent);
    return;
  }

  mLoadInfo.mSectionName = std::move(aSectionName);
  mLoadInfo.mBaseAddr = aMapBaseAddr;
  mLoadInfo.mStatus = aLoadStatus;
}

/* static */
void ModuleLoadFrame::OnBareSectionMap(
    nt::AllocatedUnicodeString&& aSectionName, const void* aMapBaseAddr,
    NTSTATUS aMapNtStatus, ModuleLoadInfo::Status aLoadStatus,
    bool aIsDependent) {
  // We call the special constructor variant that is used for bare mappings.
  ModuleLoadFrame frame(std::move(aSectionName), aMapBaseAddr, aMapNtStatus,
                        aLoadStatus, aIsDependent);
}

NTSTATUS ModuleLoadFrame::SetLoadStatus(NTSTATUS aNtStatus,
                                        PHANDLE aOutHandle) {
  mLoadNtStatus = aNtStatus;

  if (!mLSPSubstitutionRequired) {
    return aNtStatus;
  }

  if (!gLoaderPrivateAPI.SubstituteForLSP(mLoadInfo.mRequestedDllName,
                                          aOutHandle)) {
    return aNtStatus;
  }

  return STATUS_SUCCESS;
}

SafeThreadLocal<ModuleLoadFrame*> ModuleLoadFrame::sTopFrame;

}  // namespace freestanding
}  // namespace mozilla