Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / embedding / browser / activex / src / pluginhostctrl / nsPluginHostWnd.cpp
blob8d5b30fe40a229e5a48ba6964984722a0f2f5ba6
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
22 * Adam Lock <adamlock@eircom.net>
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
37 #include "stdafx.h"
39 #include "nsPluginHostWnd.h"
41 #include "nsURLDataCallback.h"
43 #include "npn.h"
45 #define NS_4XPLUGIN_CALLBACK(_type, _name) _type (__stdcall * _name)
47 typedef NS_4XPLUGIN_CALLBACK(NPError, NP_GETENTRYPOINTS) (NPPluginFuncs* pCallbacks);
48 typedef NS_4XPLUGIN_CALLBACK(NPError, NP_PLUGININIT) (const NPNetscapeFuncs* pCallbacks);
49 typedef NS_4XPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void);
51 const kArraySizeIncrement = 10;
53 nsSimpleArray<nsPluginHostWnd::LoadedPluginInfo *> nsPluginHostWnd::m_LoadedPlugins;
55 nsPluginHostWnd::nsPluginHostWnd() :
56 m_bPluginIsAlive(false),
57 m_bCreatePluginFromStreamData(false),
58 m_bPluginIsWindowless(false),
59 m_bPluginIsTransparent(false),
60 m_pLoadedPlugin(NULL),
61 m_nArgs(0),
62 m_nArgsMax(0),
63 m_pszArgNames(NULL),
64 m_pszArgValues(NULL)
66 InitPluginCallbacks();
67 memset(&m_NPPFuncs, 0, sizeof(m_NPPFuncs));
70 nsPluginHostWnd::~nsPluginHostWnd()
74 LRESULT nsPluginHostWnd::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
76 SetWindowLong(GWL_STYLE, GetWindowLong(GWL_STYLE) | WS_CLIPCHILDREN);
78 // Load a list of plugins
79 CreatePluginList(
80 PLUGINS_FROM_IE | PLUGINS_FROM_NS4X |
81 PLUGINS_FROM_FIREFOX | PLUGINS_FROM_MOZILLA);
83 HRESULT hr = E_FAIL;
84 if (m_bstrContentType.Length() == 0 &&
85 m_bstrSource.Length() != 0)
87 USES_CONVERSION;
88 // Do a late instantiation of the plugin based on the content type of
89 // the stream data.
90 m_bCreatePluginFromStreamData = true;
91 hr = OpenURLStream(OLE2T(m_bstrSource), NULL, NULL, 0);
93 else
95 // Create a plugin based upon the specified content type property
96 USES_CONVERSION;
97 hr = LoadPluginByContentType(OLE2T(m_bstrContentType));
98 if (SUCCEEDED(hr))
100 hr = CreatePluginInstance();
101 if (m_bstrSource.Length())
103 OpenURLStream(OLE2T(m_bstrSource), NULL, NULL, 0);
108 return SUCCEEDED(hr) ? 0 : -1;
111 LRESULT nsPluginHostWnd::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
113 DestroyPluginInstance();
114 UnloadPlugin();
115 CleanupPluginList();
116 return 0;
119 LRESULT nsPluginHostWnd::OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
121 SizeToFitPluginInstance();
122 return 0;
125 LRESULT nsPluginHostWnd::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
127 PAINTSTRUCT ps;
128 HDC hdc = BeginPaint(&ps);
130 RECT rc;
131 GetClientRect(&rc);
133 if (m_bPluginIsWindowless && m_NPPFuncs.event)
135 if (this->m_bPluginIsTransparent)
137 int x = 0;
138 const int inc = 20;
139 for (int i = rc.left; i < rc.right; i += inc)
141 const COLORREF c1 = RGB(255, 120, 120);
142 const COLORREF c2 = RGB(120, 120, 255);
143 RECT rcStrip = rc;
144 HBRUSH hbr = CreateSolidBrush(x % 2 ? c1 : c2);
145 rcStrip.left = i;
146 rcStrip.right = i + inc;
147 FillRect(hdc, &rcStrip, hbr);
148 DeleteObject(hbr);
149 x++;
152 else
154 FillRect(hdc, &rc, (HBRUSH) GetStockObject(GRAY_BRUSH));
157 m_NPWindow.type = NPWindowTypeDrawable;
158 m_NPWindow.window = hdc;
159 m_NPWindow.x = 0;
160 m_NPWindow.y = 0;
161 m_NPWindow.width = rc.right - rc.left;
162 m_NPWindow.height = rc.bottom - rc.top;
163 m_NPWindow.clipRect.left = 0;
164 m_NPWindow.clipRect.top = 0;
165 m_NPWindow.clipRect.right = m_NPWindow.width;
166 m_NPWindow.clipRect.bottom = m_NPWindow.height;
168 if (m_NPPFuncs.setwindow)
170 NPError npres = m_NPPFuncs.setwindow(&m_NPP, &m_NPWindow);
173 NPRect paintRect;
174 paintRect.left = rc.left;
175 paintRect.top = rc.top;
176 paintRect.right = rc.right;
177 paintRect.bottom = rc.bottom;
179 NPEvent evt;
180 evt.event = WM_PAINT;
181 evt.wParam = wParam;
182 evt.lParam = (LPARAM) &paintRect;
183 m_NPPFuncs.event(&m_NPP, &evt);
185 else
187 FillRect(hdc, &rc, (HBRUSH) GetStockObject(GRAY_BRUSH));
190 EndPaint(&ps);
192 return 0;
195 LRESULT nsPluginHostWnd::OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
197 if (m_bPluginIsWindowless && m_NPPFuncs.event)
199 NPEvent evt;
200 evt.event = uMsg;
201 evt.wParam = wParam;
202 evt.lParam = lParam;
203 m_NPPFuncs.event(&m_NPP, &evt);
205 return 0;
208 LRESULT nsPluginHostWnd::OnLButtonDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
210 if (m_bPluginIsWindowless && m_NPPFuncs.event)
212 NPEvent evt;
213 evt.event = uMsg;
214 evt.wParam = wParam;
215 evt.lParam = lParam;
216 m_NPPFuncs.event(&m_NPP, &evt);
218 return 0;
221 LRESULT nsPluginHostWnd::OnLButtonUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
223 if (m_bPluginIsWindowless && m_NPPFuncs.event)
225 NPEvent evt;
226 evt.event = uMsg;
227 evt.wParam = wParam;
228 evt.lParam = lParam;
229 m_NPPFuncs.event(&m_NPP, &evt);
231 return 0;
235 ///////////////////////////////////////////////////////////////////////////////
237 NPNetscapeFuncs nsPluginHostWnd::g_NPNFuncs;
239 HRESULT nsPluginHostWnd::InitPluginCallbacks()
241 static BOOL gCallbacksSet = FALSE;
242 if (gCallbacksSet)
244 return S_OK;
247 gCallbacksSet = TRUE;
249 memset(&g_NPNFuncs, 0, sizeof(g_NPNFuncs));
250 g_NPNFuncs.size = sizeof(g_NPNFuncs);
251 g_NPNFuncs.version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR;
253 g_NPNFuncs.geturl = NewNPN_GetURLProc(NPN_GetURL);
254 g_NPNFuncs.posturl = NewNPN_PostURLProc(NPN_PostURL);
255 g_NPNFuncs.requestread = NewNPN_RequestReadProc(NPN_RequestRead);
256 g_NPNFuncs.newstream = NewNPN_NewStreamProc(NPN_NewStream);
257 g_NPNFuncs.write = NewNPN_WriteProc(NPN_Write);
258 g_NPNFuncs.destroystream = NewNPN_DestroyStreamProc(NPN_DestroyStream);
259 g_NPNFuncs.status = NewNPN_StatusProc(NPN_Status);
260 g_NPNFuncs.uagent = NewNPN_UserAgentProc(NPN_UserAgent);
261 g_NPNFuncs.memalloc = NewNPN_MemAllocProc(NPN_MemAlloc);
262 g_NPNFuncs.memfree = NewNPN_MemFreeProc(NPN_MemFree);
263 g_NPNFuncs.memflush = NewNPN_MemFlushProc(NPN_MemFlush);
264 g_NPNFuncs.reloadplugins = NewNPN_ReloadPluginsProc(NPN_ReloadPlugins);
265 g_NPNFuncs.getJavaEnv = NewNPN_GetJavaEnvProc(NPN_GetJavaEnv);
266 g_NPNFuncs.getJavaPeer = NewNPN_GetJavaPeerProc(NPN_GetJavaPeer);
267 g_NPNFuncs.geturlnotify = NewNPN_GetURLNotifyProc(NPN_GetURLNotify);
268 g_NPNFuncs.posturlnotify = NewNPN_PostURLNotifyProc(NPN_PostURLNotify);
269 g_NPNFuncs.getvalue = NewNPN_GetValueProc(NPN_GetValue);
270 g_NPNFuncs.setvalue = NewNPN_SetValueProc(NPN_SetValue);
271 g_NPNFuncs.invalidaterect = NewNPN_InvalidateRectProc(NPN_InvalidateRect);
272 g_NPNFuncs.invalidateregion = NewNPN_InvalidateRegionProc(NPN_InvalidateRegion);
273 g_NPNFuncs.forceredraw = NewNPN_ForceRedrawProc(NPN_ForceRedraw);
275 return S_OK;
278 HRESULT nsPluginHostWnd::GetWebBrowserApp(IWebBrowserApp **pBrowser)
280 // Override this method if there is a way to get this iface
281 ATLASSERT(pBrowser);
282 if (!pBrowser)
284 return E_INVALIDARG;
286 *pBrowser = NULL;
287 return S_OK;
290 void nsPluginHostWnd::SetPluginWindowless(bool bWindowless)
292 m_bPluginIsWindowless = bWindowless;
295 void nsPluginHostWnd::SetPluginTransparent(bool bTransparent)
297 m_bPluginIsTransparent = bTransparent;
300 HRESULT nsPluginHostWnd::GetBaseURL(TCHAR **ppszBaseURL)
302 ATLASSERT(ppszBaseURL);
303 *ppszBaseURL = NULL;
305 CComPtr<IWebBrowserApp> cpWebBrowser;
306 GetWebBrowserApp(&cpWebBrowser);
307 if (!cpWebBrowser)
309 return E_FAIL;
312 USES_CONVERSION;
313 CComBSTR bstrURL;
314 cpWebBrowser->get_LocationURL(&bstrURL);
316 DWORD cbBaseURL = (bstrURL.Length() + 1) * sizeof(WCHAR);
317 DWORD cbBaseURLUsed = 0;
318 WCHAR *pszBaseURL = (WCHAR *) malloc(cbBaseURL);
319 ATLASSERT(pszBaseURL);
321 CoInternetParseUrl(
322 bstrURL.m_str,
323 PARSE_ROOTDOCUMENT,
325 pszBaseURL,
326 cbBaseURL,
327 &cbBaseURLUsed,
330 *ppszBaseURL = _tcsdup(W2T(pszBaseURL));
331 free(pszBaseURL);
333 return S_OK;
336 HRESULT nsPluginHostWnd::LoadPluginByContentType(const TCHAR *pszContentType)
338 TCHAR * pszPluginPath = NULL;
340 // Set the content type
341 USES_CONVERSION;
342 SetPluginContentType(T2OLE(pszContentType));
344 // Search for a plugin that can handle this content
345 HRESULT hr = FindPluginPathByContentType(pszContentType, &pszPluginPath);
346 if (FAILED(hr))
348 // Try the default 'catch-all' plugin
349 hr = FindPluginPathByContentType(_T("*"), &pszPluginPath);
350 if (FAILED(hr))
352 return hr;
356 hr = LoadPlugin(pszPluginPath);
357 free(pszPluginPath);
359 return hr;
364 HRESULT nsPluginHostWnd::GetPluginContentType(BSTR *pVal)
366 if (!pVal)
368 return E_INVALIDARG;
370 *pVal = m_bstrContentType.Copy();
371 return S_OK;
374 HRESULT nsPluginHostWnd::SetPluginContentType(BSTR newVal)
376 // Security. Copying the source BSTR this way ensures that embedded NULL
377 // characters do not end up in the destination BSTR. SysAllocString will
378 // create a copy truncated at the first NULL char.
379 m_bstrContentType.Empty();
380 m_bstrContentType.Attach(SysAllocString(newVal));
381 return S_OK;
384 HRESULT nsPluginHostWnd::GetPluginSource(BSTR *pVal)
386 if (!pVal)
388 return E_INVALIDARG;
390 *pVal = m_bstrSource.Copy();
391 return S_OK;
394 HRESULT nsPluginHostWnd::SetPluginSource(BSTR newVal)
396 // Security. Copying the source BSTR this way ensures that embedded NULL
397 // characters do not end up in the destination BSTR. SysAllocString will
398 // create a copy truncated at the first NULL char.
399 m_bstrSource.Empty();
400 m_bstrSource.Attach(SysAllocString(newVal));
401 return S_OK;
404 HRESULT nsPluginHostWnd::GetPluginsPage(BSTR *pVal)
406 if (!pVal)
408 return E_INVALIDARG;
410 *pVal = m_bstrPluginsPage.Copy();
411 return S_OK;
414 HRESULT nsPluginHostWnd::SetPluginsPage(BSTR newVal)
416 // Security. Copying the source BSTR this way ensures that embedded NULL
417 // characters do not end up in the destination BSTR. SysAllocString will
418 // create a copy truncated at the first NULL char.
419 m_bstrPluginsPage.Empty();
420 m_bstrPluginsPage.Attach(SysAllocString(newVal));
421 return S_OK;
424 HRESULT nsPluginHostWnd::ReadPluginsFromGeckoAppPath(const TCHAR *szAppName)
426 const TCHAR szGeneralKey[] = _T("SOFTWARE\\Mozilla\\");
427 const size_t nGeneralKeyLen = sizeof(szGeneralKey) / sizeof(TCHAR);
429 const size_t nMainKeyLen = nGeneralKeyLen + _tcslen(szAppName);
431 TCHAR *szMainKey = new TCHAR[nMainKeyLen];
432 memset(szMainKey, 0, nMainKeyLen * sizeof(TCHAR));
433 _tcscpy(szMainKey, szGeneralKey);
434 _tcscat(szMainKey, szAppName);
436 CRegKey keyGeneral;
437 if (keyGeneral.Open(HKEY_LOCAL_MACHINE, szMainKey, KEY_READ) == ERROR_SUCCESS)
439 // First find the Current Version
440 TCHAR szVersion[64];
441 const size_t nVersionLen = sizeof(szVersion) / sizeof(szVersion[0]);
442 memset(szVersion, 0, sizeof(szVersion));
444 DWORD nVersion = nVersionLen;
445 keyGeneral.QueryStringValue(_T("CurrentVersion"), szVersion, &nVersion);
446 if (nVersion > 0)
448 TCHAR *szBracket = _tcschr(szVersion, TCHAR('('));
449 if (szBracket)
451 while (szBracket >= szVersion)
453 if (*szBracket == TCHAR(' ') || *szBracket == TCHAR('('))
455 *szBracket = TCHAR('\0');
456 szBracket--;
458 else
459 break;
462 nVersion = _tcslen(szVersion);
464 TCHAR *szKey = new TCHAR[nMainKeyLen + nVersion + 32];
465 _tcscpy(szKey, szMainKey);
466 _tcscat(szKey, _T(" "));
467 _tcscat(szKey, szVersion);
468 _tcscat(szKey, _T("\\Extensions"));
470 CRegKey key;
471 if (key.Open(HKEY_LOCAL_MACHINE, szKey, KEY_READ) == ERROR_SUCCESS)
473 TCHAR szPluginsDir[_MAX_PATH];
474 memset(szPluginsDir, 0, sizeof(szPluginsDir));
475 DWORD nPluginsDir = sizeof(szPluginsDir) / sizeof(szPluginsDir[0]);
476 key.QueryStringValue(_T("Plugins"), szPluginsDir, &nPluginsDir);
477 if (szPluginsDir[0])
479 CreatePluginListFrom(szPluginsDir);
482 delete []szKey;
485 delete []szMainKey;
486 return S_OK;
489 HRESULT nsPluginHostWnd::CreatePluginList(unsigned long ulFlags)
491 // This function trawls through the plugin directory and builds a list
492 // of plugins and what MIME types each plugin handles.
494 CleanupPluginList();
496 // Firefox
497 if (ulFlags & PLUGINS_FROM_FIREFOX)
499 ReadPluginsFromGeckoAppPath(_T("Mozilla Firefox"));
502 // Mozilla
503 if (ulFlags & PLUGINS_FROM_MOZILLA)
505 ReadPluginsFromGeckoAppPath(_T("Mozilla"));
508 // Try and obtain a path to the plugins in Netscape 4.x
509 if (ulFlags & PLUGINS_FROM_NS4X)
511 TCHAR szPluginsDir[_MAX_PATH];
512 memset(szPluginsDir, 0, sizeof(szPluginsDir));
514 CRegKey keyNS;
515 const TCHAR *kNav4xKey = _T("Software\\Netscape\\Netscape Navigator");
516 if (keyNS.Open(HKEY_LOCAL_MACHINE, kNav4xKey, KEY_READ) == ERROR_SUCCESS)
518 TCHAR szVersion[10];
519 DWORD nVersion = sizeof(szVersion) / sizeof(szVersion[0]);
520 keyNS.QueryValue(szVersion, _T("CurrentVersion"), &nVersion);
522 CRegKey keyVersion;
523 if (keyVersion.Open(keyNS, szVersion, KEY_READ) == ERROR_SUCCESS)
525 CRegKey keyMain;
526 if (keyMain.Open(keyVersion, _T("Main"), KEY_READ) == ERROR_SUCCESS)
528 DWORD nPluginsDir = sizeof(szPluginsDir) / sizeof(szPluginsDir[0]);
529 keyMain.QueryValue(szPluginsDir, _T("Plugins Directory"), &nPluginsDir);
530 keyMain.Close();
532 keyVersion.Close();
534 keyNS.Close();
536 if (szPluginsDir[0])
538 CreatePluginListFrom(szPluginsDir);
542 // Try and obtain a path to the plugins in Internet Explorer
543 if (ulFlags & PLUGINS_FROM_IE)
545 TCHAR szPluginsDir[_MAX_PATH];
546 memset(szPluginsDir, 0, sizeof(szPluginsDir));
548 CRegKey keyIE;
549 const TCHAR *kIEKey = _T("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE");
550 if (keyIE.Open(HKEY_LOCAL_MACHINE, kIEKey, KEY_READ) == ERROR_SUCCESS)
552 DWORD nPluginsDir = sizeof(szPluginsDir) / sizeof(szPluginsDir[0]);
553 keyIE.QueryValue(szPluginsDir, _T("Path"), &nPluginsDir);
555 TCHAR *szSemiColon = _tcschr(szPluginsDir, _TCHAR(';'));
556 if (szSemiColon)
558 *szSemiColon = _TCHAR('\0');
561 ULONG nLen = _tcslen(szPluginsDir);
562 if (nLen > 0 && szPluginsDir[nLen - 1] == _TCHAR('\\'))
564 szPluginsDir[nLen - 1] = _TCHAR('\0');
566 _tcscat(szPluginsDir, _T("\\Plugins"));
568 keyIE.Close();
570 if (szPluginsDir[0])
572 CreatePluginListFrom(szPluginsDir);
576 return S_OK;
579 HRESULT nsPluginHostWnd::CreatePluginListFrom(const TCHAR *szPluginsDir)
581 HANDLE hFind;
582 WIN32_FIND_DATA finddata;
584 // Change to the plugin directory
585 TCHAR szCurrentDir[MAX_PATH + 1];
586 GetCurrentDirectory(sizeof(szCurrentDir) / sizeof(szCurrentDir[0]), szCurrentDir);
587 SetCurrentDirectory(szPluginsDir);
589 // Search for files matching the "np*dll" pattern
590 hFind = FindFirstFile(_T("np*dll"), &finddata);
591 if (hFind != INVALID_HANDLE_VALUE)
593 do {
594 PluginInfo *pInfo = new PluginInfo;
595 if (!pInfo)
597 CleanupPluginList();
598 SetCurrentDirectory(szCurrentDir);
599 return E_OUTOFMEMORY;
601 if (SUCCEEDED(GetPluginInfo(finddata.cFileName, pInfo)))
603 pInfo->szPluginName = _tcsdup(finddata.cFileName);
604 pInfo->szPluginPath = _tcsdup(szPluginsDir);
605 m_Plugins.AppendElement(pInfo);
607 else
609 ATLTRACE(_T("Error: Cannot plugin info for \"%s\".\n"), finddata.cFileName);
610 delete pInfo;
612 } while (FindNextFile(hFind, &finddata));
613 FindClose(hFind);
616 SetCurrentDirectory(szCurrentDir);
618 return S_OK;
622 HRESULT nsPluginHostWnd::CleanupPluginList()
624 // Free the memory used by the plugin info list
625 for (unsigned long i = 0; i < m_Plugins.Count(); i++)
627 PluginInfo *pI = m_Plugins[i];
628 if (pI->szMIMEType)
629 free(pI->szMIMEType);
630 if (pI->szPluginName)
631 free(pI->szPluginName);
632 if (pI->szPluginPath)
633 free(pI->szPluginPath);
634 free(pI);
636 m_Plugins.Empty();
637 return S_OK;
641 HRESULT nsPluginHostWnd::GetPluginInfo(const TCHAR *pszPluginPath, PluginInfo *pInfo)
643 // Get the version info from the plugin
644 USES_CONVERSION;
645 DWORD nVersionInfoSize;
646 DWORD nZero = 0;
647 void *pVersionInfo = NULL;
648 nVersionInfoSize = GetFileVersionInfoSize((TCHAR *)pszPluginPath, &nZero);
649 if (nVersionInfoSize)
651 pVersionInfo = malloc(nVersionInfoSize);
653 if (!pVersionInfo)
655 return E_OUTOFMEMORY;
658 GetFileVersionInfo((TCHAR *)pszPluginPath, NULL, nVersionInfoSize, pVersionInfo);
660 // Extract the MIMEType info
661 TCHAR *szValue = NULL;
662 UINT nValueLength = 0;
663 if (!VerQueryValue(pVersionInfo,
664 _T("\\StringFileInfo\\040904E4\\MIMEType"),
665 (void **) &szValue, &nValueLength))
667 return E_FAIL;
670 if (pInfo)
672 pInfo->szMIMEType = _tcsdup(szValue);
675 free(pVersionInfo);
677 return S_OK;
680 HRESULT nsPluginHostWnd::FindPluginPathByContentType(const TCHAR *pszContentType, TCHAR **ppszPluginPath)
682 *ppszPluginPath = NULL;
684 if (pszContentType == NULL)
686 return E_FAIL;
689 // Search the list of plugins for one that will handle the content type
690 TCHAR szPluginPath[_MAX_PATH + 1];
691 unsigned long nContentType = _tcslen(pszContentType);
692 for (unsigned long i = 0; i < m_Plugins.Count(); i++)
694 PluginInfo *pI = m_Plugins[i];
695 if (pI->szMIMEType)
697 TCHAR *pszMIMEType = pI->szMIMEType;
698 do {
699 if (_tcsncmp(pszContentType, pszMIMEType, nContentType) == 0)
701 // Found a match
702 _tmakepath(szPluginPath, NULL,
703 pI->szPluginPath, pI->szPluginName, NULL);
704 *ppszPluginPath = _tcsdup(szPluginPath);
705 return S_OK;
707 // Check the other types the plugin handles
708 pszMIMEType = _tcschr(pszMIMEType, TCHAR('|'));
709 if (pszMIMEType)
711 pszMIMEType++;
713 } while (pszMIMEType && *pszMIMEType);
717 return E_FAIL;
720 HRESULT nsPluginHostWnd::LoadPlugin(const TCHAR *szPluginPath)
722 ATLASSERT(m_pLoadedPlugin == NULL);
723 if (m_pLoadedPlugin)
725 return E_UNEXPECTED;
728 // TODO critical section
730 // Test if the plugin has already been loaded
731 for (unsigned long i = 0; i < m_LoadedPlugins.Count(); i++)
733 if (_tcscmp(m_LoadedPlugins[i]->szFullPath, szPluginPath) == 0)
735 m_pLoadedPlugin = m_LoadedPlugins[i];
736 memcpy(&m_NPPFuncs, &m_pLoadedPlugin->NPPFuncs, sizeof(m_NPPFuncs));
737 m_pLoadedPlugin->nRefCount++;
738 return S_OK;
742 // Plugin library is being loaded for the first time so initialise it
743 // and store an entry in the loaded plugins array.
745 HINSTANCE hInstance = LoadLibrary(szPluginPath);
746 if (!hInstance)
748 return E_FAIL;
751 m_pLoadedPlugin = new LoadedPluginInfo;
752 if (!m_pLoadedPlugin)
754 ATLASSERT(m_pLoadedPlugin);
755 return E_OUTOFMEMORY;
758 // Get the plugin function entry points
759 NP_GETENTRYPOINTS pfnGetEntryPoints =
760 (NP_GETENTRYPOINTS) GetProcAddress(hInstance, "NP_GetEntryPoints");
761 if (pfnGetEntryPoints)
763 pfnGetEntryPoints(&m_NPPFuncs);
766 // Tell the plugin to initialize itself
767 NP_PLUGININIT pfnInitialize = (NP_PLUGININIT)
768 GetProcAddress(hInstance, "NP_Initialize");
769 if (!pfnInitialize)
771 pfnInitialize = (NP_PLUGININIT)
772 GetProcAddress(hInstance, "NP_PluginInit");
774 if (pfnInitialize)
776 pfnInitialize(&g_NPNFuncs);
779 // Create a new entry for the plugin
780 m_pLoadedPlugin->szFullPath = _tcsdup(szPluginPath);
781 m_pLoadedPlugin->nRefCount = 1;
782 m_pLoadedPlugin->hInstance = hInstance;
783 memcpy(&m_pLoadedPlugin->NPPFuncs, &m_NPPFuncs, sizeof(m_NPPFuncs));
785 // Add it to the array
786 m_LoadedPlugins.AppendElement(m_pLoadedPlugin);
788 return S_OK;
791 HRESULT nsPluginHostWnd::UnloadPlugin()
793 if (!m_pLoadedPlugin)
795 return E_FAIL;
798 // TODO critical section
800 ATLASSERT(m_pLoadedPlugin->nRefCount > 0);
801 if (m_pLoadedPlugin->nRefCount == 1)
803 NP_PLUGINSHUTDOWN pfnShutdown = (NP_PLUGINSHUTDOWN)
804 GetProcAddress(
805 m_pLoadedPlugin->hInstance,
806 "NP_Shutdown");
807 if (pfnShutdown)
809 pfnShutdown();
811 FreeLibrary(m_pLoadedPlugin->hInstance);
813 // Delete the entry from the array
814 m_LoadedPlugins.RemoveElement(m_pLoadedPlugin);
815 free(m_pLoadedPlugin->szFullPath);
816 delete m_pLoadedPlugin;
818 else
820 m_pLoadedPlugin->nRefCount--;
823 m_pLoadedPlugin = NULL;
825 return S_OK;
829 HRESULT nsPluginHostWnd::AddPluginParam(const char *szName, const char *szValue)
831 ATLASSERT(szName);
832 ATLASSERT(szValue);
833 if (!szName || !szValue)
835 return E_INVALIDARG;
838 // Skip params that already there
839 for (unsigned long i = 0; i < m_nArgs; i++)
841 if (stricmp(szName, m_pszArgNames[i]) == 0)
843 return S_OK;
847 // Add the value
848 if (!m_pszArgNames)
850 ATLASSERT(!m_pszArgValues);
851 m_nArgsMax = kArraySizeIncrement;
852 m_pszArgNames = (char **) malloc(sizeof(char *) * m_nArgsMax);
853 m_pszArgValues = (char **) malloc(sizeof(char *) * m_nArgsMax);
855 else if (m_nArgs == m_nArgsMax)
857 m_nArgsMax += kArraySizeIncrement;
858 m_pszArgNames = (char **) realloc(m_pszArgNames, sizeof(char *) * m_nArgsMax);
859 m_pszArgValues = (char **) realloc(m_pszArgValues, sizeof(char *) * m_nArgsMax);
861 if (!m_pszArgNames || !m_pszArgValues)
863 return E_OUTOFMEMORY;
866 m_pszArgNames[m_nArgs] = strdup(szName);
867 m_pszArgValues[m_nArgs] = strdup(szValue);
869 m_nArgs++;
871 return S_OK;
875 HRESULT nsPluginHostWnd::CreatePluginInstance()
877 m_NPP.pdata = NULL;
878 m_NPP.ndata = this;
880 USES_CONVERSION;
881 char *szContentType = strdup(OLE2A(m_bstrContentType.m_str));
883 // Create a child window to house the plugin
884 RECT rc;
885 GetClientRect(&rc);
886 // m_wndPlugin.Create(m_hWnd, rc, NULL, WS_CHILD | WS_VISIBLE);
888 // m_NPWindow.window = (void *) m_wndPlugin.m_hWnd;
889 m_NPWindow.window = (void *) m_hWnd;
890 m_NPWindow.type = NPWindowTypeWindow;
892 if (m_NPPFuncs.newp)
894 // Create the arguments to be fed into the plugin
895 if (m_bstrSource.m_str)
897 AddPluginParam("SRC", OLE2A(m_bstrSource.m_str));
899 if (m_bstrContentType.m_str)
901 AddPluginParam("TYPE", OLE2A(m_bstrContentType.m_str));
903 if (m_bstrPluginsPage.m_str)
905 AddPluginParam("PLUGINSPAGE", OLE2A(m_bstrPluginsPage.m_str));
907 char szTmp[50];
908 sprintf(szTmp, "%d", (int) (rc.right - rc.left));
909 AddPluginParam("WIDTH", szTmp);
910 sprintf(szTmp, "%d", (int) (rc.bottom - rc.top));
911 AddPluginParam("HEIGHT", szTmp);
913 NPSavedData *pSaved = NULL;
915 // Create the plugin instance
916 NPError npres = m_NPPFuncs.newp(szContentType, &m_NPP, NP_EMBED,
917 (short) m_nArgs, m_pszArgNames, m_pszArgValues, pSaved);
919 if (npres != NPERR_NO_ERROR)
921 return E_FAIL;
925 m_bPluginIsAlive = true;
927 SizeToFitPluginInstance();
929 return S_OK;
932 HRESULT nsPluginHostWnd::DestroyPluginInstance()
934 if (!m_bPluginIsAlive)
936 return S_OK;
939 // Destroy the plugin
940 if (m_NPPFuncs.destroy)
942 NPSavedData *pSavedData = NULL;
943 NPError npres = m_NPPFuncs.destroy(&m_NPP, &pSavedData);
945 // TODO could store saved data instead of just deleting it.
946 if (pSavedData && pSavedData->buf)
948 NPN_MemFree(pSavedData->buf);
952 // Destroy the arguments
953 if (m_pszArgNames)
955 for (unsigned long i = 0; i < m_nArgs; i++)
957 free(m_pszArgNames[i]);
959 free(m_pszArgNames);
960 m_pszArgNames = NULL;
962 if (m_pszArgValues)
964 for (unsigned long i = 0; i < m_nArgs; i++)
966 free(m_pszArgValues[i]);
968 free(m_pszArgValues);
969 m_pszArgValues = NULL;
972 //m_wndPlugin.DestroyWindow();
974 m_bPluginIsAlive = false;
976 return S_OK;
979 HRESULT nsPluginHostWnd::SizeToFitPluginInstance()
981 if (!m_bPluginIsAlive)
983 return S_OK;
986 // Resize the plugin to fit the window
988 RECT rc;
989 GetClientRect(&rc);
991 //m_wndPlugin.SetWindowPos(HWND_TOP,
992 // rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top,
993 // SWP_NOZORDER);
995 m_NPWindow.x = 0;
996 m_NPWindow.y = 0;
997 m_NPWindow.width = rc.right - rc.left;
998 m_NPWindow.height = rc.bottom - rc.top;
999 m_NPWindow.clipRect.left = 0;
1000 m_NPWindow.clipRect.top = 0;
1001 m_NPWindow.clipRect.right = m_NPWindow.width;
1002 m_NPWindow.clipRect.bottom = m_NPWindow.height;
1004 if (m_NPPFuncs.setwindow)
1006 NPError npres = m_NPPFuncs.setwindow(&m_NPP, &m_NPWindow);
1009 return S_OK;
1012 HRESULT nsPluginHostWnd::OpenURLStream(const TCHAR *szURL, void *pNotifyData, const void *pPostData, unsigned long nPostDataLength)
1014 nsURLDataCallback::OpenURL(this, szURL, pNotifyData, pPostData, nPostDataLength);
1015 return S_OK;