Back to index

lightning-sunbird  0.9+nobinonly
nsPluginsDirWin.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /*
00039        nsPluginsDirWin.cpp
00040        
00041        Windows implementation of the nsPluginsDir/nsPluginsFile classes.
00042        
00043        by Alex Musil
00044  */
00045 
00046 #include "nsPluginsDir.h"
00047 #include "prlink.h"
00048 #include "plstr.h"
00049 #include "prmem.h"
00050 #include "prprf.h"
00051 
00052 #include "windows.h"
00053 #include "winbase.h"
00054 
00055 #include "nsString.h"
00056 
00058 
00059 /* Local helper functions */
00060 
00061 static char* GetKeyValue(char* verbuf, char* key)
00062 {
00063        char        *buf = NULL;
00064        UINT        blen;
00065 
00066        ::VerQueryValue(verbuf,
00067                                    TEXT(key),
00068                                    (void **)&buf, &blen);
00069 
00070        if(buf != NULL)
00071        {
00072 #ifdef WINCE
00073         // On windows CE, the verbuf is wide and the shunt
00074         // layer can't do much about it.  So, here we
00075         // convert the wide string.
00076               return PL_strdup(NS_ConvertUCS2toUTF8((PRUnichar*)buf).get());
00077 #else
00078               return PL_strdup(buf);      
00079 #endif
00080        }
00081 
00082        return nsnull;
00083 }
00084 
00085 static PRUint32 CalculateVariantCount(char* mimeTypes)
00086 {
00087        PRUint32 variants = 1;
00088 
00089   if(mimeTypes == NULL)
00090     return 0;
00091 
00092        char* index = mimeTypes;
00093        while (*index)
00094        {
00095               if (*index == '|')
00096                      variants++;
00097 
00098               ++index;
00099        }
00100        return variants;
00101 }
00102 
00103 static char** MakeStringArray(PRUint32 variants, char* data)
00104 {
00105 // The number of variants has been calculated based on the mime
00106 // type array. Plugins are not explicitely required to match
00107 // this number in two other arrays: file extention array and mime
00108 // description array, and some of them actually don't. 
00109 // We should handle such situations gracefully
00110 
00111   if((variants <= 0) || (data == NULL))
00112     return NULL;
00113 
00114   char ** array = (char **)PR_Calloc(variants, sizeof(char *));
00115   if(array == NULL)
00116     return NULL;
00117 
00118   char * start = data;
00119 
00120   for(PRUint32 i = 0; i < variants; i++)
00121   {
00122     char * p = PL_strchr(start, '|');
00123     if(p != NULL)
00124       *p = 0;
00125 
00126     array[i] = PL_strdup(start);
00127 
00128     if(p == NULL)
00129     { 
00130       // nothing more to look for, fill everything left 
00131       // with empty strings and break
00132       while(++i < variants)
00133         array[i] = PL_strdup("");
00134 
00135       break;
00136     }
00137 
00138     start = ++p;
00139   }
00140   return array;
00141 }
00142 
00143 static void FreeStringArray(PRUint32 variants, char ** array)
00144 {
00145   if((variants == 0) || (array == NULL))
00146     return;
00147 
00148   for(PRUint32 i = 0; i < variants; i++)
00149   {
00150     if(array[i] != NULL)
00151     {
00152       PL_strfree(array[i]);
00153       array[i] = NULL;
00154     }
00155   }
00156   PR_Free(array);
00157 }
00159 
00160 /* nsPluginsDir implementation */
00161 
00162 PRBool nsPluginsDir::IsPluginFile(nsIFile* file)
00163 {
00164     PRBool ret = PR_FALSE;
00165     nsCAutoString path;
00166     if (NS_FAILED(file->GetNativePath(path)))
00167         return PR_FALSE;
00168 
00169     const char *pathname = path.get();
00170        const char* filename;
00171        char* extension;
00172        PRUint32 len;
00173        // this is most likely a path, so skip to the filename
00174        filename = PL_strrchr(pathname, '\\');
00175        if(filename)
00176               ++filename;
00177        else
00178               filename = pathname;
00179 
00180        len = PL_strlen(filename);
00181        // the filename must be: "np*.dll"
00182        extension = PL_strrchr(filename, '.');
00183        if(extension)
00184            ++extension;
00185 
00186        if(len > 5)
00187        {
00188               if(!PL_strncasecmp(filename, "np", 2) && !PL_strcasecmp(extension, "dll"))
00189                      return PR_TRUE;
00190        }
00191     return ret;
00192 }
00193 
00195 
00196 /* nsPluginFile implementation */
00197 
00198 nsPluginFile::nsPluginFile(nsIFile* file)
00199 : mPlugin(file)
00200 {
00201        // nada
00202 }
00203 
00204 nsPluginFile::~nsPluginFile()
00205 {
00206        // nada
00207 }
00208 
00213 nsresult nsPluginFile::LoadPlugin(PRLibrary* &outLibrary)
00214 {
00215        // How can we convert to a full path names for using with NSPR?
00216     if (!mPlugin)
00217         return NS_ERROR_NULL_POINTER;
00218 
00219     nsCAutoString temp;
00220     mPlugin->GetNativePath(temp);
00221 
00222     char* index;
00223     char* pluginFolderPath = PL_strdup(temp.get());
00224     
00225     index = PL_strrchr(pluginFolderPath, '\\');
00226     *index = 0;
00227     
00228        BOOL restoreOrigDir = FALSE;
00229        char aOrigDir[MAX_PATH + 1];
00230        DWORD dwCheck = ::GetCurrentDirectory(sizeof(aOrigDir), aOrigDir);
00231        NS_ASSERTION(dwCheck <= MAX_PATH + 1, "Error in Loading plugin");
00232 
00233        if (dwCheck <= MAX_PATH + 1)
00234        {
00235               restoreOrigDir = ::SetCurrentDirectory(pluginFolderPath);
00236               NS_ASSERTION(restoreOrigDir, "Error in Loading plugin");
00237     }
00238     
00239        outLibrary = PR_LoadLibrary(temp.get());
00240     
00241        if (restoreOrigDir)
00242        {
00243         BOOL bCheck = ::SetCurrentDirectory(aOrigDir);
00244               NS_ASSERTION(bCheck, "Error in Loading plugin");
00245     }
00246     
00247     PL_strfree(pluginFolderPath);
00248     
00249        return NS_OK;
00250 }
00251 
00255 nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info)
00256 {
00257     nsresult res = NS_OK;
00258        DWORD zerome, versionsize;
00259        char* verbuf = nsnull;
00260 
00261        const char* path;
00262 
00263     if (!mPlugin)
00264         return NS_ERROR_NULL_POINTER;
00265 
00266     nsCAutoString temp;
00267     mPlugin->GetNativePath(temp);
00268     path = temp.get();
00269     
00270     versionsize = ::GetFileVersionInfoSize((char*)path, &zerome);
00271        if (versionsize > 0)
00272               verbuf = (char *)PR_Malloc(versionsize);
00273        if(!verbuf)
00274               return NS_ERROR_OUT_OF_MEMORY;
00275     
00276        if(::GetFileVersionInfo((char*)path, NULL, versionsize, verbuf))
00277     {
00278         info.fName = GetKeyValue(verbuf, "\\StringFileInfo\\040904E4\\ProductName");
00279               info.fDescription = GetKeyValue(verbuf, "\\StringFileInfo\\040904E4\\FileDescription");
00280 
00281               char *mimeType = GetKeyValue(verbuf, "\\StringFileInfo\\040904E4\\MIMEType");
00282               char *mimeDescription = GetKeyValue(verbuf, "\\StringFileInfo\\040904E4\\FileOpenName");
00283               char *extensions = GetKeyValue(verbuf, "\\StringFileInfo\\040904E4\\FileExtents");
00284 
00285               info.fVariantCount = CalculateVariantCount(mimeType);
00286               info.fMimeTypeArray = MakeStringArray(info.fVariantCount, mimeType);
00287               info.fMimeDescriptionArray = MakeStringArray(info.fVariantCount, mimeDescription);
00288               info.fExtensionArray = MakeStringArray(info.fVariantCount, extensions);
00289         info.fFileName = PL_strdup(path);
00290         
00291         PL_strfree(mimeType);
00292         PL_strfree(mimeDescription);
00293         PL_strfree(extensions);
00294        }
00295        else
00296               res = NS_ERROR_FAILURE;
00297 
00298 
00299        PR_Free(verbuf);
00300 
00301   return res;
00302 }
00303 
00304 nsresult nsPluginFile::FreePluginInfo(nsPluginInfo& info)
00305 {
00306   if(info.fName != NULL)
00307     PL_strfree(info.fName);
00308 
00309   if(info.fDescription != NULL)
00310     PL_strfree(info.fDescription);
00311 
00312   if(info.fMimeTypeArray != NULL)
00313     FreeStringArray(info.fVariantCount, info.fMimeTypeArray);
00314 
00315   if(info.fMimeDescriptionArray != NULL)
00316     FreeStringArray(info.fVariantCount, info.fMimeDescriptionArray);
00317 
00318   if(info.fExtensionArray != NULL)
00319     FreeStringArray(info.fVariantCount, info.fExtensionArray);
00320 
00321   if(info.fFileName != NULL)
00322     PL_strfree(info.fFileName);
00323 
00324   ZeroMemory((void *)&info, sizeof(info));
00325 
00326   return NS_OK;
00327 }