summaryrefslogtreecommitdiff
path: root/src/debug/di/rsmda.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/debug/di/rsmda.cpp')
-rw-r--r--src/debug/di/rsmda.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/debug/di/rsmda.cpp b/src/debug/di/rsmda.cpp
new file mode 100644
index 0000000000..d69b448309
--- /dev/null
+++ b/src/debug/di/rsmda.cpp
@@ -0,0 +1,243 @@
+// 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.
+//*****************************************************************************
+// File: RsMda.cpp
+//
+
+// Manage Debug Assistant support in the Right-Side
+//
+//*****************************************************************************
+#include "stdafx.h"
+
+#include "winbase.h"
+#include "corpriv.h"
+
+//-----------------------------------------------------------------------------
+// Cordb MDA notification
+//-----------------------------------------------------------------------------
+CordbMDA::CordbMDA(CordbProcess * pProc, DebuggerMDANotification * pData)
+: CordbBase(pProc, 0, enumCordbMDA)
+{
+ _ASSERTE(pData != NULL);
+
+ // Owning Parent process should add us to process'es neuter list.
+
+ // Pick up ownership of strings
+ m_szName = pData->szName.TransferStringData();
+ m_szDescription = pData->szDescription.TransferStringData();
+ m_szXml = pData->szXml.TransferStringData();
+
+ m_dwOSTID = pData->dwOSThreadId;
+ m_flags = pData->flags;
+}
+
+//-----------------------------------------------------------------------------
+// Destructor for CordbMDA object. Not much to do here since neutering should
+// have taken care of it all.
+//-----------------------------------------------------------------------------
+CordbMDA::~CordbMDA()
+{
+ // Strings protected w/ holders that will automatically free them.
+ _ASSERTE(IsNeutered());
+}
+
+//-----------------------------------------------------------------------------
+// Neuter the CordbMDA object.
+//-----------------------------------------------------------------------------
+void CordbMDA::Neuter()
+{
+ // Release buffers. Once we're neutered, these can no longer be accessed anyways,
+ // so may as well free them now.
+ // This is being done under the process-lock, and our accessors are also done
+ // under that lock, so we don't have to worry about any races here. :)
+ m_szName.Clear();
+ m_szDescription.Clear();
+ m_szXml.Clear();
+
+ CordbBase::Neuter();
+};
+
+//-----------------------------------------------------------------------------
+// Implement IUnknown::QueryInterface.
+//-----------------------------------------------------------------------------
+HRESULT CordbMDA::QueryInterface(REFIID riid, void **ppInterface)
+{
+ if (riid == IID_ICorDebugMDA)
+ *ppInterface = static_cast<ICorDebugMDA*>(this);
+ else if (riid == IID_IUnknown)
+ *ppInterface = static_cast<IUnknown*>(static_cast<ICorDebugMDA*>(this));
+ else
+ {
+ *ppInterface = NULL;
+ return E_NOINTERFACE;
+ }
+
+ ExternalAddRef();
+ return S_OK;
+}
+
+//-----------------------------------------------------------------------------
+// Helper to marshal a string object out through the ICorDebug interfaces
+// *GetName() functions using the common triple design pattern.
+//
+// parameters:
+// pInputString - the string that we want to marshal out via the triple
+// cchName, pcchName, szName - triple used to marshal out a string.
+// Same usage as CordbModule::GetName and other string getters on the API.
+//
+// *pcchName is always set to the length of pInputString (including NULL). This lets
+// callers know the full size of buffer they'd need to allocate to get the full string.
+//
+// if (cchName == 0) then we're in "query" mode:
+// szName must be null. pcchName must be non-null and this function will just set
+// *pcchName to let the caller know how large of a buffer to allocate.
+
+// if (cchName != 0) then we copy as much as can fit into szName. We will always
+// null terminate szName.
+// pcchName can be null. If it's non-null, we set it.
+//
+//
+// Expected usage is that caller calls us twice, once in query mode to allocate
+// buffer, then a 2nd time to fill the buffer.
+//
+// Returns: S_OK on success.
+//-----------------------------------------------------------------------------
+HRESULT CopyOutString(LPCWSTR pInputString, ULONG32 cchName, ULONG32 * pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[])
+{
+ _ASSERTE(pInputString != NULL);
+ ULONG32 len = (ULONG32) wcslen(pInputString) + 1;
+
+ if (cchName == 0)
+ {
+ // Query length
+ if ((szName != NULL) || (pcchName == NULL))
+ {
+ return E_INVALIDARG;
+ }
+ *pcchName = len;
+ return S_OK;
+ }
+ else
+ {
+ // Get data
+ if (szName == NULL)
+ {
+ return E_INVALIDARG;
+ }
+
+ // Just copy whatever we can fit into the buffer. If we truncate, that's ok.
+ // This will also guarantee that we null terminate.
+ wcsncpy_s(szName, cchName, pInputString, _TRUNCATE);
+
+ if (pcchName != 0)
+ {
+ *pcchName = len;
+ }
+
+ return S_OK;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Get the string for the type of the MDA. Never empty.
+// This is a convenient performant alternative to getting the XML stream and extracting
+// the type from that based off the schema.
+// See CopyOutString for parameter details.
+//-----------------------------------------------------------------------------
+HRESULT CordbMDA::GetName(ULONG32 cchName, ULONG32 * pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[])
+{
+ HRESULT hr = S_OK;
+ PUBLIC_API_BEGIN(this)
+ {
+#if defined(FEATURE_CORECLR)
+ hr = E_NOTIMPL;
+#else // !FEATURE_CORECLR
+ hr = CopyOutString(m_szName, cchName, pcchName, szName);
+#endif // FEATURE_CORECLR
+ }
+ PUBLIC_API_END(hr);
+ return hr;
+}
+
+//-----------------------------------------------------------------------------
+// Get a string description of the MDA. This may be empty (0-length).
+// See CopyOutString for parameter details.
+//-----------------------------------------------------------------------------
+HRESULT CordbMDA::GetDescription(ULONG32 cchName, ULONG32 * pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[])
+{
+ HRESULT hr = S_OK;
+ PUBLIC_API_BEGIN(this)
+ {
+#if defined(FEATURE_CORECLR)
+ hr = E_NOTIMPL;
+#else // !FEATURE_CORECLR
+ hr = CopyOutString(m_szDescription, cchName, pcchName, szName);
+#endif // FEATURE_CORECLR
+ }
+ PUBLIC_API_END(hr);
+ return hr;
+}
+
+//-----------------------------------------------------------------------------
+// Get the full associated XML for the MDA. This may be empty.
+// This could be a potentially expensive operation if the xml stream is large.
+// See the MDA documentation for the schema for this XML stream.
+// See CopyOutString for parameter details.
+//-----------------------------------------------------------------------------
+HRESULT CordbMDA::GetXML(ULONG32 cchName, ULONG32 * pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[])
+{
+ HRESULT hr = S_OK;
+ PUBLIC_API_BEGIN(this)
+ {
+#if defined(FEATURE_CORECLR)
+ hr = E_NOTIMPL;
+#else // !FEATURE_CORECLR
+ hr = CopyOutString(m_szXml, cchName, pcchName, szName);
+#endif // FEATURE_CORECLR
+ }
+ PUBLIC_API_END(hr);
+ return hr;
+}
+
+//-----------------------------------------------------------------------------
+// Get flags for this MDA object.
+//-----------------------------------------------------------------------------
+HRESULT CordbMDA::GetFlags(CorDebugMDAFlags * pFlags)
+{
+ HRESULT hr = S_OK;
+ PUBLIC_API_BEGIN(this)
+ {
+#if defined(FEATURE_CORECLR)
+ hr = E_NOTIMPL;
+#else // !FEATURE_CORECLR
+ ValidateOrThrow(pFlags);
+ *pFlags = this->m_flags;
+#endif // FEATURE_CORECLR
+ }
+ PUBLIC_API_END(hr);
+ return hr;
+}
+
+//-----------------------------------------------------------------------------
+// Thread that the MDA is fired on. We use the os tid instead of an ICDThread in case an MDA is fired on a
+// native thread (or a managed thread that hasn't yet entered managed code and so we don't have a ICDThread
+// object for it yet)
+//-----------------------------------------------------------------------------
+HRESULT CordbMDA::GetOSThreadId(DWORD * pOsTid)
+{
+ HRESULT hr = S_OK;
+ PUBLIC_API_BEGIN(this)
+ {
+#if defined(FEATURE_CORECLR)
+ hr = E_NOTIMPL;
+#else // !FEATURE_CORECLR
+ ValidateOrThrow(pOsTid);
+
+ *pOsTid = this->m_dwOSTID;
+#endif // FEATURE_CORECLR
+ }
+ PUBLIC_API_END(hr);
+ return hr;
+}
+