您的位置:首页 > 其它

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();
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: