#include "module.h"
#include "manager.h"
#include "attachment.h"
#include <security_cdsa_utilities/cssmbridge.h>
Module::Module(CssmManager *mgr, const MdsComponent &info, Plugin *plug)
: MdsComponent(info), cssm(*mgr), plugin(plug)
{
if (CSSM_RETURN err = plugin->load(&gGuidCssm, &myGuid(), spiEventRelay, this)) {
plugin->unload();
CssmError::throwMe(err); }
}
Module::~Module()
{
}
bool Module::unload(const ModuleCallback &callback)
{
StLock<Mutex> _(mLock);
if (callbackCount() == 1) {
if (attachmentCount() > 0)
CssmError::throwMe(CSSM_ERRCODE_FUNCTION_FAILED); if (CSSM_RETURN err = plugin->unload(&gGuidCssm, &myGuid(), spiEventRelay, this)) CssmError::throwMe(err); remove(callback);
plugin->unload();
return true;
} else {
remove(callback);
return false;
}
}
CSSM_HANDLE Module::attach(const CSSM_VERSION &version,
uint32 subserviceId,
CSSM_SERVICE_TYPE subserviceType,
const CSSM_API_MEMORY_FUNCS &memoryOps,
CSSM_ATTACH_FLAGS attachFlags,
CSSM_KEY_HIERARCHY keyHierarchy,
CSSM_FUNC_NAME_ADDR *functionTable,
uint32 functionTableSize)
{
StLock<Mutex> _(mLock);
if (!supportsService(subserviceType))
CssmError::throwMe(CSSMERR_CSSM_INVALID_SERVICE_MASK);
Attachment *attachment = cssm.attachmentMakerFor(subserviceType)->make(this,
version,
subserviceId, subserviceType,
memoryOps,
attachFlags,
keyHierarchy,
functionTable, functionTableSize);
try {
attachmentMap.insert(AttachmentMap::value_type(attachment->handle(), attachment));
} catch (...) {
delete attachment;
throw;
}
return attachment->handle();
}
void Module::detach(Attachment *attachment)
{
StLock<Mutex> _(mLock);
attachmentMap.erase(attachment->handle());
}
void Module::spiEvent(CSSM_MODULE_EVENT event,
const Guid &guid,
uint32 subserviceId,
CSSM_SERVICE_TYPE serviceType)
{
StLock<Mutex> _(mLock);
if (guid != myGuid())
CssmError::throwMe(CSSM_ERRCODE_INTERNAL_ERROR);
callbackSet(event, guid, subserviceId, serviceType);
}
CSSM_RETURN Module::spiEventRelay(const CSSM_GUID *ModuleGuid,
void *Context,
uint32 SubserviceId,
CSSM_SERVICE_TYPE ServiceType,
CSSM_MODULE_EVENT EventType)
{
BEGIN_API
static_cast<Module *>(Context)->spiEvent(EventType,
Guid::required(ModuleGuid),
SubserviceId,
ServiceType);
END_API(CSSM)
}