diff --git a/SeafoodInstrumentation/InstrumentationMethod.cpp b/SeafoodInstrumentation/InstrumentationMethod.cpp new file mode 100644 index 00000000..aea42eb5 --- /dev/null +++ b/SeafoodInstrumentation/InstrumentationMethod.cpp @@ -0,0 +1,667 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#include "stdafx.h" +#include "InstrumentationMethod.h" +#include +#include "ProfilerManagerHost.h" +#include "Util.h" +#include "ILDisassembler.h" + +using namespace vanguard::instrumentation::managed; + +static vector globalMethodCol; + +HRESULT CInstrumentationMethod::Initialize(_In_ IProfilerManager* pProfilerManager) +{ + m_pProfilerManager = pProfilerManager; + + CHandle hConfigThread; + hConfigThread.Attach(CreateThread(NULL, 0, InstrumentationMethodThreadProc, this, 0, NULL)); + + DWORD retVal = WaitForSingleObject(hConfigThread, 15000); + + if (m_bExceptionTrackingEnabled) + { + CComPtr pCorProfilerInfo; + pProfilerManager->GetCorProfilerInfo((IUnknown**)&pCorProfilerInfo); + pCorProfilerInfo->SetEventMask(COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_ENABLE_STACK_SNAPSHOT); + + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + } + + return S_OK; +} + +// The CLR doesn't initialize com before calling the profiler, and the profiler manager cannot do so itself +// as that would screw up the com state for the application's thread. Spin up a new thread to allow the instrumentation +// method to co create a free threaded version of msxml on a thread that it owns to avoid this. +DWORD WINAPI CInstrumentationMethod::InstrumentationMethodThreadProc( + _In_ LPVOID lpParameter +) +{ + CoInitialize(NULL); + + CInstrumentationMethod* pThis = (CInstrumentationMethod*)lpParameter; + CoUninitialize(); + + return S_OK; +} + +HRESULT CInstrumentationMethod::OnAppDomainCreated( + _In_ IAppDomainInfo *pAppDomainInfo) +{ + return S_OK; +} + +HRESULT CInstrumentationMethod::OnAppDomainShutdown( + _In_ IAppDomainInfo *pAppDomainInfo) +{ + return S_OK; +} + +HRESULT CInstrumentationMethod::OnAssemblyLoaded(_In_ IAssemblyInfo* pAssemblyInfo) +{ + return S_OK; +} + +HRESULT CInstrumentationMethod::OnAssemblyUnloaded(_In_ IAssemblyInfo* pAssemblyInfo) +{ + return S_OK; +} + +HRESULT CInstrumentationMethod::OnModuleLoaded(_In_ IModuleInfo* pModuleInfo) +{ + HRESULT hr = S_OK; + + CComBSTR bstrModuleName; + IfFailRet(pModuleInfo->GetModuleName(&bstrModuleName)); + + CComBSTR bstrModulePath; + IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); + + std::wstring path(bstrModulePath, SysStringLen(bstrModulePath)); + wstring pdbFile = path.substr(0, path.find_last_of(L'.')) + L".pdb"; + + FILE *file; + _wfopen_s(&file, pdbFile.c_str(), L"r"); + + if (file == NULL) + { + return S_OK; + } + else + { + fclose(file); + } + + if (m_hmod == NULL) + { + m_hmod = ::LoadLibrary(L"E:/xplat/CLRInstrumentationEngine/x64/Debug/BJSBReader.dll"); + } + + if (m_hmod != NULL) + { + ReadPdb pfnReadPdb = (ReadPdb)GetProcAddress(m_hmod, "ReadPdb"); + if (!pfnReadPdb) + { + auto error = ::GetLastError(); + FreeLibrary(m_hmod); + return HRESULT_FROM_WIN32(error); + } + + int methodCount = pfnReadPdb(pdbFile); + + const mdMethodDef baseToken = 0x06 << 24; + mdMethodDef methodDef = 1; + HRESULT methodInfoResult = S_OK; + vector methodInfoCollection; + + il_disassembler disassembler(pModuleInfo); + + while (methodCount) + { + IMethodInfo* methodInfo = NULL; + CComBSTR bstrMethodName; + + mdMethodDef token = baseToken | methodDef; + methodInfoResult = pModuleInfo->GetMethodInfoByToken(token, &methodInfo); + methodInfoCollection.push_back(methodInfo); + methodDef++; + methodCount--; + methodInfo->GetFullName(&bstrMethodName); + printf("Method Name: %S \n ", bstrMethodName); + + vanguard::instrumentation::managed::function* func = new vanguard::instrumentation::managed::function(); + func->set_token(token); + + disassembler.initialize_function(methodInfo, func); + disassembler.disassemble_function(); + + struct function_releaser + { + function_releaser(il_disassembler& d) : + _disassembler(d) + { + } + + ~function_releaser() { _disassembler.cleanup_function(); } + + private: + il_disassembler& _disassembler; + } releaser(disassembler); + + func->calculate_blocks(disassembler); + + if (func->get_block_count() > 0) + { + std::wstring methodNameStr(bstrMethodName, SysStringLen(bstrMethodName)); + globalMethodCol.push_back(methodNameStr); + + disassembler.instrument_function(); + } + } + + ModuleID modId; + pModuleInfo->GetModuleID(&modId); + + module_info* info = disassembler.get_module_info(); + info->set_block_count(disassembler.get_global_block_count()); + + _instrumented_modules.insert(make_pair(modId, info)); + + /*for each (IMethodInfo* methodInfo in methodInfoCollection) + { + IInstructionGraph* instructionsGraph; + HRESULT hr = methodInfo->GetInstructions(&instructionsGraph); + + if (hr == S_OK) + { + std::vector _il_instructions; + IInstruction* instruction = NULL; + + HRESULT instructionData = instructionsGraph->GetFirstInstruction(&instruction); + _il_instructions.push_back(instruction); + + while (instructionData == S_OK) + { + IInstruction* nextInstruction = NULL; + instructionData = instruction->GetNextInstruction(&nextInstruction); + + _il_instructions.push_back(nextInstruction); + instruction = nextInstruction; + } + } + }*/ + } + + return S_OK; +} + +HRESULT CInstrumentationMethod::OnModuleUnloaded(_In_ IModuleInfo* pModuleInfo) +{ + return S_OK; +} + +HRESULT CInstrumentationMethod::OnShutdown() +{ + if (m_bExceptionTrackingEnabled) + { + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + } + return S_OK; +} + +HRESULT CInstrumentationMethod::ShouldInstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit, _Out_ BOOL* pbInstrument) +{ + /*CComBSTR bstrMethodName; + pMethodInfo->GetFullName(&bstrMethodName); + + std::wstring methodNameStr(bstrMethodName, SysStringLen(bstrMethodName)); + + for (size_t i = 0; i < globalMethodCol.size(); i++) + { + if (methodNameStr.compare(globalMethodCol[i]) == 0) + { + *pbInstrument = TRUE; + break; + } + }*/ + + CComPtr pModuleInfo; + pMethodInfo->GetModuleInfo(&pModuleInfo); + + ModuleID modId; + pModuleInfo->GetModuleID(&modId); + + unordered_map::iterator it = _instrumented_modules.find(modId); + if (it != _instrumented_modules.end()) + { + mdToken token; + pMethodInfo->GetMethodToken(&token); + module_info *info = it->second; + *pbInstrument = info->contains_instrumented_method(token); + } + + return S_OK; +} + +HRESULT CInstrumentationMethod::InstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit) +{ + /* CComBSTR bstrMethodName; + pMethodInfo->GetFullName(&bstrMethodName); + + std::wstring methodNameStr(bstrMethodName, SysStringLen(bstrMethodName)); + + bool instrument = false; + + for (size_t i = 0; i < globalMethodCol.size(); i++) + { + if (methodNameStr.compare(globalMethodCol[i]) == 0) + { + instrument = true; + break; + } + } + + if (!instrument) + { + return S_OK; + } + + BYTE pSignature[256] = {}; + DWORD cbSignature = 0; + pMethodInfo->GetCorSignature(_countof(pSignature), pSignature, &cbSignature); + + if (cbSignature < 2) + return S_FALSE; + USHORT argsCount = pSignature[1];*/ + + CComPtr pModuleInfo; + pMethodInfo->GetModuleInfo(&pModuleInfo); + + ModuleID modId; + pModuleInfo->GetModuleID(&modId); + + module_info *instrumented_module = NULL; + + unordered_map::iterator it = _instrumented_modules.find(modId); + if (it != _instrumented_modules.end()) + { + mdToken token; + pMethodInfo->GetMethodToken(&token); + instrumented_module = it->second; + } + + mdMethodDef token; + pMethodInfo->GetMethodToken(&token); + + method_info info; + bool result = instrumented_module->get_method_info(token, info); + + if (!result) + { + return S_OK; + } + + auto block_indices = info.get_block_indexes(); + auto start_index = info.get_start_index(); + void const *coverage_buffer = instrumented_module->get_coverage_buffer(); + + auto index = reinterpret_cast<__int64>(coverage_buffer); + index = index + info.get_start_index(); + + CComPtr sptrInstructionGraph; + HRESULT hr = (pMethodInfo->GetInstructions(&sptrInstructionGraph)); + IfFailRet(hr); + + std::vector il_instructions; + CComPtr il_inst; + + hr = sptrInstructionGraph->GetFirstInstruction(&il_inst); + il_instructions.push_back(il_inst); + + while (hr == S_OK) + { + CComPtr nextInstruction; + hr = il_inst->GetNextInstruction(&nextInstruction); + + if (hr != S_OK) + { + break; + } + + il_instructions.push_back(nextInstruction); + il_inst = nextInstruction; + } + + CComPtr sptrInstructionFactory; + hr = (pMethodInfo->GetInstructionFactory(&sptrInstructionFactory)); + IfFailRet(hr); + + for (auto loc = block_indices.begin(); loc < block_indices.end(); ++loc) + { + CComPtr il_inst = il_instructions[*loc]; + + CComPtr operandInstr; + hr = (sptrInstructionFactory->CreateLongOperandInstruction(Cee_Ldc_I8, index, &operandInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBeforeAndRetargetOffsets(il_inst, operandInstr)); + IfFailRet(hr); + + CComPtr pushInstr; + hr = (sptrInstructionFactory->CreateInstruction(Cee_Ldc_I4_1, &pushInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBefore(il_inst, pushInstr)); + IfFailRet(hr); + + CComPtr commitInstr; + hr = (sptrInstructionFactory->CreateInstruction(Cee_Stind_I1, &commitInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBefore(il_inst, commitInstr)); + IfFailRet(hr); + + ++index; + } + + + /*CComPtr sptrCurrent; + hr = (sptrInstructionGraph->GetFirstInstruction(&sptrCurrent)); + IfFailRet(hr); + + CComPtr operandInstr; + hr = (sptrInstructionFactory->CreateLongOperandInstruction(Cee_Ldc_I8, index, &operandInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBeforeAndRetargetOffsets(sptrCurrent, operandInstr)); + IfFailRet(hr); + + CComPtr pushInstr; + hr = (sptrInstructionFactory->CreateInstruction(Cee_Ldc_I4_1, &pushInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBefore(sptrCurrent, pushInstr)); + IfFailRet(hr); + + CComPtr commitInstr; + hr = (sptrInstructionFactory->CreateInstruction(Cee_Stind_I1, &commitInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBefore(sptrCurrent, commitInstr)); + IfFailRet(hr);*/ + + return hr; +} + +HRESULT CInstrumentationMethod::AllowInlineSite(_In_ IMethodInfo* pMethodInfoInlinee, _In_ IMethodInfo* pMethodInfoCaller, _Out_ BOOL* pbAllowInline) +{ + *pbAllowInline = FALSE; + return S_OK; +} + + +HRESULT CInstrumentationMethod::ExceptionCatcherEnter( + _In_ IMethodInfo* pMethodInfo, + _In_ UINT_PTR objectId +) +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + CComBSTR bstrFullName; + pMethodInfo->GetFullName(&bstrFullName); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrFullName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionCatcherLeave() +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionSearchCatcherFound( + _In_ IMethodInfo* pMethodInfo +) +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + CComBSTR bstrFullName; + pMethodInfo->GetFullName(&bstrFullName); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrFullName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionSearchFilterEnter( + _In_ IMethodInfo* pMethodInfo +) +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + CComBSTR bstrFullName; + pMethodInfo->GetFullName(&bstrFullName); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrFullName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionSearchFilterLeave() +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionSearchFunctionEnter( + _In_ IMethodInfo* pMethodInfo +) +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + CComBSTR bstrFullName; + pMethodInfo->GetFullName(&bstrFullName); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrFullName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionSearchFunctionLeave() +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionThrown( + _In_ UINT_PTR thrownObjectId +) +{ + HRESULT hr = S_OK; + + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + CComPtr pCorProfilerInfo; + IfFailRet(m_pProfilerManager->GetCorProfilerInfo((IUnknown**)&pCorProfilerInfo)); + + CComPtr pCorProfilerInfo2; + pCorProfilerInfo->QueryInterface(__uuidof(ICorProfilerInfo2), (void**)&pCorProfilerInfo2); + + IfFailRet(pCorProfilerInfo2->DoStackSnapshot( + NULL, + StackSnapshotCallbackExceptionThrown, + COR_PRF_SNAPSHOT_DEFAULT, + this, + nullptr, + 0)); + + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +// static +HRESULT CInstrumentationMethod::StackSnapshotCallbackExceptionThrown( + _In_ FunctionID funcId, + _In_ UINT_PTR ip, + _In_ COR_PRF_FRAME_INFO frameInfo, + _In_ ULONG32 contextSize, + _In_reads_(contextSize) BYTE context[], + _In_ void *clientData +) +{ + HRESULT hr = S_OK; + CInstrumentationMethod* pThis = (CInstrumentationMethod*)clientData; + + IfFailRet(pThis->HandleStackSnapshotCallbackExceptionThrown( + funcId, + ip, + frameInfo, + contextSize, + context + )); + + return S_OK; +} + +HRESULT CInstrumentationMethod::HandleStackSnapshotCallbackExceptionThrown( + _In_ FunctionID funcId, + _In_ UINT_PTR ip, + _In_ COR_PRF_FRAME_INFO frameInfo, + _In_ ULONG32 contextSize, + _In_reads_(contextSize) BYTE context[] +) +{ + HRESULT hr = S_OK; + + if (funcId == 0) + { + // Can't do anything if there is no function id + return S_OK; + } + + CComPtr pAppDomainCollection; + IfFailRet(m_pProfilerManager->GetAppDomainCollection(&pAppDomainCollection)); + + CComPtr pMethodInfo; + IfFailRet(pAppDomainCollection->GetMethodInfoById(funcId, &pMethodInfo)); + + CComBSTR bstrMethodName; + IfFailRet(pMethodInfo->GetName(&bstrMethodName)); + + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrMethodName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + + // verify other code paths that don't contribute to actual baseline + // This is just to get coverage on althernative code paths to obtain method infos + CComPtr pModuleInfo; + IfFailRet(pMethodInfo->GetModuleInfo(&pModuleInfo)); + mdToken methodToken; + IfFailRet(pMethodInfo->GetMethodToken(&methodToken)); + + CComPtr pMethodInfo2; + IfFailRet(pModuleInfo->GetMethodInfoByToken(methodToken, &pMethodInfo2)); + + CComBSTR bstrMethodName2; + IfFailRet(pMethodInfo2->GetName(&bstrMethodName2)); + + if (bstrMethodName != bstrMethodName2) + { + pProfilerManagerHost->LogDumpMessage(_T("pModuleInfo->GetMethodInfoByToken did not return same method as pAppDomainCollection->GetMethodInfoById")); + return S_OK; + } + + CComPtr pInstructionGraph; + IfFailRet(pMethodInfo2->GetInstructions(&pInstructionGraph)); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionUnwindFinallyEnter( + _In_ IMethodInfo* pMethodInfo +) +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + CComBSTR bstrFullName; + pMethodInfo->GetFullName(&bstrFullName); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrFullName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionUnwindFinallyLeave() +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionUnwindFunctionEnter( + _In_ IMethodInfo* pMethodInfo +) +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + CComBSTR bstrFullName; + pMethodInfo->GetFullName(&bstrFullName); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("")); + pProfilerManagerHost->LogDumpMessage(bstrFullName); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} + +HRESULT CInstrumentationMethod::ExceptionUnwindFunctionLeave() +{ + CProfilerManagerHost* pProfilerManagerHost = CProfilerManagerHost::GetInstance(); + + pProfilerManagerHost->LogDumpMessage(_T(" ")); + pProfilerManagerHost->LogDumpMessage(_T("\r\n")); + + return S_OK; +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c197e8fe..ce42164f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -118,14 +118,10 @@ macro (build_init build_language build_type) # add_definitions(-D_DEBUG) TODO: Enable this endif () - if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) - message("Detected Linux x86_64") - add_definitions(-DLINUX64) - add_definitions(-D_M_AMD64) - add_definitions(-DTARGET_AMD64) - else (CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) - message(FATAL_ERROR "error: Detected non x86_64 target processor. Not supported!") - endif(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) + message("Detected Linux x86_64") + add_definitions(-DLINUX64) + add_definitions(-D_M_AMD64) + add_definitions(-DTARGET_AMD64) # Ignored warnings # TODO: Reenable these @@ -242,9 +238,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL Linux) endif(CMAKE_SYSTEM_NAME STREQUAL Linux) # Set flag to indicate if this will be a 64bit Linux build -if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) - set(IS_64BIT_BUILD 1) -endif (CMAKE_SYSTEM_PROCESSOR STREQUAL x86_64) +set(IS_64BIT_BUILD 1) # Ensure that on MacOS, dylibs are referenced as '@rpath/example.dylib' instead of just 'example.dylib'. Otherwise they # will not be found unless the working directory == vsdbg directory. @@ -342,4 +336,5 @@ add_subdirectory(unix/src/atl) add_subdirectory(InstrumentationEngine.Api) add_subdirectory(InstrumentationEngine.Lib) add_subdirectory(InstrumentationEngine) +add_subdirectory(LinuxProfiler) diff --git a/src/LinuxProfiler/CComPtr.h b/src/LinuxProfiler/CComPtr.h new file mode 100644 index 00000000..e5a4fa89 --- /dev/null +++ b/src/LinuxProfiler/CComPtr.h @@ -0,0 +1,81 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#pragma once + +template +class CComPtr +{ +private: + TInterface* pointer; +public: + CComPtr(const CComPtr&) = delete; // Copy constructor + CComPtr& operator= (const CComPtr&) = delete; // Copy assignment + CComPtr(CComPtr&&) = delete; // Move constructor + CComPtr& operator= (CComPtr&&) = delete; // Move assignment + + void* operator new(std::size_t) = delete; + void* operator new[](std::size_t) = delete; + + void operator delete(void *ptr) = delete; + void operator delete[](void *ptr) = delete; + + CComPtr() + { + this->pointer = nullptr; + } + + ~CComPtr() + { + if (this->pointer) + { + this->pointer->Release(); + this->pointer = nullptr; + } + } + + operator TInterface*() + { + return this->pointer; + } + + operator TInterface*() const + { + return this->pointer; + } + + TInterface& operator *() + { + return *this->pointer; + } + + TInterface& operator *() const + { + return *this->pointer; + } + + TInterface** operator&() + { + return &this->pointer; + } + + TInterface** operator&() const + { + return &this->pointer; + } + + TInterface* operator->() + { + return this->pointer; + } + + TInterface* operator->() const + { + return this->pointer; + } + + void Release() + { + this->~CComPtr(); + } +}; \ No newline at end of file diff --git a/src/LinuxProfiler/CExtensionsHost.cpp b/src/LinuxProfiler/CExtensionsHost.cpp new file mode 100644 index 00000000..8def3172 --- /dev/null +++ b/src/LinuxProfiler/CExtensionsHost.cpp @@ -0,0 +1,274 @@ +#include "stdafx.h" +#include +#include "CExtensionsHost.h" + +using namespace vanguard::instrumentation::managed; + +static vector globalMethodCol; + +HRESULT ExtensionsHostCrossPlat::CExtensionHost::Initialize( + _In_ IProfilerManager* pProfilerManager +) +{ + usleep(5*1000); + CComPtr pCorProfilerInfo; + pProfilerManager->GetCorProfilerInfo((IUnknown**)&pCorProfilerInfo); + pCorProfilerInfo->SetEventMask(COR_PRF_MONITOR_EXCEPTIONS | COR_PRF_ENABLE_STACK_SNAPSHOT); + return S_OK; +} + +HRESULT ExtensionsHostCrossPlat::CExtensionHost::InstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit) +{ + /*CComBSTR bstrMethodName; + pMethodInfo->GetFullName(&bstrMethodName); + + tstringstream methodName; + methodName << (LPWSTR)bstrMethodName; + + tstring methodNameWStr = methodName.str(); + string methodNameStr(methodNameWStr.begin(), methodNameWStr.end()); + + bool instrument = false; + + for (size_t i = 0; i < globalMethodCol.size(); i++) + { + if (methodNameStr.compare(globalMethodCol[i]) == 0) + { + instrument = true; + break; + } + } + + if (!instrument) + { + return S_OK; + } + + BYTE pSignature[256] = {}; + DWORD cbSignature = 0; + pMethodInfo->GetCorSignature(_countof(pSignature), pSignature, &cbSignature); + + if (cbSignature < 2) + return S_FALSE; + USHORT argsCount = pSignature[1];*/ + + CComPtr pModuleInfo; + pMethodInfo->GetModuleInfo(&pModuleInfo); + + ModuleID modId; + pModuleInfo->GetModuleID(&modId); + + module_info *instrumented_module = NULL; + + unordered_map::iterator it = _instrumented_modules.find(modId); + if (it != _instrumented_modules.end()) + { + mdToken token; + pMethodInfo->GetMethodToken(&token); + instrumented_module = it->second; + } + + mdMethodDef token; + pMethodInfo->GetMethodToken(&token); + + method_info info; + bool result = instrumented_module->get_method_info(token, info); + + if (!result) + { + return S_OK; + } + + auto block_indices = info.get_block_indexes(); + auto start_index = info.get_start_index(); + void const *coverage_buffer = instrumented_module->get_coverage_buffer(); + + CComPtr sptrInstructionFactory; + HRESULT hr = (pMethodInfo->GetInstructionFactory(&sptrInstructionFactory)); + IfFailRet(hr); + + CComPtr sptrInstructionGraph; + hr = (pMethodInfo->GetInstructions(&sptrInstructionGraph)); + IfFailRet(hr); + + CComPtr sptrCurrent; + hr = (sptrInstructionGraph->GetFirstInstruction(&sptrCurrent)); + IfFailRet(hr); + + auto index = reinterpret_cast<__int64>(coverage_buffer); + index = index + info.get_start_index(); + + CComPtr operandInstr; + hr = (sptrInstructionFactory->CreateLongOperandInstruction(Cee_Ldc_I8, index, &operandInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBeforeAndRetargetOffsets(sptrCurrent, operandInstr)); + IfFailRet(hr); + + CComPtr pushInstr; + hr = (sptrInstructionFactory->CreateInstruction(Cee_Ldc_I4_1, &pushInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBefore(sptrCurrent, pushInstr)); + IfFailRet(hr); + + CComPtr commitInstr; + hr = (sptrInstructionFactory->CreateInstruction(Cee_Stind_I1, &commitInstr)); + IfFailRet(hr); + hr = (sptrInstructionGraph->InsertBefore(sptrCurrent, commitInstr)); + IfFailRet(hr); + + return hr; +} + +HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnShutdown() +{ + return S_OK; +} + +HRESULT ExtensionsHostCrossPlat::CExtensionHost::ShouldInstrumentMethod(_In_ IMethodInfo* pMethodInfo, _In_ BOOL isRejit, _Out_ BOOL* pbInstrument) +{ + /*CComBSTR bstrMethodName; + pMethodInfo->GetFullName(&bstrMethodName); + + tstringstream methodName; + methodName << (LPWSTR)bstrMethodName; + + tstring methodNameWStr = methodName.str(); + string methodNameStr(methodNameWStr.begin(), methodNameWStr.end()); + + + for (size_t i = 0; i < globalMethodCol.size(); i++) + { + if (methodNameStr.compare(globalMethodCol[i]) == 0) + { + *pbInstrument = TRUE; + break; + } + }*/ + + CComPtr pModuleInfo; + pMethodInfo->GetModuleInfo(&pModuleInfo); + + ModuleID modId; + pModuleInfo->GetModuleID(&modId); + + unordered_map::iterator it = _instrumented_modules.find(modId); + if (it != _instrumented_modules.end()) + { + mdToken token; + pMethodInfo->GetMethodToken(&token); + module_info *info = it->second; + *pbInstrument = info->contains_instrumented_method(token); + } + + return S_OK; +} + +HRESULT ExtensionsHostCrossPlat::CExtensionHost::OnModuleLoaded(IModuleInfo* pModuleInfo) +{ + HRESULT hr = S_OK; + + CComBSTR bstrModuleName; + IfFailRet(pModuleInfo->GetModuleName(&bstrModuleName)); + + CComBSTR bstrModulePath; + IfFailRet(pModuleInfo->GetFullPath(&bstrModulePath)); + + tstringstream dllPath; + dllPath << (LPWSTR)bstrModulePath; + + tstring pdbPath = dllPath.str(); + pdbPath = pdbPath.substr(0, pdbPath.find_last_of(_T('.'))) + _T(".pdb"); + + string filePathChar(pdbPath.begin(), pdbPath.end()); + + tstringstream pathBuilder; + pathBuilder <<_T("/home/maban/projects/XPlatPdbReader/bin/x64/Debug/libXPlatPdbReader.so"); + + if (m_hmod == NULL) + { + m_hmod = ::LoadLibrary(pathBuilder.str().c_str()); + } + + if (m_hmod == NULL) + { + auto error = ::GetLastError(); + // Failed to load the module. + return HRESULT_FROM_WIN32(error); + } + + typedef int(__stdcall* ReadPDB)(const char* path); + + ReadPDB pfnReadPdb = (ReadPDB)GetProcAddress(m_hmod, "ReadPDB"); + if (!pfnReadPdb) + { + auto error = ::GetLastError(); + FreeLibrary(m_hmod); + return HRESULT_FROM_WIN32(error); + } + + int methodCount = 0; + methodCount = pfnReadPdb(filePathChar.c_str()); + + const mdMethodDef baseToken = 0x06 << 24; + mdMethodDef methodDef = 1; + HRESULT methodInfoResult = S_OK; + vector methodInfoCollection; + + il_disassembler disassembler(pModuleInfo); + + while (methodCount) + { + IMethodInfo* methodInfo = NULL; + CComBSTR bstrMethodName; + + mdMethodDef token = baseToken | methodDef; + methodInfoResult = pModuleInfo->GetMethodInfoByToken(token, &methodInfo); + methodInfoCollection.push_back(methodInfo); + methodDef++; + methodCount--; + methodInfo->GetFullName(&bstrMethodName); + + //printf("Method Name: %ls \n ", bstrMethodName); + vanguard::instrumentation::managed::function* func = new vanguard::instrumentation::managed::function(); + func->set_token(token); + + disassembler.initialize_function(methodInfo, func); + disassembler.disassemble_function(); + + struct function_releaser + { + function_releaser(il_disassembler& d) : + _disassembler(d) + { + } + + ~function_releaser() { _disassembler.cleanup_function(); } + + private: + il_disassembler& _disassembler; + } releaser(disassembler); + + func->calculate_blocks(disassembler); + + if (func->get_block_count() > 0) + { + tstringstream methodName; + methodName << (LPWSTR)bstrMethodName; + + tstring methodNameWStr = methodName.str(); + string methodNameStr(methodNameWStr.begin(), methodNameWStr.end()); + globalMethodCol.push_back(methodNameStr); + disassembler.instrument_function(); + } + } + + ModuleID modId; + pModuleInfo->GetModuleID(&modId); + + module_info* info = disassembler.get_module_info(); + info->set_block_count(disassembler.get_global_block_count()); + + _instrumented_modules.insert(make_pair(modId, info)); + + return hr; +} diff --git a/src/LinuxProfiler/CExtensionsHost.h b/src/LinuxProfiler/CExtensionsHost.h new file mode 100644 index 00000000..e82fbc3a --- /dev/null +++ b/src/LinuxProfiler/CExtensionsHost.h @@ -0,0 +1,84 @@ +#pragma once +#include "stdafx.h" +#include "ILDisassembler.h" +#include "managed_function.h" + +using namespace vanguard::instrumentation::managed; + +// {CA487940-57D2-10BF-11B2-A3AD5A13CBC0} +const GUID CLSID_ExtensionHost = +{ 0xCA487940, 0x57D2, 0x10BF,{ 0x11, 0xB2, 0xA3, 0xAD, 0x5A, 0x13, 0xCB, 0xC0 } }; + +namespace ExtensionsHostCrossPlat +{ + + // The existing ExtensionsHost had too much non-portable code to port to Linux. + // In order to avoid destabilizing appinsights through a rewrite, this class + // has been created to provide basic instrumentation engine host support for + // production breakpoints. + class ATL_NO_VTABLE CExtensionHost : + public IInstrumentationMethod, + public CModuleRefCount + { + public: + CExtensionHost() + { +#ifdef PLATFORM_UNIX + PAL_Initialize(0, NULL); +#endif + } + + CExtensionHost(const CExtensionHost&) = delete; + + DEFINE_DELEGATED_REFCOUNT_ADDREF(CExtensionHost) + DEFINE_DELEGATED_REFCOUNT_RELEASE(CExtensionHost) + + STDMETHOD(STDMETHODCALLTYPE) QueryInterface(REFIID riid, PVOID* ppvObject) + { + HRESULT hr = E_NOINTERFACE; + + hr = ImplQueryInterface( + static_cast(this), + riid, + ppvObject + ); + + return hr; + } + + // IProfilerManagerHost methods + public: + virtual HRESULT STDMETHODCALLTYPE Initialize(IProfilerManager* pProfilerManager); + + virtual HRESULT STDMETHODCALLTYPE OnAppDomainCreated(IAppDomainInfo *pAppDomainInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnAppDomainShutdown(IAppDomainInfo *pAppDomainInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnAssemblyLoaded(IAssemblyInfo* pAssemblyInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnAssemblyUnloaded(IAssemblyInfo* pAssemblyInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnModuleLoaded(IModuleInfo* pModuleInfo); + + virtual HRESULT STDMETHODCALLTYPE OnModuleUnloaded(IModuleInfo* pModuleInfo) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE OnShutdown(); + + virtual HRESULT STDMETHODCALLTYPE ShouldInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit, BOOL* pbInstrument); + + virtual HRESULT STDMETHODCALLTYPE BeforeInstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE InstrumentMethod(IMethodInfo* pMethodInfo, BOOL isRejit); + + virtual HRESULT STDMETHODCALLTYPE OnInstrumentationComplete(IMethodInfo* pMethodInfo, BOOL isRejit) { return S_OK; } + + virtual HRESULT STDMETHODCALLTYPE AllowInlineSite(IMethodInfo* pMethodInfoInlinee, IMethodInfo* pMethodInfoCaller, BOOL* pbAllowInline) { return S_OK; } + + private: + + HMODULE m_hmod = NULL; + unordered_map_instrumented_modules; + + }; + +} \ No newline at end of file diff --git a/src/LinuxProfiler/CMakeLists.txt b/src/LinuxProfiler/CMakeLists.txt new file mode 100644 index 00000000..7132483b --- /dev/null +++ b/src/LinuxProfiler/CMakeLists.txt @@ -0,0 +1,60 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# + +# Require at least version 2.8.12 of CMake +cmake_minimum_required(VERSION 2.8.12) +project(LinuxProfiler) + +find_package(LibXml2 REQUIRED) + +include_directories(. ../InstrumentationEngine.Lib ../InstrumentationEngine ${LIBXML2_INCLUDE_DIR}) + +build_init(CPP LinuxProfiler) + +set(src_files + ./stdafx.cpp + ./dllmain.cpp + ./CExtensionsHost.cpp + ./refcount.cpp + ./ImplQueryInterface.cpp + ./VanguardInstrumentation.cpp + ./managed_instruction.cpp + ./managed_function.cpp + ./ILDisassembler.cpp +) + +add_lib(${PROJECT_NAME} + SHARED + true # use_redefines + false # hide_symbols + ${src_files} + ) + +# Force every object to be included even if it's unused. +SET (CORECLRPAL -Wl,--whole-archive coreclrpal -Wl,--no-whole-archive) +SET (LINUXPAL -Wl,--whole-archive linux_pal -Wl,--no-whole-archive) + +# For some reason linking against musl-libc we need libintl and on glibc we need libdl. +# They have nothing to do with one another, each is just a quirk of the environment. +if(CLR_CMAKE_PLATFORM_ALPINE_LINUX) + target_link_libraries(${PROJECT_NAME} :libintl.so) +else() + # NOTE: Explicitly link to the .so version of libdl.so to make sure we don't somehow accidentally + # start statically linking to these, as these are LGPL components. + target_link_libraries(${PROJECT_NAME} :libdl.so) +endif() + +target_link_libraries(${PROJECT_NAME} + pthread + stdc++ + ${CORECLRPAL} + ${LINUXPAL} + atl + palrt + InstrumentationEngine.Lib + corguids + :libuuid.so + :libunwind-x86_64.so + ) + +add_dependencies(${PROJECT_NAME} linux_pal) \ No newline at end of file diff --git a/src/LinuxProfiler/ClassFactory.cpp b/src/LinuxProfiler/ClassFactory.cpp new file mode 100644 index 00000000..a026b148 --- /dev/null +++ b/src/LinuxProfiler/ClassFactory.cpp @@ -0,0 +1,66 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#include "ClassFactory.h" +#include "InstrumentationMethod.h" + +ClassFactory::ClassFactory() : refCount(0) +{ +} + +ClassFactory::~ClassFactory() +{ +} + +HRESULT STDMETHODCALLTYPE ClassFactory::QueryInterface(REFIID riid, void **ppvObject) +{ + if (riid == IID_IUnknown || riid == IID_IClassFactory) + { + *ppvObject = this; + this->AddRef(); + return S_OK; + } + + *ppvObject = nullptr; + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE ClassFactory::AddRef() +{ + return std::atomic_fetch_add(&this->refCount, 1) + 1; +} + +ULONG STDMETHODCALLTYPE ClassFactory::Release() +{ + int count = std::atomic_fetch_sub(&this->refCount, 1) - 1; + if (count <= 0) + { + delete this; + } + + return count; +} + +HRESULT STDMETHODCALLTYPE ClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) +{ + if (pUnkOuter != nullptr) + { + *ppvObject = nullptr; + return CLASS_E_NOAGGREGATION; + } + + CInstrumentationMethod* profiler = new CInstrumentationMethod(); + if (profiler == nullptr) + { + return E_FAIL; + } + + return profiler->QueryInterface(riid, ppvObject); + + //return S_OK; +} + +HRESULT STDMETHODCALLTYPE ClassFactory::LockServer(BOOL fLock) +{ + return S_OK; +} \ No newline at end of file diff --git a/src/LinuxProfiler/ClassFactory.h b/src/LinuxProfiler/ClassFactory.h new file mode 100644 index 00000000..b926764c --- /dev/null +++ b/src/LinuxProfiler/ClassFactory.h @@ -0,0 +1,19 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#pragma once +#include "stdafx.h" + +class ClassFactory : public IClassFactory +{ +private: + std::atomic refCount; +public: + ClassFactory(); + virtual ~ClassFactory(); + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject) override; + ULONG STDMETHODCALLTYPE AddRef(void) override; + ULONG STDMETHODCALLTYPE Release(void) override; + HRESULT STDMETHODCALLTYPE CreateInstance(IUnknown *pUnkOuter, REFIID riid, void **ppvObject) override; + HRESULT STDMETHODCALLTYPE LockServer(BOOL fLock) override; +}; diff --git a/src/LinuxProfiler/ILDisassembler.cpp b/src/LinuxProfiler/ILDisassembler.cpp new file mode 100644 index 00000000..0047fc40 --- /dev/null +++ b/src/LinuxProfiler/ILDisassembler.cpp @@ -0,0 +1,146 @@ +#include "stdafx.h" +#include "ILDisassembler.h" + +namespace vanguard { + namespace instrumentation { + namespace managed + { + il_disassembler::il_disassembler(IModuleInfo *pModuleInfo) : _global_block_count(0) + { + _module_info = new module_info(pModuleInfo); + _current_function = nullptr; + } + + void il_disassembler::disassemble_function() + { + int index = 0; + unordered_map inst_dict; + + IInstructionGraph* instructionsGraph; + HRESULT hr = _current_method_info->GetInstructions(&instructionsGraph); + + if (hr == S_OK) + { + IInstruction* il_inst = NULL; + + HRESULT instructionData = instructionsGraph->GetFirstInstruction(&il_inst); + + DWORD pOffset; + DWORD pSize; + ILOrdinalOpcode pOpCode; + + il_inst->GetOffset(&pOffset); + il_inst->GetInstructionLength(&pSize); + il_inst->GetOpCode(&pOpCode); + + instruction *inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(il_inst), index++, pOpCode); + _il_instructions.push_back(il_inst); + _instructions.push_back(inst); + inst_dict.insert(std::pair(il_inst, inst)); + + while (instructionData == S_OK) + { + IInstruction* nextInstruction = NULL; + instructionData = il_inst->GetNextInstruction(&nextInstruction); + + if (instructionData != S_OK) + { + break; + } + + _il_instructions.push_back(nextInstruction); + + nextInstruction->GetOffset(&pOffset); + nextInstruction->GetInstructionLength(&pSize); + nextInstruction->GetOpCode(&pOpCode); + + inst = new instruction((size_t)pOffset, (size_t)pSize, get_termination_type(nextInstruction), index++, pOpCode); + _instructions.push_back(inst); + + il_inst = nextInstruction; + inst_dict.insert(std::pair(il_inst, inst)); + } + } + + // Set targets + for (size_t i = 0; i < _il_instructions.size(); i++) + { + BOOL isSwitch, isBranch; + _il_instructions[i]->GetIsSwitch(&isSwitch); + _il_instructions[i]->GetIsBranch(&isBranch); + + if (isSwitch) + { + ISwitchInstruction *il_switch; + _il_instructions[i]->QueryInterface(__uuidof(ISwitchInstruction), (LPVOID*)&il_switch); + + DWORD pBranchCount = 0; + il_switch->GetBranchCount(&pBranchCount); + + _instructions[i]->set_target_count(pBranchCount); + + for (ULONG j = 0; j < pBranchCount; j++) + { + IInstruction *pBranchTarget; + + il_switch->GetBranchTarget(j, &pBranchTarget); + _instructions[i]->get_targets()[j] = lookup(pBranchTarget, inst_dict, (instruction*)nullptr); + } + } + else if (isBranch) + { + IBranchInstruction *il_branch; + _il_instructions[i]->QueryInterface(__uuidof(IBranchInstruction), (LPVOID*)&il_branch); + instruction *target = nullptr; + IInstruction* pBranchTarget; + il_branch->GetBranchTarget(&pBranchTarget); + target = lookup(pBranchTarget, inst_dict, target); + + if (target) + { + _instructions[i]->set_target_count(1); + _instructions[i]->get_targets()[0] = target; + } + } + } + } + + size_t il_disassembler::get_instructions(vanguard::instrumentation::managed::instruction **&instructions) + { + instructions = _instructions.data(); + return _instructions.size(); + } + + void il_disassembler::cleanup_function() + { + for (vector::iterator it = _instructions.begin(); it != _instructions.end(); ++it) + { + delete *it; + } + + _instructions.clear(); + _il_instructions.clear(); + _current_method_info = nullptr; + _current_function = nullptr; + } + + HRESULT il_disassembler::instrument_function(/* size_t block_index */) + { + method_info info(_current_function->get_token()); + for (vanguard::instrumentation::managed::function::block_type* block_it = _current_function->get_blocks(); block_it < _current_function->get_blocks() + _current_function->get_block_count(); ++block_it) + { + instruction* inst = block_it->get_instructions()[0]; + + info.add_block_index(inst->get_index()); + } + + info.set_start_index(_global_block_count); + _module_info->add_instrumented_functions(info); + + _global_block_count += _current_function->get_block_count(); + + return S_OK; + } + } + } +} \ No newline at end of file diff --git a/src/LinuxProfiler/ILDisassembler.h b/src/LinuxProfiler/ILDisassembler.h new file mode 100644 index 00000000..2c0db568 --- /dev/null +++ b/src/LinuxProfiler/ILDisassembler.h @@ -0,0 +1,100 @@ +#pragma once + +#include "managed_instruction.h" +#include "managed_function.h" +#include "VanguardInstrumentation.h" + +using namespace ATL; + +namespace vanguard { + namespace instrumentation { + namespace managed + { + struct il_disassembler + { + public: + il_disassembler(IModuleInfo *pModuleInfo); + + virtual void disassemble_function(); + virtual void initialize_function(IMethodInfo *methodInfo, function* current_function) + { + _current_method_info = methodInfo; + _current_function = current_function; + } + virtual size_t get_instructions(/* [out] */ instruction **&instructions); + virtual void cleanup_function(); + virtual HRESULT instrument_function(/* size_t block_index */); + + virtual module_info *get_module_info() { return _module_info; } + + size_t get_global_block_count() { return _global_block_count; } + + private: + template + target_type lookup(source_type source, std::unordered_map &input_map, target_type default_value) + { + if (source && input_map.find(source) != input_map.end()) + { + return input_map.find(source)->second; + } + + return default_value; + } + + DISCEE::TRMTA get_termination_type(IInstruction *il_inst) + { + ILOrdinalOpcode opcode; + il_inst->GetOpCode(&opcode); + if (opcode < 0) + { + return DISCEE::trmtaUnknown; + } + + switch (opcode) + { + case Cee_Break: + return DISCEE::trmtaTrap; + case Cee_Switch: + return DISCEE::trmtaBraSwitch; + case Cee_Ret: + case Cee_Endfinally: + case Cee_Endfilter: + return DISCEE::trmtaRet; + case Cee_Call: + case Cee_Jmp: + case Cee_Newobj: + return DISCEE::trmtaCall; + case Cee_Calli: + case Cee_Callvirt: + return DISCEE::trmtaCallInd; + case Cee_Br_S: + case Cee_Br: + case Cee_Leave: + case Cee_Leave_S: + return DISCEE::trmtaBra; + case Cee_Throw: + case Cee_Rethrow: + return DISCEE::trmtaBraInd; + } + + if (opcode >= Cee_Brfalse_S && opcode < Cee_Switch) + { + return DISCEE::trmtaBraCc; + } + + // For the rest (NEXT and META), they are fallthrough + return DISCEE::trmtaFallThrough; + } + + bool _use_verifiable_probe; + IMethodInfo *_current_method_info; + std::vector _instructions; + std::vector _il_instructions; + module_info *_module_info; + size_t _global_block_count; + vanguard::instrumentation::managed::function* _current_function; + }; + } + } +} + diff --git a/src/LinuxProfiler/ImplQueryInterface.cpp b/src/LinuxProfiler/ImplQueryInterface.cpp new file mode 100644 index 00000000..eec3a6de --- /dev/null +++ b/src/LinuxProfiler/ImplQueryInterface.cpp @@ -0,0 +1,102 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#include "stdafx.h" +#include "ImplQueryInterface.h" + +namespace ExtensionsHostCrossPlat +{ +namespace InternalImplQueryInterface +{ + +HRESULT MultiInterfaceImp( + _In_count_(dwNumElements) const MULTI_INTERFACE_ELEMENT *qiArray, + DWORD dwNumElements, + REFIID iidReqInterface, + _Deref_out_ PVOID *ppvObject +) +{ + HRESULT hr = S_OK; + //VSASSERT(dwNumElements > 0, L""); + + if (ppvObject != NULL) + { + if (iidReqInterface == IID_IUnknown) + { + *ppvObject = qiArray[0].pUnknown; + } + else + { + PVOID pObject = NULL; + + for (DWORD i = 0; i < dwNumElements; i++) + { + if (*qiArray[i].iidImplInterface == iidReqInterface) + { + pObject = qiArray[i].pUnknown; + } + } + + if (pObject) + { + *ppvObject = pObject; + } + else + { + *ppvObject = NULL; + hr = E_NOINTERFACE; + } + } + } + else + { + hr = E_INVALIDARG; + } + + if (hr == S_OK) + { + //VSASSERT(*ppvObject != NULL, L""); + qiArray[0].pUnknown->AddRef(); + } + + + return hr; +} + +HRESULT SingleInterfaceImp(IUnknown *pThis, REFIID iidImplInterface, REFIID iidReqInterface, _Deref_out_ PVOID *ppvObject) +{ + HRESULT hr = S_OK; + + if (ppvObject != NULL) + { + if (iidReqInterface == iidImplInterface) + { + *ppvObject = pThis; + } + else if (iidReqInterface == IID_IUnknown) + { + *ppvObject = pThis; + } + else + { + *ppvObject = NULL; + hr = E_NOINTERFACE; + } + } + else + { + hr = E_INVALIDARG; + } + + if (hr == S_OK) + { + //VSASSERT(*ppvObject != NULL, L""); + pThis->AddRef(); + } + + return hr; +} + +} +} +; // end namespace InternalImplQueryInterface \ No newline at end of file diff --git a/src/LinuxProfiler/ImplQueryInterface.h b/src/LinuxProfiler/ImplQueryInterface.h new file mode 100644 index 00000000..4ad9bc84 --- /dev/null +++ b/src/LinuxProfiler/ImplQueryInterface.h @@ -0,0 +1,1494 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#pragma once + +namespace ExtensionsHostCrossPlat +{ + #ifndef ARRAYSIZE + #define ARRAYSIZE(a) (sizeof(a)/sizeof((a)[0])) + #endif + + // + // This function maps an IID that identifies a particular module (example: IID_IAmSdmObject) to IUnknown + inline REFIID MapToTrueIID(REFIID riidModIdentifier, REFIID riidRequest) + { + return (riidModIdentifier == riidRequest) ? IID_IUnknown : riidRequest; + } + + + // + // Overloads which accept riidModIdentifier + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T *pThis, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, pThis3, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, pThis3, pThis4, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, pThis3, pThis4, pThis5, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, pThis3, pThis4, pThis5, pThis6, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, pThis3, pThis4, pThis5, pThis6, pThis7, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + template + inline HRESULT ImplQueryInterface(REFIID riidModIdentifier, _In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + return ImplQueryInterface(pThis1, pThis2, pThis3, pThis4, pThis5, pThis6, pThis7, pThis8, MapToTrueIID(riidModIdentifier, riid), ppvObject); + } + + + + + // + // Functions to implement query interface which take 1-32 interfaces as input + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T *pThis, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk = static_cast(pThis); // Verify that INTERFACE_T is a COM interface + + return InternalImplQueryInterface::SingleInterfaceImp(pUnk, __uuidof(INTERFACE_T), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[2] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[3] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[4] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[5] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[6] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[7] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[8] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[9] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[10] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[11] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[12] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[13] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[14] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[15] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[16] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[17] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[18] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[19] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[20] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[21] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[22] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[23] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[24] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[25] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[26] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, _In_ INTERFACE_T27 *pThis27, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + IUnknown *pUnk27 = static_cast(pThis27); // Verify that INTERFACE_T27 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[27] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + { pUnk27, &__uuidof(INTERFACE_T27) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, _In_ INTERFACE_T27 *pThis27, _In_ INTERFACE_T28 *pThis28, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + IUnknown *pUnk27 = static_cast(pThis27); // Verify that INTERFACE_T27 is a COM interface + IUnknown *pUnk28 = static_cast(pThis28); // Verify that INTERFACE_T28 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[28] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + { pUnk27, &__uuidof(INTERFACE_T27) }, + { pUnk28, &__uuidof(INTERFACE_T28) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, _In_ INTERFACE_T27 *pThis27, _In_ INTERFACE_T28 *pThis28, _In_ INTERFACE_T29 *pThis29, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + IUnknown *pUnk27 = static_cast(pThis27); // Verify that INTERFACE_T27 is a COM interface + IUnknown *pUnk28 = static_cast(pThis28); // Verify that INTERFACE_T28 is a COM interface + IUnknown *pUnk29 = static_cast(pThis29); // Verify that INTERFACE_T29 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[29] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + { pUnk27, &__uuidof(INTERFACE_T27) }, + { pUnk28, &__uuidof(INTERFACE_T28) }, + { pUnk29, &__uuidof(INTERFACE_T29) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, _In_ INTERFACE_T27 *pThis27, _In_ INTERFACE_T28 *pThis28, _In_ INTERFACE_T29 *pThis29, _In_ INTERFACE_T30 *pThis30, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + IUnknown *pUnk27 = static_cast(pThis27); // Verify that INTERFACE_T27 is a COM interface + IUnknown *pUnk28 = static_cast(pThis28); // Verify that INTERFACE_T28 is a COM interface + IUnknown *pUnk29 = static_cast(pThis29); // Verify that INTERFACE_T29 is a COM interface + IUnknown *pUnk30 = static_cast(pThis30); // Verify that INTERFACE_T30 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[30] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + { pUnk27, &__uuidof(INTERFACE_T27) }, + { pUnk28, &__uuidof(INTERFACE_T28) }, + { pUnk29, &__uuidof(INTERFACE_T29) }, + { pUnk30, &__uuidof(INTERFACE_T30) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, _In_ INTERFACE_T27 *pThis27, _In_ INTERFACE_T28 *pThis28, _In_ INTERFACE_T29 *pThis29, _In_ INTERFACE_T30 *pThis30, _In_ INTERFACE_T31 *pThis31, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + IUnknown *pUnk27 = static_cast(pThis27); // Verify that INTERFACE_T27 is a COM interface + IUnknown *pUnk28 = static_cast(pThis28); // Verify that INTERFACE_T28 is a COM interface + IUnknown *pUnk29 = static_cast(pThis29); // Verify that INTERFACE_T29 is a COM interface + IUnknown *pUnk30 = static_cast(pThis30); // Verify that INTERFACE_T30 is a COM interface + IUnknown *pUnk31 = static_cast(pThis31); // Verify that INTERFACE_T31 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[31] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + { pUnk27, &__uuidof(INTERFACE_T27) }, + { pUnk28, &__uuidof(INTERFACE_T28) }, + { pUnk29, &__uuidof(INTERFACE_T29) }, + { pUnk30, &__uuidof(INTERFACE_T30) }, + { pUnk31, &__uuidof(INTERFACE_T31) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + template + inline HRESULT ImplQueryInterface(_In_ INTERFACE_T1 *pThis1, _In_ INTERFACE_T2 *pThis2, _In_ INTERFACE_T3 *pThis3, _In_ INTERFACE_T4 *pThis4, _In_ INTERFACE_T5 *pThis5, _In_ INTERFACE_T6 *pThis6, _In_ INTERFACE_T7 *pThis7, _In_ INTERFACE_T8 *pThis8, _In_ INTERFACE_T9 *pThis9, _In_ INTERFACE_T10 *pThis10, _In_ INTERFACE_T11 *pThis11, _In_ INTERFACE_T12 *pThis12, _In_ INTERFACE_T13 *pThis13, _In_ INTERFACE_T14 *pThis14, _In_ INTERFACE_T15 *pThis15, _In_ INTERFACE_T16 *pThis16, _In_ INTERFACE_T17 *pThis17, _In_ INTERFACE_T18 *pThis18, _In_ INTERFACE_T19 *pThis19, _In_ INTERFACE_T20 *pThis20, _In_ INTERFACE_T21 *pThis21, _In_ INTERFACE_T22 *pThis22, _In_ INTERFACE_T23 *pThis23, _In_ INTERFACE_T24 *pThis24, _In_ INTERFACE_T25 *pThis25, _In_ INTERFACE_T26 *pThis26, _In_ INTERFACE_T27 *pThis27, _In_ INTERFACE_T28 *pThis28, _In_ INTERFACE_T29 *pThis29, _In_ INTERFACE_T30 *pThis30, _In_ INTERFACE_T31 *pThis31, _In_ INTERFACE_T32 *pThis32, REFIID riid, _Deref_out_ PVOID *ppvObject) + { + IUnknown *pUnk1 = static_cast(pThis1); // Verify that INTERFACE_T1 is a COM interface + IUnknown *pUnk2 = static_cast(pThis2); // Verify that INTERFACE_T2 is a COM interface + IUnknown *pUnk3 = static_cast(pThis3); // Verify that INTERFACE_T3 is a COM interface + IUnknown *pUnk4 = static_cast(pThis4); // Verify that INTERFACE_T4 is a COM interface + IUnknown *pUnk5 = static_cast(pThis5); // Verify that INTERFACE_T5 is a COM interface + IUnknown *pUnk6 = static_cast(pThis6); // Verify that INTERFACE_T6 is a COM interface + IUnknown *pUnk7 = static_cast(pThis7); // Verify that INTERFACE_T7 is a COM interface + IUnknown *pUnk8 = static_cast(pThis8); // Verify that INTERFACE_T8 is a COM interface + IUnknown *pUnk9 = static_cast(pThis9); // Verify that INTERFACE_T9 is a COM interface + IUnknown *pUnk10 = static_cast(pThis10); // Verify that INTERFACE_T10 is a COM interface + IUnknown *pUnk11 = static_cast(pThis11); // Verify that INTERFACE_T11 is a COM interface + IUnknown *pUnk12 = static_cast(pThis12); // Verify that INTERFACE_T12 is a COM interface + IUnknown *pUnk13 = static_cast(pThis13); // Verify that INTERFACE_T13 is a COM interface + IUnknown *pUnk14 = static_cast(pThis14); // Verify that INTERFACE_T14 is a COM interface + IUnknown *pUnk15 = static_cast(pThis15); // Verify that INTERFACE_T15 is a COM interface + IUnknown *pUnk16 = static_cast(pThis16); // Verify that INTERFACE_T16 is a COM interface + IUnknown *pUnk17 = static_cast(pThis17); // Verify that INTERFACE_T17 is a COM interface + IUnknown *pUnk18 = static_cast(pThis18); // Verify that INTERFACE_T18 is a COM interface + IUnknown *pUnk19 = static_cast(pThis19); // Verify that INTERFACE_T19 is a COM interface + IUnknown *pUnk20 = static_cast(pThis20); // Verify that INTERFACE_T20 is a COM interface + IUnknown *pUnk21 = static_cast(pThis21); // Verify that INTERFACE_T21 is a COM interface + IUnknown *pUnk22 = static_cast(pThis22); // Verify that INTERFACE_T22 is a COM interface + IUnknown *pUnk23 = static_cast(pThis23); // Verify that INTERFACE_T23 is a COM interface + IUnknown *pUnk24 = static_cast(pThis24); // Verify that INTERFACE_T24 is a COM interface + IUnknown *pUnk25 = static_cast(pThis25); // Verify that INTERFACE_T25 is a COM interface + IUnknown *pUnk26 = static_cast(pThis26); // Verify that INTERFACE_T26 is a COM interface + IUnknown *pUnk27 = static_cast(pThis27); // Verify that INTERFACE_T27 is a COM interface + IUnknown *pUnk28 = static_cast(pThis28); // Verify that INTERFACE_T28 is a COM interface + IUnknown *pUnk29 = static_cast(pThis29); // Verify that INTERFACE_T29 is a COM interface + IUnknown *pUnk30 = static_cast(pThis30); // Verify that INTERFACE_T30 is a COM interface + IUnknown *pUnk31 = static_cast(pThis31); // Verify that INTERFACE_T31 is a COM interface + IUnknown *pUnk32 = static_cast(pThis32); // Verify that INTERFACE_T32 is a COM interface + + InternalImplQueryInterface::MULTI_INTERFACE_ELEMENT qiArray[32] = + { + { pUnk1, &__uuidof(INTERFACE_T1) }, + { pUnk2, &__uuidof(INTERFACE_T2) }, + { pUnk3, &__uuidof(INTERFACE_T3) }, + { pUnk4, &__uuidof(INTERFACE_T4) }, + { pUnk5, &__uuidof(INTERFACE_T5) }, + { pUnk6, &__uuidof(INTERFACE_T6) }, + { pUnk7, &__uuidof(INTERFACE_T7) }, + { pUnk8, &__uuidof(INTERFACE_T8) }, + { pUnk9, &__uuidof(INTERFACE_T9) }, + { pUnk10, &__uuidof(INTERFACE_T10) }, + { pUnk11, &__uuidof(INTERFACE_T11) }, + { pUnk12, &__uuidof(INTERFACE_T12) }, + { pUnk13, &__uuidof(INTERFACE_T13) }, + { pUnk14, &__uuidof(INTERFACE_T14) }, + { pUnk15, &__uuidof(INTERFACE_T15) }, + { pUnk16, &__uuidof(INTERFACE_T16) }, + { pUnk17, &__uuidof(INTERFACE_T17) }, + { pUnk18, &__uuidof(INTERFACE_T18) }, + { pUnk19, &__uuidof(INTERFACE_T19) }, + { pUnk20, &__uuidof(INTERFACE_T20) }, + { pUnk21, &__uuidof(INTERFACE_T21) }, + { pUnk22, &__uuidof(INTERFACE_T22) }, + { pUnk23, &__uuidof(INTERFACE_T23) }, + { pUnk24, &__uuidof(INTERFACE_T24) }, + { pUnk25, &__uuidof(INTERFACE_T25) }, + { pUnk26, &__uuidof(INTERFACE_T26) }, + { pUnk27, &__uuidof(INTERFACE_T27) }, + { pUnk28, &__uuidof(INTERFACE_T28) }, + { pUnk29, &__uuidof(INTERFACE_T29) }, + { pUnk30, &__uuidof(INTERFACE_T30) }, + { pUnk31, &__uuidof(INTERFACE_T31) }, + { pUnk32, &__uuidof(INTERFACE_T32) }, + }; + + return InternalImplQueryInterface::MultiInterfaceImp(qiArray, ARRAYSIZE(qiArray), riid, ppvObject); + } + + + + namespace InternalImplQueryInterface + { + struct MULTI_INTERFACE_ELEMENT + { + IUnknown *pUnknown; + const IID *iidImplInterface; + }; + + HRESULT MultiInterfaceImp(_In_count_(dwNumElements) const MULTI_INTERFACE_ELEMENT *qiArray, DWORD dwNumElements, REFIID iidReqInterface, _Deref_out_ PVOID *ppvObject); + HRESULT SingleInterfaceImp(IUnknown *pThis, REFIID iidImplInterface, REFIID iidReqInterface, _Deref_out_ PVOID *ppvObject); + + }; +} \ No newline at end of file diff --git a/src/LinuxProfiler/ProductionBreakpoints_x64.config b/src/LinuxProfiler/ProductionBreakpoints_x64.config new file mode 100644 index 00000000..ea35b775 --- /dev/null +++ b/src/LinuxProfiler/ProductionBreakpoints_x64.config @@ -0,0 +1,9 @@ + + + Seafood Instrumentation + Dynamically make squids swim + libLinuxProfiler.so + {CA487940-57D2-10BF-11B2-A3AD5A13CBC0} + 50 + + \ No newline at end of file diff --git a/src/LinuxProfiler/VanguardInstrumentation.cpp b/src/LinuxProfiler/VanguardInstrumentation.cpp new file mode 100644 index 00000000..95391f75 --- /dev/null +++ b/src/LinuxProfiler/VanguardInstrumentation.cpp @@ -0,0 +1,29 @@ +#include "stdafx.h" +#include "VanguardInstrumentation.h" + +bool module_info::contains_instrumented_method(mdToken token) +{ + return _instrumented_functions_list.find(token) != _instrumented_functions_list.end(); +} + +bool module_info::get_method_info(mdToken token, method_info& info) +{ + unordered_map::iterator it = _instrumented_functions_list.find(token); + if (it != _instrumented_functions_list.end()) + { + info = it->second; + return true; + } + + return false; +} + +void module_info::set_block_count(size_t block_count) +{ + _block_count = block_count; + for (size_t i = 0; i < block_count; ++i) + { + _coverage_buffer.push_back(0); + } + +} \ No newline at end of file diff --git a/src/LinuxProfiler/VanguardInstrumentation.h b/src/LinuxProfiler/VanguardInstrumentation.h new file mode 100644 index 00000000..258a36eb --- /dev/null +++ b/src/LinuxProfiler/VanguardInstrumentation.h @@ -0,0 +1,54 @@ +#pragma once + +//#include "stdafx.h" + +using namespace ATL; + +struct method_info +{ +public: + method_info() : _token(mdTokenNil), _start_block_index(0) {} + method_info(mdToken token) : _token(token), _start_block_index(0) {} + + ~method_info() { _block_indexes.clear(); } + + mdToken get_method_token() { return _token; } + + void set_start_index(size_t start_block_index) { _start_block_index = start_block_index; } + size_t get_start_index() { return _start_block_index; } + + void add_block_index(size_t block_index) { _block_indexes.push_back(block_index); } + vector get_block_indexes() { return _block_indexes; } + +private: + mdToken _token; + vector _block_indexes; /* indices where probes are to be added */ + size_t _start_block_index; +}; + +struct module_info +{ +public: + module_info(IModuleInfo* modInfo) : _current_module_info(modInfo) {} + ~module_info() { _instrumented_functions_list.clear(); } + + void add_instrumented_functions(method_info& method_info) { _instrumented_functions_list.insert(make_pair(method_info.get_method_token(), method_info)); } + + IModuleInfo *get_module() { return _current_module_info; } + + bool contains_instrumented_method(mdToken token); + bool get_method_info(mdToken token, method_info& info); + + size_t get_block_count() { return _block_count; } + void set_block_count(size_t block_count); + + void const* get_coverage_buffer() { return (std::addressof(_coverage_buffer[0])); } + +private: + unordered_map _instrumented_functions_list; + IModuleInfo *_current_module_info; + size_t _block_count; + vector<__int64> _coverage_buffer; /* address to buffer where probes mark their value */ +}; + + diff --git a/src/LinuxProfiler/block.h b/src/LinuxProfiler/block.h new file mode 100644 index 00000000..21d2d437 --- /dev/null +++ b/src/LinuxProfiler/block.h @@ -0,0 +1,100 @@ +#pragma once + +#include "stdafx.h" + +namespace vanguard { + namespace instrumentation + { + //! Represents a basic block. + template + struct block + { + typedef instr_type instruction_type; + + //! Constructs a basic block given its starting address. + block(address_type address = 0) : + _address(address), + _size(0), + _is_prolog_block(false), + _instructions(nullptr), + _instruction_count(0), + _is_catch_block(false) + { + } + + //! Move constructor for basic block. + block(block&& other) + { + *this = std::move(other); + } + + //! Destructor + ~block() + { + if (_instructions) delete[] _instructions; + } + + //! Move assignment operator for basic block. + block& operator=(block&& other) + { + _address = other._address; + _size = other._size; + _instructions = other._instructions; + _instruction_count = other._instruction_count; + other._instructions = nullptr; + _is_prolog_block = other._is_prolog_block; + _is_catch_block = other._is_catch_block; + return *this; + } + + //! Gets the starting address of the basic block. + address_type get_address() const { return _address; } + + //! Gets the size of the basic block. + size_t get_size() const { return _size; } + + //! Sets the size of the basic block. + void set_size(size_t size) { _size = size; } + + //! Gets whether or not the block is the prolog block (only applies to x64). + bool is_prolog() const { return _is_prolog_block; } + + // Return true if block is catch handler + bool is_catch_block() const { return _is_catch_block; } + + //! Sets whether or not the block is the prolog block (only applies to x64). + void set_prolog(bool value) { _is_prolog_block = value; } + + // Sets whether or not block is of catch handler type + void set_catch_block(bool value) { _is_catch_block = value; } + + //! Gets the instructions that are part of the basic block. + instruction_type* get_instructions() { return _instructions; } + + //! Gets the instructions that are part of the basic block. + instruction_type* const get_instructions() const { return _instructions; } + + //! Gets instruction count. + size_t get_instruction_count() const { return _instruction_count; } + + //! Sets instruction count. + void set_instruction_count(size_t count) + { + if (_instructions) delete[] _instructions; + _instructions = new instruction_type[_instruction_count = count]; + } + + private: + //! Block does not implement correct copy constructor/operator, make them private. + block(const block&); + const block& operator=(const block&); + + address_type _address; + size_t _size; + instruction_type* _instructions; + size_t _instruction_count; + bool _is_prolog_block; + bool _is_catch_block; + }; + } +} \ No newline at end of file diff --git a/src/LinuxProfiler/dllmain.cpp b/src/LinuxProfiler/dllmain.cpp new file mode 100644 index 00000000..e12dfee7 --- /dev/null +++ b/src/LinuxProfiler/dllmain.cpp @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#include "stdafx.h" +#include "refcount.h" +#include "CExtensionsHost.h" + +namespace ExtensionsHostCrossPlat +{ + + class CLinuxClassFactory : public IClassFactory, public CModuleRefCount + { + private: + + public: + DEFINE_DELEGATED_REFCOUNT_ADDREF(CLinuxClassFactory); + DEFINE_DELEGATED_REFCOUNT_RELEASE(CLinuxClassFactory); + STDMETHOD(STDMETHODCALLTYPE) QueryInterface(REFIID riid, PVOID *ppvObject) + { + HRESULT hr = E_NOINTERFACE; + + hr = ImplQueryInterface( + static_cast(this), + riid, ppvObject + ); + + return hr; + } + + // IClassFactory Methods + public: + STDMETHOD(CreateInstance)( + _In_ IUnknown *pUnkOuter, + _In_ REFIID riid, + _Out_ void **ppvObject + ) + { + HRESULT hr = S_OK; + + CComPtr pExtensionHost; + pExtensionHost.Attach(new CExtensionHost()); + + IfFailRet(pExtensionHost->QueryInterface(riid, ppvObject)); + + return S_OK; + } + + STDMETHOD(LockServer)( + _In_ BOOL fLock + ) + { + return S_OK; + } + }; +} + +extern "C" HRESULT __attribute__((visibility("default"))) DllGetClassObject(_In_ REFCLSID rclsid, _In_ REFIID riid, _Outptr_ LPVOID FAR* ppv) +{ + CComPtr pClassFactory; + pClassFactory.Attach(new ExtensionsHostCrossPlat::CLinuxClassFactory); + + if (pClassFactory != nullptr) + { + return pClassFactory->QueryInterface(riid, ppv); + } + + return E_NOINTERFACE; +} diff --git a/src/LinuxProfiler/linux-profiler.vcxproj b/src/LinuxProfiler/linux-profiler.vcxproj new file mode 100644 index 00000000..495ea0ed --- /dev/null +++ b/src/LinuxProfiler/linux-profiler.vcxproj @@ -0,0 +1,112 @@ + + + + + Debug + ARM + + + Release + ARM + + + Debug + ARM64 + + + Release + ARM64 + + + Debug + x86 + + + Release + x86 + + + Debug + x64 + + + Release + x64 + + + + {c10693ba-bb9b-4571-9340-defb48bc6428} + Linux + linux_profiler + 15.0 + Linux + 1.0 + Generic + {D51BCBC9-82E9-4017-911E-C93873C4EA2B} + + + + true + + + false + + + true + + + false + + + true + DynamicLibrary + + + false + + + false + + + true + + + + + + + + clang++ + clang++ + clang++ + + + + + + + + + + + + + + + + true + + + + + /home/maban/xplat/CLRInstrumentationEngine/src/unix/inc/atl;/home/maban/xplat/CLRInstrumentationEngine/src/InstrumentationEngine.Api;/home/maban/xplat/CLRInstrumentationEngine/src/unix/inc/winsdk;/home/maban/xplat/CLRInstrumentationEngine/src/unix/inc/empty;/home/maban/xplat/CLRInstrumentationEngine/src/unix/inc;/home/maban/coreclr/src/pal/prebuilt/inc;/home/maban/coreclr/src/pal/inc;/home/maban/coreclr/src/pal/inc/rt;/home/maban/coreclr/src/inc;%(AdditionalIncludeDirectories) + + %(CppAdditionalWarning)%(CppAdditionalWarning) + -W"no-invalid-noreturn" -fPIC -fms-extensions -DBIT64 -DPAL_STDCPP_COMPAT -DPLATFORM_UNIX -std=c++14 %(AdditionalOptions) + TurnOffAllWarnings + /home/maban/xplat/CLRInstrumentationEngine/src/unix/inc/atl/atldef.h;%(ForcedIncludeFiles) + + + + + \ No newline at end of file diff --git a/src/LinuxProfiler/managed_function.cpp b/src/LinuxProfiler/managed_function.cpp new file mode 100644 index 00000000..d9a4a0bf --- /dev/null +++ b/src/LinuxProfiler/managed_function.cpp @@ -0,0 +1,156 @@ +#include "stdafx.h" +#include "managed_function.h" +#include "ILDisassembler.h" + +using namespace std; + +namespace vanguard { + namespace instrumentation { + namespace managed + { + //! Constructs a function given the symbol and metadata. + function::function() : + _id(INVALID_ID), + _rva(0), + _address(nullptr), + _token(0), + _type_token(0), + _size(0), + _name(nullptr), + _type_name(nullptr), + _namespace_name(nullptr), + _source_file(nullptr), + _blocks(nullptr), + _block_count(0) + { + } + + //! Disassembles the function and populates the list of blocks; a nop if the function has already been disassembled. + void function::calculate_blocks(il_disassembler& disassembler) + { + // If we've already disassembled or cannot disassemble, do nothing + // In case of Assembly.Load/AssemblyLoadContext.LoadFromStream, we want to instrument, even if there are no symbols + // if (_blocks || (!has_symbolic_information() && !_is_assembly_load)) + // return; + + instruction* last_inst = nullptr; + instruction** instructions; + size_t count = disassembler.get_instructions(/* [out] */ instructions); + for (instruction** it = instructions; it < instructions + count; last_inst = *it, it++) + { + //1.The tail prefix instruction must immediately precede a Call, Calli, or Callvirt instruction + //2.The instruction following the call instruction must be a ret. + //so we cannot put a probe after the call instrution as it will make IL invalid, we wait till we pass the ret instruction. + //Bug 167554:Tests pass in regular runs, but fail in coverage run + if ((*it)->get_opcode() == ILOrdinalOpcode::Cee_Tailcall) + { + it++; + while (!(*it)->is_return()) + { + it++; + } + } + else + { + // 1. Mark instructions whose previous instructions are not fallthrough as start of a block + if (!last_inst || !last_inst->is_fall_through()) + { + (*it)->set_starts_block(true); + } + + // 2. Mark the targets of branches as start of a block + if ((*it)->is_direct_branch() || (*it)->is_indirect_branch()) + { + for (instruction** target_it = (*it)->get_targets(); target_it < (*it)->get_targets() + (*it)->get_target_count(); ++target_it) + { + (*target_it)->set_starts_block(true); + } + } + } + } + + // Process the instruction map into blocks + process_blocks(disassembler); + } + + void function::process_blocks(il_disassembler& disassembler) + { + // If there we no instructions, it's invalid + instruction** instructions; + size_t inst_count = disassembler.get_instructions(/* [out] */ instructions); + if (inst_count == 0) + { + throw new exception(); + } + + //// First, mark any instructions referenced from the exception causes as starting blocks + //exception_clause* exception_clauses; + //size_t clause_count = 0; // disassembler.get_exception_clauses(/* [out] */ exception_clauses); + //for (auto clause = exception_clauses; clause < exception_clauses + clause_count; clause++) + //{ + // if (clause->get_try_instruction()) + // { + // clause->get_try_instruction()->set_starts_block(true); + // } + // if (clause->get_handler_instruction()) + // { + // clause->get_handler_instruction()->set_starts_block(true); + // } + // if (clause->get_filter_instruction()) + // { + // clause->get_filter_instruction()->set_starts_block(true); + // } + //} + + // Copy the instructions and count the number of blocks + vector blocks; + block_type* current_block = nullptr; + vector current_instructions; + size_t block_size = 0; + for (instruction** it = instructions; it < instructions + inst_count; ++it) + { + instruction* instr = *it; + + // If we're starting a new block + if (instr->get_starts_block()) + { + if (current_block) + { + size_t blockInstructionCount = current_instructions.size(); + // Set the block size for the block we're finishing + current_block->set_size(block_size); + current_block->set_instruction_count(blockInstructionCount); + for (size_t i = 0; i < blockInstructionCount; i++) + current_block->get_instructions()[i] = current_instructions[i]; + } + + // Insert a new code block. + blocks.push_back(block_type(instr->get_offset())); + current_block = &blocks.back(); + block_size = 0; + current_instructions.clear(); + } + + // Push the instruction into the current block + if (current_block) + { + block_size += instr->get_size(); + current_instructions.push_back(instr); + } + } + + if (current_block) + { + current_block->set_size(block_size); + current_block->set_instruction_count(current_instructions.size()); + for (size_t i = 0; i < current_instructions.size(); i++) + current_block->get_instructions()[i] = current_instructions[i]; + } + + _blocks = new block_type[_block_count = blocks.size()]; + for (size_t i = 0; i < _block_count; i++) + _blocks[i] = std::move(blocks[i]); + } + } + } +} diff --git a/src/LinuxProfiler/managed_function.h b/src/LinuxProfiler/managed_function.h new file mode 100644 index 00000000..b0243678 --- /dev/null +++ b/src/LinuxProfiler/managed_function.h @@ -0,0 +1,142 @@ +#pragma once + +#include "stdafx.h" +#include "block.h" +#include "managed_instruction.h" +#include + +namespace vanguard { + namespace instrumentation { + namespace managed + { + struct il_disassembler; + + //! Represents a managed function. + struct function + { + static const DWORD INVALID_ID = 0xFFFFFFFF; + typedef block block_type; + + function(); + + //! Move constructor for function. + function(function&& other) + { + *this = std::move(other); + } + + //! Destructor + ~function() + { + if (_blocks) delete[] _blocks; + } + + //! Move assignment operator for function. + function& operator=(function&& other) + { + _id = other._id; + _rva = other._rva; + _token = other._token; + _type_token = other._type_token; + _address = other._address; + _blocks = other._blocks; + _block_count = other._block_count; + other._blocks = nullptr; + _size = other._size; + _is_assembly_load = other._is_assembly_load; + return *this; + } + + //! Analyze the blocks inside the function. + void calculate_blocks(il_disassembler& disassembler); + + //! Determines if there is enough symbolic information to instrument this function. + bool has_symbolic_information() const + { + return + _id != -1 && + _rva != 0 && + _token != 0 && + _address && + wcslen(_name) > 0 && + wcslen(_source_file) > 0; + } + + //! Gets the function's identifier. + uint32_t get_id() const { return _id; } + + //! Gets the function's RVA. + uint32_t get_rva() const { return _rva; } + + //! Gets the function's metadata token. + uint32_t get_token() const { return _token; } + + //! Sets the function's metadata token. + void set_token(uint32_t token) { _token = token; } + + //! Gets the function's type's metadata token. + uint32_t get_type_token() const { return _type_token; } + + //! Get tokens of property this method is associated with. Usually there are zero or one such properties + const std::vector& get_property_tokens() const { return _property_tokens; } + + //! Gets the function's address. + _Ret_notnull_ void const* get_address() const { return _address; } + + //! Gets the function's size in bytes. + size_t get_size() const { return _size; } + + //! Sets the function's size in bytes. + void set_size(size_t size) { _size = size; } + + //! Gets the function's name. + const wchar_t* get_name() const { return _name; } + + //! Gets the function's type name. + const wchar_t* get_type_name() const { return _type_name; } + + //! Gets the function's namespace name. + const wchar_t* get_namespace_name() const { return _namespace_name; } + + //! Gets the function's source file. + const wchar_t* get_source_file() const { return _source_file; } + + //! Gets the blocks of the function. + //! Disassemble must be called before this list will be populated. + block_type* const get_blocks() const { return _blocks; } + + //! Gets the block count. + size_t get_block_count() const { return _block_count; } + + static const std::wstring separator; + + protected: + //! Constructs a function given the symbol and metadata. + + const wchar_t* _name; + const wchar_t* _type_name; + const wchar_t* _namespace_name; + const wchar_t* _source_file; + + private: + //! Function does not implement correct copy constructor/operator, make them private. + function(const function&); + const function& operator=(const function&); + + void process_blocks(il_disassembler& disassembler); + + uint32_t _id; + uint32_t _rva; + uint32_t _token; + uint32_t _type_token; + std::vector _property_tokens; + void const* _address; + block_type* _blocks; + size_t _block_count; + size_t _size; + + bool _is_assembly_load; + }; + } + } +} \ No newline at end of file diff --git a/src/LinuxProfiler/managed_instruction.cpp b/src/LinuxProfiler/managed_instruction.cpp new file mode 100644 index 00000000..86b028d1 --- /dev/null +++ b/src/LinuxProfiler/managed_instruction.cpp @@ -0,0 +1,63 @@ +#include "stdafx.h" +#include "managed_instruction.h" + +namespace vanguard { + namespace instrumentation { + namespace managed + { + //! Gets whether or not the instruction's termination type is a direct branch. + bool instruction::is_direct_branch() const + { + return _termination == DISCEE::trmtaBra || is_conditional_branch(); // In IL, all conditional branches are direct + } + + //! Gets whether or not the instruction's termination type is a conditional branch. + bool instruction::is_conditional_branch() const + { + return _termination == DISCEE::trmtaBraCc || is_switch(); // Switches are also conditional + } + + //! Gets whether or not the instruction's termination type is an indirect branch. + bool instruction::is_indirect_branch() const + { + return _termination == DISCEE::trmtaBraInd; + } + + //! Gets whether or not the instruction's termination type is a indirect call. + bool instruction::is_indirect_call() const + { + return _termination == DISCEE::trmtaCallInd; + } + + //! Gets whether or not the instruction's termination type is a direct call. + bool instruction::is_direct_call() const + { + return _termination == DISCEE::trmtaCall; + } + + //! Gets whether or not the instruction's termination type is a return. + bool instruction::is_return() const + { + return _termination == DISCEE::trmtaRet; + } + + //! Gets whether or not the instruction's termination type is falling through to the next instruction. + bool instruction::is_fall_through() const + { + return _termination == DISCEE::trmtaFallThrough; + } + + //! Gets whether or not the instruction's termination type is a trap instruction (break). + bool instruction::is_trap() const + { + return _termination == DISCEE::trmtaTrap; + } + + //! Gets whether or not the instruction's termination type is a switch. + bool instruction::is_switch() const + { + return _termination == DISCEE::trmtaBraSwitch; + } + } + } +} \ No newline at end of file diff --git a/src/LinuxProfiler/managed_instruction.h b/src/LinuxProfiler/managed_instruction.h new file mode 100644 index 00000000..8f16a0d2 --- /dev/null +++ b/src/LinuxProfiler/managed_instruction.h @@ -0,0 +1,146 @@ +#pragma once +#include "stdafx.h" + +namespace DISCEE +{ + enum TRMTA + { + trmtaTrap, + trmtaBraSwitch, + trmtaRet, + trmtaCall, + trmtaCallInd, + trmtaBra, + trmtaBraInd, + trmtaBraCc, + trmtaFallThrough, + trmtaUnknown + }; +}; + +namespace vanguard { + namespace instrumentation { + namespace managed { + + //! Represents environment independent instruction + struct instruction + { + //! Constructor + instruction(size_t offset, size_t instruction_size, DISCEE::TRMTA termination, size_t index, ILOrdinalOpcode opcode) : + _offset(offset), + _instruction_size(instruction_size), + _starts_block(false), + _termination(termination), + _index(index), + _targets(nullptr), + _target_count(0), + _opcode(opcode) + { + } + + //! Move constructor for instruction. + instruction(instruction&& other) + { + *this = std::move(other); + } + + //! Destructor + ~instruction() + { + if (_targets) delete[] _targets; + } + + //! Move assignment operator for instruction. + instruction& operator=(instruction&& other) + { + _termination = other._termination; + _starts_block = other._starts_block; + _index = other._index; + _offset = other._offset; + _instruction_size = other._instruction_size; + _targets = other._targets; + _target_count = other._target_count; + _opcode = other._opcode; + other._targets = nullptr; + + return *this; + } + + //! Gets whether or not this instruction is the start of a basic block. + bool get_starts_block() const { return _starts_block; } + + //! Sets whether or not this instruction is the start of a basic block. + void set_starts_block(bool value) { _starts_block = value; } + + //! Gets whether or not the instruction's termination type is a direct branch. + bool is_direct_branch() const; + + //! Gets whether or not the instruction's termination type is a conditional branch. + bool is_conditional_branch() const; + + //! Gets whether or not the instruction's termination type is an indirect branch. + bool is_indirect_branch() const; + + //! Gets whether or not the instruction's termination type is a indirect call. + bool is_indirect_call() const; + + //! Gets whether or not the instruction's termination type is a direct call. + bool is_direct_call() const; + + //! Gets whether or not the instruction's termination type is a return. + bool is_return() const; + + //! Gets whether or not the instruction's termination type is falling through to the next instruction. + bool is_fall_through() const; + + //! Gets whether or not the instruction's termination type is a trap instruction (break). + bool is_trap() const; + + //! Gets whether or not the instruction's termination type is a switch. + bool is_switch() const; + + //! Gets the index of the instruction (unique in its containing function) + size_t get_index() const { return _index; } + + //! Gets the targets of the instruction. + instruction** get_targets() { return _targets; } + + //! Gets the targets of the instruction. + instruction** const get_targets() const { return _targets; } + + //! Gets the target count. + size_t get_target_count() const { return _target_count; } + + //! Sets the target count. + void set_target_count(size_t count) + { + if (_targets) delete[] _targets; + _targets = new instruction*[_target_count = count]; + } + + //! Gets the instruction's offset relative to the start of the function. + size_t get_offset() const { return _offset; } + + //! Gets the size of the instruction in bytes. + size_t get_size() const { return _instruction_size; } + + ILOrdinalOpcode get_opcode() const { return _opcode; } + + private: + //! Instruction does not implement correct copy constructor/operator, make them private. + instruction(const instruction&); + const instruction& operator=(const instruction&); + + bool _starts_block; + DISCEE::TRMTA _termination; + ILOrdinalOpcode _opcode; + size_t _index; + size_t _offset; + instruction** _targets; + size_t _target_count; + size_t _instruction_size; + + }; + } + } +} \ No newline at end of file diff --git a/src/LinuxProfiler/profiler_pal.h b/src/LinuxProfiler/profiler_pal.h new file mode 100644 index 00000000..74e6ee37 --- /dev/null +++ b/src/LinuxProfiler/profiler_pal.h @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#pragma once + +#ifndef WIN32 +#include +#include "pal_mstypes.h" +#include "pal.h" +#include "ntimage.h" +#include "corhdr.h" + +#define CoTaskMemAlloc(cb) malloc(cb) +#define CoTaskMemFree(cb) free(cb) + +#define UINT_PTR_FORMAT "lx" + +#else +#define UINT_PTR_FORMAT "llx" +#endif \ No newline at end of file diff --git a/src/LinuxProfiler/refcount.cpp b/src/LinuxProfiler/refcount.cpp new file mode 100644 index 00000000..3c621b3f --- /dev/null +++ b/src/LinuxProfiler/refcount.cpp @@ -0,0 +1,248 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#include "stdafx.h" + +#include "refcount.h" +#include "intrin.h" + +// TODO: +// Clean this up. It was pulled from Debugger\inc and Debugger\common in order to get leak detection on +// ref counted objects. I didn't just use the compiled lib becase it isn't clear to me where this code +// is eventually going to live and if it turns out to be on a CDM server, the debugger lib won't exist. + +namespace ExtensionsHostCrossPlat +{ +#pragma intrinsic(_InterlockedOr) + +#ifdef _UNICODE +#define TRACE TRACEW +#else +#define TRACE TRACEA +#endif + + +#ifdef DEBUG + bool g_fDisplayTrace = true; + int g_TraceIndent = 0; + + #define TRACEA DisplayTraceA + #define TRACEW DisplayTraceW + + extern bool g_fDisplayTrace; + extern int g_TraceIndent; + + void _cdecl DisplayTraceA(LPCSTR pszFormat, ...); + void _cdecl DisplayTraceW(LPCWSTR pszFormat, ...); + void _cdecl IndentTrace(int indent); + +#else // !DEBUG + +#define TRACEA +#define TRACEW +#define IndentTrace + +#endif + +#ifdef DEBUG + void _cdecl IndentTrace(int indent) + { + g_TraceIndent += indent; + } + + void _cdecl DisplayTraceW(LPCWSTR pszFormat, ...) + { + if (g_fDisplayTrace) + { + WCHAR szTrace[1024]; + + int offset = 0; + + if (g_TraceIndent > 0) + { + offset = min(g_TraceIndent, (int)ARRAYSIZE(szTrace) - 1); + + for (int i = 0; i < offset; i++) + { + szTrace[i] = ' '; + } + } + + va_list marker; + va_start(marker, pszFormat); + _snwprintf_s(szTrace + offset, ARRAYSIZE(szTrace) - offset, _TRUNCATE, pszFormat, marker); + wcscat_s(szTrace, ARRAYSIZE(szTrace), _T("\r\n")); + OutputDebugStringW(szTrace); + } + } +#endif + + // ---------------------------------------------------------------------------- + // CRefRBMap +#ifdef DEBUG + class CRefRBMap : public ATL::CRBMap {}; +#endif + + // ---------------------------------------------------------------------------- + // CRefCount + +#ifdef DEBUG + DWORD CRefCount::g_dwRecorderOptions; //Recording is optional + bool CRefCount::g_fRecordingInitialized = false; + CRefRBMap CRefCount::g_map; + CRITICAL_SECTION CRefCount::g_crst; + + void CRefCount::InitRecorder(DWORD dwOptions) + { + //Add an environment variable hook to disable ref-recording, since this can sometimes be really slow. + if (GetEnvironmentVariable(_T("DisableRefRecording"), nullptr, 0) > 0) + { + dwOptions &= ~EnableRecorder; + } + + g_dwRecorderOptions = dwOptions; + if (g_dwRecorderOptions & EnableRecorder) + { + InitializeCriticalSection(&g_crst); + g_fRecordingInitialized = true; + } + } + + void CRefCount::TerminateRecorder(void) + { + if (g_fRecordingInitialized) + { + //VSASSERT(g_map.IsEmpty(), "Object recorder: Objects when the object recorder was terminated."); + + for (POSITION nextPosition = g_map.GetHeadPosition(); nextPosition != NULL;) + { + CRefRBMap::CPair* pPair = g_map.GetNext(nextPosition); + TRACE(_T("Object \"%s\" (%lxh) was leaked (%lu)."), pPair->m_key->m_pszCRefCountClassName, pPair->m_key, pPair->m_value); + } + + g_map.RemoveAll(); + + DeleteCriticalSection(&g_crst); + g_fRecordingInitialized = false; + } + } + + void CRefCount::RecordCreation(CRefCount* pCRefCount) + { + if (g_fRecordingInitialized) + { + EnterCriticalSection(&g_crst); + + CRefRBMap::CPair* pPair = g_map.Lookup(pCRefCount); + if (pPair) + { + //VSASSERT(false, "Object recorder: Object destroyed without the recorder being notified."); + TRACE(_T("Object \"%s\" (%lxh) destroyed without recorder being notified."), pCRefCount->m_pszCRefCountClassName, pCRefCount); + } + + g_map.SetAt(pCRefCount, 1); + + LeaveCriticalSection(&g_crst); + } + } + + void CRefCount::RecordDestruction(CRefCount* pCRefCount) + { + if (g_fRecordingInitialized) + { + EnterCriticalSection(&g_crst); + + bool fFound = g_map.RemoveKey(pCRefCount); + + //VSASSERT(fFound, "Object recorder: Object created without the recorder being notified."); + + LeaveCriticalSection(&g_crst); + } + } + + void CRefCount::RecordAddRef(CRefCount* pCRefCount) + { + if (g_fRecordingInitialized) + { + EnterCriticalSection(&g_crst); + + BOOL fFound = FALSE; + CRefRBMap::CPair* pPair = g_map.Lookup(pCRefCount); + if (pPair) + { + pPair->m_value++; + fFound = TRUE; + } + + //VSASSERT(fFound, "Object recorder: Object created without the recorder being notified."); + + LeaveCriticalSection(&g_crst); + } + } + + void CRefCount::RecordRelease(CRefCount* pCRefCount) + { + if (g_fRecordingInitialized) + { + EnterCriticalSection(&g_crst); + + BOOL fFound = FALSE; + CRefRBMap::CPair* pPair = g_map.Lookup(pCRefCount); + if (pPair) + { + pPair->m_value--; + + //VSASSERT(pPair->m_value != -1, "Object recorder: Object released too many times."); + + if (pPair->m_value == 0) + { + g_map.RemoveAt(pPair); + } + fFound = TRUE; + } + + //VSASSERT(fFound, "Object recorder: Object created without the recorder being notified."); + + LeaveCriticalSection(&g_crst); + } + } + + void CRefCount::DumpRefCount(void) + { + if (g_fRecordingInitialized) + { + EnterCriticalSection(&g_crst); + + if (!g_map.IsEmpty()) + { + TRACE(_T(">> Begin ref count dump. Leaked objects are also available in the watch window by evaluating g_map. <<")); + + for (POSITION nextPosition = g_map.GetHeadPosition(); nextPosition != NULL;) + { + CRefRBMap::CPair* pPair = g_map.GetNext(nextPosition); + TRACE(_T(">> Object \"%s\" (0x%p) contains ref-count 0x%lu."), pPair->m_key->m_pszCRefCountClassName, pPair->m_key, pPair->m_value); + } + + TRACE(_T(">> End ref count dump <<")); + } + + LeaveCriticalSection(&g_crst); + } + } + +#endif // DEBUG + + // ---------------------------------------------------------------------------- + // CModuleRefCount + + ULONG CModuleRefCount::s_ulcModuleRef = 0; + + // ---------------------------------------------------------------------------- + // module ref count support + + ULONG CModuleRefCount::GetModuleUsage(void) + { + return (ULONG)_InterlockedOr((PLONG)&s_ulcModuleRef, 0); + } + +} \ No newline at end of file diff --git a/src/LinuxProfiler/refcount.h b/src/LinuxProfiler/refcount.h new file mode 100644 index 00000000..e7255ce3 --- /dev/null +++ b/src/LinuxProfiler/refcount.h @@ -0,0 +1,204 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#pragma once + +#ifndef __REFCOUNT_H__ +#define __REFCOUNT_H__ + +namespace ExtensionsHostCrossPlat +{ + // ---------------------------------------------------------------------------- + // CRefCount macros + +#ifdef DEBUG + +#define INITIALIZE_REF_RECORDER(dwOptions) MicrosoftInstrumentationEngine::CRefCount::InitRecorder((dwOptions)) +#define TERMINATE_REF_RECORDER MicrosoftInstrumentationEngine::CRefCount::TerminateRecorder() + +#define DEFINE_REFCOUNT_NAME(cls) m_pszCRefCountClassName = (LPTSTR)_T(#cls) + +#define DUMP_REFCOUNT CRefCount::DumpRefCount() + +#else // !DEBUG + +#define INITIALIZE_REF_RECORDER(fOn) +#define TERMINATE_REF_RECORDER + +#define DEFINE_REFCOUNT_NAME(cls) + +#define DUMP_REFCOUNT + +#endif // DEBUG + + // ---------------------------------------------------------------------------- + // Define generic method delegation from a derived class to a base class. + // + // DEFINE_DELEGATED_METHOD(InprocServerClassFactory, ClassFactory, HRESULT, LockServer, (BOOL bLock), (bLock)); + // defines a delegated method call from InprocServerClassFactory::LockServer() to ClassFactory::LockServer(). + +#define DEFINE_DELEGATED_METHOD(base_cls, result_type, method, derived_paren_args, base_paren_args) \ + result_type STDMETHODCALLTYPE method derived_paren_args \ + { \ + return base_cls::method base_paren_args; \ +} + +#define DEFINE_DELEGATED_REFCOUNT_ADDREF(cls) \ + DEFINE_DELEGATED_METHOD(CRefCount, ULONG, AddRef, (void), ()) +#define DEFINE_DELEGATED_REFCOUNT_RELEASE(cls) \ + DEFINE_DELEGATED_METHOD(CRefCount, ULONG, Release, (void), ()) + +#define DEFINE_DELEGATED_REFCOUNT_ADDREF_DEBUG(cls) STDMETHOD_(ULONG, AddRef)() { ULONG result = CRefCount::AddRef(); VSASSERT(#cls); return result; } +#define DEFINE_DELEGATED_REFCOUNT_RELEASE_DEBUG(cls) STDMETHOD_(ULONG, Release)() { ULONG result = CRefCount::Release(); VSASSERT(#cls); return result; } + + // ---------------------------------------------------------------------------- + // CRefCount + + class CRefCount + { + // ctor/dtor + public: + CRefCount(void) + { + DEFINE_REFCOUNT_NAME(CRefCount); + + m_ulcRef = 1; + +#ifdef DEBUG + + RecordCreation(this); +#endif + + } + virtual ~CRefCount() + { +#ifdef DEBUG + + if (m_ulcRef > 0) + { + RecordDestruction(this); + } +#endif // DEBUG + + } + + // IUnknown methods + public: + STDMETHOD_(ULONG, AddRef)(void) + { + //VSASSERT(m_ulcRef < ULONG_MAX, L""); + + ULONG ulcRef = (ULONG)(InterlockedIncrement((LPLONG)(&m_ulcRef))); + +#ifdef DEBUG + + RecordAddRef(this); +#endif // DEBUG + + // Note: the return from InterlockedIncrement may only match the new value + // in signed-ness and zero-ness, but the return value of AddRef() + // is not guaranteed in any case. + + return ulcRef; + } + STDMETHOD_(ULONG, Release)(void) + { + //VSASSERT(m_ulcRef > 0, L""); + + ULONG ulcRef = (ULONG)(InterlockedDecrement((LPLONG)(&m_ulcRef))); + +#ifdef DEBUG + + RecordRelease(this); +#endif // DEBUG + + if (ulcRef == 0) + { + delete this; + } + + // Note: the return from InterlockedDecrement may only match the new value + // in signed-ness and zero-ness, but the return value of Release() + // is not guaranteed in any case. + + return ulcRef; + } + + // ref count + private: + ULONG m_ulcRef; + +#ifdef DEBUG + + // ------------------------------------------------------------ + // CRefCount recording stuff (for finding leaks) + // ------------------------------------------------------------ + + protected: + LPTSTR m_pszCRefCountClassName; + + private: + static DWORD g_dwRecorderOptions; // Recording is optional. + static bool g_fRecordingInitialized; + static class CRefRBMap g_map; + static CRITICAL_SECTION g_crst; + + static void RecordCreation(CRefCount *pCRefCount); + static void RecordDestruction(CRefCount *pCRefCount); + static void RecordAddRef(CRefCount *pCRefCount); + static void RecordRelease(CRefCount *pCRefCount); + public: + static void DumpRefCount(void); + + public: + enum RecorderOptions + { + EnableRecorder = 0x01, + }; + + static void InitRecorder(DWORD dwOptions); + static void TerminateRecorder(void); + +#endif // DEBUG + }; + + // ---------------------------------------------------------------------------- + // CModuleRefCount + + class CModuleRefCount : public CRefCount + { + // ctor/dtor + public: + CModuleRefCount(void) + { + IncModuleUsage(); + } + ~CModuleRefCount(void) + { + DecModuleUsage(); + } + + // module ref count support + public: + static ULONG IncModuleUsage(void) + { + //VSASSERT(s_ulcModuleRef < ULONG_MAX, L""); + + return (ULONG)InterlockedIncrement((PLONG)(&s_ulcModuleRef)); + } + static ULONG DecModuleUsage(void) + { + // This assert isn't thread-safe but its bug-catching ability is valuable + // enough to risk a few nuisance alerts. + //VSASSERT(s_ulcModuleRef > 0, L""); + ULONG ulcRef = InterlockedDecrement((PLONG)(&s_ulcModuleRef)); + + return ulcRef; + } + static ULONG GetModuleUsage(void); + private: + static ULONG s_ulcModuleRef; + }; +} + +#endif // ! __REFCOUNT_H__ diff --git a/src/LinuxProfiler/stdafx.cpp b/src/LinuxProfiler/stdafx.cpp new file mode 100644 index 00000000..c47d50c5 --- /dev/null +++ b/src/LinuxProfiler/stdafx.cpp @@ -0,0 +1,4 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#include "stdafx.h" diff --git a/src/LinuxProfiler/stdafx.h b/src/LinuxProfiler/stdafx.h new file mode 100644 index 00000000..c9f934d6 --- /dev/null +++ b/src/LinuxProfiler/stdafx.h @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// stdafx.h : include file for standard system include files, +// or project specific include files that are used frequently, but +// are changed infrequently +// + +#pragma once + +#ifdef PLATFORM_UNIX +#include "unix.h" +#include +#include +#include +#endif + +#include "targetver.h" + +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + +#include +#include "string.h" +#include // for pfn_REPORTFAULT +#include + + +#include + +#include +#ifndef PLATFORM_UNIX +#include +#include +#include +#endif +#include +//#ifndef PLATFORM_UNIX +#include +//#endif +#include + +using namespace ATL; + +#include +#include +#include +#include + +#ifndef PLATFORM_UNIX +#include +#include +#else +#include +#include +#endif + + +#ifdef PLATFORM_UNIX +#include +#endif + +#ifdef PLATFORM_UNIX +// pal.h defines these, but they aren't picked up for our build because std_c++ compatibility is defined +// in CMakeFile.txt +#define PAL_wcsnlen_s(a, b) (a != nullptr) ? PAL_wcsnlen(a, b) : 0 +#define wcsstr PAL_wcsstr +#define wcslen PAL_wcslen +#define wcsnlen_s PAL_wcsnlen_s +#endif + +#include +#include +#include +#include + +#ifdef PLATFORM_UNIX +// pal.h defines these, but they aren't picked up for our build because std_c++ compatibility is defined +// in CMakeFile.txt +#define fclose PAL_fclose +#define fflush PAL_fflush +#define fprintf PAL_fprintf +#define fwprintf PAL_fwprintf +#endif + +#include +#include +#include +#ifdef PLATFORM_UNIX +#include +#endif + +#include "Logging.h" +#include "ImplQueryInterface.h" +#include "refcount.h" +#include "SharedArray.h" + +#include "../Common.Lib/tstring.h" +#include "../Common.Lib/Macros.h" +#include "../Common.Lib/CriticalSectionHolder.h" +#include "../Common.Lib/InitOnce.h" +#include "../Common.Lib/Singleton.h" + +#include "../Common.Lib/banned.h" + +using namespace std; +using namespace MicrosoftInstrumentationEngine; \ No newline at end of file diff --git a/src/LinuxProfiler/tstring.h b/src/LinuxProfiler/tstring.h new file mode 100644 index 00000000..7af1c646 --- /dev/null +++ b/src/LinuxProfiler/tstring.h @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// + +#pragma once + +#include + +#ifdef PLATFORM_UNIX +typedef std::basic_string, std::allocator> tstring; +typedef std::basic_stringstream tstringstream; +#else +typedef std::wstring tstring; +typedef std::wstringstream tstringstream; +#endif +typedef std::basic_ofstream > tofstream; \ No newline at end of file