I am using StgOpenStorageEx() to get document properties like Title,Subject,Tag,Authors,etc..
I am successfully getting all these properties of .doc,.xls,.ppt files. But Not getting anything for .docx,.xlsx,.pptx
StgOpenStorageEx() is successfully opened for .docx file but not getting any properties.Why?
Anything am I missing?
Code:
#include <stdio.h>
#include <windows.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)\n");
return;
}
// Don't handle byref for simplicity, just inform byref.
if (pPropVar->vt & VT_BYREF) {
printf("(ByRef)\n");
return;
}
// Switch types.
switch (pPropVar->vt) {
case VT_EMPTY:
printf("(VT_EMPTY)\n");
break;
case VT_NULL:
printf("(VT_NULL)\n");
break;
case VT_BLOB:
printf("(VT_BLOB)\n");
break;
case VT_BOOL:
printf("%s (VT_BOOL)\n",
pPropVar->boolVal ? "TRUE/YES" : "FALSE/NO");
break;
case VT_I2: // 2-byte signed int.
printf("%d (VT_I2)\n", (int)pPropVar->iVal);
break;
case VT_I4: // 4-byte signed int.
printf("%d (VT_I4)\n", (int)pPropVar->lVal);
break;
case VT_R4: // 4-byte real.
printf("%.2lf (VT_R4)\n", (double)pPropVar->fltVal);
break;
case VT_R8: // 8-byte real.
printf("%.2lf (VT_R8)\n", (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)\n", dbcs);
}
break;
case VT_LPSTR: // Null-terminated string.
{
printf("%s (VT_LPSTR)\n", pPropVar->pszVal);
}
break;
case VT_FILETIME:
{
const 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)\n",
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)\n");
break;
default: // Unhandled type, consult wtypes.h's VARENUM structure.
printf("(Unhandled type: 0x%08lx)\n", pPropVar->vt);
break;
}
}
// Dump's built-in properties of a property storage.
void DumpBuiltInProps(IPropertySetStorage* pPropSetStg) {
printf("\n==================================================\n");
printf("BuiltInProperties Properties...\n");
printf("==================================================\n");
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.\n");
return;
}
// Array of PIDSI's you are interested in.
struct pidsiStruct {
const 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\n",
hr);
}
else {
// Dump properties.
for (int 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 and built-in properties of a compound document.
void DumpProps(char* filename) {
// Translate filename to Unicode.
WCHAR wcFilename[1024];
int i = mbstowcs(wcFilename, filename, strlen(filename));
wcFilename[i] = 0;
IStorage* pStorage = NULL;
IPropertySetStorage* pPropSetStg = NULL;
HRESULT hr;
hr = StgOpenStorageEx(wcFilename,
0x00400000L | STGM_READ | STGM_SHARE_DENY_NONE, // Here: 0x00400000L = STGM_DIRECT_SWMR (Direct Single Writer Multiple Reader)
STGFMT_ANY,
// STGFMT_STORAGE //Structured Storage property sets
// STGFMT_FILE //NTFS file system property sets
NULL,
NULL,
NULL,
IID_IPropertySetStorage,//IID_IPropertySetStorage,IID_IStorage
reinterpret_cast<void**>(&pPropSetStg));
if (FAILED(hr)) {
if (hr == STG_E_FILENOTFOUND)
printf("File not found.");
else if (hr == STG_E_FILEALREADYEXISTS)
printf("Not a compound file. ERROR: %08lx", hr);
else
printf("StgOpenStorage() failed w/error %08lx", hr);
return;
}
// Dump properties.
DumpBuiltInProps(pPropSetStg);
// Release obtained interfaces.
if(pPropSetStg)
pPropSetStg->Release();
}
// Program entry-point.
void main(int argc, char** argv) {
char filePath[] = "C://word1.docx"; // file
// Pass filename to the subroutine.
DumpProps(filePath);
}