1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Shell Service.
17 * The Initial Developer of the Original Code is mozilla.org.
18 * Portions created by the Initial Developer are Copyright (C) 2004
19 * the Initial Developer. All Rights Reserved.
22 * Ben Goodger <ben@mozilla.org> (Clients, Mail, New Default Browser)
23 * Joe Hewitt <hewitt@netscape.com> (Set Background)
24 * Blake Ross <blake@cs.stanford.edu> (Desktop Color, DDE support)
25 * Jungshik Shin <jshin@mailaps.org> (I18N)
26 * Robert Strong <robert.bugzilla@gmail.com>
27 * Asaf Romano <mano@mozilla.com>
28 * Ryan Jones <sciguyryan@gmail.com>
30 * Alternatively, the contents of this file may be used under the terms of
31 * either the GNU General Public License Version 2 or later (the "GPL"), or
32 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
33 * in which case the provisions of the GPL or the LGPL are applicable instead
34 * of those above. If you wish to allow use of your version of this file only
35 * under the terms of either the GPL or the LGPL, and not to allow others to
36 * use your version of this file under the terms of the MPL, indicate your
37 * decision by deleting the provisions above and replace them with the notice
38 * and other provisions required by the GPL or the LGPL. If you do not delete
39 * the provisions above, a recipient may use your version of this file under
40 * the terms of any one of the MPL, the GPL or the LGPL.
42 * ***** END LICENSE BLOCK ***** */
44 #include "gfxIImageFrame.h"
45 #include "imgIContainer.h"
46 #include "imgIRequest.h"
47 #include "nsIDOMDocument.h"
48 #include "nsIDOMElement.h"
49 #include "nsIDOMHTMLImageElement.h"
50 #include "nsIImageLoadingContent.h"
51 #include "nsIPrefService.h"
52 #include "nsIPrefLocalizedString.h"
53 #include "nsIServiceManager.h"
54 #include "nsIStringBundle.h"
55 #include "nsNetUtil.h"
56 #include "nsShellService.h"
57 #include "nsWindowsShellService.h"
58 #include "nsIProcess.h"
59 #include "nsICategoryManager.h"
60 #include "nsBrowserCompsCID.h"
61 #include "nsDirectoryServiceUtils.h"
62 #include "nsAppDirectoryServiceDefs.h"
63 #include "nsDirectoryServiceDefs.h"
64 #include "nsIWindowsRegKey.h"
65 #include "nsUnicharUtils.h"
73 #define _WIN32_WINNT 0x0600
83 #define REG_SUCCEEDED(val) \
84 (val == ERROR_SUCCESS)
86 #define REG_FAILED(val) \
87 (val != ERROR_SUCCESS)
89 NS_IMPL_ISUPPORTS2(nsWindowsShellService
, nsIWindowsShellService
, nsIShellService
)
92 OpenKeyForReading(HKEY aKeyRoot
, const nsAString
& aKeyName
, HKEY
* aKey
)
94 const nsString
&flatName
= PromiseFlatString(aKeyName
);
96 DWORD res
= ::RegOpenKeyExW(aKeyRoot
, flatName
.get(), 0, KEY_READ
, aKey
);
100 case ERROR_ACCESS_DENIED
:
101 return NS_ERROR_FILE_ACCESS_DENIED
;
102 case ERROR_FILE_NOT_FOUND
:
103 return NS_ERROR_NOT_AVAILABLE
;
109 ///////////////////////////////////////////////////////////////////////////////
110 // Default Browser Registry Settings
112 // The setting of these values are made by an external binary since writing
113 // these values may require elevation.
115 // - File Extension Mappings
116 // -----------------------
117 // The following file extensions:
118 // .htm .html .shtml .xht .xhtml
119 // are mapped like so:
121 // HKCU\SOFTWARE\Classes\.<ext>\ (default) REG_SZ FirefoxHTML
123 // as aliases to the class:
125 // HKCU\SOFTWARE\Classes\FirefoxHTML\
126 // DefaultIcon (default) REG_SZ <apppath>,1
127 // shell\open\command (default) REG_SZ <apppath> -requestPending -osint -url "%1"
128 // shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,,
129 // shell\open\ddeexec NoActivateHandler REG_SZ
130 // \Application (default) REG_SZ Firefox
131 // \Topic (default) REG_SZ WWW_OpenURL
133 // - Windows Vista Protocol Handler
135 // HKCU\SOFTWARE\Classes\FirefoxURL\ (default) REG_SZ <appname> URL
136 // EditFlags REG_DWORD 2
137 // FriendlyTypeName REG_SZ <appname> URL
138 // DefaultIcon (default) REG_SZ <apppath>,1
139 // shell\open\command (default) REG_SZ <apppath> -requestPending -osint -url "%1"
140 // shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,,
141 // shell\open\ddeexec NoActivateHandler REG_SZ
142 // \Application (default) REG_SZ Firefox
143 // \Topic (default) REG_SZ WWW_OpenURL
145 // - Protocol Mappings
147 // The following protocols:
149 // are mapped like so:
151 // HKCU\SOFTWARE\Classes\<protocol>\
152 // DefaultIcon (default) REG_SZ <apppath>,1
153 // shell\open\command (default) REG_SZ <apppath> -requestPending -osint -url "%1"
154 // shell\open\ddeexec (default) REG_SZ "%1",,0,0,,,,
155 // shell\open\ddeexec NoActivateHandler REG_SZ
156 // \Application (default) REG_SZ Firefox
157 // \Topic (default) REG_SZ WWW_OpenURL
159 // - Windows Start Menu (Win2K SP2, XP SP1, and newer)
160 // -------------------------------------------------
161 // The following keys are set to make Firefox appear in the Start Menu as the
164 // HKCU\SOFTWARE\Clients\StartMenuInternet\FIREFOX.EXE\
165 // (default) REG_SZ <appname>
166 // DefaultIcon (default) REG_SZ <apppath>,0
167 // InstallInfo HideIconsCommand REG_SZ <uninstpath> /HideShortcuts
168 // InstallInfo IconsVisible REG_DWORD 1
169 // InstallInfo ReinstallCommand REG_SZ <uninstpath> /SetAsDefaultAppGlobal
170 // InstallInfo ShowIconsCommand REG_SZ <uninstpath> /ShowShortcuts
171 // shell\open\command (default) REG_SZ <apppath>
172 // shell\properties (default) REG_SZ <appname> &Options
173 // shell\properties\command (default) REG_SZ <apppath> -preferences
174 // shell\safemode (default) REG_SZ <appname> &Safe Mode
175 // shell\safemode\command (default) REG_SZ <apppath> -safe-mode
179 NO_SUBSTITUTION
= 0x00,
180 APP_PATH_SUBSTITUTION
= 0x01,
181 EXE_NAME_SUBSTITUTION
= 0x02
192 #define APP_REG_NAME L"Firefox"
193 #define DI "\\DefaultIcon"
194 #define SOP "\\shell\\open\\command"
196 #define CLS_HTML "FirefoxHTML"
197 #define CLS_URL "FirefoxURL"
198 #define VAL_FILE_ICON "%APPPATH%,1"
199 #define VAL_OPEN "\"%APPPATH%\" -requestPending -osint -url \"%1\""
201 #define MAKE_KEY_NAME1(PREFIX, MID) \
204 // The DefaultIcon registry key value should never be used when checking if
205 // Firefox is the default browser since other applications (e.g. MS Office) may
206 // modify the DefaultIcon registry key value to add Icon Handlers.
207 // see http://msdn2.microsoft.com/en-us/library/aa969357.aspx for more info.
208 static SETTING gSettings
[] = {
209 // File Extension Class - as of 1.8.1.2 the value for VAL_OPEN is also checked
210 // for CLS_HTML since Firefox should also own opeing local files when set as
211 // the default browser.
212 { MAKE_KEY_NAME1(CLS_HTML
, SOP
), "", VAL_OPEN
, APP_PATH_SUBSTITUTION
},
214 // Protocol Handler Class - for Vista and above
215 { MAKE_KEY_NAME1(CLS_URL
, SOP
), "", VAL_OPEN
, APP_PATH_SUBSTITUTION
},
218 { MAKE_KEY_NAME1("HTTP", DI
), "", VAL_FILE_ICON
, APP_PATH_SUBSTITUTION
},
219 { MAKE_KEY_NAME1("HTTP", SOP
), "", VAL_OPEN
, APP_PATH_SUBSTITUTION
},
220 { MAKE_KEY_NAME1("HTTPS", DI
), "", VAL_FILE_ICON
, APP_PATH_SUBSTITUTION
},
221 { MAKE_KEY_NAME1("HTTPS", SOP
), "", VAL_OPEN
, APP_PATH_SUBSTITUTION
}
225 nsWindowsShellService::IsDefaultBrowserVista(PRBool
* aIsDefaultBrowser
)
227 #if !defined(MOZ_DISABLE_VISTA_SDK_REQUIREMENTS)
228 IApplicationAssociationRegistration
* pAAR
;
230 HRESULT hr
= CoCreateInstance(CLSID_ApplicationAssociationRegistration
,
233 IID_IApplicationAssociationRegistration
,
237 hr
= pAAR
->QueryAppIsDefaultAll(AL_EFFECTIVE
,
249 nsWindowsShellService::IsDefaultBrowser(PRBool aStartupCheck
,
250 PRBool
* aIsDefaultBrowser
)
252 // If this is the first browser window, maintain internal state that we've
253 // checked this session (so that subsequent window opens don't show the
254 // default browser dialog).
256 mCheckedThisSession
= PR_TRUE
;
259 SETTING
* end
= gSettings
+ sizeof(gSettings
)/sizeof(SETTING
);
261 *aIsDefaultBrowser
= PR_TRUE
;
263 PRUnichar exePath
[MAX_BUF
];
264 if (!::GetModuleFileNameW(0, exePath
, MAX_BUF
))
265 return NS_ERROR_FAILURE
;
267 nsAutoString
appLongPath(exePath
);
269 // Support short path to the exe so if it is already set the user is not
270 // prompted to set the default browser again.
271 if (!::GetShortPathNameW(exePath
, exePath
, sizeof(exePath
)))
272 return NS_ERROR_FAILURE
;
274 nsAutoString
appShortPath(exePath
);
275 ToUpperCase(appShortPath
);
277 nsCOMPtr
<nsILocalFile
> lf
;
278 nsresult rv
= NS_NewLocalFile(appShortPath
, PR_TRUE
,
283 nsAutoString exeName
;
284 rv
= lf
->GetLeafName(exeName
);
287 ToUpperCase(exeName
);
289 PRUnichar currValue
[MAX_BUF
];
290 for (settings
= gSettings
; settings
< end
; ++settings
) {
291 NS_ConvertUTF8toUTF16
dataLongPath(settings
->valueData
);
292 NS_ConvertUTF8toUTF16
dataShortPath(settings
->valueData
);
293 NS_ConvertUTF8toUTF16
key(settings
->keyName
);
294 NS_ConvertUTF8toUTF16
value(settings
->valueName
);
295 if (settings
->flags
& APP_PATH_SUBSTITUTION
) {
296 PRInt32 offset
= dataLongPath
.Find("%APPPATH%");
297 dataLongPath
.Replace(offset
, 9, appLongPath
);
298 // Remove the quotes around %APPPATH% in VAL_OPEN for short paths
299 PRInt32 offsetQuoted
= dataShortPath
.Find("\"%APPPATH%\"");
300 if (offsetQuoted
!= -1)
301 dataShortPath
.Replace(offsetQuoted
, 11, appShortPath
);
303 dataShortPath
.Replace(offset
, 9, appShortPath
);
305 if (settings
->flags
& EXE_NAME_SUBSTITUTION
) {
306 PRInt32 offset
= key
.Find("%APPEXE%");
307 key
.Replace(offset
, 8, exeName
);
310 ::ZeroMemory(currValue
, sizeof(currValue
));
312 rv
= OpenKeyForReading(HKEY_CLASSES_ROOT
, key
, &theKey
);
314 *aIsDefaultBrowser
= PR_FALSE
;
318 DWORD len
= sizeof currValue
;
319 DWORD res
= ::RegQueryValueExW(theKey
, PromiseFlatString(value
).get(),
320 NULL
, NULL
, (LPBYTE
)currValue
, &len
);
321 // Close the key we opened.
322 ::RegCloseKey(theKey
);
323 if (REG_FAILED(res
) ||
324 !dataLongPath
.Equals(currValue
, CaseInsensitiveCompare
) &&
325 !dataShortPath
.Equals(currValue
, CaseInsensitiveCompare
)) {
326 // Key wasn't set, or was set to something other than our registry entry
327 *aIsDefaultBrowser
= PR_FALSE
;
332 // Only check if Firefox is the default browser on Vista if the previous
333 // checks show that Firefox is the default browser.
334 if (*aIsDefaultBrowser
)
335 IsDefaultBrowserVista(aIsDefaultBrowser
);
341 nsWindowsShellService::SetDefaultBrowser(PRBool aClaimAllTypes
, PRBool aForAllUsers
)
344 nsCOMPtr
<nsIProperties
> directoryService
=
345 do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID
, &rv
);
346 NS_ENSURE_SUCCESS(rv
, rv
);
348 nsCOMPtr
<nsILocalFile
> appHelper
;
349 rv
= directoryService
->Get(NS_XPCOM_CURRENT_PROCESS_DIR
, NS_GET_IID(nsILocalFile
), getter_AddRefs(appHelper
));
350 NS_ENSURE_SUCCESS(rv
, rv
);
352 rv
= appHelper
->AppendNative(NS_LITERAL_CSTRING("uninstall"));
353 NS_ENSURE_SUCCESS(rv
, rv
);
355 rv
= appHelper
->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
356 NS_ENSURE_SUCCESS(rv
, rv
);
358 nsAutoString appHelperPath
;
359 rv
= appHelper
->GetPath(appHelperPath
);
360 NS_ENSURE_SUCCESS(rv
, rv
);
363 appHelperPath
.AppendLiteral(" /SetAsDefaultAppGlobal");
365 appHelperPath
.AppendLiteral(" /SetAsDefaultAppUser");
368 STARTUPINFOW si
= {sizeof(si
), 0};
369 PROCESS_INFORMATION pi
= {0};
371 BOOL ok
= CreateProcessW(NULL
, (LPWSTR
)appHelperPath
.get(), NULL
, NULL
,
372 FALSE
, 0, NULL
, NULL
, &si
, &pi
);
375 return NS_ERROR_FAILURE
;
377 CloseHandle(pi
.hProcess
);
378 CloseHandle(pi
.hThread
);
384 nsWindowsShellService::GetShouldCheckDefaultBrowser(PRBool
* aResult
)
386 // If we've already checked, the browser has been started and this is a
387 // new window open, and we don't want to check again.
388 if (mCheckedThisSession
) {
393 nsCOMPtr
<nsIPrefBranch
> prefs
;
394 nsCOMPtr
<nsIPrefService
> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID
));
396 pserve
->GetBranch("", getter_AddRefs(prefs
));
398 prefs
->GetBoolPref(PREF_CHECKDEFAULTBROWSER
, aResult
);
404 nsWindowsShellService::SetShouldCheckDefaultBrowser(PRBool aShouldCheck
)
406 nsCOMPtr
<nsIPrefBranch
> prefs
;
407 nsCOMPtr
<nsIPrefService
> pserve(do_GetService(NS_PREFSERVICE_CONTRACTID
));
409 pserve
->GetBranch("", getter_AddRefs(prefs
));
411 prefs
->SetBoolPref(PREF_CHECKDEFAULTBROWSER
, aShouldCheck
);
417 WriteBitmap(nsIFile
* aFile
, gfxIImageFrame
* aImage
)
419 PRInt32 width
, height
;
420 aImage
->GetWidth(&width
);
421 aImage
->GetHeight(&height
);
425 aImage
->LockImageData();
426 aImage
->GetImageData(&bits
, &length
);
428 aImage
->UnlockImageData();
429 return NS_ERROR_FAILURE
;
433 aImage
->GetImageBytesPerRow(&bpr
);
434 PRInt32 bitCount
= bpr
/width
;
436 // initialize these bitmap structs which we will later
437 // serialize directly to the head of the bitmap file
438 BITMAPINFOHEADER bmi
;
439 bmi
.biSize
= sizeof(BITMAPINFOHEADER
);
441 bmi
.biHeight
= height
;
443 bmi
.biBitCount
= (WORD
)bitCount
*8;
444 bmi
.biCompression
= BI_RGB
;
445 bmi
.biSizeImage
= length
;
446 bmi
.biXPelsPerMeter
= 0;
447 bmi
.biYPelsPerMeter
= 0;
449 bmi
.biClrImportant
= 0;
452 bf
.bfType
= 0x4D42; // 'BM'
455 bf
.bfOffBits
= sizeof(BITMAPFILEHEADER
) + sizeof(BITMAPINFOHEADER
);
456 bf
.bfSize
= bf
.bfOffBits
+ bmi
.biSizeImage
;
458 // get a file output stream
459 nsCOMPtr
<nsIOutputStream
> stream
;
460 nsresult rv
= NS_NewLocalFileOutputStream(getter_AddRefs(stream
), aFile
);
461 NS_ENSURE_SUCCESS(rv
, rv
);
463 // write the bitmap headers and rgb pixel data to the file
464 rv
= NS_ERROR_FAILURE
;
467 stream
->Write((const char*)&bf
, sizeof(BITMAPFILEHEADER
), &written
);
468 if (written
== sizeof(BITMAPFILEHEADER
)) {
469 stream
->Write((const char*)&bmi
, sizeof(BITMAPINFOHEADER
), &written
);
470 if (written
== sizeof(BITMAPINFOHEADER
)) {
471 // write out the image data backwards because the desktop won't
472 // show bitmaps with negative heights for top-to-bottom
476 stream
->Write(((const char*)bits
) + i
, bpr
, &written
);
477 if (written
== bpr
) {
480 rv
= NS_ERROR_FAILURE
;
490 aImage
->UnlockImageData();
495 nsWindowsShellService::SetDesktopBackground(nsIDOMElement
* aElement
,
500 nsCOMPtr
<gfxIImageFrame
> gfxFrame
;
502 nsCOMPtr
<nsIDOMHTMLImageElement
> imgElement(do_QueryInterface(aElement
));
504 // XXX write background loading stuff!
507 nsCOMPtr
<nsIImageLoadingContent
> imageContent
=
508 do_QueryInterface(aElement
, &rv
);
512 // get the image container
513 nsCOMPtr
<imgIRequest
> request
;
514 rv
= imageContent
->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST
,
515 getter_AddRefs(request
));
518 nsCOMPtr
<imgIContainer
> container
;
519 rv
= request
->GetImage(getter_AddRefs(container
));
521 return NS_ERROR_FAILURE
;
523 // get the current frame, which holds the image data
524 container
->GetCurrentFrame(getter_AddRefs(gfxFrame
));
528 return NS_ERROR_FAILURE
;
530 // get the file name from localized strings
531 nsCOMPtr
<nsIStringBundleService
>
532 bundleService(do_GetService(NS_STRINGBUNDLE_CONTRACTID
, &rv
));
533 NS_ENSURE_SUCCESS(rv
, rv
);
535 nsCOMPtr
<nsIStringBundle
> shellBundle
;
536 rv
= bundleService
->CreateBundle(SHELLSERVICE_PROPERTIES
,
537 getter_AddRefs(shellBundle
));
538 NS_ENSURE_SUCCESS(rv
, rv
);
540 // e.g. "Desktop Background.bmp"
541 nsString fileLeafName
;
542 rv
= shellBundle
->GetStringFromName
543 (NS_LITERAL_STRING("desktopBackgroundLeafNameWin").get(),
544 getter_Copies(fileLeafName
));
545 NS_ENSURE_SUCCESS(rv
, rv
);
547 // get the profile root directory
548 nsCOMPtr
<nsIFile
> file
;
549 rv
= NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR
,
550 getter_AddRefs(file
));
551 NS_ENSURE_SUCCESS(rv
, rv
);
553 // eventually, the path is "%APPDATA%\Mozilla\Firefox\Desktop Background.bmp"
554 rv
= file
->Append(fileLeafName
);
555 NS_ENSURE_SUCCESS(rv
, rv
);
558 rv
= file
->GetPath(path
);
559 NS_ENSURE_SUCCESS(rv
, rv
);
561 // write the bitmap to a file in the profile directory
562 rv
= WriteBitmap(file
, gfxFrame
);
564 // if the file was written successfully, set it as the system wallpaper
565 if (NS_SUCCEEDED(rv
)) {
566 PRBool result
= PR_FALSE
;
569 // Try to create/open a subkey under HKLM.
570 DWORD res
= ::RegCreateKeyExW(HKEY_CURRENT_USER
,
571 L
"Control Panel\\Desktop",
572 0, NULL
, REG_OPTION_NON_VOLATILE
,
573 KEY_WRITE
, NULL
, &key
, &dwDisp
);
574 if (REG_SUCCEEDED(res
)) {
575 PRUnichar tile
[2], style
[2];
577 case BACKGROUND_TILE
:
581 case BACKGROUND_CENTER
:
585 case BACKGROUND_STRETCH
:
593 // The size is always 3 unicode characters.
594 PRInt32 size
= 3 * sizeof(PRUnichar
);
595 ::RegSetValueExW(key
, L
"TileWallpaper",
596 0, REG_SZ
, (const BYTE
*)tile
, size
);
597 ::RegSetValueExW(key
, L
"WallpaperStyle",
598 0, REG_SZ
, (const BYTE
*)style
, size
);
599 ::SystemParametersInfoW(SPI_SETDESKWALLPAPER
, 0, (PVOID
)path
.get(),
600 SPIF_UPDATEINIFILE
| SPIF_SENDWININICHANGE
);
601 // Close the key we opened.
609 nsWindowsShellService::OpenApplication(PRInt32 aApplication
)
611 nsAutoString application
;
612 switch (aApplication
) {
613 case nsIShellService::APPLICATION_MAIL
:
614 application
.AssignLiteral("Mail");
616 case nsIShellService::APPLICATION_NEWS
:
617 application
.AssignLiteral("News");
621 // The Default Client section of the Windows Registry looks like this:
624 // e.g. aClient = "Mail"...
625 // \Mail\(default) = Client Subkey Name
626 // \Client Subkey Name
627 // \Client Subkey Name\shell\open\command\
628 // \Client Subkey Name\shell\open\command\(default) = path to exe
631 // Find the default application for this class.
633 nsresult rv
= OpenKeyForReading(HKEY_CLASSES_ROOT
, application
, &theKey
);
637 PRUnichar buf
[MAX_BUF
];
638 DWORD type
, len
= sizeof buf
;
639 DWORD res
= ::RegQueryValueExW(theKey
, EmptyString().get(), 0,
640 &type
, (LPBYTE
)&buf
, &len
);
642 if (REG_FAILED(res
) || !*buf
)
645 // Close the key we opened.
646 ::RegCloseKey(theKey
);
648 // Find the "open" command
649 application
.AppendLiteral("\\");
650 application
.Append(buf
);
651 application
.AppendLiteral("\\shell\\open\\command");
653 rv
= OpenKeyForReading(HKEY_CLASSES_ROOT
, application
, &theKey
);
657 ::ZeroMemory(buf
, sizeof(buf
));
659 res
= ::RegQueryValueExW(theKey
, EmptyString().get(), 0,
660 &type
, (LPBYTE
)&buf
, &len
);
661 if (REG_FAILED(res
) || !*buf
)
662 return NS_ERROR_FAILURE
;
664 // Close the key we opened.
665 ::RegCloseKey(theKey
);
667 // Look for any embedded environment variables and substitute their
668 // values, as |::CreateProcessW| is unable to do this.
669 nsAutoString
path(buf
);
670 PRInt32 end
= path
.Length();
671 PRInt32 cursor
= 0, temp
= 0;
672 ::ZeroMemory(buf
, sizeof(buf
));
674 cursor
= path
.FindChar('%', cursor
);
678 temp
= path
.FindChar('%', cursor
+ 1);
681 ::ZeroMemory(&buf
, sizeof(buf
));
683 ::GetEnvironmentVariableW(nsAutoString(Substring(path
, cursor
, temp
- cursor
)).get(),
686 // "+ 2" is to subtract the extra characters used to delimit the environment
688 path
.Replace((cursor
- 1), temp
- cursor
+ 2, nsDependentString(buf
));
692 while (cursor
< end
);
695 PROCESS_INFORMATION pi
;
697 ::ZeroMemory(&si
, sizeof(STARTUPINFOW
));
698 ::ZeroMemory(&pi
, sizeof(PROCESS_INFORMATION
));
700 BOOL success
= ::CreateProcessW(NULL
, (LPWSTR
)path
.get(), NULL
,
701 NULL
, FALSE
, 0, NULL
, NULL
,
704 return NS_ERROR_FAILURE
;
710 nsWindowsShellService::GetDesktopBackgroundColor(PRUint32
* aColor
)
712 PRUint32 color
= ::GetSysColor(COLOR_DESKTOP
);
713 *aColor
= (GetRValue(color
) << 16) | (GetGValue(color
) << 8) | GetBValue(color
);
718 nsWindowsShellService::SetDesktopBackgroundColor(PRUint32 aColor
)
720 int aParameters
[2] = { COLOR_BACKGROUND
, COLOR_DESKTOP
};
721 BYTE r
= (aColor
>> 16);
722 BYTE g
= (aColor
<< 16) >> 24;
723 BYTE b
= (aColor
<< 24) >> 24;
724 COLORREF colors
[2] = { RGB(r
,g
,b
), RGB(r
,g
,b
) };
726 ::SetSysColors(sizeof(aParameters
) / sizeof(int), aParameters
, colors
);
728 PRBool result
= PR_FALSE
;
731 // Try to create/open a subkey under HKLM.
732 DWORD rv
= ::RegCreateKeyExW(HKEY_CURRENT_USER
,
733 L
"Control Panel\\Colors", 0, NULL
,
734 REG_OPTION_NON_VOLATILE
, KEY_WRITE
, NULL
,
737 if (REG_SUCCEEDED(rv
)) {
739 sprintf((char*)rgb
, "%u %u %u\0", r
, g
, b
);
740 NS_ConvertUTF8toUTF16
backColor(rgb
);
742 ::RegSetValueExW(key
, L
"Background",
743 0, REG_SZ
, (const BYTE
*)backColor
.get(),
744 (backColor
.Length() + 1) * sizeof(PRUnichar
));
747 // Close the key we opened.
753 nsWindowsShellService::GetUnreadMailCount(PRUint32
* aCount
)
758 if (GetMailAccountKey(&accountKey
)) {
759 DWORD type
, unreadCount
;
760 DWORD len
= sizeof unreadCount
;
761 DWORD res
= ::RegQueryValueExW(accountKey
, L
"MessageCount", 0,
762 &type
, (LPBYTE
)&unreadCount
, &len
);
763 if (REG_SUCCEEDED(res
))
764 *aCount
= unreadCount
;
766 // Close the key we opened.
767 ::RegCloseKey(accountKey
);
774 nsWindowsShellService::GetMailAccountKey(HKEY
* aResult
)
776 NS_NAMED_LITERAL_STRING(unread
,
777 "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\UnreadMail\\");
780 DWORD res
= ::RegOpenKeyExW(HKEY_CURRENT_USER
, unread
.get(), 0,
781 KEY_ENUMERATE_SUB_KEYS
, &mailKey
);
785 PRUnichar subkeyName
[MAX_BUF
];
786 DWORD len
= sizeof subkeyName
;
787 res
= ::RegEnumKeyExW(mailKey
, i
++, subkeyName
, &len
, NULL
, NULL
,
789 if (REG_SUCCEEDED(res
)) {
791 res
= ::RegOpenKeyExW(mailKey
, PromiseFlatString(subkeyName
).get(),
792 0, KEY_READ
, &accountKey
);
793 if (REG_SUCCEEDED(res
)) {
794 *aResult
= accountKey
;
796 // Close the key we opened.
797 ::RegCloseKey(mailKey
);
807 // Close the key we opened.
808 ::RegCloseKey(mailKey
);
813 nsWindowsShellService::OpenApplicationWithURI(nsILocalFile
* aApplication
,
814 const nsACString
& aURI
)
817 nsCOMPtr
<nsIProcess
> process
=
818 do_CreateInstance("@mozilla.org/process/util;1", &rv
);
822 rv
= process
->Init(aApplication
);
826 const nsCString
spec(aURI
);
827 const char* specStr
= spec
.get();
829 return process
->Run(PR_FALSE
, &specStr
, 1, &pid
);
833 nsWindowsShellService::GetDefaultFeedReader(nsILocalFile
** _retval
)
838 nsCOMPtr
<nsIWindowsRegKey
> regKey
=
839 do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv
);
840 NS_ENSURE_SUCCESS(rv
, rv
);
842 rv
= regKey
->Open(nsIWindowsRegKey::ROOT_KEY_CLASSES_ROOT
,
843 NS_LITERAL_STRING("feed\\shell\\open\\command"),
844 nsIWindowsRegKey::ACCESS_READ
);
845 NS_ENSURE_SUCCESS(rv
, rv
);
848 rv
= regKey
->ReadStringValue(EmptyString(), path
);
849 NS_ENSURE_SUCCESS(rv
, rv
);
851 return NS_ERROR_FAILURE
;
853 if (path
.First() == '"') {
854 // Everything inside the quotes
855 path
= Substring(path
, 1, path
.FindChar('"', 1) - 1);
858 // Everything up to the first space
859 path
= Substring(path
, 0, path
.FindChar(' '));
862 nsCOMPtr
<nsILocalFile
> defaultReader
=
863 do_CreateInstance("@mozilla.org/file/local;1", &rv
);
864 NS_ENSURE_SUCCESS(rv
, rv
);
866 rv
= defaultReader
->InitWithPath(path
);
867 NS_ENSURE_SUCCESS(rv
, rv
);
870 rv
= defaultReader
->Exists(&exists
);
871 NS_ENSURE_SUCCESS(rv
, rv
);
873 return NS_ERROR_FAILURE
;
875 NS_ADDREF(*_retval
= defaultReader
);