#include "stdafx.h" #include #include "corhdr.h" #include "cor.h" #include "corhlpr.h" #include "corprof.h" #include "cordebug.h" #include "SimpleException.h" #include "utils.h" #define STRING_BUFFER_LEN 1024 int die (char const * szError, HRESULT hr) { fprintf (stderr, "\nDIE: %s\n", szError); fflush (stderr); if (hr != S_OK) { IErrorInfo * pIErr = NULL; BSTR bstrDesc = NULL; fprintf (stderr, "HRESULT = 0x%08x\n", hr); if (GetErrorInfo (0, &pIErr) == S_OK && pIErr->GetDescription (&bstrDesc) == S_OK) { fprintf (stderr, "%ls", bstrDesc); fflush (stderr); SysFreeString (bstrDesc); } if (pIErr) pIErr->Release(); } CoUninitialize(); exit (hr); } int show_trace (char * str, va_list marker) { CQuickBytes buffer; int count = -1; int i = 1; while (count < 0) { # if _MSC_VER < 1400 HRESULT hr; if (FAILED(hr = buffer.ReSize (STRING_BUFFER_LEN * i))) die("Resize failed.", hr); #else buffer.ReSizeThrows (STRING_BUFFER_LEN * i); #endif count = _vsnprintf ((char *) buffer.Ptr(), STRING_BUFFER_LEN * i, str, marker); i *= 2; } fprintf (stderr, "%s", (char *) buffer.Ptr()); return count; } int show_trace (char * str, ...) { va_list marker; int count; va_start (marker, str); count = show_trace (str, marker); va_end (marker); fflush (stderr); return count; } int show_traceln (char * str, ...) { va_list marker; int count; va_start (marker, str); count = show_trace (str, marker); va_end (marker); fprintf (stderr, "\n"); fflush (stderr); return count; } #define DEBUG_ENVIRONMENT "DBG_PRF" #define MAX_LENGTH 256 #define _DbgBreak() __asm { int 3 } void Failure (char *message) { if (message == NULL) message = "**** SEVERE FAILURE: TURNING OFF APPLICABLE PROFILING EVENTS ****"; // // Display the error message and turn off the profiler events except the // IMMUTABLE ones. Turning off the IMMUTABLE events can cause crashes. The only // place that we can safely enable or disable immutable events is the Initialize // callback. // TEXT_OUTLN (message); } // PrfInfo::Failure int String2Number (char * number) { WCHAR ch; int base; int iIndex = 1; BOOL errorOccurred = FALSE; // check to see if this is a valid number // if the first digit is '0', then this is // a hex or octal number if (number[0] == '0') { // // hex // if ((number[1] == 'x') || (number[1] == 'X')) { iIndex++; base = 16; while ((errorOccurred == FALSE) && ((ch = number[iIndex++]) != '\0')) { if (((ch >= '0') && (ch <= '9')) || ((ch >= 'a') && (ch <= 'f')) || ((ch >= 'A') && (ch <= 'F'))) continue; else errorOccurred = TRUE; } } // // octal // else { base = 8; while ((errorOccurred == FALSE) && ((ch = number[iIndex++]) != '\0')) { if ((ch >= '0') && (ch <= '7')) continue; else errorOccurred = TRUE; } } } // // decimal // else { base = 10; while ((errorOccurred == FALSE) && ((ch = number[iIndex++]) != '\0')) { if ((ch >= '0') && (ch <= '9')) continue; else errorOccurred = TRUE; } } return ((errorOccurred == TRUE) ? -1 : base); } DWORD GetEnvVarValue (char *value) { int base = String2Number (value); return (base != -1) ? (DWORD) strtoul (value, NULL, base) : -1; } DWORD FetchEnvironment (const char *environment) { DWORD retVal = -1; char buffer[MAX_LENGTH]; return (GetEnvironmentVariableA (environment, buffer, MAX_LENGTH) > 0 ) ? GetEnvVarValue (buffer) : -1; } void LaunchDebugger (const char *szMsg, const char *szFile, int iLine) { static DWORD launchDebugger = FetchEnvironment (DEBUG_ENVIRONMENT); if ((launchDebugger >= 1) && (launchDebugger != 0xFFFFFFFF)) { char title[MAX_LENGTH]; char message[MAX_LENGTH]; sprintf (message, "%s\n\n" \ "File: %s\n" \ "Line: %d\n", ((szMsg == NULL) ? "FAILURE" : szMsg), szFile, iLine); sprintf (title, "Test Failure (PID: %d/0x%08x, Thread: %d/0x%08x) ", GetCurrentProcessId(), GetCurrentProcessId(), GetCurrentThreadId(), GetCurrentThreadId()); switch (MessageBoxA (NULL, message, title, (MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION))) { case IDABORT: TerminateProcess (GetCurrentProcess(), 999 /* bad exit code */ ); break; case IDRETRY: _DbgBreak(); case IDIGNORE: break; } // switch } } // BASEHELPER::LaunchDebugger mdTypeRef get_type_token (IMetaDataEmit * pMetaDataEmit, LPCWSTR assembly_name, unsigned short major_version, unsigned short minor_version, unsigned short release, unsigned short revision, BYTE k0, BYTE k1, BYTE k2, BYTE k3, BYTE k4, BYTE k5, BYTE k6, BYTE k7, LPCWSTR type_name) { IMetaDataAssemblyEmit* pMetaDataAssemblyEmit; if (FAILED (pMetaDataEmit->QueryInterface (IID_IMetaDataAssemblyEmit, (void **)&pMetaDataAssemblyEmit))) _THROW_EXCEPTION ("QueryInterface IID_IMetaDataAssemblyEmit failed."); ASSEMBLYMETADATA amd; ZeroMemory (&amd, sizeof (amd)); amd.usMajorVersion = major_version; amd.usMinorVersion = minor_version; amd.usBuildNumber = release; amd.usRevisionNumber = revision; BYTE key [] = {k0, k1, k2, k3, k4, k5, k6, k7}; mdModuleRef module_token; if (FAILED (pMetaDataAssemblyEmit->DefineAssemblyRef (key, sizeof (key), assembly_name, &amd, NULL, 0, 0, &module_token))) _THROW_EXCEPTION ("DefineAssemblyRef failed."); mdTypeRef type_token; if (FAILED (pMetaDataEmit->DefineTypeRefByName (module_token, type_name, &type_token))) _THROW_EXCEPTION ("DefineTypeRefByName failed."); pMetaDataAssemblyEmit->Release(); return type_token; } mdMemberRef signature_no_args (IMetaDataEmit * pMetaDataEmit, mdTypeRef type_ref, LPCWSTR member_name, CorCallingConvention callconv, CorElementType return_type) { BYTE sigblob [] = {callconv, 0x00, //argcount return_type}; mdMemberRef token; if (FAILED (pMetaDataEmit->DefineMemberRef (type_ref, member_name, sigblob, sizeof (sigblob), &token))) _THROW_EXCEPTION ("signature_no_args failed."); return token; } mdMemberRef signature_one_arg (IMetaDataEmit * pMetaDataEmit, mdTypeRef type_ref, LPCWSTR member_name, CorCallingConvention callconv, CorElementType return_type, CorElementType arg_type) { BYTE sigblob [] = {callconv, 0x01, //argcount return_type, arg_type}; mdMemberRef token; if (FAILED (pMetaDataEmit->DefineMemberRef (type_ref, member_name, sigblob, sizeof (sigblob), &token))) _THROW_EXCEPTION ("signature_one_arg failed."); return token; } mdSignature signature_unmanaged_one_arg (IMetaDataEmit * pMetaDataEmit, CorUnmanagedCallingConvention callconv, CorElementType return_type, CorElementType arg_type) { char sigblob [] = {callconv, 0x01, //argcount return_type, arg_type}; mdSignature msig; pMetaDataEmit->GetTokenFromSig ((PCCOR_SIGNATURE)sigblob, sizeof (sigblob), &msig); return msig; }