diff --git a/contrib/password_tab/password_policy_password_tab.module b/contrib/password_tab/password_policy_password_tab.module
index 81dba6c..09765d2 100644
--- a/contrib/password_tab/password_policy_password_tab.module
+++ b/contrib/password_tab/password_policy_password_tab.module
@@ -12,36 +12,42 @@
  * Implementation of hook_menu().
  */
 function password_policy_password_tab_menu() {
-  return array(
-    'admin/settings/password_policy/password_tab' => array(
-      'title' => 'Password tab',
-      'page callback' => 'drupal_get_form',
-      'page arguments' => array('password_policy_password_tab_admin_settings'),
-      'access arguments' => array('administer site configuration'),
-      'file' => 'password_policy_password_tab.admin.inc',
-    ),
-    'user/%user/password' => array(
-      'title' => 'Password',
-      'page callback' => 'drupal_get_form',
-      'page arguments' => array('password_policy_password_tab', 1),
-      'access callback' => 'user_edit_access',
-      'access arguments' => array(1),
-      'type' => MENU_LOCAL_TASK,
-      'file' => 'password_policy_password_tab.pages.inc',
-    ),
+  $items = array();
+
+  $items['admin/config/people/password_policy/password_tab'] = array(
+    'title' => 'Password tab',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('password_policy_password_tab_admin_settings'),
+    'access arguments' => array('administer site configuration'),
+    'file' => 'password_policy_password_tab.admin.inc',
+    'type' => MENU_LOCAL_TASK,
+    'weight' => 10,
+  );
+  $items['user/%user/password'] = array(
+    'title' => 'Password',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('password_policy_password_tab', 1),
+    'access callback' => 'user_edit_access',
+    'access arguments' => array(1),
+    'type' => MENU_LOCAL_TASK,
+    'file' => 'password_policy_password_tab.pages.inc',
   );
+
+  return $items;
 }
 
 /**
- * Implementation of hook_form_alter().
+ * Implementation of hook_form_FORM_ID_alter().
+ *
+ * @see user_account_form()
  */
-function password_policy_password_tab_form_alter(&$form, $form_state, $form_id) {
-  switch ($form_id) {
-    case "user_profile_form":
-      // Hide core password field from user edit form.
-      unset($form['account']['pass']);
-      break;
+function password_policy_password_tab_form_user_profile_form_alter(&$form, &$form_state) {
+  if (isset($form['account']['current_pass_required_values']['#value']['pass'])) {
+    unset($form['account']['current_pass_required_values']['#value']['pass']);
   }
+
+  // Hide core password field from user edit form.
+  unset($form['account']['pass']);
 }
 
 /**
@@ -66,9 +72,15 @@ function password_policy_password_tab_exit($destination = NULL) {
         $processed = TRUE;
         // Change the drupal_goto to our change password tab.
         $path .= '/password';
-        $query = isset($url_parts['query']) ? $url_parts['query'] : NULL;
-        $fragment = isset($url_parts['fragment']) ? $url_parts['fragment'] : NULL;
-        drupal_goto($path, array('query' => $query, 'fragment' => $fragment));
+        $opts = array();
+        if (isset($url_parts['fragment'])) {
+          $opts['fragment'] = $url_parts['fragment'];
+        }
+        if (isset($url_parts['query'])) {
+          parse_str($url_parts['query'], $params);
+          $opts['query'] = $params;
+        }
+        drupal_goto($path, $opts);
       }
     }
   }
diff --git a/contrib/password_tab/password_policy_password_tab.pages.inc b/contrib/password_tab/password_policy_password_tab.pages.inc
index 66ac4ba..c09519a 100644
--- a/contrib/password_tab/password_policy_password_tab.pages.inc
+++ b/contrib/password_tab/password_policy_password_tab.pages.inc
@@ -9,17 +9,57 @@
  * Password change form.
  */
 function password_policy_password_tab($form, &$form_state, $account) {
-  $form['account']['pass'] = array(
+  global $user;
+
+  $form['#user'] = $account;
+  if ($user->uid == $account->uid) {
+    // To skip the current password field, the user must have logged in via a
+    // one-time link and have the token in the URL.
+    $pass_reset = isset($_SESSION['pass_reset_' . $account->uid]) && isset($_GET['pass-reset-token']) && ($_GET['pass-reset-token'] == $_SESSION['pass_reset_' . $account->uid]);
+    $protected_values = array();
+    $current_pass_description = '';
+    // The user may only change their own password without their current
+    // password if they logged in via a one-time login link.
+    if (!$pass_reset) {
+      $protected_values['mail'] = t('E-mail address');
+      $protected_values['pass'] = t('Password');
+      $request_new = l(t('Request new password'), 'user/password', array('attributes' => array('title' => t('Request new password via e-mail.'))));
+      $current_pass_description = t('Enter your current password to change the %mail or %pass. !request_new.', array('%mail' => $protected_values['mail'], '%pass' => $protected_values['pass'], '!request_new' => $request_new));
+    }
+    // The user must enter their current password to change to a new one.
+    $form['current_pass_required_values'] = array(
+      '#type' => 'value',
+      '#value' => array('pass' => $protected_values['pass']),
+    );
+    $form['account']['current_pass'] = array(
+      '#type' => 'password',
+      '#title' => t('Current password'),
+      '#size' => 25,
+      '#access' => !empty($protected_values),
+      '#description' => $current_pass_description,
+      '#weight' => -5,
+      '#attributes' => array('autocomplete' => 'off'),
+    );
+
+    $form['#validate'][] = 'user_validate_current_pass';
+  }
+
+  $form['pass'] = array(
     '#type' => 'password_confirm',
-    '#description' => t('To change the current user password, enter the new password in both fields.'),
     '#size' => 25,
+    '#required' => TRUE,
+    '#description' => t('To change the current user password, enter the new password in both fields.'),
   );
+
   $form['#uid'] = $account->uid;
   $form['_account'] = array('#type' => 'value', '#value' => $account);
-  $form['submit'] = array('#type' => 'submit', '#value' => t('Change'));
-  $form['#validate'] = array('password_policy_password_tab_validate');
-  $form['#submit'] = array('password_policy_password_tab_submit');
-  password_policy_form_alter($form, array(), 'user_profile_form');
+
+  $form['actions'] = array('#type' => 'actions');
+  $form['actions']['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Change'),
+  );
+
   return $form;
 }
 
@@ -39,14 +79,23 @@ function password_policy_password_tab_validate($form, &$form_state) {
  * Password change form submit.
  */
 function password_policy_password_tab_submit($form, &$form_state) {
-  $account = $form['_account']['#value'];
+  $account = $form_state['user'];
+
   user_module_invoke('submit', $form_state['values'], $account, 'account');
   user_save($account, array('pass' => $form_state['values']['pass']));
   drupal_set_message(t('Password has been changed.'));
+
   if (variable_get('password_policy_password_tab_redirect', '') && !preg_match('/[?&]destination=/', $form['#action'])) {
     global $user;
-    $redirect = parse_url(urldecode(strtr(variable_get('password_policy_password_tab_redirect', ''), array('%uid' => $user->uid))));
-    $form_state['redirect'] = array($redirect['path'], isset($redirect['query']) ? $redirect['query'] : NULL, isset($redirect['fragment']) ? $redirect['fragment'] : NULL);
+    $redirect = drupal_parse_url(urldecode(strtr(variable_get('password_policy_password_tab_redirect', ''), array('%uid' => $user->uid))));
+    $opts = array();
+    if (isset($redirect['fragment'])) {
+      $opts['fragment'] = $redirect['fragment'];
+    }
+    if (isset($redirect['query'])) {
+      parse_str($redirect['query'], $params);
+      $opts['query'] = $params;
+    }
   }
 }
 
diff --git a/password_policy.module b/password_policy.module
index d47adf9..6de256a 100644
--- a/password_policy.module
+++ b/password_policy.module
@@ -423,9 +423,10 @@ function password_policy_form_alter(&$form, $form_state, $form_id) {
   switch ($form_id) {
     case 'user_profile_form':
     case 'user_register_form':
+    case 'password_policy_password_tab':
       // Force password change on user account.
       if (user_access('force password change')) {
-        if ($form['#user_category'] == 'account') {
+        if (isset($form['#user_category']) && $form['#user_category'] == 'account') {
           $force_change = db_query_range('SELECT force_change FROM {password_policy_force_change} WHERE uid=:uid', 0, 1, array(':uid' => $form['#user']->uid))->fetchField();
         }
         else {
