892 lines
32 KiB
C++
Executable File
892 lines
32 KiB
C++
Executable File
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
|
*
|
|
* The contents of this file are subject to the Netscape 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/NPL/
|
|
*
|
|
* 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 mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is
|
|
* Netscape Communications Corporation.
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
* the Initial Developer. All Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
* Bill Law <law@netscape.com>
|
|
* Syd Logan <syd@netscape.com> added turbo mode stuff
|
|
* Joe Elwell <jelwell@netscape.com>
|
|
* Håkan Waara <hwaara@chello.se>
|
|
* Aaron Kaluszka <ask@swva.net>
|
|
* Blake Ross <blake@blakeross.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 NPL, 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 NPL, the GPL or the LGPL.
|
|
*
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
#ifndef MAX_BUF
|
|
#define MAX_BUF 4096
|
|
#endif
|
|
|
|
// Implementation utilities.
|
|
#include "nsIDOMWindowInternal.h"
|
|
#include "nsIServiceManager.h"
|
|
#include "nsIPromptService.h"
|
|
#include "nsIStringBundle.h"
|
|
#include "nsIAllocator.h"
|
|
#include "nsICmdLineService.h"
|
|
#include "nsXPIDLString.h"
|
|
#include "nsString.h"
|
|
#include "nsMemory.h"
|
|
#include "nsNetUtil.h"
|
|
#include "nsWindowsHooksUtil.cpp"
|
|
#include "nsWindowsHooks.h"
|
|
#include <windows.h>
|
|
#include <shlobj.h>
|
|
#include <shlguid.h>
|
|
|
|
// for set as wallpaper
|
|
#include "nsIDocument.h"
|
|
#include "nsIContent.h"
|
|
#include "nsIDOMElement.h"
|
|
#include "nsIDOMDocument.h"
|
|
#include "nsIFrame.h"
|
|
#include "nsIPresShell.h"
|
|
#include "nsIImageLoadingContent.h"
|
|
#include "imgIRequest.h"
|
|
#include "imgIContainer.h"
|
|
#include "gfxIImageFrame.h"
|
|
|
|
#define RUNKEY "Software\\Microsoft\\Windows\\CurrentVersion\\Run"
|
|
|
|
// Objects that describe the Windows registry entries that we need to tweak.
|
|
static ProtocolRegistryEntry
|
|
http( "http" ),
|
|
https( "https" ),
|
|
ftp( "ftp" ),
|
|
chrome( "chrome" ),
|
|
gopher( "gopher" );
|
|
const char *xhtmExts[] = { ".xht", ".xhtml", 0 };
|
|
const char *htmExts[] = { ".htm", ".html", ".shtml", 0 };
|
|
|
|
static FileTypeRegistryEntry
|
|
xhtml( xhtmExts, "MozillaXHTML", "XHTML Document", "", "doc-file.ico"),
|
|
mozillaMarkup( htmExts, "MozillaHTML", "HTML Document", "htmlfile", "doc-file.ico");
|
|
|
|
// Implementation of the nsIWindowsHooksSettings interface.
|
|
// Use standard implementation of nsISupports stuff.
|
|
NS_IMPL_ISUPPORTS1( nsWindowsHooksSettings, nsIWindowsHooksSettings )
|
|
|
|
nsWindowsHooksSettings::nsWindowsHooksSettings() {
|
|
}
|
|
|
|
nsWindowsHooksSettings::~nsWindowsHooksSettings() {
|
|
}
|
|
|
|
// Generic getter.
|
|
NS_IMETHODIMP
|
|
nsWindowsHooksSettings::Get( PRBool *result, PRBool nsWindowsHooksSettings::*member ) {
|
|
NS_ENSURE_ARG( result );
|
|
NS_ENSURE_ARG( member );
|
|
*result = this->*member;
|
|
return NS_OK;
|
|
}
|
|
|
|
// Generic setter.
|
|
NS_IMETHODIMP
|
|
nsWindowsHooksSettings::Set( PRBool value, PRBool nsWindowsHooksSettings::*member ) {
|
|
NS_ENSURE_ARG( member );
|
|
this->*member = value;
|
|
return NS_OK;
|
|
}
|
|
|
|
// Macros to define specific getter/setter methods.
|
|
#define DEFINE_GETTER_AND_SETTER( attr, member ) \
|
|
NS_IMETHODIMP \
|
|
nsWindowsHooksSettings::Get##attr ( PRBool *result ) { \
|
|
return this->Get( result, &nsWindowsHooksSettings::member ); \
|
|
} \
|
|
NS_IMETHODIMP \
|
|
nsWindowsHooksSettings::Set##attr ( PRBool value ) { \
|
|
return this->Set( value, &nsWindowsHooksSettings::member ); \
|
|
}
|
|
|
|
// Define all the getter/setter methods:
|
|
DEFINE_GETTER_AND_SETTER( IsHandlingHTML, mHandleHTML )
|
|
DEFINE_GETTER_AND_SETTER( IsHandlingXHTML, mHandleXHTML )
|
|
DEFINE_GETTER_AND_SETTER( IsHandlingHTTP, mHandleHTTP )
|
|
DEFINE_GETTER_AND_SETTER( IsHandlingHTTPS, mHandleHTTPS )
|
|
DEFINE_GETTER_AND_SETTER( ShowDialog, mShowDialog )
|
|
DEFINE_GETTER_AND_SETTER( HaveBeenSet, mHaveBeenSet )
|
|
|
|
|
|
// Implementation of the nsIWindowsHooks interface.
|
|
// Use standard implementation of nsISupports stuff.
|
|
NS_IMPL_ISUPPORTS2( nsWindowsHooks, nsIWindowsHooks, nsIWindowsRegistry )
|
|
|
|
nsWindowsHooks::nsWindowsHooks() {
|
|
}
|
|
|
|
nsWindowsHooks::~nsWindowsHooks() {
|
|
}
|
|
|
|
// Internal GetPreferences.
|
|
NS_IMETHODIMP
|
|
nsWindowsHooks::GetSettings( nsWindowsHooksSettings **result ) {
|
|
nsresult rv = NS_OK;
|
|
|
|
// Validate input arg.
|
|
NS_ENSURE_ARG( result );
|
|
|
|
// Allocate prefs object.
|
|
nsWindowsHooksSettings *prefs = *result = new nsWindowsHooksSettings;
|
|
NS_ENSURE_TRUE( prefs, NS_ERROR_OUT_OF_MEMORY );
|
|
|
|
// Got it, increment ref count.
|
|
NS_ADDREF( prefs );
|
|
|
|
// Get each registry value and copy to prefs structure.
|
|
prefs->mHandleHTTP = BoolRegistryEntry( "isHandlingHTTP" );
|
|
prefs->mHandleHTTPS = BoolRegistryEntry( "isHandlingHTTPS" );
|
|
prefs->mHandleHTML = BoolRegistryEntry( "isHandlingHTML" );
|
|
prefs->mHandleXHTML = BoolRegistryEntry( "isHandlingXHTML" );
|
|
prefs->mShowDialog = BoolRegistryEntry( "showDialog" );
|
|
prefs->mHaveBeenSet = BoolRegistryEntry( "haveBeenSet" );
|
|
|
|
#ifdef DEBUG_law
|
|
NS_WARN_IF_FALSE( NS_SUCCEEDED( rv ), "GetPreferences failed" );
|
|
#endif
|
|
|
|
return rv;
|
|
}
|
|
|
|
// Public interface uses internal plus a QI to get to the proper result.
|
|
NS_IMETHODIMP
|
|
nsWindowsHooks::GetSettings( nsIWindowsHooksSettings **_retval ) {
|
|
// Allocate prefs object.
|
|
nsWindowsHooksSettings *prefs;
|
|
nsresult rv = this->GetSettings( &prefs );
|
|
|
|
if ( NS_SUCCEEDED( rv ) ) {
|
|
// QI to proper interface.
|
|
rv = prefs->QueryInterface( NS_GET_IID( nsIWindowsHooksSettings ), (void**)_retval );
|
|
// Release (to undo our Get...).
|
|
NS_RELEASE( prefs );
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
static PRBool misMatch( const PRBool &flag, const ProtocolRegistryEntry &entry ) {
|
|
PRBool result = PR_FALSE;
|
|
// Check if we care.
|
|
if ( flag ) {
|
|
// Compare registry entry setting to what it *should* be.
|
|
if ( entry.currentSetting() != entry.setting ) {
|
|
result = PR_TRUE;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// isAccessRestricted - Returns PR_TRUE iff this user only has restricted access
|
|
// to the registry keys we need to modify.
|
|
static PRBool isAccessRestricted() {
|
|
char subKey[] = "Software\\Mozilla - Test Key";
|
|
PRBool result = PR_FALSE;
|
|
DWORD dwDisp = 0;
|
|
HKEY key;
|
|
// Try to create/open a subkey under HKLM.
|
|
DWORD rc = ::RegCreateKeyEx( HKEY_LOCAL_MACHINE,
|
|
subKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&key,
|
|
&dwDisp );
|
|
|
|
if ( rc == ERROR_SUCCESS ) {
|
|
// Key was opened; first close it.
|
|
::RegCloseKey( key );
|
|
// Delete it if we just created it.
|
|
switch( dwDisp ) {
|
|
case REG_CREATED_NEW_KEY:
|
|
::RegDeleteKey( HKEY_LOCAL_MACHINE, subKey );
|
|
break;
|
|
case REG_OPENED_EXISTING_KEY:
|
|
break;
|
|
}
|
|
} else {
|
|
// Can't create/open it; we don't have access.
|
|
result = PR_TRUE;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
|
|
// Implementation of method that checks whether the settings match what's in the
|
|
// Windows registry.
|
|
NS_IMETHODIMP
|
|
nsWindowsHooksSettings::GetRegistryMatches( PRBool *_retval ) {
|
|
NS_ENSURE_ARG( _retval );
|
|
*_retval = PR_TRUE;
|
|
// Test registry for all selected attributes.
|
|
if ( misMatch( mHandleHTTP, http )
|
|
||
|
|
misMatch( mHandleHTTPS, https )
|
|
||
|
|
misMatch( mHandleHTML, mozillaMarkup )
|
|
||
|
|
misMatch( mHandleXHTML, xhtml ) ) {
|
|
// Registry is out of synch.
|
|
*_retval = PR_FALSE;
|
|
}
|
|
return NS_OK;
|
|
}
|
|
|
|
// Implementation of method that checks settings versus registry and prompts user
|
|
// if out of synch.
|
|
NS_IMETHODIMP
|
|
nsWindowsHooks::CheckSettings( nsIDOMWindowInternal *aParent,
|
|
PRBool *_retval ) {
|
|
nsresult rv = NS_OK;
|
|
*_retval = PR_FALSE;
|
|
|
|
// Only do this once!
|
|
static PRBool alreadyChecked = PR_FALSE;
|
|
if ( alreadyChecked ) {
|
|
return NS_OK;
|
|
} else {
|
|
alreadyChecked = PR_TRUE;
|
|
// Don't check further if we don't have sufficient access.
|
|
if ( isAccessRestricted() ) {
|
|
return NS_OK;
|
|
}
|
|
}
|
|
|
|
// Get settings.
|
|
nsWindowsHooksSettings *settings;
|
|
rv = this->GetSettings( &settings );
|
|
|
|
if ( NS_SUCCEEDED( rv ) && settings ) {
|
|
// If not set previously, set to defaults so that they are
|
|
// set properly when/if the user says to.
|
|
if ( !settings->mHaveBeenSet ) {
|
|
settings->mHandleHTTP = PR_TRUE;
|
|
settings->mHandleHTTPS = PR_TRUE;
|
|
settings->mHandleHTML = PR_TRUE;
|
|
settings->mHandleXHTML = PR_TRUE;
|
|
|
|
settings->mShowDialog = PR_TRUE;
|
|
}
|
|
|
|
// If launched with "-installer" then override mShowDialog.
|
|
PRBool installing = PR_FALSE;
|
|
if ( !settings->mShowDialog ) {
|
|
// Get command line service.
|
|
nsCID cmdLineCID = NS_COMMANDLINE_SERVICE_CID;
|
|
nsCOMPtr<nsICmdLineService> cmdLineArgs( do_GetService( cmdLineCID, &rv ) );
|
|
if ( NS_SUCCEEDED( rv ) && cmdLineArgs ) {
|
|
// See if "-installer" was specified.
|
|
nsXPIDLCString installer;
|
|
rv = cmdLineArgs->GetCmdLineValue( "-installer", getter_Copies( installer ) );
|
|
if ( NS_SUCCEEDED( rv ) && installer ) {
|
|
installing = PR_TRUE;
|
|
}
|
|
}
|
|
}
|
|
|
|
// First, make sure the user cares.
|
|
if ( settings->mShowDialog || installing ) {
|
|
// Look at registry setting for all things that are set.
|
|
PRBool matches = PR_TRUE;
|
|
settings->GetRegistryMatches( &matches );
|
|
if ( !matches ) {
|
|
// Need to prompt user.
|
|
// First:
|
|
// o We need the common dialog service to show the dialog.
|
|
// o We need the string bundle service to fetch the appropriate
|
|
// dialog text.
|
|
nsCID bundleCID = NS_STRINGBUNDLESERVICE_CID;
|
|
nsCOMPtr<nsIPromptService> promptService( do_GetService("@mozilla.org/embedcomp/prompt-service;1"));
|
|
nsCOMPtr<nsIStringBundleService> bundleService( do_GetService( bundleCID, &rv ) );
|
|
|
|
if ( promptService && bundleService ) {
|
|
// Next, get bundle that provides text for dialog.
|
|
nsCOMPtr<nsIStringBundle> bundle;
|
|
nsCOMPtr<nsIStringBundle> brandBundle;
|
|
rv = bundleService->CreateBundle( "chrome://global-platform/locale/nsWindowsHooks.properties",
|
|
getter_AddRefs( bundle ) );
|
|
rv = bundleService->CreateBundle( "chrome://global/locale/brand.properties",
|
|
getter_AddRefs( brandBundle ) );
|
|
if ( NS_SUCCEEDED( rv ) && bundle && brandBundle ) {
|
|
nsXPIDLString text, label, shortName;
|
|
if ( NS_SUCCEEDED( ( rv = brandBundle->GetStringFromName( NS_LITERAL_STRING( "brandShortName" ).get(),
|
|
getter_Copies( shortName ) ) ) ) ) {
|
|
const PRUnichar* formatStrings[] = { shortName.get() };
|
|
if ( NS_SUCCEEDED( ( rv = bundle->FormatStringFromName( NS_LITERAL_STRING( "promptText" ).get(),
|
|
formatStrings, 1, getter_Copies( text ) ) ) )
|
|
&&
|
|
NS_SUCCEEDED( ( rv = bundle->GetStringFromName( NS_LITERAL_STRING( "checkBoxLabel" ).get(),
|
|
getter_Copies( label ) ) ) ) ) {
|
|
// Got the text, now show dialog.
|
|
PRBool showDialog = settings->mShowDialog;
|
|
PRInt32 dlgResult = -1;
|
|
// No checkbox for initial display.
|
|
const PRUnichar *labelArg = 0;
|
|
if ( settings->mHaveBeenSet ) {
|
|
// Subsequent display uses label string.
|
|
labelArg = label;
|
|
}
|
|
// Note that the buttons need to be passed in this order:
|
|
// o Yes
|
|
// o Cancel
|
|
// o No
|
|
rv = promptService->ConfirmEx(aParent, shortName, text,
|
|
(nsIPromptService::BUTTON_TITLE_YES * nsIPromptService::BUTTON_POS_0) +
|
|
(nsIPromptService::BUTTON_TITLE_CANCEL * nsIPromptService::BUTTON_POS_1) +
|
|
(nsIPromptService::BUTTON_TITLE_NO * nsIPromptService::BUTTON_POS_2),
|
|
nsnull, nsnull, nsnull, labelArg, &showDialog, &dlgResult);
|
|
|
|
if ( NS_SUCCEEDED( rv ) ) {
|
|
// Dialog was shown
|
|
*_retval = PR_TRUE;
|
|
|
|
// Did they say go ahead?
|
|
switch ( dlgResult ) {
|
|
case 0:
|
|
// User says: make the changes.
|
|
// Remember "show dialog" choice.
|
|
settings->mShowDialog = showDialog;
|
|
// Apply settings; this single line of
|
|
// code will do different things depending
|
|
// on whether this is the first time (i.e.,
|
|
// when "haveBeenSet" is false). The first
|
|
// time, this will set all prefs to true
|
|
// (because that's how we initialized 'em
|
|
// in GetSettings, above) and will update the
|
|
// registry accordingly. On subsequent passes,
|
|
// this will only update the registry (because
|
|
// the settings we got from GetSettings will
|
|
// not have changed).
|
|
//
|
|
// BTW, the term "prefs" in this context does not
|
|
// refer to conventional Mozilla "prefs." Instead,
|
|
// it refers to "Desktop Integration" prefs which
|
|
// are stored in the windows registry.
|
|
rv = SetSettings( settings );
|
|
#ifdef DEBUG_law
|
|
printf( "Yes, SetSettings returned 0x%08X\n", (int)rv );
|
|
#endif
|
|
break;
|
|
|
|
case 2:
|
|
// User says: Don't mess with Windows.
|
|
// We update only the "showDialog" and
|
|
// "haveBeenSet" keys. Note that this will
|
|
// have the effect of setting all the prefs
|
|
// *off* if the user says no to the initial
|
|
// prompt.
|
|
BoolRegistryEntry( "haveBeenSet" ).set();
|
|
if ( showDialog ) {
|
|
BoolRegistryEntry( "showDialog" ).set();
|
|
} else {
|
|
BoolRegistryEntry( "showDialog" ).reset();
|
|
}
|
|
#ifdef DEBUG_law
|
|
printf( "No, haveBeenSet=1 and showDialog=%d\n", (int)showDialog );
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
// User says: I dunno. Make no changes (which
|
|
// should produce the same dialog next time).
|
|
#ifdef DEBUG_law
|
|
printf( "Cancel\n" );
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#ifdef DEBUG_law
|
|
else { printf( "Registry and prefs match\n" ); }
|
|
#endif
|
|
}
|
|
#ifdef DEBUG_law
|
|
else { printf( "showDialog is false and not installing\n" ); }
|
|
#endif
|
|
|
|
// Release the settings.
|
|
settings->Release();
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
// Utility to set PRBool registry value from getter method.
|
|
nsresult putPRBoolIntoRegistry( const char* valueName,
|
|
nsIWindowsHooksSettings *prefs,
|
|
nsWindowsHooksSettings::getter memFun ) {
|
|
// Use getter method to extract attribute from prefs.
|
|
PRBool boolValue;
|
|
(void)(prefs->*memFun)( &boolValue );
|
|
// Convert to DWORD.
|
|
DWORD dwordValue = boolValue;
|
|
// Store into registry.
|
|
BoolRegistryEntry pref( valueName );
|
|
nsresult rv = boolValue ? pref.set() : pref.reset();
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* void setPreferences (in nsIWindowsHooksSettings prefs); */
|
|
NS_IMETHODIMP
|
|
nsWindowsHooks::SetSettings(nsIWindowsHooksSettings *prefs) {
|
|
nsresult rv = NS_ERROR_FAILURE;
|
|
|
|
putPRBoolIntoRegistry( "isHandlingHTTP", prefs, &nsIWindowsHooksSettings::GetIsHandlingHTTP );
|
|
putPRBoolIntoRegistry( "isHandlingHTTPS", prefs, &nsIWindowsHooksSettings::GetIsHandlingHTTPS );
|
|
putPRBoolIntoRegistry( "isHandlingHTML", prefs, &nsIWindowsHooksSettings::GetIsHandlingHTML );
|
|
putPRBoolIntoRegistry( "isHandlingXHTML", prefs, &nsIWindowsHooksSettings::GetIsHandlingXHTML );
|
|
putPRBoolIntoRegistry( "showDialog", prefs, &nsIWindowsHooksSettings::GetShowDialog );
|
|
|
|
// Indicate that these settings have indeed been set.
|
|
BoolRegistryEntry( "haveBeenSet" ).set();
|
|
|
|
rv = SetRegistry();
|
|
|
|
return rv;
|
|
}
|
|
|
|
// Get preferences and start handling everything selected.
|
|
NS_IMETHODIMP
|
|
nsWindowsHooks::SetRegistry() {
|
|
nsresult rv = NS_OK;
|
|
|
|
// Get raw prefs object.
|
|
nsWindowsHooksSettings *prefs;
|
|
rv = this->GetSettings( &prefs );
|
|
|
|
NS_ENSURE_TRUE( NS_SUCCEEDED( rv ), rv );
|
|
|
|
if ( prefs->mHandleHTML ) {
|
|
(void) mozillaMarkup.set();
|
|
} else {
|
|
(void) mozillaMarkup.reset();
|
|
}
|
|
if ( prefs->mHandleXHTML ) {
|
|
(void) xhtml.set();
|
|
} else {
|
|
(void) xhtml.reset();
|
|
}
|
|
if ( prefs->mHandleHTTP ) {
|
|
(void) http.set();
|
|
} else {
|
|
(void) http.reset();
|
|
}
|
|
if ( prefs->mHandleHTTPS ) {
|
|
(void) https.set();
|
|
} else {
|
|
(void) https.reset();
|
|
}
|
|
// Call SHChangeNotify() to notify the windows shell that file
|
|
// associations changed, and that an update of the icons need to occur.
|
|
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP nsWindowsHooks::GetRegistryEntry( PRInt32 aHKEYConstant, const char *aSubKeyName, const char *aValueName, char **aResult ) {
|
|
NS_ENSURE_ARG( aResult );
|
|
*aResult = 0;
|
|
// Calculate HKEY_* starting point based on input nsIWindowsHooks constant.
|
|
HKEY hKey;
|
|
switch ( aHKEYConstant ) {
|
|
case HKCR:
|
|
hKey = HKEY_CLASSES_ROOT;
|
|
break;
|
|
case HKCC:
|
|
hKey = HKEY_CURRENT_CONFIG;
|
|
break;
|
|
case HKCU:
|
|
hKey = HKEY_CURRENT_USER;
|
|
break;
|
|
case HKLM:
|
|
hKey = HKEY_LOCAL_MACHINE;
|
|
break;
|
|
case HKU:
|
|
hKey = HKEY_USERS;
|
|
break;
|
|
default:
|
|
return NS_ERROR_INVALID_ARG;
|
|
}
|
|
|
|
// Get requested registry entry.
|
|
nsCAutoString entry( RegistryEntry( hKey, aSubKeyName, aValueName, 0 ).currentSetting() );
|
|
|
|
// Copy to result.
|
|
*aResult = PL_strdup( entry.get() );
|
|
|
|
return *aResult ? NS_OK : NS_ERROR_OUT_OF_MEMORY;
|
|
}
|
|
|
|
nsresult
|
|
WriteBitmap(nsString& aPath, gfxIImageFrame* aImage)
|
|
{
|
|
PRInt32 width, height;
|
|
aImage->GetWidth(&width);
|
|
aImage->GetHeight(&height);
|
|
|
|
PRUint8* bits;
|
|
PRUint32 length;
|
|
aImage->GetImageData(&bits, &length);
|
|
if (!bits) return NS_ERROR_FAILURE;
|
|
|
|
PRUint32 bpr;
|
|
aImage->GetImageBytesPerRow(&bpr);
|
|
PRInt32 bitCount = bpr/width;
|
|
|
|
// initialize these bitmap structs which we will later
|
|
// serialize directly to the head of the bitmap file
|
|
LPBITMAPINFOHEADER bmi = (LPBITMAPINFOHEADER)new BITMAPINFO;
|
|
bmi->biSize = sizeof(BITMAPINFOHEADER);
|
|
bmi->biWidth = width;
|
|
bmi->biHeight = height;
|
|
bmi->biPlanes = 1;
|
|
bmi->biBitCount = (WORD)bitCount*8;
|
|
bmi->biCompression = BI_RGB;
|
|
bmi->biSizeImage = 0; // don't need to set this if bmp is uncompressed
|
|
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
|
|
nsresult rv;
|
|
nsCOMPtr<nsILocalFile> path;
|
|
rv = NS_NewLocalFile(aPath, PR_TRUE, getter_AddRefs(path));
|
|
|
|
if (NS_FAILED(rv))
|
|
return rv;
|
|
|
|
nsCOMPtr<nsIOutputStream> stream;
|
|
NS_NewLocalFileOutputStream(getter_AddRefs(stream), path);
|
|
|
|
// 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)) {
|
|
stream->Write((const char*)bits, length, &written);
|
|
if (written == length)
|
|
rv = NS_OK;
|
|
}
|
|
}
|
|
|
|
stream->Close();
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindowsHooks::GetDesktopColor(PRUint32* aColors)
|
|
{
|
|
PRUint32 color = ::GetSysColor(COLOR_DESKTOP);
|
|
*aColors = (GetRValue(color) << 16) | (GetGValue(color) << 8) | GetBValue(color);
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindowsHooks::SetDesktopColor(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);
|
|
|
|
char subKey[] = "Control Panel\\Colors";
|
|
PRBool result = PR_FALSE;
|
|
DWORD dwDisp = 0;
|
|
HKEY key;
|
|
// Try to create/open a subkey under HKLM.
|
|
DWORD rc = ::RegCreateKeyEx(HKEY_CURRENT_USER,
|
|
subKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&key,
|
|
&dwDisp);
|
|
if (rc == ERROR_SUCCESS) {
|
|
char* rgb = new char[12];
|
|
sprintf(rgb, "%u %u %u\0", r, g, b);
|
|
::RegSetValueEx(key, "Background", 0, REG_SZ, (const unsigned char*)rgb, strlen(rgb));
|
|
delete[] rgb;
|
|
}
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindowsHooks::SetImageAsWallpaper(nsIDOMElement* aElement, PRBool aUseBackground, PRInt32 position)
|
|
{
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<gfxIImageFrame> gfxFrame;
|
|
if (aUseBackground) {
|
|
// XXX write background loading stuff!
|
|
} 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;
|
|
nsCOMPtr<imgIContainer> container;
|
|
rv = request->GetImage(getter_AddRefs(container));
|
|
if (!request) return rv;
|
|
|
|
// get the current frame, which holds the image data
|
|
container->GetCurrentFrame(getter_AddRefs(gfxFrame));
|
|
}
|
|
|
|
if (!gfxFrame)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
// get the windows directory ('c:\windows' usually)
|
|
char winDir[256];
|
|
::GetWindowsDirectory(winDir, sizeof(winDir));
|
|
nsAutoString winPath;
|
|
winPath.AssignWithConversion(winDir);
|
|
|
|
// get the product brand name from localized strings
|
|
nsXPIDLString brandName;
|
|
nsCID bundleCID = NS_STRINGBUNDLESERVICE_CID;
|
|
nsCOMPtr<nsIStringBundleService> bundleService(do_GetService(bundleCID));
|
|
if (bundleService) {
|
|
nsCOMPtr<nsIStringBundle> brandBundle;
|
|
rv = bundleService->CreateBundle("chrome://global/locale/brand.properties",
|
|
getter_AddRefs(brandBundle));
|
|
if (NS_SUCCEEDED(rv) && brandBundle) {
|
|
if (NS_FAILED(rv = brandBundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(),
|
|
getter_Copies(brandName))))
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
// build the file name
|
|
winPath.Append(NS_LITERAL_STRING("\\").get());
|
|
winPath.Append(brandName);
|
|
winPath.Append(NS_LITERAL_STRING(" Wallpaper.bmp").get());
|
|
|
|
// write the bitmap to a file in the windows dir
|
|
rv = WriteBitmap(winPath, gfxFrame);
|
|
|
|
// if the file was written successfully, set it as the system wallpaper
|
|
if (NS_SUCCEEDED(rv)) {
|
|
char subKey[] = "Control Panel\\Desktop";
|
|
PRBool result = PR_FALSE;
|
|
DWORD dwDisp = 0;
|
|
HKEY key;
|
|
// Try to create/open a subkey under HKLM.
|
|
DWORD rc = ::RegCreateKeyEx( HKEY_CURRENT_USER,
|
|
subKey,
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_WRITE,
|
|
NULL,
|
|
&key,
|
|
&dwDisp );
|
|
if (rc == ERROR_SUCCESS) {
|
|
unsigned char tile[2];
|
|
unsigned char style[2];
|
|
if (position == WALLPAPER_TILE) {
|
|
tile[0] = '1';
|
|
style[0] = '1';
|
|
}
|
|
else if (position == WALLPAPER_CENTER) {
|
|
tile[0] = '0';
|
|
style[0] = '0';
|
|
}
|
|
else if (position == WALLPAPER_STRETCH) {
|
|
tile[0] = '0';
|
|
style[0] = '2';
|
|
}
|
|
tile[1] = '\0';
|
|
style[1] = '\0';
|
|
::RegSetValueEx(key, "TileWallpaper", 0, REG_SZ, tile, sizeof(tile));
|
|
::RegSetValueEx(key, "WallpaperStyle", 0, REG_SZ, style, sizeof(style));
|
|
::SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, ToNewCString(winPath), SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE);
|
|
}
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindowsHooks::OpenDefaultClient(const char* aClient)
|
|
{
|
|
nsresult rv;
|
|
|
|
// 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
|
|
//
|
|
nsCAutoString clientKey(NS_LITERAL_CSTRING("SOFTWARE\\Clients\\"));
|
|
clientKey += aClient;
|
|
|
|
nsXPIDLCString defaultClient;
|
|
rv = GetRegistryEntry(nsIWindowsRegistry::HKLM, clientKey.get(), "",
|
|
getter_Copies(defaultClient));
|
|
if (NS_FAILED(rv) || defaultClient.IsEmpty())
|
|
return rv;
|
|
|
|
clientKey.Append("\\");
|
|
clientKey.Append(defaultClient.get());
|
|
clientKey.Append("\\shell\\open\\command");
|
|
|
|
nsXPIDLCString path;
|
|
rv = GetRegistryEntry(nsIWindowsRegistry::HKLM, clientKey.get(), "",
|
|
getter_Copies(path));
|
|
if (NS_FAILED(rv) || path.IsEmpty())
|
|
return rv;
|
|
|
|
// Look for any embedded environment variables and substitute their
|
|
// values, as |::CreateProcess| is unable to do this.
|
|
PRInt32 end = path.Length();
|
|
PRInt32 cursor = 0, temp = 0;
|
|
char buf[_MAX_PATH];
|
|
do {
|
|
cursor = path.FindChar('%', cursor);
|
|
if (cursor < 0)
|
|
break;
|
|
|
|
temp = path.FindChar('%', cursor + 1);
|
|
|
|
++cursor;
|
|
|
|
::ZeroMemory(&buf, sizeof(buf));
|
|
::GetEnvironmentVariable(nsCAutoString(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, nsDependentCString(buf));
|
|
|
|
++cursor;
|
|
}
|
|
while (cursor < end);
|
|
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi;
|
|
|
|
::ZeroMemory(&si, sizeof(STARTUPINFO));
|
|
::ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
|
|
|
|
char* pathCStr = ToNewCString(path);
|
|
BOOL success = ::CreateProcess(NULL, pathCStr, NULL, NULL, FALSE, 0, NULL,
|
|
NULL, &si, &pi);
|
|
nsCRT::free(pathCStr);
|
|
if (!success)
|
|
return NS_ERROR_FAILURE;
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
NS_IMETHODIMP
|
|
nsWindowsHooks::GetUnreadMailCount(PRUint32* aResult)
|
|
{
|
|
*aResult = 0;
|
|
|
|
HKEY accountKey;
|
|
if (GetMailAccountKey(&accountKey)) {
|
|
DWORD type, length, unreadCount;
|
|
DWORD result = ::RegQueryValueEx(accountKey, "MessageCount", 0, &type,
|
|
(LPBYTE)&unreadCount, &length);
|
|
if (result == ERROR_SUCCESS) {
|
|
*aResult = unreadCount;
|
|
}
|
|
}
|
|
|
|
return NS_OK;
|
|
}
|
|
|
|
PRBool
|
|
nsWindowsHooks::GetMailAccountKey(HKEY* aResult)
|
|
{
|
|
HKEY mailKey;
|
|
DWORD result = ::RegOpenKeyEx(HKEY_CURRENT_USER,
|
|
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\UnreadMail\\",
|
|
0, KEY_ENUMERATE_SUB_KEYS, &mailKey);
|
|
|
|
PRInt32 i = 0;
|
|
do {
|
|
char subkeyName[_MAX_PATH];
|
|
DWORD len = sizeof subkeyName;
|
|
result = ::RegEnumKeyEx(mailKey, i++, subkeyName, &len, 0, 0, 0, 0);
|
|
if (result == ERROR_SUCCESS) {
|
|
HKEY accountKey;
|
|
result = ::RegOpenKeyEx(mailKey, subkeyName, 0, KEY_READ, &accountKey);
|
|
if (result == ERROR_SUCCESS) {
|
|
*aResult = accountKey;
|
|
return PR_TRUE;
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
while (1);
|
|
|
|
return PR_FALSE;
|
|
}
|
|
|