986 lines
32 KiB
C++
986 lines
32 KiB
C++
/*******************************************************************************
|
|
*
|
|
* (C) COPYRIGHT MICROSOFT CORPORATION, 2000
|
|
*
|
|
* TITLE: DUMPPROP.CPP
|
|
*
|
|
* VERSION: 1.0
|
|
*
|
|
* AUTHOR: ShaunIv
|
|
*
|
|
* DATE: 9/27/2000
|
|
*
|
|
* DESCRIPTION: Display the properties associated with a IWiaItem, either to the
|
|
* debugger, or to a log file.
|
|
*
|
|
*******************************************************************************/
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
#include "dumpprop.h"
|
|
|
|
//
|
|
// Change this to limit the width of individual strings (for avoiding ugliness)
|
|
//
|
|
#define MAX_DUMP_STRING 160
|
|
|
|
CWiaDebugDump::CWiaDebugDump(void)
|
|
{
|
|
}
|
|
|
|
CWiaDebugDump::~CWiaDebugDump(void)
|
|
{
|
|
}
|
|
|
|
CWiaDebugDumpToFileHandle::CWiaDebugDumpToFileHandle( HANDLE hFile )
|
|
: m_hFile(hFile)
|
|
{
|
|
}
|
|
|
|
CWiaDebugDumpToFileHandle::~CWiaDebugDumpToFileHandle(void)
|
|
{
|
|
}
|
|
|
|
void CWiaDebugDumpToFileHandle::Print( LPCTSTR pszString )
|
|
{
|
|
if (m_hFile && pszString)
|
|
{
|
|
DWORD dwWritten;
|
|
WriteFile( m_hFile, pszString, lstrlen(pszString)*sizeof(TCHAR), &dwWritten, NULL );
|
|
WriteFile( m_hFile, TEXT("\r\n"), 2*sizeof(TCHAR), &dwWritten, NULL );
|
|
}
|
|
}
|
|
|
|
|
|
CWiaDebugDumpToFile::CWiaDebugDumpToFile( LPCTSTR pszFilename, bool bOverwrite )
|
|
: m_hFile(INVALID_HANDLE_VALUE)
|
|
{
|
|
if (pszFilename && lstrlen(pszFilename))
|
|
{
|
|
m_hFile = CreateFile( pszFilename, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ, NULL, bOverwrite ? CREATE_ALWAYS : OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL );
|
|
if (!bOverwrite && m_hFile)
|
|
{
|
|
SetFilePointer( m_hFile, 0, NULL, FILE_END );
|
|
}
|
|
}
|
|
}
|
|
|
|
CWiaDebugDumpToFile::~CWiaDebugDumpToFile(void)
|
|
{
|
|
if (INVALID_HANDLE_VALUE != m_hFile)
|
|
{
|
|
CloseHandle(m_hFile);
|
|
m_hFile = INVALID_HANDLE_VALUE;
|
|
}
|
|
}
|
|
|
|
void CWiaDebugDumpToFile::Print( LPCTSTR pszString )
|
|
{
|
|
if (m_hFile && pszString)
|
|
{
|
|
DWORD dwWritten;
|
|
WriteFile( m_hFile, pszString, lstrlen(pszString)*sizeof(TCHAR), &dwWritten, NULL );
|
|
WriteFile( m_hFile, TEXT("\r\n"), 2*sizeof(TCHAR), &dwWritten, NULL );
|
|
}
|
|
}
|
|
|
|
|
|
CSimpleString CWiaDebugDump::GetTymedString( LONG tymed )
|
|
{
|
|
switch (tymed)
|
|
{
|
|
case TYMED_CALLBACK:
|
|
return TEXT("TYMED_CALLBACK");
|
|
|
|
case TYMED_FILE:
|
|
return TEXT("TYMED_FILE");
|
|
|
|
case TYMED_MULTIPAGE_CALLBACK:
|
|
return TEXT("TYMED_MULTIPAGE_CALLBACK");
|
|
|
|
case TYMED_MULTIPAGE_FILE:
|
|
return TEXT("TYMED_MULTIPAGE_FILE");
|
|
}
|
|
return CSimpleString().Format( TEXT("0x%08X"), tymed );
|
|
}
|
|
|
|
CSimpleString CWiaDebugDump::GetPropVariantTypeString( VARTYPE vt )
|
|
{
|
|
CSimpleString strResult;
|
|
|
|
static const struct
|
|
{
|
|
VARTYPE vt;
|
|
LPCTSTR pszName;
|
|
}
|
|
s_VarTypes[] =
|
|
{
|
|
{ VT_I2, TEXT("VT_I2") },
|
|
{ VT_I4, TEXT("VT_I4") },
|
|
{ VT_R4, TEXT("VT_R4") },
|
|
{ VT_R8, TEXT("VT_R8") },
|
|
{ VT_CY, TEXT("VT_CY") },
|
|
{ VT_DATE, TEXT("VT_DATE") },
|
|
{ VT_BSTR, TEXT("VT_BSTR") },
|
|
{ VT_DISPATCH, TEXT("VT_DISPATCH") },
|
|
{ VT_ERROR, TEXT("VT_ERROR") },
|
|
{ VT_BOOL, TEXT("VT_BOOL") },
|
|
{ VT_VARIANT, TEXT("VT_VARIANT") },
|
|
{ VT_UNKNOWN, TEXT("VT_UNKNOWN") },
|
|
{ VT_DECIMAL, TEXT("VT_DECIMAL") },
|
|
{ VT_I1, TEXT("VT_I1") },
|
|
{ VT_UI1, TEXT("VT_UI1") },
|
|
{ VT_UI2, TEXT("VT_UI2") },
|
|
{ VT_UI4, TEXT("VT_UI4") },
|
|
{ VT_I8, TEXT("VT_I8") },
|
|
{ VT_UI8, TEXT("VT_UI8") },
|
|
{ VT_INT, TEXT("VT_INT") },
|
|
{ VT_UINT, TEXT("VT_UINT") },
|
|
{ VT_VOID, TEXT("VT_VOID") },
|
|
{ VT_HRESULT, TEXT("VT_HRESULT") },
|
|
{ VT_PTR, TEXT("VT_PTR") },
|
|
{ VT_SAFEARRAY, TEXT("VT_SAFEARRAY") },
|
|
{ VT_CARRAY, TEXT("VT_CARRAY") },
|
|
{ VT_USERDEFINED, TEXT("VT_USERDEFINED") },
|
|
{ VT_LPSTR, TEXT("VT_LPSTR") },
|
|
{ VT_LPWSTR, TEXT("VT_LPWSTR") },
|
|
{ VT_RECORD, TEXT("VT_RECORD") },
|
|
{ VT_INT_PTR, TEXT("VT_INT_PTR") },
|
|
{ VT_UINT_PTR, TEXT("VT_UINT_PTR") },
|
|
{ VT_FILETIME, TEXT("VT_FILETIME") },
|
|
{ VT_BLOB, TEXT("VT_BLOB") },
|
|
{ VT_STREAM, TEXT("VT_STREAM") },
|
|
{ VT_STORAGE, TEXT("VT_STORAGE") },
|
|
{ VT_STREAMED_OBJECT, TEXT("VT_STREAMED_OBJECT") },
|
|
{ VT_STORED_OBJECT, TEXT("VT_STORED_OBJECT") },
|
|
{ VT_BLOB_OBJECT, TEXT("VT_BLOB_OBJECT") },
|
|
{ VT_CF, TEXT("VT_CF") },
|
|
{ VT_CLSID, TEXT("VT_CLSID") },
|
|
{ VT_VERSIONED_STREAM, TEXT("VT_VERSIONED_STREAM") }
|
|
},
|
|
s_ExtendedTypes[] =
|
|
{
|
|
{ VT_VECTOR, TEXT("VT_VECTOR") },
|
|
{ VT_ARRAY, TEXT("VT_ARRAY") },
|
|
{ VT_BYREF, TEXT("VT_BYREF") },
|
|
{ VT_RESERVED, TEXT("VT_RESERVED") }
|
|
};
|
|
for (int i=0;i<ARRAYSIZE(s_ExtendedTypes);i++)
|
|
{
|
|
if (vt & s_ExtendedTypes[i].vt)
|
|
{
|
|
if (strResult.Length())
|
|
{
|
|
strResult += TEXT(" | ");
|
|
}
|
|
strResult += s_ExtendedTypes[i].pszName;
|
|
}
|
|
}
|
|
for (int i=0;i<ARRAYSIZE(s_VarTypes);i++)
|
|
{
|
|
if ((vt & VT_TYPEMASK) == s_VarTypes[i].vt)
|
|
{
|
|
if (strResult.Length())
|
|
{
|
|
strResult += TEXT(" | ");
|
|
}
|
|
strResult += s_VarTypes[i].pszName;
|
|
}
|
|
}
|
|
if (!strResult.Length())
|
|
{
|
|
strResult.Format( TEXT("Unknown variant type: 0x%04X"), vt );
|
|
}
|
|
return strResult;
|
|
}
|
|
|
|
|
|
CSimpleString CWiaDebugDump::GetPrintableValue( PROPVARIANT &PropVariant )
|
|
{
|
|
TCHAR szValue[1024] = TEXT("");
|
|
switch (PropVariant.vt)
|
|
{
|
|
case VT_I1:
|
|
wsprintf(szValue,TEXT("%d, (0x%08X)"),PropVariant.cVal,PropVariant.cVal);
|
|
break;
|
|
|
|
case VT_UI1:
|
|
wsprintf(szValue,TEXT("%u, (0x%08X)"),PropVariant.bVal,PropVariant.bVal);
|
|
break;
|
|
|
|
case VT_I2:
|
|
wsprintf(szValue,TEXT("%d, (0x%08X)"),PropVariant.iVal,PropVariant.iVal);
|
|
break;
|
|
|
|
case VT_UI2:
|
|
wsprintf(szValue,TEXT("%u, (0x%08X)"),PropVariant.uiVal,PropVariant.uiVal);
|
|
break;
|
|
|
|
case VT_I4:
|
|
wsprintf(szValue,TEXT("%ld, (0x%08X)"),PropVariant.lVal,PropVariant.lVal);
|
|
break;
|
|
|
|
case VT_UI4:
|
|
wsprintf(szValue,TEXT("%lu, (0x%08X)"),PropVariant.ulVal,PropVariant.ulVal);
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
wsprintf(szValue,TEXT("%ws"),PropVariant.bstrVal);
|
|
break;
|
|
|
|
case VT_LPWSTR:
|
|
wsprintf(szValue,TEXT("%ws"),PropVariant.pwszVal );
|
|
break;
|
|
|
|
case VT_CLSID:
|
|
wsprintf(szValue,TEXT("%s"), GetStringFromGuid(*PropVariant.puuid).String());
|
|
break;
|
|
|
|
case VT_VECTOR|VT_I1:
|
|
{
|
|
wsprintf(szValue+lstrlen(szValue), TEXT("Length: [%d] "), PropVariant.cac.cElems );
|
|
for (int i=0;i<(int)PropVariant.cac.cElems;i++)
|
|
{
|
|
if (lstrlen(szValue) >= MAX_DUMP_STRING)
|
|
{
|
|
lstrcat( szValue, TEXT("...") );
|
|
break;
|
|
}
|
|
wsprintf(szValue+lstrlen(szValue), TEXT("%02X"), (ULONG)PropVariant.cac.pElems[i] );
|
|
if (i < (int)PropVariant.cal.cElems-1 && i % 4 == 3)
|
|
{
|
|
wsprintf(szValue+lstrlen(szValue),TEXT(" "));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR|VT_UI1:
|
|
{
|
|
wsprintf(szValue+lstrlen(szValue), TEXT("Length: [%d] "), PropVariant.caub.cElems );
|
|
for (int i=0;i<(int)PropVariant.caub.cElems;i++)
|
|
{
|
|
if (lstrlen(szValue) >= MAX_DUMP_STRING)
|
|
{
|
|
lstrcat( szValue, TEXT("...") );
|
|
break;
|
|
}
|
|
|
|
wsprintf(szValue+lstrlen(szValue), TEXT("%02X"), (ULONG)PropVariant.caub.pElems[i] );
|
|
if (i < (int)PropVariant.cal.cElems-1 && i % 4 == 3)
|
|
{
|
|
wsprintf(szValue+lstrlen(szValue),TEXT(" "));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR|VT_I2:
|
|
{
|
|
wsprintf(szValue+lstrlen(szValue), TEXT("Length: [%d] "), PropVariant.cai.cElems );
|
|
for (int i=0;i<(int)PropVariant.cai.cElems;i++)
|
|
{
|
|
if (lstrlen(szValue) >= MAX_DUMP_STRING)
|
|
{
|
|
lstrcat( szValue, TEXT("...") );
|
|
break;
|
|
}
|
|
|
|
wsprintf(szValue+lstrlen(szValue),TEXT("%04X"),(ULONG)PropVariant.cai.pElems[i]);
|
|
if (i < (int)PropVariant.cal.cElems-1)
|
|
{
|
|
wsprintf(szValue+lstrlen(szValue),TEXT(" "));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR|VT_UI2:
|
|
{
|
|
wsprintf(szValue+lstrlen(szValue), TEXT("Length: [%d] "), PropVariant.caui.cElems );
|
|
for (int i=0;i<(int)PropVariant.caui.cElems;i++)
|
|
{
|
|
if (lstrlen(szValue) >= MAX_DUMP_STRING)
|
|
{
|
|
lstrcat( szValue, TEXT("...") );
|
|
break;
|
|
}
|
|
|
|
wsprintf(szValue+lstrlen(szValue),TEXT("%04X"),(ULONG)PropVariant.caui.pElems[i]);
|
|
if (i < (int)PropVariant.cal.cElems-1)
|
|
{
|
|
wsprintf(szValue+lstrlen(szValue),TEXT(" "));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR|VT_I4:
|
|
{
|
|
wsprintf(szValue+lstrlen(szValue), TEXT("Length: [%d] "), PropVariant.cal.cElems );
|
|
for (int i=0;i<(int)PropVariant.cal.cElems;i++)
|
|
{
|
|
if (lstrlen(szValue) >= MAX_DUMP_STRING)
|
|
{
|
|
lstrcat( szValue, TEXT("...") );
|
|
break;
|
|
}
|
|
|
|
wsprintf(szValue+lstrlen(szValue),TEXT("%08X"),(ULONG)PropVariant.cal.pElems[i]);
|
|
if (i < (int)PropVariant.cal.cElems-1)
|
|
{
|
|
wsprintf(szValue+lstrlen(szValue),TEXT(" "));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
case VT_VECTOR|VT_UI4:
|
|
{
|
|
wsprintf(szValue+lstrlen(szValue), TEXT("Length: [%d] "), PropVariant.caul.cElems );
|
|
for (int i=0;i<(int)PropVariant.caul.cElems;i++)
|
|
{
|
|
if (lstrlen(szValue) >= MAX_DUMP_STRING)
|
|
{
|
|
lstrcat( szValue, TEXT("...") );
|
|
break;
|
|
}
|
|
|
|
wsprintf(szValue+lstrlen(szValue),TEXT("%08X"),(ULONG)PropVariant.caul.pElems[i]);
|
|
if (i < (int)PropVariant.cal.cElems-1)
|
|
{
|
|
wsprintf(szValue+lstrlen(szValue),TEXT(" "));
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
wsprintf(szValue,TEXT("Unknown Type %d (0x%08X)"),PropVariant.vt,PropVariant.vt);
|
|
}
|
|
|
|
return szValue;
|
|
}
|
|
|
|
CSimpleString CWiaDebugDump::GetPrintableValue( VARIANT &Variant )
|
|
{
|
|
TCHAR szValue[1024] = TEXT("");
|
|
switch (Variant.vt)
|
|
{
|
|
case VT_I1:
|
|
wsprintf(szValue,TEXT("%d, (0x%08X)"),Variant.cVal,Variant.cVal);
|
|
break;
|
|
|
|
case VT_UI1:
|
|
wsprintf(szValue,TEXT("%u, (0x%08X)"),Variant.bVal,Variant.bVal);
|
|
break;
|
|
|
|
case VT_I2:
|
|
wsprintf(szValue,TEXT("%d, (0x%08X)"),Variant.iVal,Variant.iVal);
|
|
break;
|
|
|
|
case VT_UI2:
|
|
wsprintf(szValue,TEXT("%u, (0x%08X)"),Variant.uiVal,Variant.uiVal);
|
|
break;
|
|
|
|
case VT_I4:
|
|
wsprintf(szValue,TEXT("%ld, (0x%08X)"),Variant.lVal,Variant.lVal);
|
|
break;
|
|
|
|
case VT_UI4:
|
|
wsprintf(szValue,TEXT("%lu, (0x%08X)"),Variant.ulVal,Variant.ulVal);
|
|
break;
|
|
|
|
case VT_BSTR:
|
|
wsprintf(szValue,TEXT("%ws"),Variant.bstrVal);
|
|
break;
|
|
|
|
|
|
default:
|
|
wsprintf(szValue,TEXT("Unknown Type %d (0x%08X)"),Variant.vt,Variant.vt);
|
|
}
|
|
|
|
return szValue;
|
|
}
|
|
|
|
|
|
CSimpleString CWiaDebugDump::GetPrintableName( const STATPROPSTG &StatPropStg )
|
|
{
|
|
CSimpleString strResult;
|
|
|
|
//
|
|
// Get the name
|
|
//
|
|
strResult += TEXT("[");
|
|
if (StatPropStg.lpwstrName)
|
|
{
|
|
strResult += CSimpleStringConvert::NaturalString(CSimpleStringWide(StatPropStg.lpwstrName));
|
|
}
|
|
else
|
|
{
|
|
strResult += TEXT("*No Property Name*");
|
|
}
|
|
|
|
//
|
|
// Get the propid
|
|
//
|
|
strResult += CSimpleString().Format( TEXT("], propid: %d"), StatPropStg.propid );
|
|
return strResult;
|
|
}
|
|
|
|
CSimpleString CWiaDebugDump::GetPrintableAccessFlags( ULONG nAccessFlags )
|
|
{
|
|
CSimpleString strResult;
|
|
static const struct
|
|
{
|
|
ULONG nFlag;
|
|
LPCTSTR pszName;
|
|
}
|
|
s_Flags[] =
|
|
{
|
|
{ WIA_PROP_READ, TEXT("WIA_PROP_READ") },
|
|
{ WIA_PROP_WRITE, TEXT("WIA_PROP_WRITE") },
|
|
{ WIA_PROP_SYNC_REQUIRED, TEXT("WIA_PROP_SYNC_REQUIRED") },
|
|
{ WIA_PROP_NONE, TEXT("WIA_PROP_NONE") },
|
|
{ WIA_PROP_RANGE, TEXT("WIA_PROP_RANGE") },
|
|
{ WIA_PROP_LIST, TEXT("WIA_PROP_LIST") },
|
|
{ WIA_PROP_FLAG, TEXT("WIA_PROP_FLAG") },
|
|
{ WIA_PROP_CACHEABLE, TEXT("WIA_PROP_CACHEABLE") }
|
|
};
|
|
for (int i=0;i<ARRAYSIZE(s_Flags);i++)
|
|
{
|
|
if (nAccessFlags & s_Flags[i].nFlag)
|
|
{
|
|
if (strResult.Length())
|
|
{
|
|
strResult += TEXT(" | ");
|
|
}
|
|
strResult += s_Flags[i].pszName;
|
|
}
|
|
}
|
|
if (!strResult.Length())
|
|
{
|
|
strResult = TEXT("*none*");
|
|
}
|
|
return strResult;
|
|
}
|
|
|
|
CSimpleString CWiaDebugDump::GetPrintableLegalValues( ULONG nAccessFlags, const PROPVARIANT &PropVariantAttributes )
|
|
{
|
|
CSimpleString strResult;
|
|
if ((nAccessFlags & WIA_PROP_RANGE) && (PropVariantAttributes.vt & VT_VECTOR))
|
|
{
|
|
CSimpleString strMin, strMax, strStep;
|
|
switch (PropVariantAttributes.vt & VT_TYPEMASK)
|
|
{
|
|
case VT_I1:
|
|
strMin.Format(TEXT("%d"), PropVariantAttributes.cac.pElems[WIA_RANGE_MIN] );
|
|
strMax.Format(TEXT("%d"), PropVariantAttributes.cac.pElems[WIA_RANGE_MAX] );
|
|
strStep.Format(TEXT("%d"), PropVariantAttributes.cac.pElems[WIA_RANGE_STEP] );
|
|
break;
|
|
|
|
case VT_UI1:
|
|
strMin.Format(TEXT("%u"), PropVariantAttributes.caub.pElems[WIA_RANGE_MIN] );
|
|
strMax.Format(TEXT("%u"), PropVariantAttributes.caub.pElems[WIA_RANGE_MAX] );
|
|
strStep.Format(TEXT("%u"), PropVariantAttributes.caub.pElems[WIA_RANGE_STEP] );
|
|
break;
|
|
|
|
case VT_I2:
|
|
strMin.Format(TEXT("%d"), PropVariantAttributes.cai.pElems[WIA_RANGE_MIN] );
|
|
strMax.Format(TEXT("%d"), PropVariantAttributes.cai.pElems[WIA_RANGE_MAX] );
|
|
strStep.Format(TEXT("%d"), PropVariantAttributes.cai.pElems[WIA_RANGE_STEP] );
|
|
break;
|
|
|
|
case VT_UI2:
|
|
strMin.Format(TEXT("%u"), PropVariantAttributes.caui.pElems[WIA_RANGE_MIN] );
|
|
strMax.Format(TEXT("%u"), PropVariantAttributes.caui.pElems[WIA_RANGE_MAX] );
|
|
strStep.Format(TEXT("%u"), PropVariantAttributes.caui.pElems[WIA_RANGE_STEP] );
|
|
break;
|
|
|
|
case VT_I4:
|
|
strMin.Format(TEXT("%d"), PropVariantAttributes.cal.pElems[WIA_RANGE_MIN] );
|
|
strMax.Format(TEXT("%d"), PropVariantAttributes.cal.pElems[WIA_RANGE_MAX] );
|
|
strStep.Format(TEXT("%d"), PropVariantAttributes.cal.pElems[WIA_RANGE_STEP] );
|
|
break;
|
|
|
|
case VT_UI4:
|
|
strMin.Format(TEXT("%u"), PropVariantAttributes.caul.pElems[WIA_RANGE_MIN] );
|
|
strMax.Format(TEXT("%u"), PropVariantAttributes.caul.pElems[WIA_RANGE_MAX] );
|
|
strStep.Format(TEXT("%u"), PropVariantAttributes.caul.pElems[WIA_RANGE_STEP] );
|
|
break;
|
|
|
|
case VT_I8:
|
|
strMin.Format(TEXT("%d"), PropVariantAttributes.cah.pElems[WIA_RANGE_MIN].LowPart );
|
|
strMax.Format(TEXT("%d"), PropVariantAttributes.cah.pElems[WIA_RANGE_MAX].LowPart );
|
|
strStep.Format(TEXT("%d"), PropVariantAttributes.cah.pElems[WIA_RANGE_STEP].LowPart );
|
|
break;
|
|
|
|
case VT_UI8:
|
|
strMin.Format(TEXT("%u"), PropVariantAttributes.cauh.pElems[WIA_RANGE_MIN].LowPart );
|
|
strMax.Format(TEXT("%u"), PropVariantAttributes.cauh.pElems[WIA_RANGE_MAX].LowPart );
|
|
strStep.Format(TEXT("%u"), PropVariantAttributes.cauh.pElems[WIA_RANGE_STEP].LowPart );
|
|
break;
|
|
}
|
|
strResult.Format( TEXT("%s...%s, Step: %s"), strMin.String(), strMax.String(), strStep.String() );
|
|
}
|
|
else if (nAccessFlags & WIA_PROP_LIST && (PropVariantAttributes.vt & VT_VECTOR))
|
|
{
|
|
if (((PropVariantAttributes.vt & VT_TYPEMASK) == VT_I4) || ((PropVariantAttributes.vt & VT_TYPEMASK) == VT_UI4))
|
|
{
|
|
for (ULONG i=0;i<PropVariantAttributes.cal.cElems - WIA_LIST_VALUES;i++)
|
|
{
|
|
if (strResult.Length())
|
|
{
|
|
strResult += TEXT(",");
|
|
}
|
|
if (strResult.Length() >= MAX_DUMP_STRING)
|
|
{
|
|
strResult += TEXT("...");
|
|
break;
|
|
}
|
|
strResult += CSimpleString().Format( TEXT("%d"), PropVariantAttributes.cal.pElems[WIA_LIST_VALUES + i] );
|
|
}
|
|
}
|
|
else if ((PropVariantAttributes.vt & VT_TYPEMASK) == VT_CLSID)
|
|
{
|
|
for (ULONG i=0;i<PropVariantAttributes.cauuid.cElems - WIA_LIST_VALUES;i++)
|
|
{
|
|
if (strResult.Length())
|
|
{
|
|
strResult += TEXT(",");
|
|
}
|
|
if (strResult.Length() >= MAX_DUMP_STRING)
|
|
{
|
|
strResult += TEXT("...");
|
|
break;
|
|
}
|
|
strResult += CSimpleString().Format( TEXT("%s"), GetStringFromGuid(PropVariantAttributes.cauuid.pElems[WIA_LIST_VALUES + i]).String() );
|
|
}
|
|
}
|
|
}
|
|
else if (nAccessFlags & WIA_PROP_FLAG)
|
|
{
|
|
strResult.Format( TEXT("0x%08X"), PropVariantAttributes.caul.pElems[WIA_FLAG_VALUES] );
|
|
}
|
|
return strResult;
|
|
}
|
|
|
|
CSimpleString CWiaDebugDump::GetWiaItemTypeFlags( IUnknown *pUnknown )
|
|
{
|
|
CSimpleString strResult;
|
|
if (pUnknown)
|
|
{
|
|
CComPtr<IWiaItem> pWiaItem;
|
|
HRESULT hr = pUnknown->QueryInterface( IID_IWiaItem, (void**)&pWiaItem );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LONG nItemType = 0;
|
|
hr = pWiaItem->GetItemType(&nItemType);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
static const struct
|
|
{
|
|
ULONG nFlag;
|
|
LPCTSTR pszName;
|
|
}
|
|
s_Flags[] =
|
|
{
|
|
{ WiaItemTypeFree, TEXT("WiaItemTypeFree") },
|
|
{ WiaItemTypeImage, TEXT("WiaItemTypeImage") },
|
|
{ WiaItemTypeFile, TEXT("WiaItemTypeFile") },
|
|
{ WiaItemTypeFolder, TEXT("WiaItemTypeFolder") },
|
|
{ WiaItemTypeRoot, TEXT("WiaItemTypeRoot") },
|
|
{ WiaItemTypeAnalyze, TEXT("WiaItemTypeAnalyze") },
|
|
{ WiaItemTypeAudio, TEXT("WiaItemTypeAudio") },
|
|
{ WiaItemTypeDevice, TEXT("WiaItemTypeDevice") },
|
|
{ WiaItemTypeDeleted, TEXT("WiaItemTypeDeleted") },
|
|
{ WiaItemTypeDisconnected, TEXT("WiaItemTypeDisconnected") },
|
|
{ WiaItemTypeHPanorama, TEXT("WiaItemTypeHPanorama") },
|
|
{ WiaItemTypeVPanorama, TEXT("WiaItemTypeVPanorama") },
|
|
{ WiaItemTypeBurst, TEXT("WiaItemTypeBurst") },
|
|
{ WiaItemTypeStorage, TEXT("WiaItemTypeStorage") },
|
|
{ WiaItemTypeTransfer, TEXT("WiaItemTypeTransfer") },
|
|
{ WiaItemTypeGenerated, TEXT("WiaItemTypeGenerated") },
|
|
{ WiaItemTypeHasAttachments, TEXT("WiaItemTypeHasAttachments") },
|
|
{ WiaItemTypeVideo, TEXT("WiaItemTypeVideo") }
|
|
};
|
|
for (int i=0;i<ARRAYSIZE(s_Flags);i++)
|
|
{
|
|
if (nItemType & s_Flags[i].nFlag)
|
|
{
|
|
if (strResult.Length())
|
|
{
|
|
strResult += TEXT(" | ");
|
|
}
|
|
strResult += s_Flags[i].pszName;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return strResult;
|
|
}
|
|
|
|
CSimpleString CWiaDebugDump::GetStringFromGuid( const GUID &guid )
|
|
{
|
|
static HINSTANCE s_WiaDebugInstance = NULL;
|
|
static GetStringFromGuidProc s_pfnGetStringFromGuid = NULL;
|
|
|
|
if (!s_pfnGetStringFromGuid)
|
|
{
|
|
if (!s_WiaDebugInstance)
|
|
{
|
|
s_WiaDebugInstance = LoadLibrary(TEXT("wiadebug.dll"));
|
|
}
|
|
|
|
if (s_WiaDebugInstance)
|
|
{
|
|
s_pfnGetStringFromGuid = reinterpret_cast<GetStringFromGuidProc>(GetProcAddress( s_WiaDebugInstance, GET_STRING_FROM_GUID_NAME ));
|
|
}
|
|
}
|
|
|
|
if (s_pfnGetStringFromGuid)
|
|
{
|
|
TCHAR szString[MAX_PATH];
|
|
s_pfnGetStringFromGuid( &guid, szString, ARRAYSIZE(szString) );
|
|
return szString;
|
|
}
|
|
else
|
|
{
|
|
CSimpleString strResult;
|
|
|
|
LPOLESTR pszGuid = NULL;
|
|
HRESULT hr = StringFromCLSID( guid, &pszGuid );
|
|
if (SUCCEEDED(hr) && pszGuid)
|
|
{
|
|
strResult = CSimpleStringConvert::NaturalString(CSimpleStringWide(pszGuid));
|
|
CoTaskMemFree(pszGuid);
|
|
}
|
|
return strResult;
|
|
}
|
|
}
|
|
|
|
void CWiaDebugDump::DumpWiaPropertyStorage( IUnknown *pUnknown )
|
|
{
|
|
if (OK())
|
|
{
|
|
//
|
|
// Make sure we have a non-NULL interface pointer
|
|
//
|
|
if (pUnknown)
|
|
{
|
|
//
|
|
// Get the proper interface
|
|
//
|
|
CComPtr<IWiaPropertyStorage> pWiaPropertyStorage;
|
|
HRESULT hr = pUnknown->QueryInterface( IID_IWiaPropertyStorage, (void**)&pWiaPropertyStorage );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get information about this property storage
|
|
//
|
|
CComPtr<IEnumSTATPROPSTG> pEnumStatPropStorage;
|
|
hr = pWiaPropertyStorage->Enum(&pEnumStatPropStorage);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Enumerate the properties
|
|
//
|
|
STATPROPSTG StatPropStg = {0};
|
|
while ((hr = pEnumStatPropStorage->Next(1,&StatPropStg,NULL)) == S_OK)
|
|
{
|
|
//
|
|
// Prepare the propspec
|
|
//
|
|
PROPSPEC PropSpec = {0};
|
|
PropSpec.ulKind = PRSPEC_PROPID;
|
|
PropSpec.propid = StatPropStg.propid;
|
|
|
|
//
|
|
// Prepare the propvariant
|
|
//
|
|
PROPVARIANT PropVariant = {0};
|
|
|
|
//
|
|
// Get the property
|
|
//
|
|
hr = pWiaPropertyStorage->ReadMultiple( 1, &PropSpec, &PropVariant );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get the property attributes
|
|
//
|
|
ULONG nAccessFlags = 0;
|
|
PROPVARIANT PropVariantAttributes = {0};
|
|
hr = pWiaPropertyStorage->GetPropertyAttributes( 1, &PropSpec, &nAccessFlags, &PropVariantAttributes );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Print out the properties
|
|
//
|
|
CSimpleString strName = GetPrintableName( StatPropStg );
|
|
Print( CSimpleString().Format(TEXT(" %s"), strName.String() ));
|
|
|
|
CSimpleString strType = GetPropVariantTypeString( PropVariant.vt );
|
|
Print( CSimpleString().Format(TEXT(" Type: %s"), strType.String()) );
|
|
|
|
CSimpleString strAccess = GetPrintableAccessFlags( nAccessFlags );
|
|
Print( CSimpleString().Format(TEXT(" Access: %s"), strAccess.String()) );
|
|
|
|
CSimpleString strValue = GetPrintableValue( PropVariant );
|
|
Print( CSimpleString().Format(TEXT(" Curr: %s"), strValue.String()) );
|
|
|
|
CSimpleString strLegalValues = GetPrintableLegalValues( nAccessFlags, PropVariantAttributes );
|
|
if (strLegalValues.Length())
|
|
{
|
|
Print( CSimpleString().Format(TEXT(" Legal: %s"), strLegalValues.String()) );
|
|
}
|
|
|
|
//
|
|
// Free the attributes
|
|
//
|
|
PropVariantClear(&PropVariantAttributes);
|
|
}
|
|
|
|
//
|
|
// Free the property
|
|
//
|
|
PropVariantClear(&PropVariant);
|
|
}
|
|
|
|
|
|
//
|
|
// Clean up the STATPROPSTG
|
|
//
|
|
if (StatPropStg.lpwstrName)
|
|
{
|
|
CoTaskMemFree(StatPropStg.lpwstrName);
|
|
}
|
|
ZeroMemory(&StatPropStg,sizeof(StatPropStg));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CWiaDebugDump::Print( LPCTSTR pszString )
|
|
{
|
|
WIA_TRACE((TEXT("%s"), pszString ));
|
|
}
|
|
|
|
void CWiaDebugDump::PrintAndDestroyWiaDevCap( WIA_DEV_CAP &WiaDevCap, LPCTSTR pszType )
|
|
{
|
|
if (OK())
|
|
{
|
|
Print( CSimpleString().Format(TEXT(" %s: %s"), pszType, GetStringFromGuid( WiaDevCap.guid ).String()));
|
|
Print( CSimpleString().Format(TEXT(" Flags: %08X"), WiaDevCap.ulFlags) );
|
|
if (WiaDevCap.bstrName)
|
|
{
|
|
Print( CSimpleString().Format(TEXT(" Name: %ws"), WiaDevCap.bstrName) );
|
|
SysFreeString(WiaDevCap.bstrName);
|
|
WiaDevCap.bstrName = NULL;
|
|
}
|
|
if (WiaDevCap.bstrDescription)
|
|
{
|
|
Print( CSimpleString().Format(TEXT(" Description: %ws"), WiaDevCap.bstrDescription) );
|
|
SysFreeString(WiaDevCap.bstrDescription);
|
|
WiaDevCap.bstrDescription = NULL;
|
|
}
|
|
if (WiaDevCap.bstrIcon)
|
|
{
|
|
Print( CSimpleString().Format(TEXT(" Icon: %ws"), WiaDevCap.bstrIcon));
|
|
SysFreeString(WiaDevCap.bstrIcon);
|
|
WiaDevCap.bstrIcon = NULL;
|
|
}
|
|
if (WiaDevCap.bstrCommandline)
|
|
{
|
|
Print( CSimpleString().Format(TEXT(" bstrCommandline: %ws"), WiaDevCap.bstrCommandline));
|
|
SysFreeString(WiaDevCap.bstrCommandline);
|
|
WiaDevCap.bstrCommandline = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CWiaDebugDump::DumpCaps( IUnknown *pUnknown )
|
|
{
|
|
if (pUnknown)
|
|
{
|
|
//
|
|
// Get the item
|
|
//
|
|
CComPtr<IWiaItem> pWiaItem;
|
|
HRESULT hr = pUnknown->QueryInterface( IID_IWiaItem, (void**)&pWiaItem );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get the format enumerator
|
|
//
|
|
CComPtr<IEnumWIA_DEV_CAPS> pEnumWIA_DEV_CAPS;
|
|
hr = pWiaItem->EnumDeviceCapabilities(WIA_DEVICE_COMMANDS,&pEnumWIA_DEV_CAPS);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Start at the beginning
|
|
//
|
|
hr = pEnumWIA_DEV_CAPS->Reset();
|
|
while (hr == S_OK)
|
|
{
|
|
//
|
|
// Get the next item
|
|
//
|
|
WIA_DEV_CAP WiaDevCap = {0};
|
|
hr = pEnumWIA_DEV_CAPS->Next(1, &WiaDevCap, NULL);
|
|
if (hr == S_OK)
|
|
{
|
|
PrintAndDestroyWiaDevCap( WiaDevCap, TEXT("Capability") );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CWiaDebugDump::DumpEvents( IUnknown *pUnknown )
|
|
{
|
|
if (pUnknown)
|
|
{
|
|
//
|
|
// Get the item
|
|
//
|
|
CComPtr<IWiaItem> pWiaItem;
|
|
HRESULT hr = pUnknown->QueryInterface( IID_IWiaItem, (void**)&pWiaItem );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get the format enumerator
|
|
//
|
|
CComPtr<IEnumWIA_DEV_CAPS> pEnumWIA_DEV_CAPS;
|
|
hr = pWiaItem->EnumDeviceCapabilities(WIA_DEVICE_EVENTS,&pEnumWIA_DEV_CAPS);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Start at the beginning
|
|
//
|
|
hr = pEnumWIA_DEV_CAPS->Reset();
|
|
while (hr == S_OK)
|
|
{
|
|
//
|
|
// Get the next item
|
|
//
|
|
WIA_DEV_CAP WiaDevCap = {0};
|
|
hr = pEnumWIA_DEV_CAPS->Next(1, &WiaDevCap, NULL);
|
|
if (hr == S_OK)
|
|
{
|
|
PrintAndDestroyWiaDevCap( WiaDevCap, TEXT("Event") );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CWiaDebugDump::DumpFormatInfo( IUnknown *pUnknown )
|
|
{
|
|
if (OK())
|
|
{
|
|
if (pUnknown)
|
|
{
|
|
//
|
|
// Get the data transfer interface
|
|
//
|
|
CComPtr<IWiaDataTransfer> pWiaDataTransfer;
|
|
HRESULT hr = pUnknown->QueryInterface( IID_IWiaDataTransfer, (void**)&pWiaDataTransfer );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Get the format enumerator
|
|
//
|
|
CComPtr<IEnumWIA_FORMAT_INFO> pEnumWIA_FORMAT_INFO;
|
|
hr = pWiaDataTransfer->idtEnumWIA_FORMAT_INFO(&pEnumWIA_FORMAT_INFO);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Start at the beginning
|
|
//
|
|
hr = pEnumWIA_FORMAT_INFO->Reset();
|
|
while (hr == S_OK)
|
|
{
|
|
//
|
|
// Get the next item
|
|
//
|
|
WIA_FORMAT_INFO WiaFormatInfo = {0};
|
|
hr = pEnumWIA_FORMAT_INFO->Next(1, &WiaFormatInfo, NULL);
|
|
if (hr == S_OK)
|
|
{
|
|
Print(CSimpleString().Format( TEXT(" Supported format: %s, TYMED: %s"), GetStringFromGuid( WiaFormatInfo.guidFormatID ).String(), GetTymedString( WiaFormatInfo.lTymed ).String() ));
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CWiaDebugDump::DumpWiaItem( IUnknown *pUnknown )
|
|
{
|
|
if (OK() && pUnknown)
|
|
{
|
|
CSimpleStringWide strFullItemName;
|
|
PropStorageHelpers::GetProperty( pUnknown, WIA_IPA_FULL_ITEM_NAME, strFullItemName );
|
|
Print( CSimpleString().Format( TEXT("[Dumping %ws]"), strFullItemName.String() ) );
|
|
CSimpleString strItemType = GetWiaItemTypeFlags( pUnknown );
|
|
Print( CSimpleString().Format(TEXT(" Item Type: %s"), strItemType.String()) );
|
|
DumpFormatInfo( pUnknown );
|
|
DumpCaps( pUnknown );
|
|
DumpEvents( pUnknown );
|
|
DumpWiaPropertyStorage( pUnknown );
|
|
Print( TEXT("") );
|
|
}
|
|
}
|
|
|
|
void CWiaDebugDump::DumpRecursive( IUnknown *pUnknown )
|
|
{
|
|
if (OK() && pUnknown)
|
|
{
|
|
//
|
|
// Get an item pointer
|
|
//
|
|
CComPtr<IWiaItem> pWiaItem;
|
|
HRESULT hr = pUnknown->QueryInterface( IID_IWiaItem, (void**)&pWiaItem );
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Dump this one
|
|
//
|
|
DumpWiaItem(pWiaItem);
|
|
|
|
//
|
|
// Recurse into this item's children
|
|
//
|
|
CComPtr <IEnumWiaItem> pEnumChildItem;
|
|
hr = pWiaItem->EnumChildItems(&pEnumChildItem);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Start at the beginning
|
|
//
|
|
hr = pEnumChildItem->Reset();
|
|
while (hr == S_OK)
|
|
{
|
|
//
|
|
// Get the next item
|
|
//
|
|
CComPtr<IWiaItem> pChildItem;
|
|
hr = pEnumChildItem->Next(1, &pChildItem, NULL);
|
|
if (hr == S_OK)
|
|
{
|
|
DumpRecursive( pChildItem );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|