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.

955 lines
31KB

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