320 lines
9.0 KiB
C++
320 lines
9.0 KiB
C++
#include "stdafx.h"
|
|
#include <stdio.h>
|
|
#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;
|
|
}
|