Backport from Samba 3.0.25 SVN version:

https://bugzilla.samba.org/show_bug.cgi?id=3024
http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=22812

There is a bug in winbind/nss: When there are MANY (1000+ here) AD users and 
FEW (20 here) of them actually have a unix mapping (we use idmap_ad with 
uidNumber attributes), listing the users ("getent passwd") and groups fails. 

The reason is that winbindd_getpwent (nsswitch/winbindd_user.c) and 
winbindd_getgrent (nsswitch/winbindd_group.c) fetch users/groups in chunks of 
250 by default. If there is no unix-mapped user within a chunk, it will fail 
without further searching the user list. The attached patchs changes the 
behaviour to fetch users until there are 250 users who have actually a 
unix-mapping.

--- samba-3.0.24/source/nsswitch/winbindd_user.c	2007-02-05 03:59:14.000000000 +0900
+++ samba-3.0.24.osstech/source/nsswitch/winbindd_user.c	2007-05-14 10:31:22.178749442 +0900
@@ -635,7 +635,7 @@ void winbindd_getpwent(struct winbindd_c
 {
 	struct getent_state *ent;
 	struct winbindd_pw *user_list;
-	int num_users, user_list_ndx = 0, i;
+	int num_users, user_list_ndx;
 
 	DEBUG(3, ("[%5lu]: getpwent\n", (unsigned long)state->pid));
 
@@ -649,6 +649,11 @@ void winbindd_getpwent(struct winbindd_c
 	/* Allocate space for returning a chunk of users */
 
 	num_users = MIN(MAX_GETPWENT_USERS, state->request.data.num_entries);
+
+	if (num_users == 0) {
+		request_error(state);
+		return;
+	}
 	
 	if ((state->response.extra_data.data = SMB_MALLOC_ARRAY(struct winbindd_pw, num_users)) == NULL) {
 		request_error(state);
@@ -670,7 +675,7 @@ void winbindd_getpwent(struct winbindd_c
 
 	/* Start sending back users */
 
-	for (i = 0; i < num_users; i++) {
+	for (user_list_ndx = 0; user_list_ndx < num_users; ) {
 		struct getpwent_user *name_list = NULL;
 		uint32 result;
 
@@ -713,8 +718,6 @@ void winbindd_getpwent(struct winbindd_c
 			name_list[ent->sam_entry_index].shell,
 			&user_list[user_list_ndx]);
 		
-		ent->sam_entry_index++;
-		
 		/* Add user to return list */
 		
 		if (result) {
@@ -727,6 +730,9 @@ void winbindd_getpwent(struct winbindd_c
 		} else
 			DEBUG(1, ("could not lookup domain user %s\n",
 				  name_list[ent->sam_entry_index].name));
+
+		ent->sam_entry_index++;
+		
 	}
 
 	/* Out of domains */
