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 //*****************************************************************************
8 // Manage Debug Assistant support in the Right-Side
10 //*****************************************************************************
16 //-----------------------------------------------------------------------------
17 // Cordb MDA notification
18 //-----------------------------------------------------------------------------
19 CordbMDA::CordbMDA(CordbProcess * pProc, DebuggerMDANotification * pData)
20 : CordbBase(pProc, 0, enumCordbMDA)
22 _ASSERTE(pData != NULL);
24 // Owning Parent process should add us to process'es neuter list.
26 // Pick up ownership of strings
27 m_szName = pData->szName.TransferStringData();
28 m_szDescription = pData->szDescription.TransferStringData();
29 m_szXml = pData->szXml.TransferStringData();
31 m_dwOSTID = pData->dwOSThreadId;
32 m_flags = pData->flags;
35 //-----------------------------------------------------------------------------
36 // Destructor for CordbMDA object. Not much to do here since neutering should
37 // have taken care of it all.
38 //-----------------------------------------------------------------------------
41 // Strings protected w/ holders that will automatically free them.
42 _ASSERTE(IsNeutered());
45 //-----------------------------------------------------------------------------
46 // Neuter the CordbMDA object.
47 //-----------------------------------------------------------------------------
48 void CordbMDA::Neuter()
50 // Release buffers. Once we're neutered, these can no longer be accessed anyways,
51 // so may as well free them now.
52 // This is being done under the process-lock, and our accessors are also done
53 // under that lock, so we don't have to worry about any races here. :)
55 m_szDescription.Clear();
61 //-----------------------------------------------------------------------------
62 // Implement IUnknown::QueryInterface.
63 //-----------------------------------------------------------------------------
64 HRESULT CordbMDA::QueryInterface(REFIID riid, void **ppInterface)
66 if (riid == IID_ICorDebugMDA)
67 *ppInterface = static_cast<ICorDebugMDA*>(this);
68 else if (riid == IID_IUnknown)
69 *ppInterface = static_cast<IUnknown*>(static_cast<ICorDebugMDA*>(this));
80 //-----------------------------------------------------------------------------
81 // Helper to marshal a string object out through the ICorDebug interfaces
82 // *GetName() functions using the common triple design pattern.
85 // pInputString - the string that we want to marshal out via the triple
86 // cchName, pcchName, szName - triple used to marshal out a string.
87 // Same usage as CordbModule::GetName and other string getters on the API.
89 // *pcchName is always set to the length of pInputString (including NULL). This lets
90 // callers know the full size of buffer they'd need to allocate to get the full string.
92 // if (cchName == 0) then we're in "query" mode:
93 // szName must be null. pcchName must be non-null and this function will just set
94 // *pcchName to let the caller know how large of a buffer to allocate.
96 // if (cchName != 0) then we copy as much as can fit into szName. We will always
97 // null terminate szName.
98 // pcchName can be null. If it's non-null, we set it.
101 // Expected usage is that caller calls us twice, once in query mode to allocate
102 // buffer, then a 2nd time to fill the buffer.
104 // Returns: S_OK on success.
105 //-----------------------------------------------------------------------------
106 HRESULT CopyOutString(LPCWSTR pInputString, ULONG32 cchName, ULONG32 * pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[])
108 _ASSERTE(pInputString != NULL);
109 ULONG32 len = (ULONG32) wcslen(pInputString) + 1;
114 if ((szName != NULL) || (pcchName == NULL))
129 // Just copy whatever we can fit into the buffer. If we truncate, that's ok.
130 // This will also guarantee that we null terminate.
131 wcsncpy_s(szName, cchName, pInputString, _TRUNCATE);
142 //-----------------------------------------------------------------------------
143 // Get the string for the type of the MDA. Never empty.
144 // This is a convenient performant alternative to getting the XML stream and extracting
145 // the type from that based off the schema.
146 // See CopyOutString for parameter details.
147 //-----------------------------------------------------------------------------
148 HRESULT CordbMDA::GetName(ULONG32 cchName, ULONG32 * pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[])
151 PUBLIC_API_BEGIN(this)
159 //-----------------------------------------------------------------------------
160 // Get a string description of the MDA. This may be empty (0-length).
161 // See CopyOutString for parameter details.
162 //-----------------------------------------------------------------------------
163 HRESULT CordbMDA::GetDescription(ULONG32 cchName, ULONG32 * pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[])
166 PUBLIC_API_BEGIN(this)
174 //-----------------------------------------------------------------------------
175 // Get the full associated XML for the MDA. This may be empty.
176 // This could be a potentially expensive operation if the xml stream is large.
177 // See the MDA documentation for the schema for this XML stream.
178 // See CopyOutString for parameter details.
179 //-----------------------------------------------------------------------------
180 HRESULT CordbMDA::GetXML(ULONG32 cchName, ULONG32 * pcchName, __out_ecount_part_opt(cchName, *pcchName) WCHAR szName[])
183 PUBLIC_API_BEGIN(this)
191 //-----------------------------------------------------------------------------
192 // Get flags for this MDA object.
193 //-----------------------------------------------------------------------------
194 HRESULT CordbMDA::GetFlags(CorDebugMDAFlags * pFlags)
197 PUBLIC_API_BEGIN(this)
205 //-----------------------------------------------------------------------------
206 // Thread that the MDA is fired on. We use the os tid instead of an ICDThread in case an MDA is fired on a
207 // native thread (or a managed thread that hasn't yet entered managed code and so we don't have a ICDThread
208 // object for it yet)
209 //-----------------------------------------------------------------------------
210 HRESULT CordbMDA::GetOSThreadId(DWORD * pOsTid)
213 PUBLIC_API_BEGIN(this)