|
|
//=--------------------------------------------------------------------------=
// wbclsser.h
//=--------------------------------------------------------------------------=
// Copyright 1995 Microsoft Corporation. All Rights Reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//=--------------------------------------------------------------------------=
//
// API for WebClass Designer Serialization
//
// adolfoc 7/29/97
// Renamed WCS_NODE_TYPE_URL to WCS_NODE_TYPE_PAGE,
// added WCS_NODE_TYPE_URL with value 3,
// changed URL tag to Page
//
#ifndef _WBCLSSER_H_
#include "csfdebug.h"
#include "convman_tlb.h"
// Designer State Flags
#define RUNSTATE_COMPILED 0x00000000
#define RUNSTATE_F5 0x00000001
#define DISPID_OBJECT_PROPERTY_START 0x00000500
// Serialization Versions
// 0.0 Beta1
// 0.1 PreBeta2 - WebItems must be sorted on load
// 0.2 PreBeta2 - Added Optimize member var to WebItems
// 0.3 PreBeta2 - WebEvents are now sorted on load too
// 0.4 PreBeta2 -
// 0.5 PreBeta2 - Tagattributes added anonymous tag number
// 0.6 <skipped>
// 0.7 PreRC1 - Added URLInName to design time state
// 0.8 PreRC1 - Fixed bug in WebItem and event sorting algorithm. Now we need
// to fixup old projects with bug whose WebItems and events are not
// serialized in alphabetical order.
// structure of WebClass on disk
const DWORD dwExpectedVerMajor = 0; const DWORD dwExpectedVerMinor = 8;
class CRunWebItemState; class CRunEventState;
class CStateBase { public: CStateBase() {} ~CStateBase() {}
public: //////////////////////////////////////////////////////////////////////
//
// inline ReadStrings(IStream *pStream, ULONG acbStrings[],
// BSTR *apbstrStrings[], int cStrings)
//
//
//
//////////////////////////////////////////////////////////////////////
inline ReadStrings(IStream *pStream, ULONG acbStrings[], BSTR *apbstrStrings[], int cStrings) { HRESULT hr = S_OK; ULONG cbRead = 0; char *pszReadBuf = NULL; ULONG cbLongest = 0; int i = 0;
while (i < cStrings) { if (acbStrings[i] > cbLongest) { cbLongest = acbStrings[i]; } i++; } if (0 != cbLongest) { pszReadBuf = new char[cbLongest + sizeof(WCHAR)]; CSF_CHECK(NULL != pszReadBuf, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS); } i = 0; while (i < cStrings) { if (0 == acbStrings[i]) { *(apbstrStrings[i]) = NULL; } else { hr = pStream->Read(pszReadBuf, acbStrings[i], &cbRead); CSF_CHECK(hr == S_OK, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(cbRead == acbStrings[i], STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS); *((WCHAR *)&pszReadBuf[acbStrings[i]]) = L'\0';
*(apbstrStrings[i]) = ::SysAllocString((WCHAR *)pszReadBuf); CSF_CHECK(*(apbstrStrings[i]) != NULL, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS); } i++; }
CLEANUP: if (NULL != pszReadBuf) { delete [] pszReadBuf; } return hr; }
//////////////////////////////////////////////////////////////////////
//
// inline WriteStrings(IStream *pStream, ULONG acbStrings[],
// BSTR *apbstrStrings[], int cStrings)
//
//
//////////////////////////////////////////////////////////////////////
inline WriteStrings(IStream *pStream, ULONG acbStrings[], BSTR abstrStrings[], int cStrings) { HRESULT hr = S_OK; ULONG cbWritten = 0; int i = 0;
while (i < cStrings) { if (NULL != abstrStrings[i]) { hr = pStream->Write(abstrStrings[i], acbStrings[i], &cbWritten); CSF_CHECK(hr == S_OK, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(cbWritten == acbStrings[i], STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS); } i++; }
CLEANUP: return hr; }
};
class CRunWebClassState : public CStateBase { public: CRunWebClassState() { m_dwVerMajor = dwExpectedVerMajor; m_dwVerMinor = dwExpectedVerMinor; m_bstrName = NULL; // Kill
m_bstrProgID = NULL; // Runtime only
m_StateManagementType = wcNoState; m_bstrASPName = NULL; m_bstrAppendedParams = NULL; m_bstrStartupItem = NULL; m_DIID_WebClass = GUID_NULL; m_DIID_WebClassEvents = GUID_NULL; m_dwTICookie = 0; m_dwFlags = 0; m_rgWebItemsState = 0; m_dwWebItemCount = 0; }
~CRunWebClassState() { if(m_bstrName != NULL) ::SysFreeString(m_bstrName);
if(m_bstrProgID != NULL) ::SysFreeString(m_bstrProgID);
if(m_bstrASPName != NULL) ::SysFreeString(m_bstrASPName);
if(m_bstrAppendedParams != NULL) ::SysFreeString(m_bstrAppendedParams);
if(m_bstrStartupItem != NULL) ::SysFreeString(m_bstrStartupItem); }
public: DWORD m_dwVerMajor; // major version number
DWORD m_dwVerMinor; // minor version number
BSTR m_bstrName; // WebClass name
BSTR m_bstrProgID; // WebClass progid
StateManagement m_StateManagementType; // state management type
BSTR m_bstrASPName; // name of ASP file
IID m_DIID_WebClass; // IID of WebClass' main IDispatch
IID m_DIID_WebClassEvents; // IID of WebClass' events IDispatch
DWORD m_dwTICookie; // typeinfo cookie
BSTR m_bstrAppendedParams; // URL state
BSTR m_bstrStartupItem; // f5 statup Item
DWORD m_dwFlags; CRunWebItemState* m_rgWebItemsState; DWORD m_dwWebItemCount; // runtime node types
public: HRESULT Load(LPSTREAM pStm) { HRESULT hr = S_OK; ULONG cbRead = 0; ULONG acbStrings[5]; BSTR *apbstrStrings[5];
// read structure from stream
hr = pStm->Read(this, sizeof(CRunWebClassState), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(CRunWebClassState) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
// TODO: need error codes for version incompatibility, handle backlevel formats etc.
// CSF_CHECK(dwExpectedVerMajor == m_dwVerMajor, STG_E_OLDFORMAT, CSF_TRACE_EXTERNAL_ERRORS);
// CSF_CHECK(dwExpectedVerMinor == m_dwVerMinor, STG_E_OLDFORMAT, CSF_TRACE_EXTERNAL_ERRORS);
// read string lengths from stream
hr = pStm->Read(acbStrings, sizeof(acbStrings), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(acbStrings) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
// set up array of string pointer addresses
apbstrStrings[0] = &(m_bstrName); apbstrStrings[1] = &(m_bstrProgID); apbstrStrings[2] = &(m_bstrASPName); apbstrStrings[3] = &(m_bstrAppendedParams); apbstrStrings[4] = &(m_bstrStartupItem);
// read strings from stream
hr = ReadStrings(pStm, acbStrings, apbstrStrings, (sizeof(acbStrings) / sizeof(acbStrings[0])) );
CLEANUP: return hr; }
HRESULT Save(LPSTREAM pStm) { HRESULT hr = S_OK; ULONG cbWritten = 0; ULONG acbStrings[5]; ::ZeroMemory(acbStrings, sizeof(acbStrings)); BSTR abstrStrings[5];
// write WebClass structure to stream
hr = pStm->Write(this, sizeof(CRunWebClassState), &cbWritten); CSF_CHECK(hr == S_OK, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(cbWritten == sizeof(CRunWebClassState), STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
// get lengths of strings and write them to stream
if (NULL != m_bstrName) { acbStrings[0] = ::SysStringByteLen(m_bstrName); } if (NULL != m_bstrProgID) { acbStrings[1] = ::SysStringByteLen(m_bstrProgID); } if (NULL != m_bstrASPName) { acbStrings[2] = ::SysStringByteLen(m_bstrASPName); } if (NULL != m_bstrAppendedParams) { acbStrings[3] = ::SysStringByteLen(m_bstrAppendedParams); } if (NULL != m_bstrStartupItem) { acbStrings[4] = ::SysStringByteLen(m_bstrStartupItem); }
hr = pStm->Write(acbStrings, sizeof(acbStrings), &cbWritten); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(cbWritten == sizeof(acbStrings), STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
// set up array of pointers to strings to be written to stream
abstrStrings[0] = m_bstrName; abstrStrings[1] = m_bstrProgID; abstrStrings[2] = m_bstrASPName; abstrStrings[3] = m_bstrAppendedParams; abstrStrings[4] = m_bstrStartupItem;
// write strings to stream
hr = WriteStrings(pStm, acbStrings, abstrStrings, (sizeof(acbStrings) / sizeof(acbStrings[0])) );
CLEANUP: return hr; } };
typedef struct tagWCS_NODEHEADER { BYTE bType; // node type: nested WebClass, URL, events
} WCS_NODEHEADER;
// WCS_DTNODE_TYPE_URL_BOUND_TAG is a special case because WCS_DTNODE.dispid
// contains the dispid of the referenced URL and WCS_DTNODE.bstrName contains
// the name of the referenced URL.
// structure of node on disk at runtime
class CRunWebItemState : protected CStateBase { public: CRunWebItemState() { m_dwVerMajor = dwExpectedVerMajor; m_dwVerMinor = dwExpectedVerMinor; m_dispid = -1; m_bstrName = NULL; m_bstrTemplate = NULL; m_bstrToken = NULL; m_IID_Events = GUID_NULL; m_fParseReplacements = FALSE; m_bstrAppendedParams = NULL; m_fUsesRelativePath = FALSE; m_dwTokenInfo = 0; m_dwReserved2 = 0; m_dwReserved3 = 0; m_rgEvents = 0; m_dwEventCount = 0; }
~CRunWebItemState() { if(m_bstrName != NULL) ::SysFreeString(m_bstrName);
if(m_bstrTemplate != NULL) ::SysFreeString(m_bstrTemplate);
if(m_bstrToken != NULL) ::SysFreeString(m_bstrToken);
if(m_bstrAppendedParams != NULL) ::SysFreeString(m_bstrAppendedParams); }
public: HRESULT Load(LPSTREAM pStm) { HRESULT hr = S_OK; ULONG cbRead = 0; ULONG acbStrings[4]; BSTR *apbstrStrings[4]; int cStrings = 4;
// read structure from stream
hr = pStm->Read(this, sizeof(CRunWebItemState), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(CRunWebItemState) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
// m_pvData = NULL; // don't take junk pointer value from stream
// set up array of string pointer addresses according to node type
apbstrStrings[0] = &m_bstrName; apbstrStrings[1] = &m_bstrTemplate; apbstrStrings[2] = &m_bstrToken; apbstrStrings[3] = &m_bstrAppendedParams;
// read string lengths from stream
hr = pStm->Read(acbStrings, sizeof(acbStrings), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(acbStrings) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
// read strings from stream
hr = ReadStrings(pStm, acbStrings, apbstrStrings, cStrings); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
CLEANUP: return hr; }
HRESULT Save ( LPSTREAM pStm ) { HRESULT hr = S_OK; ULONG cbWritten = 0; ULONG acbStrings[4]; ::ZeroMemory(acbStrings, sizeof(acbStrings)); BSTR abstrStrings[4]; int cStrings = 4;
// write node structure to stream
hr = pStm->Write(this, sizeof(CRunWebItemState), &cbWritten); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(CRunWebItemState) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
// set up array of strings to be written to stream and
// determine how many there will be
abstrStrings[0] = m_bstrName; if (NULL != m_bstrName) { acbStrings[0] = ::SysStringByteLen(m_bstrName); }
abstrStrings[1] = m_bstrTemplate; if (NULL != m_bstrTemplate) { acbStrings[1] = ::SysStringByteLen(m_bstrTemplate); } abstrStrings[2] = m_bstrToken; if (NULL != m_bstrToken) { acbStrings[2] = ::SysStringByteLen(m_bstrToken); } abstrStrings[3] = m_bstrAppendedParams; if (NULL != m_bstrAppendedParams) { acbStrings[3] = ::SysStringByteLen(m_bstrAppendedParams); }
// write string lengths to stream
hr = pStm->Write(acbStrings, sizeof(acbStrings), &cbWritten); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(acbStrings) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
// write strings to stream
hr = WriteStrings(pStm, acbStrings, abstrStrings, cStrings); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
CLEANUP: return hr; }
public: DWORD m_dwVerMajor; DWORD m_dwVerMinor; // common properties
DISPID m_dispid; // dispid of node
BSTR m_bstrName; // name of node
// url properties
BSTR m_bstrTemplate; // url's HTML template name
BSTR m_bstrToken; // url's token for replacement events
IID m_IID_Events; // IID of url's dynamic events interface
BOOL m_fParseReplacements; // TRUE=parse replacement recursively
BSTR m_bstrAppendedParams; // Appended params
BOOL m_fUsesRelativePath; // Specifies whether the runtime should load
// templates relative to the ASP's actual path
DWORD m_dwTokenInfo; DWORD m_dwReserved2; DWORD m_dwReserved3; CRunEventState* m_rgEvents; DWORD m_dwEventCount; };
// design time node types
#define WCS_NODE_TYPE_RESOURCE (BYTE)10
//#define WCS_DTNODE_TYPE_UNBOUND_TAG (BYTE)12
//#define WCS_DTNODE_TYPE_NESTED_WEBCLASS (BYTE)15
//#define WCS_DTNODE_TYPE_CUSTOM_EVENT (BYTE)11
//#define WCS_DTNODE_TYPE_URL_BOUND_TAG (BYTE)13
//#define WCS_DTNODE_TYPE_EVENT_BOUND_TAG (BYTE)14
class CRunEventState : public CStateBase { public: enum EventTypes { typeCustomEvent, typeURLBoundTag, typeEventBoundTag, typeUnboundTag, };
CRunEventState() { m_dwVerMajor = 0; m_dwVerMinor = 0; m_type = wcCustom; m_dispid = -1; m_bstrName = NULL; m_bstrOriginalHref = NULL; }
~CRunEventState() { if(m_bstrName != NULL) ::SysFreeString(m_bstrName);
if(m_bstrOriginalHref != NULL) ::SysFreeString(m_bstrOriginalHref); }
public: inline BOOL IsDTEvent() { return ( (m_type == EventTypes::typeCustomEvent) || (m_type == EventTypes::typeUnboundTag) || (m_type == EventTypes::typeURLBoundTag) || (m_type == EventTypes::typeEventBoundTag) ); } HRESULT Load(LPSTREAM pStm) { HRESULT hr = S_OK; ULONG cbRead = 0; ULONG acbStrings[2]; BSTR *apbstrStrings[2]; int cStrings = 2;
// TODO: Mopve this into state funcs..
hr = pStm->Read(this, sizeof(CRunEventState), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
// read design time string lengths from stream
hr = pStm->Read(acbStrings, sizeof(acbStrings), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(acbStrings) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
// now check if there are any strings to read
// if yes then set up array of string pointer addresses
apbstrStrings[0] = &m_bstrName; apbstrStrings[1] = &m_bstrOriginalHref;
hr = ReadStrings(pStm, acbStrings, apbstrStrings, 2); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
CLEANUP: return hr; }
HRESULT Save(LPSTREAM pStm) { HRESULT hr = S_OK; ULONG cbWritten = 0; ULONG acbStrings[2]; ::ZeroMemory(acbStrings, sizeof(acbStrings)); BSTR abstrStrings[2]; int cStrings = 2;
// set version numbers in node
hr = pStm->Write(this, sizeof(CRunEventState), &cbWritten); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(CRunEventState) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
// set up array of strings to be written to stream and
// determine how many there will be
if (NULL != m_bstrName) { acbStrings[0] = ::SysStringByteLen(m_bstrName); } if (NULL != m_bstrOriginalHref) { acbStrings[1] = ::SysStringByteLen(m_bstrOriginalHref); }
abstrStrings[0] = m_bstrName; abstrStrings[1] = m_bstrOriginalHref;
// write string lengths to stream
hr = pStm->Write(acbStrings, sizeof(acbStrings), &cbWritten); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(acbStrings) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
// write strings to stream
hr = WriteStrings(pStm, acbStrings, abstrStrings, cStrings); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
CLEANUP: return hr; }
inline DISPID GetDISPIDDirect() { return m_dispid; } inline BSTR GetNameDirect() {return m_bstrName; }
public: DWORD m_dwVerMajor; DWORD m_dwVerMinor; WebClassEventTypes m_type; // node type: nested WebClass, URL, events
DISPID m_dispid; // dispid of node
BSTR m_bstrName; // name of node
BSTR m_bstrOriginalHref; };
class CRunWebClassStateHeader { public: CRunWebClassStateHeader() { m_pWebClassState = NULL; m_cbWebClassState = 0; m_dwWebItemCount = 0; }
~CRunWebClassStateHeader(){}
public: CRunWebClassState* m_pWebClassState; DWORD m_cbWebClassState; DWORD m_dwWebItemCount; };
//////////////////////////////////////////////////////////////////////
//
// File Format:
//
// WCS_WEBCLASS structure
// length of WCS_WEBCLASS.bstrName
// length of WCS_WEBCLASS.bstrCatastropheURL
// length of WCS_WEBCLASS.bstrVirtualDirectory
// WCS_WEBCLASS.bstrName
// WCS_WEBCLASS.bstrCatastropheURL
// WCS_WEBCLASS.bstrVirtualDirectory
//
// WCS_WEBCLASS.cNodes instances of
// +-------------------------------
// | WCS_NODE structure
// | length of WCS_NODE.bstrName
// | lengths of other node specific strings
// | WCS_NODE.bstrName
// | other node specific strings
// +-------------------------------
//
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//
// inline void WCS_FreeWebClass(WCS_WEBCLASS *pClass)
//
// Frees all embedded BSTRs and invokes delete on structure
//
//////////////////////////////////////////////////////////////////////
/*
inline void WCS_FreeWebClass(WCS_WEBCLASS *pClass) { if (pClass->bstrName != NULL) { ::SysFreeString(pClass->bstrName); } if (pClass->bstrProgID != NULL) { ::SysFreeString(pClass->bstrProgID); } if (pClass->bstrCatastropheURL != NULL) { ::SysFreeString(pClass->bstrCatastropheURL); } if (pClass->bstrVirtualDirectory != NULL) { ::SysFreeString(pClass->bstrVirtualDirectory); } if (pClass->bstrFirstURL != NULL) { ::SysFreeString(pClass->bstrFirstURL); } if (pClass->bstrASPName != NULL) { ::SysFreeString(pClass->bstrASPName); } delete pClass; } */ //////////////////////////////////////////////////////////////////////
//
// inline void WCS_FreeNode(WCS_NODE *pNode)
//
// Frees all embedded BSTRs and invokes delete on structure
//
//////////////////////////////////////////////////////////////////////
/*
inline void WCS_FreeNode(WCS_NODE *pNode) { if (pNode->bstrName != NULL) { ::SysFreeString(pNode->bstrName); } if (WCS_NODE_TYPE_NESTED_WEBCLASS == pNode->bType) { if (pNode->bstrProgID != NULL) { ::SysFreeString(pNode->bstrProgID); } } else if ( (WCS_NODE_TYPE_PAGE == pNode->bType) || (WCS_DTNODE_TYPE_PAGE == pNode->bType) ) { if (pNode->bstrTemplate != NULL) { ::SysFreeString(pNode->Page.bstrTemplate); } if (pNode->Page.bstrToken != NULL) { ::SysFreeString(pNode->Page.bstrToken); } if (pNode->Page.bstrAppendedParams != NULL) { ::SysFreeString(pNode->Page.bstrAppendedParams); } } delete pNode; }
//////////////////////////////////////////////////////////////////////
//
// inline void WCS_FreeDTNode(WCS_NODE *pNode)
//
// Frees all embedded BSTRs and invokes delete on structure
//
//////////////////////////////////////////////////////////////////////
inline void WCS_FreeDTNode(WCS_DTNODE *pNode) { if ( (WCS_DTNODE_TYPE_URL_BOUND_TAG == pNode->bType) || (WCS_DTNODE_TYPE_EVENT_BOUND_TAG == pNode->bType) ) { if (NULL != pNode->DTEvent.bstrOriginalHref) { ::SysFreeString(pNode->DTEvent.bstrOriginalHref); } } else if (WCS_DTNODE_TYPE_PAGE == pNode->bType) { if (NULL != pNode->DTPage.bstrHTMLTemplateSrcName) { ::SysFreeString(pNode->DTPage.bstrHTMLTemplateSrcName); } } WCS_FreeNode(pNode); }
//////////////////////////////////////////////////////////////////////
//
// inline HRESULT WCS_ReadWebClass(IStream *pStream,
// WCS_WEBCLASS **ppClass)
//
//
//////////////////////////////////////////////////////////////////////
inline HRESULT WCS_ReadWebClass(IStream *pStream, WCS_WEBCLASS **ppClass) { HRESULT hr = S_OK; ULONG cbRead = 0; ULONG acbStrings[6]; BSTR *apbstrStrings[6];
// allocate structure
*ppClass = new WCS_WEBCLASS; CSF_CHECK(*ppClass != NULL, E_OUTOFMEMORY, CSF_TRACE_INTERNAL_ERRORS);
// read structure from stream
hr = pStream->Read(*ppClass, sizeof(**ppClass), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(**ppClass) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
(*ppClass)->pvData = NULL; // don't take junk pointer value from stream
// TODO: need error codes for version incompatibility, handle backlevel formats etc.
CSF_CHECK(WCS_WEBCLASS_VER_MAJOR == (*ppClass)->wVerMajor, STG_E_OLDFORMAT, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(WCS_WEBCLASS_VER_MAJOR == (*ppClass)->wVerMinor, STG_E_OLDFORMAT, CSF_TRACE_EXTERNAL_ERRORS);
// read string lengths from stream
hr = pStream->Read(acbStrings, sizeof(acbStrings), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(acbStrings) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
// set up array of string pointer addresses
apbstrStrings[0] = &((*ppClass)->bstrName); apbstrStrings[1] = &((*ppClass)->bstrProgID); apbstrStrings[2] = &((*ppClass)->bstrCatastropheURL); apbstrStrings[3] = &((*ppClass)->bstrVirtualDirectory); apbstrStrings[4] = &((*ppClass)->bstrFirstURL); apbstrStrings[5] = &((*ppClass)->bstrASPName);
// read strings from stream
hr = ReadStrings(pStream, acbStrings, apbstrStrings, (sizeof(acbStrings) / sizeof(acbStrings[0])) ); CLEANUP: if (FAILED(hr) && (*ppClass != NULL)) { WCS_FreeWebClass(*ppClass); *ppClass = NULL; } return hr; }
//=--------------------------------------------------------------------------=
//
// inline HRESULT WCS_ReadNodeFromStream(IStream *pStream, WCS_NODE *pNode)
//
// Reads a WCS_NODE structure from a stream. Caller passes in node.
//
//=--------------------------------------------------------------------------=
inline HRESULT WCS_ReadNodeFromStream(IStream *pStream, WCS_NODE *pNode) { HRESULT hr = S_OK; ULONG cbRead = 0; ULONG acbStrings[4]; BSTR *apbstrStrings[4]; int cStrings = 0;
// read structure from stream
hr = pStream->Read(pNode, sizeof(*pNode), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(*pNode) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
// TODO: need error codes for version incompatibility, handle backlevel formats etc.
CSF_CHECK(WCS_NODE_VER_MAJOR == pNode->wVerMajor, STG_E_OLDFORMAT, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(WCS_NODE_VER_MINOR == pNode->wVerMinor, STG_E_OLDFORMAT, CSF_TRACE_EXTERNAL_ERRORS);
// set up array of string pointer addresses according to node type
apbstrStrings[0] = &(pNode->bstrName);
if ( (WCS_NODE_TYPE_NESTED_WEBCLASS == pNode->bType) || (WCS_DTNODE_TYPE_NESTED_WEBCLASS == pNode->bType) ) { apbstrStrings[1] = &(pNode->bstrProgID); cStrings = 2; } else if ( (WCS_NODE_TYPE_PAGE == pNode->bType) || (WCS_DTNODE_TYPE_PAGE == pNode->bType) ) { apbstrStrings[1] = &(pNode->bstrTemplate); apbstrStrings[2] = &(pNode->bstrToken); apbstrStrings[3] = &(pNode->bstrAppendedParams); cStrings = 4; } else if ( (WCS_NODE_TYPE_EVENT == bType) || IsDTEvent(bType) ) { cStrings = 1; } else { CSF_CHECK(FALSE, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS); }
// read string lengths from stream
hr = pStream->Read(acbStrings, sizeof(acbStrings), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(acbStrings) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
// read strings from stream
hr = ReadStrings(pStream, acbStrings, apbstrStrings, cStrings);
CLEANUP: return hr; }
//////////////////////////////////////////////////////////////////////
//
// inline HRESULT WCS_ReadNode(IStream *pStream, WCS_NODE **ppNode)
//
// Allocates a WCS_NODE structure and reads its contents from the
// stream.
//
//////////////////////////////////////////////////////////////////////
inline HRESULT WCS_ReadNode(IStream *pStream, WCS_NODE **ppNode) { HRESULT hr = S_OK;
// allocate structure
*ppNode = new WCS_NODE; CSF_CHECK(*ppNode != NULL, E_OUTOFMEMORY, CSF_TRACE_INTERNAL_ERRORS);
// read node in from stream
hr = WCS_ReadNodeFromStream(pStream, *ppNode); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
CLEANUP: if (FAILED(hr) && (*ppNode != NULL)) { WCS_FreeNode(*ppNode); *ppNode = NULL; } return hr; }
//=--------------------------------------------------------------------------=
//
// inline HRESULT WCS_ReadDTNode(IStream *pStream, WCS_DTNODE **ppNode)
//
// Allocates a WCS_DTNODE and reads its contents from the stream.
//
//=--------------------------------------------------------------------------=
inline HRESULT WCS_ReadDTNode(IStream *pStream, WCS_DTNODE **ppNode) { HRESULT hr = S_OK; ULONG cbRead = 0; ULONG acbStrings[1]; BSTR *apbstrStrings[1]; int cStrings = 0;
// allocate structure
*ppNode = new WCS_DTNODE; CSF_CHECK(*ppNode != NULL, E_OUTOFMEMORY, CSF_TRACE_INTERNAL_ERRORS);
// read base class WCS_NODE first
hr = WCS_ReadNodeFromStream(pStream, *ppNode); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
// read design time fields
if (WCS_DTNODE_TYPE_PAGE == (*ppNode)->bType) { hr = pStream->Read(&(*ppNode)->DTPage, sizeof((*ppNode)->DTPage), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof((*ppNode)->DTPage) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS); } else if (WCS_DTNODE_TYPE_NESTED_WEBCLASS != (*ppNode)->bType) { hr = pStream->Read(&(*ppNode)->DTEvent, sizeof((*ppNode)->DTEvent), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof((*ppNode)->DTEvent) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS); }
// read design time string lengths from stream
hr = pStream->Read(acbStrings, sizeof(acbStrings), &cbRead); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(acbStrings) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
// now check if there are any strings to read
// if yes then set up array of string pointer addresses
if (0 == acbStrings[0]) { // There are no strings to read so store NULL pointers
if (WCS_DTNODE_TYPE_PAGE == (*ppNode)->bType) { (*ppNode)->DTPage.bstrHTMLTemplateSrcName = NULL; } else if (WCS_DTNODE_TYPE_NESTED_WEBCLASS != (*ppNode)->bType) { (*ppNode)->DTEvent.bstrOriginalHref = NULL; } goto CLEANUP; } else // There are strings so read them from the stream
{ if (WCS_DTNODE_TYPE_PAGE == (*ppNode)->bType) { apbstrStrings[0] = &((*ppNode)->DTPage.bstrHTMLTemplateSrcName); } else if (WCS_DTNODE_TYPE_NESTED_WEBCLASS != (*ppNode)->bType) { apbstrStrings[0] = &((*ppNode)->DTEvent.bstrOriginalHref); } cStrings++; }
// read strings from stream
if (cStrings > 0) { hr = ReadStrings(pStream, acbStrings, apbstrStrings, cStrings); }
CLEANUP: if (FAILED(hr) && (*ppNode != NULL)) { WCS_FreeDTNode(*ppNode); *ppNode = NULL; } return hr; }
//////////////////////////////////////////////////////////////////////
//
// inline HRESULT WCS_WriteWebClass(IStream *pStream, WCS_WEBCLASS *pClass)
//
//
//////////////////////////////////////////////////////////////////////
inline HRESULT WCS_WriteWebClass(IStream *pStream, WCS_WEBCLASS *pClass) { HRESULT hr = S_OK; ULONG cbWritten = 0; ULONG acbStrings[6]; BSTR abstrStrings[6];
// set version numbers
pClass->wVerMajor = WCS_WEBCLASS_VER_MAJOR; pClass->wVerMinor = WCS_WEBCLASS_VER_MAJOR;
// write WebClass structure to stream
hr = pStream->Write(pClass, sizeof(*pClass), &cbWritten); CSF_CHECK(hr == S_OK, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(cbWritten == sizeof(*pClass), STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
// get lengths of strings and write them to stream
acbStrings[0] = SysStringByteLen(pClass->bstrName); acbStrings[1] = SysStringByteLen(pClass->bstrProgID); acbStrings[2] = SysStringByteLen(pClass->bstrCatastropheURL); acbStrings[3] = SysStringByteLen(pClass->bstrVirtualDirectory); acbStrings[4] = SysStringByteLen(pClass->bstrFirstURL); acbStrings[5] = SysStringByteLen(pClass->bstrASPName);
hr = pStream->Write(acbStrings, sizeof(acbStrings), &cbWritten); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(cbWritten == sizeof(acbStrings), STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
// set up array of pointers to strings to be written to stream
abstrStrings[0] = pClass->bstrName; abstrStrings[1] = pClass->bstrProgID; abstrStrings[2] = pClass->bstrCatastropheURL; abstrStrings[3] = pClass->bstrVirtualDirectory; abstrStrings[4] = pClass->bstrFirstURL; abstrStrings[5] = pClass->bstrASPName;
// write strings to stream
hr = WriteStrings(pStream, acbStrings, abstrStrings, (sizeof(acbStrings) / sizeof(acbStrings[0])) );
CLEANUP: return hr; }
//////////////////////////////////////////////////////////////////////
//
// inline HRESULT WCS_WriteNode(IStream *pStream, WCS_NODE *pNode)
//
//
//////////////////////////////////////////////////////////////////////
inline HRESULT WCS_WriteNode(IStream *pStream, WCS_NODE *pNode) { HRESULT hr = S_OK; ULONG cbWritten = 0; ULONG acbStrings[4]; BSTR abstrStrings[4]; int cStrings = 0;
// set version numbers in node
pNode->wVerMajor = WCS_NODE_VER_MAJOR; pNode->wVerMinor = WCS_NODE_VER_MINOR;
// write node structure to stream
hr = pStream->Write(pNode, sizeof(*pNode), &cbWritten); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(*pNode) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
// set up array of strings to be written to stream and
// determine how many there will be
abstrStrings[0] = pNode->bstrName; acbStrings[0] = ::SysStringByteLen(pNode->bstrName);
if ( (WCS_NODE_TYPE_NESTED_WEBCLASS == pNode->bType) || (WCS_DTNODE_TYPE_NESTED_WEBCLASS == pNode->bType) ) { abstrStrings[1] = pNode->Nested.bstrProgID; acbStrings[1] = ::SysStringByteLen(pNode->Nested.bstrProgID); cStrings = 2; } else if ( (WCS_NODE_TYPE_PAGE == pNode->bType) || (WCS_DTNODE_TYPE_PAGE == pNode->bType) ) { abstrStrings[1] = pNode->Page.bstrTemplate; acbStrings[1] = ::SysStringByteLen(pNode->Page.bstrTemplate); abstrStrings[2] = pNode->Page.bstrToken; acbStrings[2] = ::SysStringByteLen(pNode->Page.bstrToken); abstrStrings[3] = pNode->Page.bstrAppendedParams; acbStrings[3] = ::SysStringByteLen(pNode->Page.bstrAppendedParams); cStrings = 4; } else if ( (WCS_NODE_TYPE_EVENT == pNode->bType) || WCS_IsDTEvent(pNode->bType) ) { cStrings = 1; } else { CSF_CHECK(FALSE, E_INVALIDARG, CSF_TRACE_INTERNAL_ERRORS); }
// write string lengths to stream
hr = pStream->Write(acbStrings, sizeof(acbStrings), &cbWritten); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(acbStrings) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
// write strings to stream
hr = WriteStrings(pStream, acbStrings, abstrStrings, cStrings);
CLEANUP: return hr; }
//=--------------------------------------------------------------------------=
//
// inline HRESULT WCS_WriteDTNode(IStream *pStream, WCS_DTNODE *pNode)
//
// Write design time node. Write the base class runtime node and then
// then extra stuff in the design time node.
//
//=--------------------------------------------------------------------------=
inline HRESULT WCS_WriteDTNode(IStream *pStream, WCS_DTNODE *pNode) { HRESULT hr = S_OK; ULONG cbWritten = 0; ULONG acbStrings[1] = { 0 }; BSTR abstrStrings[1]; int cStrings = 0;
// write run time node first
hr = WCS_WriteNode(pStream, pNode); CSF_CHECK(hr == S_OK, hr, CSF_TRACE_INTERNAL_ERRORS);
// write design time fields
if (WCS_DTNODE_TYPE_PAGE == pNode->bType) { hr = pStream->Write(&pNode->DTPage, sizeof(pNode->DTPage), &cbWritten); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(pNode->DTPage) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
if (NULL != pNode->DTPage.bstrHTMLTemplateSrcName) { abstrStrings[0] = pNode->DTPage.bstrHTMLTemplateSrcName; acbStrings[0] = ::SysStringByteLen(pNode->DTPage.bstrHTMLTemplateSrcName); cStrings++; } } else if (WCS_DTNODE_TYPE_NESTED_WEBCLASS != pNode->bType) { hr = pStream->Write(&pNode->DTEvent, sizeof(pNode->DTEvent), &cbWritten); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(pNode->DTEvent) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
if (NULL != pNode->DTEvent.bstrOriginalHref) { abstrStrings[0] = pNode->DTEvent.bstrOriginalHref; acbStrings[0] = ::SysStringByteLen(pNode->DTEvent.bstrOriginalHref); cStrings++; } }
hr = pStream->Write(acbStrings, sizeof(acbStrings), &cbWritten); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS); CSF_CHECK(sizeof(acbStrings) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
if (cStrings > 0) { hr = WriteStrings(pStream, acbStrings, abstrStrings, cStrings); CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS); }
CLEANUP: return hr; } */
#define _WBCLSSER_H_
#endif // _WBCLSSER_H_
|