| Index: mozilla/security/nss/lib/pk11wrap/pk11load.c | 
| =================================================================== | 
| --- mozilla/security/nss/lib/pk11wrap/pk11load.c	(revision 191424) | 
| +++ mozilla/security/nss/lib/pk11wrap/pk11load.c	(working copy) | 
| @@ -1,639 +0,0 @@ | 
| -/* This Source Code Form is subject to the terms of the Mozilla Public | 
| - * License, v. 2.0. If a copy of the MPL was not distributed with this | 
| - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 
| -/* | 
| - * The following handles the loading, unloading and management of | 
| - * various PCKS #11 modules | 
| - */ | 
| -#define FORCE_PR_LOG 1 | 
| -#include "seccomon.h" | 
| -#include "pkcs11.h" | 
| -#include "secmod.h" | 
| -#include "prlink.h" | 
| -#include "pk11func.h" | 
| -#include "secmodi.h" | 
| -#include "secmodti.h" | 
| -#include "nssilock.h" | 
| -#include "secerr.h" | 
| -#include "prenv.h" | 
| -#include "utilparst.h" | 
| - | 
| -#define DEBUG_MODULE 1 | 
| - | 
| -#ifdef DEBUG_MODULE | 
| -static char *modToDBG = NULL; | 
| - | 
| -#include "debug_module.c" | 
| -#endif | 
| - | 
| -/* build the PKCS #11 2.01 lock files */ | 
| -CK_RV PR_CALLBACK secmodCreateMutext(CK_VOID_PTR_PTR pmutex) { | 
| -    *pmutex = (CK_VOID_PTR) PZ_NewLock(nssILockOther); | 
| -    if ( *pmutex ) return CKR_OK; | 
| -    return CKR_HOST_MEMORY; | 
| -} | 
| - | 
| -CK_RV PR_CALLBACK secmodDestroyMutext(CK_VOID_PTR mutext) { | 
| -    PZ_DestroyLock((PZLock *)mutext); | 
| -    return CKR_OK; | 
| -} | 
| - | 
| -CK_RV PR_CALLBACK secmodLockMutext(CK_VOID_PTR mutext) { | 
| -    PZ_Lock((PZLock *)mutext); | 
| -    return CKR_OK; | 
| -} | 
| - | 
| -CK_RV PR_CALLBACK secmodUnlockMutext(CK_VOID_PTR mutext) { | 
| -    PZ_Unlock((PZLock *)mutext); | 
| -    return CKR_OK; | 
| -} | 
| - | 
| -static SECMODModuleID  nextModuleID = 1; | 
| -static const CK_C_INITIALIZE_ARGS secmodLockFunctions = { | 
| -    secmodCreateMutext, secmodDestroyMutext, secmodLockMutext, | 
| -    secmodUnlockMutext, CKF_LIBRARY_CANT_CREATE_OS_THREADS| | 
| -	CKF_OS_LOCKING_OK | 
| -    ,NULL | 
| -}; | 
| - | 
| -static PRBool loadSingleThreadedModules = PR_TRUE; | 
| -static PRBool enforceAlreadyInitializedError = PR_TRUE; | 
| -static PRBool finalizeModules = PR_TRUE; | 
| - | 
| -/* set global options for NSS PKCS#11 module loader */ | 
| -SECStatus pk11_setGlobalOptions(PRBool noSingleThreadedModules, | 
| -                                PRBool allowAlreadyInitializedModules, | 
| -                                PRBool dontFinalizeModules) | 
| -{ | 
| -    if (noSingleThreadedModules) { | 
| -        loadSingleThreadedModules = PR_FALSE; | 
| -    } else { | 
| -        loadSingleThreadedModules = PR_TRUE; | 
| -    } | 
| -    if (allowAlreadyInitializedModules) { | 
| -        enforceAlreadyInitializedError = PR_FALSE; | 
| -    } else { | 
| -        enforceAlreadyInitializedError = PR_TRUE; | 
| -    } | 
| -    if (dontFinalizeModules) { | 
| -        finalizeModules = PR_FALSE; | 
| -    } else { | 
| -        finalizeModules = PR_TRUE; | 
| -    } | 
| -    return SECSuccess; | 
| -} | 
| - | 
| -PRBool pk11_getFinalizeModulesOption(void) | 
| -{ | 
| -    return finalizeModules; | 
| -} | 
| - | 
| -/* | 
| - * Allow specification loading the same module more than once at init time. | 
| - * This enables 2 things. | 
| - * | 
| - *    1) we can load additional databases by manipulating secmod.db/pkcs11.txt. | 
| - *    2) we can handle the case where some library has already initialized NSS | 
| - *    before the main application. | 
| - * | 
| - * oldModule is the module we have already initialized. | 
| - * char *modulespec is the full module spec for the library we want to | 
| - * initialize. | 
| - */ | 
| -static SECStatus | 
| -secmod_handleReload(SECMODModule *oldModule, SECMODModule *newModule) | 
| -{ | 
| -    PK11SlotInfo *slot; | 
| -    char *modulespec; | 
| -    char *newModuleSpec; | 
| -    char **children; | 
| -    CK_SLOT_ID *ids; | 
| -    SECMODConfigList *conflist = NULL; | 
| -    SECStatus         rv       = SECFailure; | 
| -    int               count    = 0; | 
| - | 
| -    /* first look for tokens= key words from the module spec */ | 
| -    modulespec = newModule->libraryParams; | 
| -    newModuleSpec = secmod_ParseModuleSpecForTokens(PR_TRUE, | 
| -				newModule->isFIPS, modulespec, &children, &ids); | 
| -    if (!newModuleSpec) { | 
| -	return SECFailure; | 
| -    } | 
| - | 
| -    /* | 
| -     * We are now trying to open a new slot on an already loaded module. | 
| -     * If that slot represents a cert/key database, we don't want to open | 
| -     * multiple copies of that same database. Unfortunately we understand | 
| -     * the softoken flags well enough to be able to do this, so we can only get | 
| -     * the list of already loaded databases if we are trying to open another | 
| -     * internal module. | 
| -     */ | 
| -    if (oldModule->internal) { | 
| -	conflist = secmod_GetConfigList(oldModule->isFIPS, | 
| -					oldModule->libraryParams, &count); | 
| -    } | 
| - | 
| - | 
| -    /* don't open multiple of the same db */ | 
| -    if (conflist && secmod_MatchConfigList(newModuleSpec, conflist, count)) { | 
| -	rv = SECSuccess; | 
| -	goto loser; | 
| -    } | 
| -    slot = SECMOD_OpenNewSlot(oldModule, newModuleSpec); | 
| -    if (slot) { | 
| -	int newID; | 
| -	char **thisChild; | 
| -	CK_SLOT_ID *thisID; | 
| -	char *oldModuleSpec; | 
| - | 
| -	if (secmod_IsInternalKeySlot(newModule)) { | 
| -	    pk11_SetInternalKeySlotIfFirst(slot); | 
| -	} | 
| -	newID = slot->slotID; | 
| -	PK11_FreeSlot(slot); | 
| -	for (thisChild=children, thisID=ids; thisChild && *thisChild; | 
| -						thisChild++,thisID++) { | 
| -	    if (conflist && | 
| -		       secmod_MatchConfigList(*thisChild, conflist, count)) { | 
| -		*thisID = (CK_SLOT_ID) -1; | 
| -		continue; | 
| -	    } | 
| -	    slot = SECMOD_OpenNewSlot(oldModule, *thisChild); | 
| -	    if (slot) { | 
| -		*thisID = slot->slotID; | 
| -		PK11_FreeSlot(slot); | 
| -	    } else { | 
| -		*thisID = (CK_SLOT_ID) -1; | 
| -	    } | 
| -	} | 
| - | 
| -	/* update the old module initialization string in case we need to | 
| -	 * shutdown and reinit the whole mess (this is rare, but can happen | 
| -	 * when trying to stop smart card insertion/removal threads)... */ | 
| -	oldModuleSpec = secmod_MkAppendTokensList(oldModule->arena, | 
| -		oldModule->libraryParams, newModuleSpec, newID, | 
| -		children, ids); | 
| -	if (oldModuleSpec) { | 
| -	    oldModule->libraryParams = oldModuleSpec; | 
| -	} | 
| - | 
| -	rv = SECSuccess; | 
| -    } | 
| - | 
| -loser: | 
| -    secmod_FreeChildren(children, ids); | 
| -    PORT_Free(newModuleSpec); | 
| -    if (conflist) { | 
| -	secmod_FreeConfigList(conflist, count); | 
| -    } | 
| -    return rv; | 
| -} | 
| - | 
| -/* | 
| - * collect the steps we need to initialize a module in a single function | 
| - */ | 
| -SECStatus | 
| -secmod_ModuleInit(SECMODModule *mod, SECMODModule **reload, | 
| -		  PRBool* alreadyLoaded) | 
| -{ | 
| -    CK_C_INITIALIZE_ARGS moduleArgs; | 
| -    CK_VOID_PTR pInitArgs; | 
| -    CK_RV crv; | 
| - | 
| -    if (reload) { | 
| -	*reload = NULL; | 
| -    } | 
| - | 
| -    if (!mod || !alreadyLoaded) { | 
| -        PORT_SetError(SEC_ERROR_INVALID_ARGS); | 
| -        return SECFailure; | 
| -    } | 
| - | 
| -    if (mod->isThreadSafe == PR_FALSE) { | 
| -	pInitArgs = NULL; | 
| -    } else if (mod->libraryParams == NULL) { | 
| -	pInitArgs = (void *) &secmodLockFunctions; | 
| -    } else { | 
| -	moduleArgs = secmodLockFunctions; | 
| -	moduleArgs.LibraryParameters = (void *) mod->libraryParams; | 
| -	pInitArgs = &moduleArgs; | 
| -    } | 
| -    crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs); | 
| -    if (CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) { | 
| -	SECMODModule *oldModule = NULL; | 
| - | 
| -	/* Library has already been loaded once, if caller expects it, and it | 
| -	 * has additional configuration, try reloading it as well. */ | 
| -	if (reload != NULL && mod->libraryParams) { | 
| -	    oldModule = secmod_FindModuleByFuncPtr(mod->functionList); | 
| -	} | 
| -	/* Library has been loaded by NSS. It means it may be capable of | 
| -	 * reloading */ | 
| -	if (oldModule) { | 
| -	    SECStatus rv; | 
| -	    rv = secmod_handleReload(oldModule, mod); | 
| -	    if (rv == SECSuccess) { | 
| -		/* This module should go away soon, since we've | 
| -		 * simply expanded the slots on the old module. | 
| -		 * When it goes away, it should not Finalize since | 
| -		 * that will close our old module as well. Setting | 
| -		 * the function list to NULL will prevent that close */ | 
| -		mod->functionList = NULL; | 
| -		*reload = oldModule; | 
| -		return SECSuccess; | 
| -	    } | 
| -	    SECMOD_DestroyModule(oldModule); | 
| -	} | 
| -	/* reload not possible, fall back to old semantics */ | 
| -	if (!enforceAlreadyInitializedError) { | 
| -       	    *alreadyLoaded = PR_TRUE; | 
| -            return SECSuccess; | 
| -	} | 
| -    } | 
| -    if (crv != CKR_OK) { | 
| -	if (pInitArgs == NULL || | 
| -		crv == CKR_NETSCAPE_CERTDB_FAILED || | 
| -		crv == CKR_NETSCAPE_KEYDB_FAILED) { | 
| -	    PORT_SetError(PK11_MapError(crv)); | 
| -	    return SECFailure; | 
| -	} | 
| -	if (!loadSingleThreadedModules) { | 
| -	    PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11); | 
| -	    return SECFailure; | 
| -	} | 
| -	mod->isThreadSafe = PR_FALSE; | 
| -    	crv = PK11_GETTAB(mod)->C_Initialize(NULL); | 
| -	if ((CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) && | 
| -	    (!enforceAlreadyInitializedError)) { | 
| -	    *alreadyLoaded = PR_TRUE; | 
| -	    return SECSuccess; | 
| -	} | 
| -    	if (crv != CKR_OK)  { | 
| -	    PORT_SetError(PK11_MapError(crv)); | 
| -	    return SECFailure; | 
| -	} | 
| -    } | 
| -    return SECSuccess; | 
| -} | 
| - | 
| -/* | 
| - * set the hasRootCerts flags in the module so it can be stored back | 
| - * into the database. | 
| - */ | 
| -void | 
| -SECMOD_SetRootCerts(PK11SlotInfo *slot, SECMODModule *mod) { | 
| -    PK11PreSlotInfo *psi = NULL; | 
| -    int i; | 
| - | 
| -    if (slot->hasRootCerts) { | 
| -	for (i=0; i < mod->slotInfoCount; i++) { | 
| -	    if (slot->slotID == mod->slotInfo[i].slotID) { | 
| -		psi = &mod->slotInfo[i]; | 
| -		break; | 
| -	    } | 
| -	} | 
| -	if (psi == NULL) { | 
| -	   /* allocate more slots */ | 
| -	   PK11PreSlotInfo *psi_list = (PK11PreSlotInfo *) | 
| -		PORT_ArenaAlloc(mod->arena, | 
| -			(mod->slotInfoCount+1)* sizeof(PK11PreSlotInfo)); | 
| -	   /* copy the old ones */ | 
| -	   if (mod->slotInfoCount > 0) { | 
| -		PORT_Memcpy(psi_list,mod->slotInfo, | 
| -				(mod->slotInfoCount)*sizeof(PK11PreSlotInfo)); | 
| -	   } | 
| -	   /* assign psi to the last new slot */ | 
| -	   psi = &psi_list[mod->slotInfoCount]; | 
| -	   psi->slotID = slot->slotID; | 
| -	   psi->askpw = 0; | 
| -	   psi->timeout = 0; | 
| -	   psi ->defaultFlags = 0; | 
| - | 
| -	   /* increment module count & store new list */ | 
| -	   mod->slotInfo = psi_list; | 
| -	   mod->slotInfoCount++; | 
| - | 
| -	} | 
| -	psi->hasRootCerts = 1; | 
| -    } | 
| -} | 
| - | 
| -#ifdef NSS_STATIC | 
| -extern CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList); | 
| -extern CK_RV FC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList); | 
| -extern char **NSC_ModuleDBFunc(unsigned long function,char *parameters, void *args); | 
| -extern CK_RV builtinsC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList); | 
| -#else | 
| -static const char* my_shlib_name = | 
| -    SHLIB_PREFIX"nss"SHLIB_VERSION"."SHLIB_SUFFIX; | 
| -static const char* softoken_shlib_name = | 
| -    SHLIB_PREFIX"softokn"SOFTOKEN_SHLIB_VERSION"."SHLIB_SUFFIX; | 
| -static const PRCallOnceType pristineCallOnce; | 
| -static PRCallOnceType loadSoftokenOnce; | 
| -static PRLibrary* softokenLib; | 
| -static PRInt32 softokenLoadCount; | 
| -#endif  /* NSS_STATIC */ | 
| - | 
| -#include "prio.h" | 
| -#include "prprf.h" | 
| -#include <stdio.h> | 
| -#include "prsystem.h" | 
| - | 
| -#ifndef NSS_STATIC | 
| -/* This function must be run only once. */ | 
| -/*  determine if hybrid platform, then actually load the DSO. */ | 
| -static PRStatus | 
| -softoken_LoadDSO( void ) | 
| -{ | 
| -  PRLibrary *  handle; | 
| - | 
| -  handle = PORT_LoadLibraryFromOrigin(my_shlib_name, | 
| -                                      (PRFuncPtr) &softoken_LoadDSO, | 
| -                                      softoken_shlib_name); | 
| -  if (handle) { | 
| -    softokenLib = handle; | 
| -    return PR_SUCCESS; | 
| -  } | 
| -  return PR_FAILURE; | 
| -} | 
| -#endif  /* !NSS_STATIC */ | 
| - | 
| -/* | 
| - * load a new module into our address space and initialize it. | 
| - */ | 
| -SECStatus | 
| -secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule) { | 
| -    PRLibrary *library = NULL; | 
| -    CK_C_GetFunctionList entry = NULL; | 
| -    CK_INFO info; | 
| -    CK_ULONG slotCount = 0; | 
| -    SECStatus rv; | 
| -    PRBool alreadyLoaded = PR_FALSE; | 
| -    char *disableUnload = NULL; | 
| - | 
| -    if (mod->loaded) return SECSuccess; | 
| - | 
| -    /* intenal modules get loaded from their internal list */ | 
| -    if (mod->internal && (mod->dllName == NULL)) { | 
| -#ifdef NSS_STATIC | 
| -    if (mod->isFIPS) { | 
| -        entry = FC_GetFunctionList; | 
| -    } else { | 
| -        entry = NSC_GetFunctionList; | 
| -    } | 
| -    if (mod->isModuleDB) { | 
| -        mod->moduleDBFunc = NSC_ModuleDBFunc; | 
| -    } | 
| -#else | 
| -    /* | 
| -     * Loads softoken as a dynamic library, | 
| -     * even though the rest of NSS assumes this as the "internal" module. | 
| -     */ | 
| -    if (!softokenLib && | 
| -        PR_SUCCESS != PR_CallOnce(&loadSoftokenOnce, &softoken_LoadDSO)) | 
| -        return SECFailure; | 
| - | 
| -    PR_ATOMIC_INCREMENT(&softokenLoadCount); | 
| - | 
| -    if (mod->isFIPS) { | 
| -        entry = (CK_C_GetFunctionList) | 
| -                    PR_FindSymbol(softokenLib, "FC_GetFunctionList"); | 
| -    } else { | 
| -        entry = (CK_C_GetFunctionList) | 
| -                    PR_FindSymbol(softokenLib, "NSC_GetFunctionList"); | 
| -    } | 
| - | 
| -    if (!entry) | 
| -        return SECFailure; | 
| - | 
| -    if (mod->isModuleDB) { | 
| -        mod->moduleDBFunc = (CK_C_GetFunctionList) | 
| -                    PR_FindSymbol(softokenLib, "NSC_ModuleDBFunc"); | 
| -    } | 
| -#endif | 
| - | 
| -    if (mod->moduleDBOnly) { | 
| -        mod->loaded = PR_TRUE; | 
| -        return SECSuccess; | 
| -    } | 
| -    } else { | 
| -	/* Not internal, load the DLL and look up C_GetFunctionList */ | 
| -	if (mod->dllName == NULL) { | 
| -	    return SECFailure; | 
| -	} | 
| -#if defined(NSS_STATIC) && !defined(NSS_DISABLE_ROOT_CERTS) | 
| -	if (strstr(mod->dllName, "nssckbi") != NULL) { | 
| -	    mod->library = NULL; | 
| -	    PORT_Assert(!mod->moduleDBOnly); | 
| -	    entry = builtinsC_GetFunctionList; | 
| -	    PORT_Assert(!mod->isModuleDB); | 
| -	    goto library_loaded; | 
| -	} | 
| -#endif | 
| - | 
| -	/* load the library. If this succeeds, then we have to remember to | 
| -	 * unload the library if anything goes wrong from here on out... | 
| -	 */ | 
| -	library = PR_LoadLibrary(mod->dllName); | 
| -	mod->library = (void *)library; | 
| - | 
| -	if (library == NULL) { | 
| -	    return SECFailure; | 
| -	} | 
| - | 
| -	/* | 
| -	 * now we need to get the entry point to find the function pointers | 
| -	 */ | 
| -	if (!mod->moduleDBOnly) { | 
| -	    entry = (CK_C_GetFunctionList) | 
| -			PR_FindSymbol(library, "C_GetFunctionList"); | 
| -	} | 
| -	if (mod->isModuleDB) { | 
| -	    mod->moduleDBFunc = (void *) | 
| -			PR_FindSymbol(library, "NSS_ReturnModuleSpecData"); | 
| -	} | 
| -#if defined(NSS_STATIC) && !defined(NSS_DISABLE_ROOT_CERTS) | 
| -library_loaded: | 
| -#endif | 
| -	if (mod->moduleDBFunc == NULL) mod->isModuleDB = PR_FALSE; | 
| -	if (entry == NULL) { | 
| -	    if (mod->isModuleDB) { | 
| -		mod->loaded = PR_TRUE; | 
| -		mod->moduleDBOnly = PR_TRUE; | 
| -		return SECSuccess; | 
| -	    } | 
| -	    PR_UnloadLibrary(library); | 
| -	    return SECFailure; | 
| -	} | 
| -    } | 
| - | 
| -    /* | 
| -     * We need to get the function list | 
| -     */ | 
| -    if ((*entry)((CK_FUNCTION_LIST_PTR *)&mod->functionList) != CKR_OK) | 
| -								goto fail; | 
| - | 
| -#ifdef DEBUG_MODULE | 
| -    if (PR_TRUE) { | 
| -	modToDBG = PR_GetEnv("NSS_DEBUG_PKCS11_MODULE"); | 
| -	if (modToDBG && strcmp(mod->commonName, modToDBG) == 0) { | 
| -	    mod->functionList = (void *)nss_InsertDeviceLog( | 
| -	                           (CK_FUNCTION_LIST_PTR)mod->functionList); | 
| -	} | 
| -    } | 
| -#endif | 
| - | 
| -    mod->isThreadSafe = PR_TRUE; | 
| - | 
| -    /* Now we initialize the module */ | 
| -    rv = secmod_ModuleInit(mod, oldModule, &alreadyLoaded); | 
| -    if (rv != SECSuccess) { | 
| -	goto fail; | 
| -    } | 
| - | 
| -    /* module has been reloaded, this module itself is done, | 
| -     * return to the caller */ | 
| -    if (mod->functionList == NULL) { | 
| -	mod->loaded = PR_TRUE; /* technically the module is loaded.. */ | 
| -	return SECSuccess; | 
| -    } | 
| - | 
| -    /* check the version number */ | 
| -    if (PK11_GETTAB(mod)->C_GetInfo(&info) != CKR_OK) goto fail2; | 
| -    if (info.cryptokiVersion.major != 2) goto fail2; | 
| -    /* all 2.0 are a priori *not* thread safe */ | 
| -    if (info.cryptokiVersion.minor < 1) { | 
| -        if (!loadSingleThreadedModules) { | 
| -            PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11); | 
| -            goto fail2; | 
| -        } else { | 
| -            mod->isThreadSafe = PR_FALSE; | 
| -        } | 
| -    } | 
| -    mod->cryptokiVersion = info.cryptokiVersion; | 
| - | 
| -    /* If we don't have a common name, get it from the PKCS 11 module */ | 
| -    if ((mod->commonName == NULL) || (mod->commonName[0] == 0)) { | 
| -	mod->commonName = PK11_MakeString(mod->arena,NULL, | 
| -	   (char *)info.libraryDescription, sizeof(info.libraryDescription)); | 
| -	if (mod->commonName == NULL) goto fail2; | 
| -    } | 
| - | 
| - | 
| -    /* initialize the Slots */ | 
| -    if (PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, NULL, &slotCount) == CKR_OK) { | 
| -	CK_SLOT_ID *slotIDs; | 
| -	int i; | 
| -	CK_RV crv; | 
| - | 
| -	mod->slots = (PK11SlotInfo **)PORT_ArenaAlloc(mod->arena, | 
| -					sizeof(PK11SlotInfo *) * slotCount); | 
| -	if (mod->slots == NULL) goto fail2; | 
| - | 
| -	slotIDs = (CK_SLOT_ID *) PORT_Alloc(sizeof(CK_SLOT_ID)*slotCount); | 
| -	if (slotIDs == NULL) { | 
| -	    goto fail2; | 
| -	} | 
| -	crv = PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, slotIDs, &slotCount); | 
| -	if (crv != CKR_OK) { | 
| -	    PORT_Free(slotIDs); | 
| -	    goto fail2; | 
| -	} | 
| - | 
| -	/* Initialize each slot */ | 
| -	for (i=0; i < (int)slotCount; i++) { | 
| -	    mod->slots[i] = PK11_NewSlotInfo(mod); | 
| -	    PK11_InitSlot(mod,slotIDs[i],mod->slots[i]); | 
| -	    /* look down the slot info table */ | 
| -	    PK11_LoadSlotList(mod->slots[i],mod->slotInfo,mod->slotInfoCount); | 
| -	    SECMOD_SetRootCerts(mod->slots[i],mod); | 
| -	    /* explicitly mark the internal slot as such if IsInternalKeySlot() | 
| -	     * is set */ | 
| -	    if (secmod_IsInternalKeySlot(mod) && (i == (mod->isFIPS ? 0 : 1))) { | 
| -		pk11_SetInternalKeySlotIfFirst(mod->slots[i]); | 
| -	    } | 
| -	} | 
| -	mod->slotCount = slotCount; | 
| -	mod->slotInfoCount = 0; | 
| -	PORT_Free(slotIDs); | 
| -    } | 
| - | 
| -    mod->loaded = PR_TRUE; | 
| -    mod->moduleID = nextModuleID++; | 
| -    return SECSuccess; | 
| -fail2: | 
| -    if (enforceAlreadyInitializedError || (!alreadyLoaded)) { | 
| -        PK11_GETTAB(mod)->C_Finalize(NULL); | 
| -    } | 
| -fail: | 
| -    mod->functionList = NULL; | 
| -    disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD"); | 
| -    if (library && !disableUnload) { | 
| -        PR_UnloadLibrary(library); | 
| -    } | 
| -    return SECFailure; | 
| -} | 
| - | 
| -SECStatus | 
| -SECMOD_UnloadModule(SECMODModule *mod) { | 
| -    PRLibrary *library; | 
| -    char *disableUnload = NULL; | 
| - | 
| -    if (!mod->loaded) { | 
| -	return SECFailure; | 
| -    } | 
| -    if (finalizeModules) { | 
| -        if (mod->functionList &&!mod->moduleDBOnly) { | 
| -	    PK11_GETTAB(mod)->C_Finalize(NULL); | 
| -	} | 
| -    } | 
| -    mod->moduleID = 0; | 
| -    mod->loaded = PR_FALSE; | 
| - | 
| -    /* do we want the semantics to allow unloading the internal library? | 
| -     * if not, we should change this to SECFailure and move it above the | 
| -     * mod->loaded = PR_FALSE; */ | 
| -    if (mod->internal && (mod->dllName == NULL)) { | 
| -#ifndef NSS_STATIC | 
| -        if (0 == PR_ATOMIC_DECREMENT(&softokenLoadCount)) { | 
| -          if (softokenLib) { | 
| -              disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD"); | 
| -              if (!disableUnload) { | 
| -                  PRStatus status = PR_UnloadLibrary(softokenLib); | 
| -                  PORT_Assert(PR_SUCCESS == status); | 
| -              } | 
| -              softokenLib = NULL; | 
| -          } | 
| -          loadSoftokenOnce = pristineCallOnce; | 
| -        } | 
| -#endif | 
| -	return SECSuccess; | 
| -    } | 
| - | 
| -    library = (PRLibrary *)mod->library; | 
| -    /* paranoia */ | 
| -    if (library == NULL) { | 
| -#if defined(NSS_STATIC) && !defined(NSS_DISABLE_ROOT_CERTS) | 
| -	if (strstr(mod->dllName, "nssckbi") != NULL) { | 
| -	    return SECSuccess; | 
| -	} | 
| -#endif | 
| -	return SECFailure; | 
| -    } | 
| - | 
| -    disableUnload = PR_GetEnv("NSS_DISABLE_UNLOAD"); | 
| -    if (!disableUnload) { | 
| -        PR_UnloadLibrary(library); | 
| -    } | 
| -    return SECSuccess; | 
| -} | 
| - | 
| -void | 
| -nss_DumpModuleLog(void) | 
| -{ | 
| -#ifdef DEBUG_MODULE | 
| -    if (modToDBG) { | 
| -	print_final_statistics(); | 
| -    } | 
| -#endif | 
| -} | 
|  |