racket/src/mysterx/dotnet/utils.cpp
2006-06-07 16:55:53 +00:00

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;
}