/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * The contents of this file are subject to the Netscape Public License * Version 1.0 (the "NPL"); you may not use this file except in * compliance with the NPL. You may obtain a copy of the NPL at * http://www.mozilla.org/NPL/ * * Software distributed under the NPL is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL * for the specific language governing rights and limitations under the * NPL. * * The Initial Developer of this code under the NPL is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998 Netscape Communications Corporation. All Rights * Reserved. */ // npwplat.cpp #include "stdafx.h" #include #include #include #include #include #include #include #ifdef WIN32 #include #include #else #include #include #endif #include "npwplat.h" #include "nppg.h" #include "plgindll.h" #include "np.h" #include "helper.h" #if defined(OJI) #include "jvmmgr.h" #elif defined(JAVA) #include "java.h" #endif #include "edt.h" #include "npglue.h" NPPMgtBlk* g_pRegisteredPluginList = NULL; // Tests that the directory specified by "dir" exists. // Returns true if it does. static XP_Bool wfe_CheckDir(const char * dir) { int ret; XP_StatStruct statinfo; ret = _stat((char *) dir, &statinfo); if(ret == -1) return(FALSE); return(TRUE); } // Get the name of the directory where plugins live. "csDirname" is where the // name of the dir is written to, and the trailing slash is removed. // It always returns NPERR_NO_ERROR, since the Nav had to be started to get // here, and the plugin dir is under where Nav started from. NPError wfe_GetPluginsDirectory(CString& csDirname) { char ca_default[_MAX_PATH]; ::GetModuleFileName(AfxGetApp()->m_hInstance, ca_default, _MAX_PATH); char *cp_lastslash = ::strrchr(ca_default, '\\'); *cp_lastslash = NULL; csDirname = ca_default; csDirname += "\\plugins"; return NPERR_NO_ERROR; } NPError wfe_GetJavaDirectory(CString& csDirname) { char ca_default[_MAX_PATH]; ::GetModuleFileName(AfxGetApp()->m_hInstance, ca_default, _MAX_PATH); char *cp_lastslash = ::strrchr(ca_default, '\\'); *cp_lastslash = NULL; csDirname = ca_default; csDirname += "\\java\\classes"; return NPERR_NO_ERROR; } // Fetches the "MIME type" string from the DLL VERSIONINFO structure. // "pVersionInfo" is ptr to the VERSIONINFO data, and "pNPMgtBlk" is a handle // to a plugin management data structure created during fe_RegisterPlugin(). // The string is copied from the VERSIONINFO data into the // "pNPMgtBlk->szMIMEType" member. // An error is returned if out of memory. The MIME type string IS // required, so an error is returned if the string does not exist. NPError wfe_GetPluginMIMEType(VS_FIXEDFILEINFO* pVersionInfo, NPPMgtBlk* pNPMgtBlk) { // get the mime type of this plugin static char szMimeTypeBlock[] = "StringFileInfo\\040904E4\\MIMEType"; void* lpBuffer = NULL; UINT uValueSize = 0; if(::VerQueryValue(pVersionInfo, szMimeTypeBlock, &lpBuffer, &uValueSize) == 0) // couldn't find MIME type return NPERR_GENERIC_ERROR; pNPMgtBlk->szMIMEType = new char[uValueSize]; if(pNPMgtBlk->szMIMEType == NULL) return NPERR_OUT_OF_MEMORY_ERROR; strcpy(pNPMgtBlk->szMIMEType, (const char*)lpBuffer); return NPERR_NO_ERROR; } // Fetches the "File Extents" string from the DLL VERSIONINFO structure. // "pVersionInfo" is ptr to the VERSIONINFO data, and "pNPMgtBlk" is a handle // to a plugin management data structure created during fe_RegisterPlugin(). // The string is copied from the VERSIONINFO data into the // "pNPMgtBlk->szFileExtents" member. // An error is returned if out of memory, but the extents string is not // required, so it is not an error if the string does not exist. NPError wfe_GetPluginExtents(VS_FIXEDFILEINFO* pVersionInfo, NPPMgtBlk* pNPMgtBlk) { // get the file extent list of this plugin pNPMgtBlk->szFileExtents = NULL; static char szFileExtentsBlock[] = "StringFileInfo\\040904E4\\FileExtents"; void* lpBuffer = NULL; UINT uValueSize = 0; if(::VerQueryValue(pVersionInfo, szFileExtentsBlock, &lpBuffer, &uValueSize) == 0) // couldn't find file extent return NPERR_NO_ERROR; if((*((char*)lpBuffer) == '\0') || (uValueSize == 0)) // no extents return NPERR_NO_ERROR; // alloc char array pNPMgtBlk->szFileExtents = new char[uValueSize]; if(pNPMgtBlk->szFileExtents == NULL) return NPERR_OUT_OF_MEMORY_ERROR; strcpy(pNPMgtBlk->szFileExtents, (const char*)lpBuffer); return NPERR_NO_ERROR; } // Fetches the "File Open Template" string from the DLL VERSIONINFO structure. // "pVersionInfo" is ptr to the VERSIONINFO data, and "pNPMgtBlk" is a handle // to a plugin management data structure created during fe_RegisterPlugin(). // The string is copied from the VERSIONINFO data into the // "pNPMgtBlk->szFileOpenName" member. // An error is returned if out of memory, but the template string is not // required, so it is not an error if the string does not exist. NPError wfe_GetPluginFileOpenTemplate(VS_FIXEDFILEINFO* pVersionInfo, NPPMgtBlk* pNPMgtBlk) { // get the file open template this plugin pNPMgtBlk->szFileOpenName = NULL; static char szFileOpenBlock[] = "StringFileInfo\\040904E4\\FileOpenName"; void* lpBuffer = NULL; UINT uValueSize = 0; if(::VerQueryValue(pVersionInfo, szFileOpenBlock, &lpBuffer, &uValueSize) == 0) // couldn't find file extent return NPERR_NO_ERROR; if((*((char*)lpBuffer) == '\0') || (uValueSize == 0)) // no extents return NPERR_NO_ERROR; // alloc char array pNPMgtBlk->szFileOpenName = new char[uValueSize]; if(pNPMgtBlk->szFileOpenName == NULL) return NPERR_OUT_OF_MEMORY_ERROR; strcpy(pNPMgtBlk->szFileOpenName, (const char*)lpBuffer); return NPERR_NO_ERROR; } // Fetches the plugin name and description from the resource info. // Uses predefined version information strings NPError wfe_GetPluginNameAndDescription(VS_FIXEDFILEINFO* pVersionInfo, CString& strName, CString& strDescription) { static char szNameBlock[] = "StringFileInfo\\040904E4\\ProductName"; static char szDescBlock[] = "StringFileInfo\\040904E4\\FileDescription"; void* lpBuffer = NULL; UINT uValueSize = 0; // Get the product name if(::VerQueryValue(pVersionInfo, szNameBlock, &lpBuffer, &uValueSize) > 0) strName = (LPSTR)lpBuffer; // Get the file description if(::VerQueryValue(pVersionInfo, szDescBlock, &lpBuffer, &uValueSize) > 0) strDescription = (LPSTR)lpBuffer; return NPERR_NO_ERROR; } // Loads plugin properties from the DLL VERSIONINFO data structure. // MIME type and version are required, but file extents and string // file open templates are optional. "pPluginFilespec" is a string // containing the file name of a DLL. "pNPMgtBlk" is a handle to a // plugin management data structure created during fe_RegisterPlugin(). // Returns an error if "pPluginFilespec" did not have the required MIME // type and version fields. // // Also returns the plugin name and description NPError wfe_GetPluginProperties(char* pPluginFilespec, NPPMgtBlk* pNPMgtBlk, CString& strPluginName, CString& strPluginDescription) { // prepare to read the version info tags DWORD dwHandle = NULL; DWORD dwVerInfoSize = ::GetFileVersionInfoSize(pPluginFilespec, &dwHandle); if(dwVerInfoSize == NULL) return NPERR_GENERIC_ERROR; VS_FIXEDFILEINFO* pVersionInfo = (VS_FIXEDFILEINFO*)new char[dwVerInfoSize]; if(pVersionInfo == NULL) return NPERR_OUT_OF_MEMORY_ERROR; if(::GetFileVersionInfo(pPluginFilespec, dwHandle, dwVerInfoSize, pVersionInfo) == 0) { delete [] (char*)pVersionInfo; return NPERR_GENERIC_ERROR; } NPError result; // get the mime type of this plugin if((result = wfe_GetPluginMIMEType(pVersionInfo, pNPMgtBlk)) != NPERR_NO_ERROR) { delete [] (char*)pVersionInfo; return result; } // get the file extent list of this plugin if((result = wfe_GetPluginExtents(pVersionInfo, pNPMgtBlk)) != NPERR_NO_ERROR) { delete [] pNPMgtBlk->szMIMEType; delete [] (char*)pVersionInfo; return result; } // get the file type template string of this plugin if((result = wfe_GetPluginFileOpenTemplate(pVersionInfo, pNPMgtBlk)) != NPERR_NO_ERROR) { delete [] pNPMgtBlk->szFileExtents; delete [] pNPMgtBlk->szMIMEType; delete [] (char*)pVersionInfo; return result; } // get the version of this plugin void* lpBuffer = NULL; UINT uValueSize = 0; if(::VerQueryValue(pVersionInfo, "\\", &lpBuffer, &uValueSize) == 0) { // couldn't find versioninfo delete [] pNPMgtBlk->szFileExtents; delete [] pNPMgtBlk->szMIMEType; delete [] (char*)pVersionInfo; return NPERR_GENERIC_ERROR; } pNPMgtBlk->versionMS = ((VS_FIXEDFILEINFO*)lpBuffer)->dwProductVersionMS; pNPMgtBlk->versionLS = ((VS_FIXEDFILEINFO*)lpBuffer)->dwProductVersionLS; // get the plugin name and description. It's not fatal if these fail wfe_GetPluginNameAndDescription(pVersionInfo, strPluginName, strPluginDescription); delete [] (char*)pVersionInfo; return NPERR_NO_ERROR; } // Given a file open filter, e.g. Text Documents(*.txt), extracts the // description and returns a copy of it static LPSTR ExtractDescription(LPCSTR lpszFileOpenFilter) { ASSERT(lpszFileOpenFilter); LPSTR lpszDescription = XP_STRDUP(lpszFileOpenFilter); // Strip off an filter pattern at the end LPSTR lpszPattern = strrchr(lpszDescription, '('); if (lpszPattern) *lpszPattern = '\0'; return lpszDescription; } // Registers one plugin. "pPluginFilespec" is a string containing the file // name of a DLL. // This function can be called more than once so a plugin which has copied // into the plugins subdir AFTER the Nav has started can be registered // and loaded. // The DLL is a plugin candidate, and is qualified during // this function, by checking the DLL VERSIONINFO data structure for a // MIME type string. If this string is found successfully, the handle // of the management block is used to register the plugin for its MIME type. // The extents which are to be associated with this MIME type are also grokked // from the VERSIONINFO data structure, once the candidate is accepted. // This function also takes the opportunity to overrided any helper app, by // setting a helper app data structure member to allow the plugin to handle // the MIME type instead of the helper, (pApp->how_handle = HANDLE_VIA_PLUGIN). // Returns an error if "pPluginFilespec" was not registered. NPError fe_RegisterPlugin(char* pPluginFilespec) { CString strName, strDescription; // initialize a new plugin list mgt block NPPMgtBlk* pNPMgtBlk = new NPPMgtBlk; if(pNPMgtBlk == NULL) // fatal, can't continue return NPERR_OUT_OF_MEMORY_ERROR; pNPMgtBlk->pPluginFuncs = NULL; pNPMgtBlk->pLibrary = NULL; pNPMgtBlk->uRefCount = 0; pNPMgtBlk->next = NULL; // determine the MIME type and version of this plugin if(wfe_GetPluginProperties(pPluginFilespec, pNPMgtBlk, strName, strDescription) != NPERR_NO_ERROR) { delete pNPMgtBlk; return NPERR_GENERIC_ERROR; } // if a plugin is already registered for this MIME type, return. this // allows downloading and registering new plugins without exiting the nav for(NPPMgtBlk* pListBlk = g_pRegisteredPluginList; pListBlk != NULL; pListBlk = pListBlk->next) { BOOL bSameFile = (strcmp(pListBlk->pPluginFilename, pPluginFilespec) == 0); BOOL bSameMIMEtype = (strstr(pNPMgtBlk->szMIMEType, pListBlk->szMIMEType) != NULL); if(bSameFile && bSameMIMEtype) { // the plugin DLL's filename and the MIME type it's registering for // are the same, don't reregister delete pNPMgtBlk; return NPERR_GENERIC_ERROR; } } pNPMgtBlk->pPluginFilename = XP_STRDUP(pPluginFilespec); if(pNPMgtBlk->pPluginFilename == NULL) // fatal, can't continue { delete pNPMgtBlk; return NPERR_OUT_OF_MEMORY_ERROR; } // Register the plugin file with the XP plugin code NPL_RegisterPluginFile(strName, pNPMgtBlk->pPluginFilename, strDescription, pNPMgtBlk); // Iterate through the filename extensions. These are a list which are // delimited via the '|' character. The list of MIME Types,File Extents, // and Open Names must all coordinate char *pStartMIME, *pEndMIME, *pStartExt, *pEndExt, *pStartName, *pEndName; pStartMIME = pNPMgtBlk->szMIMEType; pStartExt = pNPMgtBlk->szFileExtents; pStartName = pNPMgtBlk->szFileOpenName; pEndMIME = strchr(pStartMIME ,'|'); while (pEndMIME) { pEndExt = strchr(pStartExt,'|'); pEndName = strchr(pStartName,'|'); if (pEndMIME) *pEndMIME = 0; else return NPERR_GENERIC_ERROR; if (pEndExt) *pEndExt = 0; else return NPERR_GENERIC_ERROR; if (pEndName) *pEndName = 0; else return NPERR_GENERIC_ERROR; // Register the MIME type with the XP plugin code. We need to pass in // a description. If there's a file open template specified, then use the // description from there. Otherwise use the MIME type LPSTR lpszDescription = NULL; if (pStartName) lpszDescription = ExtractDescription(pStartName); NPL_RegisterPluginType(pStartMIME, (LPCSTR)pStartExt, lpszDescription ? lpszDescription : pStartMIME, (void *)pStartName, pNPMgtBlk, TRUE); if (lpszDescription) XP_FREE(lpszDescription); CHelperApp *pApp; if(theApp.m_HelperListByType.Lookup(pStartMIME, (CObject *&)pApp)) { // We've a match. // Make sure the app is marked to handle the load // via a plugin pApp->how_handle = HANDLE_VIA_PLUGIN; } if ((pEndMIME+1) && (pEndExt+1) && (pEndName+1)) { pStartMIME = pEndMIME+1; pStartExt = pEndExt+1; pStartName = pEndName+1; } pEndMIME = strchr(pStartMIME ,'|'); } // Register the MIME type with the XP plugin code. We need to pass in // a description. If there's a file open template specified, then use the // description from there. Otherwise use the MIME type LPSTR lpszDescription = NULL; if (pStartName) lpszDescription = ExtractDescription(pStartName); NPL_RegisterPluginType(pStartMIME, (LPCSTR)pStartExt, lpszDescription ? lpszDescription : pStartMIME, (void *)pStartName, pNPMgtBlk, TRUE); if (lpszDescription) XP_FREE(lpszDescription); CHelperApp *pApp; if(theApp.m_HelperListByType.Lookup(pStartMIME, (CObject *&)pApp)) { // We've a match. // Make sure the app is marked to handle the load // via a plugin pApp->how_handle = HANDLE_VIA_PLUGIN; } // insert the plugin mgt blk at the head of the list of registered plugins. // this means they are listed in the reverse order from which they were // created, which doesn't matter. pNPMgtBlk->next = g_pRegisteredPluginList; g_pRegisteredPluginList = pNPMgtBlk; return NPERR_NO_ERROR; } // FE_RegisterPlugins is called from navigator main via npglue's NP_Init(). Finds all // plugins and begins tracking them using a NPPMgtBlk. Uses the NPPMgtBlk // block handle to register the plugin with the xp plugin glue. Looks // in the directory under the netscape.exe dir, named "plugins" and all // subdirectories in recursive way (see fe_RegisterPlugins). If the // directory doesn't exist, no warning dialog is shown. // There are no input or return vals. void fe_RegisterPlugins(char* pszPluginDir) { CString csPluginSpec; csPluginSpec = pszPluginDir; #if defined(JAVA) // add directory to the java path no matter what LJ_AddToClassPath(pszPluginDir); #endif if (thePluginManager == NULL) { static NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID); nsresult rslt = nsPluginManager::Create(NULL, kIPluginManagerIID, (void**)&thePluginManager); // XXX Out of memory already? This function should return an error code! PR_ASSERT(rslt == NS_OK); // keep going anyway... } csPluginSpec += "\\*.*"; #ifndef _WIN32 _find_t fileinfo; unsigned result = _dos_findfirst((LPSTR)((LPCSTR)csPluginSpec), _A_NORMAL | _A_SUBDIR, &fileinfo ); if (result == 0) { result = _dos_findnext(&fileinfo); // skip "." result = _dos_findnext(&fileinfo); // skip ".." CString csFileSpec; while(result == 0) { csFileSpec = pszPluginDir; csFileSpec += "\\"; csFileSpec += fileinfo.name; // we got a subdir, call recursively this function to load plugin if (fileinfo.attrib & _A_SUBDIR ) { fe_RegisterPlugins((LPSTR)(LPCSTR)csFileSpec); } else { size_t len = strlen(fileinfo.name); // it's a file, see if it can be a plugin file if ( len > 6 && // at least "np.dll" (fileinfo.name[0] == 'n' || fileinfo.name[0] == 'N') && (fileinfo.name[1] == 'p' || fileinfo.name[1] == 'P') && !_stricmp(fileinfo.name + len - 4, ".dll")) fe_RegisterPlugin((LPSTR)((LPCSTR)csFileSpec)); #ifdef EDITOR // If it's a cpXXX.zip file,register it as a composer plugin. else if ( len > 6 && // at least cp.zip (fileinfo.name[0] == 'c' || fileinfo.name[0] == 'C') && (fileinfo.name[1] == 'p' || fileinfo.name[1] == 'P') && (!_stricmp(fileinfo.name + len - 4, ".zip") || !_stricmp(fileinfo.name + len - 4, ".jar")) ) EDT_RegisterPlugin((LPSTR)((LPCSTR)csFileSpec)); #endif /* EDITOR */ } result = _dos_findnext(&fileinfo); } } #else /* _WIN32 */ _finddata_t fileinfo; unsigned handle = _findfirst((LPSTR)((LPCSTR)csPluginSpec), &fileinfo ); unsigned result = 0; if (handle != -1) { result = _findnext(handle, &fileinfo); // skip "." result = _findnext(handle, &fileinfo); // skip ".." CString csFileSpec; while((result != -1) && (handle != -1)) { csFileSpec = pszPluginDir; csFileSpec += "\\"; csFileSpec += fileinfo.name; // we got a subdir, call recursively this function to load plugin if (fileinfo.attrib & _A_SUBDIR ) { fe_RegisterPlugins((LPSTR)(LPCSTR)csFileSpec); } else { size_t len = strlen(fileinfo.name); // it's a file, see if it can be a plugin file if ( len > 6 && // at least "np.dll" (fileinfo.name[0] == 'n' || fileinfo.name[0] == 'N') && (fileinfo.name[1] == 'p' || fileinfo.name[1] == 'P') && !_stricmp(fileinfo.name + len - 4, ".dll")) fe_RegisterPlugin((LPSTR)((LPCSTR)csFileSpec)); #ifdef EDITOR // If it's a cpXXX.zip file, add it to the java class path. else if ( len > 6 && // at least cp.zip (fileinfo.name[0] == 'c' || fileinfo.name[0] == 'C') && (fileinfo.name[1] == 'p' || fileinfo.name[1] == 'P') && (!_stricmp(fileinfo.name + len - 4, ".zip") || !_stricmp(fileinfo.name + len - 4, ".jar")) ) EDT_RegisterPlugin((LPSTR)((LPCSTR)csFileSpec)); #endif } result = _findnext(handle, &fileinfo); } _findclose(handle); } #endif /* _WIN32 */ } // called from the navigator main, dispatch to the previous function void FE_RegisterPlugins() { CString csPluginDir; // get the main plugins directory and start the process wfe_GetPluginsDirectory(csPluginDir); fe_RegisterPlugins((LPSTR)(LPCSTR)csPluginDir); CString csJavaDir; wfe_GetJavaDirectory(csJavaDir); JVM_AddToClassPath(csJavaDir); } // saves the current path in the variable passed. ppPathSave is the // address of the ptr which stores the path string. returns out of memory // error if allocation for the string returned by _getcwd() fails. returns // generic error if the "one deep" stack is already full. NPError wfe_PushPath(LPSTR *ppPathSave) { // only allow "one deep" stack if(*ppPathSave != NULL) return NPERR_GENERIC_ERROR; // save the CWD *ppPathSave = _getcwd(NULL, 0); if(*ppPathSave == NULL) return NPERR_OUT_OF_MEMORY_ERROR; return NPERR_NO_ERROR; } // calculate the drive letter value for _chdrive(). ascii in, int out int wfe_MapAsciiToDriveNum(char cAsciiNum) { int iDriveLetter = cAsciiNum; if(islower(cAsciiNum)) iDriveLetter = _toupper(cAsciiNum); // plus one because for _chdrive(), A = 1, B = 2, etc return iDriveLetter - 'A' + 1; } // restores the path from the variable passed. pDirSave stores the pointer // to the path string. returns an error if a path has never been pushed. NPError wfe_PopPath(LPSTR pPathSave) { // only allows "one deep" stack if(pPathSave == NULL) return NPERR_GENERIC_ERROR; // restore the drive int chdriveErr = _chdrive(wfe_MapAsciiToDriveNum(pPathSave[0])); // restore the CWD int chdirErr = _chdir(pPathSave); free(pPathSave); return NPERR_NO_ERROR; } // Load a plugin dll. "pluginType" is a handle to a plugin management data // structure created during FE_RegisterPlugins(). "pNavigatorFuncs" is // a table of entry points into Navigator, which are the services provided // by Navigator to plugins, such as requestread() and GetUrl(). These entry // points are stored and called by the plugin when services are needed. // The return val is a table of functions which are entry points to the // newly loaded plugin, such as NewStream() and Write(). NPPluginFuncs* FE_LoadPlugin(void* pluginType, NPNetscapeFuncs* pNavigatorFuncs, np_handle* handle) { if(pluginType == NULL) return NULL; NPPMgtBlk* pNPMgtBlock = (NPPMgtBlk*)pluginType; CString csPluginDir; #ifdef OJI char* szExplicitDLL = strrchr(pNPMgtBlock->pPluginFilename, '\\'); if( szExplicitDLL ) { csPluginDir = pNPMgtBlock->pPluginFilename; // MFC copies the string csPluginDir.SetAt( szExplicitDLL - pNPMgtBlock->pPluginFilename, '\0'); } else { wfe_GetPluginsDirectory(csPluginDir); } #else wfe_GetPluginsDirectory(csPluginDir); #endif /* OJI */ LPSTR pPathSave = NULL; // storage for one dir spec wfe_PushPath(&pPathSave); // save the current drive and dir // change the default dir so that implib'd plugins won't fail if(_chdir(csPluginDir) != 0) { wfe_PopPath(pPathSave); // restore the path return NULL; } // must change the drive as well as the dir path if(isalpha(csPluginDir[0]) && csPluginDir[1] == ':') { if(_chdrive(wfe_MapAsciiToDriveNum(csPluginDir[0])) != 0) { wfe_PopPath(pPathSave); // restore the path return NULL; } } pNPMgtBlock->pLibrary = PR_LoadLibrary(pNPMgtBlock->pPluginFilename); // the cross platform code should take care of the 16/32 bit issues if(pNPMgtBlock->pLibrary == NULL) return NULL; nsFactoryProc nsGetFactory = (nsFactoryProc) PR_FindSymbol(pNPMgtBlock->pLibrary, "NSGetFactory"); if (nsGetFactory != NULL) { static NS_DEFINE_IID(kIPluginIID, NS_IPLUGIN_IID); nsIPlugin* plugin = NULL; nsresult res = nsGetFactory(kIPluginIID, (nsIFactory**)&plugin); PR_ASSERT(thePluginManager != NULL); if (res == NS_OK && plugin != NULL && plugin->Initialize((nsIPluginManager*)thePluginManager) == NS_OK) { handle->userPlugin = plugin; pNPMgtBlock->pPluginFuncs = (NPPluginFuncs*)-1; // something to say it's loaded, but != 0 #ifdef LATER // XXX coming soon... // add the plugin directory if successful JVM_AddToClassPathRecursively(csPluginDir); #endif } else { PR_UnloadLibrary(pNPMgtBlock->pLibrary); wfe_PopPath(pPathSave); // restore the path return NULL; } } else { NP_GETENTRYPOINTS getentrypoints = #ifndef NSPR20 (NP_GETENTRYPOINTS)PR_FindSymbol("NP_GetEntryPoints", pNPMgtBlock->pLibrary); #else (NP_GETENTRYPOINTS)PR_FindSymbol(pNPMgtBlock->pLibrary, "NP_GetEntryPoints"); #endif if(getentrypoints == NULL) { PR_UnloadLibrary(pNPMgtBlock->pLibrary); wfe_PopPath(pPathSave); // restore the path return NULL; } if(pNPMgtBlock->pPluginFuncs == NULL) { pNPMgtBlock->pPluginFuncs = new NPPluginFuncs; pNPMgtBlock->pPluginFuncs->size = sizeof NPPluginFuncs; pNPMgtBlock->pPluginFuncs->javaClass = NULL; if(pNPMgtBlock->pPluginFuncs == NULL) // fatal, can't continue { PR_UnloadLibrary(pNPMgtBlock->pLibrary); wfe_PopPath(pPathSave); // restore the path return NULL; } } if(getentrypoints(pNPMgtBlock->pPluginFuncs) != NPERR_NO_ERROR) { PR_UnloadLibrary(pNPMgtBlock->pLibrary); delete pNPMgtBlock->pPluginFuncs; pNPMgtBlock->pPluginFuncs = NULL; wfe_PopPath(pPathSave); // restore the path return NULL; } // if the plugin's major ver level is lower than the Navigator's, // then they are incompatible, and should return an error if(HIBYTE(pNPMgtBlock->pPluginFuncs->version) < NP_VERSION_MAJOR) { PR_UnloadLibrary(pNPMgtBlock->pLibrary); delete pNPMgtBlock->pPluginFuncs; pNPMgtBlock->pPluginFuncs = NULL; wfe_PopPath(pPathSave); // restore the path return NULL; } NP_PLUGININIT npinit = NULL; // if this DLL is not already loaded, call its initialization entry point if(pNPMgtBlock->uRefCount == 0) { // the NP_Initialize entry point was misnamed as NP_PluginInit, early // in plugin project development. Its correct name is documented // now, and new developers expect it to work. However, I don't want // to break the plugins already in the field, so I'll accept either // name npinit = #ifndef NSPR20 (NP_PLUGININIT)PR_FindSymbol("NP_Initialize", pNPMgtBlock->pLibrary); #else (NP_PLUGININIT)PR_FindSymbol(pNPMgtBlock->pLibrary, "NP_Initialize"); #endif if(!npinit) { npinit = #ifndef NSPR20 (NP_PLUGININIT)PR_FindSymbol("NP_PluginInit", pNPMgtBlock->pLibrary); #else (NP_PLUGININIT)PR_FindSymbol(pNPMgtBlock->pLibrary, "NP_PluginInit"); #endif } } if(npinit == NULL) { PR_UnloadLibrary(pNPMgtBlock->pLibrary); delete pNPMgtBlock->pPluginFuncs; pNPMgtBlock->pPluginFuncs = NULL; wfe_PopPath(pPathSave); // restore the path return NULL; } if (npinit(pNavigatorFuncs) != NPERR_NO_ERROR) { PR_UnloadLibrary(pNPMgtBlock->pLibrary); delete pNPMgtBlock->pPluginFuncs; pNPMgtBlock->pPluginFuncs = NULL; wfe_PopPath(pPathSave); // restore the path return NULL; } } pNPMgtBlock->uRefCount++; // all is well, remember it was loaded // can't pop the path until plugins have been completely loaded/init'd wfe_PopPath(pPathSave); // restore the path return pNPMgtBlock->pPluginFuncs; } // Unloads a plugin DLL. "pluginType" is a handle to a plugin management data // structure created during FE_RegisterPlugins(). There is no return val. void FE_UnloadPlugin(void* pluginType, struct _np_handle* handle) { NPPMgtBlk* pNPMgtBlk = (NPPMgtBlk*)pluginType; if (pNPMgtBlk == NULL) return; // XXX Note that we're double refcounting here. If we were rewriting this // from scratch, we could eliminate this pNPMgtBlk and its refcount and just // rely on the one in the userPlugin. pNPMgtBlk->uRefCount--; // another one bites the dust // if this DLL is the last one, call its shutdown entry point if (pNPMgtBlk->uRefCount == 0) { if (handle->userPlugin) { nsrefcnt cnt = handle->userPlugin->Release(); PR_ASSERT(cnt == 0); #if 0 // XXX later... // remove the plugin directory if successful JVM_RemoveFromClassPathRecursively(csPluginDir); #endif } else { // the NP_Shutdown entry point was misnamed as NP_PluginShutdown, early // in plugin project development. Its correct name is documented // now, and new developers expect it to work. However, I don't want // to break the plugins already in the field, so I'll accept either // name NP_PLUGINSHUTDOWN npshutdown = #ifndef NSPR20 (NP_PLUGINSHUTDOWN)PR_FindSymbol("NP_Shutdown", pNPMgtBlk->pLibrary); #else (NP_PLUGINSHUTDOWN)PR_FindSymbol(pNPMgtBlk->pLibrary, "NP_Shutdown"); #endif if (!npshutdown) { npshutdown = #ifndef NSPR20 (NP_PLUGINSHUTDOWN)PR_FindSymbol("NP_PluginShutdown", pNPMgtBlk->pLibrary); #else (NP_PLUGINSHUTDOWN)PR_FindSymbol(pNPMgtBlk->pLibrary, "NP_PluginShutdown"); #endif } if (npshutdown != NULL) { NPError result = npshutdown(); } } } PR_UnloadLibrary(pNPMgtBlk->pLibrary); pNPMgtBlk->pLibrary = NULL; if (handle->userPlugin) { PR_ASSERT(pNPMgtBlk->pPluginFuncs == (NPPluginFuncs*)-1); // set in FE_LoadPlugin handle->userPlugin = NULL; } else { delete pNPMgtBlk->pPluginFuncs; } pNPMgtBlk->pPluginFuncs = NULL; } // Removes a plugin DLL from memory, and frees its NPPMgtBlk management block. // "pluginType" is a handle to the plugin management data structure created // during FE_RegisterPlugins(). There is no return val. void FE_UnregisterPlugin(void* pluginType) { NPPMgtBlk* pNPMgtBlk = (NPPMgtBlk*)pluginType; if(pNPMgtBlk == NULL) return; if(pNPMgtBlk->pLibrary != NULL) PR_UnloadLibrary(pNPMgtBlk->pLibrary); delete [] (char*)*pNPMgtBlk->pPluginFilename; delete [] pNPMgtBlk->pPluginFilename; delete [] pNPMgtBlk->szMIMEType; delete pNPMgtBlk->pPluginFuncs; delete pNPMgtBlk; } // Provides the entry point used by xp plugin code, (NPGLUE.C), to control // scroll bars. The inputs are obvious, and there is no return val. void FE_ShowScrollBars(MWContext* pContext, XP_Bool show) { if(ABSTRACTCX(pContext)->IsWindowContext()) { CPaneCX *pPaneCX = PANECX(pContext); pPaneCX->ShowScrollBars(SB_BOTH, show); } } #ifdef XP_WIN32 void* WFE_BeginSetModuleState() { return AfxSetModuleState(AfxGetAppModuleState()); } void WFE_EndSetModuleState(void* pPrevState) { AfxSetModuleState((AFX_MODULE_STATE*)pPrevState); } #endif