Back to index

lightning-sunbird  0.9+nobinonly
nsPluginDirServiceProvider.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
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) 2001
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *  Conrad Carlen <ccarlen@netscape.com>
00024  *
00025  * Alternatively, the contents of this file may be used under the terms of
00026  * either the GNU General Public License Version 2 or later (the "GPL"), or
00027  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00028  * in which case the provisions of the GPL or the LGPL are applicable instead
00029  * of those above. If you wish to allow use of your version of this file only
00030  * under the terms of either the GPL or the LGPL, and not to allow others to
00031  * use your version of this file under the terms of the MPL, indicate your
00032  * decision by deleting the provisions above and replace them with the notice
00033  * and other provisions required by the GPL or the LGPL. If you do not delete
00034  * the provisions above, a recipient may use your version of this file under
00035  * the terms of any one of the MPL, the GPL or the LGPL.
00036  *
00037  * ***** END LICENSE BLOCK ***** */
00038 
00039 #include "nsPluginDirServiceProvider.h"
00040 
00041 #include "nsCRT.h"
00042 #include "nsILocalFile.h"
00043 #include "nsIPrefBranch.h"
00044 #include "nsIPrefService.h"
00045 #include "nsDependentString.h"
00046 #include "nsXPIDLString.h"
00047 #include "prmem.h"
00048 #include "nsCOMArray.h"
00049 #include "nsArrayEnumerator.h"
00050 
00051 #if defined (XP_WIN)
00052 #include <windows.h>
00053 
00054 typedef struct structVer
00055 {
00056   WORD wMajor;
00057   WORD wMinor;
00058   WORD wRelease;
00059   WORD wBuild;
00060 } verBlock;
00061 
00062 static void
00063 ClearVersion(verBlock *ver)
00064 {
00065   ver->wMajor   = 0;
00066   ver->wMinor   = 0;
00067   ver->wRelease = 0;
00068   ver->wBuild   = 0;
00069 }
00070 
00071 static BOOL
00072 FileExists(LPCSTR szFile)
00073 {
00074   return GetFileAttributes(szFile) != 0xFFFFFFFF;
00075 }
00076 
00077 // Get file version information from a file
00078 static BOOL
00079 GetFileVersion(LPSTR szFile, verBlock *vbVersion)
00080 {
00081   UINT              uLen;
00082   UINT              dwLen;
00083   BOOL              bRv;
00084   DWORD             dwHandle;
00085   LPVOID            lpData;
00086   LPVOID            lpBuffer;
00087   VS_FIXEDFILEINFO  *lpBuffer2;
00088 
00089   ClearVersion(vbVersion);
00090   if (FileExists(szFile)) {
00091     bRv    = TRUE;
00092     dwLen  = GetFileVersionInfoSize(szFile, &dwHandle);
00093     lpData = (LPVOID)malloc(dwLen);
00094     uLen   = 0;
00095 
00096     if (lpData && GetFileVersionInfo(szFile, dwHandle, dwLen, lpData) != 0) {
00097       if (VerQueryValue(lpData, "\\", &lpBuffer, &uLen) != 0) {
00098         lpBuffer2 = (VS_FIXEDFILEINFO *)lpBuffer;
00099 
00100         vbVersion->wMajor   = HIWORD(lpBuffer2->dwFileVersionMS);
00101         vbVersion->wMinor   = LOWORD(lpBuffer2->dwFileVersionMS);
00102         vbVersion->wRelease = HIWORD(lpBuffer2->dwFileVersionLS);
00103         vbVersion->wBuild   = LOWORD(lpBuffer2->dwFileVersionLS);
00104       }
00105     }
00106 
00107     free(lpData);
00108   } else {
00109     /* File does not exist */
00110     bRv = FALSE;
00111   }
00112 
00113   return bRv;
00114 }
00115 
00116 // Will deep copy ver2 into ver1
00117 static void
00118 CopyVersion(verBlock *ver1, verBlock *ver2)
00119 {
00120   ver1->wMajor   = ver2->wMajor;
00121   ver1->wMinor   = ver2->wMinor;
00122   ver1->wRelease = ver2->wRelease;
00123   ver1->wBuild   = ver2->wBuild;
00124 }
00125 
00126 // Convert a string version to a version struct
00127 static void
00128 TranslateVersionStr(const char* szVersion, verBlock *vbVersion)
00129 {
00130   LPSTR szNum1 = NULL;
00131   LPSTR szNum2 = NULL;
00132   LPSTR szNum3 = NULL;
00133   LPSTR szNum4 = NULL;
00134   LPSTR szJavaBuild = NULL;
00135 
00136   char *strVer = nsnull;
00137   if (szVersion) {
00138     strVer = PL_strdup(szVersion);
00139   }
00140 
00141   if (!strVer) {
00142     // Out of memory
00143     ClearVersion(vbVersion);
00144     return;
00145   }
00146 
00147   // Java may be using an underscore instead of a dot for the build ID
00148   szJavaBuild = strchr(strVer, '_');
00149   if (szJavaBuild) {
00150     szJavaBuild[0] = '.';
00151   }
00152 
00153   szNum1 = strtok(strVer, ".");
00154   szNum2 = strtok(NULL,   ".");
00155   szNum3 = strtok(NULL,   ".");
00156   szNum4 = strtok(NULL,   ".");
00157 
00158   vbVersion->wMajor   = szNum1 ? atoi(szNum1) : 0;
00159   vbVersion->wMinor   = szNum2 ? atoi(szNum2) : 0;
00160   vbVersion->wRelease = szNum3 ? atoi(szNum3) : 0;
00161   vbVersion->wBuild   = szNum4 ? atoi(szNum4) : 0;
00162 
00163   PL_strfree(strVer);
00164 }
00165 
00166 // Compare two version struct, return zero if the same
00167 static int
00168 CompareVersion(verBlock vbVersionOld, verBlock vbVersionNew)
00169 {
00170   if (vbVersionOld.wMajor > vbVersionNew.wMajor) {
00171     return 4;
00172   } else if (vbVersionOld.wMajor < vbVersionNew.wMajor) {
00173     return -4;
00174   }
00175 
00176   if (vbVersionOld.wMinor > vbVersionNew.wMinor) {
00177     return 3;
00178   } else if (vbVersionOld.wMinor < vbVersionNew.wMinor) {
00179     return -3;
00180   }
00181 
00182   if (vbVersionOld.wRelease > vbVersionNew.wRelease) {
00183     return 2;
00184   } else if (vbVersionOld.wRelease < vbVersionNew.wRelease) {
00185     return -2;
00186   }
00187 
00188   if (vbVersionOld.wBuild > vbVersionNew.wBuild) {
00189     return 1;
00190   } else if (vbVersionOld.wBuild < vbVersionNew.wBuild) {
00191     return -1;
00192   }
00193 
00194   /* the versions are all the same */
00195   return 0;
00196 }
00197 #endif
00198 
00199 //*****************************************************************************
00200 // nsPluginDirServiceProvider::Constructor/Destructor
00201 //*****************************************************************************
00202 
00203 nsPluginDirServiceProvider::nsPluginDirServiceProvider()
00204 {
00205 }
00206 
00207 nsPluginDirServiceProvider::~nsPluginDirServiceProvider()
00208 {
00209 }
00210 
00211 //*****************************************************************************
00212 // nsPluginDirServiceProvider::nsISupports
00213 //*****************************************************************************
00214 
00215 NS_IMPL_THREADSAFE_ISUPPORTS1(nsPluginDirServiceProvider,
00216                               nsIDirectoryServiceProvider)
00217 
00218 //*****************************************************************************
00219 // nsPluginDirServiceProvider::nsIDirectoryServiceProvider
00220 //*****************************************************************************
00221 
00222 NS_IMETHODIMP
00223 nsPluginDirServiceProvider::GetFile(const char *prop, PRBool *persistant,
00224                                     nsIFile **_retval)
00225 {
00226   nsCOMPtr<nsILocalFile>  localFile;
00227   nsresult rv = NS_ERROR_FAILURE;
00228 
00229   NS_ENSURE_ARG(prop);
00230   *_retval = nsnull;
00231   *persistant = PR_TRUE;
00232 
00233 #if defined(XP_WIN)
00234   nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
00235   if (!prefs) {
00236     return rv;
00237   }
00238 
00239   if (nsCRT::strcmp(prop, NS_WIN_4DOTX_SCAN_KEY) == 0) {
00240     // Check our prefs to see if scanning the 4.x folder has been
00241     // explictly overriden failure to get the pref is okay, we'll do
00242     // what we've been doing -- a filtered scan
00243     PRBool bScan4x;
00244     if (NS_SUCCEEDED(prefs->GetBoolPref(NS_WIN_4DOTX_SCAN_KEY, &bScan4x)) &&
00245         !bScan4x) {
00246       return rv;
00247     }
00248 
00249     // Look for the plugin folder that the user has in their
00250     // Communicator 4x install
00251     HKEY keyloc;
00252     long result;
00253     DWORD type;
00254     char szKey[_MAX_PATH] = "Software\\Netscape\\Netscape Navigator";
00255     char path[_MAX_PATH];
00256 
00257     result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &keyloc);
00258 
00259     if (result == ERROR_SUCCESS) {
00260       char current_version[80];
00261       DWORD length = sizeof(current_version);
00262 
00263       result = ::RegQueryValueEx(keyloc, "CurrentVersion", NULL, &type,
00264                                  (LPBYTE)&current_version, &length);
00265 
00266       ::RegCloseKey(keyloc);
00267       PL_strcat(szKey, "\\");
00268       PL_strcat(szKey, current_version);
00269       PL_strcat(szKey, "\\Main");
00270       result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &keyloc);
00271 
00272       if (result == ERROR_SUCCESS) {
00273         DWORD pathlen = sizeof(path);
00274 
00275         result = ::RegQueryValueEx(keyloc, "Plugins Directory", NULL, &type,
00276                                    (LPBYTE)&path, &pathlen);
00277         if (result == ERROR_SUCCESS) {
00278           rv = NS_NewNativeLocalFile(nsDependentCString(path), PR_TRUE,
00279                                      getter_AddRefs(localFile));
00280         }
00281 
00282         ::RegCloseKey(keyloc);
00283       }
00284     }
00285   } else if (nsCRT::strcmp(prop, NS_WIN_JRE_SCAN_KEY) == 0) {
00286     PRBool isJavaEnabled;
00287     nsXPIDLCString strVer;
00288 #ifdef OJI
00289     if ((NS_FAILED(prefs->GetBoolPref("security.enable_java", &isJavaEnabled))
00290          || !isJavaEnabled) ||
00291         NS_FAILED(prefs->GetCharPref(prop, getter_Copies(strVer))))
00292 #endif /* OJI */
00293       return NS_ERROR_FAILURE;
00294     verBlock minVer;
00295     TranslateVersionStr(strVer.get(), &minVer);
00296 
00297     // Look for the Java OJI plugin via the JRE install path
00298     HKEY baseloc;
00299     HKEY keyloc;
00300     HKEY entryloc;
00301     FILETIME modTime;
00302     DWORD type;
00303     DWORD index = 0;
00304     DWORD numChars = _MAX_PATH;
00305     DWORD pathlen;
00306     verBlock maxVer;
00307     ClearVersion(&maxVer);
00308     char curKey[_MAX_PATH] = "Software\\JavaSoft\\Java Runtime Environment";
00309     char path[_MAX_PATH];
00310     // Add + 4 to prevent buffer overrun when adding \bin
00311     char newestPath[_MAX_PATH + 4];
00312     const char mozPath[_MAX_PATH] = "Software\\mozilla.org\\Mozilla";
00313     char browserJavaVersion[_MAX_PATH];
00314 
00315     newestPath[0] = 0;
00316     LONG result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, curKey, 0, KEY_READ,
00317                                  &baseloc);
00318     if (ERROR_SUCCESS != result)
00319       return NS_ERROR_FAILURE;
00320 
00321     // Look for "BrowserJavaVersion"
00322     if (ERROR_SUCCESS != ::RegQueryValueEx(baseloc, "BrowserJavaVersion", NULL,
00323                                            NULL, (LPBYTE)&browserJavaVersion,
00324                                            &numChars))
00325       browserJavaVersion[0] = 0;
00326 
00327     // We must enumerate through the keys because what if there is
00328     // more than one version?
00329     do {
00330       path[0] = 0;
00331       numChars = _MAX_PATH;
00332       pathlen = sizeof(path);
00333       result = ::RegEnumKeyEx(baseloc, index, curKey, &numChars, NULL, NULL,
00334                               NULL, &modTime);
00335       index++;
00336 
00337       // Skip major.minor as it always points to latest in its family
00338       numChars = 0;
00339       for (char *p = curKey; *p; p++) {
00340         if (*p == '.') {
00341           numChars++;
00342         }
00343       }
00344       if (numChars < 2)
00345         continue;
00346 
00347       if (ERROR_SUCCESS == result) {
00348         if (ERROR_SUCCESS == ::RegOpenKeyEx(baseloc, curKey, 0,
00349                                             KEY_QUERY_VALUE, &keyloc)) {
00350           // We have a sub key
00351           if (ERROR_SUCCESS == ::RegQueryValueEx(keyloc, "JavaHome", NULL,
00352                                                  &type, (LPBYTE)&path,
00353                                                  &pathlen)) {
00354             verBlock curVer;
00355             TranslateVersionStr(curKey, &curVer);
00356             if (CompareVersion(curVer, minVer) >= 0) {
00357               if (!strncmp(browserJavaVersion, curKey, _MAX_PATH)) {
00358                 PL_strcpy(newestPath, path);
00359                 ::RegCloseKey(keyloc);
00360                 break;
00361               }
00362 
00363               if (CompareVersion(curVer, maxVer) >= 0) {
00364                 PL_strcpy(newestPath, path);
00365                 CopyVersion(&maxVer, &curVer);
00366               }
00367             }
00368           }
00369           ::RegCloseKey(keyloc);
00370         }
00371       }
00372     } while (ERROR_SUCCESS == result);
00373 
00374     ::RegCloseKey(baseloc);
00375 
00376     // If nothing is found, then don't add \bin dir and don't set
00377     // CurrentVersion for Mozilla
00378     if (newestPath[0] != 0) {
00379       if (ERROR_SUCCESS == ::RegCreateKeyEx(HKEY_LOCAL_MACHINE, mozPath, 0,
00380                                             NULL, REG_OPTION_NON_VOLATILE,
00381                                             KEY_SET_VALUE|KEY_QUERY_VALUE,
00382                                             NULL, &entryloc, NULL)) {
00383         if (ERROR_SUCCESS != ::RegQueryValueEx(entryloc, "CurrentVersion", 0,
00384                                                NULL, NULL, NULL)) {
00385           ::RegSetValueEx(entryloc, "CurrentVersion", 0, REG_SZ,
00386                           (const BYTE*)MOZILLA_VERSION,
00387                           sizeof(MOZILLA_VERSION));
00388         }
00389         ::RegCloseKey(entryloc);
00390       }
00391 
00392       PL_strcat(newestPath,"\\bin");
00393       rv = NS_NewNativeLocalFile(nsDependentCString(newestPath), PR_TRUE,
00394                                  getter_AddRefs(localFile));
00395     }
00396   } else if (nsCRT::strcmp(prop, NS_WIN_QUICKTIME_SCAN_KEY) == 0) {
00397     nsXPIDLCString strVer;
00398     if (NS_FAILED(prefs->GetCharPref(prop, getter_Copies(strVer))))
00399       return NS_ERROR_FAILURE;
00400     verBlock minVer;
00401     TranslateVersionStr(strVer.get(), &minVer);
00402 
00403     // Look for the Quicktime system installation plugins directory
00404     HKEY keyloc;
00405     long result;
00406     DWORD type;
00407     verBlock qtVer;
00408     ClearVersion(&qtVer);
00409     char path[_MAX_PATH];
00410     DWORD pathlen = sizeof(path);
00411 
00412     // First we need to check the version of Quicktime via checking
00413     // the EXE's version table
00414     if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, "software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\QuickTimePlayer.exe", 0, KEY_READ, &keyloc)) {
00415       if (ERROR_SUCCESS == ::RegQueryValueEx(keyloc, NULL, NULL, &type,
00416                                              (LPBYTE)&path, &pathlen)) {
00417         GetFileVersion((char*)path, &qtVer);
00418       }
00419       ::RegCloseKey(keyloc);
00420     }
00421     if (CompareVersion(qtVer, minVer) < 0)
00422       return rv;
00423 
00424     if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, "software\\Apple Computer, Inc.\\QuickTime", 0, KEY_READ, &keyloc)) {
00425       DWORD pathlen = sizeof(path);
00426 
00427       result = ::RegQueryValueEx(keyloc, "InstallDir", NULL, &type,
00428                                  (LPBYTE)&path, &pathlen);
00429       PL_strcat(path, "\\Plugins");
00430       if (result == ERROR_SUCCESS)
00431         rv = NS_NewNativeLocalFile(nsDependentCString(path), PR_TRUE,
00432                                    getter_AddRefs(localFile));
00433       ::RegCloseKey(keyloc);
00434     }
00435   } else if (nsCRT::strcmp(prop, NS_WIN_WMP_SCAN_KEY) == 0) {
00436     nsXPIDLCString strVer;
00437     if (NS_FAILED(prefs->GetCharPref(prop, getter_Copies(strVer))))
00438       return NS_ERROR_FAILURE;
00439     verBlock minVer;
00440     TranslateVersionStr(strVer.get(), &minVer);
00441 
00442     // Look for Windows Media Player system installation plugins directory
00443     HKEY keyloc;
00444     DWORD type;
00445     verBlock wmpVer;
00446     ClearVersion(&wmpVer);
00447     char path[_MAX_PATH];
00448     DWORD pathlen = sizeof(path);
00449 
00450     // First we need to check the version of WMP
00451     if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, "software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wmplayer.exe", 0, KEY_READ, &keyloc)) {
00452       if (ERROR_SUCCESS == ::RegQueryValueEx(keyloc, NULL, NULL, &type,
00453                                              (LPBYTE)&path, &pathlen)) {
00454         GetFileVersion((char*)path, &wmpVer);
00455       }
00456       ::RegCloseKey(keyloc);
00457     }
00458     if (CompareVersion(wmpVer, minVer) < 0)
00459       return rv;
00460 
00461     if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
00462                                         "software\\Microsoft\\MediaPlayer", 0,
00463                                         KEY_READ, &keyloc)) {
00464       if (ERROR_SUCCESS == ::RegQueryValueEx(keyloc, "Installation Directory",
00465                                              NULL, &type, (LPBYTE)&path,
00466                                              &pathlen)) {
00467         rv = NS_NewNativeLocalFile(nsDependentCString(path), PR_TRUE,
00468                                    getter_AddRefs(localFile));
00469       }
00470 
00471       ::RegCloseKey(keyloc);
00472     }
00473   } else if (nsCRT::strcmp(prop, NS_WIN_ACROBAT_SCAN_KEY) == 0) {
00474     nsXPIDLCString strVer;
00475     if (NS_FAILED(prefs->GetCharPref(prop, getter_Copies(strVer)))) {
00476       return NS_ERROR_FAILURE;
00477     }
00478 
00479     verBlock minVer;
00480     TranslateVersionStr(strVer.get(), &minVer);
00481 
00482     // Look for Adobe Acrobat system installation plugins directory
00483     HKEY baseloc;
00484     HKEY keyloc;
00485     FILETIME modTime;
00486     DWORD type;
00487     DWORD index = 0;
00488     DWORD numChars = _MAX_PATH;
00489     DWORD pathlen;
00490     verBlock maxVer;
00491     ClearVersion(&maxVer);
00492     char curKey[_MAX_PATH] = "software\\Adobe\\Acrobat Reader";
00493     char path[_MAX_PATH];
00494     // Add + 8 to prevent buffer overrun when adding \browser
00495     char newestPath[_MAX_PATH + 8];
00496 
00497     newestPath[0] = 0;
00498     if (ERROR_SUCCESS != ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, curKey, 0,
00499                                         KEY_READ, &baseloc)) {
00500       PL_strcpy(curKey, "software\\Adobe\\Adobe Acrobat");
00501       if (ERROR_SUCCESS != ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, curKey, 0,
00502                                           KEY_READ, &baseloc)) {
00503         return NS_ERROR_FAILURE;
00504       }
00505     }
00506 
00507     // We must enumerate through the keys because what if there is
00508     // more than one version?
00509     LONG result = ERROR_SUCCESS;
00510     while (ERROR_SUCCESS == result) {
00511       path[0] = 0;
00512       numChars = _MAX_PATH;
00513       pathlen = sizeof(path);
00514       result = ::RegEnumKeyEx(baseloc, index, curKey, &numChars, NULL, NULL,
00515                               NULL, &modTime);
00516       index++;
00517 
00518       if (ERROR_SUCCESS == result) {
00519         verBlock curVer;
00520         TranslateVersionStr(curKey, &curVer);
00521         PL_strcat(curKey, "\\InstallPath");
00522         if (ERROR_SUCCESS == ::RegOpenKeyEx(baseloc, curKey, 0,
00523                                             KEY_QUERY_VALUE, &keyloc)) {
00524           // We have a sub key
00525           if (ERROR_SUCCESS == ::RegQueryValueEx(keyloc, NULL, NULL, &type,
00526                                                  (LPBYTE)&path, &pathlen)) {
00527             if (CompareVersion(curVer, maxVer) >= 0 &&
00528                 CompareVersion(curVer, minVer) >= 0) {
00529               PL_strcpy(newestPath, path);
00530               CopyVersion(&maxVer, &curVer);
00531             }
00532           }
00533 
00534           ::RegCloseKey(keyloc);
00535         }
00536       }
00537     }
00538 
00539     ::RegCloseKey(baseloc);
00540 
00541     if (newestPath[0] != 0) {
00542       PL_strcat(newestPath,"\\browser");
00543       rv = NS_NewNativeLocalFile(nsDependentCString(newestPath), PR_TRUE,
00544                                  getter_AddRefs(localFile));
00545     }
00546 
00547   }
00548 #endif
00549 
00550   if (localFile && NS_SUCCEEDED(rv))
00551     return CallQueryInterface(localFile, _retval);
00552 
00553   return rv;
00554 }
00555 
00556 #ifdef XP_WIN
00557 nsresult
00558 nsPluginDirServiceProvider::GetPLIDDirectories(nsISimpleEnumerator **aEnumerator)
00559 {
00560   NS_ENSURE_ARG_POINTER(aEnumerator);
00561   *aEnumerator = nsnull;
00562 
00563   nsCOMArray<nsILocalFile> dirs;
00564 
00565   HKEY baseloc;
00566   HKEY keyloc;
00567   char curKey[_MAX_PATH] = "Software\\MozillaPlugins";
00568 
00569   LONG result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, curKey, 0, KEY_READ,
00570                                &baseloc);
00571   if (ERROR_SUCCESS != result)
00572     return NS_ERROR_FAILURE;
00573 
00574   DWORD index = 0;
00575   do {
00576     DWORD numChars = _MAX_PATH;
00577     FILETIME modTime;
00578     DWORD type;
00579     char path[_MAX_PATH];
00580     DWORD pathlen = sizeof(path);
00581 
00582     result = ::RegEnumKeyEx(baseloc, index++, curKey, &numChars, NULL, NULL,
00583                             NULL, &modTime);
00584 
00585     if (ERROR_SUCCESS == ::RegOpenKeyEx(baseloc, curKey, 0, KEY_QUERY_VALUE,
00586                                         &keyloc)) {
00587       if (ERROR_SUCCESS == ::RegQueryValueEx(keyloc, "Path", NULL, &type,
00588                                              (LPBYTE)&path, &pathlen)) {
00589         nsCOMPtr<nsILocalFile> localFile;
00590         if (NS_SUCCEEDED(NS_NewNativeLocalFile(nsDependentCString(path),
00591                                                PR_TRUE,
00592                                                getter_AddRefs(localFile))) &&
00593             localFile) {
00594           // Some vendors use a path directly to the DLL so chop off
00595           // the filename
00596           PRBool isDir = PR_FALSE;
00597           if (NS_SUCCEEDED(localFile->IsDirectory(&isDir)) && !isDir) {
00598             nsCOMPtr<nsIFile> temp;
00599             localFile->GetParent(getter_AddRefs(temp));
00600             if (temp)
00601               localFile = do_QueryInterface(temp);
00602           }
00603 
00604           // Now we check to make sure it's actually on disk and
00605           // To see if we already have this directory in the array
00606           PRBool isFileThere = PR_FALSE;
00607           PRBool isDupEntry = PR_FALSE;
00608           if (NS_SUCCEEDED(localFile->Exists(&isFileThere)) && isFileThere) {
00609             PRInt32 c = dirs.Count();
00610             for (PRInt32 i = 0; i < c; i++) {
00611               nsIFile *dup = NS_STATIC_CAST(nsIFile*, dirs[i]);
00612               if (dup &&
00613                   NS_SUCCEEDED(dup->Equals(localFile, &isDupEntry)) &&
00614                   isDupEntry) {
00615                 break;
00616               }
00617             }
00618 
00619             if (!isDupEntry) {
00620               dirs.AppendObject(localFile);
00621             }
00622           }
00623         }
00624       }
00625       ::RegCloseKey(keyloc);
00626     }
00627   } while (ERROR_SUCCESS == result);
00628 
00629   ::RegCloseKey(baseloc);
00630 
00631   return NS_NewArrayEnumerator(aEnumerator, dirs);
00632 }
00633 
00634 #endif
00635