1 /* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
16 * The Original Code is the Mozilla browser.
18 * The Initial Developer of the Original Code is
19 * Netscape Communications, Inc.
20 * Portions created by the Initial Developer are Copyright (C) 1999
21 * the Initial Developer. All Rights Reserved.
24 * Scott MacGregor <mscott@netscape.com>
25 * Christian Biesinger <cbiesinger@web.de>
27 * Alternatively, the contents of this file may be used under the terms of
28 * either of the GNU General Public License Version 2 or later (the "GPL"),
29 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
30 * in which case the provisions of the GPL or the LGPL are applicable instead
31 * of those above. If you wish to allow use of your version of this file only
32 * under the terms of either the GPL or the LGPL, and not to allow others to
33 * use your version of this file under the terms of the MPL, indicate your
34 * decision by deleting the provisions above and replace them with the notice
35 * and other provisions required by the GPL or the LGPL. If you do not delete
36 * the provisions above, a recipient may use your version of this file under
37 * the terms of any one of the MPL, the GPL or the LGPL.
39 * ***** END LICENSE BLOCK ***** */
41 #include "nsArrayEnumerator.h"
42 #include "nsCOMArray.h"
43 #include "nsILocalFile.h"
44 #include "nsIVariant.h"
45 #include "nsMIMEInfoWin.h"
46 #include "nsNetUtil.h"
49 #include "nsAutoPtr.h"
50 #include "nsIMutableArray.h"
54 #include "nsIWindowsRegKey.h"
55 #include "nsIProcess.h"
56 #include "nsOSHelperAppService.h"
57 #include "nsUnicharUtils.h"
59 NS_IMPL_ISUPPORTS_INHERITED1(nsMIMEInfoWin
, nsMIMEInfoBase
, nsIPropertyBag
)
61 nsMIMEInfoWin::~nsMIMEInfoWin()
66 nsMIMEInfoWin::LaunchDefaultWithFile(nsIFile
* aFile
)
68 // Launch the file, unless it is an executable.
69 nsCOMPtr
<nsILocalFile
> local(do_QueryInterface(aFile
));
71 return NS_ERROR_FAILURE
;
73 PRBool executable
= PR_TRUE
;
74 local
->IsExecutable(&executable
);
76 return NS_ERROR_FAILURE
;
78 return local
->Launch();
82 nsMIMEInfoWin::LaunchWithFile(nsIFile
* aFile
)
86 // it doesn't make any sense to call this on protocol handlers
87 NS_ASSERTION(mClass
== eMIMEInfo
,
88 "nsMIMEInfoBase should have mClass == eMIMEInfo");
90 if (mPreferredAction
== useSystemDefault
) {
91 return LaunchDefaultWithFile(aFile
);
94 if (mPreferredAction
== useHelperApp
) {
95 if (!mPreferredApplication
)
96 return NS_ERROR_FILE_NOT_FOUND
;
98 // at the moment, we only know how to hand files off to local handlers
99 nsCOMPtr
<nsILocalHandlerApp
> localHandler
=
100 do_QueryInterface(mPreferredApplication
, &rv
);
101 NS_ENSURE_SUCCESS(rv
, rv
);
103 nsCOMPtr
<nsIFile
> executable
;
104 rv
= localHandler
->GetExecutable(getter_AddRefs(executable
));
105 NS_ENSURE_SUCCESS(rv
, rv
);
108 aFile
->GetNativePath(path
);
110 // Deal with local dll based handlers
112 executable
->GetNativeLeafName(filename
);
113 if (filename
.Length() > 4) {
114 nsCString
extension(Substring(filename
, filename
.Length() - 4, 4));
116 if (extension
.LowerCaseEqualsLiteral(".dll")) {
119 // executable is rundll32, everything else is a list of parameters,
120 // including the dll handler.
121 nsCOMPtr
<nsILocalFile
> locFile(do_QueryInterface(aFile
));
123 if (!GetDllLaunchInfo(executable
, locFile
, args
, PR_FALSE
))
124 return NS_ERROR_INVALID_ARG
;
126 PRUint32 result
= (PRUint32
)
127 ::ShellExecuteW(NULL
, NULL
, L
"rundll32.exe", args
.get(),
128 NULL
, SW_SHOWNORMAL
);
129 // Returns a value greater than 32 if successful. See msdn.
136 return NS_ERROR_OUT_OF_MEMORY
;
137 case ERROR_FILE_NOT_FOUND
:
138 return NS_ERROR_FILE_NOT_FOUND
;
139 case ERROR_PATH_NOT_FOUND
:
140 return NS_ERROR_FILE_UNRECOGNIZED_PATH
;
141 case ERROR_BAD_FORMAT
:
142 return NS_ERROR_FILE_CORRUPTED
;
143 case SE_ERR_ACCESSDENIED
:
144 return NS_ERROR_FILE_ACCESS_DENIED
;
145 case SE_ERR_ASSOCINCOMPLETE
:
147 return NS_ERROR_UNEXPECTED
;
150 case SE_ERR_DDETIMEOUT
:
151 return NS_ERROR_NOT_AVAILABLE
;
152 case SE_ERR_DLLNOTFOUND
:
153 return NS_ERROR_FAILURE
;
155 return NS_ERROR_FILE_IS_LOCKED
;
157 return NS_ERROR_FILE_EXECUTION_FAILED
;
160 return LaunchWithIProcess(executable
, path
);
163 return NS_ERROR_INVALID_ARG
;
167 nsMIMEInfoWin::GetHasDefaultHandler(PRBool
* _retval
)
169 // We have a default application if we have a description
170 // We can ShellExecute anything; however, callers are probably interested if
171 // there is really an application associated with this type of file
172 *_retval
= !mDefaultAppDescription
.IsEmpty();
177 nsMIMEInfoWin::GetEnumerator(nsISimpleEnumerator
* *_retval
)
179 nsCOMArray
<nsIVariant
> properties
;
181 nsCOMPtr
<nsIVariant
> variant
;
182 GetProperty(NS_LITERAL_STRING("defaultApplicationIconURL"), getter_AddRefs(variant
));
184 properties
.AppendObject(variant
);
186 GetProperty(NS_LITERAL_STRING("customApplicationIconURL"), getter_AddRefs(variant
));
188 properties
.AppendObject(variant
);
190 return NS_NewArrayEnumerator(_retval
, properties
);
193 static nsresult
GetIconURLVariant(nsIFile
* aApplication
, nsIVariant
* *_retval
)
195 nsresult rv
= CallCreateInstance("@mozilla.org/variant;1", _retval
);
198 nsCAutoString fileURLSpec
;
199 NS_GetURLSpecFromFile(aApplication
, fileURLSpec
);
200 nsCAutoString iconURLSpec
; iconURLSpec
.AssignLiteral("moz-icon://");
201 iconURLSpec
+= fileURLSpec
;
202 nsCOMPtr
<nsIWritableVariant
> writable(do_QueryInterface(*_retval
));
203 writable
->SetAsAUTF8String(iconURLSpec
);
208 nsMIMEInfoWin::GetProperty(const nsAString
& aName
, nsIVariant
* *_retval
)
211 if (mDefaultApplication
&& aName
.EqualsLiteral(PROPERTY_DEFAULT_APP_ICON_URL
)) {
212 rv
= GetIconURLVariant(mDefaultApplication
, _retval
);
213 NS_ENSURE_SUCCESS(rv
, rv
);
214 } else if (mPreferredApplication
&&
215 aName
.EqualsLiteral(PROPERTY_CUSTOM_APP_ICON_URL
)) {
216 nsCOMPtr
<nsILocalHandlerApp
> localHandler
=
217 do_QueryInterface(mPreferredApplication
, &rv
);
218 NS_ENSURE_SUCCESS(rv
, rv
);
220 nsCOMPtr
<nsIFile
> executable
;
221 rv
= localHandler
->GetExecutable(getter_AddRefs(executable
));
222 NS_ENSURE_SUCCESS(rv
, rv
);
224 rv
= GetIconURLVariant(executable
, _retval
);
225 NS_ENSURE_SUCCESS(rv
, rv
);
231 typedef HRESULT (STDMETHODCALLTYPE
*MySHParseDisplayName
)
238 // this implementation was pretty much copied verbatime from
239 // Tony Robinson's code in nsExternalProtocolWin.cpp
241 nsMIMEInfoWin::LoadUriInternal(nsIURI
* aURL
)
245 // 1. Find the default app for this protocol
246 // 2. Set up the command line
247 // 3. Launch the app.
249 // For now, we'll just cheat essentially, check for the command line
250 // then just call ShellExecute()!
254 // extract the url spec from the url
255 nsCAutoString urlSpec
;
256 aURL
->GetAsciiSpec(urlSpec
);
258 // Some versions of windows (Win2k before SP3, Win XP before SP1)
259 // crash in ShellExecute on long URLs (bug 161357).
260 // IE 5 and 6 support URLS of 2083 chars in length, 2K is safe
261 const PRUint32
maxSafeURL(2048);
262 if (urlSpec
.Length() > maxSafeURL
)
263 return NS_ERROR_FAILURE
;
269 HMODULE hDll
= ::LoadLibraryW(L
"shell32.dll");
270 MySHParseDisplayName pMySHParseDisplayName
= NULL
;
271 // Version 6.0 and higher
272 if (pMySHParseDisplayName
=
273 (MySHParseDisplayName
)::GetProcAddress(hDll
,
274 "SHParseDisplayName")) {
275 if (SUCCEEDED(pMySHParseDisplayName(NS_ConvertUTF8toUTF16(urlSpec
).get(),
276 NULL
, &pidl
, 0, &sfgao
))) {
277 static const PRUnichar cmdVerb
[] = L
"open";
278 SHELLEXECUTEINFOW sinfo
;
279 memset(&sinfo
, 0, sizeof(sinfo
));
280 sinfo
.cbSize
= sizeof(sinfo
);
281 sinfo
.fMask
= SEE_MASK_FLAG_DDEWAIT
|
282 SEE_MASK_FLAG_NO_UI
|
283 SEE_MASK_INVOKEIDLIST
;
285 sinfo
.lpVerb
= (LPWSTR
)&cmdVerb
;
286 sinfo
.nShow
= SW_SHOWNORMAL
;
287 sinfo
.lpIDList
= pidl
;
289 BOOL result
= ShellExecuteExW(&sinfo
);
293 if (!result
|| ((int)sinfo
.hInstApp
) < 32)
294 rv
= NS_ERROR_FAILURE
;
297 // Version of shell32.dll < 6.0
298 int r
= (int) ::ShellExecuteW(NULL
, L
"open", NS_ConvertUTF8toUTF16(urlSpec
).get(),
299 NULL
, NULL
, SW_SHOWNORMAL
);
301 rv
= NS_ERROR_FAILURE
;
310 // Given a path to a local file, return its nsILocalHandlerApp instance.
311 PRBool
nsMIMEInfoWin::GetLocalHandlerApp(const nsAString
& aCommandHandler
,
312 nsCOMPtr
<nsILocalHandlerApp
>& aApp
)
314 nsCOMPtr
<nsILocalFile
> locfile
;
316 NS_NewLocalFile(aCommandHandler
, PR_TRUE
, getter_AddRefs(locfile
));
320 aApp
= do_CreateInstance("@mozilla.org/uriloader/local-handler-app;1");
324 aApp
->SetExecutable(locfile
);
328 // Return the cleaned up file path associated with a command verb
329 // located in root/Applications.
330 PRBool
nsMIMEInfoWin::GetAppsVerbCommandHandler(const nsAString
& appExeName
,
331 nsAString
& applicationPath
,
334 nsCOMPtr
<nsIWindowsRegKey
> appKey
=
335 do_CreateInstance("@mozilla.org/windows-registry-key;1");
339 // HKEY_CLASSES_ROOT\Applications\iexplore.exe
340 nsAutoString applicationsPath
;
341 applicationsPath
.AppendLiteral("Applications\\");
342 applicationsPath
.Append(appExeName
);
344 nsresult rv
= appKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
346 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
350 // Check for the NoOpenWith flag, if it exists
352 if (NS_SUCCEEDED(appKey
->ReadIntValue(
353 NS_LITERAL_STRING("NoOpenWith"), &value
)) &&
358 if (NS_SUCCEEDED(appKey
->ReadStringValue(
359 NS_LITERAL_STRING("NoOpenWith"), dummy
)))
364 // HKEY_CLASSES_ROOT\Applications\iexplore.exe\shell\open\command
365 applicationsPath
.AssignLiteral("Applications\\");
366 applicationsPath
.Append(appExeName
);
368 applicationsPath
.AppendLiteral("\\shell\\open\\command");
370 applicationsPath
.AppendLiteral("\\shell\\edit\\command");
373 rv
= appKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
375 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
379 nsAutoString appFilesystemCommand
;
380 if (NS_SUCCEEDED(appKey
->ReadStringValue(EmptyString(),
381 appFilesystemCommand
))) {
383 // Expand environment vars, clean up any misc.
384 if (!nsOSHelperAppService::CleanupCmdHandlerPath(appFilesystemCommand
))
387 applicationPath
= appFilesystemCommand
;
393 // Return a fully populated command string based on
394 // passing information. Used in launchWithFile to trace
395 // back to the full handler path based on the dll.
396 // (dll, targetfile, return args, open/edit)
397 PRBool
nsMIMEInfoWin::GetDllLaunchInfo(nsIFile
* aDll
,
398 nsILocalFile
* aFile
,
405 nsCOMPtr
<nsILocalFile
> localDll(do_QueryInterface(aDll
));
410 localDll
->GetLeafName(appExeName
);
412 nsCOMPtr
<nsIWindowsRegKey
> appKey
=
413 do_CreateInstance("@mozilla.org/windows-registry-key;1");
417 // HKEY_CLASSES_ROOT\Applications\iexplore.exe
418 nsAutoString applicationsPath
;
419 applicationsPath
.AppendLiteral("Applications\\");
420 applicationsPath
.Append(appExeName
);
422 nsresult rv
= appKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
424 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
428 // Check for the NoOpenWith flag, if it exists
430 rv
= appKey
->ReadIntValue(NS_LITERAL_STRING("NoOpenWith"), &value
);
431 if (NS_SUCCEEDED(rv
) && value
== 1)
435 if (NS_SUCCEEDED(appKey
->ReadStringValue(NS_LITERAL_STRING("NoOpenWith"),
441 // HKEY_CLASSES_ROOT\Applications\iexplore.exe\shell\open\command
442 applicationsPath
.AssignLiteral("Applications\\");
443 applicationsPath
.Append(appExeName
);
445 applicationsPath
.AppendLiteral("\\shell\\open\\command");
447 applicationsPath
.AppendLiteral("\\shell\\edit\\command");
449 rv
= appKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
451 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
455 nsAutoString appFilesystemCommand
;
456 if (NS_SUCCEEDED(appKey
->ReadStringValue(EmptyString(),
457 appFilesystemCommand
))) {
458 // Replace embedded environment variables.
460 ::ExpandEnvironmentStringsW(appFilesystemCommand
.get(),
462 if (bufLength
== 0) // Error
465 nsAutoArrayPtr
<PRUnichar
> destination(new PRUnichar
[bufLength
]);
468 if (!::ExpandEnvironmentStringsW(appFilesystemCommand
.get(),
473 appFilesystemCommand
= destination
;
475 // C:\Windows\System32\rundll32.exe "C:\Program Files\Windows
476 // Photo Gallery\PhotoViewer.dll", ImageView_Fullscreen %1
478 NS_NAMED_LITERAL_STRING(rundllSegment
, "rundll32.exe ");
479 PRInt32 index
= appFilesystemCommand
.Find(rundllSegment
);
480 if (index
> kNotFound
) {
481 params
.Append(Substring(appFilesystemCommand
,
482 index
+ rundllSegment
.Length()));
484 params
.Append(appFilesystemCommand
);
487 // check to make sure we have a %1 and fill it
488 NS_NAMED_LITERAL_STRING(percentOneParam
, "%1");
489 index
= params
.Find(percentOneParam
);
490 if (index
== kNotFound
) // no parameter
494 aFile
->GetTarget(target
);
495 params
.Replace(index
, 2, target
);
504 // Return the cleaned up file path associated with a progid command
505 // verb located in root.
506 PRBool
nsMIMEInfoWin::GetProgIDVerbCommandHandler(const nsAString
& appProgIDName
,
507 nsAString
& applicationPath
,
510 nsCOMPtr
<nsIWindowsRegKey
> appKey
=
511 do_CreateInstance("@mozilla.org/windows-registry-key;1");
515 nsAutoString
appProgId(appProgIDName
);
517 // HKEY_CLASSES_ROOT\Windows.XPSReachViewer\shell\open\command
519 appProgId
.AppendLiteral("\\shell\\open\\command");
521 appProgId
.AppendLiteral("\\shell\\edit\\command");
523 nsresult rv
= appKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
525 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
529 nsAutoString appFilesystemCommand
;
530 if (NS_SUCCEEDED(appKey
->ReadStringValue(EmptyString(), appFilesystemCommand
))) {
532 // Expand environment vars, clean up any misc.
533 if (!nsOSHelperAppService::CleanupCmdHandlerPath(appFilesystemCommand
))
536 applicationPath
= appFilesystemCommand
;
542 // Helper routine used in tracking app lists. Converts path
543 // entries to lower case and stores them in the trackList array.
544 void nsMIMEInfoWin::ProcessPath(nsCOMPtr
<nsIMutableArray
>& appList
,
545 nsTArray
<nsString
>& trackList
,
546 const nsAString
& appFilesystemCommand
)
548 nsAutoString
lower(appFilesystemCommand
);
551 // Don't include firefox.exe in the list
552 WCHAR exe
[MAX_PATH
+1];
553 PRUint32 len
= GetModuleFileNameW(NULL
, exe
, MAX_PATH
);
554 if (len
< MAX_PATH
&& len
!= 0) {
555 PRUint32 index
= lower
.Find(exe
);
560 nsCOMPtr
<nsILocalHandlerApp
> aApp
;
561 if (!GetLocalHandlerApp(appFilesystemCommand
, aApp
))
564 // Save in our main tracking arrays
565 appList
->AppendElement(aApp
, PR_FALSE
);
566 trackList
.AppendElement(lower
);
569 // Helper routine that handles a compare between a path
570 // and an array of paths.
571 static PRBool
IsPathInList(nsAString
& appPath
,
572 nsTArray
<nsString
>& trackList
)
574 // trackList data is always lowercase, see ProcessPath
576 nsAutoString
tmp(appPath
);
579 for (PRUint32 i
= 0; i
< trackList
.Length(); i
++) {
580 if (tmp
.Equals(trackList
[i
]))
587 * Returns a list of nsILocalHandlerApp objects containing local
588 * handlers associated with this mimeinfo. Implemented per
589 * platform using information in this object to generate the
590 * best list. Typically used for an "open with" style user
593 * @return nsIArray of nsILocalHandlerApp
596 nsMIMEInfoWin::GetPossibleLocalHandlers(nsIArray
**_retval
)
602 nsCOMPtr
<nsIMutableArray
> appList
=
603 do_CreateInstance("@mozilla.org/array;1");
606 return NS_ERROR_FAILURE
;
608 nsTArray
<nsString
> trackList
;
610 nsCAutoString fileExt
;
611 GetPrimaryExtension(fileExt
);
613 nsCOMPtr
<nsIWindowsRegKey
> regKey
=
614 do_CreateInstance("@mozilla.org/windows-registry-key;1");
616 return NS_ERROR_FAILURE
;
617 nsCOMPtr
<nsIWindowsRegKey
> appKey
=
618 do_CreateInstance("@mozilla.org/windows-registry-key;1");
620 return NS_ERROR_FAILURE
;
622 nsAutoString workingRegistryPath
;
624 PRBool extKnown
= PR_FALSE
;
625 if (fileExt
.IsEmpty()) {
627 // Mime type discovery is possible in some cases, through
628 // HKEY_CLASSES_ROOT\MIME\Database\Content Type, however, a number
629 // of file extensions related to mime type are simply not defined,
630 // (application/rss+xml & application/atom+xml are good examples)
631 // in which case we can only provide a generic list.
632 nsCAutoString mimeType
;
633 GetMIMEType(mimeType
);
634 if (!mimeType
.IsEmpty()) {
635 workingRegistryPath
.AppendLiteral("MIME\\Database\\Content Type\\");
636 workingRegistryPath
.Append(NS_ConvertASCIItoUTF16(mimeType
));
638 rv
= regKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
640 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
641 if(NS_SUCCEEDED(rv
)) {
642 nsAutoString mimeFileExt
;
643 if (NS_SUCCEEDED(regKey
->ReadStringValue(EmptyString(), mimeFileExt
))) {
644 CopyUTF16toUTF8(mimeFileExt
, fileExt
);
651 nsAutoString fileExtToUse
;
652 if (fileExt
.First() != '.')
653 fileExtToUse
= PRUnichar('.');
654 fileExtToUse
.Append(NS_ConvertUTF8toUTF16(fileExt
));
656 // Note, the order in which these occur has an effect on the
657 // validity of the resulting display list.
660 // 1) Get the default handler if it exists
661 workingRegistryPath
= fileExtToUse
;
663 rv
= regKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
665 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
666 if (NS_SUCCEEDED(rv
)) {
667 nsAutoString appProgId
;
668 if (NS_SUCCEEDED(regKey
->ReadStringValue(EmptyString(), appProgId
))) {
669 // Bug 358297 - ignore the embedded internet explorer handler
670 if (appProgId
!= NS_LITERAL_STRING("XPSViewer.Document")) {
671 nsAutoString appFilesystemCommand
;
672 if (GetProgIDVerbCommandHandler(appProgId
,
673 appFilesystemCommand
,
675 !IsPathInList(appFilesystemCommand
, trackList
)) {
676 ProcessPath(appList
, trackList
, appFilesystemCommand
);
684 // 2) list HKEY_CLASSES_ROOT\.ext\OpenWithList\
686 workingRegistryPath
= fileExtToUse
;
687 workingRegistryPath
.AppendLiteral("\\OpenWithList");
689 rv
= regKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
691 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
692 if (NS_SUCCEEDED(rv
)) {
694 if (NS_SUCCEEDED(regKey
->GetValueCount(&count
)) && count
> 0) {
695 for (PRUint32 index
= 0; index
< count
; index
++) {
696 nsAutoString appName
;
697 if (NS_FAILED(regKey
->GetValueName(index
, appName
)))
700 // HKEY_CLASSES_ROOT\Applications\firefox.exe = "path params"
701 nsAutoString appFilesystemCommand
;
702 if (!GetAppsVerbCommandHandler(appName
,
703 appFilesystemCommand
,
705 IsPathInList(appFilesystemCommand
, trackList
))
707 ProcessPath(appList
, trackList
, appFilesystemCommand
);
714 // 3) List HKEY_CLASSES_ROOT\.ext\OpenWithProgids, with the
715 // different step of resolving the progids for the command handler.
717 workingRegistryPath
= fileExtToUse
;
718 workingRegistryPath
.AppendLiteral("\\OpenWithProgids");
720 rv
= regKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
722 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
723 if (NS_SUCCEEDED(rv
)) {
725 if (NS_SUCCEEDED(regKey
->GetValueCount(&count
)) && count
> 0) {
726 for (PRUint32 index
= 0; index
< count
; index
++) {
727 // HKEY_CLASSES_ROOT\.ext\OpenWithProgids\Windows.XPSReachViewer
728 nsAutoString appProgId
;
729 if (NS_FAILED(regKey
->GetValueName(index
, appProgId
)))
732 nsAutoString appFilesystemCommand
;
733 if (!GetProgIDVerbCommandHandler(appProgId
,
734 appFilesystemCommand
,
736 IsPathInList(appFilesystemCommand
, trackList
))
738 ProcessPath(appList
, trackList
, appFilesystemCommand
);
745 // 4) Add any non configured applications located in the MRU list
747 // HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\
748 // Explorer\FileExts\.ext\OpenWithList
749 workingRegistryPath
=
750 NS_LITERAL_STRING("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\");
751 workingRegistryPath
+= fileExtToUse
;
752 workingRegistryPath
.AppendLiteral("\\OpenWithList");
754 rv
= regKey
->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER
,
756 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
757 if (NS_SUCCEEDED(rv
)) {
759 if (NS_SUCCEEDED(regKey
->GetValueCount(&count
)) && count
> 0) {
760 for (PRUint32 index
= 0; index
< count
; index
++) {
761 nsAutoString appName
, appValue
;
762 if (NS_FAILED(regKey
->GetValueName(index
, appName
)))
764 if (appName
.EqualsLiteral("MRUList"))
766 if (NS_FAILED(regKey
->ReadStringValue(appName
, appValue
)))
769 // HKEY_CLASSES_ROOT\Applications\firefox.exe = "path params"
770 nsAutoString appFilesystemCommand
;
771 if (!GetAppsVerbCommandHandler(appValue
,
772 appFilesystemCommand
,
774 IsPathInList(appFilesystemCommand
, trackList
))
776 ProcessPath(appList
, trackList
, appFilesystemCommand
);
782 // 5) Add any non configured progids in the MRU list, with the
783 // different step of resolving the progids for the command handler.
785 // HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\
786 // Explorer\FileExts\.ext\OpenWithProgids
787 workingRegistryPath
=
788 NS_LITERAL_STRING("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\");
789 workingRegistryPath
+= fileExtToUse
;
790 workingRegistryPath
.AppendLiteral("\\OpenWithProgids");
792 regKey
->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER
,
794 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
795 if (NS_SUCCEEDED(rv
)) {
797 if (NS_SUCCEEDED(regKey
->GetValueCount(&count
)) && count
> 0) {
798 for (PRUint32 index
= 0; index
< count
; index
++) {
799 nsAutoString appIndex
, appProgId
;
800 if (NS_FAILED(regKey
->GetValueName(index
, appProgId
)))
803 nsAutoString appFilesystemCommand
;
804 if (!GetProgIDVerbCommandHandler(appProgId
,
805 appFilesystemCommand
,
807 IsPathInList(appFilesystemCommand
, trackList
))
809 ProcessPath(appList
, trackList
, appFilesystemCommand
);
816 // 6) Check the perceived type value, and use this to lookup the perceivedtype
818 // http://msdn2.microsoft.com/en-us/library/aa969373.aspx
820 workingRegistryPath
= fileExtToUse
;
822 regKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
824 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
825 if (NS_SUCCEEDED(rv
)) {
826 nsAutoString perceivedType
;
827 rv
= regKey
->ReadStringValue(NS_LITERAL_STRING("PerceivedType"),
829 if (NS_SUCCEEDED(rv
)) {
830 nsAutoString
openWithListPath(NS_LITERAL_STRING("SystemFileAssociations\\"));
831 openWithListPath
.Append(perceivedType
); // no period
832 openWithListPath
.Append(NS_LITERAL_STRING("\\OpenWithList"));
834 nsresult rv
= appKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
836 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
837 if (NS_SUCCEEDED(rv
)) {
839 if (NS_SUCCEEDED(regKey
->GetValueCount(&count
)) && count
> 0) {
840 for (PRUint32 index
= 0; index
< count
; index
++) {
841 nsAutoString appName
;
842 if (NS_FAILED(regKey
->GetValueName(index
, appName
)))
845 // HKEY_CLASSES_ROOT\Applications\firefox.exe = "path params"
846 nsAutoString appFilesystemCommand
;
847 if (!GetAppsVerbCommandHandler(appName
, appFilesystemCommand
,
849 IsPathInList(appFilesystemCommand
, trackList
))
851 ProcessPath(appList
, trackList
, appFilesystemCommand
);
857 } // extKnown == PR_FALSE
860 // 7) list global HKEY_CLASSES_ROOT\*\OpenWithList\
861 // Listing general purpose handlers, not specific to a mime type or file extension
863 workingRegistryPath
= NS_LITERAL_STRING("*\\OpenWithList");
865 rv
= regKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
867 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
868 if (NS_SUCCEEDED(rv
)) {
870 if (NS_SUCCEEDED(regKey
->GetValueCount(&count
)) && count
> 0) {
871 for (PRUint32 index
= 0; index
< count
; index
++) {
872 nsAutoString appName
;
873 if (NS_FAILED(regKey
->GetValueName(index
, appName
)))
876 // HKEY_CLASSES_ROOT\Applications\firefox.exe = "path params"
877 nsAutoString appFilesystemCommand
;
878 if (!GetAppsVerbCommandHandler(appName
, appFilesystemCommand
,
880 IsPathInList(appFilesystemCommand
, trackList
))
882 ProcessPath(appList
, trackList
, appFilesystemCommand
);
889 // 8) General application's list - not file extension specific on windows
890 workingRegistryPath
= NS_LITERAL_STRING("Applications");
892 rv
= regKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
894 nsIWindowsRegKey::ACCESS_ENUMERATE_SUB_KEYS
|
895 nsIWindowsRegKey::ACCESS_QUERY_VALUE
);
896 if (NS_SUCCEEDED(rv
)) {
898 if (NS_SUCCEEDED(regKey
->GetChildCount(&count
)) && count
> 0) {
899 for (PRUint32 index
= 0; index
< count
; index
++) {
900 nsAutoString appName
;
901 if (NS_FAILED(regKey
->GetChildName(index
, appName
)))
904 // HKEY_CLASSES_ROOT\Applications\firefox.exe = "path params"
905 nsAutoString appFilesystemCommand
;
906 if (!GetAppsVerbCommandHandler(appName
, appFilesystemCommand
,
908 IsPathInList(appFilesystemCommand
, trackList
))
910 ProcessPath(appList
, trackList
, appFilesystemCommand
);
915 // Return to the caller