The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

944 lines
30KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-10 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. //==============================================================================
  19. /*
  20. This file contains all the gubbins to create an ActiveX browser plugin that
  21. wraps your BrowserPluginComponent object.
  22. */
  23. //==============================================================================
  24. #if _MSC_VER
  25. //==============================================================================
  26. #include <windows.h>
  27. #include <windowsx.h>
  28. #include <olectl.h>
  29. #include <objsafe.h>
  30. #include <exdisp.h>
  31. #pragma warning (disable:4584)
  32. #include "../../../juce_amalgamated.h"
  33. #include "juce_BrowserPluginComponent.h"
  34. #include "juce_IncludeBrowserPluginInfo.h"
  35. #ifndef JuceBrowserPlugin_ActiveXCLSID
  36. #error "For an activeX plugin, you need to define JuceBrowserPlugin_ActiveXCLSID in your BrowserPluginCharacteristics.h file!"
  37. #endif
  38. //==============================================================================
  39. #if JUCE_DEBUG
  40. static int numDOWID = 0, numJuceSO = 0;
  41. #endif
  42. #define log(a) DBG(a)
  43. // Cunning trick used to add functions to export list without messing about with .def files.
  44. #define EXPORTED_FUNCTION comment(linker, "/EXPORT:" __FUNCTION__ "=" __FUNCDNAME__)
  45. //==============================================================================
  46. static void juceVarToVariant (const var& v, VARIANT& dest);
  47. static const var variantTojuceVar (const VARIANT& v);
  48. //==============================================================================
  49. // Takes care of the logic in invoking var methods from IDispatch callbacks.
  50. class IDispatchHelper
  51. {
  52. public:
  53. IDispatchHelper() {}
  54. ~IDispatchHelper() {}
  55. const String getStringFromDISPID (const DISPID hash) const
  56. {
  57. for (int i = identifierPool.size(); --i >= 0;)
  58. if (getHashFromString (identifierPool[i]) == hash)
  59. return identifierPool[i];
  60. return String::empty;
  61. }
  62. HRESULT doGetIDsOfNames (LPOLESTR* rgszNames, UINT cNames, DISPID* rgDispId)
  63. {
  64. for (unsigned int i = 0; i < cNames; ++i)
  65. rgDispId[i] = getHashFromString (identifierPool.getPooledString (String (rgszNames[i])));
  66. return S_OK;
  67. }
  68. HRESULT doInvoke (const var& v,
  69. DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams,
  70. VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
  71. {
  72. const Identifier memberId (getStringFromDISPID (dispIdMember));
  73. if (memberId.toString().isEmpty() || v.getObject() == 0)
  74. return DISP_E_MEMBERNOTFOUND;
  75. if ((wFlags & DISPATCH_METHOD) != 0)
  76. {
  77. if (! v.getObject()->hasMethod (memberId))
  78. return DISP_E_MEMBERNOTFOUND;
  79. const int numArgs = pDispParams == 0 ? 0 : pDispParams->cArgs;
  80. var result;
  81. if (numArgs == 0)
  82. {
  83. result = v.call (memberId);
  84. }
  85. else
  86. {
  87. Array<var> args;
  88. for (int j = numArgs; --j >= 0;)
  89. args.add (variantTojuceVar (pDispParams->rgvarg[j]));
  90. result = v.invoke (memberId, args.getRawDataPointer(), numArgs);
  91. }
  92. if (pVarResult != 0)
  93. juceVarToVariant (result, *pVarResult);
  94. return S_OK;
  95. }
  96. else if ((wFlags & DISPATCH_PROPERTYGET) != 0)
  97. {
  98. if (! v.getObject()->hasProperty (memberId))
  99. return DISP_E_MEMBERNOTFOUND;
  100. if (pVarResult != 0)
  101. {
  102. juceVarToVariant (v.getObject()->getProperty (memberId), *pVarResult);
  103. return S_OK;
  104. }
  105. }
  106. else if ((wFlags & DISPATCH_PROPERTYPUT) != 0)
  107. {
  108. if (pDispParams != 0 && pDispParams->cArgs > 0)
  109. {
  110. v.getObject()->setProperty (memberId, variantTojuceVar (pDispParams->rgvarg[0]));
  111. return S_OK;
  112. }
  113. }
  114. return DISP_E_MEMBERNOTFOUND;
  115. }
  116. private:
  117. StringPool identifierPool;
  118. static DISPID getHashFromString (const juce_wchar* s) throw()
  119. {
  120. return (DISPID) (pointer_sized_int) s;
  121. }
  122. IDispatchHelper (const IDispatchHelper&);
  123. IDispatchHelper& operator= (const IDispatchHelper&);
  124. };
  125. //==============================================================================
  126. // Makes a var look like an IDispatch
  127. class IDispatchWrappingDynamicObject : public IDispatch
  128. {
  129. public:
  130. IDispatchWrappingDynamicObject (const var& object_)
  131. : object (object_),
  132. refCount (1)
  133. {
  134. DBG ("num Juce wrapper objs: " + String (++numJuceSO));
  135. }
  136. virtual ~IDispatchWrappingDynamicObject()
  137. {
  138. DBG ("num Juce wrapper objs: " + String (--numJuceSO));
  139. }
  140. HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
  141. {
  142. if (id == IID_IUnknown) { AddRef(); *result = (IUnknown*) this; return S_OK; }
  143. else if (id == IID_IDispatch) { AddRef(); *result = (IDispatch*) this; return S_OK; }
  144. *result = 0;
  145. return E_NOINTERFACE;
  146. }
  147. ULONG __stdcall AddRef() { return ++refCount; }
  148. ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
  149. HRESULT __stdcall GetTypeInfoCount (UINT*) { return E_NOTIMPL; }
  150. HRESULT __stdcall GetTypeInfo (UINT, LCID, ITypeInfo**) { return E_NOTIMPL; }
  151. HRESULT __stdcall GetIDsOfNames (REFIID riid, LPOLESTR* rgszNames, UINT cNames,
  152. LCID lcid, DISPID* rgDispId)
  153. {
  154. return iDispatchHelper.doGetIDsOfNames (rgszNames, cNames, rgDispId);
  155. }
  156. HRESULT __stdcall Invoke (DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
  157. DISPPARAMS* pDispParams, VARIANT* pVarResult,
  158. EXCEPINFO* pExcepInfo, UINT* puArgErr)
  159. {
  160. return iDispatchHelper.doInvoke (object, dispIdMember, riid, lcid, wFlags, pDispParams,
  161. pVarResult, pExcepInfo, puArgErr);
  162. }
  163. private:
  164. //==============================================================================
  165. var object;
  166. int refCount;
  167. IDispatchHelper iDispatchHelper;
  168. };
  169. //==============================================================================
  170. // Makes an IDispatch look like a var
  171. class DynamicObjectWrappingIDispatch : public DynamicObject
  172. {
  173. IDispatch* const source;
  174. public:
  175. DynamicObjectWrappingIDispatch (IDispatch* const source_)
  176. : source (source_)
  177. {
  178. source->AddRef();
  179. log ("num IDispatch wrapper objs: " + String (++numDOWID));
  180. }
  181. ~DynamicObjectWrappingIDispatch()
  182. {
  183. source->Release();
  184. log ("num IDispatch wrapper objs: " + String (--numDOWID));
  185. }
  186. const var getProperty (const Identifier& propertyName) const
  187. {
  188. const String nameCopy (propertyName.toString());
  189. LPCOLESTR name = (LPCOLESTR) nameCopy;
  190. DISPID id = 0;
  191. if (source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK)
  192. {
  193. EXCEPINFO excepInfo;
  194. DISPPARAMS params;
  195. zerostruct (params);
  196. UINT argError;
  197. VARIANT result;
  198. zerostruct (result);
  199. if (source->Invoke (id, IID_NULL, 0, DISPATCH_PROPERTYGET,
  200. &params, &result, &excepInfo, &argError) == S_OK)
  201. {
  202. var v (variantTojuceVar (result));
  203. VariantClear (&result);
  204. return v;
  205. }
  206. }
  207. return var::null;
  208. }
  209. bool hasProperty (const Identifier& propertyName) const
  210. {
  211. const String nameCopy (propertyName.toString());
  212. LPCOLESTR name = (LPCOLESTR) nameCopy;
  213. DISPID id = 0;
  214. return source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK;
  215. }
  216. void setProperty (const Identifier& propertyName, const var& newValue)
  217. {
  218. const String nameCopy (propertyName.toString());
  219. LPCOLESTR name = (LPCOLESTR) nameCopy;
  220. DISPID id = 0;
  221. if (source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK)
  222. {
  223. VARIANT param;
  224. zerostruct (param);
  225. juceVarToVariant (newValue, param);
  226. DISPPARAMS dispParams;
  227. zerostruct (dispParams);
  228. dispParams.cArgs = 1;
  229. dispParams.rgvarg = &param;
  230. EXCEPINFO excepInfo;
  231. zerostruct (excepInfo);
  232. VARIANT result;
  233. zerostruct (result);
  234. UINT argError = 0;
  235. if (source->Invoke (id, IID_NULL, 0, DISPATCH_PROPERTYPUT,
  236. &dispParams, &result, &excepInfo, &argError) == S_OK)
  237. {
  238. VariantClear (&result);
  239. }
  240. VariantClear (&param);
  241. }
  242. }
  243. void removeProperty (const Identifier& propertyName)
  244. {
  245. setProperty (propertyName, var::null);
  246. }
  247. bool hasMethod (const Identifier& methodName) const
  248. {
  249. const String nameCopy (methodName.toString());
  250. LPCOLESTR name = (LPCOLESTR) nameCopy;
  251. DISPID id = 0;
  252. return source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK;
  253. }
  254. const var invokeMethod (const Identifier& methodName, const var* parameters, int numParameters)
  255. {
  256. var returnValue;
  257. const String nameCopy (methodName.toString());
  258. LPCOLESTR name = (LPCOLESTR) nameCopy;
  259. DISPID id = 0;
  260. if (source->GetIDsOfNames (IID_NULL, (LPOLESTR*) &name, 1, 0, &id) == S_OK)
  261. {
  262. HeapBlock <VARIANT> params;
  263. params.calloc (numParameters + 1);
  264. for (int i = 0; i < numParameters; ++i)
  265. juceVarToVariant (parameters[(numParameters - 1) - i], params[i]);
  266. DISPPARAMS dispParams;
  267. zerostruct (dispParams);
  268. dispParams.cArgs = numParameters;
  269. dispParams.rgvarg = params;
  270. EXCEPINFO excepInfo;
  271. zerostruct (excepInfo);
  272. VARIANT result;
  273. zerostruct (result);
  274. UINT argError = 0;
  275. if (source->Invoke (id, IID_NULL, 0, DISPATCH_METHOD,
  276. &dispParams, &result, &excepInfo, &argError) == S_OK)
  277. {
  278. returnValue = variantTojuceVar (result);
  279. VariantClear (&result);
  280. }
  281. }
  282. return returnValue;
  283. }
  284. };
  285. //==============================================================================
  286. void juceVarToVariant (const var& v, VARIANT& dest)
  287. {
  288. if (v.isVoid())
  289. {
  290. dest.vt = VT_EMPTY;
  291. }
  292. else if (v.isInt())
  293. {
  294. dest.vt = VT_INT;
  295. dest.intVal = (int) v;
  296. }
  297. else if (v.isBool())
  298. {
  299. dest.vt = VT_BOOL;
  300. dest.boolVal = (int) v;
  301. }
  302. else if (v.isDouble())
  303. {
  304. dest.vt = VT_R8;
  305. dest.dblVal = (double) v;
  306. }
  307. else if (v.isString())
  308. {
  309. dest.vt = VT_BSTR;
  310. dest.bstrVal = SysAllocString (v.toString());
  311. }
  312. else if (v.isObject())
  313. {
  314. dest.vt = VT_DISPATCH;
  315. dest.pdispVal = new IDispatchWrappingDynamicObject (v);
  316. }
  317. else if (v.isMethod())
  318. {
  319. dest.vt = VT_EMPTY;
  320. }
  321. }
  322. const var variantTojuceVar (const VARIANT& v)
  323. {
  324. if ((v.vt & VT_ARRAY) != 0)
  325. {
  326. //xxx
  327. }
  328. else
  329. {
  330. switch (v.vt & ~VT_BYREF)
  331. {
  332. case VT_VOID:
  333. case VT_EMPTY: return var::null;
  334. case VT_I1: return var ((int) v.cVal);
  335. case VT_I2: return var ((int) v.iVal);
  336. case VT_I4: return var ((int) v.lVal);
  337. case VT_I8: return var (String (v.llVal));
  338. case VT_UI1: return var ((int) v.bVal);
  339. case VT_UI2: return var ((int) v.uiVal);
  340. case VT_UI4: return var ((int) v.ulVal);
  341. case VT_UI8: return var (String (v.ullVal));
  342. case VT_INT: return var ((int) v.intVal);
  343. case VT_UINT: return var ((int) v.uintVal);
  344. case VT_R4: return var ((double) v.fltVal);
  345. case VT_R8: return var ((double) v.dblVal);
  346. case VT_BSTR: return var (v.bstrVal);
  347. case VT_BOOL: return var (v.boolVal ? true : false);
  348. case VT_DISPATCH: return var (new DynamicObjectWrappingIDispatch (v.pdispVal));
  349. default:
  350. break;
  351. }
  352. }
  353. return var::null;
  354. }
  355. //==============================================================================
  356. // This acts as the embedded HWND
  357. class AXBrowserPluginHolderComponent : public Component
  358. {
  359. public:
  360. //==============================================================================
  361. AXBrowserPluginHolderComponent()
  362. : child (0),
  363. parentHWND (0),
  364. browser (0)
  365. {
  366. setOpaque (true);
  367. setWantsKeyboardFocus (false);
  368. addAndMakeVisible (child = createBrowserPlugin());
  369. jassert (child != 0); // You have to create one of these!
  370. }
  371. ~AXBrowserPluginHolderComponent()
  372. {
  373. setWindow (0);
  374. deleteAndZero (child);
  375. }
  376. //==============================================================================
  377. void paint (Graphics& g)
  378. {
  379. if (child == 0 || ! child->isOpaque())
  380. g.fillAll (Colours::white);
  381. }
  382. void resized()
  383. {
  384. if (child != 0)
  385. child->setBounds (0, 0, getWidth(), getHeight());
  386. }
  387. const var getObject() { return child->getJavascriptObject(); }
  388. void setWindow (IOleInPlaceSite* site)
  389. {
  390. if (browser != 0)
  391. {
  392. browser->Release();
  393. browser = 0;
  394. }
  395. HWND newHWND = 0;
  396. if (site != 0)
  397. {
  398. site->GetWindow (&newHWND);
  399. IServiceProvider* sp = 0;
  400. site->QueryInterface (IID_IServiceProvider, (void**) &sp);
  401. if (sp != 0)
  402. {
  403. sp->QueryService (IID_IWebBrowserApp, IID_IWebBrowser2, (void**) &browser);
  404. sp->Release();
  405. }
  406. }
  407. if (parentHWND != newHWND)
  408. {
  409. removeFromDesktop();
  410. setVisible (false);
  411. parentHWND = newHWND;
  412. if (parentHWND != 0)
  413. {
  414. addToDesktop (0);
  415. HWND ourHWND = (HWND) getWindowHandle();
  416. SetParent (ourHWND, parentHWND);
  417. DWORD val = GetWindowLong (ourHWND, GWL_STYLE);
  418. val = (val & ~WS_POPUP) | WS_CHILD;
  419. SetWindowLong (ourHWND, GWL_STYLE, val);
  420. setVisible (true);
  421. }
  422. }
  423. if (site != 0)
  424. site->OnInPlaceActivate();
  425. }
  426. const String getBrowserURL() const
  427. {
  428. if (browser == 0)
  429. return String::empty;
  430. BSTR url = 0;
  431. browser->get_LocationURL (&url);
  432. return URL::removeEscapeChars (url);
  433. }
  434. private:
  435. //==============================================================================
  436. BrowserPluginComponent* child;
  437. HWND parentHWND;
  438. IWebBrowser2* browser;
  439. };
  440. //==============================================================================
  441. extern String browserVersionDesc;
  442. static const String getExePath()
  443. {
  444. TCHAR moduleFile [2048];
  445. moduleFile[0] = 0;
  446. GetModuleFileName (0, moduleFile, 2048);
  447. return moduleFile;
  448. }
  449. static const String getExeVersion (const String& exeFileName, const String& fieldName)
  450. {
  451. String resultString;
  452. DWORD pointlessWin32Variable;
  453. DWORD size = GetFileVersionInfoSize (exeFileName, &pointlessWin32Variable);
  454. if (size > 0)
  455. {
  456. HeapBlock <char> exeInfo;
  457. exeInfo.calloc (size);
  458. if (GetFileVersionInfo (exeFileName, 0, size, exeInfo))
  459. {
  460. TCHAR* result = 0;
  461. unsigned int resultLen = 0;
  462. // try the 1200 codepage (Unicode)
  463. String queryStr ("\\StringFileInfo\\040904B0\\" + fieldName);
  464. if (! VerQueryValue (exeInfo, (LPTSTR) (LPCTSTR) queryStr, (void**) &result, &resultLen))
  465. {
  466. // try the 1252 codepage (Windows Multilingual)
  467. queryStr = "\\StringFileInfo\\040904E4\\" + fieldName;
  468. VerQueryValue (exeInfo, (LPTSTR) (LPCTSTR) queryStr, (void**) &result, &resultLen);
  469. }
  470. resultString = String (result, resultLen);
  471. }
  472. }
  473. return resultString;
  474. }
  475. static int numActivePlugins = 0;
  476. class JuceActiveXObject : public IUnknown,
  477. public IDispatch,
  478. public IObjectWithSite,
  479. public IObjectSafety,
  480. public IOleInPlaceObject
  481. {
  482. public:
  483. JuceActiveXObject()
  484. : refCount (0)
  485. {
  486. log ("JuceActiveXObject");
  487. site = 0;
  488. holderComp = 0;
  489. }
  490. ~JuceActiveXObject()
  491. {
  492. deleteHolderComp();
  493. log ("~JuceActiveXObject");
  494. }
  495. HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
  496. {
  497. if (id == IID_IUnknown) { AddRef(); *result = (IUnknown*) this; return S_OK; }
  498. else if (id == IID_IDispatch) { AddRef(); *result = (IDispatch*) this; return S_OK; }
  499. else if (id == IID_IObjectWithSite) { AddRef(); *result = (IObjectWithSite*) this; return S_OK; }
  500. else if (id == IID_IObjectSafety) { AddRef(); *result = (IObjectSafety*) this; return S_OK; }
  501. else if (id == IID_IOleInPlaceObject) { AddRef(); *result = (IOleInPlaceObject*) this; return S_OK; }
  502. else if (id == IID_IOleWindow) { AddRef(); *result = (IOleWindow*) (IOleInPlaceObject*) this; return S_OK; }
  503. *result = 0;
  504. return E_NOINTERFACE;
  505. }
  506. ULONG __stdcall AddRef() { return ++refCount; }
  507. ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
  508. HRESULT __stdcall GetTypeInfoCount (UINT* pctinfo) { return E_NOTIMPL; }
  509. HRESULT __stdcall GetTypeInfo (UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) { return E_NOTIMPL; }
  510. HRESULT __stdcall GetIDsOfNames (REFIID riid, LPOLESTR* rgszNames, UINT cNames,
  511. LCID lcid, DISPID* rgDispId)
  512. {
  513. return iDispatchHelper.doGetIDsOfNames (rgszNames, cNames, rgDispId);
  514. }
  515. HRESULT __stdcall Invoke (DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
  516. DISPPARAMS* pDispParams, VARIANT* pVarResult,
  517. EXCEPINFO* pExcepInfo, UINT* puArgErr)
  518. {
  519. if (holderComp == 0)
  520. return DISP_E_MEMBERNOTFOUND;
  521. return iDispatchHelper.doInvoke (holderComp->getObject(),
  522. dispIdMember, riid, lcid, wFlags, pDispParams,
  523. pVarResult, pExcepInfo, puArgErr);
  524. }
  525. HRESULT __stdcall SetSite (IUnknown* newSite)
  526. {
  527. if (newSite != site)
  528. {
  529. if (site != 0)
  530. site->Release();
  531. site = newSite;
  532. if (site != 0)
  533. {
  534. site->AddRef();
  535. IOleInPlaceSite* inPlaceSite = 0;
  536. site->QueryInterface (IID_IOleInPlaceSite, (void**) &inPlaceSite);
  537. if (inPlaceSite != 0)
  538. {
  539. createHolderComp();
  540. holderComp->setWindow (inPlaceSite);
  541. inPlaceSite->Release();
  542. }
  543. else
  544. {
  545. deleteHolderComp();
  546. }
  547. }
  548. else
  549. {
  550. deleteHolderComp();
  551. }
  552. }
  553. return S_OK;
  554. }
  555. void createHolderComp()
  556. {
  557. if (numActivePlugins++ == 0)
  558. {
  559. log ("initialiseJuce_GUI()");
  560. initialiseJuce_GUI();
  561. browserVersionDesc = "Internet Explorer " + getExeVersion (getExePath(), "FileVersion");
  562. }
  563. if (holderComp == 0)
  564. holderComp = new AXBrowserPluginHolderComponent();
  565. }
  566. void deleteHolderComp()
  567. {
  568. deleteAndZero (holderComp);
  569. if (--numActivePlugins == 0)
  570. {
  571. log ("shutdownJuce_GUI()");
  572. shutdownJuce_GUI();
  573. }
  574. }
  575. HRESULT __stdcall GetSite (REFIID riid, void **ppvSite)
  576. {
  577. *ppvSite = site;
  578. return S_OK;
  579. }
  580. //==============================================================================
  581. HRESULT __stdcall SetObjectRects (LPCRECT r, LPCRECT c)
  582. {
  583. if (holderComp != 0)
  584. holderComp->setBounds (r->left, r->top, r->right - r->left, r->bottom - r->top);
  585. return S_OK;
  586. }
  587. HRESULT __stdcall GetWindow (HWND* phwnd)
  588. {
  589. if (holderComp == 0)
  590. return E_NOTIMPL;
  591. *phwnd = (HWND) holderComp->getWindowHandle();
  592. return S_OK;
  593. }
  594. //==============================================================================
  595. HRESULT __stdcall ContextSensitiveHelp (BOOL fEnterMode) { return E_NOTIMPL; }
  596. HRESULT __stdcall InPlaceDeactivate() { return E_NOTIMPL; }
  597. HRESULT __stdcall UIDeactivate() { return E_NOTIMPL; }
  598. HRESULT __stdcall ReactivateAndUndo() { return E_NOTIMPL; }
  599. //==============================================================================
  600. HRESULT __stdcall GetInterfaceSafetyOptions (REFIID riid, DWORD *pdwSupportedOptions, DWORD *pdwEnabledOptions)
  601. {
  602. *pdwSupportedOptions = *pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA;
  603. return S_OK;
  604. }
  605. HRESULT __stdcall SetInterfaceSafetyOptions (REFIID, DWORD, DWORD) { return S_OK; }
  606. private:
  607. IUnknown* site;
  608. int refCount;
  609. AXBrowserPluginHolderComponent* holderComp;
  610. IDispatchHelper iDispatchHelper;
  611. JuceActiveXObject (const JuceActiveXObject&);
  612. JuceActiveXObject& operator= (const JuceActiveXObject&);
  613. };
  614. //==============================================================================
  615. class JuceActiveXObjectFactory : public IUnknown,
  616. public IClassFactory
  617. {
  618. public:
  619. JuceActiveXObjectFactory() : refCount (0) {}
  620. ~JuceActiveXObjectFactory() {}
  621. HRESULT __stdcall QueryInterface (REFIID id, void __RPC_FAR* __RPC_FAR* result)
  622. {
  623. if (id == IID_IUnknown) { AddRef(); *result = (IUnknown*) this; return S_OK; }
  624. else if (id == IID_IClassFactory) { AddRef(); *result = (IClassFactory*) this; return S_OK; }
  625. *result = 0;
  626. return E_NOINTERFACE;
  627. }
  628. ULONG __stdcall AddRef() { return ++refCount; }
  629. ULONG __stdcall Release() { const int r = --refCount; if (r == 0) delete this; return r; }
  630. HRESULT __stdcall CreateInstance (IUnknown* pUnkOuter, REFIID riid, void** ppvObject)
  631. {
  632. *ppvObject = 0;
  633. if (pUnkOuter != 0 && riid != IID_IUnknown)
  634. return CLASS_E_NOAGGREGATION;
  635. JuceActiveXObject* ax = new JuceActiveXObject();
  636. return ax->QueryInterface (riid, ppvObject);
  637. }
  638. HRESULT __stdcall LockServer (BOOL /*fLock*/) { return S_OK; }
  639. private:
  640. int refCount;
  641. JuceActiveXObjectFactory (const JuceActiveXObjectFactory&);
  642. JuceActiveXObjectFactory& operator= (const JuceActiveXObjectFactory&);
  643. };
  644. //==============================================================================
  645. const String getActiveXBrowserURL (const BrowserPluginComponent* comp)
  646. {
  647. AXBrowserPluginHolderComponent* const ax = dynamic_cast <AXBrowserPluginHolderComponent*> (comp->getParentComponent());
  648. return ax != 0 ? ax->getBrowserURL() : String::empty;
  649. }
  650. //==============================================================================
  651. extern "C" BOOL WINAPI DllMain (HANDLE instance, DWORD reason, LPVOID)
  652. {
  653. #pragma EXPORTED_FUNCTION
  654. switch (reason)
  655. {
  656. case DLL_PROCESS_ATTACH:
  657. log ("DLL_PROCESS_ATTACH");
  658. PlatformUtilities::setCurrentModuleInstanceHandle (instance);
  659. break;
  660. case DLL_PROCESS_DETACH:
  661. log ("DLL_PROCESS_DETACH");
  662. browserVersionDesc = String::empty;
  663. // IE has a tendency to leak our objects, so although none of this should be
  664. // necessary, it's best to make sure..
  665. jassert (numActivePlugins == 0);
  666. shutdownJuce_GUI();
  667. break;
  668. default:
  669. break;
  670. }
  671. return TRUE;
  672. }
  673. static const String CLSIDToJuceString (REFCLSID clsid)
  674. {
  675. LPWSTR s = 0;
  676. StringFromIID (clsid, &s);
  677. if (s == 0)
  678. return String::empty;
  679. const String result (s);
  680. LPMALLOC malloc;
  681. CoGetMalloc (1, &malloc);
  682. if (malloc != 0)
  683. {
  684. malloc->Free (s);
  685. malloc->Release();
  686. }
  687. return result.removeCharacters ("{}").trim();
  688. }
  689. STDAPI DllGetClassObject (REFCLSID rclsid, REFIID riid, LPVOID* ppv)
  690. {
  691. #pragma EXPORTED_FUNCTION
  692. *ppv = 0;
  693. if (CLSIDToJuceString (rclsid).equalsIgnoreCase (String (JuceBrowserPlugin_ActiveXCLSID)))
  694. {
  695. JuceActiveXObjectFactory* afx = new JuceActiveXObjectFactory();
  696. if (afx->QueryInterface (riid, ppv) == S_OK)
  697. return S_OK;
  698. delete afx;
  699. }
  700. return CLASS_E_CLASSNOTAVAILABLE;
  701. }
  702. STDAPI DllCanUnloadNow()
  703. {
  704. #pragma EXPORTED_FUNCTION
  705. return S_OK;
  706. }
  707. //==============================================================================
  708. static const String makeLegalRegistryName (const String& s)
  709. {
  710. return s.retainCharacters ("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.");
  711. }
  712. static HRESULT doRegistration (const bool unregister)
  713. {
  714. const String company (makeLegalRegistryName (JuceBrowserPlugin_Company));
  715. const String plugin (makeLegalRegistryName (JuceBrowserPlugin_Name));
  716. const String clsID ("{" + String (JuceBrowserPlugin_ActiveXCLSID).toUpperCase() + "}");
  717. const String root ("HKEY_CLASSES_ROOT\\");
  718. const String companyDotPlugin (company + "." + plugin);
  719. const String companyDotPluginCur (companyDotPlugin + ".1");
  720. const String clsIDRoot (root + "CLSID\\" + clsID + "\\");
  721. const String dllPath (File::getSpecialLocation (File::currentApplicationFile).getFullPathName());
  722. StringPairArray settings;
  723. settings.set (root + companyDotPluginCur + "\\", JuceBrowserPlugin_Name);
  724. settings.set (root + companyDotPluginCur + "\\CLSID\\", clsID);
  725. settings.set (root + companyDotPlugin + "\\", JuceBrowserPlugin_Name);
  726. settings.set (root + companyDotPlugin + "\\CLSID\\", clsID);
  727. settings.set (root + companyDotPlugin + "\\CurVer\\", companyDotPluginCur);
  728. settings.set (clsIDRoot, JuceBrowserPlugin_Name);
  729. settings.set (clsIDRoot + "Implemented Categories\\{7DD95801-9882-11CF-9FA9-00AA006C42C4}\\", String::empty);
  730. settings.set (clsIDRoot + "Implemented Categories\\{7DD95802-9882-11CF-9FA9-00AA006C42C4}\\", String::empty);
  731. settings.set (clsIDRoot + "ProgID\\", companyDotPluginCur);
  732. settings.set (clsIDRoot + "VersionIndependentProgID\\", companyDotPlugin);
  733. settings.set (clsIDRoot + "Programmable\\", String::empty);
  734. settings.set (clsIDRoot + "InProcServer32\\", dllPath);
  735. settings.set (clsIDRoot + "InProcServer32\\ThreadingModel", "Apartment");
  736. settings.set (clsIDRoot + "Control\\", String::empty);
  737. settings.set (clsIDRoot + "Insertable\\", String::empty);
  738. settings.set (clsIDRoot + "ToolboxBitmap32\\", dllPath + ", 101");
  739. settings.set (clsIDRoot + "TypeLib\\", "");
  740. settings.set (clsIDRoot + "Version\\", JuceBrowserPlugin_Version);
  741. if (unregister)
  742. {
  743. for (int i = 0; i < settings.getAllKeys().size(); ++i)
  744. PlatformUtilities::deleteRegistryValue (settings.getAllKeys()[i]);
  745. PlatformUtilities::deleteRegistryKey (root + companyDotPluginCur);
  746. PlatformUtilities::deleteRegistryKey (root + companyDotPlugin);
  747. PlatformUtilities::deleteRegistryKey (clsIDRoot);
  748. if (PlatformUtilities::registryValueExists (clsIDRoot + "InProcServer32"))
  749. return SELFREG_E_CLASS;
  750. }
  751. else
  752. {
  753. PlatformUtilities::deleteRegistryKey (clsIDRoot);
  754. for (int i = 0; i < settings.getAllKeys().size(); ++i)
  755. PlatformUtilities::setRegistryValue (settings.getAllKeys()[i],
  756. settings [settings.getAllKeys()[i]]);
  757. // check whether the registration actually worked - if not, we probably don't have
  758. // enough privileges to write to the registry..
  759. if (PlatformUtilities::getRegistryValue (clsIDRoot + "InProcServer32\\") != dllPath)
  760. return SELFREG_E_CLASS;
  761. }
  762. return S_OK;
  763. }
  764. STDAPI DllRegisterServer()
  765. {
  766. #pragma EXPORTED_FUNCTION
  767. return doRegistration (false);
  768. }
  769. STDAPI DllUnregisterServer()
  770. {
  771. #pragma EXPORTED_FUNCTION
  772. return doRegistration (true);
  773. }
  774. #endif