NT4/private/oleauto/tests/common/dispdbug.cpp
2020-09-30 17:12:29 +02:00

891 lines
18 KiB
C++

/***
*dispdbug.cpp
*
* Copyright (C) 1992, Microsoft Corporation. All Rights Reserved.
* Information Contained Herein Is Proprietary and Confidential.
*
*Purpose:
* Misc Debug utilities.
*
*Revision History:
*
* [00] 25-Sep-92 bradlo: Created.
*
*Implementation Notes:
*
*****************************************************************************/
#include <stdio.h>
#include <stdarg.h>
#include "common.h"
#include "dispdbug.h"
LOCAL char *rgszVtFmt[] = {
"" // VT_EMPTY
, "" // VT_NULL
, "%d" // VT_I2
, "%ld" // VT_I4
, "%#f" // VT_R4
, "%#f" // VT_R8
, "%ld.%lu" // VT_CY
, "%#f" // VT_DATE
#if HC_MPW
, "\"%s\"" // VT_BSTR
#else
, "\"%Fs\"" // VT_BSTR
#endif
, "" // VT_DISPATCH
, "0x%lX" // VT_ERROR
, "%d" // VT_BOOL
, NULL // VT_VARIANT - special format
, "" // VT_UNKNOWN
, "" // 14 is unused
, "" // 15 is unused
, "%d" // VT_I1
, "%ud" // VT_UI1
};
#if 0 /* Note: this is now supplied by the host test app */
#ifndef _MAC
extern "C" void
DbPrintf(char FAR* szFormat, ...)
{
va_list args;
char *pn, FAR* pf;
static char rgchFmtBuf[512];
static char rgchOutputBuf[1024];
// copy the 'far' format string to a near buffer so we can use
// the medium model vsprintf, which only supports near data pointers.
//
pn = rgchFmtBuf, pf=szFormat;
while(*pf != '\0')
*pn++ = *pf++;
*pn = '\0';
va_start(args, szFormat);
vsprintf(rgchOutputBuf, rgchFmtBuf, args);
OutputDebugString(rgchOutputBuf);
}
#endif
#endif
extern "C" void
DbPrVt(VARTYPE vt)
{
DbPrintf(DbSzOfVt(vt));
}
extern "C" char FAR*
SzOfVarg(VARIANTARG FAR* pvarg)
{
char *p;
short s;
VARTYPE vt;
void FAR* pv;
IUnknown FAR* punk;
IDispatch FAR* pdisp;
static char buf[512];
#if OE_WIN32
char buf2[256];
#endif
if(pvarg == NULL)
return "(null)";
p = buf;
STRCPY(p, DbSzOfVt(V_VT(pvarg)));
p += strlen(p);
vt = V_VT(pvarg) & ~(VT_BYREF | VT_ARRAY);
pv = (V_ISBYREF(pvarg)) ? V_BYREF(pvarg) : &V_NONE(pvarg);
*p++ = '(';
*p = '\0';
switch(V_VT(pvarg)){
case VT_NULL:
case VT_EMPTY:
*p = '\0';
break;
#if VBA2
case VT_UI1:
case VT_UI1 | VT_BYREF:
sprintf(p, rgszVtFmt[vt], (unsigned int)*(unsigned char FAR*)pv);
break;
#endif //VBA2
case VT_I2:
case VT_I2 | VT_BYREF:
sprintf(p, rgszVtFmt[vt], *(short FAR*)pv);
break;
case VT_I4:
case VT_ERROR:
case VT_I4 | VT_BYREF:
case VT_ERROR | VT_BYREF:
sprintf(p, rgszVtFmt[vt], *(long FAR*)pv);
break;
case VT_R4:
case VT_R4 | VT_BYREF:
sprintf(p, rgszVtFmt[vt], (double)*(float FAR*)pv);
break;
case VT_CY:
case VT_CY | VT_BYREF:
sprintf(p, rgszVtFmt[vt], ((CY FAR*)pv)->Hi, ((CY FAR*)pv)->Lo);
break;
case VT_R8:
case VT_DATE:
case VT_R8 | VT_BYREF:
case VT_DATE | VT_BYREF:
sprintf(p, rgszVtFmt[vt], *(double FAR*)pv);
break;
case VT_BSTR:
case VT_BSTR | VT_BYREF:
#if OE_WIN32
ConvertStrWtoA(*(BSTR FAR*)pv, buf2),
sprintf(p, rgszVtFmt[vt], buf2);
#else
sprintf(p, rgszVtFmt[vt], *(BSTR FAR*)pv);
#endif
break;
case VT_BOOL:
case VT_BOOL | VT_BYREF:
s = *(short FAR*)pv;
if(s == 0){
strcpy(p, "False(0)");
}else if(s == -1){
strcpy(p, "True(-1)");
}else{
*p++ = '?';
*p = '\0';
}
break;
case VT_UNKNOWN:
case VT_UNKNOWN | VT_BYREF:
punk = *(IUnknown FAR* FAR*)pv;
sprintf(p, rgszVtFmt[vt], punk);
break;
case VT_DISPATCH:
case VT_DISPATCH | VT_BYREF:
pdisp = *(IDispatch FAR* FAR*)pv;
sprintf(p, rgszVtFmt[vt], pdisp);
break;
case VT_VARIANT | VT_BYREF:
SzOfVarg(V_VARIANTREF(pvarg));
break;
default:
if(V_VT(pvarg) & VT_ARRAY){
#if 0 /* Dont print addresses, makes the logfile un-diffable */
if(V_VT(pvarg) & VT_BYREF){
sprintf(p, "%lp", V_ARRAYREF(pvarg));
}else{
sprintf(p, "%lp", V_ARRAY(pvarg));
}
#endif
}else{
*p++ = '?';
*p = '\0';
}
break;
}
p = buf + strlen(buf);
*p++ = ')';
*p = '\0';
return buf;
}
extern "C" void
DbPrVarg(VARIANTARG FAR* pvarg)
{
DbPrintf(SzOfVarg(pvarg));
}
/***
*void DbPrData(void*, VARTYPE)
*Purpose:
* Print the given data according to the given VARTYPE.
*
*Entry:
* vt = the VARTYPE of the data
* pv = pointer to the data to print
*
*Exit:
* None
*
***********************************************************************/
extern "C" void
DbPrData(void FAR* pv, VARTYPE vt)
{
#if OE_WIN32
char buf2[256];
#endif
switch(vt){
#if VBA2
case VT_UI1:
DbPrintf(rgszVtFmt[vt], (unsigned int)*(unsigned char FAR*)pv);
break;
#endif //VBA2
case VT_I2:
case VT_BOOL:
DbPrintf(rgszVtFmt[vt], *(short FAR*)pv);
break;
case VT_I4:
case VT_ERROR:
DbPrintf(rgszVtFmt[vt], *(long FAR*)pv);
break;
case VT_R4:
DbPrintf(rgszVtFmt[vt], (double)*(float FAR*)pv);
break;
case VT_R8:
case VT_DATE:
DbPrintf(rgszVtFmt[vt], *(double FAR*)pv);
break;
case VT_CY:
DbPrintf(rgszVtFmt[vt], ((CY FAR*)pv)->Hi, ((CY FAR*)pv)->Lo);
break;
case VT_BSTR:
#if OE_WIN32
ConvertStrWtoA(*(BSTR FAR*)pv, buf2),
DbPrintf(rgszVtFmt[vt], buf2);
#else
DbPrintf(rgszVtFmt[vt], *(BSTR FAR*)pv);
#endif
break;
case VT_VARIANT:
DbPrVarg((VARIANT FAR*)pv);
break;
case VT_UNKNOWN:
case VT_DISPATCH:
DbPrintf(rgszVtFmt[vt], *(IUnknown FAR* FAR*)pv);
break;
#if OE_WIN32 && 0
case VT_WBSTR:
{
BSTR bstr;
bstr = SysStringWtoA(*(WBSTR FAR*)pv, CP_ACP);
DbPrintf(rgszVtFmt[vt], bstr);
SysFreeString(bstr);
break;
}
case VT_DISPATCHW:
DbPrintf(rgszVtFmt[vt], *(IUnknown FAR* FAR*)pv);
break;
#endif
default:;
DbPrintf("?");
break;
}
}
/***
*void DbPrExcepinfo(EXCEPINFO*)
*Purpose:
* Dump the given EXCEPINFO struct to the debug window.
*
*Entry:
* pexcepinfo - the EXCEPINFO struct to dump
*
*Exit:
* None
*
***********************************************************************/
extern "C" void
DbPrExcepinfo(EXCEPINFO FAR* pexcepinfo)
{
DbPrintf("wCode=%d dwHelpContext=%ld\n",
pexcepinfo->wCode, pexcepinfo->dwHelpContext);
#if HC_MPW
DbPrintf("bstrSource = \"%s\"\n", pexcepinfo->bstrSource);
DbPrintf("bstrDescription = \"%s\"\n", pexcepinfo->bstrDescription);
DbPrintf("bstrHelpFile = \"%s\"\n", pexcepinfo->bstrHelpFile);
#else
DbPrintf("bstrSource = \"%Fs\"\n", pexcepinfo->bstrSource);
DbPrintf("bstrDescription = \"%Fs\"\n", pexcepinfo->bstrDescription);
DbPrintf("bstrHelpFile = \"%Fs\"\n", pexcepinfo->bstrHelpFile);
#endif
}
#if OE_WIN32 && 0
extern "C" void
DbPrExcepinfoW(WEXCEPINFO FAR* pexcepinfo)
{
BSTR source, description, helpFile;
source = SysStringWtoA(pexcepinfo->wbstrSource, CP_ACP);
description = SysStringWtoA(pexcepinfo->wbstrDescription, CP_ACP);
helpFile = SysStringWtoA(pexcepinfo->wbstrHelpFile, CP_ACP);
DbPrintf("wCode=%d dwHelpContext=%ld\n",
pexcepinfo->wCode, pexcepinfo->dwHelpContext);
DbPrintf("bstrSource = \"%Fs\"\n", source);
DbPrintf("bstrDescription = \"%Fs\"\n", description);
DbPrintf("bstrHelpFile = \"%Fs\"\n", helpFile);
SysFreeString(source);
SysFreeString(description);
SysFreeString(helpFile);
}
#endif
/***
*void DbPrParams(DISPPARAMS*)
*Purpose:
* Dump the given DISPPARAMS struct to the debug window.
*
*Entry:
* pdispparams = the DISPPARAMS struct to dump.
*
*Exit:
* None
*
***********************************************************************/
extern "C" void
DbPrParams(DISPPARAMS FAR* pdispparams)
{
unsigned int i;
DbPrintf("cArgs = %d\n", pdispparams->cArgs);
DbPrintf("rgvarg = [");
for(i = 0; i < pdispparams->cArgs; ++i){
DbPrVarg(&pdispparams->rgvarg[i]);
if(i+1 < pdispparams->cArgs)
DbPrintf(", ");
}
DbPrintf("]\n");
DbPrintf("cNamedArgs = %d\n", pdispparams->cNamedArgs);
DbPrintf("rgdispidNamedArgs = [");
for(i = 0; i < pdispparams->cNamedArgs; ++i){
DbPrintf("%ld", pdispparams->rgdispidNamedArgs[i]);
if(i+1 < pdispparams->cNamedArgs)
DbPrintf(", ");
}
DbPrintf("]\n");
}
void
PrScode(SCODE sc)
{
#if HC_MPW
DbPrintf("[%s]", DbSzOfScode(sc));
#else
DbPrintf("[%Fs]", DbSzOfScode(sc));
#endif
}
//---------------------------------------------------------------------
// TypeInfo dumping utilities
//---------------------------------------------------------------------
/* naming convention:
*
* Pr<type> - dump the type with cr/lf
* Pr<type>N - dump type without cr/lf
* Pr<type>X - dump type with given indent level
*
*/
void
DbIndent(int level)
{
for(int i = 0; i < level; ++i)
DbPrintf(" ");
}
void
PrGuidN(GUID FAR* pguid)
{
DbPrintf("{%08lX-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
pguid->Data1, pguid->Data2, pguid->Data3,
pguid->Data4[0], pguid->Data4[1], pguid->Data4[2], pguid->Data4[3],
pguid->Data4[4], pguid->Data4[5], pguid->Data4[6], pguid->Data4[7]);
}
void
PrGuid(GUID FAR* pguid)
{
PrGuidN(pguid);
DbPrintf("\n");
}
void
PrTypekindN(TYPEKIND tkind)
{
switch(tkind){
case TKIND_ENUM:
DbPrintf("TKIND_ENUM");
break;
case TKIND_RECORD:
DbPrintf("TKIND_RECORD");
break;
case TKIND_MODULE:
DbPrintf("TKIND_MODULE");
break;
case TKIND_INTERFACE:
DbPrintf("TKIND_INTERFACE");
break;
case TKIND_DISPATCH:
DbPrintf("TKIND_DISPATCH");
break;
case TKIND_COCLASS:
DbPrintf("TKIND_COCLASS");
break;
case TKIND_ALIAS:
DbPrintf("TKIND_ALIAS");
break;
case TKIND_UNION:
DbPrintf("TKIND_UNION");
break;
default:
DbPrintf("UNKNOWN");
break;
}
}
void PrVarkindN(VARKIND vkind)
{
switch(vkind){
case VAR_PERINSTANCE:
DbPrintf("VAR_PERINSTANCE");
break;
case VAR_STATIC:
DbPrintf("VAR_STATIC");
break;
case VAR_CONST:
DbPrintf("VAR_CONST");
break;
case VAR_DISPATCH:
DbPrintf("VAR_DISPATCH");
break;
default:
DbPrintf("UNKNOWN");
}
}
void
PrFunckindN(FUNCKIND fkind)
{
switch(fkind){
case FUNC_VIRTUAL:
DbPrintf("FUNC_VIRTUAL");
break;
case FUNC_PUREVIRTUAL:
DbPrintf("FUNC_PUREVIRTUAL");
break;
case FUNC_NONVIRTUAL:
DbPrintf("FUNC_NONVIRTUAL");
break;
case FUNC_STATIC:
DbPrintf("FUNC_STATIC");
break;
case FUNC_DISPATCH:
DbPrintf("FUNC_DISPATCH");
break;
default:
DbPrintf("UNKNOWN");
}
}
void
PrInvokekindN(INVOKEKIND invkind)
{
switch(invkind){
case INVOKE_FUNC:
DbPrintf("INVOKE_FUNC");
break;
case INVOKE_PROPERTYGET:
DbPrintf("INVOKE_PROPERTYGET");
break;
case INVOKE_PROPERTYPUT:
DbPrintf("INVOKE_PROPERTYPUT");
break;
case INVOKE_PROPERTYPUTREF:
DbPrintf("INVOKE_PROPERTYPUTREF");
break;
default:
DbPrintf("UNKNOWN");
break;
}
}
void
PrCallconvN(CALLCONV cc)
{
switch(cc){
case CC_CDECL:
DbPrintf("CC_CDECL");
break;
case CC_MSCPASCAL:
DbPrintf("CC_MSCPASCAL");
break;
case CC_MACPASCAL:
DbPrintf("CC_MACPASCAL");
break;
case CC_STDCALL:
DbPrintf("CC_STDCALL");
break;
case CC_RESERVED:
DbPrintf("CC_RESERVED");
break;
default:
DbPrintf("UNKNOWN");
break;
}
}
void
PrTypeFlagsN(unsigned short wTypeFlags)
{
DbPrintf("[");
if(wTypeFlags & TYPEFLAG_FAPPOBJECT)
DbPrintf("AppObject");
DbPrintf("]");
}
void
PrFuncFlagsN(unsigned short wFuncFlags)
{
DbPrintf("[");
if(wFuncFlags & FUNCFLAG_FRESTRICTED)
DbPrintf("Restricted");
DbPrintf("]");
}
void
PrTypedescN(TYPEDESC FAR* ptdesc)
{
DbPrVt(ptdesc->vt);
switch(ptdesc->vt){
#if 0 /* REVIEW: NYI */
case VT_CARRAY:
DbPrintf(" ");
PrAdesc(ptdesc->lpadesc);
break;
#endif
case VT_PTR:
DbPrintf(" ");
PrTypedescN(ptdesc->lptdesc);
break;
case VT_USERDEFINED:
DbPrintf(" hreftype=%d", (int)ptdesc->hreftype);
break;
#if 0 /* obsolete */
case VT_FIXEDSTRING:
DbPrintf(" cbSize=%d", (int)ptdesc->cbSize);
break;
#endif
}
}
void
PrTdesc(TYPEDESC FAR* ptdesc)
{
PrTypedescN(ptdesc);
DbPrintf("\n");
}
// print the given TYPEATTR
void
PrTypeattrXN(TYPEATTR FAR* ptattr, int level)
{
PrTypekindN(ptattr->typekind);
DbPrintf(" ");
PrGuidN(&ptattr->guid);
DbPrintf("\n");
DbIndent(level);
DbPrintf("ver=%d.%d lcid=0x%lx",
(int)ptattr->wMajorVerNum,
(int)ptattr->wMinorVerNum,
ptattr->lcid);
DbPrintf(" cFunc=%d cVar=%d cImpl=%d cbAlign=%d cbInst=%d cbVft=%d",
(int)ptattr->cFuncs,
(int)ptattr->cVars,
(int)ptattr->cImplTypes,
(int)ptattr->cbAlignment,
(int)ptattr->cbSizeInstance,
(int)ptattr->cbSizeVft);
#if 0 /* REVIEW: add support for the following */
ptattr->idldescType
ptattr->memidConstructor
ptattr->memidDestructor
#endif
if(ptattr->typekind == TKIND_ALIAS){
DbPrintf(" alias=");
PrTypedescN(&ptattr->tdescAlias);
}
DbPrintf(" ");
PrTypeFlagsN(ptattr->wTypeFlags);
}
void
PrTypeattrX(TYPEATTR FAR* ptattr, int level)
{
PrTypeattrXN(ptattr, level);
DbPrintf("\n");
}
void
PrIdldescN(IDLDESC FAR* pidldesc)
{
UNUSED(pidldesc);
// REVIEW: NYI
}
void
PrElemdescN(ELEMDESC FAR* pelemdesc)
{
PrTypedescN(&pelemdesc->tdesc);
#if 0 /* REVIEW: NYI */
DbPrintf(" ");
PrIdldescN(&pelemdesc->idldesc);
#endif
}
void
PrVardescXN(VARDESC FAR* pvdesc, int level)
{
UNUSED(level);
DbPrintf("ID(0x%lx) ", (long)pvdesc->memid);
PrVarkindN(pvdesc->varkind);
DbPrintf(" ");
PrElemdescN(&pvdesc->elemdescVar);
switch(pvdesc->varkind){
case VAR_PERINSTANCE:
DbPrintf("oInst=%lu", pvdesc->oInst);
break;
case VAR_CONST:
DbPrintf("value=%Fs", SzOfVarg(pvdesc->lpvarValue));
break;
case VAR_STATIC:
case VAR_DISPATCH:
break;
}
}
void
PrFuncdescXN(FUNCDESC FAR* pfdesc, int level)
{
int i;
PrFunckindN(pfdesc->funckind);
DbPrintf(" ID(%ld)", pfdesc->memid);
DbPrintf(" ");
PrInvokekindN(pfdesc->invkind);
DbPrintf(" ");
PrCallconvN(pfdesc->callconv);
DbPrintf(" oVft=%d", (int)pfdesc->oVft);
DbPrintf(" cParam=%d(%d)",
(int)pfdesc->cParams, (int)pfdesc->cParamsOpt);
DbPrintf(" ");
PrFuncFlagsN(pfdesc->wFuncFlags);
DbPrintf("\n");
DbIndent(level);
PrElemdescN(&pfdesc->elemdescFunc);
DbPrintf(" (");
if(pfdesc->cParams > 0){
for(i = 0;;){
PrElemdescN(&pfdesc->lprgelemdescParam[i]);
if(++i >= pfdesc->cParams)
break;
DbPrintf(", ");
}
}
DbPrintf(")");
}
// helper for PrTi()
LOCAL HRESULT
PrMembersX(
ITypeInfo FAR* ptinfo,
TYPEATTR FAR* ptattr,
int fFuncs,
int level)
{
int i, num;
MEMBERID memid;
VARDESC FAR* pvdesc;
FUNCDESC FAR* pfdesc;
unsigned long dwHelpContext;
BSTR bstrName, bstrDoc, bstrHelpFile;
#if OE_WIN32
char buf[256], buf2[256];
#endif
num = fFuncs ? ptattr->cFuncs : ptattr->cVars;
for(i = 0; i < num; ++i){
if(fFuncs){
IfFailRet(ptinfo->GetFuncDesc(i, &pfdesc));
memid = pfdesc->memid;
}else{
IfFailRet(ptinfo->GetVarDesc(i, &pvdesc));
memid = pvdesc->memid;
}
IfFailRet(ptinfo->GetDocumentation(
memid, &bstrName, &bstrDoc, &dwHelpContext, &bstrHelpFile));
DbIndent(level);
DbPrintf("- ");
if(fFuncs){
PrFuncdescXN(pfdesc, level+2);
ptinfo->ReleaseFuncDesc(pfdesc);
}else{
PrVardescXN(pvdesc, level+2);
ptinfo->ReleaseVarDesc(pvdesc);
}
DbPrintf("\n");
DbIndent(level+2);
#if OE_WIN32
ConvertStrWtoA(bstrName, buf);
DbPrintf("\"%Fs\"", buf);
#else
DbPrintf("\"%Fs\"", bstrName);
#endif
DbPrintf(" Doc=\"%Fs\" HelpFile=\"%Fs\" HelpContext=%ld\n",
#if OE_WIN32
bstrDoc == NULL ? "" : ConvertStrWtoA(bstrDoc, buf),
bstrHelpFile == NULL ? "" : ConvertStrWtoA(bstrHelpFile, buf2),
dwHelpContext);
#else
bstrDoc == NULL ? "" : bstrDoc,
bstrHelpFile == NULL ? "" : bstrHelpFile,
dwHelpContext);
#endif
SysFreeString(bstrName);
SysFreeString(bstrDoc);
SysFreeString(bstrHelpFile);
}
return NOERROR;
}
void
PrTiX(ITypeInfo FAR* ptinfo, int level)
{
int i;
HRESULT hresult;
HREFTYPE hreftype;
TYPEATTR FAR* ptattr;
ITypeInfo FAR* ptinfoRef;
// indent based on the given level
DbIndent(level);
DbPrintf("[ ");
IfFailGo(ptinfo->GetTypeAttr(&ptattr), LError0);
PrTypeattrX(ptattr, level+2);
// dump the variables, if any
if(ptattr->cVars != 0){
IfFailGo(PrMembersX(ptinfo, ptattr, FALSE, level+2), LError1);
}
// dump the functions, if any
if(ptattr->cFuncs != 0){
IfFailGo(PrMembersX(ptinfo, ptattr, TRUE, level+2), LError1);
}
// dump the referenced type infos, if any
if(ptattr->cImplTypes != 0){
for(i = 0; i < (int)ptattr->cImplTypes; ++i){
if((hresult = ptinfo->GetRefTypeOfImplType(i, &hreftype)) != NOERROR){
PrScode(GetScode(hresult));
break;
}
if((hresult = ptinfo->GetRefTypeInfo(hreftype, &ptinfoRef)) != NOERROR){
PrScode(GetScode(hresult));
break;
}
PrTiX(ptinfoRef, level+6);
ptinfoRef->Release();
}
}
DbIndent(level);
DbPrintf("]");
LError1:;
ptinfo->ReleaseTypeAttr(ptattr);
LError0:;
DbPrintf("\n");
if(hresult != NOERROR){
DbPrintf("ERROR: ");
PrScode(GetScode(hresult));
DbPrintf("\n");
}
}
// print the given TypeInfo
void
PrTi(ITypeInfo FAR* ptinfo)
{
PrTiX(ptinfo, 0);
}