summaryrefslogtreecommitdiff
path: root/src/binder/bindinglog.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/binder/bindinglog.cpp')
-rw-r--r--src/binder/bindinglog.cpp332
1 files changed, 332 insertions, 0 deletions
diff --git a/src/binder/bindinglog.cpp b/src/binder/bindinglog.cpp
new file mode 100644
index 0000000000..4466fcea28
--- /dev/null
+++ b/src/binder/bindinglog.cpp
@@ -0,0 +1,332 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+// ============================================================
+//
+// BindingLog.cpp
+//
+
+
+//
+// Implements the fusion-like BindingLog class
+//
+// ============================================================
+
+#ifdef FEATURE_VERSIONING_LOG
+
+#define DISABLE_BINDER_DEBUG_LOGGING
+
+#include "bindinglog.hpp"
+#include "assemblyname.hpp"
+#include "assembly.hpp"
+#include "applicationcontext.hpp"
+#include "bindresult.hpp"
+#include "cdebuglog.hpp"
+#include "variables.hpp"
+#include "bindresult.inl"
+
+#include "strsafe.h"
+
+#define SIZE_OF_TOKEN_INFORMATION \
+ sizeof( TOKEN_USER ) \
+ + sizeof( SID ) \
+ + sizeof( ULONG ) * SID_MAX_SUB_AUTHORITIES
+
+#include "../dlls/mscorrc/fusres.h"
+
+STDAPI BinderGetDisplayName(PEAssembly *pAssembly,
+ SString &displayName);
+
+namespace BINDER_SPACE
+{
+ namespace
+ {
+ // Ripped from Fusion
+
+ inline UINT GetPreBindStateName(AssemblyName *pAssemblyName)
+ {
+ if (pAssemblyName->HaveAssemblyVersion())
+ {
+ return ID_FUSLOG_BINDING_PRE_BIND_STATE_BY_NAME;
+ }
+ else
+ {
+ return ID_FUSLOG_BINDING_PRE_BIND_STATE_BY_NAME_PARTIAL;
+ }
+ }
+ };
+
+ BindingLog::BindingLog()
+ {
+ m_pCDebugLog = NULL;
+ }
+
+ BindingLog::~BindingLog()
+ {
+ SAFE_RELEASE(m_pCDebugLog);
+ }
+
+ /* static */
+ HRESULT BindingLog::CreateInContext(ApplicationContext *pApplicationContext,
+ SString &assemblyPath,
+ PEAssembly *pParentAssembly)
+ {
+ HRESULT hr = S_OK;
+ BINDER_LOG_ENTER(L"BindingLog::CreateInContext (assemblyPath)");
+
+ if (IsLoggingNeeded())
+ {
+ IF_FAIL_GO(CreateInContext(pApplicationContext, NULL, assemblyPath, pParentAssembly));
+ }
+
+ Exit:
+ BINDER_LOG_LEAVE_HR(L"BindingLog::CreateInContext (assemblyPath)", hr);
+ return hr;
+ }
+
+ /* static */
+ BOOL BindingLog::IsLoggingNeeded()
+ {
+#ifdef FEATURE_VERSIONING_LOG
+ return g_BinderVariables->fLoggingNeeded;
+#else // FEATURE_VERSIONING_LOG
+ return FALSE;
+#endif // FEATURE_VERSIONING_LOG
+ }
+
+ /* static */
+ HRESULT BindingLog::CreateInContext(ApplicationContext *pApplicationContext,
+ AssemblyName *pAssemblyName,
+ PEAssembly *pParentAssembly)
+ {
+ HRESULT hr = S_OK;
+ BINDER_LOG_ENTER(L"BindingLog::CreateInContext (pAssemblyName)");
+
+ if (IsLoggingNeeded())
+ {
+ SmallStackSString emptyString;
+
+ IF_FALSE_GO(pAssemblyName != NULL);
+ IF_FAIL_GO(CreateInContext(pApplicationContext,
+ pAssemblyName,
+ emptyString,
+ pParentAssembly));
+ }
+
+ Exit:
+ BINDER_LOG_LEAVE_HR(L"BindingLog::CreateInContext (pAssemblyName)", hr);
+ return hr;
+ }
+
+ HRESULT BindingLog::Log(SString &info)
+ {
+ HRESULT hr = S_OK;
+ BINDER_LOG_ENTER(L"BindingLog::Log");
+
+ IF_FAIL_GO(GetDebugLog()->LogMessage(0, FUSION_BIND_LOG_CATEGORY_DEFAULT, info));
+
+ Exit:
+ BINDER_LOG_LEAVE_HR(L"BindingLog::Log", hr);
+ return hr;
+ }
+
+ HRESULT BindingLog::LogAssemblyName(LPCWSTR pwzPrefix,
+ AssemblyName *pAssemblyName)
+ {
+ HRESULT hr = S_OK;
+ BINDER_LOG_ENTER(L"BindingLog::LogAssemblyName");
+ PathString assemblyDisplayName;
+
+ // Verify input arguments
+ IF_FALSE_GO(pwzPrefix != NULL);
+ IF_FALSE_GO(pAssemblyName != NULL);
+
+ pAssemblyName->GetDisplayName(assemblyDisplayName,
+ AssemblyName::INCLUDE_VERSION |
+ AssemblyName::INCLUDE_ARCHITECTURE);
+ IF_FAIL_GO(Log(pwzPrefix, assemblyDisplayName));
+
+ Exit:
+ BINDER_LOG_LEAVE_HR(L"BindingLog::LogAssemblyName", hr);
+ return hr;
+ }
+
+ HRESULT BindingLog::LogHR(HRESULT logHR)
+ {
+ HRESULT hr = S_OK;
+ BINDER_LOG_ENTER(L"BindingLog::LogHR");
+
+ IF_FAIL_GO(GetDebugLog()->SetResultCode(0, logHR));
+
+ Exit:
+ BINDER_LOG_LEAVE_HR(L"BindingLog::LogHR", hr);
+ return hr;
+ }
+
+ HRESULT BindingLog::LogResult(BindResult *pBindResult)
+ {
+ HRESULT hr = S_OK;
+ BINDER_LOG_ENTER(L"BindingLog::LogResult");
+ PathString assemblyDisplayName;
+ PathString format;
+ PathString info;
+
+ pBindResult->GetAssemblyName()->GetDisplayName(assemblyDisplayName,
+ AssemblyName::INCLUDE_VERSION |
+ AssemblyName::INCLUDE_ARCHITECTURE);
+
+ IF_FAIL_GO(format.LoadResourceAndReturnHR(CCompRC::Debugging,
+ ID_FUSLOG_ASSEMBLY_STATUS_BOUND_TO_ID));
+ info.Printf(format.GetUnicode(), assemblyDisplayName.GetUnicode());
+ IF_FAIL_GO(Log(info));
+
+ IUnknown *pIUnknownAssembly;
+ pIUnknownAssembly = pBindResult->GetAssembly(FALSE /* fAddRef */);
+ Assembly *pAssembly;
+ pAssembly = static_cast<Assembly *>(static_cast<void *>(pIUnknownAssembly));
+ _ASSERTE(pAssembly != NULL);
+
+ if (pAssembly->GetIsInGAC())
+ {
+ IF_FAIL_GO(info.
+ LoadResourceAndReturnHR(CCompRC::Debugging,
+ ID_FUSLOG_ASSEMBLY_STATUS_BOUND_GAC));
+ }
+ else if (pAssembly->GetIsByteArray())
+ {
+ IF_FAIL_GO(info.
+ LoadResourceAndReturnHR(CCompRC::Debugging,
+ ID_FUSLOG_ASSEMBLY_STATUS_BOUND_BYTE_ARRAY));
+ }
+ else
+ {
+ PathString assemblyPath;
+
+ BinderGetImagePath(pAssembly->GetPEImage(), assemblyPath);
+ IF_FAIL_GO(format.
+ LoadResourceAndReturnHR(CCompRC::Debugging,
+ ID_FUSLOG_ASSEMBLY_STATUS_BOUND_TO_LOCATION));
+ info.Printf(format.GetUnicode(), assemblyPath.GetUnicode());
+ }
+ IF_FAIL_GO(Log(info));
+
+ Exit:
+ BINDER_LOG_LEAVE_HR(L"BindingLog::LogResult", hr);
+ return hr;
+ }
+
+ HRESULT BindingLog::Flush()
+ {
+ HRESULT hr = S_OK;
+ BINDER_LOG_ENTER(L"BindingLog::Flush");
+
+ hr = GetDebugLog()->Flush(0, FUSION_BIND_LOG_CATEGORY_DEFAULT);
+ if (hr == E_ACCESSDENIED)
+ {
+ // We've been impersonated differently and have a old log entry
+ BINDER_LOG(L"Impersonated: E_ACCESSDENIED");
+ hr = S_OK;
+ }
+
+ BINDER_LOG_LEAVE_HR(L"BindingLog::Flush", hr);
+ return hr;
+ }
+
+ /* static */
+ HRESULT BindingLog::CreateInContext(ApplicationContext *pApplicationContext,
+ AssemblyName *pAssemblyName,
+ SString &assemblyPath,
+ PEAssembly *pParentAssembly)
+ {
+ HRESULT hr = S_OK;
+ BINDER_LOG_ENTER(L"BindingLog::CreateInContext");
+
+ BindingLog *pBindingLog = pApplicationContext->GetBindingLog();
+
+ // Invalidate existing debug log
+ pBindingLog->SetDebugLog(NULL);
+
+ IF_FAIL_GO(CDebugLog::Create(pApplicationContext,
+ pAssemblyName,
+ assemblyPath,
+ &pBindingLog->m_pCDebugLog));
+
+ IF_FAIL_GO(pBindingLog->LogPreBindState(pApplicationContext,
+ pAssemblyName,
+ assemblyPath,
+ pParentAssembly));
+ Exit:
+ BINDER_LOG_LEAVE_HR(L"BindingLog::CreateInContext", hr);
+ return hr;
+ }
+
+ HRESULT BindingLog::LogPreBindState(ApplicationContext *pApplicationContext,
+ AssemblyName *pAssemblyName,
+ SString &assemblyPath,
+ PEAssembly *pParentAssembly)
+ {
+ HRESULT hr = S_OK;
+ BINDER_LOG_ENTER(L"BindingLog::LogPreBindState");
+ PathString format;
+ PathString info;
+
+ IF_FAIL_GO(info.LoadResourceAndReturnHR(CCompRC::Debugging,
+ ID_FUSLOG_BINDING_PRE_BIND_STATE_BEGIN));
+ IF_FAIL_GO(Log(info));
+
+ if (pAssemblyName != NULL)
+ {
+ PathString assemblyDisplayName;
+
+ pAssemblyName->GetDisplayName(assemblyDisplayName,
+ AssemblyName::INCLUDE_VERSION |
+ AssemblyName::INCLUDE_ARCHITECTURE |
+ AssemblyName::INCLUDE_RETARGETABLE);
+
+ IF_FAIL_GO(format.LoadResourceAndReturnHR(CCompRC::Debugging,
+ GetPreBindStateName(pAssemblyName)));
+ info.Printf(format.GetUnicode(), assemblyDisplayName.GetUnicode());
+ }
+ else
+ {
+ IF_FAIL_GO(format.
+ LoadResourceAndReturnHR(CCompRC::Debugging,
+ ID_FUSLOG_BINDING_PRE_BIND_STATE_WHERE_REF));
+ info.Printf(format.GetUnicode(), assemblyPath.GetUnicode());
+ }
+ IF_FAIL_GO(Log(info));
+
+ if (pParentAssembly != NULL)
+ {
+ PathString parentAssemblyDisplayName;
+
+ IF_FAIL_GO(BinderGetDisplayName(pParentAssembly, parentAssemblyDisplayName));
+ IF_FAIL_GO(format.LoadResourceAndReturnHR(CCompRC::Debugging,
+ ID_FUSLOG_BINDING_PRE_BIND_STATE_CALLER));
+ info.Printf(format.GetUnicode(), parentAssemblyDisplayName.GetUnicode());
+ }
+ else
+ {
+ IF_FAIL_GO(info.
+ LoadResourceAndReturnHR(CCompRC::Debugging,
+ ID_FUSLOG_BINDING_PRE_BIND_STATE_CALLER_UNKNOWN));
+ }
+ IF_FAIL_GO(Log(info));
+
+ IF_FAIL_GO(info.LoadResourceAndReturnHR(CCompRC::Debugging,
+ ID_FUSLOG_BINDING_PRE_BIND_STATE_END));
+ IF_FAIL_GO(Log(info));
+
+ Exit:
+ BINDER_LOG_LEAVE_HR(L"BindingLog::LogPreBindState", hr);
+ return hr;
+ }
+
+ void BindingLog::SetDebugLog(CDebugLog *pCDebugLog)
+ {
+ SAFE_RELEASE(m_pCDebugLog);
+ m_pCDebugLog = pCDebugLog;
+ }
+};
+
+#endif // FEATURE_VERSIONING_LOG