Index: wp-admin/menu-header.php
===================================================================
--- wp-admin/menu-header.php	(revision 3530)
+++ wp-admin/menu-header.php	(working copy)
@@ -11,7 +11,7 @@
 	// 0 = name, 1 = capability, 2 = file
 	if (( strcmp($self, $item[2]) == 0 && empty($parent_file)) || ($parent_file && ($item[2] == $parent_file))) $class = ' class="current"';
     
-	if ( current_user_can($item[1]) ) {
+	if ( !empty($submenu[$item[2]]) || current_user_can($item[1]) ) {
 		if ( file_exists(ABSPATH . "wp-content/plugins/{$item[2]}") )
 			echo "\n\t<li><a href='" . get_settings('siteurl') . "/wp-admin/admin.php?page={$item[2]}'$class>{$item[0]}</a></li>";
 		else
Index: wp-admin/menu.php
===================================================================
--- wp-admin/menu.php	(revision 3530)
+++ wp-admin/menu.php	(working copy)
@@ -49,6 +49,51 @@
 $submenu['themes.php'][5] = array(__('Themes'), 'switch_themes', 'themes.php');
 $submenu['themes.php'][10] = array(__('Theme Editor'), 'edit_themes', 'theme-editor.php');
 
+// Loop over submenus and remove pages for which the user does not have privs.
+foreach ($submenu as $parent => $sub) {
+	foreach ($sub as $index => $data) {
+		if ( ! current_user_can($data[1]) ) {
+			$menu_nopriv[$data[2]] = true;
+			unset($submenu[$parent][$index]);
+		}
+	}
+	
+	if ( empty($submenu[$parent]) )
+		unset($submenu[$parent]);
+}
+
+// Loop over the top-level menu.
+// Remove menus that have no accessible submenus and require privs that the user does not have.
+// Menus for which the original parent is not acessible due to lack of privs will have the next
+// submenu in line be assigned as the new menu parent. 
+foreach ( $menu as $id => $data ) {
+	// If submenu is empty...
+	if ( empty($submenu[$data[2]]) ) {
+		// And user doesn't have privs, remove menu.
+		if ( ! current_user_can($data[1]) ) {
+			$menu_nopriv[$data[2]] = true;
+			unset($menu[$id]);
+		}
+	} else {
+		$subs = $submenu[$data[2]];
+		$first_sub = array_shift($subs);
+		$old_parent = $data[2];
+		$new_parent = $first_sub[2];
+		// If the first submenu is not the same as the assigned parent,
+		// make the first submenu the new parent.
+		if ( $new_parent != $old_parent ) {
+			$real_parent_file[$old_parent] = $new_parent;
+			$menu[$id][2] = $new_parent;
+			
+			foreach ($submenu[$old_parent] as $index => $data) {
+				$submenu[$new_parent][$index] = $submenu[$old_parent][$index];
+				unset($submenu[$old_parent][$index]);
+			}
+			unset($submenu[$old_parent]);	
+		}
+	}
+}
+
 // Create list of page plugin hook names.
 foreach ($menu as $menu_page) {
 	$admin_page_hooks[$menu_page[2]] = sanitize_title($menu_page[0]);
Index: wp-admin/admin-functions.php
===================================================================
--- wp-admin/admin-functions.php	(revision 3530)
+++ wp-admin/admin-functions.php	(working copy)
@@ -1231,32 +1231,37 @@
 	global $pagenow;
 	global $menu;
 	global $submenu;
+	global $menu_nopriv;
 
 	$parent = get_admin_page_parent();
+	
+	if ( isset($menu_nopriv[$pagenow]) )
+		return false;
 
-	foreach ($menu as $menu_array) {
-		//echo "parent array: " . $menu_array[2];
-		if ($menu_array[2] == $parent) {
-			if (!current_user_can($menu_array[1])) {
-				return false;
-			} else {
-				break;
-			}
-		}
-	}
+	if ( empty($parent) )
+		return true;
 
 	if (isset ($submenu[$parent])) {
 		foreach ($submenu[$parent] as $submenu_array) {
 			if ($submenu_array[2] == $pagenow) {
-				if (!current_user_can($submenu_array[1])) {
+				if (current_user_can($submenu_array[1]))
+					return true;
+				else
 					return false;
-				} else {
-					return true;
-				}
 			}
 		}
 	}
 
+	foreach ($menu as $menu_array) {
+		//echo "parent array: " . $menu_array[2];
+		if ($menu_array[2] == $parent) {
+			if (current_user_can($menu_array[1]))
+				return true;
+			else
+				return false;
+		}
+	}
+	
 	return true;
 }
 
@@ -1313,8 +1318,12 @@
 	global $submenu;
 	global $pagenow;
 	global $plugin_page;
+	global $real_parent_file;
 
-	if (isset ($parent_file) && !empty ($parent_file)) {
+	if ( !empty ($parent_file) ) {
+		if ( isset($real_parent_file[$parent_file]) )
+			$parent_file = $real_parent_file[$parent_file];
+
 		return $parent_file;
 	}
 
@@ -1322,13 +1331,18 @@
 		foreach ($menu as $parent_menu) {
 			if ($parent_menu[2] == $plugin_page) {
 				$parent_file = $plugin_page;
-				return $plugin_page;
+				if ( isset($real_parent_file[$parent_file]) )
+					$parent_file = $real_parent_file[$parent_file];
+					
+				return $parent_file;
 			}
 		}
 	}
 
 	foreach (array_keys($submenu) as $parent) {
 		foreach ($submenu[$parent] as $submenu_array) {
+			if ( isset($real_parent_file[$parent]) )
+				$parent = $real_parent_file[$parent];
 			if ($submenu_array[2] == $pagenow) {
 				$parent_file = $parent;
 				return $parent;
@@ -1363,8 +1377,12 @@
 function add_submenu_page($parent, $page_title, $menu_title, $access_level, $file, $function = '') {
 	global $submenu;
 	global $menu;
+	global $real_parent_file;
 
 	$parent = plugin_basename($parent);
+	if ( isset($real_parent_file[$parent]) )
+		$parent = $real_parent_file[$parent];
+
 	$file = plugin_basename($file);
 
 	// If the parent doesn't already have a submenu, add a link to the parent

