Bug 470455 - test_database_sync_embed_visits.js leaks, r=sdwilsh
[wine-gecko.git] / modules / plugin / base / src / nsPluginDirServiceProvider.cpp
blob572a1f32c07d7e26f2975c7ecd17521d1b29a42e
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 2001
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Conrad Carlen <ccarlen@netscape.com>
24 * Ere Maijala <emaijala@kolumbus.fi>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either the GNU General Public License Version 2 or later (the "GPL"), or
28 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "nsPluginDirServiceProvider.h"
42 #include "nsCRT.h"
43 #include "nsILocalFile.h"
44 #include "nsIPrefBranch.h"
45 #include "nsIPrefService.h"
46 #include "nsDependentString.h"
47 #include "nsXPIDLString.h"
48 #include "prmem.h"
49 #include "nsArrayEnumerator.h"
51 typedef struct structVer
53 WORD wMajor;
54 WORD wMinor;
55 WORD wRelease;
56 WORD wBuild;
57 } verBlock;
59 static void
60 ClearVersion(verBlock *ver)
62 ver->wMajor = 0;
63 ver->wMinor = 0;
64 ver->wRelease = 0;
65 ver->wBuild = 0;
68 static BOOL
69 FileExists(LPCSTR szFile)
71 return GetFileAttributes(szFile) != 0xFFFFFFFF;
74 // Get file version information from a file
75 static BOOL
76 GetFileVersion(LPSTR szFile, verBlock *vbVersion)
78 UINT uLen;
79 UINT dwLen;
80 BOOL bRv;
81 DWORD dwHandle;
82 LPVOID lpData;
83 LPVOID lpBuffer;
84 VS_FIXEDFILEINFO *lpBuffer2;
86 ClearVersion(vbVersion);
87 if (FileExists(szFile)) {
88 bRv = TRUE;
89 dwLen = GetFileVersionInfoSize(szFile, &dwHandle);
90 lpData = (LPVOID)malloc(dwLen);
91 uLen = 0;
93 if (lpData && GetFileVersionInfo(szFile, dwHandle, dwLen, lpData) != 0) {
94 if (VerQueryValue(lpData, "\\", &lpBuffer, &uLen) != 0) {
95 lpBuffer2 = (VS_FIXEDFILEINFO *)lpBuffer;
97 vbVersion->wMajor = HIWORD(lpBuffer2->dwFileVersionMS);
98 vbVersion->wMinor = LOWORD(lpBuffer2->dwFileVersionMS);
99 vbVersion->wRelease = HIWORD(lpBuffer2->dwFileVersionLS);
100 vbVersion->wBuild = LOWORD(lpBuffer2->dwFileVersionLS);
104 free(lpData);
105 } else {
106 /* File does not exist */
107 bRv = FALSE;
110 return bRv;
113 // Will deep copy ver2 into ver1
114 static void
115 CopyVersion(verBlock *ver1, verBlock *ver2)
117 ver1->wMajor = ver2->wMajor;
118 ver1->wMinor = ver2->wMinor;
119 ver1->wRelease = ver2->wRelease;
120 ver1->wBuild = ver2->wBuild;
123 // Convert a string version to a version struct
124 static void
125 TranslateVersionStr(const char* szVersion, verBlock *vbVersion)
127 LPSTR szNum1 = NULL;
128 LPSTR szNum2 = NULL;
129 LPSTR szNum3 = NULL;
130 LPSTR szNum4 = NULL;
131 LPSTR szJavaBuild = NULL;
133 char *strVer = nsnull;
134 if (szVersion) {
135 strVer = PL_strdup(szVersion);
138 if (!strVer) {
139 // Out of memory
140 ClearVersion(vbVersion);
141 return;
144 // Java may be using an underscore instead of a dot for the build ID
145 szJavaBuild = strchr(strVer, '_');
146 if (szJavaBuild) {
147 szJavaBuild[0] = '.';
150 szNum1 = strtok(strVer, ".");
151 szNum2 = strtok(NULL, ".");
152 szNum3 = strtok(NULL, ".");
153 szNum4 = strtok(NULL, ".");
155 vbVersion->wMajor = szNum1 ? atoi(szNum1) : 0;
156 vbVersion->wMinor = szNum2 ? atoi(szNum2) : 0;
157 vbVersion->wRelease = szNum3 ? atoi(szNum3) : 0;
158 vbVersion->wBuild = szNum4 ? atoi(szNum4) : 0;
160 PL_strfree(strVer);
163 // Compare two version struct, return zero if the same
164 static int
165 CompareVersion(verBlock vbVersionOld, verBlock vbVersionNew)
167 if (vbVersionOld.wMajor > vbVersionNew.wMajor) {
168 return 4;
169 } else if (vbVersionOld.wMajor < vbVersionNew.wMajor) {
170 return -4;
173 if (vbVersionOld.wMinor > vbVersionNew.wMinor) {
174 return 3;
175 } else if (vbVersionOld.wMinor < vbVersionNew.wMinor) {
176 return -3;
179 if (vbVersionOld.wRelease > vbVersionNew.wRelease) {
180 return 2;
181 } else if (vbVersionOld.wRelease < vbVersionNew.wRelease) {
182 return -2;
185 if (vbVersionOld.wBuild > vbVersionNew.wBuild) {
186 return 1;
187 } else if (vbVersionOld.wBuild < vbVersionNew.wBuild) {
188 return -1;
191 /* the versions are all the same */
192 return 0;
195 #ifdef OJI
196 // Indicate whether we should try to use the new NPRuntime-based Java
197 // Plug-In if it's available
198 static PRBool
199 TryToUseNPRuntimeJavaPlugIn(const char* javaVersion)
201 HKEY javaKey = NULL;
202 char keyName[_MAX_PATH];
203 keyName[0] = 0;
204 PL_strcat(keyName, "Software\\JavaSoft\\Java Plug-in\\");
205 PL_strcat(keyName, javaVersion);
206 DWORD val;
207 DWORD valSize = sizeof(DWORD);
209 if (ERROR_SUCCESS != ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
210 keyName, 0, KEY_READ, &javaKey)) {
211 return FALSE;
214 // Look for "UseNewJavaPlugin"
215 if (ERROR_SUCCESS != ::RegQueryValueEx(javaKey, "UseNewJavaPlugin",
216 NULL, NULL,
217 (LPBYTE) &val,
218 &valSize)) {
219 val = 0;
222 ::RegCloseKey(javaKey);
223 return (val == 0) ? PR_FALSE : PR_TRUE;
225 #endif
227 //*****************************************************************************
228 // nsPluginDirServiceProvider::Constructor/Destructor
229 //*****************************************************************************
231 nsPluginDirServiceProvider::nsPluginDirServiceProvider()
235 nsPluginDirServiceProvider::~nsPluginDirServiceProvider()
239 //*****************************************************************************
240 // nsPluginDirServiceProvider::nsISupports
241 //*****************************************************************************
243 NS_IMPL_THREADSAFE_ISUPPORTS1(nsPluginDirServiceProvider,
244 nsIDirectoryServiceProvider)
246 //*****************************************************************************
247 // nsPluginDirServiceProvider::nsIDirectoryServiceProvider
248 //*****************************************************************************
250 NS_IMETHODIMP
251 nsPluginDirServiceProvider::GetFile(const char *prop, PRBool *persistant,
252 nsIFile **_retval)
254 nsCOMPtr<nsILocalFile> localFile;
255 nsresult rv = NS_ERROR_FAILURE;
257 NS_ENSURE_ARG(prop);
258 *_retval = nsnull;
259 *persistant = PR_FALSE;
261 nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
262 if (!prefs) {
263 return rv;
266 if (nsCRT::strcmp(prop, NS_WIN_4DOTX_SCAN_KEY) == 0) {
267 // Check our prefs to see if scanning the 4.x folder has been
268 // explictly overriden failure to get the pref is okay, we'll do
269 // what we've been doing -- a filtered scan
270 PRBool bScan4x;
271 if (NS_SUCCEEDED(prefs->GetBoolPref(NS_WIN_4DOTX_SCAN_KEY, &bScan4x)) &&
272 !bScan4x) {
273 return rv;
276 // Look for the plugin folder that the user has in their
277 // Communicator 4x install
278 HKEY keyloc;
279 long result;
280 DWORD type;
281 char szKey[_MAX_PATH] = "Software\\Netscape\\Netscape Navigator";
282 char path[_MAX_PATH];
284 result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &keyloc);
286 if (result == ERROR_SUCCESS) {
287 char current_version[80];
288 DWORD length = sizeof(current_version);
290 result = ::RegQueryValueEx(keyloc, "CurrentVersion", NULL, &type,
291 (LPBYTE)&current_version, &length);
293 ::RegCloseKey(keyloc);
294 PL_strcat(szKey, "\\");
295 PL_strcat(szKey, current_version);
296 PL_strcat(szKey, "\\Main");
297 result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, szKey, 0, KEY_READ, &keyloc);
299 if (result == ERROR_SUCCESS) {
300 DWORD pathlen = sizeof(path);
302 result = ::RegQueryValueEx(keyloc, "Plugins Directory", NULL, &type,
303 (LPBYTE)&path, &pathlen);
304 if (result == ERROR_SUCCESS) {
305 rv = NS_NewNativeLocalFile(nsDependentCString(path), PR_TRUE,
306 getter_AddRefs(localFile));
309 ::RegCloseKey(keyloc);
312 } else if (nsCRT::strcmp(prop, NS_WIN_JRE_SCAN_KEY) == 0) {
313 nsXPIDLCString strVer;
314 if (NS_FAILED(prefs->GetCharPref(prop, getter_Copies(strVer))))
315 return NS_ERROR_FAILURE;
316 verBlock minVer;
317 TranslateVersionStr(strVer.get(), &minVer);
319 // Look for the Java OJI plugin via the JRE install path
320 HKEY baseloc;
321 HKEY keyloc;
322 HKEY entryloc;
323 FILETIME modTime;
324 DWORD type;
325 DWORD index = 0;
326 DWORD numChars = _MAX_PATH;
327 DWORD pathlen;
328 verBlock maxVer;
329 ClearVersion(&maxVer);
330 char curKey[_MAX_PATH] = "Software\\JavaSoft\\Java Runtime Environment";
331 char path[_MAX_PATH];
332 // Add + 15 to prevent buffer overrun when adding \bin (+ optionally
333 // \new_plugin)
334 #define JAVA_PATH_SIZE _MAX_PATH + 15
335 char newestPath[JAVA_PATH_SIZE];
336 const char mozPath[_MAX_PATH] = "Software\\mozilla.org\\Mozilla";
337 char browserJavaVersion[_MAX_PATH];
338 PRBool tryNPRuntimeJavaPlugIn =
339 #ifdef OJI
340 PR_FALSE;
341 #else
342 PR_TRUE;
343 #endif
345 newestPath[0] = 0;
346 LONG result = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, curKey, 0, KEY_READ,
347 &baseloc);
348 if (ERROR_SUCCESS != result)
349 return NS_ERROR_FAILURE;
351 // Look for "BrowserJavaVersion"
352 if (ERROR_SUCCESS != ::RegQueryValueEx(baseloc, "BrowserJavaVersion", NULL,
353 NULL, (LPBYTE)&browserJavaVersion,
354 &numChars))
355 browserJavaVersion[0] = 0;
357 // We must enumerate through the keys because what if there is
358 // more than one version?
359 do {
360 path[0] = 0;
361 numChars = _MAX_PATH;
362 pathlen = sizeof(path);
363 result = ::RegEnumKeyEx(baseloc, index, curKey, &numChars, NULL, NULL,
364 NULL, &modTime);
365 index++;
367 // Skip major.minor as it always points to latest in its family
368 numChars = 0;
369 for (char *p = curKey; *p; p++) {
370 if (*p == '.') {
371 numChars++;
374 if (numChars < 2)
375 continue;
377 if (ERROR_SUCCESS == result) {
378 if (ERROR_SUCCESS == ::RegOpenKeyEx(baseloc, curKey, 0,
379 KEY_QUERY_VALUE, &keyloc)) {
380 // We have a sub key
381 if (ERROR_SUCCESS == ::RegQueryValueEx(keyloc, "JavaHome", NULL,
382 &type, (LPBYTE)&path,
383 &pathlen)) {
384 verBlock curVer;
385 TranslateVersionStr(curKey, &curVer);
386 if (CompareVersion(curVer, minVer) >= 0) {
387 if (!strncmp(browserJavaVersion, curKey, _MAX_PATH)) {
388 PL_strcpy(newestPath, path);
389 #ifdef OJI
390 tryNPRuntimeJavaPlugIn = TryToUseNPRuntimeJavaPlugIn(curKey);
391 #endif
392 ::RegCloseKey(keyloc);
393 break;
396 if (CompareVersion(curVer, maxVer) >= 0) {
397 PL_strcpy(newestPath, path);
398 CopyVersion(&maxVer, &curVer);
399 #ifdef OJI
400 tryNPRuntimeJavaPlugIn = TryToUseNPRuntimeJavaPlugIn(curKey);
401 #endif
405 ::RegCloseKey(keyloc);
408 } while (ERROR_SUCCESS == result);
410 ::RegCloseKey(baseloc);
412 // If nothing is found, then don't add \bin dir and don't set
413 // CurrentVersion for Mozilla
414 if (newestPath[0] != 0) {
415 if (ERROR_SUCCESS == ::RegCreateKeyEx(HKEY_LOCAL_MACHINE, mozPath, 0,
416 NULL, REG_OPTION_NON_VOLATILE,
417 KEY_SET_VALUE|KEY_QUERY_VALUE,
418 NULL, &entryloc, NULL)) {
419 if (ERROR_SUCCESS != ::RegQueryValueEx(entryloc, "CurrentVersion", 0,
420 NULL, NULL, NULL)) {
421 ::RegSetValueEx(entryloc, "CurrentVersion", 0, REG_SZ,
422 (const BYTE*)MOZILLA_VERSION,
423 sizeof(MOZILLA_VERSION));
425 ::RegCloseKey(entryloc);
428 PL_strcat(newestPath,"\\bin");
430 // See whether we should use the new NPRuntime-based Java Plug-In:
431 // - If tryNPRuntimeJavaPlugIn is true, and
432 // - If the appropriate subdirectory actually exists
433 // Note that this is a temporary code path until the old
434 // OJI-based Java Plug-In isn't being shipped alongside the new
435 // one any more.
436 if (tryNPRuntimeJavaPlugIn) {
437 // See whether the "new_plugin" directory exists
438 char tmpPath[JAVA_PATH_SIZE];
439 PL_strcpy(tmpPath, newestPath);
440 PL_strcat(tmpPath, "\\new_plugin");
441 nsCOMPtr<nsILocalFile> tmpFile;
442 if (NS_SUCCEEDED(NS_NewNativeLocalFile(nsDependentCString(tmpPath),
443 PR_TRUE,
444 getter_AddRefs(tmpFile))) &&
445 tmpFile) {
446 PRBool exists = PR_FALSE;
447 PRBool isDir = PR_FALSE;
448 if (NS_SUCCEEDED(tmpFile->Exists(&exists)) && exists &&
449 NS_SUCCEEDED(tmpFile->IsDirectory(&isDir)) && isDir) {
450 // Assume we're supposed to use this as the search
451 // directory for the Java Plug-In instead of the normal
452 // one
453 PL_strcpy(newestPath, tmpPath);
458 rv = NS_NewNativeLocalFile(nsDependentCString(newestPath), PR_TRUE,
459 getter_AddRefs(localFile));
461 } else if (nsCRT::strcmp(prop, NS_WIN_QUICKTIME_SCAN_KEY) == 0) {
462 nsXPIDLCString strVer;
463 if (NS_FAILED(prefs->GetCharPref(prop, getter_Copies(strVer))))
464 return NS_ERROR_FAILURE;
465 verBlock minVer;
466 TranslateVersionStr(strVer.get(), &minVer);
468 // Look for the Quicktime system installation plugins directory
469 HKEY keyloc;
470 long result;
471 DWORD type;
472 verBlock qtVer;
473 ClearVersion(&qtVer);
474 char path[_MAX_PATH];
475 DWORD pathlen = sizeof(path);
477 // First we need to check the version of Quicktime via checking
478 // the EXE's version table
479 if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, "software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\QuickTimePlayer.exe", 0, KEY_READ, &keyloc)) {
480 if (ERROR_SUCCESS == ::RegQueryValueEx(keyloc, NULL, NULL, &type,
481 (LPBYTE)&path, &pathlen)) {
482 GetFileVersion((char*)path, &qtVer);
484 ::RegCloseKey(keyloc);
486 if (CompareVersion(qtVer, minVer) < 0)
487 return rv;
489 if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, "software\\Apple Computer, Inc.\\QuickTime", 0, KEY_READ, &keyloc)) {
490 DWORD pathlen = sizeof(path);
492 result = ::RegQueryValueEx(keyloc, "InstallDir", NULL, &type,
493 (LPBYTE)&path, &pathlen);
494 PL_strcat(path, "\\Plugins");
495 if (result == ERROR_SUCCESS)
496 rv = NS_NewNativeLocalFile(nsDependentCString(path), PR_TRUE,
497 getter_AddRefs(localFile));
498 ::RegCloseKey(keyloc);
500 } else if (nsCRT::strcmp(prop, NS_WIN_WMP_SCAN_KEY) == 0) {
501 nsXPIDLCString strVer;
502 if (NS_FAILED(prefs->GetCharPref(prop, getter_Copies(strVer))))
503 return NS_ERROR_FAILURE;
504 verBlock minVer;
505 TranslateVersionStr(strVer.get(), &minVer);
507 // Look for Windows Media Player system installation plugins directory
508 HKEY keyloc;
509 DWORD type;
510 verBlock wmpVer;
511 ClearVersion(&wmpVer);
512 char path[_MAX_PATH];
513 DWORD pathlen = sizeof(path);
515 // First we need to check the version of WMP
516 if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, "software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\wmplayer.exe", 0, KEY_READ, &keyloc)) {
517 if (ERROR_SUCCESS == ::RegQueryValueEx(keyloc, NULL, NULL, &type,
518 (LPBYTE)&path, &pathlen)) {
519 GetFileVersion((char*)path, &wmpVer);
521 ::RegCloseKey(keyloc);
523 if (CompareVersion(wmpVer, minVer) < 0)
524 return rv;
526 if (ERROR_SUCCESS == ::RegOpenKeyEx(HKEY_LOCAL_MACHINE,
527 "software\\Microsoft\\MediaPlayer", 0,
528 KEY_READ, &keyloc)) {
529 if (ERROR_SUCCESS == ::RegQueryValueEx(keyloc, "Installation Directory",
530 NULL, &type, (LPBYTE)&path,
531 &pathlen)) {
532 rv = NS_NewNativeLocalFile(nsDependentCString(path), PR_TRUE,
533 getter_AddRefs(localFile));
536 ::RegCloseKey(keyloc);
538 } else if (nsCRT::strcmp(prop, NS_WIN_ACROBAT_SCAN_KEY) == 0) {
539 nsXPIDLCString strVer;
540 if (NS_FAILED(prefs->GetCharPref(prop, getter_Copies(strVer)))) {
541 return NS_ERROR_FAILURE;
544 verBlock minVer;
545 TranslateVersionStr(strVer.get(), &minVer);
547 // Look for Adobe Acrobat system installation plugins directory
548 HKEY baseloc;
549 HKEY keyloc;
550 FILETIME modTime;
551 DWORD type;
552 DWORD index = 0;
553 DWORD numChars = _MAX_PATH;
554 DWORD pathlen;
555 verBlock maxVer;
556 ClearVersion(&maxVer);
557 char curKey[_MAX_PATH] = "software\\Adobe\\Acrobat Reader";
558 char path[_MAX_PATH];
559 // Add + 8 to prevent buffer overrun when adding \browser
560 char newestPath[_MAX_PATH + 8];
562 newestPath[0] = 0;
563 if (ERROR_SUCCESS != ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, curKey, 0,
564 KEY_READ, &baseloc)) {
565 PL_strcpy(curKey, "software\\Adobe\\Adobe Acrobat");
566 if (ERROR_SUCCESS != ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, curKey, 0,
567 KEY_READ, &baseloc)) {
568 return NS_ERROR_FAILURE;
572 // We must enumerate through the keys because what if there is
573 // more than one version?
574 LONG result = ERROR_SUCCESS;
575 while (ERROR_SUCCESS == result) {
576 path[0] = 0;
577 numChars = _MAX_PATH;
578 pathlen = sizeof(path);
579 result = ::RegEnumKeyEx(baseloc, index, curKey, &numChars, NULL, NULL,
580 NULL, &modTime);
581 index++;
583 if (ERROR_SUCCESS == result) {
584 verBlock curVer;
585 TranslateVersionStr(curKey, &curVer);
586 PL_strcat(curKey, "\\InstallPath");
587 if (ERROR_SUCCESS == ::RegOpenKeyEx(baseloc, curKey, 0,
588 KEY_QUERY_VALUE, &keyloc)) {
589 // We have a sub key
590 if (ERROR_SUCCESS == ::RegQueryValueEx(keyloc, NULL, NULL, &type,
591 (LPBYTE)&path, &pathlen)) {
592 if (CompareVersion(curVer, maxVer) >= 0 &&
593 CompareVersion(curVer, minVer) >= 0) {
594 PL_strcpy(newestPath, path);
595 CopyVersion(&maxVer, &curVer);
599 ::RegCloseKey(keyloc);
604 ::RegCloseKey(baseloc);
606 if (newestPath[0] != 0) {
607 PL_strcat(newestPath,"\\browser");
608 rv = NS_NewNativeLocalFile(nsDependentCString(newestPath), PR_TRUE,
609 getter_AddRefs(localFile));
614 if (localFile && NS_SUCCEEDED(rv))
615 return CallQueryInterface(localFile, _retval);
617 return rv;
620 nsresult
621 nsPluginDirServiceProvider::GetPLIDDirectories(nsISimpleEnumerator **aEnumerator)
623 NS_ENSURE_ARG_POINTER(aEnumerator);
624 *aEnumerator = nsnull;
626 nsCOMArray<nsILocalFile> dirs;
628 GetPLIDDirectoriesWithHKEY(HKEY_CURRENT_USER, dirs);
629 GetPLIDDirectoriesWithHKEY(HKEY_LOCAL_MACHINE, dirs);
631 return NS_NewArrayEnumerator(aEnumerator, dirs);
634 nsresult
635 nsPluginDirServiceProvider::GetPLIDDirectoriesWithHKEY(HKEY aKey, nsCOMArray<nsILocalFile> &aDirs)
637 char subkey[_MAX_PATH] = "Software\\MozillaPlugins";
638 HKEY baseloc;
640 if (ERROR_SUCCESS != ::RegOpenKeyEx(aKey, subkey, 0, KEY_READ, &baseloc))
641 return NS_ERROR_FAILURE;
643 DWORD index = 0;
644 DWORD subkeylen = _MAX_PATH;
645 FILETIME modTime;
646 while (ERROR_SUCCESS == ::RegEnumKeyEx(baseloc, index++, subkey, &subkeylen,
647 NULL, NULL, NULL, &modTime)) {
648 subkeylen = _MAX_PATH;
649 HKEY keyloc;
651 if (ERROR_SUCCESS == ::RegOpenKeyEx(baseloc, subkey, 0, KEY_QUERY_VALUE,
652 &keyloc)) {
653 DWORD type;
654 char path[_MAX_PATH];
655 DWORD pathlen = sizeof(path);
657 if (ERROR_SUCCESS == ::RegQueryValueEx(keyloc, "Path", NULL, &type,
658 (LPBYTE)&path, &pathlen)) {
659 nsCOMPtr<nsILocalFile> localFile;
660 if (NS_SUCCEEDED(NS_NewNativeLocalFile(nsDependentCString(path),
661 PR_TRUE,
662 getter_AddRefs(localFile))) &&
663 localFile) {
664 // Some vendors use a path directly to the DLL so chop off
665 // the filename
666 PRBool isDir = PR_FALSE;
667 if (NS_SUCCEEDED(localFile->IsDirectory(&isDir)) && !isDir) {
668 nsCOMPtr<nsIFile> temp;
669 localFile->GetParent(getter_AddRefs(temp));
670 if (temp)
671 localFile = do_QueryInterface(temp);
674 // Now we check to make sure it's actually on disk and
675 // To see if we already have this directory in the array
676 PRBool isFileThere = PR_FALSE;
677 PRBool isDupEntry = PR_FALSE;
678 if (NS_SUCCEEDED(localFile->Exists(&isFileThere)) && isFileThere) {
679 PRInt32 c = aDirs.Count();
680 for (PRInt32 i = 0; i < c; i++) {
681 nsIFile *dup = static_cast<nsIFile*>(aDirs[i]);
682 if (dup &&
683 NS_SUCCEEDED(dup->Equals(localFile, &isDupEntry)) &&
684 isDupEntry) {
685 break;
689 if (!isDupEntry) {
690 aDirs.AppendObject(localFile);
695 ::RegCloseKey(keyloc);
698 ::RegCloseKey(baseloc);
699 return NS_OK;