683 lines
15 KiB
C++
683 lines
15 KiB
C++
#include "wmiclnt.h"
|
|
|
|
|
|
|
|
|
|
void DumpErrorMsg
|
|
(
|
|
const char* format,
|
|
...
|
|
)
|
|
{
|
|
va_list argptr;
|
|
|
|
assert(format != NULL);
|
|
|
|
// log this message to stderr and to our log file
|
|
va_start( argptr, format );
|
|
tvfprintf( stderr, format, argptr);
|
|
tvfprintf( g_fpLogFile, format, argptr);
|
|
va_end( argptr );
|
|
}
|
|
|
|
|
|
|
|
void DumpStatusMsg
|
|
(
|
|
const char* format,
|
|
...
|
|
)
|
|
{
|
|
va_list argptr;
|
|
|
|
assert(format != NULL);
|
|
|
|
// log this message to stdout and to our log file
|
|
va_start( argptr, format );
|
|
tvfprintf( stdout, format, argptr );
|
|
tvfprintf( g_fpLogFile, format, argptr );
|
|
va_end( argptr );
|
|
}
|
|
|
|
|
|
|
|
|
|
HRESULT DumpErrorHResult
|
|
(
|
|
HRESULT hr_return,
|
|
const char *format, // can be NULL
|
|
...
|
|
)
|
|
{
|
|
char buff[100];
|
|
int cBytesWritten;
|
|
va_list argptr;
|
|
|
|
//
|
|
// Dump an error message.
|
|
// Print the text of the HRESULT,
|
|
// Return the HRESULT we were passed.
|
|
|
|
// these result codes were generated from the oledberr.h
|
|
static Note ResultCodes[] = {
|
|
// oledberr.h error codes
|
|
NOTE(DB_E_BADACCESSORHANDLE),
|
|
NOTE(DB_E_BADACCESSORHANDLE),
|
|
NOTE(DB_E_ROWLIMITEXCEEDED),
|
|
NOTE(DB_E_READONLYACCESSOR),
|
|
NOTE(DB_E_SCHEMAVIOLATION),
|
|
NOTE(DB_E_BADROWHANDLE),
|
|
NOTE(DB_E_OBJECTOPEN),
|
|
NOTE(DB_E_BADBINDINFO),
|
|
NOTE(DB_SEC_E_PERMISSIONDENIED),
|
|
NOTE(DB_E_NOTAREFERENCECOLUMN),
|
|
NOTE(DB_E_NOCOMMAND),
|
|
NOTE(DB_E_BADBOOKMARK),
|
|
NOTE(DB_E_BADLOCKMODE),
|
|
NOTE(DB_E_PARAMNOTOPTIONAL),
|
|
NOTE(DB_E_BADRATIO),
|
|
NOTE(DB_E_ERRORSINCOMMAND),
|
|
NOTE(DB_E_BADSTARTPOSITION),
|
|
NOTE(DB_E_NOTREENTRANT),
|
|
NOTE(DB_E_NOAGGREGATION),
|
|
NOTE(DB_E_DELETEDROW),
|
|
NOTE(DB_E_CANTFETCHBACKWARDS),
|
|
NOTE(DB_E_ROWSNOTRELEASED),
|
|
NOTE(DB_E_BADSTORAGEFLAG),
|
|
NOTE(DB_E_BADSTATUSVALUE),
|
|
NOTE(DB_E_CANTSCROLLBACKWARDS),
|
|
NOTE(DB_E_INTEGRITYVIOLATION),
|
|
NOTE(DB_E_ABORTLIMITREACHED),
|
|
NOTE(DB_E_DUPLICATEINDEXID),
|
|
NOTE(DB_E_NOINDEX),
|
|
NOTE(DB_E_INDEXINUSE),
|
|
NOTE(DB_E_NOTABLE),
|
|
NOTE(DB_E_CONCURRENCYVIOLATION),
|
|
NOTE(DB_E_BADCOPY),
|
|
NOTE(DB_E_BADPRECISION),
|
|
NOTE(DB_E_BADSCALE),
|
|
NOTE(DB_E_BADID),
|
|
NOTE(DB_E_BADTYPE),
|
|
NOTE(DB_E_DUPLICATECOLUMNID),
|
|
NOTE(DB_E_DUPLICATETABLEID),
|
|
NOTE(DB_E_TABLEINUSE),
|
|
NOTE(DB_E_NOLOCALE),
|
|
NOTE(DB_E_BADRECORDNUM),
|
|
NOTE(DB_E_BOOKMARKSKIPPED),
|
|
NOTE(DB_E_BADPROPERTYVALUE),
|
|
NOTE(DB_E_INVALID),
|
|
NOTE(DB_E_BADACCESSORFLAGS),
|
|
NOTE(DB_E_BADSTORAGEFLAGS),
|
|
NOTE(DB_E_BYREFACCESSORNOTSUPPORTED),
|
|
NOTE(DB_E_NULLACCESSORNOTSUPPORTED),
|
|
NOTE(DB_E_NOTPREPARED),
|
|
NOTE(DB_E_BADACCESSORTYPE),
|
|
NOTE(DB_E_WRITEONLYACCESSOR),
|
|
NOTE(DB_SEC_E_AUTH_FAILED),
|
|
NOTE(DB_E_CANCELED),
|
|
NOTE(DB_E_BADSOURCEHANDLE),
|
|
NOTE(DB_S_ROWLIMITEXCEEDED),
|
|
NOTE(DB_S_COLUMNTYPEMISMATCH),
|
|
NOTE(DB_S_TYPEINFOOVERRIDDEN),
|
|
NOTE(DB_S_BOOKMARKSKIPPED),
|
|
NOTE(DB_S_ENDOFROWSET),
|
|
NOTE(DB_S_BUFFERFULL),
|
|
NOTE(DB_S_CANTRELEASE),
|
|
NOTE(DB_S_DIALECTIGNORED),
|
|
NOTE(DB_S_UNWANTEDPHASE),
|
|
NOTE(DB_S_COLUMNSCHANGED),
|
|
NOTE(DB_S_ERRORSRETURNED),
|
|
NOTE(DB_S_BADROWHANDLE),
|
|
NOTE(DB_S_DELETEDROW),
|
|
NOTE(DB_S_STOPLIMITREACHED),
|
|
NOTE(DB_S_LOCKUPGRADED),
|
|
NOTE(DB_S_PROPERTIESCHANGED),
|
|
NOTE(DB_S_ERRORSOCCURRED),
|
|
NOTE(DB_S_PARAMUNAVAILABLE),
|
|
NOTE(DB_S_MULTIPLECHANGES),
|
|
|
|
// winerr.h
|
|
NOTE(E_UNEXPECTED),
|
|
NOTE(E_NOTIMPL),
|
|
NOTE(E_OUTOFMEMORY),
|
|
NOTE(E_INVALIDARG),
|
|
NOTE(E_NOINTERFACE),
|
|
NOTE(E_POINTER),
|
|
NOTE(E_HANDLE),
|
|
NOTE(E_ABORT),
|
|
NOTE(E_FAIL),
|
|
NOTE(E_ACCESSDENIED),
|
|
NOTE(S_OK),
|
|
NOTE(S_FALSE),
|
|
NOTE(E_UNEXPECTED),
|
|
NOTE(E_NOTIMPL),
|
|
NOTE(E_OUTOFMEMORY),
|
|
NOTE(E_INVALIDARG),
|
|
NOTE(E_NOINTERFACE),
|
|
NOTE(E_POINTER),
|
|
NOTE(E_HANDLE),
|
|
NOTE(E_ABORT),
|
|
NOTE(E_FAIL),
|
|
NOTE(E_ACCESSDENIED),
|
|
// BindMoniker Errors
|
|
NOTE(MK_E_NOOBJECT),
|
|
NOTE(MK_E_EXCEEDEDDEADLINE),
|
|
NOTE(MK_E_CONNECTMANUALLY),
|
|
NOTE(MK_E_INTERMEDIATEINTERFACENOTSUPPORTED),
|
|
NOTE(STG_E_ACCESSDENIED),
|
|
NOTE(MK_E_SYNTAX),
|
|
NOTE(MK_E_CANTOPENFILE),
|
|
};
|
|
|
|
|
|
// Format the message.
|
|
// Print name of hresult code.
|
|
|
|
if (format)
|
|
{
|
|
va_start( argptr, format );
|
|
cBytesWritten = _vsnprintf( buff, sizeof(buff), format, argptr );
|
|
va_end( argptr );
|
|
}
|
|
else
|
|
strcpy( buff, "" );
|
|
|
|
// log to stderr and also to our log file
|
|
tfprintf( stderr, "%.*s: Returned %.30s\n",
|
|
sizeof(buff), buff,
|
|
GetNoteString( ResultCodes, NUMELEM(ResultCodes), GetScode(hr_return)) );
|
|
|
|
tfprintf( g_fpLogFile, "%.*s: Returned %.30s\n",
|
|
sizeof(buff), buff,
|
|
GetNoteString( ResultCodes, NUMELEM(ResultCodes), GetScode(hr_return)) );
|
|
|
|
return ResultFromScode( hr_return );
|
|
}
|
|
|
|
|
|
|
|
|
|
void DumpColumnsInfo
|
|
(
|
|
DBCOLUMNINFO* pColInfo,
|
|
ULONG cCol
|
|
)
|
|
{
|
|
ULONG j;
|
|
|
|
assert(pColInfo != NULL);
|
|
|
|
tfprintf( g_fpLogFile, "\nColumn Information:\n\n");
|
|
|
|
for (j=0; j < cCol; j++)
|
|
{
|
|
WriteColumnInfo( g_fpLogFile, &pColInfo[j] );
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void WriteColumnInfo
|
|
(
|
|
FILE* fp,
|
|
DBCOLUMNINFO* p
|
|
)
|
|
{
|
|
DBID *pCol;
|
|
DBKIND eKind;
|
|
wchar_t wszGuidBuff[MAX_GUID_STRING];
|
|
wchar_t wszNameBuff[MAX_GUID_STRING];
|
|
|
|
static char *szDbcolkind[] = { "Guid+Name", "Guid+PropID", "Name",
|
|
"Guid+Name", "Guid+PropID", "PropID", "Guid" };
|
|
|
|
assert(p != NULL);
|
|
|
|
// For DBTYPEENUM. Doesn't need to be in order.
|
|
// Below we mask off the high bits.
|
|
static Note typenotes[] =
|
|
{
|
|
NOTE(DBTYPE_EMPTY),
|
|
NOTE(DBTYPE_NULL),
|
|
NOTE(DBTYPE_I2),
|
|
NOTE(DBTYPE_I4),
|
|
NOTE(DBTYPE_R4),
|
|
NOTE(DBTYPE_R8),
|
|
NOTE(DBTYPE_CY),
|
|
NOTE(DBTYPE_DATE),
|
|
NOTE(DBTYPE_BSTR),
|
|
NOTE(DBTYPE_IDISPATCH),
|
|
NOTE(DBTYPE_ERROR),
|
|
NOTE(DBTYPE_BOOL),
|
|
NOTE(DBTYPE_VARIANT),
|
|
NOTE(DBTYPE_IUNKNOWN),
|
|
NOTE(DBTYPE_DECIMAL),
|
|
NOTE(DBTYPE_UI1),
|
|
NOTE(DBTYPE_ARRAY),
|
|
NOTE(DBTYPE_BYREF),
|
|
NOTE(DBTYPE_I1),
|
|
NOTE(DBTYPE_UI2),
|
|
NOTE(DBTYPE_UI4),
|
|
NOTE(DBTYPE_I8),
|
|
NOTE(DBTYPE_UI8),
|
|
NOTE(DBTYPE_GUID),
|
|
NOTE(DBTYPE_VECTOR),
|
|
NOTE(DBTYPE_RESERVED),
|
|
NOTE(DBTYPE_BYTES),
|
|
NOTE(DBTYPE_STR),
|
|
NOTE(DBTYPE_WSTR),
|
|
NOTE(DBTYPE_NUMERIC),
|
|
NOTE(DBTYPE_UDT),
|
|
NOTE(DBTYPE_DBDATE),
|
|
NOTE(DBTYPE_DBTIME),
|
|
NOTE(DBTYPE_DBTIMESTAMP),
|
|
};
|
|
|
|
static Note flagnotes[] =
|
|
{
|
|
NOTE(DBCOLUMNFLAGS_ISBOOKMARK),
|
|
NOTE(DBCOLUMNFLAGS_MAYDEFER),
|
|
NOTE(DBCOLUMNFLAGS_WRITE),
|
|
NOTE(DBCOLUMNFLAGS_WRITEUNKNOWN),
|
|
NOTE(DBCOLUMNFLAGS_ISFIXEDLENGTH),
|
|
NOTE(DBCOLUMNFLAGS_ISNULLABLE),
|
|
NOTE(DBCOLUMNFLAGS_MAYBENULL),
|
|
NOTE(DBCOLUMNFLAGS_ISLONG),
|
|
NOTE(DBCOLUMNFLAGS_ISROWID),
|
|
NOTE(DBCOLUMNFLAGS_ISROWVER),
|
|
NOTE(DBCOLUMNFLAGS_CACHEDEFERRED),
|
|
};
|
|
|
|
pCol = & p->columnid;
|
|
eKind = pCol->eKind;
|
|
|
|
// stringize GUID for pretty printing
|
|
switch (eKind)
|
|
{
|
|
case DBKIND_GUID_NAME:
|
|
case DBKIND_GUID_PROPID:
|
|
case DBKIND_GUID:
|
|
StringFromGUID2( pCol->uGuid.guid, wszGuidBuff, sizeof(wszGuidBuff) );
|
|
break;
|
|
case DBKIND_PGUID_NAME:
|
|
case DBKIND_PGUID_PROPID:
|
|
StringFromGUID2( *(pCol->uGuid.pguid), wszGuidBuff, sizeof(wszGuidBuff) );
|
|
break;
|
|
default:
|
|
wcscpy( wszGuidBuff, L"<none>" );
|
|
break;
|
|
}
|
|
|
|
// stringize name or propID for pretty printing
|
|
switch (eKind)
|
|
{
|
|
case DBKIND_GUID_NAME:
|
|
case DBKIND_NAME:
|
|
case DBKIND_PGUID_NAME:
|
|
swprintf( wszNameBuff, L"[name=%.50S]", pCol->uName.pwszName ? pCol->uName.pwszName : L"(unknown)" );
|
|
break;
|
|
case DBKIND_GUID_PROPID:
|
|
case DBKIND_PGUID_PROPID:
|
|
case DBKIND_PROPID:
|
|
swprintf( wszNameBuff, L"[propid=%lu]", pCol->uName.ulPropid );
|
|
break;
|
|
default:
|
|
wcscpy( wszNameBuff, L"" );
|
|
break;
|
|
}
|
|
|
|
// pretty print column info
|
|
tfprintf( fp, "ColumnId [kind=%.40s] [guid=%.40S] %.60S\n",
|
|
szDbcolkind[eKind], wszGuidBuff, wszNameBuff );
|
|
|
|
|
|
// Now move on to other stuff...
|
|
// Name in DBCOLUMNINFO different than name in DBCOLUMNID (maybe).
|
|
tfprintf(fp, " Name = '%.50S'\n", p->pwszName );
|
|
tfprintf(fp, " iOrdinal = %d\n", p->iOrdinal);
|
|
tfprintf(fp, " wType = %.100s\n",
|
|
GetNoteString( typenotes, NUMELEM(typenotes),
|
|
p->wType & (~DBTYPE_BYREF) & (~DBTYPE_ARRAY) & (~DBTYPE_VECTOR) ) );
|
|
if (p->wType & DBTYPE_BYREF)
|
|
tfprintf(fp, " (BYREF)\n");
|
|
if (p->wType & DBTYPE_ARRAY)
|
|
tfprintf(fp, " (ARRAY)\n");
|
|
if (p->wType & DBTYPE_VECTOR)
|
|
tfprintf(fp, " (VECTOR)\n");
|
|
tfprintf(fp, " ulColumnSize = %ld\n", p->ulColumnSize );
|
|
tfprintf(fp, " bPrecision = %d\n", p->bPrecision );
|
|
tfprintf(fp, " bScale = %d\n", p->bScale );
|
|
tfprintf(fp, " dwFlags = %s\n\n",
|
|
GetNoteStringBitvals( flagnotes, NUMELEM(flagnotes), p->dwFlags ) );
|
|
|
|
|
|
}
|
|
|
|
|
|
char* GetNoteString
|
|
(
|
|
Note * rgNote,
|
|
int cNote,
|
|
DWORD dwValue
|
|
)
|
|
{
|
|
int j;
|
|
|
|
assert(rgNote != NULL);
|
|
|
|
// Scan a table of value/string,
|
|
// return ptr to string found.
|
|
|
|
for (j=0; j < cNote; j++) {
|
|
if (rgNote[j].dwFlag == dwValue)
|
|
return rgNote[j].szText;
|
|
}
|
|
return "<unknown>";
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char* GetNoteStringBitvals
|
|
(
|
|
Note* rgNote,
|
|
int cNote,
|
|
DWORD dwValue
|
|
)
|
|
{
|
|
static char buff[400];
|
|
int j;
|
|
|
|
assert(rgNote != NULL);
|
|
|
|
// Make a string that combines all the bits ORed together.
|
|
|
|
strcpy(buff, "");
|
|
for (j=0; j < cNote; j++) {
|
|
if (rgNote[j].dwFlag & dwValue) {
|
|
if (buff[0])
|
|
strcat( buff, " | " );
|
|
strcat( buff, rgNote[j].szText );
|
|
}
|
|
}
|
|
assert(strlen(buff) < sizeof(buff));
|
|
return buff;
|
|
}
|
|
|
|
|
|
|
|
|
|
ULONG CalcPrettyPrintMaxColWidth
|
|
(
|
|
DBBINDING* rgBind,
|
|
ULONG cBind
|
|
)
|
|
{
|
|
ULONG cMaxWidth;
|
|
ULONG cTotalWidth;
|
|
ULONG iBind;
|
|
|
|
assert(rgBind != NULL);
|
|
|
|
cMaxWidth = DEFAULT_CBMAXLENGTH;
|
|
while (1)
|
|
{
|
|
cTotalWidth = 0;
|
|
|
|
for (iBind=0; iBind < cBind; iBind++)
|
|
cTotalWidth += min( cMaxWidth, rgBind[iBind].cbMaxLen ) + 1;
|
|
|
|
if (cTotalWidth < PRETTYPRINT_MAXTOTALWIDTH || cMaxWidth < PRETTYPRINT_MINCOLWIDTH)
|
|
break;
|
|
|
|
cMaxWidth--;
|
|
}
|
|
|
|
return cMaxWidth;
|
|
}
|
|
|
|
|
|
|
|
void DumpColumnHeadings
|
|
(
|
|
DBBINDING* rgBind,
|
|
ULONG cBind,
|
|
DBCOLUMNINFO* pColInfo,
|
|
ULONG cCol,
|
|
ULONG cMaxColWidth
|
|
)
|
|
{
|
|
ULONG iBind;
|
|
|
|
assert(rgBind != NULL);
|
|
assert(pColInfo != NULL);
|
|
|
|
for (iBind=0; iBind < cBind; iBind++)
|
|
tfprintf( g_fpLogFile, "%-*.*S ",
|
|
min( cMaxColWidth, rgBind[iBind].cbMaxLen ),
|
|
min( cMaxColWidth, rgBind[iBind].cbMaxLen ),
|
|
LookupColumnName( pColInfo, cCol, rgBind[iBind].iOrdinal ) );
|
|
tfprintf( g_fpLogFile, "\n" );
|
|
for (iBind=0; iBind < cBind; iBind++)
|
|
tfprintf( g_fpLogFile, "%-*.*s ",
|
|
min( cMaxColWidth, rgBind[iBind].cbMaxLen ),
|
|
min( cMaxColWidth, rgBind[iBind].cbMaxLen ),
|
|
"------------------------------" );
|
|
tfprintf( g_fpLogFile, "\n" );
|
|
}
|
|
|
|
|
|
|
|
WCHAR* LookupColumnName
|
|
(
|
|
DBCOLUMNINFO* rgColInfo,
|
|
ULONG cCol,
|
|
ULONG iCol
|
|
)
|
|
{
|
|
ULONG j;
|
|
|
|
assert(rgColInfo != NULL);
|
|
|
|
// A really slow way to get the column name, given the ordinal.
|
|
// The problem is that result-set ordinals do not necessarily match
|
|
// the index into the ColumnInfo array.
|
|
// (May have bookmark, which is always column 0.)
|
|
|
|
for (j=0; j < cCol; j++)
|
|
if (rgColInfo[j].iOrdinal == iCol)
|
|
return rgColInfo[j].pwszName;
|
|
|
|
return L"Error";
|
|
}
|
|
|
|
|
|
|
|
|
|
void DumpRow
|
|
(
|
|
DBBINDING* rgBind,
|
|
ULONG cBind,
|
|
ULONG cMaxColWidth,
|
|
BYTE* pData
|
|
)
|
|
{
|
|
ULONG iBind;
|
|
TMPCOLUMNDATA* pColumn;
|
|
|
|
assert(rgBind);
|
|
assert( offsetof(TMPCOLUMNDATA, dwLength) == 0);
|
|
|
|
// Print each column we're bound to.
|
|
for (iBind=0; iBind < cBind; iBind++)
|
|
{
|
|
// Columns are bound differently; not so easy.
|
|
// Print out to at least DEFAULT_CBMAXLENGTH width (pretty),
|
|
// Limit to first dwLength characters.
|
|
|
|
pColumn = (TMPCOLUMNDATA *) (pData + rgBind[iBind].obLength);
|
|
PrintColumn( pColumn, rgBind, iBind, cMaxColWidth );
|
|
}
|
|
tfprintf( g_fpLogFile, "\n" );
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void PrintColumn
|
|
(
|
|
TMPCOLUMNDATA *pColumn,
|
|
DBBINDING *rgBind,
|
|
ULONG iBind,
|
|
ULONG cMaxColWidth
|
|
)
|
|
{
|
|
void* p;
|
|
ULONG ulPrintWidth;
|
|
ULONG ulPrintPrecision;
|
|
DWORD dwStatus;
|
|
DWORD dwLength;
|
|
BOOL fDidVariant;
|
|
BOOL fIsUnicode;
|
|
char* sFormat;
|
|
HRESULT hr;
|
|
|
|
assert(pColumn != NULL);
|
|
assert(rgBind != NULL);
|
|
|
|
// Pretty print a column.
|
|
// May have different type of binding.
|
|
|
|
fDidVariant = FALSE;
|
|
fIsUnicode = FALSE;
|
|
dwStatus = pColumn->dwStatus;
|
|
dwLength = pColumn->dwLength;
|
|
|
|
if (dwStatus == DBSTATUS_S_ISNULL)
|
|
{
|
|
p = "<null>";
|
|
dwLength = strlen( (char *) p);
|
|
}
|
|
else if (dwStatus == DBBINDSTATUS_UNSUPPORTEDCONVERSION)
|
|
{
|
|
p = "<unsupportedconversion>";
|
|
dwLength = strlen( (char *) p);
|
|
}
|
|
else
|
|
{
|
|
switch (rgBind[iBind].wType)
|
|
{
|
|
case DBTYPE_STR:
|
|
// We have a string in our buffer, so use it.
|
|
p = (void *) &pColumn->bData;
|
|
break;
|
|
case DBTYPE_VARIANT:
|
|
// We have a variant in our buffer, so convert to string.
|
|
p = (void *) &pColumn->bData;
|
|
hr = VariantChangeTypeEx(
|
|
(VARIANT *) p, // Destination (convert in place)
|
|
(VARIANT *) p, // Source
|
|
LOCALE_SYSTEM_DEFAULT, // LCID
|
|
0, // dwFlags
|
|
VT_BSTR );
|
|
if (FAILED(hr))
|
|
{
|
|
DumpErrorHResult( hr, "VariantChangeTypeEx, field %d", iBind );
|
|
return;
|
|
}
|
|
p = (wchar_t *) (((VARIANT *)p)->bstrVal) ;
|
|
dwLength = ((DWORD *)p)[-1] / sizeof(wchar_t);
|
|
fDidVariant = TRUE;
|
|
fIsUnicode = TRUE;
|
|
break;
|
|
default:
|
|
p = "??? unknown type ???";
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Print the column.
|
|
// If it has been truncated or rounded, print a '#' in
|
|
// the far right-hand column.
|
|
ulPrintWidth = min( cMaxColWidth, rgBind[iBind].cbMaxLen );
|
|
ulPrintPrecision = min( cMaxColWidth, dwLength );
|
|
if (dwStatus == DBSTATUS_S_TRUNCATED || cMaxColWidth < dwLength)
|
|
{
|
|
ulPrintWidth--;
|
|
ulPrintPrecision--;
|
|
}
|
|
|
|
sFormat = fIsUnicode ? "%-*.*S" : "%-*.*s";
|
|
|
|
tfprintf( g_fpLogFile, sFormat, ulPrintWidth, ulPrintPrecision, p );
|
|
|
|
if (dwStatus == DBSTATUS_S_TRUNCATED || cMaxColWidth < dwLength)
|
|
tfprintf( g_fpLogFile, "#" );
|
|
tfprintf( g_fpLogFile, " " );
|
|
|
|
// Free memory used by the variant.
|
|
if (fDidVariant)
|
|
VariantClear( (VARIANT *) &pColumn->bData );
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
void tfprintf
|
|
(
|
|
FILE* fp,
|
|
const char* format,
|
|
...
|
|
)
|
|
{
|
|
int cBytesWritten;
|
|
char buff[400];
|
|
va_list argptr;
|
|
|
|
assert(format != NULL);
|
|
|
|
// Dump a formatted string.
|
|
// _vsnprintf prevents overflowing our buffer.
|
|
va_start( argptr, format );
|
|
cBytesWritten = _vsnprintf( buff, sizeof(buff), format, argptr );
|
|
va_end( argptr );
|
|
buff[sizeof(buff)-1] = '\0';
|
|
|
|
// Can't use fprintf, because string could contain '%'.
|
|
if (fp)
|
|
fputs( buff, fp );
|
|
}
|
|
|
|
|
|
|
|
void tvfprintf
|
|
(
|
|
FILE* fp,
|
|
const char* format,
|
|
va_list argptr
|
|
)
|
|
{
|
|
int cBytesWritten;
|
|
char buff[400];
|
|
|
|
|
|
assert(format != NULL);
|
|
|
|
// Dump a formatted string.
|
|
// _vsnprintf prevents overflowing our buffer.
|
|
cBytesWritten = _vsnprintf( buff, sizeof(buff), format, argptr );
|
|
buff[sizeof(buff)-1] = '\0';
|
|
|
|
// Can't use fprintf, because string could contain '%'.
|
|
if (fp)
|
|
fputs( buff, fp );
|
|
}
|
|
|
|
|