diff --git a/main/OpenCover.FakesSupport/FakesDomainHelper.cs b/main/OpenCover.FakesSupport/FakesDomainHelper.cs deleted file mode 100644 index 4a43c8864..000000000 --- a/main/OpenCover.FakesSupport/FakesDomainHelper.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace OpenCover.FakesSupport -{ - public class FakesDomainHelper : IFakesDomainHelper - { - public void AddResolveEventHandler() - { - AppDomain.CurrentDomain.AssemblyResolve += - (sender, args) => args.Name.StartsWith("OpenCover.FakesSupport, Version=1.0.0.0") ? System.Reflection.Assembly.GetExecutingAssembly() : null; - } - } -} \ No newline at end of file diff --git a/main/OpenCover.Profiler/CodeCoverage.cpp b/main/OpenCover.Profiler/CodeCoverage.cpp index 289d5dd99..d20258c90 100644 --- a/main/OpenCover.Profiler/CodeCoverage.cpp +++ b/main/OpenCover.Profiler/CodeCoverage.cpp @@ -10,8 +10,6 @@ #include "NativeCallback.h" #include "dllmain.h" - - CCodeCoverage* CCodeCoverage::g_pProfiler = NULL; // CCodeCoverage @@ -100,10 +98,10 @@ HRESULT CCodeCoverage::OpenCoverInitialise(IUnknown *pICorProfilerInfoUnk){ return E_FAIL; } - FakesInitialize(pICorProfilerInfoUnk); + OpenCoverSupportInitialize(pICorProfilerInfoUnk); if (m_chainedProfiler == NULL){ - DWORD dwMask = AppendProfilerEventMask(0); + DWORD dwMask = AppendProfilerEventMask(0); COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo2->SetEventMask(dwMask), _T(" ::Initialize(...) => SetEventMask => 0x%X")); @@ -206,8 +204,6 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::ModuleAttachedToAssembly( if (m_chainedProfiler != NULL) m_chainedProfiler->ModuleAttachedToAssembly(moduleId, assemblyId); - FakesModulesAttachedToAssembly(moduleId, assemblyId); - std::wstring modulePath = GetModulePath(moduleId); std::wstring assemblyName = GetAssemblyName(assemblyId); /*ATLTRACE(_T("::ModuleAttachedToAssembly(...) => (%X => %s, %X => %s)"), @@ -232,7 +228,8 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::JITCompilationStarted( if (GetTokenAndModule(functionId, functionToken, moduleId, modulePath, &assemblyId)) { - FakesSupportCompilation(functionId, functionToken, moduleId, assemblyId, modulePath); + if (OpenCoverSupportRequired(assemblyId, functionId)) + OpenCoverSupportCompilation(functionId, functionToken, moduleId, assemblyId, modulePath); CuckooSupportCompilation(assemblyId, functionToken, moduleId); @@ -270,6 +267,7 @@ HRESULT STDMETHODCALLTYPE CCodeCoverage::JITCompilationStarted( CComPtr methodMalloc; COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo2->GetILFunctionBodyAllocator(moduleId, &methodMalloc), _T(" ::JITCompilationStarted(...) => GetILFunctionBodyAllocator=> 0x%X")); + IMAGE_COR_ILMETHOD* pNewMethod = (IMAGE_COR_ILMETHOD*)methodMalloc->Alloc(instumentedMethod.GetMethodSize()); instumentedMethod.WriteMethod(pNewMethod); COM_FAIL_MSG_RETURN_ERROR(m_profilerInfo2->SetILFunctionBody(moduleId, functionToken, (LPCBYTE)pNewMethod), diff --git a/main/OpenCover.Profiler/CodeCoverage.h b/main/OpenCover.Profiler/CodeCoverage.h index 268f51ee1..7954f2b6d 100644 --- a/main/OpenCover.Profiler/CodeCoverage.h +++ b/main/OpenCover.Profiler/CodeCoverage.h @@ -154,20 +154,25 @@ END_COM_MAP() ModuleID moduleId); private: - HRESULT FakesInitialize(IUnknown *pICorProfilerInfoUnk); - CComPtr m_chainedProfiler; - CComObject *m_infoHook; - HRESULT FakesModulesAttachedToAssembly(ModuleID moduleId, AssemblyID assemblyId); - mdMemberRef m_targetLoadOpenCoverProfilerInsteadRef; - mdMemberRef m_targetPretendWeLoadedFakesProfilerRef; - HRESULT GetFakesSupportRef(ModuleID moduleId, mdModuleRef &fakesSupportRef); - mdTypeRef m_objectTypeRef; - mdMethodDef m_pinvokeAttach; - mdMethodDef CreatePInvokeHook(IMetaDataEmit* pMetaDataEmit); - HRESULT FakesSupportCompilation(FunctionID functionId, mdToken functionToken, ModuleID moduleId, AssemblyID assemblyId, std::wstring &modulePath); + CComPtr m_chainedProfiler; + CComObject *m_infoHook; + + HRESULT OpenCoverSupportInitialize(IUnknown *pICorProfilerInfoUnk); + HRESULT GetOpenCoverSupportRef(ModuleID moduleId, mdModuleRef &supportRef); + mdMethodDef CreatePInvokeHook(ModuleID moduleId); + HRESULT OpenCoverSupportCompilation(FunctionID functionId, mdToken functionToken, ModuleID moduleId, AssemblyID assemblyId, std::wstring &modulePath); mdMethodDef Get_CurrentDomainMethod(ModuleID moduleID); HRESULT InstrumentMethodWith(ModuleID moduleId, mdToken functionToken, InstructionList &instructions); + bool OpenCoverSupportRequired(AssemblyID assemblyId, FunctionID functionId); + + mdMethodDef GetFakesHelperMethodRef(TCHAR* methodName, ModuleID moduleId); + void InstrumentTestPlatformUtilities(FunctionID functionId, mdToken functionToken, ModuleID moduleId, AssemblyID assemblyId); + void InstrumentTestPlatformTestExecutor(FunctionID functionId, mdToken functionToken, ModuleID moduleId, AssemblyID assemblyId); + + mdMethodDef GetUITestingHelperMethodRef(TCHAR* methodName, ModuleID moduleId); + void InstrumentTestToolsUITesting(FunctionID functionId, mdToken functionToken, ModuleID moduleId, AssemblyID assemblyId); + friend class CProfilerInfo; public: diff --git a/main/OpenCover.Profiler/CodeCoverage_Cuckoo.cpp b/main/OpenCover.Profiler/CodeCoverage_Cuckoo.cpp index 7498dab43..438eda007 100644 --- a/main/OpenCover.Profiler/CodeCoverage_Cuckoo.cpp +++ b/main/OpenCover.Profiler/CodeCoverage_Cuckoo.cpp @@ -213,7 +213,11 @@ HRESULT CCodeCoverage::CuckooSupportCompilation( mdToken functionToken, ModuleID moduleId) { - // add the bodies for our cuckoo methods when required + // early escape if token is not one we want + if ((m_cuckooCriticalToken != functionToken) && (m_cuckooSafeToken != functionToken)) + return S_OK; + + // check that we have the right module if (MSCORLIB_NAME == GetAssemblyName(assemblyId)) { if (m_cuckooCriticalToken == functionToken) diff --git a/main/OpenCover.Profiler/CodeCoverage_FakesSupport.cpp b/main/OpenCover.Profiler/CodeCoverage_FakesSupport.cpp deleted file mode 100644 index 6b3b8aec9..000000000 --- a/main/OpenCover.Profiler/CodeCoverage_FakesSupport.cpp +++ /dev/null @@ -1,407 +0,0 @@ -#include "stdafx.h" -#include "CodeCoverage.h" - -#include "dllmain.h" - -#include "Method.h" -#include "ProfilerInfo.h" - -#define TESTPLATFORM_UTILITIES_ASSEMBLY L"Microsoft.VisualStudio.TestPlatform.Utilities" -#define DEFAULTTESTEXECUTOR_LAUNCHPROCESS L"Microsoft.VisualStudio.TestPlatform.Utilities.DefaultTestExecutorLauncher::LaunchProcess" -#define DEFAULTTESTEXECUTOR_CTOR L"Microsoft.VisualStudio.TestPlatform.Utilities.DefaultTestExecutorLauncher::.ctor" - -#define TESTPLATFORM_TESTEXECUTOR_CORE_ASSEMBLY L"Microsoft.VisualStudio.TestPlatform.TestExecutor.Core" -#define TESTEXECUTORMAIN_RUN L"Microsoft.VisualStudio.TestPlatform.TestExecutor.TestExecutorMain::Run" -#define TESTEXECUTORMAIN_CTOR L"Microsoft.VisualStudio.TestPlatform.TestExecutor.TestExecutorMain::.ctor" - -#import raw_interfaces_only -using namespace mscorlib; - -extern COpenCoverProfilerModule _AtlModule; - -namespace { - struct __declspec(uuid("2180EC45-CF11-456E-9A76-389A4521A4BE")) - IFakesDomainHelper : IUnknown - { - virtual HRESULT __stdcall AddResolveEventHandler() = 0; - }; -} - -LPSAFEARRAY GetInjectedDllAsSafeArray() -{ - HINSTANCE hInst = _AtlModule.m_hModule; - HRSRC hClrHookDllRes = FindResource(hInst, MAKEINTRESOURCE(IDR_FAKESSUPPORT), L"ASSEMBLY"); - ATLASSERT(hClrHookDllRes != NULL); - - HGLOBAL hClrHookDllHGlb = LoadResource(hInst, hClrHookDllRes); - ATLASSERT(hClrHookDllHGlb != NULL); - - DWORD dllMemorySize = SizeofResource(hInst, hClrHookDllRes); - - LPBYTE lpDllData = (LPBYTE)LockResource(hClrHookDllHGlb); - ATLASSERT(lpDllData != NULL); - - SAFEARRAYBOUND bound = { 0 }; - bound.cElements = dllMemorySize; - bound.lLbound = 0; - - LPBYTE lpArrayData; - LPSAFEARRAY lpAsmblyData = SafeArrayCreate(VT_UI1, 1, &bound); - ATLASSERT(lpAsmblyData != NULL); - - SafeArrayAccessData(lpAsmblyData, (void**)&lpArrayData); - memcpy(lpArrayData, lpDllData, dllMemorySize); - SafeArrayUnaccessData(lpAsmblyData); - - return lpAsmblyData; -} - -EXTERN_C HRESULT STDAPICALLTYPE LoadFakesSupportAssembly(IUnknown *pUnk) -{ - ATLTRACE(_T("****LoadInjectorAssembly - Start****")); - - CComPtr<_AppDomain> pAppDomain; - HRESULT hr = pUnk->QueryInterface(__uuidof(_AppDomain), (void**)&pAppDomain); - ATLASSERT(hr == S_OK); - LPSAFEARRAY lpAsmblyData = GetInjectedDllAsSafeArray(); - ATLASSERT(lpAsmblyData != NULL); - - CComPtr<_Assembly> pAssembly; - hr = pAppDomain->Load_3(lpAsmblyData, &pAssembly); - ATLASSERT(hr == S_OK); - - SafeArrayDestroy(lpAsmblyData); - - CComVariant variant; - hr = pAssembly->CreateInstance(W2BSTR(L"OpenCover.FakesSupport.FakesDomainHelper"), &variant); - ATLASSERT(hr == S_OK); - - CComPtr pFakesDomainHelper; - hr = variant.punkVal->QueryInterface(__uuidof(IFakesDomainHelper), (void**)&pFakesDomainHelper); - ATLASSERT(hr == S_OK); - - hr = pFakesDomainHelper->AddResolveEventHandler(); - ATLASSERT(hr == S_OK); - ATLTRACE(_T("****LoadInjectorAssembly - End****")); - - return S_OK; -} - -HRESULT CCodeCoverage::FakesInitialize( - /* [in] */ IUnknown *pICorProfilerInfoUnk) -{ - TCHAR ext[1024] = { 0 }; - ::GetEnvironmentVariable(_T("CHAIN_EXTERNAL_PROFILER"), ext, 1024); - if (ext[0] != 0) - { - ATLTRACE(_T("::FakesInitialize")); - - ATLTRACE(_T(" ::Initialize(...) => ext = %s"), ext); - - TCHAR loc[1024] = { 0 }; - ::GetEnvironmentVariable(_T("CHAIN_EXTERNAL_PROFILER_LOCATION"), loc, 1024); - ATLTRACE(_T(" ::Initialize(...) => loc = %s"), loc); - - CLSID clsid; - HRESULT hr = CLSIDFromString(T2OLE(ext), &clsid); - ATLASSERT(hr == S_OK); - - HMODULE hmodule = LoadLibrary(loc); - ATLASSERT(hmodule != NULL); - - BOOL(WINAPI*DllGetClassObject)(REFCLSID, REFIID, LPVOID) = - (BOOL(WINAPI*)(REFCLSID, REFIID, LPVOID))GetProcAddress(hmodule, "DllGetClassObject"); - ATLASSERT(DllGetClassObject != NULL); - - CComPtr pClassFactory; - hr = DllGetClassObject(clsid, IID_IClassFactory, &pClassFactory); - ATLASSERT(hr == S_OK); - - - hr = pClassFactory->CreateInstance(NULL, __uuidof(ICorProfilerCallback4), (void**)&m_chainedProfiler); - ATLASSERT(hr == S_OK); - - HRESULT hr2 = CComObject::CreateInstance(&m_infoHook); - ULONG count = m_infoHook->AddRef(); - - m_infoHook->m_pProfilerHook = this; - - m_infoHook->SetProfilerInfo(pICorProfilerInfoUnk); - - hr = m_chainedProfiler->Initialize(m_infoHook); - - ATLTRACE(_T(" ::Initialize => fakes = 0x%X"), hr); - } - - return S_OK; -} - -HRESULT CCodeCoverage::GetFakesSupportRef(ModuleID moduleId, mdModuleRef &fakesSupportRef) -{ - // get interfaces - CComPtr metaDataEmit; - HRESULT hr = m_profilerInfo->GetModuleMetaData(moduleId, - ofRead | ofWrite, IID_IMetaDataEmit2, (IUnknown**)&metaDataEmit); - ATLASSERT(hr == S_OK); - - CComPtr metaDataAssemblyEmit; - hr = metaDataEmit->QueryInterface( - IID_IMetaDataAssemblyEmit, (void**)&metaDataAssemblyEmit); - ATLASSERT(hr == S_OK); - - // find injected - ASSEMBLYMETADATA assembly; - ZeroMemory(&assembly, sizeof(assembly)); - assembly.usMajorVersion = 1; - assembly.usMinorVersion = 0; - assembly.usBuildNumber = 0; - assembly.usRevisionNumber = 0; - const BYTE pubToken[] = { 0xe1, 0x91, 0x8c, 0xac, 0x69, 0xeb, 0x73, 0xf4 }; - hr = metaDataAssemblyEmit->DefineAssemblyRef(pubToken, - sizeof(pubToken), L"OpenCover.FakesSupport", &assembly, NULL, 0, 0, - &fakesSupportRef); - ATLASSERT(hr == S_OK); - return hr; -} - -HRESULT CCodeCoverage::FakesModulesAttachedToAssembly( - /* [in] */ ModuleID moduleId, - /* [in] */ AssemblyID assemblyId) -{ - - std::wstring assemblyName = GetAssemblyName(assemblyId); - - if (TESTPLATFORM_UTILITIES_ASSEMBLY == GetAssemblyName(assemblyId)) - { - std::wstring modulePath = GetModulePath(moduleId); - ATLTRACE(_T("::ModuleAttachedToAssembly(...) => (%X => %s, %X => %s)"), - moduleId, W2CT(modulePath.c_str()), - assemblyId, W2CT(assemblyName.c_str())); - - m_targetLoadOpenCoverProfilerInsteadRef = 0; - // get reference to injected - mdModuleRef injectedRef; - HRESULT hr = GetFakesSupportRef(moduleId, injectedRef); - ATLASSERT(hr == S_OK); - - // get interfaces - CComPtr metaDataEmit; - hr = m_profilerInfo->GetModuleMetaData(moduleId, - ofRead | ofWrite, IID_IMetaDataEmit, (IUnknown**)&metaDataEmit); - ATLASSERT(hr == S_OK); - - static COR_SIGNATURE methodCallSignature[] = - { - IMAGE_CEE_CS_CALLCONV_DEFAULT, - 0x01, - ELEMENT_TYPE_VOID, - ELEMENT_TYPE_OBJECT - }; - - // get method to call - mdTypeRef classTypeRef; - hr = metaDataEmit->DefineTypeRefByName(injectedRef, - L"OpenCover.FakesSupport.FakesHelper", &classTypeRef); - ATLASSERT(hr == S_OK); - - hr = metaDataEmit->DefineMemberRef(classTypeRef, - L"LoadOpenCoverProfilerInstead", methodCallSignature, - sizeof(methodCallSignature), &m_targetLoadOpenCoverProfilerInsteadRef); - ATLASSERT(hr == S_OK); - - // get object ref - mdModuleRef mscorlibRef; - hr = GetModuleRef(moduleId, MSCORLIB_NAME, mscorlibRef); - ATLASSERT(hr == S_OK); - - hr = metaDataEmit->DefineTypeRefByName(mscorlibRef, - L"System.Object", &m_objectTypeRef); - ATLASSERT(hr == S_OK); - - m_pinvokeAttach = CreatePInvokeHook(metaDataEmit); - } - - if (TESTPLATFORM_TESTEXECUTOR_CORE_ASSEMBLY == GetAssemblyName(assemblyId)) - { - std::wstring modulePath = GetModulePath(moduleId); - ATLTRACE(_T("::ModuleAttachedToAssembly(...) => (%X => %s, %X => %s)"), - moduleId, W2CT(modulePath.c_str()), - assemblyId, W2CT(assemblyName.c_str())); - - m_targetPretendWeLoadedFakesProfilerRef = 0; - // get reference to injected - mdModuleRef injectedRef; - HRESULT hr = GetFakesSupportRef(moduleId, injectedRef); - ATLASSERT(hr == S_OK); - - // get interfaces - CComPtr metaDataEmit; - hr = m_profilerInfo->GetModuleMetaData(moduleId, - ofRead | ofWrite, IID_IMetaDataEmit, (IUnknown**)&metaDataEmit); - ATLASSERT(hr == S_OK); - - static COR_SIGNATURE methodCallSignature[] = - { - IMAGE_CEE_CS_CALLCONV_DEFAULT, - 0x01, - ELEMENT_TYPE_VOID, - ELEMENT_TYPE_OBJECT - }; - - // get method to call - mdTypeRef classTypeRef; - hr = metaDataEmit->DefineTypeRefByName(injectedRef, - L"OpenCover.FakesSupport.FakesHelper", &classTypeRef); - ATLASSERT(hr == S_OK); - - hr = metaDataEmit->DefineMemberRef(classTypeRef, - L"PretendWeLoadedFakesProfiler", methodCallSignature, - sizeof(methodCallSignature), &m_targetPretendWeLoadedFakesProfilerRef); - ATLASSERT(hr == S_OK); - - // get object ref - mdModuleRef mscorlibRef; - hr = GetModuleRef(moduleId, MSCORLIB_NAME, mscorlibRef); - ATLASSERT(hr == S_OK); - - hr = metaDataEmit->DefineTypeRefByName(mscorlibRef, - L"System.Object", &m_objectTypeRef); - ATLASSERT(hr == S_OK); - - m_pinvokeAttach = CreatePInvokeHook(metaDataEmit); - - } - - return S_OK; -} - -mdMethodDef CCodeCoverage::CreatePInvokeHook(IMetaDataEmit* pMetaDataEmit){ - - mdTypeDef tkInjClass; - - HRESULT hr = pMetaDataEmit->DefineTypeDef(L"__ClrProbeInjection_", tdAbstract | tdSealed, m_objectTypeRef, NULL, &tkInjClass); - ATLASSERT(hr == S_OK); - - static BYTE sg_sigPLoadInjectorAssembly[] = { - 0, // IMAGE_CEE_CS_CALLCONV_DEFAULT - 1, // argument count - ELEMENT_TYPE_VOID, // ret = ELEMENT_TYPE_VOID - ELEMENT_TYPE_OBJECT - }; - - mdModuleRef tkRefClrProbe; - hr = pMetaDataEmit->DefineModuleRef(L"OPENCOVER.PROFILER.DLL", &tkRefClrProbe); - ATLASSERT(hr == S_OK); - - mdMethodDef tkAttachDomain; - pMetaDataEmit->DefineMethod(tkInjClass, L"LoadFakesSupportAssembly", - mdStatic | mdPinvokeImpl, - sg_sigPLoadInjectorAssembly, sizeof(sg_sigPLoadInjectorAssembly), - 0, 0, &tkAttachDomain - ); - ATLASSERT(hr == S_OK); - - BYTE tiunk = NATIVE_TYPE_IUNKNOWN; - mdParamDef paramDef; - hr = pMetaDataEmit->DefinePinvokeMap(tkAttachDomain, 0, L"LoadFakesSupportAssembly", tkRefClrProbe); - ATLASSERT(hr == S_OK); - - hr = pMetaDataEmit->DefineParam(tkAttachDomain, 1, L"appDomain", - pdIn | pdHasFieldMarshal, 0, NULL, 0, ¶mDef); - ATLASSERT(hr == S_OK); - - hr = pMetaDataEmit->SetFieldMarshal(paramDef, &tiunk, 1); - ATLASSERT(hr == S_OK); - - return tkAttachDomain; -} - -HRESULT CCodeCoverage::FakesSupportCompilation(FunctionID functionId, mdToken functionToken, ModuleID moduleId, AssemblyID assemblyId, std::wstring &modulePath) -{ - if (TESTPLATFORM_UTILITIES_ASSEMBLY == GetAssemblyName(assemblyId)) - { - std::wstring typeMethodName = GetTypeAndMethodName(functionId); - - if (DEFAULTTESTEXECUTOR_CTOR == typeMethodName) - { - ATLTRACE(_T("::JITCompilationStarted(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); - - InstructionList instructions; - - mdMethodDef getCurrentDomain = Get_CurrentDomainMethod(moduleId); - instructions.push_back(new Instruction(CEE_CALL, getCurrentDomain)); - instructions.push_back(new Instruction(CEE_CALL, m_pinvokeAttach)); - - InstrumentMethodWith(moduleId, functionToken, instructions); - } - - if (DEFAULTTESTEXECUTOR_LAUNCHPROCESS == typeMethodName) - { - ATLTRACE(_T("::JITCompilationStarted(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); - - InstructionList instructions; - - instructions.push_back(new Instruction(CEE_LDARG_S, 4)); - instructions.push_back(new Instruction(CEE_CALL, m_targetLoadOpenCoverProfilerInsteadRef)); - - InstrumentMethodWith(moduleId, functionToken, instructions); - } - - return S_OK; - } - - if (TESTPLATFORM_TESTEXECUTOR_CORE_ASSEMBLY == GetAssemblyName(assemblyId)) - { - std::wstring typeMethodName = GetTypeAndMethodName(functionId); - - if (TESTEXECUTORMAIN_CTOR == typeMethodName) - { - ATLTRACE(_T("::JITCompilationStarted(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); - - InstructionList instructions; - - mdMethodDef getCurrentDomain = Get_CurrentDomainMethod(moduleId); - instructions.push_back(new Instruction(CEE_CALL, getCurrentDomain)); - instructions.push_back(new Instruction(CEE_CALL, m_pinvokeAttach)); - - InstrumentMethodWith(moduleId, functionToken, instructions); - } - - if (TESTEXECUTORMAIN_RUN == typeMethodName) - { - ATLTRACE(_T("::JITCompilationStarted(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); - - InstructionList instructions; // NOTE: this IL will be different for an instance method or if the local vars signature is different - - instructions.push_back(new Instruction(CEE_LDARG, 0)); - instructions.push_back(new Instruction(CEE_CALL, m_targetPretendWeLoadedFakesProfilerRef)); - - InstrumentMethodWith(moduleId, functionToken, instructions); - } - } -} - -mdMethodDef CCodeCoverage::Get_CurrentDomainMethod(ModuleID moduleID) -{ - CComPtr metaDataEmit; - COM_FAIL_MSG_RETURN_OTHER(m_profilerInfo->GetModuleMetaData(moduleID, ofWrite, IID_IMetaDataEmit, (IUnknown**)&metaDataEmit), 0, - _T(" ::Get_CurrentDomainMethod(ModuleID) => GetModuleMetaData => 0x%X")); - - mdModuleRef mscorlibRef; - HRESULT hr = GetModuleRef(moduleID, MSCORLIB_NAME, mscorlibRef); - ATLASSERT(hr == S_OK); - - mdMethodDef getCurrentDomain; - mdTypeDef tkAppDomain; - hr = metaDataEmit->DefineTypeRefByName(mscorlibRef, L"System.AppDomain", &tkAppDomain); - ATLASSERT(hr == S_OK); - - BYTE importSig[] = { IMAGE_CEE_CS_CALLCONV_DEFAULT, 0 /*DefineMemberRef(tkAppDomain, L"get_CurrentDomain", importSig, 3 + l, &getCurrentDomain); - ATLASSERT(hr == S_OK); - return getCurrentDomain; -} - - - diff --git a/main/OpenCover.Profiler/CodeCoverage_Support.cpp b/main/OpenCover.Profiler/CodeCoverage_Support.cpp new file mode 100644 index 000000000..10abe8cd2 --- /dev/null +++ b/main/OpenCover.Profiler/CodeCoverage_Support.cpp @@ -0,0 +1,463 @@ +#include "stdafx.h" +#include "CodeCoverage.h" + +#include "dllmain.h" + +#include "Method.h" +#include "ProfilerInfo.h" + +#define TESTPLATFORM_UTILITIES_ASSEMBLY L"Microsoft.VisualStudio.TestPlatform.Utilities" +#define DEFAULTTESTEXECUTOR_LAUNCHPROCESS L"Microsoft.VisualStudio.TestPlatform.Utilities.DefaultTestExecutorLauncher::LaunchProcess" +#define DEFAULTTESTEXECUTOR_CTOR L"Microsoft.VisualStudio.TestPlatform.Utilities.DefaultTestExecutorLauncher::.ctor" + +#define TESTPLATFORM_TESTEXECUTOR_CORE_ASSEMBLY L"Microsoft.VisualStudio.TestPlatform.TestExecutor.Core" +#define TESTEXECUTORMAIN_RUN L"Microsoft.VisualStudio.TestPlatform.TestExecutor.TestExecutorMain::Run" +#define TESTEXECUTORMAIN_CTOR L"Microsoft.VisualStudio.TestPlatform.TestExecutor.TestExecutorMain::.ctor" + +#define TESTTOOLS_UITESTING_ASSEMBLY L"Microsoft.VisualStudio.TestTools.UITesting" +#define APPLICATIONUNDERTEST_START L"Microsoft.VisualStudio.TestTools.UITesting.ApplicationUnderTest::Start" +#define APPLICATIONUNDERTEST_CCTOR L"Microsoft.VisualStudio.TestTools.UITesting.ApplicationUnderTest::.cctor" + +#import raw_interfaces_only +using namespace mscorlib; + +extern COpenCoverProfilerModule _AtlModule; + +namespace { + struct __declspec(uuid("2180EC45-CF11-456E-9A76-389A4521A4BE")) + IDomainHelper : IUnknown + { + virtual HRESULT __stdcall AddResolveEventHandler() = 0; + }; +} + +LPSAFEARRAY GetInjectedDllAsSafeArray() +{ + HINSTANCE hInst = _AtlModule.m_hModule; + HRSRC hClrHookDllRes = FindResource(hInst, MAKEINTRESOURCE(IDR_SUPPORT), L"ASSEMBLY"); + ATLASSERT(hClrHookDllRes != NULL); + + HGLOBAL hClrHookDllHGlb = LoadResource(hInst, hClrHookDllRes); + ATLASSERT(hClrHookDllHGlb != NULL); + + DWORD dllMemorySize = SizeofResource(hInst, hClrHookDllRes); + + LPBYTE lpDllData = (LPBYTE)LockResource(hClrHookDllHGlb); + ATLASSERT(lpDllData != NULL); + + SAFEARRAYBOUND bound = { 0 }; + bound.cElements = dllMemorySize; + bound.lLbound = 0; + + LPBYTE lpArrayData; + LPSAFEARRAY lpAsmblyData = SafeArrayCreate(VT_UI1, 1, &bound); + ATLASSERT(lpAsmblyData != NULL); + + SafeArrayAccessData(lpAsmblyData, (void**)&lpArrayData); + memcpy(lpArrayData, lpDllData, dllMemorySize); + SafeArrayUnaccessData(lpAsmblyData); + + return lpAsmblyData; +} + +EXTERN_C HRESULT STDAPICALLTYPE LoadOpenCoverSupportAssembly(IUnknown *pUnk) +{ + ATLTRACE(_T("****LoadInjectorAssembly - Start****")); + + CComPtr<_AppDomain> pAppDomain; + HRESULT hr = pUnk->QueryInterface(__uuidof(_AppDomain), (void**)&pAppDomain); + ATLASSERT(hr == S_OK); + LPSAFEARRAY lpAsmblyData = GetInjectedDllAsSafeArray(); + ATLASSERT(lpAsmblyData != NULL); + + CComPtr<_Assembly> pAssembly; + hr = pAppDomain->Load_3(lpAsmblyData, &pAssembly); + ATLASSERT(hr == S_OK); + + SafeArrayDestroy(lpAsmblyData); + + CComVariant variant; + hr = pAssembly->CreateInstance(W2BSTR(L"OpenCover.Support.DomainHelper"), &variant); + ATLASSERT(hr == S_OK); + + CComPtr pDomainHelper; + hr = variant.punkVal->QueryInterface(__uuidof(IDomainHelper), (void**)&pDomainHelper); + ATLASSERT(hr == S_OK); + + hr = pDomainHelper->AddResolveEventHandler(); + ATLASSERT(hr == S_OK); + ATLTRACE(_T("****LoadInjectorAssembly - End****")); + + return S_OK; +} + +HRESULT CCodeCoverage::OpenCoverSupportInitialize( + /* [in] */ IUnknown *pICorProfilerInfoUnk) +{ + TCHAR ext[1024] = { 0 }; + ::GetEnvironmentVariable(_T("CHAIN_EXTERNAL_PROFILER"), ext, 1024); + if (ext[0] != 0) + { + ATLTRACE(_T("::OpenCoverSupportInitialize")); + + ATLTRACE(_T(" ::Initialize(...) => ext = %s"), ext); + + TCHAR loc[1024] = { 0 }; + ::GetEnvironmentVariable(_T("CHAIN_EXTERNAL_PROFILER_LOCATION"), loc, 1024); + ATLTRACE(_T(" ::Initialize(...) => loc = %s"), loc); + + CLSID clsid; + HRESULT hr = CLSIDFromString(T2OLE(ext), &clsid); + ATLASSERT(hr == S_OK); + + HMODULE hmodule = LoadLibrary(loc); + ATLASSERT(hmodule != NULL); + + BOOL(WINAPI*DllGetClassObject)(REFCLSID, REFIID, LPVOID) = + (BOOL(WINAPI*)(REFCLSID, REFIID, LPVOID))GetProcAddress(hmodule, "DllGetClassObject"); + ATLASSERT(DllGetClassObject != NULL); + + CComPtr pClassFactory; + hr = DllGetClassObject(clsid, IID_IClassFactory, &pClassFactory); + ATLASSERT(hr == S_OK); + + + hr = pClassFactory->CreateInstance(NULL, __uuidof(ICorProfilerCallback4), (void**)&m_chainedProfiler); + ATLASSERT(hr == S_OK); + + HRESULT hr2 = CComObject::CreateInstance(&m_infoHook); + ULONG count = m_infoHook->AddRef(); + + m_infoHook->m_pProfilerHook = this; + + m_infoHook->SetProfilerInfo(pICorProfilerInfoUnk); + + hr = m_chainedProfiler->Initialize(m_infoHook); + + ATLTRACE(_T(" ::OpenCoverSupportInitialize => fakes = 0x%X"), hr); + } + + return S_OK; +} + +mdMethodDef CCodeCoverage::CreatePInvokeHook(ModuleID moduleId){ + + mdTypeDef tkInjClass; + + CComPtr metaDataEmit; + HRESULT hr = m_profilerInfo->GetModuleMetaData(moduleId, + ofRead | ofWrite, IID_IMetaDataEmit, (IUnknown**)&metaDataEmit); + ATLASSERT(hr == S_OK); + + mdModuleRef mscorlibRef; + hr = GetModuleRef(moduleId, MSCORLIB_NAME, mscorlibRef); + COM_FAIL_MSG_RETURN_ERROR(hr, _T(" ::CreatePInvokeHook(...) => GetModuleRef => 0x%X")); + + mdTypeRef objectTypeRef; + hr = metaDataEmit->DefineTypeRefByName(mscorlibRef, + L"System.Object", &objectTypeRef); + COM_FAIL_MSG_RETURN_ERROR(hr, _T(" ::CreatePInvokeHook(...) => DefineTypeRefByName => 0x%X")); + + hr = metaDataEmit->DefineTypeDef(L"__OpenCoverSupportInjection__", tdAbstract | tdSealed, objectTypeRef, NULL, &tkInjClass); + ATLASSERT(hr == S_OK); + + static BYTE sg_sigPLoadInjectorAssembly[] = { + 0, // IMAGE_CEE_CS_CALLCONV_DEFAULT + 1, // argument count + ELEMENT_TYPE_VOID, // ret = ELEMENT_TYPE_VOID + ELEMENT_TYPE_OBJECT + }; + + mdModuleRef tkRefClrProbe; + hr = metaDataEmit->DefineModuleRef(L"OPENCOVER.PROFILER.DLL", &tkRefClrProbe); + ATLASSERT(hr == S_OK); + + mdMethodDef tkAttachDomain; + metaDataEmit->DefineMethod(tkInjClass, L"LoadOpenCoverSupportAssembly", + mdStatic | mdPinvokeImpl, + sg_sigPLoadInjectorAssembly, sizeof(sg_sigPLoadInjectorAssembly), + 0, 0, &tkAttachDomain + ); + ATLASSERT(hr == S_OK); + + BYTE tiunk = NATIVE_TYPE_IUNKNOWN; + mdParamDef paramDef; + hr = metaDataEmit->DefinePinvokeMap(tkAttachDomain, 0, L"LoadOpenCoverSupportAssembly", tkRefClrProbe); + ATLASSERT(hr == S_OK); + + hr = metaDataEmit->DefineParam(tkAttachDomain, 1, L"appDomain", + pdIn | pdHasFieldMarshal, 0, NULL, 0, ¶mDef); + ATLASSERT(hr == S_OK); + + hr = metaDataEmit->SetFieldMarshal(paramDef, &tiunk, 1); + ATLASSERT(hr == S_OK); + + return tkAttachDomain; +} + +mdMethodDef CCodeCoverage::Get_CurrentDomainMethod(ModuleID moduleID) +{ + CComPtr metaDataEmit; + COM_FAIL_MSG_RETURN_OTHER(m_profilerInfo->GetModuleMetaData(moduleID, ofWrite, IID_IMetaDataEmit, (IUnknown**)&metaDataEmit), 0, + _T(" ::Get_CurrentDomainMethod(ModuleID) => GetModuleMetaData => 0x%X")); + + mdModuleRef mscorlibRef; + HRESULT hr = GetModuleRef(moduleID, MSCORLIB_NAME, mscorlibRef); + ATLASSERT(hr == S_OK); + + mdMethodDef getCurrentDomain; + mdTypeDef tkAppDomain; + hr = metaDataEmit->DefineTypeRefByName(mscorlibRef, L"System.AppDomain", &tkAppDomain); + ATLASSERT(hr == S_OK); + + BYTE importSig[] = { IMAGE_CEE_CS_CALLCONV_DEFAULT, 0 /*DefineMemberRef(tkAppDomain, L"get_CurrentDomain", importSig, 3 + l, &getCurrentDomain); + ATLASSERT(hr == S_OK); + return getCurrentDomain; +} + +HRESULT CCodeCoverage::GetOpenCoverSupportRef(ModuleID moduleId, mdModuleRef &supportRef) +{ + // get interfaces + CComPtr metaDataEmit; + HRESULT hr = m_profilerInfo->GetModuleMetaData(moduleId, + ofRead | ofWrite, IID_IMetaDataEmit2, (IUnknown**)&metaDataEmit); + ATLASSERT(hr == S_OK); + + CComPtr metaDataAssemblyEmit; + hr = metaDataEmit->QueryInterface( + IID_IMetaDataAssemblyEmit, (void**)&metaDataAssemblyEmit); + ATLASSERT(hr == S_OK); + + // find injected + ASSEMBLYMETADATA assembly; + ZeroMemory(&assembly, sizeof(assembly)); + assembly.usMajorVersion = 1; + assembly.usMinorVersion = 0; + assembly.usBuildNumber = 0; + assembly.usRevisionNumber = 0; + const BYTE pubToken[] = { 0xe1, 0x91, 0x8c, 0xac, 0x69, 0xeb, 0x73, 0xf4 }; + hr = metaDataAssemblyEmit->DefineAssemblyRef(pubToken, + sizeof(pubToken), L"OpenCover.Support", &assembly, NULL, 0, 0, + &supportRef); + ATLASSERT(hr == S_OK); + return hr; +} + +HRESULT CCodeCoverage::OpenCoverSupportCompilation(FunctionID functionId, mdToken functionToken, ModuleID moduleId, AssemblyID assemblyId, std::wstring &modulePath) +{ + InstrumentTestPlatformUtilities(functionId, functionToken, moduleId, assemblyId); + InstrumentTestPlatformTestExecutor(functionId, functionToken, moduleId, assemblyId); + InstrumentTestToolsUITesting(functionId, functionToken, moduleId, assemblyId); + + return S_OK; +} + +bool CCodeCoverage::OpenCoverSupportRequired(AssemblyID assemblyId, FunctionID functionId) +{ + std::wstring assemblyName = GetAssemblyName(assemblyId); + if ((TESTPLATFORM_UTILITIES_ASSEMBLY != assemblyName) && + (TESTPLATFORM_TESTEXECUTOR_CORE_ASSEMBLY != assemblyName) && + (TESTTOOLS_UITESTING_ASSEMBLY != assemblyName)) + return false; + + std::wstring typeMethodName = GetTypeAndMethodName(functionId); + if ((TESTPLATFORM_UTILITIES_ASSEMBLY == assemblyName) && + (DEFAULTTESTEXECUTOR_CTOR != typeMethodName) && + (DEFAULTTESTEXECUTOR_LAUNCHPROCESS != typeMethodName)) + return false; + + if ((TESTPLATFORM_TESTEXECUTOR_CORE_ASSEMBLY == assemblyName) && + (TESTEXECUTORMAIN_CTOR != typeMethodName) && + (TESTEXECUTORMAIN_RUN != typeMethodName)) + return false; + + if ((TESTTOOLS_UITESTING_ASSEMBLY == assemblyName) && + (APPLICATIONUNDERTEST_CCTOR != typeMethodName) && + (APPLICATIONUNDERTEST_START != typeMethodName)) + return false; + + return true; +} + +mdMethodDef CCodeCoverage::GetFakesHelperMethodRef(TCHAR* methodName, ModuleID moduleId){ + // get reference to injected + mdModuleRef injectedRef; + HRESULT hr = GetOpenCoverSupportRef(moduleId, injectedRef); + ATLASSERT(hr == S_OK); + + // get interfaces + CComPtr metaDataEmit; + hr = m_profilerInfo->GetModuleMetaData(moduleId, + ofRead | ofWrite, IID_IMetaDataEmit, (IUnknown**)&metaDataEmit); + ATLASSERT(hr == S_OK); + + static COR_SIGNATURE methodCallSignature[] = + { + IMAGE_CEE_CS_CALLCONV_DEFAULT, + 0x01, + ELEMENT_TYPE_VOID, + ELEMENT_TYPE_OBJECT + }; + + // get method to call + mdTypeRef classTypeRef; + hr = metaDataEmit->DefineTypeRefByName(injectedRef, + L"OpenCover.Support.Fakes.FakesHelper", &classTypeRef); + ATLASSERT(hr == S_OK); + + // L"LoadOpenCoverProfilerInstead" + mdMemberRef memberRef; + hr = metaDataEmit->DefineMemberRef(classTypeRef, + T2W(methodName), methodCallSignature, + sizeof(methodCallSignature), &memberRef); + ATLASSERT(hr == S_OK); + + return memberRef; +} + +mdMethodDef CCodeCoverage::GetUITestingHelperMethodRef(TCHAR* methodName, ModuleID moduleId){ + // get reference to injected + mdModuleRef injectedRef; + HRESULT hr = GetOpenCoverSupportRef(moduleId, injectedRef); + ATLASSERT(hr == S_OK); + + // get interfaces + CComPtr metaDataEmit; + hr = m_profilerInfo->GetModuleMetaData(moduleId, + ofRead | ofWrite, IID_IMetaDataEmit, (IUnknown**)&metaDataEmit); + ATLASSERT(hr == S_OK); + + static COR_SIGNATURE methodCallSignature[] = + { + IMAGE_CEE_CS_CALLCONV_DEFAULT, + 0x01, + ELEMENT_TYPE_VOID, + ELEMENT_TYPE_OBJECT + }; + + // get method to call + mdTypeRef classTypeRef; + hr = metaDataEmit->DefineTypeRefByName(injectedRef, + L"OpenCover.Support.UITesting.UITestingHelper", &classTypeRef); + ATLASSERT(hr == S_OK); + + mdMemberRef memberRef; + hr = metaDataEmit->DefineMemberRef(classTypeRef, + T2W(methodName), methodCallSignature, + sizeof(methodCallSignature), &memberRef); + ATLASSERT(hr == S_OK); + + return memberRef; +} + +void CCodeCoverage::InstrumentTestToolsUITesting(FunctionID functionId, mdToken functionToken, ModuleID moduleId, AssemblyID assemblyId) +{ + if (TESTTOOLS_UITESTING_ASSEMBLY == GetAssemblyName(assemblyId)) + { + std::wstring typeMethodName = GetTypeAndMethodName(functionId); + + if (APPLICATIONUNDERTEST_CCTOR == typeMethodName) + { + ATLTRACE(_T("::InstrumentTestToolsUITesting(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); + + mdMethodDef invokeAttach = CreatePInvokeHook(moduleId); + InstructionList instructions; + + mdMethodDef getCurrentDomain = Get_CurrentDomainMethod(moduleId); + instructions.push_back(new Instruction(CEE_CALL, getCurrentDomain)); + instructions.push_back(new Instruction(CEE_CALL, invokeAttach)); + + InstrumentMethodWith(moduleId, functionToken, instructions); + } + + if (APPLICATIONUNDERTEST_START == typeMethodName) + { + ATLTRACE(_T("::InstrumentTestToolsUITesting(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); + + mdMemberRef memberRef = GetUITestingHelperMethodRef(_T("PropagateRequiredEnvironmentVariables"), moduleId); + InstructionList instructions; + + instructions.push_back(new Instruction(CEE_LDARG, 1)); + instructions.push_back(new Instruction(CEE_CALL, memberRef)); + + InstrumentMethodWith(moduleId, functionToken, instructions); + } + } +} + +void CCodeCoverage::InstrumentTestPlatformUtilities(FunctionID functionId, mdToken functionToken, ModuleID moduleId, AssemblyID assemblyId) +{ + if (TESTPLATFORM_UTILITIES_ASSEMBLY == GetAssemblyName(assemblyId)) + { + std::wstring typeMethodName = GetTypeAndMethodName(functionId); + + if (DEFAULTTESTEXECUTOR_CTOR == typeMethodName) + { + ATLTRACE(_T("::InstrumentTestPlatformUtilities(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); + + mdMethodDef invokeAttach = CreatePInvokeHook(moduleId); + InstructionList instructions; + + mdMethodDef getCurrentDomain = Get_CurrentDomainMethod(moduleId); + instructions.push_back(new Instruction(CEE_CALL, getCurrentDomain)); + instructions.push_back(new Instruction(CEE_CALL, invokeAttach)); + + InstrumentMethodWith(moduleId, functionToken, instructions); + } + + if (DEFAULTTESTEXECUTOR_LAUNCHPROCESS == typeMethodName) + { + ATLTRACE(_T("::InstrumentTestPlatformUtilities(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); + + mdMemberRef memberRef = GetFakesHelperMethodRef(_T("LoadOpenCoverProfilerInstead"), moduleId); + InstructionList instructions; + + instructions.push_back(new Instruction(CEE_LDARG_S, 4)); + instructions.push_back(new Instruction(CEE_CALL, memberRef)); + + InstrumentMethodWith(moduleId, functionToken, instructions); + } + } +} + +void CCodeCoverage::InstrumentTestPlatformTestExecutor(FunctionID functionId, mdToken functionToken, ModuleID moduleId, AssemblyID assemblyId) +{ + if (TESTPLATFORM_TESTEXECUTOR_CORE_ASSEMBLY == GetAssemblyName(assemblyId)) + { + std::wstring typeMethodName = GetTypeAndMethodName(functionId); + + if (TESTEXECUTORMAIN_CTOR == typeMethodName) + { + ATLTRACE(_T("::InstrumentTestPlatformTestExecutor(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); + + mdMethodDef invokeAttach = CreatePInvokeHook(moduleId); + + InstructionList instructions; + + mdMethodDef getCurrentDomain = Get_CurrentDomainMethod(moduleId); + instructions.push_back(new Instruction(CEE_CALL, getCurrentDomain)); + instructions.push_back(new Instruction(CEE_CALL, invokeAttach)); + + InstrumentMethodWith(moduleId, functionToken, instructions); + } + + if (TESTEXECUTORMAIN_RUN == typeMethodName) + { + ATLTRACE(_T("::InstrumentTestPlatformTestExecutor(%X, ...) => %d, %X => %s"), functionId, functionToken, moduleId, W2CT(typeMethodName.c_str())); + + mdMemberRef memberRef = GetFakesHelperMethodRef(_T("PretendWeLoadedFakesProfiler"), moduleId); + InstructionList instructions; + + instructions.push_back(new Instruction(CEE_LDARG, 0)); + instructions.push_back(new Instruction(CEE_CALL, memberRef)); + + InstrumentMethodWith(moduleId, functionToken, instructions); + } + } +} + + + + diff --git a/main/OpenCover.Profiler/OpenCover.Profiler.def b/main/OpenCover.Profiler/OpenCover.Profiler.def index 4d4c144bd..bd72a2b6b 100644 --- a/main/OpenCover.Profiler/OpenCover.Profiler.def +++ b/main/OpenCover.Profiler/OpenCover.Profiler.def @@ -9,4 +9,4 @@ EXPORTS DllUnregisterServer PRIVATE DllInstall PRIVATE - LoadFakesSupportAssembly @10 + LoadOpenCoverSupportAssembly @10 diff --git a/main/OpenCover.Profiler/OpenCover.Profiler.rc b/main/OpenCover.Profiler/OpenCover.Profiler.rc index a3ae169bb..25ece99d5 100644 Binary files a/main/OpenCover.Profiler/OpenCover.Profiler.rc and b/main/OpenCover.Profiler/OpenCover.Profiler.rc differ diff --git a/main/OpenCover.Profiler/OpenCover.Profiler.vcxproj b/main/OpenCover.Profiler/OpenCover.Profiler.vcxproj index 4e6be3836..aae9a7147 100644 --- a/main/OpenCover.Profiler/OpenCover.Profiler.vcxproj +++ b/main/OpenCover.Profiler/OpenCover.Profiler.vcxproj @@ -245,8 +245,8 @@ - + false @@ -334,7 +334,7 @@ - + diff --git a/main/OpenCover.Profiler/OpenCover.Profiler.vcxproj.filters b/main/OpenCover.Profiler/OpenCover.Profiler.vcxproj.filters index 8cdc8a5d9..4eef43a2a 100644 --- a/main/OpenCover.Profiler/OpenCover.Profiler.vcxproj.filters +++ b/main/OpenCover.Profiler/OpenCover.Profiler.vcxproj.filters @@ -73,10 +73,10 @@ Source Files - + Source Files - + Source Files @@ -163,7 +163,7 @@ Resource Files - + diff --git a/main/OpenCover.Profiler/Resource.h b/main/OpenCover.Profiler/Resource.h index ae9113f57..251fd8209 100644 Binary files a/main/OpenCover.Profiler/Resource.h and b/main/OpenCover.Profiler/Resource.h differ diff --git a/main/OpenCover.Support/DomainHelper.cs b/main/OpenCover.Support/DomainHelper.cs new file mode 100644 index 000000000..2eb6c62aa --- /dev/null +++ b/main/OpenCover.Support/DomainHelper.cs @@ -0,0 +1,19 @@ +using System; +using System.Reflection; + +namespace OpenCover.Support +{ + public class DomainHelper : IDomainHelper + { + public void AddResolveEventHandler() + { + AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve; + AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; + } + + static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) + { + return args.Name.StartsWith("OpenCover.Support, Version=1.0.0.0") ? Assembly.GetExecutingAssembly() : null; + } + } +} \ No newline at end of file diff --git a/main/OpenCover.FakesSupport/FakesHelper.cs b/main/OpenCover.Support/Fakes/FakesHelper.cs similarity index 68% rename from main/OpenCover.FakesSupport/FakesHelper.cs rename to main/OpenCover.Support/Fakes/FakesHelper.cs index 5ca9438c1..bc8506f8b 100644 --- a/main/OpenCover.FakesSupport/FakesHelper.cs +++ b/main/OpenCover.Support/Fakes/FakesHelper.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Microsoft.Win32; -namespace OpenCover.FakesSupport +namespace OpenCover.Support.Fakes { public class FakesHelper { @@ -10,6 +10,7 @@ public class FakesHelper private const string CorProfiler = "COR_PROFILER"; private const string ChainExternalProfiler = "CHAIN_EXTERNAL_PROFILER"; private const string ChainExternalProfilerLocation = "CHAIN_EXTERNAL_PROFILER_LOCATION"; + private const string OpenCoverProfilerGuid = "{1542C21D-80C3-45E6-A56C-A9C1E4BEB7B8}"; public static void LoadOpenCoverProfilerInstead(object data) { @@ -20,6 +21,9 @@ public static void LoadOpenCoverProfilerInstead(object data) if (!dict.ContainsKey(CorEnableProfiling) || dict[CorEnableProfiling] != "1") return; + if (!dict.ContainsKey(CorProfiler) || dict[CorProfiler] == OpenCoverProfilerGuid) + return; + var currentProfiler = dict[CorProfiler]; var key = Registry.ClassesRoot.OpenSubKey(string.Format("CLSID\\{0}\\InprocServer32", currentProfiler)); if (key == null) @@ -29,21 +33,17 @@ public static void LoadOpenCoverProfilerInstead(object data) dict[ChainExternalProfilerLocation] = location; dict[ChainExternalProfiler] = currentProfiler; - dict[CorProfiler] = "{1542C21D-80C3-45E6-A56C-A9C1E4BEB7B8}"; + dict[CorProfiler] = OpenCoverProfilerGuid; } public static void PretendWeLoadedFakesProfiler(object data) { - //var args = data as string[]; - //foreach (var arg in args ?? new string[0]) - //{ - // Console.WriteLine(arg); - //} - var enabled = Environment.GetEnvironmentVariable(CorEnableProfiling); - if (enabled == "1") + var profiler = Environment.GetEnvironmentVariable(CorEnableProfiling) ?? string.Empty; + var external = Environment.GetEnvironmentVariable(ChainExternalProfiler); + if (enabled == "1" && !string.IsNullOrEmpty(external) && + !profiler.Equals(OpenCoverProfilerGuid, StringComparison.InvariantCultureIgnoreCase)) { - var external = Environment.GetEnvironmentVariable(ChainExternalProfiler); Environment.SetEnvironmentVariable(CorProfiler, external); } } diff --git a/main/OpenCover.FakesSupport/IFakesDomainHelper.cs b/main/OpenCover.Support/IDomainHelper.cs similarity index 77% rename from main/OpenCover.FakesSupport/IFakesDomainHelper.cs rename to main/OpenCover.Support/IDomainHelper.cs index c2c710e29..72983c9df 100644 --- a/main/OpenCover.FakesSupport/IFakesDomainHelper.cs +++ b/main/OpenCover.Support/IDomainHelper.cs @@ -1,11 +1,11 @@ using System.Runtime.InteropServices; -namespace OpenCover.FakesSupport +namespace OpenCover.Support { [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] [Guid("2180EC45-CF11-456E-9A76-389A4521A4BE")] [ComVisible(true)] - public interface IFakesDomainHelper + public interface IDomainHelper { [ComVisible(true)] void AddResolveEventHandler(); diff --git a/main/OpenCover.FakesSupport/OpenCover.FakesSupport.csproj b/main/OpenCover.Support/OpenCover.Support.csproj similarity index 85% rename from main/OpenCover.FakesSupport/OpenCover.FakesSupport.csproj rename to main/OpenCover.Support/OpenCover.Support.csproj index 2b2cdf81e..985a6cc11 100644 --- a/main/OpenCover.FakesSupport/OpenCover.FakesSupport.csproj +++ b/main/OpenCover.Support/OpenCover.Support.csproj @@ -7,8 +7,8 @@ {31B0FAA6-A63F-46FC-96EE-697235DA2BB0} Library Properties - OpenCover.FakesSupport - OpenCover.FakesSupport + OpenCover.Support + OpenCover.Support v4.0 512 @@ -34,7 +34,7 @@ true - OpenCover.FakesSupport.snk + OpenCover.Support.snk @@ -49,13 +49,14 @@ Properties\GlobalAssemblyInfo.cs - - - + + + + - + + \ No newline at end of file diff --git a/main/OpenCover.UITest/Properties/AssemblyInfo.cs b/main/OpenCover.UITest/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..4907084c8 --- /dev/null +++ b/main/OpenCover.UITest/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("OpenCover.UITest")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("OpenCover.UITest")] +[assembly: AssemblyCopyright("Copyright © 2015")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8a862535-25cd-4b54-9611-6c290ba8c23e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/main/OpenCover.sln b/main/OpenCover.sln index f011382b4..07be0e2b0 100644 --- a/main/OpenCover.sln +++ b/main/OpenCover.sln @@ -1,6 +1,8 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 2012 +# Visual Studio 2013 +VisualStudioVersion = 12.0.31101.0 +MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenCover.Profiler", "OpenCover.Profiler\OpenCover.Profiler.vcxproj", "{B2CE418E-A5C8-4C46-9513-771414B3CA4C}" ProjectSection(ProjectDependencies) = postProject {31B0FAA6-A63F-46FC-96EE-697235DA2BB0} = {31B0FAA6-A63F-46FC-96EE-697235DA2BB0} @@ -62,7 +64,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.Specs", "OpenCove EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.Extensions", "OpenCover.Extensions\OpenCover.Extensions.csproj", "{EE9B358A-335C-43E9-BC35-853807C5E776}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.FakesSupport", "OpenCover.FakesSupport\OpenCover.FakesSupport.csproj", "{31B0FAA6-A63F-46FC-96EE-697235DA2BB0}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.Support", "OpenCover.Support\OpenCover.Support.csproj", "{31B0FAA6-A63F-46FC-96EE-697235DA2BB0}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenCover.UITest", "OpenCover.UITest\OpenCover.UITest.csproj", "{E8513153-6298-411D-9BD9-0DB0CC708D34}" + ProjectSection(ProjectDependencies) = postProject + {27AD5F08-0625-4093-8782-F7936737FAB7} = {27AD5F08-0625-4093-8782-F7936737FAB7} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -171,6 +178,12 @@ Global {31B0FAA6-A63F-46FC-96EE-697235DA2BB0}.Release|x64.Build.0 = Release|Any CPU {31B0FAA6-A63F-46FC-96EE-697235DA2BB0}.Release|x86.ActiveCfg = Release|Any CPU {31B0FAA6-A63F-46FC-96EE-697235DA2BB0}.Release|x86.Build.0 = Release|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Debug|x64.ActiveCfg = Debug|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Debug|x64.Build.0 = Debug|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Debug|x86.ActiveCfg = Debug|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Debug|x86.Build.0 = Debug|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Release|x64.ActiveCfg = Release|Any CPU + {E8513153-6298-411D-9BD9-0DB0CC708D34}.Release|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/main/cmdline/uitest.opencover.cmd b/main/cmdline/uitest.opencover.cmd new file mode 100644 index 000000000..332541c8c --- /dev/null +++ b/main/cmdline/uitest.opencover.cmd @@ -0,0 +1 @@ +OpenCover.Console.exe -register:user -target:"C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow\vstest.console.exe" -targetargs:"OpenCover.UITest.dll" -filter:"+[Open*]* -[OpenCover.UIT*]*" -output:opencovertests.xml -mergebyhash