home *** CD-ROM | disk | FTP | other *** search
/ Supercompiler 1997 / SUPERCOMPILER97.iso / MS_VC.50 / VC / MFC / SRC / OLEDISP2.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-30  |  13.3 KB  |  546 lines

  1. // This is a part of the Microsoft Foundation Classes C++ library.
  2. // Copyright (C) 1992-1997 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. #include <stdarg.h>
  13.  
  14. #ifdef AFX_OLE5_SEG
  15. #pragma code_seg(AFX_OLE5_SEG)
  16. #endif
  17.  
  18. #ifdef _DEBUG
  19. #undef THIS_FILE
  20. static char THIS_FILE[] = __FILE__;
  21. #endif
  22.  
  23. #define new DEBUG_NEW
  24.  
  25. /////////////////////////////////////////////////////////////////////////////
  26. // COleDispatchDriver constructors/destructors
  27.  
  28. HRESULT AFXAPI AfxGetClassIDFromString(LPCTSTR lpsz, LPCLSID lpClsID)
  29. {
  30.     USES_CONVERSION;
  31.  
  32.     HRESULT hr;
  33.     if (lpsz[0] == '{')
  34.         hr = CLSIDFromString((LPOLESTR)T2COLE(lpsz), lpClsID);
  35.     else
  36.         hr = CLSIDFromProgID(T2COLE(lpsz), lpClsID);
  37.     return hr;
  38. }
  39.  
  40. COleDispatchDriver::COleDispatchDriver()
  41. {
  42.     m_lpDispatch = NULL;
  43.     m_bAutoRelease = TRUE;
  44. }
  45.  
  46. COleDispatchDriver::COleDispatchDriver(LPDISPATCH lpDispatch, BOOL bAutoRelease)
  47. {
  48.     m_lpDispatch = lpDispatch;
  49.     m_bAutoRelease = bAutoRelease;
  50. }
  51.  
  52. COleDispatchDriver::COleDispatchDriver(const COleDispatchDriver& dispatchSrc)
  53. {
  54.     ASSERT(this != &dispatchSrc);   // constructing from self?
  55.  
  56.     m_lpDispatch = dispatchSrc.m_lpDispatch;
  57.     if (m_lpDispatch != NULL)
  58.         m_lpDispatch->AddRef();
  59.     m_bAutoRelease = TRUE;
  60. }
  61.  
  62. const COleDispatchDriver&
  63. COleDispatchDriver::operator=(const COleDispatchDriver& dispatchSrc)
  64. {
  65.     if (this != &dispatchSrc)
  66.     {
  67.         LPDISPATCH lpTemp = m_lpDispatch;
  68.         m_lpDispatch = dispatchSrc.m_lpDispatch;
  69.         if (m_lpDispatch != NULL)
  70.             m_lpDispatch->AddRef();
  71.         if (lpTemp != NULL && m_bAutoRelease)
  72.             lpTemp->Release();
  73.         m_bAutoRelease = TRUE;
  74.     }
  75.     return *this;
  76. }
  77.  
  78. BOOL COleDispatchDriver::CreateDispatch(REFCLSID clsid, COleException* pError)
  79. {
  80.     ASSERT(m_lpDispatch == NULL);
  81.  
  82.     m_bAutoRelease = TRUE;  // good default is to auto-release
  83.  
  84.     // create an instance of the object
  85.     LPUNKNOWN lpUnknown = NULL;
  86.     SCODE sc = CoCreateInstance(clsid, NULL, CLSCTX_ALL | CLSCTX_REMOTE_SERVER,
  87.         IID_IUnknown, (LPLP)&lpUnknown);
  88.     if (sc == E_INVALIDARG)
  89.     {
  90.         // may not support CLSCTX_REMOTE_SERVER, so try without
  91.         sc = CoCreateInstance(clsid, NULL, CLSCTX_ALL & ~CLSCTX_REMOTE_SERVER,
  92.             IID_IUnknown, (LPLP)&lpUnknown);
  93.     }
  94.     if (FAILED(sc))
  95.         goto Failed;
  96.  
  97.     // make sure it is running
  98.     sc = OleRun(lpUnknown);
  99.     if (FAILED(sc))
  100.         goto Failed;
  101.  
  102.     // query for IDispatch interface
  103.     m_lpDispatch = QUERYINTERFACE(lpUnknown, IDispatch);
  104.     if (m_lpDispatch == NULL)
  105.         goto Failed;
  106.  
  107.     lpUnknown->Release();
  108.     ASSERT(m_lpDispatch != NULL);
  109.     return TRUE;
  110.  
  111. Failed:
  112.     RELEASE(lpUnknown);
  113.     if (pError != NULL)
  114.         pError->m_sc = sc;
  115.     TRACE1("Warning: CreateDispatch returning scode = %s.\n",
  116.         AfxGetFullScodeString(sc));
  117.     return FALSE;
  118. }
  119.  
  120. BOOL COleDispatchDriver::CreateDispatch(LPCTSTR lpszProgID,
  121.     COleException* pError)
  122. {
  123.     ASSERT(m_lpDispatch == NULL);
  124.  
  125.     // map prog id to CLSID
  126.     CLSID clsid;
  127.     SCODE sc = AfxGetClassIDFromString(lpszProgID, &clsid);
  128.     if (FAILED(sc))
  129.     {
  130.         if (pError != NULL)
  131.             pError->m_sc = sc;
  132.         return FALSE;
  133.     }
  134.  
  135.     // create with CLSID
  136.     return CreateDispatch(clsid, pError);
  137. }
  138.  
  139. void COleDispatchDriver::AttachDispatch(LPDISPATCH lpDispatch,
  140.     BOOL bAutoRelease)
  141. {
  142.     ASSERT(lpDispatch != NULL);
  143.  
  144.     ReleaseDispatch();  // detach previous
  145.     m_lpDispatch = lpDispatch;
  146.     m_bAutoRelease = bAutoRelease;
  147. }
  148.  
  149. void COleDispatchDriver::ReleaseDispatch()
  150. {
  151.     if (m_lpDispatch != NULL)
  152.     {
  153.         if (m_bAutoRelease)
  154.             m_lpDispatch->Release();
  155.         m_lpDispatch = NULL;
  156.     }
  157. }
  158.  
  159. LPDISPATCH COleDispatchDriver::DetachDispatch()
  160. {
  161.     LPDISPATCH lpDispatch = m_lpDispatch;
  162.     m_lpDispatch = NULL;    // detach without Release
  163.     return lpDispatch;
  164. }
  165.  
  166. /////////////////////////////////////////////////////////////////////////////
  167. // COleDispatchDriver implementation
  168.  
  169. #if defined(_68K_) || defined(_X86_)
  170.     #define DOUBLE_ARG  _AFX_DOUBLE
  171. #else
  172.     #define DOUBLE_ARG  double
  173. #endif
  174.  
  175.  
  176. void COleDispatchDriver::InvokeHelperV(DISPID dwDispID, WORD wFlags,
  177.     VARTYPE vtRet, void* pvRet, const BYTE* pbParamInfo, va_list argList)
  178. {
  179.     USES_CONVERSION;
  180.  
  181.     if (m_lpDispatch == NULL)
  182.     {
  183.         TRACE0("Warning: attempt to call Invoke with NULL m_lpDispatch!\n");
  184.         return;
  185.     }
  186.  
  187.     DISPPARAMS dispparams;
  188.     memset(&dispparams, 0, sizeof dispparams);
  189.  
  190.     // determine number of arguments
  191.     if (pbParamInfo != NULL)
  192.         dispparams.cArgs = lstrlenA((LPCSTR)pbParamInfo);
  193.  
  194.     DISPID dispidNamed = DISPID_PROPERTYPUT;
  195.     if (wFlags & (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF))
  196.     {
  197.         ASSERT(dispparams.cArgs > 0);
  198.         dispparams.cNamedArgs = 1;
  199.         dispparams.rgdispidNamedArgs = &dispidNamed;
  200.     }
  201.  
  202.     if (dispparams.cArgs != 0)
  203.     {
  204.         // allocate memory for all VARIANT parameters
  205.         VARIANT* pArg = new VARIANT[dispparams.cArgs];
  206.         ASSERT(pArg != NULL);   // should have thrown exception
  207.         dispparams.rgvarg = pArg;
  208.         memset(pArg, 0, sizeof(VARIANT) * dispparams.cArgs);
  209.  
  210.         // get ready to walk vararg list
  211.         const BYTE* pb = pbParamInfo;
  212.         pArg += dispparams.cArgs - 1;   // params go in opposite order
  213.  
  214.         while (*pb != 0)
  215.         {
  216.             ASSERT(pArg >= dispparams.rgvarg);
  217.  
  218.             pArg->vt = *pb; // set the variant type
  219.             if (pArg->vt & VT_MFCBYREF)
  220.             {
  221.                 pArg->vt &= ~VT_MFCBYREF;
  222.                 pArg->vt |= VT_BYREF;
  223.             }
  224.             switch (pArg->vt)
  225.             {
  226.             case VT_UI1:
  227. #ifdef _MAC
  228.                 pArg->bVal = (BYTE)va_arg(argList, int);
  229. #else
  230.                 pArg->bVal = va_arg(argList, BYTE);
  231. #endif
  232.                 break;
  233.             case VT_I2:
  234. #ifdef _MAC
  235.                 pArg->iVal = (short)va_arg(argList, int);
  236. #else
  237.                 pArg->iVal = va_arg(argList, short);
  238. #endif
  239.                 break;
  240.             case VT_I4:
  241.                 pArg->lVal = va_arg(argList, long);
  242.                 break;
  243.             case VT_R4:
  244.                 // Note: All float arguments to vararg functions are passed
  245.                 //  as doubles instead.  Thats why they are passed as VT_R8
  246.                 //  instead of VT_R4.
  247.                 pArg->vt = VT_R8;
  248.                 *(DOUBLE_ARG*)&pArg->dblVal = va_arg(argList, DOUBLE_ARG);
  249.                 break;
  250.             case VT_R8:
  251.                 *(DOUBLE_ARG*)&pArg->dblVal = va_arg(argList, DOUBLE_ARG);
  252.                 break;
  253.             case VT_DATE:
  254.                 *(DOUBLE_ARG*)&pArg->date = va_arg(argList, DOUBLE_ARG);
  255.                 break;
  256.             case VT_CY:
  257.                 pArg->cyVal = *va_arg(argList, CY*);
  258.                 break;
  259.             case VT_BSTR:
  260.                 {
  261.                     LPCOLESTR lpsz = va_arg(argList, LPOLESTR);
  262.                     pArg->bstrVal = ::SysAllocString(lpsz);
  263.                     if (lpsz != NULL && pArg->bstrVal == NULL)
  264.                         AfxThrowMemoryException();
  265.                 }
  266.                 break;
  267. #if !defined(_UNICODE) && !defined(OLE2ANSI)
  268.             case VT_BSTRA:
  269.                 {
  270.                     LPCSTR lpsz = va_arg(argList, LPSTR);
  271.                     pArg->bstrVal = ::SysAllocString(T2COLE(lpsz));
  272.                     if (lpsz != NULL && pArg->bstrVal == NULL)
  273.                         AfxThrowMemoryException();
  274.                     pArg->vt = VT_BSTR;
  275.                 }
  276.                 break;
  277. #endif
  278.             case VT_DISPATCH:
  279.                 pArg->pdispVal = va_arg(argList, LPDISPATCH);
  280.                 break;
  281.             case VT_ERROR:
  282.                 pArg->scode = va_arg(argList, SCODE);
  283.                 break;
  284.             case VT_BOOL:
  285.                 V_BOOL(pArg) = (VARIANT_BOOL)(va_arg(argList, BOOL) ? -1 : 0);
  286.                 break;
  287.             case VT_VARIANT:
  288.                 *pArg = *va_arg(argList, VARIANT*);
  289.                 break;
  290.             case VT_UNKNOWN:
  291.                 pArg->punkVal = va_arg(argList, LPUNKNOWN);
  292.                 break;
  293.  
  294.             case VT_I2|VT_BYREF:
  295.                 pArg->piVal = va_arg(argList, short*);
  296.                 break;
  297.             case VT_UI1|VT_BYREF:
  298.                 pArg->pbVal = va_arg(argList, BYTE*);
  299.                 break;
  300.             case VT_I4|VT_BYREF:
  301.                 pArg->plVal = va_arg(argList, long*);
  302.                 break;
  303.             case VT_R4|VT_BYREF:
  304.                 pArg->pfltVal = va_arg(argList, float*);
  305.                 break;
  306.             case VT_R8|VT_BYREF:
  307.                 pArg->pdblVal = va_arg(argList, double*);
  308.                 break;
  309.             case VT_DATE|VT_BYREF:
  310.                 pArg->pdate = va_arg(argList, DATE*);
  311.                 break;
  312.             case VT_CY|VT_BYREF:
  313.                 pArg->pcyVal = va_arg(argList, CY*);
  314.                 break;
  315.             case VT_BSTR|VT_BYREF:
  316.                 pArg->pbstrVal = va_arg(argList, BSTR*);
  317.                 break;
  318.             case VT_DISPATCH|VT_BYREF:
  319.                 pArg->ppdispVal = va_arg(argList, LPDISPATCH*);
  320.                 break;
  321.             case VT_ERROR|VT_BYREF:
  322.                 pArg->pscode = va_arg(argList, SCODE*);
  323.                 break;
  324.             case VT_BOOL|VT_BYREF:
  325.                 {
  326.                     // coerce BOOL into VARIANT_BOOL
  327.                     BOOL* pboolVal = va_arg(argList, BOOL*);
  328. #ifndef _MAC
  329.                     *pboolVal = *pboolVal ? MAKELONG(-1, 0) : 0;
  330. #else
  331.                     *pboolVal = *pboolVal ? MAKELONG(0, -1) : 0;
  332. #endif
  333.                     pArg->pboolVal = (VARIANT_BOOL*)pboolVal;
  334.                 }
  335.                 break;
  336.             case VT_VARIANT|VT_BYREF:
  337.                 pArg->pvarVal = va_arg(argList, VARIANT*);
  338.                 break;
  339.             case VT_UNKNOWN|VT_BYREF:
  340.                 pArg->ppunkVal = va_arg(argList, LPUNKNOWN*);
  341.                 break;
  342.  
  343.             default:
  344.                 ASSERT(FALSE);  // unknown type!
  345.                 break;
  346.             }
  347.  
  348.             --pArg; // get ready to fill next argument
  349.             ++pb;
  350.         }
  351.     }
  352.  
  353.     // initialize return value
  354.     VARIANT* pvarResult = NULL;
  355.     VARIANT vaResult;
  356.     AfxVariantInit(&vaResult);
  357.     if (vtRet != VT_EMPTY)
  358.         pvarResult = &vaResult;
  359.  
  360.     // initialize EXCEPINFO struct
  361.     EXCEPINFO excepInfo;
  362.     memset(&excepInfo, 0, sizeof excepInfo);
  363.  
  364.     UINT nArgErr = (UINT)-1;  // initialize to invalid arg
  365.  
  366.     // make the call
  367.     SCODE sc = m_lpDispatch->Invoke(dwDispID, IID_NULL, 0, wFlags,
  368.         &dispparams, pvarResult, &excepInfo, &nArgErr);
  369.  
  370.     // cleanup any arguments that need cleanup
  371.     if (dispparams.cArgs != 0)
  372.     {
  373.         VARIANT* pArg = dispparams.rgvarg + dispparams.cArgs - 1;
  374.         const BYTE* pb = pbParamInfo;
  375.         while (*pb != 0)
  376.         {
  377.             switch ((VARTYPE)*pb)
  378.             {
  379. #if !defined(_UNICODE) && !defined(OLE2ANSI)
  380.             case VT_BSTRA:
  381. #endif
  382.             case VT_BSTR:
  383.                 VariantClear(pArg);
  384.                 break;
  385.             }
  386.             --pArg;
  387.             ++pb;
  388.         }
  389.     }
  390.     delete[] dispparams.rgvarg;
  391.  
  392.     // throw exception on failure
  393.     if (FAILED(sc))
  394.     {
  395.         VariantClear(&vaResult);
  396.         if (sc != DISP_E_EXCEPTION)
  397.         {
  398.             // non-exception error code
  399.             AfxThrowOleException(sc);
  400.         }
  401.  
  402.         // make sure excepInfo is filled in
  403.         if (excepInfo.pfnDeferredFillIn != NULL)
  404.             excepInfo.pfnDeferredFillIn(&excepInfo);
  405.  
  406.         // allocate new exception, and fill it
  407.         COleDispatchException* pException =
  408.             new COleDispatchException(NULL, 0, excepInfo.wCode);
  409.         ASSERT(pException->m_wCode == excepInfo.wCode);
  410.         if (excepInfo.bstrSource != NULL)
  411.         {
  412.             pException->m_strSource = excepInfo.bstrSource;
  413.             SysFreeString(excepInfo.bstrSource);
  414.         }
  415.         if (excepInfo.bstrDescription != NULL)
  416.         {
  417.             pException->m_strDescription = excepInfo.bstrDescription;
  418.             SysFreeString(excepInfo.bstrDescription);
  419.         }
  420.         if (excepInfo.bstrHelpFile != NULL)
  421.         {
  422.             pException->m_strHelpFile = excepInfo.bstrHelpFile;
  423.             SysFreeString(excepInfo.bstrHelpFile);
  424.         }
  425.         pException->m_dwHelpContext = excepInfo.dwHelpContext;
  426.         pException->m_scError = excepInfo.scode;
  427.  
  428.         // then throw the exception
  429.         THROW(pException);
  430.         ASSERT(FALSE);  // not reached
  431.     }
  432.  
  433.     if (vtRet != VT_EMPTY)
  434.     {
  435.         // convert return value
  436.         if (vtRet != VT_VARIANT)
  437.         {
  438.             SCODE sc = VariantChangeType(&vaResult, &vaResult, 0, vtRet);
  439.             if (FAILED(sc))
  440.             {
  441.                 TRACE0("Warning: automation return value coercion failed.\n");
  442.                 VariantClear(&vaResult);
  443.                 AfxThrowOleException(sc);
  444.             }
  445.             ASSERT(vtRet == vaResult.vt);
  446.         }
  447.  
  448.         // copy return value into return spot!
  449.         switch (vtRet)
  450.         {
  451.         case VT_UI1:
  452.             *(BYTE*)pvRet = vaResult.bVal;
  453.             break;
  454.         case VT_I2:
  455.             *(short*)pvRet = vaResult.iVal;
  456.             break;
  457.         case VT_I4:
  458.             *(long*)pvRet = vaResult.lVal;
  459.             break;
  460.         case VT_R4:
  461.             *(_AFX_FLOAT*)pvRet = *(_AFX_FLOAT*)&vaResult.fltVal;
  462.             break;
  463.         case VT_R8:
  464.             *(_AFX_DOUBLE*)pvRet = *(_AFX_DOUBLE*)&vaResult.dblVal;
  465.             break;
  466.         case VT_DATE:
  467.             *(_AFX_DOUBLE*)pvRet = *(_AFX_DOUBLE*)&vaResult.date;
  468.             break;
  469.         case VT_CY:
  470.             *(CY*)pvRet = vaResult.cyVal;
  471.             break;
  472.         case VT_BSTR:
  473.             AfxBSTR2CString((CString*)pvRet, vaResult.bstrVal);
  474.             SysFreeString(vaResult.bstrVal);
  475.             break;
  476.         case VT_DISPATCH:
  477.             *(LPDISPATCH*)pvRet = vaResult.pdispVal;
  478.             break;
  479.         case VT_ERROR:
  480.             *(SCODE*)pvRet = vaResult.scode;
  481.             break;
  482.         case VT_BOOL:
  483.             *(BOOL*)pvRet = (V_BOOL(&vaResult) != 0);
  484.             break;
  485.         case VT_VARIANT:
  486.             *(VARIANT*)pvRet = vaResult;
  487.             break;
  488.         case VT_UNKNOWN:
  489.             *(LPUNKNOWN*)pvRet = vaResult.punkVal;
  490.             break;
  491.  
  492.         default:
  493.             ASSERT(FALSE);  // invalid return type specified
  494.         }
  495.     }
  496. }
  497.  
  498. void AFX_CDECL COleDispatchDriver::InvokeHelper(DISPID dwDispID, WORD wFlags,
  499.     VARTYPE vtRet, void* pvRet, const BYTE* pbParamInfo, ...)
  500. {
  501.     va_list argList;
  502.     va_start(argList, pbParamInfo);
  503.  
  504.     InvokeHelperV(dwDispID, wFlags, vtRet, pvRet, pbParamInfo, argList);
  505.  
  506.     va_end(argList);
  507. }
  508.  
  509. void COleDispatchDriver::GetProperty(DISPID dwDispID, VARTYPE vtProp,
  510.     void* pvProp) const
  511. {
  512.     ((COleDispatchDriver*)this)->InvokeHelper(dwDispID,
  513.         DISPATCH_PROPERTYGET, vtProp, pvProp, NULL);
  514. }
  515.  
  516. void AFX_CDECL COleDispatchDriver::SetProperty(DISPID dwDispID, VARTYPE vtProp, ...)
  517. {
  518.     va_list argList;    // really only one arg, but...
  519.     va_start(argList, vtProp);
  520. #ifdef _MAC
  521.     argList -= 2;
  522. #endif
  523.  
  524.     BYTE rgbParams[2];
  525.     if (vtProp & VT_BYREF)
  526.     {
  527.         vtProp &= ~VT_BYREF;
  528.         vtProp |= VT_MFCBYREF;
  529.     }
  530.  
  531. #if !defined(_UNICODE) && !defined(OLE2ANSI)
  532.         if (vtProp == VT_BSTR)
  533.             vtProp = VT_BSTRA;
  534. #endif
  535.  
  536.     rgbParams[0] = (BYTE)vtProp;
  537.     rgbParams[1] = 0;
  538.     WORD wFlags = (WORD)(vtProp == VT_DISPATCH ?
  539.         DISPATCH_PROPERTYPUTREF : DISPATCH_PROPERTYPUT);
  540.     InvokeHelperV(dwDispID, wFlags, VT_EMPTY, NULL, rgbParams, argList);
  541.  
  542.     va_end(argList);
  543. }
  544.  
  545. /////////////////////////////////////////////////////////////////////////////
  546.