123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278 |
- /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
- /* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
- #include "nsWindowsShellService.h"
- #include "imgIContainer.h"
- #include "imgIRequest.h"
- #include "mozilla/gfx/2D.h"
- #include "mozilla/RefPtr.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 "nsServiceManagerUtils.h"
- #include "nsShellService.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 "nsIWinTaskbar.h"
- #include "nsISupportsPrimitives.h"
- #include "nsIURLFormatter.h"
- #include "nsThreadUtils.h"
- #include "nsXULAppAPI.h"
- #include "mozilla/WindowsVersion.h"
- #include "windows.h"
- #include "shellapi.h"
- #ifdef _WIN32_WINNT
- #undef _WIN32_WINNT
- #endif
- #define _WIN32_WINNT 0x0600
- #define INITGUID
- #undef NTDDI_VERSION
- #define NTDDI_VERSION NTDDI_WIN8
- // Needed for access to IApplicationActivationManager
- #include <shlobj.h>
- #include <mbstring.h>
- #include <shlwapi.h>
- #include <lm.h>
- #undef ACCESS_READ
- #ifndef MAX_BUF
- #define MAX_BUF 4096
- #endif
- #define REG_SUCCEEDED(val) \
- (val == ERROR_SUCCESS)
- #define REG_FAILED(val) \
- (val != ERROR_SUCCESS)
- #define NS_TASKBAR_CONTRACTID "@mozilla.org/windows-taskbar;1"
- using mozilla::IsWin8OrLater;
- using namespace mozilla;
- using namespace mozilla::gfx;
- NS_IMPL_ISUPPORTS(nsWindowsShellService, nsIWindowsShellService, nsIShellService)
- 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;
- }
- ///////////////////////////////////////////////////////////////////////////////
- // 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 PaleMoonHTML
- //
- // as aliases to the class:
- //
- // HKCU\SOFTWARE\Classes\PaleMoonHTML\
- // DefaultIcon (default) REG_SZ <apppath>,1
- // shell\open\command (default) REG_SZ <apppath> -osint -url "%1"
- // shell\open\ddeexec (default) REG_SZ <empty string>
- //
- // - Windows Vista and above Protocol Handler
- //
- // HKCU\SOFTWARE\Classes\PaleMoonURL\ (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> -osint -url "%1"
- // shell\open\ddeexec (default) REG_SZ <empty string>
- //
- // - 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> -osint -url "%1"
- // shell\open\ddeexec (default) REG_SZ <empty string>
- //
- // - Windows Start Menu (XP SP1 and newer)
- // -------------------------------------------------
- // The following keys are set to make PaleMoon appear in the Start Menu as the
- // browser:
- //
- // HKCU\SOFTWARE\Clients\StartMenuInternet\PaleMoon.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
- //
- // The values checked are all default values so the value name is not needed.
- typedef struct {
- const char* keyName;
- const char* valueData;
- const char* oldValueData;
- } SETTING;
- #define APP_REG_NAME L"Pale Moon"
- #define VAL_FILE_ICON "%APPPATH%,1"
- #define VAL_OPEN "\"%APPPATH%\" -osint -url \"%1\""
- #define OLD_VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\""
- #define DI "\\DefaultIcon"
- #define SOC "\\shell\\open\\command"
- #define SOD "\\shell\\open\\ddeexec"
- // Used for updating the FTP protocol handler's shell open command under HKCU.
- #define FTP_SOC L"Software\\Classes\\ftp\\shell\\open\\command"
- #define MAKE_KEY_NAME1(PREFIX, MID) \
- PREFIX MID
- // The DefaultIcon registry key value should never be used when checking if
- // PaleMoon 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. The FTP protocol is not checked so advanced users can set the FTP
- // handler to another application and still have PaleMoon check if it is the
- // default HTTP and HTTPS handler.
- // *** Do not add additional checks here unless you skip them when aForAllTypes
- // is false below***.
- static SETTING gSettings[] = {
- // File Handler Class
- // ***keep this as the first entry because when aForAllTypes is not set below
- // it will skip over this check.***
- { MAKE_KEY_NAME1("PaleMoonHTML", SOC), VAL_OPEN, OLD_VAL_OPEN },
- // Protocol Handler Class - for Vista and above
- { MAKE_KEY_NAME1("PaleMoonURL", SOC), VAL_OPEN, OLD_VAL_OPEN },
- // Protocol Handlers
- { MAKE_KEY_NAME1("HTTP", DI), VAL_FILE_ICON },
- { MAKE_KEY_NAME1("HTTP", SOC), VAL_OPEN, OLD_VAL_OPEN },
- { MAKE_KEY_NAME1("HTTPS", DI), VAL_FILE_ICON },
- { MAKE_KEY_NAME1("HTTPS", SOC), VAL_OPEN, OLD_VAL_OPEN }
- };
- // The settings to disable DDE are separate from the default browser settings
- // since they are only checked when PaleMoon is the default browser and if they
- // are incorrect they are fixed without notifying the user.
- static SETTING gDDESettings[] = {
- // File Handler Class
- { MAKE_KEY_NAME1("Software\\Classes\\PaleMoonHTML", SOD) },
- // Protocol Handler Class - for Vista and above
- { MAKE_KEY_NAME1("Software\\Classes\\PaleMoonURL", SOD) },
- // Protocol Handlers
- { MAKE_KEY_NAME1("Software\\Classes\\FTP", SOD) },
- { MAKE_KEY_NAME1("Software\\Classes\\HTTP", SOD) },
- { MAKE_KEY_NAME1("Software\\Classes\\HTTPS", SOD) }
- };
- nsresult
- GetHelperPath(nsAutoString& aPath)
- {
- nsresult rv;
- nsCOMPtr<nsIProperties> directoryService =
- do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- nsCOMPtr<nsIFile> appHelper;
- rv = directoryService->Get(XRE_EXECUTABLE_FILE,
- NS_GET_IID(nsIFile),
- getter_AddRefs(appHelper));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = appHelper->SetNativeLeafName(NS_LITERAL_CSTRING("uninstall"));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = appHelper->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
- NS_ENSURE_SUCCESS(rv, rv);
- rv = appHelper->GetPath(aPath);
- aPath.Insert(L'"', 0);
- aPath.Append(L'"');
- return rv;
- }
- nsresult
- LaunchHelper(nsAutoString& aPath)
- {
- STARTUPINFOW si = {sizeof(si), 0};
- PROCESS_INFORMATION pi = {0};
- if (!CreateProcessW(nullptr, (LPWSTR)aPath.get(), nullptr, nullptr, FALSE,
- 0, nullptr, nullptr, &si, &pi)) {
- return NS_ERROR_FAILURE;
- }
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsWindowsShellService::ShortcutMaintenance()
- {
- nsresult rv;
- // XXX App ids were updated to a constant install path hash,
- // XXX this code can be removed after a few upgrade cycles.
- // Launch helper.exe so it can update the application user model ids on
- // shortcuts in the user's taskbar and start menu. This keeps older pinned
- // shortcuts grouped correctly after major updates. Note, we also do this
- // through the upgrade installer script, however, this is the only place we
- // have a chance to trap links created by users who do control the install/
- // update process of the browser.
- nsCOMPtr<nsIWinTaskbar> taskbarInfo =
- do_GetService(NS_TASKBAR_CONTRACTID);
- if (!taskbarInfo) // If we haven't built with win7 sdk features, this fails.
- return NS_OK;
- // Avoid if this isn't Win7+
- bool isSupported = false;
- taskbarInfo->GetAvailable(&isSupported);
- if (!isSupported)
- return NS_OK;
- nsAutoString appId;
- if (NS_FAILED(taskbarInfo->GetDefaultGroupId(appId)))
- return NS_ERROR_UNEXPECTED;
- NS_NAMED_LITERAL_CSTRING(prefName, "browser.taskbar.lastgroupid");
- nsCOMPtr<nsIPrefBranch> prefs =
- do_GetService(NS_PREFSERVICE_CONTRACTID);
- if (!prefs)
- return NS_ERROR_UNEXPECTED;
- nsCOMPtr<nsISupportsString> prefString;
- rv = prefs->GetComplexValue(prefName.get(),
- NS_GET_IID(nsISupportsString),
- getter_AddRefs(prefString));
- if (NS_SUCCEEDED(rv)) {
- nsAutoString version;
- prefString->GetData(version);
- if (!version.IsEmpty() && version.Equals(appId)) {
- // We're all good, get out of here.
- return NS_OK;
- }
- }
- // Update the version in prefs
- prefString =
- do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID, &rv);
- if (NS_FAILED(rv))
- return rv;
- prefString->SetData(appId);
- rv = prefs->SetComplexValue(prefName.get(),
- NS_GET_IID(nsISupportsString),
- prefString);
- if (NS_FAILED(rv)) {
- NS_WARNING("Couldn't set last user model id!");
- return NS_ERROR_UNEXPECTED;
- }
- nsAutoString appHelperPath;
- if (NS_FAILED(GetHelperPath(appHelperPath)))
- return NS_ERROR_UNEXPECTED;
- appHelperPath.AppendLiteral(" /UpdateShortcutAppUserModelIds");
- return LaunchHelper(appHelperPath);
- }
- static bool
- IsAARDefault(const RefPtr<IApplicationAssociationRegistration>& pAAR,
- LPCWSTR aClassName)
- {
- // Make sure the Prog ID matches what we have
- LPWSTR registeredApp;
- bool isProtocol = *aClassName != L'.';
- ASSOCIATIONTYPE queryType = isProtocol ? AT_URLPROTOCOL : AT_FILEEXTENSION;
- HRESULT hr = pAAR->QueryCurrentDefault(aClassName, queryType, AL_EFFECTIVE,
- ®isteredApp);
- if (FAILED(hr)) {
- return false;
- }
- LPCWSTR progID = isProtocol ? L"PaleMoonURL" : L"PaleMoonHTML";
- bool isDefault = !wcsicmp(registeredApp, progID);
- CoTaskMemFree(registeredApp);
- return isDefault;
- }
- static void
- IsDefaultBrowserWin8(bool aCheckAllTypes, bool* aIsDefaultBrowser)
- {
- RefPtr<IApplicationAssociationRegistration> pAAR;
- HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
- nullptr,
- CLSCTX_INPROC,
- IID_IApplicationAssociationRegistration,
- getter_AddRefs(pAAR));
- if (FAILED(hr)) {
- return;
- }
- bool res = IsAARDefault(pAAR, L"http");
- if (*aIsDefaultBrowser) {
- *aIsDefaultBrowser = res;
- }
- res = IsAARDefault(pAAR, L".html");
- if (*aIsDefaultBrowser && aCheckAllTypes) {
- *aIsDefaultBrowser = res;
- }
- }
- /*
- * Query's the AAR for the default status.
- * This only checks for PaleMoonURL and if aCheckAllTypes is set, then
- * it also checks for PaleMoonHTML. Note that those ProgIDs are shared
- * by all PaleMoon browsers.
- */
- bool
- nsWindowsShellService::IsDefaultBrowserVista(bool aCheckAllTypes,
- bool* aIsDefaultBrowser)
- {
- RefPtr<IApplicationAssociationRegistration> pAAR;
- HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
- nullptr,
- CLSCTX_INPROC,
- IID_IApplicationAssociationRegistration,
- getter_AddRefs(pAAR));
- if (FAILED(hr)) {
- return false;
- }
- if (aCheckAllTypes) {
- BOOL res;
- hr = pAAR->QueryAppIsDefaultAll(AL_EFFECTIVE,
- APP_REG_NAME,
- &res);
- *aIsDefaultBrowser = res;
- } else if (!IsWin8OrLater()) {
- *aIsDefaultBrowser = IsAARDefault(pAAR, L"http");
- }
- return true;
- }
- NS_IMETHODIMP
- nsWindowsShellService::IsDefaultBrowser(bool aStartupCheck,
- bool aForAllTypes,
- bool* aIsDefaultBrowser)
- {
- // Assume we're the default unless one of the several checks below tell us
- // otherwise.
- *aIsDefaultBrowser = true;
- wchar_t exePath[MAX_BUF];
- if (!::GetModuleFileNameW(0, exePath, MAX_BUF))
- return NS_ERROR_FAILURE;
- // Convert the path to a long path since GetModuleFileNameW returns the path
- // that was used to launch PaleMoon which is not necessarily a long path.
- if (!::GetLongPathNameW(exePath, exePath, MAX_BUF))
- return NS_ERROR_FAILURE;
- nsAutoString appLongPath(exePath);
- HKEY theKey;
- DWORD res;
- nsresult rv;
- wchar_t currValue[MAX_BUF];
- SETTING* settings = gSettings;
- if (!aForAllTypes && IsWin8OrLater()) {
- // Skip over the file handler check
- settings++;
- }
- SETTING* end = gSettings + sizeof(gSettings) / sizeof(SETTING);
- for (; settings < end; ++settings) {
- NS_ConvertUTF8toUTF16 keyName(settings->keyName);
- NS_ConvertUTF8toUTF16 valueData(settings->valueData);
- int32_t offset = valueData.Find("%APPPATH%");
- valueData.Replace(offset, 9, appLongPath);
- rv = OpenKeyForReading(HKEY_CLASSES_ROOT, keyName, &theKey);
- if (NS_FAILED(rv)) {
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
- ::ZeroMemory(currValue, sizeof(currValue));
- DWORD len = sizeof currValue;
- res = ::RegQueryValueExW(theKey, L"", nullptr, nullptr,
- (LPBYTE)currValue, &len);
- // Close the key that was opened.
- ::RegCloseKey(theKey);
- if (REG_FAILED(res) ||
- _wcsicmp(valueData.get(), currValue)) {
- // Key wasn't set or was set to something other than our registry entry.
- NS_ConvertUTF8toUTF16 oldValueData(settings->oldValueData);
- offset = oldValueData.Find("%APPPATH%");
- oldValueData.Replace(offset, 9, appLongPath);
- // The current registry value doesn't match the current or the old format.
- if (_wcsicmp(oldValueData.get(), currValue)) {
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
- res = ::RegOpenKeyExW(HKEY_CLASSES_ROOT, PromiseFlatString(keyName).get(),
- 0, KEY_SET_VALUE, &theKey);
- if (REG_FAILED(res)) {
- // If updating the open command fails try to update it using the helper
- // application when setting PaleMoon as the default browser.
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
- const nsString &flatValue = PromiseFlatString(valueData);
- res = ::RegSetValueExW(theKey, L"", 0, REG_SZ,
- (const BYTE *) flatValue.get(),
- (flatValue.Length() + 1) * sizeof(char16_t));
- // Close the key that was created.
- ::RegCloseKey(theKey);
- if (REG_FAILED(res)) {
- // If updating the open command fails try to update it using the helper
- // application when setting PaleMoon as the default browser.
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
- }
- }
- // Only check if PaleMoon is the default browser on Vista and above if the
- // previous checks show that PaleMoon is the default browser.
- if (*aIsDefaultBrowser) {
- IsDefaultBrowserVista(aForAllTypes, aIsDefaultBrowser);
- if (IsWin8OrLater()) {
- IsDefaultBrowserWin8(aForAllTypes, aIsDefaultBrowser);
- }
- }
- // To handle the case where DDE isn't disabled due for a user because there
- // account didn't perform a PaleMoon update this will check if PaleMoon is the
- // default browser and if dde is disabled for each handler
- // and if it isn't disable it. When PaleMoon is not the default browser the
- // helper application will disable dde for each handler.
- if (*aIsDefaultBrowser && aForAllTypes) {
- // Check ftp settings
- end = gDDESettings + sizeof(gDDESettings) / sizeof(SETTING);
- for (settings = gDDESettings; settings < end; ++settings) {
- NS_ConvertUTF8toUTF16 keyName(settings->keyName);
- rv = OpenKeyForReading(HKEY_CURRENT_USER, keyName, &theKey);
- if (NS_FAILED(rv)) {
- ::RegCloseKey(theKey);
- // If disabling DDE fails try to disable it using the helper
- // application when setting PaleMoon as the default browser.
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
- ::ZeroMemory(currValue, sizeof(currValue));
- DWORD len = sizeof currValue;
- res = ::RegQueryValueExW(theKey, L"", nullptr, nullptr,
- (LPBYTE)currValue, &len);
- // Close the key that was opened.
- ::RegCloseKey(theKey);
- if (REG_FAILED(res) || char16_t('\0') != *currValue) {
- // Key wasn't set or was set to something other than our registry entry.
- // Delete the key along with all of its childrean and then recreate it.
- const nsString &flatName = PromiseFlatString(keyName);
- ::SHDeleteKeyW(HKEY_CURRENT_USER, flatName.get());
- res = ::RegCreateKeyExW(HKEY_CURRENT_USER, flatName.get(), 0, nullptr,
- REG_OPTION_NON_VOLATILE, KEY_SET_VALUE,
- nullptr, &theKey, nullptr);
- if (REG_FAILED(res)) {
- // If disabling DDE fails try to disable it using the helper
- // application when setting PaleMoon as the default browser.
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
- res = ::RegSetValueExW(theKey, L"", 0, REG_SZ, (const BYTE *) L"",
- sizeof(char16_t));
- // Close the key that was created.
- ::RegCloseKey(theKey);
- if (REG_FAILED(res)) {
- // If disabling DDE fails try to disable it using the helper
- // application when setting PaleMoon as the default browser.
- *aIsDefaultBrowser = false;
- return NS_OK;
- }
- }
- }
- // Update the FTP protocol handler's shell open command if it is the old
- // format.
- res = ::RegOpenKeyExW(HKEY_CURRENT_USER, FTP_SOC, 0, KEY_ALL_ACCESS,
- &theKey);
- // Don't update the FTP protocol handler's shell open command when opening
- // its registry key fails under HKCU since it most likely doesn't exist.
- if (NS_FAILED(rv)) {
- return NS_OK;
- }
- NS_ConvertUTF8toUTF16 oldValueOpen(OLD_VAL_OPEN);
- int32_t offset = oldValueOpen.Find("%APPPATH%");
- oldValueOpen.Replace(offset, 9, appLongPath);
- ::ZeroMemory(currValue, sizeof(currValue));
- DWORD len = sizeof currValue;
- res = ::RegQueryValueExW(theKey, L"", nullptr, nullptr, (LPBYTE)currValue,
- &len);
- // Don't update the FTP protocol handler's shell open command when the
- // current registry value doesn't exist or matches the old format.
- if (REG_FAILED(res) ||
- _wcsicmp(oldValueOpen.get(), currValue)) {
- ::RegCloseKey(theKey);
- return NS_OK;
- }
- NS_ConvertUTF8toUTF16 valueData(VAL_OPEN);
- valueData.Replace(offset, 9, appLongPath);
- const nsString &flatValue = PromiseFlatString(valueData);
- res = ::RegSetValueExW(theKey, L"", 0, REG_SZ,
- (const BYTE *) flatValue.get(),
- (flatValue.Length() + 1) * sizeof(char16_t));
- // Close the key that was created.
- ::RegCloseKey(theKey);
- // If updating the FTP protocol handlers shell open command fails try to
- // update it using the helper application when setting PaleMoon as the
- // default browser.
- if (REG_FAILED(res)) {
- *aIsDefaultBrowser = false;
- }
- }
- return NS_OK;
- }
- static nsresult
- DynSHOpenWithDialog(HWND hwndParent, const OPENASINFO *poainfo)
- {
- // shell32.dll is in the knownDLLs list so will always be loaded from the
- // system32 directory.
- static const wchar_t kSehllLibraryName[] = L"shell32.dll";
- HMODULE shellDLL = ::LoadLibraryW(kSehllLibraryName);
- if (!shellDLL) {
- return NS_ERROR_FAILURE;
- }
- decltype(SHOpenWithDialog)* SHOpenWithDialogFn =
- (decltype(SHOpenWithDialog)*) GetProcAddress(shellDLL, "SHOpenWithDialog");
- if (!SHOpenWithDialogFn) {
- return NS_ERROR_FAILURE;
- }
- nsresult rv;
- HRESULT hr = SHOpenWithDialogFn(hwndParent, poainfo);
- if (SUCCEEDED(hr) || (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))) {
- rv = NS_OK;
- } else {
- rv = NS_ERROR_FAILURE;
- }
- FreeLibrary(shellDLL);
- return rv;
- }
- nsresult
- nsWindowsShellService::LaunchControlPanelDefaultsSelectionUI()
- {
- IApplicationAssociationRegistrationUI* pAARUI;
- HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistrationUI,
- NULL,
- CLSCTX_INPROC,
- IID_IApplicationAssociationRegistrationUI,
- (void**)&pAARUI);
- if (SUCCEEDED(hr)) {
- hr = pAARUI->LaunchAdvancedAssociationUI(APP_REG_NAME);
- pAARUI->Release();
- }
- return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
- }
- nsresult
- nsWindowsShellService::LaunchControlPanelDefaultPrograms()
- {
- // Build the path control.exe path safely
- WCHAR controlEXEPath[MAX_PATH + 1] = { '\0' };
- if (!GetSystemDirectoryW(controlEXEPath, MAX_PATH)) {
- return NS_ERROR_FAILURE;
- }
- LPCWSTR controlEXE = L"control.exe";
- if (wcslen(controlEXEPath) + wcslen(controlEXE) >= MAX_PATH) {
- return NS_ERROR_FAILURE;
- }
- if (!PathAppendW(controlEXEPath, controlEXE)) {
- return NS_ERROR_FAILURE;
- }
- WCHAR params[] = L"control.exe /name Microsoft.DefaultPrograms /page "
- "pageDefaultProgram\\pageAdvancedSettings?pszAppName=" APP_REG_NAME;
- STARTUPINFOW si = {sizeof(si), 0};
- si.dwFlags = STARTF_USESHOWWINDOW;
- si.wShowWindow = SW_SHOWDEFAULT;
- PROCESS_INFORMATION pi = {0};
- if (!CreateProcessW(controlEXEPath, params, nullptr, nullptr, FALSE,
- 0, nullptr, nullptr, &si, &pi)) {
- return NS_ERROR_FAILURE;
- }
- CloseHandle(pi.hProcess);
- CloseHandle(pi.hThread);
- return NS_OK;
- }
- static bool
- IsWindowsLogonConnected()
- {
- WCHAR userName[UNLEN + 1];
- DWORD size = ArrayLength(userName);
- if (!GetUserNameW(userName, &size)) {
- return false;
- }
- LPUSER_INFO_24 info;
- if (NetUserGetInfo(nullptr, userName, 24, (LPBYTE *)&info)
- != NERR_Success) {
- return false;
- }
- bool connected = info->usri24_internet_identity;
- NetApiBufferFree(info);
- return connected;
- }
- static bool
- SettingsAppBelievesConnected()
- {
- nsresult rv;
- nsCOMPtr<nsIWindowsRegKey> regKey =
- do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
- if (NS_FAILED(rv)) {
- return false;
- }
- rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
- NS_LITERAL_STRING("SOFTWARE\\Microsoft\\Windows\\Shell\\Associations"),
- nsIWindowsRegKey::ACCESS_READ);
- if (NS_FAILED(rv)) {
- return false;
- }
- uint32_t value;
- rv = regKey->ReadIntValue(NS_LITERAL_STRING("IsConnectedAtLogon"), &value);
- if (NS_FAILED(rv)) {
- return false;
- }
- return !!value;
- }
- nsresult
- nsWindowsShellService::LaunchModernSettingsDialogDefaultApps()
- {
- if (!IsWindowsBuildOrLater(14965) &&
- !IsWindowsLogonConnected() && SettingsAppBelievesConnected()) {
- // Use the classic Control Panel to work around a bug of older
- // builds of Windows 10.
- return LaunchControlPanelDefaultPrograms();
- }
- IApplicationActivationManager* pActivator;
- HRESULT hr = CoCreateInstance(CLSID_ApplicationActivationManager,
- nullptr,
- CLSCTX_INPROC,
- IID_IApplicationActivationManager,
- (void**)&pActivator);
- if (SUCCEEDED(hr)) {
- DWORD pid;
- hr = pActivator->ActivateApplication(
- L"windows.immersivecontrolpanel_cw5n1h2txyewy"
- L"!microsoft.windows.immersivecontrolpanel",
- L"page=SettingsPageAppsDefaults", AO_NONE, &pid);
- if (SUCCEEDED(hr)) {
- // Do not check error because we could at least open
- // the "Default apps" setting.
- pActivator->ActivateApplication(
- L"windows.immersivecontrolpanel_cw5n1h2txyewy"
- L"!microsoft.windows.immersivecontrolpanel",
- L"page=SettingsPageAppsDefaults"
- L"&target=SystemSettings_DefaultApps_Browser", AO_NONE, &pid);
- }
- pActivator->Release();
- return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
- }
- return NS_OK;
- }
- nsresult
- nsWindowsShellService::InvokeHTTPOpenAsVerb()
- {
- nsCOMPtr<nsIURLFormatter> formatter(
- do_GetService("@mozilla.org/toolkit/URLFormatterService;1"));
- if (!formatter) {
- return NS_ERROR_UNEXPECTED;
- }
- nsString urlStr;
- nsresult rv = formatter->FormatURLPref(
- NS_LITERAL_STRING("app.support.baseURL"), urlStr);
- if (NS_FAILED(rv)) {
- return rv;
- }
- if (!StringBeginsWith(urlStr, NS_LITERAL_STRING("https://"))) {
- return NS_ERROR_FAILURE;
- }
- urlStr.AppendLiteral("win10-default-browser");
- SHELLEXECUTEINFOW seinfo = { sizeof(SHELLEXECUTEINFOW) };
- seinfo.lpVerb = L"openas";
- seinfo.lpFile = urlStr.get();
- seinfo.nShow = SW_SHOWNORMAL;
- if (!ShellExecuteExW(&seinfo)) {
- return NS_ERROR_FAILURE;
- }
- return NS_OK;
- }
- nsresult
- nsWindowsShellService::LaunchHTTPHandlerPane()
- {
- OPENASINFO info;
- info.pcszFile = L"http";
- info.pcszClass = nullptr;
- info.oaifInFlags = OAIF_FORCE_REGISTRATION |
- OAIF_URL_PROTOCOL |
- OAIF_REGISTER_EXT;
- return DynSHOpenWithDialog(nullptr, &info);
- }
- NS_IMETHODIMP
- nsWindowsShellService::SetDefaultBrowser(bool aClaimAllTypes, bool aForAllUsers)
- {
- nsAutoString appHelperPath;
- if (NS_FAILED(GetHelperPath(appHelperPath)))
- return NS_ERROR_FAILURE;
- if (aForAllUsers) {
- appHelperPath.AppendLiteral(" /SetAsDefaultAppGlobal");
- } else {
- appHelperPath.AppendLiteral(" /SetAsDefaultAppUser");
- }
- nsresult rv = LaunchHelper(appHelperPath);
- if (NS_SUCCEEDED(rv) && IsWin8OrLater()) {
- if (aClaimAllTypes) {
- if (IsWin10OrLater()) {
- rv = LaunchModernSettingsDialogDefaultApps();
- } else {
- rv = LaunchControlPanelDefaultsSelectionUI();
- }
- // The above call should never really fail, but just in case
- // fall back to showing the HTTP association screen only.
- if (NS_FAILED(rv)) {
- if (IsWin10OrLater()) {
- rv = InvokeHTTPOpenAsVerb();
- } else {
- rv = LaunchHTTPHandlerPane();
- }
- }
- } else {
- // Windows 10 blocks attempts to load the
- // HTTP Handler association dialog.
- if (IsWin10OrLater()) {
- rv = LaunchModernSettingsDialogDefaultApps();
- } else {
- rv = LaunchHTTPHandlerPane();
- }
- // The above call should never really fail, but just in case
- // fall back to showing control panel for all defaults
- if (NS_FAILED(rv)) {
- rv = LaunchControlPanelDefaultsSelectionUI();
- }
- }
- }
- nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
- if (prefs) {
- (void) prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, true);
- // Reset the number of times the dialog should be shown
- // before it is silenced.
- (void) prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, 0);
- }
- return rv;
- }
- static nsresult
- WriteBitmap(nsIFile* aFile, imgIContainer* aImage)
- {
- nsresult rv;
- RefPtr<SourceSurface> surface =
- aImage->GetFrame(imgIContainer::FRAME_FIRST,
- imgIContainer::FLAG_SYNC_DECODE);
- NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
- // For either of the following formats we want to set the biBitCount member
- // of the BITMAPINFOHEADER struct to 32, below. For that value the bitmap
- // format defines that the A8/X8 WORDs in the bitmap byte stream be ignored
- // for the BI_RGB value we use for the biCompression member.
- MOZ_ASSERT(surface->GetFormat() == SurfaceFormat::B8G8R8A8 ||
- surface->GetFormat() == SurfaceFormat::B8G8R8X8);
- RefPtr<DataSourceSurface> dataSurface = surface->GetDataSurface();
- NS_ENSURE_TRUE(dataSurface, NS_ERROR_FAILURE);
- int32_t width = dataSurface->GetSize().width;
- int32_t height = dataSurface->GetSize().height;
- int32_t bytesPerPixel = 4 * sizeof(uint8_t);
- uint32_t bytesPerRow = bytesPerPixel * 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)bytesPerPixel*8;
- bmi.biCompression = BI_RGB;
- bmi.biSizeImage = bytesPerRow * height;
- 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);
- DataSourceSurface::MappedSurface map;
- if (!dataSurface->Map(DataSourceSurface::MapType::READ, &map)) {
- return NS_ERROR_FAILURE;
- }
- // write the bitmap headers and rgb pixel data to the file
- rv = NS_ERROR_FAILURE;
- if (stream) {
- uint32_t 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
- uint32_t i = map.mStride * height;
- do {
- i -= map.mStride;
- stream->Write(((const char*)map.mData) + i, bytesPerRow, &written);
- if (written == bytesPerRow) {
- rv = NS_OK;
- } else {
- rv = NS_ERROR_FAILURE;
- break;
- }
- } while (i != 0);
- }
- }
- stream->Close();
- }
- dataSurface->Unmap();
- return rv;
- }
- NS_IMETHODIMP
- nsWindowsShellService::SetDesktopBackground(nsIDOMElement* aElement,
- int32_t 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
- (u"desktopBackgroundLeafNameWin",
- 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\PaleMoon\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)) {
- nsCOMPtr<nsIWindowsRegKey> regKey =
- do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
- NS_LITERAL_STRING("Control Panel\\Desktop"),
- nsIWindowsRegKey::ACCESS_SET_VALUE);
- NS_ENSURE_SUCCESS(rv, rv);
- nsAutoString tile;
- nsAutoString style;
- switch (aPosition) {
- case BACKGROUND_TILE:
- style.Assign('0');
- tile.Assign('1');
- break;
- case BACKGROUND_CENTER:
- style.Assign('0');
- tile.Assign('0');
- break;
- case BACKGROUND_STRETCH:
- style.Assign('2');
- tile.Assign('0');
- break;
- case BACKGROUND_FILL:
- style.AssignLiteral("10");
- tile.Assign('0');
- break;
- case BACKGROUND_FIT:
- style.Assign('6');
- tile.Assign('0');
- break;
- }
- rv = regKey->WriteStringValue(NS_LITERAL_STRING("TileWallpaper"), tile);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = regKey->WriteStringValue(NS_LITERAL_STRING("WallpaperStyle"), style);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = regKey->Close();
- NS_ENSURE_SUCCESS(rv, rv);
- ::SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (PVOID)path.get(),
- SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
- }
- return rv;
- }
- NS_IMETHODIMP
- nsWindowsShellService::OpenApplication(int32_t 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;
- wchar_t 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.Append('\\');
- 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);
- int32_t end = path.Length();
- int32_t 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(nullptr, (LPWSTR)path.get(), nullptr,
- nullptr, FALSE, 0, nullptr, nullptr,
- &si, &pi);
- if (!success)
- return NS_ERROR_FAILURE;
- return NS_OK;
- }
- NS_IMETHODIMP
- nsWindowsShellService::GetDesktopBackgroundColor(uint32_t* aColor)
- {
- uint32_t color = ::GetSysColor(COLOR_DESKTOP);
- *aColor = (GetRValue(color) << 16) | (GetGValue(color) << 8) | GetBValue(color);
- return NS_OK;
- }
- NS_IMETHODIMP
- nsWindowsShellService::SetDesktopBackgroundColor(uint32_t 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);
- nsresult rv;
- nsCOMPtr<nsIWindowsRegKey> regKey =
- do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
- NS_LITERAL_STRING("Control Panel\\Colors"),
- nsIWindowsRegKey::ACCESS_SET_VALUE);
- NS_ENSURE_SUCCESS(rv, rv);
- wchar_t rgb[12];
- _snwprintf(rgb, 12, L"%u %u %u", r, g, b);
- rv = regKey->WriteStringValue(NS_LITERAL_STRING("Background"),
- nsDependentString(rgb));
- NS_ENSURE_SUCCESS(rv, rv);
- return regKey->Close();
- }
- nsWindowsShellService::nsWindowsShellService()
- {
- }
- nsWindowsShellService::~nsWindowsShellService()
- {
- }
- NS_IMETHODIMP
- nsWindowsShellService::OpenApplicationWithURI(nsIFile* 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(false, &specStr, 1);
- }
- NS_IMETHODIMP
- nsWindowsShellService::GetDefaultFeedReader(nsIFile** _retval)
- {
- *_retval = nullptr;
- 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<nsIFile> defaultReader =
- do_CreateInstance("@mozilla.org/file/local;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
- rv = defaultReader->InitWithPath(path);
- NS_ENSURE_SUCCESS(rv, rv);
- bool exists;
- rv = defaultReader->Exists(&exists);
- NS_ENSURE_SUCCESS(rv, rv);
- if (!exists)
- return NS_ERROR_FAILURE;
- NS_ADDREF(*_retval = defaultReader);
- return NS_OK;
- }
|