503 lines
14 KiB
C
503 lines
14 KiB
C
|
// ----------------------------------------------------------------------------
|
||
|
// 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 <windows.h>
|
||
|
#include <stdio.h>
|
||
|
#include <time.h>
|
||
|
//#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
|