diff --git a/apps/app_originate.c b/apps/app_originate.c
index b196194e44daefca3e8a692a90909aefc68f50d6..9fceb08498e9904f2e783fc9421f0ebf7ac63e70 100644
--- a/apps/app_originate.c
+++ b/apps/app_originate.c
@@ -177,14 +177,14 @@ static int originate_exec(struct ast_channel *chan, const char *data)
 				chantech, chandata, args.arg1, exten, priority);
 
 		ast_pbx_outgoing_exten(chantech, cap_slin, chandata,
-				timeout * 1000, args.arg1, exten, priority, &outgoing_status, 0, NULL,
+				timeout * 1000, args.arg1, exten, priority, &outgoing_status, 1, NULL,
 				NULL, NULL, NULL, NULL, 0, NULL);
 	} else if (!strcasecmp(args.type, "app")) {
 		ast_debug(1, "Originating call to '%s/%s' and connecting them to %s(%s)\n",
 				chantech, chandata, args.arg1, S_OR(args.arg2, ""));
 
 		ast_pbx_outgoing_app(chantech, cap_slin, chandata,
-				timeout * 1000, args.arg1, args.arg2, &outgoing_status, 0, NULL,
+				timeout * 1000, args.arg1, args.arg2, &outgoing_status, 1, NULL,
 				NULL, NULL, NULL, NULL, NULL);
 	} else {
 		ast_log(LOG_ERROR, "Incorrect type, it should be 'exten' or 'app': %s\n",
diff --git a/include/asterisk/pbx.h b/include/asterisk/pbx.h
index 784b976ccded3b0f3bdb69328786148b347d8c66..795af05842aa4e118994b8cee4ac43428254e68d 100644
--- a/include/asterisk/pbx.h
+++ b/include/asterisk/pbx.h
@@ -1102,7 +1102,8 @@ int ast_async_goto(struct ast_channel *chan, const char *context, const char *ex
  */
 int ast_async_goto_by_name(const char *chan, const char *context, const char *exten, int priority);
 
-/*! \brief Synchronously or asynchronously make an outbound call and send it to a
+/*!
+ * \brief Synchronously or asynchronously make an outbound call and send it to a
  * particular extension
  *
  * \param type The channel technology to create
@@ -1112,27 +1113,34 @@ int ast_async_goto_by_name(const char *chan, const char *context, const char *ex
  * \param context The destination context for the outbound channel
  * \param exten The destination extension for the outbound channel
  * \param priority The destination priority for the outbound channel
- * \param reason Optional. If provided, the hangup cause code of the outbound channel if
- *  it failed
- * \param sync If non-zero, block until the outbound channel answers
+ * \param reason Optional.  If provided, the dialed status of the outgoing channel.
+ *        Codes are AST_CONTROL_xxx values.  Valid only if synchronous is non-zero.
+ * \param synchronous If zero then don't wait for anything.
+ *        If one then block until the outbound channel answers or the call fails.
+ *        If greater than one then wait for the call to complete or if the call doesn't
+ *        answer and failed@context exists then run a channel named OutgoingSpoolFailed
+ *        at failed@context.
  * \param cid_num The caller ID number to set on the outbound channel
  * \param cid_name The caller ID name to set on the outbound channel
  * \param vars Variables to set on the outbound channel
  * \param account The accountcode for the outbound channel
- * \param locked_channel Optional. The outbound channel that was created. This is returned
- *  both locked and reference bumped. If a caller provides a channel parameter, it must
- *  unlock the channel and decrement the reference count.
- *  \param assignedid Optional. The uniqueid to assign the channel that was created.
- *  \param assignedid2 Optional. The uniqueid to assign the second local channel.
- * \param early_media If non-zero, allow early-media on the originated channel
+ * \param locked_channel Optional.  The outbound channel that was created if success
+ *        is returned.  Otherwise it is set to NULL.  This is returned both locked
+ *        and reference bumped.
+ * \param early_media If non-zero the channel "answers" when progress is indicated.
+ * \param assignedids Optional. The uniqueid(s) to assign the channel(s) that are created.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
  */
 int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr,
-    int timeout, const char *context, const char *exten, int priority, int *reason,
-    int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars,
-    const char *account, struct ast_channel **locked_channel, int early_media,
+	int timeout, const char *context, const char *exten, int priority, int *reason,
+	int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars,
+	const char *account, struct ast_channel **locked_channel, int early_media,
 	const struct ast_assigned_ids *assignedids);
 
-/*! \brief Synchronously or asynchronously make an outbound call and execute an
+/*!
+ * \brief Synchronously or asynchronously make an outbound call and execute an
  *  application on the channel.
  *
  * Note that when the application stops executing, the channel is hungup.
@@ -1143,23 +1151,27 @@ int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const c
  * \param timeout How long we should attempt to dial the outbound channel
  * \param app The name of the application to execute
  * \param appdata Data to pass to the application
- * \param reason Optional. If provided, the hangup cause code of the outbound channel if
- *  it failed
- * \param sync If non-zero, block until the outbound channel answers
+ * \param reason Optional.  If provided, the dialed status of the outgoing channel.
+ *        Codes are AST_CONTROL_xxx values.  Valid only if synchronous is non-zero.
+ * \param synchronous If zero then don't wait for anything.
+ *        If one then block until the outbound channel answers or the call fails.
+ *        If greater than one then wait for the call to complete.
  * \param cid_num The caller ID number to set on the outbound channel
  * \param cid_name The caller ID name to set on the outbound channel
  * \param vars Variables to set on the outbound channel
  * \param account The accountcode for the outbound channel
- * \param locked_channel Optional. The outbound channel that was created. This is returned
- *  \param assignedid Optional. The uniqueid to assign the channel that was created.
- *  \param assignedid2 Optional. The uniqueid to assign the second local channel.
- *  both locked and reference bumped. If a caller provides a channel parameter, it must
- *  unlock the channel and decrement the reference count.
+ * \param locked_channel Optional.  The outbound channel that was created if success
+ *        is returned.  Otherwise it is set to NULL.  This is returned both locked
+ *        and reference bumped.
+ * \param assignedids Optional. The uniqueid(s) to assign the channel(s) that are created.
+ *
+ * \retval 0 on success
+ * \retval -1 on failure
  */
 int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr,
-    int timeout, const char *app, const char *appdata, int *reason, int sync,
-    const char *cid_num, const char *cid_name, struct ast_variable *vars,
-    const char *account, struct ast_channel **locked_channel,
+	int timeout, const char *app, const char *appdata, int *reason, int synchronous,
+	const char *cid_num, const char *cid_name, struct ast_variable *vars,
+	const char *account, struct ast_channel **locked_channel,
 	const struct ast_assigned_ids *assignedids);
 
 /*!
diff --git a/main/dial.c b/main/dial.c
index bf0d51c5e21c0f2728628745bbc5430a0ff9d2d4..2563c707b5cc7445f5e7cedaec098c4cc66eb1c5 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -541,12 +541,14 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
 			ast_verb(3, "%s is busy\n", ast_channel_name(channel->owner));
 			ast_channel_publish_dial(chan, channel->owner, channel->device, "BUSY");
 			ast_hangup(channel->owner);
+			channel->cause = AST_CAUSE_USER_BUSY;
 			channel->owner = NULL;
 			break;
 		case AST_CONTROL_CONGESTION:
 			ast_verb(3, "%s is circuit-busy\n", ast_channel_name(channel->owner));
 			ast_channel_publish_dial(chan, channel->owner, channel->device, "CONGESTION");
 			ast_hangup(channel->owner);
+			channel->cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
 			channel->owner = NULL;
 			break;
 		case AST_CONTROL_INCOMPLETE:
@@ -593,7 +595,7 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
 			break;
 		case AST_CONTROL_HOLD:
 			ast_verb(3, "Call on %s placed on hold\n", ast_channel_name(chan));
-			ast_indicate(chan, AST_CONTROL_HOLD);
+			ast_indicate_data(chan, AST_CONTROL_HOLD, fr->data.ptr, fr->datalen);
 			break;
 		case AST_CONTROL_UNHOLD:
 			ast_verb(3, "Call on %s left from hold\n", ast_channel_name(chan));
@@ -613,8 +615,6 @@ static void handle_frame(struct ast_dial *dial, struct ast_dial_channel *channel
 			break;
 		}
 	}
-
-	return;
 }
 
 /*! \brief Helper function that handles control frames WITHOUT owner */
@@ -638,12 +638,25 @@ static void handle_frame_ownerless(struct ast_dial *dial, struct ast_dial_channe
 		ast_verb(3, "%s is busy\n", ast_channel_name(channel->owner));
 		ast_channel_publish_dial(NULL, channel->owner, channel->device, "BUSY");
 		ast_hangup(channel->owner);
+		channel->cause = AST_CAUSE_USER_BUSY;
 		channel->owner = NULL;
 		break;
 	case AST_CONTROL_CONGESTION:
 		ast_verb(3, "%s is circuit-busy\n", ast_channel_name(channel->owner));
 		ast_channel_publish_dial(NULL, channel->owner, channel->device, "CONGESTION");
 		ast_hangup(channel->owner);
+		channel->cause = AST_CAUSE_NORMAL_CIRCUIT_CONGESTION;
+		channel->owner = NULL;
+		break;
+	case AST_CONTROL_INCOMPLETE:
+		/*
+		 * Nothing to do but abort the call since we have no
+		 * controlling channel to ask for more digits.
+		 */
+		ast_verb(3, "%s dialed Incomplete extension %s\n",
+			ast_channel_name(channel->owner), ast_channel_exten(channel->owner));
+		ast_hangup(channel->owner);
+		channel->cause = AST_CAUSE_UNALLOCATED;
 		channel->owner = NULL;
 		break;
 	case AST_CONTROL_RINGING:
@@ -661,8 +674,6 @@ static void handle_frame_ownerless(struct ast_dial *dial, struct ast_dial_channe
 	default:
 		break;
 	}
-
-	return;
 }
 
 /*! \brief Helper function to handle when a timeout occurs on dialing attempt */
@@ -686,6 +697,7 @@ static int handle_timeout_trip(struct ast_dial *dial, struct timeval start)
 	AST_LIST_TRAVERSE(&dial->channels, channel, list) {
 		if (dial->state == AST_DIAL_RESULT_TIMEOUT || diff >= channel->timeout) {
 			ast_hangup(channel->owner);
+			channel->cause = AST_CAUSE_NO_ANSWER;
 			channel->owner = NULL;
 		} else if ((lowest_timeout == -1) || (lowest_timeout > channel->timeout)) {
 			lowest_timeout = channel->timeout;
@@ -835,6 +847,7 @@ static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_chann
 				ast_poll_channel_del(chan, channel->owner);
 			ast_channel_publish_dial(chan, channel->owner, channel->device, "CANCEL");
 			ast_hangup(channel->owner);
+			channel->cause = AST_CAUSE_ANSWERED_ELSEWHERE;
 			channel->owner = NULL;
 		}
 		AST_LIST_UNLOCK(&dial->channels);
@@ -859,6 +872,7 @@ static enum ast_dial_result monitor_dial(struct ast_dial *dial, struct ast_chann
 				ast_poll_channel_del(chan, channel->owner);
 			ast_channel_publish_dial(chan, channel->owner, channel->device, "CANCEL");
 			ast_hangup(channel->owner);
+			channel->cause = AST_CAUSE_NORMAL_CLEARING;
 			channel->owner = NULL;
 		}
 		AST_LIST_UNLOCK(&dial->channels);
diff --git a/main/pbx.c b/main/pbx.c
index d1611174618ba556ca2e30526c222f82880f07d2..c8421bd83e0e23062ffea05a37d5364da1cbd59b 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -10092,8 +10092,6 @@ static int ast_add_extension2_lockopt(struct ast_context *con,
 struct pbx_outgoing {
 	/*! \brief Dialing structure being used */
 	struct ast_dial *dial;
-	/*! \brief Mutex lock for synchronous dialing */
-	ast_mutex_t lock;
 	/*! \brief Condition for synchronous dialing */
 	ast_cond_t cond;
 	/*! \brief Application to execute */
@@ -10123,7 +10121,6 @@ static void pbx_outgoing_destroy(void *obj)
 		ast_dial_destroy(outgoing->dial);
 	}
 
-	ast_mutex_destroy(&outgoing->lock);
 	ast_cond_destroy(&outgoing->cond);
 
 	ast_free(outgoing->appdata);
@@ -10136,12 +10133,12 @@ static void *pbx_outgoing_exec(void *data)
 	enum ast_dial_result res;
 
 	/* Notify anyone interested that dialing is complete */
-	ast_mutex_lock(&outgoing->lock);
 	res = ast_dial_run(outgoing->dial, NULL, 0);
+	ao2_lock(outgoing);
 	outgoing->dial_res = res;
 	outgoing->dialed = 1;
 	ast_cond_signal(&outgoing->cond);
-	ast_mutex_unlock(&outgoing->lock);
+	ao2_unlock(outgoing);
 
 	/* If the outgoing leg was not answered we can immediately return and go no further */
 	if (res != AST_DIAL_RESULT_ANSWERED) {
@@ -10182,10 +10179,10 @@ static void *pbx_outgoing_exec(void *data)
 	}
 
 	/* Notify anyone else again that may be interested that execution is complete */
-	ast_mutex_lock(&outgoing->lock);
+	ao2_lock(outgoing);
 	outgoing->executed = 1;
 	ast_cond_signal(&outgoing->cond);
-	ast_mutex_unlock(&outgoing->lock);
+	ao2_unlock(outgoing);
 
 	return NULL;
 }
@@ -10209,21 +10206,69 @@ static void pbx_outgoing_state_callback(struct ast_dial *dial)
 	ast_queue_control(channel, AST_CONTROL_ANSWER);
 }
 
-static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context,
-	const char *exten, int priority, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num,
-	const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, int early_media, const struct ast_assigned_ids *assignedids)
+/*!
+ * \brief Attempt to convert disconnect cause to old originate reason.
+ *
+ * \todo XXX The old originate reasons need to be trashed and replaced
+ * with normal disconnect cause codes if the call was not answered.
+ * The internal consumers of the reason values would also need to be
+ * updated: app_originate, call files, and AMI OriginateResponse.
+ */
+static enum ast_control_frame_type pbx_dial_reason(enum ast_dial_result dial_result, int cause)
+{
+	enum ast_control_frame_type pbx_reason;
+
+	if (dial_result == AST_DIAL_RESULT_ANSWERED) {
+		/* Remote end answered. */
+		pbx_reason = AST_CONTROL_ANSWER;
+	} else if (dial_result == AST_DIAL_RESULT_HANGUP) {
+		/* Caller hungup */
+		pbx_reason = AST_CONTROL_HANGUP;
+	} else {
+		switch (cause) {
+		case AST_CAUSE_USER_BUSY:
+			pbx_reason = AST_CONTROL_BUSY;
+			break;
+		case AST_CAUSE_CALL_REJECTED:
+		case AST_CAUSE_NETWORK_OUT_OF_ORDER:
+		case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
+		case AST_CAUSE_NORMAL_TEMPORARY_FAILURE:
+		case AST_CAUSE_SWITCH_CONGESTION:
+		case AST_CAUSE_NORMAL_CIRCUIT_CONGESTION:
+			pbx_reason = AST_CONTROL_CONGESTION;
+			break;
+		case AST_CAUSE_ANSWERED_ELSEWHERE:
+		case AST_CAUSE_NO_ANSWER:
+			/* Remote end was ringing (but isn't anymore) */
+			pbx_reason = AST_CONTROL_RINGING;
+			break;
+		case AST_CAUSE_UNALLOCATED:
+		default:
+			/* Call Failure (not BUSY, and not NO_ANSWER, maybe Circuit busy or down?) */
+			pbx_reason = 0;
+			break;
+		}
+	}
+
+	return pbx_reason;
+}
+
+static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap,
+	const char *addr, int timeout, const char *context, const char *exten, int priority,
+	const char *app, const char *appdata, int *reason, int synchronous,
+	const char *cid_num, const char *cid_name, struct ast_variable *vars,
+	const char *account, struct ast_channel **locked_channel, int early_media,
+	const struct ast_assigned_ids *assignedids)
 {
-	RAII_VAR(struct pbx_outgoing *, outgoing, ao2_alloc(sizeof(*outgoing), pbx_outgoing_destroy), ao2_cleanup);
+	RAII_VAR(struct pbx_outgoing *, outgoing, NULL, ao2_cleanup);
 	struct ast_channel *dialed;
 	pthread_t thread;
 
+	outgoing = ao2_alloc(sizeof(*outgoing), pbx_outgoing_destroy);
 	if (!outgoing) {
 		return -1;
 	}
-
-	if (channel) {
-		*channel = NULL;
-	}
+	ast_cond_init(&outgoing->cond, NULL);
 
 	if (!ast_strlen_zero(app)) {
 		ast_copy_string(outgoing->app, app, sizeof(outgoing->app));
@@ -10245,6 +10290,10 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
 	ast_dial_set_global_timeout(outgoing->dial, timeout);
 
 	if (ast_dial_prerun(outgoing->dial, NULL, cap)) {
+		if (synchronous && reason) {
+			*reason = pbx_dial_reason(AST_DIAL_RESULT_FAILED,
+				ast_dial_reason(outgoing->dial, 0));
+		}
 		return -1;
 	}
 
@@ -10257,7 +10306,6 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
 	if (vars) {
 		ast_set_variables(dialed, vars);
 	}
-
 	if (account) {
 		ast_channel_accountcode_set(dialed, account);
 	}
@@ -10295,107 +10343,148 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
 		ast_dial_set_state_callback(outgoing->dial, pbx_outgoing_state_callback);
 	}
 
-	if (channel) {
-		*channel = dialed;
-		ast_channel_ref(*channel);
-		ast_channel_lock(*channel);
+	if (locked_channel) {
+		/*
+		 * Keep a dialed channel ref since the caller wants
+		 * the channel returned.  We must get the ref before
+		 * spawning off pbx_outgoing_exec().
+		 */
+		ast_channel_ref(dialed);
+		if (!synchronous) {
+			/*
+			 * Lock it now to hold off pbx_outgoing_exec() in case the
+			 * calling function needs the channel state/snapshot before
+			 * dialing actually happens.
+			 */
+			ast_channel_lock(dialed);
+		}
 	}
 
-	ast_mutex_init(&outgoing->lock);
-	ast_cond_init(&outgoing->cond, NULL);
-
 	ao2_ref(outgoing, +1);
-
-	ast_mutex_lock(&outgoing->lock);
-
 	if (ast_pthread_create_detached(&thread, NULL, pbx_outgoing_exec, outgoing)) {
 		ast_log(LOG_WARNING, "Unable to spawn dialing thread for '%s/%s'\n", type, addr);
-		if (channel) {
-			ast_channel_unlock(*channel);
-			ast_channel_unref(*channel);
-		}
-		ast_mutex_unlock(&outgoing->lock);
 		ao2_ref(outgoing, -1);
+		if (locked_channel) {
+			if (!synchronous) {
+				ast_channel_unlock(dialed);
+			}
+			ast_channel_unref(dialed);
+		}
 		return -1;
 	}
 
-	/* Wait for dialing to complete */
 	if (synchronous) {
-		if (channel && *channel) {
-			ast_channel_unlock(*channel);
-		}
+		ao2_lock(outgoing);
+		/* Wait for dialing to complete */
 		while (!outgoing->dialed) {
-			ast_cond_wait(&outgoing->cond, &outgoing->lock);
+			ast_cond_wait(&outgoing->cond, ao2_object_get_lockaddr(outgoing));
+		}
+		if (1 < synchronous
+			&& outgoing->dial_res == AST_DIAL_RESULT_ANSWERED) {
+			/* Wait for execution to complete */
+			while (!outgoing->executed) {
+				ast_cond_wait(&outgoing->cond, ao2_object_get_lockaddr(outgoing));
+			}
+		}
+		ao2_unlock(outgoing);
 
-			if (outgoing->dial_res != AST_DIAL_RESULT_ANSWERED) {
-				ast_mutex_unlock(&outgoing->lock);
-				/* The dial operation failed. */
-				return -1;
+		/* Determine the outcome of the dialing attempt up to it being answered. */
+		if (reason) {
+			*reason = pbx_dial_reason(outgoing->dial_res,
+				ast_dial_reason(outgoing->dial, 0));
+		}
+
+		if (outgoing->dial_res != AST_DIAL_RESULT_ANSWERED) {
+			/* The dial operation failed. */
+			if (locked_channel) {
+				ast_channel_unref(dialed);
 			}
+			return -1;
 		}
-		if (channel && *channel) {
-			ast_channel_lock(*channel);
+		if (locked_channel) {
+			ast_channel_lock(dialed);
 		}
 	}
 
-	/* Wait for execution to complete */
-	if (synchronous > 1) {
-		while (!outgoing->executed) {
-			ast_cond_wait(&outgoing->cond, &outgoing->lock);
-		}
+	if (locked_channel) {
+		*locked_channel = dialed;
 	}
+	return 0;
+}
 
-	ast_mutex_unlock(&outgoing->lock);
+int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr,
+	int timeout, const char *context, const char *exten, int priority, int *reason,
+	int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars,
+	const char *account, struct ast_channel **locked_channel, int early_media,
+	const struct ast_assigned_ids *assignedids)
+{
+	int res;
+	int my_reason;
 
-	if (reason) {
-		*reason = ast_dial_reason(outgoing->dial, 0);
+	if (!reason) {
+		reason = &my_reason;
+	}
+	*reason = 0;
+	if (locked_channel) {
+		*locked_channel = NULL;
 	}
 
-	if ((synchronous > 1) && ast_dial_state(outgoing->dial) != AST_DIAL_RESULT_ANSWERED &&
-		ast_strlen_zero(app) &&	ast_exists_extension(NULL, context, "failed", 1, NULL)) {
-		struct ast_channel *failed = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, NULL, 0, "OutgoingSpoolFailed");
+	res = pbx_outgoing_attempt(type, cap, addr, timeout, context, exten, priority,
+		NULL, NULL, reason, synchronous, cid_num, cid_name, vars, account, locked_channel,
+		early_media, assignedids);
 
-		if (failed) {
-			char failed_reason[4] = "";
+	if (res < 0 /* Call failed to get connected for some reason. */
+		&& 1 < synchronous
+		&& ast_exists_extension(NULL, context, "failed", 1, NULL)) {
+		struct ast_channel *failed;
 
-			if (!ast_strlen_zero(context)) {
-				ast_channel_context_set(failed, context);
-			}
+		/* We do not have to worry about a locked_channel if dialing failed. */
+		ast_assert(!locked_channel || !*locked_channel);
 
-			if (account) {
-				ast_channel_accountcode_set(failed, account);
-			}
+		/*!
+		 * \todo XXX Not good.  The channel name is not unique if more than
+		 * one originate fails at a time.
+		 */
+		failed = ast_channel_alloc(0, AST_STATE_DOWN, cid_num, cid_name, account,
+			"failed", context, NULL, NULL, 0, "OutgoingSpoolFailed");
+		if (failed) {
+			char failed_reason[12];
 
-			set_ext_pri(failed, "failed", 1);
 			ast_set_variables(failed, vars);
-			snprintf(failed_reason, sizeof(failed_reason), "%d", ast_dial_reason(outgoing->dial, 0));
+			snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
 			pbx_builtin_setvar_helper(failed, "REASON", failed_reason);
 			ast_channel_unlock(failed);
 
 			if (ast_pbx_run(failed)) {
-				ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n", ast_channel_name(failed));
+				ast_log(LOG_ERROR, "Unable to run PBX on '%s'\n",
+					ast_channel_name(failed));
 				ast_hangup(failed);
 			}
 		}
 	}
 
-	return 0;
-}
-
-int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, int early_media, const struct ast_assigned_ids *assignedids)
-{
-	return pbx_outgoing_attempt(type, cap, addr, timeout, context, exten, priority, NULL, NULL, reason, synchronous, cid_num,
-		cid_name, vars, account, channel, early_media, assignedids);
+	return res;
 }
 
-int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids)
+int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr,
+	int timeout, const char *app, const char *appdata, int *reason, int synchronous,
+	const char *cid_num, const char *cid_name, struct ast_variable *vars,
+	const char *account, struct ast_channel **locked_channel,
+	const struct ast_assigned_ids *assignedids)
 {
+	if (reason) {
+		*reason = 0;
+	}
+	if (locked_channel) {
+		*locked_channel = NULL;
+	}
 	if (ast_strlen_zero(app)) {
 		return -1;
 	}
 
-	return pbx_outgoing_attempt(type, cap, addr, timeout, NULL, NULL, 0, app, appdata, reason, synchronous, cid_num,
-		cid_name, vars, account, locked_channel, 0, assignedids);
+	return pbx_outgoing_attempt(type, cap, addr, timeout, NULL, NULL, 0, app, appdata,
+		reason, synchronous, cid_num, cid_name, vars, account, locked_channel, 0,
+		assignedids);
 }
 
 /* this is the guts of destroying a context --