You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
507 lines
11 KiB
507 lines
11 KiB
///////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 1998, Microsoft Corp. All rights reserved.
|
|
//
|
|
// FILE
|
|
//
|
|
// iastrace.cpp
|
|
//
|
|
// SYNOPSIS
|
|
//
|
|
// Defines the API into the SA trace facility.
|
|
//
|
|
// MODIFICATION HISTORY
|
|
//
|
|
// 08/18/1998 Original version.
|
|
// 01/27/1999 Stolen from IAS Project
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <windows.h>
|
|
#include <rtutils.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
//
|
|
// trace libarary name
|
|
//
|
|
const TCHAR TRACE_LIBRARY [] = TEXT ("rtutils.dll");
|
|
|
|
const DWORD MAX_DEBUGSTRING_LENGTH = 512;
|
|
|
|
//
|
|
// tracing library method names
|
|
//
|
|
const char TRACE_REGISTER_FUNC[] = "TraceRegisterExW";
|
|
const char TRACE_DEREGISTER_FUNC[] = "TraceDeregisterW";
|
|
const char TRACE_VPRINTF_FUNC[] = "TraceVprintfExA";
|
|
const char TRACE_PUTS_FUNC[] = "TracePutsExA";
|
|
const char TRACE_DUMP_FUNC[] = "TraceDumpExA";
|
|
|
|
//
|
|
// signatures of methods in rtutils.dll
|
|
//
|
|
typedef DWORD (*PTRACE_REGISTER_FUNC) (
|
|
LPCWSTR lpszCallerName,
|
|
DWORD dwFlags
|
|
);
|
|
|
|
typedef DWORD (*PTRACE_DEREGISTER_FUNC) (
|
|
DWORD dwTraceID
|
|
);
|
|
|
|
typedef DWORD (*PTRACE_VPRINTF_FUNC) (
|
|
DWORD dwTraceID,
|
|
DWORD dwFlags,
|
|
LPCSTR lpszFormat,
|
|
va_list arglist
|
|
);
|
|
|
|
typedef DWORD (*PTRACE_PUTS_FUNC) (
|
|
DWORD dwTraceID,
|
|
DWORD dwFlags,
|
|
LPCSTR lpszString
|
|
);
|
|
|
|
typedef DWORD (*PTRACE_DUMP_FUNC) (
|
|
DWORD dwTraceID,
|
|
DWORD dwFlags,
|
|
LPBYTE lpBytes,
|
|
DWORD dwByteCount,
|
|
DWORD dwGroupSize,
|
|
BOOL bAddressPrefix,
|
|
LPCSTR lpszPrefix
|
|
);
|
|
|
|
//
|
|
// pointer to the functsion in rtutils.dll
|
|
//
|
|
PTRACE_REGISTER_FUNC pfnTraceRegisterExW = NULL;
|
|
PTRACE_DEREGISTER_FUNC pfnTraceDeregisterW = NULL;
|
|
PTRACE_VPRINTF_FUNC pfnTraceVprintfExA = NULL;
|
|
PTRACE_PUTS_FUNC pfnTracePutsExA = NULL;
|
|
PTRACE_DUMP_FUNC pfnTraceDumpExA = NULL;
|
|
|
|
//
|
|
// flags specifies that the tracing is being done for the first time
|
|
//
|
|
BOOL fFirstTime = TRUE;
|
|
|
|
//
|
|
// this flag is used to signify whether Trace DLL is initialized
|
|
// no tracing is done if DLL is not initialized
|
|
//
|
|
BOOL fInitDLL = FALSE;
|
|
|
|
//
|
|
// new line char
|
|
//
|
|
CHAR NEWLINE[] = "\n";
|
|
|
|
//////////
|
|
// Flags passed for all trace calls.
|
|
//////////
|
|
#define SA_TRACE_FLAGS (0x00010000 | TRACE_USE_MASK | TRACE_USE_MSEC)
|
|
|
|
//////////
|
|
// Trace ID for this module.
|
|
//////////
|
|
DWORD dwTraceID = INVALID_TRACEID;
|
|
|
|
//////////
|
|
// Flag indicating whether the API has been registered.
|
|
//////////
|
|
BOOL fRegistered = FALSE;
|
|
|
|
//////////
|
|
// Non-zero if the registration code is locked.
|
|
//////////
|
|
LONG lLocked = 0;
|
|
|
|
//////////
|
|
// Macros to lock/unlock the registration code.
|
|
//////////
|
|
#define LOCK_TRACE() \
|
|
while (InterlockedExchange(&lLocked, 1)) Sleep(5)
|
|
|
|
#define UNLOCK_TRACE() \
|
|
InterlockedExchange(&lLocked, 0)
|
|
|
|
//
|
|
// signature of method used to initialize trace DLL
|
|
//
|
|
VOID InitializeTraceDLL(
|
|
VOID
|
|
);
|
|
|
|
//////////
|
|
// Formats an error message from the system message table.
|
|
//////////
|
|
DWORD
|
|
WINAPI
|
|
SAFormatSysErr(
|
|
DWORD dwError,
|
|
PSTR lpBuffer,
|
|
DWORD nSize
|
|
)
|
|
{
|
|
DWORD nChar;
|
|
|
|
// Attempt to format the message using the system message table.
|
|
nChar = FormatMessageA(
|
|
FORMAT_MESSAGE_FROM_SYSTEM,
|
|
NULL,
|
|
dwError,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
lpBuffer,
|
|
nSize,
|
|
NULL
|
|
);
|
|
|
|
if (nChar > 0)
|
|
{
|
|
// Format succeeded, so strip any trailing newline and exit.
|
|
if (lpBuffer[nChar - 1] == '\n')
|
|
{
|
|
--nChar;
|
|
lpBuffer[nChar] = '\0';
|
|
|
|
if (lpBuffer[nChar - 1] == '\r')
|
|
{
|
|
--nChar;
|
|
lpBuffer[nChar] = '\0';
|
|
}
|
|
}
|
|
|
|
goto exit;
|
|
}
|
|
|
|
// Only error condition we can handle is when the message is not found.
|
|
if (GetLastError() != ERROR_MR_MID_NOT_FOUND)
|
|
{
|
|
goto exit;
|
|
}
|
|
|
|
// Do we have enough space for the fallback error message ?
|
|
if (nSize < 25)
|
|
{
|
|
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
|
|
|
goto exit;
|
|
}
|
|
|
|
// No entry in the message table, so just format the raw error code.
|
|
nChar = wsprintfA(lpBuffer, "Unknown error 0x%0lX", dwError);
|
|
|
|
exit:
|
|
return nChar;
|
|
}
|
|
|
|
//////////
|
|
// Deregisters the module.
|
|
//////////
|
|
VOID
|
|
__cdecl
|
|
SATraceDeregister( VOID )
|
|
{
|
|
if (NULL != pfnTraceDeregisterW)
|
|
{
|
|
pfnTraceDeregisterW(dwTraceID);
|
|
}
|
|
|
|
LOCK_TRACE();
|
|
fRegistered = FALSE;
|
|
UNLOCK_TRACE();
|
|
}
|
|
|
|
//////////
|
|
// Registers the module.
|
|
//////////
|
|
VOID
|
|
WINAPI
|
|
SATraceRegister( VOID )
|
|
{
|
|
LONG state;
|
|
DWORD status;
|
|
MEMORY_BASIC_INFORMATION mbi;
|
|
WCHAR filename[MAX_PATH + 1], *basename, *suffix;
|
|
|
|
|
|
if ((fRegistered) || (NULL == pfnTraceRegisterExW))
|
|
{
|
|
return;
|
|
}
|
|
|
|
LOCK_TRACE();
|
|
|
|
|
|
//////////
|
|
// Now that we have the lock, double check that we need to register.
|
|
//////////
|
|
|
|
//////////
|
|
// Find the base address of this module.
|
|
//////////
|
|
|
|
status = VirtualQuery(
|
|
SATraceRegister,
|
|
&mbi,
|
|
sizeof(mbi)
|
|
);
|
|
if (status == 0) { goto exit; }
|
|
|
|
//////////
|
|
// Get the module filename.
|
|
//////////
|
|
|
|
status = GetModuleFileNameW(
|
|
(HINSTANCE)mbi.AllocationBase,
|
|
filename,
|
|
MAX_PATH
|
|
);
|
|
if (status == 0) { goto exit; }
|
|
|
|
//////////
|
|
// Strip everything before the last backslash.
|
|
//////////
|
|
|
|
basename = wcsrchr(filename, L'\\');
|
|
if (basename == NULL)
|
|
{
|
|
basename = filename;
|
|
}
|
|
else
|
|
{
|
|
++basename;
|
|
}
|
|
|
|
//////////
|
|
// Strip everything after the last dot.
|
|
//////////
|
|
|
|
suffix = wcsrchr(basename, L'.');
|
|
if (suffix)
|
|
{
|
|
*suffix = L'\0';
|
|
}
|
|
|
|
//////////
|
|
// Convert to uppercase.
|
|
//////////
|
|
|
|
_wcsupr(basename);
|
|
|
|
//////////
|
|
// Register the module.
|
|
//////////
|
|
|
|
dwTraceID = pfnTraceRegisterExW(basename, 0);
|
|
if (dwTraceID != INVALID_TRACEID)
|
|
{
|
|
fRegistered = TRUE;
|
|
|
|
|
|
//////////
|
|
// Deregister when we exit.
|
|
//////////
|
|
|
|
atexit(SATraceDeregister);
|
|
}
|
|
exit:
|
|
UNLOCK_TRACE();
|
|
}
|
|
|
|
VOID
|
|
WINAPIV
|
|
SATracePrintf(
|
|
IN PCSTR szFormat,
|
|
...
|
|
)
|
|
{
|
|
va_list marker;
|
|
|
|
#if (defined (DEBUG) || defined (_DEBUG))
|
|
//
|
|
// in case of debug build always output the output string
|
|
//
|
|
CHAR szDebugString[MAX_DEBUGSTRING_LENGTH +1];
|
|
va_start(marker, szFormat);
|
|
_vsnprintf (szDebugString, MAX_DEBUGSTRING_LENGTH, szFormat, marker);
|
|
szDebugString[MAX_DEBUGSTRING_LENGTH] = '\0';
|
|
OutputDebugString (szDebugString);
|
|
OutputDebugString (NEWLINE);
|
|
va_end(marker);
|
|
#endif // (defined (DEBUG) || defined (_DEBUG)
|
|
|
|
if (fFirstTime) {InitializeTraceDLL();}
|
|
|
|
if (!fInitDLL) {return;}
|
|
|
|
SATraceRegister();
|
|
|
|
if ((fRegistered) && (NULL != pfnTraceVprintfExA))
|
|
{
|
|
va_start(marker, szFormat);
|
|
pfnTraceVprintfExA(
|
|
dwTraceID,
|
|
SA_TRACE_FLAGS,
|
|
szFormat,
|
|
marker
|
|
);
|
|
va_end(marker);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
WINAPI
|
|
SATraceString(
|
|
IN PCSTR szString
|
|
)
|
|
{
|
|
|
|
#if (defined (DEBUG) || defined (_DEBUG))
|
|
//
|
|
// in case of debug build always output the output string
|
|
//
|
|
OutputDebugString (szString);
|
|
OutputDebugString (NEWLINE);
|
|
#endif // (defined (DEBUG) || defined (_DEBUG)
|
|
|
|
if (fFirstTime) {InitializeTraceDLL();}
|
|
|
|
if (!fInitDLL) {return;}
|
|
|
|
SATraceRegister();
|
|
|
|
if ((fRegistered) && (NULL != pfnTracePutsExA))
|
|
{
|
|
pfnTracePutsExA(
|
|
dwTraceID,
|
|
SA_TRACE_FLAGS,
|
|
szString
|
|
);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
WINAPI
|
|
SATraceBinary(
|
|
IN CONST BYTE* lpbBytes,
|
|
IN DWORD dwByteCount
|
|
)
|
|
{
|
|
if (fFirstTime) {InitializeTraceDLL();}
|
|
|
|
if (!fInitDLL) {return;}
|
|
|
|
SATraceRegister();
|
|
|
|
if ((fRegistered) && (NULL != pfnTraceDumpExA))
|
|
{
|
|
pfnTraceDumpExA(
|
|
dwTraceID,
|
|
SA_TRACE_FLAGS,
|
|
(LPBYTE)lpbBytes,
|
|
dwByteCount,
|
|
1,
|
|
FALSE,
|
|
NULL
|
|
);
|
|
}
|
|
}
|
|
|
|
VOID
|
|
WINAPI
|
|
SATraceFailure(
|
|
IN PCSTR szFunction,
|
|
IN DWORD dwError
|
|
)
|
|
{
|
|
CHAR szMessage[256];
|
|
DWORD nChar;
|
|
|
|
nChar = SAFormatSysErr(
|
|
dwError,
|
|
szMessage,
|
|
sizeof(szMessage)
|
|
);
|
|
|
|
szMessage[nChar] = '\0';
|
|
|
|
SATracePrintf("%s failed: %s\n", szFunction, szMessage);
|
|
|
|
}
|
|
|
|
//
|
|
// this is the internal trace method used to initialize platform specific
|
|
// stuff
|
|
|
|
VOID InitializeTraceDLL(
|
|
VOID
|
|
)
|
|
{
|
|
OSVERSIONINFO OsInfo;
|
|
HINSTANCE hInst = NULL;
|
|
DWORD dwSize = sizeof (OSVERSIONINFO);
|
|
|
|
LOCK_TRACE ();
|
|
|
|
do
|
|
{
|
|
if (!fFirstTime) {break;}
|
|
|
|
fFirstTime = FALSE;
|
|
|
|
//
|
|
// check the platform we are running in
|
|
//
|
|
ZeroMemory (&OsInfo, dwSize);
|
|
OsInfo.dwOSVersionInfoSize = dwSize;
|
|
if (!GetVersionEx (&OsInfo)) {break;}
|
|
|
|
//
|
|
// no tracing if this is not NT
|
|
//
|
|
if (VER_PLATFORM_WIN32_NT != OsInfo.dwPlatformId) {break;}
|
|
|
|
//
|
|
// Load the trace library (rtutils.dll)
|
|
//
|
|
hInst = LoadLibrary (TRACE_LIBRARY);
|
|
if (NULL == hInst) {break;}
|
|
|
|
//
|
|
// get the address of the methods in the DLL
|
|
//
|
|
pfnTraceRegisterExW = (PTRACE_REGISTER_FUNC)
|
|
GetProcAddress (hInst, (LPCSTR)TRACE_REGISTER_FUNC);
|
|
if (NULL == pfnTraceRegisterExW) {break;}
|
|
|
|
pfnTraceDeregisterW = (PTRACE_DEREGISTER_FUNC)
|
|
GetProcAddress (hInst, (LPCSTR)TRACE_DEREGISTER_FUNC);
|
|
if (NULL == pfnTraceDeregisterW) {break;}
|
|
|
|
pfnTraceVprintfExA = (PTRACE_VPRINTF_FUNC)
|
|
GetProcAddress (hInst, (LPCSTR)TRACE_VPRINTF_FUNC);
|
|
if (NULL == pfnTraceVprintfExA) {break;}
|
|
|
|
pfnTracePutsExA = (PTRACE_PUTS_FUNC)
|
|
GetProcAddress (hInst, (LPCSTR)TRACE_PUTS_FUNC);
|
|
if (NULL == pfnTracePutsExA) {break;}
|
|
|
|
pfnTraceDumpExA = (PTRACE_DUMP_FUNC)
|
|
GetProcAddress (hInst, (LPCSTR)TRACE_DUMP_FUNC);
|
|
if (NULL == pfnTraceDumpExA) {break;}
|
|
|
|
//
|
|
// successfully initialized tracing DLL
|
|
//
|
|
fInitDLL = TRUE;
|
|
}
|
|
while (FALSE);
|
|
|
|
UNLOCK_TRACE();
|
|
|
|
return;
|
|
|
|
} // end of InitializeTraceDLL method
|