1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4// ============================================================
5//
6// BindingLog.cpp
7//
8
9
10//
11// Implements the fusion-like BindingLog class
12//
13// ============================================================
14
15#ifdef FEATURE_VERSIONING_LOG
16
17#define DISABLE_BINDER_DEBUG_LOGGING
18
19#include "bindinglog.hpp"
20#include "assemblyname.hpp"
21#include "assembly.hpp"
22#include "applicationcontext.hpp"
23#include "bindresult.hpp"
24#include "cdebuglog.hpp"
25#include "variables.hpp"
26#include "bindresult.inl"
27
28#include "strsafe.h"
29
30#define SIZE_OF_TOKEN_INFORMATION \
31 sizeof( TOKEN_USER ) \
32 + sizeof( SID ) \
33 + sizeof( ULONG ) * SID_MAX_SUB_AUTHORITIES
34
35#include "../dlls/mscorrc/fusres.h"
36
37STDAPI BinderGetDisplayName(PEAssembly *pAssembly,
38 SString &displayName);
39
40namespace BINDER_SPACE
41{
42 namespace
43 {
44 inline UINT GetPreBindStateName(AssemblyName *pAssemblyName)
45 {
46 if (pAssemblyName->HaveAssemblyVersion())
47 {
48 return ID_FUSLOG_BINDING_PRE_BIND_STATE_BY_NAME;
49 }
50 else
51 {
52 return ID_FUSLOG_BINDING_PRE_BIND_STATE_BY_NAME_PARTIAL;
53 }
54 }
55 };
56
57 BindingLog::BindingLog()
58 {
59 m_pCDebugLog = NULL;
60 }
61
62 BindingLog::~BindingLog()
63 {
64 SAFE_RELEASE(m_pCDebugLog);
65 }
66
67 /* static */
68 HRESULT BindingLog::CreateInContext(ApplicationContext *pApplicationContext,
69 SString &assemblyPath,
70 PEAssembly *pParentAssembly)
71 {
72 HRESULT hr = S_OK;
73 BINDER_LOG_ENTER(L"BindingLog::CreateInContext (assemblyPath)");
74
75 if (IsLoggingNeeded())
76 {
77 IF_FAIL_GO(CreateInContext(pApplicationContext, NULL, assemblyPath, pParentAssembly));
78 }
79
80 Exit:
81 BINDER_LOG_LEAVE_HR(L"BindingLog::CreateInContext (assemblyPath)", hr);
82 return hr;
83 }
84
85 /* static */
86 BOOL BindingLog::IsLoggingNeeded()
87 {
88#ifdef FEATURE_VERSIONING_LOG
89 return g_BinderVariables->fLoggingNeeded;
90#else // FEATURE_VERSIONING_LOG
91 return FALSE;
92#endif // FEATURE_VERSIONING_LOG
93 }
94
95 /* static */
96 HRESULT BindingLog::CreateInContext(ApplicationContext *pApplicationContext,
97 AssemblyName *pAssemblyName,
98 PEAssembly *pParentAssembly)
99 {
100 HRESULT hr = S_OK;
101 BINDER_LOG_ENTER(L"BindingLog::CreateInContext (pAssemblyName)");
102
103 if (IsLoggingNeeded())
104 {
105 SmallStackSString emptyString;
106
107 IF_FALSE_GO(pAssemblyName != NULL);
108 IF_FAIL_GO(CreateInContext(pApplicationContext,
109 pAssemblyName,
110 emptyString,
111 pParentAssembly));
112 }
113
114 Exit:
115 BINDER_LOG_LEAVE_HR(L"BindingLog::CreateInContext (pAssemblyName)", hr);
116 return hr;
117 }
118
119 HRESULT BindingLog::Log(SString &info)
120 {
121 HRESULT hr = S_OK;
122 BINDER_LOG_ENTER(L"BindingLog::Log");
123
124 IF_FAIL_GO(GetDebugLog()->LogMessage(0, FUSION_BIND_LOG_CATEGORY_DEFAULT, info));
125
126 Exit:
127 BINDER_LOG_LEAVE_HR(L"BindingLog::Log", hr);
128 return hr;
129 }
130
131 HRESULT BindingLog::LogAssemblyName(LPCWSTR pwzPrefix,
132 AssemblyName *pAssemblyName)
133 {
134 HRESULT hr = S_OK;
135 BINDER_LOG_ENTER(L"BindingLog::LogAssemblyName");
136 PathString assemblyDisplayName;
137
138 // Verify input arguments
139 IF_FALSE_GO(pwzPrefix != NULL);
140 IF_FALSE_GO(pAssemblyName != NULL);
141
142 pAssemblyName->GetDisplayName(assemblyDisplayName,
143 AssemblyName::INCLUDE_VERSION |
144 AssemblyName::INCLUDE_ARCHITECTURE);
145 IF_FAIL_GO(Log(pwzPrefix, assemblyDisplayName));
146
147 Exit:
148 BINDER_LOG_LEAVE_HR(L"BindingLog::LogAssemblyName", hr);
149 return hr;
150 }
151
152 HRESULT BindingLog::LogHR(HRESULT logHR)
153 {
154 HRESULT hr = S_OK;
155 BINDER_LOG_ENTER(L"BindingLog::LogHR");
156
157 IF_FAIL_GO(GetDebugLog()->SetResultCode(0, logHR));
158
159 Exit:
160 BINDER_LOG_LEAVE_HR(L"BindingLog::LogHR", hr);
161 return hr;
162 }
163
164 HRESULT BindingLog::LogResult(BindResult *pBindResult)
165 {
166 HRESULT hr = S_OK;
167 BINDER_LOG_ENTER(L"BindingLog::LogResult");
168 PathString assemblyDisplayName;
169 PathString format;
170 PathString info;
171
172 pBindResult->GetAssemblyName()->GetDisplayName(assemblyDisplayName,
173 AssemblyName::INCLUDE_VERSION |
174 AssemblyName::INCLUDE_ARCHITECTURE);
175
176 IF_FAIL_GO(format.LoadResourceAndReturnHR(CCompRC::Debugging,
177 ID_FUSLOG_ASSEMBLY_STATUS_BOUND_TO_ID));
178 info.Printf(format.GetUnicode(), assemblyDisplayName.GetUnicode());
179 IF_FAIL_GO(Log(info));
180
181 IUnknown *pIUnknownAssembly;
182 pIUnknownAssembly = pBindResult->GetAssembly(FALSE /* fAddRef */);
183 Assembly *pAssembly;
184 pAssembly = static_cast<Assembly *>(static_cast<void *>(pIUnknownAssembly));
185 _ASSERTE(pAssembly != NULL);
186
187 if (pAssembly->GetIsInGAC())
188 {
189 IF_FAIL_GO(info.
190 LoadResourceAndReturnHR(CCompRC::Debugging,
191 ID_FUSLOG_ASSEMBLY_STATUS_BOUND_GAC));
192 }
193 else if (pAssembly->GetIsByteArray())
194 {
195 IF_FAIL_GO(info.
196 LoadResourceAndReturnHR(CCompRC::Debugging,
197 ID_FUSLOG_ASSEMBLY_STATUS_BOUND_BYTE_ARRAY));
198 }
199 else
200 {
201 PathString assemblyPath;
202
203 BinderGetImagePath(pAssembly->GetPEImage(), assemblyPath);
204 IF_FAIL_GO(format.
205 LoadResourceAndReturnHR(CCompRC::Debugging,
206 ID_FUSLOG_ASSEMBLY_STATUS_BOUND_TO_LOCATION));
207 info.Printf(format.GetUnicode(), assemblyPath.GetUnicode());
208 }
209 IF_FAIL_GO(Log(info));
210
211 Exit:
212 BINDER_LOG_LEAVE_HR(L"BindingLog::LogResult", hr);
213 return hr;
214 }
215
216 HRESULT BindingLog::Flush()
217 {
218 HRESULT hr = S_OK;
219 BINDER_LOG_ENTER(L"BindingLog::Flush");
220
221 hr = GetDebugLog()->Flush(0, FUSION_BIND_LOG_CATEGORY_DEFAULT);
222 if (hr == E_ACCESSDENIED)
223 {
224 // We've been impersonated differently and have a old log entry
225 BINDER_LOG(L"Impersonated: E_ACCESSDENIED");
226 hr = S_OK;
227 }
228
229 BINDER_LOG_LEAVE_HR(L"BindingLog::Flush", hr);
230 return hr;
231 }
232
233 /* static */
234 HRESULT BindingLog::CreateInContext(ApplicationContext *pApplicationContext,
235 AssemblyName *pAssemblyName,
236 SString &assemblyPath,
237 PEAssembly *pParentAssembly)
238 {
239 HRESULT hr = S_OK;
240 BINDER_LOG_ENTER(L"BindingLog::CreateInContext");
241
242 BindingLog *pBindingLog = pApplicationContext->GetBindingLog();
243
244 // Invalidate existing debug log
245 pBindingLog->SetDebugLog(NULL);
246
247 IF_FAIL_GO(CDebugLog::Create(pApplicationContext,
248 pAssemblyName,
249 assemblyPath,
250 &pBindingLog->m_pCDebugLog));
251
252 IF_FAIL_GO(pBindingLog->LogPreBindState(pApplicationContext,
253 pAssemblyName,
254 assemblyPath,
255 pParentAssembly));
256 Exit:
257 BINDER_LOG_LEAVE_HR(L"BindingLog::CreateInContext", hr);
258 return hr;
259 }
260
261 HRESULT BindingLog::LogPreBindState(ApplicationContext *pApplicationContext,
262 AssemblyName *pAssemblyName,
263 SString &assemblyPath,
264 PEAssembly *pParentAssembly)
265 {
266 HRESULT hr = S_OK;
267 BINDER_LOG_ENTER(L"BindingLog::LogPreBindState");
268 PathString format;
269 PathString info;
270
271 IF_FAIL_GO(info.LoadResourceAndReturnHR(CCompRC::Debugging,
272 ID_FUSLOG_BINDING_PRE_BIND_STATE_BEGIN));
273 IF_FAIL_GO(Log(info));
274
275 if (pAssemblyName != NULL)
276 {
277 PathString assemblyDisplayName;
278
279 pAssemblyName->GetDisplayName(assemblyDisplayName,
280 AssemblyName::INCLUDE_VERSION |
281 AssemblyName::INCLUDE_ARCHITECTURE |
282 AssemblyName::INCLUDE_RETARGETABLE);
283
284 IF_FAIL_GO(format.LoadResourceAndReturnHR(CCompRC::Debugging,
285 GetPreBindStateName(pAssemblyName)));
286 info.Printf(format.GetUnicode(), assemblyDisplayName.GetUnicode());
287 }
288 else
289 {
290 IF_FAIL_GO(format.
291 LoadResourceAndReturnHR(CCompRC::Debugging,
292 ID_FUSLOG_BINDING_PRE_BIND_STATE_WHERE_REF));
293 info.Printf(format.GetUnicode(), assemblyPath.GetUnicode());
294 }
295 IF_FAIL_GO(Log(info));
296
297 if (pParentAssembly != NULL)
298 {
299 PathString parentAssemblyDisplayName;
300
301 IF_FAIL_GO(BinderGetDisplayName(pParentAssembly, parentAssemblyDisplayName));
302 IF_FAIL_GO(format.LoadResourceAndReturnHR(CCompRC::Debugging,
303 ID_FUSLOG_BINDING_PRE_BIND_STATE_CALLER));
304 info.Printf(format.GetUnicode(), parentAssemblyDisplayName.GetUnicode());
305 }
306 else
307 {
308 IF_FAIL_GO(info.
309 LoadResourceAndReturnHR(CCompRC::Debugging,
310 ID_FUSLOG_BINDING_PRE_BIND_STATE_CALLER_UNKNOWN));
311 }
312 IF_FAIL_GO(Log(info));
313
314 IF_FAIL_GO(info.LoadResourceAndReturnHR(CCompRC::Debugging,
315 ID_FUSLOG_BINDING_PRE_BIND_STATE_END));
316 IF_FAIL_GO(Log(info));
317
318 Exit:
319 BINDER_LOG_LEAVE_HR(L"BindingLog::LogPreBindState", hr);
320 return hr;
321 }
322
323 void BindingLog::SetDebugLog(CDebugLog *pCDebugLog)
324 {
325 SAFE_RELEASE(m_pCDebugLog);
326 m_pCDebugLog = pCDebugLog;
327 }
328};
329
330#endif // FEATURE_VERSIONING_LOG
331