3. |
将以下代码复制到 main.cpp:
#include
<
stdio.h
>
#include
<
windows.h
>
#include
<
ole2.h
>
#include
<
locale.h
>
//
Dumps simple PROPVARIANT values.
void
DumpPropVariant(PROPVARIANT
*
pPropVar)
...
{ // Don't iterate arrays, just inform as an array. if(pPropVar->vt & VT_ARRAY) ...{ printf("(Array) "); return; }
// Don't handle byref for simplicity, just inform byref. if(pPropVar->vt & VT_BYREF) ...{ printf("(ByRef) "); return; }
// Switch types. switch(pPropVar->vt) ...{ case VT_EMPTY: printf("(VT_EMPTY) "); break; case VT_NULL: printf("(VT_NULL) "); break; case VT_BLOB: printf("(VT_BLOB) "); break; case VT_BOOL: printf("%s (VT_BOOL) ", pPropVar->boolVal ? "TRUE/YES" : "FALSE/NO"); break; case VT_I2: // 2-byte signed int. printf("%d (VT_I2) ", (int)pPropVar->iVal); break; case VT_I4: // 4-byte signed int. printf("%d (VT_I4) ", (int)pPropVar->lVal); break; case VT_R4: // 4-byte real. printf("%.2lf (VT_R4) ", (double)pPropVar->fltVal); break; case VT_R8: // 8-byte real. printf("%.2lf (VT_R8) ", (double)pPropVar->dblVal); break; case VT_BSTR: // OLE Automation string. ...{ // Translate into ASCII. char dbcs[1024]; char *pbstr = (char *)pPropVar->bstrVal; int i = wcstombs( dbcs, pPropVar->bstrVal, *((DWORD *)(pbstr-4))); dbcs[i] = 0; printf("%s (VT_BSTR) ", dbcs); } break; case VT_LPSTR: // Null-terminated string. ...{ printf("%s (VT_LPSTR) ", pPropVar->pszVal); } break; case VT_FILETIME: ...{ char *dayPre[] = ...{"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
FILETIME lft; FileTimeToLocalFileTime(&pPropVar->filetime, &lft); SYSTEMTIME lst; FileTimeToSystemTime(&lft, &lst);
printf("%02d:%02d.%02d %s, %s %02d/%02d/%d (VT_FILETIME) ", 1+(lst.wHour-1)%12, lst.wMinute, lst.wSecond, (lst.wHour>=12) ? "pm" : "am", dayPre[lst.wDayOfWeek%7], lst.wMonth, lst.wDay, lst.wYear); } break; case VT_CF: // Clipboard format. printf("(Clipboard format) ");
break; default: // Unhandled type, consult wtypes.h's VARENUM structure. printf("(Unhandled type: 0x%08lx) ", pPropVar->vt); break; } }
//
Dump's built-in properties of a property storage.
void
DumpBuiltInProps(IPropertySetStorage
*
pPropSetStg)
...
{ printf(" ================================================== "); printf("BuiltInProperties Properties... "); printf("================================================== ");
IPropertyStorage *pPropStg = NULL; HRESULT hr;
// Open summary information, getting an IpropertyStorage. hr = pPropSetStg->Open(FMTID_SummaryInformation, STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg); //hr = pPropSetStg->Open(FMTID_UserDefinedProperties, //STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg); if(FAILED(hr)) ...{ printf("No Summary-Information. "); return; } // Array of PIDSI's you are interested in. struct pidsiStruct ...{ char *name; long pidsi; } pidsiArr[] = ...{ ...{"Title", PIDSI_TITLE}, // VT_LPSTR ...{"Subject", PIDSI_SUBJECT}, // ... ...{"Author", PIDSI_AUTHOR}, ...{"Keywords", PIDSI_KEYWORDS}, ...{"Comments", PIDSI_COMMENTS}, ...{"Template", PIDSI_TEMPLATE}, ...{"LastAuthor", PIDSI_LASTAUTHOR}, ...{"Revision Number", PIDSI_REVNUMBER}, ...{"Edit Time", PIDSI_EDITTIME}, // VT_FILENAME (UTC) ...{"Last printed", PIDSI_LASTPRINTED}, // ... ...{"Created", PIDSI_CREATE_DTM}, ...{"Last Saved", PIDSI_LASTSAVE_DTM}, ...{"Page Count", PIDSI_PAGECOUNT}, // VT_I4 ...{"Word Count", PIDSI_WORDCOUNT}, // ... ...{"Char Count", PIDSI_CHARCOUNT},
...{"Thumpnail", PIDSI_THUMBNAIL}, // VT_CF ...{"AppName", PIDSI_APPNAME}, // VT_LPSTR ...{"Doc Security", PIDSI_DOC_SECURITY}, // VT_I4 ...{0, 0} }; // Count elements in pidsiArr. int nPidsi = 0; for(nPidsi=0; pidsiArr[nPidsi].name; nPidsi++);
// Initialize PROPSPEC for the properties you want. PROPSPEC *pPropSpec = new PROPSPEC [nPidsi]; PROPVARIANT *pPropVar = new PROPVARIANT [nPidsi];
for(int i=0; i<nPidsi; i++) ...{ ZeroMemory(&pPropSpec[i], sizeof(PROPSPEC)); pPropSpec[i].ulKind = PRSPEC_PROPID; pPropSpec[i].propid = pidsiArr[i].pidsi; }
// Read properties. hr = pPropStg->ReadMultiple(nPidsi, pPropSpec, pPropVar);
if(FAILED(hr)) ...{ printf("IPropertyStg::ReadMultiple() failed w/error %08lx ", hr); } else ...{ // Dump properties. for(i=0; i<nPidsi; i++) ...{ printf("%16s: ", pidsiArr[i].name); DumpPropVariant(pPropVar + i); } }
// De-allocate memory. delete [] pPropVar; delete [] pPropSpec;
// Release obtained interface. pPropStg->Release();
}
//
Dump's custom properties of a property storage.
void
DumpCustomProps(IPropertySetStorage
*
pPropSetStg)
...
{ printf(" ================================================== "); printf("Custom Properties... "); printf("================================================== ");
IPropertyStorage *pPropStg = NULL; HRESULT hr; IEnumSTATPROPSTG *pEnumProp;
// Open User-Defined-Properties, getting an IpropertyStorage. hr = pPropSetStg->Open(FMTID_UserDefinedProperties, STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg); if(FAILED(hr)) ...{ printf("No User Defined Properties. "); return; }
// Get property enumerator. hr = pPropStg->Enum(&pEnumProp); if(FAILED(hr)) ...{ pPropStg->Release(); printf("Couldn't enumerate custom properties. "); return; }
// Enumerate properties. STATPROPSTG sps; ULONG fetched; PROPSPEC propSpec[1]; PROPVARIANT propVar[1]; while(pEnumProp->Next(1, &sps, &fetched) == S_OK) ...{ // Build a PROPSPEC for this property. ZeroMemory(&propSpec[0], sizeof(PROPSPEC)); propSpec[0].ulKind = PRSPEC_PROPID; propSpec[0].propid = sps.propid;
// Read this property.
hr = pPropStg->ReadMultiple(1, &propSpec[0], &propVar[0]); if(!FAILED(hr)) ...{ // Translate Prop name into ASCII. char dbcs[1024]; char *pbstr = (char *)sps.lpwstrName; int i = wcstombs(dbcs, sps.lpwstrName, *((DWORD *)(pbstr-4))); dbcs[i] = 0;
// Dump this property. printf("%16s: ", dbcs); DumpPropVariant(&propVar[0]); } }
// Release obtained interface. pEnumProp->Release(); pPropStg->Release();
}
//
Dump's custom and built-in properties of a compound document.
void
DumpProps(
char
*
filename)
...
{ // Translate filename to Unicode. WCHAR wcFilename[1024]; setlocale( LC_ALL, "" ); int i = mbstowcs(wcFilename, filename, strlen(filename)); setlocale( LC_ALL, "C" ); wcFilename[i] = 0;
IStorage *pStorage = NULL; IPropertySetStorage *pPropSetStg = NULL; HRESULT hr;
// Open the document as an OLE compound document. hr = ::StgOpenStorage(wcFilename, NULL, STGM_READ | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStorage);
if(FAILED(hr)) ...{ if(hr == STG_E_FILENOTFOUND) printf("File not found."); else if(hr == STG_E_FILEALREADYEXISTS) printf("Not a compound file."); else printf("StgOpenStorage() failed w/error %08lx", hr); return; }
// Obtain the IPropertySetStorage interface. hr = pStorage->QueryInterface( IID_IPropertySetStorage, (void **)&pPropSetStg); if(FAILED(hr)) ...{ printf("QI for IPropertySetStorage failed w/error %08lx", hr); pStorage->Release(); return; }
// Dump properties. DumpBuiltInProps(pPropSetStg); DumpCustomProps(pPropSetStg);
// Release obtained interfaces. pPropSetStg->Release(); pStorage->Release(); }
//
Program entry-point.
void
main(
int
argc,
char
**
argv)
...
{ // Validate arguments. if(argc != 2) ...{ printf("- OLE Document Property Viewer "); printf("- Usage: %s filename", argv[0]); return; }
// Pass filename to the subroutine. DumpProps(argv[1]); }
|