oledisp2.cpp 13 KB

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