// MccPluginHostCtrl.cpp : CMccPluginHostCtrl のインプリメンテーション #include "stdafx.h" #include "MccPlugin.h" #include "MccPluginHostCtrl.h" #include "nsURLDataCallback.h" #include "npn.h" #define NS_4XPLUGIN_CALLBACK(_type, _name) _type (__stdcall * _name) typedef NS_4XPLUGIN_CALLBACK(NPError, NP_GETENTRYPOINTS) (NPPluginFuncs* pCallbacks); typedef NS_4XPLUGIN_CALLBACK(NPError, NP_PLUGININIT) (const NPNetscapeFuncs* pCallbacks); typedef NS_4XPLUGIN_CALLBACK(NPError, NP_PLUGINSHUTDOWN) (void); const kArraySizeIncrement = 10; nsSimpleArray CMccPluginHostCtrl::m_LoadedPlugins; #define PLG_VERSION_MAJOR 0 #define PLG_VERSION_MINOR 11 NPNetscapeFuncs g_nfuncs; void* Rrr_MemAlloc(uint32 size) { void *m; m=malloc(size); ATLTRACE("Rrr_MemAlloc address:%lx size:%ld\n",m,size); return m; } void Rrr_MemFree(void* ptr) { ATLTRACE("Rrr_MemFree address:%ld\n",ptr); free(ptr); } const char* Rrr_UserAgent(NPP instance) { ATLTRACE("Rrr_UserAgent\n"); return "Microsoft Internet Explorer"; } NPError Rrr_GetURL(NPP instance, const char* url, const char* target) { ATLTRACE("Rrr_GetURL\n"); /* CMccPluginHostCtrl *ctrl; ctrl= (CMccPluginHostCtrl*)(instance->ndata); WCHAR wurl[520], wtgt[110]; MultiByteToWideChar(CP_ACP,0,url ,-1,wurl,512); MultiByteToWideChar(CP_ACP,0,target,-1,wtgt,100); HlinkSimpleNavigateToString( wurl, NULL, wtgt , ctrl->punkMe, NULL, NULL, HLNF_INTERNALJUMP, 0);*/ return NPERR_NO_ERROR; } NPError Rrr_PostURL(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file) { ATLTRACE("Rrr_PostURL\n"); /* CMccPluginHostCtrl *ctrl; ctrl= (CMccPluginHostCtrl*)(instance->ndata); ctrl->DisplayMsg(MSG_E,"NPN_PostURL not implemented [%s,%s]",url,window);*/ return NPERR_GENERIC_ERROR; } NPError Rrr_RequestRead(NPStream* stream, NPByteRange* rangeList) { ATLTRACE("Rrr_RequestRead\n"); /* CMccPluginHostCtrl *ctrl; ctrl= (CMccPluginHostCtrl*)(stream->ndata); ctrl->DisplayMsg(MSG_E,"NPN_RequestRead not implemented");*/ return NPERR_GENERIC_ERROR; } NPError Rrr_NewStream(NPP instance, NPMIMEType type, const char* window, NPStream** stream) { ATLTRACE("Rrr_NewStream\n"); /* CMccPluginHostCtrl *ctrl; ctrl= (CMccPluginHostCtrl*)(instance->ndata); ctrl->DisplayMsg(MSG_E,"NPN_NewStream not implemented");*/ return NPERR_GENERIC_ERROR; } int32 Rrr_Write(NPP instance, NPStream* stream, int32 len, void* buffer) { ATLTRACE("Rrr_Write\n"); /* CMccPluginHostCtrl *ctrl; ctrl= (CMccPluginHostCtrl*)(instance->ndata); ctrl->DisplayMsg(MSG_E,"NPN_Write not implemented");*/ return (int32)0; } NPError Rrr_DestroyStream(NPP instance, NPStream* stream, NPReason reason) { ATLTRACE("Rrr_DestroyStream\n"); /* CMccPluginHostCtrl *ctrl; ctrl= (CMccPluginHostCtrl*)(instance->ndata); ctrl->DisplayMsg(MSG_E,"NPN_DestroyStream not implemented");*/ return NPERR_GENERIC_ERROR; } void Rrr_Status(NPP instance, const char* message) { ATLTRACE("Rrr_Status\n"); // fixme - set statusbar to return; } uint32 Rrr_MemFlush(uint32 size) { ATLTRACE("Rrr_MemFlush\n"); return (uint32)0; } void Rrr_ReloadPlugins(NPBool reloadPages) { ATLTRACE("Rrr_ReloadPlugins\n"); return; } JRIEnv* Rrr_GetJavaEnv(void) { ATLTRACE("Rrr_GetJavaEnv\n"); return NULL; } jref Rrr_GetJavaPeer(NPP instance) { ATLTRACE("Rrr_GetJavaPeer\n"); return NULL; } NPError Rrr_GetURLNotify(NPP instance, const char* url, const char* window, void* notifyData) { ATLTRACE("Rrr_GetURLNotify\n"); /* CMccPluginHostCtrl *ctrl; ctrl= (CMccPluginHostCtrl*)(instance->ndata); ctrl->DisplayMsg(MSG_E,"NPN_GetURLNotify not implemented");*/ return NPERR_GENERIC_ERROR; } NPError Rrr_PostURLNotify(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file, void* notifyData) { ATLTRACE("Rrr_PostURLNotify\n"); /* CMccPluginHostCtrl *ctrl; ctrl= (CMccPluginHostCtrl*)(instance->ndata); ctrl->DisplayMsg(MSG_E,"NPN_PostURLNotify not implemented");*/ return NPERR_GENERIC_ERROR; } NPError Rrr_GetValue(NPP instance, NPNVariable variable, void *ret_value) { ATLTRACE("Rrr_GetValue\n"); /* int a; char **s; s=(char**)ret_value; a=(int)variable; switch(a) { case 30000: (*s) = replug_versionstring; return NPERR_NO_ERROR; } */ return NPERR_GENERIC_ERROR; } NPError Rrr_SetValue(NPP instance, NPPVariable variable, void *value) { ATLTRACE("Rrr_SetValue\n"); return NPERR_GENERIC_ERROR; } void Rrr_InvalidateRect(NPP instance, NPRect *rect) { ATLTRACE("Rrr_InvalidateRect\n"); return; } void Rrr_InvalidateRegion(NPP instance, NPRegion region) { ATLTRACE("Rrr_InvalidateRegion\n"); return; } void Rrr_ForceRedraw(NPP instance) { ATLTRACE("Rrr_ForceRedraw\n"); return; } // called by DllMain when control is loaded void replug_init(void) { ATLTRACE("replug_init()\n"); // fill in NPN function pointers g_nfuncs.size= sizeof(g_nfuncs); g_nfuncs.version= (PLG_VERSION_MAJOR << 8) | PLG_VERSION_MINOR; g_nfuncs.geturl= Rrr_GetURL; g_nfuncs.posturl= Rrr_PostURL; g_nfuncs.requestread= Rrr_RequestRead; g_nfuncs.newstream= Rrr_NewStream; g_nfuncs.write= Rrr_Write; g_nfuncs.destroystream= Rrr_DestroyStream; g_nfuncs.status= Rrr_Status; g_nfuncs.uagent= Rrr_UserAgent; g_nfuncs.memalloc= Rrr_MemAlloc; g_nfuncs.memfree= Rrr_MemFree; g_nfuncs.memflush= Rrr_MemFlush; g_nfuncs.reloadplugins= Rrr_ReloadPlugins; g_nfuncs.getJavaEnv= Rrr_GetJavaEnv; g_nfuncs.getJavaPeer= Rrr_GetJavaPeer; g_nfuncs.geturlnotify= Rrr_GetURLNotify; g_nfuncs.posturlnotify= Rrr_PostURLNotify; g_nfuncs.getvalue= Rrr_GetValue; g_nfuncs.setvalue= Rrr_SetValue; g_nfuncs.invalidaterect= Rrr_InvalidateRect; g_nfuncs.invalidateregion= Rrr_InvalidateRegion; g_nfuncs.forceredraw= Rrr_ForceRedraw; } ///////////////////////////////////////////////////////////////////////////// // CMccPluginHostCtrl CMccPluginHostCtrl::CMccPluginHostCtrl() { ATLTRACE("CMccPluginHostCtrl::CMccPluginHostCtrl()\n"); m_bWindowOnly = TRUE; m_bPluginIsAlive = FALSE; m_bCreatePluginFromStreamData = FALSE; m_pLoadedPlugin = NULL; m_nArgs = 0; m_nArgsMax = 0; m_pszArgNames = NULL; m_pszArgValues = NULL; replug_init(); memset(&m_NPPFuncs, 0, sizeof(m_NPPFuncs)); } CMccPluginHostCtrl::~CMccPluginHostCtrl() { } LPTSTR URLHostAddressAdd(LPTSTR hostAddress,LPTSTR URL) { char hostAddressWK[512]; char URLWK[512]; static char mkBuff[512]; char *p; LPSTR retPoint; retPoint = URL; strcpy(hostAddressWK,hostAddress); strcpy(URLWK,_strlwr(URL)); memset(mkBuff,0,sizeof(mkBuff)); if ((p = strstr(URLWK,"//")) != 0) { return NULL; } if ((p = strstr(URLWK,"iviewav")) != 0) { strcat(mkBuff,hostAddressWK); strcat(mkBuff,p-1); retPoint = (LPTSTR)mkBuff; } else if ((p = strstr(URLWK,"iviewisa")) != 0) { strcat(mkBuff,hostAddressWK); strcat(mkBuff,p-1); retPoint = (LPTSTR)mkBuff; } else if ((p = strstr(URLWK,"almlist")) != 0) { strcat(mkBuff,hostAddressWK); strcat(mkBuff,p-1); retPoint = (LPTSTR)mkBuff; } return retPoint; } LRESULT CMccPluginHostCtrl::OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { ATLTRACE("CMccPluginHostCtrl::OnCreate()\n"); LPTSTR URLTEMP; LPTSTR FULLURL; SetWindowLong(GWL_STYLE, GetWindowLong(GWL_STYLE) | WS_CLIPCHILDREN); // Load a list of plugins CreatePluginList( PLUGINS_FROM_IE | PLUGINS_FROM_NS4X | PLUGINS_FROM_NS6X | PLUGINS_FROM_MOZILLA); HRESULT hr = E_FAIL; if (m_bstrContentType.Length() == 0 && m_bstrSource.Length() != 0) { USES_CONVERSION; // Do a late instantiation of the plugin based on the content type of // the stream data. m_bCreatePluginFromStreamData = TRUE; GetBaseURL(&URLTEMP); FULLURL = URLHostAddressAdd(URLTEMP,OLE2T(m_bstrSource)); if (FULLURL) { m_bstrSource = FULLURL; } hr = OpenURLStream(OLE2T(m_bstrSource), NULL, NULL, 0); } else { // Create a plugin based upon the specified content type property USES_CONVERSION; hr = LoadPluginByContentType(OLE2T(m_bstrContentType)); if (SUCCEEDED(hr)) { GetBaseURL(&URLTEMP); FULLURL = URLHostAddressAdd(URLTEMP,OLE2T(m_bstrSource)); if (FULLURL) { m_bstrSource = FULLURL; } hr = CreatePluginInstance(); if (m_bstrSource.Length()) { OpenURLStream(OLE2T(m_bstrSource), NULL, NULL, 0); } } } return SUCCEEDED(hr) ? 0 : -1; } LRESULT CMccPluginHostCtrl::OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { ATLTRACE(_T("-- CMccPluginHostCtrl::OnDestroy() start------------------------\n")); DestroyPluginInstance(); UnloadPlugin(); CleanupPluginList(); ATLTRACE(_T("-- CMccPluginHostCtrl::OnDestroy() end ------------------------\n")); return 0; } LRESULT CMccPluginHostCtrl::OnSize(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) { SizeToFitPluginInstance(); return 0; } LRESULT CMccPluginHostCtrl::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) { PAINTSTRUCT ps; HDC hdc; RECT rc; hdc = BeginPaint(&ps); GetClientRect(&rc); FillRect(hdc, &rc, (HBRUSH) GetStockObject(GRAY_BRUSH)); EndPaint(&ps); return 0; } HRESULT CMccPluginHostCtrl::GetWebBrowserApp(IWebBrowserApp **pBrowser) { ATLTRACE("CMccPluginHostCtrl::GetWebBrowserApp()\n"); ATLASSERT(pBrowser); if (!pBrowser) { return E_INVALIDARG; } // Get the web browser through the site the control is attached to. // Note: The control could be running in some other container than IE // so code shouldn't expect this function to work all the time. CComPtr cpWebBrowser; CComQIPtr cpServiceProvider = m_spClientSite; HRESULT hr; if (cpServiceProvider) { hr = cpServiceProvider->QueryService(IID_IWebBrowserApp, &cpWebBrowser); } if (!cpWebBrowser) { return E_FAIL; } *pBrowser = cpWebBrowser; (*pBrowser)->AddRef(); return S_OK; } HRESULT CMccPluginHostCtrl::GetBaseURL(TCHAR **ppszBaseURL) { ATLTRACE("CMccPluginHostCtrl::GetBaseURL()\n"); ATLASSERT(ppszBaseURL); *ppszBaseURL = NULL; CComPtr cpWebBrowser; GetWebBrowserApp(&cpWebBrowser); if (!cpWebBrowser) { return E_FAIL; } USES_CONVERSION; CComBSTR bstrURL; cpWebBrowser->get_LocationURL(&bstrURL); DWORD cbBaseURL = (bstrURL.Length() + 1) * sizeof(WCHAR); DWORD cbBaseURLUsed = 0; WCHAR *pszBaseURL = (WCHAR *) malloc(cbBaseURL); ATLASSERT(pszBaseURL); CoInternetParseUrl( bstrURL.m_str, PARSE_ROOTDOCUMENT, 0, pszBaseURL, cbBaseURL, &cbBaseURLUsed, 0); *ppszBaseURL = _tcsdup(W2T(pszBaseURL)); free(pszBaseURL); return S_OK; } HRESULT CMccPluginHostCtrl::LoadPluginByContentType(const TCHAR *pszContentType) { ATLTRACE("CMccPluginHostCtrl::LoadPluginByContentType()\n"); TCHAR * pszPluginPath = NULL; // Set the content type USES_CONVERSION; put_PluginContentType(T2OLE(pszContentType)); // Search for a plugin that can handle this content HRESULT hr = FindPluginPathByContentType(pszContentType, &pszPluginPath); if (FAILED(hr)) { // Try the default 'catch-all' plugin hr = FindPluginPathByContentType(_T("*"), &pszPluginPath); if (FAILED(hr)) { return hr; } } hr = LoadPlugin(pszPluginPath); free(pszPluginPath); return hr; } HRESULT CMccPluginHostCtrl::CreatePluginList(unsigned long ulFlags) { ATLTRACE("CMccPluginHostCtrl::CreatePluginList()\n"); // This function trawls through the plugin directory and builds a list // of plugins and what MIME types each plugin handles. CleanupPluginList(); // Try and obtain a path to the plugins in Netscape 6.x or Mozilla if (ulFlags & PLUGINS_FROM_NS6X || ulFlags & PLUGINS_FROM_MOZILLA) { // TODO search for Mozilla/NS 6.x plugins dir } // Try and obtain a path to the plugins in Netscape 4.x if (ulFlags & PLUGINS_FROM_NS4X) { TCHAR szPluginsDir[_MAX_PATH]; memset(szPluginsDir, 0, sizeof(szPluginsDir)); CRegKey keyNS; const TCHAR *kNav4xKey = _T("Software\\Netscape\\Netscape Navigator"); if (keyNS.Open(HKEY_LOCAL_MACHINE, kNav4xKey, KEY_READ) == ERROR_SUCCESS) { TCHAR szVersion[10]; DWORD nVersion = sizeof(szVersion) / sizeof(szVersion[0]); keyNS.QueryValue(szVersion, _T("CurrentVersion"), &nVersion); CRegKey keyVersion; if (keyVersion.Open(keyNS, szVersion, KEY_READ) == ERROR_SUCCESS) { CRegKey keyMain; if (keyMain.Open(keyVersion, _T("Main"), KEY_READ) == ERROR_SUCCESS) { DWORD nPluginsDir = sizeof(szPluginsDir) / sizeof(szPluginsDir[0]); keyMain.QueryValue(szPluginsDir, _T("Plugins Directory"), &nPluginsDir); keyMain.Close(); } keyVersion.Close(); } keyNS.Close(); } if (szPluginsDir[0]) { CreatePluginListFrom(szPluginsDir); } } // Try and obtain a path to the plugins in Internet Explorer if (ulFlags & PLUGINS_FROM_IE) { TCHAR szPluginsDir[_MAX_PATH]; memset(szPluginsDir, 0, sizeof(szPluginsDir)); CRegKey keyIE; const TCHAR *kIEKey = _T("Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\IEXPLORE.EXE"); if (keyIE.Open(HKEY_LOCAL_MACHINE, kIEKey, KEY_READ) == ERROR_SUCCESS) { DWORD nPluginsDir = sizeof(szPluginsDir) / sizeof(szPluginsDir[0]); keyIE.QueryValue(szPluginsDir, _T("Path"), &nPluginsDir); TCHAR *szSemiColon = _tcschr(szPluginsDir, _TCHAR(';')); if (szSemiColon) { *szSemiColon = _TCHAR('\0'); } ULONG nLen = _tcslen(szPluginsDir); if (nLen > 0 && szPluginsDir[nLen - 1] == _TCHAR('\\')) { szPluginsDir[nLen - 1] = _TCHAR('\0'); } _tcscat(szPluginsDir, _T("\\Plugins")); keyIE.Close(); } if (szPluginsDir[0]) { CreatePluginListFrom(szPluginsDir); } } return S_OK; } HRESULT CMccPluginHostCtrl::CreatePluginListFrom(const TCHAR *szPluginsDir) { ATLTRACE("CMccPluginHostCtrl::CreatePluginListFrom()\n"); HANDLE hFind; WIN32_FIND_DATA finddata; // Change to the plugin directory TCHAR szCurrentDir[MAX_PATH + 1]; GetCurrentDirectory(sizeof(szCurrentDir) / sizeof(szCurrentDir[0]), szCurrentDir); SetCurrentDirectory(szPluginsDir); // Search for files matching the "np*dll" pattern hFind = FindFirstFile(_T("np*dll"), &finddata); if (hFind != INVALID_HANDLE_VALUE) { do { PluginInfo *pInfo = new PluginInfo; if (!pInfo) { CleanupPluginList(); SetCurrentDirectory(szCurrentDir); return E_OUTOFMEMORY; } if (SUCCEEDED(GetPluginInfo(finddata.cFileName, pInfo))) { pInfo->szPluginName = _tcsdup(finddata.cFileName); pInfo->szPluginPath = _tcsdup(szPluginsDir); m_Plugins.AppendElement(pInfo); } else { ATLTRACE(_T("Error: Cannot plugin info for \"%s\".\n"), finddata.cFileName); delete pInfo; } } while (FindNextFile(hFind, &finddata)); FindClose(hFind); } SetCurrentDirectory(szCurrentDir); return S_OK; } HRESULT CMccPluginHostCtrl::CleanupPluginList() { ATLTRACE("CMccPluginHostCtrl::CleanupPluginList()\n"); // Free the memory used by the plugin info list for (unsigned long i = 0; i < m_Plugins.Count(); i++) { PluginInfo *pI = m_Plugins[i]; if (pI->szMIMEType) free(pI->szMIMEType); if (pI->szPluginName) free(pI->szPluginName); if (pI->szPluginPath) free(pI->szPluginPath); free(pI); } m_Plugins.Empty(); return S_OK; } HRESULT CMccPluginHostCtrl::GetPluginInfo(const TCHAR *pszPluginPath, PluginInfo *pInfo) { ATLTRACE("CMccPluginHostCtrl::GetPluginInfo()\n"); // Get the version info from the plugin USES_CONVERSION; DWORD nVersionInfoSize; DWORD nZero = 0; void *pVersionInfo = NULL; nVersionInfoSize = GetFileVersionInfoSize((TCHAR *)pszPluginPath, &nZero); if (nVersionInfoSize) { pVersionInfo = malloc(nVersionInfoSize); } if (!pVersionInfo) { return E_OUTOFMEMORY; } GetFileVersionInfo((TCHAR *)pszPluginPath, NULL, nVersionInfoSize, pVersionInfo); // Extract the MIMEType info TCHAR *szValue = NULL; UINT nValueLength = 0; if (!VerQueryValue(pVersionInfo, _T("\\StringFileInfo\\040904E4\\MIMEType"), (void **) &szValue, &nValueLength)) { return E_FAIL; } // m_bstrContentType is "text/html" when RVC data is protected. // so Nprvc32.dll need to support this type also. if (!_tcscmp(szValue,_T("video/x-rvc"))) { _tcsncat(szValue, _T("|text/html"), _tcslen(_T("|text/html"))); } if (pInfo) { pInfo->szMIMEType = _tcsdup(szValue); } free(pVersionInfo); return S_OK; } HRESULT CMccPluginHostCtrl::FindPluginPathByContentType(const TCHAR *pszContentType, TCHAR **ppszPluginPath) { ATLTRACE("CMccPluginHostCtrl::FindPluginPathByContentType()\n"); *ppszPluginPath = NULL; if (pszContentType == NULL) { return E_FAIL; } // Search the list of plugins for one that will handle the content type TCHAR szPluginPath[_MAX_PATH + 1]; unsigned long nContentType = _tcslen(pszContentType); for (unsigned long i = 0; i < m_Plugins.Count(); i++) { PluginInfo *pI = m_Plugins[i]; if (pI->szMIMEType) { TCHAR *pszMIMEType = pI->szMIMEType; do { if (_tcsncmp(pszContentType, pszMIMEType, nContentType) == 0) { // Found a match _tmakepath(szPluginPath, NULL, pI->szPluginPath, pI->szPluginName, NULL); *ppszPluginPath = _tcsdup(szPluginPath); return S_OK; } // Check the other types the plugin handles pszMIMEType = _tcschr(pszMIMEType, TCHAR('|')); if (pszMIMEType) { pszMIMEType++; } } while (pszMIMEType && *pszMIMEType); } } return E_FAIL; } // Given a filename with a full path, CD to its directory. void ChangeToDirectoryOf(const TCHAR *fn) { int p,i; char d[MAX_PATH]; strcpy(d,fn); p=0; for(i=0;d[i];i++) { // find last '\' if(d[i]=='\\') p=i; } if(p<1) return; d[p]='\0'; SetCurrentDirectory(d); } HRESULT CMccPluginHostCtrl::LoadPlugin(const TCHAR *szPluginPath) { ATLTRACE("CMccPluginHostCtrl::LoadPlugin()\n"); NPError err; ATLASSERT(m_pLoadedPlugin == NULL); if (m_pLoadedPlugin) { return E_UNEXPECTED; } // TODO critical section // Test if the plugin has already been loaded for (unsigned long i = 0; i < m_LoadedPlugins.Count(); i++) { if (_tcscmp(m_LoadedPlugins[i]->szFullPath, szPluginPath) == 0) { m_pLoadedPlugin = m_LoadedPlugins[i]; memcpy(&m_NPPFuncs, &m_pLoadedPlugin->NPPFuncs, sizeof(m_NPPFuncs)); m_pLoadedPlugin->nRefCount++; return S_OK; } } // Plugin library is being loaded for the first time so initialise it // and store an entry in the loaded plugins array. ::ChangeToDirectoryOf(szPluginPath); // Guard from freeze Sleep(100); HINSTANCE hInstance=LoadLibrary(szPluginPath); if(!hInstance) { return E_FAIL; } m_pLoadedPlugin = new LoadedPluginInfo; if (!m_pLoadedPlugin) { ATLASSERT(m_pLoadedPlugin); return E_OUTOFMEMORY; } // Try to retrieve the function pointers by name. NP_GETENTRYPOINTS pfnGetEntryPoints; NP_PLUGININIT pfnPluginInit; NP_PLUGINSHUTDOWN pfnPluginShutdown; pfnGetEntryPoints = (NP_GETENTRYPOINTS)GetProcAddress(hInstance,"NP_GetEntryPoints"); pfnPluginInit = (NP_PLUGININIT )GetProcAddress(hInstance,"NP_Initialize"); pfnPluginShutdown = (NP_PLUGINSHUTDOWN)GetProcAddress(hInstance,"NP_Shutdown"); // If that doesn't work for some reason, try by ordinal. if(!pfnGetEntryPoints) pfnGetEntryPoints = (NP_GETENTRYPOINTS)GetProcAddress(hInstance,(LPCSTR)1); if(!pfnPluginInit) pfnPluginInit = (NP_PLUGININIT )GetProcAddress(hInstance,(LPCSTR)2); if(!pfnPluginShutdown) pfnPluginShutdown = (NP_PLUGINSHUTDOWN)GetProcAddress(hInstance,(LPCSTR)3); if(!pfnGetEntryPoints || !pfnPluginInit || !pfnPluginShutdown) { FreeLibrary(hInstance); return E_FAIL; } ZeroMemory(&m_NPPFuncs,sizeof(m_NPPFuncs)); m_NPPFuncs.size=sizeof(m_NPPFuncs); // Get the plugin function entry points err = pfnGetEntryPoints(&m_NPPFuncs); if(err!=NPERR_NO_ERROR) { FreeLibrary(hInstance); return E_FAIL; } // Tell the plugin to initialize itself err = pfnPluginInit(&g_nfuncs); if(err != NPERR_NO_ERROR) { FreeLibrary(hInstance); return E_FAIL; } // Create a new entry for the plugin m_pLoadedPlugin->szFullPath = _tcsdup(szPluginPath); m_pLoadedPlugin->nRefCount = 1; m_pLoadedPlugin->hInstance = hInstance; memcpy(&m_pLoadedPlugin->NPPFuncs, &m_NPPFuncs, sizeof(m_NPPFuncs)); // Add it to the array m_LoadedPlugins.AppendElement(m_pLoadedPlugin); return S_OK; } HRESULT CMccPluginHostCtrl::UnloadPlugin() { ATLTRACE("CMccPluginHostCtrl::UnloadPlugin()\n"); if (!m_pLoadedPlugin) { return E_FAIL; } // TODO critical section ATLASSERT(m_pLoadedPlugin->nRefCount > 0); if (m_pLoadedPlugin->nRefCount == 1) { NP_PLUGINSHUTDOWN pfnShutdown = (NP_PLUGINSHUTDOWN) GetProcAddress( m_pLoadedPlugin->hInstance, "NP_Shutdown"); if (pfnShutdown) { pfnShutdown(); } FreeLibrary(m_pLoadedPlugin->hInstance); // Delete the entry from the array m_LoadedPlugins.RemoveElement(m_pLoadedPlugin); free(m_pLoadedPlugin->szFullPath); delete m_pLoadedPlugin; } else { m_pLoadedPlugin->nRefCount--; } m_pLoadedPlugin = NULL; return S_OK; } HRESULT CMccPluginHostCtrl::AddPluginParam(const char *szName, const char *szValue) { ATLTRACE("CMccPluginHostCtrl::AddPluginParam()\n"); ATLASSERT(szName); ATLASSERT(szValue); if (!szName || !szValue) { return E_INVALIDARG; } // Skip params that already there for (unsigned long i = 0; i < m_nArgs; i++) { if (stricmp(szName, m_pszArgNames[i]) == 0) { return S_OK; } } // Add the value if (!m_pszArgNames) { ATLASSERT(!m_pszArgValues); m_nArgsMax = kArraySizeIncrement; m_pszArgNames = (char **) malloc(sizeof(char *) * m_nArgsMax); m_pszArgValues = (char **) malloc(sizeof(char *) * m_nArgsMax); } else if (m_nArgs == m_nArgsMax) { m_nArgsMax += kArraySizeIncrement; m_pszArgNames = (char **) realloc(m_pszArgNames, sizeof(char *) * m_nArgsMax); m_pszArgValues = (char **) realloc(m_pszArgValues, sizeof(char *) * m_nArgsMax); } if (!m_pszArgNames || !m_pszArgValues) { return E_OUTOFMEMORY; } m_pszArgNames[m_nArgs] = strdup(szName); m_pszArgValues[m_nArgs] = strdup(szValue); m_nArgs++; return S_OK; } HRESULT CMccPluginHostCtrl::CreatePluginInstance() { ATLTRACE(" !!!! CMccPluginHostCtrl::CreatePluginInstance()\n"); m_NPP.pdata = NULL; m_NPP.ndata = this; USES_CONVERSION; char *szContentType = strdup(OLE2A(m_bstrContentType.m_str)); // Create a child window to house the plugin RECT rc; GetClientRect(&rc); m_wndPlugin.Create(m_hWnd, rc, NULL, WS_CHILD | WS_VISIBLE); m_NPWindow.window = (void *) m_wndPlugin.m_hWnd; m_NPWindow.type = NPWindowTypeWindow; if (m_NPPFuncs.newp) { // Create the arguments to be fed into the plugin if (m_bstrSource.m_str) { AddPluginParam("SRC", OLE2A(m_bstrSource.m_str)); } if (m_bstrContentType.m_str) { AddPluginParam("TYPE", OLE2A(m_bstrContentType.m_str)); } if (m_bstrPluginsPage.m_str) { AddPluginParam("PLUGINSPAGE", OLE2A(m_bstrPluginsPage.m_str)); } char szTmp[50]; sprintf(szTmp, "%d", (int) (rc.right - rc.left)); AddPluginParam("WIDTH", szTmp); sprintf(szTmp, "%d", (int) (rc.bottom - rc.top)); AddPluginParam("HEIGHT", szTmp); NPSavedData *pSaved = NULL; // Create the plugin instance NPError npres = m_NPPFuncs.newp(szContentType, &m_NPP, NP_EMBED, (short) m_nArgs, m_pszArgNames, m_pszArgValues, pSaved); if (npres != NPERR_NO_ERROR) { return E_FAIL; } } m_bPluginIsAlive = TRUE; SizeToFitPluginInstance(); return S_OK; } HRESULT CMccPluginHostCtrl::DestroyPluginInstance() { ATLTRACE(" !!!! CMccPluginHostCtrl::DestroyPluginInstance()\n"); if (!m_bPluginIsAlive) { return S_OK; } // Destroy the plugin if (m_NPPFuncs.destroy) { NPSavedData *pSavedData = NULL; ATLTRACE(" Pre NPP_Destroy() call\n"); NPError npres = m_NPPFuncs.destroy(&m_NPP, &pSavedData); ATLTRACE(" After NPP_Destroy() call\n"); // TODO could store saved data instead of just deleting it. if (pSavedData && pSavedData->buf) { Rrr_MemFree(pSavedData->buf); } } // Destroy the arguments if (m_pszArgNames) { for (unsigned long i = 0; i < m_nArgs; i++) { free(m_pszArgNames[i]); } free(m_pszArgNames); m_pszArgNames = NULL; } if (m_pszArgValues) { for (unsigned long i = 0; i < m_nArgs; i++) { free(m_pszArgValues[i]); } free(m_pszArgValues); m_pszArgValues = NULL; } m_wndPlugin.DestroyWindow(); m_bPluginIsAlive = FALSE; return S_OK; } HRESULT CMccPluginHostCtrl::SizeToFitPluginInstance() { ATLTRACE("CMccPluginHostCtrl::SizeToFitPluginInstance()\n"); if (!m_bPluginIsAlive) { return S_OK; } // Resize the plugin to fit the window RECT rc; GetClientRect(&rc); m_wndPlugin.SetWindowPos(HWND_TOP, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, SWP_NOZORDER); m_NPWindow.x = 0; m_NPWindow.y = 0; m_NPWindow.width = rc.right - rc.left; m_NPWindow.height = rc.bottom - rc.top; m_NPWindow.clipRect.left = 0; m_NPWindow.clipRect.top = 0; m_NPWindow.clipRect.right = (unsigned short)m_NPWindow.width; m_NPWindow.clipRect.bottom = (unsigned short)m_NPWindow.height; if (m_NPPFuncs.setwindow) { NPError npres = m_NPPFuncs.setwindow(&m_NPP, &m_NPWindow); } return S_OK; } HRESULT CMccPluginHostCtrl::OpenURLStream(const TCHAR *szURL, void *pNotifyData, const void *pPostData, unsigned long nPostDataLength) { ATLTRACE("CMccPluginHostCtrl::OpenURLStream()\n"); nsURLDataCallback::OpenURL(this, szURL, pNotifyData, pPostData, nPostDataLength); return S_OK; } /////////////////////////////////////////////////////////////////////////////// // IMccPluginHostCtrl STDMETHODIMP CMccPluginHostCtrl::SetInterfaceSafetyOptions(REFIID riid, DWORD dwSupportedOptions, DWORD dwEnabledOptions) { ATLTRACE("CMccPluginHostCtrl::SetInterfaceSafetyOptions()\n"); if (riid == IID_IPersistPropertyBag) { if ((dwEnabledOptions == INTERFACESAFE_FOR_UNTRUSTED_DATA )|| (dwEnabledOptions == INTERFACESAFE_FOR_UNTRUSTED_CALLER ) ) { return S_OK; } return E_FAIL; } return IObjectSafetyImpl::SetInterfaceSafetyOptions(riid, dwSupportedOptions, dwEnabledOptions); } STDMETHODIMP CMccPluginHostCtrl::Load(LPPROPERTYBAG pPropBag, LPERRORLOG pErrorLog) { ATLTRACE("CMccPluginHostCtrl::Load()\n"); CComQIPtr cpPropBag2 = pPropBag; if (cpPropBag2) { // Read *all* the properties via IPropertyBag2 and store them somewhere // so they can be fed into the plugin instance at creation.. ULONG nProperties; cpPropBag2->CountProperties(&nProperties); if (nProperties > 0) { PROPBAG2 *pProperties = (PROPBAG2 *) malloc(sizeof(PROPBAG2) * nProperties); ULONG nPropertiesGotten = 0; cpPropBag2->GetPropertyInfo(0, nProperties, pProperties, &nPropertiesGotten); for (ULONG i = 0; i < nPropertiesGotten; i++) { if (pProperties[i].vt == VT_BSTR) { USES_CONVERSION; CComVariant v; HRESULT hrRead; cpPropBag2->Read(1, &pProperties[i], NULL, &v, &hrRead); AddPluginParam(OLE2A(pProperties[i].pstrName), OLE2A(v.bstrVal)); } if (pProperties[i].pstrName) { CoTaskMemFree(pProperties[i].pstrName); } } free(pProperties); } } return IPersistPropertyBagImpl::Load(pPropBag, pErrorLog); } /////////////////////////////////////////////////////////////////////////////// // IMccPluginHostCtrl STDMETHODIMP CMccPluginHostCtrl::get_PluginContentType(BSTR *pVal) { if (!pVal) { return E_INVALIDARG; } *pVal = m_bstrContentType.Copy(); return S_OK; } STDMETHODIMP CMccPluginHostCtrl::put_PluginContentType(BSTR newVal) { // Security. Copying the source BSTR this way ensures that embedded NULL // characters do not end up in the destination BSTR. SysAllocString will // create a copy truncated at the first NULL char. m_bstrContentType.Empty(); m_bstrContentType.Attach(SysAllocString(newVal)); return S_OK; } STDMETHODIMP CMccPluginHostCtrl::get_PluginSource(BSTR *pVal) { if (!pVal) { return E_INVALIDARG; } *pVal = m_bstrSource.Copy(); return S_OK; } STDMETHODIMP CMccPluginHostCtrl::put_PluginSource(BSTR newVal) { // Security. Copying the source BSTR this way ensures that embedded NULL // characters do not end up in the destination BSTR. SysAllocString will // create a copy truncated at the first NULL char. m_bstrSource.Empty(); m_bstrSource.Attach(SysAllocString(newVal)); return S_OK; } STDMETHODIMP CMccPluginHostCtrl::get_PluginsPage(BSTR *pVal) { if (!pVal) { return E_INVALIDARG; } *pVal = m_bstrPluginsPage.Copy(); return S_OK; } STDMETHODIMP CMccPluginHostCtrl::put_PluginsPage(BSTR newVal) { // Security. Copying the source BSTR this way ensures that embedded NULL // characters do not end up in the destination BSTR. SysAllocString will // create a copy truncated at the first NULL char. m_bstrPluginsPage.Empty(); m_bstrPluginsPage.Attach(SysAllocString(newVal)); return S_OK; }