Password input, replacing characters with asterisks

William Hemsworth 0 Tallied Votes 506 Views Share

This snippet basically shows you how to input a password from the user without actually displaying the characters, instead they are replaced with the ' * ' character as you type.

The code is uncommented, so I will briefly explain it.

This function: void PasswordInput(char *password, size_t maxLength) has two parameters, the first one is a pointer to a buffer containing enough free space to input up to maxLength number of characters.

#include <windows.h>
#include <iostream>

void PasswordInput(char *password, size_t maxLength) {
  static HANDLE hOut = GetStdHandle( STD_OUTPUT_HANDLE );
  static CONSOLE_SCREEN_BUFFER_INFO csbi;
  static COORD c;

  ZeroMemory( password, maxLength );
  --maxLength;

  HANDLE hStdin; 
  DWORD cNumRead; 
  INPUT_RECORD irInBuf[1];
  GetConsoleScreenBufferInfo ( hOut, &csbi );

  int startX = csbi.dwCursorPosition.X;
  int startY = csbi.dwCursorPosition.Y;

  size_t curLength = 0;

  if ( HANDLE(hStdin = GetStdHandle( STD_INPUT_HANDLE )) == INVALID_HANDLE_VALUE )
    return;

  while ( true )  { 
    if (! ReadConsoleInput( hStdin, irInBuf, 1, &cNumRead) )
      return;

    for (DWORD i = 0; i < cNumRead; ++i)
      if ( irInBuf[i].EventType == KEY_EVENT && irInBuf[i].Event.KeyEvent.bKeyDown ) {
        if ( irInBuf[i].Event.KeyEvent.uChar.AsciiChar >= 33  && 
             irInBuf[i].Event.KeyEvent.uChar.AsciiChar <= 126 ||
             irInBuf[i].Event.KeyEvent.uChar.AsciiChar == ' ') {
          if ( curLength < maxLength ) {
            std::cout << '*';
            password[ curLength++ ] = irInBuf[i].Event.KeyEvent.uChar.AsciiChar;
          }
        } else if ( irInBuf[i].Event.KeyEvent.uChar.AsciiChar == '\b' ) {
          GetConsoleScreenBufferInfo ( hOut, &csbi );
          if ( csbi.dwCursorPosition.X > startX || csbi.dwCursorPosition.Y > startY ) {
            c.X = csbi.dwCursorPosition.X-1;
            c.Y = csbi.dwCursorPosition.Y;
            SetConsoleCursorPosition( hOut, c );
            std::cout << ' ';
            if ( csbi.dwCursorPosition.X == 0 ) {
              c.X = csbi.dwSize.X-1;
              c.Y = csbi.dwCursorPosition.Y-1;
              SetConsoleCursorPosition( hOut, c );
              std::cout << ' ';
              SetConsoleCursorPosition( hOut, c );
            } else {
              csbi.dwCursorPosition.X--;
              SetConsoleCursorPosition( hOut, csbi.dwCursorPosition );
            }
            password[ --curLength ] = 0;
          }
        } else if ( irInBuf[i].Event.KeyEvent.wVirtualKeyCode == VK_RETURN ) {
          std::cout << '\n';
          return;
        }
      }
  }
}

int main() {
  const int maxPasswordLength = 500;
  char password[maxPasswordLength];

  std::cout << "Enter password: ";
  PasswordInput( password, maxPasswordLength );

  std::cout << "\nPassword entered: ";
  std::cout << password;

  std::cin.ignore();
}