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);
}
static xpc_object_t
auth_item_copy_auth_item_xpc(auth_item_t item)
{
    xpc_object_t xpc_data = xpc_dictionary_create(NULL, NULL, 0);
    xpc_dictionary_set_string(xpc_data, AUTH_XPC_ITEM_NAME, item->data.name);
    if (item->data.value) {
        xpc_dictionary_set_data(xpc_data, AUTH_XPC_ITEM_VALUE, item->data.value, item->data.valueLength);
    }
    xpc_dictionary_set_uint64(xpc_data, AUTH_XPC_ITEM_FLAGS, item->data.flags);
    xpc_dictionary_set_uint64(xpc_data, AUTH_XPC_ITEM_TYPE, item->type);
    return xpc_data;
}
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);
}