ebb_ews_save_contact_sync (EBookMetaBackend *meta_backend,
			   gboolean overwrite_existing,
			   EConflictResolution conflict_resolution,
			   /* const */ EContact *contact,
			   const gchar *extra,
			   gchar **out_new_uid,
			   gchar **out_new_extra,
			   GCancellable *cancellable,
			   GError **error)
{
	EBookBackendEws *bbews;
	EwsFolderId *fid;
	GSList *items = NULL;
	gboolean is_dl = FALSE;
	gboolean success;

	g_return_val_if_fail (E_IS_BOOK_BACKEND_EWS (meta_backend), FALSE);
	g_return_val_if_fail (E_IS_CONTACT (contact), FALSE);
	g_return_val_if_fail (out_new_uid != NULL, FALSE);
	g_return_val_if_fail (out_new_extra != NULL, FALSE);

	bbews = E_BOOK_BACKEND_EWS (meta_backend);

	g_rec_mutex_lock (&bbews->priv->cnc_lock);

	if (e_contact_get (contact, E_CONTACT_IS_LIST)) {
		if (!e_ews_connection_satisfies_server_version (bbews->priv->cnc, E_EWS_EXCHANGE_2010)) {
			g_rec_mutex_unlock (&bbews->priv->cnc_lock);
			g_propagate_error (error, EDB_ERROR_EX (NOT_SUPPORTED,
				_("Cannot save contact list, it’s only supported on EWS Server 2010 or later")));
			return FALSE;
		}

		is_dl = TRUE;
	}

	fid = e_ews_folder_id_new (bbews->priv->folder_id, NULL, FALSE);
	if (overwrite_existing) {
		EBookCache *book_cache;
		EContact *old_contact = NULL;

		book_cache = e_book_meta_backend_ref_cache (meta_backend);

		success = e_book_cache_get_contact (book_cache, e_contact_get_const (contact, E_CONTACT_UID), FALSE, &old_contact, cancellable, error);
		if (success) {
			const gchar *original_vcard;

			/* This is for offline changes, where the EContact in the cache
			   is already modified, while the original, the one on the server,
			   is different. Using the cached EContact in this case generates
			   empty UpdateItem request and nothing is saved. */
			original_vcard = ebb_ews_get_original_vcard (old_contact);
			if (original_vcard) {
				EContact *tmp;

				tmp = e_contact_new_from_vcard (original_vcard);
				if (tmp) {
					g_object_unref (old_contact);
					old_contact = tmp;
				}
			}
		}

		if (success) {
			ConvertData cd;
			const gchar *conflict_res = "AlwaysOverwrite";

			cd.bbews = bbews;
			cd.cancellable = cancellable;
			cd.error = error;
			cd.old_contact = old_contact;
			cd.new_contact = contact;
			cd.change_key = NULL;

			if (conflict_resolution == E_CONFLICT_RESOLUTION_FAIL)
				conflict_res = "NeverOverwrite";

			success = e_ews_connection_update_items_sync (bbews->priv->cnc, EWS_PRIORITY_MEDIUM,
				conflict_res, "SendAndSaveCopy", "SendToAllAndSaveCopy",
				bbews->priv->folder_id, is_dl ? ebb_ews_convert_dl_to_updatexml_cb : ebb_ews_convert_contact_to_updatexml_cb,
				&cd, &items, cancellable, error);

			g_free (cd.change_key);
		}

		g_clear_object (&old_contact);
		g_clear_object (&book_cache);
	} else {
		success = e_ews_connection_create_items_sync (bbews->priv->cnc, EWS_PRIORITY_MEDIUM, NULL, NULL,
			fid, is_dl ? ebb_ews_convert_dl_to_xml_cb : ebb_ews_convert_contact_to_xml_cb, contact,
			&items, cancellable, error);
	}

	if (success && items) {
		EEwsItem *item = items->data;
		const EwsId *item_id;

		item_id = e_ews_item_get_id (item);
		*out_new_uid = g_strdup (item_id->id);

		/*
		 * Support for ContactPhoto was added in Exchange 2010 SP2.
		 * We don't want to try to set/get this property if we are running in older version of the server.
		 */
		if (!overwrite_existing &&
		    e_ews_connection_satisfies_server_version (bbews->priv->cnc, E_EWS_EXCHANGE_2010_SP2)) {
			EContactPhoto *photo;

			/*
			 * The contact photo is basically an attachment with a special name.
			 * Considering this, we only can set the contact photo after create the contact itself.
			 * Then we are able to attach the picture to the "Contact Item".
			 */
			photo = e_contact_get (contact, E_CONTACT_PHOTO);
			if (photo) {
				GError *local_error = NULL;

				set_photo (bbews, item_id, contact, photo, NULL, cancellable, &local_error);
				e_contact_photo_free (photo);

				if (local_error) {
					g_propagate_error (error, local_error);
					g_prefix_error (error, "%s", _("Failed to set contact photo:"));
					success = FALSE;
				}
			}
		}
	}

	g_slist_free_full (items, g_object_unref);
	e_ews_folder_id_free (fid);

	g_rec_mutex_unlock (&bbews->priv->cnc_lock);

	ebb_ews_convert_error_to_edb_error (error);
	ebb_ews_maybe_disconnect_sync (bbews, error, cancellable);

	return success;
}