CoreFoundationBasics.cpp [plain text]
#include <libkern/OSAtomic.h>
#include <CoreFoundation/CoreFoundation.h>
#include "CoreFoundationBasics.h"
#include "Block.h"
#include "TransformFactory.h"
#include "Utilities.h"
#include "syslog.h"
#include "misc.h"
using namespace std;
const CFStringRef gInternalCFObjectName = CFSTR("SecTransform Internal Object");
const CFStringRef gInternalProtectedCFObjectName = CFSTR("SecTransform Internal Object (protected)");
struct RegisteredClassInfo
{
CFRuntimeClass mClass;
CFTypeID mClassID;
RegisteredClassInfo();
void Register(CFStringRef name);
static const RegisteredClassInfo *Find(CFStringRef name);
static dispatch_queue_t readWriteLock;
static dispatch_once_t initializationGuard;
static CFMutableDictionaryRef registeredInfos;
};
dispatch_queue_t RegisteredClassInfo::readWriteLock;
dispatch_once_t RegisteredClassInfo::initializationGuard;
CFMutableDictionaryRef RegisteredClassInfo::registeredInfos;
static CFErrorRef gNoMemory;
CFErrorRef GetNoMemoryError()
{
return gNoMemory;
}
CFErrorRef GetNoMemoryErrorAndRetain()
{
return (CFErrorRef) CFRetain(gNoMemory);
}
static void CoreFoundationObjectRegister()
{
static dispatch_once_t gate = 0;
dispatch_once(&gate,
^{
gNoMemory = CreateGenericErrorRef(kCFErrorDomainPOSIX, ENOMEM, "Out of memory.");
CoreFoundationObject::RegisterObject(gInternalCFObjectName, false);
CoreFoundationObject::RegisterObject(gInternalProtectedCFObjectName, true);
TransformFactory::Setup();
});
}
RegisteredClassInfo::RegisteredClassInfo()
{
memset(&mClass, 0, sizeof(mClass));
dispatch_once(&RegisteredClassInfo::initializationGuard, ^(void) {
RegisteredClassInfo::readWriteLock = dispatch_queue_create("com.apple.security.transform.cfobject.RegisteredClassInfo", DISPATCH_QUEUE_CONCURRENT);
RegisteredClassInfo::registeredInfos = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, NULL);
});
}
CoreFoundationObject::CoreFoundationObject(CFStringRef name) : mHolder(NULL), mObjectType(name)
{
}
CoreFoundationObject::~CoreFoundationObject()
{
}
CFHashCode CoreFoundationObject::Hash()
{
return (CFHashCode)mHolder;
}
void CoreFoundationObject::Finalize()
{
delete this;
}
std::string CoreFoundationObject::FormattingDescription(CFDictionaryRef options)
{
return "CoreFoundationObject";
}
std::string CoreFoundationObject::DebugDescription()
{
return "CoreFoundationObject";
}
Boolean CoreFoundationObject::Equal(const CoreFoundationObject* obj)
{
return mHolder == obj->mHolder;
}
static void FinalizeStub(CFTypeRef typeRef)
{
CoreFoundationHolder::ObjectFromCFType(typeRef)->Finalize();
}
static Boolean IsEqualTo(CFTypeRef ref1, CFTypeRef ref2)
{
if (CFGetTypeID(ref1) != CFGetTypeID(ref2)) {
return false;
}
CoreFoundationHolder* tr1 = (CoreFoundationHolder*) ref1;
CoreFoundationHolder* tr2 = (CoreFoundationHolder*) ref2;
return tr1->mObject->Equal(tr2->mObject);
}
static CFHashCode MakeHash(CFTypeRef typeRef)
{
CoreFoundationHolder* tr = (CoreFoundationHolder*) typeRef;
return tr->mObject->Hash();
}
static CFStringRef MakeFormattingDescription(CFTypeRef typeRef, CFDictionaryRef formatOptions)
{
CoreFoundationHolder* tr = (CoreFoundationHolder*) typeRef;
string desc = tr->mObject->FormattingDescription(formatOptions);
if (desc.length() == 0)
{
return NULL;
}
return CFStringCreateWithCString(NULL, desc.c_str(), kCFStringEncodingMacRoman);
}
static CFStringRef MakeDebugDescription(CFTypeRef typeRef)
{
CoreFoundationHolder* tr = (CoreFoundationHolder*) typeRef;
string desc = tr->mObject->DebugDescription();
if (desc.length() == 0)
{
return NULL;
}
return CFStringCreateWithCString(NULL, desc.c_str(), kCFStringEncodingMacRoman);
}
void CoreFoundationObject::RegisterObject(CFStringRef name, bool protectDelete)
{
RegisteredClassInfo *classRecord = new RegisteredClassInfo;
classRecord->mClass.version = 0;
char *utf8_name = utf8(name);
classRecord->mClass.className = strdup(utf8_name);
free(utf8_name);
classRecord->mClass.init = NULL;
classRecord->mClass.copy = NULL;
classRecord->mClass.finalize = protectDelete ? NULL : FinalizeStub;
classRecord->mClass.equal = IsEqualTo;
classRecord->mClass.hash = MakeHash;
classRecord->mClass.copyFormattingDesc = MakeFormattingDescription;
classRecord->mClass.copyDebugDesc = MakeDebugDescription;
classRecord->mClassID = _CFRuntimeRegisterClass((const CFRuntimeClass * const)&classRecord->mClass);
classRecord->Register(name);
}
CFTypeID CoreFoundationObject::FindObjectType(CFStringRef name)
{
const RegisteredClassInfo *classInfo = RegisteredClassInfo::Find(name);
if (classInfo) {
return classInfo->mClassID;
} else {
return _kCFRuntimeNotATypeID;
}
}
const RegisteredClassInfo *RegisteredClassInfo::Find(CFStringRef name)
{
__block const RegisteredClassInfo *ret = NULL;
dispatch_sync(RegisteredClassInfo::readWriteLock, ^(void) {
ret = (const RegisteredClassInfo *)CFDictionaryGetValue(RegisteredClassInfo::registeredInfos, name);
});
return ret;
}
void RegisteredClassInfo::Register(CFStringRef name)
{
dispatch_barrier_sync(RegisteredClassInfo::readWriteLock, ^(void) {
CFDictionarySetValue(RegisteredClassInfo::registeredInfos, name, this);
});
}
CFStringRef CoreFoundationObject::GetTypeAsCFString()
{
return mObjectType;
}
CoreFoundationHolder* CoreFoundationHolder::MakeHolder(CFStringRef name, CoreFoundationObject* object)
{
CoreFoundationObjectRegister();
CoreFoundationHolder* data = (CoreFoundationHolder*) _CFRuntimeCreateInstance(kCFAllocatorDefault,
CoreFoundationObject::FindObjectType(name),
sizeof(CoreFoundationHolder) - sizeof(CFRuntimeBase),
NULL);
data->mObject = object;
object->SetHolder(data);
return data;
}
CoreFoundationObject* CoreFoundationHolder::ObjectFromCFType(CFTypeRef type)
{
return ((CoreFoundationHolder*) type)->mObject;
}