[evolution-mapi] Use one mapi_context for each EMapiConnection



commit ac237b8fbcc063f6a6ddaf2e1262e355eda9a6c5
Author: Milan Crha <mcrha redhat com>
Date:   Wed Nov 2 15:26:02 2011 +0100

    Use one mapi_context for each EMapiConnection

 .../e-mapi-account-listener.c                      |   26 ++-
 src/account-setup-eplugin/e-mapi-account-setup.c   |   16 +-
 src/libexchangemapi/e-mapi-cal-utils.c             |    2 +-
 src/libexchangemapi/e-mapi-connection.c            |  205 +++++++-------------
 src/libexchangemapi/e-mapi-connection.h            |   12 +-
 src/libexchangemapi/e-mapi-utils.c                 |   94 +++++++++-
 src/libexchangemapi/e-mapi-utils.h                 |    9 +-
 7 files changed, 208 insertions(+), 156 deletions(-)
---
diff --git a/src/account-setup-eplugin/e-mapi-account-listener.c b/src/account-setup-eplugin/e-mapi-account-listener.c
index 09793cc..a577e5d 100644
--- a/src/account-setup-eplugin/e-mapi-account-listener.c
+++ b/src/account-setup-eplugin/e-mapi-account-listener.c
@@ -1166,9 +1166,14 @@ mapi_account_removed (EAccountList *account_listener, EAccount *account)
 	if (url != NULL) {
 		const gchar *profile = camel_url_get_param (url, "profile");
 		gchar *key = camel_url_to_string (url, CAMEL_URL_HIDE_PARAMS);
+		struct mapi_context *mapi_ctx = NULL;
 		GError *error = NULL;
 
-		e_mapi_delete_profile (profile, &error);
+		if (e_mapi_utils_create_mapi_context (&mapi_ctx, &error)) {
+			e_mapi_delete_profile (mapi_ctx, profile, &error);
+			e_mapi_utils_destroy_mapi_context (mapi_ctx);
+		}
+
 		e_passwords_forget_password (NULL, key);
 
 		g_free (key);
@@ -1189,10 +1194,18 @@ create_profile_entry (CamelURL *url, EAccount *account, CamelMapiSettings *setti
 	gboolean status = FALSE;
 	guint8 attempts = 0;
 	EMapiProfileData empd = { 0 };
+	struct mapi_context *mapi_ctx = NULL;
+	GError *error = NULL;
 
 	if (!e_shell_get_online (e_shell_get_default ()))
 		return FALSE;
 
+	if (!e_mapi_utils_create_mapi_context (&mapi_ctx, &error)) {
+		g_warning ("%s: Failed to create mapi context: %s", G_STRFUNC, error ? error->message : "Unknown error");
+		g_clear_error (&error);
+		return FALSE;
+	}
+	
 	empd.server = url->host;
 	empd.username = url->user;
 	e_mapi_util_profiledata_from_settings (&empd, settings);
@@ -1218,14 +1231,14 @@ create_profile_entry (CamelURL *url, EAccount *account, CamelMapiSettings *setti
 		if (empd.password || empd.krb_sso) {
 			GError *error = NULL;
 
-			status = e_mapi_create_profile (&empd, NULL, NULL, NULL, &error);
+			status = e_mapi_create_profile (mapi_ctx, &empd, NULL, NULL, NULL, &error);
 			if (status) {
 				/* profile was created, try to connect to the server */
 				EMapiConnection *conn;
 				gchar *profname;
 
 				status = FALSE;
-				profname = e_mapi_util_profile_name (&empd, FALSE);
+				profname = e_mapi_util_profile_name (mapi_ctx, &empd, FALSE);
 
 				conn = e_mapi_connection_new (profname, empd.password, NULL, &error);
 				if (conn) {
@@ -1245,6 +1258,8 @@ create_profile_entry (CamelURL *url, EAccount *account, CamelMapiSettings *setti
 		++attempts;
 	}
 
+	e_mapi_utils_destroy_mapi_context (mapi_ctx);
+
 	return status;
 }
 
@@ -1314,8 +1329,7 @@ mapi_account_changed_async (gpointer worker_data, gboolean cancelled, gpointer u
 			empd.server = new_url->host;
 			empd.username = new_url->user;
 			e_mapi_util_profiledata_from_settings (&empd, CAMEL_MAPI_SETTINGS (settings));
-			profname = e_mapi_util_profile_name (&empd,
-								    FALSE);
+			profname = e_mapi_util_profile_name (NULL, &empd, FALSE);
 			camel_mapi_settings_set_profile (CAMEL_MAPI_SETTINGS (settings), profname);
 			camel_settings_save_to_url (settings, new_url);
 			g_free (profname);
@@ -1352,7 +1366,7 @@ mapi_account_changed_async (gpointer worker_data, gboolean cancelled, gpointer u
 				empd.server = new_url->host;
 				empd.username = new_url->user;
 				e_mapi_util_profiledata_from_settings (&empd, CAMEL_MAPI_SETTINGS (settings));
-				profname = e_mapi_util_profile_name (&empd, FALSE);
+				profname = e_mapi_util_profile_name (NULL, &empd, FALSE);
 				camel_mapi_settings_set_profile (CAMEL_MAPI_SETTINGS (settings), profname);
 				camel_settings_save_to_url (settings, new_url);
 				g_free (profname);
diff --git a/src/account-setup-eplugin/e-mapi-account-setup.c b/src/account-setup-eplugin/e-mapi-account-setup.c
index bd59f20..fb59ce8 100644
--- a/src/account-setup-eplugin/e-mapi-account-setup.c
+++ b/src/account-setup-eplugin/e-mapi-account-setup.c
@@ -316,18 +316,18 @@ validate_credentials (GtkWidget *widget, EConfig *config)
 	}
 
 	if (COMPLETE_PROFILEDATA(&empd)) {
-		gboolean status = e_mapi_create_profile (&empd,
-								(mapi_profile_callback_t) create_profile_callback,
-								empd.username,
-								NULL, &error);
+		gboolean status;
+		struct mapi_context *mapi_ctx = NULL;
+
+		status = e_mapi_utils_create_mapi_context (&mapi_ctx, &error);
+		status = status && e_mapi_create_profile (mapi_ctx, &empd, (mapi_profile_callback_t) create_profile_callback, empd.username, NULL, &error);
 		if (status) {
 			/* profile was created, try to connect to the server */
 			EMapiConnection *conn;
 			gchar *profname;
 
 			status = FALSE;
-			profname = e_mapi_util_profile_name (&empd,
-								    FALSE);
+			profname = e_mapi_util_profile_name (mapi_ctx, &empd, FALSE);
 
 			conn = e_mapi_connection_new (profname, empd.password, NULL, &error);
 			if (conn) {
@@ -342,8 +342,7 @@ validate_credentials (GtkWidget *widget, EConfig *config)
 			/* Things are successful */
 			gchar *profname = NULL;
 
-			profname = e_mapi_util_profile_name (&empd,
-								    FALSE);
+			profname = e_mapi_util_profile_name (mapi_ctx, &empd, FALSE);
 			camel_mapi_settings_set_profile (mapi_settings, profname);
 			g_free (profname);
 
@@ -360,6 +359,7 @@ validate_credentials (GtkWidget *widget, EConfig *config)
 			g_free (e);
 		}
 
+		e_mapi_utils_destroy_mapi_context (mapi_ctx);
 	} else {
 		e_passwords_forget_password (NULL, key);
 		e_notice (NULL, GTK_MESSAGE_ERROR, "%s", _("Authentication failed."));
diff --git a/src/libexchangemapi/e-mapi-cal-utils.c b/src/libexchangemapi/e-mapi-cal-utils.c
index de2662e..3f080f0 100644
--- a/src/libexchangemapi/e-mapi-cal-utils.c
+++ b/src/libexchangemapi/e-mapi-cal-utils.c
@@ -2332,7 +2332,7 @@ e_mapi_cal_utils_get_free_busy_data (EMapiConnection *conn, const GSList *users,
 		e_cal_component_commit_sequence (comp);
 		*freebusy = g_slist_append (*freebusy, e_cal_component_get_as_string (comp));
 		g_object_unref (comp);
-		MAPIFreeBuffer(aRow.lpProps);
+		talloc_free (aRow.lpProps);
 	}
 
 	return TRUE;
diff --git a/src/libexchangemapi/e-mapi-connection.c b/src/libexchangemapi/e-mapi-connection.c
index bcfcbd2..0abc68c 100644
--- a/src/libexchangemapi/e-mapi-connection.c
+++ b/src/libexchangemapi/e-mapi-connection.c
@@ -40,22 +40,18 @@
 #include "e-mapi-fast-transfer.h"
 #include <param.h>
 
-#define DEFAULT_PROF_NAME "mapi-profiles.ldb"
-
 static void register_connection (EMapiConnection *conn);
 static void unregister_connection (EMapiConnection *conn);
-static gboolean mapi_profile_create (const EMapiProfileData *empd, mapi_profile_callback_t callback, gconstpointer data, GCancellable *cancellable, GError **perror, gboolean use_locking);
-static struct mapi_session *mapi_profile_load (const gchar *profname, const gchar *password, GCancellable *cancellable, GError **perror);
-static void ema_global_lock (void);
-static void ema_global_unlock (void);
+static gboolean mapi_profile_create (struct mapi_context *mapi_ctx, const EMapiProfileData *empd, mapi_profile_callback_t callback, gconstpointer data, GCancellable *cancellable, GError **perror, gboolean use_locking);
+static struct mapi_session *mapi_profile_load (struct mapi_context *mapi_ctx, const gchar *profname, const gchar *password, GCancellable *cancellable, GError **perror);
 
 /* GObject foo - begin */
 
 G_DEFINE_TYPE (EMapiConnection, e_mapi_connection, G_TYPE_OBJECT)
 
 /* These two macros require 'priv' variable of type EMapiConnectionPrivate */
-#define LOCK()		e_mapi_debug_print ("%s: %s: lock(session/global_lock)", G_STRLOC, G_STRFUNC); g_static_rec_mutex_lock (&priv->session_lock); ema_global_lock();
-#define UNLOCK()	e_mapi_debug_print ("%s: %s: unlock(session/global_lock)", G_STRLOC, G_STRFUNC); g_static_rec_mutex_unlock (&priv->session_lock); ema_global_unlock();
+#define LOCK()		e_mapi_debug_print ("%s: %s: lock(session & global)", G_STRLOC, G_STRFUNC); g_static_rec_mutex_lock (&priv->session_lock); e_mapi_utils_global_lock ();
+#define UNLOCK()	e_mapi_debug_print ("%s: %s: unlock(session & global)", G_STRLOC, G_STRFUNC); g_static_rec_mutex_unlock (&priv->session_lock); e_mapi_utils_global_unlock ();
 
 #define e_return_val_mapi_error_if_fail(expr, _code, _val)				\
 	G_STMT_START {									\
@@ -144,9 +140,8 @@ make_mapi_error (GError **perror, const gchar *context, enum MAPISTATUS mapi_sta
 	g_propagate_error (perror, error);
 }
 
-struct mapi_context *mapi_ctx = NULL;
-
 struct _EMapiConnectionPrivate {
+	struct mapi_context *mapi_ctx;
 	struct mapi_session *session;
 	GStaticRecMutex session_lock;
 
@@ -238,6 +233,9 @@ e_mapi_connection_finalize (GObject *object)
 		UNLOCK ();
 		g_static_rec_mutex_free (&priv->session_lock);
 		g_static_rec_mutex_free (&priv->folders_lock);
+
+		e_mapi_utils_destroy_mapi_context (priv->mapi_ctx);
+		priv->mapi_ctx = NULL;
 	}
 
 	if (G_OBJECT_CLASS (e_mapi_connection_parent_class)->finalize)
@@ -364,14 +362,18 @@ e_mapi_connection_new (const gchar *profile, const gchar *password, GCancellable
 {
 	EMapiConnection *conn;
 	EMapiConnectionPrivate *priv;
+	struct mapi_context *mapi_ctx = NULL;
 	struct mapi_session *session;
 	enum MAPISTATUS ms;
 
 	e_return_val_mapi_error_if_fail (profile != NULL, MAPI_E_INVALID_PARAMETER, NULL);
 
-	session = mapi_profile_load (profile, password, cancellable, perror);
+	if (!e_mapi_utils_create_mapi_context (&mapi_ctx, perror))
+		return NULL;
+
+	session = mapi_profile_load (mapi_ctx, profile, password, cancellable, perror);
 	if (!session) {
-		e_mapi_debug_print ("%s: %s: Login failed ", G_STRLOC, G_STRFUNC);
+		e_mapi_utils_destroy_mapi_context (mapi_ctx);
 		return NULL;
 	}
 
@@ -381,6 +383,7 @@ e_mapi_connection_new (const gchar *profile, const gchar *password, GCancellable
 
 	LOCK ();
 	mapi_object_init (&priv->msg_store);
+	priv->mapi_ctx = mapi_ctx;
 	priv->session = session;
 
 	/* Open the message store and keep it opened for all the life-time for this connection */
@@ -443,7 +446,7 @@ e_mapi_connection_reconnect (EMapiConnection *conn, const gchar *password, GCanc
 	if (priv->session)
 		e_mapi_connection_close (conn);
 
-	priv->session = mapi_profile_load (priv->profile, password, cancellable, perror);
+	priv->session = mapi_profile_load (priv->mapi_ctx, priv->profile, password, cancellable, perror);
 	if (!priv->session) {
 		e_mapi_debug_print ("%s: %s: Login failed ", G_STRLOC, G_STRFUNC);
 		UNLOCK ();
@@ -1298,7 +1301,7 @@ e_mapi_util_get_attachments (EMapiConnection *conn,
 					if ((lpProps->ulPropTag & 0xFFFF) == PT_UNICODE)
 						attachment->lpProps[az] = *lpProps;
 				}
-				MAPIFreeBuffer (tags);
+				talloc_free (tags);
 			}
 
 			az++;
@@ -1407,21 +1410,21 @@ e_mapi_connection_fetch_gal (EMapiConnection *conn,
 			break;
 		}
 		if (aRowSet->cRows) {
-			ema_global_unlock ();
+			e_mapi_utils_global_unlock ();
 			for (i = 0; i < aRowSet->cRows; i++, count++) {
 				if (!cb (conn, count, n_rows, &aRowSet->aRow[i], data, cancellable, perror)) {
 					ms = MAPI_E_RESERVED;
 					break;
 				}
 			}
-			ema_global_lock ();
+			e_mapi_utils_global_lock ();
 		} else {
-			MAPIFreeBuffer (aRowSet);
+			talloc_free (aRowSet);
 			break;
 		}
 
 		ulFlags = TABLE_CUR;
-		MAPIFreeBuffer (aRowSet);
+		talloc_free (aRowSet);
 	}
 
 	talloc_free (mem_ctx);
@@ -2118,9 +2121,9 @@ e_mapi_connection_fetch_items  (EMapiConnection *conn,
 				item_data->total = count; //Total entries in the table.
 				item_data->index = cursor_pos + i; //cursor_pos + current_table_index
 
-				ema_global_unlock ();
+				e_mapi_utils_global_unlock ();
 				cb_retval = cb (item_data, data, cancellable, perror);
-				ema_global_lock ();
+				e_mapi_utils_global_lock ();
 
 				g_free (item_data);
 			} else {
@@ -2149,7 +2152,7 @@ e_mapi_connection_fetch_items  (EMapiConnection *conn,
 
  cleanup:
 	if (propsTagArray)
-		MAPIFreeBuffer (propsTagArray);
+		talloc_free (propsTagArray);
 	mapi_object_release(&obj_folder);
 	mapi_object_release(&obj_table);
 	talloc_free (mem_ctx);
@@ -2315,10 +2318,10 @@ e_mapi_connection_fetch_object_props (EMapiConnection *conn,
 		item_data->recipients = recip_list;
 		item_data->attachments = attach_list;
 
-		ema_global_unlock ();
 		/* NOTE: stream_list, recipient_list and attach_list should be freed by the callback */
+		e_mapi_utils_global_unlock ();
 		cb (item_data, data, cancellable, perror);
-		ema_global_lock ();
+		e_mapi_utils_global_lock ();
 
 		g_free (item_data);
 	} else {
@@ -3520,7 +3523,7 @@ mapi_move_items (EMapiConnection *conn,
 		mapi_id_array_t msg_id_array;
 		gint count = 0;
 
-		mapi_id_array_init (mapi_ctx, &msg_id_array);
+		mapi_id_array_init (conn->priv->mapi_ctx, &msg_id_array);
 
 		for (l = mid_list; l != NULL && count < 500; l = g_slist_next (l), count++)
 			mapi_id_array_add_id (&msg_id_array, *((mapi_id_t *)l->data));
@@ -3799,7 +3802,7 @@ get_child_folders (EMapiConnection *conn,
 	ms = foreach_tablerow (conn, folder_id, mem_ctx, &obj_table, get_folder_hierarchy_cb, &gfh, cancellable, perror);
 
  cleanup:
-	MAPIFreeBuffer (spropTagArray);
+	talloc_free (spropTagArray);
 	mapi_object_release (&obj_folder);
 	mapi_object_release (&obj_table);
 
@@ -4022,7 +4025,7 @@ e_mapi_connection_get_folders_list (EMapiConnection *conn,
 
 	lpProps = talloc_zero(mem_ctx, struct SPropValue);
 	ms = GetProps (&priv->msg_store, MAPI_PROPS_SKIP_NAMEDID_CHECK | MAPI_UNICODE, SPropTagArray, &lpProps, &count);
-	MAPIFreeBuffer(SPropTagArray);
+	talloc_free (SPropTagArray);
 
 	if (ms != MAPI_E_SUCCESS) {
 		make_mapi_error (perror, "GetProps", ms);
@@ -4322,8 +4325,12 @@ e_mapi_connection_events_monitor (EMapiConnection *conn, struct mapi_notify_cont
 
 struct tcp_data
 {
+	struct mapi_context *mapi_ctx;
 	const gchar *profname;
 	const gchar *password;
+	GCancellable *cancellable;
+	GError **perror;
+
 	EFlag *eflag;
 	gboolean has_profile;
 };
@@ -4360,11 +4367,11 @@ try_create_profile_main_thread_cb (struct tcp_data *data)
 			empd.password = (gchar*)data->password;
 
 			if (COMPLETE_PROFILEDATA(&empd)) {
-				gchar *profname = e_mapi_util_profile_name (&empd, FALSE);
+				gchar *profname = e_mapi_util_profile_name (data->mapi_ctx, &empd, FALSE);
 
 				if (profname && g_str_equal (profname, data->profname)) {
 					/* do not use locking here, because when this is called then other thread is holding the lock */
-					data->has_profile = mapi_profile_create (&empd, NULL, NULL, NULL, NULL, FALSE);
+					data->has_profile = mapi_profile_create (data->mapi_ctx, &empd, NULL, NULL, NULL, data->perror, FALSE);
 
 					g_free (profname);
 					g_object_unref (settings);
@@ -4389,17 +4396,21 @@ try_create_profile_main_thread_cb (struct tcp_data *data)
 }
 
 static gboolean
-try_create_profile (const gchar *profname, const gchar *password)
+try_create_profile (struct mapi_context *mapi_ctx, const gchar *profname, const gchar *password, GCancellable *cancellable, GError **perror)
 {
 	struct tcp_data data;
 
+	g_return_val_if_fail (mapi_ctx != NULL, FALSE);
 	g_return_val_if_fail (profname != NULL, FALSE);
 	g_return_val_if_fail (*profname != 0, FALSE);
 
+	data.mapi_ctx = mapi_ctx;
 	data.profname = profname;
 	data.password = password;
 	data.eflag = e_flag_new ();
 	data.has_profile = FALSE;
+	data.cancellable = cancellable;
+	data.perror = perror;
 
 	if (!g_main_context_is_owner (g_main_context_default ())) {
 		/* function called from other than main thread */
@@ -4414,89 +4425,20 @@ try_create_profile (const gchar *profname, const gchar *password)
 	return data.has_profile;
 }
 
-static gboolean
-ensure_mapi_init_called (GError **perror)
-{
-	static gboolean called = FALSE;
-	static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
-	const gchar *user_data_dir;
-	gchar *profpath;
-	enum MAPISTATUS ms;
-
-	g_static_mutex_lock (&mutex);
-	if (called) {
-		g_static_mutex_unlock (&mutex);
-		return TRUE;
-	}
-
-	user_data_dir = e_get_user_data_dir ();
-	profpath = g_build_filename (user_data_dir, DEFAULT_PROF_NAME, NULL);
-
-	if (!g_file_test (profpath, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
-		/* Create a ProfileStore */
-		ms = CreateProfileStore (profpath, LIBMAPI_LDIF_DIR);
-		if (ms != MAPI_E_SUCCESS && (ms != MAPI_E_NO_ACCESS || !g_file_test (profpath, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
-			make_mapi_error (perror, "CreateProfileStore", ms);
-			g_free (profpath);
-
-			g_static_mutex_unlock (&mutex);
-			return FALSE;
-		}
-	}
-
-	ms = MAPIInitialize (&mapi_ctx, profpath);
-	if (ms == MAPI_E_SESSION_LIMIT) {
-		/* do nothing, the profile store is already initialized */
-		/* but this shouldn't happen */
-	} else if (ms != MAPI_E_SUCCESS) {
-		make_mapi_error (perror, "MAPIInitialize", ms);
-		g_free (profpath);
-
-		g_static_mutex_unlock (&mutex);
-		return FALSE;
-	}
-
-	g_free (profpath);
-
-	called = TRUE;
-	g_static_mutex_unlock (&mutex);
-
-	return TRUE;
-}
-
-/* used when dealing with profiles */
-static GStaticRecMutex profile_mutex = G_STATIC_REC_MUTEX_INIT;
-
-/* because openchange/samba4 is not thread safe */
-static void
-ema_global_lock (void)
-{
-	g_static_rec_mutex_lock (&profile_mutex);
-}
-
-/* because openchange/samba4 is not thread safe */
-static void
-ema_global_unlock (void)
-{
-	g_static_rec_mutex_unlock (&profile_mutex);
-}
-
 static struct mapi_session *
-mapi_profile_load (const gchar *profname, const gchar *password, GCancellable *cancellable, GError **perror)
+mapi_profile_load (struct mapi_context *mapi_ctx, const gchar *profname, const gchar *password, GCancellable *cancellable, GError **perror)
 {
 	enum MAPISTATUS	ms = MAPI_E_SUCCESS;
 	struct mapi_session *session = NULL;
 	guint32 debug_log_level = 0;
 
+	e_return_val_mapi_error_if_fail (mapi_ctx != NULL, MAPI_E_INVALID_PARAMETER, NULL);
 	e_return_val_mapi_error_if_fail (profname != NULL, MAPI_E_INVALID_PARAMETER, NULL);
 
-	g_static_rec_mutex_lock (&profile_mutex);
+	e_mapi_utils_global_lock ();
 
 	e_mapi_debug_print("%s: Entering %s ", G_STRLOC, G_STRFUNC);
 
-	if (!ensure_mapi_init_called (perror))
-		goto cleanup;
-
 	/* Initialize libmapi logger*/
 	if (g_getenv ("MAPI_DEBUG")) {
 		debug_log_level = atoi (g_getenv ("MAPI_DEBUG"));
@@ -4507,7 +4449,7 @@ mapi_profile_load (const gchar *profname, const gchar *password, GCancellable *c
 	e_mapi_debug_print("Loading profile %s ", profname);
 
 	ms = MapiLogonEx (mapi_ctx, &session, profname, password);
-	if (ms == MAPI_E_NOT_FOUND && try_create_profile (profname, password))
+	if (ms == MAPI_E_NOT_FOUND && try_create_profile (mapi_ctx, profname, password, cancellable, perror))
 		ms = MapiLogonEx (mapi_ctx, &session, profname, password);
 
 	if (ms != MAPI_E_SUCCESS) {
@@ -4516,7 +4458,7 @@ mapi_profile_load (const gchar *profname, const gchar *password, GCancellable *c
 	}
 
  cleanup:
-	g_static_rec_mutex_unlock (&profile_mutex);
+	e_mapi_utils_global_unlock ();
 	e_mapi_debug_print ("%s: Leaving %s ", G_STRLOC, G_STRFUNC);
 
 	return session;
@@ -4543,7 +4485,8 @@ create_profile_fallback_callback (struct SRowSet *rowset, gconstpointer data)
 }
 
 static gboolean
-mapi_profile_create (const EMapiProfileData *empd,
+mapi_profile_create (struct mapi_context *mapi_ctx,
+		     const EMapiProfileData *empd,
 		     mapi_profile_callback_t callback, gconstpointer data,
 		     GCancellable *cancellable,
 		     GError **perror,
@@ -4555,6 +4498,8 @@ mapi_profile_create (const EMapiProfileData *empd,
 	gchar *profname = NULL;
 	struct mapi_session *session = NULL;
 
+	e_return_val_mapi_error_if_fail (mapi_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
+
 	if (!callback) {
 		callback = create_profile_fallback_callback;
 		data = (gpointer) empd->username;
@@ -4565,18 +4510,12 @@ mapi_profile_create (const EMapiProfileData *empd,
 					 MAPI_E_INVALID_PARAMETER, FALSE);
 
 	if (use_locking)
-		g_static_rec_mutex_lock (&profile_mutex);
+		e_mapi_utils_global_lock ();
 
 	e_mapi_debug_print ("Create profile with %s %s %s\n", empd->username,
 		 empd->domain, empd->server);
 
-	if (!ensure_mapi_init_called (perror)) {
-		if (use_locking)
-			g_static_rec_mutex_unlock (&profile_mutex);
-		return FALSE;
-	}
-
-	profname = e_mapi_util_profile_name (empd, TRUE);
+	profname = e_mapi_util_profile_name (mapi_ctx, empd, TRUE);
 
 	/* Delete any existing profiles with the same profilename */
 	ms = DeleteProfile (mapi_ctx, profname);
@@ -4662,58 +4601,64 @@ mapi_profile_create (const EMapiProfileData *empd,
 	}*/
 
 	if (use_locking)
-		g_static_rec_mutex_unlock (&profile_mutex);
+		e_mapi_utils_global_unlock ();
 
 	return result;
 }
 
 gboolean
-e_mapi_create_profile (EMapiProfileData *empd,
+e_mapi_create_profile (struct mapi_context *mapi_ctx,
+		       EMapiProfileData *empd,
 		       mapi_profile_callback_t callback,
 		       gconstpointer data,
 		       GCancellable *cancellable,
 		       GError **perror)
 {
-	return mapi_profile_create (empd, callback, data, cancellable, perror, TRUE);
+	return mapi_profile_create (mapi_ctx, empd, callback, data, cancellable, perror, TRUE);
 }
 
 gboolean
-e_mapi_delete_profile (const gchar *profile, GError **perror)
+e_mapi_delete_profile (struct mapi_context *mapi_ctx,
+		       const gchar *profile,
+		       GError **perror)
 {
 	gboolean result = FALSE;
+	enum MAPISTATUS ms;
 
-	g_static_rec_mutex_lock (&profile_mutex);
+	e_return_val_mapi_error_if_fail (mapi_ctx != NULL, MAPI_E_INVALID_PARAMETER, FALSE);
 
-	if (ensure_mapi_init_called (perror)) {
-		enum MAPISTATUS ms;
+	e_mapi_utils_global_lock ();
 
-		e_mapi_debug_print ("Deleting profile %s ", profile);
+	e_mapi_debug_print ("Deleting profile %s ", profile);
 
-		ms = DeleteProfile (mapi_ctx, profile);
-		if (ms == MAPI_E_SUCCESS) {
-			result = TRUE;
-		} else {
-			make_mapi_error (perror, "DeleteProfile", ms);
-		}
+	ms = DeleteProfile (mapi_ctx, profile);
+	if (ms == MAPI_E_SUCCESS || ms == MAPI_E_NOT_FOUND) {
+		result = TRUE;
+	} else {
+		make_mapi_error (perror, "DeleteProfile", ms);
 	}
 
-	g_static_rec_mutex_unlock (&profile_mutex);
+	e_mapi_utils_global_unlock ();
 
 	return result;
 }
 
 void
-e_mapi_rename_profile (const gchar *old_name, const gchar *new_name)
+e_mapi_rename_profile (struct mapi_context *mapi_ctx,
+		       const gchar *old_name,
+		       const gchar *new_name,
+		       GError **perror)
 {
+	g_return_if_fail (mapi_ctx != NULL);
 	g_return_if_fail (old_name != NULL);
 	g_return_if_fail (new_name != NULL);
 
 	/* do not use locking here, it's called with a lock held already */
-	/* g_static_rec_mutex_lock (&profile_mutex); */
+	/* e_mapi_utils_global_lock (); */
 
 	RenameProfile (mapi_ctx, old_name, new_name);
 
-	/* g_static_rec_mutex_unlock (&profile_mutex); */
+	/* e_mapi_utils_global_unlock (); */
 }
 
 /* profile related functions - end */
diff --git a/src/libexchangemapi/e-mapi-connection.h b/src/libexchangemapi/e-mapi-connection.h
index 3097599..4eaa370 100644
--- a/src/libexchangemapi/e-mapi-connection.h
+++ b/src/libexchangemapi/e-mapi-connection.h
@@ -470,16 +470,20 @@ typedef struct {
 	 && (((x)->domain && *(x)->domain && (x)->password && *(x)->password) \
 	     || ((x)->krb_sso && (x)->krb_realm && *(x)->krb_realm)))
 
-gboolean		e_mapi_create_profile			(EMapiProfileData *profile,
+gboolean		e_mapi_create_profile			(struct mapi_context *mapi_ctx,
+								 EMapiProfileData *profile,
 								 mapi_profile_callback_t cb,
 								 gconstpointer data,
 								 GCancellable *cancellable,
 								 GError **perror);
 
-gboolean		e_mapi_delete_profile			(const gchar *profile,
+gboolean		e_mapi_delete_profile			(struct mapi_context *mapi_ctx,
+								 const gchar *profile,
+								 GError **perror);
+void			e_mapi_rename_profile			(struct mapi_context *mapi_ctx,
+								 const gchar *old_name,
+								 const gchar *new_name,
 								 GError **perror);
-void			e_mapi_rename_profile			(const gchar *old_name,
-								 const gchar *new_name);
 
 /* utility functions */
 
diff --git a/src/libexchangemapi/e-mapi-utils.c b/src/libexchangemapi/e-mapi-utils.c
index f974343..6f5b766 100644
--- a/src/libexchangemapi/e-mapi-utils.c
+++ b/src/libexchangemapi/e-mapi-utils.c
@@ -28,6 +28,8 @@
 #include <glib.h>
 #include <gio/gio.h>
 
+#include <libedataserver/e-data-server-util.h>
+
 #include "e-mapi-utils.h"
 #include "e-mapi-mail-utils.h"
 
@@ -41,6 +43,8 @@
 #define gmtime_r(tp,tmp) (gmtime(tp)?(*(tmp)=*gmtime(tp),(tmp)):0)
 #endif
 
+#define DEFAULT_PROF_NAME "mapi-profiles.ldb"
+
 /* Used for callout to krb5-auth-dialog */
 #define KRB_DBUS_PATH               "/org/gnome/KrbAuthDialog"
 #define KRB_DBUS_INTERFACE          "org.gnome.KrbAuthDialog"
@@ -915,6 +919,7 @@ e_mapi_util_trigger_krb_auth (const EMapiProfileData *empd, GError **error) {
 
 /**
  * e_mapi_util_profile_name:
+ * @mapi_ctx: a mapi context; can be NULL if @migrate is FALSE
  * @empd: profile information used to construct the name
  * @migrate: whether migrate old profile name to a new one
  *
@@ -923,23 +928,23 @@ e_mapi_util_trigger_krb_auth (const EMapiProfileData *empd, GError **error) {
  * rename old profile name string to a new name, if requested.
  **/
 gchar *
-e_mapi_util_profile_name (const EMapiProfileData *empd, gboolean migrate)
+e_mapi_util_profile_name (struct mapi_context *mapi_ctx, const EMapiProfileData *empd, gboolean migrate)
 {
 	gchar *res;
 
-	res = g_strdup_printf ("%s %s@%s", empd->username, empd->domain,
-			       empd->server);
+	res = g_strdup_printf ("%s %s@%s", empd->username, empd->domain, empd->server);
 	res = g_strcanon (res, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789  -", '_');
 
 	if (migrate) {
 		/* expects MAPIInitialize already called! */
 		gchar *old_name;
 
-		old_name = g_strdup_printf ("%s %s", empd->username,
-					    empd->domain);
+		g_return_val_if_fail (mapi_ctx != NULL, res);
+
+		old_name = g_strdup_printf ("%s %s", empd->username, empd->domain);
 		old_name = g_strcanon (old_name, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@", '_');
 
-		e_mapi_rename_profile (old_name, res);
+		e_mapi_rename_profile (mapi_ctx, old_name, res, NULL);
 
 		g_free (old_name);
 	}
@@ -1173,3 +1178,80 @@ e_mapi_util_time_t_to_filetime (const time_t tt, struct FILETIME *filetime)
 	nt = nt >> 32;
 	filetime->dwHighDateTime = nt & 0xFFFFFFFF;
 }
+
+static void
+manage_global_lock (gboolean lock)
+{
+	static GStaticRecMutex global_lock = G_STATIC_REC_MUTEX_INIT;
+
+	if (lock)
+		g_static_rec_mutex_lock (&global_lock);
+	else
+		g_static_rec_mutex_unlock (&global_lock);
+}
+
+void
+e_mapi_utils_global_lock (void)
+{
+	manage_global_lock (TRUE);
+}
+
+void
+e_mapi_utils_global_unlock (void)
+{
+	manage_global_lock (FALSE);
+}
+
+gboolean
+e_mapi_utils_create_mapi_context (struct mapi_context **mapi_ctx, GError **perror)
+{
+	const gchar *user_data_dir;
+	gchar *profpath;
+	enum MAPISTATUS ms;
+
+	g_return_val_if_fail (mapi_ctx != NULL, FALSE);
+
+	e_mapi_utils_global_lock ();
+
+	*mapi_ctx = NULL;
+	user_data_dir = e_get_user_data_dir ();
+	profpath = g_build_filename (user_data_dir, DEFAULT_PROF_NAME, NULL);
+
+	if (!g_file_test (profpath, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
+		/* Create a ProfileStore */
+		ms = CreateProfileStore (profpath, LIBMAPI_LDIF_DIR);
+		if (ms != MAPI_E_SUCCESS && (ms != MAPI_E_NO_ACCESS || !g_file_test (profpath, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))) {
+			make_mapi_error (perror, "CreateProfileStore", ms);
+			g_free (profpath);
+
+			e_mapi_utils_global_unlock ();
+			return FALSE;
+		}
+	}
+
+	ms = MAPIInitialize (mapi_ctx, profpath);
+	if (ms != MAPI_E_SUCCESS) {
+		make_mapi_error (perror, "MAPIInitialize", ms);
+		g_free (profpath);
+
+		e_mapi_utils_global_unlock ();
+		return FALSE;
+	}
+
+	g_free (profpath);
+
+	e_mapi_utils_global_unlock ();
+
+	return TRUE;
+}
+
+void
+e_mapi_utils_destroy_mapi_context (struct mapi_context *mapi_ctx)
+{
+	if (!mapi_ctx)
+		return;
+
+	e_mapi_utils_global_lock ();
+	MAPIUninitialize (mapi_ctx);
+	e_mapi_utils_global_unlock ();
+}
diff --git a/src/libexchangemapi/e-mapi-utils.h b/src/libexchangemapi/e-mapi-utils.h
index 01c39ef..0d47066 100644
--- a/src/libexchangemapi/e-mapi-utils.h
+++ b/src/libexchangemapi/e-mapi-utils.h
@@ -59,7 +59,9 @@ gchar *exchange_lf_to_crlf (const gchar *in);
 gchar *exchange_crlf_to_lf (const gchar *in);
 
 void e_mapi_util_profiledata_from_settings (EMapiProfileData *empd, CamelMapiSettings *settings);
-gchar *e_mapi_util_profile_name (const EMapiProfileData *empd, gboolean migrate);
+gchar *		e_mapi_util_profile_name			(struct mapi_context *mapi_ctx,
+								 const EMapiProfileData *empd,
+								 gboolean migrate);
 gboolean e_mapi_util_trigger_krb_auth (const EMapiProfileData *empd, GError **error);
 
 gboolean	e_mapi_utils_add_props_to_props_array		(TALLOC_CTX *mem_ctx,
@@ -98,4 +100,9 @@ void e_mapi_util_free_binary_r (struct Binary_r *bin);
 time_t e_mapi_util_filetime_to_time_t (const struct FILETIME *filetime);
 void e_mapi_util_time_t_to_filetime (const time_t tt, struct FILETIME *filetime);
 
+void		e_mapi_utils_global_lock			(void);
+void		e_mapi_utils_global_unlock			(void);
+gboolean	e_mapi_utils_create_mapi_context		(struct mapi_context **mapi_ctx, GError **perror);
+void		e_mapi_utils_destroy_mapi_context		(struct mapi_context *mapi_ctx);
+
 #endif



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]