VARIANT类型和值的转换函数-msdn
2013-03-05 15:05
183 查看
//http://technet.microsoft.com/en-us/subscriptions/aa379016%28v=vs.85%29.aspx /* Sample has Bug pwszChildStorageName[ cchChildStorageName-1 ] = L'\0'; //Delete //--cchChildStorageName; wcsncpy_s( pwszChildStorageName, cchChildStorageName, pwszStorageName, cchChildStorageName ); //Delete //cchChildStorageName -= wcslen(pwszStorageName); wcsncat_s( pwszChildStorageName, cchChildStorageName, L"\\", cchChildStorageName ); //Delete //cchChildStorageName -= 2; wcsncat_s( pwszChildStorageName, cchChildStorageName, statstg.pwcsName, cchChildStorageName ); Reason:Buffer is too small. */ //+=================================================================== // // To Build: cl /GX enumall.cpp // // The following code example dumps all the properties in all property // sets of a storage file. // //+=================================================================== #define UNICODE #define _UNICODE #include <stdio.h> #include <windows.h> #pragma comment( lib, "ole32.lib" ) //+------------------------------------------------------------------- // // ConvertVarTypeToString // // Generate a string for a given PROPVARIANT variable type (VT). // For the given vt, write the string to pwszType, which is a buffer // of size cchType characters. // //+------------------------------------------------------------------- void ConvertVarTypeToString( VARTYPE vt, WCHAR *pwszType, ULONG cchType ) { const WCHAR *pwszModifier; // Ensure that the output string is terminated // (wcsncpy does not guarantee termination) pwszType[ cchType-1 ] = L'\0'; --cchType; // Create a string using the basic type. switch( vt & VT_TYPEMASK ) { case VT_EMPTY: wcsncpy_s( pwszType, cchType, L"VT_EMPTY", cchType ); break; case VT_NULL: wcsncpy_s( pwszType, cchType, L"VT_NULL", cchType ); break; case VT_I2: wcsncpy_s( pwszType, cchType, L"VT_I2", cchType ); break; case VT_I4: wcsncpy_s( pwszType, cchType, L"VT_I4", cchType ); break; case VT_I8: wcsncpy_s( pwszType, cchType, L"VT_I8", cchType ); break; case VT_UI2: wcsncpy_s( pwszType, cchType, L"VT_UI2", cchType ); break; case VT_UI4: wcsncpy_s( pwszType, cchType, L"VT_UI4", cchType ); break; case VT_UI8: wcsncpy_s( pwszType, cchType, L"VT_UI8", cchType ); break; case VT_R4: wcsncpy_s( pwszType, cchType, L"VT_R4", cchType ); break; case VT_R8: wcsncpy_s( pwszType, cchType, L"VT_R8", cchType ); break; case VT_CY: wcsncpy_s( pwszType, cchType, L"VT_CY", cchType ); break; case VT_DATE: wcsncpy_s( pwszType, cchType, L"VT_DATE", cchType ); break; case VT_BSTR: wcsncpy_s( pwszType, cchType, L"VT_BSTR", cchType ); break; case VT_ERROR: wcsncpy_s( pwszType, cchType, L"VT_ERROR", cchType ); break; case VT_BOOL: wcsncpy_s( pwszType, cchType, L"VT_BOOL", cchType ); break; case VT_VARIANT: wcsncpy_s( pwszType, cchType, L"VT_VARIANT", cchType ); break; case VT_DECIMAL: wcsncpy_s( pwszType, cchType, L"VT_DECIMAL", cchType ); break; case VT_I1: wcsncpy_s( pwszType, cchType, L"VT_I1", cchType ); break; case VT_UI1: wcsncpy_s( pwszType, cchType, L"VT_UI1", cchType ); break; case VT_INT: wcsncpy_s( pwszType, cchType, L"VT_INT", cchType ); break; case VT_UINT: wcsncpy_s( pwszType, cchType, L"VT_UINT", cchType ); break; case VT_VOID: wcsncpy_s( pwszType, cchType, L"VT_VOID", cchType ); break; case VT_SAFEARRAY: wcsncpy_s( pwszType, cchType, L"VT_SAFEARRAY", cchType ); break; case VT_USERDEFINED: wcsncpy_s( pwszType, cchType, L"VT_USERDEFINED", cchType ); break; case VT_LPSTR: wcsncpy_s( pwszType, cchType, L"VT_LPSTR", cchType ); break; case VT_LPWSTR: wcsncpy_s( pwszType, cchType, L"VT_LPWSTR", cchType ); break; case VT_RECORD: wcsncpy_s( pwszType, cchType, L"VT_RECORD", cchType ); break; case VT_FILETIME: wcsncpy_s( pwszType, cchType, L"VT_FILETIME", cchType ); break; case VT_BLOB: wcsncpy_s( pwszType, cchType, L"VT_BLOB", cchType ); break; case VT_STREAM: wcsncpy_s( pwszType, cchType, L"VT_STREAM", cchType ); break; case VT_STORAGE: wcsncpy_s( pwszType, cchType, L"VT_STORAGE", cchType ); break; case VT_STREAMED_OBJECT: wcsncpy_s( pwszType, cchType, L"VT_STREAMED_OBJECT", cchType ); break; case VT_STORED_OBJECT: wcsncpy_s( pwszType, cchType, L"VT_BLOB_OBJECT", cchType ); break; case VT_CF: wcsncpy_s( pwszType, cchType, L"VT_CF", cchType ); break; case VT_CLSID: wcsncpy_s( pwszType, cchType, L"VT_CLSID", cchType ); break; default: _snwprintf_s( pwszType, cchType, cchType, L"Unknown (%d)", vt & VT_TYPEMASK ); break; } // Adjust cchType for the added characters. cchType -= wcslen(pwszType); // Add the type modifiers, if present. if( vt & VT_VECTOR ) { pwszModifier = L" | VT_VECTOR"; wcsncat_s( pwszType, cchType, pwszModifier, cchType ); cchType -= wcslen( pwszModifier ); } if( vt & VT_ARRAY ) { pwszModifier = L" | VT_ARRAY"; wcsncat_s( pwszType, cchType, pwszModifier, cchType ); cchType -= wcslen( pwszModifier ); } if( vt & VT_RESERVED ) { pwszModifier = L" | VT_RESERVED"; wcsncat_s( pwszType, cchType, pwszModifier, cchType ); cchType -= wcslen( pwszModifier ); } } //+------------------------------------------------------------------- // // ConvertValueToString // // Generate a string for the value in a given PROPVARIANT structure. // The most common types are supported; that is, those that can be // displayed with printf. For other types, only an ellipses (...) // is displayed. // // The property to create a string from is in propvar, the resulting // string is placed into pwszValue, which is a buffer with space for // cchValue characters (including the string terminator). // //+------------------------------------------------------------------- void ConvertValueToString( const PROPVARIANT &propvar, WCHAR *pwszValue, ULONG cchValue ) { // Ensure that the output string is terminated pwszValue[ cchValue - 1 ] = L'\0'; --cchValue; // Based on the type, put the value into pwszValue as a string. switch( propvar.vt ) { case VT_EMPTY: wcsncpy_s( pwszValue, cchValue, L"", cchValue ); break; case VT_NULL: wcsncpy_s( pwszValue, cchValue, L"", cchValue ); break; case VT_I2: _snwprintf_s( pwszValue, cchValue, cchValue, L"%i", propvar.iVal ); break; case VT_I4: case VT_INT: _snwprintf_s( pwszValue, cchValue, cchValue, L"%li", propvar.lVal ); break; case VT_I8: _snwprintf_s( pwszValue, cchValue, cchValue, L"%I64i", propvar.hVal ); break; case VT_UI2: _snwprintf_s( pwszValue, cchValue, cchValue, L"%u", propvar.uiVal ); break; case VT_UI4: case VT_UINT: _snwprintf_s( pwszValue, cchValue, cchValue, L"%lu", propvar.ulVal ); break; case VT_UI8: _snwprintf_s( pwszValue, cchValue, cchValue, L"%I64u", propvar.uhVal ); break; case VT_R4: _snwprintf_s( pwszValue, cchValue, cchValue, L"%f", propvar.fltVal ); break; case VT_R8: _snwprintf_s( pwszValue, cchValue, cchValue, L"%lf", propvar.dblVal ); break; case VT_BSTR: _snwprintf_s( pwszValue, cchValue, cchValue, L"\"%s\"", propvar.bstrVal ); break; case VT_ERROR: _snwprintf_s( pwszValue, cchValue, cchValue, L"0x%08X", propvar.scode ); break; case VT_BOOL: _snwprintf_s( pwszValue, cchValue, cchValue, L"%s", VARIANT_TRUE == propvar.boolVal ? L"True" : L"False" ); break; case VT_I1: _snwprintf_s( pwszValue, cchValue, cchValue, L"%i", propvar.cVal ); break; case VT_UI1: _snwprintf_s( pwszValue, cchValue, cchValue, L"%u", propvar.bVal ); break; case VT_VOID: wcsncpy_s( pwszValue, cchValue, L"", cchValue ); break; case VT_LPSTR: if( 0 > _snwprintf_s( pwszValue, cchValue, cchValue, L"\"%hs\"", propvar.pszVal )) // String is too large for pwszValue wcsncpy_s( pwszValue, cchValue, L"...", cchValue ); break; case VT_LPWSTR: if( 0 > _snwprintf_s( pwszValue, cchValue, cchValue, L"\"%s\"", propvar.pwszVal )) // String is too large for pwszValue wcsncpy_s( pwszValue, cchValue, L"...", cchValue ); break; case VT_FILETIME: _snwprintf_s( pwszValue, cchValue, cchValue, L"%08x:%08x", propvar.filetime.dwHighDateTime, propvar.filetime.dwLowDateTime ); break; case VT_CLSID: pwszValue[0] = L'\0'; StringFromGUID2( *propvar.puuid, pwszValue, cchValue ); break; default: wcsncpy_s( pwszValue, cchValue, L"...", cchValue ); break; } } //+------------------------------------------------------------------- // // DisplayProperty // // Dump the ID, name, type, and value of a property. // //+------------------------------------------------------------------- void DisplayProperty( const PROPVARIANT &propvar, const STATPROPSTG &statpropstg ) { WCHAR wsz[ MAX_PATH + 1 ]; ConvertVarTypeToString( statpropstg.vt, wsz, sizeof(wsz)/sizeof(wsz[0]) ); wprintf( L" -------------------------------------------------\n" L" PropID = %-5d VarType = %-23s", statpropstg.propid, wsz ); if( NULL != statpropstg.lpwstrName ) wprintf( L" Name = %s", statpropstg.lpwstrName ); ConvertValueToString( propvar, wsz, sizeof(wsz)/sizeof(wsz[0]) ); wprintf( L"\n Value = %s\n", wsz ); } //+------------------------------------------------------------------- // // DisplayPropertySet // // Dump all the properties into a given property set. // //+------------------------------------------------------------------- void DisplayPropertySet( FMTID fmtid, const WCHAR *pwszStorageName, IPropertyStorage *pPropStg ) { IEnumSTATPROPSTG *penum = NULL; HRESULT hr = S_OK; STATPROPSTG statpropstg; PROPVARIANT propvar; PROPSPEC propspec; PROPID propid; WCHAR *pwszFriendlyName = NULL; // This string will hold a string-formatted FMTID. It must // be 38 characters, plus the terminator character. // For best practice, create a moderately longer string. WCHAR wszFMTID[ 64 ] = { L"" }; PropVariantInit( &propvar ); memset( &statpropstg, 0, sizeof(statpropstg) ); try { // Display the ID of the property set. StringFromGUID2( fmtid, wszFMTID, sizeof(wszFMTID)/sizeof(wszFMTID[0]) ); wprintf( L"\n Property Set %s\n", wszFMTID ); // If this is a common property set, display. if( FMTID_SummaryInformation == fmtid ) wprintf( L" (SummaryInformation property set)\n" ); else if( FMTID_DocSummaryInformation == fmtid ) wprintf( L" (DocumentSummaryInformation property set)\n" ); else if( FMTID_UserDefinedProperties == fmtid ) wprintf( L" (UserDefined property set)\n" ); // Also display the name of the storage that contains // this property set. wprintf( L" in \"%s\":\n", pwszStorageName ); // If this property set has a friendly name, display it now. // (Property names are stored in the special dictionary // property - the name of the property set is indicated by // naming the dictionary property itself.) propid = PID_DICTIONARY; pwszFriendlyName = NULL; hr = pPropStg->ReadPropertyNames( 1, &propid, &pwszFriendlyName ); if( S_OK == hr ) { wprintf( L" (Friendly name is \"%s\")\n\n", pwszFriendlyName ); CoTaskMemFree( pwszFriendlyName ); pwszFriendlyName = NULL; } else wprintf( L"\n" ); // Get a property enumerator. hr = pPropStg->Enum( &penum ); if( FAILED(hr) ) throw L"Failed IPropertyStorage::Enum"; // Get the first property in the enumeration. hr = penum->Next( 1, &statpropstg, NULL ); // Loop through and display each property. The 'Next' // call above, and at the bottom of the while loop, // will return S_OK if it returns another property, // S_FALSE if there are no more properties, // and anything else is an error. while( S_OK == hr ) { // Read the property out of the property set PropVariantInit( &propvar ); propspec.ulKind = PRSPEC_PROPID; propspec.propid = statpropstg.propid; hr = pPropStg->ReadMultiple( 1, &propspec, &propvar ); if( FAILED(hr) ) throw L"Failed IPropertyStorage::ReadMultiple"; // Display the property value, type, and so on. DisplayProperty( propvar, statpropstg ); // Free buffers allocated during the read, and // by the enumerator. PropVariantClear( &propvar ); CoTaskMemFree( statpropstg.lpwstrName ); statpropstg.lpwstrName = NULL; // Move to the next property in the enumeration hr = penum->Next( 1, &statpropstg, NULL ); } if( FAILED(hr) ) throw L"Failed IEnumSTATPROPSTG::Next"; } catch( LPCWSTR pwszErrorMessage ) { wprintf( L"Error in DumpPropertySet: %s (hr = %08x)\n", pwszErrorMessage, hr ); } if( NULL != penum ) penum->Release(); if( NULL != statpropstg.lpwstrName ) CoTaskMemFree( statpropstg.lpwstrName ); PropVariantClear( &propvar ); } //+------------------------------------------------------------------- // // DisplayPropertySetsInStorage // // Dump the property sets in the top level of a given storage. // //+------------------------------------------------------------------- void DisplayPropertySetsInStorage( const WCHAR *pwszStorageName, IPropertySetStorage *pPropSetStg ) { IEnumSTATPROPSETSTG *penum = NULL; HRESULT hr = S_OK; IPropertyStorage *pPropStg = NULL; STATPROPSETSTG statpropsetstg; try { // Get a property-set enumerator, which only enumerates // the property sets at this level of the storage, not // its child objects. hr = pPropSetStg->Enum( &penum ); if( FAILED(hr) ) throw L"failed IPropertySetStorage::Enum"; // Get the first property set in the enumeration. // (The field used to open the property set is // statpropsetstg.fmtid. memset( &statpropsetstg, 0, sizeof(statpropsetstg) ); hr = penum->Next( 1, &statpropsetstg, NULL ); // Loop through all the property sets. while( S_OK == hr ) { // Open the property set. hr = pPropSetStg->Open( statpropsetstg.fmtid, STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg ); if( FAILED(hr) ) throw L"failed IPropertySetStorage::Open"; // Display the properties in the property set. DisplayPropertySet( statpropsetstg.fmtid, pwszStorageName, pPropStg ); pPropStg->Release(); pPropStg = NULL; // Get the FMTID of the next property set in the // enumeration. hr = penum->Next( 1, &statpropsetstg, NULL ); } if( FAILED(hr) ) throw L"Failed IEnumSTATPROPSETSTG::Next"; // Special-case handling for the UserDefined property set: // This property set actually lives inside the well-known // DocumentSummaryInformation property set. It is the only // property set which is allowed to live inside another // (and exists for legacy compatibility). It does not get // included in a normal enumeration, so verify that it is // done explicitly. Look for it when the end of the // enumerator is reached. hr = pPropSetStg->Open( FMTID_UserDefinedProperties, STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg ); if( SUCCEEDED(hr) ) { DisplayPropertySet( FMTID_UserDefinedProperties, pwszStorageName, pPropStg ); pPropStg->Release(); pPropStg = NULL; } } catch( LPCWSTR pwszErrorMessage ) { wprintf( L"Error in DumpPropertySetsInStorage: %s (hr = %08x)\n", pwszErrorMessage, hr ); } if( NULL != pPropStg ) pPropStg->Release(); if( NULL != penum ) penum->Release(); } //+------------------------------------------------------------------- // // DisplayStorageTree // // Dump all the property sets in the given storage and recursively in // all its child objects. // //+------------------------------------------------------------------- void DisplayStorageTree( const WCHAR *pwszStorageName, IStorage *pStg ) { IPropertySetStorage *pPropSetStg = NULL; IStorage *pStgChild = NULL; WCHAR *pwszChildStorageName = NULL; IEnumSTATSTG *penum = NULL; HRESULT hr = S_OK; STATSTG statstg; memset( &statstg, 0, sizeof(statstg) ); try { // Dump the property sets at this storage level hr = pStg->QueryInterface( IID_IPropertySetStorage, reinterpret_cast<void**>(&pPropSetStg) ); if( FAILED(hr) ) throw L"Failed IStorage::QueryInterface(IID_IPropertySetStorage)"; DisplayPropertySetsInStorage( pwszStorageName, pPropSetStg ); // Get an enumerator for this storage. hr = pStg->EnumElements( NULL, NULL, NULL, &penum ); if( FAILED(hr) ) throw L"failed IStorage::Enum"; // Get the name of the first element (stream/storage) // in the enumeration. As usual, 'Next' will return // S_OK if it returns an element of the enumerator, // S_FALSE if there are no more elements, and an // error otherwise. hr = penum->Next( 1, &statstg, 0 ); // Loop through all the child objects of this storage. while( S_OK == hr ) { // Verify that this is a storage that is not a property // set, because the property sets are displayed above). // If the first character of its name is the '\005' // reserved character, it is a stream /storage property // set. if( STGTY_STORAGE == statstg.type && L'\005' != statstg.pwcsName[0] ) { // Indicates normal storage, not a propset. // Open the storage. ULONG cchChildStorageName; hr = pStg->OpenStorage( statstg.pwcsName, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStgChild ); if( FAILED(hr) ) throw L"failed IStorage::OpenStorage"; // Compose a name of the form // "Storage\ChildStorage\..." for display purposes. // First, allocate it. cchChildStorageName = wcslen(pwszStorageName) + wcslen(statstg.pwcsName) + 2 // For two "\" chars + 1; // For string terminator pwszChildStorageName = new WCHAR[ cchChildStorageName ]; if( NULL == pwszChildStorageName ) { hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY); throw L"couldn't allocate memory"; } // Terminate the name. pwszChildStorageName[ cchChildStorageName-1 ] = L'\0'; --cchChildStorageName; // Build the name. wcsncpy_s( pwszChildStorageName, cchChildStorageName, pwszStorageName, cchChildStorageName ); cchChildStorageName -= wcslen(pwszStorageName); wcsncat_s( pwszChildStorageName, cchChildStorageName, L"\\", cchChildStorageName ); cchChildStorageName -= 2; wcsncat_s( pwszChildStorageName, cchChildStorageName, statstg.pwcsName, cchChildStorageName ); // Dump all property sets under this child storage. DisplayStorageTree( pwszChildStorageName, pStgChild ); pStgChild->Release(); pStgChild = NULL; delete[] pwszChildStorageName; pwszChildStorageName = NULL; } // Move to the next element in the enumeration of // this storage. CoTaskMemFree( statstg.pwcsName ); statstg.pwcsName = NULL; hr = penum->Next( 1, &statstg, 0 ); } if( FAILED(hr) ) throw L"failed IEnumSTATSTG::Next"; } catch( LPCWSTR pwszErrorMessage ) { wprintf( L"Error in DumpStorageTree: %s (hr = %08x)\n", pwszErrorMessage, hr ); } // Cleanup before returning. if( NULL != statstg.pwcsName ) CoTaskMemFree( statstg.pwcsName ); if( NULL != pStgChild ) pStgChild->Release(); if( NULL != pStg ) pStg->Release(); if( NULL != penum ) penum->Release(); if( NULL != pwszChildStorageName ) delete[] pwszChildStorageName; } //+------------------------------------------------------------------- // // wmain // // Dump all the property sets in a file which is a storage. // //+------------------------------------------------------------------- extern "C" void wmain( int cArgs, WCHAR *rgwszArgs[] ) { HRESULT hr = S_OK; IStorage *pStg = NULL; // Display usage information if necessary. if( 1 == cArgs || 0 == wcscmp( L"-?", rgwszArgs[1] ) || 0 == wcscmp( L"/?", rgwszArgs[1] )) { printf( "\n" "Purpose: Enumerate all properties in all\n" " property sets for a storage file\n" "Usage: PropDump <filename>\n" "E.g.: PropDump word.doc\n" "\n" ); exit(0); } // Open the root storage. hr = StgOpenStorageEx( rgwszArgs[1], STGM_READ | STGM_SHARE_DENY_WRITE, STGFMT_ANY, 0, NULL, NULL, IID_IStorage, reinterpret_cast<void**>(&pStg) ); // Dump all the properties in all the property sets within this // storage. if( FAILED(hr) ) { wprintf( L"Error: couldn't open storage \"%s\" (hr = %08x)\n", rgwszArgs[1], hr ); } else { printf( "\nDisplaying all property sets ...\n" ); DisplayStorageTree( rgwszArgs[1], pStg ); pStg->Release(); } }
相关文章推荐
- VARIANT类型的两个转换函数
- [CLR via C#]5.2 引用类型和值类型
- 哈希表集合类型[MSDN]
- sql server中的数据类型转换函数
- Java语言中try-catch-finally中return解析以及引用类型和值类型区分
- 变体类型转换成字符串(优先使用 _variant_t,尽量不用 VARIANT )
- C#中引用类型和值类型分别有哪些
- 引用类型和值类型
- 常用python数据类型转换函数总结
- _variant_t 数据类型
- delphi 流Stream 和 Variant 的转换函数
- 【Java Script 入门之路之数据类型和值】
- (LUA教程)第2章 类型和值
- _variant_t与其他数据类型的转换
- C#的类型、变量和值
- 引用类型和值类型,以及引用传递和值传递
- C#命名空间的使用、添加命名空间、引用类型和值类型、字符串与char数组转换
- MFC ADO数据库编程中的_variant_t和_bstr_t类型
- C#引用类型和值类型的区别——值类型和引用类型在内存中的部署
- Variant类型在各语言中的参数传递