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.
9 #include "mdaassistants.h"
11 #include "dllimport.h"
12 #ifdef FEATURE_COMINTEROP
13 #include "runtimecallablewrapper.h"
14 #include "comcallablewrapper.h"
16 #include "comtoclrcall.h"
19 #include "sigformat.h"
20 #include "fieldmarshaler.h"
21 #include "dllimportcallback.h"
22 #include "dbginterface.h"
23 #include "finalizerthread.h"
25 #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT
26 #include "olecontexthelpers.h"
27 #endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
38 void MdaFramework::DumpDiagnostics()
48 ManagedDebuggingAssistants* pMda = g_mdaStaticHeap.m_pMda;
51 if (m_dumpSchemaSchema)
53 MdaXmlElement* pXmlSchemaSchema = pMda->m_pSchemaSchema->ToXml(pMda->m_pMdaXmlIndustry);
54 // MdaXmlMessage::SendMessage(pXmlSchemaSchema, TRUE, pMda->m_pSchemaSchema);
57 if (m_dumpAssistantSchema)
59 MdaXmlElement* pXmlAssistantMsgSchema = pMda->m_pAssistantMsgSchema->ToXml(pMda->m_pMdaXmlIndustry);
60 // MdaXmlMessage::SendMessage(pXmlAssistantMsgSchema, TRUE, pMda->m_pSchemaSchema);
63 if (m_dumpAssistantMsgSchema)
65 MdaXmlElement* pXmlAssistantSchema = pMda->m_pAssistantSchema->ToXml(pMda->m_pMdaXmlIndustry);
66 // MdaXmlMessage::SendMessage(pXmlAssistantSchema, TRUE, pMda->m_pSchemaSchema);
72 extern BOOL g_bMdaDisableAsserts;
75 void MdaFramework::Initialize(MdaXmlElement* pXmlInput)
86 ManagedDebuggingAssistants* pMda = g_mdaStaticHeap.m_pMda;
87 g_bMdaDisableAsserts = pXmlInput->GetAttributeValueAsBool(MdaAttrDecl(DisableAsserts));
88 MdaXmlElement* pXmlDiagnostics = pXmlInput->GetChild(MdaElemDecl(Diagnostics));
92 m_dumpSchemaSchema = pXmlDiagnostics->GetAttributeValueAsBool(MdaAttrDecl(DumpSchemaSchema), FALSE);
93 m_dumpAssistantSchema = pXmlDiagnostics->GetAttributeValueAsBool(MdaAttrDecl(DumpAssistantSchema), FALSE);
94 m_dumpAssistantMsgSchema = pXmlDiagnostics->GetAttributeValueAsBool(MdaAttrDecl(DumpAssistantMsgSchema), FALSE);
100 // MdaGcUnmanagedToManaged
102 void MdaGcUnmanagedToManaged::TriggerGC()
106 TriggerGCForMDAInternal();
111 // MdaGcManagedToUnmanaged
113 void MdaGcManagedToUnmanaged::TriggerGC()
117 TriggerGCForMDAInternal();
120 void TriggerGCForMDAInternal()
132 GCHeapUtilities::GetGCHeap()->GarbageCollect();
135 // It is very dangerous to wait for finalizer thread here if we are inside a wait
136 // operation, as the wait operation might call into interop which calls this MDA
137 // and call into FinalizerThreadWait. In this case, we might run into infinite recursion:
138 // SynchronizationContext.Wait -> P/Invoke -> WaitForPendingFinalizer ->
139 // SynchronizationContext.Wait ....
141 // So, if we are inside a SyncContext.Wait, don't call out to FinalizerThreadWait
143 if (!GetThread()->HasThreadStateNC(Thread::TSNC_InsideSyncContextWait))
144 // It is possible that user code run as part of finalization will wait for this thread.
145 // To avoid deadlocks, we limit the wait time to 10 seconds (an arbitrary number).
146 FinalizerThread::FinalizerThreadWait(10 * 1000);
150 // Caller cannot take exceptions.
152 EX_END_CATCH(SwallowAllExceptions);
156 // MdaCallbackOnCollectedDelegate
159 MdaCallbackOnCollectedDelegate::~MdaCallbackOnCollectedDelegate()
163 if (m_pList && m_size)
165 for (int i=0; i < m_size; i++)
166 ReplaceEntry(i, NULL);
173 void MdaCallbackOnCollectedDelegate::ReportViolation(MethodDesc* pMD)
184 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
185 MdaXmlElement* pDelegate = pXml->AddChild(MdaElemDecl(Delegate));
186 StackSString delegateName;
190 AsMdaAssistant()->OutputMethodDesc(pMD, pDelegate);
191 AsMdaAssistant()->ToString(delegateName, pMD);
194 msg.SendMessagef(MDARC_CALLBACK_ON_COLLECTED_DELEGATE, delegateName.GetUnicode());
197 void MdaCallbackOnCollectedDelegate::AddToList(UMEntryThunk* pEntryThunk)
204 PRECONDITION(CheckPointer(pEntryThunk));
208 // Get an index to use.
209 ULONG oldIndex = m_iIndex;
210 ULONG newIndex = oldIndex + 1;
211 if (newIndex >= (ULONG)m_size)
214 while ((ULONG)FastInterlockCompareExchange((LONG*)&m_iIndex, newIndex, oldIndex) != oldIndex)
217 newIndex = oldIndex + 1;
218 if (newIndex >= (ULONG)m_size)
222 // We successfully incremented the index and can use the oldIndex value as our entry.
223 ReplaceEntry(oldIndex, pEntryThunk);
226 void MdaCallbackOnCollectedDelegate::ReplaceEntry(int index, UMEntryThunk* pET)
233 PRECONDITION((index >= 0) && (index < m_size));
234 PRECONDITION(CheckPointer(m_pList));
238 if ((m_pList) && (m_size > index) && (index >= 0))
240 UMEntryThunk* pETTemp = m_pList[index];
241 while (FastInterlockCompareExchangePointer((LPVOID*)&m_pList[index], (LPVOID)pET, (LPVOID)pETTemp) != (LPVOID)pETTemp)
243 pETTemp = m_pList[index];
248 pETTemp->Terminate();
253 #ifdef FEATURE_COMINTEROP
255 void MdaInvalidMemberDeclaration::ReportViolation(ComCallMethodDesc *pCMD, OBJECTREF *pExceptionObj)
268 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
271 StackSString strMemberName;
272 StackSString strTypeName;
273 StackSString strMessage;
275 GetExceptionMessage(*pExceptionObj, strMessage);
277 if (pCMD->IsFieldCall())
279 FieldDesc *pFD = pCMD->GetFieldDesc();
281 th = pFD->GetFieldTypeHandleThrowing();
282 strMemberName.SetUTF8(pFD->GetName());
283 AsMdaAssistant()->OutputFieldDesc(pFD, pXml->AddChild(MdaElemDecl(Field)));
287 MethodDesc *pMD = pCMD->GetCallMethodDesc();
289 th = TypeHandle(pMD->GetMethodTable());
290 strMemberName.SetUTF8(pMD->GetName());
291 AsMdaAssistant()->OutputMethodDesc(pMD, pXml->AddChild(MdaElemDecl(Method)));
294 th.GetName(strTypeName);
296 AsMdaAssistant()->OutputTypeHandle(th, pXml->AddChild(MdaElemDecl(Type)));
297 AsMdaAssistant()->OutputException(pExceptionObj, pXml->AddChild(MdaElemDecl(Exception)));
299 msg.SendMessagef(MDARC_INVALID_MEMBER_DECLARATION,
300 strMemberName.GetUnicode(), strTypeName.GetUnicode(), strMessage.GetUnicode());
304 // Caller cannot take exceptions.
306 EX_END_CATCH(SwallowAllExceptions);
309 #endif //FEATURE_COMINTEROP
313 // MdaExceptionSwallowedOnCallFromCom
315 void MdaExceptionSwallowedOnCallFromCom::ReportViolation(MethodDesc *pMD, OBJECTREF *pExceptionObj)
327 StackSString strMessage;
328 StackSString strTypeName;
329 StackSString strMemberName;
332 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
334 TypeHandle th = TypeHandle(pMD->GetMethodTable());
336 GetExceptionMessage(*pExceptionObj, strMessage);
337 th.GetName(strTypeName);
338 strMemberName.SetUTF8(pMD->GetName());
340 AsMdaAssistant()->OutputMethodDesc(pMD, pXml->AddChild(MdaElemDecl(Method)));
341 AsMdaAssistant()->OutputTypeHandle(th, pXml->AddChild(MdaElemDecl(Type)));
342 AsMdaAssistant()->OutputException(pExceptionObj, pXml->AddChild(MdaElemDecl(Exception)));
344 msg.SendMessagef(MDARC_EXCEPTION_SWALLOWED_COM_TO_CLR,
345 strMemberName.GetUnicode(), strTypeName.GetUnicode(), strMessage.GetUnicode());
349 // Caller cannot take exceptions.
351 EX_END_CATCH(SwallowAllExceptions);
358 void MdaInvalidVariant::ReportViolation()
369 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
371 msg.SendMessagef(MDARC_INVALID_VARIANT);
376 // MdaInvalidIUnknown
378 void MdaInvalidIUnknown::ReportViolation()
389 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
391 msg.SendMessagef(MDARC_INVALID_IUNKNOWN);
396 // MdaContextSwitchDeadlock
398 void MdaContextSwitchDeadlock::ReportDeadlock(LPVOID Origin, LPVOID Destination)
408 if (g_fEEShutDown == 0)
413 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
415 msg.SendMessagef(MDARC_CONTEXT_SWITCH_DEADLOCK, Origin, Destination);
419 // Caller cannot take exceptions.
421 EX_END_CATCH(SwallowAllExceptions);
427 // MdaRaceOnRCWCleanup
429 void MdaRaceOnRCWCleanup::ReportViolation()
440 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
442 msg.SendMessagef(MDARC_RCW_CLEANUP_RACE);
449 void MdaFailedQI::ReportAdditionalInfo(HRESULT hr, RCW* pRCW, GUID iid, MethodTable* pMT)
460 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
463 SafeComHolder<IUnknown> pInnerUnk = pRCW->GetIUnknown();
465 // We are interested in the case where the QI fails because of wrong context.
466 if (!pRCW->IsFreeThreaded() && GetCurrentCtxCookie() != pRCW->GetWrapperCtxCookie())
468 // Try to change context and perform the QI in the new context again.
469 MdaFailedQIAssistantCallbackData data;
471 data.pWrapper = pRCW;
474 pRCW->EnterContext(MdaFailedQIAssistantCallback, &data);
477 // QI succeeds in the other context, i.e. the original QI fails because of wrong context.
478 pXml = AsMdaAssistant()->OutputTypeHandle(th, pXml->AddChild(MdaElemDecl(Type)));
481 WCHAR strNativeItfIID[39];
482 StringFromGUID2(iid, strNativeItfIID, sizeof(strNativeItfIID) / sizeof(WCHAR));
484 // Map HRESULT to a message
485 StackSString sszHR2Description;
486 GetHRMsg(hr, sszHR2Description);
488 // Format the HRESULT as a string
489 StackSString sszHR2Hex;
490 sszHR2Hex.Printf("%.8x", hr);
492 StackSString sszTypeName;
493 th.GetName(sszTypeName);
495 msg.SendMessagef(MDARC_FAILED_QI, sszTypeName.GetUnicode(), strNativeItfIID, sszHR2Hex.GetUnicode(), sszHR2Description.GetUnicode());
498 else if (hr == E_NOINTERFACE)
501 // BUG: You'd have to check the registry to ensure that the proxy stub it's not actually there as opposed to the
502 // COM object QI simply returning a failure code.
505 // Check if pInnerUnk is actually pointing to a proxy, i.e. that it is pointing to an address
506 // within the loaded ole32.dll image. Note that WszGetModuleHandle does not increment the
508 HINSTANCE hModOle32 = WszGetModuleHandle(OLE32DLL);
509 if (hModOle32 && IsIPInModule(hModOle32, (BYTE *)(*(BYTE **)(IUnknown*)pInnerUnk)))
511 pXml = AsMdaAssistant()->OutputTypeHandle(th, pXml->AddChild(MdaElemDecl(Type)));
514 GuidToLPWSTR(iid, strGuid, 40);
515 msg.SendMessagef(MDARC_FAILED_QI, strGuid);
521 HRESULT MdaFailedQIAssistantCallback(LPVOID pData)
528 PRECONDITION(CheckPointer(pData));
534 BEGIN_EXTERNAL_ENTRYPOINT(&hr)
536 SafeComHolder<IUnknown> pDummyUnk;
538 MdaFailedQIAssistantCallbackData *pCallbackData = (MdaFailedQIAssistantCallbackData *)pData;
540 // Initialize the fSuccess flag to false until we know for a fact the QI will succeed.
541 pCallbackData->fSuccess = FALSE;
543 // QI for the requested interface.
544 hr = pCallbackData->pWrapper->SafeQueryInterfaceRemoteAware(pCallbackData->iid, &pDummyUnk);
546 // If the QI call succeded then set the fSuccess flag to true.
548 pCallbackData->fSuccess = TRUE;
550 END_EXTERNAL_ENTRYPOINT;
552 return S_OK; // Need to return S_OK so that the assert in CtxEntry::EnterContext() won't fire.
556 // MdaDisconnectedContext
558 void MdaDisconnectedContext::ReportViolationDisconnected(LPVOID context, HRESULT hr)
568 if (g_fEEShutDown == 0)
571 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
573 StackSString strHRMsg;
574 GetHRMsg(hr, strHRMsg);
576 msg.SendMessagef(MDARC_DISCONNECTED_CONTEXT_1, context, strHRMsg.GetUnicode());
580 void MdaDisconnectedContext::ReportViolationCleanup(LPVOID context1, LPVOID context2, HRESULT hr)
590 if (g_fEEShutDown == 0)
595 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
597 StackSString strHRMsg;
598 GetHRMsg(hr, strHRMsg);
600 msg.SendMessagef(MDARC_DISCONNECTED_CONTEXT_2, context1, strHRMsg.GetUnicode(), context2);
604 // Caller cannot take exceptions.
606 EX_END_CATCH(SwallowAllExceptions)
612 // MdaInvalidApartmentStateChange
614 void MdaInvalidApartmentStateChange::ReportViolation(Thread* pThread, Thread::ApartmentState newstate, BOOL fAlreadySet)
627 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
629 AsMdaAssistant()->OutputThread(pThread, pXml->AddChild(MdaElemDecl(Thread)));
633 if (newstate == Thread::AS_InSTA)
635 msg.SendMessagef(MDARC_INVALID_APT_STATE_CHANGE_SET, W("STA"), W("MTA"));
639 msg.SendMessagef(MDARC_INVALID_APT_STATE_CHANGE_SET, W("MTA"), W("STA"));
644 if (newstate == Thread::AS_InSTA)
646 msg.SendMessagef(MDARC_INVALID_APT_STATE_CHANGE_NOTSET, W("STA"), W("MTA"));
650 msg.SendMessagef(MDARC_INVALID_APT_STATE_CHANGE_NOTSET, W("MTA"), W("STA"));
656 // Caller cannot take exceptions.
658 EX_END_CATCH(SwallowAllExceptions);
662 // MdaDllMainReturnsFalse
664 void MdaDllMainReturnsFalse::ReportError()
675 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
677 msg.SendMessagef(MDARC_DLLMAIN_RETURNS_FALSE);
681 // MdaOverlappedFreeError
683 void MdaOverlappedFreeError::ReportError(LPVOID pOverlapped)
694 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
696 msg.SendMessagef(MDARC_INVALID_OVERLAPPED_FREE,
701 // MdaInvalidOverlappedToPinvoke
704 // NOTE: the overlapped pointer needs to be named "overlapped".
705 // It is embedded in the (Args) and (ArgsUsed) sections.
708 #define CREATE_WRAPPER_FUNCTION(DllName, Return, Flags, Name, Args, ArgsUsed) \
711 #include "invalidoverlappedwrappers.h"
713 #undef CREATE_WRAPPER_FUNCTION
715 #define CREATE_WRAPPER_FUNCTION(DllName, Return, Flags, Name, Args, ArgsUsed) \
716 Return Flags Mda_##Name Args \
725 Return (Flags *old##Name) Args; \
726 MdaInvalidOverlappedToPinvoke *pOverlapCheck = MDA_GET_ASSISTANT(InvalidOverlappedToPinvoke); \
727 _ASSERTE(pOverlapCheck); \
728 *(PVOID *)&(old##Name) = pOverlapCheck->CheckOverlappedPointer(DllName##_##Name, (LPVOID) overlapped); \
729 return old##Name ArgsUsed; \
731 #include "invalidoverlappedwrappers.h"
732 #undef CREATE_WRAPPER_FUNCTION
734 #define CREATE_WRAPPER_FUNCTION(DllName, Return, Flags, Name, Args, ArgsUsed) \
735 { L#DllName W(".DLL"), L#Name, Mda_##Name, NULL, NULL },
736 static MdaInvalidOverlappedToPinvoke::pinvoke_entry PInvokeTable[] = {
737 #include "invalidoverlappedwrappers.h"
739 #undef CREATE_WRAPPER_FUNCTION
741 void MdaInvalidOverlappedToPinvoke::Initialize(MdaXmlElement* pXmlInput)
751 m_entries = PInvokeTable;
752 m_entryCount = sizeof(PInvokeTable) / sizeof(pinvoke_entry);
753 m_bJustMyCode = pXmlInput->GetAttributeValueAsBool(MdaAttrDecl(JustMyCode));
756 BOOL MdaInvalidOverlappedToPinvoke::InitializeModuleFunctions(HINSTANCE hmod)
766 // For every entry where m_moduleName matches moduleName, fill in m_hmod with hmod
767 // and fill in the m_realFunction pointer.
769 BOOL bFoundSomething = FALSE;
771 SString moduleNameFullPath, moduleName;
772 ClrGetModuleFileNameNoThrow(hmod,moduleNameFullPath);
773 // Strip any path info
774 SString::CIterator iM = moduleNameFullPath.End();
775 if (moduleNameFullPath.FindBack(iM, W('\\')))
778 moduleName.Set(moduleNameFullPath, iM, moduleNameFullPath.End());
781 for (UINT i=0; i<m_entryCount; i++)
783 if (SString::_wcsicmp(m_entries[i].m_moduleName, moduleName.GetUnicode()) == 0)
785 if (m_entries[i].m_hmod == NULL)
787 SString moduleNameForLookup(m_entries[i].m_functionName);
788 StackScratchBuffer ansiVersion;
789 m_entries[i].m_realFunction = GetProcAddress(hmod, moduleNameForLookup.GetANSI(ansiVersion));
790 m_entries[i].m_hmod = hmod;
792 bFoundSomething = TRUE;
796 return bFoundSomething;
799 LPVOID MdaInvalidOverlappedToPinvoke::CheckOverlappedPointer(UINT index, LPVOID pOverlapped)
809 MdaInvalidOverlappedToPinvoke::pinvoke_entry *pEntry = m_entries + index;
811 // pEntry should always be non-NULL, because we got the address of pvMdaFunction
812 // from the entries table in the first place.
819 // Is the overlapped pointer in the gc heap?
820 if (pOverlapped != NULL)
826 IGCHeap *pHeap = GCHeapUtilities::GetGCHeap();
827 fHeapPointer = pHeap->IsHeapPointer(pOverlapped);
834 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
836 msg.SendMessagef(MDARC_INVALID_OVERLAPPED_TO_PINVOKE,
838 pEntry->m_functionName,
839 pEntry->m_moduleName);
843 return pEntry->m_realFunction;
846 // We want to hook the functions where it is in the user's code only, unless
847 // the attribute JustMyCode is set to false. In that case, we want all
849 BOOL MdaInvalidOverlappedToPinvoke::ShouldHook(MethodDesc *pMD)
851 LIMITED_METHOD_CONTRACT;
852 return (m_bJustMyCode ? IsJustMyCode(pMD) : TRUE);
855 LPVOID MdaInvalidOverlappedToPinvoke::Register(HINSTANCE hmod,LPVOID pvTarget)
865 // Quick lookup - do we have a matching target?
866 // walk our entries, looking for a match.
867 BOOL bNullModules = FALSE;
868 BOOL bSeenThisModule = FALSE;
870 for (UINT i=0; i<m_entryCount; i++)
872 MdaInvalidOverlappedToPinvoke::pinvoke_entry *pEntry = m_entries + i;
873 if (pvTarget == pEntry->m_realFunction)
875 return pEntry->m_mdaFunction;
878 bNullModules |= (pEntry->m_hmod == NULL);
879 bSeenThisModule |= (pEntry->m_hmod == hmod);
882 // if we have some NULL targets, do we have a matching hmod?
884 if (bNullModules && !bSeenThisModule)
886 if (InitializeModuleFunctions(hmod))
889 for (UINT i=0; i<m_entryCount; i++)
891 pinvoke_entry *pEntry = m_entries + i;
892 if (pvTarget == pEntry->m_realFunction)
894 return pEntry->m_mdaFunction;
906 BOOL MdaPInvokeLog::Filter(SString& sszDllName)
916 MdaXmlElement* pXmlFilter = m_pXmlInput->GetChild(MdaElemDecl(Filter));
921 for (COUNT_T i = 0; i < pXmlFilter->GetChildren().GetCount(); i ++)
923 if (pXmlFilter->GetChildren()[i]->GetAttribute(MdaAttrDecl(DllName))->GetValueAsCSString()->EqualsCaseInsensitive(sszDllName))
933 void MdaPInvokeLog::LogPInvoke(NDirectMethodDesc* pMD, HINSTANCE hMod)
945 StackSString sszEntryPoint;
946 sszEntryPoint.SetUTF8(pMD->GetEntrypointName());
948 PathString szDllFullName ;
949 WCHAR szDrive[_MAX_PATH] = {0};
950 WCHAR szPath[_MAX_PATH] = {0};
951 WCHAR szFileName[_MAX_PATH] = {0};
952 WCHAR szExt[_MAX_PATH] = {0};
953 WszGetModuleFileName(hMod, szDllFullName);
954 SplitPath(szDllFullName, szDrive, _MAX_PATH, szPath, _MAX_PATH, szFileName, _MAX_PATH, szExt, _MAX_PATH);
956 StackSString sszDllName;
957 sszDllName.Append(szFileName);
959 sszDllName.Append(szExt);
961 if (Filter(sszDllName))
964 MdaXmlMessage msg(this->AsMdaAssistant(), FALSE, &pXml);
966 MdaXmlElement* pMethod = pXml->AddChild(MdaElemDecl(Method));
967 AsMdaAssistant()->OutputMethodDesc(pMD, pMethod);
969 MdaXmlElement* pDllImport = pXml->AddChild(MdaElemDecl(DllImport));
970 pDllImport->AddAttributeSz(MdaAttrDecl(DllName), szDllFullName);
971 pDllImport->AddAttributeSz(MdaAttrDecl(EntryPoint), sszEntryPoint.GetUnicode());
978 // Caller cannot take exceptions.
980 EX_END_CATCH(SwallowAllExceptions);
986 // MdaPInvokeStackImbalance
988 void MdaPInvokeStackImbalance::CheckStack(StackImbalanceCookie *pSICookie, DWORD dwPostEsp)
998 DWORD dwEspAfterPushedArgs = pSICookie->m_dwSavedEsp;
999 DWORD dwEspBeforePushedArgs = dwEspAfterPushedArgs + pSICookie->m_dwStackArgSize;
1000 BOOL bStackImbalance = false;
1002 // Note: We use relaxed rules here depending on the NetFx40_PInvokeStackResilience compat switch in order to mimic 2.0 behavior.
1003 switch (pSICookie->m_callConv & pmCallConvMask)
1005 // Caller cleans stack
1006 case pmCallConvCdecl:
1007 if (dwPostEsp != dwEspAfterPushedArgs)
1009 if (dwPostEsp != dwEspBeforePushedArgs)
1011 bStackImbalance = true;
1015 // If NetFx40_PInvokeStackResilience is on, ignore the case where we see that the callee cleaned the stack.
1016 BOOL fPreV4Method = pSICookie->m_pMD->GetModule()->IsPreV4Assembly();
1017 if (!g_pConfig->PInvokeRestoreEsp(fPreV4Method))
1018 bStackImbalance = true;
1023 // Callee cleans stack
1024 case pmCallConvThiscall:
1025 case pmCallConvWinapi:
1026 case pmCallConvStdcall:
1027 if (dwPostEsp != dwEspBeforePushedArgs)
1029 if (dwPostEsp != dwEspAfterPushedArgs)
1031 bStackImbalance = true;
1035 // If NetFx40_PInvokeStackResilience is on, ignore the case where we see that the callee did not clean the stack
1036 BOOL fPreV4Method = pSICookie->m_pMD->GetModule()->IsPreV4Assembly();
1037 if (!g_pConfig->PInvokeRestoreEsp(fPreV4Method))
1038 bStackImbalance = true;
1043 // Unsupported calling convention
1044 case pmCallConvFastcall:
1046 _ASSERTE(!"Unsupported calling convention");
1050 if (!bStackImbalance)
1053 MdaXmlElement* pXml;
1054 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1055 MdaXmlElement* pMethod = pXml->AddChild(MdaElemDecl(Method));
1056 AsMdaAssistant()->OutputMethodDesc(pSICookie->m_pMD, pMethod);
1058 StackSString sszMethodName;
1059 msg.SendMessagef(MDARC_PINVOKE_SIGNATURE_MISMATCH, AsMdaAssistant()->ToString(sszMethodName, pSICookie->m_pMD).GetUnicode());
1065 // MdaJitCompilationStart
1067 void MdaJitCompilationStart::Initialize(MdaXmlElement* pXmlInput)
1077 m_bBreak = pXmlInput->GetAttributeValueAsBool(MdaAttrDecl(Break));
1078 MdaXmlElement* pXmlMethodFilter = pXmlInput->GetChild(MdaElemDecl(Methods));
1079 m_pMethodFilter = NULL;
1081 if (pXmlMethodFilter)
1083 m_pMethodFilter = new MdaQuery::CompiledQueries();
1084 MdaQuery::Compile(pXmlMethodFilter, m_pMethodFilter);
1088 void MdaJitCompilationStart::NowCompiling(MethodDesc* pMD)
1098 if (m_pMethodFilter && !m_pMethodFilter->Test(pMD))
1101 MdaXmlElement* pXml;
1102 MdaXmlMessage msg(this->AsMdaAssistant(), m_bBreak, &pXml);
1104 MdaXmlElement* pMethod = pXml->AddChild(MdaElemDecl(Method));
1105 AsMdaAssistant()->OutputMethodDesc(pMD, pMethod);
1111 // MdaLoadFromContext
1113 void MdaLoadFromContext::NowLoading(IAssembly** ppIAssembly, StackCrawlMark *pCallerStackMark)
1123 if (ppIAssembly && *ppIAssembly) {
1125 // Send an MDA if this assembly was loaded in the LoadFrom context
1126 if ((*ppIAssembly)->GetFusionLoadContext() == LOADCTX_TYPE_LOADFROM) {
1127 // Apply MDA filtering
1128 if (g_pDebugInterface && pCallerStackMark && ManagedDebuggingAssistants::IsManagedDebuggerAttached()) {
1129 MethodDesc *pMethodDesc = NULL;
1132 pMethodDesc = SystemDomain::GetCallersMethod(pCallerStackMark, NULL);
1134 if (pMethodDesc && !g_pDebugInterface->IsJMCMethod(pMethodDesc->GetModule(), pMethodDesc->GetMemberDef()))
1138 MdaXmlElement *pXml;
1139 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1141 MdaXmlElement *pXmlAssembly = pXml->AddChild(MdaElemDecl(AssemblyInfo));
1143 StackSString sszAssemblyName;
1144 StackSString sszCodeBase;
1145 SafeComHolder<IAssemblyName> pNameDef;
1147 if (FAILED((*ppIAssembly)->GetAssemblyNameDef(&pNameDef))) {
1151 if ((!FusionBind::GetAssemblyNameStringProperty(pNameDef, ASM_NAME_NAME, sszAssemblyName)) ||
1152 (!FusionBind::GetAssemblyNameStringProperty(pNameDef, ASM_NAME_CODEBASE_URL, sszCodeBase))) {
1156 pXmlAssembly->AddAttributeSz(MdaAttrDecl(DisplayName), sszAssemblyName.GetUnicode());
1157 pXmlAssembly->AddAttributeSz(MdaAttrDecl(CodeBase), sszCodeBase.GetUnicode());
1159 msg.SendMessagef(MDARC_LOAD_FROM_CONTEXT, sszAssemblyName.GetUnicode(), sszCodeBase.GetUnicode());
1164 const LPCWSTR ContextIdName[] =
1172 // MdaBindingFailure
1174 void MdaBindingFailure::BindFailed(AssemblySpec *pSpec, OBJECTREF *pExceptionObj)
1184 MdaXmlElement *pXml;
1185 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1187 MdaXmlElement *pXmlAssembly = pXml->AddChild(MdaElemDecl(AssemblyInfo));
1189 DWORD dwAppDomainId;
1190 SString sszAssemblyName;
1191 SString sszCodeBase;
1193 int iBindingContext;
1196 // determine AppDomain ID
1197 AppDomain *appDomain = pSpec->GetAppDomain();
1199 dwAppDomainId = appDomain->GetId().m_dwId;
1203 pXmlAssembly->AddAttributeInt(MdaAttrDecl(AppDomainId), dwAppDomainId);
1205 // determine Assembly display name
1206 LPCSTR assemblyName = pSpec->GetName();
1207 if (assemblyName && assemblyName[0]) {
1208 sszAssemblyName.SetASCII(assemblyName);
1210 pXmlAssembly->AddAttributeSz(MdaAttrDecl(DisplayName), sszAssemblyName.GetUnicode());
1212 // determine Assembly code base
1213 if (pSpec->GetCodeBase() && pSpec->GetCodeBase()[0]) {
1214 sszCodeBase.Set(pSpec->GetCodeBase());
1216 pXmlAssembly->AddAttributeSz(MdaAttrDecl(CodeBase), sszCodeBase.GetUnicode());
1218 // retrieve the exception message.
1219 GetExceptionMessage(*pExceptionObj, sszMessage);
1221 // determine failing HRESULT
1222 hr = GetExceptionHResult(*pExceptionObj);
1223 pXmlAssembly->AddAttributeInt(MdaAttrDecl(HResult), hr);
1225 // determine binding context Assembly would have been loaded in (based on parent)
1226 IAssembly* pParentAssembly = pSpec->GetParentIAssembly();
1227 if (pParentAssembly) {
1228 iBindingContext = pParentAssembly->GetFusionLoadContext();
1231 // if the parent hasn't been set but the code base has, it's in LoadFrom
1232 iBindingContext = LOADCTX_TYPE_LOADFROM;
1234 pXmlAssembly->AddAttributeInt(MdaAttrDecl(BindingContextId), iBindingContext);
1236 // Make sure the binding context ID isn't larger then our ID to name lookup table.
1237 _ASSERTE(iBindingContext < COUNTOF(ContextIdName));
1239 if (sszAssemblyName.IsEmpty())
1241 _ASSERTE(!sszCodeBase.IsEmpty());
1242 msg.SendMessagef(MDARC_BINDING_FAILURE_CODEBASE_ONLY, sszCodeBase.GetUnicode(),
1243 ContextIdName[iBindingContext], dwAppDomainId, sszMessage.GetUnicode());
1245 else if (sszCodeBase.IsEmpty())
1247 _ASSERTE(!sszAssemblyName.IsEmpty());
1248 msg.SendMessagef(MDARC_BINDING_FAILURE_DISPLAYNAME_ONLY, sszAssemblyName.GetUnicode(),
1249 ContextIdName[iBindingContext], dwAppDomainId, sszMessage.GetUnicode());
1253 msg.SendMessagef(MDARC_BINDING_FAILURE, sszAssemblyName.GetUnicode(), sszCodeBase.GetUnicode(),
1254 ContextIdName[iBindingContext], dwAppDomainId, sszMessage.GetUnicode());
1259 // MdaNotMarshalable
1261 void MdaNotMarshalable::ReportViolation()
1271 MdaXmlElement* pXml;
1272 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1274 msg.SendMessagef(MDARC_NOTMARSHALABLE);
1279 // MdaMarshalCleanupError
1281 void MdaMarshalCleanupError::ReportErrorThreadCulture(OBJECTREF *pExceptionObj)
1293 MdaXmlElement* pXml;
1294 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1296 // retrieve the exception message.
1298 GetExceptionMessage(*pExceptionObj, sszMessage);
1300 msg.SendMessagef(MDARC_MARSHALCLEANUPERROR_THREADCULTURE, sszMessage.GetUnicode());
1305 EX_END_CATCH(SwallowAllExceptions);
1308 void MdaMarshalCleanupError::ReportErrorSafeHandleProp(OBJECTREF *pExceptionObj)
1320 MdaXmlElement* pXml;
1321 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1323 // retrieve the exception message.
1325 GetExceptionMessage(*pExceptionObj, sszMessage);
1327 msg.SendMessagef(MDARC_MARSHALCLEANUPERROR_SAFEHANDLEPROP, sszMessage.GetUnicode());
1332 EX_END_CATCH(SwallowAllExceptions);
1335 void MdaMarshalCleanupError::ReportErrorCustomMarshalerCleanup(TypeHandle typeCustomMarshaler, OBJECTREF *pExceptionObj)
1348 MdaXmlElement* pXml;
1349 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1351 // retrieve the exception message.
1353 GetExceptionMessage(*pExceptionObj, sszMessage);
1355 // Retrieve the type name.
1356 StackSString sszType;
1357 typeCustomMarshaler.GetName(sszType);
1359 msg.SendMessagef(MDARC_MARSHALCLEANUPERROR_CUSTOMCLEANUP, sszType.GetUnicode(), sszMessage.GetUnicode());
1364 EX_END_CATCH(SwallowAllExceptions);
1370 void MdaLoaderLock::ReportViolation(HINSTANCE hInst)
1382 MdaXmlElement* pXml;
1383 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1389 cName = WszGetModuleFileName(hInst, szName);
1394 msg.SendMessagef(MDARC_LOADER_LOCK_DLL, szName);
1398 msg.SendMessagef(MDARC_LOADER_LOCK);
1403 // Caller cannot take exceptions.
1405 EX_END_CATCH(SwallowAllExceptions);
1412 void MdaReentrancy::ReportViolation()
1424 MdaXmlElement* pXml;
1425 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1427 msg.SendMessagef(MDARC_REENTRANCY);
1431 // Caller cannot take exceptions.
1433 EX_END_CATCH(SwallowAllExceptions);
1437 // MdaAsynchronousThreadAbort
1439 void MdaAsynchronousThreadAbort::ReportViolation(Thread *pCallingThread, Thread *pAbortedThread)
1451 MdaXmlElement* pXml;
1452 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1454 AsMdaAssistant()->OutputThread(pCallingThread, pXml->AddChild(MdaElemDecl(CallingThread)));
1455 AsMdaAssistant()->OutputThread(pAbortedThread, pXml->AddChild(MdaElemDecl(AbortedThread)));
1457 msg.SendMessagef(MDARC_ASYNCHRONOUS_THREADABORT, pCallingThread->GetOSThreadId(), pAbortedThread->GetOSThreadId());
1461 // Caller cannot take exceptions.
1463 EX_END_CATCH(SwallowAllExceptions);
1468 // MdaAsynchronousThreadAbort
1470 void MdaDangerousThreadingAPI::ReportViolation(__in_z WCHAR *apiName)
1480 MdaXmlElement* pXml;
1481 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1483 msg.SendMessagef(MDARC_DANGEROUS_THREADINGAPI, apiName);
1488 // MdaReportAvOnComRelease
1491 void MdaReportAvOnComRelease::ReportHandledException(RCW* pRCW)
1505 // TODO: comment this code...
1506 MdaXmlElement* pXml;
1507 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1511 LPVOID vtablePtr = pRCW->GetVTablePtr();
1512 msg.SendMessagef(MDARC_REPORT_AV_ON_COM_RELEASE_WITH_VTABLE, vtablePtr);
1516 msg.SendMessagef(MDARC_REPORT_AV_ON_COM_RELEASE);
1521 // Caller cannot take exceptions.
1523 EX_END_CATCH(SwallowAllExceptions);
1526 void MdaInvalidFunctionPointerInDelegate::ReportViolation(LPVOID pFunc)
1536 MdaXmlElement* pXml;
1537 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1539 msg.SendMessagef(MDARC_INVALID_FUNCTION_PTR_IN_DELEGATE, pFunc);
1543 // MdaDirtyCastAndCallOnInterface
1546 void MdaDirtyCastAndCallOnInterface::ReportViolation(IUnknown* pUnk)
1556 MdaXmlElement* pXml;
1557 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1559 msg.SendMessagef(MDARC_DIRTY_CAST_AND_CALL_ON_INTERFACE);
1563 // MdaFatalExecutionEngineError
1565 void MdaFatalExecutionEngineError::ReportFEEE(TADDR addrOfError, HRESULT hrError)
1577 MdaXmlElement* pXml;
1578 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1580 DWORD tid = GetCurrentThreadId();
1582 msg.SendMessagef(MDARC_FATAL_EXECUTION_ENGINE_ERROR, addrOfError, tid, hrError);
1586 // Caller cannot take exceptions.
1588 EX_END_CATCH(SwallowAllExceptions);
1593 // MdaInvalidCERCall
1595 void MdaInvalidCERCall::ReportViolation(MethodDesc* pCallerMD, MethodDesc *pCalleeMD, DWORD dwOffset)
1605 MdaXmlElement* pXml;
1606 MdaXmlMessage msg(this->AsMdaAssistant(), FALSE, &pXml);
1608 AsMdaAssistant()->OutputMethodDesc(pCalleeMD, pXml->AddChild(MdaElemDecl(Method)));
1609 AsMdaAssistant()->OutputCallsite(pCallerMD, dwOffset, pXml->AddChild(MdaElemDecl(Callsite)));
1611 StackSString sszCalleeMethodName(SString::Utf8, pCalleeMD->GetName());
1612 StackSString sszCallerMethodName(SString::Utf8, pCallerMD->GetName());
1613 msg.SendMessagef(MDARC_INVALID_CER_CALL, sszCallerMethodName.GetUnicode(), dwOffset, sszCalleeMethodName.GetUnicode());
1618 // MdaVirtualCERCall
1620 void MdaVirtualCERCall::ReportViolation(MethodDesc* pCallerMD, MethodDesc *pCalleeMD, DWORD dwOffset)
1630 MdaXmlElement* pXml;
1631 MdaXmlMessage msg(this->AsMdaAssistant(), FALSE, &pXml);
1633 AsMdaAssistant()->OutputMethodDesc(pCalleeMD, pXml->AddChild(MdaElemDecl(Method)));
1634 AsMdaAssistant()->OutputCallsite(pCallerMD, dwOffset, pXml->AddChild(MdaElemDecl(Callsite)));
1636 StackSString sszCalleeMethodName(SString::Utf8, pCalleeMD->GetName());
1637 StackSString sszCallerMethodName(SString::Utf8, pCallerMD->GetName());
1638 msg.SendMessagef(MDARC_VIRTUAL_CER_CALL, sszCallerMethodName.GetUnicode(), dwOffset, sszCalleeMethodName.GetUnicode());
1643 // MdaOpenGenericCERCall
1645 void MdaOpenGenericCERCall::ReportViolation(MethodDesc* pMD)
1655 MdaXmlElement* pXml;
1656 MdaXmlMessage msg(this->AsMdaAssistant(), FALSE, &pXml);
1658 AsMdaAssistant()->OutputMethodDesc(pMD, pXml->AddChild(MdaElemDecl(Method)));
1660 StackSString sszMethodName(SString::Utf8, pMD->GetName());
1661 msg.SendMessagef(MDARC_OPENGENERIC_CER_CALL, sszMethodName.GetUnicode());
1666 // MdaIllegalPrepareConstrainedRegion
1668 void MdaIllegalPrepareConstrainedRegion::ReportViolation(MethodDesc* pMD, DWORD dwOffset)
1678 MdaXmlElement* pXml;
1679 MdaXmlMessage msg(this->AsMdaAssistant(), FALSE, &pXml);
1681 AsMdaAssistant()->OutputCallsite(pMD, dwOffset, pXml->AddChild(MdaElemDecl(Callsite)));
1683 StackSString sszMethodName(SString::Utf8, pMD->GetName());
1684 msg.SendMessagef(MDARC_ILLEGAL_PCR, sszMethodName.GetUnicode(), dwOffset);
1689 // MdaReleaseHandleFailed
1691 void MdaReleaseHandleFailed::ReportViolation(TypeHandle th, LPVOID lpvHandle)
1701 MdaXmlElement* pXml;
1702 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1704 AsMdaAssistant()->OutputTypeHandle(th, pXml->AddChild(MdaElemDecl(Type)));
1706 StackSString sszHandle;
1707 sszHandle.Printf(W("0x%p"), lpvHandle);
1708 pXml->AddChild(MdaElemDecl(Handle))->AddAttributeSz(MdaAttrDecl(Value), sszHandle.GetUnicode());
1710 StackSString sszType;
1711 th.GetName(sszType);
1712 msg.SendMessagef(MDARC_SAFEHANDLE_CRITICAL_FAILURE, sszType.GetUnicode(), lpvHandle);
1716 #ifdef FEATURE_COMINTEROP
1718 // MdaReleaseHandleFailed
1720 void MdaNonComVisibleBaseClass::ReportViolation(MethodTable *pMT, BOOL fForIDispatch)
1730 MdaXmlElement* pXml;
1731 MdaXmlMessage msg(this->AsMdaAssistant(), TRUE, &pXml);
1733 TypeHandle thDerived = TypeHandle(pMT);
1734 TypeHandle thBase = thDerived.GetParent();
1736 while (IsTypeVisibleFromCom(thBase))
1737 thBase = thBase.GetParent();
1739 // If we get there, one of the parents must be non COM visible.
1740 _ASSERTE(!thBase.IsNull());
1742 AsMdaAssistant()->OutputTypeHandle(thDerived, pXml->AddChild(MdaElemDecl(DerivedType)));
1743 AsMdaAssistant()->OutputTypeHandle(thBase, pXml->AddChild(MdaElemDecl(BaseType)));
1745 SString strDerivedClassName;
1746 SString strBaseClassName;
1748 thDerived.GetName(strDerivedClassName);
1749 thBase.GetName(strBaseClassName);
1752 msg.SendMessagef(fForIDispatch ? MDARC_NON_COMVISIBLE_BASE_CLASS_IDISPATCH : MDARC_NON_COMVISIBLE_BASE_CLASS_CLASSITF,
1753 strDerivedClassName.GetUnicode(), strBaseClassName.GetUnicode());
1755 #endif //FEATURE_COMINTEROP
1760 // MdaXmlValidationError
1762 void MdaXmlValidationError::ReportError(MdaSchema::ValidationResult* pValidationResult)
1772 PRECONDITION(CheckPointer(pValidationResult->m_pViolatingElement));
1773 PRECONDITION(CheckPointer(pValidationResult->m_pViolatedElement));
1775 MdaXmlElement* pXml;
1776 MdaXmlMessage msg(this->AsMdaAssistant(), FALSE, &pXml);
1778 pXml->AddChild(MdaElemDecl(ViolatingXml))->AddChild(pValidationResult->m_pXmlRoot);
1779 pValidationResult->m_pSchema->ToXml(pXml->AddChild(MdaElemDecl(ViolatedXsd)));
1781 msg.SendMessage(W("The following XML does not match its schema."));
1787 // InvalidConfigFile
1789 void MdaInvalidConfigFile::ReportError(MdaElemDeclDef configFile)
1800 MdaXmlElement* pXml;
1801 MdaXmlMessage report(this->AsMdaAssistant(), TRUE, &pXml);
1803 LPCWSTR szConfigFile = MdaSchema::GetElementName(configFile);
1804 pXml->AddAttributeSz(MdaAttrDecl(ConfigFile), szConfigFile);
1806 report.SendMessagef(MDARC_INVALID_CONFIG_FILE, szConfigFile);
1810 #endif //MDA_SUPPORTED