/******************************************************************************* * * (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= 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= 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= 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 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(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 pWiaPropertyStorage; HRESULT hr = pUnknown->QueryInterface( IID_IWiaPropertyStorage, (void**)&pWiaPropertyStorage ); if (SUCCEEDED(hr)) { // // Get information about this property storage // CComPtr 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 pWiaItem; HRESULT hr = pUnknown->QueryInterface( IID_IWiaItem, (void**)&pWiaItem ); if (SUCCEEDED(hr)) { // // Get the format enumerator // CComPtr 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 pWiaItem; HRESULT hr = pUnknown->QueryInterface( IID_IWiaItem, (void**)&pWiaItem ); if (SUCCEEDED(hr)) { // // Get the format enumerator // CComPtr 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 pWiaDataTransfer; HRESULT hr = pUnknown->QueryInterface( IID_IWiaDataTransfer, (void**)&pWiaDataTransfer ); if (SUCCEEDED(hr)) { // // Get the format enumerator // CComPtr 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 pWiaItem; HRESULT hr = pUnknown->QueryInterface( IID_IWiaItem, (void**)&pWiaItem ); if (SUCCEEDED(hr)) { // // Dump this one // DumpWiaItem(pWiaItem); // // Recurse into this item's children // CComPtr pEnumChildItem; hr = pWiaItem->EnumChildItems(&pEnumChildItem); if (SUCCEEDED(hr)) { // // Start at the beginning // hr = pEnumChildItem->Reset(); while (hr == S_OK) { // // Get the next item // CComPtr pChildItem; hr = pEnumChildItem->Next(1, &pChildItem, NULL); if (hr == S_OK) { DumpRecursive( pChildItem ); } } } } } }