forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			995 lines
		
	
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			995 lines
		
	
	
	
		
			32 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 | |
| /* ***** BEGIN LICENSE BLOCK *****
 | |
|  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 | |
|  *
 | |
|  * The contents of this file are subject to the Mozilla Public License Version
 | |
|  * 1.1 (the "License"); you may not use this file except in compliance with
 | |
|  * the License. You may obtain a copy of the License at
 | |
|  * http://www.mozilla.org/MPL/
 | |
|  *
 | |
|  * Software distributed under the License is distributed on an "AS IS" basis,
 | |
|  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 | |
|  * for the specific language governing rights and limitations under the
 | |
|  * License.
 | |
|  *
 | |
|  * The Original Code is Shell Service.
 | |
|  *
 | |
|  * The Initial Developer of the Original Code is mozilla.org.
 | |
|  * Portions created by the Initial Developer are Copyright (C) 2004
 | |
|  * the Initial Developer. All Rights Reserved.
 | |
|  *
 | |
|  * Contributor(s):
 | |
|  *  Ben Goodger    <ben@mozilla.org>       (Clients, Mail, New Default Browser)
 | |
|  *  Joe Hewitt     <hewitt@netscape.com>   (Set Background)
 | |
|  *  Blake Ross     <blake@cs.stanford.edu> (Desktop Color, DDE support)
 | |
|  *  Jungshik Shin  <jshin@mailaps.org>     (I18N)
 | |
|  *  Robert Strong  <robert.bugzilla@gmail.com>
 | |
|  *  Asaf Romano    <mano@mozilla.com>
 | |
|  *  Ryan Jones     <sciguyryan@gmail.com>
 | |
|  *  Paul O'Shannessy <paul@oshannessy.com>
 | |
|  *
 | |
|  * Alternatively, the contents of this file may be used under the terms of
 | |
|  * either the GNU General Public License Version 2 or later (the "GPL"), or
 | |
|  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 | |
|  * in which case the provisions of the GPL or the LGPL are applicable instead
 | |
|  * of those above. If you wish to allow use of your version of this file only
 | |
|  * under the terms of either the GPL or the LGPL, and not to allow others to
 | |
|  * use your version of this file under the terms of the MPL, indicate your
 | |
|  * decision by deleting the provisions above and replace them with the notice
 | |
|  * and other provisions required by the GPL or the LGPL. If you do not delete
 | |
|  * the provisions above, a recipient may use your version of this file under
 | |
|  * the terms of any one of the MPL, the GPL or the LGPL.
 | |
|  *
 | |
|  * ***** END LICENSE BLOCK ***** */
 | |
| 
 | |
| #include "imgIContainer.h"
 | |
| #include "imgIRequest.h"
 | |
| #include "nsIDOMDocument.h"
 | |
| #include "nsIDOMElement.h"
 | |
| #include "nsIDOMHTMLImageElement.h"
 | |
| #include "nsIImageLoadingContent.h"
 | |
| #include "nsIPrefService.h"
 | |
| #include "nsIPrefLocalizedString.h"
 | |
| #include "nsIServiceManager.h"
 | |
| #include "nsIStringBundle.h"
 | |
| #include "nsNetUtil.h"
 | |
| #include "nsShellService.h"
 | |
| #include "nsWindowsShellService.h"
 | |
| #include "nsIProcess.h"
 | |
| #include "nsICategoryManager.h"
 | |
| #include "nsBrowserCompsCID.h"
 | |
| #include "nsDirectoryServiceUtils.h"
 | |
| #include "nsAppDirectoryServiceDefs.h"
 | |
| #include "nsDirectoryServiceDefs.h"
 | |
| #include "nsIWindowsRegKey.h"
 | |
| #include "nsUnicharUtils.h"
 | |
| 
 | |
| #include "windows.h"
 | |
| #include "shellapi.h"
 | |
| 
 | |
| #ifdef _WIN32_WINNT
 | |
| #undef _WIN32_WINNT
 | |
| #endif
 | |
| #define _WIN32_WINNT 0x0600
 | |
| #define INITGUID
 | |
| #include <shlobj.h>
 | |
| 
 | |
| #include <mbstring.h>
 | |
| 
 | |
| #ifndef MAX_BUF
 | |
| #define MAX_BUF 4096
 | |
| #endif
 | |
| 
 | |
| #define REG_SUCCEEDED(val) \
 | |
|   (val == ERROR_SUCCESS)
 | |
| 
 | |
| #define REG_FAILED(val) \
 | |
|   (val != ERROR_SUCCESS)
 | |
| 
 | |
| #ifndef WINCE
 | |
| NS_IMPL_ISUPPORTS2(nsWindowsShellService, nsIWindowsShellService, nsIShellService)
 | |
| #else
 | |
| NS_IMPL_ISUPPORTS1(nsWindowsShellService, nsIShellService)
 | |
| #endif
 | |
| 
 | |
| static nsresult
 | |
| OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName, HKEY* aKey)
 | |
| {
 | |
|   const nsString &flatName = PromiseFlatString(aKeyName);
 | |
| 
 | |
|   DWORD res = ::RegOpenKeyExW(aKeyRoot, flatName.get(), 0, KEY_READ, aKey);
 | |
|   switch (res) {
 | |
|   case ERROR_SUCCESS:
 | |
|     break;
 | |
|   case ERROR_ACCESS_DENIED:
 | |
|     return NS_ERROR_FILE_ACCESS_DENIED;
 | |
|   case ERROR_FILE_NOT_FOUND:
 | |
|     return NS_ERROR_NOT_AVAILABLE;
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| #ifdef WINCE
 | |
| static nsresult
 | |
| OpenKeyForWriting(HKEY aStartKey, const nsAString& aKeyName, HKEY* aKey)
 | |
| {
 | |
|   const nsString &flatName = PromiseFlatString(aKeyName);
 | |
| 
 | |
|   DWORD dwDisp = 0;
 | |
|   DWORD res = ::RegCreateKeyExW(aStartKey, flatName.get(), 0, NULL,
 | |
|                                 0, KEY_READ | KEY_WRITE, NULL, aKey,
 | |
|                                 &dwDisp);
 | |
|   switch (res) {
 | |
|   case ERROR_SUCCESS:
 | |
|     break;
 | |
|   case ERROR_ACCESS_DENIED:
 | |
|     return NS_ERROR_FILE_ACCESS_DENIED;
 | |
|   case ERROR_FILE_NOT_FOUND:
 | |
|     res = ::RegCreateKeyExW(aStartKey, flatName.get(), 0, NULL,
 | |
|                             0, KEY_READ | KEY_WRITE, NULL, aKey,
 | |
|                             NULL);
 | |
|     if (res != ERROR_SUCCESS)
 | |
|       return NS_ERROR_FILE_ACCESS_DENIED;
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| ///////////////////////////////////////////////////////////////////////////////
 | |
| // Default Browser Registry Settings
 | |
| //
 | |
| // The setting of these values are made by an external binary since writing
 | |
| // these values may require elevation.
 | |
| //
 | |
| // - File Extension Mappings
 | |
| //   -----------------------
 | |
| //   The following file extensions:
 | |
| //    .htm .html .shtml .xht .xhtml 
 | |
| //   are mapped like so:
 | |
| //
 | |
| //   HKCU\SOFTWARE\Classes\.<ext>\      (default)         REG_SZ     FirefoxHTML
 | |
| //
 | |
| //   as aliases to the class:
 | |
| //
 | |
| //   HKCU\SOFTWARE\Classes\FirefoxHTML\
 | |
| //     DefaultIcon                      (default)         REG_SZ     <apppath>,1
 | |
| //     shell\open\command               (default)         REG_SZ     <apppath> -requestPending -osint -url "%1"
 | |
| //     shell\open\ddeexec               (default)         REG_SZ     "%1",,0,0,,,,
 | |
| //     shell\open\ddeexec               NoActivateHandler REG_SZ
 | |
| //                       \Application   (default)         REG_SZ     Firefox
 | |
| //                       \Topic         (default)         REG_SZ     WWW_OpenURL
 | |
| //
 | |
| // - Windows Vista Protocol Handler
 | |
| //
 | |
| //   HKCU\SOFTWARE\Classes\FirefoxURL\  (default)         REG_SZ     <appname> URL
 | |
| //                                      EditFlags         REG_DWORD  2
 | |
| //                                      FriendlyTypeName  REG_SZ     <appname> URL
 | |
| //     DefaultIcon                      (default)         REG_SZ     <apppath>,1
 | |
| //     shell\open\command               (default)         REG_SZ     <apppath> -requestPending -osint -url "%1"
 | |
| //     shell\open\ddeexec               (default)         REG_SZ     "%1",,0,0,,,,
 | |
| //     shell\open\ddeexec               NoActivateHandler REG_SZ
 | |
| //                       \Application   (default)         REG_SZ     Firefox
 | |
| //                       \Topic         (default)         REG_SZ     WWW_OpenURL
 | |
| //
 | |
| // - Protocol Mappings
 | |
| //   -----------------
 | |
| //   The following protocols:
 | |
| //    HTTP, HTTPS, FTP
 | |
| //   are mapped like so:
 | |
| //
 | |
| //   HKCU\SOFTWARE\Classes\<protocol>\
 | |
| //     DefaultIcon                      (default)         REG_SZ     <apppath>,1
 | |
| //     shell\open\command               (default)         REG_SZ     <apppath> -requestPending -osint -url "%1"
 | |
| //     shell\open\ddeexec               (default)         REG_SZ     "%1",,0,0,,,,
 | |
| //     shell\open\ddeexec               NoActivateHandler REG_SZ
 | |
| //                       \Application   (default)         REG_SZ     Firefox
 | |
| //                       \Topic         (default)         REG_SZ     WWW_OpenURL
 | |
| //
 | |
| // - Windows Start Menu (Win2K SP2, XP SP1, and newer)
 | |
| //   -------------------------------------------------
 | |
| //   The following keys are set to make Firefox appear in the Start Menu as the
 | |
| //   browser:
 | |
| //   
 | |
| //   HKCU\SOFTWARE\Clients\StartMenuInternet\FIREFOX.EXE\
 | |
| //                                      (default)         REG_SZ     <appname>
 | |
| //     DefaultIcon                      (default)         REG_SZ     <apppath>,0
 | |
| //     InstallInfo                      HideIconsCommand  REG_SZ     <uninstpath> /HideShortcuts
 | |
| //     InstallInfo                      IconsVisible      REG_DWORD  1
 | |
| //     InstallInfo                      ReinstallCommand  REG_SZ     <uninstpath> /SetAsDefaultAppGlobal
 | |
| //     InstallInfo                      ShowIconsCommand  REG_SZ     <uninstpath> /ShowShortcuts
 | |
| //     shell\open\command               (default)         REG_SZ     <apppath>
 | |
| //     shell\properties                 (default)         REG_SZ     <appname> &Options
 | |
| //     shell\properties\command         (default)         REG_SZ     <apppath> -preferences
 | |
| //     shell\safemode                   (default)         REG_SZ     <appname> &Safe Mode
 | |
| //     shell\safemode\command           (default)         REG_SZ     <apppath> -safe-mode
 | |
| //
 | |
| 
 | |
| typedef struct {
 | |
|   char* keyName;
 | |
|   char* valueName;
 | |
|   char* valueData;
 | |
| } SETTING;
 | |
| 
 | |
| #ifndef WINCE
 | |
| #define APP_REG_NAME L"Firefox"
 | |
| #define CLS_HTML "FirefoxHTML"
 | |
| #define CLS_URL "FirefoxURL"
 | |
| #define CPL_DESKTOP L"Control Panel\\Desktop"
 | |
| #define VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\""
 | |
| #define VAL_FILE_ICON "%APPPATH%,1"
 | |
| #else
 | |
| #define CPL_DESKTOP L"ControlPanel\\Desktop"
 | |
| #define VAL_OPEN "\"%APPPATH%\" -osint -url \"%1\""
 | |
| #define VAL_FILE_ICON "%APPPATH%,-2"
 | |
| #endif
 | |
| 
 | |
| #define DI "\\DefaultIcon"
 | |
| #define SOP "\\shell\\open\\command"
 | |
| 
 | |
| 
 | |
| #define MAKE_KEY_NAME1(PREFIX, MID) \
 | |
|   PREFIX MID
 | |
| 
 | |
| // The DefaultIcon registry key value should never be used when checking if
 | |
| // Firefox is the default browser for file handlers since other applications
 | |
| // (e.g. MS Office) may modify the DefaultIcon registry key value to add Icon
 | |
| // Handlers. see http://msdn2.microsoft.com/en-us/library/aa969357.aspx for
 | |
| // more info.
 | |
| static SETTING gSettings[] = {
 | |
| #ifndef WINCE
 | |
|   // File Handler Class
 | |
|   { MAKE_KEY_NAME1(CLS_HTML, SOP), "", VAL_OPEN },
 | |
| 
 | |
|   // Protocol Handler Class - for Vista and above
 | |
|   { MAKE_KEY_NAME1(CLS_URL, SOP), "", VAL_OPEN },
 | |
| #else
 | |
|   { MAKE_KEY_NAME1("FTP", DI), "", VAL_FILE_ICON },
 | |
|   { MAKE_KEY_NAME1("FTP", SOP), "", VAL_OPEN },
 | |
| 
 | |
|   // File handlers for Windows CE
 | |
|   { MAKE_KEY_NAME1("bmpfile", DI), "", VAL_FILE_ICON },
 | |
|   { MAKE_KEY_NAME1("bmpfile", SOP), "", VAL_OPEN },
 | |
|   { MAKE_KEY_NAME1("giffile", DI), "", VAL_FILE_ICON },
 | |
|   { MAKE_KEY_NAME1("giffile", SOP), "", VAL_OPEN },
 | |
|   { MAKE_KEY_NAME1("jpegfile", DI), "", VAL_FILE_ICON },
 | |
|   { MAKE_KEY_NAME1("jpegfile", SOP), "", VAL_OPEN },
 | |
|   { MAKE_KEY_NAME1("pngfile", DI), "", VAL_FILE_ICON },
 | |
|   { MAKE_KEY_NAME1("pngfile", SOP), "", VAL_OPEN },
 | |
|   { MAKE_KEY_NAME1("htmlfile", DI), "", VAL_FILE_ICON },
 | |
|   { MAKE_KEY_NAME1("htmlfile", SOP), "", VAL_OPEN },
 | |
| #endif
 | |
| 
 | |
|   // Protocol Handlers
 | |
|   { MAKE_KEY_NAME1("HTTP", DI),    "", VAL_FILE_ICON },
 | |
|   { MAKE_KEY_NAME1("HTTP", SOP),   "", VAL_OPEN },
 | |
|   { MAKE_KEY_NAME1("HTTPS", DI),   "", VAL_FILE_ICON },
 | |
|   { MAKE_KEY_NAME1("HTTPS", SOP),  "", VAL_OPEN }
 | |
| };
 | |
| 
 | |
| #ifndef WINCE
 | |
| PRBool
 | |
| nsWindowsShellService::IsDefaultBrowserVista(PRBool* aIsDefaultBrowser)
 | |
| {
 | |
| #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
 | |
|   IApplicationAssociationRegistration* pAAR;
 | |
|   
 | |
|   HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
 | |
|                                 NULL,
 | |
|                                 CLSCTX_INPROC,
 | |
|                                 IID_IApplicationAssociationRegistration,
 | |
|                                 (void**)&pAAR);
 | |
| 
 | |
|   if (SUCCEEDED(hr)) {
 | |
|     hr = pAAR->QueryAppIsDefaultAll(AL_EFFECTIVE,
 | |
|                                     APP_REG_NAME,
 | |
|                                     aIsDefaultBrowser);
 | |
| 
 | |
|     pAAR->Release();
 | |
|     return PR_TRUE;
 | |
|   }
 | |
| #endif  
 | |
|   return PR_FALSE;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWindowsShellService::IsDefaultBrowser(PRBool aStartupCheck,
 | |
|                                         PRBool* aIsDefaultBrowser)
 | |
| {
 | |
|   // If this is the first browser window, maintain internal state that we've
 | |
|   // checked this session (so that subsequent window opens don't show the 
 | |
|   // default browser dialog).
 | |
|   if (aStartupCheck)
 | |
|     mCheckedThisSession = PR_TRUE;
 | |
| 
 | |
|   SETTING* settings;
 | |
|   SETTING* end = gSettings + sizeof(gSettings)/sizeof(SETTING);
 | |
| 
 | |
|   *aIsDefaultBrowser = PR_TRUE;
 | |
| 
 | |
|   PRUnichar exePath[MAX_BUF];
 | |
|   if (!::GetModuleFileNameW(0, exePath, MAX_BUF))
 | |
|     return NS_ERROR_FAILURE;
 | |
| 
 | |
| #ifndef WINCE
 | |
|   // Convert the path to a long path since GetModuleFileNameW returns the path
 | |
|   // that was used to launch Firefox which is not necessarily a long path.
 | |
|   if (!::GetLongPathNameW(exePath, exePath, MAX_BUF))
 | |
|     return NS_ERROR_FAILURE;
 | |
| #endif
 | |
| 
 | |
|   nsAutoString appLongPath(exePath);
 | |
| 
 | |
|   nsresult rv;
 | |
|   PRUnichar currValue[MAX_BUF];
 | |
|   for (settings = gSettings; settings < end; ++settings) {
 | |
|     NS_ConvertUTF8toUTF16 dataLongPath(settings->valueData);
 | |
|     NS_ConvertUTF8toUTF16 key(settings->keyName);
 | |
|     NS_ConvertUTF8toUTF16 value(settings->valueName);
 | |
|     PRInt32 offset = dataLongPath.Find("%APPPATH%");
 | |
|     dataLongPath.Replace(offset, 9, appLongPath);
 | |
| 
 | |
|     ::ZeroMemory(currValue, sizeof(currValue));
 | |
|     HKEY theKey;
 | |
|     rv = OpenKeyForReading(HKEY_CLASSES_ROOT, key, &theKey);
 | |
|     if (NS_FAILED(rv)) {
 | |
|       *aIsDefaultBrowser = PR_FALSE;
 | |
|       return NS_OK;
 | |
|     }
 | |
| 
 | |
|     DWORD len = sizeof currValue;
 | |
|     DWORD res = ::RegQueryValueExW(theKey, PromiseFlatString(value).get(),
 | |
|                                    NULL, NULL, (LPBYTE)currValue, &len);
 | |
|     // Close the key we opened.
 | |
|     ::RegCloseKey(theKey);
 | |
|     if (REG_FAILED(res) ||
 | |
|         !dataLongPath.Equals(currValue, CaseInsensitiveCompare)) {
 | |
|       // Key wasn't set, or was set to something other than our registry entry
 | |
|       *aIsDefaultBrowser = PR_FALSE;
 | |
|       return NS_OK;
 | |
|     }
 | |
|   }
 | |
| 
 | |
| #ifndef WINCE
 | |
|   // Only check if Firefox is the default browser on Vista if the previous
 | |
|   // checks show that Firefox is the default browser.
 | |
|   if (*aIsDefaultBrowser)
 | |
|     IsDefaultBrowserVista(aIsDefaultBrowser);
 | |
| #endif
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWindowsShellService::SetDefaultBrowser(PRBool aClaimAllTypes, PRBool aForAllUsers)
 | |
| {
 | |
| #ifndef WINCE
 | |
|   nsresult rv;
 | |
|   nsCOMPtr<nsIProperties> directoryService = 
 | |
|     do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   nsCOMPtr<nsILocalFile> appHelper;
 | |
|   rv = directoryService->Get(NS_XPCOM_CURRENT_PROCESS_DIR, NS_GET_IID(nsILocalFile), getter_AddRefs(appHelper));
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   rv = appHelper->AppendNative(NS_LITERAL_CSTRING("uninstall"));
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   rv = appHelper->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   nsAutoString appHelperPath;
 | |
|   rv = appHelper->GetPath(appHelperPath);
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   if (aForAllUsers) {
 | |
|     appHelperPath.AppendLiteral(" /SetAsDefaultAppGlobal");
 | |
|   } else {
 | |
|     appHelperPath.AppendLiteral(" /SetAsDefaultAppUser");
 | |
|   }
 | |
| 
 | |
|   STARTUPINFOW si = {sizeof(si), 0};
 | |
|   PROCESS_INFORMATION pi = {0};
 | |
| 
 | |
|   BOOL ok = CreateProcessW(NULL, (LPWSTR)appHelperPath.get(), NULL, NULL,
 | |
|                            FALSE, 0, NULL, NULL, &si, &pi);
 | |
| 
 | |
|   if (!ok)
 | |
|     return NS_ERROR_FAILURE;
 | |
| 
 | |
|   CloseHandle(pi.hProcess);
 | |
|   CloseHandle(pi.hThread);
 | |
| #else
 | |
|   SETTING* settings;
 | |
|   SETTING* end = gSettings + sizeof(gSettings)/sizeof(SETTING);
 | |
| 
 | |
|   PRUnichar exePath[MAX_BUF];
 | |
|   if (!::GetModuleFileNameW(0, exePath, MAX_BUF))
 | |
|     return NS_ERROR_FAILURE;
 | |
| 
 | |
|   nsAutoString appLongPath(exePath);
 | |
| 
 | |
|   // The .png registry key isn't present by default so also add Content Type.
 | |
|   SetRegKey(NS_LITERAL_STRING(".png"), EmptyString(),
 | |
|             NS_LITERAL_STRING("pngfile"));
 | |
|   SetRegKey(NS_LITERAL_STRING(".png"), NS_LITERAL_STRING("Content Type"),
 | |
|             NS_LITERAL_STRING("image/png"));
 | |
| 
 | |
|   // Set these keys to their default value for a clean install in case another
 | |
|   // app has changed these keys.
 | |
|   SetRegKey(NS_LITERAL_STRING(".htm"), EmptyString(),
 | |
|             NS_LITERAL_STRING("htmlfile"));
 | |
|   SetRegKey(NS_LITERAL_STRING(".html"), EmptyString(),
 | |
|             NS_LITERAL_STRING("htmlfile"));
 | |
|   SetRegKey(NS_LITERAL_STRING(".bmp"), EmptyString(),
 | |
|             NS_LITERAL_STRING("bmpfile"));
 | |
|   SetRegKey(NS_LITERAL_STRING(".gif"), EmptyString(),
 | |
|             NS_LITERAL_STRING("giffile"));
 | |
|   SetRegKey(NS_LITERAL_STRING(".jpe"), EmptyString(),
 | |
|             NS_LITERAL_STRING("jpegfile"));
 | |
|   SetRegKey(NS_LITERAL_STRING(".jpg"), EmptyString(),
 | |
|             NS_LITERAL_STRING("jpegfile"));
 | |
|   SetRegKey(NS_LITERAL_STRING(".jpeg"), EmptyString(),
 | |
|             NS_LITERAL_STRING("jpegfile"));
 | |
| 
 | |
|   for (settings = gSettings; settings < end; ++settings) {
 | |
|     NS_ConvertUTF8toUTF16 dataLongPath(settings->valueData);
 | |
|     NS_ConvertUTF8toUTF16 key(settings->keyName);
 | |
|     NS_ConvertUTF8toUTF16 value(settings->valueName);
 | |
|     PRInt32 offset = dataLongPath.Find("%APPPATH%");
 | |
|     dataLongPath.Replace(offset, 9, appLongPath);
 | |
|     SetRegKey(key, value, dataLongPath);
 | |
|   }
 | |
|   // On Windows CE RegFlushKey can negatively impact performance if there are a
 | |
|   // lot of pending writes to the HKEY_CLASSES_ROOT registry hive but it is
 | |
|   // necessary to save the values in the case where the user performs a hard
 | |
|   // power off of the device.
 | |
|   ::RegFlushKey(HKEY_CLASSES_ROOT);
 | |
| #endif
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| #ifdef WINCE
 | |
| void
 | |
| nsWindowsShellService::SetRegKey(const nsString& aKeyName,
 | |
|                                  const nsString& aValueName,
 | |
|                                  const nsString& aValue)
 | |
| {
 | |
|   PRUnichar buf[MAX_BUF];
 | |
|   DWORD len = sizeof buf;
 | |
| 
 | |
|   HKEY theKey;
 | |
|   nsresult rv = OpenKeyForWriting(HKEY_CLASSES_ROOT, aKeyName, &theKey);
 | |
|   if (NS_FAILED(rv))
 | |
|     return;
 | |
| 
 | |
|   // Get the current value.
 | |
|   DWORD res = ::RegQueryValueExW(theKey, PromiseFlatString(aValueName).get(),
 | |
|                                  NULL, NULL, (LPBYTE)buf, &len);
 | |
| 
 | |
|   // Set the new value if it doesn't exist or it is different than the current
 | |
|   // value.
 | |
|   nsAutoString current(buf);
 | |
|   if (REG_FAILED(res) || !current.Equals(aValue)) {
 | |
|     const nsString &flatValue = PromiseFlatString(aValue);
 | |
| 
 | |
|     ::RegSetValueExW(theKey, PromiseFlatString(aValueName).get(),
 | |
|                      0, REG_SZ, (const BYTE *)flatValue.get(),
 | |
|                      (flatValue.Length() + 1) * sizeof(PRUnichar));
 | |
|   }
 | |
| 
 | |
|   // Close the key we opened.
 | |
|   ::RegCloseKey(theKey);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWindowsShellService::GetShouldCheckDefaultBrowser(PRBool* aResult)
 | |
| {
 | |
|   // If we've already checked, the browser has been started and this is a 
 | |
|   // new window open, and we don't want to check again.
 | |
|   if (mCheckedThisSession) {
 | |
|     *aResult = PR_FALSE;
 | |
|     return NS_OK;
 | |
|   }
 | |
| 
 | |
|   nsCOMPtr<nsIPrefBranch> prefs;
 | |
|   nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
 | |
|   if (pserve)
 | |
|     pserve->GetBranch("", getter_AddRefs(prefs));
 | |
| 
 | |
|   prefs->GetBoolPref(PREF_CHECKDEFAULTBROWSER, aResult);
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWindowsShellService::SetShouldCheckDefaultBrowser(PRBool aShouldCheck)
 | |
| {
 | |
|   nsCOMPtr<nsIPrefBranch> prefs;
 | |
|   nsCOMPtr<nsIPrefService> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID));
 | |
|   if (pserve)
 | |
|     pserve->GetBranch("", getter_AddRefs(prefs));
 | |
| 
 | |
|   prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, aShouldCheck);
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| static nsresult
 | |
| WriteBitmap(nsIFile* aFile, imgIContainer* aImage)
 | |
| {
 | |
|   nsRefPtr<gfxImageSurface> image;
 | |
|   nsresult rv = aImage->CopyFrame(imgIContainer::FRAME_FIRST,
 | |
|                                   imgIContainer::FLAG_SYNC_DECODE,
 | |
|                                   getter_AddRefs(image));
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   PRInt32 width = image->Width();
 | |
|   PRInt32 height = image->Height();
 | |
| 
 | |
|   PRUint8* bits = image->Data();
 | |
|   PRUint32 length = image->GetDataSize();
 | |
|   PRUint32 bpr = PRUint32(image->Stride());
 | |
|   PRInt32 bitCount = bpr/width;
 | |
| 
 | |
|   // initialize these bitmap structs which we will later
 | |
|   // serialize directly to the head of the bitmap file
 | |
|   BITMAPINFOHEADER bmi;
 | |
|   bmi.biSize = sizeof(BITMAPINFOHEADER);
 | |
|   bmi.biWidth = width;
 | |
|   bmi.biHeight = height;
 | |
|   bmi.biPlanes = 1;
 | |
|   bmi.biBitCount = (WORD)bitCount*8;
 | |
|   bmi.biCompression = BI_RGB;
 | |
|   bmi.biSizeImage = length;
 | |
|   bmi.biXPelsPerMeter = 0;
 | |
|   bmi.biYPelsPerMeter = 0;
 | |
|   bmi.biClrUsed = 0;
 | |
|   bmi.biClrImportant = 0;
 | |
| 
 | |
|   BITMAPFILEHEADER bf;
 | |
|   bf.bfType = 0x4D42; // 'BM'
 | |
|   bf.bfReserved1 = 0;
 | |
|   bf.bfReserved2 = 0;
 | |
|   bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
 | |
|   bf.bfSize = bf.bfOffBits + bmi.biSizeImage;
 | |
| 
 | |
|   // get a file output stream
 | |
|   nsCOMPtr<nsIOutputStream> stream;
 | |
|   rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), aFile);
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   // write the bitmap headers and rgb pixel data to the file
 | |
|   rv = NS_ERROR_FAILURE;
 | |
|   if (stream) {
 | |
|     PRUint32 written;
 | |
|     stream->Write((const char*)&bf, sizeof(BITMAPFILEHEADER), &written);
 | |
|     if (written == sizeof(BITMAPFILEHEADER)) {
 | |
|       stream->Write((const char*)&bmi, sizeof(BITMAPINFOHEADER), &written);
 | |
|       if (written == sizeof(BITMAPINFOHEADER)) {
 | |
|         // write out the image data backwards because the desktop won't
 | |
|         // show bitmaps with negative heights for top-to-bottom
 | |
|         PRUint32 i = length;
 | |
|         do {
 | |
|           i -= bpr;
 | |
|           stream->Write(((const char*)bits) + i, bpr, &written);
 | |
|           if (written == bpr) {
 | |
|             rv = NS_OK;
 | |
|           } else {
 | |
|             rv = NS_ERROR_FAILURE;
 | |
|             break;
 | |
|           }
 | |
|         } while (i != 0);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     stream->Close();
 | |
|   }
 | |
| 
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWindowsShellService::SetDesktopBackground(nsIDOMElement* aElement, 
 | |
|                                             PRInt32 aPosition)
 | |
| {
 | |
|   nsresult rv;
 | |
| 
 | |
|   nsCOMPtr<imgIContainer> container;
 | |
|   nsCOMPtr<nsIDOMHTMLImageElement> imgElement(do_QueryInterface(aElement));
 | |
|   if (!imgElement) {
 | |
|     // XXX write background loading stuff!
 | |
|     return NS_ERROR_NOT_AVAILABLE;
 | |
|   } 
 | |
|   else {
 | |
|     nsCOMPtr<nsIImageLoadingContent> imageContent =
 | |
|       do_QueryInterface(aElement, &rv);
 | |
|     if (!imageContent)
 | |
|       return rv;
 | |
| 
 | |
|     // get the image container
 | |
|     nsCOMPtr<imgIRequest> request;
 | |
|     rv = imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
 | |
|                                   getter_AddRefs(request));
 | |
|     if (!request)
 | |
|       return rv;
 | |
|     rv = request->GetImage(getter_AddRefs(container));
 | |
|     if (!container)
 | |
|       return NS_ERROR_FAILURE;
 | |
|   }
 | |
| 
 | |
|   // get the file name from localized strings
 | |
|   nsCOMPtr<nsIStringBundleService>
 | |
|     bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   nsCOMPtr<nsIStringBundle> shellBundle;
 | |
|   rv = bundleService->CreateBundle(SHELLSERVICE_PROPERTIES,
 | |
|                                    getter_AddRefs(shellBundle));
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
|  
 | |
|   // e.g. "Desktop Background.bmp"
 | |
|   nsString fileLeafName;
 | |
|   rv = shellBundle->GetStringFromName
 | |
|                       (NS_LITERAL_STRING("desktopBackgroundLeafNameWin").get(),
 | |
|                        getter_Copies(fileLeafName));
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   // get the profile root directory
 | |
|   nsCOMPtr<nsIFile> file;
 | |
|   rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR,
 | |
|                               getter_AddRefs(file));
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   // eventually, the path is "%APPDATA%\Mozilla\Firefox\Desktop Background.bmp"
 | |
|   rv = file->Append(fileLeafName);
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   nsAutoString path;
 | |
|   rv = file->GetPath(path);
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   // write the bitmap to a file in the profile directory
 | |
|   rv = WriteBitmap(file, container);
 | |
| 
 | |
|   // if the file was written successfully, set it as the system wallpaper
 | |
|   if (NS_SUCCEEDED(rv)) {
 | |
|      PRBool result = PR_FALSE;
 | |
|      DWORD  dwDisp = 0;
 | |
|      HKEY   key;
 | |
|      // Try to create/open a subkey under HKCU.
 | |
|      DWORD res = ::RegCreateKeyExW(HKEY_CURRENT_USER, CPL_DESKTOP,
 | |
|                                    0, NULL, REG_OPTION_NON_VOLATILE,
 | |
|                                    KEY_WRITE, NULL, &key, &dwDisp);
 | |
|     if (REG_SUCCEEDED(res)) {
 | |
| #ifndef WINCE
 | |
|       PRUnichar tile[2], style[2];
 | |
|       switch (aPosition) {
 | |
|         case BACKGROUND_TILE:
 | |
|           tile[0] = '1';
 | |
|           style[0] = '1';
 | |
|           break;
 | |
|         case BACKGROUND_CENTER:
 | |
|           tile[0] = '0';
 | |
|           style[0] = '0';
 | |
|           break;
 | |
|         case BACKGROUND_STRETCH:
 | |
|           tile[0] = '0';
 | |
|           style[0] = '2';
 | |
|           break;
 | |
|       }
 | |
|       tile[1] = '\0';
 | |
|       style[1] = '\0';
 | |
| 
 | |
|       // The size is always 3 unicode characters.
 | |
|       PRInt32 size = 3 * sizeof(PRUnichar);
 | |
|       ::RegSetValueExW(key, L"TileWallpaper",
 | |
|                        0, REG_SZ, (const BYTE *)tile, size);
 | |
|       ::RegSetValueExW(key, L"WallpaperStyle",
 | |
|                        0, REG_SZ, (const BYTE *)style, size);
 | |
|       ::SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (PVOID)path.get(),
 | |
|                               SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
 | |
| #else
 | |
|       DWORD tile = (aPosition == BACKGROUND_TILE);
 | |
|       ::RegSetValueExW(key, L"Tile",
 | |
|                        0, REG_DWORD, (const BYTE *)&tile, sizeof(DWORD));
 | |
|       // On WinCE SPI_SETDESKWALLPAPER isn't available, so set the registry
 | |
|       // entry ourselves and then broadcast UI change
 | |
|       PRInt32 size = (path.Length() + 1) * sizeof(PRUnichar);
 | |
|       ::RegSetValueExW(key, L"Wallpaper",
 | |
|                        0, REG_SZ, (const BYTE *)path.get(), size);
 | |
|       ::SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, NULL, 0);
 | |
| #endif
 | |
| 
 | |
|       // Close the key we opened.
 | |
|       ::RegCloseKey(key);
 | |
| 
 | |
| #ifdef WINCE
 | |
|       // Ensure that the writes are flushed in case of hard reboot
 | |
|       ::RegFlushKey(HKEY_CURRENT_USER);
 | |
| #endif
 | |
|     }
 | |
|   }
 | |
|   return rv;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWindowsShellService::OpenApplication(PRInt32 aApplication)
 | |
| {
 | |
|   nsAutoString application;
 | |
|   switch (aApplication) {
 | |
|   case nsIShellService::APPLICATION_MAIL:
 | |
|     application.AssignLiteral("Mail");
 | |
|     break;
 | |
|   case nsIShellService::APPLICATION_NEWS:
 | |
|     application.AssignLiteral("News");
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   // The Default Client section of the Windows Registry looks like this:
 | |
|   // 
 | |
|   // Clients\aClient\
 | |
|   //  e.g. aClient = "Mail"...
 | |
|   //        \Mail\(default) = Client Subkey Name
 | |
|   //             \Client Subkey Name
 | |
|   //             \Client Subkey Name\shell\open\command\ 
 | |
|   //             \Client Subkey Name\shell\open\command\(default) = path to exe
 | |
|   //
 | |
| 
 | |
|   // Find the default application for this class.
 | |
|   HKEY theKey;
 | |
|   nsresult rv = OpenKeyForReading(HKEY_CLASSES_ROOT, application, &theKey);
 | |
|   if (NS_FAILED(rv))
 | |
|     return rv;
 | |
| 
 | |
|   PRUnichar buf[MAX_BUF];
 | |
|   DWORD type, len = sizeof buf;
 | |
|   DWORD res = ::RegQueryValueExW(theKey, EmptyString().get(), 0,
 | |
|                                  &type, (LPBYTE)&buf, &len);
 | |
| 
 | |
|   if (REG_FAILED(res) || !*buf)
 | |
|     return NS_OK;
 | |
| 
 | |
|   // Close the key we opened.
 | |
|   ::RegCloseKey(theKey);
 | |
| 
 | |
|   // Find the "open" command
 | |
|   application.AppendLiteral("\\");
 | |
|   application.Append(buf);
 | |
|   application.AppendLiteral("\\shell\\open\\command");
 | |
| 
 | |
|   rv = OpenKeyForReading(HKEY_CLASSES_ROOT, application, &theKey);
 | |
|   if (NS_FAILED(rv))
 | |
|     return rv;
 | |
| 
 | |
|   ::ZeroMemory(buf, sizeof(buf));
 | |
|   len = sizeof buf;
 | |
|   res = ::RegQueryValueExW(theKey, EmptyString().get(), 0,
 | |
|                            &type, (LPBYTE)&buf, &len);
 | |
|   if (REG_FAILED(res) || !*buf)
 | |
|     return NS_ERROR_FAILURE;
 | |
| 
 | |
|   // Close the key we opened.
 | |
|   ::RegCloseKey(theKey);
 | |
| 
 | |
|   // Look for any embedded environment variables and substitute their 
 | |
|   // values, as |::CreateProcessW| is unable to do this.
 | |
|   nsAutoString path(buf);
 | |
|   PRInt32 end = path.Length();
 | |
|   PRInt32 cursor = 0, temp = 0;
 | |
|   ::ZeroMemory(buf, sizeof(buf));
 | |
|   do {
 | |
|     cursor = path.FindChar('%', cursor);
 | |
|     if (cursor < 0) 
 | |
|       break;
 | |
| 
 | |
|     temp = path.FindChar('%', cursor + 1);
 | |
|     ++cursor;
 | |
| 
 | |
|     ::ZeroMemory(&buf, sizeof(buf));
 | |
| 
 | |
|     ::GetEnvironmentVariableW(nsAutoString(Substring(path, cursor, temp - cursor)).get(),
 | |
|                               buf, sizeof(buf));
 | |
|     
 | |
|     // "+ 2" is to subtract the extra characters used to delimit the environment
 | |
|     // variable ('%').
 | |
|     path.Replace((cursor - 1), temp - cursor + 2, nsDependentString(buf));
 | |
| 
 | |
|     ++cursor;
 | |
|   }
 | |
|   while (cursor < end);
 | |
| 
 | |
|   STARTUPINFOW si;
 | |
|   PROCESS_INFORMATION pi;
 | |
| 
 | |
|   ::ZeroMemory(&si, sizeof(STARTUPINFOW));
 | |
|   ::ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
 | |
| 
 | |
|   BOOL success = ::CreateProcessW(NULL, (LPWSTR)path.get(), NULL,
 | |
|                                   NULL, FALSE, 0, NULL,  NULL,
 | |
|                                   &si, &pi);
 | |
|   if (!success)
 | |
|     return NS_ERROR_FAILURE;
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWindowsShellService::GetDesktopBackgroundColor(PRUint32* aColor)
 | |
| {
 | |
|   PRUint32 color = ::GetSysColor(COLOR_DESKTOP);
 | |
|   *aColor = (GetRValue(color) << 16) | (GetGValue(color) << 8) | GetBValue(color);
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWindowsShellService::SetDesktopBackgroundColor(PRUint32 aColor)
 | |
| {
 | |
|   int aParameters[2] = { COLOR_BACKGROUND, COLOR_DESKTOP };
 | |
|   BYTE r = (aColor >> 16);
 | |
|   BYTE g = (aColor << 16) >> 24;
 | |
|   BYTE b = (aColor << 24) >> 24;
 | |
|   COLORREF colors[2] = { RGB(r,g,b), RGB(r,g,b) };
 | |
| 
 | |
|   ::SetSysColors(sizeof(aParameters) / sizeof(int), aParameters, colors);
 | |
| 
 | |
|   // SetSysColors is persisting across sessions on Windows CE, so no need to
 | |
|   // write to registry
 | |
| #ifndef WINCE
 | |
|   PRBool result = PR_FALSE;
 | |
|   DWORD  dwDisp = 0;
 | |
|   HKEY   key;
 | |
|   // Try to create/open a subkey under HKCU.
 | |
|   DWORD rv = ::RegCreateKeyExW(HKEY_CURRENT_USER,
 | |
|                                L"Control Panel\\Colors", 0, NULL,
 | |
|                                REG_OPTION_NON_VOLATILE, KEY_WRITE, NULL,
 | |
|                                &key, &dwDisp);
 | |
| 
 | |
|   if (REG_SUCCEEDED(rv)) {
 | |
|     char rgb[12];
 | |
|     sprintf((char*)rgb, "%u %u %u\0", r, g, b);
 | |
|     NS_ConvertUTF8toUTF16 backColor(rgb);
 | |
| 
 | |
|     ::RegSetValueExW(key, L"Background",
 | |
|                      0, REG_SZ, (const BYTE *)backColor.get(),
 | |
|                      (backColor.Length() + 1) * sizeof(PRUnichar));
 | |
|   }
 | |
|   
 | |
|   // Close the key we opened.
 | |
|   ::RegCloseKey(key);
 | |
| #endif
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| #ifndef WINCE
 | |
| NS_IMETHODIMP
 | |
| nsWindowsShellService::GetUnreadMailCount(PRUint32* aCount)
 | |
| {
 | |
|   *aCount = 0;
 | |
| 
 | |
|   HKEY accountKey;
 | |
|   if (GetMailAccountKey(&accountKey)) {
 | |
|     DWORD type, unreadCount;
 | |
|     DWORD len = sizeof unreadCount;
 | |
|     DWORD res = ::RegQueryValueExW(accountKey, L"MessageCount", 0,
 | |
|                                    &type, (LPBYTE)&unreadCount, &len);
 | |
|     if (REG_SUCCEEDED(res))
 | |
|       *aCount = unreadCount;
 | |
| 
 | |
|     // Close the key we opened.
 | |
|     ::RegCloseKey(accountKey);
 | |
|   }
 | |
| 
 | |
|   return NS_OK;
 | |
| }
 | |
| 
 | |
| PRBool
 | |
| nsWindowsShellService::GetMailAccountKey(HKEY* aResult)
 | |
| {
 | |
|   NS_NAMED_LITERAL_STRING(unread,
 | |
|     "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\UnreadMail\\");
 | |
| 
 | |
|   HKEY mailKey;
 | |
|   DWORD res = ::RegOpenKeyExW(HKEY_CURRENT_USER, unread.get(), 0,
 | |
|                               KEY_ENUMERATE_SUB_KEYS, &mailKey);
 | |
| 
 | |
|   PRInt32 i = 0;
 | |
|   do {
 | |
|     PRUnichar subkeyName[MAX_BUF];
 | |
|     DWORD len = sizeof subkeyName;
 | |
|     res = ::RegEnumKeyExW(mailKey, i++, subkeyName, &len, NULL, NULL,
 | |
|                           NULL, NULL);
 | |
|     if (REG_SUCCEEDED(res)) {
 | |
|       HKEY accountKey;
 | |
|       res = ::RegOpenKeyExW(mailKey, PromiseFlatString(subkeyName).get(),
 | |
|                             0, KEY_READ, &accountKey);
 | |
|       if (REG_SUCCEEDED(res)) {
 | |
|         *aResult = accountKey;
 | |
|     
 | |
|         // Close the key we opened.
 | |
|         ::RegCloseKey(mailKey);
 | |
| 	 
 | |
|         return PR_TRUE;
 | |
|       }
 | |
|     }
 | |
|     else
 | |
|       break;
 | |
|   }
 | |
|   while (1);
 | |
| 
 | |
|   // Close the key we opened.
 | |
|   ::RegCloseKey(mailKey);
 | |
|   return PR_FALSE;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWindowsShellService::OpenApplicationWithURI(nsILocalFile* aApplication,
 | |
|                                               const nsACString& aURI)
 | |
| {
 | |
|   nsresult rv;
 | |
|   nsCOMPtr<nsIProcess> process = 
 | |
|     do_CreateInstance("@mozilla.org/process/util;1", &rv);
 | |
|   if (NS_FAILED(rv))
 | |
|     return rv;
 | |
|   
 | |
|   rv = process->Init(aApplication);
 | |
|   if (NS_FAILED(rv))
 | |
|     return rv;
 | |
|   
 | |
|   const nsCString spec(aURI);
 | |
|   const char* specStr = spec.get();
 | |
|   return process->Run(PR_FALSE, &specStr, 1);
 | |
| }
 | |
| 
 | |
| NS_IMETHODIMP
 | |
| nsWindowsShellService::GetDefaultFeedReader(nsILocalFile** _retval)
 | |
| {
 | |
|   *_retval = nsnull;
 | |
| 
 | |
|   nsresult rv;
 | |
|   nsCOMPtr<nsIWindowsRegKey> regKey =
 | |
|     do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT,
 | |
|                     NS_LITERAL_STRING("feed\\shell\\open\\command"),
 | |
|                     nsIWindowsRegKey::ACCESS_READ);
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   nsAutoString path;
 | |
|   rv = regKey->ReadStringValue(EmptyString(), path);
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
|   if (path.IsEmpty())
 | |
|     return NS_ERROR_FAILURE;
 | |
| 
 | |
|   if (path.First() == '"') {
 | |
|     // Everything inside the quotes
 | |
|     path = Substring(path, 1, path.FindChar('"', 1) - 1);
 | |
|   }
 | |
|   else {
 | |
|     // Everything up to the first space
 | |
|     path = Substring(path, 0, path.FindChar(' '));
 | |
|   }
 | |
| 
 | |
|   nsCOMPtr<nsILocalFile> defaultReader =
 | |
|     do_CreateInstance("@mozilla.org/file/local;1", &rv);
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   rv = defaultReader->InitWithPath(path);
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
| 
 | |
|   PRBool exists;
 | |
|   rv = defaultReader->Exists(&exists);
 | |
|   NS_ENSURE_SUCCESS(rv, rv);
 | |
|   if (!exists)
 | |
|     return NS_ERROR_FAILURE;
 | |
| 
 | |
|   NS_ADDREF(*_retval = defaultReader);
 | |
|   return NS_OK;
 | |
| }
 | 
