Leaked source code of windows server 2003
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
35 KiB

  1. //=--------------------------------------------------------------------------=
  2. // wbclsser.h
  3. //=--------------------------------------------------------------------------=
  4. // Copyright 1995 Microsoft Corporation. All Rights Reserved.
  5. //
  6. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  7. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  8. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  9. // PARTICULAR PURPOSE.
  10. //=--------------------------------------------------------------------------=
  11. //
  12. // API for WebClass Designer Serialization
  13. //
  14. // adolfoc 7/29/97
  15. // Renamed WCS_NODE_TYPE_URL to WCS_NODE_TYPE_PAGE,
  16. // added WCS_NODE_TYPE_URL with value 3,
  17. // changed URL tag to Page
  18. //
  19. #ifndef _WBCLSSER_H_
  20. #include "csfdebug.h"
  21. #include "convman_tlb.h"
  22. // Designer State Flags
  23. #define RUNSTATE_COMPILED 0x00000000
  24. #define RUNSTATE_F5 0x00000001
  25. #define DISPID_OBJECT_PROPERTY_START 0x00000500
  26. // Serialization Versions
  27. // 0.0 Beta1
  28. // 0.1 PreBeta2 - WebItems must be sorted on load
  29. // 0.2 PreBeta2 - Added Optimize member var to WebItems
  30. // 0.3 PreBeta2 - WebEvents are now sorted on load too
  31. // 0.4 PreBeta2 -
  32. // 0.5 PreBeta2 - Tagattributes added anonymous tag number
  33. // 0.6 <skipped>
  34. // 0.7 PreRC1 - Added URLInName to design time state
  35. // 0.8 PreRC1 - Fixed bug in WebItem and event sorting algorithm. Now we need
  36. // to fixup old projects with bug whose WebItems and events are not
  37. // serialized in alphabetical order.
  38. // structure of WebClass on disk
  39. const DWORD dwExpectedVerMajor = 0;
  40. const DWORD dwExpectedVerMinor = 8;
  41. class CRunWebItemState;
  42. class CRunEventState;
  43. class CStateBase
  44. {
  45. public:
  46. CStateBase() {}
  47. ~CStateBase() {}
  48. public:
  49. //////////////////////////////////////////////////////////////////////
  50. //
  51. // inline ReadStrings(IStream *pStream, ULONG acbStrings[],
  52. // BSTR *apbstrStrings[], int cStrings)
  53. //
  54. //
  55. //
  56. //////////////////////////////////////////////////////////////////////
  57. inline ReadStrings(IStream *pStream, ULONG acbStrings[],
  58. BSTR *apbstrStrings[], int cStrings)
  59. {
  60. HRESULT hr = S_OK;
  61. ULONG cbRead = 0;
  62. char *pszReadBuf = NULL;
  63. ULONG cbLongest = 0;
  64. int i = 0;
  65. while (i < cStrings)
  66. {
  67. if (acbStrings[i] > cbLongest)
  68. {
  69. cbLongest = acbStrings[i];
  70. }
  71. i++;
  72. }
  73. if (0 != cbLongest)
  74. {
  75. pszReadBuf = new char[cbLongest + sizeof(WCHAR)];
  76. CSF_CHECK(NULL != pszReadBuf, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
  77. }
  78. i = 0;
  79. while (i < cStrings)
  80. {
  81. if (0 == acbStrings[i])
  82. {
  83. *(apbstrStrings[i]) = NULL;
  84. }
  85. else
  86. {
  87. hr = pStream->Read(pszReadBuf, acbStrings[i], &cbRead);
  88. CSF_CHECK(hr == S_OK, hr, CSF_TRACE_EXTERNAL_ERRORS);
  89. CSF_CHECK(cbRead == acbStrings[i], STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  90. *((WCHAR *)&pszReadBuf[acbStrings[i]]) = L'\0';
  91. *(apbstrStrings[i]) = ::SysAllocString((WCHAR *)pszReadBuf);
  92. CSF_CHECK(*(apbstrStrings[i]) != NULL, E_OUTOFMEMORY, CSF_TRACE_EXTERNAL_ERRORS);
  93. }
  94. i++;
  95. }
  96. CLEANUP:
  97. if (NULL != pszReadBuf)
  98. {
  99. delete [] pszReadBuf;
  100. }
  101. return hr;
  102. }
  103. //////////////////////////////////////////////////////////////////////
  104. //
  105. // inline WriteStrings(IStream *pStream, ULONG acbStrings[],
  106. // BSTR *apbstrStrings[], int cStrings)
  107. //
  108. //
  109. //////////////////////////////////////////////////////////////////////
  110. inline WriteStrings(IStream *pStream, ULONG acbStrings[],
  111. BSTR abstrStrings[], int cStrings)
  112. {
  113. HRESULT hr = S_OK;
  114. ULONG cbWritten = 0;
  115. int i = 0;
  116. while (i < cStrings)
  117. {
  118. if (NULL != abstrStrings[i])
  119. {
  120. hr = pStream->Write(abstrStrings[i], acbStrings[i], &cbWritten);
  121. CSF_CHECK(hr == S_OK, hr, CSF_TRACE_EXTERNAL_ERRORS);
  122. CSF_CHECK(cbWritten == acbStrings[i], STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  123. }
  124. i++;
  125. }
  126. CLEANUP:
  127. return hr;
  128. }
  129. };
  130. class CRunWebClassState : public CStateBase
  131. {
  132. public:
  133. CRunWebClassState()
  134. {
  135. m_dwVerMajor = dwExpectedVerMajor;
  136. m_dwVerMinor = dwExpectedVerMinor;
  137. m_bstrName = NULL; // Kill
  138. m_bstrProgID = NULL; // Runtime only
  139. m_StateManagementType = wcNoState;
  140. m_bstrASPName = NULL;
  141. m_bstrAppendedParams = NULL;
  142. m_bstrStartupItem = NULL;
  143. m_DIID_WebClass = GUID_NULL;
  144. m_DIID_WebClassEvents = GUID_NULL;
  145. m_dwTICookie = 0;
  146. m_dwFlags = 0;
  147. m_rgWebItemsState = 0;
  148. m_dwWebItemCount = 0;
  149. }
  150. ~CRunWebClassState()
  151. {
  152. if(m_bstrName != NULL)
  153. ::SysFreeString(m_bstrName);
  154. if(m_bstrProgID != NULL)
  155. ::SysFreeString(m_bstrProgID);
  156. if(m_bstrASPName != NULL)
  157. ::SysFreeString(m_bstrASPName);
  158. if(m_bstrAppendedParams != NULL)
  159. ::SysFreeString(m_bstrAppendedParams);
  160. if(m_bstrStartupItem != NULL)
  161. ::SysFreeString(m_bstrStartupItem);
  162. }
  163. public:
  164. DWORD m_dwVerMajor; // major version number
  165. DWORD m_dwVerMinor; // minor version number
  166. BSTR m_bstrName; // WebClass name
  167. BSTR m_bstrProgID; // WebClass progid
  168. StateManagement m_StateManagementType; // state management type
  169. BSTR m_bstrASPName; // name of ASP file
  170. IID m_DIID_WebClass; // IID of WebClass' main IDispatch
  171. IID m_DIID_WebClassEvents; // IID of WebClass' events IDispatch
  172. DWORD m_dwTICookie; // typeinfo cookie
  173. BSTR m_bstrAppendedParams; // URL state
  174. BSTR m_bstrStartupItem; // f5 statup Item
  175. DWORD m_dwFlags;
  176. CRunWebItemState* m_rgWebItemsState;
  177. DWORD m_dwWebItemCount; // runtime node types
  178. public:
  179. HRESULT Load(LPSTREAM pStm)
  180. {
  181. HRESULT hr = S_OK;
  182. ULONG cbRead = 0;
  183. ULONG acbStrings[5];
  184. BSTR *apbstrStrings[5];
  185. // read structure from stream
  186. hr = pStm->Read(this, sizeof(CRunWebClassState), &cbRead);
  187. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  188. CSF_CHECK(sizeof(CRunWebClassState) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  189. // TODO: need error codes for version incompatibility, handle backlevel formats etc.
  190. // CSF_CHECK(dwExpectedVerMajor == m_dwVerMajor, STG_E_OLDFORMAT, CSF_TRACE_EXTERNAL_ERRORS);
  191. // CSF_CHECK(dwExpectedVerMinor == m_dwVerMinor, STG_E_OLDFORMAT, CSF_TRACE_EXTERNAL_ERRORS);
  192. // read string lengths from stream
  193. hr = pStm->Read(acbStrings, sizeof(acbStrings), &cbRead);
  194. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  195. CSF_CHECK(sizeof(acbStrings) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  196. // set up array of string pointer addresses
  197. apbstrStrings[0] = &(m_bstrName);
  198. apbstrStrings[1] = &(m_bstrProgID);
  199. apbstrStrings[2] = &(m_bstrASPName);
  200. apbstrStrings[3] = &(m_bstrAppendedParams);
  201. apbstrStrings[4] = &(m_bstrStartupItem);
  202. // read strings from stream
  203. hr = ReadStrings(pStm, acbStrings, apbstrStrings,
  204. (sizeof(acbStrings) / sizeof(acbStrings[0])) );
  205. CLEANUP:
  206. return hr;
  207. }
  208. HRESULT Save(LPSTREAM pStm)
  209. {
  210. HRESULT hr = S_OK;
  211. ULONG cbWritten = 0;
  212. ULONG acbStrings[5];
  213. ::ZeroMemory(acbStrings, sizeof(acbStrings));
  214. BSTR abstrStrings[5];
  215. // write WebClass structure to stream
  216. hr = pStm->Write(this, sizeof(CRunWebClassState), &cbWritten);
  217. CSF_CHECK(hr == S_OK, hr, CSF_TRACE_EXTERNAL_ERRORS);
  218. CSF_CHECK(cbWritten == sizeof(CRunWebClassState), STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  219. // get lengths of strings and write them to stream
  220. if (NULL != m_bstrName)
  221. {
  222. acbStrings[0] = ::SysStringByteLen(m_bstrName);
  223. }
  224. if (NULL != m_bstrProgID)
  225. {
  226. acbStrings[1] = ::SysStringByteLen(m_bstrProgID);
  227. }
  228. if (NULL != m_bstrASPName)
  229. {
  230. acbStrings[2] = ::SysStringByteLen(m_bstrASPName);
  231. }
  232. if (NULL != m_bstrAppendedParams)
  233. {
  234. acbStrings[3] = ::SysStringByteLen(m_bstrAppendedParams);
  235. }
  236. if (NULL != m_bstrStartupItem)
  237. {
  238. acbStrings[4] = ::SysStringByteLen(m_bstrStartupItem);
  239. }
  240. hr = pStm->Write(acbStrings, sizeof(acbStrings), &cbWritten);
  241. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  242. CSF_CHECK(cbWritten == sizeof(acbStrings), STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  243. // set up array of pointers to strings to be written to stream
  244. abstrStrings[0] = m_bstrName;
  245. abstrStrings[1] = m_bstrProgID;
  246. abstrStrings[2] = m_bstrASPName;
  247. abstrStrings[3] = m_bstrAppendedParams;
  248. abstrStrings[4] = m_bstrStartupItem;
  249. // write strings to stream
  250. hr = WriteStrings(pStm, acbStrings, abstrStrings,
  251. (sizeof(acbStrings) / sizeof(acbStrings[0])) );
  252. CLEANUP:
  253. return hr;
  254. }
  255. };
  256. typedef struct tagWCS_NODEHEADER
  257. {
  258. BYTE bType; // node type: nested WebClass, URL, events
  259. } WCS_NODEHEADER;
  260. // WCS_DTNODE_TYPE_URL_BOUND_TAG is a special case because WCS_DTNODE.dispid
  261. // contains the dispid of the referenced URL and WCS_DTNODE.bstrName contains
  262. // the name of the referenced URL.
  263. // structure of node on disk at runtime
  264. class CRunWebItemState : protected CStateBase
  265. {
  266. public:
  267. CRunWebItemState()
  268. {
  269. m_dwVerMajor = dwExpectedVerMajor;
  270. m_dwVerMinor = dwExpectedVerMinor;
  271. m_dispid = -1;
  272. m_bstrName = NULL;
  273. m_bstrTemplate = NULL;
  274. m_bstrToken = NULL;
  275. m_IID_Events = GUID_NULL;
  276. m_fParseReplacements = FALSE;
  277. m_bstrAppendedParams = NULL;
  278. m_fUsesRelativePath = FALSE;
  279. m_dwTokenInfo = 0;
  280. m_dwReserved2 = 0;
  281. m_dwReserved3 = 0;
  282. m_rgEvents = 0;
  283. m_dwEventCount = 0;
  284. }
  285. ~CRunWebItemState()
  286. {
  287. if(m_bstrName != NULL)
  288. ::SysFreeString(m_bstrName);
  289. if(m_bstrTemplate != NULL)
  290. ::SysFreeString(m_bstrTemplate);
  291. if(m_bstrToken != NULL)
  292. ::SysFreeString(m_bstrToken);
  293. if(m_bstrAppendedParams != NULL)
  294. ::SysFreeString(m_bstrAppendedParams);
  295. }
  296. public:
  297. HRESULT Load(LPSTREAM pStm)
  298. {
  299. HRESULT hr = S_OK;
  300. ULONG cbRead = 0;
  301. ULONG acbStrings[4];
  302. BSTR *apbstrStrings[4];
  303. int cStrings = 4;
  304. // read structure from stream
  305. hr = pStm->Read(this, sizeof(CRunWebItemState), &cbRead);
  306. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  307. CSF_CHECK(sizeof(CRunWebItemState) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  308. // m_pvData = NULL; // don't take junk pointer value from stream
  309. // set up array of string pointer addresses according to node type
  310. apbstrStrings[0] = &m_bstrName;
  311. apbstrStrings[1] = &m_bstrTemplate;
  312. apbstrStrings[2] = &m_bstrToken;
  313. apbstrStrings[3] = &m_bstrAppendedParams;
  314. // read string lengths from stream
  315. hr = pStm->Read(acbStrings, sizeof(acbStrings), &cbRead);
  316. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  317. CSF_CHECK(sizeof(acbStrings) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  318. // read strings from stream
  319. hr = ReadStrings(pStm, acbStrings, apbstrStrings, cStrings);
  320. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
  321. CLEANUP:
  322. return hr;
  323. }
  324. HRESULT Save
  325. (
  326. LPSTREAM pStm
  327. )
  328. {
  329. HRESULT hr = S_OK;
  330. ULONG cbWritten = 0;
  331. ULONG acbStrings[4];
  332. ::ZeroMemory(acbStrings, sizeof(acbStrings));
  333. BSTR abstrStrings[4];
  334. int cStrings = 4;
  335. // write node structure to stream
  336. hr = pStm->Write(this, sizeof(CRunWebItemState), &cbWritten);
  337. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  338. CSF_CHECK(sizeof(CRunWebItemState) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  339. // set up array of strings to be written to stream and
  340. // determine how many there will be
  341. abstrStrings[0] = m_bstrName;
  342. if (NULL != m_bstrName)
  343. {
  344. acbStrings[0] = ::SysStringByteLen(m_bstrName);
  345. }
  346. abstrStrings[1] = m_bstrTemplate;
  347. if (NULL != m_bstrTemplate)
  348. {
  349. acbStrings[1] = ::SysStringByteLen(m_bstrTemplate);
  350. }
  351. abstrStrings[2] = m_bstrToken;
  352. if (NULL != m_bstrToken)
  353. {
  354. acbStrings[2] = ::SysStringByteLen(m_bstrToken);
  355. }
  356. abstrStrings[3] = m_bstrAppendedParams;
  357. if (NULL != m_bstrAppendedParams)
  358. {
  359. acbStrings[3] = ::SysStringByteLen(m_bstrAppendedParams);
  360. }
  361. // write string lengths to stream
  362. hr = pStm->Write(acbStrings, sizeof(acbStrings), &cbWritten);
  363. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  364. CSF_CHECK(sizeof(acbStrings) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  365. // write strings to stream
  366. hr = WriteStrings(pStm, acbStrings, abstrStrings, cStrings);
  367. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
  368. CLEANUP:
  369. return hr;
  370. }
  371. public:
  372. DWORD m_dwVerMajor;
  373. DWORD m_dwVerMinor;
  374. // common properties
  375. DISPID m_dispid; // dispid of node
  376. BSTR m_bstrName; // name of node
  377. // url properties
  378. BSTR m_bstrTemplate; // url's HTML template name
  379. BSTR m_bstrToken; // url's token for replacement events
  380. IID m_IID_Events; // IID of url's dynamic events interface
  381. BOOL m_fParseReplacements; // TRUE=parse replacement recursively
  382. BSTR m_bstrAppendedParams; // Appended params
  383. BOOL m_fUsesRelativePath; // Specifies whether the runtime should load
  384. // templates relative to the ASP's actual path
  385. DWORD m_dwTokenInfo;
  386. DWORD m_dwReserved2;
  387. DWORD m_dwReserved3;
  388. CRunEventState* m_rgEvents;
  389. DWORD m_dwEventCount;
  390. };
  391. // design time node types
  392. #define WCS_NODE_TYPE_RESOURCE (BYTE)10
  393. //#define WCS_DTNODE_TYPE_UNBOUND_TAG (BYTE)12
  394. //#define WCS_DTNODE_TYPE_NESTED_WEBCLASS (BYTE)15
  395. //#define WCS_DTNODE_TYPE_CUSTOM_EVENT (BYTE)11
  396. //#define WCS_DTNODE_TYPE_URL_BOUND_TAG (BYTE)13
  397. //#define WCS_DTNODE_TYPE_EVENT_BOUND_TAG (BYTE)14
  398. class CRunEventState : public CStateBase
  399. {
  400. public:
  401. enum EventTypes
  402. {
  403. typeCustomEvent,
  404. typeURLBoundTag,
  405. typeEventBoundTag,
  406. typeUnboundTag,
  407. };
  408. CRunEventState()
  409. {
  410. m_dwVerMajor = 0;
  411. m_dwVerMinor = 0;
  412. m_type = wcCustom;
  413. m_dispid = -1;
  414. m_bstrName = NULL;
  415. m_bstrOriginalHref = NULL;
  416. }
  417. ~CRunEventState()
  418. {
  419. if(m_bstrName != NULL)
  420. ::SysFreeString(m_bstrName);
  421. if(m_bstrOriginalHref != NULL)
  422. ::SysFreeString(m_bstrOriginalHref);
  423. }
  424. public:
  425. inline BOOL IsDTEvent()
  426. {
  427. return ( (m_type == EventTypes::typeCustomEvent) ||
  428. (m_type == EventTypes::typeUnboundTag) ||
  429. (m_type == EventTypes::typeURLBoundTag) ||
  430. (m_type == EventTypes::typeEventBoundTag)
  431. );
  432. }
  433. HRESULT Load(LPSTREAM pStm)
  434. {
  435. HRESULT hr = S_OK;
  436. ULONG cbRead = 0;
  437. ULONG acbStrings[2];
  438. BSTR *apbstrStrings[2];
  439. int cStrings = 2;
  440. // TODO: Mopve this into state funcs..
  441. hr = pStm->Read(this, sizeof(CRunEventState), &cbRead);
  442. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  443. // read design time string lengths from stream
  444. hr = pStm->Read(acbStrings, sizeof(acbStrings), &cbRead);
  445. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  446. CSF_CHECK(sizeof(acbStrings) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  447. // now check if there are any strings to read
  448. // if yes then set up array of string pointer addresses
  449. apbstrStrings[0] = &m_bstrName;
  450. apbstrStrings[1] = &m_bstrOriginalHref;
  451. hr = ReadStrings(pStm, acbStrings, apbstrStrings, 2);
  452. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
  453. CLEANUP:
  454. return hr;
  455. }
  456. HRESULT Save(LPSTREAM pStm)
  457. {
  458. HRESULT hr = S_OK;
  459. ULONG cbWritten = 0;
  460. ULONG acbStrings[2];
  461. ::ZeroMemory(acbStrings, sizeof(acbStrings));
  462. BSTR abstrStrings[2];
  463. int cStrings = 2;
  464. // set version numbers in node
  465. hr = pStm->Write(this, sizeof(CRunEventState), &cbWritten);
  466. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  467. CSF_CHECK(sizeof(CRunEventState) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  468. // set up array of strings to be written to stream and
  469. // determine how many there will be
  470. if (NULL != m_bstrName)
  471. {
  472. acbStrings[0] = ::SysStringByteLen(m_bstrName);
  473. }
  474. if (NULL != m_bstrOriginalHref)
  475. {
  476. acbStrings[1] = ::SysStringByteLen(m_bstrOriginalHref);
  477. }
  478. abstrStrings[0] = m_bstrName;
  479. abstrStrings[1] = m_bstrOriginalHref;
  480. // write string lengths to stream
  481. hr = pStm->Write(acbStrings, sizeof(acbStrings), &cbWritten);
  482. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  483. CSF_CHECK(sizeof(acbStrings) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  484. // write strings to stream
  485. hr = WriteStrings(pStm, acbStrings, abstrStrings, cStrings);
  486. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
  487. CLEANUP:
  488. return hr;
  489. }
  490. inline DISPID GetDISPIDDirect() { return m_dispid; }
  491. inline BSTR GetNameDirect() {return m_bstrName; }
  492. public:
  493. DWORD m_dwVerMajor;
  494. DWORD m_dwVerMinor;
  495. WebClassEventTypes m_type; // node type: nested WebClass, URL, events
  496. DISPID m_dispid; // dispid of node
  497. BSTR m_bstrName; // name of node
  498. BSTR m_bstrOriginalHref;
  499. };
  500. class CRunWebClassStateHeader
  501. {
  502. public:
  503. CRunWebClassStateHeader()
  504. {
  505. m_pWebClassState = NULL;
  506. m_cbWebClassState = 0;
  507. m_dwWebItemCount = 0;
  508. }
  509. ~CRunWebClassStateHeader(){}
  510. public:
  511. CRunWebClassState* m_pWebClassState;
  512. DWORD m_cbWebClassState;
  513. DWORD m_dwWebItemCount;
  514. };
  515. //////////////////////////////////////////////////////////////////////
  516. //
  517. // File Format:
  518. //
  519. // WCS_WEBCLASS structure
  520. // length of WCS_WEBCLASS.bstrName
  521. // length of WCS_WEBCLASS.bstrCatastropheURL
  522. // length of WCS_WEBCLASS.bstrVirtualDirectory
  523. // WCS_WEBCLASS.bstrName
  524. // WCS_WEBCLASS.bstrCatastropheURL
  525. // WCS_WEBCLASS.bstrVirtualDirectory
  526. //
  527. // WCS_WEBCLASS.cNodes instances of
  528. // +-------------------------------
  529. // | WCS_NODE structure
  530. // | length of WCS_NODE.bstrName
  531. // | lengths of other node specific strings
  532. // | WCS_NODE.bstrName
  533. // | other node specific strings
  534. // +-------------------------------
  535. //
  536. //////////////////////////////////////////////////////////////////////
  537. //////////////////////////////////////////////////////////////////////
  538. //
  539. // inline void WCS_FreeWebClass(WCS_WEBCLASS *pClass)
  540. //
  541. // Frees all embedded BSTRs and invokes delete on structure
  542. //
  543. //////////////////////////////////////////////////////////////////////
  544. /*
  545. inline void WCS_FreeWebClass(WCS_WEBCLASS *pClass)
  546. {
  547. if (pClass->bstrName != NULL)
  548. {
  549. ::SysFreeString(pClass->bstrName);
  550. }
  551. if (pClass->bstrProgID != NULL)
  552. {
  553. ::SysFreeString(pClass->bstrProgID);
  554. }
  555. if (pClass->bstrCatastropheURL != NULL)
  556. {
  557. ::SysFreeString(pClass->bstrCatastropheURL);
  558. }
  559. if (pClass->bstrVirtualDirectory != NULL)
  560. {
  561. ::SysFreeString(pClass->bstrVirtualDirectory);
  562. }
  563. if (pClass->bstrFirstURL != NULL)
  564. {
  565. ::SysFreeString(pClass->bstrFirstURL);
  566. }
  567. if (pClass->bstrASPName != NULL)
  568. {
  569. ::SysFreeString(pClass->bstrASPName);
  570. }
  571. delete pClass;
  572. }
  573. */
  574. //////////////////////////////////////////////////////////////////////
  575. //
  576. // inline void WCS_FreeNode(WCS_NODE *pNode)
  577. //
  578. // Frees all embedded BSTRs and invokes delete on structure
  579. //
  580. //////////////////////////////////////////////////////////////////////
  581. /*
  582. inline void WCS_FreeNode(WCS_NODE *pNode)
  583. {
  584. if (pNode->bstrName != NULL)
  585. {
  586. ::SysFreeString(pNode->bstrName);
  587. }
  588. if (WCS_NODE_TYPE_NESTED_WEBCLASS == pNode->bType)
  589. {
  590. if (pNode->bstrProgID != NULL)
  591. {
  592. ::SysFreeString(pNode->bstrProgID);
  593. }
  594. }
  595. else if ( (WCS_NODE_TYPE_PAGE == pNode->bType) ||
  596. (WCS_DTNODE_TYPE_PAGE == pNode->bType) )
  597. {
  598. if (pNode->bstrTemplate != NULL)
  599. {
  600. ::SysFreeString(pNode->Page.bstrTemplate);
  601. }
  602. if (pNode->Page.bstrToken != NULL)
  603. {
  604. ::SysFreeString(pNode->Page.bstrToken);
  605. }
  606. if (pNode->Page.bstrAppendedParams != NULL)
  607. {
  608. ::SysFreeString(pNode->Page.bstrAppendedParams);
  609. }
  610. }
  611. delete pNode;
  612. }
  613. //////////////////////////////////////////////////////////////////////
  614. //
  615. // inline void WCS_FreeDTNode(WCS_NODE *pNode)
  616. //
  617. // Frees all embedded BSTRs and invokes delete on structure
  618. //
  619. //////////////////////////////////////////////////////////////////////
  620. inline void WCS_FreeDTNode(WCS_DTNODE *pNode)
  621. {
  622. if ( (WCS_DTNODE_TYPE_URL_BOUND_TAG == pNode->bType) ||
  623. (WCS_DTNODE_TYPE_EVENT_BOUND_TAG == pNode->bType) )
  624. {
  625. if (NULL != pNode->DTEvent.bstrOriginalHref)
  626. {
  627. ::SysFreeString(pNode->DTEvent.bstrOriginalHref);
  628. }
  629. }
  630. else if (WCS_DTNODE_TYPE_PAGE == pNode->bType)
  631. {
  632. if (NULL != pNode->DTPage.bstrHTMLTemplateSrcName)
  633. {
  634. ::SysFreeString(pNode->DTPage.bstrHTMLTemplateSrcName);
  635. }
  636. }
  637. WCS_FreeNode(pNode);
  638. }
  639. //////////////////////////////////////////////////////////////////////
  640. //
  641. // inline HRESULT WCS_ReadWebClass(IStream *pStream,
  642. // WCS_WEBCLASS **ppClass)
  643. //
  644. //
  645. //////////////////////////////////////////////////////////////////////
  646. inline HRESULT WCS_ReadWebClass(IStream *pStream, WCS_WEBCLASS **ppClass)
  647. {
  648. HRESULT hr = S_OK;
  649. ULONG cbRead = 0;
  650. ULONG acbStrings[6];
  651. BSTR *apbstrStrings[6];
  652. // allocate structure
  653. *ppClass = new WCS_WEBCLASS;
  654. CSF_CHECK(*ppClass != NULL, E_OUTOFMEMORY, CSF_TRACE_INTERNAL_ERRORS);
  655. // read structure from stream
  656. hr = pStream->Read(*ppClass, sizeof(**ppClass), &cbRead);
  657. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  658. CSF_CHECK(sizeof(**ppClass) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  659. (*ppClass)->pvData = NULL; // don't take junk pointer value from stream
  660. // TODO: need error codes for version incompatibility, handle backlevel formats etc.
  661. CSF_CHECK(WCS_WEBCLASS_VER_MAJOR == (*ppClass)->wVerMajor, STG_E_OLDFORMAT, CSF_TRACE_EXTERNAL_ERRORS);
  662. CSF_CHECK(WCS_WEBCLASS_VER_MAJOR == (*ppClass)->wVerMinor, STG_E_OLDFORMAT, CSF_TRACE_EXTERNAL_ERRORS);
  663. // read string lengths from stream
  664. hr = pStream->Read(acbStrings, sizeof(acbStrings), &cbRead);
  665. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  666. CSF_CHECK(sizeof(acbStrings) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  667. // set up array of string pointer addresses
  668. apbstrStrings[0] = &((*ppClass)->bstrName);
  669. apbstrStrings[1] = &((*ppClass)->bstrProgID);
  670. apbstrStrings[2] = &((*ppClass)->bstrCatastropheURL);
  671. apbstrStrings[3] = &((*ppClass)->bstrVirtualDirectory);
  672. apbstrStrings[4] = &((*ppClass)->bstrFirstURL);
  673. apbstrStrings[5] = &((*ppClass)->bstrASPName);
  674. // read strings from stream
  675. hr = ReadStrings(pStream, acbStrings, apbstrStrings,
  676. (sizeof(acbStrings) / sizeof(acbStrings[0])) );
  677. CLEANUP:
  678. if (FAILED(hr) && (*ppClass != NULL))
  679. {
  680. WCS_FreeWebClass(*ppClass);
  681. *ppClass = NULL;
  682. }
  683. return hr;
  684. }
  685. //=--------------------------------------------------------------------------=
  686. //
  687. // inline HRESULT WCS_ReadNodeFromStream(IStream *pStream, WCS_NODE *pNode)
  688. //
  689. // Reads a WCS_NODE structure from a stream. Caller passes in node.
  690. //
  691. //=--------------------------------------------------------------------------=
  692. inline HRESULT WCS_ReadNodeFromStream(IStream *pStream, WCS_NODE *pNode)
  693. {
  694. HRESULT hr = S_OK;
  695. ULONG cbRead = 0;
  696. ULONG acbStrings[4];
  697. BSTR *apbstrStrings[4];
  698. int cStrings = 0;
  699. // read structure from stream
  700. hr = pStream->Read(pNode, sizeof(*pNode), &cbRead);
  701. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  702. CSF_CHECK(sizeof(*pNode) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  703. // TODO: need error codes for version incompatibility, handle backlevel formats etc.
  704. CSF_CHECK(WCS_NODE_VER_MAJOR == pNode->wVerMajor, STG_E_OLDFORMAT, CSF_TRACE_EXTERNAL_ERRORS);
  705. CSF_CHECK(WCS_NODE_VER_MINOR == pNode->wVerMinor, STG_E_OLDFORMAT, CSF_TRACE_EXTERNAL_ERRORS);
  706. // set up array of string pointer addresses according to node type
  707. apbstrStrings[0] = &(pNode->bstrName);
  708. if ( (WCS_NODE_TYPE_NESTED_WEBCLASS == pNode->bType) ||
  709. (WCS_DTNODE_TYPE_NESTED_WEBCLASS == pNode->bType) )
  710. {
  711. apbstrStrings[1] = &(pNode->bstrProgID);
  712. cStrings = 2;
  713. }
  714. else if ( (WCS_NODE_TYPE_PAGE == pNode->bType) ||
  715. (WCS_DTNODE_TYPE_PAGE == pNode->bType) )
  716. {
  717. apbstrStrings[1] = &(pNode->bstrTemplate);
  718. apbstrStrings[2] = &(pNode->bstrToken);
  719. apbstrStrings[3] = &(pNode->bstrAppendedParams);
  720. cStrings = 4;
  721. }
  722. else if ( (WCS_NODE_TYPE_EVENT == bType) ||
  723. IsDTEvent(bType) )
  724. {
  725. cStrings = 1;
  726. }
  727. else
  728. {
  729. CSF_CHECK(FALSE, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  730. }
  731. // read string lengths from stream
  732. hr = pStream->Read(acbStrings, sizeof(acbStrings), &cbRead);
  733. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  734. CSF_CHECK(sizeof(acbStrings) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  735. // read strings from stream
  736. hr = ReadStrings(pStream, acbStrings, apbstrStrings, cStrings);
  737. CLEANUP:
  738. return hr;
  739. }
  740. //////////////////////////////////////////////////////////////////////
  741. //
  742. // inline HRESULT WCS_ReadNode(IStream *pStream, WCS_NODE **ppNode)
  743. //
  744. // Allocates a WCS_NODE structure and reads its contents from the
  745. // stream.
  746. //
  747. //////////////////////////////////////////////////////////////////////
  748. inline HRESULT WCS_ReadNode(IStream *pStream, WCS_NODE **ppNode)
  749. {
  750. HRESULT hr = S_OK;
  751. // allocate structure
  752. *ppNode = new WCS_NODE;
  753. CSF_CHECK(*ppNode != NULL, E_OUTOFMEMORY, CSF_TRACE_INTERNAL_ERRORS);
  754. // read node in from stream
  755. hr = WCS_ReadNodeFromStream(pStream, *ppNode);
  756. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
  757. CLEANUP:
  758. if (FAILED(hr) && (*ppNode != NULL))
  759. {
  760. WCS_FreeNode(*ppNode);
  761. *ppNode = NULL;
  762. }
  763. return hr;
  764. }
  765. //=--------------------------------------------------------------------------=
  766. //
  767. // inline HRESULT WCS_ReadDTNode(IStream *pStream, WCS_DTNODE **ppNode)
  768. //
  769. // Allocates a WCS_DTNODE and reads its contents from the stream.
  770. //
  771. //=--------------------------------------------------------------------------=
  772. inline HRESULT WCS_ReadDTNode(IStream *pStream, WCS_DTNODE **ppNode)
  773. {
  774. HRESULT hr = S_OK;
  775. ULONG cbRead = 0;
  776. ULONG acbStrings[1];
  777. BSTR *apbstrStrings[1];
  778. int cStrings = 0;
  779. // allocate structure
  780. *ppNode = new WCS_DTNODE;
  781. CSF_CHECK(*ppNode != NULL, E_OUTOFMEMORY, CSF_TRACE_INTERNAL_ERRORS);
  782. // read base class WCS_NODE first
  783. hr = WCS_ReadNodeFromStream(pStream, *ppNode);
  784. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
  785. // read design time fields
  786. if (WCS_DTNODE_TYPE_PAGE == (*ppNode)->bType)
  787. {
  788. hr = pStream->Read(&(*ppNode)->DTPage, sizeof((*ppNode)->DTPage), &cbRead);
  789. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  790. CSF_CHECK(sizeof((*ppNode)->DTPage) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  791. }
  792. else if (WCS_DTNODE_TYPE_NESTED_WEBCLASS != (*ppNode)->bType)
  793. {
  794. hr = pStream->Read(&(*ppNode)->DTEvent, sizeof((*ppNode)->DTEvent), &cbRead);
  795. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  796. CSF_CHECK(sizeof((*ppNode)->DTEvent) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  797. }
  798. // read design time string lengths from stream
  799. hr = pStream->Read(acbStrings, sizeof(acbStrings), &cbRead);
  800. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  801. CSF_CHECK(sizeof(acbStrings) == cbRead, STG_E_DOCFILECORRUPT, CSF_TRACE_EXTERNAL_ERRORS);
  802. // now check if there are any strings to read
  803. // if yes then set up array of string pointer addresses
  804. if (0 == acbStrings[0])
  805. {
  806. // There are no strings to read so store NULL pointers
  807. if (WCS_DTNODE_TYPE_PAGE == (*ppNode)->bType)
  808. {
  809. (*ppNode)->DTPage.bstrHTMLTemplateSrcName = NULL;
  810. }
  811. else if (WCS_DTNODE_TYPE_NESTED_WEBCLASS != (*ppNode)->bType)
  812. {
  813. (*ppNode)->DTEvent.bstrOriginalHref = NULL;
  814. }
  815. goto CLEANUP;
  816. }
  817. else // There are strings so read them from the stream
  818. {
  819. if (WCS_DTNODE_TYPE_PAGE == (*ppNode)->bType)
  820. {
  821. apbstrStrings[0] = &((*ppNode)->DTPage.bstrHTMLTemplateSrcName);
  822. }
  823. else if (WCS_DTNODE_TYPE_NESTED_WEBCLASS != (*ppNode)->bType)
  824. {
  825. apbstrStrings[0] = &((*ppNode)->DTEvent.bstrOriginalHref);
  826. }
  827. cStrings++;
  828. }
  829. // read strings from stream
  830. if (cStrings > 0)
  831. {
  832. hr = ReadStrings(pStream, acbStrings, apbstrStrings, cStrings);
  833. }
  834. CLEANUP:
  835. if (FAILED(hr) && (*ppNode != NULL))
  836. {
  837. WCS_FreeDTNode(*ppNode);
  838. *ppNode = NULL;
  839. }
  840. return hr;
  841. }
  842. //////////////////////////////////////////////////////////////////////
  843. //
  844. // inline HRESULT WCS_WriteWebClass(IStream *pStream, WCS_WEBCLASS *pClass)
  845. //
  846. //
  847. //////////////////////////////////////////////////////////////////////
  848. inline HRESULT WCS_WriteWebClass(IStream *pStream, WCS_WEBCLASS *pClass)
  849. {
  850. HRESULT hr = S_OK;
  851. ULONG cbWritten = 0;
  852. ULONG acbStrings[6];
  853. BSTR abstrStrings[6];
  854. // set version numbers
  855. pClass->wVerMajor = WCS_WEBCLASS_VER_MAJOR;
  856. pClass->wVerMinor = WCS_WEBCLASS_VER_MAJOR;
  857. // write WebClass structure to stream
  858. hr = pStream->Write(pClass, sizeof(*pClass), &cbWritten);
  859. CSF_CHECK(hr == S_OK, hr, CSF_TRACE_EXTERNAL_ERRORS);
  860. CSF_CHECK(cbWritten == sizeof(*pClass), STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  861. // get lengths of strings and write them to stream
  862. acbStrings[0] = SysStringByteLen(pClass->bstrName);
  863. acbStrings[1] = SysStringByteLen(pClass->bstrProgID);
  864. acbStrings[2] = SysStringByteLen(pClass->bstrCatastropheURL);
  865. acbStrings[3] = SysStringByteLen(pClass->bstrVirtualDirectory);
  866. acbStrings[4] = SysStringByteLen(pClass->bstrFirstURL);
  867. acbStrings[5] = SysStringByteLen(pClass->bstrASPName);
  868. hr = pStream->Write(acbStrings, sizeof(acbStrings), &cbWritten);
  869. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  870. CSF_CHECK(cbWritten == sizeof(acbStrings), STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  871. // set up array of pointers to strings to be written to stream
  872. abstrStrings[0] = pClass->bstrName;
  873. abstrStrings[1] = pClass->bstrProgID;
  874. abstrStrings[2] = pClass->bstrCatastropheURL;
  875. abstrStrings[3] = pClass->bstrVirtualDirectory;
  876. abstrStrings[4] = pClass->bstrFirstURL;
  877. abstrStrings[5] = pClass->bstrASPName;
  878. // write strings to stream
  879. hr = WriteStrings(pStream, acbStrings, abstrStrings,
  880. (sizeof(acbStrings) / sizeof(acbStrings[0])) );
  881. CLEANUP:
  882. return hr;
  883. }
  884. //////////////////////////////////////////////////////////////////////
  885. //
  886. // inline HRESULT WCS_WriteNode(IStream *pStream, WCS_NODE *pNode)
  887. //
  888. //
  889. //////////////////////////////////////////////////////////////////////
  890. inline HRESULT WCS_WriteNode(IStream *pStream, WCS_NODE *pNode)
  891. {
  892. HRESULT hr = S_OK;
  893. ULONG cbWritten = 0;
  894. ULONG acbStrings[4];
  895. BSTR abstrStrings[4];
  896. int cStrings = 0;
  897. // set version numbers in node
  898. pNode->wVerMajor = WCS_NODE_VER_MAJOR;
  899. pNode->wVerMinor = WCS_NODE_VER_MINOR;
  900. // write node structure to stream
  901. hr = pStream->Write(pNode, sizeof(*pNode), &cbWritten);
  902. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  903. CSF_CHECK(sizeof(*pNode) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  904. // set up array of strings to be written to stream and
  905. // determine how many there will be
  906. abstrStrings[0] = pNode->bstrName;
  907. acbStrings[0] = ::SysStringByteLen(pNode->bstrName);
  908. if ( (WCS_NODE_TYPE_NESTED_WEBCLASS == pNode->bType) ||
  909. (WCS_DTNODE_TYPE_NESTED_WEBCLASS == pNode->bType) )
  910. {
  911. abstrStrings[1] = pNode->Nested.bstrProgID;
  912. acbStrings[1] = ::SysStringByteLen(pNode->Nested.bstrProgID);
  913. cStrings = 2;
  914. }
  915. else if ( (WCS_NODE_TYPE_PAGE == pNode->bType) ||
  916. (WCS_DTNODE_TYPE_PAGE == pNode->bType) )
  917. {
  918. abstrStrings[1] = pNode->Page.bstrTemplate;
  919. acbStrings[1] = ::SysStringByteLen(pNode->Page.bstrTemplate);
  920. abstrStrings[2] = pNode->Page.bstrToken;
  921. acbStrings[2] = ::SysStringByteLen(pNode->Page.bstrToken);
  922. abstrStrings[3] = pNode->Page.bstrAppendedParams;
  923. acbStrings[3] = ::SysStringByteLen(pNode->Page.bstrAppendedParams);
  924. cStrings = 4;
  925. }
  926. else if ( (WCS_NODE_TYPE_EVENT == pNode->bType) ||
  927. WCS_IsDTEvent(pNode->bType) )
  928. {
  929. cStrings = 1;
  930. }
  931. else
  932. {
  933. CSF_CHECK(FALSE, E_INVALIDARG, CSF_TRACE_INTERNAL_ERRORS);
  934. }
  935. // write string lengths to stream
  936. hr = pStream->Write(acbStrings, sizeof(acbStrings), &cbWritten);
  937. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  938. CSF_CHECK(sizeof(acbStrings) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  939. // write strings to stream
  940. hr = WriteStrings(pStream, acbStrings, abstrStrings, cStrings);
  941. CLEANUP:
  942. return hr;
  943. }
  944. //=--------------------------------------------------------------------------=
  945. //
  946. // inline HRESULT WCS_WriteDTNode(IStream *pStream, WCS_DTNODE *pNode)
  947. //
  948. // Write design time node. Write the base class runtime node and then
  949. // then extra stuff in the design time node.
  950. //
  951. //=--------------------------------------------------------------------------=
  952. inline HRESULT WCS_WriteDTNode(IStream *pStream, WCS_DTNODE *pNode)
  953. {
  954. HRESULT hr = S_OK;
  955. ULONG cbWritten = 0;
  956. ULONG acbStrings[1] = { 0 };
  957. BSTR abstrStrings[1];
  958. int cStrings = 0;
  959. // write run time node first
  960. hr = WCS_WriteNode(pStream, pNode);
  961. CSF_CHECK(hr == S_OK, hr, CSF_TRACE_INTERNAL_ERRORS);
  962. // write design time fields
  963. if (WCS_DTNODE_TYPE_PAGE == pNode->bType)
  964. {
  965. hr = pStream->Write(&pNode->DTPage, sizeof(pNode->DTPage), &cbWritten);
  966. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  967. CSF_CHECK(sizeof(pNode->DTPage) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  968. if (NULL != pNode->DTPage.bstrHTMLTemplateSrcName)
  969. {
  970. abstrStrings[0] = pNode->DTPage.bstrHTMLTemplateSrcName;
  971. acbStrings[0] = ::SysStringByteLen(pNode->DTPage.bstrHTMLTemplateSrcName);
  972. cStrings++;
  973. }
  974. }
  975. else if (WCS_DTNODE_TYPE_NESTED_WEBCLASS != pNode->bType)
  976. {
  977. hr = pStream->Write(&pNode->DTEvent, sizeof(pNode->DTEvent), &cbWritten);
  978. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  979. CSF_CHECK(sizeof(pNode->DTEvent) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  980. if (NULL != pNode->DTEvent.bstrOriginalHref)
  981. {
  982. abstrStrings[0] = pNode->DTEvent.bstrOriginalHref;
  983. acbStrings[0] = ::SysStringByteLen(pNode->DTEvent.bstrOriginalHref);
  984. cStrings++;
  985. }
  986. }
  987. hr = pStream->Write(acbStrings, sizeof(acbStrings), &cbWritten);
  988. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_EXTERNAL_ERRORS);
  989. CSF_CHECK(sizeof(acbStrings) == cbWritten, STG_E_WRITEFAULT, CSF_TRACE_EXTERNAL_ERRORS);
  990. if (cStrings > 0)
  991. {
  992. hr = WriteStrings(pStream, acbStrings, abstrStrings, cStrings);
  993. CSF_CHECK(S_OK == hr, hr, CSF_TRACE_INTERNAL_ERRORS);
  994. }
  995. CLEANUP:
  996. return hr;
  997. }
  998. */
  999. #define _WBCLSSER_H_
  1000. #endif // _WBCLSSER_H_