// @pymethod <o PyIPropertyStore>|propsys|PSCreatePropertyStoreFromPropertySetStorage|Wraps a <o PyIPropertySetStorage> interface in a <o PyIPropertyStore> object // @comm This function does not work for the NTFS property storage implementation based on // alternate data streams. static PyObject *PyPSCreatePropertyStoreFromPropertySetStorage(PyObject *self, PyObject *args) { PyObject *obpss; IPropertySetStorage *pipss; DWORD mode; IID riid = IID_IPropertyStore; void *ret; // @pyparm <o PyIPropertySetStorage>|pss||Property container to be adapted // @pyparm int|Mode||Read or write mode, shellcon.STGM_*. Must match mode used to open input interface. // @pyparm <o PyIID>|riid|IID_IPropertyStore|The interface to create if (!PyArg_ParseTuple(args, "Ok|O&:PSCreatePropertyStoreFromPropertySetStorage", &obpss, &mode, PyWinObject_AsIID, &riid)) return NULL; if (!PyCom_InterfaceFromPyInstanceOrObject(obpss, IID_IPropertySetStorage, (void **)&pipss, FALSE)) return NULL; HRESULT hr; PY_INTERFACE_PRECALL; hr = PSCreateMemoryPropertyStore(riid, &ret); pipss->Release(); PY_INTERFACE_POSTCALL; if (FAILED(hr)) return PyCom_BuildPyException(hr); return PyCom_PyObjectFromIUnknown((IUnknown *) ret, riid); };
void App::GetProperties() { LPSTORAGE pStorage = NULL; IPropertySetStorage* pPropertySetStorage = NULL; IPropertyStorage* pSummaryInfoStorage = NULL; IPropertyStorage* pDocumentSummaryInfoStorage = NULL; IPropertyStorage* pUserDefinedPropertyStorage = NULL; wchar_t wfilename[_MAX_PATH]; char szBuf[256]; char filename[MAX_PATH]; SendMessage(GetDlgItem(hPropDialog, IDC_TITLE), WM_SETTEXT, 0, (LPARAM)""); SendMessage(GetDlgItem(hPropDialog, IDC_SUBJECT), WM_SETTEXT, 0, (LPARAM)""); SendMessage(GetDlgItem(hPropDialog, IDC_AUTHOR), WM_SETTEXT, 0, (LPARAM)""); SendMessage(GetDlgItem(hPropDialog, IDC_MANAGER), WM_SETTEXT, 0, (LPARAM)""); SendMessage(GetDlgItem(hPropDialog, IDC_COMPANY), WM_SETTEXT, 0, (LPARAM)""); SendMessage(GetDlgItem(hPropDialog, IDC_CATEGORY), WM_SETTEXT, 0, (LPARAM)""); SendMessage(GetDlgItem(hPropDialog, IDC_KEYWORDS), WM_SETTEXT, 0, (LPARAM)""); SendMessage(GetDlgItem(hPropDialog, IDC_COMMENTS), WM_SETTEXT, 0, (LPARAM)""); SendMessage(GetDlgItem(hPropDialog, IDC_CONTENTS), LB_RESETCONTENT, 0, 0); ListView_DeleteAllItems(GetDlgItem(hPropDialog, IDC_CUSTOM)); int idx = SendMessage(hListBox, LB_GETCURSEL, 0, 0); SendMessage(hListBox, LB_GETTEXT, idx, (LPARAM)filename); SetWindowText(hPropDialog, filename); MultiByteToWideChar(CP_ACP, 0, filename, -1, wfilename, _MAX_PATH); HRESULT res = StgOpenStorage(wfilename, (LPSTORAGE)0, STGM_DIRECT|STGM_READ|STGM_SHARE_EXCLUSIVE, NULL,0,&pStorage); if (res!=S_OK) { return; } // Get the Storage interface if (S_OK != pStorage->QueryInterface(IID_IPropertySetStorage, (void**)&pPropertySetStorage)) { pStorage->Release(); return; } // Get the SummaryInfo property set interface if (S_OK == pPropertySetStorage->Open(FMTID_SummaryInformation, STGM_READ|STGM_SHARE_EXCLUSIVE, &pSummaryInfoStorage)) { BOOL bFound = FALSE; PROPSPEC PropSpec[5]; PROPVARIANT PropVar[5]; PropSpec[0].ulKind = PRSPEC_PROPID; PropSpec[0].propid = PID_TITLE; PropSpec[1].ulKind = PRSPEC_PROPID; PropSpec[1].propid = PID_SUBJECT; PropSpec[2].ulKind = PRSPEC_PROPID; PropSpec[2].propid = PID_AUTHOR; PropSpec[3].ulKind = PRSPEC_PROPID; PropSpec[3].propid = PID_KEYWORDS; PropSpec[4].ulKind = PRSPEC_PROPID; PropSpec[4].propid = PID_COMMENTS; HRESULT hr = pSummaryInfoStorage->ReadMultiple(5, PropSpec, PropVar); if (S_OK == hr) { if (PropVar[0].vt == VT_LPSTR) { SendMessage(GetDlgItem(hPropDialog, IDC_TITLE), WM_SETTEXT, 0, (LPARAM)PropVar[0].pszVal); } if (PropVar[1].vt == VT_LPSTR) { SendMessage(GetDlgItem(hPropDialog, IDC_SUBJECT), WM_SETTEXT, 0, (LPARAM)PropVar[1].pszVal); } if (PropVar[2].vt == VT_LPSTR) { SendMessage(GetDlgItem(hPropDialog, IDC_AUTHOR), WM_SETTEXT, 0, (LPARAM)PropVar[2].pszVal); } if (PropVar[3].vt == VT_LPSTR) { SendMessage(GetDlgItem(hPropDialog, IDC_KEYWORDS), WM_SETTEXT, 0, (LPARAM)PropVar[3].pszVal); } if (PropVar[4].vt == VT_LPSTR) { SendMessage(GetDlgItem(hPropDialog, IDC_COMMENTS), WM_SETTEXT, 0, (LPARAM)PropVar[4].pszVal); } } FreePropVariantArray(5, PropVar); pSummaryInfoStorage->Release(); } // Get the DocumentSummaryInfo property set interface if (S_OK == pPropertySetStorage->Open(FMTID_DocSummaryInformation, STGM_READ|STGM_SHARE_EXCLUSIVE, &pDocumentSummaryInfoStorage)) { BOOL bFound = FALSE; PROPSPEC PropSpec[5]; PROPVARIANT PropVar[5]; PropSpec[0].ulKind = PRSPEC_PROPID; PropSpec[0].propid = PID_MANAGER; PropSpec[1].ulKind = PRSPEC_PROPID; PropSpec[1].propid = PID_COMPANY; PropSpec[2].ulKind = PRSPEC_PROPID; PropSpec[2].propid = PID_CATEGORY; PropSpec[3].ulKind = PRSPEC_PROPID; PropSpec[3].propid = PID_HEADINGPAIR; PropSpec[4].ulKind = PRSPEC_PROPID; PropSpec[4].propid = PID_DOCPARTS; HRESULT hr = pDocumentSummaryInfoStorage->ReadMultiple(5, PropSpec, PropVar); if (S_OK == hr) { if (PropVar[0].vt == VT_LPSTR) { SendMessage(GetDlgItem(hPropDialog, IDC_MANAGER), WM_SETTEXT, 0, (LPARAM)PropVar[0].pszVal); } if (PropVar[1].vt == VT_LPSTR) { SendMessage(GetDlgItem(hPropDialog, IDC_COMPANY), WM_SETTEXT, 0, (LPARAM)PropVar[1].pszVal); } if (PropVar[2].vt == VT_LPSTR) { SendMessage(GetDlgItem(hPropDialog, IDC_CATEGORY), WM_SETTEXT, 0, (LPARAM)PropVar[2].pszVal); } if ((PropVar[3].vt == (VT_VARIANT | VT_VECTOR)) && (PropVar[4].vt == (VT_LPSTR | VT_VECTOR))) { CAPROPVARIANT* pHeading = &PropVar[3].capropvar; CALPSTR* pDocPart = &PropVar[4].calpstr; // Headings: // ========= // 0 - General // 2 - Mesh Totals // 4 - Scene Totals // 6 - External Dependencies // 8 - Objects // 10 - Materials // 12 - Plug-Ins int nDocPart = 0; for (UINT i=0; i<pHeading->cElems; i+=2) { SendMessage(GetDlgItem(hPropDialog, IDC_CONTENTS), LB_ADDSTRING, 0, (LPARAM)pHeading->pElems[i].pszVal); for (int j=0; j<pHeading->pElems[i+1].lVal; j++) { sprintf(szBuf, "\t%s", pDocPart->pElems[nDocPart]); SendMessage(GetDlgItem(hPropDialog, IDC_CONTENTS), LB_ADDSTRING, 0, (LPARAM)szBuf); nDocPart++; } } } } FreePropVariantArray(5, PropVar); pDocumentSummaryInfoStorage->Release(); } if (S_OK == pPropertySetStorage->Open(FMTID_UserDefinedProperties, STGM_READ|STGM_SHARE_EXCLUSIVE, &pUserDefinedPropertyStorage)) { int numUserProps = 0; // First we need to count the properties IEnumSTATPROPSTG* pIPropertyEnum; if (S_OK == pUserDefinedPropertyStorage->Enum(&pIPropertyEnum)) { STATPROPSTG property; while (pIPropertyEnum->Next(1, &property, NULL) == S_OK) { if (property.lpwstrName) { CoTaskMemFree(property.lpwstrName); property.lpwstrName = NULL; numUserProps++; } } PROPSPEC* pPropSpec = new PROPSPEC[numUserProps]; PROPVARIANT* pPropVar = new PROPVARIANT[numUserProps]; ZeroMemory(pPropVar, numUserProps*sizeof(PROPVARIANT)); ZeroMemory(pPropSpec, numUserProps*sizeof(PROPSPEC)); pIPropertyEnum->Reset(); int idx = 0; while (pIPropertyEnum->Next(1, &property, NULL) == S_OK) { if (property.lpwstrName) { pPropSpec[idx].ulKind = PRSPEC_LPWSTR; pPropSpec[idx].lpwstr = (LPWSTR)CoTaskMemAlloc(sizeof(wchar_t)*(wcslen(property.lpwstrName)+1)); wcscpy(pPropSpec[idx].lpwstr, property.lpwstrName); idx++; CoTaskMemFree(property.lpwstrName); property.lpwstrName = NULL; } } pIPropertyEnum->Release(); ListView_DeleteAllItems(GetDlgItem(hPropDialog, IDC_CUSTOM)); HRESULT hr = pUserDefinedPropertyStorage->ReadMultiple(idx, pPropSpec, pPropVar); if (S_OK == hr) { for (int i=0; i<idx; i++) { wcstombs(szBuf, pPropSpec[i].lpwstr, 255); LV_ITEM item; item.mask = LVIF_TEXT; item.iItem = i; item.iSubItem = 0; item.pszText = szBuf; item.cchTextMax = strlen(szBuf); ListView_InsertItem(GetDlgItem(hPropDialog, IDC_CUSTOM), &item); VariantToString(this, &pPropVar[i], szBuf, 255); item.iSubItem = 1; item.pszText = szBuf; item.cchTextMax = strlen(szBuf); ListView_SetItem(GetDlgItem(hPropDialog, IDC_CUSTOM), &item); TypeNameFromVariant(this, &pPropVar[i], szBuf, 255); item.iSubItem = 2; item.pszText = szBuf; item.cchTextMax = strlen(szBuf); ListView_SetItem(GetDlgItem(hPropDialog, IDC_CUSTOM), &item); } } for (int i=0; i<idx; i++) { CoTaskMemFree(pPropSpec[i].lpwstr); } FreePropVariantArray(numUserProps, pPropVar); delete [] pPropSpec; delete [] pPropVar; } pUserDefinedPropertyStorage->Release(); } pPropertySetStorage->Release(); pStorage->Release(); }
BOOL CDocFile::Load(TCHAR* wszFilePath) { IStorage *pStorage = NULL; IPropertySetStorage *pPropSetStg = NULL; IStream *pStream = NULL, *pTableStream = NULL; HRESULT hr; // Open the document as an OLE compound document. hr = ::StgOpenStorage(wszFilePath, NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, NULL, 0, &pStorage); if(FAILED(hr)) { _tprintf( L"A file is locked by another program: [%s]\n", wszFilePath); return FALSE; } #ifdef CONTENT_EXTRACTION hr = pStorage->OpenStream(L"WordDocument", NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pStream); if(FAILED(hr)) { _tprintf( L"A file is invalid or damaged: [%s]\n", wszFilePath); pStorage->Release(); return FALSE; } STATSTG stat; pStream->Stat(&stat, 0); UINT size = (UINT) stat.cbSize.QuadPart; BYTE *buffer = new BYTE[size]; USHORT usFlag; INT pdcOffset; UINT pdcLength; LARGE_INTEGER liTmpSeek; ULONG cbRead; liTmpSeek.QuadPart = 10; pStream->Seek(liTmpSeek, 0, NULL); pStream->Read(&usFlag, 2, &cbRead); liTmpSeek.QuadPart = 418; pStream->Seek(liTmpSeek, 0, NULL); pStream->Read(&pdcOffset, 4, &cbRead); pStream->Read(&pdcLength, 4, &cbRead); hr = pStorage->OpenStream((usFlag & (0x1 << 9)) ? L"1Table" : L"0Table", NULL, STGM_READWRITE | STGM_SHARE_EXCLUSIVE, 0, &pTableStream); liTmpSeek.QuadPart = pdcOffset; pTableStream->Seek(liTmpSeek, 0, NULL); INT nCount = 0; INT *aOffsets = NULL; struct Desc { BYTE Flags; BYTE Fn; UINT32 Fc; SHORT Prm; } *aDescs = NULL; UINT nPointer = 0; while (nPointer < pdcLength) { BYTE nType = 0; pTableStream->Read(&nType, 1, &cbRead); switch(nType) { case 0: BYTE nTmp; pTableStream->Read(&nTmp, 1, &cbRead); nPointer++; break; case 1: { SHORT cbGrpprl; BYTE *grpprlData = NULL; pTableStream->Read(&cbGrpprl, 2, &cbRead); nPointer+=2; grpprlData = new BYTE[cbGrpprl]; pTableStream->Read(grpprlData, cbGrpprl, &cbRead); nPointer+=cbGrpprl; delete grpprlData; break; } case 2: INT nTableLen = 0; pTableStream->Read(&nTableLen, 4, &cbRead); nPointer+=4; nCount = (nTableLen - 4) / (8 + 4) + 1; aOffsets = new INT[nCount]; for(int i = 0; i < nCount; i++) { pTableStream->Read(&aOffsets[i], 4, &cbRead); nPointer +=4; } aDescs = new Desc[nCount-1]; for(int i = 0; i < nCount-1; i++) { pTableStream->Read(&aDescs[i].Flags, 1, &cbRead); pTableStream->Read(&aDescs[i].Fn, 1, &cbRead); pTableStream->Read(&aDescs[i].Fc, 4, &cbRead); pTableStream->Read(&aDescs[i].Prm, 2, &cbRead); nPointer+=sizeof(struct Desc); } break; } } for (int i = 0; i < nCount - 1; i++) { UINT pieceStart = 0xffffffff; UINT pieceEnd = 0xffffffff; BOOL bUnicode = FALSE; bUnicode = (aDescs[i].Fc & (1 << 30)) == 0 ? 1 : 0; if (!bUnicode) pieceStart = (aDescs[i].Fc & ~(1 << 30)) / 2; else pieceStart = aDescs[i].Fc; UINT nLength = aOffsets[i + 1] - aOffsets[i]; pieceEnd = pieceStart + nLength * (bUnicode ? 2 : 1); liTmpSeek.QuadPart = pieceStart; hr = pStream->Seek(liTmpSeek, 0, NULL); //m_wszContent += ReadString(documentReader, pieceEnd - pieceStart, isUnicode); if (nLength == 0) continue; for (UINT i = 0; i < nLength; i++) { if (!bUnicode) { BYTE ch = 0; pStream->Read(&ch, 1, NULL); m_wszContent += (CHAR)ch; } else { SHORT ch = 0; pStream->Read(&ch, 2, NULL); m_wszContent += (WCHAR)ch; } } } pStream->Release(); pTableStream->Release(); #endif // Obtain the IPropertySetStorage interface. hr = pStorage->QueryInterface(IID_IPropertySetStorage, (void **)&pPropSetStg); IPropertyStorage *pPropStg = NULL; struct pidsiStruct { TCHAR *name; LONG pid; } pidsiArr[] = { {L"Author", PIDSI_AUTHOR}, {L"Title", PIDSI_TITLE}, {L"Subject", PIDSI_SUBJECT}, {L"Keywords", PIDSI_KEYWORDS}, {L"Status", PIDMSI_STATUS}, {L"AppName", PIDSI_APPNAME}, {L"Comments", PIDSI_COMMENTS}, {L"Template", PIDSI_TEMPLATE}, {L"Revision Number", PIDSI_REVNUMBER}, {L"Created", PIDSI_CREATE_DTM}, {L"Edit Time", PIDSI_EDITTIME}, {L"Last Saved", PIDSI_LASTSAVE_DTM}, {L"LastAuthor", PIDSI_LASTAUTHOR}, {L"Last printed", PIDSI_LASTPRINTED}, {L"Page Count", PIDSI_PAGECOUNT}, {L"Word Count", PIDSI_WORDCOUNT}, {L"Char Count", PIDSI_CHARCOUNT}, {L"Thumbnail", PIDSI_THUMBNAIL}, {L"Doc Security", PIDSI_DOC_SECURITY}, {0, 0} }, pidsdiArr[] = { {L"Company", PIDDSI_COMPANY}, {L"Slide notes", PIDDSI_SLIDECOUNT}, {0, 0} }; // Count elements in pidsiArr. INT nPidsi = 0, nPidsdi = 0; for(nPidsi=0; pidsiArr[nPidsi].name; nPidsi++); for(nPidsdi=0; pidsdiArr[nPidsdi].name; nPidsdi++); // Initialize PROPSPEC for the properties you want. PROPSPEC *pPropSpec = new PROPSPEC [nPidsi]; PROPVARIANT *pPropVar = new PROPVARIANT [nPidsi]; PROPSPEC *pDocPropSpec = new PROPSPEC [nPidsdi]; PROPVARIANT *pDocPropVar = new PROPVARIANT [nPidsdi]; for(INT i=0; i<nPidsi; i++) { ZeroMemory(&pPropSpec[i], sizeof(PROPSPEC)); pPropSpec[i].ulKind = PRSPEC_PROPID; pPropSpec[i].propid = pidsiArr[i].pid; } for(INT i=0; i<nPidsdi; i++) { ZeroMemory(&pDocPropSpec[i], sizeof(PROPSPEC)); pDocPropSpec[i].ulKind = PRSPEC_PROPID; pDocPropSpec[i].propid = pidsdiArr[i].pid; } // Obtain meta infos from FMTID_SummaryInformation hr = pPropSetStg->Open(FMTID_SummaryInformation, STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg); // Read properties. hr = pPropStg->ReadMultiple(nPidsi, pPropSpec, pPropVar); if(FAILED(hr)) { _tprintf(L"IPropertyStg::ReadMultiple() failed w/error %08lx",hr); } pPropStg->Release(); pPropStg = NULL; // Obtain meta infos from FMTID_DocSummaryInformation hr = pPropSetStg->Open(FMTID_DocSummaryInformation, STGM_READ | STGM_SHARE_EXCLUSIVE, &pPropStg); // Read properties. hr = pPropStg->ReadMultiple(nPidsdi, pDocPropSpec, pDocPropVar); if(FAILED(hr)) { _tprintf(L"IPropertyStg::ReadMultiple() failed w/error %08lx",hr); } pPropStg->Release(); // Copy Meta fields out from FMTID_SummaryInformation for(int i = 0; i < nPidsi; i++) { switch(pidsiArr[i].pid) { case PIDSI_AUTHOR: DumpPropVariant(pPropVar + i, m_wszAuthor, MAX_META_LEN); break; case PIDSI_TITLE: DumpPropVariant(pPropVar + i, m_wszTitle, MAX_META_LEN); break; case PIDSI_SUBJECT: DumpPropVariant(pPropVar + i, m_wszSubject, MAX_META_LEN); break; case PIDSI_KEYWORDS: DumpPropVariant(pPropVar + i, m_wszKeywords, MAX_META_LEN); break; case PIDSI_APPNAME: DumpPropVariant(pPropVar + i, m_wszApplication, MAX_META_LEN); break; case PIDSI_COMMENTS: DumpPropVariant(pPropVar + i, m_wszComments, MAX_META_LEN); break; case PIDSI_TEMPLATE: DumpPropVariant(pPropVar + i, m_wszTemplateUsed, MAX_META_LEN); break; case PIDSI_REVNUMBER: DumpPropVariant(pPropVar + i, m_wszRevisionNumber, MAX_META_LEN); break; case PIDSI_EDITTIME: DumpPropVariant(pPropVar + i, m_wszTotalEditingTime, MAX_META_LEN); break; case PIDSI_LASTSAVE_DTM: DumpPropVariant(pPropVar + i, m_wszLastSaved, MAX_META_LEN); break; case PIDSI_LASTAUTHOR: DumpPropVariant(pPropVar + i, m_wszLastEditedBy, MAX_META_LEN); break; case PIDSI_LASTPRINTED: DumpPropVariant(pPropVar + i, m_wszLastPrinted, MAX_META_LEN); break; case PIDSI_PAGECOUNT: DumpPropVariant(pPropVar + i, m_wszPageCount, MAX_META_LEN); break; case PIDSI_WORDCOUNT: DumpPropVariant(pPropVar + i, m_wszWordCount, MAX_META_LEN); break; case PIDSI_CHARCOUNT: DumpPropVariant(pPropVar + i, m_wszCharacterCount, MAX_META_LEN); break; } } // Copy Meta fields out from FMTID_DocSummaryInformation for(int i = 0; i < nPidsdi; i++) { switch(pidsdiArr[i].pid) { case PIDDSI_COMPANY: DumpPropVariant(pDocPropVar + i, m_wszCompany, MAX_META_LEN); break; } } // De-allocate memory. delete [] pPropVar; delete [] pPropSpec; delete [] pDocPropVar; delete [] pDocPropSpec; // Release obtained interface. pPropSetStg->Release(); pStorage->Release(); return TRUE; }