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 | |
37 | STDAPI BinderGetDisplayName(PEAssembly *pAssembly, |
38 | SString &displayName); |
39 | |
40 | namespace 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 | |