From 48857f7cbd68d72d8f573ba34c0f0ef7c0942b03 Mon Sep 17 00:00:00 2001 From: "law%netscape.com" Date: Wed, 10 Feb 1999 23:27:09 +0000 Subject: [PATCH] moz->ns --- modules/libreg/xpcom/nsRegistry.cpp | 1204 +++++++++++++++++++++++++++ xpcom/base/nsError.h | 1 + xpcom/components/nsIRegistry.h | 326 ++++++++ xpcom/components/nsRegistry.cpp | 1204 +++++++++++++++++++++++++++ xpcom/public/nsError.h | 1 + xpcom/public/nsIRegistry.h | 326 ++++++++ xpcom/src/nsRegistry.cpp | 1204 +++++++++++++++++++++++++++ xpcom/tools/registry/makefile.win | 1 - xpcom/tools/registry/regExport.cpp | 52 +- 9 files changed, 4292 insertions(+), 27 deletions(-) create mode 100644 modules/libreg/xpcom/nsRegistry.cpp create mode 100644 xpcom/components/nsIRegistry.h create mode 100644 xpcom/components/nsRegistry.cpp create mode 100644 xpcom/public/nsIRegistry.h create mode 100644 xpcom/src/nsRegistry.cpp diff --git a/modules/libreg/xpcom/nsRegistry.cpp b/modules/libreg/xpcom/nsRegistry.cpp new file mode 100644 index 00000000000..0d26c07efb3 --- /dev/null +++ b/modules/libreg/xpcom/nsRegistry.cpp @@ -0,0 +1,1204 @@ +/* -*- 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.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "nsIRegistry.h" +#include "nsIEnumerator.h" +#include "NSReg.h" +#include "prmem.h" + +/*-------------------------------- nsRegistry ---------------------------------- +| This class implements the nsIRegistry interface using the functions | +| provided by libreg (as declared in mozilla/modules/libreg/include/NSReg.h). | +| | +| Since that interface is designed to match the libreg function, this class | +| is implemented with each member function being a simple wrapper for the | +| corresponding libreg function. | +------------------------------------------------------------------------------*/ +struct nsRegistry : public nsIRegistry { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // This class implements the nsIRegistry interface functions. + NS_IMETHOD Open( const char *regFile = 0 ); + NS_IMETHOD OpenDefault(); + NS_IMETHOD Close(); + + NS_IMETHOD GetString( Key baseKey, const char *path, char **result ); + NS_IMETHOD SetString( Key baseKey, const char *path, const char *value ); + NS_IMETHOD GetInt( Key baseKey, const char *path, int32 *result ); + NS_IMETHOD SetInt( Key baseKey, const char *path, int32 value ); + NS_IMETHOD GetBytes( Key baseKey, const char *path, void **result, uint32 *len ); + NS_IMETHOD SetBytes( Key baseKey, const char *path, void *value, uint32 len ); + NS_IMETHOD GetIntArray( Key baseKey, const char *path, int32 **result, uint32 *len ); + NS_IMETHOD SetIntArray( Key baseKey, const char *path, const int32 *value, uint32 len ); + + NS_IMETHOD AddSubtree( Key baseKey, const char *path, Key *result ); + NS_IMETHOD RemoveSubtree( Key baseKey, const char *path ); + NS_IMETHOD GetSubtree( Key baseKey, const char *path, Key *result ); + + NS_IMETHOD EnumerateSubtrees( Key baseKey, nsIEnumerator **result ); + NS_IMETHOD EnumerateAllSubtrees( Key baseKey, nsIEnumerator **result ); + + NS_IMETHOD GetValueType( Key baseKey, const char *path, uint32 *result ); + NS_IMETHOD GetValueLength( Key baseKey, const char *path, uint32 *result ); + + NS_IMETHOD EnumerateValues( Key baseKey, nsIEnumerator **result ); + + NS_IMETHOD GetCurrentUserName( char **result ); + NS_IMETHOD SetCurrentUserName( const char *name ); + + NS_IMETHOD Pack(); + + // ctor/dtor + nsRegistry(); + ~nsRegistry(); + +protected: + HREG mReg; // Registry handle. + REGERR mErr; // Last libreg error code. +}; // nsRegistry + + +#include "nsIFactory.h" +/*----------------------------- nsRegistryFactory ------------------------------ +| Class factory for nsRegistry objects. | +------------------------------------------------------------------------------*/ +struct nsRegistryFactory : public nsIFactory { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // nsIFactory methods + NS_IMETHOD CreateInstance(nsISupports *,const nsIID &,void **); + NS_IMETHOD LockFactory(PRBool aLock); + + // ctor + nsRegistryFactory(); +}; + + +/*--------------------------- nsRegSubtreeEnumerator --------------------------- +| This class implements the nsIEnumerator interface and is used to implement | +| the nsRegistry EnumerateSubtrees and EnumerateAllSubtrees functions. | +------------------------------------------------------------------------------*/ +struct nsRegSubtreeEnumerator : public nsIEnumerator { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // This class implements the nsIEnumerator interface functions. + nsresult First(); + nsresult Last(); + nsresult Next(); + nsresult Prev(); + nsresult CurrentItem(nsISupports **aItem); + nsresult IsDone(); + + // ctor/dtor + nsRegSubtreeEnumerator( HREG hReg, RKEY rKey, PRBool all ); + +protected: + NS_IMETHOD advance(); // Implementation file; does appropriate NR_RegEnum call. + HREG mReg; // Handle to registry we're affiliated with. + RKEY mKey; // Base key being enumerated. + REGENUM mEnum; // Corresponding libreg "enumerator". + REGENUM mNext; // Lookahead value. + uint32 mStyle; // Style (indicates all or some); + PRBool mDone; // Done flag. + REGERR mErr; // Last libreg error code. +}; // nsRegSubtreeEnumerator + + +/*--------------------------- nsRegValueEnumerator ----------------------------- +| This class is a variation on nsRegSubtreeEnumerator that allocates | +| nsRegistryValue objects rather than nsRegistryNode objects. It also | +| overrides certain functions to make sure the "value" oriented libreg | +| functions used rather than the subtree oriented ones. | +------------------------------------------------------------------------------*/ +struct nsRegValueEnumerator : public nsRegSubtreeEnumerator { + // Override CurrentItem to allocate nsRegistryValue objects. + nsresult CurrentItem( nsISupports **result ); + + // Override advance() to use proper NR_RegEnumEntries. + NS_IMETHOD advance(); + + // ctor/dtor + nsRegValueEnumerator( HREG hReg, RKEY rKey ); +}; // nsRegValueEnumerator + +/*------------------------------ nsRegistryNode -------------------------------- +| This class implements the nsIRegistryNode interface. Instances are | +| allocated by nsRegSubtreeEnumerator::CurrentItem. | +------------------------------------------------------------------------------*/ +struct nsRegistryNode : public nsIRegistryNode { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // This class implements the nsIRegistryNode interface functions. + NS_IMETHOD GetName( char **result ); + + // ctor + nsRegistryNode( HREG hReg, RKEY key, REGENUM slot ); + +protected: + HREG mReg; // Handle to registry this node is part of. + RKEY mKey; // Key this node is under. + REGENUM mEnum; // Copy of corresponding content of parent enumerator. + REGERR mErr; // Last libreg error code. + char mName[MAXREGPATHLEN]; // Buffer to hold name. +}; // nsRegistryNode + + +/*------------------------------ nsRegistryValue ------------------------------- +| This class implements the nsIRegistryValue interface. Instances are | +| allocated by nsRegValueEnumerator::CurrentItem. | +------------------------------------------------------------------------------*/ +struct nsRegistryValue : public nsIRegistryValue { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // This class implements the nsIRegistryValue interface functions. + NS_IMETHOD GetName( char **result ); + NS_IMETHOD GetValueType( uint32 *result ); + NS_IMETHOD GetValueLength( uint32 *result ); + + // ctor + nsRegistryValue( HREG hReg, RKEY key, REGENUM slot ); + +protected: + nsresult getInfo(); // Get registry info. + HREG mReg; // Handle to registry this node is part of. + RKEY mKey; // Key this node is under. + REGENUM mEnum; // Copy of corresponding content of parent enumerator. + REGERR mErr; // Last libreg error code. + REGINFO mInfo; // Value info. + char mName[MAXREGNAMELEN]; // Buffer to hold name. +}; // nsRegistryValue + + +/*----------------------------- regerr2nsresult -------------------------------- +| This utility function maps a REGERR value to a corresponding nsresult | +| error code. | +------------------------------------------------------------------------------*/ +static nsresult regerr2nsresult( REGERR err ) { + nsresult rv = NS_ERROR_UNEXPECTED; + switch( err ) { + case REGERR_OK: + rv = NS_OK; + break; + + case REGERR_FAIL: + rv = NS_ERROR_FAILURE; + break; + + case REGERR_NOMORE: + rv = NS_ERROR_REG_NO_MORE; + break; + + case REGERR_NOFIND: + rv = NS_ERROR_REG_NOT_FOUND; + break; + + case REGERR_PARAM: + case REGERR_BADTYPE: + case REGERR_BADNAME: + rv = NS_ERROR_INVALID_ARG; + break; + + case REGERR_NOFILE: + rv = NS_ERROR_REG_NOFILE; + break; + + case REGERR_MEMORY: + rv = NS_ERROR_OUT_OF_MEMORY; + break; + + case REGERR_BUFTOOSMALL: + rv = NS_ERROR_REG_BUFFER_TOO_SMALL; + break; + + case REGERR_NAMETOOLONG: + rv = NS_ERROR_REG_NAME_TOO_LONG; + break; + + case REGERR_NOPATH: + rv = NS_ERROR_REG_NO_PATH; + break; + + case REGERR_READONLY: + rv = NS_ERROR_REG_READ_ONLY; + break; + + case REGERR_BADUTF8: + rv = NS_ERROR_REG_BAD_UTF8; + break; + + } + return rv; +} + +/*----------------------------- reginfo2DataType ------------------------------- +| This utility function converts the type field in the REGINFO structure to | +| the corresponding nsIRegistry::DataType value. | +------------------------------------------------------------------------------*/ +static void reginfo2DataType( const REGINFO &in, uint32 &out ) { + // Transfer information, based on entry type. + switch( in.entryType ) { + case REGTYPE_ENTRY_STRING_UTF: + out = nsIRegistry::String; + //out.length = in.entryLength; + break; + + case REGTYPE_ENTRY_INT32_ARRAY: + out = nsIRegistry::Int32; + // Convert length in bytes to array dimension. + //out.length = in.entryLength / sizeof(int32); + break; + + case REGTYPE_ENTRY_BYTES: + out = nsIRegistry::Bytes; + //out.length = in.entryLength; + break; + + case REGTYPE_ENTRY_FILE: + out = nsIRegistry::File; + //out.length = in.entryLength; + break; + } +} + +/*----------------------------- reginfo2DataType ------------------------------- +| This utility function converts the length field in the REGINFO structure to | +| the proper units (if type==Int32 array, we divide by sizeof(int32)). | +------------------------------------------------------------------------------*/ +static void reginfo2Length( const REGINFO &in, uint32 &out ) { + // Transfer information, based on entry type. + switch( in.entryType ) { + case REGTYPE_ENTRY_STRING_UTF: + out = in.entryLength; + break; + + case REGTYPE_ENTRY_INT32_ARRAY: + // Convert length in bytes to array dimension. + out = in.entryLength / sizeof(int32); + break; + + case REGTYPE_ENTRY_BYTES: + out = in.entryLength; + break; + + case REGTYPE_ENTRY_FILE: + out = in.entryLength; + break; + } +} + +/*----------------------------------- IIDs ------------------------------------- +| Static IID values for each imterface implemented here; required by the | +| NS_IMPL_ISUPPORTS macro. | +------------------------------------------------------------------------------*/ +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIRegistryIID, NS_IREGISTRY_IID); +static NS_DEFINE_IID(kIRegistryNodeIID, NS_IREGISTRYNODE_IID); +static NS_DEFINE_IID(kIRegistryValueIID, NS_IREGISTRYVALUE_IID); + +static NS_DEFINE_IID(kIEnumeratorIID, NS_IENUMERATOR_IID); + +static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); + +/*------------------------ nsISupports Implementation -------------------------- +| This code generates the implementation of the nsISupports member functions | +| for each class implemented in this file. | +------------------------------------------------------------------------------*/ +NS_IMPL_ISUPPORTS( nsRegistry, kIRegistryIID ); +NS_IMPL_ISUPPORTS( nsRegSubtreeEnumerator, kIEnumeratorIID ); +NS_IMPL_ISUPPORTS( nsRegistryNode, kIRegistryNodeIID ); +NS_IMPL_ISUPPORTS( nsRegistryValue, kIRegistryValueIID ); + +/*-------------------------- nsRegistry::nsRegistry ---------------------------- +| Vanilla nsRegistry constructor. The first time called, it does | +| NR_StartupRegistry. | +------------------------------------------------------------------------------*/ +nsRegistry::nsRegistry() + : mReg( 0 ) { + NS_INIT_REFCNT(); + + // Ensure libreg is started. + static PRBool libregStarted = PR_FALSE; + if( !libregStarted ) { + NR_StartupRegistry(); + libregStarted = PR_TRUE; + } + + return; +} + +/*------------------------- nsRegistry::~nsRegistry ---------------------------- +| The dtor closes the registry file(if open). | +------------------------------------------------------------------------------*/ +nsRegistry::~nsRegistry() { + if( mReg ) { + Close(); + } + return; +} + +/*----------------------------- nsRegistry::Open ------------------------------- +| If the argument is null, delegate to OpenDefault, else open the registry | +| file. We first check to see if a registry file is already open and close | +| it if so. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::Open( const char *regFile ) { + // Check for default. + if( !regFile ) { + return OpenDefault(); + } + // Ensure existing registry is closed. + Close(); + // Open specified registry. + mErr = NR_RegOpen((char*)regFile, &mReg ); + // Convert the result. + return regerr2nsresult( mErr ); +} + +/*-------------------------- nsRegistry::OpenDefault --------------------------- +| Open the "default" registry; in the case of this libreg-based implementation | +| that is done by passing a null file name pointer to NR_RegOpen. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::OpenDefault() { + // Ensure existing registry is closed. + Close(); + // Open default registry. + mErr = NR_RegOpen( 0, &mReg ); + // Convert the result. + return regerr2nsresult( mErr ); +} + +/*----------------------------- nsRegistry::Close ------------------------------ +| Tests the mReg handle and if non-null, closes the registry via NR_RegClose. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::Close() { + mErr = REGERR_OK; + if( mReg ) { + mErr = NR_RegClose( mReg ); + mReg = 0; + } + return regerr2nsresult( mErr ); +} + +/*--------------------------- nsRegistry::GetString ---------------------------- +| First, look for the entry using GetValueInfo. If found, and it's a string, | +| allocate space for it and fetch the value. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetString( Key baseKey, const char *path, char **result ) { + nsresult rv = NS_OK; + // Make sure caller gave us place for result. + if( result ) { + *result = 0; // Clear result. + + // Get info about the requested entry. + uint32 type, length; + rv = GetValueType( baseKey, path, &type ); + if ( rv == NS_OK ) { + rv = GetValueLength( baseKey, path, &length ); + } + // See if that worked. + if( rv == NS_OK ) { + // Make sure the entry is a string. + if( type == String ) { + // Allocate space for result. + *result =(char*)PR_Malloc( length + 1 ); + if( *result ) { + // Get string from registry into result buffer. + mErr = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, *result, length+1 ); + // Convert status. + rv = regerr2nsresult( mErr ); + // Test result. + if( rv != NS_OK ) { + // Didn't get result, free buffer. + PR_Free( *result ); + *result = 0; + } + } else { + // Couldn't allocate buffer. + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + // They asked for the wrong type of value. + rv = regerr2nsresult( REGERR_BADTYPE ); + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*--------------------------- nsRegistry::SetString ---------------------------- +| Simply sets the registry contents using NR_RegSetEntryString. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetString( Key baseKey, const char *path, const char *value ) { + nsresult rv = NS_OK; + // Set the contents. + mErr = NR_RegSetEntryString( mReg,(RKEY)baseKey,(char*)path,(char*)value ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*---------------------------- nsRegistry::GetInt ------------------------------ +| This function is just shorthand for fetching a 1-element int32 array. We | +| implement it "manually" using NR_RegGetEntry(versus calling GetIntArray) | +| to save allocating a copy of the result. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetInt( Key baseKey, const char *path, int32 *result ) { + nsresult rv = NS_OK; + + // Make sure caller gave us place for result. + if( result ) { + // Get info about the requested entry. + uint32 type; + rv = GetValueType( baseKey, path, &type ); + // See if that worked. + if( rv == NS_OK ) { + // Make sure the entry is an int32 array. + if( type == Int32 ) { + uint32 len = sizeof *result; + // Get int from registry into result field. + mErr = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path, result, &len ); + // Convert status. + rv = regerr2nsresult( mErr ); + } else { + // They asked for the wrong type of value. + rv = NS_ERROR_REG_BADTYPE; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------------- nsRegistry::SetInt ------------------------------ +| Write out the value as a one-element int32 array, using NR_RegSetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetInt( Key baseKey, const char *path, int32 value ) { + nsresult rv = NS_OK; + // Set the contents. + mErr = NR_RegSetEntry( mReg, + (RKEY)baseKey, + (char*)path, + REGTYPE_ENTRY_INT32_ARRAY, + &value, + sizeof value ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*--------------------------- nsRegistry::GetBytes ----------------------------- +| Get the registry contents at specified location using NR_RegGetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetBytes( Key baseKey, const char *path, void **result, uint32 *len ) { + nsresult rv = NS_OK; + + // Make sure caller gave us place for result. + if( result && len ) { + // Get info about the requested entry. + uint32 type; + rv = GetValueType( baseKey, path, &type ); + // See if that worked. + if( rv == NS_OK ) { + // Make sure the entry is bytes. + if( type == Bytes ) { + // Get bytes from registry into result field. + mErr = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path, result, len ); + // Convert status. + rv = regerr2nsresult( mErr ); + } else { + // They asked for the wrong type of value. + rv = NS_ERROR_REG_BADTYPE; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*--------------------------- nsRegistry::SetBytes ----------------------------- +| Set the contents at the specified registry location, using NR_RegSetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetBytes( Key baseKey, const char *path, void *value, uint32 len ) { + nsresult rv = NS_OK; + // Set contents. + mErr = NR_RegSetEntry( mReg,(RKEY)baseKey,(char*)path, + REGTYPE_ENTRY_BYTES, value, len ); + // Convert result; + rv = regerr2nsresult( mErr ); + return rv; +} + +/*-------------------------- nsRegistry::GetIntArray --------------------------- +| Find out about the entry using GetValueInfo. We check the type and then | +| use NR_RegGetEntry to get the actual array. We have to convert from the | +| array dimension to number of bytes in the process. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetIntArray( Key baseKey, const char *path, int32 **result, uint32 *len ) { + nsresult rv = NS_OK; + + // Make sure caller gave us place for result. + if( result && len ) { + // Get info about the requested entry. + uint32 type, length; + rv = GetValueType( baseKey, path, &type ); + if ( rv == NS_OK ) { + rv = GetValueLength( baseKey, path, &length ); + } + // See if that worked. + if( rv == NS_OK ) { + // Make sure the entry is bytes. + if( type == Int32 ) { + // Allocate space for result. + *len = length * sizeof(int32); + *result =(int32*)PR_Malloc( *len ); + // Make sure that worked. + if( *result ) { + // Get array from registry into result field. + mErr = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path, *result, len ); + // Convert status. + if( mErr == REGERR_OK ) { + // Convert size in bytes to array dimension. + *len /= sizeof(int32); + } else { + rv = regerr2nsresult( mErr ); + // Free buffer that we allocated(error will tell caller not to). + PR_Free( *result ); + *result = 0; + } + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + // They asked for the wrong type of value. + rv = NS_ERROR_REG_BADTYPE; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*-------------------------- nsRegistry::SetIntArray --------------------------- +| Store the given integer array at the given point in the registry. The | +| length given is the size of the array, we have to convert that to the | +| size in bytes in order to use NR_RegSetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetIntArray( Key baseKey, const char *path, const int32 *value, uint32 len ) { + nsresult rv = NS_OK; + // Convert array dimension to byte count. + uint32 size = len * sizeof(int32); + // Set contents. + mErr = NR_RegSetEntry( mReg,(RKEY)baseKey,(char*)path, + REGTYPE_ENTRY_INT32_ARRAY,(void*)value, size ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*-------------------------- nsRegistry::AddSubtree ---------------------------- +| Add a new registry subkey with the specified name, using NR_RegAddKey. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::AddSubtree( Key baseKey, const char *path, Key *result ) { + nsresult rv = NS_OK; + // Add the subkey. + mErr = NR_RegAddKey( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*------------------------- nsRegistry::RemoveSubtree -------------------------- +| Deletes the subtree at a given location using NR_RegDeleteKey. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::RemoveSubtree( Key baseKey, const char *path ) { + nsresult rv = NS_OK; + // Delete the subkey. + mErr = NR_RegDeleteKey( mReg,(RKEY)baseKey,(char*)path ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*-------------------------- nsRegistry::GetSubtree ---------------------------- +| Returns a nsIRegistry::Key(RKEY) for a given key/path. The key is | +| obtained using NR_RegGetKey. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetSubtree( Key baseKey, const char *path, Key *result ) { + nsresult rv = NS_OK; + // Make sure we have a place for the result. + if( result ) { + // Get key. + mErr = NR_RegGetKey( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result ); + // Convert result. + rv = regerr2nsresult( mErr ); + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*----------------------- nsRegistry::EnumerateSubtrees ------------------------ +| Allocate a nsRegSubtreeEnumerator object and return it to the caller. | +| We construct the enumerator using the registry handle from this registry | +| object, the user-specified registry key, and indicate that we don't want | +| to recurse down subtrees. No libreg functions are invoked at this point | +|(that will happen when the enumerator member functions are called). | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::EnumerateSubtrees( Key baseKey, nsIEnumerator **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + *result = new nsRegSubtreeEnumerator( mReg,(RKEY)baseKey, PR_FALSE ); + // Check for success. + if( *result ) { + // Bump refcnt on behalf of caller. + (*result)->AddRef(); + } else { + // Unable to allocate space for the enumerator object. + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*--------------------- nsRegistry::EnumerateAllSubtrees ----------------------- +| Same as EnumerateSubtrees but we pass PR_TRUE to request that the | +| enumerator object descend subtrees when it is used. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::EnumerateAllSubtrees( Key baseKey, nsIEnumerator **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + *result = new nsRegSubtreeEnumerator( mReg,(RKEY)baseKey, PR_TRUE ); + // Check for success. + if( *result ) { + // Bump refcnt on behalf of caller. + (*result)->AddRef(); + } else { + // Unable to allocate space for the enumerator object. + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*------------------------- nsRegistry::GetValueType --------------------------- +| Gets the type from the registry using the NR_GetEntryInfo libreg API. | +| The result is transferred to the uint32 value passed in (with conversion | +| to the appropriate nsIRegistry::DataType value). | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetValueType( Key baseKey, const char *path, uint32 *result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + // Get registry info into local structure. + REGINFO info = { sizeof info, 0, 0 }; + mErr = NR_RegGetEntryInfo( mReg,(RKEY)baseKey,(char*)path, &info ); + if( mErr == REGERR_OK ) { + // Copy info to user's result value. + reginfo2DataType( info, *result ); + } else { + rv = regerr2nsresult( mErr ); + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*------------------------ nsRegistry::GetValueLength -------------------------- +| Gets the registry value info via NR_RegGetEntryInfo. The length is | +| converted to the proper "units" via reginfo2Length. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetValueLength( Key baseKey, const char *path, uint32 *result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + // Get registry info into local structure. + REGINFO info = { sizeof info, 0, 0 }; + mErr = NR_RegGetEntryInfo( mReg,(RKEY)baseKey,(char*)path, &info ); + if( mErr == REGERR_OK ) { + // Copy info to user's result value. + reginfo2Length( info, *result ); + } else { + rv = regerr2nsresult( mErr ); + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*------------------------ nsRegistry::EnumerateValues ------------------------- +| Allocates and returns an instance of nsRegValueEnumerator constructed in | +| a similar fashion as the nsRegSubtreeEnumerator is allocated/returned by | +| EnumerateSubtrees. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::EnumerateValues( Key baseKey, nsIEnumerator **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + *result = new nsRegValueEnumerator( mReg,(RKEY)baseKey ); + // Check for success. + if( *result ) { + // Bump refcnt on behalf of caller. + (*result)->AddRef(); + } else { + // Unable to allocate space for the enumerator object. + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------- nsRegistry::GetCurrentUserName ------------------------ +| Simple wrapper for NR_RegGetUsername. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetCurrentUserName( char **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + // Get the user name. + mErr = NR_RegGetUsername( result ); + // Convert the result. + rv = regerr2nsresult( mErr ); + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------- nsRegistry::SetCurrentUserName ------------------------ +| Simple wrapper for NR_RegSetUsername. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetCurrentUserName( const char *name ) { + nsresult rv = NS_OK; + // Set the user name. + mErr = NR_RegSetUsername( name ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*----------------------------- nsRegistry::Pack ------------------------------- +| Simple wrapper for NR_RegPack. We don't set up any callback. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::Pack() { + nsresult rv = NS_OK; + // Pack the registry. + mErr = NR_RegPack( mReg, 0, 0 ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*-------------- nsRegSubtreeEnumerator::nsRegSubtreeEnumerator ---------------- +| The ctor simply stashes all the information that will be needed to enumerate | +| the subkeys. | +------------------------------------------------------------------------------*/ +nsRegSubtreeEnumerator::nsRegSubtreeEnumerator( HREG hReg, RKEY rKey, PRBool all ) + : mReg( hReg ), mKey( rKey ), mEnum( 0 ), mNext( 0 ), + mStyle( all ? REGENUM_DESCEND : 0 ), mDone( PR_FALSE ), mErr( -1 ) { + NS_INIT_REFCNT(); + return; +} + +/*----------------------- nsRegSubtreeEnumerator::First ------------------------ +| Set mEnum to 0; this will cause the next NR_RegEnum call to go to | +| the beginning. We then do a Next() call in order to do a "lookahead" to | +| properly detect an empty list (i.e., set the mDone flag). | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::First() { + nsresult rv = NS_OK; + // Reset "done" flag. + mDone = PR_FALSE; + // Go to beginning. + mEnum = mNext = 0; + // Lookahead so mDone flag gets set for empty list. + rv = Next(); + return rv; +} + +/*----------------------- nsRegSubtreeEnumerator::Last ------------------------- +| This can't be implemented using the libreg functions. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::Last() { + nsresult rv = NS_ERROR_NOT_IMPLEMENTED; + return rv; +} + +/*----------------------- nsRegSubtreeEnumerator::Next ------------------------- +| First, we check if we've already advanced to the end by checking the mDone | +| flag. | +| | +| We advance mEnum to the next enumeration value which is in the mNext | +| lookahead buffer. We must then call advance to lookahead and properly set | +| the isDone flag. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::Next() { + nsresult rv = NS_OK; + // Check for at end. + if ( !mDone ) { + // Advance to next spot. + mEnum = mNext; + // Lookahead so mDone is properly set (and to update mNext). + rv = advance(); + } else { + // Set result accordingly. + rv = regerr2nsresult( REGERR_NOMORE ); + } + return rv; +} + +/*---------------------- nsRegSubtreeEnumerator::advance ----------------------- +| Advance mNext to next subkey using NR_RegEnumSubkeys. We set mDone if | +| there are no more subkeys. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegSubtreeEnumerator::advance() { + char name[MAXREGPATHLEN]; + uint32 len = sizeof name; + mErr = NR_RegEnumSubkeys( mReg, mKey, &mNext, name, len, mStyle ); + // See if we ran off end. + if( mErr == REGERR_NOMORE ) { + // Remember we've run off end. + mDone = PR_TRUE; + } + // Convert result. + nsresult rv = regerr2nsresult( mErr ); + return rv; +}; + +/*----------------------- nsRegSubtreeEnumerator::Prev ------------------------- +| This can't be implemented on top of libreg. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::Prev() { + nsresult rv = NS_ERROR_NOT_IMPLEMENTED; + return rv; +} + +/*-------------------- nsRegSubtreeEnumerator::CurrentItem --------------------- +| Allocates and returns a new instance of class nsRegistryNode. The node | +| object will hold the curent mEnum value so it can obtain its name from | +| the registry when asked. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::CurrentItem( nsISupports **result) { + nsresult rv = NS_OK; + // Make sure there is a place to put the result. + if( result ) { + *result = new nsRegistryNode( mReg, mKey, mEnum ); + if( *result ) { + (*result)->AddRef(); + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------- nsRegSubtreeEnumerator::IsDone ------------------------ +| Simply return mDone. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::IsDone() { + nsresult rv = mDone; + return rv; +} + + +/*---------------- nsRegValueEnumerator::nsRegValueEnumerator ------------------ +| Delegates everything to the base class constructor. | +------------------------------------------------------------------------------*/ +nsRegValueEnumerator::nsRegValueEnumerator( HREG hReg, RKEY rKey ) + : nsRegSubtreeEnumerator( hReg, rKey, PR_FALSE ) { + return; +} + + +/*--------------------- nsRegValueEnumerator::CurrentItem ---------------------- +| As the nsRegSubtreeEnumerator counterpart, but allocates an object of | +| class nsRegistryValue. | +------------------------------------------------------------------------------*/ +nsresult nsRegValueEnumerator::CurrentItem( nsISupports **result ) { + nsresult rv = NS_OK; + // Make sure there is a place to put the result. + if( result ) { + *result = new nsRegistryValue( mReg, mKey, mEnum ); + if( *result ) { + (*result)->AddRef(); + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*----------------------- nsRegValueEnumerator::advance ------------------------ +| Advance mNext to next subkey using NR_RegEnumEntries. We set mDone if | +| there are no more entries. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegValueEnumerator::advance() { + char name[MAXREGNAMELEN]; + uint32 len = sizeof name; + REGINFO info = { sizeof info, 0, 0 }; + mErr = NR_RegEnumEntries( mReg, mKey, &mNext, name, len, &info ); + // See if we ran off end. + if( mErr == REGERR_NOMORE ) { + // Remember we've run off end. + mDone = PR_TRUE; + } + // Convert result. + nsresult rv = regerr2nsresult( mErr ); + return rv; +}; + + +/*---------------------- nsRegistryNode::nsRegistryNode ------------------------ +| Store the arguments in the corresponding data members and initialize | +| the other data members. We defer the libreg calls till we're asked for | +| our name. We use mErr==-1 to indicate we haven't fetched the name yet. | +------------------------------------------------------------------------------*/ +nsRegistryNode::nsRegistryNode( HREG hReg, RKEY key, REGENUM slot ) + : mReg( hReg ), mKey( key ), mEnum( slot ), mErr( -1 ) { + NS_INIT_REFCNT(); + return; +} + + +/*-------------------------------- PR_strdup ----------------------------------- +| Utility function that does PR_Malloc and copies argument string. Caller | +| must do PR_Free. | +------------------------------------------------------------------------------*/ +static char *PR_strdup( const char *in ) { + char *result = (char*)PR_Malloc( strlen( in ) + 1 ); + if ( result ) { + strcpy( result, in ); + } + return result; +} + +/*-------------------------- nsRegistryNode::GetName --------------------------- +| If we haven't fetched it yet, get the name of the corresponding subkey now, | +| using NR_RegEnumSubkeys. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistryNode::GetName( char **result ) { + nsresult rv = NS_OK; + // Make sure there is a place to put the result. + if( result ) { + // Test whether we haven't tried to get it yet. + if( mErr == -1 ) { + REGENUM temp = mEnum; + // Get name. + mErr = NR_RegEnumSubkeys( mReg, mKey, &temp, mName, sizeof mName, PR_FALSE ); + } + // Convert result from prior libreg call. + rv = regerr2nsresult( mErr ); + if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) { + // worked, return actual result. + *result = PR_strdup( mName ); + if ( *result ) { + rv = NS_OK; + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + + + +/*--------------------- nsRegistryValue::nsRegistryValue ----------------------- +| Implemented the same way as the nsRegistryNode ctor. | +------------------------------------------------------------------------------*/ +nsRegistryValue::nsRegistryValue( HREG hReg, RKEY key, REGENUM slot ) + : mReg( hReg ), mKey( key ), mEnum( slot ), mErr( -1 ) { + NS_INIT_REFCNT(); + return; +} + +/*------------------------- nsRegistryValue::GetName --------------------------- +| See nsRegistryNode::GetName; we use NR_RegEnumEntries in this case. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistryValue::GetName( char **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + // Ensure we've got the info we need. + rv = getInfo(); + if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) { + // worked, return actual result. + *result = PR_strdup( mName ); + if ( *result ) { + rv = NS_OK; + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*----------------------- nsRegistryValue::GetValueType ------------------------ +| We test if we've got the info already. If not, we git it by calling | +| getInfo. We calculate the result by converting the REGINFO type field to | +| a nsIRegistry::DataType value (using reginfo2DataType). | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistryValue::GetValueType( uint32 *result ) { + nsresult rv = NS_OK; + // Make sure we have room for th result. + if( result ) { + // Make sure we've got the info we need. + rv = getInfo(); + // Check if it worked. + if( rv == NS_OK ) { + // Convert result from REGINFO to nsIRegistry::ValueInfo. + reginfo2DataType( mInfo, *result ); + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------- nsRegistryValue::GetValueLength ----------------------- +| We test if we've got the info already. If not, we git it by calling | +| getInfo. We calculate the result by converting the REGINFO type field to | +| a nsIRegistry::DataType value (using reginfo2Length). | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistryValue::GetValueLength( uint32 *result ) { + nsresult rv = NS_OK; + // Make sure we have room for th result. + if( result ) { + // Make sure we've got the info we need. + rv = getInfo(); + // Check if it worked. + if( rv == NS_OK ) { + // Convert result from REGINFO to length. + reginfo2Length( mInfo, *result ); + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*------------------------- nsRegistryValue::getInfo --------------------------- +| Call NR_RegEnumEntries to set the mInfo/mName data members. | +------------------------------------------------------------------------------*/ +nsresult nsRegistryValue::getInfo() { + nsresult rv = NS_OK; + // Test whether we haven't tried to get it yet. + if( mErr == -1 ) { + REGENUM temp = mEnum; + // Get name and info. + mErr = NR_RegEnumEntries( mReg, mKey, &temp, mName, sizeof mName, &mInfo ); + // Convert result. + rv = regerr2nsresult( mErr ); + } + return rv; +} + + +nsRegistryFactory::nsRegistryFactory() { + NS_INIT_REFCNT(); +} + +NS_IMPL_ISUPPORTS(nsRegistryFactory, kIFactoryIID); + +NS_IMETHODIMP +nsRegistryFactory::CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult) { + nsresult rv = NS_OK; + nsRegistry* newRegistry; + + if(aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } else { + *aResult = NULL; + } + + if(0 != aOuter) { + return NS_ERROR_NO_AGGREGATION; + } + + NS_NEWXPCOM(newRegistry, nsRegistry); + + if(newRegistry == NULL) { + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(newRegistry); + rv = newRegistry->QueryInterface(aIID, aResult); + NS_RELEASE(newRegistry); + + return rv; +} + +nsresult +nsRegistryFactory::LockFactory(PRBool aLock) +{ + // Not implemented in simplest case. + return NS_OK; +} + +// This is a temporary hack; needs work to support dynamic binding +// via nsRepository and support for multiple factories per DLL. +extern "C" NS_EXPORT nsresult +nsRegistry_GetFactory(const nsCID &cid, nsISupports* servMgr, nsIFactory** aFactory ) { + nsresult rv = NS_OK; + + if( aFactory == 0 ) { + return NS_ERROR_NULL_POINTER; + } else { + *aFactory = 0; + } + + nsIFactory* inst = new nsRegistryFactory(); + if(0 == inst) { + rv = NS_ERROR_OUT_OF_MEMORY; + } else { + NS_ADDREF(inst); + *aFactory = inst; + } + + return rv; +} diff --git a/xpcom/base/nsError.h b/xpcom/base/nsError.h index 862d723197a..1c22f321b1b 100644 --- a/xpcom/base/nsError.h +++ b/xpcom/base/nsError.h @@ -63,6 +63,7 @@ typedef PRUint32 nsresult; #define NS_ERROR_MODULE_HTMLPARSER 9 #define NS_ERROR_MODULE_RDF 10 #define NS_ERROR_MODULE_UCONV 11 +#define NS_ERROR_MODULE_REG 12 #define NS_ERROR_MODULE_MAILNEWS 16 diff --git a/xpcom/components/nsIRegistry.h b/xpcom/components/nsIRegistry.h new file mode 100644 index 00000000000..a78ee4bb377 --- /dev/null +++ b/xpcom/components/nsIRegistry.h @@ -0,0 +1,326 @@ +/* -*- 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.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#ifndef __nsIRegistry_h +#define __nsIRegistry_h + +#include "nsISupports.h" + +class nsIEnumerator; + +/*-------------------------------- nsIRegistry --------------------------------- +| This interface provides access to a tree of arbitrary values. | +| | +| Each node of the tree contains either a value or a subtree or both. | +| | +| The value at any of these leaf nodes can be any of these "primitive" types: | +| o string (null terminated UTF string) | +| o array of 32-bit integers | +| o arbitrary array of bytes | +| o file identifier | +| Of course, since you can store an arbitrary array of bytes, you can put | +| any data you like into a registry (although you have the burden of | +| encoding/decoding your data in that case). | +| | +| Each branch of the tree is labelled with a string "key." The entire path | +| from a given point of the tree to another point further down can be | +| presented as a single string composed of each branch's label, concatenated | +| to the next, with an intervening forward slash ('/'). The term "key" | +| refers to both specific tree branch labels and to such concatenated paths. | +| | +| The branches from a given node must have unique labels. Distinct nodes can | +| have branches with the same label. | +| | +| For example, here's a small registry tree: | +| | | +| /\ | +| / \ | +| / \ | +| / \ | +| "Classes" "Users" | +| / \ | +| / \ | +| / ["joe"] | +| / / \ | +| | / \ | +| /\ / \ | +| / \ "joe" "bob" | +| / \ / \ | +| / \ | +| "{xxxx-xx-1}" "{xxxx-xx-2}" ["c:/joe"] ["d:/Robert"] | +| | | | +| /\ /\ | +| / \ / \ | +| / \ / \ | +| "Library" "Version" "Library" "Version" | +| / \ / \ | +| ["foo.dll"] 2 ["bar.dll"] 1 | +| | +| In this example, there are 2 keys under the root: "Classes" and "Users". | +| The first denotes a subtree only (which has two subtrees, ...). The second | +| denotes both a value ["joe"] and two subtrees labelled "joe" and "bob". | +| The value at the node "/Users" is ["joe"], at "/Users/bob" is ["d:/Robert"]. | +| The value at "/Classes/{xxxx-xx-1}/Version" is 2. | +| | +| The registry interface provides functions that let you navigate the tree | +| and manipulate it's contents. | +| | +| Please note that the registry itself does not impose any structure or | +| meaning on the contents of the tree. For example, the registry doesn't | +| control whether the value at the key "/Users" is the label for the subtree | +| with information about the last active user. That meaning is applied by | +| the code that stores these values and uses them for that purpose. | +| | +| [Any resemblence between this example and actual contents of any actual | +| registry is purely coincidental.] | +------------------------------------------------------------------------------*/ +struct nsIRegistry : public nsISupports { + /*------------------------------ Constants --------------------------------- + | The following enumerated types and values are used by the registry | + | interface. | + --------------------------------------------------------------------------*/ + typedef enum { + String = 1, + Int32, + Bytes, + File + } DataType; + + /*-------------------------------- Types ----------------------------------- + | The following data types are used by this interface. All are basically | + | opaque types. You obtain objects of these types via certain member | + | function calls and re-use them later (without having to know what they | + | contain). | + | | + | Key - Placeholder to represent a particular node in a registry | + | tree. There are 3 enumerated values that correspond to | + | specific nodes: | + | Common - Where most stuff goes. | + | Users - Special subtree to hold info about | + | "users"; if you don't know what goes | + | here, don't mess with it. | + | CurrentUser - Subtree under Users corresponding to | + | whatever user is designed the "current" | + | one; see note above. | + | You can specify any of these enumerated values as "keys" | + | on any member function that takes a nsRegistry::Key. | + | ValueInfo - Structure describing a registry value. | + --------------------------------------------------------------------------*/ + typedef uint32 Key; + + enum { Users = 1, Common = 2, CurrentUser = 3 }; + + struct ValueInfo { + DataType type; + uint32 length; + }; + + /*--------------------------- Opening/Closing ------------------------------ + | These functions open the specified registry file (Open() with a non-null | + | argument) or the default "standard" registry file (Open() with a null | + | argument or OpenDefault()). | + | | + | Once opened, you can access the registry contents via the read/write | + | or query functions. | + | | + | The registry file will be closed automatically when the registry object | + | is destroyed. You can close the file prior to that by using the | + | Close() function. | + --------------------------------------------------------------------------*/ + NS_IMETHOD Open( const char *regFile = 0 ) = 0; + NS_IMETHOD OpenDefault() = 0; + NS_IMETHOD Close() = 0; + + /*----------------------- Reading/Writing Values --------------------------- + | These functions read/write the registry values at a given node. | + | | + | All functions require you to specify where in the registry key to | + | get/set the value. The location is specified using two components: | + | o A "base key" indicating where to start from; this is a value of type | + | nsIRegistry::Key. You use either one of the special "root" key | + | values or a subkey obtained via some other member function call. | + | o A "relative path," expressed as a sequence of subtree names | + | separated by forward slashes. This path describes how to get from | + | the base key to the node at which you want to store the data. This | + | component can be a null pointer which means the value goes directly | + | at the node denoted by the base key. | + | | + | When you request a value of a given type, the data stored at the | + | specified node must be of the type requested. If not, an error results. | + | | + | GetString - Obtains a newly allocated copy of a string type value. The | + | caller is obligated to free the returned string using | + | PR_Free. | + | SetString - Stores the argument string at the specified node. | + | GetInt - Obtains an int32 value at the specified node. The result | + | is returned into an int32 location you specify. | + | SetInt - Stores a given int32 value at a node. | + | GetBytes - Obtains a byte array value; this returns both an allocated | + | array of bytes and a length (necessary because there may be | + | embedded null bytes in the array). You must free the | + | resulting array using PR_Free. | + | SetBytes - Stores a given array of bytes; you specify the bytes via a | + | pointer and a length. | + | GetIntArray - Obtains the array of int32 values stored at a given node. | + | The result is composed of two values: a pointer to an | + | array of integer values (which must be freed using | + | PR_Free) and the number of elements in that array. | + | SetIntArray - Stores a set of int32 values at a given node. You must | + | provide a pointer to the array and the number of entries. | + --------------------------------------------------------------------------*/ + NS_IMETHOD GetString( Key baseKey, const char *path, char **result ) = 0; + NS_IMETHOD SetString( Key baseKey, const char *path, const char *value ) = 0; + NS_IMETHOD GetInt( Key baseKey, const char *path, int32 *result ) = 0; + NS_IMETHOD SetInt( Key baseKey, const char *path, int32 value ) = 0; + NS_IMETHOD GetBytes( Key baseKey, const char *path, void **result, uint32 *len ) = 0; + NS_IMETHOD SetBytes( Key baseKey, const char *path, void *value, uint32 len ) = 0; + NS_IMETHOD GetIntArray( Key baseKey, const char *path, int32 **result, uint32 *len ) = 0; + NS_IMETHOD SetIntArray( Key baseKey, const char *path, const int32 *value, uint32 len ) = 0; + + /*------------------------------ Navigation -------------------------------- + | These functions let you navigate through the registry tree, querying | + | its contents. | + | | + | As above, all these functions requires a starting tree location ("base | + | key") specified as a nsIRegistry::Key. Some also require a path | + | name to locate the registry node location relative to this base key. | + | | + | AddSubtree - Adds a new registry subtree at the specified | + | location. Returns the resulting key in | + | the location specified by the third argument | + | (unless that pointer is 0). | + | RemoveNode - Removes the specified registry subtree or | + | value at the specified location. | + | GetSubtree - Returns a nsIRegistry::Key that can be used | + | to refer to the specified registry location. | + | EnumerateSubtrees - Returns a nsIEnumerator object that you can | + | use to enumerate all the subtrees descending | + | from a specified location. You must free the | + | enumerator via Release() when you're done with | + | it. | + | EnumerateAllSubtrees - Like EnumerateSubtrees, but will recursively | + | enumerate lower-level subtrees, too. | + | GetValueInfo - Returns a uint32 value that designates the type | + | of data stored at this location in the registry; | + | the possible values are defined by the enumerated | + | type nsIRegistry::DataType. | + | GetValueLength - Returns a uint32 value that indicates the length | + | of this registry value; the length is the number | + | of characters (for Strings), the number of bytes | + | (for Bytes), or the number of int32 values (for | + | Int32). | + | EnumerateValues - Returns a nsIEnumerator that you can use to | + | enumerate all the value nodes descending from | + | a specified location. | + --------------------------------------------------------------------------*/ + NS_IMETHOD AddSubtree( Key baseKey, const char *path, Key *result ) = 0; + NS_IMETHOD RemoveSubtree( Key baseKey, const char *path ) = 0; + NS_IMETHOD GetSubtree( Key baseKey, const char *path, Key *result ) = 0; + + NS_IMETHOD EnumerateSubtrees( Key baseKey, nsIEnumerator **result ) = 0; + NS_IMETHOD EnumerateAllSubtrees( Key baseKey, nsIEnumerator **result ) = 0; + + NS_IMETHOD GetValueType( Key baseKey, const char *path, uint32 *result ) = 0; + NS_IMETHOD GetValueLength( Key baseKey, const char *path, uint32 *result ) = 0; + + NS_IMETHOD EnumerateValues( Key baseKey, nsIEnumerator **result ) = 0; + + /*------------------------------ User Name --------------------------------- + | These functions manipulate the current "user name." This value controls | + | the behavior of certain registry functions (namely, ?). | + | | + | GetCurrentUserName allocates a copy of the current user name (which the | + | caller should free using PR_Free). | + --------------------------------------------------------------------------*/ + NS_IMETHOD GetCurrentUserName( char **result ) = 0; + NS_IMETHOD SetCurrentUserName( const char *name ) = 0; + + /*------------------------------ Utilities --------------------------------- + | Various utility functions: | + | | + | Pack() is used to compress the contents of an open registry file. | + --------------------------------------------------------------------------*/ + NS_IMETHOD Pack() = 0; + +}; // nsIRegistry + +/*------------------------------ nsIRegistryNode ------------------------------- +| This interface is implemented by all the objects obtained from the | +| nsIEnumerators that nsIRegistry provides when you call either of the | +| subtree enumeration functions EnumerateSubtrees or EnumerateAllSubtrees. | +| | +| You can call this function to get the name of this subtree. This is the | +| relative path from the base key from which you got this interface. | +| | +| GetName - Returns the path name of this node; this is the relative path | +| from the base key from which this subtree was obtained. The | +| function allocates a copy of the name; the caller must free it | +| using PR_Free. | +------------------------------------------------------------------------------*/ +struct nsIRegistryNode : public nsISupports { + NS_IMETHOD GetName( char **result ) = 0; +}; // nsIRegistryNode + +/*------------------------------ nsIRegistryValue ------------------------------ +| This interface is implemented by the objects obtained from the | +| nsIEnumerators that nsIRegistry provides when you call the | +| EnumerateValues function. An object supporting this interface is | +| returned when you call the CurrentItem() function on that enumerator. | +| | +| You use the member functions of this interface to obtain information | +| about each registry value. | +| | +| GetName - Returns the path name of this node; this is the relative | +| path\ from the base key from which this value was obtained. | +| The function allocates a copy of the name; the caller must | +| subsequently free it via PR_Free. | +| GetValueType - Returns (into a location provided by the caller) the type | +| of the value; the types are defined by the enumerated | +| type nsIRegistry::DataType. | +| GetValueLength - Returns a uint32 value that indicates the length | +| of this registry value; the length is the number | +| of characters (for Strings), the number of bytes | +| (for Bytes), or the number of int32 values (for | +| Int32). | +------------------------------------------------------------------------------*/ +struct nsIRegistryValue : public nsISupports { + NS_IMETHOD GetName( char **result ) = 0; + NS_IMETHOD GetValueType( uint32 *result ) = 0; + NS_IMETHOD GetValueLength( uint32 *result ) = 0; +}; // nsIRegistryEntry + + +/*------------------------------- Error Codes ---------------------------------- +------------------------------------------------------------------------------*/ +#define NS_ERROR_REG_BADTYPE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 1 ) +#define NS_ERROR_REG_NO_MORE NS_ERROR_GENERATE_SUCCESS( NS_ERROR_MODULE_REG, 2 ) +#define NS_ERROR_REG_NOT_FOUND NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 3 ) +#define NS_ERROR_REG_NOFILE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 4 ) +#define NS_ERROR_REG_BUFFER_TOO_SMALL NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 5 ) +#define NS_ERROR_REG_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 6 ) +#define NS_ERROR_REG_NO_PATH NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 7 ) +#define NS_ERROR_REG_READ_ONLY NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 8 ) +#define NS_ERROR_REG_BAD_UTF8 NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 9 ) + +// {5D41A440-8E37-11d2-8059-00600811A9C3} +#define NS_IREGISTRY_IID { 0x5d41a440, 0x8e37, 0x11d2, { 0x80, 0x59, 0x0, 0x60, 0x8, 0x11, 0xa9, 0xc3 } } +// {D1B54831-AC07-11d2-805E-00600811A9C3} +#define NS_IREGISTRYNODE_IID { 0xd1b54831, 0xac07, 0x11d2, { 0x80, 0x5e, 0x0, 0x60, 0x8, 0x11, 0xa9, 0xc3 } } +// {5316C380-B2F8-11d2-A374-0080C6F80E4B} +#define NS_IREGISTRYVALUE_IID { 0x5316c380, 0xb2f8, 0x11d2, { 0xa3, 0x74, 0x0, 0x80, 0xc6, 0xf8, 0xe, 0x4b } } + +#endif diff --git a/xpcom/components/nsRegistry.cpp b/xpcom/components/nsRegistry.cpp new file mode 100644 index 00000000000..0d26c07efb3 --- /dev/null +++ b/xpcom/components/nsRegistry.cpp @@ -0,0 +1,1204 @@ +/* -*- 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.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "nsIRegistry.h" +#include "nsIEnumerator.h" +#include "NSReg.h" +#include "prmem.h" + +/*-------------------------------- nsRegistry ---------------------------------- +| This class implements the nsIRegistry interface using the functions | +| provided by libreg (as declared in mozilla/modules/libreg/include/NSReg.h). | +| | +| Since that interface is designed to match the libreg function, this class | +| is implemented with each member function being a simple wrapper for the | +| corresponding libreg function. | +------------------------------------------------------------------------------*/ +struct nsRegistry : public nsIRegistry { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // This class implements the nsIRegistry interface functions. + NS_IMETHOD Open( const char *regFile = 0 ); + NS_IMETHOD OpenDefault(); + NS_IMETHOD Close(); + + NS_IMETHOD GetString( Key baseKey, const char *path, char **result ); + NS_IMETHOD SetString( Key baseKey, const char *path, const char *value ); + NS_IMETHOD GetInt( Key baseKey, const char *path, int32 *result ); + NS_IMETHOD SetInt( Key baseKey, const char *path, int32 value ); + NS_IMETHOD GetBytes( Key baseKey, const char *path, void **result, uint32 *len ); + NS_IMETHOD SetBytes( Key baseKey, const char *path, void *value, uint32 len ); + NS_IMETHOD GetIntArray( Key baseKey, const char *path, int32 **result, uint32 *len ); + NS_IMETHOD SetIntArray( Key baseKey, const char *path, const int32 *value, uint32 len ); + + NS_IMETHOD AddSubtree( Key baseKey, const char *path, Key *result ); + NS_IMETHOD RemoveSubtree( Key baseKey, const char *path ); + NS_IMETHOD GetSubtree( Key baseKey, const char *path, Key *result ); + + NS_IMETHOD EnumerateSubtrees( Key baseKey, nsIEnumerator **result ); + NS_IMETHOD EnumerateAllSubtrees( Key baseKey, nsIEnumerator **result ); + + NS_IMETHOD GetValueType( Key baseKey, const char *path, uint32 *result ); + NS_IMETHOD GetValueLength( Key baseKey, const char *path, uint32 *result ); + + NS_IMETHOD EnumerateValues( Key baseKey, nsIEnumerator **result ); + + NS_IMETHOD GetCurrentUserName( char **result ); + NS_IMETHOD SetCurrentUserName( const char *name ); + + NS_IMETHOD Pack(); + + // ctor/dtor + nsRegistry(); + ~nsRegistry(); + +protected: + HREG mReg; // Registry handle. + REGERR mErr; // Last libreg error code. +}; // nsRegistry + + +#include "nsIFactory.h" +/*----------------------------- nsRegistryFactory ------------------------------ +| Class factory for nsRegistry objects. | +------------------------------------------------------------------------------*/ +struct nsRegistryFactory : public nsIFactory { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // nsIFactory methods + NS_IMETHOD CreateInstance(nsISupports *,const nsIID &,void **); + NS_IMETHOD LockFactory(PRBool aLock); + + // ctor + nsRegistryFactory(); +}; + + +/*--------------------------- nsRegSubtreeEnumerator --------------------------- +| This class implements the nsIEnumerator interface and is used to implement | +| the nsRegistry EnumerateSubtrees and EnumerateAllSubtrees functions. | +------------------------------------------------------------------------------*/ +struct nsRegSubtreeEnumerator : public nsIEnumerator { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // This class implements the nsIEnumerator interface functions. + nsresult First(); + nsresult Last(); + nsresult Next(); + nsresult Prev(); + nsresult CurrentItem(nsISupports **aItem); + nsresult IsDone(); + + // ctor/dtor + nsRegSubtreeEnumerator( HREG hReg, RKEY rKey, PRBool all ); + +protected: + NS_IMETHOD advance(); // Implementation file; does appropriate NR_RegEnum call. + HREG mReg; // Handle to registry we're affiliated with. + RKEY mKey; // Base key being enumerated. + REGENUM mEnum; // Corresponding libreg "enumerator". + REGENUM mNext; // Lookahead value. + uint32 mStyle; // Style (indicates all or some); + PRBool mDone; // Done flag. + REGERR mErr; // Last libreg error code. +}; // nsRegSubtreeEnumerator + + +/*--------------------------- nsRegValueEnumerator ----------------------------- +| This class is a variation on nsRegSubtreeEnumerator that allocates | +| nsRegistryValue objects rather than nsRegistryNode objects. It also | +| overrides certain functions to make sure the "value" oriented libreg | +| functions used rather than the subtree oriented ones. | +------------------------------------------------------------------------------*/ +struct nsRegValueEnumerator : public nsRegSubtreeEnumerator { + // Override CurrentItem to allocate nsRegistryValue objects. + nsresult CurrentItem( nsISupports **result ); + + // Override advance() to use proper NR_RegEnumEntries. + NS_IMETHOD advance(); + + // ctor/dtor + nsRegValueEnumerator( HREG hReg, RKEY rKey ); +}; // nsRegValueEnumerator + +/*------------------------------ nsRegistryNode -------------------------------- +| This class implements the nsIRegistryNode interface. Instances are | +| allocated by nsRegSubtreeEnumerator::CurrentItem. | +------------------------------------------------------------------------------*/ +struct nsRegistryNode : public nsIRegistryNode { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // This class implements the nsIRegistryNode interface functions. + NS_IMETHOD GetName( char **result ); + + // ctor + nsRegistryNode( HREG hReg, RKEY key, REGENUM slot ); + +protected: + HREG mReg; // Handle to registry this node is part of. + RKEY mKey; // Key this node is under. + REGENUM mEnum; // Copy of corresponding content of parent enumerator. + REGERR mErr; // Last libreg error code. + char mName[MAXREGPATHLEN]; // Buffer to hold name. +}; // nsRegistryNode + + +/*------------------------------ nsRegistryValue ------------------------------- +| This class implements the nsIRegistryValue interface. Instances are | +| allocated by nsRegValueEnumerator::CurrentItem. | +------------------------------------------------------------------------------*/ +struct nsRegistryValue : public nsIRegistryValue { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // This class implements the nsIRegistryValue interface functions. + NS_IMETHOD GetName( char **result ); + NS_IMETHOD GetValueType( uint32 *result ); + NS_IMETHOD GetValueLength( uint32 *result ); + + // ctor + nsRegistryValue( HREG hReg, RKEY key, REGENUM slot ); + +protected: + nsresult getInfo(); // Get registry info. + HREG mReg; // Handle to registry this node is part of. + RKEY mKey; // Key this node is under. + REGENUM mEnum; // Copy of corresponding content of parent enumerator. + REGERR mErr; // Last libreg error code. + REGINFO mInfo; // Value info. + char mName[MAXREGNAMELEN]; // Buffer to hold name. +}; // nsRegistryValue + + +/*----------------------------- regerr2nsresult -------------------------------- +| This utility function maps a REGERR value to a corresponding nsresult | +| error code. | +------------------------------------------------------------------------------*/ +static nsresult regerr2nsresult( REGERR err ) { + nsresult rv = NS_ERROR_UNEXPECTED; + switch( err ) { + case REGERR_OK: + rv = NS_OK; + break; + + case REGERR_FAIL: + rv = NS_ERROR_FAILURE; + break; + + case REGERR_NOMORE: + rv = NS_ERROR_REG_NO_MORE; + break; + + case REGERR_NOFIND: + rv = NS_ERROR_REG_NOT_FOUND; + break; + + case REGERR_PARAM: + case REGERR_BADTYPE: + case REGERR_BADNAME: + rv = NS_ERROR_INVALID_ARG; + break; + + case REGERR_NOFILE: + rv = NS_ERROR_REG_NOFILE; + break; + + case REGERR_MEMORY: + rv = NS_ERROR_OUT_OF_MEMORY; + break; + + case REGERR_BUFTOOSMALL: + rv = NS_ERROR_REG_BUFFER_TOO_SMALL; + break; + + case REGERR_NAMETOOLONG: + rv = NS_ERROR_REG_NAME_TOO_LONG; + break; + + case REGERR_NOPATH: + rv = NS_ERROR_REG_NO_PATH; + break; + + case REGERR_READONLY: + rv = NS_ERROR_REG_READ_ONLY; + break; + + case REGERR_BADUTF8: + rv = NS_ERROR_REG_BAD_UTF8; + break; + + } + return rv; +} + +/*----------------------------- reginfo2DataType ------------------------------- +| This utility function converts the type field in the REGINFO structure to | +| the corresponding nsIRegistry::DataType value. | +------------------------------------------------------------------------------*/ +static void reginfo2DataType( const REGINFO &in, uint32 &out ) { + // Transfer information, based on entry type. + switch( in.entryType ) { + case REGTYPE_ENTRY_STRING_UTF: + out = nsIRegistry::String; + //out.length = in.entryLength; + break; + + case REGTYPE_ENTRY_INT32_ARRAY: + out = nsIRegistry::Int32; + // Convert length in bytes to array dimension. + //out.length = in.entryLength / sizeof(int32); + break; + + case REGTYPE_ENTRY_BYTES: + out = nsIRegistry::Bytes; + //out.length = in.entryLength; + break; + + case REGTYPE_ENTRY_FILE: + out = nsIRegistry::File; + //out.length = in.entryLength; + break; + } +} + +/*----------------------------- reginfo2DataType ------------------------------- +| This utility function converts the length field in the REGINFO structure to | +| the proper units (if type==Int32 array, we divide by sizeof(int32)). | +------------------------------------------------------------------------------*/ +static void reginfo2Length( const REGINFO &in, uint32 &out ) { + // Transfer information, based on entry type. + switch( in.entryType ) { + case REGTYPE_ENTRY_STRING_UTF: + out = in.entryLength; + break; + + case REGTYPE_ENTRY_INT32_ARRAY: + // Convert length in bytes to array dimension. + out = in.entryLength / sizeof(int32); + break; + + case REGTYPE_ENTRY_BYTES: + out = in.entryLength; + break; + + case REGTYPE_ENTRY_FILE: + out = in.entryLength; + break; + } +} + +/*----------------------------------- IIDs ------------------------------------- +| Static IID values for each imterface implemented here; required by the | +| NS_IMPL_ISUPPORTS macro. | +------------------------------------------------------------------------------*/ +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIRegistryIID, NS_IREGISTRY_IID); +static NS_DEFINE_IID(kIRegistryNodeIID, NS_IREGISTRYNODE_IID); +static NS_DEFINE_IID(kIRegistryValueIID, NS_IREGISTRYVALUE_IID); + +static NS_DEFINE_IID(kIEnumeratorIID, NS_IENUMERATOR_IID); + +static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); + +/*------------------------ nsISupports Implementation -------------------------- +| This code generates the implementation of the nsISupports member functions | +| for each class implemented in this file. | +------------------------------------------------------------------------------*/ +NS_IMPL_ISUPPORTS( nsRegistry, kIRegistryIID ); +NS_IMPL_ISUPPORTS( nsRegSubtreeEnumerator, kIEnumeratorIID ); +NS_IMPL_ISUPPORTS( nsRegistryNode, kIRegistryNodeIID ); +NS_IMPL_ISUPPORTS( nsRegistryValue, kIRegistryValueIID ); + +/*-------------------------- nsRegistry::nsRegistry ---------------------------- +| Vanilla nsRegistry constructor. The first time called, it does | +| NR_StartupRegistry. | +------------------------------------------------------------------------------*/ +nsRegistry::nsRegistry() + : mReg( 0 ) { + NS_INIT_REFCNT(); + + // Ensure libreg is started. + static PRBool libregStarted = PR_FALSE; + if( !libregStarted ) { + NR_StartupRegistry(); + libregStarted = PR_TRUE; + } + + return; +} + +/*------------------------- nsRegistry::~nsRegistry ---------------------------- +| The dtor closes the registry file(if open). | +------------------------------------------------------------------------------*/ +nsRegistry::~nsRegistry() { + if( mReg ) { + Close(); + } + return; +} + +/*----------------------------- nsRegistry::Open ------------------------------- +| If the argument is null, delegate to OpenDefault, else open the registry | +| file. We first check to see if a registry file is already open and close | +| it if so. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::Open( const char *regFile ) { + // Check for default. + if( !regFile ) { + return OpenDefault(); + } + // Ensure existing registry is closed. + Close(); + // Open specified registry. + mErr = NR_RegOpen((char*)regFile, &mReg ); + // Convert the result. + return regerr2nsresult( mErr ); +} + +/*-------------------------- nsRegistry::OpenDefault --------------------------- +| Open the "default" registry; in the case of this libreg-based implementation | +| that is done by passing a null file name pointer to NR_RegOpen. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::OpenDefault() { + // Ensure existing registry is closed. + Close(); + // Open default registry. + mErr = NR_RegOpen( 0, &mReg ); + // Convert the result. + return regerr2nsresult( mErr ); +} + +/*----------------------------- nsRegistry::Close ------------------------------ +| Tests the mReg handle and if non-null, closes the registry via NR_RegClose. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::Close() { + mErr = REGERR_OK; + if( mReg ) { + mErr = NR_RegClose( mReg ); + mReg = 0; + } + return regerr2nsresult( mErr ); +} + +/*--------------------------- nsRegistry::GetString ---------------------------- +| First, look for the entry using GetValueInfo. If found, and it's a string, | +| allocate space for it and fetch the value. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetString( Key baseKey, const char *path, char **result ) { + nsresult rv = NS_OK; + // Make sure caller gave us place for result. + if( result ) { + *result = 0; // Clear result. + + // Get info about the requested entry. + uint32 type, length; + rv = GetValueType( baseKey, path, &type ); + if ( rv == NS_OK ) { + rv = GetValueLength( baseKey, path, &length ); + } + // See if that worked. + if( rv == NS_OK ) { + // Make sure the entry is a string. + if( type == String ) { + // Allocate space for result. + *result =(char*)PR_Malloc( length + 1 ); + if( *result ) { + // Get string from registry into result buffer. + mErr = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, *result, length+1 ); + // Convert status. + rv = regerr2nsresult( mErr ); + // Test result. + if( rv != NS_OK ) { + // Didn't get result, free buffer. + PR_Free( *result ); + *result = 0; + } + } else { + // Couldn't allocate buffer. + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + // They asked for the wrong type of value. + rv = regerr2nsresult( REGERR_BADTYPE ); + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*--------------------------- nsRegistry::SetString ---------------------------- +| Simply sets the registry contents using NR_RegSetEntryString. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetString( Key baseKey, const char *path, const char *value ) { + nsresult rv = NS_OK; + // Set the contents. + mErr = NR_RegSetEntryString( mReg,(RKEY)baseKey,(char*)path,(char*)value ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*---------------------------- nsRegistry::GetInt ------------------------------ +| This function is just shorthand for fetching a 1-element int32 array. We | +| implement it "manually" using NR_RegGetEntry(versus calling GetIntArray) | +| to save allocating a copy of the result. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetInt( Key baseKey, const char *path, int32 *result ) { + nsresult rv = NS_OK; + + // Make sure caller gave us place for result. + if( result ) { + // Get info about the requested entry. + uint32 type; + rv = GetValueType( baseKey, path, &type ); + // See if that worked. + if( rv == NS_OK ) { + // Make sure the entry is an int32 array. + if( type == Int32 ) { + uint32 len = sizeof *result; + // Get int from registry into result field. + mErr = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path, result, &len ); + // Convert status. + rv = regerr2nsresult( mErr ); + } else { + // They asked for the wrong type of value. + rv = NS_ERROR_REG_BADTYPE; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------------- nsRegistry::SetInt ------------------------------ +| Write out the value as a one-element int32 array, using NR_RegSetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetInt( Key baseKey, const char *path, int32 value ) { + nsresult rv = NS_OK; + // Set the contents. + mErr = NR_RegSetEntry( mReg, + (RKEY)baseKey, + (char*)path, + REGTYPE_ENTRY_INT32_ARRAY, + &value, + sizeof value ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*--------------------------- nsRegistry::GetBytes ----------------------------- +| Get the registry contents at specified location using NR_RegGetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetBytes( Key baseKey, const char *path, void **result, uint32 *len ) { + nsresult rv = NS_OK; + + // Make sure caller gave us place for result. + if( result && len ) { + // Get info about the requested entry. + uint32 type; + rv = GetValueType( baseKey, path, &type ); + // See if that worked. + if( rv == NS_OK ) { + // Make sure the entry is bytes. + if( type == Bytes ) { + // Get bytes from registry into result field. + mErr = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path, result, len ); + // Convert status. + rv = regerr2nsresult( mErr ); + } else { + // They asked for the wrong type of value. + rv = NS_ERROR_REG_BADTYPE; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*--------------------------- nsRegistry::SetBytes ----------------------------- +| Set the contents at the specified registry location, using NR_RegSetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetBytes( Key baseKey, const char *path, void *value, uint32 len ) { + nsresult rv = NS_OK; + // Set contents. + mErr = NR_RegSetEntry( mReg,(RKEY)baseKey,(char*)path, + REGTYPE_ENTRY_BYTES, value, len ); + // Convert result; + rv = regerr2nsresult( mErr ); + return rv; +} + +/*-------------------------- nsRegistry::GetIntArray --------------------------- +| Find out about the entry using GetValueInfo. We check the type and then | +| use NR_RegGetEntry to get the actual array. We have to convert from the | +| array dimension to number of bytes in the process. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetIntArray( Key baseKey, const char *path, int32 **result, uint32 *len ) { + nsresult rv = NS_OK; + + // Make sure caller gave us place for result. + if( result && len ) { + // Get info about the requested entry. + uint32 type, length; + rv = GetValueType( baseKey, path, &type ); + if ( rv == NS_OK ) { + rv = GetValueLength( baseKey, path, &length ); + } + // See if that worked. + if( rv == NS_OK ) { + // Make sure the entry is bytes. + if( type == Int32 ) { + // Allocate space for result. + *len = length * sizeof(int32); + *result =(int32*)PR_Malloc( *len ); + // Make sure that worked. + if( *result ) { + // Get array from registry into result field. + mErr = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path, *result, len ); + // Convert status. + if( mErr == REGERR_OK ) { + // Convert size in bytes to array dimension. + *len /= sizeof(int32); + } else { + rv = regerr2nsresult( mErr ); + // Free buffer that we allocated(error will tell caller not to). + PR_Free( *result ); + *result = 0; + } + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + // They asked for the wrong type of value. + rv = NS_ERROR_REG_BADTYPE; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*-------------------------- nsRegistry::SetIntArray --------------------------- +| Store the given integer array at the given point in the registry. The | +| length given is the size of the array, we have to convert that to the | +| size in bytes in order to use NR_RegSetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetIntArray( Key baseKey, const char *path, const int32 *value, uint32 len ) { + nsresult rv = NS_OK; + // Convert array dimension to byte count. + uint32 size = len * sizeof(int32); + // Set contents. + mErr = NR_RegSetEntry( mReg,(RKEY)baseKey,(char*)path, + REGTYPE_ENTRY_INT32_ARRAY,(void*)value, size ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*-------------------------- nsRegistry::AddSubtree ---------------------------- +| Add a new registry subkey with the specified name, using NR_RegAddKey. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::AddSubtree( Key baseKey, const char *path, Key *result ) { + nsresult rv = NS_OK; + // Add the subkey. + mErr = NR_RegAddKey( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*------------------------- nsRegistry::RemoveSubtree -------------------------- +| Deletes the subtree at a given location using NR_RegDeleteKey. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::RemoveSubtree( Key baseKey, const char *path ) { + nsresult rv = NS_OK; + // Delete the subkey. + mErr = NR_RegDeleteKey( mReg,(RKEY)baseKey,(char*)path ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*-------------------------- nsRegistry::GetSubtree ---------------------------- +| Returns a nsIRegistry::Key(RKEY) for a given key/path. The key is | +| obtained using NR_RegGetKey. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetSubtree( Key baseKey, const char *path, Key *result ) { + nsresult rv = NS_OK; + // Make sure we have a place for the result. + if( result ) { + // Get key. + mErr = NR_RegGetKey( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result ); + // Convert result. + rv = regerr2nsresult( mErr ); + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*----------------------- nsRegistry::EnumerateSubtrees ------------------------ +| Allocate a nsRegSubtreeEnumerator object and return it to the caller. | +| We construct the enumerator using the registry handle from this registry | +| object, the user-specified registry key, and indicate that we don't want | +| to recurse down subtrees. No libreg functions are invoked at this point | +|(that will happen when the enumerator member functions are called). | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::EnumerateSubtrees( Key baseKey, nsIEnumerator **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + *result = new nsRegSubtreeEnumerator( mReg,(RKEY)baseKey, PR_FALSE ); + // Check for success. + if( *result ) { + // Bump refcnt on behalf of caller. + (*result)->AddRef(); + } else { + // Unable to allocate space for the enumerator object. + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*--------------------- nsRegistry::EnumerateAllSubtrees ----------------------- +| Same as EnumerateSubtrees but we pass PR_TRUE to request that the | +| enumerator object descend subtrees when it is used. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::EnumerateAllSubtrees( Key baseKey, nsIEnumerator **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + *result = new nsRegSubtreeEnumerator( mReg,(RKEY)baseKey, PR_TRUE ); + // Check for success. + if( *result ) { + // Bump refcnt on behalf of caller. + (*result)->AddRef(); + } else { + // Unable to allocate space for the enumerator object. + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*------------------------- nsRegistry::GetValueType --------------------------- +| Gets the type from the registry using the NR_GetEntryInfo libreg API. | +| The result is transferred to the uint32 value passed in (with conversion | +| to the appropriate nsIRegistry::DataType value). | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetValueType( Key baseKey, const char *path, uint32 *result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + // Get registry info into local structure. + REGINFO info = { sizeof info, 0, 0 }; + mErr = NR_RegGetEntryInfo( mReg,(RKEY)baseKey,(char*)path, &info ); + if( mErr == REGERR_OK ) { + // Copy info to user's result value. + reginfo2DataType( info, *result ); + } else { + rv = regerr2nsresult( mErr ); + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*------------------------ nsRegistry::GetValueLength -------------------------- +| Gets the registry value info via NR_RegGetEntryInfo. The length is | +| converted to the proper "units" via reginfo2Length. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetValueLength( Key baseKey, const char *path, uint32 *result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + // Get registry info into local structure. + REGINFO info = { sizeof info, 0, 0 }; + mErr = NR_RegGetEntryInfo( mReg,(RKEY)baseKey,(char*)path, &info ); + if( mErr == REGERR_OK ) { + // Copy info to user's result value. + reginfo2Length( info, *result ); + } else { + rv = regerr2nsresult( mErr ); + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*------------------------ nsRegistry::EnumerateValues ------------------------- +| Allocates and returns an instance of nsRegValueEnumerator constructed in | +| a similar fashion as the nsRegSubtreeEnumerator is allocated/returned by | +| EnumerateSubtrees. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::EnumerateValues( Key baseKey, nsIEnumerator **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + *result = new nsRegValueEnumerator( mReg,(RKEY)baseKey ); + // Check for success. + if( *result ) { + // Bump refcnt on behalf of caller. + (*result)->AddRef(); + } else { + // Unable to allocate space for the enumerator object. + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------- nsRegistry::GetCurrentUserName ------------------------ +| Simple wrapper for NR_RegGetUsername. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetCurrentUserName( char **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + // Get the user name. + mErr = NR_RegGetUsername( result ); + // Convert the result. + rv = regerr2nsresult( mErr ); + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------- nsRegistry::SetCurrentUserName ------------------------ +| Simple wrapper for NR_RegSetUsername. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetCurrentUserName( const char *name ) { + nsresult rv = NS_OK; + // Set the user name. + mErr = NR_RegSetUsername( name ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*----------------------------- nsRegistry::Pack ------------------------------- +| Simple wrapper for NR_RegPack. We don't set up any callback. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::Pack() { + nsresult rv = NS_OK; + // Pack the registry. + mErr = NR_RegPack( mReg, 0, 0 ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*-------------- nsRegSubtreeEnumerator::nsRegSubtreeEnumerator ---------------- +| The ctor simply stashes all the information that will be needed to enumerate | +| the subkeys. | +------------------------------------------------------------------------------*/ +nsRegSubtreeEnumerator::nsRegSubtreeEnumerator( HREG hReg, RKEY rKey, PRBool all ) + : mReg( hReg ), mKey( rKey ), mEnum( 0 ), mNext( 0 ), + mStyle( all ? REGENUM_DESCEND : 0 ), mDone( PR_FALSE ), mErr( -1 ) { + NS_INIT_REFCNT(); + return; +} + +/*----------------------- nsRegSubtreeEnumerator::First ------------------------ +| Set mEnum to 0; this will cause the next NR_RegEnum call to go to | +| the beginning. We then do a Next() call in order to do a "lookahead" to | +| properly detect an empty list (i.e., set the mDone flag). | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::First() { + nsresult rv = NS_OK; + // Reset "done" flag. + mDone = PR_FALSE; + // Go to beginning. + mEnum = mNext = 0; + // Lookahead so mDone flag gets set for empty list. + rv = Next(); + return rv; +} + +/*----------------------- nsRegSubtreeEnumerator::Last ------------------------- +| This can't be implemented using the libreg functions. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::Last() { + nsresult rv = NS_ERROR_NOT_IMPLEMENTED; + return rv; +} + +/*----------------------- nsRegSubtreeEnumerator::Next ------------------------- +| First, we check if we've already advanced to the end by checking the mDone | +| flag. | +| | +| We advance mEnum to the next enumeration value which is in the mNext | +| lookahead buffer. We must then call advance to lookahead and properly set | +| the isDone flag. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::Next() { + nsresult rv = NS_OK; + // Check for at end. + if ( !mDone ) { + // Advance to next spot. + mEnum = mNext; + // Lookahead so mDone is properly set (and to update mNext). + rv = advance(); + } else { + // Set result accordingly. + rv = regerr2nsresult( REGERR_NOMORE ); + } + return rv; +} + +/*---------------------- nsRegSubtreeEnumerator::advance ----------------------- +| Advance mNext to next subkey using NR_RegEnumSubkeys. We set mDone if | +| there are no more subkeys. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegSubtreeEnumerator::advance() { + char name[MAXREGPATHLEN]; + uint32 len = sizeof name; + mErr = NR_RegEnumSubkeys( mReg, mKey, &mNext, name, len, mStyle ); + // See if we ran off end. + if( mErr == REGERR_NOMORE ) { + // Remember we've run off end. + mDone = PR_TRUE; + } + // Convert result. + nsresult rv = regerr2nsresult( mErr ); + return rv; +}; + +/*----------------------- nsRegSubtreeEnumerator::Prev ------------------------- +| This can't be implemented on top of libreg. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::Prev() { + nsresult rv = NS_ERROR_NOT_IMPLEMENTED; + return rv; +} + +/*-------------------- nsRegSubtreeEnumerator::CurrentItem --------------------- +| Allocates and returns a new instance of class nsRegistryNode. The node | +| object will hold the curent mEnum value so it can obtain its name from | +| the registry when asked. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::CurrentItem( nsISupports **result) { + nsresult rv = NS_OK; + // Make sure there is a place to put the result. + if( result ) { + *result = new nsRegistryNode( mReg, mKey, mEnum ); + if( *result ) { + (*result)->AddRef(); + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------- nsRegSubtreeEnumerator::IsDone ------------------------ +| Simply return mDone. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::IsDone() { + nsresult rv = mDone; + return rv; +} + + +/*---------------- nsRegValueEnumerator::nsRegValueEnumerator ------------------ +| Delegates everything to the base class constructor. | +------------------------------------------------------------------------------*/ +nsRegValueEnumerator::nsRegValueEnumerator( HREG hReg, RKEY rKey ) + : nsRegSubtreeEnumerator( hReg, rKey, PR_FALSE ) { + return; +} + + +/*--------------------- nsRegValueEnumerator::CurrentItem ---------------------- +| As the nsRegSubtreeEnumerator counterpart, but allocates an object of | +| class nsRegistryValue. | +------------------------------------------------------------------------------*/ +nsresult nsRegValueEnumerator::CurrentItem( nsISupports **result ) { + nsresult rv = NS_OK; + // Make sure there is a place to put the result. + if( result ) { + *result = new nsRegistryValue( mReg, mKey, mEnum ); + if( *result ) { + (*result)->AddRef(); + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*----------------------- nsRegValueEnumerator::advance ------------------------ +| Advance mNext to next subkey using NR_RegEnumEntries. We set mDone if | +| there are no more entries. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegValueEnumerator::advance() { + char name[MAXREGNAMELEN]; + uint32 len = sizeof name; + REGINFO info = { sizeof info, 0, 0 }; + mErr = NR_RegEnumEntries( mReg, mKey, &mNext, name, len, &info ); + // See if we ran off end. + if( mErr == REGERR_NOMORE ) { + // Remember we've run off end. + mDone = PR_TRUE; + } + // Convert result. + nsresult rv = regerr2nsresult( mErr ); + return rv; +}; + + +/*---------------------- nsRegistryNode::nsRegistryNode ------------------------ +| Store the arguments in the corresponding data members and initialize | +| the other data members. We defer the libreg calls till we're asked for | +| our name. We use mErr==-1 to indicate we haven't fetched the name yet. | +------------------------------------------------------------------------------*/ +nsRegistryNode::nsRegistryNode( HREG hReg, RKEY key, REGENUM slot ) + : mReg( hReg ), mKey( key ), mEnum( slot ), mErr( -1 ) { + NS_INIT_REFCNT(); + return; +} + + +/*-------------------------------- PR_strdup ----------------------------------- +| Utility function that does PR_Malloc and copies argument string. Caller | +| must do PR_Free. | +------------------------------------------------------------------------------*/ +static char *PR_strdup( const char *in ) { + char *result = (char*)PR_Malloc( strlen( in ) + 1 ); + if ( result ) { + strcpy( result, in ); + } + return result; +} + +/*-------------------------- nsRegistryNode::GetName --------------------------- +| If we haven't fetched it yet, get the name of the corresponding subkey now, | +| using NR_RegEnumSubkeys. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistryNode::GetName( char **result ) { + nsresult rv = NS_OK; + // Make sure there is a place to put the result. + if( result ) { + // Test whether we haven't tried to get it yet. + if( mErr == -1 ) { + REGENUM temp = mEnum; + // Get name. + mErr = NR_RegEnumSubkeys( mReg, mKey, &temp, mName, sizeof mName, PR_FALSE ); + } + // Convert result from prior libreg call. + rv = regerr2nsresult( mErr ); + if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) { + // worked, return actual result. + *result = PR_strdup( mName ); + if ( *result ) { + rv = NS_OK; + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + + + +/*--------------------- nsRegistryValue::nsRegistryValue ----------------------- +| Implemented the same way as the nsRegistryNode ctor. | +------------------------------------------------------------------------------*/ +nsRegistryValue::nsRegistryValue( HREG hReg, RKEY key, REGENUM slot ) + : mReg( hReg ), mKey( key ), mEnum( slot ), mErr( -1 ) { + NS_INIT_REFCNT(); + return; +} + +/*------------------------- nsRegistryValue::GetName --------------------------- +| See nsRegistryNode::GetName; we use NR_RegEnumEntries in this case. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistryValue::GetName( char **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + // Ensure we've got the info we need. + rv = getInfo(); + if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) { + // worked, return actual result. + *result = PR_strdup( mName ); + if ( *result ) { + rv = NS_OK; + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*----------------------- nsRegistryValue::GetValueType ------------------------ +| We test if we've got the info already. If not, we git it by calling | +| getInfo. We calculate the result by converting the REGINFO type field to | +| a nsIRegistry::DataType value (using reginfo2DataType). | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistryValue::GetValueType( uint32 *result ) { + nsresult rv = NS_OK; + // Make sure we have room for th result. + if( result ) { + // Make sure we've got the info we need. + rv = getInfo(); + // Check if it worked. + if( rv == NS_OK ) { + // Convert result from REGINFO to nsIRegistry::ValueInfo. + reginfo2DataType( mInfo, *result ); + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------- nsRegistryValue::GetValueLength ----------------------- +| We test if we've got the info already. If not, we git it by calling | +| getInfo. We calculate the result by converting the REGINFO type field to | +| a nsIRegistry::DataType value (using reginfo2Length). | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistryValue::GetValueLength( uint32 *result ) { + nsresult rv = NS_OK; + // Make sure we have room for th result. + if( result ) { + // Make sure we've got the info we need. + rv = getInfo(); + // Check if it worked. + if( rv == NS_OK ) { + // Convert result from REGINFO to length. + reginfo2Length( mInfo, *result ); + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*------------------------- nsRegistryValue::getInfo --------------------------- +| Call NR_RegEnumEntries to set the mInfo/mName data members. | +------------------------------------------------------------------------------*/ +nsresult nsRegistryValue::getInfo() { + nsresult rv = NS_OK; + // Test whether we haven't tried to get it yet. + if( mErr == -1 ) { + REGENUM temp = mEnum; + // Get name and info. + mErr = NR_RegEnumEntries( mReg, mKey, &temp, mName, sizeof mName, &mInfo ); + // Convert result. + rv = regerr2nsresult( mErr ); + } + return rv; +} + + +nsRegistryFactory::nsRegistryFactory() { + NS_INIT_REFCNT(); +} + +NS_IMPL_ISUPPORTS(nsRegistryFactory, kIFactoryIID); + +NS_IMETHODIMP +nsRegistryFactory::CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult) { + nsresult rv = NS_OK; + nsRegistry* newRegistry; + + if(aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } else { + *aResult = NULL; + } + + if(0 != aOuter) { + return NS_ERROR_NO_AGGREGATION; + } + + NS_NEWXPCOM(newRegistry, nsRegistry); + + if(newRegistry == NULL) { + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(newRegistry); + rv = newRegistry->QueryInterface(aIID, aResult); + NS_RELEASE(newRegistry); + + return rv; +} + +nsresult +nsRegistryFactory::LockFactory(PRBool aLock) +{ + // Not implemented in simplest case. + return NS_OK; +} + +// This is a temporary hack; needs work to support dynamic binding +// via nsRepository and support for multiple factories per DLL. +extern "C" NS_EXPORT nsresult +nsRegistry_GetFactory(const nsCID &cid, nsISupports* servMgr, nsIFactory** aFactory ) { + nsresult rv = NS_OK; + + if( aFactory == 0 ) { + return NS_ERROR_NULL_POINTER; + } else { + *aFactory = 0; + } + + nsIFactory* inst = new nsRegistryFactory(); + if(0 == inst) { + rv = NS_ERROR_OUT_OF_MEMORY; + } else { + NS_ADDREF(inst); + *aFactory = inst; + } + + return rv; +} diff --git a/xpcom/public/nsError.h b/xpcom/public/nsError.h index 862d723197a..1c22f321b1b 100644 --- a/xpcom/public/nsError.h +++ b/xpcom/public/nsError.h @@ -63,6 +63,7 @@ typedef PRUint32 nsresult; #define NS_ERROR_MODULE_HTMLPARSER 9 #define NS_ERROR_MODULE_RDF 10 #define NS_ERROR_MODULE_UCONV 11 +#define NS_ERROR_MODULE_REG 12 #define NS_ERROR_MODULE_MAILNEWS 16 diff --git a/xpcom/public/nsIRegistry.h b/xpcom/public/nsIRegistry.h new file mode 100644 index 00000000000..a78ee4bb377 --- /dev/null +++ b/xpcom/public/nsIRegistry.h @@ -0,0 +1,326 @@ +/* -*- 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.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ +#ifndef __nsIRegistry_h +#define __nsIRegistry_h + +#include "nsISupports.h" + +class nsIEnumerator; + +/*-------------------------------- nsIRegistry --------------------------------- +| This interface provides access to a tree of arbitrary values. | +| | +| Each node of the tree contains either a value or a subtree or both. | +| | +| The value at any of these leaf nodes can be any of these "primitive" types: | +| o string (null terminated UTF string) | +| o array of 32-bit integers | +| o arbitrary array of bytes | +| o file identifier | +| Of course, since you can store an arbitrary array of bytes, you can put | +| any data you like into a registry (although you have the burden of | +| encoding/decoding your data in that case). | +| | +| Each branch of the tree is labelled with a string "key." The entire path | +| from a given point of the tree to another point further down can be | +| presented as a single string composed of each branch's label, concatenated | +| to the next, with an intervening forward slash ('/'). The term "key" | +| refers to both specific tree branch labels and to such concatenated paths. | +| | +| The branches from a given node must have unique labels. Distinct nodes can | +| have branches with the same label. | +| | +| For example, here's a small registry tree: | +| | | +| /\ | +| / \ | +| / \ | +| / \ | +| "Classes" "Users" | +| / \ | +| / \ | +| / ["joe"] | +| / / \ | +| | / \ | +| /\ / \ | +| / \ "joe" "bob" | +| / \ / \ | +| / \ | +| "{xxxx-xx-1}" "{xxxx-xx-2}" ["c:/joe"] ["d:/Robert"] | +| | | | +| /\ /\ | +| / \ / \ | +| / \ / \ | +| "Library" "Version" "Library" "Version" | +| / \ / \ | +| ["foo.dll"] 2 ["bar.dll"] 1 | +| | +| In this example, there are 2 keys under the root: "Classes" and "Users". | +| The first denotes a subtree only (which has two subtrees, ...). The second | +| denotes both a value ["joe"] and two subtrees labelled "joe" and "bob". | +| The value at the node "/Users" is ["joe"], at "/Users/bob" is ["d:/Robert"]. | +| The value at "/Classes/{xxxx-xx-1}/Version" is 2. | +| | +| The registry interface provides functions that let you navigate the tree | +| and manipulate it's contents. | +| | +| Please note that the registry itself does not impose any structure or | +| meaning on the contents of the tree. For example, the registry doesn't | +| control whether the value at the key "/Users" is the label for the subtree | +| with information about the last active user. That meaning is applied by | +| the code that stores these values and uses them for that purpose. | +| | +| [Any resemblence between this example and actual contents of any actual | +| registry is purely coincidental.] | +------------------------------------------------------------------------------*/ +struct nsIRegistry : public nsISupports { + /*------------------------------ Constants --------------------------------- + | The following enumerated types and values are used by the registry | + | interface. | + --------------------------------------------------------------------------*/ + typedef enum { + String = 1, + Int32, + Bytes, + File + } DataType; + + /*-------------------------------- Types ----------------------------------- + | The following data types are used by this interface. All are basically | + | opaque types. You obtain objects of these types via certain member | + | function calls and re-use them later (without having to know what they | + | contain). | + | | + | Key - Placeholder to represent a particular node in a registry | + | tree. There are 3 enumerated values that correspond to | + | specific nodes: | + | Common - Where most stuff goes. | + | Users - Special subtree to hold info about | + | "users"; if you don't know what goes | + | here, don't mess with it. | + | CurrentUser - Subtree under Users corresponding to | + | whatever user is designed the "current" | + | one; see note above. | + | You can specify any of these enumerated values as "keys" | + | on any member function that takes a nsRegistry::Key. | + | ValueInfo - Structure describing a registry value. | + --------------------------------------------------------------------------*/ + typedef uint32 Key; + + enum { Users = 1, Common = 2, CurrentUser = 3 }; + + struct ValueInfo { + DataType type; + uint32 length; + }; + + /*--------------------------- Opening/Closing ------------------------------ + | These functions open the specified registry file (Open() with a non-null | + | argument) or the default "standard" registry file (Open() with a null | + | argument or OpenDefault()). | + | | + | Once opened, you can access the registry contents via the read/write | + | or query functions. | + | | + | The registry file will be closed automatically when the registry object | + | is destroyed. You can close the file prior to that by using the | + | Close() function. | + --------------------------------------------------------------------------*/ + NS_IMETHOD Open( const char *regFile = 0 ) = 0; + NS_IMETHOD OpenDefault() = 0; + NS_IMETHOD Close() = 0; + + /*----------------------- Reading/Writing Values --------------------------- + | These functions read/write the registry values at a given node. | + | | + | All functions require you to specify where in the registry key to | + | get/set the value. The location is specified using two components: | + | o A "base key" indicating where to start from; this is a value of type | + | nsIRegistry::Key. You use either one of the special "root" key | + | values or a subkey obtained via some other member function call. | + | o A "relative path," expressed as a sequence of subtree names | + | separated by forward slashes. This path describes how to get from | + | the base key to the node at which you want to store the data. This | + | component can be a null pointer which means the value goes directly | + | at the node denoted by the base key. | + | | + | When you request a value of a given type, the data stored at the | + | specified node must be of the type requested. If not, an error results. | + | | + | GetString - Obtains a newly allocated copy of a string type value. The | + | caller is obligated to free the returned string using | + | PR_Free. | + | SetString - Stores the argument string at the specified node. | + | GetInt - Obtains an int32 value at the specified node. The result | + | is returned into an int32 location you specify. | + | SetInt - Stores a given int32 value at a node. | + | GetBytes - Obtains a byte array value; this returns both an allocated | + | array of bytes and a length (necessary because there may be | + | embedded null bytes in the array). You must free the | + | resulting array using PR_Free. | + | SetBytes - Stores a given array of bytes; you specify the bytes via a | + | pointer and a length. | + | GetIntArray - Obtains the array of int32 values stored at a given node. | + | The result is composed of two values: a pointer to an | + | array of integer values (which must be freed using | + | PR_Free) and the number of elements in that array. | + | SetIntArray - Stores a set of int32 values at a given node. You must | + | provide a pointer to the array and the number of entries. | + --------------------------------------------------------------------------*/ + NS_IMETHOD GetString( Key baseKey, const char *path, char **result ) = 0; + NS_IMETHOD SetString( Key baseKey, const char *path, const char *value ) = 0; + NS_IMETHOD GetInt( Key baseKey, const char *path, int32 *result ) = 0; + NS_IMETHOD SetInt( Key baseKey, const char *path, int32 value ) = 0; + NS_IMETHOD GetBytes( Key baseKey, const char *path, void **result, uint32 *len ) = 0; + NS_IMETHOD SetBytes( Key baseKey, const char *path, void *value, uint32 len ) = 0; + NS_IMETHOD GetIntArray( Key baseKey, const char *path, int32 **result, uint32 *len ) = 0; + NS_IMETHOD SetIntArray( Key baseKey, const char *path, const int32 *value, uint32 len ) = 0; + + /*------------------------------ Navigation -------------------------------- + | These functions let you navigate through the registry tree, querying | + | its contents. | + | | + | As above, all these functions requires a starting tree location ("base | + | key") specified as a nsIRegistry::Key. Some also require a path | + | name to locate the registry node location relative to this base key. | + | | + | AddSubtree - Adds a new registry subtree at the specified | + | location. Returns the resulting key in | + | the location specified by the third argument | + | (unless that pointer is 0). | + | RemoveNode - Removes the specified registry subtree or | + | value at the specified location. | + | GetSubtree - Returns a nsIRegistry::Key that can be used | + | to refer to the specified registry location. | + | EnumerateSubtrees - Returns a nsIEnumerator object that you can | + | use to enumerate all the subtrees descending | + | from a specified location. You must free the | + | enumerator via Release() when you're done with | + | it. | + | EnumerateAllSubtrees - Like EnumerateSubtrees, but will recursively | + | enumerate lower-level subtrees, too. | + | GetValueInfo - Returns a uint32 value that designates the type | + | of data stored at this location in the registry; | + | the possible values are defined by the enumerated | + | type nsIRegistry::DataType. | + | GetValueLength - Returns a uint32 value that indicates the length | + | of this registry value; the length is the number | + | of characters (for Strings), the number of bytes | + | (for Bytes), or the number of int32 values (for | + | Int32). | + | EnumerateValues - Returns a nsIEnumerator that you can use to | + | enumerate all the value nodes descending from | + | a specified location. | + --------------------------------------------------------------------------*/ + NS_IMETHOD AddSubtree( Key baseKey, const char *path, Key *result ) = 0; + NS_IMETHOD RemoveSubtree( Key baseKey, const char *path ) = 0; + NS_IMETHOD GetSubtree( Key baseKey, const char *path, Key *result ) = 0; + + NS_IMETHOD EnumerateSubtrees( Key baseKey, nsIEnumerator **result ) = 0; + NS_IMETHOD EnumerateAllSubtrees( Key baseKey, nsIEnumerator **result ) = 0; + + NS_IMETHOD GetValueType( Key baseKey, const char *path, uint32 *result ) = 0; + NS_IMETHOD GetValueLength( Key baseKey, const char *path, uint32 *result ) = 0; + + NS_IMETHOD EnumerateValues( Key baseKey, nsIEnumerator **result ) = 0; + + /*------------------------------ User Name --------------------------------- + | These functions manipulate the current "user name." This value controls | + | the behavior of certain registry functions (namely, ?). | + | | + | GetCurrentUserName allocates a copy of the current user name (which the | + | caller should free using PR_Free). | + --------------------------------------------------------------------------*/ + NS_IMETHOD GetCurrentUserName( char **result ) = 0; + NS_IMETHOD SetCurrentUserName( const char *name ) = 0; + + /*------------------------------ Utilities --------------------------------- + | Various utility functions: | + | | + | Pack() is used to compress the contents of an open registry file. | + --------------------------------------------------------------------------*/ + NS_IMETHOD Pack() = 0; + +}; // nsIRegistry + +/*------------------------------ nsIRegistryNode ------------------------------- +| This interface is implemented by all the objects obtained from the | +| nsIEnumerators that nsIRegistry provides when you call either of the | +| subtree enumeration functions EnumerateSubtrees or EnumerateAllSubtrees. | +| | +| You can call this function to get the name of this subtree. This is the | +| relative path from the base key from which you got this interface. | +| | +| GetName - Returns the path name of this node; this is the relative path | +| from the base key from which this subtree was obtained. The | +| function allocates a copy of the name; the caller must free it | +| using PR_Free. | +------------------------------------------------------------------------------*/ +struct nsIRegistryNode : public nsISupports { + NS_IMETHOD GetName( char **result ) = 0; +}; // nsIRegistryNode + +/*------------------------------ nsIRegistryValue ------------------------------ +| This interface is implemented by the objects obtained from the | +| nsIEnumerators that nsIRegistry provides when you call the | +| EnumerateValues function. An object supporting this interface is | +| returned when you call the CurrentItem() function on that enumerator. | +| | +| You use the member functions of this interface to obtain information | +| about each registry value. | +| | +| GetName - Returns the path name of this node; this is the relative | +| path\ from the base key from which this value was obtained. | +| The function allocates a copy of the name; the caller must | +| subsequently free it via PR_Free. | +| GetValueType - Returns (into a location provided by the caller) the type | +| of the value; the types are defined by the enumerated | +| type nsIRegistry::DataType. | +| GetValueLength - Returns a uint32 value that indicates the length | +| of this registry value; the length is the number | +| of characters (for Strings), the number of bytes | +| (for Bytes), or the number of int32 values (for | +| Int32). | +------------------------------------------------------------------------------*/ +struct nsIRegistryValue : public nsISupports { + NS_IMETHOD GetName( char **result ) = 0; + NS_IMETHOD GetValueType( uint32 *result ) = 0; + NS_IMETHOD GetValueLength( uint32 *result ) = 0; +}; // nsIRegistryEntry + + +/*------------------------------- Error Codes ---------------------------------- +------------------------------------------------------------------------------*/ +#define NS_ERROR_REG_BADTYPE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 1 ) +#define NS_ERROR_REG_NO_MORE NS_ERROR_GENERATE_SUCCESS( NS_ERROR_MODULE_REG, 2 ) +#define NS_ERROR_REG_NOT_FOUND NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 3 ) +#define NS_ERROR_REG_NOFILE NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 4 ) +#define NS_ERROR_REG_BUFFER_TOO_SMALL NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 5 ) +#define NS_ERROR_REG_NAME_TOO_LONG NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 6 ) +#define NS_ERROR_REG_NO_PATH NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 7 ) +#define NS_ERROR_REG_READ_ONLY NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 8 ) +#define NS_ERROR_REG_BAD_UTF8 NS_ERROR_GENERATE_FAILURE( NS_ERROR_MODULE_REG, 9 ) + +// {5D41A440-8E37-11d2-8059-00600811A9C3} +#define NS_IREGISTRY_IID { 0x5d41a440, 0x8e37, 0x11d2, { 0x80, 0x59, 0x0, 0x60, 0x8, 0x11, 0xa9, 0xc3 } } +// {D1B54831-AC07-11d2-805E-00600811A9C3} +#define NS_IREGISTRYNODE_IID { 0xd1b54831, 0xac07, 0x11d2, { 0x80, 0x5e, 0x0, 0x60, 0x8, 0x11, 0xa9, 0xc3 } } +// {5316C380-B2F8-11d2-A374-0080C6F80E4B} +#define NS_IREGISTRYVALUE_IID { 0x5316c380, 0xb2f8, 0x11d2, { 0xa3, 0x74, 0x0, 0x80, 0xc6, 0xf8, 0xe, 0x4b } } + +#endif diff --git a/xpcom/src/nsRegistry.cpp b/xpcom/src/nsRegistry.cpp new file mode 100644 index 00000000000..0d26c07efb3 --- /dev/null +++ b/xpcom/src/nsRegistry.cpp @@ -0,0 +1,1204 @@ +/* -*- 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.0 (the "NPL"); you may not use this file except in + * compliance with the NPL. You may obtain a copy of the NPL at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the NPL is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL + * for the specific language governing rights and limitations under the + * NPL. + * + * The Initial Developer of this code under the NPL is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + */ + +#include "nsIRegistry.h" +#include "nsIEnumerator.h" +#include "NSReg.h" +#include "prmem.h" + +/*-------------------------------- nsRegistry ---------------------------------- +| This class implements the nsIRegistry interface using the functions | +| provided by libreg (as declared in mozilla/modules/libreg/include/NSReg.h). | +| | +| Since that interface is designed to match the libreg function, this class | +| is implemented with each member function being a simple wrapper for the | +| corresponding libreg function. | +------------------------------------------------------------------------------*/ +struct nsRegistry : public nsIRegistry { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // This class implements the nsIRegistry interface functions. + NS_IMETHOD Open( const char *regFile = 0 ); + NS_IMETHOD OpenDefault(); + NS_IMETHOD Close(); + + NS_IMETHOD GetString( Key baseKey, const char *path, char **result ); + NS_IMETHOD SetString( Key baseKey, const char *path, const char *value ); + NS_IMETHOD GetInt( Key baseKey, const char *path, int32 *result ); + NS_IMETHOD SetInt( Key baseKey, const char *path, int32 value ); + NS_IMETHOD GetBytes( Key baseKey, const char *path, void **result, uint32 *len ); + NS_IMETHOD SetBytes( Key baseKey, const char *path, void *value, uint32 len ); + NS_IMETHOD GetIntArray( Key baseKey, const char *path, int32 **result, uint32 *len ); + NS_IMETHOD SetIntArray( Key baseKey, const char *path, const int32 *value, uint32 len ); + + NS_IMETHOD AddSubtree( Key baseKey, const char *path, Key *result ); + NS_IMETHOD RemoveSubtree( Key baseKey, const char *path ); + NS_IMETHOD GetSubtree( Key baseKey, const char *path, Key *result ); + + NS_IMETHOD EnumerateSubtrees( Key baseKey, nsIEnumerator **result ); + NS_IMETHOD EnumerateAllSubtrees( Key baseKey, nsIEnumerator **result ); + + NS_IMETHOD GetValueType( Key baseKey, const char *path, uint32 *result ); + NS_IMETHOD GetValueLength( Key baseKey, const char *path, uint32 *result ); + + NS_IMETHOD EnumerateValues( Key baseKey, nsIEnumerator **result ); + + NS_IMETHOD GetCurrentUserName( char **result ); + NS_IMETHOD SetCurrentUserName( const char *name ); + + NS_IMETHOD Pack(); + + // ctor/dtor + nsRegistry(); + ~nsRegistry(); + +protected: + HREG mReg; // Registry handle. + REGERR mErr; // Last libreg error code. +}; // nsRegistry + + +#include "nsIFactory.h" +/*----------------------------- nsRegistryFactory ------------------------------ +| Class factory for nsRegistry objects. | +------------------------------------------------------------------------------*/ +struct nsRegistryFactory : public nsIFactory { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // nsIFactory methods + NS_IMETHOD CreateInstance(nsISupports *,const nsIID &,void **); + NS_IMETHOD LockFactory(PRBool aLock); + + // ctor + nsRegistryFactory(); +}; + + +/*--------------------------- nsRegSubtreeEnumerator --------------------------- +| This class implements the nsIEnumerator interface and is used to implement | +| the nsRegistry EnumerateSubtrees and EnumerateAllSubtrees functions. | +------------------------------------------------------------------------------*/ +struct nsRegSubtreeEnumerator : public nsIEnumerator { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // This class implements the nsIEnumerator interface functions. + nsresult First(); + nsresult Last(); + nsresult Next(); + nsresult Prev(); + nsresult CurrentItem(nsISupports **aItem); + nsresult IsDone(); + + // ctor/dtor + nsRegSubtreeEnumerator( HREG hReg, RKEY rKey, PRBool all ); + +protected: + NS_IMETHOD advance(); // Implementation file; does appropriate NR_RegEnum call. + HREG mReg; // Handle to registry we're affiliated with. + RKEY mKey; // Base key being enumerated. + REGENUM mEnum; // Corresponding libreg "enumerator". + REGENUM mNext; // Lookahead value. + uint32 mStyle; // Style (indicates all or some); + PRBool mDone; // Done flag. + REGERR mErr; // Last libreg error code. +}; // nsRegSubtreeEnumerator + + +/*--------------------------- nsRegValueEnumerator ----------------------------- +| This class is a variation on nsRegSubtreeEnumerator that allocates | +| nsRegistryValue objects rather than nsRegistryNode objects. It also | +| overrides certain functions to make sure the "value" oriented libreg | +| functions used rather than the subtree oriented ones. | +------------------------------------------------------------------------------*/ +struct nsRegValueEnumerator : public nsRegSubtreeEnumerator { + // Override CurrentItem to allocate nsRegistryValue objects. + nsresult CurrentItem( nsISupports **result ); + + // Override advance() to use proper NR_RegEnumEntries. + NS_IMETHOD advance(); + + // ctor/dtor + nsRegValueEnumerator( HREG hReg, RKEY rKey ); +}; // nsRegValueEnumerator + +/*------------------------------ nsRegistryNode -------------------------------- +| This class implements the nsIRegistryNode interface. Instances are | +| allocated by nsRegSubtreeEnumerator::CurrentItem. | +------------------------------------------------------------------------------*/ +struct nsRegistryNode : public nsIRegistryNode { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // This class implements the nsIRegistryNode interface functions. + NS_IMETHOD GetName( char **result ); + + // ctor + nsRegistryNode( HREG hReg, RKEY key, REGENUM slot ); + +protected: + HREG mReg; // Handle to registry this node is part of. + RKEY mKey; // Key this node is under. + REGENUM mEnum; // Copy of corresponding content of parent enumerator. + REGERR mErr; // Last libreg error code. + char mName[MAXREGPATHLEN]; // Buffer to hold name. +}; // nsRegistryNode + + +/*------------------------------ nsRegistryValue ------------------------------- +| This class implements the nsIRegistryValue interface. Instances are | +| allocated by nsRegValueEnumerator::CurrentItem. | +------------------------------------------------------------------------------*/ +struct nsRegistryValue : public nsIRegistryValue { + // This class implements the nsISupports interface functions. + NS_DECL_ISUPPORTS + + // This class implements the nsIRegistryValue interface functions. + NS_IMETHOD GetName( char **result ); + NS_IMETHOD GetValueType( uint32 *result ); + NS_IMETHOD GetValueLength( uint32 *result ); + + // ctor + nsRegistryValue( HREG hReg, RKEY key, REGENUM slot ); + +protected: + nsresult getInfo(); // Get registry info. + HREG mReg; // Handle to registry this node is part of. + RKEY mKey; // Key this node is under. + REGENUM mEnum; // Copy of corresponding content of parent enumerator. + REGERR mErr; // Last libreg error code. + REGINFO mInfo; // Value info. + char mName[MAXREGNAMELEN]; // Buffer to hold name. +}; // nsRegistryValue + + +/*----------------------------- regerr2nsresult -------------------------------- +| This utility function maps a REGERR value to a corresponding nsresult | +| error code. | +------------------------------------------------------------------------------*/ +static nsresult regerr2nsresult( REGERR err ) { + nsresult rv = NS_ERROR_UNEXPECTED; + switch( err ) { + case REGERR_OK: + rv = NS_OK; + break; + + case REGERR_FAIL: + rv = NS_ERROR_FAILURE; + break; + + case REGERR_NOMORE: + rv = NS_ERROR_REG_NO_MORE; + break; + + case REGERR_NOFIND: + rv = NS_ERROR_REG_NOT_FOUND; + break; + + case REGERR_PARAM: + case REGERR_BADTYPE: + case REGERR_BADNAME: + rv = NS_ERROR_INVALID_ARG; + break; + + case REGERR_NOFILE: + rv = NS_ERROR_REG_NOFILE; + break; + + case REGERR_MEMORY: + rv = NS_ERROR_OUT_OF_MEMORY; + break; + + case REGERR_BUFTOOSMALL: + rv = NS_ERROR_REG_BUFFER_TOO_SMALL; + break; + + case REGERR_NAMETOOLONG: + rv = NS_ERROR_REG_NAME_TOO_LONG; + break; + + case REGERR_NOPATH: + rv = NS_ERROR_REG_NO_PATH; + break; + + case REGERR_READONLY: + rv = NS_ERROR_REG_READ_ONLY; + break; + + case REGERR_BADUTF8: + rv = NS_ERROR_REG_BAD_UTF8; + break; + + } + return rv; +} + +/*----------------------------- reginfo2DataType ------------------------------- +| This utility function converts the type field in the REGINFO structure to | +| the corresponding nsIRegistry::DataType value. | +------------------------------------------------------------------------------*/ +static void reginfo2DataType( const REGINFO &in, uint32 &out ) { + // Transfer information, based on entry type. + switch( in.entryType ) { + case REGTYPE_ENTRY_STRING_UTF: + out = nsIRegistry::String; + //out.length = in.entryLength; + break; + + case REGTYPE_ENTRY_INT32_ARRAY: + out = nsIRegistry::Int32; + // Convert length in bytes to array dimension. + //out.length = in.entryLength / sizeof(int32); + break; + + case REGTYPE_ENTRY_BYTES: + out = nsIRegistry::Bytes; + //out.length = in.entryLength; + break; + + case REGTYPE_ENTRY_FILE: + out = nsIRegistry::File; + //out.length = in.entryLength; + break; + } +} + +/*----------------------------- reginfo2DataType ------------------------------- +| This utility function converts the length field in the REGINFO structure to | +| the proper units (if type==Int32 array, we divide by sizeof(int32)). | +------------------------------------------------------------------------------*/ +static void reginfo2Length( const REGINFO &in, uint32 &out ) { + // Transfer information, based on entry type. + switch( in.entryType ) { + case REGTYPE_ENTRY_STRING_UTF: + out = in.entryLength; + break; + + case REGTYPE_ENTRY_INT32_ARRAY: + // Convert length in bytes to array dimension. + out = in.entryLength / sizeof(int32); + break; + + case REGTYPE_ENTRY_BYTES: + out = in.entryLength; + break; + + case REGTYPE_ENTRY_FILE: + out = in.entryLength; + break; + } +} + +/*----------------------------------- IIDs ------------------------------------- +| Static IID values for each imterface implemented here; required by the | +| NS_IMPL_ISUPPORTS macro. | +------------------------------------------------------------------------------*/ +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIRegistryIID, NS_IREGISTRY_IID); +static NS_DEFINE_IID(kIRegistryNodeIID, NS_IREGISTRYNODE_IID); +static NS_DEFINE_IID(kIRegistryValueIID, NS_IREGISTRYVALUE_IID); + +static NS_DEFINE_IID(kIEnumeratorIID, NS_IENUMERATOR_IID); + +static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); + +/*------------------------ nsISupports Implementation -------------------------- +| This code generates the implementation of the nsISupports member functions | +| for each class implemented in this file. | +------------------------------------------------------------------------------*/ +NS_IMPL_ISUPPORTS( nsRegistry, kIRegistryIID ); +NS_IMPL_ISUPPORTS( nsRegSubtreeEnumerator, kIEnumeratorIID ); +NS_IMPL_ISUPPORTS( nsRegistryNode, kIRegistryNodeIID ); +NS_IMPL_ISUPPORTS( nsRegistryValue, kIRegistryValueIID ); + +/*-------------------------- nsRegistry::nsRegistry ---------------------------- +| Vanilla nsRegistry constructor. The first time called, it does | +| NR_StartupRegistry. | +------------------------------------------------------------------------------*/ +nsRegistry::nsRegistry() + : mReg( 0 ) { + NS_INIT_REFCNT(); + + // Ensure libreg is started. + static PRBool libregStarted = PR_FALSE; + if( !libregStarted ) { + NR_StartupRegistry(); + libregStarted = PR_TRUE; + } + + return; +} + +/*------------------------- nsRegistry::~nsRegistry ---------------------------- +| The dtor closes the registry file(if open). | +------------------------------------------------------------------------------*/ +nsRegistry::~nsRegistry() { + if( mReg ) { + Close(); + } + return; +} + +/*----------------------------- nsRegistry::Open ------------------------------- +| If the argument is null, delegate to OpenDefault, else open the registry | +| file. We first check to see if a registry file is already open and close | +| it if so. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::Open( const char *regFile ) { + // Check for default. + if( !regFile ) { + return OpenDefault(); + } + // Ensure existing registry is closed. + Close(); + // Open specified registry. + mErr = NR_RegOpen((char*)regFile, &mReg ); + // Convert the result. + return regerr2nsresult( mErr ); +} + +/*-------------------------- nsRegistry::OpenDefault --------------------------- +| Open the "default" registry; in the case of this libreg-based implementation | +| that is done by passing a null file name pointer to NR_RegOpen. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::OpenDefault() { + // Ensure existing registry is closed. + Close(); + // Open default registry. + mErr = NR_RegOpen( 0, &mReg ); + // Convert the result. + return regerr2nsresult( mErr ); +} + +/*----------------------------- nsRegistry::Close ------------------------------ +| Tests the mReg handle and if non-null, closes the registry via NR_RegClose. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::Close() { + mErr = REGERR_OK; + if( mReg ) { + mErr = NR_RegClose( mReg ); + mReg = 0; + } + return regerr2nsresult( mErr ); +} + +/*--------------------------- nsRegistry::GetString ---------------------------- +| First, look for the entry using GetValueInfo. If found, and it's a string, | +| allocate space for it and fetch the value. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetString( Key baseKey, const char *path, char **result ) { + nsresult rv = NS_OK; + // Make sure caller gave us place for result. + if( result ) { + *result = 0; // Clear result. + + // Get info about the requested entry. + uint32 type, length; + rv = GetValueType( baseKey, path, &type ); + if ( rv == NS_OK ) { + rv = GetValueLength( baseKey, path, &length ); + } + // See if that worked. + if( rv == NS_OK ) { + // Make sure the entry is a string. + if( type == String ) { + // Allocate space for result. + *result =(char*)PR_Malloc( length + 1 ); + if( *result ) { + // Get string from registry into result buffer. + mErr = NR_RegGetEntryString( mReg,(RKEY)baseKey,(char*)path, *result, length+1 ); + // Convert status. + rv = regerr2nsresult( mErr ); + // Test result. + if( rv != NS_OK ) { + // Didn't get result, free buffer. + PR_Free( *result ); + *result = 0; + } + } else { + // Couldn't allocate buffer. + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + // They asked for the wrong type of value. + rv = regerr2nsresult( REGERR_BADTYPE ); + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*--------------------------- nsRegistry::SetString ---------------------------- +| Simply sets the registry contents using NR_RegSetEntryString. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetString( Key baseKey, const char *path, const char *value ) { + nsresult rv = NS_OK; + // Set the contents. + mErr = NR_RegSetEntryString( mReg,(RKEY)baseKey,(char*)path,(char*)value ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*---------------------------- nsRegistry::GetInt ------------------------------ +| This function is just shorthand for fetching a 1-element int32 array. We | +| implement it "manually" using NR_RegGetEntry(versus calling GetIntArray) | +| to save allocating a copy of the result. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetInt( Key baseKey, const char *path, int32 *result ) { + nsresult rv = NS_OK; + + // Make sure caller gave us place for result. + if( result ) { + // Get info about the requested entry. + uint32 type; + rv = GetValueType( baseKey, path, &type ); + // See if that worked. + if( rv == NS_OK ) { + // Make sure the entry is an int32 array. + if( type == Int32 ) { + uint32 len = sizeof *result; + // Get int from registry into result field. + mErr = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path, result, &len ); + // Convert status. + rv = regerr2nsresult( mErr ); + } else { + // They asked for the wrong type of value. + rv = NS_ERROR_REG_BADTYPE; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------------- nsRegistry::SetInt ------------------------------ +| Write out the value as a one-element int32 array, using NR_RegSetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetInt( Key baseKey, const char *path, int32 value ) { + nsresult rv = NS_OK; + // Set the contents. + mErr = NR_RegSetEntry( mReg, + (RKEY)baseKey, + (char*)path, + REGTYPE_ENTRY_INT32_ARRAY, + &value, + sizeof value ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*--------------------------- nsRegistry::GetBytes ----------------------------- +| Get the registry contents at specified location using NR_RegGetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetBytes( Key baseKey, const char *path, void **result, uint32 *len ) { + nsresult rv = NS_OK; + + // Make sure caller gave us place for result. + if( result && len ) { + // Get info about the requested entry. + uint32 type; + rv = GetValueType( baseKey, path, &type ); + // See if that worked. + if( rv == NS_OK ) { + // Make sure the entry is bytes. + if( type == Bytes ) { + // Get bytes from registry into result field. + mErr = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path, result, len ); + // Convert status. + rv = regerr2nsresult( mErr ); + } else { + // They asked for the wrong type of value. + rv = NS_ERROR_REG_BADTYPE; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*--------------------------- nsRegistry::SetBytes ----------------------------- +| Set the contents at the specified registry location, using NR_RegSetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetBytes( Key baseKey, const char *path, void *value, uint32 len ) { + nsresult rv = NS_OK; + // Set contents. + mErr = NR_RegSetEntry( mReg,(RKEY)baseKey,(char*)path, + REGTYPE_ENTRY_BYTES, value, len ); + // Convert result; + rv = regerr2nsresult( mErr ); + return rv; +} + +/*-------------------------- nsRegistry::GetIntArray --------------------------- +| Find out about the entry using GetValueInfo. We check the type and then | +| use NR_RegGetEntry to get the actual array. We have to convert from the | +| array dimension to number of bytes in the process. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetIntArray( Key baseKey, const char *path, int32 **result, uint32 *len ) { + nsresult rv = NS_OK; + + // Make sure caller gave us place for result. + if( result && len ) { + // Get info about the requested entry. + uint32 type, length; + rv = GetValueType( baseKey, path, &type ); + if ( rv == NS_OK ) { + rv = GetValueLength( baseKey, path, &length ); + } + // See if that worked. + if( rv == NS_OK ) { + // Make sure the entry is bytes. + if( type == Int32 ) { + // Allocate space for result. + *len = length * sizeof(int32); + *result =(int32*)PR_Malloc( *len ); + // Make sure that worked. + if( *result ) { + // Get array from registry into result field. + mErr = NR_RegGetEntry( mReg,(RKEY)baseKey,(char*)path, *result, len ); + // Convert status. + if( mErr == REGERR_OK ) { + // Convert size in bytes to array dimension. + *len /= sizeof(int32); + } else { + rv = regerr2nsresult( mErr ); + // Free buffer that we allocated(error will tell caller not to). + PR_Free( *result ); + *result = 0; + } + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + // They asked for the wrong type of value. + rv = NS_ERROR_REG_BADTYPE; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*-------------------------- nsRegistry::SetIntArray --------------------------- +| Store the given integer array at the given point in the registry. The | +| length given is the size of the array, we have to convert that to the | +| size in bytes in order to use NR_RegSetEntry. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetIntArray( Key baseKey, const char *path, const int32 *value, uint32 len ) { + nsresult rv = NS_OK; + // Convert array dimension to byte count. + uint32 size = len * sizeof(int32); + // Set contents. + mErr = NR_RegSetEntry( mReg,(RKEY)baseKey,(char*)path, + REGTYPE_ENTRY_INT32_ARRAY,(void*)value, size ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*-------------------------- nsRegistry::AddSubtree ---------------------------- +| Add a new registry subkey with the specified name, using NR_RegAddKey. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::AddSubtree( Key baseKey, const char *path, Key *result ) { + nsresult rv = NS_OK; + // Add the subkey. + mErr = NR_RegAddKey( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*------------------------- nsRegistry::RemoveSubtree -------------------------- +| Deletes the subtree at a given location using NR_RegDeleteKey. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::RemoveSubtree( Key baseKey, const char *path ) { + nsresult rv = NS_OK; + // Delete the subkey. + mErr = NR_RegDeleteKey( mReg,(RKEY)baseKey,(char*)path ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*-------------------------- nsRegistry::GetSubtree ---------------------------- +| Returns a nsIRegistry::Key(RKEY) for a given key/path. The key is | +| obtained using NR_RegGetKey. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetSubtree( Key baseKey, const char *path, Key *result ) { + nsresult rv = NS_OK; + // Make sure we have a place for the result. + if( result ) { + // Get key. + mErr = NR_RegGetKey( mReg,(RKEY)baseKey,(char*)path,(RKEY*)result ); + // Convert result. + rv = regerr2nsresult( mErr ); + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*----------------------- nsRegistry::EnumerateSubtrees ------------------------ +| Allocate a nsRegSubtreeEnumerator object and return it to the caller. | +| We construct the enumerator using the registry handle from this registry | +| object, the user-specified registry key, and indicate that we don't want | +| to recurse down subtrees. No libreg functions are invoked at this point | +|(that will happen when the enumerator member functions are called). | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::EnumerateSubtrees( Key baseKey, nsIEnumerator **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + *result = new nsRegSubtreeEnumerator( mReg,(RKEY)baseKey, PR_FALSE ); + // Check for success. + if( *result ) { + // Bump refcnt on behalf of caller. + (*result)->AddRef(); + } else { + // Unable to allocate space for the enumerator object. + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*--------------------- nsRegistry::EnumerateAllSubtrees ----------------------- +| Same as EnumerateSubtrees but we pass PR_TRUE to request that the | +| enumerator object descend subtrees when it is used. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::EnumerateAllSubtrees( Key baseKey, nsIEnumerator **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + *result = new nsRegSubtreeEnumerator( mReg,(RKEY)baseKey, PR_TRUE ); + // Check for success. + if( *result ) { + // Bump refcnt on behalf of caller. + (*result)->AddRef(); + } else { + // Unable to allocate space for the enumerator object. + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*------------------------- nsRegistry::GetValueType --------------------------- +| Gets the type from the registry using the NR_GetEntryInfo libreg API. | +| The result is transferred to the uint32 value passed in (with conversion | +| to the appropriate nsIRegistry::DataType value). | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetValueType( Key baseKey, const char *path, uint32 *result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + // Get registry info into local structure. + REGINFO info = { sizeof info, 0, 0 }; + mErr = NR_RegGetEntryInfo( mReg,(RKEY)baseKey,(char*)path, &info ); + if( mErr == REGERR_OK ) { + // Copy info to user's result value. + reginfo2DataType( info, *result ); + } else { + rv = regerr2nsresult( mErr ); + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*------------------------ nsRegistry::GetValueLength -------------------------- +| Gets the registry value info via NR_RegGetEntryInfo. The length is | +| converted to the proper "units" via reginfo2Length. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetValueLength( Key baseKey, const char *path, uint32 *result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + // Get registry info into local structure. + REGINFO info = { sizeof info, 0, 0 }; + mErr = NR_RegGetEntryInfo( mReg,(RKEY)baseKey,(char*)path, &info ); + if( mErr == REGERR_OK ) { + // Copy info to user's result value. + reginfo2Length( info, *result ); + } else { + rv = regerr2nsresult( mErr ); + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*------------------------ nsRegistry::EnumerateValues ------------------------- +| Allocates and returns an instance of nsRegValueEnumerator constructed in | +| a similar fashion as the nsRegSubtreeEnumerator is allocated/returned by | +| EnumerateSubtrees. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::EnumerateValues( Key baseKey, nsIEnumerator **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + *result = new nsRegValueEnumerator( mReg,(RKEY)baseKey ); + // Check for success. + if( *result ) { + // Bump refcnt on behalf of caller. + (*result)->AddRef(); + } else { + // Unable to allocate space for the enumerator object. + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------- nsRegistry::GetCurrentUserName ------------------------ +| Simple wrapper for NR_RegGetUsername. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::GetCurrentUserName( char **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + // Get the user name. + mErr = NR_RegGetUsername( result ); + // Convert the result. + rv = regerr2nsresult( mErr ); + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------- nsRegistry::SetCurrentUserName ------------------------ +| Simple wrapper for NR_RegSetUsername. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::SetCurrentUserName( const char *name ) { + nsresult rv = NS_OK; + // Set the user name. + mErr = NR_RegSetUsername( name ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*----------------------------- nsRegistry::Pack ------------------------------- +| Simple wrapper for NR_RegPack. We don't set up any callback. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistry::Pack() { + nsresult rv = NS_OK; + // Pack the registry. + mErr = NR_RegPack( mReg, 0, 0 ); + // Convert result. + rv = regerr2nsresult( mErr ); + return rv; +} + +/*-------------- nsRegSubtreeEnumerator::nsRegSubtreeEnumerator ---------------- +| The ctor simply stashes all the information that will be needed to enumerate | +| the subkeys. | +------------------------------------------------------------------------------*/ +nsRegSubtreeEnumerator::nsRegSubtreeEnumerator( HREG hReg, RKEY rKey, PRBool all ) + : mReg( hReg ), mKey( rKey ), mEnum( 0 ), mNext( 0 ), + mStyle( all ? REGENUM_DESCEND : 0 ), mDone( PR_FALSE ), mErr( -1 ) { + NS_INIT_REFCNT(); + return; +} + +/*----------------------- nsRegSubtreeEnumerator::First ------------------------ +| Set mEnum to 0; this will cause the next NR_RegEnum call to go to | +| the beginning. We then do a Next() call in order to do a "lookahead" to | +| properly detect an empty list (i.e., set the mDone flag). | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::First() { + nsresult rv = NS_OK; + // Reset "done" flag. + mDone = PR_FALSE; + // Go to beginning. + mEnum = mNext = 0; + // Lookahead so mDone flag gets set for empty list. + rv = Next(); + return rv; +} + +/*----------------------- nsRegSubtreeEnumerator::Last ------------------------- +| This can't be implemented using the libreg functions. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::Last() { + nsresult rv = NS_ERROR_NOT_IMPLEMENTED; + return rv; +} + +/*----------------------- nsRegSubtreeEnumerator::Next ------------------------- +| First, we check if we've already advanced to the end by checking the mDone | +| flag. | +| | +| We advance mEnum to the next enumeration value which is in the mNext | +| lookahead buffer. We must then call advance to lookahead and properly set | +| the isDone flag. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::Next() { + nsresult rv = NS_OK; + // Check for at end. + if ( !mDone ) { + // Advance to next spot. + mEnum = mNext; + // Lookahead so mDone is properly set (and to update mNext). + rv = advance(); + } else { + // Set result accordingly. + rv = regerr2nsresult( REGERR_NOMORE ); + } + return rv; +} + +/*---------------------- nsRegSubtreeEnumerator::advance ----------------------- +| Advance mNext to next subkey using NR_RegEnumSubkeys. We set mDone if | +| there are no more subkeys. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegSubtreeEnumerator::advance() { + char name[MAXREGPATHLEN]; + uint32 len = sizeof name; + mErr = NR_RegEnumSubkeys( mReg, mKey, &mNext, name, len, mStyle ); + // See if we ran off end. + if( mErr == REGERR_NOMORE ) { + // Remember we've run off end. + mDone = PR_TRUE; + } + // Convert result. + nsresult rv = regerr2nsresult( mErr ); + return rv; +}; + +/*----------------------- nsRegSubtreeEnumerator::Prev ------------------------- +| This can't be implemented on top of libreg. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::Prev() { + nsresult rv = NS_ERROR_NOT_IMPLEMENTED; + return rv; +} + +/*-------------------- nsRegSubtreeEnumerator::CurrentItem --------------------- +| Allocates and returns a new instance of class nsRegistryNode. The node | +| object will hold the curent mEnum value so it can obtain its name from | +| the registry when asked. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::CurrentItem( nsISupports **result) { + nsresult rv = NS_OK; + // Make sure there is a place to put the result. + if( result ) { + *result = new nsRegistryNode( mReg, mKey, mEnum ); + if( *result ) { + (*result)->AddRef(); + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------- nsRegSubtreeEnumerator::IsDone ------------------------ +| Simply return mDone. | +------------------------------------------------------------------------------*/ +nsresult nsRegSubtreeEnumerator::IsDone() { + nsresult rv = mDone; + return rv; +} + + +/*---------------- nsRegValueEnumerator::nsRegValueEnumerator ------------------ +| Delegates everything to the base class constructor. | +------------------------------------------------------------------------------*/ +nsRegValueEnumerator::nsRegValueEnumerator( HREG hReg, RKEY rKey ) + : nsRegSubtreeEnumerator( hReg, rKey, PR_FALSE ) { + return; +} + + +/*--------------------- nsRegValueEnumerator::CurrentItem ---------------------- +| As the nsRegSubtreeEnumerator counterpart, but allocates an object of | +| class nsRegistryValue. | +------------------------------------------------------------------------------*/ +nsresult nsRegValueEnumerator::CurrentItem( nsISupports **result ) { + nsresult rv = NS_OK; + // Make sure there is a place to put the result. + if( result ) { + *result = new nsRegistryValue( mReg, mKey, mEnum ); + if( *result ) { + (*result)->AddRef(); + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*----------------------- nsRegValueEnumerator::advance ------------------------ +| Advance mNext to next subkey using NR_RegEnumEntries. We set mDone if | +| there are no more entries. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegValueEnumerator::advance() { + char name[MAXREGNAMELEN]; + uint32 len = sizeof name; + REGINFO info = { sizeof info, 0, 0 }; + mErr = NR_RegEnumEntries( mReg, mKey, &mNext, name, len, &info ); + // See if we ran off end. + if( mErr == REGERR_NOMORE ) { + // Remember we've run off end. + mDone = PR_TRUE; + } + // Convert result. + nsresult rv = regerr2nsresult( mErr ); + return rv; +}; + + +/*---------------------- nsRegistryNode::nsRegistryNode ------------------------ +| Store the arguments in the corresponding data members and initialize | +| the other data members. We defer the libreg calls till we're asked for | +| our name. We use mErr==-1 to indicate we haven't fetched the name yet. | +------------------------------------------------------------------------------*/ +nsRegistryNode::nsRegistryNode( HREG hReg, RKEY key, REGENUM slot ) + : mReg( hReg ), mKey( key ), mEnum( slot ), mErr( -1 ) { + NS_INIT_REFCNT(); + return; +} + + +/*-------------------------------- PR_strdup ----------------------------------- +| Utility function that does PR_Malloc and copies argument string. Caller | +| must do PR_Free. | +------------------------------------------------------------------------------*/ +static char *PR_strdup( const char *in ) { + char *result = (char*)PR_Malloc( strlen( in ) + 1 ); + if ( result ) { + strcpy( result, in ); + } + return result; +} + +/*-------------------------- nsRegistryNode::GetName --------------------------- +| If we haven't fetched it yet, get the name of the corresponding subkey now, | +| using NR_RegEnumSubkeys. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistryNode::GetName( char **result ) { + nsresult rv = NS_OK; + // Make sure there is a place to put the result. + if( result ) { + // Test whether we haven't tried to get it yet. + if( mErr == -1 ) { + REGENUM temp = mEnum; + // Get name. + mErr = NR_RegEnumSubkeys( mReg, mKey, &temp, mName, sizeof mName, PR_FALSE ); + } + // Convert result from prior libreg call. + rv = regerr2nsresult( mErr ); + if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) { + // worked, return actual result. + *result = PR_strdup( mName ); + if ( *result ) { + rv = NS_OK; + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + + + +/*--------------------- nsRegistryValue::nsRegistryValue ----------------------- +| Implemented the same way as the nsRegistryNode ctor. | +------------------------------------------------------------------------------*/ +nsRegistryValue::nsRegistryValue( HREG hReg, RKEY key, REGENUM slot ) + : mReg( hReg ), mKey( key ), mEnum( slot ), mErr( -1 ) { + NS_INIT_REFCNT(); + return; +} + +/*------------------------- nsRegistryValue::GetName --------------------------- +| See nsRegistryNode::GetName; we use NR_RegEnumEntries in this case. | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistryValue::GetName( char **result ) { + nsresult rv = NS_OK; + // Make sure we have a place to put the result. + if( result ) { + // Ensure we've got the info we need. + rv = getInfo(); + if( rv == NS_OK || rv == NS_ERROR_REG_NO_MORE ) { + // worked, return actual result. + *result = PR_strdup( mName ); + if ( *result ) { + rv = NS_OK; + } else { + rv = NS_ERROR_OUT_OF_MEMORY; + } + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*----------------------- nsRegistryValue::GetValueType ------------------------ +| We test if we've got the info already. If not, we git it by calling | +| getInfo. We calculate the result by converting the REGINFO type field to | +| a nsIRegistry::DataType value (using reginfo2DataType). | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistryValue::GetValueType( uint32 *result ) { + nsresult rv = NS_OK; + // Make sure we have room for th result. + if( result ) { + // Make sure we've got the info we need. + rv = getInfo(); + // Check if it worked. + if( rv == NS_OK ) { + // Convert result from REGINFO to nsIRegistry::ValueInfo. + reginfo2DataType( mInfo, *result ); + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*---------------------- nsRegistryValue::GetValueLength ----------------------- +| We test if we've got the info already. If not, we git it by calling | +| getInfo. We calculate the result by converting the REGINFO type field to | +| a nsIRegistry::DataType value (using reginfo2Length). | +------------------------------------------------------------------------------*/ +NS_IMETHODIMP nsRegistryValue::GetValueLength( uint32 *result ) { + nsresult rv = NS_OK; + // Make sure we have room for th result. + if( result ) { + // Make sure we've got the info we need. + rv = getInfo(); + // Check if it worked. + if( rv == NS_OK ) { + // Convert result from REGINFO to length. + reginfo2Length( mInfo, *result ); + } + } else { + rv = NS_ERROR_NULL_POINTER; + } + return rv; +} + +/*------------------------- nsRegistryValue::getInfo --------------------------- +| Call NR_RegEnumEntries to set the mInfo/mName data members. | +------------------------------------------------------------------------------*/ +nsresult nsRegistryValue::getInfo() { + nsresult rv = NS_OK; + // Test whether we haven't tried to get it yet. + if( mErr == -1 ) { + REGENUM temp = mEnum; + // Get name and info. + mErr = NR_RegEnumEntries( mReg, mKey, &temp, mName, sizeof mName, &mInfo ); + // Convert result. + rv = regerr2nsresult( mErr ); + } + return rv; +} + + +nsRegistryFactory::nsRegistryFactory() { + NS_INIT_REFCNT(); +} + +NS_IMPL_ISUPPORTS(nsRegistryFactory, kIFactoryIID); + +NS_IMETHODIMP +nsRegistryFactory::CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult) { + nsresult rv = NS_OK; + nsRegistry* newRegistry; + + if(aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } else { + *aResult = NULL; + } + + if(0 != aOuter) { + return NS_ERROR_NO_AGGREGATION; + } + + NS_NEWXPCOM(newRegistry, nsRegistry); + + if(newRegistry == NULL) { + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(newRegistry); + rv = newRegistry->QueryInterface(aIID, aResult); + NS_RELEASE(newRegistry); + + return rv; +} + +nsresult +nsRegistryFactory::LockFactory(PRBool aLock) +{ + // Not implemented in simplest case. + return NS_OK; +} + +// This is a temporary hack; needs work to support dynamic binding +// via nsRepository and support for multiple factories per DLL. +extern "C" NS_EXPORT nsresult +nsRegistry_GetFactory(const nsCID &cid, nsISupports* servMgr, nsIFactory** aFactory ) { + nsresult rv = NS_OK; + + if( aFactory == 0 ) { + return NS_ERROR_NULL_POINTER; + } else { + *aFactory = 0; + } + + nsIFactory* inst = new nsRegistryFactory(); + if(0 == inst) { + rv = NS_ERROR_OUT_OF_MEMORY; + } else { + NS_ADDREF(inst); + *aFactory = inst; + } + + return rv; +} diff --git a/xpcom/tools/registry/makefile.win b/xpcom/tools/registry/makefile.win index dbe5fb5e4c0..99c45fd400f 100644 --- a/xpcom/tools/registry/makefile.win +++ b/xpcom/tools/registry/makefile.win @@ -31,7 +31,6 @@ PROGRAMS = $(PROG1) LLIBS = \ $(LIBNSPR) \ $(DIST)\lib\xpcom$(MOZ_BITS).lib \ - $(DIST)\lib\libreg32.lib \ !if "$(MOZ_BITS)"=="32" && defined(MOZ_DEBUG) && defined(GLOWCODE) $(GLOWDIR)\glowcode.lib \ !endif diff --git a/xpcom/tools/registry/regExport.cpp b/xpcom/tools/registry/regExport.cpp index c4bc4967556..da6bd9d5d6b 100644 --- a/xpcom/tools/registry/regExport.cpp +++ b/xpcom/tools/registry/regExport.cpp @@ -18,30 +18,30 @@ #include -#include "mozIRegistry.h" +#include "nsIRegistry.h" #include "nsIEnumerator.h" #include "nsIFactory.h" #include "prmem.h" -// Hack to get to mozRegistry implementation. +// Hack to get to nsRegistry implementation. extern "C" NS_EXPORT nsresult -mozRegistry_GetFactory(const nsCID &cid, nsISupports* servMgr, nsIFactory** aFactory ); +nsRegistry_GetFactory(const nsCID &cid, nsISupports* servMgr, nsIFactory** aFactory ); -static void display( mozIRegistry *reg, mozIRegistry::Key root, const char *name ); -static void displayValues( mozIRegistry *reg, mozIRegistry::Key root ); +static void display( nsIRegistry *reg, nsIRegistry::Key root, const char *name ); +static void displayValues( nsIRegistry *reg, nsIRegistry::Key root ); static void printString( const char *value, int indent ); int main( int argc, char *argv[] ) { - // Get mozRegistry factory. - nsCID cid = MOZ_IREGISTRY_IID; // Not really an IID, but this factory stuff is a hack anyway. + // Get nsRegistry factory. + nsCID cid = NS_IREGISTRY_IID; // Not really an IID, but this factory stuff is a hack anyway. nsIFactory *factory; - nsresult rv = mozRegistry_GetFactory( cid, 0, &factory ); + nsresult rv = nsRegistry_GetFactory( cid, 0, &factory ); // Check result. if ( rv == NS_OK ) { // Create registry implementation object. - nsIID regIID = MOZ_IREGISTRY_IID; - mozIRegistry *reg; + nsIID regIID = NS_IREGISTRY_IID; + nsIRegistry *reg; rv = factory->CreateInstance( 0, regIID, (void**)® ); // Check result. @@ -56,9 +56,9 @@ int main( int argc, char *argv[] ) { printf( "Registry %s opened OK.\n", argv[1] ? argv[1] : "" ); // Recurse over all 3 branches. - display( reg, mozIRegistry::Common, "mozRegistry::Common" ); - display( reg, mozIRegistry::Users, "mozRegistry::Users" ); - display( reg, mozIRegistry::Common, "mozRegistry::CurrentUser" ); + display( reg, nsIRegistry::Common, "nsRegistry::Common" ); + display( reg, nsIRegistry::Users, "nsRegistry::Users" ); + display( reg, nsIRegistry::Common, "nsRegistry::CurrentUser" ); } else { printf( "Error opening registry file %s, rv=0x%08X\n", argv[1] ? argv[1] : "", (int)rv ); @@ -66,18 +66,18 @@ int main( int argc, char *argv[] ) { // Release the registry. reg->Release(); } else { - printf( "Error creating mozRegistry object, rv=0x%08X\n", (int)rv ); + printf( "Error creating nsRegistry object, rv=0x%08X\n", (int)rv ); } // Release the factory. factory->Release(); } else { - printf( "Error creating mozRegistry factory, rv=0x%08X\n", (int)rv ); + printf( "Error creating nsRegistry factory, rv=0x%08X\n", (int)rv ); } return rv; } -void display( mozIRegistry *reg, mozIRegistry::Key root, const char *rootName ) { +void display( nsIRegistry *reg, nsIRegistry::Key root, const char *rootName ) { // Enumerate all subkeys under the given node. nsIEnumerator *keys; nsresult rv = reg->EnumerateAllSubtrees( root, &keys ); @@ -95,8 +95,8 @@ void display( mozIRegistry *reg, mozIRegistry::Key root, const char *rootName ) // Test result. if ( rv == NS_OK ) { // Get specific interface. - mozIRegistryNode *node; - nsIID nodeIID = MOZ_IREGISTRYNODE_IID; + nsIRegistryNode *node; + nsIID nodeIID = NS_IREGISTRYNODE_IID; rv = base->QueryInterface( nodeIID, (void**)&node ); // Test that result. if ( rv == NS_OK ) { @@ -108,7 +108,7 @@ void display( mozIRegistry *reg, mozIRegistry::Key root, const char *rootName ) // Print name: printf( "\t%s\n", name ); // Display values under this key. - mozIRegistry::Key key; + nsIRegistry::Key key; rv = reg->GetSubtree( root, name, &key ); if ( rv == NS_OK ) { displayValues( reg, key ); @@ -147,7 +147,7 @@ void display( mozIRegistry *reg, mozIRegistry::Key root, const char *rootName ) return; } -static void displayValues( mozIRegistry *reg, mozIRegistry::Key root ) { +static void displayValues( nsIRegistry *reg, nsIRegistry::Key root ) { // Emumerate values at this registry location. nsIEnumerator *values; nsresult rv = reg->EnumerateValues( root, &values ); @@ -164,8 +164,8 @@ static void displayValues( mozIRegistry *reg, mozIRegistry::Key root ) { // Test result. if ( rv == NS_OK ) { // Get specific interface. - mozIRegistryValue *value; - nsIID valueIID = MOZ_IREGISTRYVALUE_IID; + nsIRegistryValue *value; + nsIID valueIID = NS_IREGISTRYVALUE_IID; rv = base->QueryInterface( valueIID, (void**)&value ); // Test that result. if ( rv == NS_OK ) { @@ -182,7 +182,7 @@ static void displayValues( mozIRegistry *reg, mozIRegistry::Key root ) { if ( rv == NS_OK ) { // Print value contents. switch ( type ) { - case mozIRegistry::String: { + case nsIRegistry::String: { char *value; rv = reg->GetString( root, name, &value ); if ( rv == NS_OK ) { @@ -194,15 +194,15 @@ static void displayValues( mozIRegistry *reg, mozIRegistry::Key root ) { } break; - case mozIRegistry::Int32: + case nsIRegistry::Int32: printf( "\t= Int32" ); break; - case mozIRegistry::Bytes: + case nsIRegistry::Bytes: printf( "\t= Bytes" ); break; - case mozIRegistry::File: + case nsIRegistry::File: printf( "\t= File (?)" ); break;