summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Zemtsov <e.zemtsov@gmail.com>2015-04-28 20:29:32 -0700
committerEugene Zemtsov <e.zemtsov@gmail.com>2015-04-28 20:29:32 -0700
commit1827eb2ae3201ccba95ca228d657041c8af3410c (patch)
treec3ed7da642a685eb8c3836d1bab3e3afcb281c74
parent1d940c1961bb90b7a7ca35b730dbf8de0e608718 (diff)
parentf4f5df8e66f36959ea9af838c58aa820f654b05a (diff)
downloadcoreclr-1827eb2ae3201ccba95ca228d657041c8af3410c.tar.gz
coreclr-1827eb2ae3201ccba95ca228d657041c8af3410c.tar.bz2
coreclr-1827eb2ae3201ccba95ca228d657041c8af3410c.zip
Merge pull request #848 from Djuffin/dbi-linux
Make DbgShim really useful for managed attach on Linux
-rw-r--r--src/debug/di/process.cpp4
-rw-r--r--src/debug/di/shimpriv.h6
-rw-r--r--src/debug/di/shimprocess.cpp109
-rw-r--r--src/dlls/dbgshim/CMakeLists.txt1
-rw-r--r--src/dlls/dbgshim/dbgshim.cpp51
-rw-r--r--src/dlls/dbgshim/dbgshim.h12
-rw-r--r--src/inc/MSCOREE.IDL4
-rw-r--r--src/pal/inc/rt/palrt.h75
-rw-r--r--src/pal/prebuilt/inc/mscoree.h7
9 files changed, 52 insertions, 217 deletions
diff --git a/src/debug/di/process.cpp b/src/debug/di/process.cpp
index 167692be72..41613d8213 100644
--- a/src/debug/di/process.cpp
+++ b/src/debug/di/process.cpp
@@ -1112,8 +1112,6 @@ HRESULT ShimProcess::CreateProcess(
{
pShim.Assign(new ShimProcess());
- pShim->CheckForPortInfo(pRemoteTarget);
-
// Indicate that this process was started under the debugger as opposed to attaching later.
pShim->m_attached = false;
@@ -1178,8 +1176,6 @@ HRESULT ShimProcess::DebugActiveProcess(
{
pShim.Assign(new ShimProcess());
- pShim->CheckForPortInfo(pRemoteTarget);
-
// Indicate that this process was attached to, asopposed to being started under the debugger.
pShim->m_attached = true;
diff --git a/src/debug/di/shimpriv.h b/src/debug/di/shimpriv.h
index c3a505175c..4a6179c007 100644
--- a/src/debug/di/shimpriv.h
+++ b/src/debug/di/shimpriv.h
@@ -480,12 +480,6 @@ public:
// Look for a CLR in the process and if found, return it's instance ID
HRESULT FindLoadedCLR(CORDB_ADDRESS * pClrInstanceId);
- // Check whether the debugger has given us an ICorDebugRemoteTarget to query for the host name of the remote machine.
- void CheckForPortInfo(ICorDebugRemoteTarget * pRemoteTarget);
-
- // Resolve the host name given to us by the debugger to an IP address. Currently we don't support IPv6.
- DWORD ResolveHostName(ICorDebugRemoteTarget * pRemoteTarget);
-
// Retrieve the IP address and the port number of the debugger proxy.
MachineInfo GetMachineInfo();
diff --git a/src/debug/di/shimprocess.cpp b/src/debug/di/shimprocess.cpp
index efea6d55b9..cd090b63b8 100644
--- a/src/debug/di/shimprocess.cpp
+++ b/src/debug/di/shimprocess.cpp
@@ -19,12 +19,8 @@
#include <limits.h>
#include "shimpriv.h"
-#if defined(FEATURE_PAL)
-#include "debug-pal.h"
-#else
+#if !defined(FEATURE_CORESYSTEM)
#include <tlhelp32.h>
-#define PSAPI_VERSION 2
-#include <psapi.h>
#endif
//---------------------------------------------------------------------------------------
@@ -1737,28 +1733,6 @@ void ShimProcess::PreDispatchEvent(bool fRealCreateProcessEvent /*= false*/)
}
-#if defined(FEATURE_CORESYSTEM) && !defined(FEATURE_PAL)
-// Returns true if the named of a given module is [Core]Clr.dll
-static bool IsClrModule(HANDLE hProcess, HMODULE hModule)
-{
- WCHAR modulePath[MAX_PATH] = {};
- if(GetModuleFileNameEx(hProcess, hModule, modulePath, MAX_PATH) == 0)
- {
- return false;
- }
-
- //strip off everything up to and including the last slash in the path to get name
- const WCHAR* pModuleName = modulePath;
- while(wcschr(pModuleName, W('\\')) != NULL)
- {
- pModuleName = wcschr(pModuleName, W('\\'));
- pModuleName++; // pass the slash
- }
-
- return _wcsicmp(pModuleName, MAIN_CLR_DLL_NAME_W) == 0;
-}
-#endif
-
// ----------------------------------------------------------------------------
// ShimProcess::GetCLRInstanceBaseAddress
// Finds the base address of [core]clr.dll
@@ -1769,41 +1743,10 @@ CORDB_ADDRESS ShimProcess::GetCLRInstanceBaseAddress()
{
CORDB_ADDRESS baseAddress = CORDB_ADDRESS(NULL);
DWORD dwPid = m_pLiveDataTarget->GetPid();
-#if defined(FEATURE_PAL)
- baseAddress = PTR_TO_CORDB_ADDRESS (GetDynamicLibraryAddressInProcess(dwPid, MAKEDLLNAME_A(MAIN_CLR_MODULE_NAME_A)));
-#elif defined(FEATURE_CORESYSTEM)
- HandleHolder hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
- if (NULL == hProcess)
- return baseAddress;
-
- // These shouldn't be closed
- HMODULE modules[1000];
- DWORD cbNeeded;
- if(!EnumProcessModules(hProcess, modules, sizeof(modules), &cbNeeded))
- {
- return baseAddress;
- }
-
- DWORD countModules = min(cbNeeded, sizeof(modules)) / sizeof(HMODULE);
- for(DWORD i = 0; i < countModules; i++)
- {
- if (IsClrModule(hProcess, modules[i]))
- {
- MODULEINFO info;
- if (GetModuleInformation(hProcess, modules[i], &info, sizeof(info)))
- {
- if (baseAddress)
- {
- // We already found an instance of [core]clr.dll, and this is a second one
- // it means we can't automatically detect CLR module, ergo return NULL.
- baseAddress = NULL;
- break;
- }
- baseAddress = CORDB_ADDRESS(info.lpBaseOfDll);
- }
- }
- }
-
+#if defined(FEATURE_CORESYSTEM)
+ // Debugger attaching to CoreCLR via CoreCLRCreateCordbObject should have already specified CLR module address.
+ // Code that help to find it now lives in dbgshim.
+ baseAddress = PTR_TO_CORDB_ADDRESS(0);
#else
// get a "snapshot" of all modules in the target
HandleHolder hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPid);
@@ -1869,48 +1812,6 @@ HRESULT ShimProcess::FindLoadedCLR(CORDB_ADDRESS * pClrInstanceId)
return S_OK;
}
-//---------------------------------------------------------------------------------------
-//
-// If a debugger calls ICDRemote::CreateProcessEx() or ICDRemote::DebugActiveProcessEx(),
-// then an ICDRemoteTarget should have been passed to us. We can query this port to find
-// out the remote IP address (and possibly port) that the user wants to connect to.
-//
-// Arguments:
-// pRemoteTarget - provided by the debugger for us to query the host name of the target machine
-//
-// Return Value:
-// None. Throws on errors.
-//
-
-void ShimProcess::CheckForPortInfo(ICorDebugRemoteTarget * pRemoteTarget)
-{
-#if defined(FEATURE_DBGIPC_TRANSPORT_DI)
- if (pRemoteTarget != NULL)
- {
- DWORD dwIPAddress = ResolveHostName(pRemoteTarget);
- m_machineInfo.Init(dwIPAddress, 0);
- }
-#endif // FEATURE_DBGIPC_TRANSPORT_DI
-}
-
-//---------------------------------------------------------------------------------------
-//
-// Resolve the host name given by the ICorDebugRemote to an IP address. Currently only IPv4 and fully
-// qualified domain name are supported.
-//
-// Arguments:
-// pRemoteTarget - provides the host name
-//
-// Return Value:
-// Returns the IPv4 address of the target machine.
-// Throws on errors.
-//
-
-DWORD ShimProcess::ResolveHostName(ICorDebugRemoteTarget * pRemoteTarget)
-{
- DWORD dwIPAddress = 0;
- return dwIPAddress;
-}
//---------------------------------------------------------------------------------------
//
diff --git a/src/dlls/dbgshim/CMakeLists.txt b/src/dlls/dbgshim/CMakeLists.txt
index 5b0f767a5d..7eef457bc7 100644
--- a/src/dlls/dbgshim/CMakeLists.txt
+++ b/src/dlls/dbgshim/CMakeLists.txt
@@ -31,6 +31,7 @@ endif(CLR_CMAKE_PLATFORM_LINUX)
add_library(dbgshim SHARED ${DBGSHIM_SOURCES})
set(DBGSHIM_LIBRARIES
+ debug-pal
debugshim
corguids
dbgutil
diff --git a/src/dlls/dbgshim/dbgshim.cpp b/src/dlls/dbgshim/dbgshim.cpp
index 5519234bd7..aa972d8d2f 100644
--- a/src/dlls/dbgshim/dbgshim.cpp
+++ b/src/dlls/dbgshim/dbgshim.cpp
@@ -26,8 +26,12 @@
#include <getproductversionnumber.h>
#include <dbgenginemetrics.h>
+#if defined(FEATURE_PAL)
+#include "debug-pal.h"
+#else
#define PSAPI_VERSION 2
#include <psapi.h>
+#endif
#include "dbgshim.h"
@@ -587,7 +591,7 @@ BYTE* GetRemoteModuleBaseAddress(DWORD dwPID, LPCWSTR szFullModulePath)
ThrowHR(HRESULT_FROM_WIN32(GetLastError()));
}
- DWORD countModules = cbNeeded/sizeof(HMODULE);
+ DWORD countModules = min(cbNeeded, sizeof(modules)) / sizeof(HMODULE);
for(DWORD i = 0; i < countModules; i++)
{
WCHAR modulePath[MAX_PATH];
@@ -623,6 +627,7 @@ const int c_iMaxVersionStringLen = 8 + 1 + 8 + 1 + 16; // 64-bit hmodule
const int c_iMinVersionStringLen = 8 + 1 + 8 + 1 + 8; // 32-bit hmodule
const int c_idxFirstSemi = 8;
const int c_idxSecondSemi = 17;
+const WCHAR *c_versionStrFormat = W("%08x;%08x;%p");
//-----------------------------------------------------------------------------
// Public API.
@@ -640,6 +645,7 @@ const int c_idxSecondSemi = 17;
// S_OK - on success.
// E_INVALIDARG -
// HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER) if the buffer is too small.
+// COR_E_FILENOTFOUND - module is not found in a given debugee process
//
// Notes:
// The null-terminated version string including null, is
@@ -680,34 +686,42 @@ HRESULT CreateVersionStringFromModule(DWORD pidDebuggee,
}
else if (pBuffer != NULL)
{
-#ifndef FEATURE_PAL
+
HRESULT hr = S_OK;
EX_TRY
{
CorDebugInterfaceVersion dbiVersion = CorDebugInvalidVersion;
- DWORD pid = pidDebuggee;
-
+ BYTE* hmodTargetCLR = NULL;
+#ifndef FEATURE_PAL
CLR_ENGINE_METRICS metricsStruct;
GetTargetCLRMetrics(szModuleName, &metricsStruct); // throws
dbiVersion = (CorDebugInterfaceVersion) metricsStruct.dwDbiVersion;
- BYTE* hmodTargetCLR = GetRemoteModuleBaseAddress(pidDebuggee, szModuleName); // throws
+ hmodTargetCLR = GetRemoteModuleBaseAddress(pidDebuggee, szModuleName); // throws
+#else
+ //TODO: So far on POSIX systems we only support one version of debugging interface
+ // in future we might want to detect it the same way we do it on Windows.
+ dbiVersion = CorDebugLatestVersion;
+ hmodTargetCLR = (BYTE *)GetDynamicLibraryAddressInProcess(pidDebuggee, MAKEDLLNAME_A(MAIN_CLR_MODULE_NAME_A));
+#endif // FEATURE_PAL
- swprintf_s(pBuffer, cchBuffer, W("%08x;%08x;%p"), dbiVersion, pid, hmodTargetCLR);
+ if (hmodTargetCLR == NULL)
+ {
+ hr = COR_E_FILENOTFOUND;
+ }
+ else
+ {
+ swprintf_s(pBuffer, cchBuffer, c_versionStrFormat, dbiVersion, pidDebuggee, hmodTargetCLR);
+ }
}
EX_CATCH_HRESULT(hr);
return hr;
-#else
- swprintf_s(pBuffer, cchBuffer, W("%08x"), pidDebuggee);
-#endif // FEATURE_PAL
}
return S_OK;
}
-#ifndef FEATURE_PAL
-
// Functions that we'll look for in the loaded Mscordbi module.
typedef HRESULT (STDAPICALLTYPE *FPCoreCLRCreateCordbObject)(
int iDebuggerVersion,
@@ -744,9 +758,8 @@ HRESULT ParseVersionString(LPCWSTR szDebuggeeVersion, CorDebugInterfaceVersion *
return E_INVALIDARG;
}
-
- int numFieldsAssigned = swscanf_s(szDebuggeeVersion, W("%08x;%08x;%p;"), piDebuggerVersion, pdwPidDebuggee,
- phmodTargetCLR);
+ int numFieldsAssigned = swscanf_s(szDebuggeeVersion, c_versionStrFormat, piDebuggerVersion, pdwPidDebuggee, phmodTargetCLR);
+
if (numFieldsAssigned != 3)
{
return E_FAIL;
@@ -755,6 +768,7 @@ HRESULT ParseVersionString(LPCWSTR szDebuggeeVersion, CorDebugInterfaceVersion *
return S_OK;
}
+#ifndef FEATURE_PAL
//-----------------------------------------------------------------------------
// Appends "\mscordbi.dll" to the path. This converts a directory name into the full path to mscordbi.dll.
//
@@ -901,7 +915,7 @@ HRESULT CreateDebuggingInterfaceFromVersionEx(
*ppCordb = NULL;
-#ifndef FEATURE_PAL
+
//
// Step 1: Parse version information into internal data structures
//
@@ -914,6 +928,7 @@ HRESULT CreateDebuggingInterfaceFromVersionEx(
if (FAILED(hr))
goto Exit;
+#ifndef FEATURE_PAL
//
// Step 2: Find the proper Dbi module (mscordbi.dll) and load it.
//
@@ -980,13 +995,13 @@ HRESULT CreateDebuggingInterfaceFromVersionEx(
hr = CORDBG_E_DEBUG_COMPONENT_MISSING;
goto Exit;
}
- FPCreateCordbObject fpCreate = (FPCreateCordbObject)GetProcAddress(hMod, "CreateCordbObject");
- if (fpCreate == NULL)
+ FPCoreCLRCreateCordbObject fpCreate2 = (FPCoreCLRCreateCordbObject)GetProcAddress(hMod, "CoreCLRCreateCordbObject");
+ if (hmodTargetCLR == NULL || fpCreate2 == NULL)
{
hr = CORDBG_E_INCOMPATIBLE_PROTOCOL;
goto Exit;
}
- hr = fpCreate(iDebuggerVersion, &pCordb);
+ hr = fpCreate2(iDebuggerVersion, pidDebuggee, hmodTargetCLR, &pCordb);
}
#endif // FEATURE_PAL
_ASSERTE((pCordb == NULL) == FAILED(hr));
diff --git a/src/dlls/dbgshim/dbgshim.h b/src/dlls/dbgshim/dbgshim.h
index a4c5d3ee5c..4623e0d344 100644
--- a/src/dlls/dbgshim/dbgshim.h
+++ b/src/dlls/dbgshim/dbgshim.h
@@ -9,28 +9,28 @@
#include <windows.h>
-HRESULT GetStartupNotificationEvent(DWORD debuggeePID,
+EXTERN_C HRESULT GetStartupNotificationEvent(DWORD debuggeePID,
__out HANDLE* phStartupEvent);
-HRESULT CloseCLREnumeration(HANDLE* pHandleArray, LPWSTR* pStringArray, DWORD dwArrayLength);
+EXTERN_C HRESULT CloseCLREnumeration(HANDLE* pHandleArray, LPWSTR* pStringArray, DWORD dwArrayLength);
-HRESULT EnumerateCLRs(DWORD debuggeePID,
+EXTERN_C HRESULT EnumerateCLRs(DWORD debuggeePID,
__out HANDLE** ppHandleArrayOut,
__out LPWSTR** ppStringArrayOut,
__out DWORD* pdwArrayLengthOut);
-HRESULT CreateVersionStringFromModule(DWORD pidDebuggee,
+EXTERN_C HRESULT CreateVersionStringFromModule(DWORD pidDebuggee,
LPCWSTR szModuleName,
__out_ecount_part(cchBuffer, *pdwLength) LPWSTR pBuffer,
DWORD cchBuffer,
__out DWORD* pdwLength);
-HRESULT CreateDebuggingInterfaceFromVersionEx(
+EXTERN_C HRESULT CreateDebuggingInterfaceFromVersionEx(
int iDebuggerVersion,
LPCWSTR szDebuggeeVersion,
IUnknown ** ppCordb);
-HRESULT CreateDebuggingInterfaceFromVersion(
+EXTERN_C HRESULT CreateDebuggingInterfaceFromVersion(
LPCWSTR szDebuggeeVersion,
IUnknown ** ppCordb);
diff --git a/src/inc/MSCOREE.IDL b/src/inc/MSCOREE.IDL
index ddb326b8ce..cbb055c138 100644
--- a/src/inc/MSCOREE.IDL
+++ b/src/inc/MSCOREE.IDL
@@ -272,6 +272,7 @@ cpp_quote("EXTERN_GUID(IID_ITypeNameFactory, 0xB81FF171, 0x20F3, 0x11d2, 0x8d, 0
#pragma midl_echo("DEPRECATED_CLR_STDAPI LoadStringRCEx(LCID lcid, UINT iResouceID, _Out_writes_z_(iMax) LPWSTR szBuffer, int iMax, int bQuiet, int *pcwchUsed);")
#endif
+#ifndef FEATURE_CORECLR
// Ideally we would like to make the function pointer definition below as DEPRECATED_CLR_STDAPI. However,
// since it is referenced in the following definition of LockClrVersion, it will result in a build failure
// in our own build (since we treat warnings as errors).
@@ -283,6 +284,9 @@ cpp_quote("EXTERN_GUID(IID_ITypeNameFactory, 0xB81FF171, 0x20F3, 0x11d2, 0x8d, 0
#pragma midl_echo("DEPRECATED_CLR_STDAPI LockClrVersion(FLockClrVersionCallback hostCallback,FLockClrVersionCallback *pBeginHostSetup,FLockClrVersionCallback *pEndHostSetup);")
#pragma midl_echo("DEPRECATED_CLR_STDAPI CreateDebuggingInterfaceFromVersion(int iDebuggerVersion, LPCWSTR szDebuggeeVersion, IUnknown ** ppCordb);")
#pragma midl_echo("DEPRECATED_CLR_STDAPI GetVersionFromProcess(HANDLE hProcess, _Out_writes_to_(cchBuffer, *pdwLength) LPWSTR pVersion, DWORD cchBuffer, _Out_ DWORD* dwLength);")
+#endif
+
+
#ifdef FEATURE_CORECLR
#pragma midl_echo("typedef HRESULT (STDAPICALLTYPE *FnGetCLRRuntimeHost)(REFIID riid, IUnknown **pUnk);")
#endif
diff --git a/src/pal/inc/rt/palrt.h b/src/pal/inc/rt/palrt.h
index 10e9f13400..1d6344d969 100644
--- a/src/pal/inc/rt/palrt.h
+++ b/src/pal/inc/rt/palrt.h
@@ -878,8 +878,8 @@ Remember to fix the errcode defintion in safecrt.h.
#define _vsnwprintf_s _vsnwprintf_unsafe
#define _snprintf_s _snprintf_unsafe
#define _vsnprintf_s _vsnprintf_unsafe
-#define swscanf_s _swscanf_unsafe
-#define sscanf_s _sscanf_unsafe
+#define swscanf_s swscanf
+#define sscanf_s sscanf
#define _wfopen_s _wfopen_unsafe
#define fopen_s _fopen_unsafe
@@ -1022,77 +1022,6 @@ inline int __cdecl _snprintf_unsafe(char *_Dst, size_t _SizeInWords, size_t _Cou
return ret;
}
-inline int __cdecl _swscanf_unsafe(const wchar_t *_Dst, const wchar_t *_Format,...)
-{
- int ret;
- va_list _ArgList;
- va_start(_ArgList, _Format);
- wchar_t *tempFormat;
-
- tempFormat = (wchar_t*) _Format;
-
- while (*tempFormat != L'\0') {
-
- if (*tempFormat == L'%') {
-
- //
- // If scanf takes parameters other than numbers, return error.
- //
-
- if (! ((*(tempFormat+1)==L'x') || (*(tempFormat+1)==L'd') ||
- (*(tempFormat+1)==L'X') || (*(tempFormat+1)==L'D')) ) {
-
- _ASSERTE(FALSE);
- return -1;
-
- }
- }
-
- tempFormat++;
- }
-
- ret = swscanf(_Dst, _Format, _ArgList);
- va_end(_ArgList);
- return ret;
-}
-
-inline int __cdecl _sscanf_unsafe(const char *_Dst, const char *_Format,...)
-{
- int ret;
- char *tempFormat;
-
- va_list _ArgList;
- va_start(_ArgList, _Format);
-
- tempFormat = (char*) _Format;
-
- while (*tempFormat != '\0') {
-
- if (*tempFormat == '%') {
-
- //
- // If scanf takes parameters other than numbers, return error.
- //
-
- if (! ((*(tempFormat+1)=='x') || (*(tempFormat+1)=='d') ||
- (*(tempFormat+1)=='X') || (*(tempFormat+1)=='D')) ) {
-
- _ASSERTE(FALSE);
- return -1;
-
- }
- }
-
- tempFormat++;
- }
-
-
- ret = sscanf(_Dst, _Format, _ArgList);
- va_end(_ArgList);
-
- return ret;
-}
-
inline errno_t __cdecl _wfopen_unsafe(FILE * *ff, const wchar_t *fileName, const wchar_t *mode)
{
FILE *result = _wfopen(fileName, mode);
diff --git a/src/pal/prebuilt/inc/mscoree.h b/src/pal/prebuilt/inc/mscoree.h
index a526da58b6..a725eda75e 100644
--- a/src/pal/prebuilt/inc/mscoree.h
+++ b/src/pal/prebuilt/inc/mscoree.h
@@ -4,7 +4,6 @@
//
-
/* this ALWAYS GENERATED file contains the definitions for the interfaces */
@@ -236,7 +235,7 @@ struct IActivationFactory;
#define CLR_MINOR_VERSION ( 0 )
-#define CLR_BUILD_VERSION ( 22719 )
+#define CLR_BUILD_VERSION ( 22828 )
#define CLR_ASSEMBLY_MAJOR_VERSION ( 4 )
@@ -279,10 +278,6 @@ DEPRECATED_CLR_STDAPI CallFunctionShim(LPCWSTR szDllName, LPCSTR szFunctionName,
DEPRECATED_CLR_STDAPI GetRealProcAddress(LPCSTR pwszProcName, VOID** ppv);
DECLARE_DEPRECATED void STDMETHODCALLTYPE CorExitProcess(int exitCode);
DEPRECATED_CLR_STDAPI LoadStringRC(UINT iResouceID, _Out_writes_z_(iMax) LPWSTR szBuffer, int iMax, int bQuiet);
-typedef HRESULT (__stdcall *FLockClrVersionCallback) ();
-DEPRECATED_CLR_STDAPI LockClrVersion(FLockClrVersionCallback hostCallback,FLockClrVersionCallback *pBeginHostSetup,FLockClrVersionCallback *pEndHostSetup);
-DEPRECATED_CLR_STDAPI CreateDebuggingInterfaceFromVersion(int iDebuggerVersion, LPCWSTR szDebuggeeVersion, IUnknown ** ppCordb);
-DEPRECATED_CLR_STDAPI GetVersionFromProcess(HANDLE hProcess, _Out_writes_to_(cchBuffer, *pdwLength) LPWSTR pVersion, DWORD cchBuffer, _Out_ DWORD* dwLength);
typedef HRESULT (STDAPICALLTYPE *FnGetCLRRuntimeHost)(REFIID riid, IUnknown **pUnk);
typedef /* [public] */
enum __MIDL___MIDL_itf_mscoree_0000_0000_0001