diff --git a/main/pbx.c b/main/pbx.c
index 2c12f794cc363122139c88ee902904ba77d944ee..670195e4885560782c6370a5509bb7d805b9286b 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -194,6 +194,7 @@ struct scoreboard  /* make sure all fields are 0 before calling new_find_extensi
 	int total_length;
 	char last_char;   /* set to ! or . if they are the end of the pattern */
 	int canmatch;     /* if the string to match was just too short */
+	struct match_char *node;
 	struct ast_exten *canmatch_exten;
 	struct ast_exten *exten;
 };
@@ -319,7 +320,7 @@ static int pbx_builtin_importvar(struct ast_channel *, void *);
 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri);
 void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid);
 struct match_char *already_in_tree(struct match_char *current, char *pat);
-struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1);
+struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly);
 struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, char *pattern, int is_pattern, int already, int specificity);
 void create_match_char_tree(struct ast_context *con);
 struct ast_exten *get_canmatch_exten(struct match_char *node);
@@ -823,7 +824,7 @@ static void pbx_destroy(struct ast_pbx *p)
  */
 
 
-static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted)
+static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
 {
 	/* doing a matchcid() check here would be easy and cheap, but...
 	   unfortunately, it only works if an extension can have only one 
@@ -834,17 +835,18 @@ static void update_scoreboard(struct scoreboard *board, int length, int spec, st
 	   on the scoreboard, it will never be found */
 	if (deleted)
 		return;
-	
 	if (length > board->total_length) {
 		board->total_specificity = spec;
 		board->total_length = length;
 		board->exten = exten;
 		board->last_char = last;
+		board->node = node;
 	} else if (length == board->total_length && spec < board->total_specificity) {
 		board->total_specificity = spec;
 		board->total_length = length;
 		board->exten = exten;
 		board->last_char = last;
+		board->node = node;
 	}
 }
 
@@ -888,13 +890,38 @@ struct ast_exten *get_canmatch_exten(struct match_char *node)
 	return 0;
 }
 
+static struct ast_exten *trie_find_next_match(struct match_char *node)
+{
+	struct match_char *m3;
+	struct match_char *m4;
+	struct ast_exten *e3;
+	
+	if (!node || !node->next_char)
+		return NULL;
+	
+	m3 = node->next_char;
+
+	if (m3->exten)
+		return m3->exten;
+	for(m4=m3->alt_char; m4; m4 = m4->alt_char) {
+		if (m4->exten)
+			return m4->exten;
+	}
+	for(m4=m3; m4; m4 = m4->alt_char) {
+		e3 = trie_find_next_match(m3);
+		if (e3)
+			return e3;
+	}
+	return NULL;
+}
+
 void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid)
 {
 	struct match_char *p; /* note minimal stack storage requirements */
 	for (p=tree; p; p=p->alt_char) {
 		if (p->x[0] == 'N' && p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
 			if (p->exten) /* if a shorter pattern matches along the way, might as well report it */
-				update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted);
+				update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted, p);
 
 			if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0))) {
 				if (*(str+1))
@@ -909,7 +936,7 @@ void new_find_extension(const char *str, struct scoreboard *score, struct match_
 			}
 		} else if (p->x[0] == 'Z' && p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
 			if (p->exten) /* if a shorter pattern matches along the way, might as well report it */
-				update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted);
+				update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted,p);
 
 			if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0))) {
 				if (*(str+1))
@@ -924,7 +951,7 @@ void new_find_extension(const char *str, struct scoreboard *score, struct match_
 			}
 		} else if (p->x[0] == 'X' && p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
 			if (p->exten) /* if a shorter pattern matches along the way, might as well report it */
-				update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted);
+				update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted,p);
 
 			if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0))) {
 				if (*(str+1))
@@ -944,7 +971,7 @@ void new_find_extension(const char *str, struct scoreboard *score, struct match_
 				i++;
 			}
 			if (p->exten)
-				update_scoreboard(score, length+i, spec+(i*p->specificity), p->exten, '.', callerid, p->deleted);
+				update_scoreboard(score, length+i, spec+(i*p->specificity), p->exten, '.', callerid, p->deleted, p);
 			if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
 				new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid);
 			}
@@ -956,7 +983,7 @@ void new_find_extension(const char *str, struct scoreboard *score, struct match_
 				i++;
 			}
 			if (p->exten)
-				update_scoreboard(score, length+1, spec+(p->specificity*i), p->exten, '!', callerid, p->deleted);
+				update_scoreboard(score, length+1, spec+(p->specificity*i), p->exten, '!', callerid, p->deleted, p);
 			if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
 				new_find_extension("/", score, p->next_char, length+i, spec+(p->specificity*i), callerid);
 			}
@@ -968,7 +995,7 @@ void new_find_extension(const char *str, struct scoreboard *score, struct match_
 			}
 		} else if (index(p->x, *str)) {
 			if (p->exten) /* if a shorter pattern matches along the way, might as well report it */
-				update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted);
+				update_scoreboard(score, length+1, spec+p->specificity, p->exten,0,callerid, p->deleted, p);
 
 
 			if (p->next_char && ( *(str+1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0))) {
@@ -1050,7 +1077,7 @@ struct match_char *add_pattern_node(struct ast_context *con, struct match_char *
 	return m;
 }
 
-struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1)
+struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
 {
 	struct match_char *m1=0,*m2=0;
 	int specif;
@@ -1131,9 +1158,15 @@ struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast
 			m1 = m2->next_char; /* m1 points to the node to compare against */
 		} else {
 			if (m2) {
+				if (findonly)
+					return m2;
 				m1 = m2;
-			} else 
+			} else {
+				if (findonly)
+					return m1;
 				m1 = add_pattern_node(con, m1, buf, pattern, already,specif); /* m1 is the node just added */
+			}
+			
 			if (!(*(s1+1)))
 				m1->exten = e1;
 			already = 0;
@@ -1158,7 +1191,7 @@ void create_match_char_tree(struct ast_context *con)
 	t1 = ast_hashtab_start_traversal(con->root_tree);
 	while( (e1 = ast_hashtab_next(t1)) ) {
 		if (e1->exten)
-			add_exten_to_pattern_tree(con, e1);
+			add_exten_to_pattern_tree(con, e1, 0);
 		else
 			ast_log(LOG_ERROR,"Attempt to create extension with no extension name.\n");
 	}
@@ -1532,7 +1565,6 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
 	pattern.label = label;
 	pattern.priority = priority;
 
-
 	/* Initialize status if appropriate */
 	if (q->stacklen == 0) {
 		q->status = STATUS_NO_CONTEXT;
@@ -1565,12 +1597,14 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
 #endif
 		if (!tmp)
 			return NULL;
+		
 	}
 
 	if (q->status < STATUS_NO_EXTENSION)
 		q->status = STATUS_NO_EXTENSION;
 	
 	/* Do a search for matching extension */
+
 	eroot = NULL;
 	score.total_specificity = 0;
 	score.exten = 0;
@@ -1599,8 +1633,14 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
 		return score.canmatch_exten;
 	}
 
-	if (action == E_MATCHMORE && eroot)
+	if (action == E_MATCHMORE && eroot) {
+		if (score.node) {
+			struct ast_exten *z = trie_find_next_match(score.node);
+			return z;
+		}
 		return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
+	}
+	
 
 	if (eroot) {
 		/* found entry, now look for the right priority */
@@ -1703,8 +1743,11 @@ struct ast_exten *pbx_find_extension(struct ast_channel *chan,
 	/* Now try any includes we have in this context */
 	for (i = tmp->includes; i; i = i->next) {
 		if (include_valid(i)) {
-			if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action)))
+			if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
+				ast_log(LOG_NOTICE,"pbx_find_extension returns exten %s from recursive call\n", e->exten);
 				return e;
+			}
+			
 			if (q->swo)
 				return NULL;
 		}
@@ -3614,7 +3657,7 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
 			if (priority == 0)
 			{
 				/* success, this exten is in this pattern tree. */
-				struct match_char *x = add_exten_to_pattern_tree(con, exten);
+				struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
 				if (x->exten) { /* this test for safety purposes */
 					x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
 					x->exten = 0; /* get rid of what will become a bad pointer */
@@ -3636,7 +3679,7 @@ int ast_context_remove_extension2(struct ast_context *con, const char *extension
 					if (ast_hashtab_size(exten->peer_tree) == 0) {
 						/* well, if the last priority of an exten is to be removed,
 						   then, the extension is removed, too! */
-						struct match_char *x = add_exten_to_pattern_tree(con, exten);
+						struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
 						if (x->exten) { /* this test for safety purposes */
 							x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
 							x->exten = 0; /* get rid of what will become a bad pointer */
@@ -5796,7 +5839,7 @@ int ast_add_extension2(struct ast_context *con,
 		tmp2 = ast_hashtab_lookup(con->root_tree,&dummy_exten);
 		if (!tmp2) {
 			/* hmmm, not in the trie; */
-			add_exten_to_pattern_tree(con, tmp);
+			add_exten_to_pattern_tree(con, tmp, 0);
 			ast_hashtab_insert_safe(con->root_tree, tmp); /* for the sake of completeness */
 		}
 	}