| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551 |
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
- #include "stdafx.h"
- #include <malloc.h>
- #include <ole2.h>
- #include <oleauto.h>
- #ifdef AFXCTL_PROP_SEG
- #pragma code_seg(AFXCTL_PROP_SEG)
- #endif
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- #define new DEBUG_NEW
- /////////////////////////////////////////////////////////////////////////////
- // Helper functions used by CProperty, CPropertySection, CPropertySet classes
- AFX_STATIC LPVOID AFXAPI _AfxCountPrefixedStringA(LPCSTR lpsz)
- {
- DWORD cb = (lstrlenA(lpsz) + 1);
- LPDWORD lp = (LPDWORD)malloc((int)cb + sizeof(DWORD));
- if (lp)
- {
- *lp = cb;
- lstrcpyA((LPSTR)(lp+1), lpsz);
- }
- return (LPVOID)lp;
- }
- #ifndef OLE2ANSI
- AFX_STATIC LPVOID AFXAPI _AfxCountPrefixedStringW(LPCWSTR lpsz)
- {
- DWORD cb = (wcslen(lpsz) + 1);
- LPDWORD lp = (LPDWORD)malloc((int)cb * sizeof(WCHAR) + sizeof(DWORD));
- if (lp)
- {
- *lp = cb;
- wcscpy((LPWSTR)(lp+1), lpsz);
- }
- return (LPVOID)lp;
- }
- #endif
- #ifdef _UNICODE
- #define _AfxCountPrefixedString _AfxCountPrefixedStringW
- #else
- #define _AfxCountPrefixedString _AfxCountPrefixedStringA
- #endif
- #ifdef _UNICODE
- #define MAX_STRLEN 1024
- AFX_STATIC LPBYTE AFXAPI _AfxConvertStringProp(LPBYTE pbProp, DWORD dwType, ULONG nReps,
- size_t cbCharSize)
- {
- LPBYTE pbResult = NULL; // Return value
- ULONG cbResult = 0; // Number of bytes in pbResult
- LPBYTE pbBuffer; // Temporary holding space
- ULONG cchOrig; // Number of characters in original string
- ULONG cchCopy; // Number of characters to copy
- ULONG cbCopy; // Number of bytes to copy
- LPBYTE pbResultNew; // Used for realloc of pbResult
- pbBuffer = (LPBYTE)malloc(MAX_STRLEN * cbCharSize);
- if (pbBuffer == NULL)
- return NULL;
- // If it's a vector, the count goes first.
- if (dwType & VT_VECTOR)
- {
- pbResult = (LPBYTE)malloc(sizeof(DWORD));
- if (pbResult == NULL)
- {
- free(pbBuffer);
- return NULL;
- }
- *(LPDWORD)pbResult = nReps;
- cbResult = sizeof(DWORD);
- }
- while (nReps--)
- {
- cchOrig = *(LPDWORD)pbProp;
- pbProp += sizeof(DWORD);
- // Convert multibyte string to Unicode.
- if (cbCharSize == sizeof(WCHAR))
- {
- cchCopy = _mbstowcsz((LPWSTR)pbBuffer, (LPSTR)pbProp,
- min(cchOrig, MAX_STRLEN));
- }
- else
- {
- cchCopy = _wcstombsz((LPSTR)pbBuffer, (LPWSTR)pbProp,
- min(cchOrig, MAX_STRLEN));
- }
- // Allocate space to append string.
- cbCopy = cchCopy * cbCharSize;
- pbResultNew = (LPBYTE)realloc(pbResult, cbResult + sizeof(DWORD) +
- cbCopy);
- // If allocation failed, cleanup and return NULL;
- if (pbResultNew == NULL)
- {
- free(pbResult);
- free(pbBuffer);
- return NULL;
- }
- pbResult = pbResultNew;
- // Copy character count and converted string into place,
- // then update the total size.
- memcpy(pbResult + cbResult, (LPBYTE)&cchCopy, sizeof(DWORD));
- memcpy(pbResult + cbResult + sizeof(DWORD), pbBuffer, cbCopy);
- cbResult += sizeof(DWORD) + cbCopy;
- // Advance to the next vector element
- pbProp += (cchOrig * cbCharSize);
- }
- free(pbBuffer);
- return pbResult;
- }
- #endif // _UNICODE
- /////////////////////////////////////////////////////////////////////////////
- // Implementation of the CProperty class
- CProperty::CProperty()
- {
- m_dwPropID = 0;
- m_dwType = VT_EMPTY;
- m_pValue = NULL; // must init to NULL
- }
- CProperty::CProperty(DWORD dwID, const LPVOID pValue, DWORD dwType)
- {
- m_dwPropID = dwID;
- m_dwType = dwType;
- m_pValue = NULL; // must init to NULL
- Set(dwID, pValue, dwType);
- }
- CProperty::~CProperty()
- {
- FreeValue();
- }
- BOOL CProperty::Set(DWORD dwID, const LPVOID pValue, DWORD dwType)
- {
- m_dwType = dwType;
- m_dwPropID = dwID;
- return Set(pValue);
- }
- BOOL CProperty::Set(const LPVOID pValue, DWORD dwType)
- {
- m_dwType = dwType;
- return Set(pValue);
- }
- BOOL CProperty::Set(const LPVOID pVal)
- {
- ULONG cb;
- ULONG cbItem;
- ULONG cbValue;
- ULONG nReps;
- LPBYTE pCur;
- LPVOID pValue = pVal;
- DWORD dwType = m_dwType;
- LPVOID pValueOrig = NULL;
- if (m_pValue != NULL)
- {
- FreeValue();
- }
- if (pValue == NULL || m_dwType == 0)
- return TRUE;
- // Given pValue, determine how big it is
- // Then allocate a new buffer for m_pValue and copy...
- nReps = 1;
- cbValue = 0;
- pCur = (LPBYTE)pValue;
- if (m_dwType & VT_VECTOR)
- {
- // The next DWORD is a count of the elements
- nReps = *(LPDWORD)pValue;
- cb = sizeof(nReps);
- pCur += cb;
- cbValue += cb;
- dwType &= ~VT_VECTOR;
- }
- else
- {
- // If we get any of the string-like types,
- // and we are not a vector create a count-prefixed
- // buffer.
- switch (dwType)
- {
- case VT_LPSTR: // null terminated string
- pValueOrig = pValue;
- pValue = _AfxCountPrefixedStringA((LPSTR)pValueOrig);
- pCur = (LPBYTE)pValue;
- break;
- case VT_BSTR: // binary string
- case VT_STREAM: // Name of the stream follows
- case VT_STORAGE: // Name of the storage follows
- case VT_STREAMED_OBJECT:// Stream contains an object
- case VT_STORED_OBJECT: // Storage contains an object
- pValueOrig = pValue;
- pValue = _AfxCountPrefixedString((LPTSTR)pValueOrig);
- pCur = (LPBYTE)pValue;
- break;
- #ifndef OLE2ANSI
- case VT_LPWSTR: // UNICODE string
- pValueOrig = pValue;
- pValue = _AfxCountPrefixedStringW((LPWSTR)pValueOrig);
- pCur = (LPBYTE)pValue;
- break;
- #endif
- }
- }
- // Since a value can be made up of a vector (VT_VECTOR) of
- // items, we first seek through the value, picking out
- // each item, getting it's size.
- //
- cbItem = 0; // Size of the current item
- while (nReps--)
- {
- switch (dwType)
- {
- case VT_EMPTY: // nothing
- cbItem = 0;
- break;
- case VT_I2: // 2 byte signed int
- case VT_BOOL: // True=-1, False=0
- cbItem = 2;
- break;
- case VT_I4: // 4 byte signed int
- case VT_R4: // 4 byte real
- cbItem = 4;
- break;
- case VT_R8: // 8 byte real
- case VT_CY: // currency
- case VT_DATE: // date
- case VT_I8: // signed 64-bit int
- case VT_FILETIME: // FILETIME
- cbItem = 8;
- break;
- case VT_CLSID: // A Class ID
- cbItem = sizeof(CLSID);
- break;
- #ifndef _UNICODE
- case VT_BSTR: // binary string
- case VT_STREAM: // Name of the stream follows
- case VT_STORAGE: // Name of the storage follows
- case VT_STREAMED_OBJECT:// Stream contains an object
- case VT_STORED_OBJECT: // Storage contains an object
- case VT_STREAMED_PROPSET:// Stream contains a propset
- case VT_STORED_PROPSET: // Storage contains a propset
- #endif // _UNICODE
- case VT_LPSTR: // null terminated string
- case VT_BLOB_OBJECT: // Blob contains an object
- case VT_BLOB_PROPSET: // Blob contains a propset
- case VT_BLOB: // Length prefixed bytes
- case VT_CF: // Clipboard format
- // Get the DWORD that gives us the size, making
- // sure we increment cbValue.
- cbItem = *(LPDWORD)pCur;
- cb = sizeof(cbItem);
- pCur += cb;
- cbValue += cb;
- break;
- #ifdef _UNICODE
- case VT_BSTR: // binary string
- case VT_STREAM: // Name of the stream follows
- case VT_STORAGE: // Name of the storage follows
- case VT_STREAMED_OBJECT:// Stream contains an object
- case VT_STORED_OBJECT: // Storage contains an object
- case VT_STREAMED_PROPSET:// Stream contains a propset
- case VT_STORED_PROPSET: // Storage contains a propset
- #endif // _UNICODE
- case VT_LPWSTR: // UNICODE string
- cbItem = *(LPDWORD)pCur * sizeof(WCHAR);
- cb = sizeof(cbItem);
- pCur += cb;
- cbValue += cb;
- break;
- default:
- if (pValueOrig)
- free(pValue);
- return FALSE;
- }
- // Seek to the next item
- pCur += cbItem;
- cbValue += cbItem;
- }
- if (NULL == AllocValue(cbValue))
- {
- TRACE0("CProperty::AllocValue failed");
- return FALSE;
- }
- memcpy(m_pValue, pValue, (int)cbValue);
- if (pValueOrig)
- free(pValue);
- return TRUE;
- }
- LPVOID CProperty::Get()
- { return Get((DWORD*)NULL); }
- LPVOID CProperty::Get(DWORD* pcb)
- {
- DWORD cb;
- LPBYTE p = NULL;
- p = (LPBYTE)m_pValue;
- // m_pValue points to a Property "Value" which may
- // have size information included...
- switch (m_dwType)
- {
- case VT_EMPTY: // nothing
- cb = 0;
- break;
- case VT_I2: // 2 byte signed int
- case VT_BOOL: // True=-1, False=0
- cb = 2;
- break;
- case VT_I4: // 4 byte signed int
- case VT_R4: // 4 byte real
- cb = 4;
- break;
- case VT_R8: // 8 byte real
- case VT_CY: // currency
- case VT_DATE: // date
- case VT_I8: // signed 64-bit int
- case VT_FILETIME: // FILETIME
- cb = 8;
- break;
- #ifndef _UNICODE
- case VT_BSTR: // binary string
- case VT_STREAM: // Name of the stream follows
- case VT_STORAGE: // Name of the storage follows
- case VT_STREAMED_OBJECT:// Stream contains an object
- case VT_STORED_OBJECT: // Storage contains an object
- case VT_STREAMED_PROPSET:// Stream contains a propset
- case VT_STORED_PROPSET: // Storage contains a propset
- #endif // UNICODE
- case VT_LPSTR: // null terminated string
- case VT_CF: // Clipboard format
- // Read the DWORD that gives us the size, making
- // sure we increment cbValue.
- cb = *(LPDWORD)p;
- p += sizeof(DWORD);
- break;
- case VT_BLOB: // Length prefixed bytes
- case VT_BLOB_OBJECT: // Blob contains an object
- case VT_BLOB_PROPSET: // Blob contains a propset
- // Read the DWORD that gives us the size.
- cb = *(LPDWORD)p;
- break;
- #ifdef _UNICODE
- case VT_BSTR: // binary string
- case VT_STREAM: // Name of the stream follows
- case VT_STORAGE: // Name of the storage follows
- case VT_STREAMED_OBJECT:// Stream contains an object
- case VT_STORED_OBJECT: // Storage contains an object
- case VT_STREAMED_PROPSET:// Stream contains a propset
- case VT_STORED_PROPSET: // Storage contains a propset
- #endif // _UNICODE
- case VT_LPWSTR: // UNICODE string
- cb = *(LPDWORD)p * sizeof(WCHAR);
- p += sizeof(DWORD);
- break;
- case VT_CLSID: // A Class ID
- cb = sizeof(CLSID);
- break;
- default:
- return NULL;
- }
- if (pcb != NULL)
- *pcb = cb;
- return p;
- }
- DWORD CProperty::GetType()
- { return m_dwType; }
- void CProperty::SetType(DWORD dwType)
- { m_dwType = dwType; }
- DWORD CProperty::GetID()
- { return m_dwPropID; }
- void CProperty::SetID(DWORD dwPropID)
- { m_dwPropID = dwPropID; }
- LPVOID CProperty::GetRawValue()
- { return m_pValue; }
- BOOL CProperty::WriteToStream(IStream* pIStream)
- {
- ULONG cb;
- ULONG cbTotal; // Total size of the whole value
- DWORD dwType = m_dwType;
- DWORD nReps;
- LPBYTE pValue;
- LPBYTE pCur;
- BOOL bSuccess = FALSE;
- BYTE b = 0;
- nReps = 1;
- pValue = (LPBYTE)m_pValue;
- pCur = pValue;
- cbTotal = 0;
- if (m_dwType & VT_VECTOR)
- {
- // Value is a DWORD count of elements followed by
- // that many repititions of the value.
- //
- nReps = *(LPDWORD)pCur;
- cbTotal = sizeof(DWORD);
- pCur += cbTotal;
- dwType &= ~VT_VECTOR;
- }
- #ifdef _UNICODE
- switch (dwType)
- {
- case VT_BSTR: // binary string
- case VT_STREAM: // Name of the stream follows
- case VT_STORAGE: // Name of the storage follows
- case VT_STREAMED_OBJECT:// Stream contains an object
- case VT_STORED_OBJECT: // Storage contains an object
- case VT_STREAMED_PROPSET:// Stream contains a propset
- case VT_STORED_PROPSET: // Storage contains a propset
- pValue = _AfxConvertStringProp(pCur, m_dwType, nReps, sizeof(char));
- if (m_dwType & VT_VECTOR)
- pCur = pValue + sizeof(DWORD);
- break;
- }
- #endif // _UNICODE
- // Figure out how big the data is.
- while (nReps--)
- {
- switch (dwType)
- {
- case VT_EMPTY: // nothing
- cb = 0;
- break;
- case VT_I2: // 2 byte signed int
- case VT_BOOL: // True=-1, False=0
- cb = 2;
- break;
- case VT_I4: // 4 byte signed int
- case VT_R4: // 4 byte real
- cb = 4;
- break;
- case VT_R8: // 8 byte real
- case VT_CY: // currency
- case VT_DATE: // date
- case VT_I8: // signed 64-bit int
- case VT_FILETIME: // FILETIME
- cb = 8;
- break;
- case VT_LPSTR: // null terminated string
- case VT_BSTR: // binary string
- case VT_STREAM: // Name of the stream follows
- case VT_STORAGE: // Name of the storage follows
- case VT_STREAMED_OBJECT:// Stream contains an object
- case VT_STORED_OBJECT: // Storage contains an object
- case VT_STREAMED_PROPSET:// Stream contains a propset
- case VT_STORED_PROPSET: // Storage contains a propset
- case VT_BLOB: // Length prefixed bytes
- case VT_BLOB_OBJECT: // Blob contains an object
- case VT_BLOB_PROPSET: // Blob contains a propset
- case VT_CF: // Clipboard format
- cb = sizeof(DWORD) + *(LPDWORD)pCur;
- break;
- case VT_LPWSTR: // UNICODE string
- cb = sizeof(DWORD) + (*(LPDWORD)pCur * sizeof(WCHAR));
- break;
- case VT_CLSID: // A Class ID
- cb = sizeof(CLSID);
- break;
- default:
- return FALSE;
- }
- pCur += cb;
- cbTotal+= cb;
- }
- // Write the type
- pIStream->Write((LPVOID)&m_dwType, sizeof(m_dwType), &cb);
- if (cb != sizeof(m_dwType))
- goto Cleanup;
- // Write the value
- pIStream->Write((LPVOID)pValue, cbTotal, &cb);
- if (cb != cbTotal)
- goto Cleanup;
- // Make sure we are 32 bit aligned
- cbTotal = (((cbTotal + 3) >> 2) << 2) - cbTotal;
- while (cbTotal--)
- {
- pIStream->Write((LPVOID)&b, 1, &cb);
- if (cb != sizeof(BYTE))
- goto Cleanup;
- }
- bSuccess = TRUE;
- Cleanup:
- if (pValue != m_pValue)
- free(pValue);
- return bSuccess;
- }
- BOOL CProperty::ReadFromStream(IStream* pIStream)
- {
- ULONG cb;
- ULONG cbItem;
- ULONG cbValue;
- DWORD dwType;
- ULONG nReps;
- ULONG iReps;
- LPSTREAM pIStrItem;
- LARGE_INTEGER li;
- // All properties are made up of a type/value pair.
- // The obvious first thing to do is to get the type...
- pIStream->Read((LPVOID)&m_dwType, sizeof(m_dwType), &cb);
- if (cb != sizeof(m_dwType))
- return FALSE;
- dwType = m_dwType;
- nReps = 1;
- cbValue = 0;
- if (m_dwType & VT_VECTOR)
- {
- // The next DWORD in the stream is a count of the
- // elements
- pIStream->Read((LPVOID)&nReps, sizeof(nReps), &cb);
- if (cb != sizeof(nReps))
- return FALSE;
- cbValue += cb;
- dwType &= ~VT_VECTOR;
- }
- // Since a value can be made up of a vector (VT_VECTOR) of
- // items, we first seek through the value, picking out
- // each item, getting it's size. We use a cloned
- // stream for this (pIStrItem).
- // We then use our pIStream to read the entire 'blob' into
- // the allocated buffer.
- //
- cbItem = 0; // Size of the current item
- pIStream->Clone(&pIStrItem);
- ASSERT(pIStrItem != NULL);
- iReps = nReps;
- while (iReps--)
- {
- switch (dwType)
- {
- case VT_EMPTY: // nothing
- cbItem = 0;
- break;
- case VT_I2: // 2 byte signed int
- case VT_BOOL: // True=-1, False=0
- cbItem = 2;
- break;
- case VT_I4: // 4 byte signed int
- case VT_R4: // 4 byte real
- cbItem = 4;
- break;
- case VT_R8: // 8 byte real
- case VT_CY: // currency
- case VT_DATE: // date
- case VT_I8: // signed 64-bit int
- case VT_FILETIME: // FILETIME
- cbItem = 8;
- break;
- case VT_LPSTR: // null terminated string
- case VT_BSTR: // binary string
- case VT_STREAM: // Name of the stream follows
- case VT_STORAGE: // Name of the storage follows
- case VT_STREAMED_OBJECT:// Stream contains an object
- case VT_STORED_OBJECT: // Storage contains an object
- case VT_STREAMED_PROPSET:// Stream contains a propset
- case VT_STORED_PROPSET: // Storage contains a propset
- case VT_BLOB: // Length prefixed bytes
- case VT_BLOB_OBJECT: // Blob contains an object
- case VT_BLOB_PROPSET: // Blob contains a propset
- case VT_CF: // Clipboard format
- // Read the DWORD that gives us the size, making
- // sure we increment cbValue.
- pIStream->Read((LPVOID)&cbItem, sizeof(cbItem), &cb);
- if (cb != sizeof(cbItem))
- return FALSE;
- LISet32(li, -(LONG)cb);
- pIStream->Seek(li, STREAM_SEEK_CUR, NULL);
- cbValue += cb;
- break;
- case VT_LPWSTR: // UNICODE string
- pIStream->Read((LPVOID)&cbItem, sizeof(cbItem), &cb);
- if (cb != sizeof(cbItem))
- return FALSE;
- LISet32(li, -(LONG)cb);
- pIStream->Seek(li, STREAM_SEEK_CUR, NULL);
- cbValue += cb;
- cbItem *= sizeof(WCHAR);
- break;
- case VT_CLSID: // A Class ID
- cbItem = sizeof(CLSID);
- break;
- default:
- pIStrItem->Release();
- return FALSE;
- }
- // Seek to the next item
- LISet32(li, cbItem);
- pIStrItem->Seek(li, STREAM_SEEK_CUR, NULL);
- cbValue += cbItem;
- }
- pIStrItem->Release();
- #ifdef _UNICODE
- LPBYTE pTmp;
- switch (dwType)
- {
- case VT_BSTR: // binary string
- case VT_STREAM: // Name of the stream follows
- case VT_STORAGE: // Name of the storage follows
- case VT_STREAMED_OBJECT:// Stream contains an object
- case VT_STORED_OBJECT: // Storage contains an object
- case VT_STREAMED_PROPSET:// Stream contains a propset
- case VT_STORED_PROPSET: // Storage contains a propset
- pTmp = (LPBYTE)malloc((int)cbValue);
- pIStream->Read(pTmp, cbValue, &cb);
- m_pValue = _AfxConvertStringProp(pTmp, m_dwType, nReps, sizeof(WCHAR));
- free(pTmp);
- break;
- default:
- #endif // _UNICODE
- // Allocate cbValue bytes
- if (NULL == AllocValue(cbValue))
- return FALSE;
- // Read the buffer from pIStream
- pIStream->Read(m_pValue, cbValue, &cb);
- if (cb != cbValue)
- return FALSE;
- #ifdef _UNICODE
- break;
- }
- #endif // _UNICODE
- // Done!
- return TRUE;
- }
- LPVOID CProperty::AllocValue(ULONG cb)
- {
- return m_pValue = malloc((int)cb);
- }
- void CProperty::FreeValue()
- {
- if (m_pValue != NULL)
- {
- free(m_pValue);
- m_pValue = NULL;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // Implementation of the CPropertySection class
- CPropertySection::CPropertySection()
- {
- m_FormatID = GUID_NULL;
- m_SH.cbSection = 0;
- m_SH.cProperties = 0;
- }
- CPropertySection::CPropertySection(CLSID FormatID)
- {
- m_FormatID = FormatID;
- m_SH.cbSection = 0;
- m_SH.cProperties = 0;
- }
- CPropertySection::~CPropertySection()
- {
- RemoveAll();
- return;
- }
- CLSID CPropertySection::GetFormatID()
- { return m_FormatID; }
- void CPropertySection::SetFormatID(CLSID FormatID)
- { m_FormatID = FormatID; }
- BOOL CPropertySection::Set(DWORD dwPropID, LPVOID pValue, DWORD dwType)
- {
- CProperty* pProp = GetProperty(dwPropID);
- if (pProp == NULL)
- {
- if ((pProp = new CProperty(dwPropID, pValue, dwType)) != NULL)
- AddProperty(pProp);
- return (pProp != NULL);
- }
- pProp->Set(dwPropID, pValue, dwType);
- return TRUE;
- }
- BOOL CPropertySection::Set(DWORD dwPropID, LPVOID pValue)
- {
- // Since no dwType was specified, the property is assumed
- // to exist. Fail if it does not.
- CProperty* pProp = GetProperty(dwPropID);
- if (pProp != NULL && pProp->m_dwType)
- {
- pProp->Set(dwPropID, pValue, pProp->m_dwType);
- return TRUE;
- }
- else
- return FALSE;
- }
- LPVOID CPropertySection::Get(DWORD dwPropID)
- { return Get(dwPropID, (DWORD*)NULL); }
- LPVOID CPropertySection::Get(DWORD dwPropID, DWORD* pcb)
- {
- CProperty* pProp = GetProperty(dwPropID);
- if (pProp)
- return pProp->Get(pcb);
- else
- return NULL;
- }
- void CPropertySection::Remove(DWORD dwID)
- {
- POSITION pos = m_PropList.GetHeadPosition();
- CProperty* pProp;
- while (pos != NULL)
- {
- POSITION posRemove = pos;
- pProp = (CProperty*)m_PropList.GetNext(pos);
- if (pProp->m_dwPropID == dwID)
- {
- m_PropList.RemoveAt(posRemove);
- delete pProp;
- m_SH.cProperties--;
- return;
- }
- }
- }
- void CPropertySection::RemoveAll()
- {
- POSITION pos = m_PropList.GetHeadPosition();
- while (pos != NULL)
- delete (CProperty*)m_PropList.GetNext(pos);
- m_PropList.RemoveAll();
- m_SH.cProperties = 0;
- }
- CProperty* CPropertySection::GetProperty(DWORD dwPropID)
- {
- POSITION pos = m_PropList.GetHeadPosition();
- CProperty* pProp;
- while (pos != NULL)
- {
- pProp= (CProperty*)m_PropList.GetNext(pos);
- if (pProp->m_dwPropID == dwPropID)
- return pProp;
- }
- return NULL;
- }
- void CPropertySection::AddProperty(CProperty* pProp)
- {
- m_PropList.AddTail(pProp);
- m_SH.cProperties++;
- }
- DWORD CPropertySection::GetSize()
- { return m_SH.cbSection; }
- DWORD CPropertySection::GetCount()
- { return m_PropList.GetCount(); }
- CPtrList* CPropertySection::GetList()
- { return &m_PropList; }
- BOOL CPropertySection::WriteToStream(IStream* pIStream)
- {
- // Create a dummy property entry for the name dictionary (ID == 0).
- Set(0, NULL, VT_EMPTY);
- ULONG cb;
- ULARGE_INTEGER ulSeekOld;
- ULARGE_INTEGER ulSeek;
- LPSTREAM pIStrPIDO;
- PROPERTYIDOFFSET pido;
- LARGE_INTEGER li;
- // The Section header contains the number of bytes in the
- // section. Thus we need to go back to where we should
- // write the count of bytes
- // after we write all the property sets..
- // We accomplish this by saving the seek pointer to where
- // the size should be written in ulSeekOld
- m_SH.cbSection = 0;
- m_SH.cProperties = m_PropList.GetCount();
- LISet32(li, 0);
- pIStream->Seek(li, STREAM_SEEK_CUR, &ulSeekOld);
- pIStream->Write((LPVOID)&m_SH, sizeof(m_SH), &cb);
- if (sizeof(m_SH) != cb)
- {
- TRACE0("Write of section header failed (1).\n");
- return FALSE;
- }
- if (m_PropList.IsEmpty())
- {
- TRACE0("Warning: Wrote empty property section.\n");
- return TRUE;
- }
- // After the section header is the list of property ID/Offset pairs
- // Since there is an ID/Offset pair for each property and we
- // need to write the ID/Offset pair as we write each property
- // we clone the stream and use the clone to access the
- // table of ID/offset pairs (PIDO)...
- //
- pIStream->Clone(&pIStrPIDO);
- // Now seek pIStream past the PIDO list
- //
- LISet32(li, m_SH.cProperties * sizeof(PROPERTYIDOFFSET));
- pIStream->Seek(li, STREAM_SEEK_CUR, &ulSeek);
- // Now write each section to pIStream.
- CProperty* pProp = NULL;
- POSITION pos = m_PropList.GetHeadPosition();
- while (pos != NULL)
- {
- // Get next element (note cast)
- pProp = (CProperty*)m_PropList.GetNext(pos);
- if (pProp->m_dwPropID != 0)
- {
- // Write it
- if (!pProp->WriteToStream(pIStream))
- {
- pIStrPIDO->Release();
- return FALSE;
- }
- }
- else
- {
- if (!WriteNameDictToStream(pIStream))
- {
- pIStrPIDO->Release();
- return FALSE;
- }
- }
- // Using our cloned stream write the Format ID / Offset pair
- // The offset to this property is the current seek pointer
- // minus the pointer to the beginning of the section
- pido.dwOffset = ulSeek.LowPart - ulSeekOld.LowPart;
- pido.propertyID = pProp->m_dwPropID;
- pIStrPIDO->Write((LPVOID)&pido, sizeof(pido), &cb);
- if (sizeof(pido) != cb)
- {
- TRACE0("Write of 'pido' failed\n");
- pIStrPIDO->Release();
- return FALSE;
- }
- // Get the seek offset after the write
- LISet32(li, 0);
- pIStream->Seek(li, STREAM_SEEK_CUR, &ulSeek);
- }
- pIStrPIDO->Release();
- // Now go back to ulSeekOld and write the section header.
- // Size of section is current seek point minus old seek point
- //
- m_SH.cbSection = ulSeek.LowPart - ulSeekOld.LowPart;
- // Seek to beginning of this section and write the section header.
- LISet32(li, ulSeekOld.LowPart);
- pIStream->Seek(li, STREAM_SEEK_SET, NULL);
- pIStream->Write((LPVOID)&m_SH, sizeof(m_SH), &cb);
- if (sizeof(m_SH) != cb)
- {
- TRACE0("Write of section header failed (2).\n");
- return FALSE;
- }
- // Now seek to end of of the now written section
- LISet32(li, ulSeek.LowPart);
- pIStream->Seek(li, STREAM_SEEK_SET, NULL);
- return TRUE;
- }
- BOOL CPropertySection::ReadFromStream(IStream* pIStream,
- LARGE_INTEGER liPropSet)
- {
- ULONG cb;
- PROPERTYIDOFFSET pido;
- ULONG cProperties;
- LPSTREAM pIStrPIDO;
- ULARGE_INTEGER ulSectionStart;
- LARGE_INTEGER li;
- CProperty* pProp;
- if (m_SH.cProperties || !m_PropList.IsEmpty())
- RemoveAll();
- // pIStream is pointing to the beginning of the section we
- // are to read. First there is a DWORD that is the count
- // of bytes in this section, then there is a count
- // of properties, followed by a list of propertyID/offset pairs,
- // followed by type/value pairs.
- //
- LISet32(li, 0);
- pIStream->Seek(li, STREAM_SEEK_CUR, &ulSectionStart);
- pIStream->Read((LPVOID)&m_SH, sizeof(m_SH), &cb);
- if (cb != sizeof(m_SH))
- return FALSE;
- // Now we're pointing at the first of the PropID/Offset pairs
- // (PIDOs). To get to each property we use a cloned stream
- // to stay back and point at the PIDOs (pIStrPIDO). We seek
- // pIStream to each of the Type/Value pairs, creating CProperites
- // and so forth as we go...
- //
- pIStream->Clone(&pIStrPIDO);
- cProperties = m_SH.cProperties;
- while (cProperties--)
- {
- pIStrPIDO->Read((LPVOID)&pido, sizeof(pido), &cb);
- if (cb != sizeof(pido))
- {
- pIStrPIDO->Release();
- return FALSE;
- }
- // Do a seek from the beginning of the property set.
- LISet32(li, ulSectionStart.LowPart + pido.dwOffset);
- pIStream->Seek(liPropSet, STREAM_SEEK_SET, NULL);
- 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
|