Per bug 3690:

Added new functions to the registry for reading / writing byte arrays
of binary content and escaping registry keys that contain binary
content.  Modified code which reads/writes location of dll or javascript
for components to use new ReadBytesUTF8/WriteBytesUTF8 and which uses
or reads the keys to use EscapeKey and UnescapeKey.

r=dveditz
This commit is contained in:
rayw%netscape.com 2000-05-12 01:24:36 +00:00
parent 71c6e11ea9
commit d0199a10bc
8 changed files with 835 additions and 202 deletions

View File

@ -51,11 +51,17 @@ interface nsIRegistry : nsISupports
string getStringUTF8(in nsRegistryKey baseKey, in string path);
void setStringUTF8(in nsRegistryKey baseKey, in string path, in string value);
void getBytesUTF8(in nsRegistryKey baseKey, in string path, out PRUint32 length, [retval, array, size_is(length)] out PRUint8 valueArray);
void setBytesUTF8(in nsRegistryKey baseKey, in string path, in PRUint32 length, [array, size_is(length)] in PRUint8 valueArray);
PRInt32 getInt(in nsRegistryKey baseKey, in string path);
void setInt(in nsRegistryKey baseKey, in string path, in PRInt32 value);
PRInt64 getLongLong(in nsRegistryKey baseKey, in string path);
void setLongLong(in nsRegistryKey baseKey, in string path, inout PRInt64 value);
/**
* addSubtree() and friends need to be renamed to addKeyUTF8().
* If you are using these forms make sure you pass UTF8 data
*/
nsRegistryKey addSubtree(in nsRegistryKey baseKey, in string path);
void removeSubtree(in nsRegistryKey baseKey, in string path);
nsRegistryKey getSubtree(in nsRegistryKey baseKey, in string path);
@ -77,6 +83,13 @@ interface nsIRegistry : nsISupports
PRUint32 getValueLength(in nsRegistryKey baseKey, in string path);
void deleteValue(in nsRegistryKey baseKey, in string path);
/**
* escapeKey() takes arbitrary binary data and converts it into
* valid ASCII which can be used as registry key or value names
*/
void escapeKey([array, size_is(length)] in PRUint8 key, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 escaped);
void unescapeKey([array, size_is(length)] in PRUint8 escaped, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 key);
attribute string currentUserName;
void pack();

View File

@ -73,9 +73,9 @@ struct nsRegistry : public nsIRegistry {
protected:
HREG mReg; // Registry handle.
#ifdef EXTRA_THREADSAFE
PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize.
PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize.
#endif
char *mCurRegFile; // these are to prevent open from opening the registry again
char *mCurRegFile; // these are to prevent open from opening the registry again
nsWellKnownRegistry mCurRegID;
NS_IMETHOD Close();
@ -167,7 +167,7 @@ struct nsRegistryNode : public nsIRegistryNode {
protected:
HREG mReg; // Handle to registry this node is part of.
char mName[MAXREGPATHLEN]; // Buffer to hold name.
RKEY mChildKey; // Key corresponding to mName
RKEY mChildKey; // Key corresponding to mName
#ifdef EXTRA_THREADSAFE
PRLock *mregLock;
#endif
@ -735,6 +735,94 @@ NS_IMETHODIMP nsRegistry::SetStringUTF8( nsRegistryKey baseKey, const char *path
return regerr2nsresult( err );
}
/*---------------------------- nsRegistry::GetBytesUTF8 ------------------------------
| This function is just shorthand for fetching a char array. We |
| implement it "manually" using NR_RegGetEntry |
------------------------------------------------------------------------------*/
NS_IMETHODIMP nsRegistry::GetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32* length, PRUint8** result) {
nsresult rv = NS_OK;
REGERR err = REGERR_OK;
if ( !result )
return NS_ERROR_NULL_POINTER;
char regStr[MAXREGPATHLEN];
// initialize the return value
*length = 0;
*result = 0;
// Get info about the requested entry.
PRUint32 type;
rv = GetValueType( baseKey, path, &type );
// See if that worked.
if( rv == NS_OK )
{
// Make sure the entry is an PRInt8 array.
if( type == Bytes )
{
// Attempt to get string into our fixed buffer
PR_Lock(mregLock);
uint32 length2 = sizeof regStr;
err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), regStr, &length2);
PR_Unlock(mregLock);
if ( err == REGERR_OK )
{
*length = length2;
*result = (PRUint8*)(nsCRT::strdup(regStr));
if (!*result)
{
rv = NS_ERROR_OUT_OF_MEMORY;
*length = 0;
}
else
{
*length = length2;
}
}
else if ( err == REGERR_BUFTOOSMALL )
{
// find the real size and malloc it
rv = GetValueLength( baseKey, path, length );
// See if that worked.
if( rv == NS_OK )
{
*result = NS_REINTERPRET_CAST(PRUint8*,nsAllocator::Alloc( *length ));
if( *result )
{
// Get bytes from registry into result field.
PR_Lock(mregLock);
length2 = *length;
err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), *result, &length2);
*length = length2;
PR_Unlock(mregLock);
// Convert status.
rv = regerr2nsresult( err );
if ( rv != NS_OK )
{
// Didn't get result, free buffer
nsCRT::free( NS_REINTERPRET_CAST(char*, *result) );
*result = 0;
*length = 0;
}
}
else
{
rv = NS_ERROR_OUT_OF_MEMORY;
}
}
}
}
else
{
// They asked for the wrong type of value.
rv = NS_ERROR_REG_BADTYPE;
}
}
return rv;
}
/*---------------------------- nsRegistry::GetInt ------------------------------
| This function is just shorthand for fetching a 1-element PRInt32 array. We |
| implement it "manually" using NR_RegGetEntry |
@ -788,6 +876,24 @@ NS_IMETHODIMP nsRegistry::GetLongLong( nsRegistryKey baseKey, const char *path,
// Convert status.
return regerr2nsresult( err );
}
/*---------------------------- nsRegistry::SetBytesUTF8 ------------------------------
| Write out the value as a char array, using NR_RegSetEntry. |
------------------------------------------------------------------------------*/
NS_IMETHODIMP nsRegistry::SetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32 length, PRUint8* value) {
REGERR err = REGERR_OK;
// Set the contents.
PR_Lock(mregLock);
err = NR_RegSetEntry( mReg,
(RKEY)baseKey,
(char*)path,
REGTYPE_ENTRY_BYTES,
(char*)value,
length);
PR_Unlock(mregLock);
// Convert result.
return regerr2nsresult( err );
}
/*---------------------------- nsRegistry::SetInt ------------------------------
| Write out the value as a one-element PRInt32 array, using NR_RegSetEntry. |
------------------------------------------------------------------------------*/
@ -862,8 +968,8 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path
nsresult rv = NS_OK;
REGERR err = REGERR_OK;
// libreg doesn't delete keys if there are subkeys under the key
// Hence we have to recurse through to delete the subtree
// libreg doesn't delete keys if there are subkeys under the key
// Hence we have to recurse through to delete the subtree
RKEY key;
@ -871,13 +977,13 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path
err = NR_RegGetKey(mReg, baseKey, (char *)path, &key);
PR_Unlock(mregLock);
if (err != REGERR_OK)
{
rv = regerr2nsresult( err );
{
rv = regerr2nsresult( err );
return rv;
}
}
// Now recurse through and delete all keys under hierarchy
char subkeyname[MAXREGPATHLEN+1];
REGENUM state = 0;
subkeyname[0] = '\0';
@ -885,7 +991,7 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path
REGENUM_NORMAL) == REGERR_OK)
{
#ifdef DEBUG_dp
printf("...recursing into %s\n", subkeyname);
printf("...recursing into %s\n", subkeyname);
#endif /* DEBUG_dp */
// Even though this is not a "Raw" API the subkeys may still, in fact,
// *be* raw. Since we're recursively deleting this will work either way.
@ -899,15 +1005,15 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path
if (err == REGERR_OK)
{
#ifdef DEBUG_dp
printf("...deleting %s\n", path);
printf("...deleting %s\n", path);
#endif /* DEBUG_dp */
PR_Lock(mregLock);
err = NR_RegDeleteKey(mReg, baseKey, (char *)path);
PR_Unlock(mregLock);
}
// Convert result.
rv = regerr2nsresult( err );
// Convert result.
rv = regerr2nsresult( err );
return rv;
}
@ -919,8 +1025,8 @@ NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *k
nsresult rv = NS_OK;
REGERR err = REGERR_OK;
// libreg doesn't delete keys if there are subkeys under the key
// Hence we have to recurse through to delete the subtree
// libreg doesn't delete keys if there are subkeys under the key
// Hence we have to recurse through to delete the subtree
RKEY key;
char subkeyname[MAXREGPATHLEN+1];
@ -931,18 +1037,18 @@ NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *k
err = NR_RegGetKeyRaw(mReg, baseKey, (char *)keyname, &key);
PR_Unlock(mregLock);
if (err != REGERR_OK)
{
rv = regerr2nsresult( err );
{
rv = regerr2nsresult( err );
return rv;
}
}
// Now recurse through and delete all keys under hierarchy
subkeyname[0] = '\0';
while (NR_RegEnumSubkeys(mReg, key, &state, subkeyname, n, REGENUM_NORMAL) == REGERR_OK)
{
#ifdef DEBUG_dp
printf("...recursing into %s\n", subkeyname);
printf("...recursing into %s\n", subkeyname);
#endif /* DEBUG_dp */
err = RemoveSubtreeRaw(key, subkeyname);
if (err != REGERR_OK) break;
@ -952,15 +1058,15 @@ NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *k
if (err == REGERR_OK)
{
#ifdef DEBUG_dp
printf("...deleting %s\n", keyname);
printf("...deleting %s\n", keyname);
#endif /* DEBUG_dp */
PR_Lock(mregLock);
err = NR_RegDeleteKeyRaw(mReg, baseKey, (char *)keyname);
PR_Unlock(mregLock);
}
// Convert result.
rv = regerr2nsresult( err );
// Convert result.
rv = regerr2nsresult( err );
return rv;
}
/*-------------------------- nsRegistry::GetSubtree ----------------------------
@ -1196,6 +1302,157 @@ NS_IMETHODIMP nsRegistry::Pack() {
return rv;
}
/*----------------------------- nsRegistry::EscapeKey -------------------------------
| Escape a binary key so that the registry works OK, since it expects UTF8
| with no slashes or control characters. This is probably better than raw.
| If no escaping is required, then the method is successful and a null is
| returned, indicating that the caller should use the original string.
------------------------------------------------------------------------------*/
static const char sEscapeKeyHex[] = "0123456789abcdef0123456789ABCDEF";
NS_IMETHODIMP nsRegistry::EscapeKey(PRUint8* key, PRUint32 termination, PRUint32* length, PRUint8** escaped)
{
nsresult rv = NS_OK;
char* value = (char*)key;
char* b = value;
char* e = b + *length;
int escapees = 0;
while (b < e) // Count characters outside legal range or slash
{
int c = *b++;
if (c <= ' '
|| c > '~'
|| c == '/'
|| c == '%')
{
escapees++;
}
}
if (escapees == 0) // If no escapees, then no results
{
*length = 0;
*escaped = nsnull;
return NS_OK;
}
// New length includes two extra chars for escapees.
*length += escapees * 2;
*escaped = (PRUint8*)nsAllocator::Alloc(*length + termination);
if (*escaped == nsnull)
{
*length = 0;
*escaped = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
char* n = (char*)*escaped;
b = value;
while (escapees && b < e)
{
char c = *b++;
if (c < ' '
|| c > '~'
|| c == '/'
|| c == '%')
{
*(n++) = '%';
*(n++) = sEscapeKeyHex[ 0xF & (c >> 4) ];
*(n++) = sEscapeKeyHex[ 0xF & c ];
escapees--;
}
else
{
*(n++) = c;
}
}
e += termination;
if (b < e)
{
strncpy(n, b, e - b);
}
return rv;
}
/*----------------------------- nsRegistry::UnescapeKey -------------------------------
| Unscape a binary key so that the registry works OK, since it expects UTF8
| with no slashes or control characters. This is probably better than raw.
| If no escaping is required, then the method is successful and a null is
| returned, indicating that the caller should use the original string.
------------------------------------------------------------------------------*/
NS_IMETHODIMP nsRegistry::UnescapeKey(PRUint8* escaped, PRUint32 termination, PRUint32* length, PRUint8** key)
{
nsresult rv = NS_OK;
char* value = (char*)escaped;
char* b = value;
char* e = b + *length;
int escapees = 0;
while (b < e) // Count characters outside legal range or slash
{
if (*b++ == '%')
{
escapees++;
}
}
if (escapees == 0) // If no escapees, then no results
{
*length = 0;
*key = nsnull;
return NS_OK;
}
// New length includes two extra chars for escapees.
*length -= escapees * 2;
*key = (PRUint8*)nsAllocator::Alloc(*length + termination);
if (*key == nsnull)
{
*length = 0;
*key = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
char* n = (char*)*key;
b = value;
while (escapees && b < e)
{
char c = *(b++);
if (c == '%')
{
if (e - b >= 2)
{
char* c1 = strchr(sEscapeKeyHex, *(b++));
char* c2 = strchr(sEscapeKeyHex, *(b++));
if (c1 != nsnull
&& c2 != nsnull)
{
*(n++) = ((c2 - sEscapeKeyHex) & 0xF)
| (((c1 - sEscapeKeyHex) & 0xF) << 4);
}
else
{
escapees = -1;
}
}
else
{
escapees = -1;
}
escapees--;
}
else
{
*(n++) = c;
}
}
if (escapees < 0)
{
nsAllocator::Free(*key);
*length = 0;
*key = nsnull;
return NS_ERROR_INVALID_ARG;
}
e += termination;
if (b < e)
{
strncpy(n, b, e - b);
}
return rv;
}
/*-------------- nsRegSubtreeEnumerator::nsRegSubtreeEnumerator ----------------
| The ctor simply stashes all the information that will be needed to enumerate |
| the subkeys. |
@ -1437,7 +1694,7 @@ NS_IMETHODIMP nsRegistryNode::GetNameUTF8( char **result ) {
}
/*-------------------------- nsRegistryNode::GetKey ----------------------------
| Get the subkey corresponding to this node |
| Get the subkey corresponding to this node |
| using NR_RegEnumSubkeys. |
------------------------------------------------------------------------------*/
NS_IMETHODIMP nsRegistryNode::GetKey( nsRegistryKey *r_key ) {

View File

@ -123,32 +123,32 @@ extern PRBool gShuttingDown;
nsresult
nsCreateInstanceByCID::operator()( const nsIID& aIID, void** aInstancePtr ) const
{
nsresult status = nsComponentManager::CreateInstance(mCID, mOuter, aIID, aInstancePtr);
if ( !NS_SUCCEEDED(status) )
*aInstancePtr = 0;
{
nsresult status = nsComponentManager::CreateInstance(mCID, mOuter, aIID, aInstancePtr);
if ( !NS_SUCCEEDED(status) )
*aInstancePtr = 0;
if ( mErrorPtr )
*mErrorPtr = status;
return status;
}
if ( mErrorPtr )
*mErrorPtr = status;
return status;
}
nsresult
nsCreateInstanceByProgID::operator()( const nsIID& aIID, void** aInstancePtr ) const
{
nsresult status;
if ( mProgID )
{
if ( !NS_SUCCEEDED(status = nsComponentManager::CreateInstance(mProgID, mOuter, aIID, aInstancePtr)) )
*aInstancePtr = 0;
}
else
status = NS_ERROR_NULL_POINTER;
{
nsresult status;
if ( mProgID )
{
if ( !NS_SUCCEEDED(status = nsComponentManager::CreateInstance(mProgID, mOuter, aIID, aInstancePtr)) )
*aInstancePtr = 0;
}
else
status = NS_ERROR_NULL_POINTER;
if ( mErrorPtr )
*mErrorPtr = status;
return status;
}
if ( mErrorPtr )
*mErrorPtr = status;
return status;
}
/* prototypes for the Mac */
PRBool PR_CALLBACK
@ -211,7 +211,7 @@ nsCID_Destroy(nsHashKey *aKey, void *aData, void* closure)
nsCID* entry = NS_STATIC_CAST(nsCID*, aData);
// nasty hack. We "know" that kNoCID was entered into the hash table.
if (entry != &kNoCID)
delete entry;
delete entry;
return PR_TRUE;
}
@ -260,11 +260,11 @@ nsresult nsComponentManagerImpl::Init(void)
}
if (mLoaders == nsnull) {
mLoaders = new nsSupportsHashtable(16, /* Thread safe */ PR_TRUE);
if (mLoaders == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
nsStringKey loaderKey(nativeComponentType);
mLoaders->Put(&loaderKey, mNativeComponentLoader);
mLoaders = new nsSupportsHashtable(16, /* Thread safe */ PR_TRUE);
if (mLoaders == nsnull)
return NS_ERROR_OUT_OF_MEMORY;
nsStringKey loaderKey(nativeComponentType);
mLoaders->Put(&loaderKey, mNativeComponentLoader);
}
#ifdef USE_REGISTRY
@ -306,12 +306,12 @@ nsresult nsComponentManagerImpl::Shutdown(void)
#endif /* USE_REGISTRY */
// This is were the nsFileSpec was deleted, so I am
// going to assign zero to
mComponentsDir = 0;
// going to assign zero to
mComponentsDir = 0;
// Release all the component loaders
if (mLoaders)
delete mLoaders;
delete mLoaders;
// we have an extra reference on this one, which is probably a good thing
NS_IF_RELEASE(mNativeComponentLoader);
@ -358,7 +358,7 @@ nsComponentManagerImpl::PlatformInit(void)
// We need to create our registry. Since we are in the constructor
// we haven't gone as far as registering the registry factory.
// Hence, we hand create a registry.
if (mRegistry == NULL) {
if (mRegistry == NULL) {
nsIFactory *registryFactory = NULL;
rv = NS_RegistryGetFactory(&registryFactory);
if (NS_SUCCEEDED(rv))
@ -452,15 +452,15 @@ nsComponentManagerImpl::PlatformInit(void)
if (!mComponentsDir)
return NS_ERROR_OUT_OF_MEMORY;
char* componentDescriptor;
mComponentsDir->GetPath(&componentDescriptor);
if (!componentDescriptor)
return NS_ERROR_NULL_POINTER;
char* componentDescriptor;
mComponentsDir->GetPath(&componentDescriptor);
if (!componentDescriptor)
return NS_ERROR_NULL_POINTER;
mComponentsOffset = strlen(componentDescriptor);
if (componentDescriptor)
nsAllocator::Free(componentDescriptor);
mComponentsOffset = strlen(componentDescriptor);
if (componentDescriptor)
nsAllocator::Free(componentDescriptor);
@ -549,6 +549,7 @@ nsComponentManagerImpl::PlatformVersionCheck(nsRegistryKey *aXPCOMRootKey)
}
#if 0
// If ever revived, this code is not fully updated to escape the dll location
void
nsComponentManagerImpl::PlatformSetFileInfo(nsRegistryKey key, PRUint32 lastModifiedTime, PRUint32 fileSize)
{
@ -561,7 +562,7 @@ nsComponentManagerImpl::PlatformSetFileInfo(nsRegistryKey key, PRUint32 lastModi
*
* Stores the dll name, last modified time, size and 0 for number of
* components in dll in the registry at location
* ROOTKEY_COMMON/Software/Mozilla/XPCOM/Components/dllname
* ROOTKEY_COMMON/Software/Mozilla/XPCOM/Components/dllname
*/
nsresult
nsComponentManagerImpl::PlatformMarkNoComponents(nsDll *dll)
@ -576,7 +577,7 @@ nsComponentManagerImpl::PlatformMarkNoComponents(nsDll *dll)
{
return rv;
}
PlatformSetFileInfo(dllPathKey, dll->GetLastModifiedTime(), dll->GetSize());
rv = mRegistry->SetInt(dllPathKey, componentCountValueName, 0);
@ -605,7 +606,9 @@ nsComponentManagerImpl::PlatformRegister(const char *cidString,
{
rv = mRegistry->SetStringUTF8(IDkey,progIDValueName, progID);
}
rv = mRegistry->SetStringUTF8(IDkey, inprocServerValueName, dll->GetPersistentDescriptorString());
rv = mRegistry->SetBytesUTF8(IDkey, inprocServerValueName,
strlen(dll->GetPersistentDescriptorString()) + 1,
NS_REINTERPRET_CAST(char*, dll->GetPersistentDescriptorString()));
if (progID)
{
@ -631,10 +634,21 @@ nsComponentManagerImpl::PlatformRegister(const char *cidString,
nsresult
nsComponentManagerImpl::PlatformUnregister(const char *cidString,
const char *aLibrary)
{
{
nsresult rv;
PRUint32 length = strlen(aLibrary);
char* eLibrary;
rv = mRegistry->EscapeKey((PRUint8*)aLibrary, 1, &length, (PRUint8**)&eLibrary);
if (rv != NS_OK)
{
return rv;
}
if (eLibrary == nsnull) // No escaping required
eLibrary = (char*)aLibrary;
PR_ASSERT(mRegistry!=NULL);
nsresult rv;
nsRegistryKey cidKey;
rv = mRegistry->AddSubtreeRaw(mCLSIDKey, cidString, &cidKey);
@ -648,9 +662,9 @@ nsComponentManagerImpl::PlatformUnregister(const char *cidString,
}
mRegistry->RemoveSubtree(mCLSIDKey, cidString);
nsRegistryKey libKey;
rv = mRegistry->GetSubtreeRaw(mXPCOMKey, aLibrary, &libKey);
rv = mRegistry->GetSubtreeRaw(mXPCOMKey, eLibrary, &libKey);
if(NS_FAILED(rv)) return rv;
// We need to reduce the ComponentCount by 1.
@ -662,13 +676,16 @@ nsComponentManagerImpl::PlatformUnregister(const char *cidString,
if (nComponents <= 0)
{
rv = mRegistry->RemoveSubtreeRaw(mXPCOMKey, aLibrary);
rv = mRegistry->RemoveSubtreeRaw(mXPCOMKey, eLibrary);
}
else
{
rv = mRegistry->SetInt(libKey, componentCountValueName, nComponents);
}
if (eLibrary != aLibrary)
nsAllocator::Free(eLibrary);
return rv;
}
@ -688,8 +705,9 @@ nsComponentManagerImpl::PlatformFind(const nsCID &aCID, nsFactoryEntry* *result)
if (NS_FAILED(rv)) return rv;
nsXPIDLCString library;
rv = mRegistry->GetStringUTF8(cidKey, inprocServerValueName,
getter_Copies(library));
PRUint32 tmp;
rv = mRegistry->GetBytesUTF8(cidKey, inprocServerValueName,
&tmp, (PRUint8**)getter_Copies(library).operator char**());
if (NS_FAILED(rv))
{
// Registry inconsistent. No File name for CLSID.
@ -729,7 +747,7 @@ nsComponentManagerImpl::PlatformProgIDToCLSID(const char *aProgID, nsCID *aClass
PR_ASSERT(mRegistry);
nsresult rv;
nsRegistryKey progIDKey;
rv = mRegistry->GetSubtreeRaw(mClassesKey, aProgID, &progIDKey);
if (NS_FAILED(rv)) return NS_ERROR_FACTORY_NOT_REGISTERED;
@ -750,7 +768,7 @@ nsresult
nsComponentManagerImpl::PlatformCLSIDToProgID(const nsCID *aClass,
char* *aClassName, char* *aProgID)
{
PR_ASSERT(aClass);
PR_ASSERT(mRegistry);
@ -809,8 +827,9 @@ nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry()
// Create the CID entry
nsXPIDLCString library;
rv = mRegistry->GetStringUTF8(cidKey, inprocServerValueName,
getter_Copies(library));
PRUint32 tmp;
rv = mRegistry->GetBytesUTF8(cidKey, inprocServerValueName,
&tmp, (PRUint8**)getter_Copies(library).operator char**());
if (NS_FAILED(rv)) continue;
nsCID aClass;
@ -864,7 +883,7 @@ nsresult nsComponentManagerImpl::PlatformPrePopulateRegistry()
if (NS_FAILED(rv)) continue;
nsCID *aClass = new nsCID();
if (!aClass) continue; // Protect against out of memory.
if (!aClass) continue; // Protect against out of memory.
if (!(aClass->Parse(cidString)))
{
delete aClass;
@ -948,7 +967,7 @@ nsComponentManagerImpl::LoadFactory(nsFactoryEntry *aEntry,
(const char *)aEntry->location, (const char *)aEntry->type));
return rv;
}
return NS_OK;
}
@ -1031,7 +1050,7 @@ nsComponentManagerImpl::GetClassObject(const nsCID &aClass, const nsIID &aIID,
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
("\t\tGetClassObject() %s", NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
return rv;
}
@ -1164,7 +1183,7 @@ nsComponentManagerImpl::CreateInstance(const nsCID &aClass,
return NS_ERROR_NULL_POINTER;
}
*aResult = NULL;
nsIFactory *factory = NULL;
nsresult res = FindFactory(aClass, &factory);
if (NS_SUCCEEDED(res))
@ -1270,14 +1289,14 @@ nsComponentManagerImpl::RegistryLocationForSpec(nsIFile *aSpec,
char *persistentDescriptor;
if (containedIn){
rv = aSpec->GetPath(&persistentDescriptor);
rv = aSpec->GetPath(&persistentDescriptor);
if (NS_FAILED(rv))
return rv;
char* relativeLocation = persistentDescriptor + mComponentsOffset + 1;
rv = MakeRegistryName(relativeLocation, XPCOM_RELCOMPONENT_PREFIX,
char* relativeLocation = persistentDescriptor + mComponentsOffset + 1;
rv = MakeRegistryName(relativeLocation, XPCOM_RELCOMPONENT_PREFIX,
aRegistryName);
} else {
/* absolute names include volume info on Mac, so persistent descriptor */
@ -1400,11 +1419,11 @@ nsComponentManagerImpl::RegisterFactory(const nsCID &aClass,
return rv;
}
}
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
("\t\tFactory register succeeded progid=%s.",
aProgID ? aProgID : "<none>"));
return NS_OK;
}
@ -1535,17 +1554,17 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
rv = AddComponentToRegistry(aClass, className, progID,
aRegistryName, aType);
if (NS_FAILED(rv)) {
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tadding %s %s to registry FAILED", className, progID));
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tadding %s %s to registry FAILED", className, progID));
goto out;
}
}
}
#endif
rv = GetLoaderForType(aType, getter_AddRefs(loader));
if (NS_FAILED(rv)) {
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tgetting loader for %s FAILED\n", aType));
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tgetting loader for %s FAILED\n", aType));
goto out;
}
@ -1556,7 +1575,7 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
}
if (entry) { // aReplace implicit from test above
delete entry;
delete entry;
}
/* unless the fabric of the universe bends, we'll get entry back */
@ -1565,7 +1584,7 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
/* don't try to clean up, just drop everything and run */
if (!sanity)
return NS_ERROR_FACTORY_NOT_REGISTERED;
return NS_ERROR_FACTORY_NOT_REGISTERED;
/* we've put the new entry in the hash table, so don't delete on error */
newEntry = nsnull;
@ -1578,10 +1597,10 @@ nsComponentManagerImpl::RegisterComponentCommon(const nsCID &aClass,
) {
rv = HashProgID(progID, aClass);
if (NS_FAILED(rv)) {
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tHashProgID(%s) FAILED\n", progID));
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR,
("\t\tHashProgID(%s) FAILED\n", progID));
goto out;
}
}
}
// Let the loader do magic things now
@ -1615,9 +1634,9 @@ nsComponentManagerImpl::GetLoaderForType(const char *aType,
loader = (nsIComponentLoader *)mLoaders->Get(&typeKey);
if (loader) {
// nsSupportsHashtable does the AddRef
*aLoader = loader;
return NS_OK;
// nsSupportsHashtable does the AddRef
*aLoader = loader;
return NS_OK;
}
nsRegistryKey loaderKey;
@ -1634,7 +1653,7 @@ nsComponentManagerImpl::GetLoaderForType(const char *aType,
fprintf(stderr, "nCMI: constructing loader for type %s = %s\n", aType, progID);
#endif
rv = CreateInstanceByProgID(progID, nsnull, NS_GET_IID(nsIComponentLoader), (void **)&loader);
rv = CreateInstanceByProgID(progID, nsnull, NS_GET_IID(nsIComponentLoader), (void **)&loader);
PR_FREEIF(progID);
if (NS_FAILED(rv))
return rv;
@ -1642,8 +1661,8 @@ nsComponentManagerImpl::GetLoaderForType(const char *aType,
rv = loader->Init(this, mRegistry);
if (NS_SUCCEEDED(rv)) {
mLoaders->Put(&typeKey, loader);
*aLoader = loader;
mLoaders->Put(&typeKey, loader);
*aLoader = loader;
}
return rv;
}
@ -1676,6 +1695,16 @@ nsComponentManagerImpl::AddComponentToRegistry(const nsCID &aClass,
const char *aType)
{
nsresult rv;
PRUint32 length = strlen(aRegistryName);
char* eRegistryName;
rv = mRegistry->EscapeKey((PRUint8*)aRegistryName, 1, &length, (PRUint8**)&eRegistryName);
if (rv != NS_OK)
{
return rv;
}
if (eRegistryName == nsnull) // No escaping required
eRegistryName = (char*)aRegistryName;
nsRegistryKey IDKey;
PRInt32 nComponents = 0;
@ -1693,7 +1722,9 @@ nsComponentManagerImpl::AddComponentToRegistry(const nsCID &aClass,
goto out;
}
rv = mRegistry->SetStringUTF8(IDKey, inprocServerValueName, aRegistryName);
rv = mRegistry->SetBytesUTF8(IDKey, inprocServerValueName,
strlen(aRegistryName) + 1,
(PRUint8*)aRegistryName);
if (NS_FAILED(rv))
goto out;
@ -1716,7 +1747,7 @@ nsComponentManagerImpl::AddComponentToRegistry(const nsCID &aClass,
}
nsRegistryKey compKey;
rv = mRegistry->AddSubtreeRaw(mXPCOMKey, aRegistryName, &compKey);
rv = mRegistry->AddSubtreeRaw(mXPCOMKey, eRegistryName, &compKey);
// update component count
rv = mRegistry->GetInt(compKey, componentCountValueName, &nComponents);
@ -1728,6 +1759,8 @@ nsComponentManagerImpl::AddComponentToRegistry(const nsCID &aClass,
out:
// XXX if failed, undo registry adds or set invalid bit? How?
nsCRT::free(cidString);
if (eRegistryName != aRegistryName)
nsAllocator::Free(eRegistryName);
return rv;
}
@ -1742,7 +1775,7 @@ nsComponentManagerImpl::UnregisterFactory(const nsCID &aClass,
("nsComponentManager: UnregisterFactory(%s)", buf));
delete [] buf;
}
nsIDKey key(aClass);
nsresult res = NS_ERROR_FACTORY_NOT_REGISTERED;
nsFactoryEntry *old = (nsFactoryEntry *) mFactories->Get(&key);
@ -1790,9 +1823,9 @@ nsComponentManagerImpl::UnregisterComponent(const nsCID &aClass,
rv = PlatformUnregister(cidString, registryName);
delete [] cidString;
#endif
PR_ExitMonitor(mMon);
PR_LOG(nsComponentManagerLog, PR_LOG_WARNING,
("nsComponentManager: Factory unregister(%s) %s.", registryName,
NS_SUCCEEDED(rv) ? "succeeded" : "FAILED"));
@ -1821,18 +1854,18 @@ CanUnload_enumerate(nsHashKey *key, void *aData, void *aClosure)
{
nsIComponentLoader *loader = (nsIComponentLoader *)aData;
struct CanUnload_closure *closure =
(struct CanUnload_closure *)aClosure;
(struct CanUnload_closure *)aClosure;
if (loader == closure->native) {
#ifdef DEBUG
fprintf(stderr, "CanUnload_enumerate: skipping native\n");
fprintf(stderr, "CanUnload_enumerate: skipping native\n");
#endif
return PR_TRUE;
return PR_TRUE;
}
closure->status = loader->UnloadAll(closure->when);
if (NS_FAILED(closure->status))
return PR_FALSE;
return PR_FALSE;
return PR_TRUE;
}
@ -1854,7 +1887,7 @@ nsComponentManagerImpl::UnloadLibraries(nsIServiceManager *serviceMgr, PRInt32 a
nsresult rv = NS_OK;
PR_EnterMonitor(mMon);
PR_LOG(nsComponentManagerLog, PR_LOG_ALWAYS,
("nsComponentManager: Unloading Libraries."));
@ -1883,9 +1916,9 @@ nsComponentManagerImpl::UnloadLibraries(nsIServiceManager *serviceMgr, PRInt32 a
* of all components. No default director is looked at.
*
* Directory and fullname are what NSPR will accept. For eg.
* WIN y:/home/dp/mozilla/dist/bin
* UNIX /home/dp/mozilla/dist/bin
* MAC /Hard drive/mozilla/dist/apprunner
* WIN y:/home/dp/mozilla/dist/bin
* UNIX /home/dp/mozilla/dist/bin
* MAC /Hard drive/mozilla/dist/apprunner
*
* This will take care not loading already registered dlls, finding and
* registering new dlls, re-registration of modified dlls
@ -1905,10 +1938,10 @@ AutoRegister_enumerate(nsHashKey *key, void *aData, void *aClosure)
{
nsIComponentLoader *loader = NS_STATIC_CAST(nsIComponentLoader *, aData);
struct AutoReg_closure *closure =
(struct AutoReg_closure *)aClosure;
(struct AutoReg_closure *)aClosure;
if (loader == closure->native)
return PR_TRUE;
return PR_TRUE;
PR_ASSERT(NS_SUCCEEDED(closure->status));
@ -1922,7 +1955,7 @@ RegisterDeferred_enumerate(nsHashKey *key, void *aData, void *aClosure)
{
nsIComponentLoader *loader = NS_STATIC_CAST(nsIComponentLoader *, aData);
struct AutoReg_closure *closure =
(struct AutoReg_closure *)aClosure;
(struct AutoReg_closure *)aClosure;
PR_ASSERT(NS_SUCCEEDED(closure->status));
PRBool registered;
@ -1947,7 +1980,7 @@ nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFile *inDirSpec)
{
// Use supplied components' directory
dir = inDirSpec;
// Set components' directory for AutoRegisterInterfces to query
NS_WITH_SERVICE(nsIProperties, directoryService, NS_DIRECTORY_SERVICE_PROGID, &rv);
if (NS_FAILED(rv)) return rv;
@ -1976,12 +2009,12 @@ nsComponentManagerImpl::AutoRegister(PRInt32 when, nsIFile *inDirSpec)
rv = iim->AutoRegisterInterfaces();
if (NS_FAILED(rv))
return rv;
return rv;
/* do the native loader first, so we can find other loaders */
rv = mNativeComponentLoader->AutoRegisterComponents((PRInt32)when, dir);
if (NS_FAILED(rv))
return rv;
return rv;
/* XXX eagerly instantiate all known loaders */
nsCOMPtr<nsIEnumerator> loaderEnum;
@ -2043,14 +2076,14 @@ AutoRegisterComponent_enumerate(nsHashKey *key, void *aData, void *aClosure)
PRBool didRegister;
nsIComponentLoader *loader = (nsIComponentLoader *)aData;
struct AutoReg_closure *closure =
(struct AutoReg_closure *)aClosure;
(struct AutoReg_closure *)aClosure;
closure->status = loader->AutoRegisterComponent(closure->when,
closure->spec,
&didRegister);
closure->spec,
&didRegister);
if (NS_SUCCEEDED(closure->status) && didRegister)
return PR_FALSE; // Stop enumeration as we are done
return PR_FALSE; // Stop enumeration as we are done
return PR_TRUE;
}
@ -2060,7 +2093,7 @@ AutoUnregisterComponent_enumerate(nsHashKey *key, void *aData, void *aClosure)
PRBool didUnregister;
nsIComponentLoader *loader = (nsIComponentLoader *)aData;
struct AutoReg_closure *closure =
(struct AutoReg_closure *)aClosure;
(struct AutoReg_closure *)aClosure;
closure->status = loader->AutoUnregisterComponent(closure->when,
closure->spec,
@ -2088,7 +2121,7 @@ nsComponentManagerImpl::AutoRegisterComponent(PRInt32 when,
*/
mLoaders->Enumerate(AutoRegisterComponent_enumerate, &closure);
return NS_FAILED(closure.status)
? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK;
? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK;
}
@ -2106,7 +2139,7 @@ nsComponentManagerImpl::AutoUnregisterComponent(PRInt32 when,
mLoaders->Enumerate(AutoUnregisterComponent_enumerate, &closure);
return NS_FAILED(closure.status)
? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK;
? NS_ERROR_FACTORY_NOT_REGISTERED : NS_OK;
}

View File

@ -170,8 +170,9 @@ protected:
* alpha0.70 : using nsIFileSpec. PRTime -> PRUint32
* alpha0.90 : using nsIComponentLoader, abs:/rel:/lib:, shaver-cleanup
* alpha0.92 : restructured registry keys
* alpha0.93 : changed component names to native strings instead of UTF8
*/
#define NS_XPCOM_COMPONENT_MANAGER_VERSION_STRING "alpha0.92"
#define NS_XPCOM_COMPONENT_MANAGER_VERSION_STRING "alpha0.93"
////////////////////////////////////////////////////////////////////////////////
/**

View File

@ -51,11 +51,17 @@ interface nsIRegistry : nsISupports
string getStringUTF8(in nsRegistryKey baseKey, in string path);
void setStringUTF8(in nsRegistryKey baseKey, in string path, in string value);
void getBytesUTF8(in nsRegistryKey baseKey, in string path, out PRUint32 length, [retval, array, size_is(length)] out PRUint8 valueArray);
void setBytesUTF8(in nsRegistryKey baseKey, in string path, in PRUint32 length, [array, size_is(length)] in PRUint8 valueArray);
PRInt32 getInt(in nsRegistryKey baseKey, in string path);
void setInt(in nsRegistryKey baseKey, in string path, in PRInt32 value);
PRInt64 getLongLong(in nsRegistryKey baseKey, in string path);
void setLongLong(in nsRegistryKey baseKey, in string path, inout PRInt64 value);
/**
* addSubtree() and friends need to be renamed to addKeyUTF8().
* If you are using these forms make sure you pass UTF8 data
*/
nsRegistryKey addSubtree(in nsRegistryKey baseKey, in string path);
void removeSubtree(in nsRegistryKey baseKey, in string path);
nsRegistryKey getSubtree(in nsRegistryKey baseKey, in string path);
@ -77,6 +83,13 @@ interface nsIRegistry : nsISupports
PRUint32 getValueLength(in nsRegistryKey baseKey, in string path);
void deleteValue(in nsRegistryKey baseKey, in string path);
/**
* escapeKey() takes arbitrary binary data and converts it into
* valid ASCII which can be used as registry key or value names
*/
void escapeKey([array, size_is(length)] in PRUint8 key, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 escaped);
void unescapeKey([array, size_is(length)] in PRUint8 escaped, in PRUint32 terminator, inout PRUint32 length, [retval, array, size_is(length)] out PRUint8 key);
attribute string currentUserName;
void pack();

View File

@ -202,19 +202,35 @@ nsNativeComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aReg)
// Get library name
nsXPIDLCString library;
rv = node->GetNameUTF8(getter_Copies(library));
if (NS_FAILED(rv)) continue;
char* uLibrary;
char* eLibrary = (char*)library.operator const char*();
PRUint32 length = strlen(eLibrary);
rv = mRegistry->UnescapeKey((PRUint8*)eLibrary, 1, &length, (PRUint8**)&uLibrary);
if (NS_FAILED(rv)) continue;
if (uLibrary == nsnull)
uLibrary = eLibrary;
// Get key associated with library
nsRegistryKey libKey;
rv = node->GetKey(&libKey);
if (NS_FAILED(rv)) continue;
if (!NS_FAILED(rv)) // Cannot continue here, because we have to free unescape
{
// Create nsDll with this name
nsDll *dll = NULL;
PRInt64 lastModTime;
PRInt64 fileSize;
GetRegistryDllInfo(libKey, &lastModTime, &fileSize);
rv = CreateDll(NULL, uLibrary, &lastModTime, &fileSize, &dll);
}
if (uLibrary != eLibrary
&& uLibrary != nsnull)
nsAllocator::Free(uLibrary);
// Create nsDll with this name
nsDll *dll = NULL;
PRInt64 lastModTime;
PRInt64 fileSize;
GetRegistryDllInfo(libKey, &lastModTime, &fileSize);
rv = CreateDll(NULL, library, &lastModTime, &fileSize, &dll);
if (NS_FAILED(rv)) continue;
}
@ -337,7 +353,7 @@ nsFreeLibrary(nsDll *dll, nsIServiceManager *serviceMgr, PRInt32 when)
if (proc)
{
canUnload = proc(serviceMgr);
rv = NS_OK; // No error status returned by call.
rv = NS_OK; // No error status returned by call.
}
else
{
@ -527,13 +543,13 @@ nsNativeComponentLoader::DumpLoadError(nsDll *dll,
nsCAutoString errorMsg(aNsprErrorMsg);
#if defined(MOZ_DEMANGLE_SYMBOLS)
// Demangle undefined symbols
nsCAutoString undefinedMagicString("undefined symbol:");
// Demangle undefined symbols
nsCAutoString undefinedMagicString("undefined symbol:");
PRInt32 offset = errorMsg.Find(undefinedMagicString, PR_TRUE);
PRInt32 offset = errorMsg.Find(undefinedMagicString, PR_TRUE);
if (offset != kNotFound)
{
if (offset != kNotFound)
{
nsCAutoString symbol(errorMsg);
nsCAutoString demangledSymbol("");
@ -563,8 +579,8 @@ nsNativeComponentLoader::DumpLoadError(nsDll *dll,
tmp += demangledSymbol;
errorMsg = tmp;
}
}
}
}
#endif // MOZ_DEMANGLE_SYMBOLS
// Do NSPR log
@ -708,24 +724,24 @@ nsNativeComponentLoader::AutoRegisterComponent(PRInt32 when,
#ifdef XP_MAC // sdagley dougt fix
// rjc - on Mac, check the file's type code (skip checking the creator code)
nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface(component);
if (localFileMac)
{
OSType type;
OSType creator;
rv = localFileMac->GetFileTypeAndCreator(&type, &creator);
if (NS_SUCCEEDED(rv))
{
// on Mac, Mozilla shared libraries are of type 'shlb'
// Note: we don't check the creator (which for Mozilla is 'MOZZ')
// so that 3rd party shared libraries will be noticed!
if (type == 'shlb')
{
validExtension = PR_TRUE;
}
}
}
nsCOMPtr<nsILocalFileMac> localFileMac = do_QueryInterface(component);
if (localFileMac)
{
OSType type;
OSType creator;
rv = localFileMac->GetFileTypeAndCreator(&type, &creator);
if (NS_SUCCEEDED(rv))
{
// on Mac, Mozilla shared libraries are of type 'shlb'
// Note: we don't check the creator (which for Mozilla is 'MOZZ')
// so that 3rd party shared libraries will be noticed!
if (type == 'shlb')
{
validExtension = PR_TRUE;
}
}
}
#else
char *leafName = NULL;
@ -934,12 +950,25 @@ nsNativeComponentLoader::GetRegistryDllInfo(const char *aLocation,
PRInt64 *fileSize)
{
nsresult rv;
PRUint32 length = strlen(aLocation);
char* eLocation;
rv = mRegistry->EscapeKey((PRUint8*)aLocation, 1, &length, (PRUint8**)&eLocation);
if (rv != NS_OK)
{
return rv;
}
if (eLocation == nsnull) // No escaping required
eLocation = (char*)aLocation;
nsRegistryKey key;
rv = mRegistry->GetSubtreeRaw(mXPCOMKey, aLocation, &key);
rv = mRegistry->GetSubtreeRaw(mXPCOMKey, eLocation, &key);
if (NS_FAILED(rv)) return rv;
return GetRegistryDllInfo(key, lastModifiedTime, fileSize);
rv = GetRegistryDllInfo(key, lastModifiedTime, fileSize);
if (aLocation != eLocation)
nsAllocator::Free(eLocation);
return rv;
}
nsresult
@ -955,8 +984,7 @@ nsNativeComponentLoader::GetRegistryDllInfo(nsRegistryKey key,
PRInt64 fsize;
rv = mRegistry->GetLongLong(key, fileSizeValueName, &fsize);
if (NS_FAILED(rv)) return rv;
*fileSize = fsize;
*fileSize = fsize;
return NS_OK;
}
@ -966,20 +994,46 @@ nsNativeComponentLoader::SetRegistryDllInfo(const char *aLocation,
PRInt64 *fileSize)
{
nsresult rv;
PRUint32 length = strlen(aLocation);
char* eLocation;
rv = mRegistry->EscapeKey((PRUint8*)aLocation, 1, &length, (PRUint8**)&eLocation);
if (rv != NS_OK)
{
return rv;
}
if (eLocation == nsnull) // No escaping required
eLocation = (char*)aLocation;
nsRegistryKey key;
rv = mRegistry->GetSubtreeRaw(mXPCOMKey, aLocation, &key);
rv = mRegistry->GetSubtreeRaw(mXPCOMKey, eLocation, &key);
if (NS_FAILED(rv)) return rv;
rv = mRegistry->SetLongLong(key, lastModValueName, lastModifiedTime);
if (NS_FAILED(rv)) return rv;
rv = mRegistry->SetLongLong(key, fileSizeValueName, fileSize);
if (aLocation != eLocation)
nsAllocator::Free(eLocation);
return rv;
}
nsresult
nsNativeComponentLoader::RemoveRegistryDllInfo(const char *aLocation)
{
return mRegistry->RemoveSubtree(mXPCOMKey, aLocation);
nsresult rv;
PRUint32 length = strlen(aLocation);
char* eLocation;
rv = mRegistry->EscapeKey((PRUint8*)aLocation, 1, &length, (PRUint8**)&eLocation);
if (rv != NS_OK)
{
return rv;
}
if (eLocation == nsnull) // No escaping required
eLocation = (char*)aLocation;
rv = mRegistry->RemoveSubtree(mXPCOMKey, eLocation);
if (aLocation != eLocation)
nsAllocator::Free(eLocation);
return rv;
}
//
@ -988,18 +1042,18 @@ nsNativeComponentLoader::RemoveRegistryDllInfo(const char *aLocation)
// be called in multiple situations:
//
// 1. Autoregister will create one for each dll it is trying to register. This
// call will be passing a spec in.
// {spec, NULL, 0, 0}
// call will be passing a spec in.
// {spec, NULL, 0, 0}
//
// 2. GetFactory() This will call CreateDll() with a null spec but will give
// the registry represented name of the dll. If modtime and size are zero,
// we will go the registry to find the right modtime and size.
// {NULL, rel:libpref.so, 0, 0}
// the registry represented name of the dll. If modtime and size are zero,
// we will go the registry to find the right modtime and size.
// {NULL, rel:libpref.so, 0, 0}
//
// 3. Prepopulation of dllCache A dll object created off a registry entry.
// Specifically dll name is stored in rel: or abs: or lib: formats in the
// registry along with its lastModTime and fileSize.
// {NULL, rel:libpref.so, 8985659, 20987}
// Specifically dll name is stored in rel: or abs: or lib: formats in the
// registry along with its lastModTime and fileSize.
// {NULL, rel:libpref.so, 8985659, 20987}
nsresult
nsNativeComponentLoader::CreateDll(nsIFile *aSpec, const char *aLocation,
PRInt64 *modificationTime, PRInt64 *fileSize,

View File

@ -73,9 +73,9 @@ struct nsRegistry : public nsIRegistry {
protected:
HREG mReg; // Registry handle.
#ifdef EXTRA_THREADSAFE
PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize.
PRLock *mregLock; // libreg isn't threadsafe. Use locks to synchronize.
#endif
char *mCurRegFile; // these are to prevent open from opening the registry again
char *mCurRegFile; // these are to prevent open from opening the registry again
nsWellKnownRegistry mCurRegID;
NS_IMETHOD Close();
@ -167,7 +167,7 @@ struct nsRegistryNode : public nsIRegistryNode {
protected:
HREG mReg; // Handle to registry this node is part of.
char mName[MAXREGPATHLEN]; // Buffer to hold name.
RKEY mChildKey; // Key corresponding to mName
RKEY mChildKey; // Key corresponding to mName
#ifdef EXTRA_THREADSAFE
PRLock *mregLock;
#endif
@ -735,6 +735,94 @@ NS_IMETHODIMP nsRegistry::SetStringUTF8( nsRegistryKey baseKey, const char *path
return regerr2nsresult( err );
}
/*---------------------------- nsRegistry::GetBytesUTF8 ------------------------------
| This function is just shorthand for fetching a char array. We |
| implement it "manually" using NR_RegGetEntry |
------------------------------------------------------------------------------*/
NS_IMETHODIMP nsRegistry::GetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32* length, PRUint8** result) {
nsresult rv = NS_OK;
REGERR err = REGERR_OK;
if ( !result )
return NS_ERROR_NULL_POINTER;
char regStr[MAXREGPATHLEN];
// initialize the return value
*length = 0;
*result = 0;
// Get info about the requested entry.
PRUint32 type;
rv = GetValueType( baseKey, path, &type );
// See if that worked.
if( rv == NS_OK )
{
// Make sure the entry is an PRInt8 array.
if( type == Bytes )
{
// Attempt to get string into our fixed buffer
PR_Lock(mregLock);
uint32 length2 = sizeof regStr;
err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), regStr, &length2);
PR_Unlock(mregLock);
if ( err == REGERR_OK )
{
*length = length2;
*result = (PRUint8*)(nsCRT::strdup(regStr));
if (!*result)
{
rv = NS_ERROR_OUT_OF_MEMORY;
*length = 0;
}
else
{
*length = length2;
}
}
else if ( err == REGERR_BUFTOOSMALL )
{
// find the real size and malloc it
rv = GetValueLength( baseKey, path, length );
// See if that worked.
if( rv == NS_OK )
{
*result = NS_REINTERPRET_CAST(PRUint8*,nsAllocator::Alloc( *length ));
if( *result )
{
// Get bytes from registry into result field.
PR_Lock(mregLock);
length2 = *length;
err = NR_RegGetEntry( mReg,(RKEY)baseKey,NS_CONST_CAST(char*,path), *result, &length2);
*length = length2;
PR_Unlock(mregLock);
// Convert status.
rv = regerr2nsresult( err );
if ( rv != NS_OK )
{
// Didn't get result, free buffer
nsCRT::free( NS_REINTERPRET_CAST(char*, *result) );
*result = 0;
*length = 0;
}
}
else
{
rv = NS_ERROR_OUT_OF_MEMORY;
}
}
}
}
else
{
// They asked for the wrong type of value.
rv = NS_ERROR_REG_BADTYPE;
}
}
return rv;
}
/*---------------------------- nsRegistry::GetInt ------------------------------
| This function is just shorthand for fetching a 1-element PRInt32 array. We |
| implement it "manually" using NR_RegGetEntry |
@ -788,6 +876,24 @@ NS_IMETHODIMP nsRegistry::GetLongLong( nsRegistryKey baseKey, const char *path,
// Convert status.
return regerr2nsresult( err );
}
/*---------------------------- nsRegistry::SetBytesUTF8 ------------------------------
| Write out the value as a char array, using NR_RegSetEntry. |
------------------------------------------------------------------------------*/
NS_IMETHODIMP nsRegistry::SetBytesUTF8( nsRegistryKey baseKey, const char *path, PRUint32 length, PRUint8* value) {
REGERR err = REGERR_OK;
// Set the contents.
PR_Lock(mregLock);
err = NR_RegSetEntry( mReg,
(RKEY)baseKey,
(char*)path,
REGTYPE_ENTRY_BYTES,
(char*)value,
length);
PR_Unlock(mregLock);
// Convert result.
return regerr2nsresult( err );
}
/*---------------------------- nsRegistry::SetInt ------------------------------
| Write out the value as a one-element PRInt32 array, using NR_RegSetEntry. |
------------------------------------------------------------------------------*/
@ -862,8 +968,8 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path
nsresult rv = NS_OK;
REGERR err = REGERR_OK;
// libreg doesn't delete keys if there are subkeys under the key
// Hence we have to recurse through to delete the subtree
// libreg doesn't delete keys if there are subkeys under the key
// Hence we have to recurse through to delete the subtree
RKEY key;
@ -871,13 +977,13 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path
err = NR_RegGetKey(mReg, baseKey, (char *)path, &key);
PR_Unlock(mregLock);
if (err != REGERR_OK)
{
rv = regerr2nsresult( err );
{
rv = regerr2nsresult( err );
return rv;
}
}
// Now recurse through and delete all keys under hierarchy
char subkeyname[MAXREGPATHLEN+1];
REGENUM state = 0;
subkeyname[0] = '\0';
@ -885,7 +991,7 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path
REGENUM_NORMAL) == REGERR_OK)
{
#ifdef DEBUG_dp
printf("...recursing into %s\n", subkeyname);
printf("...recursing into %s\n", subkeyname);
#endif /* DEBUG_dp */
// Even though this is not a "Raw" API the subkeys may still, in fact,
// *be* raw. Since we're recursively deleting this will work either way.
@ -899,15 +1005,15 @@ NS_IMETHODIMP nsRegistry::RemoveSubtree( nsRegistryKey baseKey, const char *path
if (err == REGERR_OK)
{
#ifdef DEBUG_dp
printf("...deleting %s\n", path);
printf("...deleting %s\n", path);
#endif /* DEBUG_dp */
PR_Lock(mregLock);
err = NR_RegDeleteKey(mReg, baseKey, (char *)path);
PR_Unlock(mregLock);
}
// Convert result.
rv = regerr2nsresult( err );
// Convert result.
rv = regerr2nsresult( err );
return rv;
}
@ -919,8 +1025,8 @@ NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *k
nsresult rv = NS_OK;
REGERR err = REGERR_OK;
// libreg doesn't delete keys if there are subkeys under the key
// Hence we have to recurse through to delete the subtree
// libreg doesn't delete keys if there are subkeys under the key
// Hence we have to recurse through to delete the subtree
RKEY key;
char subkeyname[MAXREGPATHLEN+1];
@ -931,18 +1037,18 @@ NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *k
err = NR_RegGetKeyRaw(mReg, baseKey, (char *)keyname, &key);
PR_Unlock(mregLock);
if (err != REGERR_OK)
{
rv = regerr2nsresult( err );
{
rv = regerr2nsresult( err );
return rv;
}
}
// Now recurse through and delete all keys under hierarchy
subkeyname[0] = '\0';
while (NR_RegEnumSubkeys(mReg, key, &state, subkeyname, n, REGENUM_NORMAL) == REGERR_OK)
{
#ifdef DEBUG_dp
printf("...recursing into %s\n", subkeyname);
printf("...recursing into %s\n", subkeyname);
#endif /* DEBUG_dp */
err = RemoveSubtreeRaw(key, subkeyname);
if (err != REGERR_OK) break;
@ -952,15 +1058,15 @@ NS_IMETHODIMP nsRegistry::RemoveSubtreeRaw( nsRegistryKey baseKey, const char *k
if (err == REGERR_OK)
{
#ifdef DEBUG_dp
printf("...deleting %s\n", keyname);
printf("...deleting %s\n", keyname);
#endif /* DEBUG_dp */
PR_Lock(mregLock);
err = NR_RegDeleteKeyRaw(mReg, baseKey, (char *)keyname);
PR_Unlock(mregLock);
}
// Convert result.
rv = regerr2nsresult( err );
// Convert result.
rv = regerr2nsresult( err );
return rv;
}
/*-------------------------- nsRegistry::GetSubtree ----------------------------
@ -1196,6 +1302,157 @@ NS_IMETHODIMP nsRegistry::Pack() {
return rv;
}
/*----------------------------- nsRegistry::EscapeKey -------------------------------
| Escape a binary key so that the registry works OK, since it expects UTF8
| with no slashes or control characters. This is probably better than raw.
| If no escaping is required, then the method is successful and a null is
| returned, indicating that the caller should use the original string.
------------------------------------------------------------------------------*/
static const char sEscapeKeyHex[] = "0123456789abcdef0123456789ABCDEF";
NS_IMETHODIMP nsRegistry::EscapeKey(PRUint8* key, PRUint32 termination, PRUint32* length, PRUint8** escaped)
{
nsresult rv = NS_OK;
char* value = (char*)key;
char* b = value;
char* e = b + *length;
int escapees = 0;
while (b < e) // Count characters outside legal range or slash
{
int c = *b++;
if (c <= ' '
|| c > '~'
|| c == '/'
|| c == '%')
{
escapees++;
}
}
if (escapees == 0) // If no escapees, then no results
{
*length = 0;
*escaped = nsnull;
return NS_OK;
}
// New length includes two extra chars for escapees.
*length += escapees * 2;
*escaped = (PRUint8*)nsAllocator::Alloc(*length + termination);
if (*escaped == nsnull)
{
*length = 0;
*escaped = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
char* n = (char*)*escaped;
b = value;
while (escapees && b < e)
{
char c = *b++;
if (c < ' '
|| c > '~'
|| c == '/'
|| c == '%')
{
*(n++) = '%';
*(n++) = sEscapeKeyHex[ 0xF & (c >> 4) ];
*(n++) = sEscapeKeyHex[ 0xF & c ];
escapees--;
}
else
{
*(n++) = c;
}
}
e += termination;
if (b < e)
{
strncpy(n, b, e - b);
}
return rv;
}
/*----------------------------- nsRegistry::UnescapeKey -------------------------------
| Unscape a binary key so that the registry works OK, since it expects UTF8
| with no slashes or control characters. This is probably better than raw.
| If no escaping is required, then the method is successful and a null is
| returned, indicating that the caller should use the original string.
------------------------------------------------------------------------------*/
NS_IMETHODIMP nsRegistry::UnescapeKey(PRUint8* escaped, PRUint32 termination, PRUint32* length, PRUint8** key)
{
nsresult rv = NS_OK;
char* value = (char*)escaped;
char* b = value;
char* e = b + *length;
int escapees = 0;
while (b < e) // Count characters outside legal range or slash
{
if (*b++ == '%')
{
escapees++;
}
}
if (escapees == 0) // If no escapees, then no results
{
*length = 0;
*key = nsnull;
return NS_OK;
}
// New length includes two extra chars for escapees.
*length -= escapees * 2;
*key = (PRUint8*)nsAllocator::Alloc(*length + termination);
if (*key == nsnull)
{
*length = 0;
*key = nsnull;
return NS_ERROR_OUT_OF_MEMORY;
}
char* n = (char*)*key;
b = value;
while (escapees && b < e)
{
char c = *(b++);
if (c == '%')
{
if (e - b >= 2)
{
char* c1 = strchr(sEscapeKeyHex, *(b++));
char* c2 = strchr(sEscapeKeyHex, *(b++));
if (c1 != nsnull
&& c2 != nsnull)
{
*(n++) = ((c2 - sEscapeKeyHex) & 0xF)
| (((c1 - sEscapeKeyHex) & 0xF) << 4);
}
else
{
escapees = -1;
}
}
else
{
escapees = -1;
}
escapees--;
}
else
{
*(n++) = c;
}
}
if (escapees < 0)
{
nsAllocator::Free(*key);
*length = 0;
*key = nsnull;
return NS_ERROR_INVALID_ARG;
}
e += termination;
if (b < e)
{
strncpy(n, b, e - b);
}
return rv;
}
/*-------------- nsRegSubtreeEnumerator::nsRegSubtreeEnumerator ----------------
| The ctor simply stashes all the information that will be needed to enumerate |
| the subkeys. |
@ -1437,7 +1694,7 @@ NS_IMETHODIMP nsRegistryNode::GetNameUTF8( char **result ) {
}
/*-------------------------- nsRegistryNode::GetKey ----------------------------
| Get the subkey corresponding to this node |
| Get the subkey corresponding to this node |
| using NR_RegEnumSubkeys. |
------------------------------------------------------------------------------*/
NS_IMETHODIMP nsRegistryNode::GetKey( nsRegistryKey *r_key ) {

View File

@ -260,24 +260,29 @@ void nsHashtable::Reset(nsHashtableEnumFunc destroyFunc, void* closure)
nsStringKey::nsStringKey(const char* str)
{
MOZ_COUNT_CTOR(nsStringKey);
mStr.AssignWithConversion(str);
}
nsStringKey::nsStringKey(const PRUnichar* str)
{
MOZ_COUNT_CTOR(nsStringKey);
mStr.Assign(str);
}
nsStringKey::nsStringKey(const nsString& str) {
MOZ_COUNT_CTOR(nsStringKey);
mStr.Assign(str);
}
nsStringKey::nsStringKey(const nsCString& str) {
MOZ_COUNT_CTOR(nsStringKey);
mStr.AssignWithConversion(str);
}
nsStringKey::~nsStringKey(void)
{
MOZ_COUNT_DTOR(nsStringKey);
}
PRUint32 nsStringKey::HashValue(void) const