#ifndef _H_ATTACHMENT
#define _H_ATTACHMENT
#include "cssmint.h"
#include "module.h"
#include <Security/handleobject.h>
#include <Security/cssmalloc.h>
#ifdef _CPP_ATTACHMENT
# pragma export on
#endif
class Attachment : public HandleObject, public CssmMemoryFunctionsAllocator, public CountingMutex { NOCOPY(Attachment)
public:
Attachment(Module *theModule,
const CSSM_VERSION &version,
uint32 subserviceId,
CSSM_SERVICE_TYPE subserviceType,
const CSSM_API_MEMORY_FUNCS &memoryOps,
CSSM_ATTACH_FLAGS attachFlags,
CSSM_KEY_HIERARCHY keyHierarchy);
virtual ~Attachment();
Module &module;
const Guid &myGuid() const { return module.myGuid(); }
CSSM_SERVICE_TYPE subserviceType() const { return mSubserviceType; }
uint32 subserviceId() const { return mSubserviceId; }
const CSSM_VERSION &pluginVersion() const { return mVersion; }
CSSM_ATTACH_FLAGS attachFlags() const { return mAttachFlags; }
bool isThreadSafe() const { return module.isThreadSafe(); }
virtual void resolveSymbols(CSSM_FUNC_NAME_ADDR *FunctionTable,
uint32 NumFunctions) = 0;
void detach(bool isLocked);
template <class Sub> friend Sub &enterAttachment(CSSM_HANDLE);
void lock() { CountingMutex::lock(); }
bool tryLock() { return CountingMutex::tryLock(); }
private:
bool mIsActive;
uint32 mSubserviceId; CSSM_SERVICE_TYPE mSubserviceType;
CSSM_VERSION mVersion; CSSM_ATTACH_FLAGS mAttachFlags; CSSM_KEY_HIERARCHY mKeyHierarchy;
protected:
CSSM_MODULE_FUNCS *spiFunctionTable;
private:
CSSM_UPCALLS upcalls;
static void *upcallMalloc(CSSM_HANDLE handle, uint32 size);
static void upcallFree(CSSM_HANDLE handle, void *mem);
static void *upcallRealloc(CSSM_HANDLE handle, void *mem,uint32 size);
static void *upcallCalloc(CSSM_HANDLE handle, uint32 num, uint32 size);
static CSSM_RETURN upcallCcToHandle(CSSM_CC_HANDLE handle, CSSM_MODULE_HANDLE *modHandle);
static CSSM_RETURN upcallGetModuleInfo(CSSM_MODULE_HANDLE Module,
CSSM_GUID_PTR Guid,
CSSM_VERSION_PTR Version,
uint32 *SubServiceId,
CSSM_SERVICE_TYPE *SubServiceType,
CSSM_ATTACH_FLAGS *AttachFlags,
CSSM_KEY_HIERARCHY *KeyHierarchy,
CSSM_API_MEMORY_FUNCS_PTR AttachedMemFuncs,
CSSM_FUNC_NAME_ADDR_PTR FunctionTable,
uint32 NumFunctions);
};
template <class AttachmentSubclass>
inline AttachmentSubclass &enterAttachment(CSSM_HANDLE h)
{
AttachmentSubclass &attachment = findHandleAndLock<AttachmentSubclass>(h);
attachment.finishEnter();
return attachment;
}
template <CSSM_SERVICE_TYPE type, class FunctionTable>
class StandardAttachment : public Attachment {
public:
typedef map<const char *, unsigned int> NameMap;
StandardAttachment(Module *theModule,
const NameMap &names,
const CSSM_VERSION &version,
uint32 subserviceId,
CSSM_SERVICE_TYPE subserviceType,
const CSSM_API_MEMORY_FUNCS &memoryOps,
CSSM_ATTACH_FLAGS attachFlags,
CSSM_KEY_HIERARCHY keyHierarchy)
: Attachment(theModule, version, subserviceId, subserviceType,
memoryOps, attachFlags, keyHierarchy),
nameMap(names)
{
try {
if (spiFunctionTable->NumberOfServiceFuncs <
sizeof(FunctionTable) / sizeof(CSSM_PROC_ADDR))
CssmError::throwMe(CSSMERR_CSSM_INVALID_ADDIN_FUNCTION_TABLE);
memcpy(&downcalls, spiFunctionTable->ServiceFuncs, sizeof(downcalls));
} catch (...) {
detach(false);
throw;
}
}
void resolveSymbols(CSSM_FUNC_NAME_ADDR *inFunctionTable,
uint32 NumFunctions)
{
for (unsigned n = 0; n < NumFunctions; n++) {
NameMap::const_iterator it = nameMap.find(inFunctionTable[n].Name);
inFunctionTable[n].Address =
(it == nameMap.end()) ? NULL : downcallNumber(it->second);
}
}
FunctionTable downcalls;
CSSM_PROC_ADDR downcallNumber(uint32 index) const
{
assert(index < sizeof(downcalls) / sizeof(CSSM_PROC_ADDR));
return reinterpret_cast<const CSSM_PROC_ADDR *>(&downcalls)[index];
}
private:
const NameMap &nameMap;
};
#ifdef _CPP_ATTACHMENT
# pragma export off
#endif
#endif //_H_ATTACHMENT