home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / ctlpropx.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  30KB  |  1,170 lines

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