/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK *****
*
* This Original Code has been modified by IBM Corporation.
* Modifications made by IBM described herein are
* Copyright (c) International Business Machines
* Corporation, 2000
*
* Modifications to Mozilla code or documentation
* identified per MPL Section 3.3
*
* Date Modified by Description of modification
* 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
*/
#include <stdlib.h>
#include "nscore.h"
#include "nsISupports.h"
#include "nspr.h"
#include "nsCRT.h" // for atoll
// Arena used by component manager for storing contractid string, dll
// location strings and small objects
// CAUTION: Arena align mask needs to be defined before including plarena.h
// currently from nsComponentManager.h
#include "nsAutoLock.h"
#include "nsCOMPtr.h"
#include "nsComponentManager.h"
#include "nsComponentManagerObsolete.h"
#include "nsDirectoryService.h"
#include "nsDirectoryServiceDefs.h"
#include "nsCategoryManager.h"
#include "nsCategoryManagerUtils.h"
#include "nsIComponentLoader.h"
#include "nsIEnumerator.h"
#include "nsIInterfaceInfoManager.h"
#include "nsIModule.h"
#include "nsIObserverService.h"
#include "nsISimpleEnumerator.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsLocalFile.h"
#include "nsNativeComponentLoader.h"
#include "nsReadableUtils.h"
#include "nsString.h"
#include "nsXPIDLString.h"
#include "prcmon.h"
#include "xptinfo.h" // this after nsISupports, to pick up IID so that xpt stuff doesn't try to define it itself...
#include "nsInt64.h"
#include "nsManifestLineReader.h"
#include NEW_H // for placement new
#ifdef XP_BEOS
#include <FindDirectory.h>
#include <Path.h>
#endif
#include "prlog.h"
#if 0 || defined (DEBUG_timeless)
#define SHOW_DENIED_ON_SHUTDOWN
#define SHOW_CI_ON_EXISTING_SERVICE
#define XPCOM_CHECK_PENDING_CIDS
#endif
// Loader Types
// Bloated registry buffer size to improve startup performance -- needs to
// be big enough to fit the entire file into memory or it'll thrash.
// 512K is big enough to allow for some future growth in the registry.
// Common Key Names
// Common Value Names
static const char gIDFormat[] =
"{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}";
#define NS_EMPTY_IID \
{ \
0x00000000, \
0x0000, \
0x0000, \
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} \
}
// Set to true from NS_ShutdownXPCOM.
extern PRBool gXPCOMShuttingDown;
{
}
{
/*
* If I were a real man, I would consolidate this with
* nsGetServiceFromContractID::operator().
*/
// when categories have defaults, use that for null mEntry
goto error;
}
/* find the contractID for category.entry */
if (!value) {
goto error;
}
if (!compMgr)
return NS_ERROR_FAILURE;
aIID,
*aInstancePtr = 0;
}
return rv;
}
{
// when categories have defaults, use that for null mEntry
goto error;
}
/* find the contractID for category.entry */
if (!value) {
goto error;
}
if (mServiceManager) {
} else {
if (mgr)
}
*aInstancePtr = 0;
}
return rv;
}
////////////////////////////////////////////////////////////////////////////////
// Arena helper functions
////////////////////////////////////////////////////////////////////////////////
char *
{
void *mem;
// Include trailing null in the len
if (mem)
return NS_STATIC_CAST(char *, mem);
}
char*
{
}
////////////////////////////////////////////////////////////////////////////////
// Hashtable Callbacks
////////////////////////////////////////////////////////////////////////////////
PR_STATIC_CALLBACK(const void *)
{
}
{
}
const void *aKey)
{
}
PR_STATIC_CALLBACK(void)
{
// nsFactoryEntry is arena allocated. So we dont delete it.
// We call the destructor by hand.
}
};
PR_STATIC_CALLBACK(void)
{
// this object is owned by the hash.
// nsFactoryEntry is arena allocated. So we dont delete it.
// We call the destructor by hand.
}
// contractIDs are arena allocated. No need to free them.
}
};
////////////////////////////////////////////////////////////////////////////////
// nsFactoryEntry
////////////////////////////////////////////////////////////////////////////////
const char *aLocation,
int aType,
class nsFactoryEntry* parent)
{
// Arena allocate the location string
mLocation = ArenaStrndup(aLocation, locationlen, &nsComponentManagerImpl::gComponentManager->mArena);
}
class nsFactoryEntry* parent)
{
}
// nsFactoryEntry is usually arena allocated including the strings it
// holds. So we call destructor by hand.
nsFactoryEntry::~nsFactoryEntry(void)
{
// Release the reference to the factory
// Release any service reference
// nsFactoryEntry is arena allocated. So we dont delete it.
// We call the destructor by hand.
if (mParent)
mParent->~nsFactoryEntry();
}
{
// cid has to match
// SERVICE_ONLY entries can be promoted to an entry of another type
// Arena allocate the location string
mTypeIndex = aType;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// Hashtable Enumeration
////////////////////////////////////////////////////////////////////////////////
const PLDHashEntryHdr *hdr,
void *data,
nsISupports **retval);
public nsISimpleEnumerator
{
public:
void *converterData);
private:
PLDHashTableEnumeratorImpl(); /* no implementation */
struct Closure {
void *data;
};
void *data);
};
// static
void *data)
{
return PL_DHASH_STOP;
}
return PL_DHASH_NEXT;
}
void *converterData)
: mCurrent(0)
{
if (!c.succeeded) {
mCount = 0;
}
}
{
(void) ReleaseElements();
// Destroy the Lock
if (mMonitor)
}
{
mElements[i]);
}
return NS_OK;
}
void *converterData,
{
if (!impl)
return NS_ERROR_OUT_OF_MEMORY;
// conversion failed
return NS_ERROR_FAILURE;
}
return NS_OK;
}
{
if (!mCount)
return NS_ERROR_FAILURE;
mCurrent = 0;
return NS_OK;
}
{
if (!mCount)
return NS_ERROR_FAILURE;
return NS_OK;
}
{
if (!mCurrent)
return NS_ERROR_FAILURE;
mCurrent--;
return NS_OK;
}
{
// If empty or we're past the end, or we are at the end return error
return NS_ERROR_FAILURE;
return NS_OK;
}
{
return NS_ERROR_FAILURE;
if (*retval)
return NS_OK;
}
{
return NS_OK;
return NS_ENUMERATOR_FALSE;
}
{
else
return NS_OK;
}
{
return CurrentItem(_retval);
}
static NS_IMETHODIMP
const PLDHashEntryHdr *hdr,
{
if (entry) {
return NS_OK;
}
return rv;
}
static NS_IMETHODIMP
const PLDHashEntryHdr *hdr,
{
entry->mContractIDLen));
return NS_OK;
}
// this is safe to call during InitXPCOM
{
if (!directoryService)
return NS_ERROR_FAILURE;
(void**)aDirectory);
}
////////////////////////////////////////////////////////////////////////////////
// nsComponentManagerImpl
////////////////////////////////////////////////////////////////////////////////
:
#endif
{
}
{
if (mShuttingDown == NS_SHUTDOWN_INPROGRESS)
return NS_ERROR_FAILURE;
if (nsComponentManagerLog == nsnull)
{
}
// Initialize our arena
if (!mFactories.ops) {
0, sizeof(nsFactoryTableEntry),
1024)) {
return NS_ERROR_OUT_OF_MEMORY;
}
// Minimum alpha uses k=2 because nsFactoryTableEntry saves two
// words compared to what a chained hash table requires.
0.875,
}
if (!mContractIDs.ops) {
0, sizeof(nsContractIDTableEntry),
1024)) {
return NS_ERROR_OUT_OF_MEMORY;
}
// Minimum alpha uses k=1 because nsContractIDTableEntry saves one
// word compared to what a chained hash table requires.
#if 0
0.875,
#endif
}
return NS_ERROR_OUT_OF_MEMORY;
}
if (mNativeComponentLoader == nsnull) {
/* Create the NativeComponentLoader */
if (!mNativeComponentLoader)
return NS_ERROR_OUT_OF_MEMORY;
return rv;
}
// Add predefined loaders
if (!mLoaderData)
return NS_ERROR_OUT_OF_MEMORY;
mNLoaderData++;
if (mStaticComponentLoader == nsnull) {
if (!mStaticComponentLoader)
return NS_ERROR_OUT_OF_MEMORY;
}
mNLoaderData++;
if (mStaticComponentLoader) {
/* Init the static loader */
}
#endif
if (!mComponentsDir)
return NS_ERROR_OUT_OF_MEMORY;
return rv;
if (mGREComponentsDir) {
NS_WARNING("No GRE component manager");
return rv;
}
}
if(!mRegistryFile) {
NS_WARNING("No Component Registry file was found in the directory service");
return NS_ERROR_FAILURE;
}
("nsComponentManager: Initialized."));
return NS_OK;
}
{
delete (AutoRegEntry*)aData;
return kHashEnumerateNext;
}
{
return NS_ERROR_FAILURE;
// Shutdown the component manager
PRInt32 i;
// Write out our component data file.
if (mRegistryDirty) {
PR_LOG(nsComponentManagerLog, PR_LOG_ERROR, ("nsComponentManager: Could not write out perisistant registry."));
#ifdef DEBUG
printf("Could not write out perisistant registry!\n");
#endif
}
}
// Release all cached factories
if (mContractIDs.ops) {
}
if (mFactories.ops) {
}
// Unload libraries
// delete arena for strings and small objects
mComponentsDir = 0;
mCategoryManager = 0;
// Release all the component data - loaders and type strings
for (i=0; i < mNLoaderData; i++) {
}
// we have an extra reference on this one, which is probably a good thing
#endif
return NS_OK;
}
{
if (mShuttingDown != NS_SHUTDOWN_COMPLETE)
Shutdown();
if (mMon) {
}
}
{
{
if (!mNativeComponentLoader)
return NS_ERROR_NOT_INITIALIZED;
}
NS_WARNING("This isn't supported");
// fall through to QI as anything QIable is a superset of what can be
// got via the GetInterface()
}
////////////////////////////////////////////////////////////////////////////////
// nsComponentManagerImpl: Platform methods
////////////////////////////////////////////////////////////////////////////////
#define PERSISTENT_REGISTRY_VERSION_MAJOR 0
{
}
{
}
{
}
void
{
if (mData)
if (!data) {
return;
}
}
static
{
while (1)
{
{
if (*p != ']')
break;
*p = 0;
break;
// ignore the leading '['
break;
return PR_TRUE;
}
break;
}
return PR_FALSE;
}
{
// populate Category Manager. need to get this early so that we don't get
// skipped by 'goto out'
return rv;
if (!mComponentsDir)
return NS_ERROR_NOT_INITIALIZED; // this should have been set by Init().
// Set From Init
if (!mRegistryFile) {
return NS_ERROR_FILE_NOT_FOUND;
}
if (!file)
return NS_ERROR_OUT_OF_MEMORY;
return rv;
{
return rv;
}
if (flen == 0)
{
NS_WARNING("Persistent Registry Empty!");
return NS_OK; // ERROR CONDITION
}
if (!registry)
goto out;
{
goto out;
}
goto out;
goto out;
// VersionLiteral,major,minor
goto out;
// VersionLiteral
goto out;
// major
goto out;
// minor
goto out;
goto out;
while (1)
{
break;
//name,last_modification_date[,optionaldata]
if (2 > parts)
break;
if (!entry)
return NS_ERROR_OUT_OF_MEMORY;
if (parts == 3)
}
goto out;
while (1)
{
break;
// cid,contract_id,type,class_name,inproc_server
break;
continue;
if (loadertype < 0) {
continue;
}
void *mem;
if (!mem)
return NS_ERROR_OUT_OF_MEMORY;
&aClass,
PL_DHASH_ADD));
if (!factoryTableEntry)
return NS_ERROR_OUT_OF_MEMORY;
}
goto out;
while (1)
{
break;
//contractID,cid
break;
continue;
//need to find the location for this cid.
continue; //what should we really do?
values[0],
PL_DHASH_ADD));
if (!contractIDTableEntry) {
continue;
}
if (!contractIDTableEntry->mContractID) {
}
}
#ifdef XPCOM_CHECK_PENDING_CIDS
{
/*
* If you get Asserts when you define SHOW_CI_ON_EXISTING_SERVICE and want to
* track down their cause, then you should add the contracts listed by the
* assertion to abusedContracts. The next time you run your xpcom app, xpcom
* will assert the first time the object associated with the contract is
* instantiated (which in many cases is the source of the problem).
*
* If you're doing this then you might want to NOP and soft breakpoint the
* lines labeled: NOP_AND_BREAK.
*
* Otherwise XPCOM will refuse to create the object for the caller, which
* while reasonable at some level, will almost certainly cause the app to
* stop functioning normally.
*/
/*// Example contracts:
"@mozilla.org/rdf/container;1",
"@mozilla.org/intl/charsetalias;1",
"@mozilla.org/locale/win32-locale;1",
"@mozilla.org/widget/lookandfeel/win;1",
// */
{ 0 }
};
for (int i=0; abusedContracts[i] && *abusedContracts[i]; i++) {
}
}
}
#endif
goto out;
while (1)
{
break;
//type,name,value
break;
values[1],
values[2],
0);
}
out:
if (fd)
if (registry)
delete [] registry;
return rv;
}
struct PersistentWriterArgs
{
};
void *arg)
{
// for now, we only save out the top most parent.
while (factoryEntry->mParent)
if (factoryEntry->mTypeIndex < 0)
return PL_DHASH_NEXT;
return PL_DHASH_NEXT;
}
void *arg)
{
// for now, we only save out the top most parent.
while (factoryEntry->mParent)
if (factoryEntry->mTypeIndex < 0) {
return PL_DHASH_NEXT;
}
if (classInfo)
{
}
if (factoryEntry->mTypeIndex)
// cid,contract_id,type,class_name,inproc_server
"%s,%s,%s,%s,%s\n",
if (contractID)
if (className)
return PL_DHASH_NEXT;
}
{
const char *fmt;
if (extraData)
fmt = "%s,%lld,%s\n";
else
fmt = "%s,%lld\n";
return PR_TRUE;
}
{
if (!mRegistryFile)
return NS_ERROR_FAILURE; // this should have been set by Init().
if (!file)
return NS_ERROR_OUT_OF_MEMORY;
return rv;
goto out;
}
goto out;
}
goto out;
}
goto out;
}
goto out;
}
goto out;
}
if (!mCategoryManager) {
NS_WARNING("Could not access category manager. Will not be able to save categories!");
} else {
}
out:
if (fd)
// don't create the file is there was a problem????
if (!mRegistryFile)
return NS_ERROR_NOT_INITIALIZED;
return PR_FALSE;
return PR_FALSE;
return rv;
}
////////////////////////////////////////////////////////////////////////////////
// Hash Functions
////////////////////////////////////////////////////////////////////////////////
{
if(!aContractID || !aContractIDLen)
return NS_ERROR_NULL_POINTER;
PL_DHASH_ADD));
if (!contractIDTableEntry)
return NS_ERROR_OUT_OF_MEMORY;
NS_ASSERTION(!contractIDTableEntry->mContractID || !strcmp(contractIDTableEntry->mContractID, aContractID), "contractid conflict");
if (!contractIDTableEntry->mContractID) {
}
return NS_OK;
}
/**
* LoadFactory()
*
* Given a FactoryEntry, this loads the dll if it has to, find the NSGetFactory
* symbol, calls the routine to create a new factory and returns it to the
* caller.
*
* No attempt is made to store the factory in any form anywhere.
*/
{
if (!aFactory)
return NS_ERROR_NULL_POINTER;
("nsComponentManager: FAILED to load factory from %s (%s)\n",
return rv;
}
return NS_OK;
}
{
{
}
} //exit monitor
return fe;
}
{
{
}
} // exit monitor
return entry;
}
/**
* FindFactory()
*
* Given a classID, this finds the factory for this CID by first searching the
* local CID<->factory mapping. Next it searches for a Dll that implements
* this classID and calls LoadFactory() to create the factory.
*
* Again, no attempt is made at storing the factory.
*/
{
if (!entry)
return NS_ERROR_FACTORY_NOT_REGISTERED;
}
{
if (!entry)
return NS_ERROR_FACTORY_NOT_REGISTERED;
}
/**
* GetClassObject()
*
* Given a classID, this finds the singleton ClassObject that implements the CID.
* Returns an interface of type aIID off the singleton classobject.
*/
void **aResult)
{
#ifdef PR_LOGGING
{
if (buf)
}
#endif
return rv;
}
void **aResult)
{
#ifdef PR_LOGGING
{
}
#endif
return rv;
}
/**
* ContractIDToClassID()
*
* Mapping function from a ContractID to a classID. Directly talks to the registry.
*
*/
{
if (!aContractID)
return NS_ERROR_NULL_POINTER;
if (!aClass)
return NS_ERROR_NULL_POINTER;
if (fe) {
}
#ifdef PR_LOGGING
char *buf = 0;
if (NS_SUCCEEDED(rv))
("nsComponentManager: ContractIDToClassID(%s)->%s", aContractID,
if (buf)
}
#endif
return rv;
}
/**
* CLSIDToContractID()
*
* Translates a classID to a {ContractID, Class Name}. Does direct registry
* access to do the translation.
*
* NOTE: Since this isn't heavily used, we arent caching this.
*/
char* *aClassName,
char* *aContractID)
{
NS_WARNING("Need to implement CLSIDToContractID");
#ifdef PR_LOGGING
{
("nsComponentManager: CLSIDToContractID(%s)->%s", buf,
if (buf)
}
#endif
return rv;
}
#ifdef XPCOM_CHECK_PENDING_CIDS
// This method must be called from within the mMon monitor
{
{
// Note that you may see this assertion by near-simultaneous
// calls to GetService on multiple threads.
return NS_ERROR_NOT_AVAILABLE;
}
}
return NS_OK;
}
// This method must be called from within the mMon monitor
void
{
}
#endif
/**
* CreateInstance()
*
* Create an instance of an object that implements an interface and belongs
* to the implementation aClass using the factory. The factory is immediately
* released and not held onto for any longer.
*/
void **aResult)
{
// test this first, since there's no point in creating a component during
// shutdown -- whether it's available or not would depend on the order it
// occurs in the list
if (gXPCOMShuttingDown) {
// When processing shutdown, dont process new GetService() requests
#ifdef SHOW_DENIED_ON_SHUTDOWN
#endif /* SHOW_DENIED_ON_SHUTDOWN */
return NS_ERROR_UNEXPECTED;
}
{
return NS_ERROR_NULL_POINTER;
}
if (!entry)
return NS_ERROR_FACTORY_NOT_REGISTERED;
#ifdef SHOW_CI_ON_EXISTING_SERVICE
if (entry->mServiceObject) {
}
#endif
if (NS_SUCCEEDED(rv))
{
}
else
{
// Translate error values
}
#ifdef PR_LOGGING
{
("nsComponentManager: CreateInstance(%s) %s", buf,
if (buf)
}
#endif
return rv;
}
/**
* CreateInstanceByContractID()
*
* A variant of CreateInstance() that creates an instance of the object that
* implements the interface aIID and whose implementation has a contractID aContractID.
*
* This is only a convenience routine that turns around can calls the
* CreateInstance() with classid and iid.
*/
void **aResult)
{
// test this first, since there's no point in creating a component during
// shutdown -- whether it's available or not would depend on the order it
// occurs in the list
if (gXPCOMShuttingDown) {
// When processing shutdown, dont process new GetService() requests
#ifdef SHOW_DENIED_ON_SHUTDOWN
#endif /* SHOW_DENIED_ON_SHUTDOWN */
return NS_ERROR_UNEXPECTED;
}
{
return NS_ERROR_NULL_POINTER;
}
if (!entry)
return NS_ERROR_FACTORY_NOT_REGISTERED;
#ifdef SHOW_CI_ON_EXISTING_SERVICE
if (entry->mServiceObject) {
message =
NS_LITERAL_CSTRING("You are calling CreateInstance \"") +
NS_LITERAL_CSTRING("\" when a service for this CID already exists! "
"Add it to abusedContracts to track down the service consumer.");
}
#endif
if (NS_SUCCEEDED(rv))
{
}
else
{
// Translate error values
}
("nsComponentManager: CreateInstanceByContractID(%s) %s", aContractID,
return rv;
}
// Service Manager Impl
static
void *aData)
{
if (!entry->mFactoryEntry)
return PL_DHASH_NEXT;
return PL_DHASH_NEXT;
}
static
void *aData)
{
if (!entry->mFactoryEntry)
return PL_DHASH_NEXT;
return PL_DHASH_NEXT;
}
{
if (!gXPCOMShuttingDown)
return NS_ERROR_FAILURE;
if (mContractIDs.ops) {
}
if (mFactories.ops) {
}
return NS_OK;
}
void* *result)
{
// test this first, since there's no point in returning a service during
// shutdown -- whether it's available or not would depend on the order it
// occurs in the list
if (gXPCOMShuttingDown) {
// When processing shutdown, dont process new GetService() requests
#ifdef SHOW_DENIED_ON_SHUTDOWN
#endif /* SHOW_DENIED_ON_SHUTDOWN */
return NS_ERROR_UNEXPECTED;
}
}
}
#ifdef XPCOM_CHECK_PENDING_CIDS
return rv; // NOP_AND_BREAK
#endif
// We need to not be holding the service manager's monitor while calling
// CreateInstance, because it invokes user code which could try to re-enter
// the service manager:
#ifdef XPCOM_CHECK_PENDING_CIDS
#endif
return rv;
if (!entry) { // second hash lookup for GetService
}
if (!entry) return NS_ERROR_FAILURE;
}
return rv;
}
{
// check to see if we have a factory entry for the service
if (!entry) { // XXXdougt - should we require that all services register factories?? probably not.
void *mem;
if (!mem)
return NS_ERROR_OUT_OF_MEMORY;
PL_DHASH_ADD));
if (!factoryTableEntry)
return NS_ERROR_OUT_OF_MEMORY;
}
else {
if (entry->mServiceObject)
return NS_ERROR_FAILURE;
}
return NS_OK;
}
{
}
return NS_ERROR_SERVICE_NOT_AVAILABLE;
return rv;
}
{
// check to see if we have a factory entry for the service
if (!entry) { // XXXdougt - should we require that all services register factories?? probably not.
void *mem;
if (!mem)
return NS_ERROR_OUT_OF_MEMORY;
PL_DHASH_ADD));
if (!contractIDTableEntry) {
delete entry;
return NS_ERROR_OUT_OF_MEMORY;
}
if (!contractIDTableEntry->mContractID) {
}
}
else {
if (entry->mServiceObject)
return NS_ERROR_FAILURE;
}
return NS_OK;
}
{
// Now we want to get the service if we already got it. If not, we dont want
// to create an instance of it. mmh!
// test this first, since there's no point in returning a service during
// shutdown -- whether it's available or not would depend on the order it
// occurs in the list
if (gXPCOMShuttingDown) {
// When processing shutdown, dont process new GetService() requests
#ifdef SHOW_DENIED_ON_SHUTDOWN
#endif /* SHOW_DENIED_ON_SHUTDOWN */
return NS_ERROR_UNEXPECTED;
}
}
}
return rv;
}
{
// Now we want to get the service if we already got it. If not, we dont want
// to create an instance of it. mmh!
// test this first, since there's no point in returning a service during
// shutdown -- whether it's available or not would depend on the order it
// occurs in the list
if (gXPCOMShuttingDown) {
// When processing shutdown, dont process new GetService() requests
#ifdef SHOW_DENIED_ON_SHUTDOWN
#endif /* SHOW_DENIED_ON_SHUTDOWN */
return NS_ERROR_UNEXPECTED;
}
{
}
} // exit monitor
}
return rv;
}
{
}
return NS_ERROR_SERVICE_NOT_AVAILABLE;
return rv;
}
void* *result)
{
// test this first, since there's no point in returning a service during
// shutdown -- whether it's available or not would depend on the order it
// occurs in the list
if (gXPCOMShuttingDown) {
// When processing shutdown, dont process new GetService() requests
#ifdef SHOW_DENIED_ON_SHUTDOWN
#endif /* SHOW_DENIED_ON_SHUTDOWN */
return NS_ERROR_UNEXPECTED;
}
}
if (entry) {
if (entry->mServiceObject) {
}
#ifdef XPCOM_CHECK_PENDING_CIDS
return rv; // NOP_AND_BREAK
#endif
}
// We need to not be holding the service manager's monitor while calling
// CreateInstance, because it invokes user code which could try to re-enter
// the service manager:
#ifdef XPCOM_CHECK_PENDING_CIDS
if (entry)
#endif
return rv;
if (!entry) { // second hash lookup for GetService
}
if (!entry) return NS_ERROR_FAILURE;
}
return rv;
}
{
}
{
}
{
return NS_OK;
}
{
return NS_OK;
}
/*
* I want an efficient way to allocate a buffer to the right size
* and stick the prefix and dllName in, then be able to hand that buffer
* off to the FactoryEntry. Is that so wrong?
*
* *regName is allocated on success.
*
* This should live in nsNativeComponentLoader.cpp, I think.
*/
static nsresult
{
char *registryName;
// from here on it, we want len sans terminating NUL
if (!registryName)
return NS_ERROR_OUT_OF_MEMORY;
*regName = registryName;
#ifdef DEBUG_shaver_off
#endif
return NS_OK;
}
char **aRegistryName)
{
if (!mComponentsDir)
return NS_ERROR_NOT_INITIALIZED;
if (!aSpec) {
return NS_OK;
}
// First check to see if this component is in the application
// components directory
if (containedIn){
return rv;
}
// Next check to see if this component is in the GRE
// components directory
if (containedIn){
return rv;
}
/* absolute names include volume info on Mac, so persistent descriptor */
return rv;
}
{
// i18n: assuming aLocation is encoded for the current locale
return NS_ERROR_NULL_POINTER;
/* abs:/full/path/to/libcomponent.so */
if (!file) return NS_ERROR_FAILURE;
return rv;
}
if (!mComponentsDir)
return NS_ERROR_NOT_INITIALIZED;
return rv;
}
if (!mGREComponentsDir)
return NS_ERROR_NOT_INITIALIZED;
return rv;
}
return NS_ERROR_INVALID_ARG;
}
/**
* RegisterFactory()
*
* Register a factory to be responsible for creation of implementation of
* classID aClass. Plus creates as association of aClassName and aContractID
* to the classID. If replace is PR_TRUE, we replace any existing registrations
* with this one.
*
* Once registration is complete, we add the class to the factories cache
* that we maintain. The factories cache is the ONLY place where these
* registrations are ever kept.
*
* The other RegisterFunctions create a loader mapping and persistent
* location, but we just slam it into the cache here. And we don't call the
* loader's OnRegister function, either.
*/
const char *aClassName,
const char *aContractID,
{
#ifdef PR_LOGGING
{
("nsComponentManager: RegisterFactory(%s, %s)", buf,
if (buf)
}
#endif
&aClass,
PL_DHASH_ADD));
if (!factoryTableEntry)
return NS_ERROR_OUT_OF_MEMORY;
}
{
// Already registered
("\t\tFactory already registered."));
return NS_ERROR_FACTORY_EXISTS;
}
void *mem;
if (!mem)
return NS_ERROR_OUT_OF_MEMORY;
if (!entry)
return NS_ERROR_OUT_OF_MEMORY;
// Update the ContractID->CLSID Map
if (aContractID) {
("\t\tFactory register succeeded. "
"Hashing contractid (%s) FAILED.", aContractID));
return rv;
}
}
("\t\tFactory register succeeded contractid=%s.",
return NS_OK;
}
const char *aClassName,
const char *aContractID,
const char *aPersistentDescriptor,
{
strlen(aPersistentDescriptor) : 0,
}
const char *aClassName,
const char *aContractID,
const char *aLocation,
const char *aType)
{
aType);
}
/*
* Register a component, using whatever they stuck in the nsIFile.
*/
const char *aClassName,
const char *aContractID,
{
return rv;
return rv;
}
const char *aClassName,
const char *aContractID,
const char *aDllName,
{
// deprecated and obsolete.
return NS_ERROR_NOT_IMPLEMENTED;
}
/*
* Add a component to the known universe of components.
* Once we enter this function, we own aRegistryName, and must free it
* or hand it to nsFactoryEntry. Common exit point ``out'' helps keep us
* sane.
*/
const char *aClassName,
const char *aContractID,
const char *aRegistryName,
const char *aType)
{
// Normalize proid and classname
#ifdef PR_LOGGING
{
("nsComponentManager: RegisterComponentCommon(%s, %s, %s, %s)",
buf,
aRegistryName, aType));
if (buf)
}
#endif
("\t\tFactory already registered."));
return NS_ERROR_FACTORY_EXISTS;
}
("\t\tgetting loader for %s FAILED\n", aType));
return rv;
}
if (entry) {
}
else {
// Arena allocate the nsFactoryEntry
void *mem;
if (!mem)
return NS_ERROR_OUT_OF_MEMORY;
if (!entry)
return NS_ERROR_OUT_OF_MEMORY;
PL_DHASH_ADD));
if (!factoryTableEntry)
return NS_ERROR_OUT_OF_MEMORY;
}
// Update the ContractID->CLSID Map
if (contractID) {
("\t\tHashContractID(%s) FAILED\n", contractID));
return rv;
}
}
return rv;
}
{
// Make sure we have a valid type
return NS_ERROR_INVALID_ARG;
if (*aLoader) {
return NS_OK;
}
return rv;
if (NS_SUCCEEDED(rv)) {
}
return rv;
}
// Convert a loader type string into an index into the component data
// array. Empty loader types are converted to NATIVE. Returns -1 if
// loader type cannot be determined.
int
{
// Empty type strings are NATIVE
return NS_COMPONENT_TYPE_NATIVE;
}
for (int i=NS_COMPONENT_TYPE_NATIVE; i<mNLoaderData; i++) {
return i;
}
// Not found
return NS_COMPONENT_TYPE_FACTORY_ONLY;
}
// Add a loader type if not already known. Out the typeIndex
// if the loader type is either added or already there.
{
if (typeIndex >= 0) {
*aTypeIndex = typeIndex;
return NS_OK;
}
// Add the loader type
if (mNLoaderData >= mMaxNLoaderData) {
"Memory corruption. nsComponentManagerImpl::mLoaderData array overrun.");
// Need to increase our loader array
nsLoaderdata *new_mLoaderData = (nsLoaderdata *) PR_Realloc(mLoaderData, (mMaxNLoaderData + NS_LOADER_DATA_ALLOC_STEP) * sizeof(nsLoaderdata));
if (!new_mLoaderData)
return NS_ERROR_OUT_OF_MEMORY;
}
// mmh! no memory. return failure.
return NS_ERROR_OUT_OF_MEMORY;
}
mNLoaderData++;
*aTypeIndex = typeIndex;
return NS_OK;
}
typedef struct
{
const char* regName;
static PLDHashOperator PR_CALLBACK
void *aData)
{
if (!entry->mFactoryEntry)
return PL_DHASH_NEXT;
return PL_DHASH_REMOVE;
return PL_DHASH_NEXT;
}
void
{
}
void
{
}
{
#ifdef PR_LOGGING
{
("nsComponentManager: UnregisterFactory(%s)", buf));
if (buf)
}
#endif
// first delete all contract id entries that are registered with this cid.
// next check to see if there is a CID registered
{
}
("\t\tUnregisterFactory() %s",
return rv;
}
const char *registryName)
{
#ifdef PR_LOGGING
{
("nsComponentManager: UnregisterComponent(%s)", buf));
if (buf)
}
#endif
// first delete all contract id entries that are registered with this cid.
// next check to see if there is a CID registered
{
}
("nsComponentManager: Factory unregister(%s) succeeded.", registryName));
return NS_OK;
}
{
}
// XXX Need to pass in aWhen and servicemanager
{
}
// Private implementation of unloading libraries
{
("nsComponentManager: Unloading Libraries."));
// UnloadAll the loaders
/* iterate over all known loaders and ask them to autoregister. */
// Skip mNativeComponentLoader
if (mLoaderData[i].loader) {
break;
}
}
// UnloadAll the native loader
return rv;
}
////////////////////////////////////////////////////////////////////////////////
/**
* AutoRegister(RegistrationInstant, const char *directory)
*
* Given a directory in the following format, this will ensure proper registration
* of all components. No default directory is looked at.
*
* Directory and fullname are what NSPR will accept. For eg.
*
* This will take care not loading already registered dlls, finding and
* registering new dlls, re-registration of modified dlls
*
*/
{
}
{
#ifdef DEBUG
// testing release behaviour
if (getenv("XPCOM_NO_AUTOREG"))
return NS_OK;
#endif
if (inDirSpec)
{
// Use supplied components' directory
}
else
{
if (!dir)
return NS_ERROR_NOT_INITIALIZED;
}
if (!iim)
return NS_ERROR_UNEXPECTED;
// Notify observers of xpcom autoregistration start
"start");
/* do the native loader first, so we can find other loaders */
#endif
/* do InterfaceInfoManager after native loader so it can use components. */
if (!mCategoryManager) {
NS_WARNING("mCategoryManager is null");
return NS_ERROR_UNEXPECTED;
}
continue;
if (!supStr)
continue;
continue;
// We depend on the loader being created. Add the loader type and
// create the loader object too.
int typeIndex;
return rv;
}
// Notify observers of xpcom autoregistration completion
"end");
if (mRegistryDirty)
return rv;
}
{
if (!directory) {
if (!directory)
return NS_ERROR_NOT_INITIALIZED;
}
for (int i = 1; i < mNLoaderData; i++) {
if (!mLoaderData[i].loader) {
continue;
}
break;
}
if (NS_SUCCEEDED(rv))
{
do {
for (int i = 0; i < mNLoaderData; i++) {
if (mLoaderData[i].loader) {
continue;
registered |= b;
}
}
}
return rv;
}
{
/*
* Do we have to give the native loader first crack at it?
* I vote ``no''.
*/
for (int i = 0; i < mNLoaderData; i++) {
if (!mLoaderData[i].loader) {
continue;
// |GetLoaderForType| has filled in |mLoaderData[i].loader|:
}
} else if (didRegister) {
return rv;
}
}
return res;
}
{
for (int i = 0; i < mNLoaderData; i++) {
if (!mLoaderData[i].loader) {
continue;
}
// we need to remove this file from our list of known libraries.
break;
}
}
}
{
if (!aRegistered)
{
NS_ASSERTION(0, "null ptr");
return NS_ERROR_NULL_POINTER;
}
return NS_OK;
}
{
if (!aEnumerator)
{
return NS_ERROR_NULL_POINTER;
}
*aEnumerator = nsnull;
(void*)this,
&aEnum);
return rv;
return NS_OK;
}
{
if (!aEnumerator)
{
return NS_ERROR_NULL_POINTER;
}
*aEnumerator = nsnull;
(void*)this,
&aEnum);
return rv;
return NS_OK;
}
// nsIComponentRegistrar
{
return AutoRegisterImpl(0, aSpec);
if (directory)
return AutoRegisterComponent(0, aSpec);
}
{
// unregistering a complete directory is not implmeneted yet...FIX
return NS_ERROR_NOT_IMPLEMENTED;
if (directory)
return NS_ERROR_NOT_IMPLEMENTED;
return AutoUnregisterComponent(0, aSpec);
}
const char *aClassName,
const char *aContractID,
{
return RegisterFactory(aClass,
PR_TRUE);
}
const char *aClassName,
const char *aContractID,
const char *loaderStr,
const char *aType)
{
if (!loaderStr)
{
return rv;
}
return rv;
}
{
}
{
}
{
if (entry)
else
return NS_OK;
}
{
if (!aEnumerator)
return NS_ERROR_NULL_POINTER;
*aEnumerator = nsnull;
(void*)this,
&aEnum);
return rv;
return NS_OK;
}
{
if (!aEnumerator)
return NS_ERROR_NULL_POINTER;
*aEnumerator = nsnull;
(void*)this,
&aEnum);
return rv;
return NS_OK;
}
char **_retval)
{
return CLSIDToContractID(aClass,
_retval);
}
{
if (!*_retval)
return NS_ERROR_OUT_OF_MEMORY;
}
return rv;
}
// end nsIComponentRegistrar
nsComponentManagerImpl::HasFileChanged(nsIFile *file, const char *loaderString, PRInt64 modDate, PRBool *_retval)
{
return rv;
if (entry)
else
return NS_OK;
}
{
return rv;
// check to see if exists in the array before adding it so that we don't have dups.
if (entry)
{
return NS_OK;
}
if (!entry)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
{
return rv;
if (entry)
delete entry;
return NS_OK;
}
const char *loaderString,
char **_retval)
{
return rv;
if (!entry) {
return NS_ERROR_NOT_INITIALIZED;
}
if (opData)
else
return NS_OK;
}
const char *loaderString,
const char *data)
{
return rv;
if (!entry) {
if (!entry)
return NS_ERROR_OUT_OF_MEMORY;
}
return NS_OK;
}
{
if (now)
return WritePersistentRegistry();
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// Static Access Functions
////////////////////////////////////////////////////////////////////////////////
{
#ifdef DEBUG_dougt
// NS_WARNING("DEPRECATED FUNCTION: Use NS_GetComponentManager");
#endif
{
// XPCOM needs initialization.
}
if (NS_SUCCEEDED(rv))
{
// NO ADDREF since this is never intended to be released.
// See nsComponentManagerObsolete.h for the reason for such
// casting uglyness
*result = (nsIComponentManager*)(void*)(nsIComponentManagerObsolete*) nsComponentManagerImpl::gComponentManager;
}
return rv;
}
{
{
// XPCOM needs initialization.
return rv;
}
return NS_OK;
}
{
{
#ifdef VBOX
// While XPCOM might need initialization, we're not in a position
// to pass the right values to this call. This is actually triggered
// on object destruction, so there is no point in re-initializing,
// and actually the attempt would lead to nested calls to
// xptiInterfaceInfoManager::BuildFileSearchPath, which it detects
// as unsafe in debug builds. Just fail, no real problem.
#ifdef DEBUG
printf("NS_GetServiceManager: no current instance, suppressed XPCOM initialization!\n");
#endif
#else /* !VBOX */
// XPCOM needs initialization.
#endif /* !VBOX */
}
return rv;
return NS_OK;
}
{
{
// XPCOM needs initialization.
}
return rv;
return NS_OK;
}
// nsIComponentLoaderManager is not frozen, but is defined here
// so that I can use it internally in xpcom.
{
{
// XPCOM needs initialization.
}
return rv;
return NS_OK;
}