//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1992 - 1996. // // File: oleprint.cxx // // Contents: printf for API/Method trace // // Functions: oleprintf // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- #include #include #include #include #if DBG==1 #include "outfuncs.h" #include "oleprint.hxx" // *** Constants *** const char *pscTabString = " "; // 3 space tabs // *** Types and Enums *** // Enumeration of basic types enum { TYP_INT = 0, TYP_UNSIGNED, TYP_HEX, TYP_HEXCAPS, TYP_LARGE, TYP_BOOL, TYP_BOOLCAPS, TYP_POINTER, TYP_POINTERCAPS, TYP_HANDLE, TYP_HANDLECAPS, TYP_STR, TYP_WIDESTR, TYP_GUID, TYP_STRUCT, NO_TYPE }; // Type of parameter printing functions typedef void (*ParamFunc) (CTextBufferA &buf, va_list ¶m, char *&ppstr); // Enumeration of Structure types enum { STRUCT_BIND_OPTS=0, STRUCT_DVTARGETDEVICE, STRUCT_FORMATETC, STRUCT_FILETIME, STRUCT_INTERFACEINFO, STRUCT_LOGPALETTE, STRUCT_MSG, STRUCT_OLEINPLACEFRAMEINFO, STRUCT_OLEMENUGROUPWIDTHS, STRUCT_POINT, STRUCT_RECT, STRUCT_STGMEDIUM, STRUCT_STATSTG, STRUCT_SIZE, NO_STRUCT }; // Type of structure printing functions typedef void (*WriteFunc) (CTextBufferA &buf, void *pParam); // *** Prototypes *** // Functions to handle writing out parameters static void WriteInt(CTextBufferA &buf, va_list &, char *&); static void WriteUnsigned(CTextBufferA &buf, va_list &, char *&); static void WriteHex(CTextBufferA &buf, va_list &, char *&); static void WriteHexCaps(CTextBufferA &buf, va_list &, char *&); static void WriteLarge(CTextBufferA &buf, va_list &, char *&); static void WriteBool(CTextBufferA &buf, va_list &, char *&); static void WriteBoolCaps(CTextBufferA &buf, va_list &, char *&); static void WritePointer(CTextBufferA &buf, va_list &, char *&); static void WritePointerCaps(CTextBufferA &buf, va_list &, char *&); static void WriteString(CTextBufferA &buf, va_list &, char *&); static void WriteWideString(CTextBufferA &buf, va_list &, char *&); static void WriteGUID(CTextBufferA &buf, va_list &, char *&); static void WriteStruct(CTextBufferA &buf, va_list &, char *&); // *** Global Data *** char gPidString[20]; // this table holds the functions for writing base types static ParamFunc g_pFuncs[] = {WriteInt, WriteUnsigned, WriteHex, WriteHexCaps, WriteLarge, WriteBool, WriteBoolCaps,WritePointer,WritePointerCaps, WriteHex,WriteHexCaps,WriteString, WriteWideString, WriteGUID, WriteStruct, NULL}; // this table starts at 'A' == 65 // This is the base type lookup table -> tells what kind of base type to print out static const BYTE g_tcLookup[] = {NO_TYPE, TYP_BOOLCAPS, NO_TYPE, TYP_INT, NO_TYPE, // 'A' - 'E' NO_TYPE, NO_TYPE, NO_TYPE, TYP_GUID, NO_TYPE, // 'F' - 'J' NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, // 'K' - 'O' TYP_POINTERCAPS, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, // 'P' - 'T' TYP_UNSIGNED, NO_TYPE, NO_TYPE, TYP_HEXCAPS, NO_TYPE, // 'U' - 'Y' NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, NO_TYPE, // 'Z' - '^' NO_TYPE, NO_TYPE, NO_TYPE, TYP_BOOL, NO_TYPE, // '_' - 'c' TYP_INT, NO_TYPE, NO_TYPE, NO_TYPE, TYP_HANDLE, // 'd' - 'h' NO_TYPE, NO_TYPE, NO_TYPE, TYP_LARGE, NO_TYPE, // 'i' - 'm' NO_TYPE, NO_TYPE, TYP_POINTER, NO_TYPE, NO_TYPE, // 'n' - 'r' TYP_STR, TYP_STRUCT, TYP_UNSIGNED, NO_TYPE, TYP_WIDESTR, // 's' - 'w' TYP_HEX, NO_TYPE, NO_TYPE}; // 'x' - 'z' // This holds the functions for writing out structures static WriteFunc g_pStructFuncs[] = {(WriteFunc) WriteBIND_OPTS, (WriteFunc) WriteDVTARGETDEVICE, (WriteFunc) WriteFORMATETC, (WriteFunc) WriteFILETIME, (WriteFunc) WriteINTERFACEINFO, (WriteFunc) WriteLOGPALETTE, (WriteFunc) WriteMSG, (WriteFunc) WriteOLEINPLACEFRAMEINFO, (WriteFunc) WriteOLEMENUGROUPWIDTHS, (WriteFunc) WritePOINT, (WriteFunc) WriteRECT, (WriteFunc) WriteSTGMEDIUM, (WriteFunc) WriteSTATSTG, (WriteFunc) WriteSIZE, NULL }; // this table starts at 'a' == 97 // this table holds what type of structure to print out static const BYTE g_structLookup[] = {NO_STRUCT, STRUCT_BIND_OPTS, NO_STRUCT, STRUCT_DVTARGETDEVICE, // 'a' - 'd' STRUCT_FORMATETC, STRUCT_FILETIME, NO_STRUCT, NO_STRUCT, // 'e' - 'h' STRUCT_INTERFACEINFO, NO_STRUCT, NO_STRUCT, STRUCT_LOGPALETTE, // 'i' - 'l' STRUCT_MSG, NO_STRUCT, STRUCT_OLEINPLACEFRAMEINFO, STRUCT_POINT,// 'm' - 'p' NO_STRUCT, STRUCT_RECT, STRUCT_STGMEDIUM, STRUCT_STATSTG , // 'q' - 't' NO_STRUCT, NO_STRUCT, STRUCT_OLEMENUGROUPWIDTHS, NO_STRUCT, // 'u' - 'x' NO_STRUCT, STRUCT_SIZE }; // 'y' - 'z' //+--------------------------------------------------------------------------- // // Function: oleprintf // // Synopsis: Prints out trace information using a given function, given a // nesting depth (for indenting), an API/Method name, a format string, // and a variable number of arguments // // Arguments: [depth] - nesting/indentation level // [pscApiName] - name of API/Method traced // [pscFormat] - format string // [argptr] - variable argument list // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void __cdecl oleprintf(int depth, const char *pscApiName, const char *pscFormat, va_list argptr) { // buffer all output so that multithreaded traces look right CTextBufferA buf; char temp[20]; char *pscPos; // first print out the process id buf << gPidString; buf << '.'; // now print out the thread id _itoa(GetCurrentThreadId(), temp, 10); buf << temp; buf << "> "; // tab to nesting/indent depth while(depth-- > 0) { buf << pscTabString; } // now print out API name buf << pscApiName; // now we are ready to print out what was passed pscPos = strchr(pscFormat, '%'); while(pscPos != NULL) { // insert the text up to the found '%' character into the buffer buf.Insert(pscFormat, (int)(pscPos-pscFormat)); if(*(pscPos+1) == '%') // this is '%%', we only print one '%' and don't print an argument { buf << *pscPos; pscFormat = pscPos+2; } else { BYTE argType = NO_TYPE; // advance pscPos to type specifier pscPos++; // we need to take an argument and handle it if(*pscPos >= 'A' && *pscPos <= 'z') { argType = g_tcLookup[*pscPos- 'A']; } if(argType != NO_TYPE) { // handle argument // function will advance pscPos past format specifier g_pFuncs[argType](buf, argptr, pscPos); } else { // assume we've got a one character format specifier pscPos++; // unknown type, assume size of int va_arg(argptr, int); } // advance search pointer past type specifier pscFormat = pscPos; } pscPos = strchr(pscFormat, '%'); } // print out remainder of string buf << pscFormat; // destructor will flush buffer for us } //+--------------------------------------------------------------------------- // // Function: WriteHex // // Synopsis: Prints out a lower case hex value // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WriteHex(CTextBufferA &buf, va_list ¶m, char *&pFormat) { WriteHexCommon(buf, va_arg(param, unsigned long), FALSE); //advance format pointer pFormat++; } //+--------------------------------------------------------------------------- // // Function: WriteHexCaps // // Synopsis: Prints out an upper case hex value // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WriteHexCaps(CTextBufferA &buf, va_list ¶m, char *&pFormat) { WriteHexCommon(buf, va_arg(param, unsigned long), TRUE); //advance format pointer pFormat++; } //+--------------------------------------------------------------------------- // // Function: WriteInt // // Synopsis: Prints out a signed integer value // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WriteInt(CTextBufferA &buf, va_list ¶m, char *&pFormat) { WriteIntCommon(buf, va_arg(param, unsigned int), FALSE); // advance pointer pFormat++; } //+--------------------------------------------------------------------------- // // Function: WriteUnsigned // // Synopsis: Prints out a unsigned value, may be 64 bit or 32 bit // depending on next character in format specifier // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WriteUnsigned(CTextBufferA &buf, va_list ¶m, char *&pFormat) { switch(*(pFormat+1)) // next character determines type { case 'd': // 32-bit case 'D': WriteIntCommon(buf, va_arg(param, unsigned long), TRUE); // Advance format pointer pFormat+=2; break; case 'l': // 64-bit case 'L': WriteLargeCommon(buf, va_arg(param, __int64 *), TRUE); // advance format pointer if(*(pFormat+2) == 'd' || *(pFormat+2) == 'D') { pFormat+=3; } else { pFormat+=2; } break; default: pFormat++; // assume it's just one char-type specifier break; } } //+--------------------------------------------------------------------------- // // Function: WritePointer // // Synopsis: Prints out a lower case pointer value, // checks to make sure pointer is good value // prints out symbol if a symbol maps to pointer // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WritePointer(CTextBufferA &buf, va_list ¶m, char *&pFormat) { if(*(pFormat+1) != 'p') { WritePointerCommon(buf, va_arg(param, void *), FALSE, FALSE, FALSE); pFormat++; } else { void **pPointer = NULL; BufferContext bc; // take snapshot of buffer buf.SnapShot(bc); // write pointer to pointer // first validate this pointer __try { pPointer = va_arg(param, void **); WritePointerCommon(buf, *pPointer, FALSE, FALSE, FALSE); } __except(ExceptionFilter(_exception_code())) { // try to revert buffer buf.Revert(bc); WritePointerCommon(buf, pPointer, FALSE, TRUE, FALSE); } pFormat +=2; } } //+--------------------------------------------------------------------------- // // Function: WritePointerCaps // // Synopsis: Prints out an upper case pointer value, // checks to make sure pointer is good value // prints out symbol if a symbol maps to pointer // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WritePointerCaps(CTextBufferA &buf, va_list ¶m, char *&pFormat) { WritePointerCommon(buf, va_arg(param, void *), TRUE, FALSE, FALSE); pFormat++; } //+--------------------------------------------------------------------------- // // Function: WriteLarge // // Synopsis: Prints out a 64-bit integer // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WriteLarge(CTextBufferA &buf, va_list ¶m, char *&pFormat) { WriteLargeCommon(buf, va_arg(param, __int64 *), FALSE); if(*(pFormat+1) == 'd' || *(pFormat+1) == 'D') { pFormat+=2; } else { pFormat++; } } //+--------------------------------------------------------------------------- // // Function: WriteBool // // Synopsis: Prints out a lower case boolean value // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WriteBool(CTextBufferA &buf, va_list ¶m, char *&pFormat) { WriteBoolCommon(buf, va_arg(param, BOOL), FALSE); pFormat++; } //+--------------------------------------------------------------------------- // // Function: WriteBoolCaps // // Synopsis: Prints out an upper case boolean value // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WriteBoolCaps(CTextBufferA &buf, va_list ¶m, char *&pFormat) { WriteBoolCommon(buf, va_arg(param, BOOL), TRUE); pFormat++; } //+--------------------------------------------------------------------------- // // Function: WriteString // // Synopsis: Prints out an ASCII string // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WriteString(CTextBufferA &buf, va_list ¶m, char *&pFormat) { WriteStringCommon(buf, va_arg(param, const char *)); // Advance format pointer pFormat++; } //+--------------------------------------------------------------------------- // // Function: WriteWideString // // Synopsis: Prints out a UNICODE string, but only supports ASCII characters // if character > 256 is encountered, an "unprintable character" char // is printed // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WriteWideString(CTextBufferA &buf, va_list ¶m, char *&pFormat) { WriteWideStringCommon(buf, va_arg(param, const WCHAR *)); // Advance format pointer if(*(pFormat+1) == 's') { pFormat+=2; } else { pFormat++; } } //+--------------------------------------------------------------------------- // // Function: WriteGUID // // Synopsis: Prints out a GUID // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WriteGUID(CTextBufferA &buf, va_list ¶m, char *&pFormat) { WriteGUIDCommon(buf, va_arg(param, GUID *)); // Advance format pointer pFormat++; } //+--------------------------------------------------------------------------- // // Function: WriteStuct // // Synopsis: Prints out a structure. If structure expansion is enabled // expands the structure depending on it's type // // Arguments: [buf] - reference to text buffer to write text to // [param] - reference to variable argument list // [pFormat] - reference to a char * to the format string, // used to advance string past specifier string // // Returns: nothing // // History: 11-Jul-95 t-stevan Created // //---------------------------------------------------------------------------- void WriteStruct(CTextBufferA &buf, va_list ¶m, char *&pFormat) { void *pArg; BYTE bType = NO_STRUCT; pArg = va_arg(param, void *); if(*(pFormat+1) >= 'a' && *(pFormat+1) <= 'z') { bType = g_structLookup[*(pFormat+1) - 'a']; } if(bType != NO_STRUCT) // only print out known structures { BufferContext bc; buf.SnapShot(bc); // take a snapshot of the buffer __try { g_pStructFuncs[bType](buf, pArg); } __except (ExceptionFilter(_exception_code())) { buf.Revert(bc); // try to revert to the old buffer // bad pointer WritePointerCommon(buf, pArg, FALSE, TRUE, FALSE); } } else { // write out the pointer WritePointerCommon(buf, pArg, FALSE, FALSE, FALSE); } // increment format pointer pFormat += 2; } #endif // DBG==1