New files for windows desktop integration (not built yet)

This commit is contained in:
law%netscape.com 2000-05-10 01:50:59 +00:00
parent be759e1524
commit 4f65713bc1
4 changed files with 1023 additions and 0 deletions

View File

@ -0,0 +1,60 @@
#!nmake
#
# 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 Netscape are
# Copyright (C) 1998 Netscape Communications Corporation. All
# Rights Reserved.
#
# Contributor(s):
# Bill Law <law@netscape.com>
MODULE=winhooks
DEPTH=..\..\..
XPIDL_MODULE=winhooks
XPIDLSRCS=\
.\nsIWindowsHooks.idl \
$(NULL)
include <$(DEPTH)/config/config.mak>
DLLNAME = winhooks
DLL1NAME = winhooks
PDBFILE = $(DLLNAME).pdb
MAPFILE = $(DLLNAME).map
DLL =.\$(OBJDIR)\$(DLLNAME).dll
MAKE_OBJ_TYPE = DLL
LINCS = \
$(NULL)
LLIBS = \
$(DIST)\lib\xpcom.lib \
$(NULL)
OBJS = \
.\$(OBJDIR)\nsWindowsHooks.obj \
$(NULL)
include <$(DEPTH)\config\rules.mak>
install:: $(DLL)
$(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin\components
clobber::
rm -f $(DIST)\bin\components\$(DLLNAME).dll

View File

@ -0,0 +1,139 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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 Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Bill Law <law@netscape.com>
*/
#include "nsISupports.idl"
/* These interface provides support for integrating Mozilla into Windows.
* This integration consists primarily of setting Mozilla as the "default
* browser." Or more precisely, setting Mozilla as the executable to
* handle certain file types.
*
* There are two subtly different types of desktop objects that Mozilla
* can be configured to "handle:"
* o File types (based on file extension)
* o Internet shortcuts (based on URL protocol).
*
* While these are different types of objects, the mechanism by which
* applications are matched with them is essentially the same.
*
* In the case of files, there is one more level of indirection. File
* extensions are assigned a "file type" via a Windows registry entry.
* For example, given the file extension ".foo", the file type is
* determined by examing the value stored in the "default" value stored
* at the registry key HEKY_LOCAL_MACHINE\Software\Classes\.foo.
*
* Once you have the "file type" then you use that the same way you use
* Internet Shortcut protocol names to determine which application to
* launch. The application is specified by the default value stored in
* the registry key
* HKEY_LOCAL_MACHINE\Software\Classes\<X>\shell\open\command, where
* <X> is the "file type" or protocol name.
*
* If there are additional keys under "shell" then these appear on the
* context menu for files/shortcuts of this type. Typically, there are
* entries for "print." But Mozilla does not currently support a command
* line option to print so we don't offer that.
*
* Previously, Netscape Communicator made itself the handler of standard
* web things by creating a new file type "NetscapeMarkup" and mapping
* extensions to that (.htm, .html, .shtml, .xbm), or, by setting itself
* up as the "handler" for the file types of other web things (.jpg, .gif)
* and Internet Shortcut protocols (ftp, gopher, http, https, mailto, news,
* snews).
*
* In order to better enable Mozilla to co-exist with other browsers
* (including Communicator), it will create yet another new file type,
* "MozillaMarkup," that will be used to make Mozilla the default handler
* for certain file extensions. This will be done by remapping those
* extensions to this new type.
*
* Mozilla will attempt to remember the original mapping and restore it
* when the user decides to no longer have Mozilla be the default handler
* for that extension.
*
* Mozilla will drop support for some items that are no longer germane:
* the .shtml file extension and the gopher: protocol. We will also, perhaps
* only temporarily, drop support for protocols that aren't accessible from
* the command line: mailto:, news:, and snews:.
*
* We will be adding support for the chrome: protocol (using the "-chrome"
* command line option) and for .png, .xul and .xml file extensions.
*
* Missing Features:
*
* Currently, there is no way to extend the set of file types or protocols
* that Mozilla can be associated with (save manually tweaking the Windows
* registry). This is likely to be a problem for branded Mozilla browsers
* that might support specialized file types or protocols (e.g., .aim files).
*
* The plan is to extend this interface so that such file types and protocols
* can be set up using the implementation of the interfaces defined here.
*/
/* nsIWindowsHooksSettings
*
* This interface is used to get/set the user preferences relating to
* "windows hooks" (aka "windows integration"). It is basically just
* a conglomeration of a bunch of boolean attributes; it exists mainly
* for historical reasons (it corresponds to the internal Prefs struct
* that was in nsIDefaultBrowser.h in Mozilla Classic).
*/
[scriptable, uuid(4ce9aa90-0a6a-11d4-8076-00600811a9c3)]
interface nsIWindowsHooksSettings : nsISupports {
// Internet shortcuts (based on "protocol").
attribute boolean isHandlingHTTP;
attribute boolean isHandlingHTTPS;
attribute boolean isHandlingFTP;
attribute boolean isHandlingCHROME;
// File handling (based on extension).
attribute boolean isHandlingHTML;
attribute boolean isHandlingJPEG;
attribute boolean isHandlingGIF;
attribute boolean isHandlingPNG;
attribute boolean isHandlingXML;
attribute boolean isHandlingXUL;
};
/* nsIWindowsHooks
*
* This interface describes the service that you can use to
* get/set the various windows integration features specified
* by the nsIWindowsHooksPrefs attributes.
*/
[scriptable, uuid(19c9fbb0-06a3-11d4-8076-00600811a9c3)]
interface nsIWindowsHooks : nsISupports {
// Settings. Get/set this to query or modify them. The Windows
// registry is updated when you set this attribute.
attribute nsIWindowsHooksSettings settings;
};
%{C++
#define NS_IWINDOWSHOOKS_PROGID "component://mozilla/winhooks"
#define NS_IWINDOWSHOOKS_CLASSNAME "Mozilla Windows Integration Hooks"
%}

View File

@ -0,0 +1,382 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* 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 Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Bill Law <law@netscape.com>
*/
#include "nsIWindowsHooks.h"
#include "nsIGenericFactory.h"
#include <windows.h>
// Implementation utilities.
#include "nsWindowsHooksUtil.cpp"
// Objects that describe the Windows registry entries that we need to tweak.
static ProtocolRegistryEntry
http( "http" ),
https( "https" ),
ftp( "ftp" ),
chrome( "chrome" );
const char *jpgExts[] = { ".jpg", ".jpeg", 0 };
const char *gifExts[] = { ".gif", 0 };
const char *pngExts[] = { ".png", 0 };
const char *xmlExts[] = { ".xml", 0 };
const char *xulExts[] = { ".xul", 0 };
const char *htmExts[] = { ".htm", ".html", 0 };
static FileTypeRegistryEntry
jpg( jpgExts, "MozillaJPEG", "Mozilla JPEG Image File" ),
gif( gifExts, "MozillaGIF", "Mozilla GIF Image File" ),
png( pngExts, "MozillaPNG", "Mozilla Portable Network Graphic Image File" ),
xml( xmlExts, "MozillaXML", "Mozilla Extensible Markup Language Document" ),
xul( xulExts, "MozillaXUL", "Mozilla Extensible User-interface Language Document" );
static EditableFileTypeRegistryEntry
mozillaMarkup( htmExts, "MozillaHTML", "Mozilla Hypertext Markup Language Document" );
/* c09bc130-0a71-11d4-8076-00600811a9c3 */
#define NS_IWINDOWSHOOKS_CID \
{ 0xc09bc130, 0x0a71, 0x11d4, {0x80, 0x76, 0x00, 0x60, 0x08, 0x11, 0xa9, 0xc3} }
// Implementation of the nsIWindowsHooksSettings interface.
class nsWindowsHooksSettings : public nsIWindowsHooksSettings {
public:
// ctor/dtor
nsWindowsHooksSettings();
virtual ~nsWindowsHooksSettings();
// Declare all interface methods we must implement.
NS_DECL_ISUPPORTS
NS_DECL_NSIWINDOWSHOOKSSETTINGS
// Typedef for nsIWindowsHooksSettings getter/setter member functions.
typedef nsresult (__stdcall nsIWindowsHooksSettings::*getter)( PRBool* );
typedef nsresult (__stdcall nsIWindowsHooksSettings::*setter)( PRBool );
protected:
// General purpose getter.
NS_IMETHOD Get( PRBool *result, PRBool nsWindowsHooksSettings::*member );
// General purpose setter.
NS_IMETHOD Set( PRBool value, PRBool nsWindowsHooksSettings::*member );
private:
// Internet shortcut protocols.
struct {
PRBool mHandleHTTP;
PRBool mHandleHTTPS;
PRBool mHandleFTP;
PRBool mHandleCHROME;
};
// File types.
struct {
PRBool mHandleHTML;
PRBool mHandleJPEG;
PRBool mHandleGIF;
PRBool mHandlePNG;
PRBool mHandleXML;
PRBool mHandleXUL;
};
friend class nsWindowsHooks;
}; // nsWindowsHooksSettings
// Use standard implementation of nsISupports stuff.
NS_IMPL_ISUPPORTS1( nsWindowsHooksSettings, nsIWindowsHooksSettings );
nsWindowsHooksSettings::nsWindowsHooksSettings() {
NS_INIT_ISUPPORTS();
}
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( IsHandlingXML, mHandleXML )
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 )
// Implementation of the nsIWindowsHooks interface.
class nsWindowsHooks : public nsIWindowsHooks {
public:
// ctor/dtor
nsWindowsHooks();
virtual ~nsWindowsHooks();
// Declare all interface methods we must implement.
NS_DECL_ISUPPORTS
NS_DECL_NSIWINDOWSHOOKS
protected:
// Internal flavor of GetPreferences.
NS_IMETHOD GetSettings( nsWindowsHooksSettings ** );
// Set registry according to settings.
NS_IMETHOD SetRegistry();
private:
// Module stuff.
static NS_METHOD CreateWindowsHooks( nsISupports *aOuter,
REFNSIID aIID,
void **aResult );
static nsWindowsHooks *mInstance;
public:
static nsModuleComponentInfo components[];
}; // nsWindowsHooksSettings
// Use standard implementation of nsISupports stuff.
NS_IMPL_ISUPPORTS1( nsWindowsHooks, nsIWindowsHooks );
nsWindowsHooks::nsWindowsHooks() {
NS_INIT_ISUPPORTS();
}
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 = (void*)( BoolRegistryEntry( "isHandlingHTTP" ) ) ? PR_TRUE : PR_FALSE;
prefs->mHandleHTTPS = (void*)( BoolRegistryEntry( "isHandlingHTTPS" ) ) ? PR_TRUE : PR_FALSE;
prefs->mHandleFTP = (void*)( BoolRegistryEntry( "isHandlingFTP" ) ) ? PR_TRUE : PR_FALSE;
prefs->mHandleCHROME = (void*)( BoolRegistryEntry( "isHandlingCHROME" ) ) ? PR_TRUE : PR_FALSE;
prefs->mHandleHTML = (void*)( BoolRegistryEntry( "isHandlingHTML" ) ) ? PR_TRUE : PR_FALSE;
prefs->mHandleJPEG = (void*)( BoolRegistryEntry( "isHandlingJPEG" ) ) ? PR_TRUE : PR_FALSE;
prefs->mHandleGIF = (void*)( BoolRegistryEntry( "isHandlingGIF" ) ) ? PR_TRUE : PR_FALSE;
prefs->mHandlePNG = (void*)( BoolRegistryEntry( "isHandlingPNG" ) ) ? PR_TRUE : PR_FALSE;
prefs->mHandleXML = (void*)( BoolRegistryEntry( "isHandlingXML" ) ) ? PR_TRUE : PR_FALSE;
prefs->mHandleXUL = (void*)( BoolRegistryEntry( "isHandlingXUL" ) ) ? PR_TRUE : PR_FALSE;
#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;
}
// 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( "isHandlingHTML", prefs, &nsIWindowsHooksSettings::GetIsHandlingHTML );
putPRBoolIntoRegistry( "isHandlingJPEG", prefs, &nsIWindowsHooksSettings::GetIsHandlingJPEG );
putPRBoolIntoRegistry( "isHandlingGIF", prefs, &nsIWindowsHooksSettings::GetIsHandlingGIF );
putPRBoolIntoRegistry( "isHandlingPNG", prefs, &nsIWindowsHooksSettings::GetIsHandlingPNG );
putPRBoolIntoRegistry( "isHandlingXML", prefs, &nsIWindowsHooksSettings::GetIsHandlingXML );
putPRBoolIntoRegistry( "isHandlingXUL", prefs, &nsIWindowsHooksSettings::GetIsHandlingXUL );
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->mHandleXML ) {
(void) xml.set();
} else {
(void) xml.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) ftp.set();
} else {
(void) ftp.reset();
}
return NS_OK;
}
NS_IMETHODIMP
nsWindowsHooks::CreateWindowsHooks( nsISupports *aOuter,
REFNSIID aIID,
void **aResult ) {
if ( !aResult ) {
return NS_ERROR_INVALID_POINTER;
}
if ( aOuter ) {
*aResult = nsnull;
return NS_ERROR_NO_AGGREGATION;
}
if (mInstance == nsnull) {
mInstance = new nsWindowsHooks();
}
if ( mInstance == nsnull )
return NS_ERROR_OUT_OF_MEMORY;
nsresult rv = mInstance->QueryInterface( aIID, aResult );
if ( NS_FAILED(rv) ) {
*aResult = nsnull;
}
return rv;
}
nsWindowsHooks* nsWindowsHooks::mInstance = nsnull;
nsModuleComponentInfo nsWindowsHooks::components[] = {
{ NS_IWINDOWSHOOKS_CLASSNAME,
NS_IWINDOWSHOOKS_CID,
NS_IWINDOWSHOOKS_PROGID,
nsWindowsHooks::CreateWindowsHooks },
};
NS_IMPL_NSGETMODULE( "nsWindowsHooks", nsWindowsHooks::components )

View File

@ -0,0 +1,442 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/*
* 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 Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
* Bill Law <law@netscape.com>
*/
#include <windows.h>
#include <string.h>
#include "nsString.h"
// Where Mozilla stores its own registry values.
const char * const mozillaKeyName = "Software\\Mozilla\\Desktop";
static const char shortcutSuffix[] = " -url \"%1\"";
static const char chromeSuffix[] = " -chrome \"%1\"";
// Returns the (fully-qualified) name of this executable.
static nsCString thisApplication() {
static nsCString result;
if ( result.IsEmpty() ) {
char buffer[MAX_PATH] = { 0 };
DWORD len = ::GetModuleFileName( NULL, buffer, sizeof buffer );
len = ::GetShortPathName( buffer, buffer, sizeof buffer );
result = buffer;
result.ToUpperCase();
}
return result;
}
// Returns this
// RegistryEntry
//
// Generic registry entry (no saving of previous values). Each is comprised of:
// o A base HKEY
// o A subkey name.
// o An optional value name (empty for the "default" value).
// o The registry setting we'd like this entry to have when set.
struct RegistryEntry {
HKEY baseKey; // e.g., HKEY_CURRENT_USER
nsCString keyName; // Key name.
nsCString valueName; // Value name (can be empty, which implies NULL).
nsCString setting; // What we set it to.
RegistryEntry( HKEY baseKey, const char* keyName, const char* valueName, const char* setting )
: baseKey( baseKey ), keyName( keyName ), valueName( valueName ), setting( setting ) {
}
PRBool isAlreadySet() const;
nsresult set();
nsresult reset();
nsCString currentSetting() const;
// Return value name in proper form for passing to ::Reg functions
// (i.e., emptry string is converted to a NULL pointer).
const char* valueNameArg() const {
return valueName.IsEmpty() ? NULL : valueName.GetBuffer();
}
nsCString fullName() const;
};
// BoolRegistryEntry
//
// These are used to store the "windows integration" preferences.
// You can query the value via operator void* (i.e., if ( boolPref )... ).
// These are stored under HKEY_LOCAL_MACHINE\Software\Mozilla\Desktop.
// Set sets the stored value to "1". Reset deletes it (which implies 0).
struct BoolRegistryEntry : public RegistryEntry {
BoolRegistryEntry( const char *name )
: RegistryEntry( HKEY_LOCAL_MACHINE, mozillaKeyName, name, "1" ) {
}
operator void*();
};
// SavedRegistryEntry
//
// Like a plain RegistryEntry, but set/reset save/restore the
// it had before we set it.
struct SavedRegistryEntry : public RegistryEntry {
SavedRegistryEntry( HKEY baseKey, const char *keyName, const char *valueName, const char *setting )
: RegistryEntry( baseKey, keyName, valueName, setting ) {
}
nsresult set();
nsresult reset();
};
// ProtocolRegistryEntry
//
// For setting entries for a given Internet Shortcut protocol.
// The key name is calculated as
// HKEY_LOCAL_MACHINE\Software\Classes\protocol\shell\open\command.
// The setting is this executable (with appropriate suffix).
// Set/reset are trickier in this case.
struct ProtocolRegistryEntry : public SavedRegistryEntry {
nsCString protocol;
ProtocolRegistryEntry( const char* protocol )
: SavedRegistryEntry( HKEY_LOCAL_MACHINE, "", "", thisApplication() ),
protocol( protocol ) {
keyName = "Software\\Classes\\";
keyName += protocol;
keyName += "\\shell\\open\\command";
// Append appropriate suffix to setting.
if ( protocol == "chrome" ) {
// Use "-chrome" command line flag.
setting += chromeSuffix;
} else {
// Use standard "-url" command line flag.
setting += shortcutSuffix;
}
}
nsresult set();
nsresult reset();
};
// DDERegistryEntry
//
// Like a protocol registry entry, but for the shell\open\ddeexec subkey.
// We don't need to do anything special for set/reset, either.
struct DDERegistryEntry : public SavedRegistryEntry {
DDERegistryEntry( const char *protocol )
: SavedRegistryEntry( HKEY_LOCAL_MACHINE, "", "", thisApplication() ) {
keyName = "Software\\Classes\\";
keyName += protocol;
keyName += "\\shell\\open\\ddeexec";
}
};
// FileTypeRegistryEntry
//
// For setting entries relating to a file extension (or extensions).
// This object itself is for the "file type" associated with the extension.
// Set/reset manage the mapping from extension to the file type, as well.
struct FileTypeRegistryEntry : public ProtocolRegistryEntry {
nsCString fileType;
const char **ext;
nsCString desc;
FileTypeRegistryEntry ( const char **ext, const char *fileType, const char *desc )
: ProtocolRegistryEntry( fileType ),
fileType( fileType ),
ext( ext ),
desc( desc ) {
}
nsresult set();
nsresult reset();
};
// EditableFileTypeRegistryEntry
//
// Extends FileTypeRegistryEntry by setting an additional handler for an "edit" command.
struct EditableFileTypeRegistryEntry : public FileTypeRegistryEntry {
EditableFileTypeRegistryEntry( const char **ext, const char *fileType, const char *desc )
: FileTypeRegistryEntry( ext, fileType, desc ) {
}
nsresult set();
};
// Generate the "full" name of this registry entry.
nsCString RegistryEntry::fullName() const {
nsCString result;
if ( baseKey == HKEY_CURRENT_USER ) {
result = "HKEY_CURRENT_USER\\";
} else if ( baseKey == HKEY_LOCAL_MACHINE ) {
result = "HKEY_LOCAL_MACHINE\\";
} else {
result = "\\";
}
result += keyName;
if ( !valueName.IsEmpty() ) {
result += "[";
result += valueName;
result += "]";
}
return result;
}
// Tests whether registry entry already has desired setting.
PRBool RegistryEntry::isAlreadySet() const {
PRBool result = FALSE;
nsCString current = currentSetting();
result = ( current == setting );
return result;
}
// Gives registry entry the desired setting.
nsresult RegistryEntry::set() {
#ifdef DEBUG_law
printf( "Setting %s=%s\n", (const char*)fullName(), (const char*)setting );
#endif
nsresult result = NS_ERROR_FAILURE;
HKEY key;
LONG rc = ::RegOpenKey( baseKey, keyName, &key );
// See if key doesn't exist yet...
if ( rc == ERROR_FILE_NOT_FOUND ) {
rc = ::RegCreateKey( baseKey, keyName, &key );
}
if ( rc == ERROR_SUCCESS ) {
char buffer[4096] = { 0 };
DWORD len = sizeof buffer;
rc = ::RegQueryValueEx( key, valueNameArg(), NULL, NULL, (LPBYTE)buffer, &len );
if ( strcmp( setting, buffer ) != 0 ) {
rc = ::RegSetValueEx( key, valueNameArg(), NULL, REG_SZ, (LPBYTE)(const char*)setting, strlen(setting) );
#ifdef DEBUG_law
NS_WARN_IF_FALSE( rc == ERROR_SUCCESS, (const char*)fullName() );
#endif
if ( rc == ERROR_SUCCESS ) {
result = NS_OK;
}
} else {
// Already has desired setting.
result = NS_OK;
}
::RegCloseKey( key );
} else {
#ifdef DEBUG_law
NS_WARN_IF_FALSE( rc == ERROR_SUCCESS, (const char*)fullName() );
#endif
}
return result;
}
// Get current setting, set new one, then save the previous.
nsresult SavedRegistryEntry::set() {
nsresult rv = NS_OK;
nsCString prev = currentSetting();
// See if value is changing.
if ( setting != prev ) {
// Set new.
rv = RegistryEntry::set();
if ( NS_SUCCEEDED( rv ) ) {
// Save old.
RegistryEntry( HKEY_LOCAL_MACHINE, "Software\\Mozilla\\Desktop", fullName(), prev ).set();
}
}
return rv;
}
// Set this entry and its corresponding DDE entry. The DDE entry
// must be turned off to stop Windows from trying to use DDE.
nsresult ProtocolRegistryEntry::set() {
// Set this entry.
nsresult rv = SavedRegistryEntry::set();
// Save and set corresponding DDE entry. This stops Windows from trying to use
// DDE (and getting an error).
nsCString ddeName = "Software\\Classes\\";
ddeName += protocol;
ddeName += "\\shell\\open\\ddeexec";
SavedRegistryEntry( HKEY_LOCAL_MACHINE, ddeName, NULL, NULL ).set();
// Special case.
if ( protocol = "http" ) {
// We need to zap HKR\Software\Classes\http\shell\open\ddeexec\Application
// because Communicator looks there to determine whether they're the
// "default browser." If they are (the value there is "NSShell" or "Netscape")
// then it will reset lots of registry entries, "stealing" them from us.
SavedRegistryEntry special( HKEY_LOCAL_MACHINE, "Software\\Classes\\http\\shell\\open\\ddeexec\\Application", NULL, NULL );
nsCString specialVal = special.currentSetting();
if ( specialVal == "NSShell" || specialVal == "Netscape" ) {
// Reset this so Communicator will at least prompt the user.
special.set();
}
}
return rv;
}
// Not being a "saved" entry, we can't restore, so just delete it.
nsresult RegistryEntry::reset() {
HKEY key;
LONG rc = ::RegOpenKey( baseKey, keyName, &key );
if ( rc == ERROR_SUCCESS ) {
rc = ::RegDeleteValue( key, valueNameArg() );
}
return NS_OK;
}
// Resets registry entry to the saved value (if there is one). We first
// ensure that we still "own" that entry (by comparing its value to what
// we would set it to).
nsresult SavedRegistryEntry::reset() {
nsresult result = NS_OK;
// Get current setting for this key/value.
nsCString current = currentSetting();
// Test if we "own" it.
if ( current == setting ) {
// Unset it, then. First get saved value it had previously.
RegistryEntry saved = RegistryEntry( HKEY_LOCAL_MACHINE, mozillaKeyName, fullName(), "" );
saved.setting = saved.currentSetting();
if ( !saved.setting.IsEmpty() ) {
// Set to previous value.
setting = saved.setting;
result = RegistryEntry::set();
// Remove saved entry.
saved.reset();
} else {
// Just delete this key/value.
result = RegistryEntry::reset();
}
}
return result;
}
// Restore this entry and corresponding DDE entry.
nsresult ProtocolRegistryEntry::reset() {
// Restore this entry.
nsresult rv = SavedRegistryEntry::reset();
// Do same for corresponding DDE entry (which we had to zap to stop DDE).
DDERegistryEntry( protocol ).reset();
// Special case.
if ( protocol = "http" ) {
// We had to zap HKR\Software\Classes\http\shell\open\ddeexec\Application
// (see comment above under ProtocolRegistryEntry::set). Restore it here.
SavedRegistryEntry( HKEY_LOCAL_MACHINE, "Software\\Classes\\http\\shell\\open\\ddeexec\\Application", NULL, NULL ).reset();
}
return rv;
}
// Return current setting for this registry entry.
nsCString RegistryEntry::currentSetting() const {
nsCString result;
HKEY key;
LONG rc = ::RegOpenKey( baseKey, keyName, &key );
if ( rc == ERROR_SUCCESS ) {
char buffer[4096];
DWORD len = sizeof buffer;
rc = ::RegQueryValueEx( key, valueNameArg(), NULL, NULL, (LPBYTE)buffer, &len );
if ( rc == ERROR_SUCCESS ) {
result = buffer;
}
::RegCloseKey( key );
}
return result;
}
// For each file extension, map it to this entry's file type.
// Set the file type so this application opens files of that type.
nsresult FileTypeRegistryEntry::set() {
nsresult rv = NS_OK;
// Set file extensions.
for ( int i = 0; NS_SUCCEEDED( rv ) && ext[i]; i++ ) {
nsCString thisExt = "Software\\Classes\\";
thisExt += ext[i];
rv = SavedRegistryEntry( HKEY_LOCAL_MACHINE, thisExt, "", fileType ).set();
}
// If OK, set file type opener.
if ( NS_SUCCEEDED( rv ) ) {
rv = ProtocolRegistryEntry::set();
// If we just created this file type entry, set description and default icon.
if ( NS_SUCCEEDED( rv ) ) {
nsCString descKey = "Software\\Classes\\";
descKey += protocol;
RegistryEntry descEntry( HKEY_LOCAL_MACHINE, descKey, NULL, desc );
if ( descEntry.currentSetting().IsEmpty() ) {
descEntry.set();
}
nsCString iconKey = "Software\\Classes\\";
iconKey += protocol;
iconKey += "\\DefaultIcon";
RegistryEntry iconEntry( HKEY_LOCAL_MACHINE, iconKey, NULL, thisApplication()+",1" );
if ( iconEntry.currentSetting().IsEmpty() ) {
iconEntry.set();
}
}
}
return rv;
}
// Basically, the inverse of set().
// First, reset the opener for this entry's file type.
// Then, reset the file type associated with each extension.
nsresult FileTypeRegistryEntry::reset() {
nsresult rv = ProtocolRegistryEntry::reset();
for ( int i = 0; ext[ i ]; i++ ) {
nsCString thisExt = "Software\\Classes\\";
thisExt += ext[i];
(void)SavedRegistryEntry( HKEY_LOCAL_MACHINE, thisExt, "", fileType ).reset();
}
return rv;
}
// Do inherited set() and also set key for edit (with -edit option).
//
// Note: We make the rash assumption that we "own" this filetype (aka "protocol").
// If we ever start commandeering some other file type then this may have to be
// rethought. The solution is to override reset() and undo this (and make the
// "edit" entry a SavedRegistryEntry).
nsresult EditableFileTypeRegistryEntry::set() {
nsresult rv = FileTypeRegistryEntry::set();
if ( NS_SUCCEEDED( rv ) ) {
nsCString editKey = "Software\\Classes\\";
editKey += protocol;
editKey += "\\shell\\edit\\command";
nsCString editor = thisApplication();
editor += " -edit \"%1\"";
rv = RegistryEntry( HKEY_LOCAL_MACHINE, editKey, "", editor ).set();
}
return rv;
}
// Convert current registry setting to boolean.
BoolRegistryEntry::operator void*() {
return (void*)( currentSetting() == "1" ? PR_TRUE : PR_FALSE );
}