CFErrorRef SecCreateCFErrorWithXPCObject(xpc_object_t xpc_error)
{
    CFErrorRef result = NULL;

    if (xpc_get_type(xpc_error) == XPC_TYPE_DICTIONARY) {
        CFStringRef domain = NULL;

        const char * domain_string = xpc_dictionary_get_string(xpc_error, kDomainKey);
        if (domain_string != NULL) {
            domain = CFStringCreateWithCString(kCFAllocatorDefault, domain_string, kCFStringEncodingUTF8);
        } else {
            domain = sSecXPCErrorDomain;
            CFRetain(domain);
        }
        CFIndex code = (CFIndex) xpc_dictionary_get_int64(xpc_error, kCodeKey);

        const char *description = xpc_dictionary_get_string(xpc_error, kDescriptionKey);

        SecCFCreateErrorWithFormat(code, domain, NULL, &result, NULL, CFSTR("Remote error : %s"), description);

        CFReleaseSafe(domain);
    } else {
        SecCFCreateErrorWithFormat(kSecXPCErrorUnexpectedType, sSecXPCErrorDomain, NULL, &result, NULL, CFSTR("Remote error not dictionary!: %@"), xpc_error);
    }
    return result;
}
CFDictionaryRef xpcEngineUpdate(CFTypeRef target, uint flags, CFDictionaryRef context)
{
	Message msg("update");
	// target can be NULL, a CFURLRef, a SecRequirementRef, or a CFNumberRef
	if (target) {
		if (CFGetTypeID(target) == CFNumberGetTypeID())
			xpc_dictionary_set_uint64(msg, "rule", cfNumber<int64_t>(CFNumberRef(target)));
		else if (CFGetTypeID(target) == CFURLGetTypeID())
			xpc_dictionary_set_string(msg, "url", cfString(CFURLRef(target)).c_str());
		else if (CFGetTypeID(target) == SecRequirementGetTypeID()) {
			CFRef<CFDataRef> data;
			MacOSError::check(SecRequirementCopyData(SecRequirementRef(target), kSecCSDefaultFlags, &data.aref()));
			xpc_dictionary_set_data(msg, "requirement", CFDataGetBytePtr(data), CFDataGetLength(data));
		} else
			MacOSError::throwMe(errSecCSInvalidObjectRef);
	}
	xpc_dictionary_set_int64(msg, "flags", flags);
	CFRef<CFMutableDictionaryRef> ctx = makeCFMutableDictionary();
	if (context)
		CFDictionaryApplyFunction(context, copyCFDictionary, ctx);
	AuthorizationRef localAuthorization = NULL;
	if (CFDictionaryGetValue(ctx, kSecAssessmentUpdateKeyAuthorization) == NULL) {	// no caller-provided authorization
		MacOSError::check(AuthorizationCreate(NULL, NULL, kAuthorizationFlagDefaults, &localAuthorization));
		AuthorizationExternalForm extForm;
		MacOSError::check(AuthorizationMakeExternalForm(localAuthorization, &extForm));
		CFDictionaryAddValue(ctx, kSecAssessmentUpdateKeyAuthorization, CFTempData(&extForm, sizeof(extForm)));
	}
	CFRef<CFDataRef> contextData = makeCFData(CFDictionaryRef(ctx));
	xpc_dictionary_set_data(msg, "context", CFDataGetBytePtr(contextData), CFDataGetLength(contextData));
	
	msg.send();

	if (localAuthorization)
		AuthorizationFree(localAuthorization, kAuthorizationFlagDefaults);
	
	if (int64_t error = xpc_dictionary_get_int64(msg, "error"))
		MacOSError::throwMe(error);
	
	size_t resultLength;
	const void *resultData = xpc_dictionary_get_data(msg, "result", &resultLength);
	return makeCFDictionaryFrom(resultData, resultLength);
}
	void send()
	{
		xpc_object_t reply = xpc_connection_send_message_with_reply_sync(service, obj);
		xpc_release(obj);
		obj = NULL;
		xpc_type_t type = xpc_get_type(reply);
		if (type == XPC_TYPE_DICTIONARY) {
			obj = reply;
			if (int64_t error = xpc_dictionary_get_int64(obj, "error"))
				MacOSError::throwMe(error);
		} else if (type == XPC_TYPE_ERROR) {
			const char *s = xpc_copy_description(reply);
			printf("Error returned: %s\n", s);
			free((char*)s);
			MacOSError::throwMe(errSecCSInternalError);
		} else {
			const char *s = xpc_copy_description(reply);
			printf("Unexpected type of return object: %s\n", s);
			free((char*)s);
		}
	}
void xpcEngineAssess(CFURLRef path, uint flags, CFDictionaryRef context, CFMutableDictionaryRef result)
{
	Message msg("assess");
	xpc_dictionary_set_string(msg, "path", cfString(path).c_str());
	xpc_dictionary_set_int64(msg, "flags", flags);
	CFRef<CFMutableDictionaryRef> ctx = makeCFMutableDictionary();
	if (context)
		CFDictionaryApplyFunction(context, copyCFDictionary, ctx);
	CFRef<CFDataRef> contextData = makeCFData(CFDictionaryRef(ctx));
	xpc_dictionary_set_data(msg, "context", CFDataGetBytePtr(contextData), CFDataGetLength(contextData));
	
	msg.send();
	
	if (int64_t error = xpc_dictionary_get_int64(msg, "error"))
		MacOSError::throwMe(error);

	size_t resultLength;
	const void *resultData = xpc_dictionary_get_data(msg, "result", &resultLength);
	CFRef<CFDictionaryRef> resultDict = makeCFDictionaryFrom(resultData, resultLength);
	CFDictionaryApplyFunction(resultDict, copyCFDictionary, result);
	CFDictionaryAddValue(result, CFSTR("assessment:remote"), kCFBooleanTrue);
}