XTPPropExchange.cpp
上传用户:szled88
上传日期:2015-04-09
资源大小:43957k
文件大小:61k
源码类别:

对话框与窗口

开发平台:

Visual C++

  1. // XTPPropExchange.cpp: implementation of the CXTPPropExchange class.
  2. //
  3. // This file is a part of the XTREME TOOLKIT PRO MFC class library.
  4. // (c)1998-2008 Codejock Software, All Rights Reserved.
  5. //
  6. // THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
  7. // RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
  8. // CONSENT OF CODEJOCK SOFTWARE.
  9. //
  10. // THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
  11. // IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
  12. // YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
  13. // SINGLE COMPUTER.
  14. //
  15. // CONTACT INFORMATION:
  16. // support@codejock.com
  17. // http://www.codejock.com
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "XTPMacros.h"
  22. #include "XTPPropExchange.h"
  23. #include "XTPVC80Helpers.h"
  24. #include "XTPVC50Helpers.h"
  25. #include "XTPResourceManager.h"
  26. #ifdef _DEBUG
  27. #undef THIS_FILE
  28. static char THIS_FILE[] = __FILE__;
  29. #define new DEBUG_NEW
  30. #endif
  31. #pragma warning(disable : 4310)
  32. #ifdef _UNICODE
  33. #define CT2BSTR(x) (BSTR)(LPCWSTR)x
  34. #else
  35. #define CT2BSTR(x) (BSTR)XTP_CT2CW(x)
  36. #endif
  37. enum VARTYPE_EX
  38. {
  39. VT_EX_RECT = 100,
  40. VT_EX_SIZE = 101
  41. };
  42. LCID CXTPPropExchange::m_lcidDateTime = XTP_LOCALE_ISO8601;
  43. /////////////////////////////////////////////////////////////////////////////
  44. BOOL ParseDateTimeISO8601(COleDateTime& rDT, LPCTSTR pcszDateTime)
  45. {
  46. SYSTEMTIME st;
  47. ZeroMemory(&st, sizeof(SYSTEMTIME));
  48. int nResult = SCANF_S(pcszDateTime, _T("%hu-%hu-%huT%hu:%hu:%hu"),
  49. &st.wYear, &st.wDay, &st.wMonth, &st.wHour, &st.wMinute, &st.wSecond);
  50. if (nResult == 3 || nResult == 5 || nResult == 6)
  51. {
  52. COleDateTime dtTemp(st);
  53. if (dtTemp.GetStatus() != COleDateTime::valid)
  54. return FALSE;
  55. rDT = dtTemp;
  56. return TRUE;
  57. }
  58. ZeroMemory(&st, sizeof(SYSTEMTIME));
  59. nResult = SCANF_S(pcszDateTime, _T("%hu:%hu:%hu"),
  60. &st.wHour, &st.wMinute, &st.wSecond);
  61. if (nResult == 2 || nResult == 3)
  62. {
  63. double dblTime = (((long)st.wHour * 3600L) +  // hrs in seconds
  64. ((long)st.wMinute * 60L) +  // mins in seconds
  65. ((long)st.wSecond)) / 86400.;
  66. rDT = dblTime;
  67. return TRUE;
  68. }
  69. return FALSE;
  70. }
  71. CString FormatDateTimeISO8601(const COleDateTime& dt)
  72. {
  73. ASSERT(dt.m_status == COleDateTime::valid);
  74. CString strValue;
  75. if ((DWORD)dt == 0)
  76. {
  77. strValue = dt.Format(_T("%H:%M:%S"));
  78. }
  79. else if ((double)(DWORD)(dt) == (double)dt)
  80. {
  81. strValue = dt.Format(_T("%Y-%d-%m"));
  82. }
  83. else
  84. {
  85. strValue = dt.Format(_T("%Y-%d-%mT%H:%M:%S"));
  86. }
  87. return strValue;
  88. }
  89. //////////////////////////////////////////////////////////////////////////
  90. // CXTPPropExchangeEnumerator
  91. CXTPPropExchangeEnumerator::CXTPPropExchangeEnumerator(CXTPPropExchange* pContainer, LPCTSTR lpszSection)
  92. {
  93. m_pContainer = pContainer;
  94. m_strSectionName = lpszSection;
  95. m_nCount = 0;
  96. }
  97. CXTPPropExchangeEnumerator::~CXTPPropExchangeEnumerator()
  98. {
  99. }
  100. POSITION CXTPPropExchangeEnumerator::GetPosition(DWORD dwCount /*= 0*/, BOOL bCompactMode /*= TRUE*/)
  101. {
  102. m_nCount = dwCount;
  103. if (!m_pContainer)
  104. return NULL;
  105. if (!bCompactMode)
  106. {
  107. PX_DWord(m_pContainer, _T("Count"), m_nCount, 0);
  108. }
  109. else
  110. {
  111. if (m_pContainer->IsStoring())
  112. m_pContainer->WriteCount(m_nCount);
  113. else
  114. m_nCount = m_pContainer->ReadCount();
  115. }
  116. return m_nCount == 0 ? NULL : (POSITION)1;
  117. }
  118. CXTPPropExchange* CXTPPropExchangeEnumerator::GetNext(POSITION& pos)
  119. {
  120. CString strSection;
  121. strSection.Format(_T("%s%i"), (LPCTSTR)m_strSectionName, (DWORD)(DWORD_PTR)pos - 1);
  122. CXTPPropExchange* pSection = m_pContainer->GetSection(strSection);
  123. pos++;
  124. if ((DWORD)(DWORD_PTR)pos > m_nCount) pos = NULL;
  125. return pSection;
  126. }
  127. //////////////////////////////////////////////////////////////////////
  128. // Construction/Destruction
  129. //////////////////////////////////////////////////////////////////////
  130. IMPLEMENT_DYNAMIC(CXTPPropExchange, CCmdTarget)
  131. CXTPPropExchange::CXTPPropExchange()
  132. {
  133. m_bLoading = FALSE;
  134. m_dwData = 0;
  135. m_pOwner = NULL;
  136. m_nSchema = _XTP_SCHEMA_CURRENT;
  137. m_bChildSection = FALSE;
  138. m_bInitialized = FALSE;
  139. m_bEmptySection = FALSE;
  140. m_bUseDefaultOnLoad = TRUE;
  141. m_bUseDefaultOnSave = TRUE;
  142. }
  143. CXTPPropExchange::~CXTPPropExchange()
  144. {
  145. }
  146. void CXTPPropExchange::InitSection(CXTPPropExchange* pRootSection)
  147. {
  148. ASSERT(m_bLoading == pRootSection->m_bLoading);
  149. m_bChildSection = TRUE;
  150. m_nSchema = pRootSection->m_nSchema;
  151. m_dwData = pRootSection->m_dwData;
  152. m_bEmptySection = pRootSection->m_bEmptySection;
  153. m_bUseDefaultOnLoad = pRootSection->m_bUseDefaultOnLoad;
  154. m_bUseDefaultOnSave = pRootSection->m_bUseDefaultOnSave;
  155. }
  156. void CXTPPropExchange::EmptySection()
  157. {
  158. m_bEmptySection = TRUE;
  159. }
  160. DWORD CXTPPropExchange::GetSizeOfVarType(VARTYPE vt)
  161. {
  162. switch (vt)
  163. {
  164. case VT_BOOL: return sizeof(BOOL);
  165. case VT_UI1: return sizeof(BYTE);
  166. case VT_I2: return 2;
  167. case VT_I4: return 4;
  168. case VT_R4:
  169. ASSERT(sizeof(float) == 4);
  170. return 4;
  171. case VT_R8:
  172. ASSERT(sizeof(double) == 8);
  173. return 8;
  174. case VT_EX_RECT: return sizeof(RECT);
  175. case VT_EX_SIZE: return sizeof(SIZE);
  176. case VT_CY: return sizeof(CURRENCY);
  177. case VT_BSTR:return sizeof(BSTR);
  178. case VT_VARIANT: return sizeof(VARIANT);
  179. case VT_DATE: return sizeof(COleDateTime);
  180. }
  181. return 0;
  182. }
  183. void CXTPPropExchange::Write (LPCTSTR pszPropName, const void* lpBuf, UINT nCount)
  184. {
  185. ASSERT(IsStoring());
  186. ASSERT(lpBuf != NULL);
  187. ExchangeBlobProp(pszPropName, (BYTE*&)lpBuf, (DWORD&)nCount);
  188. }
  189. UINT CXTPPropExchange::Read (LPCTSTR pszPropName, void* lpBuf, UINT nCount)
  190. {
  191. ASSERT(IsLoading());
  192. ASSERT(lpBuf != NULL);
  193. if (!ExchangeBlobProp(pszPropName, (BYTE*&)lpBuf, (DWORD&)nCount))
  194. return 0;
  195. return nCount;
  196. }
  197. AFX_INLINE int REPLACEW_S(BSTR& strReplace, LPCWSTR lpszOld, LPCWSTR lpszNew)
  198. {
  199. int nOldLength = (strReplace == NULL) ? 0 : (int)wcslen(strReplace);
  200. int nSourceLen = (lpszOld == NULL) ? 0 : (int)wcslen(lpszOld);
  201. if (nSourceLen == 0 || nOldLength == 0)
  202. return 0;
  203. int nReplacementLen = (lpszNew == NULL) ? 0 : (int)wcslen(lpszNew);
  204. // loop once to figure out the size of the result string
  205. int nCount = 0;
  206. LPWSTR lpszStart = strReplace;
  207. LPWSTR lpszTarget;
  208. while ((lpszTarget = wcsstr(lpszStart, lpszOld)) != NULL)
  209. {
  210. nCount++;
  211. lpszStart = lpszTarget + nSourceLen;
  212. }
  213. // if any changes were made, make them
  214. if (nCount > 0)
  215. {
  216. int nNewLength = nOldLength + (nReplacementLen-nSourceLen)*nCount;
  217. ASSERT(nNewLength <= nOldLength); // not implemented
  218. lpszStart = strReplace;
  219. // loop again to actually do the work
  220. while ((lpszTarget = wcsstr(lpszStart, lpszOld)) != NULL)
  221. {
  222. int nBalance = nOldLength - int(lpszTarget - strReplace + nSourceLen);
  223. MEMMOVE_S(lpszTarget + nReplacementLen, lpszTarget + nSourceLen,
  224. nBalance * sizeof(WORD));
  225. MEMCPY_S(lpszTarget, lpszNew, nReplacementLen*sizeof(WORD));
  226. lpszStart = lpszTarget + nReplacementLen;
  227. lpszStart[nBalance] = '';
  228. nOldLength += (nReplacementLen - nSourceLen);
  229. }
  230. ASSERT(strReplace[nNewLength] == '');
  231. }
  232. return nCount;
  233. }
  234. void CXTPPropExchange::PreformatString(BSTR bstrValue)
  235. {
  236. ASSERT(bstrValue && m_bLoading);
  237. REPLACEW_S(bstrValue, L"\\", L"0101");
  238. REPLACEW_S(bstrValue, L"\n", L"n");
  239. REPLACEW_S(bstrValue, L"\r", L"r");
  240. REPLACEW_S(bstrValue, L"\t", L"t");
  241. REPLACEW_S(bstrValue, L"0101", L"\");
  242. }
  243. void CXTPPropExchange::PreformatString(CString& strValue, BOOL bLoading)
  244. {
  245. if (bLoading)
  246. {
  247. if (strValue.Find(_T('\')) == -1)
  248. return;
  249. REPLACE_S(strValue, _T("\\"), _T("0101"));
  250. REPLACE_S(strValue, _T("\n"), _T("n"));
  251. REPLACE_S(strValue, _T("\r"), _T("r"));
  252. REPLACE_S(strValue, _T("\t"), _T("t"));
  253. REPLACE_S(strValue, _T("0101"), _T("\"));
  254. }
  255. else
  256. {
  257. REPLACE_S(strValue, _T("\"), _T("\\"));
  258. REPLACE_S(strValue, _T("n"), _T("\n"));
  259. REPLACE_S(strValue, _T("r"), _T("\r"));
  260. REPLACE_S(strValue, _T("t"), _T("\t"));
  261. }
  262. }
  263. void CXTPPropExchange::PreformatString(CString& strValue)
  264. {
  265. PreformatString(strValue, m_bLoading);
  266. }
  267. BOOL CXTPPropExchange::ExchangePropDateHelper(CString& strValue, COleDateTime& dt)
  268. {
  269. if (m_lcidDateTime == XTP_LOCALE_ISO8601)
  270. {
  271. if (m_bLoading)
  272. {
  273. return ParseDateTimeISO8601(dt, strValue);
  274. }
  275. else
  276. {
  277. strValue = FormatDateTimeISO8601(dt);
  278. }
  279. return TRUE;
  280. }
  281. if (m_bLoading)
  282. {
  283. if (!dt.ParseDateTime(strValue, 0, m_lcidDateTime))
  284. return FALSE;
  285. }
  286. else
  287. {
  288. TRY
  289. {
  290. strValue = dt.Format(0, m_lcidDateTime);
  291. }
  292. CATCH_ALL(e)
  293. {
  294. VERIFY(strValue.LoadString(AFX_IDS_INVALID_DATETIME));
  295. }
  296. END_CATCH_ALL
  297. }
  298. return TRUE;
  299. }
  300. BOOL CXTPPropExchange::ExchangePropStringHelper(CString& strValue, VARTYPE vtProp,
  301. void* pvProp, const void* pvDefault)
  302. {
  303. if (m_bLoading)
  304. {
  305. switch (vtProp)
  306. {
  307. case VT_UI1:
  308. case VT_I2:
  309. case VT_I4:
  310. case VT_BOOL:
  311. {
  312. int dwValue = _ttoi(strValue);
  313. return CopyPropValue(vtProp, pvProp, &dwValue);
  314. }
  315. case VT_R4:
  316. {
  317. TCHAR* pChar = NULL;
  318. float fValue = (float)_tcstod(strValue, &pChar);
  319. return CopyPropValue(vtProp, pvProp, &fValue);
  320. }
  321. case VT_R8:
  322. {
  323. TCHAR* pChar = NULL;
  324. double fValue = _tcstod(strValue, &pChar);
  325. return CopyPropValue(vtProp, pvProp, &fValue);
  326. }
  327. case VT_DATE:
  328. {
  329. COleDateTime dt;
  330. if (!ExchangePropDateHelper(strValue, dt))
  331. return FALSE;
  332. *(COleDateTime*)pvProp = dt;
  333. return TRUE;
  334. }
  335. case VT_BSTR:
  336. ASSERT(FALSE);
  337. return FALSE;
  338. case VT_LPSTR:
  339. case VT_EX_SIZE:
  340. case VT_EX_RECT:
  341. {
  342. if (vtProp == VT_EX_SIZE)
  343. {
  344. SIZE sz = {0, 0};
  345. if (SCANF_S(strValue, _T("%i, %i"), &sz.cx, &sz.cy) != 2)
  346. return CopyPropValue(vtProp, pvProp, pvDefault);
  347. *((LPSIZE)pvProp) = sz;
  348. }
  349. else if (vtProp == VT_EX_RECT)
  350. {
  351. RECT rc = {0, 0, 0, 0};
  352. if (SCANF_S(strValue, _T("%i, %i, %i, %i"), &rc.left, &rc.top, &rc.right, &rc.bottom) != 4)
  353. return CopyPropValue(vtProp, pvProp, pvDefault);
  354. *((LPRECT)pvProp) = rc;
  355. }
  356. else
  357. {
  358. PreformatString(strValue);
  359. *(CString*)pvProp = strValue;
  360. }
  361. return TRUE;
  362. }
  363. case VT_VARIANT:
  364. {
  365. COleVariant varValue(strValue);
  366. if (m_lcidDateTime == XTP_LOCALE_ISO8601)
  367. {
  368. COleDateTime dt;
  369. if (ParseDateTimeISO8601(dt, strValue))
  370. {
  371. varValue = dt;
  372. }
  373. }
  374. return CopyPropValue(vtProp, pvProp, &varValue);
  375. }
  376. }
  377. }
  378. else
  379. {
  380. switch (vtProp)
  381. {
  382. case VT_UI1:
  383. case VT_I2:
  384. case VT_I4:
  385. case VT_BOOL:
  386. {
  387. int nValue = 0;
  388. memcpy(&nValue, pvProp, GetSizeOfVarType(vtProp));
  389. strValue.Format(_T("%i"), nValue);
  390. }
  391. return TRUE;
  392. case VT_BSTR:
  393. ASSERT(FALSE);
  394. return FALSE;
  395. case VT_LPSTR:
  396. {
  397. strValue = *(CString*)pvProp;
  398. PreformatString(strValue);
  399. }
  400. return TRUE;
  401. case VT_DATE:
  402. {
  403. COleDateTime& dt = *(COleDateTime*)pvProp;
  404. ExchangePropDateHelper(strValue, dt);
  405. }
  406. return TRUE;
  407. case VT_R4:
  408. {
  409. double d = (double) *(float*)pvProp;
  410. strValue.Format(_T("%g"), d);
  411. return TRUE;
  412. }
  413. case VT_R8:
  414. strValue.Format(_T("%g"), *(double*)pvProp);
  415. return TRUE;
  416. case VT_EX_SIZE:
  417. {
  418. strValue.Format(_T("%i, %i"), ((LPSIZE)pvProp)->cx, ((LPSIZE)pvProp)->cy);
  419. }
  420. return TRUE;
  421. case VT_EX_RECT:
  422. {
  423. strValue.Format(_T("%i, %i, %i, %i"), ((LPRECT)pvProp)->left, ((LPRECT)pvProp)->top, ((LPRECT)pvProp)->right, ((LPRECT)pvProp)->bottom);
  424. }
  425. return TRUE;
  426. case VT_VARIANT:
  427. LCID lcidID = m_lcidDateTime;
  428. COleVariant& varProp = *((COleVariant*)pvProp);
  429. if (lcidID == XTP_LOCALE_ISO8601 && varProp.vt == VT_DATE)
  430. {
  431. strValue = FormatDateTimeISO8601(varProp.date);
  432. return TRUE;
  433. }
  434. if (lcidID == XTP_LOCALE_ISO8601)
  435. {
  436. lcidID = LOCALE_NEUTRAL;
  437. }
  438. COleVariant var;
  439. HRESULT hr = VariantChangeTypeEx(&var, &varProp, lcidID, 0, VT_BSTR);
  440. if (FAILED(hr) || var.vt != VT_BSTR)
  441. return FALSE;
  442. strValue = var.bstrVal;
  443. return TRUE;
  444. }
  445. }
  446. return FALSE;
  447. }
  448. BOOL CXTPPropExchange::ExchangeBlobProp(LPCTSTR pszPropName, BYTE*& pData, DWORD& nBytes)
  449. {
  450. if (IsStoring())
  451. {
  452. CString str;
  453. if (nBytes > 0)
  454. {
  455. LPTSTR lpsz = new TCHAR[nBytes * 2 + 1];
  456. for (UINT i = 0; i < nBytes; i++)
  457. {
  458. lpsz[i * 2] = (TCHAR)((pData[i] & 0x0F) + 'A'); //low nibble
  459. lpsz[i * 2 + 1] = (TCHAR)(((pData[i] >> 4) & 0x0F) + 'A'); //high nibble
  460. }
  461. lpsz[nBytes * 2] = 0;
  462. str = lpsz;
  463. delete[] lpsz;
  464. }
  465. PX_String(this, pszPropName, str, _T(""));
  466. }
  467. else
  468. {
  469. CString str;
  470. if (!PX_String(this, pszPropName, str))
  471. return FALSE;
  472. if (str.GetLength() > 0)
  473. {
  474. int nLen = str.GetLength();
  475. if ((nLen == 0) || (nLen % 2 != 0))
  476. return FALSE;
  477. DWORD nCount = nLen/2;
  478. if (pData == NULL)
  479. {
  480. pData = (BYTE*)malloc(nCount);
  481. nBytes = nCount;
  482. }
  483. if (pData == NULL)
  484. return FALSE;
  485. if (nBytes < nCount)
  486. return FALSE;
  487. for (int i = 0; i < nLen; i += 2)
  488. {
  489. (pData)[i/2] = (BYTE)
  490. (((str[i + 1] - 'A') << 4) + (str[i] - 'A'));
  491. }
  492. }
  493. }
  494. return TRUE;
  495. }
  496. BOOL CXTPPropExchange::IsSamePropValue(VARTYPE vtProp, const void* pv1, const void* pv2)
  497. {
  498. if (pv1 == pv2)
  499. return TRUE;
  500. if ((pv1 == NULL) || (pv2 == NULL))
  501. return FALSE;
  502. BOOL bSame = FALSE;
  503. switch (vtProp)
  504. {
  505. case VT_BSTR:
  506. bSame = wcscmp(*(BSTR*)pv1, (BSTR)pv2) == 0;
  507. break;
  508. case VT_LPSTR:
  509. bSame = ((CString*)pv1)->Compare((LPCTSTR)pv2) == 0;
  510. break;
  511. case VT_BOOL:
  512. case VT_UI1:
  513. case VT_I2:
  514. case VT_I4:
  515. case VT_CY:
  516. case VT_R4:
  517. case VT_R8:
  518. case VT_EX_RECT:
  519. case VT_EX_SIZE:
  520. bSame = memcmp(pv1, pv2, GetSizeOfVarType(vtProp)) == 0;
  521. break;
  522. case VT_VARIANT:
  523. bSame = *((COleVariant*)pv1) == *((COleVariant*)pv2);
  524. break;
  525. case VT_DATE:
  526. bSame = *((COleDateTime*)pv1) == *((COleDateTime*)pv2);
  527. break;
  528. }
  529. return bSame;
  530. }
  531. BOOL CXTPPropExchange::CopyPropValue(VARTYPE vtProp, void* pvDest, const void* pvSrc)
  532. {
  533. ASSERT(AfxIsValidAddress(pvDest, 1));
  534. if (pvSrc != NULL)
  535. {
  536. ASSERT(AfxIsValidAddress(pvSrc, 1, FALSE));
  537. switch (vtProp)
  538. {
  539. case VT_UI1:
  540. *(BYTE*)pvDest = *(BYTE*)pvSrc;
  541. break;
  542. case VT_I2:
  543. *(short*)pvDest = *(short*)pvSrc;
  544. break;
  545. case VT_I4:
  546. *(long*)pvDest = *(long*)pvSrc;
  547. break;
  548. case VT_BOOL:
  549. *(BOOL*)pvDest = *(BOOL*)pvSrc;
  550. break;
  551. case VT_BSTR:
  552. *(BSTR*)pvDest = SysAllocString((BSTR)pvSrc);
  553. break;
  554. case VT_LPSTR:
  555. *(CString*)pvDest = (LPCTSTR)pvSrc;
  556. break;
  557. case VT_CY:
  558. *(CY*)pvDest = *(CY*)pvSrc;
  559. break;
  560. case VT_R4:
  561. *(float*)pvDest = *(float*)pvSrc;
  562. break;
  563. case VT_R8:
  564. *(double*)pvDest = *(double*)pvSrc;
  565. break;
  566. case VT_EX_RECT:
  567. *(RECT*)pvDest = *(RECT*)pvSrc;
  568. break;
  569. case VT_EX_SIZE:
  570. *(SIZE*)pvDest = *(SIZE*)pvSrc;
  571. break;
  572. case VT_DATE:
  573. *(COleDateTime*)pvDest = *(COleDateTime*)pvSrc;
  574. break;
  575. case VT_VARIANT:
  576. TRY
  577. {
  578. *(COleVariant*)pvDest = *(COleVariant*)pvSrc;
  579. }
  580. CATCH_ALL(e)
  581. {
  582. return FALSE;
  583. }
  584. END_CATCH_ALL
  585. return TRUE;
  586. default:
  587. return FALSE;
  588. }
  589. }
  590. return pvSrc != NULL;
  591. }
  592. CRuntimeClass* CXTPPropExchange::FindRuntimeClass(LPCSTR szClassName)
  593. {
  594. CRuntimeClass* pClass;
  595. // search app specific classes
  596. AFX_MODULE_STATE* pModuleState = AfxGetModuleState();
  597. for (pClass = pModuleState->m_classList; pClass != NULL;
  598. pClass = pClass->m_pNextClass)
  599. {
  600. if (lstrcmpA(szClassName, pClass->m_lpszClassName) == 0)
  601. {
  602. return pClass;
  603. }
  604. }
  605. #ifdef _AFXDLL
  606. // search classes in shared DLLs
  607. for (CDynLinkLibrary* pDLL = pModuleState->m_libraryList; pDLL != NULL;
  608. pDLL = pDLL->m_pNextDLL)
  609. {
  610. for (pClass = pDLL->m_classList; pClass != NULL;
  611. pClass = pClass->m_pNextClass)
  612. {
  613. if (lstrcmpA(szClassName, pClass->m_lpszClassName) == 0)
  614. {
  615. return pClass;
  616. }
  617. }
  618. }
  619. #endif
  620. ASSERT(FALSE);
  621. return 0;
  622. }
  623. BOOL CXTPPropExchange::ExchangeRuntimeClass(LPCTSTR pszPropName, CRuntimeClass*& pClass, CRuntimeClass* pDefaultClass)
  624. {
  625. CString strClassName;
  626. if (!IsLoading())
  627. {
  628. strClassName = CString(pClass->m_lpszClassName);
  629. PX_String(this, pszPropName, strClassName, CString(pDefaultClass->m_lpszClassName));
  630. }
  631. else
  632. {
  633. if (!PX_String(this, pszPropName, strClassName))
  634. {
  635. pClass = pDefaultClass;
  636. return TRUE;
  637. }
  638. pClass = FindRuntimeClass(XTP_CT2CA(strClassName));
  639. if (!pClass)
  640. return FALSE;
  641. }
  642. return TRUE;
  643. }
  644. BOOL CXTPPropExchange::ExchangeObjectInstance(CObject*& pObject, CRuntimeClass* pObjectRuntime)
  645. {
  646. if (!IsLoading())
  647. {
  648. CRuntimeClass* pClass = pObject->GetRuntimeClass();
  649. PX_RuntimeClass(this, _T("Class"), pClass, pObjectRuntime);
  650. }
  651. else
  652. {
  653. CRuntimeClass* pClass = NULL;
  654. PX_RuntimeClass(this, _T("Class"), pClass, pObjectRuntime);
  655. if (!pClass)
  656. return FALSE;
  657. pObject = (CObject*)AfxDynamicDownCast(pObjectRuntime, pClass->CreateObject());
  658. if (!pObject)
  659. return FALSE;
  660. }
  661. return TRUE;
  662. }
  663. void CXTPPropExchange::WriteCount (DWORD dwCount)
  664. {
  665. PX_DWord(this, _T("Count"), dwCount, 0);
  666. }
  667. DWORD CXTPPropExchange::ReadCount()
  668. {
  669. DWORD nCount = 0;
  670. PX_DWord(this, _T("Count"), nCount, 0);
  671. return nCount;
  672. }
  673. CArchive* CXTPPropExchange::GetArchive(LPCTSTR pszPropName)
  674. {
  675. if (IsStoring())
  676. {
  677. CMemFile* pMemFile = new CMemFile();
  678. CArchive* pArchive = new CArchive(pMemFile, CArchive::store);
  679. return pArchive;
  680. }
  681. DWORD nBytes = 0;
  682. BYTE* pData = NULL;
  683. PX_Blob(this, pszPropName, pData, nBytes);
  684. if (nBytes == 0)
  685. return NULL;
  686. CMemFile* pMemFile = new CMemFile(pData, nBytes);
  687. CArchive* pArchive = new CArchive(pMemFile, CArchive::load);
  688. return pArchive;
  689. }
  690. void CXTPPropExchange::ReleaseArchive(LPCTSTR pszPropName, CArchive* pArchive)
  691. {
  692. ASSERT(pArchive);
  693. if (!pArchive)
  694. return;
  695. CMemFile* pFile = DYNAMIC_DOWNCAST(CMemFile, pArchive->GetFile());
  696. ASSERT(pFile);
  697. if (!pFile)
  698. return;
  699. BYTE* pData = NULL;
  700. if (IsStoring())
  701. {
  702. pArchive->Flush();
  703. DWORD nBytes = (DWORD)pFile->GetPosition();
  704. pData = pFile->Detach();
  705. PX_Blob(this, pszPropName, pData, nBytes);
  706. }
  707. else
  708. {
  709. pData = pFile->Detach();
  710. }
  711. pArchive->Abort();
  712. pFile->Close();
  713. free(pData);
  714. delete pFile;
  715. delete pArchive;
  716. }
  717. void CXTPPropExchange::ExchangeSchema()
  718. {
  719. PX_Long(this, _T("Schema"), (long&)m_nSchema, _XTP_SCHEMA_CURRENT);
  720. }
  721. void CXTPPropExchange::ExchangeSchemaSafe()
  722. {
  723. PX_Long(this, _T("Schema"), (long&)m_nSchema, _XTP_SCHEMA_1122);
  724. }
  725. void CXTPPropExchange::ExchangeLocale()
  726. {
  727. PX_DWord(this, _T("Locale"), (DWORD&)CXTPPropExchange::m_lcidDateTime, XTP_LOCALE_ISO8601);
  728. }
  729. CXTPPropExchangeEnumerator* CXTPPropExchange::GetEnumerator(LPCTSTR lpszSection)
  730. {
  731. return new CXTPPropExchangeEnumerator(this, lpszSection);
  732. }
  733. //////////////////////////////////////////////////////////////////////////
  734. // CXTPPropExchangeArchive
  735. IMPLEMENT_DYNAMIC(CXTPPropExchangeArchive, CXTPPropExchange)
  736. CXTPPropExchangeArchive::CXTPPropExchangeArchive(CArchive& ar) :
  737. m_ar((CSelfArchive&)ar)
  738. {
  739. ASSERT_POINTER(&ar, CArchive);
  740. m_bLoading = m_ar.IsLoading();
  741. }
  742. CXTPPropExchange* CXTPPropExchangeArchive::GetSection(LPCTSTR /*pszSection*/)
  743. {
  744. CXTPPropExchangeArchive* pSection = new CXTPPropExchangeArchive(m_ar);
  745. pSection->InitSection(this);
  746. return pSection;
  747. }
  748. BOOL CXTPPropExchangeArchive::ExchangeRuntimeClass(LPCTSTR /*pszPropName*/, CRuntimeClass*& pClass, CRuntimeClass* pDefaultClass)
  749. {
  750. if (!OnBeforeExchange())
  751. return FALSE;
  752. if (!IsLoading())
  753. {
  754. m_ar.WriteClass(pClass);
  755. }
  756. else
  757. {
  758. pClass = m_ar.ReadClass(pDefaultClass, &m_nSchema);
  759. if (!pClass)
  760. return FALSE;
  761. }
  762. return TRUE;
  763. }
  764. BOOL CXTPPropExchangeArchive::ExchangeObjectInstance(CObject*& pObject, CRuntimeClass* pObjectRuntime)
  765. {
  766. if (!CXTPPropExchange::ExchangeObjectInstance(pObject, pObjectRuntime))
  767. return FALSE;
  768. if (IsLoading())
  769. {
  770. m_ar.CheckCount();
  771. m_ar.m_pLoadArray->InsertAt(m_ar.m_nMapCount++, pObject);
  772. }
  773. else
  774. {
  775. m_ar.MapObject(NULL);
  776. m_ar.CheckCount();
  777. m_ar.m_pStoreMap->SetAt(pObject, (LPVOID)(DWORD_PTR)m_ar.m_nMapCount++);
  778. }
  779. return TRUE;
  780. }
  781. BOOL CXTPPropExchangeArchive::ExchangeProp(LPCTSTR /*pszPropName*/, VARTYPE vtProp,
  782. void* pvProp, const void* pvDefault)
  783. {
  784. if (!OnBeforeExchange())
  785. return FALSE;
  786. UNUSED(pvDefault);       // unused in release builds
  787. ASSERT(AfxIsValidAddress(pvProp, 1, FALSE));
  788. ASSERT((pvDefault == NULL) || AfxIsValidAddress(pvDefault, 1, FALSE));
  789. if (m_bLoading)
  790. {
  791. switch (vtProp)
  792. {
  793. case VT_UI1:
  794. m_ar >> *(BYTE*)pvProp;
  795. break;
  796. case VT_I2:
  797. m_ar >> *(WORD*)pvProp;
  798. break;
  799. case VT_I4:
  800. m_ar >> *(long*)pvProp;
  801. break;
  802. case VT_BOOL:
  803. m_ar >> *(BOOL*)pvProp;
  804. break;
  805. case VT_BSTR:
  806. ASSERT(FALSE);
  807. break;
  808. case VT_LPSTR:
  809. m_ar >> *(CString*)pvProp;
  810. break;
  811. case VT_CY:
  812. m_ar >> ((CY*)pvProp)->Lo;
  813. m_ar >> ((CY*)pvProp)->Hi;
  814. break;
  815. case VT_R4:
  816. m_ar >> *(float*)pvProp;
  817. break;
  818. case VT_R8:
  819. m_ar >> *(double*)pvProp;
  820. break;
  821. case VT_EX_RECT:
  822. m_ar >> *(RECT*)pvProp;
  823. break;
  824. case VT_EX_SIZE:
  825. m_ar >> *(SIZE*)pvProp;
  826. break;
  827. case VT_VARIANT:
  828. m_ar >> *(COleVariant*)pvProp;
  829. break;
  830. case VT_DATE:
  831. m_ar >> *(COleDateTime*)pvProp;
  832. break;
  833. }
  834. }
  835. else
  836. {
  837. switch (vtProp)
  838. {
  839. case VT_UI1:
  840. m_ar << *(BYTE*)pvProp;
  841. break;
  842. case VT_I2:
  843. m_ar << *(WORD*)pvProp;
  844. break;
  845. case VT_I4:
  846. m_ar << *(long*)pvProp;
  847. break;
  848. case VT_BOOL:
  849. m_ar << *(BOOL*)pvProp;
  850. break;
  851. case VT_BSTR:
  852. ASSERT(FALSE);
  853. break;
  854. case VT_LPSTR:
  855. m_ar << *(CString*)pvProp;
  856. break;
  857. case VT_CY:
  858. m_ar << ((CY*)pvProp)->Lo;
  859. m_ar << ((CY*)pvProp)->Hi;
  860. break;
  861. case VT_R4:
  862. m_ar << *(float*)pvProp;
  863. break;
  864. case VT_R8:
  865. m_ar << *(double*)pvProp;
  866. break;
  867. case VT_EX_RECT:
  868. m_ar << *(RECT*)pvProp;
  869. break;
  870. case VT_EX_SIZE:
  871. m_ar << *(SIZE*)pvProp;
  872. break;
  873. case VT_VARIANT:
  874. m_ar << *(COleVariant*)pvProp;
  875. break;
  876. case VT_DATE:
  877. m_ar << *(COleDateTime*)pvProp;
  878. break;
  879. }
  880. }
  881. return TRUE;
  882. }
  883. void CXTPPropExchangeArchive::WriteCount (DWORD dwCount)
  884. {
  885. m_ar.WriteCount(dwCount);
  886. }
  887. DWORD CXTPPropExchangeArchive::ReadCount()
  888. {
  889. return (DWORD)m_ar.ReadCount();
  890. }
  891. void CXTPPropExchangeArchive::Write (LPCTSTR /*pszPropName*/, const void* lpBuf, UINT nCount)
  892. {
  893. ASSERT(lpBuf);
  894. m_ar.Write(lpBuf, nCount);
  895. }
  896. UINT CXTPPropExchangeArchive::Read (LPCTSTR /*pszPropName*/, void* lpBuf, UINT nCount)
  897. {
  898. ASSERT(lpBuf);
  899. return m_ar.Read(lpBuf, nCount);
  900. }
  901. BOOL CXTPPropExchangeArchive::ExchangeBlobProp(LPCTSTR /*pszPropName*/, BYTE*& pData, DWORD& nBytes)
  902. {
  903. if (!OnBeforeExchange())
  904. return FALSE;
  905. if (IsStoring())
  906. {
  907. WriteCount(nBytes);
  908. m_ar.Write(pData, nBytes);
  909. }
  910. else
  911. {
  912. DWORD nCount = ReadCount();
  913. if (pData == NULL)
  914. {
  915. pData = (BYTE*)malloc(nCount);
  916. nBytes = nCount;
  917. }
  918. if (nBytes < nCount)
  919. return FALSE;
  920. return m_ar.Read(pData, nCount) == nCount;
  921. }
  922. return TRUE;
  923. }
  924. CArchive* CXTPPropExchangeArchive::GetArchive(LPCTSTR /*pszPropName*/)
  925. {
  926. return &m_ar;
  927. }
  928. void CXTPPropExchangeArchive::ReleaseArchive(LPCTSTR /*pszPropName*/, CArchive* /*pArchive*/)
  929. {
  930. }
  931. void CXTPPropExchangeArchive::ExchangeSchemaSafe()
  932. {
  933. DWORD dwSafe = 0xFF0ADBF;
  934. if (IsStoring())
  935. {
  936. m_ar << dwSafe;
  937. m_ar << m_nSchema;
  938. }
  939. else
  940. {
  941. if (m_ar.m_lpBufCur + sizeof(DWORD) > m_ar.m_lpBufMax)
  942. m_ar.FillBuffer(sizeof(DWORD));
  943. DWORD dw = *(DWORD*)m_ar.m_lpBufCur;
  944. if (dw == dwSafe)
  945. {
  946. m_ar >> dwSafe;
  947. m_ar >> m_nSchema;
  948. }
  949. else
  950. {
  951. m_nSchema = _XTP_SCHEMA_100;
  952. }
  953. }
  954. }
  955. //////////////////////////////////////////////////////////////////////////
  956. // CXTPPropExchangeRegistry
  957. IMPLEMENT_DYNAMIC(CXTPPropExchangeRegistry, CXTPPropExchange)
  958. CXTPPropExchangeRegistry::CXTPPropExchangeRegistry(BOOL bLoading, HKEY hParentKey, LPCTSTR lpszSection)
  959. {
  960. ASSERT(lpszSection != NULL);
  961. if (hParentKey == 0)
  962. {
  963. m_hParentKey = AfxGetApp()->GetAppRegistryKey();
  964. m_bCloseParentKey = TRUE;
  965. }
  966. else
  967. {
  968. m_hParentKey = hParentKey;
  969. m_bCloseParentKey = FALSE;
  970. }
  971. m_bLoading = bLoading;
  972. m_strSectionName = lpszSection;
  973. m_hSectionKey = NULL;
  974. }
  975. CXTPPropExchangeRegistry::~CXTPPropExchangeRegistry()
  976. {
  977. if (m_hSectionKey)
  978. {
  979. RegCloseKey(m_hSectionKey);
  980. }
  981. if (m_bCloseParentKey && m_hParentKey)
  982. {
  983. RegCloseKey(m_hParentKey);
  984. }
  985. }
  986. CXTPPropExchange* CXTPPropExchangeRegistry::GetSection(LPCTSTR lpszSection)
  987. {
  988. OnBeforeExchange();
  989. CXTPPropExchangeRegistry* pSection = new CXTPPropExchangeRegistry(IsLoading(), m_hSectionKey, lpszSection);
  990. pSection->InitSection(this);
  991. return pSection;
  992. }
  993. BOOL CXTPPropExchangeRegistry::IsPropertyExists(LPCTSTR pszPropName)
  994. {
  995. if (!OnBeforeExchange())
  996. return FALSE;
  997. return RegQueryValueEx(m_hSectionKey, (LPTSTR)pszPropName, NULL, NULL, NULL, NULL) == ERROR_SUCCESS;
  998. }
  999. BOOL CXTPPropExchangeRegistry::IsSectionExists(LPCTSTR lpszSection)
  1000. {
  1001. if (!OnBeforeExchange())
  1002. return FALSE;
  1003. HKEY hSectionKey = 0;
  1004. if (RegOpenKeyEx(m_hSectionKey, lpszSection, 0, m_bLoading ? KEY_READ : KEY_WRITE, &hSectionKey) == ERROR_SUCCESS)
  1005. {
  1006. RegCloseKey(hSectionKey);
  1007. return TRUE;
  1008. }
  1009. return FALSE;
  1010. }
  1011. BOOL CXTPPropExchangeRegistry::OnBeforeExchange()
  1012. {
  1013. if (m_hParentKey == NULL)
  1014. return FALSE;
  1015. if (!m_bInitialized)
  1016. {
  1017. ASSERT(m_hSectionKey == 0);
  1018. VERIFY(RegCreateKeyEx(m_hParentKey, m_strSectionName, 0, REG_NONE, REG_OPTION_NON_VOLATILE, m_bLoading ? KEY_READ : KEY_WRITE, NULL, &m_hSectionKey, NULL) == ERROR_SUCCESS);
  1019. m_bInitialized = TRUE;
  1020. }
  1021. return m_hSectionKey != NULL;
  1022. }
  1023. void CXTPPropExchangeRegistry::EmptySection()
  1024. {
  1025. CXTPPropExchange::EmptySection();
  1026. if (m_hSectionKey)
  1027. {
  1028. RegCloseKey(m_hSectionKey);
  1029. m_hSectionKey = 0;
  1030. }
  1031. AfxDelRegTreeHelper(m_hParentKey, m_strSectionName);
  1032. m_bInitialized = FALSE;
  1033. }
  1034. BOOL CXTPPropExchangeRegistry::ExchangeProp(LPCTSTR pszPropName, VARTYPE vtProp,
  1035. void* pvProp, const void* pvDefault /*= NULL*/)
  1036. {
  1037. if (m_bLoading)
  1038. {
  1039. if (!m_bUseDefaultOnLoad)
  1040. pvDefault = NULL;
  1041. if (!OnBeforeExchange())
  1042. return CopyPropValue(vtProp, pvProp, pvDefault);
  1043. ASSERT(m_hSectionKey);
  1044. switch (vtProp)
  1045. {
  1046. case VT_R4:
  1047. case VT_R8:
  1048. case VT_DATE:
  1049. case VT_BSTR:
  1050. ASSERT(FALSE); // Not Implemented
  1051. return FALSE;
  1052. case VT_VARIANT:
  1053. return FALSE; // Not Implemented
  1054. case VT_UI1:
  1055. case VT_I2:
  1056. case VT_I4:
  1057. case VT_BOOL:
  1058. {
  1059. DWORD dwValue;
  1060. DWORD dwType;
  1061. DWORD dwCount = sizeof(DWORD);
  1062. LONG lResult = RegQueryValueEx(m_hSectionKey, (LPTSTR)pszPropName, NULL, &dwType,
  1063. (LPBYTE)&dwValue, &dwCount);
  1064. if (lResult == ERROR_SUCCESS)
  1065. {
  1066. ASSERT(dwType == REG_DWORD);
  1067. ASSERT(dwCount == sizeof(DWORD));
  1068. return CopyPropValue(vtProp, pvProp, &dwValue);
  1069. }
  1070. else
  1071. {
  1072. return CopyPropValue(vtProp, pvProp, pvDefault);
  1073. }
  1074. }
  1075. case VT_LPSTR:
  1076. case VT_EX_SIZE:
  1077. case VT_EX_RECT:
  1078. {
  1079. CString strValue;
  1080. DWORD dwType, dwCount;
  1081. LONG lResult = RegQueryValueEx(m_hSectionKey, (LPTSTR)pszPropName, NULL, &dwType,
  1082. NULL, &dwCount);
  1083. if (lResult == ERROR_SUCCESS)
  1084. {
  1085. ASSERT(dwType == REG_SZ);
  1086. lResult = RegQueryValueEx(m_hSectionKey, (LPTSTR)pszPropName, NULL, &dwType,
  1087. (LPBYTE)strValue.GetBuffer(dwCount/sizeof(TCHAR)), &dwCount);
  1088. strValue.ReleaseBuffer();
  1089. }
  1090. if (lResult == ERROR_SUCCESS)
  1091. {
  1092. ASSERT(dwType == REG_SZ);
  1093. if (vtProp == VT_EX_SIZE)
  1094. {
  1095. SIZE sz = {0, 0};
  1096. if (SCANF_S(strValue, _T("%i, %i"), &sz.cx, &sz.cy) != 2)
  1097. return CopyPropValue(vtProp, pvProp, pvDefault);
  1098. *((LPSIZE)pvProp) = sz;
  1099. }
  1100. else if (vtProp == VT_EX_RECT)
  1101. {
  1102. RECT rc = {0, 0, 0, 0};
  1103. if (SCANF_S(strValue, _T("%i, %i, %i, %i"), &rc.left, &rc.top, &rc.right, &rc.bottom) != 4)
  1104. return CopyPropValue(vtProp, pvProp, pvDefault);
  1105. *((LPRECT)pvProp) = rc;
  1106. }
  1107. else
  1108. {
  1109. *(CString*)pvProp = strValue;
  1110. }
  1111. }
  1112. else
  1113. {
  1114. return CopyPropValue(vtProp, pvProp, pvDefault);
  1115. }
  1116. return TRUE;
  1117. }
  1118. }
  1119. }
  1120. else
  1121. {
  1122. if (!m_bUseDefaultOnSave)
  1123. pvDefault = NULL;
  1124. if (!OnBeforeExchange())
  1125. return FALSE;
  1126. if (IsSamePropValue(vtProp, pvProp, pvDefault))
  1127. {
  1128. if (m_hSectionKey && !m_bEmptySection)
  1129. RegDeleteValue(m_hSectionKey, pszPropName);
  1130. return TRUE;
  1131. }
  1132. LONG lResult = -1;
  1133. switch (vtProp)
  1134. {
  1135. case VT_UI1:
  1136. case VT_I2:
  1137. case VT_I4:
  1138. case VT_BOOL:
  1139. {
  1140. DWORD dwValue = 0;
  1141. CopyPropValue(vtProp, &dwValue, pvProp);
  1142. lResult = RegSetValueEx(m_hSectionKey, pszPropName, NULL, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD));
  1143. }
  1144. break;
  1145. case VT_LPSTR:
  1146. {
  1147. CString& strValue = *(CString*)pvProp;
  1148. lResult = RegSetValueEx(m_hSectionKey, pszPropName, NULL, REG_SZ,
  1149. (LPBYTE)(LPCTSTR)strValue, (strValue.GetLength() + 1) * sizeof(TCHAR));
  1150. }
  1151. break;
  1152. case VT_R4:
  1153. case VT_R8:
  1154. lResult = RegSetValueEx(m_hSectionKey, pszPropName, NULL, REG_BINARY, (LPBYTE)pvProp, GetSizeOfVarType(vtProp));
  1155. break;
  1156. case VT_DATE:
  1157. case VT_VARIANT:
  1158. case VT_BSTR:
  1159. ASSERT(FALSE); // Not Implemented
  1160. break;
  1161. case VT_EX_SIZE:
  1162. {
  1163. CString strValue;
  1164. strValue.Format(_T("%i, %i"), ((LPSIZE)pvProp)->cx, ((LPSIZE)pvProp)->cy);
  1165. lResult = RegSetValueEx(m_hSectionKey, pszPropName, NULL, REG_SZ,
  1166. (LPBYTE)(LPCTSTR)strValue, (strValue.GetLength() + 1) * sizeof(TCHAR));
  1167. }
  1168. break;
  1169. case VT_EX_RECT:
  1170. CString strValue;
  1171. strValue.Format(_T("%i, %i, %i, %i"), ((LPRECT)pvProp)->left, ((LPRECT)pvProp)->top, ((LPRECT)pvProp)->right, ((LPRECT)pvProp)->bottom);
  1172. lResult = RegSetValueEx(m_hSectionKey, pszPropName, NULL, REG_SZ,
  1173. (LPBYTE)(LPCTSTR)strValue, (strValue.GetLength() + 1) * sizeof(TCHAR));
  1174. break;
  1175. }
  1176. return lResult == ERROR_SUCCESS;
  1177. }
  1178. return FALSE;
  1179. }
  1180. BOOL CXTPPropExchangeRegistry::ExchangeBlobProp(LPCTSTR pszPropName, BYTE*& pData, DWORD& nBytes)
  1181. {
  1182. if (!OnBeforeExchange())
  1183. return FALSE;
  1184. ASSERT(m_hSectionKey != 0);
  1185. if (IsStoring())
  1186. {
  1187. LONG lResult = ::RegSetValueEx(m_hSectionKey, pszPropName, NULL, REG_BINARY,
  1188. pData, nBytes);
  1189. return lResult == ERROR_SUCCESS;
  1190. }
  1191. else
  1192. {
  1193. DWORD dwType, dwCount;
  1194. LONG lResult = RegQueryValueEx(m_hSectionKey, (LPTSTR)pszPropName, NULL, &dwType,
  1195. NULL, &dwCount);
  1196. if (lResult != ERROR_SUCCESS)
  1197. return FALSE;
  1198. ASSERT(dwType == REG_BINARY);
  1199. if (pData == NULL)
  1200. {
  1201. pData = (BYTE*)malloc(dwCount);
  1202. nBytes = dwCount;
  1203. }
  1204. if (nBytes < dwCount)
  1205. return FALSE;
  1206. lResult = RegQueryValueEx(m_hSectionKey, (LPTSTR)pszPropName, NULL, &dwType,
  1207. (LPBYTE)pData, &dwCount);
  1208. if (lResult != ERROR_SUCCESS)
  1209. return FALSE;
  1210. }
  1211. return TRUE;
  1212. }
  1213. //////////////////////////////////////////////////////////////////////////
  1214. // CXTPPropExchangeXMLNode
  1215. #ifndef _XTP_EXCLUDE_XML
  1216. IMPLEMENT_DYNAMIC(CXTPPropExchangeXMLNode, CXTPPropExchange)
  1217. CXTPPropExchangeXMLNode::CXTPPropExchangeXMLNode(BOOL bLoading, CXTPDOMNodePtr xmlParentNode, LPCTSTR lpszSection)
  1218. {
  1219. m_bLoading = bLoading;
  1220. m_strSectionName = lpszSection;
  1221. m_xmlParentNode = xmlParentNode;
  1222. m_xmlSectionNode = NULL;
  1223. m_bCompactMode = TRUE;
  1224. if (xmlParentNode)
  1225. {
  1226. xmlParentNode->get_ownerDocument(&m_xmlDocPtr);
  1227. if (m_xmlDocPtr == 0)
  1228. {
  1229. m_xmlDocPtr = xmlParentNode;
  1230. }
  1231. }
  1232. m_strEncoding = _T("UTF-8");
  1233. }
  1234. BOOL CXTPPropExchangeXMLNode::IsXMLSupported()
  1235. {
  1236. CXTPDOMDocumentPtr xmlDocPtr;
  1237. if (!SUCCEEDED(xmlDocPtr.CreateInstance(CLSID_XTPDOMDocument)))
  1238. {
  1239. return FALSE;
  1240. }
  1241. return TRUE;
  1242. }
  1243. BOOL CXTPPropExchangeXMLNode::CreateDocumentInstance()
  1244. {
  1245. if (m_xmlDocPtr == NULL)
  1246. {
  1247. if (!SUCCEEDED(m_xmlDocPtr.CreateInstance(CLSID_XTPDOMDocument)))
  1248. {
  1249. TRACE(_T("Warning: CreateDocumentInstance failed in CXTPPropExchangeXMLNode --n"));
  1250. TRACE(_T("tperhaps AfxOleInit() has not been called, or msxml3.dll not found."));
  1251. return FALSE;
  1252. }
  1253. m_xmlDocPtr->put_preserveWhiteSpace(VARIANT_TRUE);
  1254. }
  1255. return TRUE;
  1256. }
  1257. void CXTPPropExchangeXMLNode::TraceParseError()
  1258. {
  1259. #ifdef _DEBUG
  1260. XTPXML::IXMLDOMParseErrorPtr parseError = 0;
  1261. if (FAILED(m_xmlDocPtr->get_parseError(&parseError)))
  1262. return;
  1263. BSTR bstrReason = 0;
  1264. if (FAILED(parseError->get_reason(&bstrReason)))
  1265. return;
  1266. CString strReason(bstrReason);
  1267. TRACE(_T("Warning: CXTPPropExchangeXMLNode::LoadFromString failed. ParseError.Reason = %s"), (LPCTSTR)strReason);
  1268. SysFreeString(bstrReason);
  1269. #endif
  1270. }
  1271. BOOL CXTPPropExchangeXMLNode::LoadFromString(LPCSTR lpszState)
  1272. {
  1273. if (!lpszState)
  1274. return FALSE;
  1275. if (!CreateDocumentInstance())
  1276. return FALSE;
  1277. ASSERT(m_xmlDocPtr != 0);
  1278. VARIANT_BOOL bResult;
  1279. VARIANT va;
  1280. va.vt = VT_ARRAY | VT_UI1;
  1281. ULONG nLen = (ULONG)strlen(lpszState);
  1282. va.parray = SafeArrayCreateVector(VT_UI1, 0, nLen);
  1283. MEMCPY_S(va.parray->pvData, lpszState, nLen);
  1284. HRESULT hr = m_xmlDocPtr->load(va, &bResult);
  1285. VariantClear(&va);
  1286. if (FAILED(hr) || bResult == VARIANT_FALSE)
  1287. {
  1288. TraceParseError();
  1289. return FALSE;
  1290. }
  1291. m_xmlParentNode = m_xmlDocPtr;
  1292. m_xmlSectionNode = NULL;
  1293. m_bInitialized = FALSE;
  1294. return TRUE;
  1295. }
  1296. BOOL CXTPPropExchangeXMLNode::LoadFromString(LPCWSTR lpszState)
  1297. {
  1298. return LoadFromString((BSTR)lpszState);
  1299. }
  1300. BOOL CXTPPropExchangeXMLNode::LoadFromString(BSTR lpszState)
  1301. {
  1302. if (!CreateDocumentInstance())
  1303. return FALSE;
  1304. ASSERT(m_xmlDocPtr != 0);
  1305. VARIANT_BOOL bResult;
  1306. HRESULT hr = m_xmlDocPtr->loadXML(lpszState, &bResult);
  1307. if (FAILED(hr) || bResult == VARIANT_FALSE)
  1308. {
  1309. TraceParseError();
  1310. return FALSE;
  1311. }
  1312. m_xmlParentNode = m_xmlDocPtr;
  1313. m_xmlSectionNode = NULL;
  1314. m_bInitialized = FALSE;
  1315. return TRUE;
  1316. }
  1317. BOOL CXTPPropExchangeXMLNode::LoadFromResource(HINSTANCE hInstance, LPCTSTR lpszResourceName, LPCTSTR lpszResourceType)
  1318. {
  1319. HRSRC hRsrc = ::FindResource(hInstance, lpszResourceName, lpszResourceType);
  1320. if (hRsrc == NULL)
  1321. return FALSE;
  1322. HGLOBAL hGlobal = LoadResource(hInstance, hRsrc);
  1323. if (hGlobal == NULL)
  1324. return FALSE;
  1325. LPCSTR pData = (LPCSTR)LockResource(hGlobal);
  1326. if (pData == NULL)
  1327. return FALSE;
  1328. DWORD dwSize = (DWORD)SizeofResource(hInstance, hRsrc);
  1329. if (dwSize == 0)
  1330. return FALSE;
  1331. LPSTR lpstr = (LPSTR)malloc(dwSize + 1);
  1332. if (!lpstr)
  1333. return FALSE;
  1334. MEMCPY_S(lpstr, pData, dwSize);
  1335. lpstr[dwSize] = 0;
  1336. BOOL bResult = LoadFromString(lpstr);
  1337. UnlockResource(hGlobal);
  1338. FreeResource(hGlobal);
  1339. free(lpstr);
  1340. return bResult;
  1341. }
  1342. BOOL CXTPPropExchangeXMLNode::LoadFromFile(LPCTSTR strFileName)
  1343. {
  1344. if (!FILEEXISTS_S(strFileName))
  1345. return FALSE;
  1346. if (!CreateDocumentInstance())
  1347. return FALSE;
  1348. ASSERT(m_xmlDocPtr != 0);
  1349. VARIANT_BOOL bResult;
  1350. HRESULT hr = m_xmlDocPtr->load(COleVariant(strFileName), &bResult);
  1351. if (FAILED(hr) || bResult == VARIANT_FALSE)
  1352. {
  1353. TraceParseError();
  1354. return FALSE;
  1355. }
  1356. m_xmlParentNode = m_xmlDocPtr;
  1357. m_xmlSectionNode = NULL;
  1358. m_bInitialized = FALSE;
  1359. return TRUE;
  1360. }
  1361. CString CXTPPropExchangeXMLNode::GetXML(BOOL bFormatted)
  1362. {
  1363. const LPCTSTR lpszCrLf = _T("rn");
  1364. #define ADDINDENT(str, i, strOffset)
  1365. INSERT_S(str, i, lpszCrLf);
  1366. INSERT_S(str, i + 2, strOffset);
  1367. i += strOffset.GetLength() + 2;
  1368. CString str;
  1369. if (!OnBeforeExchange())
  1370. return str;
  1371. ASSERT(m_xmlDocPtr != 0);
  1372. BSTR bstrXML = 0;
  1373. if (IsRootSection())
  1374. {
  1375. if (FAILED(m_xmlDocPtr->get_xml(&bstrXML)))
  1376. return str;
  1377. }
  1378. else
  1379. {
  1380. if (FAILED(m_xmlSectionNode->get_xml(&bstrXML)))
  1381. return str;
  1382. }
  1383. str = bstrXML;
  1384. SysFreeString(bstrXML);
  1385. if (bFormatted)
  1386. {
  1387. CString strOffset(_T('t'));
  1388. for (int i = 1; i < str.GetLength(); i++)
  1389. {
  1390. if (((str[i] == _T('>')) && (str[i - 1] == _T('/'))) || ((str[i] == _T('<')) && (str[i + 1] == _T('/'))))
  1391. {
  1392. DELETE_S(strOffset, strOffset.GetLength() - 1);
  1393. if (str[i] == _T('<') && str[i - 1] == _T('>'))
  1394. {
  1395. ADDINDENT(str, i, strOffset);
  1396. }
  1397. }
  1398. else if (str[i] == _T('<'))
  1399. {
  1400. ADDINDENT(str, i, strOffset);
  1401. strOffset += _T('t');
  1402. }
  1403. }
  1404. }
  1405. return str;
  1406. }
  1407. void CXTPPropExchangeXMLNode::FormatFile(LPCTSTR lpszFileName)
  1408. {
  1409. const LPCSTR lpszCrLf = "rn";
  1410. const LPCSTR lpszOffset = "t";
  1411. #define WRITEINDENT
  1412. file.Write(lpszBegin, int(lpszCurrent - lpszBegin) - nWhiteSpace);
  1413. file.Write(lpszCrLf, 2);
  1414. for (int j = 0; j < nOffset; j++) file.Write(lpszOffset, 1);
  1415. lpszBegin = lpszCurrent
  1416. CFile file;
  1417. if (!file.Open(lpszFileName, CFile::modeRead))
  1418. return;
  1419. DWORD dwLength = (DWORD)file.GetLength();
  1420. if (dwLength < 3)
  1421. return;
  1422. BYTE* lpszBuffer = new BYTE[dwLength + 1];
  1423. file.Read(lpszBuffer, dwLength);
  1424. lpszBuffer[dwLength] = 0;
  1425. file.Close();
  1426. if (!file.Open(lpszFileName, CFile::modeWrite | CFile::modeCreate))
  1427. {
  1428. delete[] lpszBuffer;
  1429. return;
  1430. }
  1431. int nOffset = 1, nWhiteSpace = 0;
  1432. if (dwLength > 2 && lpszBuffer[dwLength - 2] == 'r')
  1433. lpszBuffer[dwLength - 2] = 0;
  1434. BYTE *lpszCurrent = lpszBuffer + 1, *lpszBegin = lpszBuffer;
  1435. while (*lpszCurrent++)
  1436. {
  1437. BYTE& chCurrent = *lpszCurrent;
  1438. if (((chCurrent == _T('>')) && (*(lpszCurrent - 1) == '/' || *(lpszCurrent - 1) == '?'))
  1439. || ((chCurrent == _T('<')) && (*(lpszCurrent + 1) == '/')))
  1440. {
  1441. nOffset--;
  1442. if (chCurrent == '<' && *(lpszCurrent - 1 - nWhiteSpace) == '>')
  1443. {
  1444. WRITEINDENT;
  1445. }
  1446. }
  1447. else if (chCurrent == '<')
  1448. {
  1449. WRITEINDENT;
  1450. nOffset++;
  1451. }
  1452. nWhiteSpace = (chCurrent == 'r' || chCurrent == 'n' || chCurrent == 't') ? nWhiteSpace + 1 : 0;
  1453. }
  1454. file.Write(lpszBegin, int(lpszCurrent - lpszBegin) - 1);
  1455. file.Write(lpszCrLf, 2);
  1456. file.Close();
  1457. delete[] lpszBuffer;
  1458. }
  1459. HRESULT CXTPPropExchangeXMLNode::SaveToFile(LPCTSTR strFileName, BOOL bFormatted)
  1460. {
  1461. CString str;
  1462. if (!OnBeforeExchange())
  1463. return E_FAIL;
  1464. ASSERT(m_xmlDocPtr != 0);
  1465. CString strInstruction = _T("version="1.0" encoding="") + m_strEncoding + _T(""");
  1466. BOOL bInstructionExists = FALSE;
  1467. CXTPDOMNodePtr ptrBaseInstruction = 0;
  1468. if (SUCCEEDED(m_xmlDocPtr->selectSingleNode(L"/node()", &ptrBaseInstruction)) && ptrBaseInstruction != 0)
  1469. {
  1470. BSTR bstrNodeName = 0;
  1471. ptrBaseInstruction->get_nodeName(&bstrNodeName);
  1472. if (wcscmp(bstrNodeName, L"xml") == 0)
  1473. {
  1474. bInstructionExists = TRUE;
  1475. }
  1476. SysFreeString(bstrNodeName);
  1477. }
  1478. XTPXML::IXMLDOMProcessingInstructionPtr ptrInstruction = 0;
  1479. if (!bInstructionExists && SUCCEEDED(m_xmlDocPtr->createProcessingInstruction(L"xml", CT2BSTR(strInstruction), &ptrInstruction)))
  1480. {
  1481. CXTPDOMNodePtr xmlNodePtr;
  1482. if (SUCCEEDED(m_xmlDocPtr->selectSingleNode(L"/node()", &xmlNodePtr)))
  1483. {
  1484. m_xmlDocPtr->insertBefore(ptrInstruction, _variant_t(xmlNodePtr.GetInterfacePtr()), 0);
  1485. }
  1486. }
  1487. HRESULT hr = m_xmlDocPtr->save(COleVariant(strFileName));
  1488. if (FAILED(hr))
  1489. return hr;
  1490. if (bFormatted)
  1491. {
  1492. FormatFile(strFileName);
  1493. }
  1494. return S_OK;
  1495. }
  1496. CXTPPropExchange* CXTPPropExchangeXMLNode::GetSection(LPCTSTR lpszSection)
  1497. {
  1498. OnBeforeExchange();
  1499. CXTPPropExchangeXMLNode* pSection = new CXTPPropExchangeXMLNode(IsLoading(), m_xmlSectionNode, lpszSection);
  1500. pSection->m_bCompactMode = m_bCompactMode;
  1501. pSection->InitSection(this);
  1502. return pSection;
  1503. }
  1504. BOOL CXTPPropExchangeXMLNode::OnBeforeExchange()
  1505. {
  1506. if (!m_bInitialized)
  1507. {
  1508. m_bInitialized = TRUE;
  1509. if (m_xmlDocPtr == NULL && IsRootSection())
  1510. {
  1511. ASSERT(m_xmlParentNode == 0);
  1512. if (!CreateDocumentInstance())
  1513. return FALSE;
  1514. if (m_xmlDocPtr == 0)
  1515. return FALSE;
  1516. m_xmlParentNode = m_xmlDocPtr;
  1517. ASSERT(m_xmlParentNode != 0);
  1518. }
  1519. if ((m_xmlDocPtr == NULL) || (m_xmlParentNode == NULL))
  1520. return FALSE;
  1521. ASSERT(m_xmlSectionNode == 0);
  1522. m_xmlSectionNode = GetProfileNode(m_strSectionName);
  1523. if (m_xmlSectionNode != NULL && IsRootSection())
  1524. {
  1525. PX_Bool(this, _T("CompactMode"), m_bCompactMode, FALSE);
  1526. }
  1527. }
  1528. if ((m_xmlDocPtr == NULL) || (m_xmlParentNode == NULL))
  1529. return FALSE;
  1530. return m_xmlSectionNode != NULL;
  1531. }
  1532. void CXTPPropExchangeXMLNode::EmptySection()
  1533. {
  1534. CXTPPropExchange::EmptySection();
  1535. OnBeforeExchange();
  1536. if (m_xmlSectionNode != 0 && m_xmlParentNode != 0)
  1537. {
  1538. m_xmlParentNode->removeChild(m_xmlSectionNode, NULL);
  1539. m_xmlSectionNode = 0;
  1540. m_bInitialized = FALSE;
  1541. }
  1542. }
  1543. void CXTPPropExchangeXMLNode::SetCompactMode(BOOL bCompactMode)
  1544. {
  1545. m_bCompactMode = bCompactMode;
  1546. }
  1547. CXTPDOMNodePtr CXTPPropExchangeXMLNode::GetProfileNode(LPCTSTR strSection)
  1548. {
  1549. ASSERT(m_xmlParentNode != 0);
  1550. CXTPDOMNodePtr xmlNodePtr;
  1551. CXTPDOMElementPtr xmlElementPtr;
  1552. HRESULT hr = m_xmlParentNode->selectSingleNode(CT2BSTR(strSection), &xmlNodePtr);
  1553. if (FAILED(hr) || xmlNodePtr == NULL)
  1554. {
  1555. m_xmlDocPtr->createElement(CT2BSTR(strSection), &xmlElementPtr);
  1556. ASSERT(xmlElementPtr != 0);
  1557. if (xmlElementPtr)
  1558. {
  1559. m_xmlParentNode->appendChild(xmlElementPtr, &xmlNodePtr);
  1560. }
  1561. }
  1562. return xmlNodePtr;
  1563. }
  1564. CXTPDOMNodePtr CXTPPropExchangeXMLNode::GetEntryNode(LPCTSTR lpszEntry, BOOL bCreate)
  1565. {
  1566. ASSERT(m_xmlSectionNode != 0);
  1567. CXTPDOMNodePtr xmlNodeEntryPtr;
  1568. if (lpszEntry == 0 || _tcslen(lpszEntry) == 0)
  1569. return m_xmlSectionNode;
  1570. if (m_bCompactMode)
  1571. {
  1572. XTPXML::IXMLDOMNamedNodeMapPtr map;
  1573. m_xmlSectionNode->get_attributes(&map);
  1574. HRESULT hr = map->getNamedItem(CT2BSTR(lpszEntry), &xmlNodeEntryPtr);
  1575. if (FAILED(hr) || xmlNodeEntryPtr == NULL)
  1576. {
  1577. if (bCreate)
  1578. {
  1579. XTPXML::IXMLDOMAttributePtr xmlElementPtr;
  1580. m_xmlDocPtr->createAttribute(CT2BSTR(lpszEntry), &xmlElementPtr);
  1581. if (xmlElementPtr)
  1582. {
  1583. map->setNamedItem(xmlElementPtr, &xmlNodeEntryPtr);
  1584. }
  1585. }
  1586. else
  1587. {
  1588. return 0;
  1589. }
  1590. }
  1591. }
  1592. else
  1593. {
  1594. CXTPDOMNodePtr xmlNodeSectionPtr = m_xmlSectionNode;
  1595. HRESULT hr = xmlNodeSectionPtr->selectSingleNode(CT2BSTR(lpszEntry), &xmlNodeEntryPtr);
  1596. if (FAILED(hr) || xmlNodeEntryPtr == NULL)
  1597. {
  1598. if (bCreate)
  1599. {
  1600. CXTPDOMElementPtr xmlElementPtr;
  1601. m_xmlDocPtr->createElement(CT2BSTR(lpszEntry), &xmlElementPtr);
  1602. ASSERT(xmlElementPtr != 0);
  1603. if (xmlElementPtr)
  1604. {
  1605. xmlNodeSectionPtr->appendChild(xmlElementPtr, &xmlNodeEntryPtr);
  1606. }
  1607. }
  1608. else
  1609. {
  1610. return 0;
  1611. }
  1612. }
  1613. }
  1614. ASSERT(xmlNodeEntryPtr != 0);
  1615. return xmlNodeEntryPtr;
  1616. }
  1617. CString CXTPPropExchangeXMLNode::BstrToString(BSTR bstrVal)
  1618. {
  1619. return CString(XTP_CW2CT(bstrVal));
  1620. }
  1621. BOOL CXTPPropExchangeXMLNode::ExchangeProp(LPCTSTR pszPropName, VARTYPE vtProp,
  1622. void* pvProp, const void* pvDefault)
  1623. {
  1624. if (m_bLoading)
  1625. {
  1626. if (!m_bUseDefaultOnLoad)
  1627. pvDefault = NULL;
  1628. if (!OnBeforeExchange())
  1629. return CopyPropValue(vtProp, pvProp, pvDefault);
  1630. CXTPDOMNodePtr xmlEntryPtr = GetEntryNode(pszPropName, FALSE);
  1631. if (xmlEntryPtr == 0)
  1632. return CopyPropValue(vtProp, pvProp, pvDefault);
  1633. BSTR bstrValue = NULL;
  1634. xmlEntryPtr->get_text(&bstrValue);
  1635. if (vtProp == VT_BSTR)
  1636. {
  1637. PreformatString(bstrValue);
  1638. *(BSTR*)pvProp = bstrValue;
  1639. return TRUE;
  1640. }
  1641. CString strValue(BstrToString(bstrValue));
  1642. if (bstrValue) SysFreeString(bstrValue);
  1643. return ExchangePropStringHelper(strValue, vtProp, pvProp, pvDefault);
  1644. }
  1645. else
  1646. {
  1647. if (!m_bUseDefaultOnSave)
  1648. pvDefault = NULL;
  1649. if (IsSamePropValue(vtProp, pvProp, pvDefault))
  1650. return TRUE;
  1651. if (!OnBeforeExchange())
  1652. return FALSE;
  1653. CXTPDOMNodePtr xmlEntryPtr = GetEntryNode(pszPropName, TRUE);
  1654. ASSERT(xmlEntryPtr != 0);
  1655. if (vtProp == VT_BSTR)
  1656. {
  1657. xmlEntryPtr->put_text(*(BSTR*)pvProp);
  1658. return TRUE;
  1659. }
  1660. CString strValue;
  1661. if (!ExchangePropStringHelper(strValue, vtProp, pvProp, pvDefault))
  1662. return FALSE;
  1663. xmlEntryPtr->put_text(CT2BSTR(strValue));
  1664. }
  1665. return TRUE;
  1666. }
  1667. CString CXTPPropExchangeXMLNode::GetSectionName()
  1668. {
  1669. if (!OnBeforeExchange())
  1670. return _T("");
  1671. BSTR bstrValue = NULL;
  1672. m_xmlSectionNode->get_nodeName(&bstrValue);
  1673. CString strValue(bstrValue);
  1674. if (bstrValue) SysFreeString(bstrValue);
  1675. return strValue;
  1676. }
  1677. BOOL CXTPPropExchangeXMLNode::IsSectionExists(LPCTSTR lpszSection)
  1678. {
  1679. if (!OnBeforeExchange())
  1680. return FALSE;
  1681. CXTPDOMNodePtr xmlNodePtr;
  1682. HRESULT hr = m_xmlSectionNode->selectSingleNode(CT2BSTR(lpszSection), &xmlNodePtr);
  1683. if (FAILED(hr) || xmlNodePtr == NULL)
  1684. return FALSE;
  1685. return TRUE;
  1686. }
  1687. BOOL CXTPPropExchangeXMLNode::PutSection(CXTPPropExchangeXMLNode* pNode)
  1688. {
  1689. if (!pNode)
  1690. return FALSE;
  1691. if (!OnBeforeExchange())
  1692. return FALSE;
  1693. if (!pNode || !pNode->OnBeforeExchange())
  1694. return FALSE;
  1695. ASSERT(m_xmlSectionNode != 0);
  1696. if (FAILED(m_xmlSectionNode->appendChild(pNode->m_xmlSectionNode, NULL)))
  1697. return FALSE;
  1698. return TRUE;
  1699. }
  1700. void CXTPPropExchangeXMLNode::SetLoading(BOOL bLoading)
  1701. {
  1702. m_bLoading = bLoading;
  1703. }
  1704. BOOL CXTPPropExchangeXMLNode::IsPropertyExists(LPCTSTR pszPropName)
  1705. {
  1706. if (!OnBeforeExchange())
  1707. return FALSE;
  1708. if (GetEntryNode(pszPropName, FALSE) != NULL)
  1709. return TRUE;
  1710. return FALSE;
  1711. }
  1712. class CXTPPropExchangeXMLNode::CXMLEnumerator : public CXTPPropExchangeEnumerator
  1713. {
  1714. public:
  1715. CXMLEnumerator::CXMLEnumerator(CXTPPropExchangeXMLNode* pContainer, LPCTSTR lpszSection)
  1716. : CXTPPropExchangeEnumerator(pContainer, lpszSection)
  1717. {
  1718. }
  1719. public:
  1720. CXTPDOMNodePtr GetProfileNode(POSITION pos)
  1721. {
  1722. CXTPDOMNodePtr xmlNodePtr;
  1723. CString strNode;
  1724. strNode.Format(_T("%s[%i]"), m_strSectionName.IsEmpty() ? _T("*") : (LPCTSTR)m_strSectionName, (int)(INT_PTR)pos);
  1725. if (SUCCEEDED(((CXTPPropExchangeXMLNode*)m_pContainer)->m_xmlSectionNode->selectSingleNode(CT2BSTR(strNode), &xmlNodePtr)))
  1726. return xmlNodePtr;
  1727. return 0;
  1728. }
  1729. POSITION GetPosition(DWORD dwCount = 0, BOOL /*bCompactMode*/ = TRUE)
  1730. {
  1731. m_nCount = dwCount;
  1732. if (!m_pContainer)
  1733. return NULL;
  1734. if (m_pContainer->IsLoading())
  1735. {
  1736. if (!m_pContainer->OnBeforeExchange())
  1737. return NULL;
  1738. m_xmNextNode = GetProfileNode(0);
  1739. if (m_xmNextNode == 0)
  1740. return NULL;
  1741. }
  1742. return (POSITION)1;
  1743. }
  1744. CXTPPropExchange* GetNext(POSITION& pos)
  1745. {
  1746. CXTPPropExchangeXMLNode* pSection = (CXTPPropExchangeXMLNode*)m_pContainer->GetSection(m_strSectionName);
  1747. CXTPDOMNodePtr xmlNodePtr;
  1748. CXTPDOMElementPtr xmlElementPtr;
  1749. if (m_pContainer->IsStoring())
  1750. {
  1751. ASSERT((DWORD)(DWORD_PTR)pos <= m_nCount);
  1752. pSection->m_xmlDocPtr->createElement(CT2BSTR(m_strSectionName), &xmlElementPtr);
  1753. ASSERT(xmlElementPtr != 0);
  1754. if (xmlElementPtr)
  1755. {
  1756. ((CXTPPropExchangeXMLNode*)m_pContainer)->m_xmlSectionNode->appendChild(xmlElementPtr, &xmlNodePtr);
  1757. }
  1758. pos++;
  1759. if ((DWORD)(DWORD_PTR)pos > m_nCount) pos = NULL;
  1760. }
  1761. else
  1762. {
  1763. ASSERT(m_xmNextNode != NULL);
  1764. xmlNodePtr = m_xmNextNode;
  1765. m_xmNextNode = GetProfileNode(pos);
  1766. if (m_xmNextNode == NULL)
  1767. pos = NULL;
  1768. else
  1769. pos++;
  1770. }
  1771. pSection->m_bInitialized = TRUE;
  1772. pSection->m_xmlSectionNode = xmlNodePtr;
  1773. return pSection;
  1774. }
  1775. protected:
  1776. CXTPDOMNodePtr m_xmNextNode;
  1777. };
  1778. CXTPPropExchangeEnumerator* CXTPPropExchangeXMLNode::GetEnumerator(LPCTSTR lpszSection)
  1779. {
  1780. if (IsStoring() || !IsPropertyExists(_T("Count")))
  1781. return new CXMLEnumerator(this, lpszSection);
  1782. return new CXTPPropExchangeEnumerator(this, lpszSection);
  1783. }
  1784. void CXTPPropExchangeXMLNode::SetEncoding(LPCTSTR lpszEncoding)
  1785. {
  1786. m_strEncoding = lpszEncoding;
  1787. }
  1788. #endif
  1789. //////////////////////////////////////////////////////////////////////////
  1790. // CXTPPropExchangeIniFile
  1791. IMPLEMENT_DYNAMIC(CXTPPropExchangeIniFile, CXTPPropExchange)
  1792. CXTPPropExchangeIniFile::CXTPPropExchangeIniFile(BOOL bLoading, LPCTSTR lpszParentSection, LPCTSTR lpszSection)
  1793. {
  1794. ASSERT(lpszSection != NULL);
  1795. m_bLoading = bLoading;
  1796. m_bTempFile = TRUE;
  1797. m_bEmptySection = TRUE;
  1798. if (lpszParentSection == NULL)
  1799. {
  1800. m_strSectionName = lpszSection;
  1801. }
  1802. else
  1803. {
  1804. m_strSectionName = CString(lpszParentSection) + _T("\") + CString(lpszSection);
  1805. }
  1806. }
  1807. CXTPPropExchangeIniFile::~CXTPPropExchangeIniFile()
  1808. {
  1809. if (IsRootSection() && !m_strFileName.IsEmpty() && m_bTempFile)
  1810. {
  1811. ::DeleteFile((LPTSTR)(LPCTSTR)m_strFileName);
  1812. }
  1813. }
  1814. void CXTPPropExchangeIniFile::EmptySection()
  1815. {
  1816. if (m_bEmptySection || m_strSectionName.IsEmpty())
  1817. return;
  1818. CXTPPropExchange::EmptySection();
  1819. size_t nLength = (size_t)m_strSectionName.GetLength();
  1820. LPTSTR lpszBuffer = 0;
  1821. int nSize = 8000;
  1822. do
  1823. {
  1824. lpszBuffer = new TCHAR[nSize];
  1825. int nResult = GetPrivateProfileSectionNames(lpszBuffer, nSize, m_strFileName);
  1826. if (nResult == 0)
  1827. {
  1828. delete[] lpszBuffer;
  1829. return;
  1830. }
  1831. if (nResult == nSize - 2)
  1832. {
  1833. nSize = nSize * 2;
  1834. delete[] lpszBuffer;
  1835. lpszBuffer = 0;
  1836. }
  1837. }
  1838. while (lpszBuffer == 0);
  1839. LPTSTR lpszSection = lpszBuffer;
  1840. size_t nSectionLen = _tcslen(lpszSection);
  1841. while (nSectionLen > 0)
  1842. {
  1843. if (nLength <= nSectionLen &&
  1844. (memcmp((LPCTSTR)m_strSectionName, lpszSection, nLength * sizeof(TCHAR)) == 0) &&
  1845. (nLength == nSectionLen || lpszSection[nLength] == _T('\')))
  1846. {
  1847. WritePrivateProfileString(lpszSection, NULL, NULL, m_strFileName);
  1848. }
  1849. lpszSection = lpszSection + nSectionLen + 1;
  1850. nSectionLen = _tcslen(lpszSection);
  1851. }
  1852. delete[] lpszBuffer;
  1853. }
  1854. CXTPPropExchange* CXTPPropExchangeIniFile::GetSection(LPCTSTR lpszSection)
  1855. {
  1856. OnBeforeExchange();
  1857. CXTPPropExchangeIniFile* pSection = new CXTPPropExchangeIniFile(IsLoading(), m_strSectionName, lpszSection);
  1858. pSection->InitSection(this);
  1859. pSection->m_strFileName = m_strFileName;
  1860. pSection->m_bTempFile = m_bTempFile;
  1861. return pSection;
  1862. }
  1863. BOOL CXTPPropExchangeIniFile::OnBeforeExchange()
  1864. {
  1865. if (!m_bInitialized)
  1866. {
  1867. if (m_strFileName.IsEmpty())
  1868. {
  1869. TCHAR lpszTempPath[MAX_PATH];
  1870. TCHAR lpszTempFileName[MAX_PATH];
  1871. if (GetTempPath(MAX_PATH, lpszTempPath) == 0)
  1872. return FALSE;
  1873. if (GetTempFileName(lpszTempPath, _T("xtp"), 0, lpszTempFileName) == 0)
  1874. return FALSE;
  1875. m_strFileName = lpszTempFileName;
  1876. m_bTempFile = TRUE;
  1877. }
  1878. m_bInitialized = TRUE;
  1879. }
  1880. return !m_strFileName.IsEmpty();
  1881. }
  1882. BOOL CXTPPropExchangeIniFile::ExchangeProp(LPCTSTR pszPropName, VARTYPE vtProp,
  1883. void* pvProp, const void* pvDefault /*= NULL*/)
  1884. {
  1885. if (m_bLoading)
  1886. {
  1887. if (!m_bUseDefaultOnLoad)
  1888. pvDefault = NULL;
  1889. if (!OnBeforeExchange())
  1890. return CopyPropValue(vtProp, pvProp, pvDefault);
  1891. CString strValue;
  1892. DWORD dwSize = GetPrivateProfileString(m_strSectionName, pszPropName, NULL, strValue.GetBuffer(256), 256, m_strFileName);
  1893. if (dwSize == 0)
  1894. return CopyPropValue(vtProp, pvProp, pvDefault);
  1895. if (dwSize == 256 - 1)
  1896. {
  1897. dwSize = GetPrivateProfileString(m_strSectionName, pszPropName, NULL, strValue.GetBuffer(16000), 16000, m_strFileName);
  1898. ASSERT(dwSize < 16000 - 1);
  1899. }
  1900. strValue.ReleaseBuffer(dwSize);
  1901. return ExchangePropStringHelper(strValue, vtProp, pvProp, pvDefault);
  1902. }
  1903. else
  1904. {
  1905. if (!m_bUseDefaultOnSave)
  1906. pvDefault = NULL;
  1907. if (!OnBeforeExchange())
  1908. return FALSE;
  1909. if (IsSamePropValue(vtProp, pvProp, pvDefault))
  1910. {
  1911. if (!m_bEmptySection)
  1912. WritePrivateProfileString (m_strSectionName, pszPropName, NULL, m_strFileName);
  1913. return TRUE;
  1914. }
  1915. CString strValue;
  1916. if (!ExchangePropStringHelper(strValue, vtProp, pvProp, pvDefault))
  1917. return FALSE;
  1918. if (!WritePrivateProfileString (m_strSectionName, pszPropName, strValue, m_strFileName))
  1919. return FALSE;
  1920. }
  1921. return TRUE;
  1922. }
  1923. void CXTPPropExchangeIniFile::SaveToFile(LPCTSTR strFileName)
  1924. {
  1925. ASSERT(IsRootSection() && IsStoring());
  1926. if (m_strFileName.Compare(strFileName) != 0 && !m_strFileName.IsEmpty())
  1927. {
  1928. ::DeleteFile(strFileName);
  1929. ::CopyFile(m_strFileName, strFileName, FALSE);
  1930. }
  1931. }
  1932. BOOL CXTPPropExchangeIniFile::LoadFromFile(LPCTSTR strFileName)
  1933. {
  1934. ASSERT(IsRootSection() && IsLoading());
  1935. if (!FILEEXISTS_S(strFileName))
  1936. return FALSE;
  1937. if (!OnBeforeExchange())
  1938. return FALSE;
  1939. return ::CopyFile(strFileName, m_strFileName, FALSE);
  1940. }
  1941. void CXTPPropExchangeIniFile::AssignFile(LPCTSTR strFileName)
  1942. {
  1943. m_strFileName = strFileName;
  1944. m_bTempFile = FALSE;
  1945. m_bEmptySection = FALSE;
  1946. }
  1947. /////////////////////////////////////////////////////////////////////////////
  1948. // PX_ functions
  1949. BOOL AFX_CDECL PX_Byte(CXTPPropExchange* pPX, LPCTSTR pszPropName, BYTE& nValue, BYTE nDefault)
  1950. {
  1951. ASSERT_POINTER(pPX, CXTPPropExchange);
  1952. ASSERT_POINTER(&nValue, short);
  1953. if (!pPX)
  1954. return FALSE;
  1955. return  pPX->ExchangeProp(pszPropName, VT_UI1, &nValue, &nDefault);
  1956. }
  1957. BOOL AFX_CDECL PX_Short(CXTPPropExchange* pPX, LPCTSTR pszPropName, short& sValue)
  1958. {
  1959. ASSERT_POINTER(pPX, CXTPPropExchange);
  1960. ASSERT_POINTER(&sValue, short);
  1961. if (!pPX)
  1962. return FALSE;
  1963. return  pPX->ExchangeProp(pszPropName, VT_I2, &sValue);
  1964. }
  1965. BOOL AFX_CDECL PX_Short(CXTPPropExchange* pPX, LPCTSTR pszPropName, short& sValue,
  1966. short sDefault)
  1967. {
  1968. ASSERT_POINTER(pPX, CXTPPropExchange);
  1969. ASSERT_POINTER(&sValue, short);
  1970. if (!pPX)
  1971. return FALSE;
  1972. return pPX->ExchangeProp(pszPropName, VT_I2, &sValue, &sDefault);
  1973. }
  1974. BOOL AFX_CDECL PX_UShort(CXTPPropExchange* pPX, LPCTSTR pszPropName, USHORT& usValue)
  1975. {
  1976. ASSERT_POINTER(pPX, CXTPPropExchange);
  1977. ASSERT_POINTER(&usValue, USHORT);
  1978. if (!pPX)
  1979. return FALSE;
  1980. return pPX->ExchangeProp(pszPropName, VT_I2, &usValue);
  1981. }
  1982. BOOL AFX_CDECL PX_UShort(CXTPPropExchange* pPX, LPCTSTR pszPropName, USHORT& usValue,
  1983. USHORT usDefault)
  1984. {
  1985. ASSERT_POINTER(pPX, CXTPPropExchange);
  1986. ASSERT_POINTER(&usValue, USHORT);
  1987. if (!pPX)
  1988. return FALSE;
  1989. return pPX->ExchangeProp(pszPropName, VT_I2, &usValue, &usDefault);
  1990. }
  1991. BOOL AFX_CDECL PX_Long(CXTPPropExchange* pPX, LPCTSTR pszPropName, long& lValue)
  1992. {
  1993. ASSERT_POINTER(pPX, CXTPPropExchange);
  1994. ASSERT_POINTER(&lValue, long);
  1995. if (!pPX)
  1996. return FALSE;
  1997. return pPX->ExchangeProp(pszPropName, VT_I4, &lValue);
  1998. }
  1999. BOOL AFX_CDECL PX_Long(CXTPPropExchange* pPX, LPCTSTR pszPropName, long& lValue,
  2000. long lDefault)
  2001. {
  2002. ASSERT_POINTER(pPX, CXTPPropExchange);
  2003. ASSERT_POINTER(&lValue, long);
  2004. if (!pPX)
  2005. return FALSE;
  2006. return pPX->ExchangeProp(pszPropName, VT_I4, &lValue, &lDefault);
  2007. }
  2008. BOOL AFX_CDECL PX_DWord(CXTPPropExchange* pPX, LPCTSTR pszPropName, DWORD& dwValue)
  2009. {
  2010. ASSERT_POINTER(pPX, CXTPPropExchange);
  2011. ASSERT_POINTER(&dwValue, DWORD);
  2012. if (!pPX)
  2013. return FALSE;
  2014. return pPX->ExchangeProp(pszPropName, VT_I4, &dwValue);
  2015. }
  2016. BOOL AFX_CDECL PX_DWord(CXTPPropExchange* pPX, LPCTSTR pszPropName, DWORD& dwValue,
  2017. DWORD dwDefault)
  2018. {
  2019. ASSERT_POINTER(pPX, CXTPPropExchange);
  2020. ASSERT_POINTER(&dwValue, DWORD);
  2021. if (!pPX)
  2022. return FALSE;
  2023. return pPX->ExchangeProp(pszPropName, VT_I4, &dwValue, &dwDefault);
  2024. }
  2025. BOOL AFX_CDECL PX_UI8(CXTPPropExchange* pPX, LPCTSTR pszPropName,
  2026. ULONGLONG& ullValue, ULONGLONG ullDefault)
  2027. {
  2028. POINT ptData64 = {(LONG)(DWORD)(ullValue >> 32), (LONG)(DWORD)ullValue};
  2029. POINT ptDefault = {(LONG)(DWORD)(ullDefault >> 32), (LONG)(DWORD)ullDefault};
  2030. BOOL bResult = PX_Point(pPX, pszPropName, ptData64, ptDefault);
  2031. if (bResult && pPX->IsLoading())
  2032. {
  2033. ullValue = (DWORD)ptData64.x;
  2034. ullValue = ullValue << 32;
  2035. ullValue += (DWORD)ptData64.y;
  2036. }
  2037. return bResult;
  2038. }
  2039. BOOL AFX_CDECL PX_Int(CXTPPropExchange* pPX, LPCTSTR pszPropName, int& nValue)
  2040. {
  2041. ASSERT_POINTER(pPX, CXTPPropExchange);
  2042. ASSERT_POINTER(&nValue, int);
  2043. if (!pPX)
  2044. return FALSE;
  2045. return pPX->ExchangeProp(pszPropName, VT_I4, &nValue);
  2046. }
  2047. BOOL AFX_CDECL PX_Int(CXTPPropExchange* pPX, LPCTSTR pszPropName, int& nValue,
  2048. int nDefault)
  2049. {
  2050. ASSERT_POINTER(pPX, CXTPPropExchange);
  2051. ASSERT_POINTER(&nValue, int);
  2052. if (!pPX)
  2053. return FALSE;
  2054. return pPX->ExchangeProp(pszPropName, VT_I4, &nValue, &nDefault);
  2055. }
  2056. BOOL AFX_CDECL PX_ULong(CXTPPropExchange* pPX, LPCTSTR pszPropName, ULONG& ulValue)
  2057. {
  2058. ASSERT_POINTER(pPX, CXTPPropExchange);
  2059. ASSERT_POINTER(&ulValue, ULONG);
  2060. if (!pPX)
  2061. return FALSE;
  2062. return pPX->ExchangeProp(pszPropName, VT_I4, &ulValue);
  2063. }
  2064. BOOL AFX_CDECL PX_ULong(CXTPPropExchange* pPX, LPCTSTR pszPropName, ULONG& ulValue,
  2065. ULONG ulDefault)
  2066. {
  2067. ASSERT_POINTER(pPX, CXTPPropExchange);
  2068. ASSERT_POINTER(&ulValue, ULONG);
  2069. if (!pPX)
  2070. return FALSE;
  2071. return pPX->ExchangeProp(pszPropName, VT_I4, &ulValue, &ulDefault);
  2072. }
  2073. BOOL AFX_CDECL PX_Bool(CXTPPropExchange* pPX, LPCTSTR pszPropName, BOOL& bValue)
  2074. {
  2075. ASSERT_POINTER(pPX, CXTPPropExchange);
  2076. ASSERT_POINTER(&bValue, BOOL);
  2077. if (!pPX)
  2078. return FALSE;
  2079. return pPX->ExchangeProp(pszPropName, VT_BOOL, &bValue);
  2080. }
  2081. BOOL AFX_CDECL PX_Bool(CXTPPropExchange* pPX, LPCTSTR pszPropName, BOOL& bValue,
  2082. BOOL bDefault)
  2083. {
  2084. ASSERT_POINTER(pPX, CXTPPropExchange);
  2085. ASSERT_POINTER(&bValue, BOOL);
  2086. if (!pPX)
  2087. return FALSE;
  2088. return pPX->ExchangeProp(pszPropName, VT_BOOL, &bValue, &bDefault);
  2089. }
  2090. BOOL AFX_CDECL PX_String(CXTPPropExchange* pPX, LPCTSTR pszPropName, CString& strValue)
  2091. {
  2092. ASSERT_POINTER(pPX, CXTPPropExchange);
  2093. ASSERT_POINTER(&strValue, CString);
  2094. if (!pPX)
  2095. return FALSE;
  2096. return pPX->ExchangeProp(pszPropName, VT_LPSTR, &strValue);
  2097. }
  2098. BOOL AFX_CDECL PX_String(CXTPPropExchange* pPX, LPCTSTR pszPropName, CString& strValue,
  2099. LPCTSTR lpszDefault)
  2100. {
  2101. ASSERT_POINTER(pPX, CXTPPropExchange);
  2102. ASSERT_POINTER(&strValue, CString);
  2103. if (!pPX)
  2104. return FALSE;
  2105. return pPX->ExchangeProp(pszPropName, VT_LPSTR, &strValue, lpszDefault);
  2106. }
  2107. BOOL AFX_CDECL PX_Bstr(CXTPPropExchange* pPX, LPCTSTR pszPropName, BSTR& lpszValue,
  2108. BSTR lpszDefault)
  2109. {
  2110. ASSERT_POINTER(pPX, CXTPPropExchange);
  2111. ASSERT_POINTER(&lpszValue, BSTR);
  2112. if (!pPX)
  2113. return FALSE;
  2114. return pPX->ExchangeProp(pszPropName, VT_BSTR, &lpszValue, lpszDefault);
  2115. }
  2116. BOOL AFX_CDECL PX_Float(CXTPPropExchange* pPX, LPCTSTR pszPropName, float& floatValue)
  2117. {
  2118. ASSERT_POINTER(pPX, CXTPPropExchange);
  2119. ASSERT_POINTER(&floatValue, float);
  2120. if (!pPX)
  2121. return FALSE;
  2122. return pPX->ExchangeProp(pszPropName, VT_R4, &floatValue);
  2123. }
  2124. BOOL AFX_CDECL PX_Float(CXTPPropExchange* pPX, LPCTSTR pszPropName, float& floatValue,
  2125. float floatDefault)
  2126. {
  2127. ASSERT_POINTER(pPX, CXTPPropExchange);
  2128. ASSERT_POINTER(&floatValue, float);
  2129. if (!pPX)
  2130. return FALSE;
  2131. return pPX->ExchangeProp(pszPropName, VT_R4, &floatValue, &floatDefault);
  2132. }
  2133. BOOL AFX_CDECL PX_Double(CXTPPropExchange* pPX, LPCTSTR pszPropName, double& doubleValue)
  2134. {
  2135. ASSERT_POINTER(pPX, CXTPPropExchange);
  2136. ASSERT_POINTER(&doubleValue, double);
  2137. if (!pPX)
  2138. return FALSE;
  2139. return pPX->ExchangeProp(pszPropName, VT_R8, &doubleValue);
  2140. }
  2141. BOOL AFX_CDECL PX_DateTime(CXTPPropExchange* pPX, LPCTSTR pszPropName, COleDateTime& dtValue)
  2142. {
  2143. ASSERT_POINTER(pPX, CXTPPropExchange);
  2144. ASSERT_POINTER(&dtValue, COleDateTime);
  2145. if (!pPX)
  2146. return FALSE;
  2147. return pPX->ExchangeProp(pszPropName, VT_DATE, &dtValue);
  2148. }
  2149. BOOL AFX_CDECL PX_Double(CXTPPropExchange* pPX, LPCTSTR pszPropName, double& doubleValue,
  2150. double doubleDefault)
  2151. {
  2152. ASSERT_POINTER(pPX, CXTPPropExchange);
  2153. ASSERT_POINTER(&doubleValue, double);
  2154. if (!pPX)
  2155. return FALSE;
  2156. return pPX->ExchangeProp(pszPropName, VT_R8, &doubleValue, &doubleDefault);
  2157. }
  2158. BOOL AFX_CDECL PX_Size(CXTPPropExchange* pPX, LPCTSTR pszPropName, SIZE& szValue, SIZE szDefault)
  2159. {
  2160. ASSERT_POINTER(pPX, CXTPPropExchange);
  2161. if (!pPX)
  2162. return FALSE;
  2163. return pPX->ExchangeProp(pszPropName, VT_EX_SIZE, &szValue, &szDefault);
  2164. }
  2165. BOOL AFX_CDECL PX_Point(CXTPPropExchange* pPX, LPCTSTR pszPropName, POINT& ptValue, POINT ptDefault)
  2166. {
  2167. ASSERT_POINTER(pPX, CXTPPropExchange);
  2168. ASSERT(sizeof(POINT) == sizeof(SIZE));
  2169. if (!pPX)
  2170. return FALSE;
  2171. return pPX->ExchangeProp(pszPropName, VT_EX_SIZE, &ptValue, &ptDefault);
  2172. }
  2173. BOOL AFX_CDECL PX_Rect(CXTPPropExchange* pPX, LPCTSTR pszPropName, RECT& rcValue, RECT rcDefault)
  2174. {
  2175. ASSERT_POINTER(pPX, CXTPPropExchange);
  2176. if (!pPX)
  2177. return FALSE;
  2178. return pPX->ExchangeProp(pszPropName, VT_EX_RECT, &rcValue, &rcDefault);
  2179. }
  2180. BOOL AFX_CDECL PX_Variant(CXTPPropExchange* pPX, LPCTSTR pszPropName, COleVariant& variant, COleVariant variantDefault)
  2181. {
  2182. ASSERT_POINTER(pPX, CXTPPropExchange);
  2183. if (!pPX)
  2184. return FALSE;
  2185. return pPX->ExchangeProp(pszPropName, VT_VARIANT, &variant, &variantDefault);
  2186. }
  2187. BOOL AFX_CDECL PX_RuntimeClass(CXTPPropExchange* pPX, LPCTSTR pszPropName, CRuntimeClass*& pClass, CRuntimeClass* pDefaultClass)
  2188. {
  2189. if (!pPX)
  2190. return FALSE;
  2191. return pPX->ExchangeRuntimeClass(pszPropName, pClass, pDefaultClass);
  2192. }
  2193. BOOL AFX_CDECL PX_Blob(CXTPPropExchange* pPX, LPCTSTR pszPropName, BYTE*& pData, DWORD& nBytes)
  2194. {
  2195. if (!pPX)
  2196. return FALSE;
  2197. return pPX->ExchangeBlobProp(pszPropName, pData, nBytes);
  2198. }
  2199. BOOL AFX_CDECL PX_Serialize(CXTPPropExchange* pPX, LPCTSTR pszPropName, CObject* pObject)
  2200. {
  2201. if (!pPX)
  2202. return FALSE;
  2203. CArchive* pArchive = pPX->GetArchive(pszPropName);
  2204. if (!pArchive)
  2205. return FALSE;
  2206. BOOL bResult = FALSE;
  2207. try
  2208. {
  2209. pObject->Serialize(*pArchive);
  2210. bResult = TRUE;
  2211. }
  2212. catch (COleException* pEx)
  2213. {
  2214. pEx->Delete ();
  2215. }
  2216. catch (CArchiveException* pEx)
  2217. {
  2218. pEx->Delete ();
  2219. }
  2220. pPX->ReleaseArchive(pszPropName, pArchive);
  2221. return bResult;
  2222. }