/* * ++ Copyright (c) 2001 Microsoft Corporation Module Name: tracer.h Abstract: * Retail tracing for WinHttp DLL * Author: S. Ganesh * Environment: Win32 user-mode */ #if defined(__cplusplus) extern "C" { #endif #ifndef ENABLE_DEBUG typedef enum { None, Bool, Int, Dword, String, Handle, Pointer } TRACE_FUNCTION_RETURN_TYPE; #else typedef DEBUG_FUNCTION_RETURN_TYPE TRACE_FUNCTION_RETURN_TYPE; #endif /* Externs: */ class HANDLE_OBJECT; struct TraceValues { long _dwPrefix; LPCSTR _lpszFnName; TRACE_FUNCTION_RETURN_TYPE _ReturnType; TraceValues() : _dwPrefix(-1), _lpszFnName(NULL), _ReturnType(None) { } TraceValues (long dwPrefix, LPCSTR lpszFnName, TRACE_FUNCTION_RETURN_TYPE ReturnType) : _dwPrefix(dwPrefix), _lpszFnName(lpszFnName), _ReturnType(ReturnType) { } }; class CTracer { /* ----------------------------------------------------------------------------------------------------------------------- Statics: ----------------------------------------------------------------------------------------------------------------------- */ private: /* Global-level CTracer instance, instantiated in GlobalDataInitialize(): */ static CTracer *s_pTracer; static BOOL s_bTraceInitialized; static BOOL s_bTraceEnabled; static BOOL s_bApiTraceEnabled; static DWORD s_dwMaxFileSize; public: static CCritSec s_CritSectionTraceInit; /* ----------------------------------------------------------------------------------------------------------------------- Instance: ----------------------------------------------------------------------------------------------------------------------- */ private: DWORD _traceControlFlags; HANDLE _traceFileHandle; DWORD _dwWritten; CRITICAL_SECTION _CriticalSection; static DWORD ReadTraceSettingsDwordKey(IN LPCSTR ParameterName, OUT LPDWORD ParameterValue); static DWORD ReadTraceSettingsStringKey ( IN LPCSTR ParameterName, OUT LPSTR ParameterValue, IN OUT LPDWORD ParameterLength ); /* ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- */ public: static BOOL GlobalTraceInit( BOOL fOverrideRegistryToEnableTracing = FALSE); static BOOL unlockedGlobalTraceInit( BOOL fOverrideRegistryToEnableTracing = FALSE); static void GlobalTraceTerm(void); static void EnableTracing(void) { s_bTraceEnabled = TRUE; } static void DisableTracing(void) { s_bTraceEnabled = FALSE; } static BOOL IsTracingEnabled(void) { return s_bTraceEnabled; } static void EnableApiTracing(void) { s_bApiTraceEnabled = TRUE; } static void DisableApiTracing(void) { s_bApiTraceEnabled = FALSE; } static BOOL IsApiTracingEnabled(void) { return s_bApiTraceEnabled; } static CTracer *GlobalTracer(void) { return s_pTracer; } CTracer(DWORD traceControlFlags); ~CTracer(void); /* ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- */ private: BOOL OpenTraceFile(IN LPSTR Filename); VOID CloseTraceFile(VOID); /* ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- */ public: TraceValues TraceFnEnter ( IN DWORD Category, IN TRACE_FUNCTION_RETURN_TYPE ReturnType, IN LPCSTR Function, IN LPCSTR ParameterList OPTIONAL, IN... ); TraceValues TraceFnEnter2 ( IN DWORD Category, IN TRACE_FUNCTION_RETURN_TYPE ReturnType, IN LPCSTR Function, IN HINTERNET hInternet, IN LPCSTR ParameterList OPTIONAL, IN... ); VOID TraceFnLeave(IN DWORD_PTR Variable, IN TraceValues *pTraceValues); VOID TracePrintError(IN DWORD Error, IN TraceValues *pTraceValues); VOID TracePrint(IN DWORD dwPrefix, IN LPSTR Format, ...); VOID TracePrint2(IN LPSTR Format, ...); VOID TracePrintString(IN LPSTR String, IN long dwPrefix = -1); VOID TraceOut(IN LPSTR Buffer); VOID TraceDump(IN LPSTR Text, IN LPBYTE Address, IN DWORD Size, IN long dwPrefix = -1); DWORD TraceDumpFormat(IN LPBYTE Address, IN DWORD Size, IN DWORD ElementSize, OUT LPSTR Buffer); DWORD TraceDumpText ( IN LPBYTE Address, IN DWORD Size, OUT LPSTR Buffer, IN DWORD BufferSize, IN long dwPrefix = -1 ); /* ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- */ private: static LPSTR TraceSetPrefix(IN LPSTR Buffer, IN long dwPrefix = -1); /* ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- */ private: class CCounter { /* ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- */ private: LONG _dwRef; /* ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- */ public: CCounter() : _dwRef(0) { } DWORD AddOne(void) { return(DWORD)::InterlockedIncrement(&_dwRef); } }; /* ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- */ public: DWORD GetOneUniqueId(void) { return uniqueIdGenerator.AddOne(); } /* =================================================================================================================== Helper, since there's no strnstr in std lib: =================================================================================================================== */ static LPSTR strnstr(LPSTR haystack, int Len, LPCSTR needle) { /*~~~~~~~~~~~~~~~~~~~~~~*/ int found = 0; int need = strlen(needle); int i, start; /*~~~~~~~~~~~~~~~~~~~~~~*/ for(start = i = 0; i < Len; i++) { if(haystack[i] == needle[found]) { if(++found == need) { i -= need - 1; /* beginning of string */ return haystack + i; } } else { found = 0; } } return NULL; } /* ----------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------------------------------------------------------------- */ private: CCounter uniqueIdGenerator; }; #define GLOBAL_TRACER() \ if(CTracer::IsTracingEnabled() && CTracer::GlobalTracer()) \ CTracer::GlobalTracer()-> /* ======================================================================================================================= TRACE_START - initialize debugging support ======================================================================================================================= */ #define TRACE_START() CTracer::GlobalTraceInit() /* ======================================================================================================================= TRACE_FINISH - terminate debugging support ======================================================================================================================= */ #define TRACE_FINISH() CTracer::GlobalTraceTerm() /* ======================================================================================================================= TRACE_ENTER_API - Call when entering an API function ======================================================================================================================= */ #define TRACE_ENTER_API(ParameterList) \ TraceValues a_traceValues; \ if(CTracer::IsTracingEnabled() && CTracer::GlobalTracer()) \ { \ /* * TraceFnEnter has a dual-purpose: one, to return a TraceValues structure after * splitting ParameterList, * and two, to print the FnEnter messages */ \ a_traceValues = CTracer::GlobalTracer()->TraceFnEnter ParameterList; \ } /* ======================================================================================================================= See related DEBUG_ENTER2_API in inetdbg.h ======================================================================================================================= */ #define TRACE_ENTER2_API(ParameterList) \ TraceValues a_traceValues; \ if(CTracer::IsTracingEnabled() && CTracer::GlobalTracer()) \ { \ /* * TraceFnEnter2 has a dual-purpose: one, to return a TraceValues structure after * splitting ParameterList, * and two, to print the FnEnter messages */ \ a_traceValues = CTracer::GlobalTracer()->TraceFnEnter2 ParameterList; \ } #define TRACE_LEAVE_API(Variable) \ if \ ( \ CTracer::IsTracingEnabled() \ && CTracer::GlobalTracer() \ && CTracer::IsApiTracingEnabled() \ ) \ { \ CTracer::GlobalTracer()->TraceFnLeave(Variable, &a_traceValues); \ } /* ======================================================================================================================= TRACE_ERROR - displays an error and its symbolic name ======================================================================================================================= */ #define TRACE_ERROR(Category, Error) \ if \ ( \ CTracer::IsTracingEnabled() \ && CTracer::GlobalTracer() \ && a_traceValues._lpszFnName \ ) \ { \ CTracer::GlobalTracer()->TracePrintError(Error, &a_traceValues); \ } #define TRACE_PRINT_API(Category, ErrorLevel, Args) GLOBAL_TRACER() TracePrint2 Args #define TRACE_DUMP_API(Category, Text, Address, Length, dwPrefix) \ GLOBAL_TRACER() TraceDump \ ( \ Text, \ (LPBYTE) Address, \ Length, \ dwPrefix \ ) #define TRACE_GET_REQUEST_ID() \ CTracer::IsTracingEnabled() \ && CTracer::GlobalTracer() ? CTracer::GlobalTracer()->GetOneUniqueId() : -1 #define TRACE_SET_ID_FROM_HANDLE(hInternet) \ if \ ( \ hInternet \ && CTracer::IsTracingEnabled() \ && CTracer::GlobalTracer() \ && a_traceValues._lpszFnName \ ) \ { \ HINTERNET a_hRequestMapped = NULL; \ if(MapHandleToAddress(hInternet, (LPVOID *) &a_hRequestMapped, FALSE) == ERROR_SUCCESS) \ { \ BOOL a_isLocal; \ BOOL a_isAsync; \ if(RIsHandleLocal(a_hRequestMapped, &a_isLocal, &a_isAsync, TypeHttpRequestHandle) == ERROR_SUCCESS) \ { \ a_traceValues._dwPrefix = ((HTTP_REQUEST_HANDLE_OBJECT *) (a_hRequestMapped))->GetRequestId(); \ } \ DereferenceObject(a_hRequestMapped); \ } \ } #if defined(__cplusplus) } #endif