/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is 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 * Syd Logan added turbo mode stuff * Joe Elwell * Håkan Waara * Aaron Kaluszka * Jeremy Morton * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ #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 "nsXPIDLString.h" #include "nsString.h" #include "nsMemory.h" #include "nsNetUtil.h" #include "nsWindowsHooks.h" #include #include #include // 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" #include "nsDirectoryServiceUtils.h" #include "nsAppDirectoryServiceDefs.h" #ifndef MOZ_XUL_APP #include "nsICmdLineService.h" #endif #include "nsXPFEComponentsCID.h" #include "nsEmbedCID.h" #define RUNKEY "Software\\Microsoft\\Windows\\CurrentVersion\\Run" static nsWindowsHooks *gWindowsHooks = nsnull; // 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( IsHandlingJPEG, mHandleJPEG ) DEFINE_GETTER_AND_SETTER( IsHandlingGIF, mHandleGIF ) DEFINE_GETTER_AND_SETTER( IsHandlingPNG, mHandlePNG ) DEFINE_GETTER_AND_SETTER( IsHandlingXBM, mHandleXBM ) DEFINE_GETTER_AND_SETTER( IsHandlingBMP, mHandleBMP ) DEFINE_GETTER_AND_SETTER( IsHandlingICO, mHandleICO ) DEFINE_GETTER_AND_SETTER( IsHandlingXML, mHandleXML ) DEFINE_GETTER_AND_SETTER( IsHandlingXHTML, mHandleXHTML ) DEFINE_GETTER_AND_SETTER( IsHandlingXUL, mHandleXUL ) DEFINE_GETTER_AND_SETTER( IsHandlingHTTP, mHandleHTTP ) DEFINE_GETTER_AND_SETTER( IsHandlingHTTPS, mHandleHTTPS ) DEFINE_GETTER_AND_SETTER( IsHandlingFTP, mHandleFTP ) DEFINE_GETTER_AND_SETTER( IsHandlingCHROME, mHandleCHROME ) DEFINE_GETTER_AND_SETTER( IsHandlingGOPHER, mHandleGOPHER ) 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_ISUPPORTS1( nsWindowsHooks, nsIWindowsHooks ) static const char *jpgExts[] = { ".jpg", ".jpe", ".jpeg", ".jfif", ".pjpeg", ".pjp", 0 }; static const char *gifExts[] = { ".gif", 0 }; static const char *pngExts[] = { ".png", 0 }; static const char *xbmExts[] = { ".xbm", 0 }; static const char *bmpExts[] = { ".bmp", ".rle", ".dib", 0 }; static const char *icoExts[] = { ".ico", 0 }; static const char *xmlExts[] = { ".xml", 0 }; static const char *xhtmExts[] = { ".xht", ".xhtml", 0 }; static const char *xulExts[] = { ".xul", 0 }; static const char *htmExts[] = { ".htm", ".html", ".shtml", 0 }; nsWindowsHooks::nsWindowsHooks() : http( "http" ), https( "https" ), ftp( "ftp" ), chrome( "chrome" ), gopher( "gopher" ), jpg( jpgExts, "MozillaJPEG", "JPEG Image", "jpegfile", "jpeg-file.ico"), gif( gifExts, "MozillaGIF", "GIF Image", "giffile", "gif-file.ico"), png( pngExts, "MozillaPNG", "PNG Image", "pngfile", "image-file.ico"), xbm( xbmExts, "MozillaXBM", "XBM Image", "xbmfile", "image-file.ico"), bmp( bmpExts, "MozillaBMP", "BMP Image", "", "image-file.ico"), ico( icoExts, "MozillaICO", "Icon", "icofile", "%1"), xml( xmlExts, "MozillaXML", "XML Document", "xmlfile", "xml-file.ico"), xhtml( xhtmExts, "MozillaXHTML", "XHTML Document", "", "misc-file.ico"), xul( xulExts, "MozillaXUL", "Mozilla XUL Document", "", "xul-file.ico"), mozillaMarkup( htmExts, "MozillaHTML", "HTML Document", "htmlfile", "html-file.ico") { gWindowsHooks = this; } nsWindowsHooks::~nsWindowsHooks() { gWindowsHooks = nsnull; } // 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->mHandleFTP = BoolRegistryEntry( "isHandlingFTP" ); prefs->mHandleCHROME = BoolRegistryEntry( "isHandlingCHROME" ); prefs->mHandleGOPHER = BoolRegistryEntry( "isHandlingGOPHER" ); prefs->mHandleHTML = BoolRegistryEntry( "isHandlingHTML" ); prefs->mHandleJPEG = BoolRegistryEntry( "isHandlingJPEG" ); prefs->mHandleGIF = BoolRegistryEntry( "isHandlingGIF" ); prefs->mHandlePNG = BoolRegistryEntry( "isHandlingPNG" ); prefs->mHandleXBM = BoolRegistryEntry( "isHandlingXBM" ); prefs->mHandleBMP = BoolRegistryEntry( "isHandlingBMP" ); prefs->mHandleICO = BoolRegistryEntry( "isHandlingICO" ); prefs->mHandleXML = BoolRegistryEntry( "isHandlingXML" ); prefs->mHandleXHTML = BoolRegistryEntry( "isHandlingXHTML" ); prefs->mHandleXUL = BoolRegistryEntry( "isHandlingXUL" ); prefs->mShowDialog = BoolRegistryEntry( "showDialog" ); prefs->mHaveBeenSet = BoolRegistryEntry( "haveBeenSet" ); #ifdef DEBUG_law NS_ASSERTION( 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, gWindowsHooks->http ) || misMatch( mHandleHTTPS, gWindowsHooks->https ) || misMatch( mHandleFTP, gWindowsHooks->ftp ) || misMatch( mHandleCHROME, gWindowsHooks->chrome ) || misMatch( mHandleGOPHER, gWindowsHooks->gopher ) || misMatch( mHandleHTML, gWindowsHooks->mozillaMarkup ) || misMatch( mHandleJPEG, gWindowsHooks->jpg ) || misMatch( mHandleGIF, gWindowsHooks->gif ) || misMatch( mHandlePNG, gWindowsHooks->png ) || misMatch( mHandleXBM, gWindowsHooks->xbm ) || misMatch( mHandleBMP, gWindowsHooks->bmp ) || misMatch( mHandleICO, gWindowsHooks->ico ) || misMatch( mHandleXML, gWindowsHooks->xml ) || misMatch( mHandleXHTML, gWindowsHooks->xhtml ) || misMatch( mHandleXUL, gWindowsHooks->xul ) ) { // 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->mHandleFTP = PR_TRUE; settings->mHandleCHROME = PR_TRUE; settings->mHandleGOPHER = PR_TRUE; settings->mHandleHTML = PR_TRUE; settings->mHandleJPEG = PR_FALSE; settings->mHandleGIF = PR_FALSE; settings->mHandlePNG = PR_FALSE; settings->mHandleXBM = PR_FALSE; settings->mHandleBMP = PR_FALSE; settings->mHandleICO = PR_FALSE; settings->mHandleXML = PR_TRUE; settings->mHandleXHTML = PR_TRUE; settings->mHandleXUL = PR_TRUE; settings->mShowDialog = PR_TRUE; } // If launched with "-installer" then override mShowDialog. PRBool installing = PR_FALSE; #ifndef MOZ_XUL_APP if ( !settings->mShowDialog ) { // Get command line service. nsCOMPtr cmdLineArgs (do_GetService(NS_COMMANDLINESERVICE_CONTRACTID, &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; } } } #endif // 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. nsCOMPtr promptService( do_GetService(NS_PROMPTSERVICE_CONTRACTID)); nsCOMPtr bundleService( do_GetService( NS_STRINGBUNDLE_CONTRACTID, &rv ) ); if ( promptService && bundleService ) { // Next, get bundle that provides text for dialog. nsCOMPtr bundle; nsCOMPtr brandBundle; rv = bundleService->CreateBundle( "chrome://global-platform/locale/nsWindowsHooks.properties", getter_AddRefs( bundle ) ); rv = bundleService->CreateBundle( "chrome://branding/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( "isHandlingFTP", prefs, &nsIWindowsHooksSettings::GetIsHandlingFTP ); putPRBoolIntoRegistry( "isHandlingCHROME", prefs, &nsIWindowsHooksSettings::GetIsHandlingCHROME ); putPRBoolIntoRegistry( "isHandlingGOPHER", prefs, &nsIWindowsHooksSettings::GetIsHandlingGOPHER ); putPRBoolIntoRegistry( "isHandlingHTML", prefs, &nsIWindowsHooksSettings::GetIsHandlingHTML ); putPRBoolIntoRegistry( "isHandlingJPEG", prefs, &nsIWindowsHooksSettings::GetIsHandlingJPEG ); putPRBoolIntoRegistry( "isHandlingGIF", prefs, &nsIWindowsHooksSettings::GetIsHandlingGIF ); putPRBoolIntoRegistry( "isHandlingPNG", prefs, &nsIWindowsHooksSettings::GetIsHandlingPNG ); putPRBoolIntoRegistry( "isHandlingXBM", prefs, &nsIWindowsHooksSettings::GetIsHandlingXBM ); putPRBoolIntoRegistry( "isHandlingBMP", prefs, &nsIWindowsHooksSettings::GetIsHandlingBMP ); putPRBoolIntoRegistry( "isHandlingICO", prefs, &nsIWindowsHooksSettings::GetIsHandlingICO ); putPRBoolIntoRegistry( "isHandlingXML", prefs, &nsIWindowsHooksSettings::GetIsHandlingXML ); putPRBoolIntoRegistry( "isHandlingXHTML", prefs, &nsIWindowsHooksSettings::GetIsHandlingXHTML ); putPRBoolIntoRegistry( "isHandlingXUL", prefs, &nsIWindowsHooksSettings::GetIsHandlingXUL ); 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->mHandleJPEG ) { (void) jpg.set(); } else { (void) jpg.reset(); } if ( prefs->mHandleGIF ) { (void) gif.set(); } else { (void) gif.reset(); } if ( prefs->mHandlePNG ) { (void) png.set(); } else { (void) png.reset(); } if ( prefs->mHandleXBM ) { (void) xbm.set(); } else { (void) xbm.reset(); } if ( prefs->mHandleBMP ) { (void) bmp.set(); } else { (void) bmp.reset(); } if ( prefs->mHandleICO ) { (void) ico.set(); } else { (void) ico.reset(); } if ( prefs->mHandleXML ) { (void) xml.set(); } else { (void) xml.reset(); } if ( prefs->mHandleXHTML ) { (void) xhtml.set(); } else { (void) xhtml.reset(); } if ( prefs->mHandleXUL ) { (void) xul.set(); } else { (void) xul.reset(); } if ( prefs->mHandleHTTP ) { (void) http.set(); } else { (void) http.reset(); } if ( prefs->mHandleHTTPS ) { (void) https.set(); } else { (void) https.reset(); } if ( prefs->mHandleFTP ) { (void) ftp.set(); } else { (void) ftp.reset(); } if ( prefs->mHandleCHROME ) { (void) chrome.set(); } else { (void) chrome.reset(); } if ( prefs->mHandleGOPHER ) { (void) gopher.set(); } else { (void) gopher.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; } // nsIWindowsHooks.idl for documentation /* * Name: IsOptionEnabled * Arguments: * PRUnichar* option - the option line switch we check to see if it is in the registry key * * Return Value: * PRBool* _retval - PR_TRUE if option is already in the registry key, otherwise PR_FALSE * * Description: * This function merely checks if the passed in string exists in the (appname) Quick Launch Key or not. * * Author: * Joseph Elwell 3/1/2002 */ NS_IMETHODIMP nsWindowsHooks::IsOptionEnabled(const char* option, PRBool *_retval) { NS_ASSERTION(option, "nsWindowsHooks::IsOptionEnabled requires something like \"-turbo\""); *_retval = PR_FALSE; RegistryEntry startup ( HKEY_CURRENT_USER, RUNKEY, NS_QUICKLAUNCH_RUN_KEY, NULL ); nsCString cargs = startup.currentSetting(); if (cargs.Find(option, PR_TRUE) != kNotFound) *_retval = PR_TRUE; return NS_OK; } /* * Name: grabArgs * Arguments: * char* optionline - the full optionline as read from the (appname) Quick Launch registry key * * Return Value: * char** args - A pointer to the arguments (string in optionline) * passed to the executable in the (appname) Quick Launch registry key * * Description: * This function separates out the arguments from the optinline string * Returning a pointer into the first arguments buffer. * This function is used only locally, and is meant to reduce code size and readability. * * Author: * Joseph Elwell 3/1/2002 */ void grabArgs(char* optionline, char** args) { nsCRT::strtok(optionline, "\"", &optionline); if (optionline != NULL) *args = nsCRT::strtok(optionline, "\"", &optionline); } /* * Name: StartupAddOption * Arguments: * PRUnichar* option - the option line switch we want to add to the registry key * * Return Value: none * * Description: * This function adds the given option line argument to the (appname) Quick Launch registry key * * Author: * Joseph Elwell 3/1/2002 */ NS_IMETHODIMP nsWindowsHooks::StartupAddOption(const char* option) { NS_ASSERTION(option, "nsWindowsHooks::StartupAddOption requires something like \"-turbo\""); PRBool retval; IsOptionEnabled(option, &retval); if (retval) return NS_OK; //already in there RegistryEntry startup ( HKEY_CURRENT_USER, RUNKEY, NS_QUICKLAUNCH_RUN_KEY, NULL ); nsCString cargs = startup.currentSetting(); nsCAutoString newsetting; newsetting.Assign('\"'); newsetting.Append(thisApplication()); newsetting.Append('\"'); if (!cargs.IsEmpty()) { char* args; // exploiting the fact that nsString's storage is also a char* buffer. // NS_CONST_CAST is safe here because nsCRT::strtok will only modify // the existing buffer grabArgs(cargs.BeginWriting(), &args); if (args != NULL) newsetting.Append(args); else { // check for the old style registry key that doesnot quote its executable IsOptionEnabled("-turbo", &retval); if (retval) newsetting.Append(" -turbo"); } } newsetting.Append(' '); newsetting.Append(option); startup.setting = newsetting; startup.set(); return NS_OK; } /* * Name: StartupRemoveOption * Arguments: * PRUnichar* option - the option line switch we want to remove from the registry key * * Return Value: none. * * Description: * This function removes the given option from the (appname) Quick Launch Key. * And deletes the key entirely if no options are left. * * Author: * Joseph Elwell 3/1/2002 */ NS_IMETHODIMP nsWindowsHooks::StartupRemoveOption(const char* option) { NS_ASSERTION(option, "nsWindowsHooks::StartupRemoveOption requires something like \"-turbo\""); PRBool startupFound; IsOptionEnabled(option, &startupFound ); if ( !startupFound ) return NS_OK; // already disabled, no need to do anything RegistryEntry startup ( HKEY_CURRENT_USER, RUNKEY, NS_QUICKLAUNCH_RUN_KEY, NULL ); nsCString cargs = startup.currentSetting(); char* args; // exploiting the fact that nsString's storage is also a char* buffer. // NS_CONST_CAST is safe here because nsCRT::strtok will only modify // the existing buffer grabArgs(cargs.BeginWriting(), &args); nsCAutoString launchcommand; if (args) { launchcommand.Assign(args); PRInt32 optionlocation = launchcommand.Find(option, PR_TRUE); // modify by one to get rid of the space we prepended in StartupAddOption if (optionlocation != kNotFound) launchcommand.Cut(optionlocation - 1, strlen(option) + 1); } if (launchcommand.IsEmpty()) { startup.set(); } else { nsCAutoString ufileName; ufileName.Assign('\"'); ufileName.Append(thisApplication()); ufileName.Append('\"'); ufileName.Append(launchcommand); startup.setting = ufileName; startup.set(); } return NS_OK; } nsresult WriteBitmap(nsIFile* aFile, gfxIImageFrame* aImage) { PRInt32 width, height; aImage->GetWidth(&width); aImage->GetHeight(&height); PRUint8* bits; PRUint32 length; aImage->LockImageData(); aImage->GetImageData(&bits, &length); if (!bits) { aImage->UnlockImageData(); 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 BITMAPINFOHEADER bmi; bmi.biSize = sizeof(BITMAPINFOHEADER); bmi.biWidth = width; bmi.biHeight = height; bmi.biPlanes = 1; bmi.biBitCount = (WORD)bitCount*8; bmi.biCompression = BI_RGB; bmi.biSizeImage = length; bmi.biXPelsPerMeter = 0; bmi.biYPelsPerMeter = 0; bmi.biClrUsed = 0; bmi.biClrImportant = 0; BITMAPFILEHEADER bf; bf.bfType = 0x4D42; // 'BM' bf.bfReserved1 = 0; bf.bfReserved2 = 0; bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); bf.bfSize = bf.bfOffBits + bmi.biSizeImage; // get a file output stream nsresult rv; nsCOMPtr stream; rv = NS_NewLocalFileOutputStream(getter_AddRefs(stream), aFile); NS_ENSURE_SUCCESS(rv, rv); // write the bitmap headers and rgb pixel data to the file rv = NS_ERROR_FAILURE; if (stream) { PRUint32 written; stream->Write((const char*)&bf, sizeof(BITMAPFILEHEADER), &written); if (written == sizeof(BITMAPFILEHEADER)) { stream->Write((const char*)&bmi, sizeof(BITMAPINFOHEADER), &written); if (written == sizeof(BITMAPINFOHEADER)) { #ifndef MOZ_CAIRO_GFX stream->Write((const char*)bits, length, &written); if (written == length) rv = NS_OK; #else // write out the image data backwards because the desktop won't // show bitmaps with negative heights for top-to-bottom PRUint32 i = length; rv = NS_OK; do { i -= bpr; stream->Write(((const char*)bits) + i, bpr, &written); if (written != bpr) { rv = NS_ERROR_FAILURE; break; } } while (i != 0); #endif } } stream->Close(); } aImage->UnlockImageData(); return rv; } NS_IMETHODIMP nsWindowsHooks::SetImageAsWallpaper(nsIDOMElement* aElement, PRBool aUseBackground) { nsresult rv; nsCOMPtr gfxFrame; if (aUseBackground) { // XXX write background loading stuff! } else { nsCOMPtr imageContent = do_QueryInterface(aElement, &rv); if (!imageContent) return rv; // get the image container nsCOMPtr request; rv = imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST, getter_AddRefs(request)); if (!request) return rv; nsCOMPtr container; rv = request->GetImage(getter_AddRefs(container)); if (!container) return NS_ERROR_FAILURE; // get the current frame, which holds the image data container->GetCurrentFrame(getter_AddRefs(gfxFrame)); } if (!gfxFrame) return NS_ERROR_FAILURE; // get the profile root directory nsCOMPtr file; rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR, getter_AddRefs(file)); NS_ENSURE_SUCCESS(rv, rv); // get the product brand name from localized strings nsXPIDLString brandName, fileLeafName; nsCOMPtr bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); NS_ENSURE_TRUE(bundleService, rv); // get the product brand name from localized strings nsCOMPtr bundle; rv = bundleService->CreateBundle("chrome://branding/locale/brand.properties", getter_AddRefs(bundle)); NS_ENSURE_SUCCESS(rv, rv); rv = bundle->GetStringFromName(NS_LITERAL_STRING("brandShortName").get(), getter_Copies(brandName)); NS_ENSURE_SUCCESS(rv, rv); // get the file leaf name from localized strings (e.g. "%S Wallpaper.bmp") rv = bundleService->CreateBundle("chrome://global-platform/locale/nsWindowsHooks.properties", getter_AddRefs(bundle)); NS_ENSURE_SUCCESS(rv, rv); const PRUnichar* stringArray[] = { brandName.get() }; rv = bundle->FormatStringFromName(NS_LITERAL_STRING("wallpaperFile").get(), stringArray, NS_ARRAY_LENGTH(stringArray), getter_Copies(fileLeafName)); NS_ENSURE_SUCCESS(rv, rv); // eventually, the path is %APPDATA%\Mozilla\Mozilla Wallpaper.bmp fileLeafName.AppendLiteral(".bmp"); rv = file->Append(fileLeafName); NS_ENSURE_SUCCESS(rv, rv); // write the bitmap to the target file rv = WriteBitmap(file, gfxFrame); NS_ENSURE_SUCCESS(rv, rv); // set it as the system wallpaper nsCAutoString nativePath; rv = file->GetNativePath(nativePath); NS_ENSURE_SUCCESS(rv, rv); ::SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID) nativePath.get(), SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE); return rv; }