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.

963 lines
31KB

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