ecb_ews_get_items_sync (ECalBackendEws *cbews,
			const GSList *item_ids, /* gchar * */
			const gchar *default_props,
			const EEwsAdditionalProps *add_props,
			GSList **out_components, /* ECalComponent * */
			GCancellable *cancellable,
			GError **error)
{
	GSList *items = NULL, *link, *retry_ids = NULL;
	gboolean success = TRUE;

	g_return_val_if_fail (E_IS_CAL_BACKEND_EWS (cbews), FALSE);
	g_return_val_if_fail (out_components != NULL, FALSE);

	while (success = success && !g_cancellable_set_error_if_cancelled (cancellable, error), success) {
		GSList *received = NULL, *new_retry_ids = NULL, *ids_link;

		success = e_ews_connection_get_items_sync (
			cbews->priv->cnc,
			EWS_PRIORITY_MEDIUM,
			item_ids,
			default_props,
			add_props,
			FALSE,
			NULL,
			E_EWS_BODY_TYPE_TEXT,
			&received,
			NULL, NULL,
			cancellable,
			error);

		for (link = received, ids_link = (GSList *) item_ids; success && link && ids_link; link = g_slist_next (link), ids_link = g_slist_next (ids_link)) {
			EEwsItem *item = link->data;

			if (!item)
				continue;

			if (e_ews_item_get_item_type (item) == E_EWS_ITEM_TYPE_ERROR) {
				const GError *item_error;

				item_error = e_ews_item_get_error (item);
				if (g_error_matches (item_error, EWS_CONNECTION_ERROR, EWS_CONNECTION_ERROR_BATCHPROCESSINGSTOPPED)) {
					new_retry_ids = g_slist_prepend (new_retry_ids, g_strdup (ids_link->data));
					g_object_unref (item);
				} else {
					items = g_slist_prepend (items, item);
				}
			} else {
				items = g_slist_prepend (items, item);
			}
		}

		g_slist_free_full (retry_ids, g_free);
		g_slist_free (received);
		retry_ids = new_retry_ids;

		if (!retry_ids)
			break;

		item_ids = retry_ids;
	}

	g_slist_free_full (retry_ids, g_free);

	items = g_slist_reverse (items);

	if (!success)
		goto exit;

	/* fetch modified occurrences */
	for (link = items; link; link = g_slist_next (link)) {
		EEwsItem *item = link->data;
		const GSList *modified_occurrences;

		if (!item || e_ews_item_get_item_type (item) == E_EWS_ITEM_TYPE_ERROR)
			continue;

		modified_occurrences = e_ews_item_get_modified_occurrences (item);
		if (modified_occurrences) {
			EEwsAdditionalProps *modified_add_props;

			modified_add_props = e_ews_additional_props_new ();
			if (e_ews_connection_satisfies_server_version (cbews->priv->cnc, E_EWS_EXCHANGE_2010)) {
				EEwsExtendedFieldURI *ext_uri;

				modified_add_props->field_uri = g_strdup (GET_ITEMS_SYNC_PROPERTIES_2010);

				ext_uri = e_ews_extended_field_uri_new ();
				ext_uri->distinguished_prop_set_id = g_strdup ("PublicStrings");
				ext_uri->prop_name = g_strdup ("EvolutionEWSStartTimeZone");
				ext_uri->prop_type = g_strdup ("String");
				modified_add_props->extended_furis = g_slist_append (modified_add_props->extended_furis, ext_uri);

				ext_uri = e_ews_extended_field_uri_new ();
				ext_uri->distinguished_prop_set_id = g_strdup ("PublicStrings");
				ext_uri->prop_name = g_strdup ("EvolutionEWSEndTimeZone");
				ext_uri->prop_type = g_strdup ("String");
				modified_add_props->extended_furis = g_slist_append (modified_add_props->extended_furis, ext_uri);
			} else {
				modified_add_props->field_uri = g_strdup (GET_ITEMS_SYNC_PROPERTIES_2007);
			}

			success = ecb_ews_get_items_sync (cbews, modified_occurrences, "IdOnly", modified_add_props, out_components, cancellable, error);

			e_ews_additional_props_free (modified_add_props);

			if (!success)
				goto exit;
		}
	}

	for (link = items; link; link = g_slist_next (link)) {
		EEwsItem *item = link->data;
		ECalComponent *comp;
		GError *local_error = NULL;

		if (!item || e_ews_item_get_item_type (item) == E_EWS_ITEM_TYPE_ERROR)
			continue;

		comp = ecb_ews_item_to_component_sync (cbews, item, cancellable, &local_error);
		if (!comp) {
			if (!local_error)
				continue;

			g_propagate_error (error, local_error);
			success = FALSE;
			break;
		}

		ecb_ews_store_original_comp (comp);

		*out_components = g_slist_prepend (*out_components, comp);
	}

 exit:
	g_slist_free_full (items, g_object_unref);

	return success;
}