PROPSET.CPP
上传用户:sesekoo
上传日期:2020-07-18
资源大小:21543k
文件大小:40k
- // 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>
- #ifndef __DRAWCLI_PROPSET_H
- #include "propset.h"
- #endif // __DRAWCLI_PROPSET_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
- static LPVOID CountPrefixedStringA(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;
- }
- static LPVOID CountPrefixedStringW(LPCWSTR lpsz)
- {
- DWORD cb = DWORD( wcslen( lpsz ) + 1 );
- LPDWORD lp = (LPDWORD)malloc( (int)cb * sizeof(WCHAR) + sizeof(DWORD) );
- if (lp)
- {
- *lp = cb;
- __EXT_MFC_WCSCPY( (LPWSTR)(lp+1), wcslen( (LPWSTR)(lp+1) ), lpsz );
- }
- return (LPVOID)lp;
- }
- #ifdef _UNICODE
- #define CountPrefixedStringT CountPrefixedStringW
- #else
- #define CountPrefixedStringT CountPrefixedStringA
- #endif
- #ifdef _UNICODE
- #define MAX_STRLEN 1024
- static LPBYTE ConvertStringProp(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 = ULONG( 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 CDrawCliProperty class
- CDrawCliProperty::CDrawCliProperty( void )
- {
- m_dwPropID = 0;
- m_dwType = VT_EMPTY;
- m_pValue = NULL; // must init to NULL
- }
- CDrawCliProperty::CDrawCliProperty( DWORD dwID, const LPVOID pValue, DWORD dwType )
- {
- m_dwPropID = dwID;
- m_dwType = dwType;
- m_pValue = NULL; // must init to NULL
- Set( dwID, pValue, dwType );
- }
- CDrawCliProperty::~CDrawCliProperty()
- {
- FreeValue();
- }
- BOOL CDrawCliProperty::Set( DWORD dwID, const LPVOID pValue, DWORD dwType )
- {
- m_dwType = dwType;
- m_dwPropID = dwID;
- return Set( pValue );
- }
- BOOL CDrawCliProperty::Set( const LPVOID pValue, DWORD dwType )
- {
- m_dwType = dwType;
- return Set( pValue );
- }
- BOOL CDrawCliProperty::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 = CountPrefixedStringA( (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 = CountPrefixedStringT( (LPTSTR)pValueOrig );
- pCur = (LPBYTE)pValue;
- break;
- case VT_LPWSTR: // UNICODE string
- pValueOrig = pValue;
- pValue = CountPrefixedStringW( (LPWSTR)pValueOrig );
- pCur = (LPBYTE)pValue;
- break;
- }
- }
- // 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;
- case VT_VARIANT: // VARIANT*
- break;
- default:
- if (pValueOrig)
- free( pValue );
- return FALSE;
- }
- // Add 'cb' to cbItem before seeking...
- //
- // Seek to the next item
- pCur += cbItem;
- cbValue += cbItem;
- }
- if (NULL == AllocValue(cbValue))
- {
- TRACE0("CDrawCliProperty::AllocValue failed");
- return FALSE;
- }
- memcpy( m_pValue, pValue, (int)cbValue );
- if (pValueOrig)
- free( pValue );
- return TRUE;
- }
- LPVOID CDrawCliProperty::Get( void )
- { return Get( (DWORD*)NULL ); }
- LPVOID CDrawCliProperty::Get( DWORD* pcb )
- {
- DWORD cb = 0;
- 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;
- case VT_VARIANT: // VARIANT*
- break;
- default:
- return NULL;
- }
- if (pcb != NULL)
- *pcb = cb;
- return p;
- }
- DWORD CDrawCliProperty::GetType( void )
- { return m_dwType; }
- void CDrawCliProperty::SetType( DWORD dwType )
- { m_dwType = dwType; }
- DWORD CDrawCliProperty::GetID( void )
- { return m_dwPropID; }
- void CDrawCliProperty::SetID( DWORD dwPropID )
- { m_dwPropID = dwPropID; }
- LPVOID CDrawCliProperty::GetRawValue( void )
- { return m_pValue; }
- BOOL CDrawCliProperty::WriteToStream( IStream* pIStream )
- {
- ULONG cb = 0;
- 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 = ConvertStringProp(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;
- case VT_VARIANT: // VARIANT*
- 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 CDrawCliProperty::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;
- case VT_VARIANT: // VARIANT*
- break;
- default:
- pIStrItem->Release();
- return FALSE;
- }
- // Add 'cb' to cbItem before seeking...
- //
- // 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 = ConvertStringProp(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 CDrawCliProperty::AllocValue(ULONG cb)
- {
- return m_pValue = malloc((int)cb);
- }
- void CDrawCliProperty::FreeValue()
- {
- if (m_pValue != NULL)
- {
- free(m_pValue);
- m_pValue = NULL;
- }
- }
- /////////////////////////////////////////////////////////////////////////////
- // Implementation of the CDrawCliPropertySection Class
- CDrawCliPropertySection::CDrawCliPropertySection( void )
- {
- m_FormatID = GUID_NULL;
- m_SH.cbSection = 0;
- m_SH.cProperties = 0;
- }
- CDrawCliPropertySection::CDrawCliPropertySection( CLSID FormatID )
- {
- m_FormatID = FormatID;
- m_SH.cbSection = 0;
- m_SH.cProperties = 0;
- }
- CDrawCliPropertySection::~CDrawCliPropertySection( void )
- {
- RemoveAll();
- return;
- }
- CLSID CDrawCliPropertySection::GetFormatID( void )
- { return m_FormatID; }
- void CDrawCliPropertySection::SetFormatID( CLSID FormatID )
- { m_FormatID = FormatID; }
- BOOL CDrawCliPropertySection::Set( DWORD dwPropID, LPVOID pValue, DWORD dwType )
- {
- CDrawCliProperty* pProp = GetProperty( dwPropID );
- if (pProp == NULL)
- {
- if ((pProp = new CDrawCliProperty( dwPropID, pValue, dwType )) != NULL)
- AddProperty( pProp );
- return (pProp != NULL);
- }
- pProp->Set( dwPropID, pValue, dwType );
- return TRUE;
- }
- BOOL CDrawCliPropertySection::Set( DWORD dwPropID, LPVOID pValue )
- {
- // Since no dwType was specified, the property is assumed
- // to exist. Fail if it does not.
- CDrawCliProperty* pProp = GetProperty( dwPropID );
- if (pProp != NULL && pProp->m_dwType)
- {
- pProp->Set( dwPropID, pValue, pProp->m_dwType );
- return TRUE;
- }
- else
- return FALSE;
- }
- LPVOID CDrawCliPropertySection::Get( DWORD dwPropID )
- { return Get( dwPropID, (DWORD*)NULL ); }
- LPVOID CDrawCliPropertySection::Get( DWORD dwPropID, DWORD* pcb )
- {
- CDrawCliProperty* pProp = GetProperty( dwPropID );
- if (pProp)
- {
- #if (defined _DEBUG)
- pProp->AssertValid();
- #endif
- return pProp->Get( pcb );
- }
- else
- return NULL;
- }
- void CDrawCliPropertySection::Remove( DWORD dwID )
- {
- POSITION pos = m_PropList.GetHeadPosition();
- CDrawCliProperty* pProp;
- while( pos != NULL )
- {
- POSITION posRemove = pos;
- pProp = (CDrawCliProperty*)m_PropList.GetNext( pos );
- if (pProp->m_dwPropID == dwID)
- {
- m_PropList.RemoveAt( posRemove );
- delete pProp;
- m_SH.cProperties--;
- return;
- }
- }
- }
- void CDrawCliPropertySection::RemoveAll( )
- {
- POSITION pos = m_PropList.GetHeadPosition();
- while( pos != NULL )
- delete (CDrawCliProperty*)m_PropList.GetNext( pos );
- m_PropList.RemoveAll();
- m_SH.cProperties = 0;
- }
- CDrawCliProperty* CDrawCliPropertySection::GetProperty( DWORD dwPropID )
- {
- POSITION pos = m_PropList.GetHeadPosition();
- #if (defined _DEBUG)
- m_PropList.AssertValid();
- #endif
- CDrawCliProperty* pProp;
- while (pos != NULL)
- {
- pProp= (CDrawCliProperty*)m_PropList.GetNext( pos );
- #if (defined _DEBUG)
- pProp->AssertValid();
- #endif
- if (pProp->m_dwPropID == dwPropID)
- return pProp;
- }
- return NULL;
- }
- void CDrawCliPropertySection::AddProperty( CDrawCliProperty* pProp )
- {
- m_PropList.AddTail( pProp );
- m_SH.cProperties++;
- }
- DWORD CDrawCliPropertySection::GetSize( void )
- { return m_SH.cbSection; }
- DWORD CDrawCliPropertySection::GetCount( void )
- { return DWORD( m_PropList.GetCount() ); }
- CObList* CDrawCliPropertySection::GetList( void )
- { return &m_PropList; }
- BOOL CDrawCliPropertySection::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 = DWORD( 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.
- CDrawCliProperty* pProp = NULL;
- POSITION pos = m_PropList.GetHeadPosition();
- while( pos != NULL )
- {
- // Get next element (note cast)
- pProp = (CDrawCliProperty*)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' failedn");
- 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 CDrawCliPropertySection::ReadFromStream( IStream* pIStream,
- LARGE_INTEGER liPropSet )
- {
- ULONG cb;
- PROPERTYIDOFFSET pido;
- ULONG cProperties;
- LPSTREAM pIStrPIDO;
- ULARGE_INTEGER ulSectionStart;
- LARGE_INTEGER li;
- CDrawCliProperty* 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 CDrawCliProperty( pido.propertyID, NULL, 0 );
- pProp->ReadFromStream( pIStream );
- #if (defined _DEBUG)
- pProp->AssertValid();
- #endif
- m_PropList.AddTail( pProp );
- #if (defined _DEBUG)
- m_PropList.AssertValid();
- #endif
- }
- else
- {
- ReadNameDictFromStream( pIStream );
- }
- }
- pIStrPIDO->Release();
- return TRUE;
- }
- BOOL CDrawCliPropertySection::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 CDrawCliPropertySection::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 CDrawCliPropertySection::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;
- }
- static BOOL WriteNameDictEntry(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 CDrawCliPropertySection::WriteNameDictToStream( IStream* pIStream )
- {
- ULONG cb;
- // Write dictionary header (count).
- ULONG cProperties = ULONG( 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 (! WriteNameDictEntry(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 (! WriteNameDictEntry(pIStream, (DWORD)pvID, strName))
- return FALSE;
- }
- return TRUE;
- }
- BOOL CDrawCliPropertySection::SetSectionName( LPCTSTR pszName )
- {
- m_strSectionName = pszName;
- return TRUE;
- }
- LPCTSTR CDrawCliPropertySection::GetSectionName( void )
- {
- return (LPCTSTR)m_strSectionName;
- }
- /////////////////////////////////////////////////////////////////////////////
- // Implementation of the CDrawCliPropertySet class
- CDrawCliPropertySet::CDrawCliPropertySet( void )
- {
- 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;
- }
- CDrawCliPropertySet::CDrawCliPropertySet( 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;
- }
- CDrawCliPropertySet::~CDrawCliPropertySet()
- { RemoveAll(); }
- BOOL CDrawCliPropertySet::Set( CLSID FormatID, DWORD dwPropID, LPVOID pValue, DWORD dwType )
- {
- CDrawCliPropertySection* pSect = GetSection( FormatID );
- if (pSect == NULL)
- {
- if ((pSect = new CDrawCliPropertySection( FormatID )) != NULL)
- AddSection( pSect );
- }
- pSect->Set( dwPropID, pValue, dwType );
- return TRUE;
- }
- BOOL CDrawCliPropertySet::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.
- CDrawCliPropertySection* pSect = GetSection( FormatID );
- if (pSect != NULL)
- return pSect->Set( dwPropID, pValue );
- else
- return FALSE;
- }
- LPVOID CDrawCliPropertySet::Get( CLSID FormatID, DWORD dwPropID, DWORD* pcb )
- {
- CDrawCliPropertySection* pSect = GetSection( FormatID );
- if (pSect)
- return pSect->Get( dwPropID, pcb );
- else
- return NULL;
- }
- LPVOID CDrawCliPropertySet::Get( CLSID FormatID, DWORD dwPropID )
- { return Get( FormatID, dwPropID, (DWORD*)NULL ); }
- void CDrawCliPropertySet::Remove( CLSID FormatID, DWORD dwPropID )
- {
- CDrawCliPropertySection* pSect = GetSection( FormatID );
- if (pSect)
- pSect->Remove( dwPropID );
- }
- void CDrawCliPropertySet::Remove( CLSID FormatID )
- {
- CDrawCliPropertySection* pSect;
- POSITION posRemove = m_SectionList.GetHeadPosition();
- POSITION pos = posRemove;
- while( posRemove != NULL )
- {
- pSect = (CDrawCliPropertySection*)m_SectionList.GetNext( pos );
- if (IsEqualCLSID( pSect->m_FormatID, FormatID ))
- {
- m_SectionList.RemoveAt( posRemove );
- delete pSect;
- m_PH.cSections--;
- return;
- }
- posRemove = pos;
- }
- }
- void CDrawCliPropertySet::RemoveAll( )
- {
- POSITION pos = m_SectionList.GetHeadPosition();
- while( pos != NULL )
- {
- delete (CDrawCliPropertySection*)m_SectionList.GetNext( pos );
- }
- m_SectionList.RemoveAll();
- m_PH.cSections = 0;
- }
- CDrawCliPropertySection* CDrawCliPropertySet::GetSection( CLSID FormatID )
- {
- POSITION pos = m_SectionList.GetHeadPosition();
- CDrawCliPropertySection* pSect;
- while (pos != NULL)
- {
- pSect = (CDrawCliPropertySection*)m_SectionList.GetNext( pos );
- if (IsEqualCLSID( pSect->m_FormatID, FormatID ))
- return pSect;
- }
- return NULL;
- }
- CDrawCliPropertySection* CDrawCliPropertySet::AddSection( CLSID FormatID )
- {
- CDrawCliPropertySection* pSect = GetSection( FormatID );
- if (pSect)
- return pSect;
- pSect = new CDrawCliPropertySection( FormatID ) ;
- if (pSect)
- AddSection( pSect );
- return pSect;
- }
- void CDrawCliPropertySet::AddSection( CDrawCliPropertySection* pSect )
- {
- m_SectionList.AddTail( pSect );
- m_PH.cSections++;
- }
- CDrawCliProperty* CDrawCliPropertySet::GetProperty( CLSID FormatID, DWORD dwPropID )
- {
- CDrawCliPropertySection* pSect = GetSection( FormatID );
- if (pSect)
- return pSect->GetProperty( dwPropID );
- else
- return NULL;
- }
- void CDrawCliPropertySet::AddProperty( CLSID FormatID, CDrawCliProperty* pProp )
- {
- CDrawCliPropertySection* pSect = GetSection( FormatID );
- if (pSect)
- pSect->AddProperty( pProp );
- }
- WORD CDrawCliPropertySet::GetByteOrder( void )
- { return m_PH.wByteOrder; }
- WORD CDrawCliPropertySet::GetFormatVersion( void )
- { return m_PH.wFormat; }
- void CDrawCliPropertySet::SetFormatVersion( WORD wFmtVersion )
- { m_PH.wFormat = wFmtVersion; }
- DWORD CDrawCliPropertySet::GetOSVersion( void )
- { return m_PH.dwOSVer; }
- void CDrawCliPropertySet::SetOSVersion( DWORD dwOSVer )
- { m_PH.dwOSVer = dwOSVer; }
- CLSID CDrawCliPropertySet::GetClassID( void )
- { return m_PH.clsID; }
- void CDrawCliPropertySet::SetClassID( CLSID clsID )
- { m_PH.clsID = clsID; }
- DWORD CDrawCliPropertySet::GetCount( void )
- { return WORD( m_SectionList.GetCount() ); }
- CObList* CDrawCliPropertySet::GetList( void )
- { return &m_SectionList; }
- BOOL CDrawCliPropertySet::WriteToStream( IStream* pIStream )
- {
- LPSTREAM pIStrFIDO;
- FORMATIDOFFSET fido;
- ULONG cb;
- ULARGE_INTEGER ulSeek;
- LARGE_INTEGER li;
- // Write the Property List Header
- m_PH.cSections = DWORD( 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.
- CDrawCliPropertySection* pSect = NULL;
- POSITION pos = m_SectionList.GetHeadPosition();
- while( pos != NULL )
- {
- // Get next element (note cast)
- pSect = (CDrawCliPropertySection*)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 CDrawCliPropertySet::ReadFromStream( IStream* pIStream )
- {
- ULONG cb;
- FORMATIDOFFSET fido;
- ULONG cSections;
- LPSTREAM pIStrFIDO;
- CDrawCliPropertySection* 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 CDrawCliPropertySection;
- 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