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.

927 lines
30KB

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