| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519 |
- // This is a part of the Microsoft Foundation Classes C++ library.
- // Copyright (C) 1992-1998 Microsoft Corporation
- // All rights reserved.
- //
- // This source code is only intended as a supplement to the
- // Microsoft Foundation Classes Reference and related
- // electronic documentation provided with the library.
- // See these sources for detailed information regarding the
- // Microsoft Foundation Classes product.
- #include "stdafx.h"
- #include <stdarg.h>
- #ifdef AFX_OLE5_SEG
- #pragma code_seg(AFX_OLE5_SEG)
- #endif
- #ifdef _DEBUG
- #undef THIS_FILE
- static char THIS_FILE[] = __FILE__;
- #endif
- #define new DEBUG_NEW
- /////////////////////////////////////////////////////////////////////////////
- // COleDispatchDriver constructors/destructors
- HRESULT AFXAPI AfxGetClassIDFromString(LPCTSTR lpsz, LPCLSID lpClsID)
- {
- USES_CONVERSION;
- HRESULT hr;
- if (lpsz[0] == '{')
- hr = CLSIDFromString((LPOLESTR)T2COLE(lpsz), lpClsID);
- else
- hr = CLSIDFromProgID(T2COLE(lpsz), lpClsID);
- return hr;
- }
- COleDispatchDriver::COleDispatchDriver()
- {
- m_lpDispatch = NULL;
- m_bAutoRelease = TRUE;
- }
- COleDispatchDriver::COleDispatchDriver(LPDISPATCH lpDispatch, BOOL bAutoRelease)
- {
- m_lpDispatch = lpDispatch;
- m_bAutoRelease = bAutoRelease;
- }
- COleDispatchDriver::COleDispatchDriver(const COleDispatchDriver& dispatchSrc)
- {
- ASSERT(this != &dispatchSrc); // constructing from self?
- m_lpDispatch = dispatchSrc.m_lpDispatch;
- if (m_lpDispatch != NULL)
- m_lpDispatch->AddRef();
- m_bAutoRelease = TRUE;
- }
- const COleDispatchDriver&
- COleDispatchDriver::operator=(const COleDispatchDriver& dispatchSrc)
- {
- if (this != &dispatchSrc)
- {
- LPDISPATCH lpTemp = m_lpDispatch;
- m_lpDispatch = dispatchSrc.m_lpDispatch;
- if (m_lpDispatch != NULL)
- m_lpDispatch->AddRef();
- if (lpTemp != NULL && m_bAutoRelease)
- lpTemp->Release();
- m_bAutoRelease = TRUE;
- }
- return *this;
- }
- BOOL COleDispatchDriver::CreateDispatch(REFCLSID clsid, COleException* pError)
- {
- ASSERT(m_lpDispatch == NULL);
- m_bAutoRelease = TRUE; // good default is to auto-release
- // create an instance of the object
- LPUNKNOWN lpUnknown = NULL;
- SCODE sc = CoCreateInstance(clsid, NULL, CLSCTX_ALL | CLSCTX_REMOTE_SERVER,
- IID_IUnknown, (LPLP)&lpUnknown);
- if (sc == E_INVALIDARG)
- {
- // may not support CLSCTX_REMOTE_SERVER, so try without
- sc = CoCreateInstance(clsid, NULL, CLSCTX_ALL & ~CLSCTX_REMOTE_SERVER,
- IID_IUnknown, (LPLP)&lpUnknown);
- }
- if (FAILED(sc))
- goto Failed;
- // make sure it is running
- sc = OleRun(lpUnknown);
- if (FAILED(sc))
- goto Failed;
- // query for IDispatch interface
- m_lpDispatch = QUERYINTERFACE(lpUnknown, IDispatch);
- if (m_lpDispatch == NULL)
- goto Failed;
- lpUnknown->Release();
- ASSERT(m_lpDispatch != NULL);
- return TRUE;
- Failed:
- RELEASE(lpUnknown);
- if (pError != NULL)
- pError->m_sc = sc;
- TRACE1("Warning: CreateDispatch returning scode = %s.\n",
- AfxGetFullScodeString(sc));
- return FALSE;
- }
- BOOL COleDispatchDriver::CreateDispatch(LPCTSTR lpszProgID,
- COleException* pError)
- {
- ASSERT(m_lpDispatch == NULL);
- // map prog id to CLSID
- CLSID clsid;
- SCODE sc = AfxGetClassIDFromString(lpszProgID, &clsid);
- if (FAILED(sc))
- {
- if (pError != NULL)
- pError->m_sc = sc;
- return FALSE;
- }
- // create with CLSID
- return CreateDispatch(clsid, pError);
- }
- void COleDispatchDriver::AttachDispatch(LPDISPATCH lpDispatch,
- BOOL bAutoRelease)
- {
- ASSERT(lpDispatch != NULL);
- ReleaseDispatch(); // detach previous
- m_lpDispatch = lpDispatch;
- m_bAutoRelease = bAutoRelease;
- }
- void COleDispatchDriver::ReleaseDispatch()
- {
- if (m_lpDispatch != NULL)
- {
- if (m_bAutoRelease)
- m_lpDispatch->Release();
- m_lpDispatch = NULL;
- }
- }
- LPDISPATCH COleDispatchDriver::DetachDispatch()
- {
- LPDISPATCH lpDispatch = m_lpDispatch;
- m_lpDispatch = NULL; // detach without Release
- return lpDispatch;
- }
- /////////////////////////////////////////////////////////////////////////////
- // COleDispatchDriver implementation
- void COleDispatchDriver::InvokeHelperV(DISPID dwDispID, WORD wFlags,
- VARTYPE vtRet, void* pvRet, const BYTE* pbParamInfo, va_list argList)
- {
- USES_CONVERSION;
- if (m_lpDispatch == NULL)
- {
- TRACE0("Warning: attempt to call Invoke with NULL m_lpDispatch!\n");
- return;
- }
- DISPPARAMS dispparams;
- memset(&dispparams, 0, sizeof dispparams);
- // determine number of arguments
- if (pbParamInfo != NULL)
- dispparams.cArgs = lstrlenA((LPCSTR)pbParamInfo);
- DISPID dispidNamed = DISPID_PROPERTYPUT;
- if (wFlags & (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF))
- {
- ASSERT(dispparams.cArgs > 0);
- dispparams.cNamedArgs = 1;
- dispparams.rgdispidNamedArgs = &dispidNamed;
- }
- if (dispparams.cArgs != 0)
- {
- // allocate memory for all VARIANT parameters
- VARIANT* pArg = new VARIANT[dispparams.cArgs];
- ASSERT(pArg != NULL); // should have thrown exception
- dispparams.rgvarg = pArg;
- memset(pArg, 0, sizeof(VARIANT) * dispparams.cArgs);
- // get ready to walk vararg list
- const BYTE* pb = pbParamInfo;
- pArg += dispparams.cArgs - 1; // params go in opposite order
- while (*pb != 0)
- {
- ASSERT(pArg >= dispparams.rgvarg);
- pArg->vt = *pb; // set the variant type
- if (pArg->vt & VT_MFCBYREF)
- {
- pArg->vt &= ~VT_MFCBYREF;
- pArg->vt |= VT_BYREF;
- }
- switch (pArg->vt)
- {
- case VT_UI1:
- pArg->bVal = va_arg(argList, BYTE);
- break;
- case VT_I2:
- pArg->iVal = va_arg(argList, short);
- break;
- case VT_I4:
- pArg->lVal = va_arg(argList, long);
- break;
- case VT_R4:
- pArg->fltVal = (float)va_arg(argList, double);
- break;
- case VT_R8:
- pArg->dblVal = va_arg(argList, double);
- break;
- case VT_DATE:
- pArg->date = va_arg(argList, DATE);
- break;
- case VT_CY:
- pArg->cyVal = *va_arg(argList, CY*);
- break;
- case VT_BSTR:
- {
- LPCOLESTR lpsz = va_arg(argList, LPOLESTR);
- pArg->bstrVal = ::SysAllocString(lpsz);
- if (lpsz != NULL && pArg->bstrVal == NULL)
- AfxThrowMemoryException();
- }
- break;
- #if !defined(_UNICODE) && !defined(OLE2ANSI)
- case VT_BSTRA:
- {
- LPCSTR lpsz = va_arg(argList, LPSTR);
- pArg->bstrVal = ::SysAllocString(T2COLE(lpsz));
- if (lpsz != NULL && pArg->bstrVal == NULL)
- AfxThrowMemoryException();
- pArg->vt = VT_BSTR;
- }
- break;
- #endif
- case VT_DISPATCH:
- pArg->pdispVal = va_arg(argList, LPDISPATCH);
- break;
- case VT_ERROR:
- pArg->scode = va_arg(argList, SCODE);
- break;
- case VT_BOOL:
- V_BOOL(pArg) = (VARIANT_BOOL)(va_arg(argList, BOOL) ? -1 : 0);
- break;
- case VT_VARIANT:
- *pArg = *va_arg(argList, VARIANT*);
- break;
- case VT_UNKNOWN:
- pArg->punkVal = va_arg(argList, LPUNKNOWN);
- break;
- case VT_I2|VT_BYREF:
- pArg->piVal = va_arg(argList, short*);
- break;
- case VT_UI1|VT_BYREF:
- pArg->pbVal = va_arg(argList, BYTE*);
- break;
- case VT_I4|VT_BYREF:
- pArg->plVal = va_arg(argList, long*);
- break;
- case VT_R4|VT_BYREF:
- pArg->pfltVal = va_arg(argList, float*);
- break;
- case VT_R8|VT_BYREF:
- pArg->pdblVal = va_arg(argList, double*);
- break;
- case VT_DATE|VT_BYREF:
- pArg->pdate = va_arg(argList, DATE*);
- break;
- case VT_CY|VT_BYREF:
- pArg->pcyVal = va_arg(argList, CY*);
- break;
- case VT_BSTR|VT_BYREF:
- pArg->pbstrVal = va_arg(argList, BSTR*);
- break;
- case VT_DISPATCH|VT_BYREF:
- pArg->ppdispVal = va_arg(argList, LPDISPATCH*);
- break;
- case VT_ERROR|VT_BYREF:
- pArg->pscode = va_arg(argList, SCODE*);
- break;
- case VT_BOOL|VT_BYREF:
- {
- // coerce BOOL into VARIANT_BOOL
- BOOL* pboolVal = va_arg(argList, BOOL*);
- *pboolVal = *pboolVal ? MAKELONG(-1, 0) : 0;
- pArg->pboolVal = (VARIANT_BOOL*)pboolVal;
- }
- break;
- case VT_VARIANT|VT_BYREF:
- pArg->pvarVal = va_arg(argList, VARIANT*);
- break;
- case VT_UNKNOWN|VT_BYREF:
- pArg->ppunkVal = va_arg(argList, LPUNKNOWN*);
- break;
- default:
- ASSERT(FALSE); // unknown type!
- break;
- }
- --pArg; // get ready to fill next argument
- ++pb;
- }
- }
- // initialize return value
- VARIANT* pvarResult = NULL;
- VARIANT vaResult;
- AfxVariantInit(&vaResult);
- if (vtRet != VT_EMPTY)
- pvarResult = &vaResult;
- // initialize EXCEPINFO struct
- EXCEPINFO excepInfo;
- memset(&excepInfo, 0, sizeof excepInfo);
- UINT nArgErr = (UINT)-1; // initialize to invalid arg
- // make the call
- SCODE sc = m_lpDispatch->Invoke(dwDispID, IID_NULL, 0, wFlags,
- &dispparams, pvarResult, &excepInfo, &nArgErr);
- // cleanup any arguments that need cleanup
- if (dispparams.cArgs != 0)
- {
- VARIANT* pArg = dispparams.rgvarg + dispparams.cArgs - 1;
- const BYTE* pb = pbParamInfo;
- while (*pb != 0)
- {
- switch ((VARTYPE)*pb)
- {
- #if !defined(_UNICODE) && !defined(OLE2ANSI)
- case VT_BSTRA:
- #endif
- case VT_BSTR:
- VariantClear(pArg);
- break;
- }
- --pArg;
- ++pb;
- }
- }
- delete[] dispparams.rgvarg;
- // throw exception on failure
- if (FAILED(sc))
- {
- VariantClear(&vaResult);
- if (sc != DISP_E_EXCEPTION)
- {
- // non-exception error code
- AfxThrowOleException(sc);
- }
- // make sure excepInfo is filled in
- if (excepInfo.pfnDeferredFillIn != NULL)
- excepInfo.pfnDeferredFillIn(&excepInfo);
- // allocate new exception, and fill it
- COleDispatchException* pException =
- new COleDispatchException(NULL, 0, excepInfo.wCode);
- ASSERT(pException->m_wCode == excepInfo.wCode);
- if (excepInfo.bstrSource != NULL)
- {
- pException->m_strSource = excepInfo.bstrSource;
- SysFreeString(excepInfo.bstrSource);
- }
- if (excepInfo.bstrDescription != NULL)
- {
- pException->m_strDescription = excepInfo.bstrDescription;
- SysFreeString(excepInfo.bstrDescription);
- }
- if (excepInfo.bstrHelpFile != NULL)
- {
- pException->m_strHelpFile = excepInfo.bstrHelpFile;
- SysFreeString(excepInfo.bstrHelpFile);
- }
- pException->m_dwHelpContext = excepInfo.dwHelpContext;
- pException->m_scError = excepInfo.scode;
- // then throw the exception
- THROW(pException);
- ASSERT(FALSE); // not reached
- }
- if (vtRet != VT_EMPTY)
- {
- // convert return value
- if (vtRet != VT_VARIANT)
- {
- SCODE sc = VariantChangeType(&vaResult, &vaResult, 0, vtRet);
- if (FAILED(sc))
- {
- TRACE0("Warning: automation return value coercion failed.\n");
- VariantClear(&vaResult);
- AfxThrowOleException(sc);
- }
- ASSERT(vtRet == vaResult.vt);
- }
- // copy return value into return spot!
- switch (vtRet)
- {
- case VT_UI1:
- *(BYTE*)pvRet = vaResult.bVal;
- break;
- case VT_I2:
- *(short*)pvRet = vaResult.iVal;
- break;
- case VT_I4:
- *(long*)pvRet = vaResult.lVal;
- break;
- case VT_R4:
- *(_AFX_FLOAT*)pvRet = *(_AFX_FLOAT*)&vaResult.fltVal;
- break;
- case VT_R8:
- *(_AFX_DOUBLE*)pvRet = *(_AFX_DOUBLE*)&vaResult.dblVal;
- break;
- case VT_DATE:
- *(_AFX_DOUBLE*)pvRet = *(_AFX_DOUBLE*)&vaResult.date;
- break;
- case VT_CY:
- *(CY*)pvRet = vaResult.cyVal;
- break;
- case VT_BSTR:
- AfxBSTR2CString((CString*)pvRet, vaResult.bstrVal);
- SysFreeString(vaResult.bstrVal);
- break;
- case VT_DISPATCH:
- *(LPDISPATCH*)pvRet = vaResult.pdispVal;
- break;
- case VT_ERROR:
- *(SCODE*)pvRet = vaResult.scode;
- break;
- case VT_BOOL:
- *(BOOL*)pvRet = (V_BOOL(&vaResult) != 0);
- break;
- case VT_VARIANT:
- *(VARIANT*)pvRet = vaResult;
- break;
- case VT_UNKNOWN:
- *(LPUNKNOWN*)pvRet = vaResult.punkVal;
- break;
- default:
- ASSERT(FALSE); // invalid return type specified
- }
- }
- }
- void AFX_CDECL COleDispatchDriver::InvokeHelper(DISPID dwDispID, WORD wFlags,
- VARTYPE vtRet, void* pvRet, const BYTE* pbParamInfo, ...)
- {
- va_list argList;
- va_start(argList, pbParamInfo);
- InvokeHelperV(dwDispID, wFlags, vtRet, pvRet, pbParamInfo, argList);
- va_end(argList);
- }
- void COleDispatchDriver::GetProperty(DISPID dwDispID, VARTYPE vtProp,
- void* pvProp) const
- {
- ((COleDispatchDriver*)this)->InvokeHelper(dwDispID,
- DISPATCH_PROPERTYGET, vtProp, pvProp, NULL);
- }
- void AFX_CDECL COleDispatchDriver::SetProperty(DISPID dwDispID, VARTYPE vtProp, ...)
- {
- va_list argList; // really only one arg, but...
- va_start(argList, vtProp);
- BYTE rgbParams[2];
- if (vtProp & VT_BYREF)
- {
- vtProp &= ~VT_BYREF;
- vtProp |= VT_MFCBYREF;
- }
- #if !defined(_UNICODE) && !defined(OLE2ANSI)
- if (vtProp == VT_BSTR)
- vtProp = VT_BSTRA;
- #endif
- rgbParams[0] = (BYTE)vtProp;
- rgbParams[1] = 0;
- WORD wFlags = (WORD)(vtProp == VT_DISPATCH ?
- DISPATCH_PROPERTYPUTREF : DISPATCH_PROPERTYPUT);
- InvokeHelperV(dwDispID, wFlags, VT_EMPTY, NULL, rgbParams, argList);
- va_end(argList);
- }
- /////////////////////////////////////////////////////////////////////////////
|