📄 propset.cpp
字号:
// This is a part of the Microsoft Foundation Classes C++ library.
// Copyright (C) 1992-1997 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"
#if !defined(_MAC)
#include <malloc.h>
#include <ole2.h>
#include <oleauto.h>
#include "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 = (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;
}
#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 = 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( void )
{
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 = 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("CProperty::AllocValue failed");
return FALSE;
}
memcpy( m_pValue, pValue, (int)cbValue );
if (pValueOrig)
free( pValue );
return TRUE;
}
LPVOID CProperty::Get( void )
{ 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;
case VT_VARIANT: // VARIANT*
break;
default:
return NULL;
}
if (pcb != NULL)
*pcb = cb;
return p;
}
DWORD CProperty::GetType( void )
{ return m_dwType; }
void CProperty::SetType( DWORD dwType )
{ m_dwType = dwType; }
DWORD CProperty::GetID( void )
{ return m_dwPropID; }
void CProperty::SetID( DWORD dwPropID )
{ m_dwPropID = dwPropID; }
LPVOID CProperty::GetRawValue( void )
{ 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 = 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -