PPInterface.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566
  1. // Filename: PPInterface.cpp
  2. // Created by: atrestman (14Sept09)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #include "stdafx.h"
  15. #include "PPInterface.h"
  16. #include "PPPandaObject.h"
  17. #include "PPBrowserObject.h"
  18. #include "PPInstance.h"
  19. #include "P3DActiveXCtrl.h"
  20. #include <strstream>
  21. #include "Mshtml.h"
  22. PPInterface::PPInterface( )
  23. {
  24. }
  25. PPInterface::~PPInterface( )
  26. {
  27. }
  28. HRESULT PPInterface::GetIdOfName( IDispatch* pDisp, CString& ptName, DISPID* dispID )
  29. {
  30. if( !pDisp )
  31. {
  32. return E_FAIL;
  33. }
  34. OLECHAR* pElementName = ptName.AllocSysString();
  35. HRESULT hr = pDisp->GetIDsOfNames(IID_NULL, &pElementName, 1, LOCALE_USER_DEFAULT, dispID);
  36. SysFreeString( pElementName );
  37. return hr;
  38. }
  39. HRESULT PPInterface::Invoke(int nType, IDispatch* pDisp, CString& ptName, VARIANT* pvResult, int cArgs, VARIANT* params)
  40. {
  41. if( !pDisp )
  42. {
  43. return E_FAIL;
  44. }
  45. DISPPARAMS dp = { NULL, NULL, 0, 0 };
  46. DISPID dispidNamed = DISPID_PROPERTYPUT;
  47. DISPID dispID;
  48. CComPtr<IDispatchEx> pDispEx;
  49. HRESULT hr = GetIdOfName( pDisp, ptName, &dispID );
  50. if ( DISP_E_UNKNOWNNAME == hr )
  51. {
  52. hr = pDisp->QueryInterface( IID_IDispatchEx, ( void** )&pDispEx );
  53. if ( SUCCEEDED( hr ) && pDispEx )
  54. {
  55. OLECHAR* pElementName = ptName.AllocSysString();
  56. hr = pDispEx->GetDispID( pElementName, fdexNameEnsure, &dispID );
  57. SysFreeString( pElementName );
  58. }
  59. }
  60. if ( FAILED( hr ) )
  61. {
  62. return hr;
  63. }
  64. // Allocate memory for arguments...
  65. VARIANT *pArgs = new VARIANT[ cArgs + 1 ];
  66. // Reversing the arguments!!!
  67. // NOTE: http://msdn.microsoft.com/en-us/library/cc237569(PROT.10).aspx
  68. // pDispParams: MUST point to a DISPPARAMS structure that defines the arguments passed to the method.
  69. // Arguments MUST be stored in pDispParams->rgvarg in reverse order, so that the first argument is
  70. // the one with the highest index in the array. Byref arguments MUST be marked in this array
  71. // as VT_EMPTY entries, and stored in rgVarRef instead.
  72. for( int i = 0; i < cArgs; i++ )
  73. {
  74. pArgs[i] = params[ cArgs - 1 - i ];
  75. }
  76. // Build DISPPARAMS
  77. dp.cArgs = cArgs;
  78. dp.rgvarg = pArgs;
  79. // Handle special-case for property-puts!
  80. if( nType & DISPATCH_PROPERTYPUT )
  81. {
  82. dp.cNamedArgs = 1;
  83. dp.rgdispidNamedArgs = &dispidNamed;
  84. }
  85. // Make the call!
  86. if ( pDispEx )
  87. {
  88. hr = pDispEx->InvokeEx(dispID, LOCALE_USER_DEFAULT,
  89. nType, &dp, pvResult, NULL, NULL);
  90. }
  91. else
  92. {
  93. hr = pDisp->Invoke( dispID, IID_NULL, LOCALE_USER_DEFAULT,
  94. nType, &dp, pvResult, NULL, NULL );
  95. }
  96. delete [] pArgs;
  97. return hr;
  98. }
  99. HRESULT PPInterface::GetHtmlDocDispatch( CComPtr<IDispatch>& pDispScript )
  100. {
  101. HRESULT hr = S_OK;
  102. CComPtr<IOleClientSite> pOleClientSite = GetClientSte( );
  103. ASSERT( pOleClientSite );
  104. CComPtr<IOleContainer> pOleContainer;
  105. hr = pOleClientSite->GetContainer(& pOleContainer );
  106. ASSERT( SUCCEEDED( hr ) && pOleContainer );
  107. CComPtr<IHTMLDocument> pHtmlDoc;
  108. hr = pOleContainer->QueryInterface( IID_IHTMLDocument, ( void** )&pHtmlDoc );
  109. ASSERT( SUCCEEDED( hr ) && pHtmlDoc );
  110. // Get the script object (this returns the script object, NOT the script
  111. // element(s) that the get_scripts method does).
  112. hr = pHtmlDoc->get_Script( &pDispScript );
  113. ASSERT( SUCCEEDED( hr ) && pDispScript );
  114. CComPtr<IDispatchEx> pDispExScript;
  115. hr = pDispScript->QueryInterface( IID_IDispatchEx, ( void** )&pDispExScript );
  116. ASSERT( SUCCEEDED( hr ) && pDispExScript );
  117. pDispScript = pDispExScript;
  118. CComPtr<ITypeInfo> pTypeInfo;
  119. hr = pDispScript->GetTypeInfo( 0, 0, &pTypeInfo );
  120. return hr;
  121. }
  122. HRESULT PPInterface::HasProperty( CComPtr<IDispatch>& pDispatch, CString& name )
  123. {
  124. HRESULT hr = S_OK;
  125. if ( pDispatch == NULL )
  126. {
  127. hr = GetHtmlDocDispatch( pDispatch );
  128. }
  129. DISPID dispID;
  130. if ( SUCCEEDED( hr ) )
  131. {
  132. hr = GetIdOfName( pDispatch, name, &dispID );
  133. }
  134. return hr;
  135. }
  136. HRESULT PPInterface::CallMethod( CComPtr<IDispatch>& pDispatch, CString& name, COleVariant& varResult, int numParams, COleVariant* params )
  137. {
  138. HRESULT hr = S_OK;
  139. if ( pDispatch == NULL )
  140. {
  141. hr = GetHtmlDocDispatch( pDispatch );
  142. }
  143. if ( SUCCEEDED( hr ) )
  144. {
  145. hr = Invoke( DISPATCH_METHOD, pDispatch, name, &varResult, numParams, params );
  146. }
  147. return hr;
  148. }
  149. HRESULT PPInterface::GetProperty( CComPtr<IDispatch>& pDispatch, CString& name, COleVariant& varResult )
  150. {
  151. HRESULT hr = S_OK;
  152. if ( pDispatch == NULL )
  153. {
  154. hr = GetHtmlDocDispatch( pDispatch );
  155. }
  156. if ( SUCCEEDED( hr ) )
  157. {
  158. hr = Invoke( DISPATCH_PROPERTYGET, pDispatch, name, &varResult, 0, NULL );
  159. }
  160. return hr;
  161. }
  162. HRESULT PPInterface::SetProperty( CComPtr<IDispatch>& pDispatch, CString& name, COleVariant& varValue, COleVariant& varResult )
  163. {
  164. HRESULT hr = S_OK;
  165. if ( pDispatch == NULL )
  166. {
  167. hr = GetHtmlDocDispatch( pDispatch );
  168. }
  169. if ( SUCCEEDED( hr ) )
  170. {
  171. hr = Invoke( DISPATCH_PROPERTYPUT, pDispatch, name, &varResult, 1, &varValue );
  172. }
  173. return hr;
  174. }
  175. HRESULT PPInterface::EvalExpression( CComPtr<IDispatch>& pDispatch, CString& expression, COleVariant& varResult )
  176. {
  177. HRESULT hr = S_OK;
  178. if ( pDispatch == NULL )
  179. {
  180. hr = GetHtmlDocDispatch( pDispatch );
  181. }
  182. if ( SUCCEEDED( hr ) )
  183. {
  184. COleVariant param( expression );
  185. hr = Invoke( DISPATCH_METHOD, pDispatch, CString("eval"), &varResult, 1, &param );
  186. }
  187. return hr;
  188. }
  189. HRESULT PPInterface::P3DHasMethod( P3D_object* p3dObject, CString& name, bool& result )
  190. {
  191. if ( !p3dObject )
  192. {
  193. p3dObject = GetP3DObject( );
  194. if ( !p3dObject )
  195. {
  196. return E_FAIL;
  197. }
  198. }
  199. result = P3D_OBJECT_HAS_METHOD( p3dObject, name );
  200. return S_OK;
  201. }
  202. HRESULT PPInterface::P3DCallMethod( P3D_object* p3dObject, CString& name, DISPPARAMS FAR* pdispparams, VARIANT FAR* varResult )
  203. {
  204. if ( !p3dObject )
  205. {
  206. p3dObject = GetP3DObject( );
  207. if ( !p3dObject )
  208. {
  209. return E_FAIL;
  210. }
  211. }
  212. P3D_object** params = new P3D_object*[pdispparams->cArgs];
  213. for ( UINT i = 0; i < pdispparams->cArgs; i++ )
  214. {
  215. // Reversing the arguments!!!
  216. // http://msdn.microsoft.com/en-us/library/cc237569(PROT.10).aspx
  217. // pDispParams: MUST point to a DISPPARAMS structure that defines the arguments passed to the method.
  218. // Arguments MUST be stored in pDispParams->rgvarg in reverse order, so that the first argument is
  219. // the one with the highest index in the array. Byref arguments MUST be marked in this array
  220. // as VT_EMPTY entries, and stored in rgVarRef instead.
  221. COleVariant vaArg( pdispparams->rgvarg[pdispparams->cArgs - 1 - i] );
  222. params[i] = variant_to_p3dobj( &vaArg );
  223. }
  224. bool needResult( false );
  225. if ( varResult )
  226. {
  227. needResult = true;
  228. }
  229. P3D_object* p3dObjectResult = P3D_OBJECT_CALL( p3dObject, name, needResult, params, pdispparams->cArgs );
  230. if ( p3dObjectResult )
  231. {
  232. p3dobj_to_variant( varResult, p3dObjectResult );
  233. P3D_OBJECT_DECREF( p3dObjectResult );
  234. }
  235. for ( UINT i = 0; i < pdispparams->cArgs; i++ )
  236. {
  237. P3D_OBJECT_DECREF( params[i] );
  238. }
  239. delete [] params;
  240. return S_OK;
  241. }
  242. HRESULT PPInterface::P3DGetProperty( P3D_object* p3dObject, CString& name, VARIANT FAR* varResult )
  243. {
  244. if ( !p3dObject )
  245. {
  246. p3dObject = GetP3DObject( );
  247. if ( !p3dObject )
  248. {
  249. return E_FAIL;
  250. }
  251. }
  252. P3D_object* p3dObjectResult = P3D_OBJECT_GET_PROPERTY( p3dObject, name );
  253. if ( p3dObjectResult )
  254. {
  255. p3dobj_to_variant( varResult, p3dObjectResult );
  256. P3D_OBJECT_DECREF( p3dObjectResult );
  257. }
  258. return S_OK;
  259. }
  260. HRESULT PPInterface::P3DSetProperty( P3D_object* p3dObject, CString& name, DISPPARAMS FAR* pdispparams, bool& result )
  261. {
  262. if ( !p3dObject )
  263. {
  264. p3dObject = GetP3DObject( );
  265. if ( !p3dObject )
  266. {
  267. return E_FAIL;
  268. }
  269. }
  270. COleVariant vaArg( pdispparams->rgvarg );
  271. P3D_object* param = variant_to_p3dobj( &vaArg );
  272. result = P3D_OBJECT_SET_PROPERTY( p3dObject, name, true, param );
  273. P3D_OBJECT_DECREF( param );
  274. if (!result) {
  275. return E_FAIL;
  276. }
  277. return S_OK;
  278. }
  279. void PPInterface::p3dobj_to_variant(VARIANT* result, P3D_object* object)
  280. {
  281. if ( !result )
  282. {
  283. return;
  284. }
  285. switch ( P3D_OBJECT_GET_TYPE( object ) )
  286. {
  287. case P3D_OT_undefined:
  288. {
  289. result->vt = VT_EMPTY;
  290. break;
  291. }
  292. case P3D_OT_none:
  293. {
  294. result->vt = VT_EMPTY;
  295. break;
  296. }
  297. case P3D_OT_bool:
  298. {
  299. result->vt = VT_BOOL;
  300. result->bVal = P3D_OBJECT_GET_BOOL( object );
  301. break;
  302. }
  303. case P3D_OT_int:
  304. {
  305. result->vt = VT_I4;
  306. result->lVal = P3D_OBJECT_GET_INT( object );
  307. break;
  308. }
  309. case P3D_OT_float:
  310. {
  311. result->vt = VT_R4;
  312. result->fltVal = P3D_OBJECT_GET_FLOAT( object );
  313. break;
  314. }
  315. case P3D_OT_string:
  316. {
  317. int size = P3D_OBJECT_GET_STRING(object, NULL, 0);
  318. char *buffer = new char[ size ];
  319. P3D_OBJECT_GET_STRING(object, buffer, size);
  320. CString tmp( buffer, size );
  321. result->vt = VT_BSTR;
  322. result->bstrVal = tmp.AllocSysString();
  323. delete [] buffer;
  324. break;
  325. }
  326. case P3D_OT_object:
  327. {
  328. PPBrowserObject *ppBrowserObject = (PPBrowserObject *)object;
  329. PPandaObject* ppPandaObject = new PPandaObject( this, ppBrowserObject );
  330. result->vt = VT_DISPATCH;
  331. result->pdispVal = ppPandaObject;
  332. break;
  333. }
  334. default:
  335. {
  336. result->vt = VT_EMPTY;
  337. break;
  338. }
  339. }
  340. }
  341. P3D_object* PPInterface::variant_to_p3dobj(COleVariant* variant)
  342. {
  343. if ( !variant )
  344. {
  345. return P3D_new_none_object();
  346. }
  347. switch( variant->vt )
  348. {
  349. case VT_VOID:
  350. {
  351. return P3D_new_undefined_object();
  352. break;
  353. }
  354. case VT_EMPTY:
  355. {
  356. // return P3D_new_none_object();
  357. // A.T. Panda really expect undefined object here
  358. return P3D_new_undefined_object();
  359. break;
  360. }
  361. case VT_BOOL:
  362. {
  363. return P3D_new_bool_object( variant->bVal );
  364. break;
  365. }
  366. case VT_I2:
  367. {
  368. return P3D_new_int_object( variant->iVal );
  369. break;
  370. }
  371. case VT_I4:
  372. {
  373. return P3D_new_int_object( variant->lVal );
  374. break;
  375. }
  376. case VT_I8:
  377. {
  378. return P3D_new_int_object( variant->llVal );
  379. break;
  380. }
  381. case VT_R4:
  382. {
  383. return P3D_new_float_object( variant->fltVal );
  384. break;
  385. }
  386. case VT_R8:
  387. {
  388. return P3D_new_float_object( variant->dblVal );
  389. break;
  390. }
  391. case VT_BSTR:
  392. {
  393. CString str( *variant );
  394. return P3D_new_string_object( str.GetBuffer(), str.GetLength() );
  395. break;
  396. }
  397. case VT_DISPATCH:
  398. {
  399. // The following commented-out code crashes IE7:
  400. /*
  401. CComPtr<IDispatch> pDispObject( variant->pdispVal );
  402. CComPtr<ITypeInfo> pTypeInfo;
  403. HRESULT hr = pDispObject->GetTypeInfo( 0, 0, &pTypeInfo );
  404. if ( SUCCEEDED( hr ) && pTypeInfo )
  405. {
  406. TYPEATTR* pTypeAttr;
  407. hr = pTypeInfo->GetTypeAttr( &pTypeAttr );
  408. pTypeInfo->ReleaseTypeAttr( pTypeAttr );
  409. }
  410. */
  411. return new PPBrowserObject( this, variant->pdispVal );
  412. break;
  413. }
  414. default:
  415. {
  416. return P3D_new_undefined_object();
  417. break;
  418. }
  419. }
  420. }
  421. CString PPInterface::get_repr(COleVariant& variant)
  422. {
  423. std::strstream repr;
  424. repr << "IDispatch";
  425. switch( variant.vt )
  426. {
  427. case VT_VOID:
  428. {
  429. repr << ":VT_VOID";
  430. break;
  431. }
  432. case VT_EMPTY:
  433. {
  434. repr << ":VT_EMPTY";
  435. break;
  436. }
  437. case VT_BOOL:
  438. {
  439. repr << ":VT_BOOL:" << variant.bVal;
  440. break;
  441. }
  442. case VT_I2:
  443. {
  444. repr << ":VT_I2:" << variant.iVal;
  445. break;
  446. }
  447. case VT_I4:
  448. {
  449. repr << ":VT_I4:" << variant.lVal;
  450. break;
  451. }
  452. case VT_I8:
  453. {
  454. repr << ":VT_I8:" << variant.llVal;
  455. break;
  456. }
  457. case VT_R4:
  458. {
  459. repr << ":VT_R4:" << variant.fltVal;
  460. break;
  461. }
  462. case VT_R8:
  463. {
  464. repr << ":VT_R8:" << variant.dblVal;
  465. break;
  466. }
  467. case VT_BSTR:
  468. {
  469. CString str( variant );
  470. repr << ":VT_BSTR:" << str;
  471. break;
  472. }
  473. case VT_DISPATCH:
  474. {
  475. if ( variant.pdispVal )
  476. {
  477. CComPtr<IDispatch> pDispObject( variant.pdispVal );
  478. CComPtr<ITypeInfo> pTypeInfo;
  479. HRESULT hr = pDispObject->GetTypeInfo( 0, 0, &pTypeInfo );
  480. if ( SUCCEEDED( hr ) && pTypeInfo )
  481. {
  482. TYPEATTR* pTypeAttr;
  483. hr = pTypeInfo->GetTypeAttr( &pTypeAttr );
  484. if ( pTypeAttr )
  485. {
  486. OLECHAR szGuid[40] = { 0 };
  487. int nCount = ::StringFromGUID2( pTypeAttr->guid, szGuid, sizeof( szGuid ) );
  488. CString guid( szGuid, nCount );
  489. repr << ":VT_DISPATCH:GUID:" << guid;
  490. pTypeInfo->ReleaseTypeAttr( pTypeAttr );
  491. }
  492. else
  493. {
  494. repr << ":VT_DISPATCH:" << variant.pdispVal;
  495. }
  496. }
  497. else
  498. {
  499. repr << ":VT_DISPATCH:" << variant.pdispVal;
  500. }
  501. }
  502. else
  503. {
  504. repr << ":UNKNOWN";
  505. }
  506. break;
  507. }
  508. default:
  509. {
  510. repr << ":UNKNOWN";
  511. break;
  512. }
  513. }
  514. return CString ( repr.str(), repr.pcount() );
  515. }