ctlpropx.cpp 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169
  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1998 Microsoft Corporation
  3. // All rights reserved.
  4. //
  5. // This source code is only intended as a supplement to the
  6. // Microsoft Foundation Classes Reference and related
  7. // electronic documentation provided with the library.
  8. // See these sources for detailed information regarding the
  9. // Microsoft Foundation Classes product.
  10. #include "stdafx.h"
  11. #ifdef AFXCTL_PROP_SEG
  12. #pragma code_seg(AFXCTL_PROP_SEG)
  13. #endif
  14. #ifdef _DEBUG
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. #define new DEBUG_NEW
  19. #ifdef _DEBUG
  20. #define ASSERT_BUFFER_VALID(p, cb, bWrite) \
  21. ASSERT(AfxIsValidAddress(p, cb, bWrite))
  22. #else
  23. #define ASSERT_BUFFER_VALID(p, cb, bWrite)
  24. #endif
  25. // Old class ID for picture type
  26. AFX_STATIC_DATA const CLSID _afx_CLSID_StdPicture2_V1 =
  27. { 0xfb8f0824,0x0164,0x101b, { 0x84,0xed,0x08,0x00,0x2b,0x2e,0xc7,0x13 } };
  28. /////////////////////////////////////////////////////////////////////////////
  29. // _AfxGetArchiveStream
  30. LPSTREAM AFXAPI _AfxGetArchiveStream(CArchive& ar, CArchiveStream& stm)
  31. {
  32. // Obtain direct access to the archive's LPSTREAM.
  33. ar.Flush();
  34. CFile* pFile = ar.GetFile();
  35. ASSERT(pFile != NULL);
  36. LPSTREAM pstm;
  37. if (pFile->IsKindOf(RUNTIME_CLASS(COleStreamFile)))
  38. {
  39. pstm = ((COleStreamFile*)pFile)->m_lpStream;
  40. ASSERT(pstm != NULL);
  41. }
  42. else
  43. {
  44. ASSERT(stm.m_pArchive == NULL || stm.m_pArchive == &ar);
  45. stm.m_pArchive = &ar;
  46. pstm = &stm;
  47. }
  48. return pstm;
  49. }
  50. /////////////////////////////////////////////////////////////////////////////
  51. // _AfxInitBlob
  52. BOOL AFXAPI _AfxInitBlob(HGLOBAL* phDst, void* pvSrc)
  53. {
  54. BOOL bResult = FALSE;
  55. ULONG cb;
  56. if ((cb = *(long*)pvSrc) > 0)
  57. {
  58. ASSERT_BUFFER_VALID(pvSrc, sizeof(cb) + cb, TRUE);
  59. *phDst = GlobalAlloc(GMEM_MOVEABLE, sizeof(cb) + cb);
  60. if (*phDst != NULL)
  61. {
  62. void* pvDst = GlobalLock(*phDst);
  63. ASSERT(pvDst != NULL);
  64. memcpy(pvDst, pvSrc, sizeof(cb) + cb);
  65. bResult = TRUE;
  66. GlobalUnlock(*phDst);
  67. }
  68. }
  69. return bResult;
  70. }
  71. /////////////////////////////////////////////////////////////////////////////
  72. // _AfxCopyBlob
  73. BOOL AFXAPI _AfxCopyBlob(HGLOBAL* phDst, HGLOBAL hSrc)
  74. {
  75. BOOL bResult = FALSE;
  76. void* pvSrc = GlobalLock(hSrc);
  77. if (pvSrc != NULL)
  78. {
  79. bResult = _AfxInitBlob(phDst, pvSrc);
  80. GlobalUnlock(hSrc);
  81. }
  82. return bResult;
  83. }
  84. /////////////////////////////////////////////////////////////////////////////
  85. // _AfxCopyPropValue
  86. BOOL AFXAPI _AfxCopyPropValue(VARTYPE vtProp, void* pvDest, const void * pvSrc)
  87. {
  88. ASSERT(AfxIsValidAddress(pvDest, 1));
  89. if (pvSrc != NULL)
  90. {
  91. ASSERT(AfxIsValidAddress(pvSrc, 1, FALSE));
  92. switch (vtProp)
  93. {
  94. case VT_UI1:
  95. *(BYTE*)pvDest = *(BYTE*)pvSrc;
  96. break;
  97. case VT_I2:
  98. *(short*)pvDest = *(short*)pvSrc;
  99. break;
  100. case VT_I4:
  101. *(long*)pvDest = *(long*)pvSrc;
  102. break;
  103. case VT_BOOL:
  104. *(BOOL*)pvDest = *(BOOL*)pvSrc;
  105. break;
  106. case VT_BSTR:
  107. *(CString*)pvDest = *(CString*)pvSrc;
  108. break;
  109. case VT_LPSTR:
  110. *(CString*)pvDest = (LPCTSTR)pvSrc;
  111. break;
  112. case VT_CY:
  113. *(CY*)pvDest = *(CY*)pvSrc;
  114. break;
  115. case VT_R4:
  116. *(_AFX_FLOAT*)pvDest = *(_AFX_FLOAT*)pvSrc;
  117. break;
  118. case VT_R8:
  119. *(_AFX_DOUBLE*)pvDest = *(_AFX_DOUBLE*)pvSrc;
  120. break;
  121. default:
  122. return FALSE;
  123. }
  124. }
  125. return pvSrc != NULL;
  126. }
  127. /////////////////////////////////////////////////////////////////////////////
  128. // COleControl::ExchangeExtent
  129. BOOL COleControl::ExchangeExtent(CPropExchange* pPX)
  130. {
  131. // Save extent
  132. SIZEL szl;
  133. szl.cx = m_cxExtent;
  134. szl.cy = m_cyExtent;
  135. if (PX_Long(pPX, _T("_ExtentX"), szl.cx) &&
  136. PX_Long(pPX, _T("_ExtentY"), szl.cy))
  137. {
  138. if ((pPX->IsLoading()) &&
  139. ((m_cxExtent != szl.cx) || (m_cyExtent != szl.cy)))
  140. {
  141. m_xOleObject.SetExtent(DVASPECT_CONTENT, &szl);
  142. }
  143. return TRUE;
  144. }
  145. return FALSE;
  146. }
  147. /////////////////////////////////////////////////////////////////////////////
  148. // Serialization for version number
  149. DWORD COleControl::SerializeVersion(CArchive& ar, DWORD dwVersionDefault,
  150. BOOL bConvert)
  151. {
  152. DWORD dwVersion;
  153. if (ar.IsLoading())
  154. {
  155. ar >> m_dwVersionLoaded;
  156. dwVersion = m_dwVersionLoaded;
  157. }
  158. else
  159. {
  160. dwVersion = bConvert ? dwVersionDefault : m_dwVersionLoaded;
  161. ar << dwVersion;
  162. }
  163. return dwVersion;
  164. }
  165. /////////////////////////////////////////////////////////////////////////////
  166. // Initialization for version number
  167. void COleControl::ResetVersion(DWORD dwVersionDefault)
  168. {
  169. m_dwVersionLoaded = dwVersionDefault;
  170. }
  171. /////////////////////////////////////////////////////////////////////////////
  172. // Serialization for extent
  173. void COleControl::SerializeExtent(CArchive& ar)
  174. {
  175. if (ar.IsLoading())
  176. {
  177. SIZEL szl;
  178. ar >> szl.cx;
  179. ar >> szl.cy;
  180. if ((m_cxExtent != szl.cx) || (m_cyExtent != szl.cy))
  181. m_xOleObject.SetExtent(DVASPECT_CONTENT, &szl);
  182. }
  183. else
  184. {
  185. ar << m_cxExtent;
  186. ar << m_cyExtent;
  187. }
  188. }
  189. /////////////////////////////////////////////////////////////////////////////
  190. // CPropExchange member functions
  191. BOOL CPropExchange::ExchangeVersion(DWORD& dwVersionLoaded,
  192. DWORD dwVersionDefault, BOOL bConvert)
  193. {
  194. BOOL bResult;
  195. if (m_bLoading)
  196. {
  197. bResult = PX_ULong(this, _T("_Version"), m_dwVersion,
  198. dwVersionDefault);
  199. dwVersionLoaded = m_dwVersion;
  200. }
  201. else
  202. {
  203. m_dwVersion = bConvert ? dwVersionDefault : dwVersionLoaded;
  204. bResult = PX_ULong(this, _T("_Version"), m_dwVersion);
  205. }
  206. return bResult;
  207. }
  208. /////////////////////////////////////////////////////////////////////////////
  209. // CArchivePropExchange member functions
  210. CArchivePropExchange::CArchivePropExchange(CArchive& ar) :
  211. m_ar(ar)
  212. {
  213. ASSERT_POINTER(&ar, CArchive);
  214. m_bLoading = m_ar.IsLoading();
  215. }
  216. BOOL CArchivePropExchange::ExchangeProp(LPCTSTR pszPropName, VARTYPE vtProp,
  217. void* pvProp, const void* pvDefault)
  218. {
  219. UNUSED(pszPropName); // unused in release builds
  220. UNUSED(pvDefault); // unused in release builds
  221. ASSERT(AfxIsValidString(pszPropName));
  222. ASSERT(AfxIsValidAddress(pvProp, 1, FALSE));
  223. ASSERT((pvDefault == NULL) || AfxIsValidAddress(pvDefault, 1, FALSE));
  224. if (m_bLoading)
  225. {
  226. switch (vtProp)
  227. {
  228. case VT_UI1:
  229. m_ar >> *(BYTE*)pvProp;
  230. break;
  231. case VT_I2:
  232. m_ar >> *(WORD*)pvProp;
  233. break;
  234. case VT_I4:
  235. m_ar >> *(long*)pvProp;
  236. break;
  237. case VT_BOOL:
  238. *(BOOL*)pvProp = 0;
  239. m_ar >> *(BYTE*)pvProp;
  240. break;
  241. case VT_LPSTR:
  242. case VT_BSTR:
  243. m_ar >> *(CString*)pvProp;
  244. break;
  245. case VT_CY:
  246. m_ar >> ((CY*)pvProp)->Lo;
  247. m_ar >> ((CY*)pvProp)->Hi;
  248. break;
  249. case VT_R4:
  250. m_ar >> *(float*)pvProp;
  251. break;
  252. case VT_R8:
  253. m_ar >> *(double*)pvProp;
  254. break;
  255. }
  256. }
  257. else
  258. {
  259. switch (vtProp)
  260. {
  261. case VT_UI1:
  262. m_ar << *(BYTE*)pvProp;
  263. break;
  264. case VT_I2:
  265. m_ar << *(WORD*)pvProp;
  266. break;
  267. case VT_I4:
  268. m_ar << *(long*)pvProp;
  269. break;
  270. case VT_BOOL:
  271. m_ar << *(BYTE*)pvProp;
  272. break;
  273. case VT_LPSTR:
  274. case VT_BSTR:
  275. m_ar << *(CString*)pvProp;
  276. break;
  277. case VT_CY:
  278. m_ar << ((CY*)pvProp)->Lo;
  279. m_ar << ((CY*)pvProp)->Hi;
  280. break;
  281. case VT_R4:
  282. m_ar << *(float*)pvProp;
  283. break;
  284. case VT_R8:
  285. m_ar << *(double*)pvProp;
  286. break;
  287. }
  288. }
  289. return TRUE;
  290. }
  291. BOOL CArchivePropExchange::ExchangeBlobProp(LPCTSTR pszPropName,
  292. HGLOBAL* phBlob, HGLOBAL /*hBlobDefault*/)
  293. {
  294. UNUSED(pszPropName); // unused in release builds
  295. ASSERT(AfxIsValidString(pszPropName));
  296. ASSERT_POINTER(phBlob, HGLOBAL);
  297. DWORD cb;
  298. if (m_bLoading)
  299. {
  300. // free previous memory block
  301. if (*phBlob != NULL)
  302. {
  303. GlobalFree(*phBlob);
  304. *phBlob = NULL;
  305. }
  306. // read new size
  307. m_ar >> cb;
  308. // allocate and fill new memory block
  309. *phBlob = GlobalAlloc(GMEM_MOVEABLE, sizeof(cb)+cb);
  310. if (*phBlob != NULL)
  311. {
  312. void* pvBlob = GlobalLock(*phBlob);
  313. ASSERT(pvBlob != NULL);
  314. *(long*)pvBlob = cb;
  315. if (m_ar.Read((BYTE*)pvBlob+sizeof(cb), cb) != cb)
  316. AfxThrowArchiveException(CArchiveException::endOfFile);
  317. GlobalUnlock(*phBlob);
  318. }
  319. }
  320. else
  321. {
  322. if (*phBlob != NULL)
  323. {
  324. void* pvBlob = GlobalLock(*phBlob);
  325. ASSERT(pvBlob != NULL);
  326. cb = *(long*)pvBlob;
  327. ASSERT_BUFFER_VALID(pvBlob, sizeof(cb)+cb, FALSE);
  328. m_ar.Write(pvBlob, sizeof(cb)+cb);
  329. GlobalUnlock(*phBlob);
  330. }
  331. else
  332. m_ar << (DWORD)0;
  333. }
  334. return TRUE;
  335. }
  336. BOOL AFXAPI _AfxPeekAtClassIDInStream(LPSTREAM pstm, LPCLSID lpClassID)
  337. {
  338. // Read the class ID, then restore the seek pointer.
  339. LARGE_INTEGER li;
  340. li.LowPart = (DWORD)(-(long)sizeof(CLSID));
  341. li.HighPart = -1;
  342. return (SUCCEEDED(ReadClassStm(pstm, lpClassID)) &&
  343. SUCCEEDED(pstm->Seek(li, STREAM_SEEK_CUR, NULL)));
  344. }
  345. BOOL AFXAPI _AfxIsSameUnknownObject(REFIID iid, LPUNKNOWN pUnk1, LPUNKNOWN pUnk2)
  346. {
  347. if (pUnk1 == pUnk2)
  348. return TRUE;
  349. if (pUnk1 == NULL || pUnk2 == NULL)
  350. return FALSE;
  351. LPUNKNOWN pI1 = NULL;
  352. LPUNKNOWN pI2 = NULL;
  353. BOOL bResult = FALSE;
  354. if (SUCCEEDED(pUnk1->QueryInterface(iid, (void**)&pI1)))
  355. {
  356. ASSERT_POINTER(pI1, IUnknown);
  357. if (SUCCEEDED(pUnk2->QueryInterface(iid, (void**)&pI2)))
  358. {
  359. ASSERT_POINTER(pI2, IUnknown);
  360. bResult = (pI1 == pI2);
  361. pI2->Release();
  362. }
  363. pI1->Release();
  364. }
  365. return bResult;
  366. }
  367. BOOL CArchivePropExchange::ExchangePersistentProp(LPCTSTR pszPropName,
  368. LPUNKNOWN* ppUnk, REFIID iid, LPUNKNOWN pUnkDefault)
  369. {
  370. UNUSED(pszPropName); // unused in release builds
  371. ASSERT(AfxIsValidString(pszPropName));
  372. ASSERT_POINTER(ppUnk, LPUNKNOWN);
  373. ASSERT_NULL_OR_POINTER(pUnkDefault, IUnknown);
  374. BOOL bResult = FALSE;
  375. CArchiveStream stm(&m_ar);
  376. if (m_bLoading)
  377. {
  378. RELEASE(*ppUnk);
  379. *ppUnk = NULL;
  380. BYTE bFlag;
  381. m_ar >> bFlag;
  382. if (bFlag != 0xFF)
  383. {
  384. // read the CLSID
  385. CLSID clsid;
  386. m_ar >> clsid.Data1;
  387. m_ar >> clsid.Data2;
  388. m_ar >> clsid.Data3;
  389. m_ar.Read(&clsid.Data4[0], sizeof clsid.Data4);
  390. // check for GUID_NULL first and skip if found
  391. if (IsEqualCLSID(clsid, GUID_NULL))
  392. bResult = TRUE;
  393. else
  394. {
  395. // otherwise will need a stream
  396. LPSTREAM pstm = _AfxGetArchiveStream(m_ar, stm);
  397. if (IsEqualCLSID(clsid, CLSID_StdPicture) ||
  398. IsEqualCLSID(clsid, _afx_CLSID_StdPicture2_V1))
  399. {
  400. // special case for pictures
  401. bResult = SUCCEEDED(::OleLoadPicture(pstm, 0, FALSE, iid,
  402. (void**)ppUnk));
  403. }
  404. else
  405. {
  406. // otherwise, seek back to the CLSID
  407. LARGE_INTEGER li;
  408. li.LowPart = (DWORD)(-(long)sizeof(CLSID));
  409. li.HighPart = -1;
  410. VERIFY(SUCCEEDED(pstm->Seek(li, STREAM_SEEK_CUR, NULL)));
  411. // and load the object normally
  412. CLSID clsid;
  413. if (SUCCEEDED(::ReadClassStm(pstm, &clsid)) &&
  414. (SUCCEEDED(::CoCreateInstance(clsid, NULL,
  415. CLSCTX_SERVER | CLSCTX_REMOTE_SERVER,
  416. iid, (void**)ppUnk)) ||
  417. SUCCEEDED(::CoCreateInstance(clsid, NULL,
  418. CLSCTX_SERVER & ~CLSCTX_REMOTE_SERVER,
  419. iid, (void**)ppUnk))))
  420. {
  421. LPPERSISTSTREAM pps = NULL;
  422. if (SUCCEEDED((*ppUnk)->QueryInterface(
  423. IID_IPersistStream, (void**)&pps)) ||
  424. SUCCEEDED((*ppUnk)->QueryInterface(
  425. IID_IPersistStreamInit, (void**)&pps)))
  426. {
  427. ASSERT_POINTER(pps, IPersistStream);
  428. bResult = SUCCEEDED(pps->Load(pstm));
  429. pps->Release();
  430. }
  431. if (!bResult)
  432. {
  433. (*ppUnk)->Release();
  434. *ppUnk = NULL;
  435. }
  436. }
  437. }
  438. }
  439. }
  440. else
  441. {
  442. // Use default value.
  443. bResult = pUnkDefault == NULL ||
  444. SUCCEEDED(pUnkDefault->QueryInterface(iid, (LPVOID*)ppUnk));
  445. }
  446. }
  447. else
  448. {
  449. ASSERT_NULL_OR_POINTER(*ppUnk, IUnknown);
  450. // Check if *ppUnk and pUnkDefault are the same thing. If so, don't
  451. // bother saving the object; just write a special flag instead.
  452. if (_AfxIsSameUnknownObject(iid, *ppUnk, pUnkDefault))
  453. {
  454. m_ar << (BYTE)0xFF;
  455. bResult = TRUE;
  456. }
  457. else
  458. {
  459. m_ar << (BYTE)0x00;
  460. if (*ppUnk != NULL)
  461. {
  462. LPPERSISTSTREAM pps = NULL;
  463. if (SUCCEEDED((*ppUnk)->QueryInterface(
  464. IID_IPersistStream, (void**)&pps)) ||
  465. SUCCEEDED((*ppUnk)->QueryInterface(
  466. IID_IPersistStreamInit, (void**)&pps)))
  467. {
  468. ASSERT_POINTER(pps, IPersistStream);
  469. LPSTREAM pstm = _AfxGetArchiveStream(m_ar, stm);
  470. bResult = SUCCEEDED(::OleSaveToStream(pps, pstm));
  471. pps->Release();
  472. }
  473. }
  474. else
  475. {
  476. // If no object, write null class ID.
  477. m_ar.Write(&GUID_NULL, sizeof(GUID));
  478. }
  479. }
  480. }
  481. // throw exception in case of unthrown errors
  482. if (!bResult)
  483. AfxThrowArchiveException(CArchiveException::generic);
  484. return TRUE;
  485. }
  486. BOOL CArchivePropExchange::ExchangeFontProp(LPCTSTR pszPropName,
  487. CFontHolder& font, const FONTDESC* pFontDesc, LPFONTDISP pFontDispAmbient)
  488. {
  489. UNUSED(pszPropName); // unused in release builds
  490. ASSERT(AfxIsValidString(pszPropName));
  491. ASSERT_POINTER(&font, CFontHolder);
  492. ASSERT_NULL_OR_POINTER(pFontDesc, FONTDESC);
  493. ASSERT_NULL_OR_POINTER(pFontDispAmbient, IFontDisp);
  494. BOOL bResult = FALSE;
  495. CArchiveStream stm(&m_ar);
  496. LPFONT pFont;
  497. if (m_bLoading)
  498. {
  499. BYTE bFlag;
  500. m_ar >> bFlag;
  501. if (bFlag != 0xFF)
  502. {
  503. LPSTREAM pstm = _AfxGetArchiveStream(m_ar, stm);
  504. pFont = _AfxCreateFontFromStream(pstm);
  505. if (pFont != NULL)
  506. {
  507. font.SetFont(pFont);
  508. bResult = TRUE;
  509. }
  510. }
  511. if (!bResult)
  512. {
  513. font.InitializeFont(pFontDesc, pFontDispAmbient);
  514. bResult = TRUE;
  515. }
  516. }
  517. else
  518. {
  519. pFont = font.m_pFont;
  520. if (pFont != NULL)
  521. {
  522. // If same as ambient font (or error), write 0xFF for the flag
  523. if (!_AfxIsSameFont(font, pFontDesc, pFontDispAmbient))
  524. {
  525. LPPERSISTSTREAM pps = NULL;
  526. if (SUCCEEDED(pFont->QueryInterface(IID_IPersistStream,
  527. (LPVOID*)&pps)))
  528. {
  529. ASSERT_POINTER(pps, IPersistStream);
  530. m_ar << (BYTE)0x00;
  531. LPSTREAM pstm = _AfxGetArchiveStream(m_ar, stm);
  532. bResult = SUCCEEDED(::OleSaveToStream(pps, pstm));
  533. pps->Release();
  534. if (!bResult)
  535. AfxThrowArchiveException(CArchiveException::generic);
  536. }
  537. }
  538. }
  539. if (!bResult)
  540. {
  541. m_ar << (BYTE)0xFF;
  542. bResult = TRUE;
  543. }
  544. }
  545. return bResult;
  546. }
  547. /////////////////////////////////////////////////////////////////////////////
  548. // CResetPropExchange member functions
  549. CResetPropExchange::CResetPropExchange()
  550. {
  551. m_bLoading = TRUE;
  552. }
  553. BOOL CResetPropExchange::ExchangeProp(LPCTSTR pszPropName, VARTYPE vtProp,
  554. void* pvProp, const void* pvDefault)
  555. {
  556. UNUSED(pszPropName); // unused in release builds
  557. ASSERT(AfxIsValidString(pszPropName));
  558. ASSERT(AfxIsValidAddress(pvProp, 1, FALSE));
  559. ASSERT((pvDefault == NULL) || AfxIsValidAddress(pvDefault, 1, FALSE));
  560. return _AfxCopyPropValue(vtProp, pvProp, pvDefault);
  561. }
  562. BOOL CResetPropExchange::ExchangeBlobProp(LPCTSTR pszPropName,
  563. HGLOBAL* phBlob, HGLOBAL hBlobDefault)
  564. {
  565. UNUSED(pszPropName); // unused in release builds
  566. ASSERT(AfxIsValidString(pszPropName));
  567. ASSERT_POINTER(phBlob, HGLOBAL);
  568. // free the previous memory block
  569. if (*phBlob != NULL)
  570. {
  571. GlobalFree(*phBlob);
  572. *phBlob = NULL;
  573. }
  574. // copy the memory block
  575. BOOL bResult = TRUE;
  576. if (hBlobDefault != NULL)
  577. bResult = _AfxCopyBlob(phBlob, hBlobDefault);
  578. return bResult;
  579. }
  580. BOOL CResetPropExchange::ExchangePersistentProp(LPCTSTR pszPropName,
  581. LPUNKNOWN* ppUnk, REFIID iid, LPUNKNOWN pUnkDefault)
  582. {
  583. UNUSED(pszPropName); // unused in release builds
  584. ASSERT(AfxIsValidString(pszPropName));
  585. ASSERT_POINTER(ppUnk, LPUNKNOWN);
  586. ASSERT_NULL_OR_POINTER(pUnkDefault, IUnknown);
  587. RELEASE(*ppUnk);
  588. BOOL bResult = TRUE;
  589. if (pUnkDefault != NULL)
  590. {
  591. bResult = SUCCEEDED(pUnkDefault->QueryInterface(iid,
  592. (LPVOID*)ppUnk));
  593. }
  594. return bResult;
  595. }
  596. BOOL CResetPropExchange::ExchangeFontProp(
  597. LPCTSTR pszPropName, CFontHolder& font, const FONTDESC* pFontDesc,
  598. LPFONTDISP pFontDispAmbient)
  599. {
  600. UNUSED(pszPropName); // unused in release builds
  601. ASSERT(AfxIsValidString(pszPropName));
  602. ASSERT_POINTER(&font, CFontHolder);
  603. ASSERT_NULL_OR_POINTER(pFontDesc, FONTDESC);
  604. ASSERT_NULL_OR_POINTER(pFontDispAmbient, IFontDisp);
  605. font.InitializeFont(pFontDesc, pFontDispAmbient);
  606. return TRUE;
  607. }
  608. /////////////////////////////////////////////////////////////////////////////
  609. // CAsyncPropExchange member functions
  610. CAsyncPropExchange::CAsyncPropExchange(DWORD dwVersion)
  611. {
  612. m_bAsync = TRUE;
  613. m_bLoading = TRUE;
  614. m_dwVersion = dwVersion;
  615. }
  616. BOOL CAsyncPropExchange::ExchangeVersion(DWORD& dwVersionLoaded,
  617. DWORD dwVersionDefault, BOOL bConvert)
  618. {
  619. if (m_bLoading)
  620. {
  621. dwVersionLoaded = m_dwVersion;
  622. return TRUE;
  623. }
  624. else
  625. {
  626. return m_dwVersion == (bConvert ? dwVersionDefault : dwVersionLoaded);
  627. }
  628. }
  629. BOOL CAsyncPropExchange::ExchangeProp(LPCTSTR pszPropName, VARTYPE vtProp,
  630. void* pvProp, const void* pvDefault)
  631. {
  632. // Should never be called
  633. UNUSED_ALWAYS(pszPropName);
  634. UNUSED_ALWAYS(vtProp);
  635. UNUSED_ALWAYS(pvProp);
  636. UNUSED_ALWAYS(pvDefault);
  637. ASSERT(FALSE);
  638. return FALSE;
  639. }
  640. BOOL CAsyncPropExchange::ExchangeBlobProp(LPCTSTR pszPropName, HGLOBAL* phBlob,
  641. HGLOBAL hBlobDefault)
  642. {
  643. // Should never be called
  644. UNUSED_ALWAYS(pszPropName);
  645. UNUSED_ALWAYS(phBlob);
  646. UNUSED_ALWAYS(hBlobDefault);
  647. ASSERT(FALSE);
  648. return FALSE;
  649. }
  650. BOOL CAsyncPropExchange::ExchangeFontProp(LPCTSTR pszPropName,
  651. CFontHolder& font, const FONTDESC* pFontDesc, LPFONTDISP pFontDispAmbient)
  652. {
  653. // Should never be called
  654. UNUSED_ALWAYS(pszPropName);
  655. UNUSED_ALWAYS(font);
  656. UNUSED_ALWAYS(pFontDesc);
  657. UNUSED_ALWAYS(pFontDispAmbient);
  658. ASSERT(FALSE);
  659. return FALSE;
  660. }
  661. BOOL CAsyncPropExchange::ExchangePersistentProp(LPCTSTR pszPropName,
  662. LPUNKNOWN* ppUnk, REFIID iid, LPUNKNOWN pUnkDefault)
  663. {
  664. // Should never be called
  665. UNUSED_ALWAYS(pszPropName);
  666. UNUSED_ALWAYS(ppUnk);
  667. UNUSED_ALWAYS(iid);
  668. UNUSED_ALWAYS(pUnkDefault);
  669. ASSERT(FALSE);
  670. return FALSE;
  671. }
  672. /////////////////////////////////////////////////////////////////////////////
  673. // PX_ functions
  674. BOOL AFX_CDECL PX_Short(CPropExchange* pPX, LPCTSTR pszPropName, short& sValue)
  675. {
  676. ASSERT_POINTER(pPX, CPropExchange);
  677. ASSERT(AfxIsValidString(pszPropName));
  678. ASSERT_POINTER(&sValue, short);
  679. if (pPX->IsAsynchronous())
  680. return TRUE;
  681. return pPX->ExchangeProp(pszPropName, VT_I2, &sValue);
  682. }
  683. BOOL AFX_CDECL PX_Short(CPropExchange* pPX, LPCTSTR pszPropName, short& sValue,
  684. short sDefault)
  685. {
  686. ASSERT_POINTER(pPX, CPropExchange);
  687. ASSERT(AfxIsValidString(pszPropName));
  688. ASSERT_POINTER(&sValue, short);
  689. if (pPX->IsAsynchronous())
  690. return TRUE;
  691. return pPX->ExchangeProp(pszPropName, VT_I2, &sValue, &sDefault);
  692. }
  693. BOOL AFX_CDECL PX_UShort(CPropExchange* pPX, LPCTSTR pszPropName, USHORT& usValue)
  694. {
  695. ASSERT_POINTER(pPX, CPropExchange);
  696. ASSERT(AfxIsValidString(pszPropName));
  697. ASSERT_POINTER(&usValue, USHORT);
  698. if (pPX->IsAsynchronous())
  699. return TRUE;
  700. return pPX->ExchangeProp(pszPropName, VT_I2, &usValue);
  701. }
  702. BOOL AFX_CDECL PX_UShort(CPropExchange* pPX, LPCTSTR pszPropName, USHORT& usValue,
  703. USHORT usDefault)
  704. {
  705. ASSERT_POINTER(pPX, CPropExchange);
  706. ASSERT(AfxIsValidString(pszPropName));
  707. ASSERT_POINTER(&usValue, USHORT);
  708. if (pPX->IsAsynchronous())
  709. return TRUE;
  710. return pPX->ExchangeProp(pszPropName, VT_I2, &usValue, &usDefault);
  711. }
  712. BOOL AFX_CDECL PX_Long(CPropExchange* pPX, LPCTSTR pszPropName, long& lValue)
  713. {
  714. ASSERT_POINTER(pPX, CPropExchange);
  715. ASSERT(AfxIsValidString(pszPropName));
  716. ASSERT_POINTER(&lValue, long);
  717. if (pPX->IsAsynchronous())
  718. return TRUE;
  719. return pPX->ExchangeProp(pszPropName, VT_I4, &lValue);
  720. }
  721. BOOL AFX_CDECL PX_Long(CPropExchange* pPX, LPCTSTR pszPropName, long& lValue,
  722. long lDefault)
  723. {
  724. ASSERT_POINTER(pPX, CPropExchange);
  725. ASSERT(AfxIsValidString(pszPropName));
  726. ASSERT_POINTER(&lValue, long);
  727. if (pPX->IsAsynchronous())
  728. return TRUE;
  729. return pPX->ExchangeProp(pszPropName, VT_I4, &lValue, &lDefault);
  730. }
  731. BOOL AFX_CDECL PX_ULong(CPropExchange* pPX, LPCTSTR pszPropName, ULONG& ulValue)
  732. {
  733. ASSERT_POINTER(pPX, CPropExchange);
  734. ASSERT(AfxIsValidString(pszPropName));
  735. ASSERT_POINTER(&ulValue, ULONG);
  736. if (pPX->IsAsynchronous())
  737. return TRUE;
  738. return pPX->ExchangeProp(pszPropName, VT_I4, &ulValue);
  739. }
  740. BOOL AFX_CDECL PX_ULong(CPropExchange* pPX, LPCTSTR pszPropName, ULONG& ulValue,
  741. ULONG ulDefault)
  742. {
  743. ASSERT_POINTER(pPX, CPropExchange);
  744. ASSERT(AfxIsValidString(pszPropName));
  745. ASSERT_POINTER(&ulValue, ULONG);
  746. if (pPX->IsAsynchronous())
  747. return TRUE;
  748. return pPX->ExchangeProp(pszPropName, VT_I4, &ulValue, &ulDefault);
  749. }
  750. BOOL AFX_CDECL PX_Color(CPropExchange* pPX, LPCTSTR pszPropName, OLE_COLOR& clrValue)
  751. {
  752. ASSERT_POINTER(pPX, CPropExchange);
  753. ASSERT(AfxIsValidString(pszPropName));
  754. ASSERT_POINTER(&clrValue, OLE_COLOR);
  755. if (pPX->IsAsynchronous())
  756. return TRUE;
  757. return pPX->ExchangeProp(pszPropName, VT_I4, &clrValue);
  758. }
  759. BOOL AFX_CDECL PX_Color(CPropExchange* pPX, LPCTSTR pszPropName, OLE_COLOR& clrValue,
  760. OLE_COLOR clrDefault)
  761. {
  762. ASSERT_POINTER(pPX, CPropExchange);
  763. ASSERT(AfxIsValidString(pszPropName));
  764. ASSERT_POINTER(&clrValue, OLE_COLOR);
  765. if (pPX->IsAsynchronous())
  766. return TRUE;
  767. return pPX->ExchangeProp(pszPropName, VT_I4, &clrValue, &clrDefault);
  768. }
  769. BOOL AFX_CDECL PX_Bool(CPropExchange* pPX, LPCTSTR pszPropName, BOOL& bValue)
  770. {
  771. ASSERT_POINTER(pPX, CPropExchange);
  772. ASSERT(AfxIsValidString(pszPropName));
  773. ASSERT_POINTER(&bValue, BOOL);
  774. if (pPX->IsAsynchronous())
  775. return TRUE;
  776. return pPX->ExchangeProp(pszPropName, VT_BOOL, &bValue);
  777. }
  778. BOOL AFX_CDECL PX_Bool(CPropExchange* pPX, LPCTSTR pszPropName, BOOL& bValue,
  779. BOOL bDefault)
  780. {
  781. ASSERT_POINTER(pPX, CPropExchange);
  782. ASSERT(AfxIsValidString(pszPropName));
  783. ASSERT_POINTER(&bValue, BOOL);
  784. if (pPX->IsAsynchronous())
  785. return TRUE;
  786. return pPX->ExchangeProp(pszPropName, VT_BOOL, &bValue, &bDefault);
  787. }
  788. BOOL AFX_CDECL PX_String(CPropExchange* pPX, LPCTSTR pszPropName, CString& strValue)
  789. {
  790. ASSERT_POINTER(pPX, CPropExchange);
  791. ASSERT(AfxIsValidString(pszPropName));
  792. ASSERT_POINTER(&strValue, CString);
  793. if (pPX->IsAsynchronous())
  794. return TRUE;
  795. return pPX->ExchangeProp(pszPropName, VT_BSTR, &strValue);
  796. }
  797. BOOL AFX_CDECL PX_String(CPropExchange* pPX, LPCTSTR pszPropName, CString& strValue,
  798. const CString& strDefault)
  799. {
  800. ASSERT_POINTER(pPX, CPropExchange);
  801. ASSERT(AfxIsValidString(pszPropName));
  802. ASSERT_POINTER(&strValue, CString);
  803. if (pPX->IsAsynchronous())
  804. return TRUE;
  805. return pPX->ExchangeProp(pszPropName, VT_BSTR, &strValue, &strDefault);
  806. }
  807. BOOL AFX_CDECL PX_String(CPropExchange* pPX, LPCTSTR pszPropName, CString& strValue,
  808. LPCTSTR lpszDefault)
  809. {
  810. ASSERT_POINTER(pPX, CPropExchange);
  811. ASSERT(AfxIsValidString(pszPropName));
  812. ASSERT_POINTER(&strValue, CString);
  813. if (pPX->IsAsynchronous())
  814. return TRUE;
  815. return pPX->ExchangeProp(pszPropName, VT_LPSTR, &strValue, lpszDefault);
  816. }
  817. BOOL AFX_CDECL PX_Currency(CPropExchange* pPX, LPCTSTR pszPropName, CY& cyValue)
  818. {
  819. ASSERT_POINTER(pPX, CPropExchange);
  820. ASSERT(AfxIsValidString(pszPropName));
  821. ASSERT_POINTER(&cyValue, CY);
  822. if (pPX->IsAsynchronous())
  823. return TRUE;
  824. return pPX->ExchangeProp(pszPropName, VT_CY, &cyValue);
  825. }
  826. BOOL AFX_CDECL PX_Currency(CPropExchange* pPX, LPCTSTR pszPropName, CY& cyValue,
  827. CY cyDefault)
  828. {
  829. ASSERT_POINTER(pPX, CPropExchange);
  830. ASSERT(AfxIsValidString(pszPropName));
  831. ASSERT_POINTER(&cyValue, CY);
  832. if (pPX->IsAsynchronous())
  833. return TRUE;
  834. return pPX->ExchangeProp(pszPropName, VT_CY, &cyValue, &cyDefault);
  835. }
  836. BOOL AFX_CDECL PX_Float(CPropExchange* pPX, LPCTSTR pszPropName, float& floatValue)
  837. {
  838. ASSERT_POINTER(pPX, CPropExchange);
  839. ASSERT(AfxIsValidString(pszPropName));
  840. ASSERT_POINTER(&floatValue, float);
  841. if (pPX->IsAsynchronous())
  842. return TRUE;
  843. return pPX->ExchangeProp(pszPropName, VT_R4, &floatValue);
  844. }
  845. BOOL AFX_CDECL PX_Float(CPropExchange* pPX, LPCTSTR pszPropName, float& floatValue,
  846. float floatDefault)
  847. {
  848. ASSERT_POINTER(pPX, CPropExchange);
  849. ASSERT(AfxIsValidString(pszPropName));
  850. ASSERT_POINTER(&floatValue, float);
  851. if (pPX->IsAsynchronous())
  852. return TRUE;
  853. return pPX->ExchangeProp(pszPropName, VT_R4, &floatValue, &floatDefault);
  854. }
  855. BOOL AFX_CDECL PX_Double(CPropExchange* pPX, LPCTSTR pszPropName, double& doubleValue)
  856. {
  857. ASSERT_POINTER(pPX, CPropExchange);
  858. ASSERT(AfxIsValidString(pszPropName));
  859. ASSERT_POINTER(&doubleValue, double);
  860. if (pPX->IsAsynchronous())
  861. return TRUE;
  862. return pPX->ExchangeProp(pszPropName, VT_R8, &doubleValue);
  863. }
  864. BOOL AFX_CDECL PX_Double(CPropExchange* pPX, LPCTSTR pszPropName, double& doubleValue,
  865. double doubleDefault)
  866. {
  867. ASSERT_POINTER(pPX, CPropExchange);
  868. ASSERT(AfxIsValidString(pszPropName));
  869. ASSERT_POINTER(&doubleValue, double);
  870. if (pPX->IsAsynchronous())
  871. return TRUE;
  872. return pPX->ExchangeProp(pszPropName, VT_R8, &doubleValue, &doubleDefault);
  873. }
  874. BOOL AFX_CDECL PX_Blob(CPropExchange* pPX, LPCTSTR pszPropName, HGLOBAL& hBlob,
  875. HGLOBAL hBlobDefault)
  876. {
  877. ASSERT_POINTER(pPX, CPropExchange);
  878. ASSERT(AfxIsValidString(pszPropName));
  879. ASSERT_POINTER(&hBlob, HGLOBAL);
  880. if (pPX->IsAsynchronous())
  881. return TRUE;
  882. return pPX->ExchangeBlobProp(pszPropName, &hBlob, hBlobDefault);
  883. }
  884. BOOL AFX_CDECL PX_Font(CPropExchange* pPX, LPCTSTR pszPropName, CFontHolder& font,
  885. const FONTDESC* pFontDesc, LPFONTDISP pFontDispAmbient)
  886. {
  887. ASSERT_POINTER(pPX, CPropExchange);
  888. ASSERT(AfxIsValidString(pszPropName));
  889. ASSERT_POINTER(&font, CFontHolder);
  890. ASSERT_NULL_OR_POINTER(pFontDesc, FONTDESC);
  891. ASSERT_NULL_OR_POINTER(pFontDispAmbient, IFontDisp);
  892. if (pPX->IsAsynchronous())
  893. return TRUE;
  894. return pPX->ExchangeFontProp(pszPropName, font, pFontDesc,
  895. pFontDispAmbient);
  896. }
  897. BOOL AFX_CDECL PX_IUnknown(CPropExchange* pPX, LPCTSTR pszPropName, LPUNKNOWN& pUnk,
  898. REFIID iid, LPUNKNOWN pUnkDefault)
  899. {
  900. ASSERT_POINTER(pPX, CPropExchange);
  901. ASSERT(AfxIsValidString(pszPropName));
  902. ASSERT_POINTER(&pUnk, LPUNKNOWN);
  903. ASSERT_NULL_OR_POINTER(pUnk, IUnknown);
  904. ASSERT_NULL_OR_POINTER(pUnkDefault, IUnknown);
  905. if (pPX->IsAsynchronous())
  906. return TRUE;
  907. return pPX->ExchangePersistentProp(pszPropName, &pUnk, iid, pUnkDefault);
  908. }
  909. BOOL AFX_CDECL PX_Picture(CPropExchange* pPX, LPCTSTR pszPropName, CPictureHolder& pict)
  910. {
  911. ASSERT_POINTER(pPX, CPropExchange);
  912. ASSERT(AfxIsValidString(pszPropName));
  913. ASSERT_POINTER(&pict, CPictureHolder);
  914. if (pPX->IsAsynchronous())
  915. return TRUE;
  916. LPUNKNOWN& pUnk = (LPUNKNOWN&)pict.m_pPict;
  917. return PX_IUnknown(pPX, pszPropName, pUnk, IID_IPicture);
  918. }
  919. BOOL AFX_CDECL PX_Picture(CPropExchange* pPX, LPCTSTR pszPropName, CPictureHolder& pict,
  920. CPictureHolder& pictDefault)
  921. {
  922. ASSERT_POINTER(pPX, CPropExchange);
  923. ASSERT(AfxIsValidString(pszPropName));
  924. ASSERT_POINTER(&pict, CPictureHolder);
  925. if (pPX->IsAsynchronous())
  926. return TRUE;
  927. LPUNKNOWN& pUnk = (LPUNKNOWN&)pict.m_pPict;
  928. return PX_IUnknown(pPX, pszPropName, pUnk, IID_IPicture,
  929. pictDefault.m_pPict);
  930. }
  931. BOOL AFX_CDECL PX_VBXFontConvert(CPropExchange* pPX, CFontHolder& font)
  932. {
  933. USES_CONVERSION;
  934. ASSERT_POINTER(pPX, CPropExchange);
  935. ASSERT_POINTER(&font, CFontHolder);
  936. if (pPX->IsAsynchronous())
  937. return TRUE;
  938. if (font.m_pFont != NULL)
  939. {
  940. CString strName;
  941. if (PX_String(pPX, _T("FontName"), strName))
  942. {
  943. BSTR bstrName;
  944. bstrName = SysAllocString(T2COLE(strName));
  945. font.m_pFont->put_Name(bstrName);
  946. SysFreeString(bstrName);
  947. }
  948. CY cySize;
  949. if (PX_Currency(pPX, _T("FontSize"), cySize))
  950. font.m_pFont->put_Size(cySize);
  951. BOOL bFlag;
  952. if (PX_Bool(pPX, _T("FontBold"), bFlag))
  953. font.m_pFont->put_Bold(bFlag);
  954. if (PX_Bool(pPX, _T("FontItalic"), bFlag))
  955. font.m_pFont->put_Italic(bFlag);
  956. if (PX_Bool(pPX, _T("FontUnderline"), bFlag))
  957. font.m_pFont->put_Underline(bFlag);
  958. if (PX_Bool(pPX, _T("FontStrikethru"), bFlag))
  959. font.m_pFont->put_Strikethrough(bFlag);
  960. }
  961. return TRUE;
  962. }
  963. AFX_STATIC BOOL AFXAPI _Afx_PX_DataPath(CPropExchange* pPX, LPCTSTR pszPropName,
  964. CDataPathProperty& dataPathProp, VARTYPE vtDefault, const void* pvDefault)
  965. {
  966. ASSERT_POINTER(pPX, CPropExchange);
  967. ASSERT(AfxIsValidString(pszPropName));
  968. const BOOL bIsLoading = pPX->IsLoading();
  969. COleControl* pControl = dataPathProp.GetControl();
  970. if (!pControl)
  971. TRACE0("No control in PX_DataPath!");
  972. BOOL bHasClientSite = pControl ? NULL != pControl->GetClientSite() : FALSE;
  973. if (!pPX->IsAsynchronous())
  974. {
  975. CString strPath;
  976. if (!bIsLoading)
  977. strPath = dataPathProp.GetPath();
  978. if (((pvDefault != NULL) && !pPX->ExchangeProp(pszPropName, vtDefault, &strPath, pvDefault)) ||
  979. ((pvDefault == NULL) && !pPX->ExchangeProp(pszPropName, VT_BSTR, &strPath)))
  980. return FALSE;
  981. if (bIsLoading)
  982. dataPathProp.SetPath(strPath);
  983. if (pControl && !bHasClientSite)
  984. pControl->RequestAsynchronousExchange(pPX->GetVersion());
  985. }
  986. if (pPX->IsAsynchronous() || bHasClientSite)
  987. {
  988. #ifdef _DEBUG
  989. {
  990. if (!bHasClientSite)
  991. TRACE0("No client site in PX_DataPath!");
  992. }
  993. #endif // _DEBUG
  994. if (bIsLoading)
  995. return dataPathProp.Open();
  996. }
  997. return TRUE;
  998. }
  999. BOOL AFX_CDECL PX_DataPath(CPropExchange* pPX, LPCTSTR pszPropName,
  1000. CDataPathProperty& dataPathProp, LPCTSTR pszDefault)
  1001. {
  1002. return _Afx_PX_DataPath(pPX, pszPropName, dataPathProp, VT_LPSTR, pszDefault);
  1003. }
  1004. BOOL AFX_CDECL PX_DataPath(CPropExchange* pPX, LPCTSTR pszPropName,
  1005. CDataPathProperty& dataPathProp, const CString& strDefault)
  1006. {
  1007. return _Afx_PX_DataPath(pPX, pszPropName, dataPathProp, VT_BSTR, &strDefault);
  1008. }
  1009. /////////////////////////////////////////////////////////////////////////////
  1010. // Force any extra compiler-generated code into AFX_INIT_SEG
  1011. #ifdef AFX_INIT_SEG
  1012. #pragma code_seg(AFX_INIT_SEG)
  1013. #endif