// ---------------------------------------------------------------------------- // debug.c // // Microsoft At Work Fax Debugging Utilities // // Copyright (C) 1993 Microsoft Corporation // ---------------------------------------------------------------------------- /* Revision History: * * When Who What * -------- ------------------ --------------------------------------- * 3.17.94 MAPI Original source from MAPI mapidbg.c * 3.17.94 Yoram Yaacovi Modifications to overcome compobj.h problems * 3.7.94 Yoram Yaacovi Update to MAPI build 154 * 12.1.94 Yoram Yaacovi Added DebugLog() * ***********************************************************************/ #include #include #include //#include "faxcfg.h" #include "mapi.h" #include "mapidbg.h" #include "mapidefs.h" #include "mapicode.h" #ifdef DEBUG /* * * From current\src\mapi\inc\_memcpy.h * * MemCopy() * * A much safer version of memcpy that checks the value of the byte * count before calling the memcpy() function. This macro is only built * into the 16 bit non-debug builds. */ #ifndef __MEMCPY_H_ #define __MEMCPY_H_ #define MemCopy(_dst,_src,_cb) memcpy(_dst,_src,(size_t)(_cb)) #endif #if defined(WIN16) || defined(WIN32) static BOOL fTraceEnabled = -1; static BOOL fLogTraceEnabled = -1; static BOOL fAssertLeaks = -1; static TCHAR szKeyTraceEnabled[] = TEXT("DebugTrace"); static TCHAR szKeyLogTraceEnabled[] = TEXT("DebugTraceLog"); static TCHAR szKeyDebugTrap[] = TEXT("DebugTrap"); static TCHAR szKeyExtendedDebug[] = TEXT("ExtendedDebug"); static TCHAR szKeyUseVirtual[] = TEXT("VirtualMemory"); static TCHAR szKeyAssertLeaks[] = TEXT("AssertLeaks"); static TCHAR szKeyCheckOften[] = TEXT("CheckHeapOften"); static TCHAR szSectionDebug[] = TEXT("General"); static TCHAR szDebugIni[] = TEXT("MAWFDBG.INI"); #endif // ExtendedDebug -------------------------------------------------------------- BOOL ExtendedDebug(void) { return (GetPrivateProfileInt(szSectionDebug, szKeyExtendedDebug, 0, szDebugIni)); } // DebugTrap -------------------------------------------------------------- void DebugTrap(void) { if (GetPrivateProfileInt(szSectionDebug, szKeyDebugTrap, 0, szDebugIni)) DebugBreak(); } // DebugLog -------------------------------------------------------------- void DebugLog(LPSTR szString) { FILE *logfile; // open a log file for appending. create if does not exist if ((logfile = fopen ("c:\\uilog.txt", "a+")) != NULL) { fwrite (szString, 1, strlen(szString), logfile); fclose(logfile); } } // DebugOutputFn -------------------------------------------------------------- void DebugOutputFn(char *psz) { #if defined(_MAC) OutputDebugString(psz); #else char * pszBeg; char * pszEnd; char szBuf[3]; #if defined(WIN16) || defined(WIN32) if (fTraceEnabled == -1) { fTraceEnabled = GetPrivateProfileInt(szSectionDebug, szKeyTraceEnabled, 0, szDebugIni); } if (!fTraceEnabled) return; if (fLogTraceEnabled == -1) { fLogTraceEnabled = GetPrivateProfileInt(szSectionDebug, szKeyLogTraceEnabled, 0, szDebugIni); } #endif for (pszBeg = psz; pszBeg && *pszBeg; pszBeg = pszEnd) { pszEnd = strchr(pszBeg, '\n'); if (pszEnd) { MemCopy(szBuf, pszEnd, 3); if (pszEnd > pszBeg && *(pszEnd - 1) != '\r') strcpy(pszEnd, "\r\n"); else *(pszEnd + 1) = 0; } if (fLogTraceEnabled) DebugLog(pszBeg); else OutputDebugStringA(pszBeg); if (pszEnd) { MemCopy(pszEnd, szBuf, 3); pszEnd += 1; } } #endif } // DebugTrapFn ---------------------------------------------------------------- #if defined(WIN32) && defined(THREAD_MSG_BOX) typedef struct { char * sz1; char * sz2; UINT rgf; int iResult; } MBContext; DWORD WINAPI MessageBoxFnThreadMain(MBContext *pmbc) { pmbc->iResult = MessageBoxA(NULL, pmbc->sz1, pmbc->sz2, pmbc->rgf | MB_SETFOREGROUND); return(0); } int MessageBoxFn(char *sz1, char *sz2, UINT rgf) { HANDLE hThread; DWORD dwThreadId; MBContext mbc; mbc.sz1 = sz1; mbc.sz2 = sz2; mbc.rgf = rgf; mbc.iResult = IDRETRY; hThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)MessageBoxFnThreadMain, &mbc, 0, &dwThreadId); if (hThread != NULL) { WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); } return(mbc.iResult); } #else #define MessageBoxFn(sz1, sz2, rgf) MessageBoxA(NULL, sz1, sz2, rgf) #endif int __cdecl DebugTrapFn(int fFatal, char *pszFile, int iLine, char *pszFormat, ...) { char sz[512]; va_list vl; #if defined(WIN16) || defined(WIN32) int id; #endif strcpy(sz, "++++ MAWF Debug Trap ("); _strdate(sz + strlen(sz)); strcat(sz, " "); _strtime(sz + strlen(sz)); strcat(sz, ")\n"); DebugOutputFn(sz); va_start(vl, pszFormat); wvsprintfA(sz, pszFormat, vl); va_end(vl); wsprintfA(sz + strlen(sz), "\n[File %s, Line %d]\n\n", pszFile, iLine); DebugOutputFn(sz); #if defined(DOS) _asm { int 3 } #endif #if defined(WIN16) || defined(WIN32) // Hold down control key to prevent MessageBox if ( GetAsyncKeyState(VK_CONTROL) >= 0 ) { id = MessageBoxFn(sz, "Microsoft At Work Fax Debug Trap", MB_ABORTRETRYIGNORE | MB_ICONHAND | MB_TASKMODAL | (fFatal ? MB_DEFBUTTON1 : MB_DEFBUTTON3)); if (id == IDABORT) *((LPBYTE)NULL) = 0; else if (id == IDRETRY) DebugBreak(); } #endif return(0); } // ExtendedDebugTraceFn --------------------------------------------------------------- int __cdecl ExtendedDebugTraceFn(char *pszFormat, ...) { char sz[512]; int fAutoLF = 0; va_list vl; if (ExtendedDebug()) { if (*pszFormat == '~') { pszFormat += 1; fAutoLF = 1; } va_start(vl, pszFormat); wvsprintfA(sz, pszFormat, vl); va_end(vl); if (fAutoLF) strcat(sz, "\n"); DebugOutputFn(sz); } return(0); } // DebugTraceFn --------------------------------------------------------------- int __cdecl DebugTraceFn(char *pszFormat, ...) { char sz[512]; char sz1[512]; int fAutoLF = 0; va_list vl; HINSTANCE hInst=NULL; // this really needs to be a parameter if (*pszFormat == '~') { pszFormat += 1; fAutoLF = 1; } va_start(vl, pszFormat); wvsprintfA(sz, pszFormat, vl); va_end(vl); if (fAutoLF) strcat(sz, "\n"); strcpy(sz1, sz); DebugOutputFn(sz1); return(0); } // SCODE & PropTag decoding --------------------------------------------------- typedef struct { char * psz; unsigned long ulPropTag; } PT; typedef struct { char * psz; SCODE sc; } SC; #define Pt(_ptag) {#_ptag, _ptag} #define Sc(_sc) {#_sc, _sc} #if !defined(DOS) static PT rgpt[] = { /* * Property types */ Pt(PT_UNSPECIFIED), Pt(PT_NULL), Pt(PT_I2), Pt(PT_LONG), Pt(PT_R4), Pt(PT_DOUBLE), Pt(PT_CURRENCY), Pt(PT_APPTIME), Pt(PT_ERROR), Pt(PT_BOOLEAN), Pt(PT_OBJECT), Pt(PT_I8), Pt(PT_STRING8), Pt(PT_UNICODE), Pt(PT_SYSTIME), Pt(PT_CLSID), Pt(PT_BINARY), Pt(PT_TSTRING), Pt(PT_MV_I2), Pt(PT_MV_LONG), Pt(PT_MV_R4), Pt(PT_MV_DOUBLE), Pt(PT_MV_CURRENCY), Pt(PT_MV_APPTIME), Pt(PT_MV_SYSTIME), Pt(PT_MV_STRING8), Pt(PT_MV_BINARY), Pt(PT_MV_UNICODE), Pt(PT_MV_CLSID), Pt(PT_MV_I8) }; #define cpt (sizeof(rgpt) / sizeof(PT)) static SC rgsc[] = { /* FACILITY_NULL error codes from OLE */ Sc(S_OK), Sc(S_FALSE), Sc(E_UNEXPECTED), Sc(E_NOTIMPL), Sc(E_OUTOFMEMORY), Sc(E_INVALIDARG), Sc(E_NOINTERFACE), Sc(E_POINTER), Sc(E_HANDLE), Sc(E_ABORT), Sc(E_FAIL), Sc(E_ACCESSDENIED), /* General errors (used by more than one MAPI object) */ Sc(MAPI_E_NO_SUPPORT), Sc(MAPI_E_BAD_CHARWIDTH), Sc(MAPI_E_STRING_TOO_LONG), Sc(MAPI_E_UNKNOWN_FLAGS), Sc(MAPI_E_INVALID_ENTRYID), Sc(MAPI_E_INVALID_OBJECT), Sc(MAPI_E_OBJECT_CHANGED), Sc(MAPI_E_OBJECT_DELETED), Sc(MAPI_E_BUSY), Sc(MAPI_E_NOT_ENOUGH_DISK), Sc(MAPI_E_NOT_ENOUGH_RESOURCES), Sc(MAPI_E_NOT_FOUND), Sc(MAPI_E_VERSION), Sc(MAPI_E_LOGON_FAILED), Sc(MAPI_E_SESSION_LIMIT), Sc(MAPI_E_USER_CANCEL), Sc(MAPI_E_UNABLE_TO_ABORT), Sc(MAPI_E_NETWORK_ERROR), Sc(MAPI_E_DISK_ERROR), Sc(MAPI_E_TOO_COMPLEX), Sc(MAPI_E_BAD_COLUMN), Sc(MAPI_E_EXTENDED_ERROR), Sc(MAPI_E_COMPUTED), /* MAPI base function and status object specific errors and warnings */ Sc(MAPI_E_END_OF_SESSION), Sc(MAPI_E_UNKNOWN_ENTRYID), Sc(MAPI_E_MISSING_REQUIRED_COLUMN), /* Property specific errors and warnings */ Sc(MAPI_E_BAD_VALUE), Sc(MAPI_E_INVALID_TYPE), Sc(MAPI_E_TYPE_NO_SUPPORT), Sc(MAPI_E_UNEXPECTED_TYPE), Sc(MAPI_E_TOO_BIG), Sc(MAPI_W_ERRORS_RETURNED), /* Table specific errors and warnings */ Sc(MAPI_E_UNABLE_TO_COMPLETE), Sc(MAPI_E_TABLE_EMPTY), Sc(MAPI_E_TABLE_TOO_BIG), Sc(MAPI_E_INVALID_BOOKMARK), Sc(MAPI_W_POSITION_CHANGED), Sc(MAPI_W_APPROX_COUNT), /* Transport specific errors and warnings */ Sc(MAPI_E_WAIT), Sc(MAPI_E_CANCEL), Sc(MAPI_E_NOT_ME), Sc(MAPI_W_CANCEL_MESSAGE), /* Message Store, Folder, and Message specific errors and warnings */ Sc(MAPI_E_CORRUPT_STORE), Sc(MAPI_E_NOT_IN_QUEUE), Sc(MAPI_E_NO_SUPPRESS), Sc(MAPI_E_COLLISION), Sc(MAPI_E_NOT_INITIALIZED), Sc(MAPI_E_NON_STANDARD), Sc(MAPI_E_NO_RECIPIENTS), Sc(MAPI_E_SUBMITTED), Sc(MAPI_E_HAS_FOLDERS), Sc(MAPI_E_HAS_MESSAGES), Sc(MAPI_E_FOLDER_CYCLE), /* Address Book specific errors and warnings */ Sc(MAPI_E_AMBIGUOUS_RECIP) }; #define csc (sizeof(rgsc) / sizeof(SC)) #endif char * __cdecl SzDecodeScodeFn(SCODE sc) { static char rgch[64]; #if !defined(DOS) int isc; for (isc = 0; isc < csc; ++isc) if (sc == rgsc[isc].sc) return rgsc[isc].psz; #endif wsprintfA (rgch, "%08lX", sc); return rgch; } #else // no DEBUG typedef long SCODE; // need to define empty functions for DEF file resolution BOOL ExtendedDebug(void) { return FALSE; } void DebugTrap(void) { } int __cdecl DebugTrapFn(int fFatal, char *pszFile, int iLine, char *pszFormat, ...) { return 0; } int __cdecl DebugTraceFn(char *pszFormat, ...) { return 0; } int __cdecl ExtendedDebugTraceFn(char *pszFormat, ...) { return 0; } char * __cdecl SzDecodeScodeFn(SCODE sc) { return NULL; } #endif