📄 olepset.cpp
字号:
pIStream->Seek(li, STREAM_SEEK_CUR, NULL);
// Now pIStream is at the type/value pair
if (pido.propertyID != 0)
{
pProp = new CProperty(pido.propertyID, NULL, 0);
pProp->ReadFromStream(pIStream);
m_PropList.AddTail(pProp);
}
else
{
ReadNameDictFromStream(pIStream);
}
}
pIStrPIDO->Release();
return TRUE;
}
BOOL CPropertySection::GetID(LPCTSTR pszName, DWORD* pdwPropID)
{
CString strName(pszName);
strName.MakeLower(); // Dictionary stores all names in lowercase
void* pvID;
if (m_NameDict.Lookup(strName, pvID))
{
*pdwPropID = (DWORD)pvID;
return TRUE;
}
// Failed to find entry in dictionary
return FALSE;
}
BOOL CPropertySection::SetName(DWORD dwPropID, LPCTSTR pszName)
{
BOOL bSuccess = TRUE;
CString strName(pszName);
strName.MakeLower(); // Dictionary stores all names in lowercase
TRY
{
void* pDummy;
BOOL bNameExists = m_NameDict.Lookup(strName, pDummy);
ASSERT(!bNameExists); // Property names must be unique.
if (bNameExists)
bSuccess = FALSE;
else
m_NameDict.SetAt(strName, (void*)dwPropID);
}
CATCH (CException, e)
{
TRACE0("Failed to add entry to dictionary.\n");
bSuccess = FALSE;
}
END_CATCH
return bSuccess;
}
struct DICTENTRYHEADER
{
DWORD dwPropID;
DWORD cb;
};
struct DICTENTRY
{
DICTENTRYHEADER hdr;
char sz[256];
};
BOOL CPropertySection::ReadNameDictFromStream(IStream* pIStream)
{
ULONG cb;
ULONG cbRead = 0;
// Read dictionary header (count).
ULONG cProperties = 0;
pIStream->Read((LPVOID)&cProperties, sizeof(cProperties), &cb);
if (sizeof(cProperties) != cb)
{
TRACE0("Read of dictionary header failed.\n");
return FALSE;
}
ULONG iProp;
DICTENTRY entry;
for (iProp = 0; iProp < cProperties; iProp++)
{
// Read entry header (dwPropID, cch).
if (FAILED(pIStream->Read((LPVOID)&entry, sizeof(DICTENTRYHEADER),
&cbRead)) ||
(sizeof(DICTENTRYHEADER) != cbRead))
{
TRACE0("Read of dictionary entry failed.\n");
return FALSE;
}
// Read entry data (name).
cb = entry.hdr.cb;
if (FAILED(pIStream->Read((LPVOID)&entry.sz, cb, &cbRead)) ||
(cbRead != cb))
{
TRACE0("Read of dictionary entry failed.\n");
return FALSE;
}
LPTSTR pszName;
#ifdef _UNICODE
// Persistent form is always ANSI/DBCS. Convert to Unicode.
WCHAR wszName[256];
_mbstowcsz(wszName, entry.sz, 256);
pszName = wszName;
#else // _UNICODE
pszName = entry.sz;
#endif // _UNICODE
// Section's "name" appears first in list and has dwPropID == 0.
if ((iProp == 0) && (entry.hdr.dwPropID == 0))
m_strSectionName = pszName; // Section name
else
SetName(entry.hdr.dwPropID, pszName); // Some other property
}
return TRUE;
}
AFX_STATIC BOOL AFXAPI _AfxWriteNameDictEntry(IStream* pIStream, DWORD dwPropID, CString& strName)
{
ULONG cb;
ULONG cbWritten = 0;
DICTENTRY entry;
entry.hdr.dwPropID = dwPropID;
entry.hdr.cb = min(strName.GetLength() + 1, 255);
#ifdef _UNICODE
// Persistent form is always ANSI/DBCS. Convert from Unicode.
_wcstombsz(entry.sz, (LPCWSTR)strName, 256);
#else // _UNICODE
memcpy(entry.sz, (LPCSTR)strName, (size_t)entry.hdr.cb);
#endif // _UNICODE
cb = sizeof(DICTENTRYHEADER) + entry.hdr.cb;
if (FAILED(pIStream->Write((LPVOID)&entry, cb, &cbWritten)) ||
(cbWritten != cb))
{
TRACE0("Write of dictionary entry failed.\n");
return FALSE;
}
return TRUE;
}
BOOL CPropertySection::WriteNameDictToStream(IStream* pIStream)
{
ULONG cb;
// Write dictionary header (count).
ULONG cProperties = m_NameDict.GetCount() + 1;
pIStream->Write((LPVOID)&cProperties, sizeof(cProperties), &cb);
if (sizeof(cProperties) != cb)
{
TRACE0("Write of dictionary header failed.\n");
return FALSE;
}
POSITION pos;
CString strName;
void* pvID;
// Write out section's "name" with dwPropID == 0 first
if (!_AfxWriteNameDictEntry(pIStream, 0, m_strSectionName))
return FALSE;
// Enumerate contents of dictionary and write out (dwPropID, cb, name).
pos = m_NameDict.GetStartPosition();
while (pos != NULL)
{
m_NameDict.GetNextAssoc(pos, strName, pvID);
if (!_AfxWriteNameDictEntry(pIStream, (DWORD)pvID, strName))
return FALSE;
}
return TRUE;
}
BOOL CPropertySection::SetSectionName(LPCTSTR pszName)
{
m_strSectionName = pszName;
return TRUE;
}
LPCTSTR CPropertySection::GetSectionName()
{
return (LPCTSTR)m_strSectionName;
}
/////////////////////////////////////////////////////////////////////////////
// Implementation of the CPropertySet class
CPropertySet::CPropertySet()
{
m_PH.wByteOrder = 0xFFFE;
m_PH.wFormat = 0;
m_PH.dwOSVer = (DWORD)MAKELONG(LOWORD(GetVersion()), 2);
m_PH.clsID = GUID_NULL;
m_PH.cSections = 0;
}
CPropertySet::CPropertySet(CLSID clsID)
{
m_PH.wByteOrder = 0xFFFE;
m_PH.wFormat = 0;
m_PH.dwOSVer = (DWORD)MAKELONG(LOWORD(GetVersion()), 2);
m_PH.clsID = clsID;
m_PH.cSections = 0;
}
CPropertySet::~CPropertySet()
{ RemoveAll(); }
BOOL CPropertySet::Set(CLSID FormatID, DWORD dwPropID, LPVOID pValue, DWORD dwType)
{
CPropertySection* pSect = GetSection(FormatID);
if (pSect == NULL)
{
if ((pSect = new CPropertySection(FormatID)) != NULL)
AddSection(pSect);
}
pSect->Set(dwPropID, pValue, dwType);
return TRUE;
}
BOOL CPropertySet::Set(CLSID FormatID, DWORD dwPropID, LPVOID pValue)
{
// Since there is no dwType, we have to assume that the property
// already exists. If it doesn't, fail.
CPropertySection* pSect = GetSection(FormatID);
if (pSect != NULL)
return pSect->Set(dwPropID, pValue);
else
return FALSE;
}
LPVOID CPropertySet::Get(CLSID FormatID, DWORD dwPropID, DWORD* pcb)
{
CPropertySection* pSect = GetSection(FormatID);
if (pSect)
return pSect->Get(dwPropID, pcb);
else
return NULL;
}
LPVOID CPropertySet::Get(CLSID FormatID, DWORD dwPropID)
{ return Get(FormatID, dwPropID, (DWORD*)NULL); }
void CPropertySet::Remove(CLSID FormatID, DWORD dwPropID)
{
CPropertySection* pSect = GetSection(FormatID);
if (pSect)
pSect->Remove(dwPropID);
}
void CPropertySet::Remove(CLSID FormatID)
{
CPropertySection* pSect;
POSITION posRemove = m_SectionList.GetHeadPosition();
POSITION pos = posRemove;
while (posRemove != NULL)
{
pSect = (CPropertySection*)m_SectionList.GetNext(pos);
if (IsEqualCLSID(pSect->m_FormatID, FormatID))
{
m_SectionList.RemoveAt(posRemove);
delete pSect;
m_PH.cSections--;
return;
}
posRemove = pos;
}
}
void CPropertySet::RemoveAll()
{
POSITION pos = m_SectionList.GetHeadPosition();
while (pos != NULL)
{
delete (CPropertySection*)m_SectionList.GetNext(pos);
}
m_SectionList.RemoveAll();
m_PH.cSections = 0;
}
CPropertySection* CPropertySet::GetSection(CLSID FormatID)
{
POSITION pos = m_SectionList.GetHeadPosition();
CPropertySection* pSect;
while (pos != NULL)
{
pSect = (CPropertySection*)m_SectionList.GetNext(pos);
if (IsEqualCLSID(pSect->m_FormatID, FormatID))
return pSect;
}
return NULL;
}
CPropertySection* CPropertySet::AddSection(CLSID FormatID)
{
CPropertySection* pSect = GetSection(FormatID);
if (pSect)
return pSect;
pSect = new CPropertySection(FormatID);
if (pSect)
AddSection(pSect);
return pSect;
}
void CPropertySet::AddSection(CPropertySection* pSect)
{
m_SectionList.AddTail(pSect);
m_PH.cSections++;
}
CProperty* CPropertySet::GetProperty(CLSID FormatID, DWORD dwPropID)
{
CPropertySection* pSect = GetSection(FormatID);
if (pSect)
return pSect->GetProperty(dwPropID);
else
return NULL;
}
void CPropertySet::AddProperty(CLSID FormatID, CProperty* pProp)
{
CPropertySection* pSect = GetSection(FormatID);
if (pSect)
pSect->AddProperty(pProp);
}
WORD CPropertySet::GetByteOrder()
{ return m_PH.wByteOrder; }
WORD CPropertySet::GetFormatVersion()
{ return m_PH.wFormat; }
void CPropertySet::SetFormatVersion(WORD wFmtVersion)
{ m_PH.wFormat = wFmtVersion; }
DWORD CPropertySet::GetOSVersion()
{ return m_PH.dwOSVer; }
void CPropertySet::SetOSVersion(DWORD dwOSVer)
{ m_PH.dwOSVer = dwOSVer; }
CLSID CPropertySet::GetClassID()
{ return m_PH.clsID; }
void CPropertySet::SetClassID(CLSID clsID)
{ m_PH.clsID = clsID; }
DWORD CPropertySet::GetCount()
{ return m_SectionList.GetCount(); }
CPtrList* CPropertySet::GetList()
{ return &m_SectionList; }
BOOL CPropertySet::WriteToStream(IStream* pIStream)
{
LPSTREAM pIStrFIDO;
FORMATIDOFFSET fido;
ULONG cb;
ULARGE_INTEGER ulSeek;
LARGE_INTEGER li;
// Write the Property List Header
m_PH.cSections = m_SectionList.GetCount();
pIStream->Write((LPVOID)&m_PH, sizeof(m_PH), &cb);
if (sizeof(m_PH) != cb)
{
TRACE0("Write of Property Set Header failed.\n");
return FALSE;
}
if (m_SectionList.IsEmpty())
{
TRACE0("Warning: Wrote empty property set.\n");
return TRUE;
}
// After the header is the list of Format ID/Offset pairs
// Since there is an ID/Offset pair for each section and we
// need to write the ID/Offset pair as we write each section
// we clone the stream and use the clone to access the
// table of ID/offset pairs (FIDO)...
//
pIStream->Clone(&pIStrFIDO);
// Now seek pIStream past the FIDO list
//
LISet32(li, m_PH.cSections * sizeof(FORMATIDOFFSET));
pIStream->Seek(li, STREAM_SEEK_CUR, &ulSeek);
// Write each section.
CPropertySection* pSect = NULL;
POSITION pos = m_SectionList.GetHeadPosition();
while (pos != NULL)
{
// Get next element (note cast)
pSect = (CPropertySection*)m_SectionList.GetNext(pos);
// Write it
if (!pSect->WriteToStream(pIStream))
{
pIStrFIDO->Release();
return FALSE;
}
// Using our cloned stream write the Format ID / Offset pair
fido.formatID = pSect->m_FormatID;
fido.dwOffset = ulSeek.LowPart;
pIStrFIDO->Write((LPVOID)&fido, sizeof(fido), &cb);
if (sizeof(fido) != cb)
{
TRACE0("Write of 'fido' failed.\n");
pIStrFIDO->Release();
return FALSE;
}
// Get the seek offset (for pIStream) after the write
LISet32(li, 0);
pIStream->Seek(li, STREAM_SEEK_CUR, &ulSeek);
}
pIStrFIDO->Release();
return TRUE;
}
BOOL CPropertySet::ReadFromStream(IStream* pIStream)
{
ULONG cb;
FORMATIDOFFSET fido;
ULONG cSections;
LPSTREAM pIStrFIDO;
CPropertySection* pSect;
LARGE_INTEGER li;
LARGE_INTEGER liPropSet;
// Save the stream position at which the property set starts.
LARGE_INTEGER liZero = {0,0};
pIStream->Seek(liZero, STREAM_SEEK_CUR, (ULARGE_INTEGER*)&liPropSet);
if (m_PH.cSections || !m_SectionList.IsEmpty())
RemoveAll();
// The stream starts like this:
// wByteOrder wFmtVer dwOSVer clsID cSections
// Which is nice, because our PROPHEADER is the same!
pIStream->Read((LPVOID)&m_PH, sizeof(m_PH), &cb);
if (cb != sizeof(m_PH))
return FALSE;
// Now we're pointing at the first of the FormatID/Offset pairs
// (FIDOs). To get to each section we use a cloned stream
// to stay back and point at the FIDOs (pIStrFIDO). We seek
// pIStream to each of the sections, creating CProperitySection
// and so forth as we go...
//
pIStream->Clone(&pIStrFIDO);
cSections = m_PH.cSections;
while (cSections--)
{
pIStrFIDO->Read((LPVOID)&fido, sizeof(fido), &cb);
if (cb != sizeof(fido))
{
pIStrFIDO->Release();
return FALSE;
}
// Do a seek from the beginning of the property set.
LISet32(li, fido.dwOffset);
pIStream->Seek(liPropSet, STREAM_SEEK_SET, NULL);
pIStream->Seek(li, STREAM_SEEK_CUR, NULL);
// Now pIStream is at the type/value pair
pSect = new CPropertySection;
pSect->SetFormatID(fido.formatID);
pSect->ReadFromStream(pIStream, liPropSet);
m_SectionList.AddTail(pSect);
}
pIStrFIDO->Release();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
// Force any extra compiler-generated code into AFX_INIT_SEG
#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -