windows-nt/Source/XPSP1/NT/sdktools/trace/logman/win2000/propbag.cpp
2020-09-26 16:20:57 +08:00

436 lines
12 KiB
C++

/*++
Copyright (C) 1999-2000 Microsoft Corporation
Module Name:
PropBag.cpp
Abstract:
Implementation of the private IPropertyBag interface used by
the Performance Log Manager.
--*/
#include "logman.h"
#include "stdafx.h"
#include "unihelpr.h"
#include "strings.h"
#include "propbag.h"
#define MAX_GUID_STRING_LENGTH 39
/*
* CPropertyBag::CPropertyBag
*
* Purpose:
* Constructor.
*
* Return Value:
*/
CPropertyBag::CPropertyBag ( void )
: m_pszData ( NULL ),
m_dwCurrentDataLength ( 0 ),
m_plistData ( NULL )
{
return;
}
/*
* CPropertyBag::~CPropertyBag
*
* Purpose:
* Destructor.
*
* Return Value:
*/
CPropertyBag::~CPropertyBag ( void )
{
if ( NULL != m_pszData ) {
delete m_pszData;
}
while ( NULL != m_plistData ) {
PPARAM_DATA pData = DataListRemoveHead();
VariantClear ( &pData->vValue );
delete pData;
}
return;
}
/*
* CPropertyBag::Read
*
* Purpose:
*
* This function is called to read a property from the property bag.
*
* Parameters:
* pszPropName Pointer to name of property to be read
* pVar Pointer to the VARIANT to receive the property value
* pIErrorLog Pointer to the caller's error log
*/
HRESULT
CPropertyBag::Read (
LPCWSTR pszPropName, //Pointer to the property to be read
VARIANT* pVar ) //Pointer to the VARIANT to receive the
//property value
{
HRESULT hr = NOERROR;
PPARAM_DATA pData = NULL;
assert ( NULL != pszPropName );
assert ( NULL != pVar );
if ( NULL == pszPropName )
return ResultFromScode ( E_POINTER );
if ( NULL == pVar )
return ResultFromScode ( E_POINTER );
//Read the specified data into the passed variant.
pData = FindProperty ( pszPropName );
if ( NULL != pData ) {
hr = VariantChangeType ( pVar, &pData->vValue, NULL, pVar->vt );
} else {
hr = E_INVALIDARG;
}
return hr;
}
/*
* CPropertyBag::Write
*
* Purpose:
*
* This function is called to write a property to the property bag.
*
* Parameters:
* pszPropName Pointer to name of property to be written
* pVar Pointer to the VARIANT containing the property value
*/
HRESULT
CPropertyBag::Write (
LPCWSTR pszPropName, //Pointer to the property to be written
VARIANT* pVar ) //Pointer to the VARIANT containing the
//property value and type
{
HRESULT hr = S_OK;
VARIANT vValueBstr;
DWORD dwNameLength;
DWORD dwDataLength;
static DWORD dwDelimiterLength = 0;
static DWORD dwParamNameLength = 0;
static DWORD dwEolTagLength = 0;
static DWORD dwValueTagLength = 0;
HRESULT hrConvert;
LPWSTR pszNextField = m_pszData;
DWORD dwCurrentDataUsedLength;
assert ( NULL != pszPropName );
assert ( NULL != pVar );
if ( NULL == pszPropName )
return ResultFromScode ( E_POINTER );
if ( NULL == pVar )
return ResultFromScode ( E_POINTER );
USES_CONVERSION
VariantInit ( &vValueBstr );
hrConvert = VariantChangeType ( &vValueBstr, pVar, NULL, VT_BSTR );
// All length values calculated number of WCHARs.
if ( 0 == dwDelimiterLength ) {
// Initialize static values
dwParamNameLength = lstrlenW (cwszHtmlParamTag);
dwValueTagLength = lstrlenW ( cwszHtmlValueTag );
dwEolTagLength = lstrlenW ( cwszHtmlValueEolTag );
dwDelimiterLength = dwParamNameLength + dwValueTagLength + dwEolTagLength;
}
if ( SUCCEEDED ( hr ) ) {
hr = E_NOTIMPL;
// Todo: Implement
dwNameLength = lstrlenW ( pszPropName );
dwDataLength = lstrlenW ( vValueBstr.bstrVal );
dwCurrentDataUsedLength = lstrlenW ( m_pszData );
// Add 1 to size calculation for NULL buffer terminator.
if ( m_dwCurrentDataLength
< dwCurrentDataUsedLength + dwNameLength + dwDataLength + dwDelimiterLength + 1 ) {
LPWSTR pszNewBuffer;
if ( 0 == m_dwCurrentDataLength ) {
m_dwCurrentDataLength += eDefaultBufferLength;
} else {
m_dwCurrentDataLength *= 2;
}
pszNewBuffer = new WCHAR[m_dwCurrentDataLength];
if ( NULL == pszNewBuffer )
return E_OUTOFMEMORY;
if ( NULL != m_pszData ) {
memcpy ( pszNewBuffer, m_pszData, dwCurrentDataUsedLength * sizeof(WCHAR) );
delete m_pszData;
}
m_pszData = pszNewBuffer;
}
// Build the new string and add it to the current data.
pszNextField = m_pszData + dwCurrentDataUsedLength;
memcpy ( pszNextField, cwszHtmlParamTag, dwParamNameLength * sizeof(WCHAR) );
pszNextField += dwParamNameLength;
memcpy ( pszNextField, pszPropName, dwNameLength * sizeof(WCHAR) );
pszNextField += dwNameLength;
memcpy ( pszNextField, cwszHtmlValueTag, dwValueTagLength * sizeof(WCHAR) );
pszNextField += dwValueTagLength;
memcpy ( pszNextField, W2T(vValueBstr.bstrVal), dwDataLength * sizeof(WCHAR) );
pszNextField += dwDataLength;
memcpy ( pszNextField, cwszHtmlValueEolTag, dwEolTagLength * sizeof(WCHAR) );
pszNextField += dwEolTagLength;
lstrcpyW ( pszNextField, cwszNull );
}
return hr;
}
/*
* CPropertyBag::GetData
*
* Purpose:
* Return pointer to the data buffer.
*
* Return Value:
* Pointer to the data buffer.
*/
LPWSTR
CPropertyBag::GetData ( void )
{
return m_pszData;
}
/*
* CPropertyBag::LoadData
*
* Purpose:
* Load data from the supplied buffer into internal data structures.
*
* Return Value:
* Status.
*/
DWORD
CPropertyBag::LoadData (
LPCTSTR pszData,
LPTSTR& rpszNextData )
{
DWORD dwStatus = ERROR_SUCCESS;
LPWSTR szNextEoo = NULL;
BOOL bUnicode = TRUE;
USES_CONVERSION
assert ( NULL != pszData );
rpszNextData = NULL;
if ( NULL != pszData ) {
LPWSTR pszDataW = NULL;
LPWSTR pszDataAllocW = NULL;
LPWSTR pszCurrentPos;
LPWSTR pszGuid;
// Unicode search: Begin the search after the first instance
// of the System Monitor class id.
pszGuid = wcstok ( const_cast<LPWSTR>(cwszHtmlObjectClassId), L"{} " );
pszCurrentPos = wcsstr( (LPWSTR) pszData, pszGuid );
// Handle wide vs ansi.
if ( NULL != pszCurrentPos ) {
pszDataW = (LPWSTR)pszData;
bUnicode = TRUE;
} else {
// Check for ANSI version:
LPSTR pszGuidA = NULL;
LPSTR pszCurrentPosA = NULL;
LPSTR pszDataA = (CHAR*) pszData;
pszGuidA = W2A( pszGuid );
pszCurrentPosA = strstr ( pszDataA, pszGuidA );
if ( NULL != pszCurrentPosA ) {
pszDataAllocW = A2W ( pszDataA );
pszDataW = pszDataAllocW;
bUnicode = FALSE;
pszCurrentPos = wcsstr(pszDataW, pszGuid );
}
}
if ( NULL != pszCurrentPos ) {
LPWSTR szEoo;
// End of object is the first object footer tag after the first sysmon
// class id found. If multiple objects in the data block, only parse the first sysmon.
szEoo = wcsstr(pszCurrentPos, cwszHtmlObjectFooter );
if ( NULL != szEoo ) {
// Find first parameter tag.
pszCurrentPos = wcsstr(pszCurrentPos, cwszHtmlParamSearchTag );
while ( NULL != pszCurrentPos && pszCurrentPos < szEoo ) {
LPWSTR pszNextPos;
INT lStrLength;
PPARAM_DATA pParamData;
LPWSTR szTemp;
// Store parameter/property name.
// Find one past first quote.
pszCurrentPos = wcsstr(pszCurrentPos, cwszQuote ) + 1;
// The param name is between first and second quote.
pszNextPos = wcsstr(pszCurrentPos, cwszQuote );
lStrLength = ( (INT)((UINT_PTR)pszNextPos - (UINT_PTR)pszCurrentPos) ) / sizeof ( WCHAR ) ;
pParamData = new PARAM_DATA;
if ( NULL != pParamData ) {
pParamData->pNextParam = NULL;
VariantInit ( &pParamData->vValue );
pParamData->vValue.vt = VT_BSTR;
} else {
dwStatus = ERROR_OUTOFMEMORY;
break;
}
wcsncpy ( pParamData->pszPropertyName, pszCurrentPos, lStrLength );
pParamData->pszPropertyName[lStrLength] = TEXT ('\0');
// Find value tag and store parameter/property value.
// Find value tag
pszCurrentPos = wcsstr ( pszCurrentPos, cwszHtmlValueSearchTag );
// Find one past first quote
pszCurrentPos = wcsstr ( pszCurrentPos, cwszQuote ) + 1;
// The value is between first and second quote.
pszNextPos = wcsstr ( pszCurrentPos, cwszQuote );
lStrLength = ( (INT)((UINT_PTR)pszNextPos - (UINT_PTR)pszCurrentPos) ) / sizeof ( WCHAR );
szTemp = new WCHAR[lStrLength+1];
if (szTemp != NULL) {
wcsncpy ( szTemp, pszCurrentPos, lStrLength );
szTemp[lStrLength] = TEXT('\0');
pParamData->vValue.bstrVal =
SysAllocString ( szTemp );
delete szTemp;
DataListAddHead ( pParamData );
// Find next parameter/property tag.
pszCurrentPos = wcsstr(pszCurrentPos, cwszHtmlParamSearchTag );
} else {
delete pParamData;
dwStatus = ERROR_OUTOFMEMORY;
break;
}
} // While parameter tags exist for a single object.
// Search for next object
// Start after current object footer
szEoo += lstrlenW ( cwszHtmlObjectFooter );
szNextEoo = wcsstr(szEoo, cwszHtmlObjectFooter);
// Successful. Return pointer to end of the current object, or NULL if all
// objects have been processed.
if ( NULL != szNextEoo ) {
if ( bUnicode ) {
rpszNextData = (LPTSTR)szEoo;
} else {
INT lStrLength;
lStrLength = ( (INT)((UINT_PTR)szEoo - (UINT_PTR)pszDataW) ) / sizeof ( WCHAR ) ;
// Add string length to original buffer pointer
rpszNextData = (LPTSTR)((LPSTR)pszData + lStrLength);
}
}
} else {
dwStatus = LOGMAN_NO_SYSMON_OBJECT;
}
} else {
dwStatus = LOGMAN_NO_SYSMON_OBJECT;
}
} else {
dwStatus = ERROR_INVALID_PARAMETER;
}
return dwStatus;
}
void
CPropertyBag::DataListAddHead ( PPARAM_DATA pData )
{
assert ( NULL != pData );
pData->pNextParam = m_plistData;
m_plistData = pData;
return;
}
CPropertyBag::PPARAM_DATA
CPropertyBag::DataListRemoveHead ( )
{
PPARAM_DATA pReturnData;
pReturnData = m_plistData;
if ( NULL != m_plistData )
m_plistData = m_plistData->pNextParam;
return pReturnData;
}
CPropertyBag::PPARAM_DATA
CPropertyBag::FindProperty ( LPCWSTR pszPropName )
{
PPARAM_DATA pReturnData;
pReturnData = m_plistData;
while ( NULL != pReturnData ) {
if ( 0 == lstrcmpiW ( pszPropName, pReturnData->pszPropertyName ) )
break;
pReturnData = pReturnData->pNextParam;
}
return pReturnData;
}