Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1220 lines
34 KiB

//=--------------------------------------------------------------------------=
// 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_