home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / mfc / src / daodfx.cpp < prev    next >
C/C++ Source or Header  |  1998-06-16  |  36KB  |  1,509 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.  
  12. #include "stdafx.h"
  13. #include "math.h"
  14.  
  15. #ifdef AFX_DB_SEG
  16. #pragma code_seg(AFX_DB_SEG)
  17. #endif
  18.  
  19. #ifdef _DEBUG
  20. #undef THIS_FILE
  21. static char THIS_FILE[] = __FILE__;
  22. #endif
  23.  
  24. #define new DEBUG_NEW
  25.  
  26. //////////////////////////////////////////////////////////////////////////
  27. // Helpers
  28.  
  29. // Helpers for floating point operations
  30. AFX_STATIC_DATA const float _afxFloatPseudoNull = AFX_RFX_SINGLE_PSEUDO_NULL;
  31. AFX_STATIC_DATA const double _afxDoublePseudoNull = AFX_RFX_DOUBLE_PSEUDO_NULL;
  32.  
  33. // Long binary allocation helper
  34. void AFX_CDECL AllocLongBinary(CLongBinary& lb, DWORD dwDataLength);
  35.  
  36. // Memory allocation callbacks used by ICDAOGetRows
  37. STDAPI DaoStringAllocCallback(DWORD dwLen, DWORD pData, void** ppv);
  38. STDAPI DaoBinaryAllocCallback(DWORD dwLen, DWORD pData, void** ppv);
  39. STDAPI DaoLongBinaryAllocCallback(DWORD dwLen, DWORD pData, void** ppv);
  40.  
  41. //////////////////////////////////////////////////////////////////////////
  42. // CDaoFieldExchange
  43.  
  44. CDaoFieldExchange::CDaoFieldExchange(UINT nOperation,
  45.     CDaoRecordset* prs, void* pvField)
  46. {
  47.     ASSERT(nOperation < MaxDFXOperation);
  48.  
  49.     m_nFieldType = none;
  50.     m_nOperation = nOperation;
  51.     m_prs = prs;
  52.     m_pvField = pvField;
  53.     m_nField = 0;
  54.     m_nParam = 0;
  55. }
  56.  
  57. BOOL CDaoFieldExchange::IsValidOperation()
  58. {
  59.     if (m_nOperation >= MaxDFXOperation)
  60.     {
  61.         // Invalid operation
  62.         ASSERT(FALSE);
  63.         return FALSE;
  64.     }
  65.  
  66.     // Operations valid for both field types
  67. #ifdef _DEBUG
  68.     if (m_nOperation == DumpField || m_nOperation == SetFieldNull)
  69.         return TRUE;
  70. #endif
  71.  
  72.     // Operations only valid for outputColumn OR param types
  73.     if ((m_nOperation == AddToParameterList) ||
  74.         (m_nOperation == BindParam))
  75.         return (m_nFieldType == param);
  76.     else
  77.         return (m_nFieldType == outputColumn);
  78. }
  79.  
  80. void CDaoFieldExchange::AppendParamType(CString& strParamList,
  81.     DWORD dwParamType)
  82. {
  83.     switch (dwParamType)
  84.     {
  85.     default:
  86.         ASSERT(FALSE);
  87.         break;
  88.  
  89.     case AFX_RFX_TEXT:
  90.         strParamList += " Text";
  91.         break;
  92.  
  93.     case AFX_RFX_BINARY:
  94.         strParamList += " LongBinary";
  95.         break;
  96.  
  97.     case AFX_RFX_LONGBINARY:
  98.         strParamList += " LongBinary";
  99.         break;
  100.  
  101.     case AFX_RFX_BOOL:
  102.         strParamList += " Bit";
  103.         break;
  104.  
  105.     case AFX_RFX_BYTE:
  106.         strParamList += " Byte";
  107.         break;
  108.  
  109.     case AFX_RFX_SHORT:
  110.         strParamList += " Short";
  111.         break;
  112.  
  113.     case AFX_RFX_LONG:
  114.         strParamList += " Long";
  115.         break;
  116.  
  117.     case AFX_RFX_CURRENCY:
  118.         strParamList += " Currency";
  119.         break;
  120.  
  121.     case AFX_RFX_SINGLE:
  122.         strParamList += " IEEESingle";
  123.         break;
  124.  
  125.     case AFX_RFX_DOUBLE:
  126.         strParamList += " IEEEDouble";
  127.         break;
  128.  
  129.     case AFX_RFX_DATE:
  130.         strParamList += " DateTime";
  131.         break;
  132.     }
  133. }
  134.  
  135. CDaoFieldCache* CDaoFieldExchange::GetCacheValue(CDaoRecordset* prs, void* pv)
  136. {
  137.     // Lookup storage locations
  138.     void* pvCache;
  139.     if (!prs->m_pMapFieldCache->Lookup(pv, pvCache))
  140.         AfxThrowDaoException(AFX_DAO_ERROR_DFX_BIND);
  141.     return (CDaoFieldCache*)pvCache;
  142. }
  143.  
  144. void CDaoFieldExchange::SetNullValue(void* pv, DWORD dwDataType)
  145. {
  146.     switch (dwDataType)
  147.     {
  148.     default:
  149.         ASSERT(FALSE);
  150.         break;
  151.  
  152.     case AFX_RFX_TEXT:
  153.         ((CString*)pv)->Empty();
  154.         break;
  155.  
  156.     case AFX_RFX_BINARY:
  157.         ((CByteArray*)pv)->SetSize(0);
  158.         break;
  159.  
  160.     case AFX_RFX_LONGBINARY:
  161.         ((CLongBinary*)pv)->m_dwDataLength = 0;
  162.         break;
  163.  
  164.     case AFX_RFX_BOOL:
  165.         *(BOOL*)pv = AFX_RFX_BOOL_PSEUDO_NULL;
  166.         break;
  167.  
  168.     case AFX_RFX_BYTE:
  169.         *(BYTE*)pv = AFX_RFX_BYTE_PSEUDO_NULL;
  170.         break;
  171.  
  172.     case AFX_RFX_SHORT:
  173.         *(short*)pv = AFX_RFX_SHORT_PSEUDO_NULL;
  174.         break;
  175.  
  176.     case AFX_RFX_LONG:
  177.         *(long*)pv = AFX_RFX_LONG_PSEUDO_NULL;
  178.         break;
  179.  
  180.     case AFX_RFX_CURRENCY:
  181.         ((COleCurrency*)pv)->SetStatus(COleCurrency::null);
  182.         break;
  183.  
  184.     case AFX_RFX_SINGLE:
  185.         *(float*)pv = _afxFloatPseudoNull;
  186.         break;
  187.  
  188.     case AFX_RFX_DOUBLE:
  189.         *(double*)pv = _afxDoublePseudoNull;
  190.         break;
  191.  
  192.     case AFX_RFX_DATE:
  193.         ((COleDateTime*)pv)->SetStatus(COleDateTime::null);
  194.         break;
  195.     }
  196. }
  197.  
  198. BOOL CDaoFieldExchange::IsNullValue(void* pv, DWORD dwDataType)
  199. {
  200.     BOOL bNull = FALSE;
  201.  
  202.     switch (dwDataType)
  203.     {
  204.     default:
  205.         ASSERT(FALSE);
  206.         break;
  207.  
  208.     case AFX_RFX_TEXT:
  209.         if (((CString*)pv)->IsEmpty())
  210.             bNull = TRUE;
  211.         break;
  212.  
  213.     case AFX_RFX_BINARY:
  214.         if (((CByteArray*)pv)->GetSize() == 0)
  215.             bNull = TRUE;
  216.         break;
  217.  
  218.     case AFX_RFX_LONGBINARY:
  219.         if (((CLongBinary*)pv)->m_dwDataLength == 0)
  220.             bNull = TRUE;
  221.         break;
  222.  
  223.     case AFX_RFX_BOOL:
  224.         if (*(BOOL*)pv == AFX_RFX_BOOL_PSEUDO_NULL)
  225.             bNull = TRUE;
  226.         break;
  227.  
  228.     case AFX_RFX_BYTE:
  229.         if (*(BYTE*)pv == AFX_RFX_BYTE_PSEUDO_NULL)
  230.             bNull = TRUE;
  231.         break;
  232.  
  233.     case AFX_RFX_SHORT:
  234.         if (*(short*)pv == AFX_RFX_SHORT_PSEUDO_NULL)
  235.             bNull = TRUE;
  236.         break;
  237.  
  238.     case AFX_RFX_LONG:
  239.         if (*(long*)pv == AFX_RFX_LONG_PSEUDO_NULL)
  240.             bNull = TRUE;
  241.         break;
  242.  
  243.     case AFX_RFX_CURRENCY:
  244.         if (((COleCurrency*)pv)->GetStatus() == COleCurrency::null)
  245.             bNull = TRUE;
  246.         break;
  247.  
  248.     case AFX_RFX_SINGLE:
  249.         if (*(float*)pv == _afxFloatPseudoNull)
  250.             bNull = TRUE;
  251.         break;
  252.  
  253.     case AFX_RFX_DOUBLE:
  254.         if (*(double*)pv == _afxDoublePseudoNull)
  255.             bNull = TRUE;
  256.         break;
  257.  
  258.     case AFX_RFX_DATE:
  259.         if (((COleDateTime*)pv)->GetStatus() == COleDateTime::null)
  260.             bNull = TRUE;
  261.         break;
  262.     }
  263.  
  264.     return bNull;
  265. }
  266.  
  267. void CDaoFieldExchange::AllocCacheValue(CDaoFieldCache*& pCache,
  268.     DWORD dwDataType)
  269. {
  270.     // Initialize a new field cache
  271.     pCache = new CDaoFieldCache;
  272.     pCache->m_nStatus = 0;
  273.  
  274.     switch (dwDataType)
  275.     {
  276.     default:
  277.         ASSERT(FALSE);
  278.         break;
  279.  
  280.     case AFX_RFX_TEXT:
  281.         pCache->m_pvData = new CString();
  282.         pCache->m_nDataType = AFX_RFX_TEXT;
  283.         break;
  284.  
  285.     case AFX_RFX_BINARY:
  286.         pCache->m_pvData = new CByteArray();
  287.         pCache->m_nDataType = AFX_RFX_BINARY;
  288.         break;
  289.  
  290.     case AFX_RFX_LONGBINARY:
  291.         pCache->m_pvData = new CLongBinary();
  292.         pCache->m_nDataType = AFX_RFX_LONGBINARY;
  293.         break;
  294.  
  295.     case AFX_RFX_BOOL:
  296.         pCache->m_nDataType = AFX_RFX_BOOL;
  297.         break;
  298.  
  299.     case AFX_RFX_BYTE:
  300.         pCache->m_nDataType = AFX_RFX_BYTE;
  301.         break;
  302.  
  303.     case AFX_RFX_SHORT:
  304.         pCache->m_nDataType = AFX_RFX_SHORT;
  305.         break;
  306.  
  307.     case AFX_RFX_LONG:
  308.         pCache->m_nDataType = AFX_RFX_LONG;
  309.         break;
  310.  
  311.     case AFX_RFX_CURRENCY:
  312.         pCache->m_pvData = new COleCurrency();
  313.         pCache->m_nDataType = AFX_RFX_CURRENCY;
  314.         break;
  315.  
  316.     case AFX_RFX_SINGLE:
  317.         pCache->m_nDataType = AFX_RFX_SINGLE;
  318.         break;
  319.  
  320.     case AFX_RFX_DOUBLE:
  321.         pCache->m_pvData = new double;
  322.         pCache->m_nDataType = AFX_RFX_DOUBLE;
  323.         break;
  324.  
  325.     case AFX_RFX_DATE:
  326.         pCache->m_pvData = new COleDateTime();
  327.         pCache->m_nDataType = AFX_RFX_DATE;
  328.         break;
  329.     }
  330. }
  331.  
  332. void CDaoFieldExchange::DeleteCacheValue(CDaoFieldCache* pCache,
  333.     DWORD dwDataType)
  334. {
  335.     switch (dwDataType)
  336.     {
  337.     default:
  338.         ASSERT(FALSE);
  339.         break;
  340.  
  341.     case AFX_RFX_TEXT:
  342.         delete (CString*)pCache->m_pvData;
  343.         break;
  344.  
  345.     case AFX_RFX_BINARY:
  346.         delete (CByteArray*)pCache->m_pvData;
  347.         break;
  348.  
  349.     case AFX_RFX_LONGBINARY:
  350.         delete (CLongBinary*)pCache->m_pvData;
  351.         break;
  352.  
  353.     case AFX_RFX_BOOL:
  354.     case AFX_RFX_BYTE:
  355.     case AFX_RFX_SHORT:
  356.     case AFX_RFX_LONG:
  357.     case AFX_RFX_SINGLE:
  358.         break;
  359.  
  360.     case AFX_RFX_CURRENCY:
  361.         delete (COleCurrency*)pCache->m_pvData;
  362.         break;
  363.  
  364.     case AFX_RFX_DOUBLE:
  365.         delete (double*)pCache->m_pvData;
  366.         break;
  367.  
  368.     case AFX_RFX_DATE:
  369.         delete (COleDateTime*)pCache->m_pvData;
  370.         break;
  371.     }
  372.  
  373.     delete pCache;
  374.     pCache = NULL;
  375. }
  376.  
  377. void CDaoFieldExchange::CopyValue(void* pvSrc, void* pvDest,
  378.     DWORD dwDataType)
  379. {
  380.     switch (dwDataType)
  381.     {
  382.     default:
  383.         ASSERT(FALSE);
  384.         break;
  385.  
  386.     case AFX_RFX_TEXT:
  387.         *(CString*)pvDest = *(CString*)pvSrc;
  388.         break;
  389.  
  390.     case AFX_RFX_BINARY:
  391.         ((CByteArray*)pvDest)->Copy(*(CByteArray*)pvSrc);
  392.         break;
  393.  
  394.     case AFX_RFX_LONGBINARY:
  395.         {
  396.             CLongBinary* pLongBinarySrc = (CLongBinary*)pvSrc;
  397.             CLongBinary* pLongBinaryDest = (CLongBinary*)pvDest;
  398.  
  399.             // Reallocate memory in destination if necessary
  400.             AllocLongBinary(*pLongBinaryDest, pLongBinarySrc->m_dwDataLength);
  401.             pLongBinaryDest->m_dwDataLength =
  402.                 pLongBinarySrc->m_dwDataLength;
  403.  
  404.             BYTE* pbSrc = (BYTE*)::GlobalLock(pLongBinarySrc->m_hData);
  405.             BYTE* pbDest = (BYTE*)::GlobalLock(pLongBinaryDest->m_hData);
  406.             memcpy(pbDest, pbSrc, pLongBinarySrc->m_dwDataLength);
  407.             ::GlobalUnlock(pLongBinarySrc->m_hData);
  408.             ::GlobalUnlock(pLongBinaryDest->m_hData);
  409.         }
  410.         break;
  411.  
  412.     case AFX_RFX_BOOL:
  413.         *(BOOL*)pvDest = *(BOOL*)pvSrc;
  414.         break;
  415.  
  416.     case AFX_RFX_BYTE:
  417.         *(BYTE*)pvDest = *(BYTE*)pvSrc;
  418.         break;
  419.  
  420.     case AFX_RFX_SHORT:
  421.         *(short*)pvDest = *(short*)pvSrc;
  422.         break;
  423.  
  424.     case AFX_RFX_LONG:
  425.         *(long*)pvDest = *(long*)pvSrc;
  426.         break;
  427.  
  428.     case AFX_RFX_CURRENCY:
  429.         *(COleCurrency*)pvDest = *(COleCurrency*)pvSrc;
  430.         break;
  431.  
  432.     case AFX_RFX_SINGLE:
  433.         *(float*)pvDest = *(float*)pvSrc;
  434.         break;
  435.  
  436.     case AFX_RFX_DOUBLE:
  437.         *(double*)pvDest = *(double*)pvSrc;
  438.         break;
  439.  
  440.     case AFX_RFX_DATE:
  441.         *(COleDateTime*)pvDest = *(COleDateTime*)pvSrc;
  442.         break;
  443.     }
  444. }
  445.  
  446. BOOL CDaoFieldExchange::CompareValue(void* pvSrc, void* pvDest,
  447.     DWORD dwDataType)
  448. {
  449.     BOOL bDirty = FALSE;
  450.  
  451.     switch (dwDataType)
  452.     {
  453.     default:
  454.         ASSERT(FALSE);
  455.         break;
  456.  
  457.     case AFX_RFX_TEXT:
  458.         if (*(CString*)pvDest != *(CString*)pvSrc)
  459.             bDirty = TRUE;
  460.         break;
  461.  
  462.     case AFX_RFX_BINARY:
  463.         {
  464.             CByteArray* pByteArraySrc = (CByteArray*)pvSrc;
  465.             CByteArray* pByteArrayDest = (CByteArray*)pvDest;
  466.  
  467.             int nSize = pByteArraySrc->GetSize();
  468.             // If sizes don't compare, must be dirty
  469.             if (nSize != pByteArrayDest->GetSize())
  470.                 bDirty = TRUE;
  471.             else
  472.             {
  473.                 // If sizes compare, compare the data
  474.                 if (memcmp(&pByteArrayDest[0], &pByteArraySrc[0], nSize) != 0)
  475.                     bDirty = TRUE;
  476.             }
  477.         }
  478.         break;
  479.  
  480.     case AFX_RFX_LONGBINARY:
  481.         {
  482.             CLongBinary* pLongBinarySrc = (CLongBinary*)pvSrc;
  483.             CLongBinary* pLongBinaryDest = (CLongBinary*)pvDest;
  484.  
  485.             BYTE* pbSrc = (BYTE*)::GlobalLock(pLongBinarySrc->m_hData);
  486.             BYTE* pbDest = (BYTE*)::GlobalLock(pLongBinaryDest->m_hData);
  487.  
  488.             // If sizes don't compare, must be dirty
  489.             if (pLongBinarySrc->m_dwDataLength !=
  490.                 pLongBinaryDest->m_dwDataLength)
  491.             {
  492.                 bDirty = TRUE;
  493.             }
  494.             else
  495.             {
  496.                 // If sizes compare, compare the data
  497.                 if (memcmp(pbDest, pbSrc, pLongBinarySrc->m_dwDataLength) != 0)
  498.                     bDirty = TRUE;
  499.             }
  500.  
  501.             ::GlobalUnlock(pLongBinarySrc->m_hData);
  502.             ::GlobalUnlock(pLongBinaryDest->m_hData);
  503.         }
  504.         break;
  505.  
  506.     case AFX_RFX_BOOL:
  507.         if (*(BOOL*)pvDest != *(BOOL*)pvSrc)
  508.             bDirty = TRUE;
  509.         break;
  510.  
  511.     case AFX_RFX_BYTE:
  512.         if (*(BYTE*)pvDest != *(BYTE*)pvSrc)
  513.             bDirty = TRUE;
  514.         break;
  515.  
  516.     case AFX_RFX_SHORT:
  517.         if (*(short*)pvDest != *(short*)pvSrc)
  518.             bDirty = TRUE;
  519.         break;
  520.  
  521.     case AFX_RFX_LONG:
  522.         if (*(long*)pvDest != *(long*)pvSrc)
  523.             bDirty = TRUE;
  524.         break;
  525.  
  526.     case AFX_RFX_CURRENCY:
  527.         if (*(COleCurrency*)pvDest != *(COleCurrency*)pvSrc)
  528.             bDirty = TRUE;
  529.         break;
  530.  
  531.     case AFX_RFX_SINGLE:
  532.         if (*(float*)pvDest != *(float*)pvSrc)
  533.             bDirty = TRUE;
  534.         break;
  535.  
  536.     case AFX_RFX_DOUBLE:
  537.         if (*(double*)pvDest != *(double*)pvSrc)
  538.             bDirty = TRUE;
  539.         break;
  540.  
  541.     case AFX_RFX_DATE:
  542.         if (*(COleDateTime*)pvDest != *(COleDateTime*)pvSrc)
  543.             bDirty = TRUE;
  544.         break;
  545.     }
  546.  
  547.     return bDirty;
  548. }
  549.  
  550. void CDaoFieldExchange::FillVariant(void* pvValue, DWORD dwDataType,
  551.     COleVariant** ppVar)
  552. {
  553.     COleVariant* pVar;
  554.  
  555.     if (dwDataType == AFX_RFX_TEXT)
  556.         pVar = new COleVariant(*(CString*)pvValue, VT_BSTRT);
  557.     else if (dwDataType == AFX_RFX_BOOL)
  558.         pVar = new COleVariant(*(long*)pvValue, VT_BOOL);
  559.     else
  560.     {
  561.         pVar = new COleVariant;
  562.  
  563.         switch (dwDataType)
  564.         {
  565.         default:
  566.             ASSERT(FALSE);
  567.             break;
  568.  
  569.         case AFX_RFX_BINARY:
  570.             *pVar = *(CByteArray*)pvValue;
  571.             break;
  572.  
  573.         case AFX_RFX_LONGBINARY:
  574.             *pVar = *(CLongBinary*)pvValue;
  575.             break;
  576.  
  577.         case AFX_RFX_BYTE:
  578.             *pVar = *(BYTE*)pvValue;
  579.             break;
  580.  
  581.         case AFX_RFX_SHORT:
  582.             *pVar = *(short*)pvValue;
  583.             break;
  584.  
  585.         case AFX_RFX_LONG:
  586.             *pVar = *(long*)pvValue;
  587.             break;
  588.  
  589.         case AFX_RFX_CURRENCY:
  590.             *pVar = *(COleCurrency*)pvValue;
  591.             break;
  592.  
  593.         case AFX_RFX_SINGLE:
  594.             *pVar = *(float*)pvValue;
  595.             break;
  596.  
  597.         case AFX_RFX_DOUBLE:
  598.             *pVar = *(double*)pvValue;
  599.             break;
  600.  
  601.         case AFX_RFX_DATE:
  602.             *pVar = *(COleDateTime*)pvValue;
  603.         }
  604.     }
  605.  
  606.     *ppVar = pVar;
  607. }
  608.  
  609. // Default implementation for RFX functions
  610. void CDaoFieldExchange::Default(LPCTSTR lpszName, void* pv,
  611.     DWORD dwColumnType, DWORD dwBindOptions)
  612. {
  613.     switch (m_nOperation)
  614.     {
  615.     case AddToParameterList:
  616.         if (m_nParam != 1)
  617.             m_prs->m_strSQL += ",";
  618.         m_prs->m_strSQL += lpszName;
  619.         AppendParamType(m_prs->m_strSQL, dwColumnType);
  620.         return;
  621.  
  622.     case AddToSelectList:
  623.         if (m_nField != 1)
  624.             m_prs->m_strSQL += ",";
  625.         m_prs->m_strSQL += lpszName;
  626.         return;
  627.  
  628.     case BindField:
  629.         {
  630.             // Query parser needs "[" & "]", GetRows can't tolerate them.
  631.             LPTSTR lpszNoBracketName = new TCHAR[lstrlen(lpszName) + 1];
  632.             m_prs->StripBrackets(lpszName, lpszNoBracketName);
  633.  
  634.             // Finish setting up column binding info struct
  635.             LPDAOCOLUMNBINDING pcb =
  636.                 &m_prs->m_prgDaoColBindInfo[m_nField-1];
  637.             pcb->cbInfoOffset =
  638.                 (DWORD)&m_prs->m_pulColumnLengths[m_nField-1];
  639. #ifndef _UNICODE
  640.             pcb->columnID.dwKind = DAOCOLKIND_STR;
  641.             pcb->columnID.lpstr = lpszNoBracketName;
  642. #else
  643.             pcb->columnID.dwKind = DAOCOLKIND_WSTR;
  644.             pcb->columnID.lpwstr = lpszNoBracketName;
  645. #endif
  646.  
  647.             // Setup the field index map (and store value as void ptr)
  648.             m_prs->m_pMapFieldIndex->SetAt(pv, (void*)m_nField);
  649.         }
  650.         return;
  651.  
  652.     case BindParam:
  653.         {
  654.             COleVariant* pvar = NULL;
  655.  
  656.             TRY
  657.             {
  658.                 // NULL params not supported, use IS NULL in SQL
  659.                 // (i.e. - m_strFilter = _T("Foo IS NULL");
  660.                 FillVariant(pv, dwColumnType, &pvar);
  661.                 m_prs->m_pQueryDef->SetParamValue(lpszName, *pvar);
  662.             }
  663.             CATCH_ALL(e)
  664.             {
  665.                 if (pvar != NULL)
  666.                     pvar->Clear();
  667.                 delete pvar;
  668.                 pvar = NULL;
  669.                 THROW_LAST();
  670.             }
  671.             END_CATCH_ALL
  672.  
  673.             pvar->Clear();
  674.             delete pvar;
  675.             pvar = NULL;
  676.         }
  677.         return;
  678.  
  679.     case Fixup:
  680.         if (m_prs->GetFieldLength(m_nField-1) == DAO_NULL)
  681.         {
  682.             // Set the value to PSEUDO NULL and mark the status NULL
  683.             SetNullValue(pv, dwColumnType);
  684.             m_prs->SetNullFieldStatus(m_nField-1);
  685.         }
  686.         return;
  687.  
  688.     case AllocCache:
  689.         if (dwBindOptions & AFX_DAO_ENABLE_FIELD_CACHE)
  690.         {
  691.             CDaoFieldCache* pCache;
  692.  
  693.             // Allocate new storage and add to map
  694.             AllocCacheValue(pCache, dwColumnType);
  695.             m_prs->m_pMapFieldCache->SetAt(pv, pCache);
  696.         }
  697.         return;
  698.  
  699.     case StoreField:
  700.         if (dwBindOptions & AFX_DAO_ENABLE_FIELD_CACHE)
  701.         {
  702.             CDaoFieldCache* pCache = GetCacheValue(m_prs, pv);
  703.  
  704.             // Copy the data to the cache
  705.             if (dwBindOptions & AFX_DAO_CACHE_BY_VALUE)
  706.                 CopyValue(pv, (void*)&pCache->m_pvData, dwColumnType);
  707.             else
  708.                 CopyValue(pv, pCache->m_pvData, dwColumnType);
  709.  
  710.             // Cache the NULL status
  711.             if (m_prs->IsFieldStatusNull(m_nField-1))
  712.                 pCache->m_nStatus |= AFX_DAO_FIELD_FLAG_NULL;
  713.             else
  714.                 pCache->m_nStatus &= ~AFX_DAO_FIELD_FLAG_NULL;
  715.         }
  716.         return;
  717.  
  718.     case LoadField:
  719.         if (dwBindOptions & AFX_DAO_ENABLE_FIELD_CACHE)
  720.         {
  721.             CDaoFieldCache* pCache = GetCacheValue(m_prs, pv);
  722.  
  723.             // Copy the data from the cache
  724.             if (dwBindOptions & AFX_DAO_CACHE_BY_VALUE)
  725.                 CopyValue((void*)&pCache->m_pvData, pv, dwColumnType);
  726.             else
  727.                 CopyValue(pCache->m_pvData, pv, dwColumnType);
  728.  
  729.             // Set the NULL status from the cache
  730.             if (pCache->m_nStatus & AFX_DAO_FIELD_FLAG_NULL)
  731.                 m_prs->SetNullFieldStatus(m_nField-1);
  732.             else
  733.                 m_prs->ClearNullFieldStatus(m_nField-1);
  734.         }
  735.         return;
  736.  
  737.     case SetFieldNull:
  738.         // Setting field NOT NULL doesn't require field exchange
  739.         if ((m_pvField == NULL && m_nFieldType == outputColumn)
  740.             || m_pvField == pv)
  741.         {
  742.             SetNullValue(pv, dwColumnType);
  743.  
  744.             // Also set the status array if not a parameter
  745.             if (m_nFieldType == outputColumn)
  746.                 m_prs->SetNullFieldStatus(m_nField-1);
  747.  
  748. #ifdef _DEBUG
  749.             m_nFieldFound = m_nField;
  750. #endif
  751.         }
  752.         return;
  753.  
  754.     case MarkForAddNew:
  755.         if (dwBindOptions & AFX_DAO_ENABLE_FIELD_CACHE)
  756.         {
  757.             // Don't need to do anything if field marked dirty
  758.             if (!m_prs->IsFieldStatusDirty(m_nField-1))
  759.             {
  760.                 // Mark dirty & not NULL if not set to pseudo NULL value
  761.                 if (!IsNullValue(pv, dwColumnType))
  762.                 {
  763.                     m_prs->SetDirtyFieldStatus(m_nField-1);
  764.                     m_prs->ClearNullFieldStatus(m_nField-1);
  765.                 }
  766.             }
  767.         }
  768.         return;
  769.  
  770.     case MarkForEdit:
  771.         if (dwBindOptions & AFX_DAO_ENABLE_FIELD_CACHE)
  772.         {
  773.             // If value not pseudo NULL value, clear NULL status
  774.             if (!IsNullValue(pv, dwColumnType))
  775.                 m_prs->ClearNullFieldStatus(m_nField-1);
  776.  
  777.             // If field already marked dirty, don't need to check cache
  778.             if (!m_prs->IsFieldStatusDirty(m_nField-1))
  779.             {
  780.                 CDaoFieldCache* pCache = GetCacheValue(m_prs, pv);
  781.  
  782.                 BOOL bNullField = m_prs->IsFieldStatusNull(m_nField-1);
  783.                 BOOL bNullCache = pCache->m_nStatus & AFX_DAO_FIELD_FLAG_NULL;
  784.  
  785.                 void* pvData;
  786.                 if (dwBindOptions & AFX_DAO_CACHE_BY_VALUE)
  787.                     pvData = &pCache->m_pvData;
  788.                 else
  789.                     pvData = pCache->m_pvData;
  790.  
  791.                 // Mark dirty if NULL status differs or value differs
  792.                 if ( (bNullCache && !bNullField) ||
  793.                     (!bNullCache && bNullField) ||
  794.                     CompareValue(pv, pvData, dwColumnType))
  795.                 {
  796.                     m_prs->SetDirtyFieldStatus(m_nField-1);
  797.                 }
  798.             }
  799.         }
  800.         return;
  801.  
  802.     case SetDirtyField:
  803.         if (m_prs->IsFieldStatusDirty(m_nField-1))
  804.         {
  805.             COleVariant* pvar = NULL;
  806.  
  807.             TRY
  808.             {
  809.                 // If field is NULL don't set the value
  810.                 if (!m_prs->IsFieldStatusNull(m_nField-1))
  811.                     FillVariant(pv, dwColumnType, &pvar);
  812.                 else
  813.                 {
  814.                     pvar = new COleVariant;
  815.                     pvar->vt = VT_NULL;
  816.                 }
  817.  
  818.                 // SetFieldValue (put_Collect) doesn't like brackets
  819.                 // Assumes no brackets if first char not a bracket
  820.                 LPTSTR lpszModifiedName = NULL;
  821.                 if (*lpszName == '[')
  822.                 {
  823.                     lpszModifiedName = new TCHAR[lstrlen(lpszName) + 1];
  824.  
  825.                     // Copy the name with no brackets, and reset lpszName
  826.                     m_prs->StripBrackets(lpszName, lpszModifiedName);
  827.                     lpszName = lpszModifiedName;
  828.                 }
  829.  
  830.                 m_prs->SetFieldValue(lpszName, *pvar);
  831.                 delete lpszModifiedName;
  832.             }
  833.             CATCH_ALL(e)
  834.             {
  835.                 if (pvar != NULL)
  836.                     pvar->Clear();
  837.                 delete pvar;
  838.                 pvar = NULL;
  839.                 THROW_LAST();
  840.             }
  841.             END_CATCH_ALL
  842.  
  843.             pvar->Clear();
  844.             delete pvar;
  845.             pvar = NULL;
  846.         }
  847.         return;
  848.  
  849.     default:
  850.         ASSERT(FALSE);
  851.         return;
  852.     }
  853. }
  854.  
  855. void AFXAPI DFX_Text(CDaoFieldExchange* pFX, LPCTSTR lpszName,
  856.     CString& value, int nPreAllocSize, DWORD dwBindOptions)
  857. {
  858.     (pFX->m_nFieldType == CDaoFieldExchange::outputColumn) ?
  859.         ++pFX->m_nField: ++pFX->m_nParam;
  860.  
  861.     // Do nothing if op not supported for outputColumn or param type
  862.     if (!pFX->IsValidOperation())
  863.         return;
  864.  
  865.     DWORD dwDAOType;
  866.  
  867. #ifdef _UNICODE
  868.     dwDAOType = DAO_WCHAR;
  869. #else
  870.     dwDAOType = DAO_CHAR;
  871. #endif
  872.  
  873.     switch (pFX->m_nOperation)
  874.     {
  875.     case CDaoFieldExchange::BindField:
  876.         {
  877.             // Pre-allocate buffer to prevent needless re-allocations
  878.             value.GetBuffer(nPreAllocSize);
  879.             value.ReleaseBuffer();
  880.  
  881.             LPDAOCOLUMNBINDING pcb =
  882.                 &pFX->m_prs->m_prgDaoColBindInfo[pFX->m_nField-1];
  883.             pcb->dwDataType = dwDAOType;
  884.             pcb->dwBinding = DAOBINDING_DIRECT | DAOBINDING_CALLBACK;
  885.             pcb->dwUser = (DWORD)&value;
  886.             pcb->cbDataOffset = (DWORD)DaoStringAllocCallback;
  887.             pcb->cbMaxLen = INT_MAX;
  888.         }
  889.         // Fall through to finish setting up column binding struct
  890.  
  891.     default:
  892.         pFX->Default(lpszName, (void*)&value, AFX_RFX_TEXT,
  893.             dwBindOptions);
  894.         return;
  895.  
  896.     case CDaoFieldExchange::Fixup:
  897.         if (pFX->m_prs->m_pulColumnLengths[pFX->m_nField-1] == 0 ||
  898.             pFX->m_prs->m_pulColumnLengths[pFX->m_nField-1] == DAO_NULL)
  899.         {
  900.             // If null or empty string set length zero
  901.             value.GetBufferSetLength(0);
  902.         }
  903.         else
  904.         {
  905.             // Make sure length correct
  906.             value.GetBufferSetLength(
  907.                 ((pFX->m_prs->m_pulColumnLengths[pFX->m_nField-1])/sizeof(TCHAR))-1);
  908.         }
  909.  
  910.         pFX->Default(lpszName, (void*)&value,
  911.             AFX_RFX_TEXT, dwBindOptions);
  912.         return;
  913.  
  914. #ifdef _DEBUG
  915.     case CDaoFieldExchange::DumpField:
  916.         *pFX->m_pdcDump << "\n" << lpszName << " = " << value;
  917.         return;
  918. #endif //_DEBUG
  919.     }
  920. }
  921.  
  922. void AFXAPI DFX_Binary(CDaoFieldExchange* pFX, LPCTSTR lpszName,
  923.     CByteArray& value, int nPreAllocSize, DWORD dwBindOptions)
  924. {
  925.     (pFX->m_nFieldType == CDaoFieldExchange::outputColumn) ?
  926.         ++pFX->m_nField: ++pFX->m_nParam;
  927.  
  928.     // Do nothing if op not supported for outputColumn or param type
  929.     if (!pFX->IsValidOperation())
  930.         return;
  931.  
  932.     switch (pFX->m_nOperation)
  933.     {
  934.     case CDaoFieldExchange::BindField:
  935.         {
  936.             // Pre-allocate buffer to prevent needless re-allocations
  937.             value.SetSize(nPreAllocSize);
  938.  
  939.             LPDAOCOLUMNBINDING pcb =
  940.                 &pFX->m_prs->m_prgDaoColBindInfo[pFX->m_nField-1];
  941.             pcb->dwDataType = DAO_BYTES;
  942.             pcb->dwBinding = DAOBINDING_DIRECT | DAOBINDING_CALLBACK;
  943.             pcb->dwUser = (DWORD)&value;
  944.             pcb->cbDataOffset = (ULONG)DaoBinaryAllocCallback;
  945.             pcb->cbMaxLen = INT_MAX;
  946.         }
  947.         // Fall through to finish setting up column binding struct
  948.  
  949.     default:
  950.         pFX->Default(lpszName, (void*)&value, AFX_RFX_BINARY,
  951.             dwBindOptions);
  952.         return;
  953.  
  954. #ifdef _DEBUG
  955.     case CDaoFieldExchange::DumpField:
  956.         *pFX->m_pdcDump << "\n" << lpszName << " = " << value;
  957.         return;
  958. #endif //_DEBUG
  959.     }
  960. }
  961.  
  962. void AFXAPI DFX_LongBinary(CDaoFieldExchange* pFX, LPCTSTR lpszName,
  963.     CLongBinary& value, DWORD dwPreAllocSize, DWORD dwBindOptions)
  964. {
  965.     (pFX->m_nFieldType == CDaoFieldExchange::outputColumn) ?
  966.         ++pFX->m_nField: ++pFX->m_nParam;
  967.  
  968.     // Do nothing if op not supported for outputColumn or param type
  969.     if (!pFX->IsValidOperation())
  970.         return;
  971.  
  972.     switch (pFX->m_nOperation)
  973.     {
  974.     case CDaoFieldExchange::BindField:
  975.         {
  976.             // Pre-allocate buffer to prevent needless re-allocations
  977.             AllocLongBinary(value, dwPreAllocSize);
  978.  
  979.             LPDAOCOLUMNBINDING pcb =
  980.                 &pFX->m_prs->m_prgDaoColBindInfo[pFX->m_nField-1];
  981.             pcb->dwDataType = DAO_BYTES;
  982.             pcb->dwBinding = DAOBINDING_DIRECT | DAOBINDING_CALLBACK;
  983.             pcb->dwUser = (DWORD)&value;
  984.             pcb->cbDataOffset = (DWORD)DaoLongBinaryAllocCallback;
  985.             pcb->cbMaxLen = ULONG_MAX;
  986.         }
  987.         // Fall through to finish setting up column binding struct
  988.  
  989.     default:
  990.         pFX->Default(lpszName, (void*)&value,
  991.             AFX_RFX_LONGBINARY, dwBindOptions);
  992.         return;
  993.  
  994.     case CDaoFieldExchange::Fixup:
  995.         // Unlock data locked in DaoLongBinaryAllocCallback
  996.         if (value.m_dwDataLength != 0)
  997.             ::GlobalUnlock(value.m_hData);
  998.  
  999.         pFX->Default(lpszName, (void*)&value,
  1000.             AFX_RFX_LONGBINARY, dwBindOptions);
  1001.         return;
  1002.  
  1003. #ifdef _DEBUG
  1004.     case CDaoFieldExchange::DumpField:
  1005.         *pFX->m_pdcDump << "\n" << lpszName << " = " << value;
  1006.         return;
  1007. #endif //_DEBUG
  1008.     }
  1009. }
  1010.  
  1011. void AFXAPI DFX_Bool(CDaoFieldExchange* pFX, LPCTSTR lpszName,
  1012.     BOOL& value, DWORD dwBindOptions)
  1013. {
  1014.     (pFX->m_nFieldType == CDaoFieldExchange::outputColumn) ?
  1015.         ++pFX->m_nField: ++pFX->m_nParam;
  1016.  
  1017.     // Do nothing if op not supported for outputColumn or param type
  1018.     if (!pFX->IsValidOperation())
  1019.         return;
  1020.  
  1021.     // Mark as CACHE_BY_VALUE (size <= sizeof(void*))
  1022.     dwBindOptions |= AFX_DAO_CACHE_BY_VALUE;
  1023.  
  1024.     switch (pFX->m_nOperation)
  1025.     {
  1026.     case CDaoFieldExchange::BindField:
  1027.         {
  1028.             LPDAOCOLUMNBINDING pcb =
  1029.                 &pFX->m_prs->m_prgDaoColBindInfo[pFX->m_nField-1];
  1030.             pcb->dwDataType = DAO_BOOL;
  1031.             pcb->dwBinding = DAOBINDING_DIRECT;
  1032.             pcb->cbDataOffset = (DWORD)&value;
  1033.             pcb->dwUser = 0;
  1034.             pcb->cbMaxLen = sizeof(value);
  1035.  
  1036.             pFX->m_prs->m_cbFixedLengthFields += pcb->cbMaxLen;
  1037.         }
  1038.         // Fall through to finish setting up column binding struct
  1039.  
  1040.     default:
  1041.         pFX->Default(lpszName, (void*)&value, AFX_RFX_BOOL,
  1042.             dwBindOptions);
  1043.         return;
  1044.  
  1045.     case CDaoFieldExchange::Fixup:
  1046.         // Convert BOOL value from AFX_DAO_TRUE/FALSE to TRUE/FALSE
  1047.         value = (value != AFX_DAO_FALSE);
  1048.  
  1049.         pFX->Default(lpszName, (void*)&value,
  1050.             AFX_RFX_BOOL, dwBindOptions);
  1051.         return;
  1052.  
  1053. #ifdef _DEBUG
  1054.     case CDaoFieldExchange::DumpField:
  1055.         *pFX->m_pdcDump << "\n" << lpszName << " = " << value;
  1056.         return;
  1057. #endif //_DEBUG
  1058.     }
  1059. }
  1060.  
  1061. void AFXAPI DFX_Byte(CDaoFieldExchange* pFX, LPCTSTR lpszName,
  1062.     BYTE& value, DWORD dwBindOptions)
  1063. {
  1064.     (pFX->m_nFieldType == CDaoFieldExchange::outputColumn) ?
  1065.         ++pFX->m_nField: ++pFX->m_nParam;
  1066.  
  1067.     // Do nothing if op not supported for outputColumn or param type
  1068.     if (!pFX->IsValidOperation())
  1069.         return;
  1070.  
  1071.     // Mark as CACHE_BY_VALUE (size <= sizeof(void*))
  1072.     dwBindOptions |= AFX_DAO_CACHE_BY_VALUE;
  1073.  
  1074.     switch (pFX->m_nOperation)
  1075.     {
  1076.     case CDaoFieldExchange::BindField:
  1077.         {
  1078.             LPDAOCOLUMNBINDING pcb =
  1079.                 &pFX->m_prs->m_prgDaoColBindInfo[pFX->m_nField-1];
  1080.             pcb->dwDataType = DAO_BYTE;
  1081.             pcb->dwBinding = DAOBINDING_DIRECT;
  1082.             pcb->cbDataOffset = (DWORD)&value;
  1083.             pcb->dwUser = 0;
  1084.             pcb->cbMaxLen = sizeof(value);
  1085.  
  1086.             pFX->m_prs->m_cbFixedLengthFields += pcb->cbMaxLen;
  1087.         }
  1088.         // Fall through to finish setting up column binding struct
  1089.  
  1090.     default:
  1091.         pFX->Default(lpszName, (void*)&value, AFX_RFX_BYTE,
  1092.             dwBindOptions);
  1093.         return;
  1094.  
  1095. #ifdef _DEBUG
  1096.     case CDaoFieldExchange::DumpField:
  1097.         *pFX->m_pdcDump << "\n" << lpszName << " = " << value;
  1098.         return;
  1099. #endif //_DEBUG
  1100.     }
  1101. }
  1102.  
  1103. void AFXAPI DFX_Short(CDaoFieldExchange* pFX, LPCTSTR lpszName,
  1104.     short& value, DWORD dwBindOptions)
  1105. {
  1106.     (pFX->m_nFieldType == CDaoFieldExchange::outputColumn) ?
  1107.         ++pFX->m_nField: ++pFX->m_nParam;
  1108.  
  1109.     // Do nothing if op not supported for outputColumn or param type
  1110.     if (!pFX->IsValidOperation())
  1111.         return;
  1112.  
  1113.     // Mark as CACHE_BY_VALUE (size <= sizeof(void*))
  1114.     dwBindOptions |= AFX_DAO_CACHE_BY_VALUE;
  1115.  
  1116.     switch (pFX->m_nOperation)
  1117.     {
  1118.     case CDaoFieldExchange::BindField:
  1119.         {
  1120.             LPDAOCOLUMNBINDING pcb =
  1121.                 &pFX->m_prs->m_prgDaoColBindInfo[pFX->m_nField-1];
  1122.             pcb->dwDataType = DAO_I2;
  1123.             pcb->dwBinding = DAOBINDING_DIRECT;
  1124.             pcb->cbDataOffset = (DWORD)&value;
  1125.             pcb->dwUser = 0;
  1126.             pcb->cbMaxLen = sizeof(value);
  1127.  
  1128.             pFX->m_prs->m_cbFixedLengthFields += pcb->cbMaxLen;
  1129.         }
  1130.         // Fall through to finish setting up column binding struct
  1131.  
  1132.     default:
  1133.         pFX->Default(lpszName, (void*)&value, AFX_RFX_SHORT,
  1134.             dwBindOptions);
  1135.         return;
  1136.  
  1137. #ifdef _DEBUG
  1138.     case CDaoFieldExchange::DumpField:
  1139.         *pFX->m_pdcDump << "\n" << lpszName << " = " << value;
  1140.         return;
  1141. #endif //_DEBUG
  1142.     }
  1143. }
  1144.  
  1145. void AFXAPI DFX_Long(CDaoFieldExchange* pFX, LPCTSTR lpszName,
  1146.     long& value, DWORD dwBindOptions)
  1147. {
  1148.     (pFX->m_nFieldType == CDaoFieldExchange::outputColumn) ?
  1149.         ++pFX->m_nField: ++pFX->m_nParam;
  1150.  
  1151.     // Do nothing if op not supported for outputColumn or param type
  1152.     if (!pFX->IsValidOperation())
  1153.         return;
  1154.  
  1155.     // Mark as CACHE_BY_VALUE (size <= sizeof(void*))
  1156.     dwBindOptions |= AFX_DAO_CACHE_BY_VALUE;
  1157.  
  1158.     switch (pFX->m_nOperation)
  1159.     {
  1160.     case CDaoFieldExchange::BindField:
  1161.         {
  1162.             LPDAOCOLUMNBINDING pcb =
  1163.                 &pFX->m_prs->m_prgDaoColBindInfo[pFX->m_nField-1];
  1164.             pcb->dwDataType = DAO_I4;
  1165.             pcb->dwBinding = DAOBINDING_DIRECT;
  1166.             pcb->cbDataOffset = (DWORD)&value;
  1167.             pcb->dwUser = 0;
  1168.             pcb->cbMaxLen = sizeof(value);
  1169.  
  1170.             pFX->m_prs->m_cbFixedLengthFields += pcb->cbMaxLen;
  1171.         }
  1172.         // Fall through to finish setting up column binding struct
  1173.  
  1174.     default:
  1175.         pFX->Default(lpszName, (void*)&value, AFX_RFX_LONG,
  1176.             dwBindOptions);
  1177.         return;
  1178.  
  1179. #ifdef _DEBUG
  1180.     case CDaoFieldExchange::DumpField:
  1181.         *pFX->m_pdcDump << "\n" << lpszName << " = " << value;
  1182.         return;
  1183. #endif //_DEBUG
  1184.     }
  1185. }
  1186.  
  1187. void AFXAPI DFX_Currency(CDaoFieldExchange* pFX, LPCTSTR lpszName,
  1188.     COleCurrency& value, DWORD dwBindOptions)
  1189. {
  1190.     (pFX->m_nFieldType == CDaoFieldExchange::outputColumn) ?
  1191.         ++pFX->m_nField: ++pFX->m_nParam;
  1192.  
  1193.     // Do nothing if op not supported for outputColumn or param type
  1194.     if (!pFX->IsValidOperation())
  1195.         return;
  1196.  
  1197.     switch (pFX->m_nOperation)
  1198.     {
  1199.     case CDaoFieldExchange::BindField:
  1200.         {
  1201.             LPDAOCOLUMNBINDING pcb =
  1202.                 &pFX->m_prs->m_prgDaoColBindInfo[pFX->m_nField-1];
  1203.             pcb->dwDataType = DAO_CURRENCY;
  1204.             pcb->dwBinding = DAOBINDING_DIRECT;
  1205.             pcb->cbDataOffset = (DWORD)&value.m_cur;
  1206.             pcb->dwUser = 0;
  1207.             pcb->cbMaxLen = sizeof(CURRENCY);
  1208.  
  1209.             pFX->m_prs->m_cbFixedLengthFields += pcb->cbMaxLen;
  1210.  
  1211.             // Finish setting up column binding struct
  1212.             pFX->Default(lpszName, (void*)&value, AFX_RFX_CURRENCY,
  1213.                 dwBindOptions);
  1214.             return;
  1215.         }
  1216.  
  1217.     case CDaoFieldExchange::Fixup:
  1218.         // Must reset the valid currency flag
  1219.         if (pFX->m_prs->GetFieldLength(pFX->m_nField-1) == DAO_NULL)
  1220.             value.SetStatus(COleCurrency::null);
  1221.         else
  1222.             value.SetStatus(COleCurrency::valid);
  1223.  
  1224.         // Fall through to reset the NULL status
  1225.  
  1226.     default:
  1227.         pFX->Default(lpszName, (void*)&value, AFX_RFX_CURRENCY,
  1228.             dwBindOptions);
  1229.         return;
  1230.  
  1231. #ifdef _DEBUG
  1232.     case CDaoFieldExchange::DumpField:
  1233.         *pFX->m_pdcDump << "\n" << lpszName << ":" << value;
  1234.         return;
  1235. #endif //_DEBUG
  1236.     }
  1237. }
  1238.  
  1239. void AFXAPI DFX_Single(CDaoFieldExchange* pFX, LPCTSTR lpszName,
  1240.     float& value, DWORD dwBindOptions)
  1241. {
  1242.     (pFX->m_nFieldType == CDaoFieldExchange::outputColumn) ?
  1243.         ++pFX->m_nField: ++pFX->m_nParam;
  1244.  
  1245.     // Do nothing if op not supported for outputColumn or param type
  1246.     if (!pFX->IsValidOperation())
  1247.         return;
  1248.  
  1249.     // Mark as CACHE_BY_VALUE (size <= sizeof(void*))
  1250.     dwBindOptions |= AFX_DAO_CACHE_BY_VALUE;
  1251.  
  1252.     switch (pFX->m_nOperation)
  1253.     {
  1254.     case CDaoFieldExchange::BindField:
  1255.         {
  1256.             LPDAOCOLUMNBINDING pcb =
  1257.                 &pFX->m_prs->m_prgDaoColBindInfo[pFX->m_nField-1];
  1258.             pcb->dwDataType = DAO_R4;
  1259.             pcb->dwBinding = DAOBINDING_DIRECT;
  1260.             pcb->cbDataOffset = (DWORD)&value;
  1261.             pcb->dwUser = 0;
  1262.             pcb->cbMaxLen = sizeof(value);
  1263.  
  1264.             pFX->m_prs->m_cbFixedLengthFields += pcb->cbMaxLen;
  1265.         }
  1266.         // Fall through to finish setting up column binding struct
  1267.  
  1268.     default:
  1269.         pFX->Default(lpszName, (void*)&value, AFX_RFX_SINGLE,
  1270.             dwBindOptions);
  1271.         return;
  1272.  
  1273. #ifdef _DEBUG
  1274.     case CDaoFieldExchange::DumpField:
  1275.         *pFX->m_pdcDump << "\n" << lpszName << " = " << value;
  1276.         return;
  1277. #endif //_DEBUG
  1278.     }
  1279. }
  1280.  
  1281. void AFXAPI DFX_Double(CDaoFieldExchange* pFX, LPCTSTR lpszName,
  1282.     double& value, DWORD dwBindOptions)
  1283. {
  1284.     (pFX->m_nFieldType == CDaoFieldExchange::outputColumn) ?
  1285.         ++pFX->m_nField: ++pFX->m_nParam;
  1286.  
  1287.     // Do nothing if op not supported for outputColumn or param type
  1288.     if (!pFX->IsValidOperation())
  1289.         return;
  1290.  
  1291.     switch (pFX->m_nOperation)
  1292.     {
  1293.     case CDaoFieldExchange::BindField:
  1294.         {
  1295.             LPDAOCOLUMNBINDING pcb =
  1296.                 &pFX->m_prs->m_prgDaoColBindInfo[pFX->m_nField-1];
  1297.             pcb->dwDataType = DAO_R8;
  1298.             pcb->dwBinding = DAOBINDING_DIRECT;
  1299.             pcb->cbDataOffset = (DWORD)&value;
  1300.             pcb->dwUser = 0;
  1301.             pcb->cbMaxLen = sizeof(value);
  1302.  
  1303.             pFX->m_prs->m_cbFixedLengthFields += pcb->cbMaxLen;
  1304.         }
  1305.         // Fall through to finish setting up column binding struct
  1306.  
  1307.     default:
  1308.         pFX->Default(lpszName, (void*)&value, AFX_RFX_DOUBLE,
  1309.             dwBindOptions);
  1310.         return;
  1311.  
  1312. #ifdef _DEBUG
  1313.     case CDaoFieldExchange::DumpField:
  1314.         *pFX->m_pdcDump << "\n" << lpszName << " = " << value;
  1315.         return;
  1316. #endif //_DEBUG
  1317.     }
  1318. }
  1319.  
  1320. void AFXAPI DFX_DateTime(CDaoFieldExchange* pFX, LPCTSTR lpszName,
  1321.     COleDateTime& value, DWORD dwBindOptions)
  1322. {
  1323.     (pFX->m_nFieldType == CDaoFieldExchange::outputColumn) ?
  1324.         ++pFX->m_nField: ++pFX->m_nParam;
  1325.  
  1326.     // Do nothing if op not supported for outputColumn or param type
  1327.     if (!pFX->IsValidOperation())
  1328.         return;
  1329.  
  1330.     switch (pFX->m_nOperation)
  1331.     {
  1332.     case CDaoFieldExchange::BindField:
  1333.         {
  1334.             LPDAOCOLUMNBINDING pcb =
  1335.                 &pFX->m_prs->m_prgDaoColBindInfo[pFX->m_nField-1];
  1336.             pcb->dwDataType = DAO_DATE;
  1337.             pcb->dwBinding = DAOBINDING_DIRECT;
  1338.             pcb->cbDataOffset = (DWORD)&value.m_dt;
  1339.             pcb->dwUser = 0;
  1340.             pcb->cbMaxLen = sizeof(DATE);
  1341.  
  1342.             pFX->m_prs->m_cbFixedLengthFields += pcb->cbMaxLen;
  1343.  
  1344.             // Finish setting up column binding struct
  1345.             pFX->Default(lpszName,(void*)&value, AFX_RFX_DATE,
  1346.                 dwBindOptions);
  1347.             return;
  1348.         }
  1349.  
  1350.     case CDaoFieldExchange::Fixup:
  1351.         // Must reset the valid currency flag
  1352.         if (pFX->m_prs->GetFieldLength(pFX->m_nField-1) == DAO_NULL)
  1353.             value.SetStatus(COleDateTime::null);
  1354.         else
  1355.             value.SetStatus(COleDateTime::valid);
  1356.  
  1357.         // Fall through to reset the NULL status
  1358.  
  1359.     default:
  1360.         pFX->Default(lpszName, (void*)&value, AFX_RFX_DATE,
  1361.             dwBindOptions);
  1362.         return;
  1363.  
  1364. #ifdef _DEBUG
  1365.     case CDaoFieldExchange::DumpField:
  1366.         *pFX->m_pdcDump << "\n" << lpszName << ":" << value;
  1367.         return;
  1368. #endif //_DEBUG
  1369.     }
  1370. }
  1371.  
  1372. //////////////////////////////////////////////////////////////////////////////
  1373. // DAO memory allocation callback helpers
  1374.  
  1375. STDAPI DaoStringAllocCallback(DWORD dwLen, DWORD pData, void** ppv)
  1376. {
  1377.     LPTSTR lpsz;
  1378.     CString* pstr = (CString*)pData;
  1379.  
  1380. #ifndef _UNICODE
  1381.     // If using ANSI DAO interfaces, DAO reports field length
  1382.     // rather than data length. In this case there will not be space
  1383.     // for NULL terminator if data length equals field length. Make room.
  1384.     dwLen++;
  1385. #endif
  1386.  
  1387.     TRY
  1388.     {
  1389.         // Only re-allocate if necessary
  1390.         lpsz = pstr->GetBufferSetLength(dwLen/sizeof(TCHAR));
  1391.         *ppv = (void*)(dwLen > 0 ? lpsz : NULL);
  1392.     }
  1393.     CATCH_ALL(e)
  1394.     {
  1395.         e->Delete();
  1396.         return E_OUTOFMEMORY;
  1397.     }
  1398.     END_CATCH_ALL
  1399.  
  1400.     return S_OK;
  1401. }
  1402.  
  1403.  
  1404. STDAPI DaoBinaryAllocCallback(DWORD dwLen, DWORD pData, void** ppv)
  1405. {
  1406.     CByteArray* pByteArray = (CByteArray*)pData;
  1407.  
  1408.     TRY
  1409.     {
  1410.         // Only re-allocate if necessary
  1411.         pByteArray->SetSize(dwLen);
  1412.         *ppv = (void*)(dwLen > 0 ? &((*pByteArray)[0]) : NULL);
  1413.     }
  1414.     CATCH_ALL(e)
  1415.     {
  1416.         // Only exceptions thrown should be CMemoryException
  1417.         e->Delete();
  1418.         return E_OUTOFMEMORY;
  1419.     }
  1420.     END_CATCH_ALL
  1421.  
  1422.     return S_OK;
  1423. }
  1424.  
  1425.  
  1426. STDAPI DaoLongBinaryAllocCallback(DWORD dwLen, DWORD pData, void** ppv)
  1427. {
  1428.     CLongBinary* pLongBinary = (CLongBinary*)pData;
  1429.  
  1430.     TRY
  1431.     {
  1432.         AllocLongBinary(*pLongBinary, dwLen);
  1433.     }
  1434.     CATCH_ALL(e)
  1435.     {
  1436.         // Only exception is memory exception, just pass back error.
  1437.         DELETE_EXCEPTION(e);
  1438.         return E_OUTOFMEMORY;
  1439.     }
  1440.     END_CATCH_ALL
  1441.  
  1442.     if (pLongBinary->m_dwDataLength != 0)
  1443.     {
  1444.         const BYTE* pByte;
  1445.         pByte = (const BYTE*)::GlobalLock(pLongBinary->m_hData);
  1446.  
  1447.         // If mem can't be locked, free up and return error
  1448.         if (pByte == NULL)
  1449.         {
  1450.             ::GlobalFree(pLongBinary->m_hData);
  1451.             pLongBinary->m_hData = NULL;
  1452.             return E_OUTOFMEMORY;
  1453.         }
  1454.  
  1455.         *ppv = (void*)pByte;
  1456.     }
  1457.     else
  1458.         *ppv = NULL;
  1459.  
  1460.     return S_OK;
  1461. }
  1462.  
  1463. void AFX_CDECL AllocLongBinary(CLongBinary& lb, DWORD dwDataLength)
  1464. {
  1465.     if (lb.m_hData == NULL)
  1466.     {
  1467.         if (dwDataLength > 0)
  1468.         {
  1469.             // Alloc memory, return error if not possible
  1470.             lb.m_hData = ::GlobalAlloc(GMEM_MOVEABLE, dwDataLength);
  1471.             if (lb.m_hData == NULL)
  1472.                 AfxThrowMemoryException();
  1473.         }
  1474.     }
  1475.     else if (::GlobalSize(lb.m_hData) < dwDataLength)
  1476.     {
  1477.         // Save the old address in case ReAlloc fails
  1478.         HGLOBAL hOldData = lb.m_hData;
  1479.  
  1480.         // Alloc more mem, free up mem and throw exception if not possible
  1481.         lb.m_hData = ::GlobalReAlloc(hOldData, dwDataLength, GMEM_MOVEABLE);
  1482.         if (lb.m_hData == NULL)
  1483.         {
  1484.             lb.m_hData = hOldData;
  1485.             AfxThrowMemoryException();
  1486.         }
  1487.     }
  1488.     lb.m_dwDataLength = dwDataLength;
  1489. }
  1490.  
  1491. //////////////////////////////////////////////////////////////////////////////
  1492. // Inline function declarations expanded out-of-line
  1493.  
  1494. #ifndef _AFX_ENABLE_INLINES
  1495.  
  1496. static char _szAfxDaoInl[] = "afxdao.inl";
  1497. #undef THIS_FILE
  1498. #define THIS_FILE _szAfxDaoInl
  1499. #define _AFXDAODFX_INLINE
  1500. #include "afxdao.inl"
  1501.  
  1502. #endif
  1503.  
  1504. #ifdef AFX_INIT_SEG
  1505. #pragma code_seg(AFX_INIT_SEG)
  1506. #endif
  1507.  
  1508. /////////////////////////////////////////////////////////////////////////////
  1509.