WindowsXP-SP1/admin/cmdline/lib/cmdline.c
2020-09-30 16:53:49 +02:00

1866 lines
50 KiB
C

// *********************************************************************************
//
// Copyright (c) Microsoft Corporation
//
// Module Name:
//
// Common.c
//
// Abstract:
//
// This modules implements common functionality for all the command line tools.
//
//
// Author:
//
// Sunil G.V.N. Murali (murali.sunil@wipro.com) 01-Sep-2000
//
// Revision History:
//
// Sunil G.V.N. Murali (murali.sunil@wipro.com) 01-Sep-2000 : Created It.
//
// *********************************************************************************
#include "pch.h"
#include "cmdlineres.h"
#include "cmdline.h"
#include <limits.h>
//
// global variable(s) that are exposed to the external world
//
#ifdef _MT
// multi-threaded variable ( thread local storage )
_declspec( thread ) static LPTSTR g_pszInfo = NULL;
_declspec( thread ) static LPTSTR g_pszString = NULL;
_declspec( thread ) static LPWSTR g_pwszResourceString = NULL;
_declspec( thread ) static TARRAY g_arrQuotes = NULL;
#else
static LPTSTR g_pszInfo = NULL; // holds the reason for the last failure
static LPTSTR g_pszString = NULL; // used to get the resource table's string
static LPWSTR g_pwszResourceString = NULL; // temporary unicode buffer
static TARRAY g_arrQuotes = NULL;
#endif
// SPECIAL: process level globals
BOOL g_bWinsockLoaded = FALSE;
DWORD g_dwMajorVersion = 5;
DWORD g_dwMinorVersion = 1;
WORD g_wServicePackMajor = 0;
//
// private functions
//
BOOL SetThreadUILanguage0( DWORD dwReserved );
//
// public functions
//
// ***************************************************************************
// Routine Description:
//
// Arguments:
//
// Return Value:
//
// ***************************************************************************
BOOL SetOsVersion( DWORD dwMajor, DWORD dwMinor, WORD wServicePackMajor )
{
// local variables
static BOOL bSet = FALSE;
// we won't support below Windows 2000
if ( dwMajor < 5 )
{
return FALSE;
}
else if ( bSet == TRUE )
{
// version is already set -- version cannot be changed frequently
return FALSE;
}
// rest of information we need not bother
bSet = TRUE;
g_dwMajorVersion = dwMajor;
g_dwMinorVersion = dwMinor;
g_wServicePackMajor = wServicePackMajor;
// return
return TRUE;
}
// ***************************************************************************
// Routine Description:
//
// Arguments:
//
// Return Value:
//
// ***************************************************************************
BOOL IsWin2KOrLater()
{
// local variables
OSVERSIONINFOEX osvi;
DWORDLONG dwlConditionMask = 0;
// Initialize the OSVERSIONINFOEX structure.
ZeroMemory( &osvi, sizeof( OSVERSIONINFOEX ) );
osvi.dwOSVersionInfoSize = sizeof( OSVERSIONINFOEX );
osvi.dwMajorVersion = g_dwMajorVersion;
osvi.dwMinorVersion = g_dwMinorVersion;
osvi.wServicePackMajor = g_wServicePackMajor;
// Initialize the condition mask.
VER_SET_CONDITION( dwlConditionMask, VER_MAJORVERSION, VER_GREATER_EQUAL );
VER_SET_CONDITION( dwlConditionMask, VER_MINORVERSION, VER_GREATER_EQUAL );
VER_SET_CONDITION( dwlConditionMask, VER_SERVICEPACKMAJOR, VER_GREATER_EQUAL );
// Perform the test.
return VerifyVersionInfo( &osvi, VER_MAJORVERSION | VER_MINORVERSION, dwlConditionMask );
}
// ***************************************************************************
// Routine Description:
//
// Saves the last occured windows error.
//
// Arguments:
//
// None.
//
// Return Value:
//
// VOID
//
// ***************************************************************************
VOID SaveLastError()
{
// local variables
DWORD dwErrorCode = 0;
LPVOID lpMsgBuf = NULL; // pointer to handle error message
// get the last error
dwErrorCode = GetLastError();
// Complex scripts cannot be rendered in the console, so we
// force the English (US) resource.
SetThreadUILanguage0( 0 );
// load the system error message from the windows itself
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dwErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf, 0, NULL );
// display error message on console screen ... ERROR place
if ( lpMsgBuf != NULL )
SetReason( ( LPCTSTR ) lpMsgBuf );
// Free the buffer ... using LocalFree is slow, but still, we are using ...
// later on need to replaced with HeapXXX functions
if ( lpMsgBuf != NULL )
LocalFree( lpMsgBuf );
}
// ***************************************************************************
// Routine Description:
//
// Saves the last occured windows network error and returns the error code obtained.
//
// Arguments:
//
// None
//
// Return Value:
//
// DWORD -- error code
//
// ***************************************************************************
DWORD WNetSaveLastError()
{
// local variables
DWORD dwErrorCode = 0;
__MAX_SIZE_STRING szMessage = NULL_STRING; // handle error message
__MAX_SIZE_STRING szProvider = NULL_STRING; // store the provider for error
// load the system error message from the windows itself
WNetGetLastError( &dwErrorCode, szMessage, SIZE_OF_ARRAY( szMessage ),
szProvider, SIZE_OF_ARRAY( szProvider ) );
// save the error
SetReason( szMessage );
// return the error code obtained
return dwErrorCode;
}
// ***************************************************************************
// Routine Description:
//
// writes the last saved error description in the given file.
//
// Arguments:
//
// [in] fp -- file to write the error description.
//
// Return Value:
//
// VOID
//
// ***************************************************************************
VOID ShowLastError( FILE* fp )
{
// local variables
DWORD dwErrorCode = 0;
LPVOID lpMsgBuf = NULL; // pointer to handle error message
// get the last error
dwErrorCode = GetLastError();
// Complex scripts cannot be rendered in the console, so we
// force the English (US) resource.
SetThreadUILanguage0( 0 );
// load the system error message from the windows itself
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, dwErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf, 0, NULL );
// buffer might not have allocated
if ( lpMsgBuf == NULL )
return;
// display error message on console screen ... ERROR place
DISPLAY_MESSAGE( fp, ( LPCTSTR ) lpMsgBuf );
// Free the buffer ... using LocalFree is slow, but still, we are using ...
// later on need to replaced with HeapXXX functions
LocalFree( lpMsgBuf );
}
// ***************************************************************************
// Routine Description:
//
// writes the last saved nerwork error description in the given file.
//
// Arguments:
//
// [in] fp --fle to write the error description.
//
// Return Value:
//
// DWORD --error code
//
// ***************************************************************************
DWORD WNetShowLastError( FILE* fp )
{
// local variables
DWORD dwErrorCode = 0;
__MAX_SIZE_STRING szMessage = NULL_STRING; // handle error message
__MAX_SIZE_STRING szProvider = NULL_STRING; // store the provider for error
// load the system error message from the windows itself
WNetGetLastError( &dwErrorCode, szMessage, SIZE_OF_ARRAY( szMessage ),
szProvider, SIZE_OF_ARRAY( szProvider ) );
// display error message on console screen ... ERROR place
DISPLAY_MESSAGE( fp, szMessage );
// return the error code obtained
return dwErrorCode;
}
// ***************************************************************************
// Routine Description:
//
// Releases all the global values that are used.
//
// Arguments:
//
// None.
//
// Return Value:
//
// VOID
//
// ***************************************************************************
LONG StringLengthInBytes( LPCTSTR pszText )
{
// local variables
LONG lLength = 0;
#ifdef UNICODE
// get the length of the string in bytes
// since this function includes the count for null character also, ignore that information
lLength = WideCharToMultiByte( _DEFAULT_CODEPAGE, 0, pszText, -1, NULL, 0, NULL, NULL ) - 1;
#else
lLength = lstrlen( pszText );
#endif
// return the length information
return lLength;
}
// ***************************************************************************
// Routine Description:
//
// Converts the Unicode string to ansi string.
//
// Arguments:
//
// [in] pszSource --Unicode string to be converted,
// [out] pszDestination --Converted String
// [in] dwLength --Length of the string
//
// Return Value:
//
// LPSTR --Converted string
//
// ***************************************************************************
LPSTR GetAsMultiByteString( LPCTSTR pszSource, LPSTR pszDestination, DWORD dwLength )
{
// check the input values
if ( pszSource == NULL || pszDestination == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return "";
}
// initialize the values with zeros
// NOTE:- WideCharToMultiByte wont null terminate its result so
// if its not initialized to nulls, you'll get junk after
// the converted string and will result in crashes
ZeroMemory( pszDestination, dwLength * sizeof( char ) );
#ifdef UNICODE
// convert string from UNICODE version to ANSI version
WideCharToMultiByte( _DEFAULT_CODEPAGE, 0, pszSource, -1,
pszDestination, dwLength, NULL, NULL );
#else
// just do the copy
lstrcpyn( pszDestination, pszSource, dwLength );
#endif
// return the destination as return value
return pszDestination;
}
// ***************************************************************************
// Routine Description:
//
// Convertes a wide charecter string to Ansi string.
//
// Arguments:
//
// [in] pwszSource --Wide charecter string to convert.
// [out] pszDestination, --Translated String
// [in] dwLength --Size of the String
//
// Return Value:
//
// LPSTR --Translated String.
//
// ***************************************************************************
LPSTR GetAsMultiByteStringEx( LPCWSTR pwszSource, LPSTR pszDestination, DWORD dwLength )
{
// check the input values
if ( pwszSource == NULL || pszDestination == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return "";
}
// initialize the values with zeros
// NOTE:- WideCharToMultiByte wont null terminate its result so
// if its not initialized to nulls, you'll get junk after
// the converted string and will result in crashes
ZeroMemory( pszDestination, dwLength * sizeof( char ) );
// convert string from UNICODE version to ANSI version
WideCharToMultiByte( _DEFAULT_CODEPAGE, 0, pwszSource, -1,
pszDestination, dwLength, NULL, NULL );
// return the destination as return value
return pszDestination;
}
// ***************************************************************************
// Routine Description:
//
// Translates the Ansi string in to the Unicode string.
//
// Arguments:
//
// [in] pszSource -- Ansi string to be translated,
// [out] pwszDestination -- Translated string.
// [in] dwLength -- Size of the string
//
// Return Value:
//
// LPWSTR --Translated string.
//
// ***************************************************************************
LPWSTR GetAsUnicodeString( LPCTSTR pszSource, LPWSTR pwszDestination, DWORD dwLength )
{
// check the input values
if ( pszSource == NULL || pwszDestination == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return L"";
}
// initialize the values with zeros
// NOTE:- MultiByteToWideChar wont null terminate its result so
// if its not initialized to nulls, you'll get junk after
// the converted string and will result in crashes
ZeroMemory( pwszDestination, dwLength * sizeof( wchar_t ) );
#ifdef UNICODE
// just do the copy
lstrcpyn( pwszDestination, pszSource, dwLength );
#else
// convert string from ANSI version to UNICODE version
MultiByteToWideChar( _DEFAULT_CODEPAGE, 0, pszSource, -1, pwszDestination, dwLength );
#endif
// return the destination as return value
return pwszDestination;
}
// ***************************************************************************
// Routine Description:
//
// Convertes ansi string to wide charecter string.
//
// Arguments:
//
// [in] pszSource -- String to be converted.
// [out] pwszDestination -- Converted string
// [in] dwLength -- length of the string
//
// Return Value:
//
// LPWSTR --Converted String
//
// ***************************************************************************
LPWSTR GetAsUnicodeStringEx( LPCSTR pszSource, LPWSTR pwszDestination, DWORD dwLength )
{
// check the input values
if ( pszSource == NULL || pwszDestination == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return L"";
}
// initialize the values with zeros
// NOTE:- MultiByteToWideChar wont null terminate its result so
// if its not initialized to nulls, you'll get junk after
// the converted string and will result in crashes
ZeroMemory( pwszDestination, dwLength * sizeof( wchar_t ) );
// convert string from ANSI version to UNICODE version
MultiByteToWideChar( _DEFAULT_CODEPAGE, 0, pszSource, -1, pwszDestination, dwLength );
// return the destination as return value
return pwszDestination;
}
// ***************************************************************************
// Routine Description:
//
// Convertes the given string as a float value.
//
// Arguments:
//
// [in] szValue -- String to convert
//
// Return Value:
//
// double -- converted double
//
// ***************************************************************************
double AsFloat( LPCTSTR szValue )
{
// local variables
double dblValue = 0;
LPTSTR pszStopString = NULL;
__MAX_SIZE_STRING szValueString = NULL_STRING;
// check the input value
if ( szValue == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return 0.0f;
}
// convert the string value into double value
lstrcpy( szValueString, szValue ); // copy org value into local buffer
dblValue = _tcstod( szValueString, &pszStopString );
// return converted value
return dblValue;
}
// ***************************************************************************
// Routine Description:
//
// Convertes the string in to the long value based on the given base.
//
// Arguments:
//
// [in] szValue --Srtring to convert
// [in] dwBase --Base value
//
// Return Value:
//
// LONG --converted long value
//
// ***************************************************************************
LONG AsLong( LPCTSTR szValue, DWORD dwBase )
{
// local variables
LONG lValue = 0;
LPTSTR pszStopString = NULL;
__MAX_SIZE_STRING szValueString = NULL_STRING;
// validate the base
// value should be in the range of 2 - 36 only
if ( dwBase < 2 || dwBase > 36 )
return -1;
// check the input value
if ( szValue == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return 0L;
}
// convert the string value into long value
lstrcpy( szValueString, szValue ); // copy org value into local buffer
lValue = _tcstol( szValueString, &pszStopString, dwBase );
// return converted value
return lValue;
}
// ***************************************************************************
// Routine Description:
//
// Checks whether the given string is a float string
//
// Arguments:
//
// [in] szValue --String to check
//
// Return Value:
//
// BOOL --True if the given string is a floating point string
// --False Otherwise
//
// ***************************************************************************
BOOL IsFloatingPoint( LPCTSTR szValue )
{
// local variables
double dblValue = 0;
LPTSTR pszStopString = NULL;
__MAX_SIZE_STRING szValueString = NULL_STRING;
// check the input value
if ( szValue == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return FALSE;
}
// convert the string value into double value
lstrcpy( szValueString, szValue ); // copy org value into local buffer
dblValue = _tcstod( szValueString, &pszStopString );
// now check whether the value is completely converted to floating point or not
// if not converted completely, then value is not correct
// if completely converted, the value is pure floating point
if ( lstrlen( pszStopString ) != 0 )
return FALSE;
// value is valid floating point
return TRUE;
}
// ***************************************************************************
// Routine Description:
//
// Checks whether the given string is Numeric or not.
//
// Arguments:
//
// [in] szValue --String to check
// [in] dwBase -- The base value
// [in] bSigned -- signed information
// -- true if signed, otherwise false
//
// Return Value:
//
// BOOL --true if it is a numeric with that base
// --false otherwise.
//
// ***************************************************************************
BOOL IsNumeric( LPCTSTR szValue, DWORD dwBase, BOOL bSigned )
{
// local variables
long lValue = 0;
double dblValue = 0;
LPTSTR pszStopString = NULL;
__MAX_SIZE_STRING szValueString = NULL_STRING;
// validate the base
// value should be in the range of 2 - 36 only
if ( dwBase < 2 || dwBase > 36 )
return FALSE;
// check the input value
if ( szValue == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return FALSE;
}
// convert the string value into numeric value
lstrcpy( szValueString, szValue ); // copy org value into local buffer
lValue = _tcstol( szValueString, &pszStopString, dwBase );
// now check whether the value is completely converted to numeric value or not
// if not converted completely, then value is not correct
// if completely converted, the value is pure numeric value
if ( lstrlen( pszStopString ) != 0 )
return FALSE;
// check whether the numeric value can be signed or not
if ( bSigned == FALSE && lValue < 0 )
return FALSE; // value cannot be -ve
// furthur check whether converted value is valid or not - overflow might have occurred
// NOTE: because of the limitations of libraries which we have in 'C' we cannot
// check for the overflow exactly using the LONG datatype.
// for that reason we are using 'double' data type to check for overflow
lstrcpy( szValueString, szValue ); // copy org value into local buffer
dblValue = _tcstod( szValueString, &pszStopString );
// validate the number
if ( bSigned == FALSE && dblValue > ((double) ULONG_MAX) )
return FALSE;
else if (bSigned && ( dblValue > ((double) LONG_MAX) || dblValue < ((double) LONG_MIN) ))
return FALSE;
// value is valid numeric
return TRUE;
}
// ***************************************************************************
// Routine Description:
//
// Replicates the szChar string dwCount times and saves the result in pszBuffer.
//
// Arguments:
//
// [in] pszBuffer --String to copy the replicate string
// [in] szChar --String to replicate
// [in] dwCount -- Number of times
//
// Return Value:
//
// LPTSTR --Replicated string
//
// ***************************************************************************
LPTSTR Replicate( LPTSTR pszBuffer, LPCTSTR szChar, DWORD dwCount )
{
// local variables
DWORD dw = 0;
// validate the input buffers
if ( pszBuffer == NULL || szChar == NULL )
return NULL_STRING;
// form the string of required length
lstrcpy( pszBuffer, NULL_STRING );
for( dw = 0; dw < dwCount; dw++ )
{
// append the replication character
lstrcat( pszBuffer, szChar );
}
// return the replicated buffer
return pszBuffer;
}
// ***************************************************************************
// Routine Description:
//
// Adjust the length of a string with spaces depending on the given pad.
//
// Arguments:
//
// [in] szValue -- Given string
// [in] dwLength -- Actual length of the string
// [in] bPadLeft -- Padding property
// -- true if left padding is required
// -- false otherwise
// Return Value:
//
// LPTSTR -- String with actual length.
//
// ***************************************************************************
LPTSTR AdjustStringLength( LPTSTR szValue, DWORD dwLength, BOOL bPadLeft )
{
// local variables
DWORD dw = 0;
DWORD dwTemp = 0;
DWORD dwCurrLength = 0;
LPTSTR pszBuffer = NULL;
LPTSTR pszSpaces = NULL;
// check the input value
if ( szValue == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return NULL_STRING;
}
// allocate the buffers
// ( accomadate space double the original buffer/required length - this will save us from crashes )
dwTemp = (( StringLengthInBytes( szValue ) > (LONG) dwLength ) ? StringLengthInBytes( szValue ) : dwLength );
pszSpaces = __calloc( dwTemp * 2, sizeof( TCHAR ) );
pszBuffer = __calloc( dwTemp * 2, sizeof( TCHAR ) );
if ( pszBuffer == NULL || pszSpaces == NULL )
{
__free( pszBuffer );
__free( pszSpaces );
return szValue;
}
// get the current length of the string
// NOTE: the string might contain the meta characters which will count in length
// so get the actual string contents which whill be displayed
lstrcpy( pszBuffer, szValue );
wsprintf( pszSpaces, pszBuffer );
dwCurrLength = StringLengthInBytes( pszSpaces );
// reset the data
lstrcpy( pszBuffer, NULL_STRING );
lstrcpy( pszSpaces, NULL_STRING );
// adjust the string value
if ( dwCurrLength < dwLength )
{
//
// length of the current value is less than the needed
// get the spaces for the rest of the length
Replicate( pszSpaces, _T( " " ), dwLength - dwCurrLength );
// append the spaces either to the end of the value or begining of the value
// based on the padding property
if ( bPadLeft )
{
// spaces first and then value
lstrcpy( pszBuffer, pszSpaces );
lstrcat( pszBuffer, szValue );
}
else
{
// value first and then spaces
lstrcpy( pszBuffer, szValue );
lstrcat( pszBuffer, pszSpaces );
}
}
else
{
// prepare the buffer ... we will avoid '%' characters here
lstrcpy( pszSpaces, szValue );
wsprintf( pszBuffer, pszSpaces );
// copy only the characters of required length
lstrcpyn( pszSpaces, pszBuffer, dwLength + 1 );
// now re-insert the '%' characters
lstrcpy( pszBuffer, _X( pszSpaces ) );
}
// copy the contents back to the original buffer
lstrcpy( szValue, pszBuffer );
// free the buffer
__free( pszBuffer );
__free( pszSpaces );
// return the same buffer back to the caller
return szValue;
}
// ***************************************************************************
// Routine Description:
//
// Trims the string on both sides (left and/or right)
//
// Arguments:
//
// [in] lpsz --String to trim
// [in] dwFlags --Flags for specifying left and/or right trim
//
// Return Value:
//
// LPTSTR -- Trimmed string.
//
// ***************************************************************************
LPTSTR TrimString( LPTSTR lpsz, DWORD dwFlags )
{
// local varibles
DWORD dwBegin = 0, dwEnd = 0;
LPTSTR pszTemp = NULL;
LPTSTR pszBuffer = NULL;
// validate the parameter
if ( lpsz == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return NULL_STRING;
}
// check length of the string if it empty string ...
if ( lstrlen( lpsz ) == 0 )
return lpsz;
// get the duplicate copy
pszTemp = _tcsdup( lpsz );
if ( pszTemp == NULL )
{
SetLastError( E_OUTOFMEMORY );
SaveLastError();
return NULL_STRING;
}
// traverse both from the end of the string and begining of the string
dwBegin = 0;
dwEnd = lstrlen( pszTemp ) - 1;
for( ; *( pszTemp + dwBegin ) == _T( ' ' ) || *( pszTemp + dwEnd ) == _T( ' ' ); )
{
// check the character at the current begining .. if space, move the pointer
if ( *( pszTemp + dwBegin ) == _T( ' ' ) && ( dwFlags & TRIM_LEFT ) )
dwBegin++;
// check whether the last character is space or not
// if space, decrement the size
if ( *( pszTemp + dwEnd ) == _T( ' ' ) && ( dwFlags & TRIM_RIGHT ) )
dwEnd--;
}
// do the actual trimming now
pszBuffer = pszTemp; // save the pointer ... needs to freed
*( pszTemp + dwEnd + 1 ) = NULL_CHAR; // remove trailing spaces first
pszTemp += dwBegin; // then leading spaces
lstrcpy( lpsz, pszTemp ); // copy to the source buffer
free( pszBuffer ); // release the duplicated memory
// return the string
return lpsz;
}
// ***************************************************************************
// Routine Description:
//
// Takes the password from the keyboard. While entering the password it shows
// the charecters as '*'
//
// Arguments:
//
// [in] pszPassword --password string to store password
// [in] dwMaxPasswordSize --Maximun size of the password. MAX_PASSWORD_LENGTH.
//
// Return Value:
//
// BOOL --If this function succeds returns true otherwise retuens false.
//
// ***************************************************************************
BOOL GetPassword( LPTSTR pszPassword, DWORD dwMaxPasswordSize )
{
// local variables
TCHAR ch;
DWORD dwIndex = 0;
DWORD dwCharsRead = 0;
DWORD dwCharsWritten = 0;
DWORD dwPrevConsoleMode = 0;
HANDLE hInputConsole = NULL;
TCHAR szBuffer[ 10 ] = NULL_STRING; // actually contains only character at all the times
BOOL bIndirectionInput = FALSE;
TCHAR szTmpBuffer[MAX_PASSWORD_LENGTH] = NULL_STRING;
HANDLE hnd;
// check the input value
if ( pszPassword == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return FALSE;
}
// get the handle for the standard input
hInputConsole = GetStdHandle( STD_INPUT_HANDLE );
if ( hInputConsole == NULL )
{
// could not get the handle so return failure
return FALSE;
}
// check for the input redirect
if( ( hInputConsole != (HANDLE)0x00000003 ) && ( hInputConsole != INVALID_HANDLE_VALUE ) )
{
bIndirectionInput = TRUE;
}
// redirect the data from StdIn.txt file into the console
if ( bIndirectionInput == FALSE )
{
// Get the current input mode of the input buffer
GetConsoleMode( hInputConsole, &dwPrevConsoleMode );
// Set the mode such that the control keys are processed by the system
if ( SetConsoleMode( hInputConsole, ENABLE_PROCESSED_INPUT ) == 0 )
{
// could not set the mode, return failure
return FALSE;
}
}
// Read the characters until a carriage return is hit
while( TRUE )
{
if ( bIndirectionInput == TRUE )
{
//read the contents of file
if ( ReadFile( hInputConsole, &ch, 1, &dwCharsRead, NULL ) == FALSE )
{
return FALSE;
}
// check for end of file
if ( dwCharsRead == 0 )
{
break;
}
}
else
{
if ( ReadConsole( hInputConsole, &ch, 1, &dwCharsRead, NULL ) == 0 )
{
// Set the original console settings
SetConsoleMode( hInputConsole, dwPrevConsoleMode );
// return failure
return FALSE;
}
}
// Check for carraige return
if ( ch == CARRIAGE_RETURN )
{
// break from the loop
break;
}
// Check id back space is hit
if ( ch == BACK_SPACE )
{
if ( dwIndex != 0 )
{
//
// Remove a asterix from the console
// move the cursor one character back
FORMAT_STRING( szBuffer, _T( "%c" ), BACK_SPACE );
WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), szBuffer, 1,
&dwCharsWritten, NULL );
// replace the existing character with space
FORMAT_STRING( szBuffer, _T( "%c" ), BLANK_CHAR );
WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), szBuffer, 1,
&dwCharsWritten, NULL );
// now set the cursor at back position
FORMAT_STRING( szBuffer, _T( "%c" ), BACK_SPACE );
WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), szBuffer, 1,
&dwCharsWritten, NULL );
// decrement the index
dwIndex--;
}
// process the next character
continue;
}
// if the max password length has been reached then sound a beep
if ( dwIndex == ( dwMaxPasswordSize - 1 ) )
{
WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), BEEP_SOUND, 1,
&dwCharsWritten, NULL );
}
else
{
// check for new line character
if ( ch != '\n' )
{
// store the input character
*( pszPassword + dwIndex ) = ch;
dwIndex++;
// display asterix onto the console
WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), ASTERIX, 1,
&dwCharsWritten, NULL );
}
}
}
// Add the NULL terminator
*( pszPassword + dwIndex ) = NULL_CHAR;
//Set the original console settings
SetConsoleMode( hInputConsole, dwPrevConsoleMode );
// display the character ( new line character )
FORMAT_STRING( szBuffer, _T( "%s" ), _T( "\n\n" ) );
WriteConsole( GetStdHandle( STD_OUTPUT_HANDLE ), szBuffer, 2,
&dwCharsWritten, NULL );
// Return success
return TRUE;
}
// ***************************************************************************
// Routine Description:
//
// Searches for a string in a string.
//
// Arguments:
//
// [in] szString --Null termibated string to search
// [in] szList --Null-terminated string to search for
// [in] bIgnoreCase --True for ignore the case
// --False for case sensitive search
//
// Return Value:
//
// BOOL --True if the string is found otherwise false
//
// ***************************************************************************
BOOL InString( LPCTSTR szString, LPCTSTR szList, BOOL bIgnoreCase )
{
// local variables
__MAX_SIZE_STRING szFmtList = NULL_STRING;
__MAX_SIZE_STRING szFmtString = NULL_STRING;
// check the input value
if ( szString == NULL || szList == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return FALSE;
}
// prepare the strings for searching
FORMAT_STRING( szFmtList, _T( "|%s|" ), szList );
FORMAT_STRING( szFmtString, _T( "|%s|" ), szString );
// check whether is comparision is case-sensitive or case-insensitive
if ( bIgnoreCase )
{
// convert the list and string to uppercase
CharUpper( szFmtList );
CharUpper( szFmtString );
}
// search for the string in the list and return result based
return ( _tcsstr( szFmtList, szFmtString ) != NULL );
}
// ***************************************************************************
// Routine Description:
//
// Compares the two given strings.
//
// Arguments:
//
// [in] szString1 --first null-terminated string to be compared
// [in] szString2 --second first null-terminated string to be compared
// [in] bIgnoreCase --True for ignoring the case.
// --False for case sensitive.
// [in] dwCount --Number of charecters to compare.
//
// Return Value:
//
// LONG -- < 0 szString1 substring less than szString2 substring
// -- = 0 szString1 substring identical to szString2 substring
// -- > 0 szString1 substring greater than szString2 substring
//
// ***************************************************************************
LONG StringCompare( LPCTSTR szString1, LPCTSTR szString2, BOOL bIgnoreCase, DWORD dwCount )
{
// local variables
LONG lResult;
// check the input value
if ( szString1 == NULL || szString2 == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return 0;
}
//
// start the comparision
if ( bIgnoreCase )
{
//
// do case in-sensitive comparision
// if count info is not available,
if ( dwCount == 0 )
lResult = lstrcmpi( szString1, szString2 );
else // otherwise
lResult = _tcsnicmp( szString1, szString2, dwCount );
}
else // case sensitive
{
//
// do case in-sensitive comparision
// if count info is not available,
if ( dwCount == 0 )
lResult = lstrcmp( szString1, szString2 );
else // otherwise
lResult = _tcsncmp( szString1, szString2, dwCount );
}
// now return comparision result
return lResult;
}
// ***************************************************************************
// Routine Description:
//
// Returns the resource string from the resource for the given resource ID.
//
// Arguments:
//
// [in] uID --Windows string resource identifier.
//
// Return Value:
//
// LPCTSTR --Resource string from the resource.
//
// ***************************************************************************
LPCTSTR GetResString( UINT uID )
{
// check whether memory is allocated or not
// if memory is not allocated, allocate now
if ( g_pszString == NULL )
{
g_pszString = ( LPTSTR ) __calloc( MAX_RES_STRING + 5, sizeof( TCHAR ) );
if ( g_pszString == NULL )
return NULL_STRING;
}
// load the string from the resource table
if ( LoadResString( uID, g_pszString, MAX_RES_STRING ) == 0 )
return NULL_STRING;
// return the string
return g_pszString;
}
// ***************************************************************************
// Routine Description:
//
// Returns the resourse string from the resource for the given resource ID.
//
// Arguments:
//
// [in] uID --Windows string resource identifier.
//
// Return Value:
//
// LPTSTR --Resource string from the resource.
//
// ***************************************************************************
LPTSTR GetResStringEx( UINT uID )
{
// local variables
LPTSTR pszBuffer = NULL;
// allocate the memory
pszBuffer = ( LPTSTR ) __calloc( MAX_RES_STRING + 5, sizeof( TCHAR ) );
if ( pszBuffer == NULL )
{
// ran out of memory
SetLastError( E_OUTOFMEMORY );
SaveLastError();
return NULL;
}
// load the string from the resource table
if ( LoadResString( uID, pszBuffer, MAX_RES_STRING ) == 0 )
return NULL;
// return the string
return pszBuffer;
}
// ***************************************************************************
// Routine Description:
//
// Loads the Resource String corresponding to the given ID.
//
// Arguments:
//
// [in] uID --Windows string resource identifier.
// LPTSTR pszValue --Nullterminated string to get the resource string.
// DWORD dwBufferMax --Size of the pszvalue.
//
// Return Value:
//
// DWORD --if success,Returns the size of the resource string.
// --otherwise returns 0.
//
// ***************************************************************************
DWORD LoadResString( UINT uID, LPTSTR pszValue, DWORD dwBufferMax )
{
// local variables
DWORD dwResult = 0;
static DWORD dwCurrentSize = 0;
static BOOL bThreadLocale = FALSE;
//
// because we operate in multi-lingual mode, it is good to set the appropriate
// thread locale and get the strings from resource table
//
if ( bThreadLocale == FALSE )
{
SetThreadUILanguage0( 0 );
bThreadLocale = TRUE;
}
// check the input value
if ( pszValue == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return 0;
}
// allocate memory for unicode buffer
if ( g_pwszResourceString == NULL )
{
dwCurrentSize = dwBufferMax; // save the size of the buffer
g_pwszResourceString = ( LPWSTR ) __calloc( dwBufferMax + 5, sizeof( wchar_t ) );
if ( g_pwszResourceString == NULL )
{
// ran out of memory
SetLastError( E_OUTOFMEMORY );
SaveLastError();
return 0;
}
}
else if ( dwCurrentSize < dwBufferMax )
{
// the existing size is less than the required, re-allocate buffer
dwCurrentSize = dwBufferMax;
g_pwszResourceString = ( LPWSTR ) __realloc( g_pwszResourceString,
(dwBufferMax + 1) * sizeof( wchar_t ) );
if ( g_pwszResourceString == NULL )
{
// ran out of memory
SetLastError( E_OUTOFMEMORY );
SaveLastError();
return 0;
}
}
// ( try ) loading the string from resource file string table
dwResult = LoadStringW( NULL, uID, g_pwszResourceString, dwBufferMax );
// check the result of loading string from string table
// if success, make the string into compatible string and copy it to the
// specified buffer
if ( dwResult != 0 )
{
// get the compatible string
GetCompatibleStringFromUnicode( g_pwszResourceString, pszValue, dwBufferMax );
}
// return
return dwResult;
}
// ***************************************************************************
// Routine Description:
//
// Writes the Message corrsponding to the given id in the given file.
//
// Arguments:
//
// [in] fp --File to write the string.
// [in] uID --Windows string resource identifier.
//
// Return Value:
//
// VOID
//
// ***************************************************************************
VOID ShowResMessage( FILE* fp, UINT uID )
{
// local variables
__RESOURCE_STRING szValue = NULL_STRING;
// check the input value
if ( fp == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return;
}
// load the string from the resource table
if ( LoadResString( uID, szValue, MAX_RES_STRING ) )
{
DISPLAY_MESSAGE( fp, szValue ); // display the message to the specified file
}
}
// ***************************************************************************
// Routine Description:
// Displays the given input message
// Arguments:
// [in] fp - file pointer
// [in] szMessage - Message to be shown
//
// Return Value:
//
// ***************************************************************************
VOID ShowMessage( FILE* fp, LPCTSTR szMessage )
{
// local variables
DWORD dw = 0;
DWORD dwTemp = 0;
DWORD dwLength = 0;
DWORD dwBufferSize = 0;
BOOL bResult = FALSE;
BOOL bCustom = FALSE;
HANDLE hOutput = NULL;
DWORD dwStdHandle = 0;
LPTSTR pszTemp = NULL;
LPCTSTR pszMessageBuffer = NULL;
char szBuffer[ 256 ] = "\0";
// check the input value
if ( fp == NULL || szMessage == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return;
}
// determine the length(s)
dwLength = lstrlen( szMessage );
dwBufferSize = SIZE_OF_ARRAY( szBuffer );
// determine the file handle
bCustom = FALSE;
if ( fp == stdout )
{
dwStdHandle = STD_OUTPUT_HANDLE;
}
else if ( fp == stderr )
{
dwStdHandle = STD_ERROR_HANDLE;
}
else
{
// currently default the unknown files to stderr
bCustom = TRUE;
dwStdHandle = STD_OUTPUT_HANDLE;
}
// get the handle to the stdout ( console )
hOutput = GetStdHandle( dwStdHandle );
if ( bCustom == FALSE && (((DWORD_PTR) hOutput) & 1) )
{
//
// sting might have contained '%' (extra) chars added by QuoteMeta
if ( FindOneOf( szMessage, _T( "%" ), 0 ) != NULL )
{
// allocate memory for formatting
pszTemp = __calloc( lstrlen( szMessage ) + 10, sizeof( TCHAR ) );
if ( pszTemp != NULL )
{
// we are not checking for non-null case which is out of memory error
// just to avoid too many complications
wsprintf( pszTemp, szMessage );
// make the temporary pointer point to the formatted text
pszMessageBuffer = pszTemp;
}
}
// check whether we did any formatting or not
if ( pszMessageBuffer == NULL )
{
// make the temporary pointer point to the original text
pszMessageBuffer = szMessage;
}
// display the output
bResult = WriteConsole( hOutput, pszMessageBuffer, dwLength, &dwTemp, NULL );
// free the memory allocated if allocated
if ( pszTemp != NULL )
{
__free( pszTemp );
pszTemp = NULL;
}
}
else
{
// show the text in shunks of buffer size
dw = 0;
while ( dwLength > dw )
{
// get the string in 'multibyte' format
GetAsMultiByteString( szMessage + dw, szBuffer, dwBufferSize - 1 );
// WideCharToMultiByte( CP_ACP, 0,
// szMessage + dw, dwBufferSize, szBuffer, dwBufferSize, NULL, NULL );
// determine the remaining buffer length
dw += dwBufferSize - 1;
// display string onto the specified file
// bResult = WriteFile( hOutput, szBuffer, lstrlenA( szBuffer ), &dwTemp, NULL );
// if ( bResult == FALSE )
// {
// break;
// }
fprintf( fp, szBuffer );
fflush( fp );
}
}
}
// ***************************************************************************
// Routine Description:
//
// Gets the Last error description
//
// Arguments:
//
// None
//
// Return Value:
//
// LPCTSTR The error description string
//
// ***************************************************************************
LPCTSTR GetReason()
{
// check whether buffer is allocated or not ... if not, empty string
if ( g_pszInfo == NULL )
return NULL_STRING;
// returh the reason for the last failure
return g_pszInfo;
}
// ***************************************************************************
// Routine Description:
//
// Sets teh last occured error as the given string.
//
// Arguments:
//
// [in] szReason -- Null terminated string taht holds the error description.
//
// Return Value:
//
// VOID
//
// ***************************************************************************
VOID SetReason( LPCTSTR szReason )
{
// check the input value
if ( szReason == NULL )
{
SetLastError( ERROR_INVALID_PARAMETER );
SaveLastError();
return;
}
// check whether memory is allocated or not
// if memory is not allocated, allocate now
if ( g_pszInfo == NULL )
{
g_pszInfo = ( LPTSTR ) __calloc( MAX_STRING_LENGTH + 5, sizeof( TCHAR ) );
if ( g_pszInfo == NULL )
return;
}
// set the reason .. max. allowed characters only
lstrcpyn( g_pszInfo, szReason, MAX_STRING_LENGTH + 1 );
}
// ***************************************************************************
// Routine Description:
//
// Arguments:
//
// Return Value:
//
// ***************************************************************************
LPCTSTR FindChar( LPCTSTR pszText, TCHAR ch, DWORD dwFrom )
{
// local variables
DWORD i = 0;
DWORD dwLength = 0;
// check the inputs
if ( pszText == NULL )
return NULL;
// get the lengths
dwLength = lstrlen( pszText );
// check the length of the text that has to be find. if it is
// more than the original it is obvious that it cannot be found
if ( dwLength == 0 || dwFrom >= dwLength )
return NULL;
// traverse thru the original text
for( i = dwFrom; i < dwLength; i++ )
{
// traverse thru the find string until characters were matching (or) string reached NULL
if ( pszText[ i ] == ch )
return pszText + i;
}
// string not found
return NULL;
}
// ***************************************************************************
// Routine Description:
//
// Arguments:
//
// Return Value:
//
// ***************************************************************************
LPCTSTR FindString( LPCTSTR pszText, LPCTSTR pszTextToFind, DWORD dwFrom )
{
// local variables
DWORD i = 0, j = 0;
DWORD dwLength = 0;
DWORD dwFindLength = 0;
// check the inputs
if ( pszText == NULL || pszTextToFind == NULL )
return NULL;
// get the lengths
dwLength = lstrlen( pszText );
dwFindLength = lstrlen( pszTextToFind );
// check the length of the text that has to be find. if it is
// more than the original it is obvious that it cannot be found
if ( (dwLength + dwFrom < dwFindLength) || dwFindLength == 0 || dwLength == 0 )
return NULL;
// traverse thru the original text
for( i = dwFrom; i < dwLength; i++ )
{
// traverse thru the find string until characters were matching (or) string reached NULL
for( j = 0; pszText[ i + j ] == pszTextToFind[ j ] && j < dwFindLength; j++ );
// check whether completer string is matched or not
if ( j == dwFindLength )
return pszText + i;
}
// string not found
return NULL;
}
// ***************************************************************************
// Routine Description:
//
// Arguments:
//
// Return Value:
//
// ***************************************************************************
LPCTSTR FindOneOf( LPCTSTR pszText, LPCTSTR pszTextToFind, DWORD dwFrom )
{
// local variables
DWORD i = 0, j = 0;
DWORD dwLength = 0;
DWORD dwFindLength = 0;
// check the inputs
if ( pszText == NULL || pszTextToFind == NULL )
return NULL;
// get the lengths
dwLength = lstrlen( pszText );
dwFindLength = lstrlen( pszTextToFind );
// check the length of the text that has to be find. if it is
// more than the original it is obvious that it cannot be found
if ( dwLength == 0 || dwFindLength == 0 || dwFrom >= dwLength )
return NULL;
// traverse thru the original text
for( i = dwFrom; i < dwLength; i++ )
{
// traverse thru the find string until characters were matching (or) string reached NULL
for( j = 0; pszText[ i ] != pszTextToFind[ j ] && j < dwFindLength; j++ );
// check whether completer string is matched or not
if ( j != dwFindLength )
return pszText + i;
}
// string not found
return NULL;
}
// ***************************************************************************
// Routine Description:
//
// Arguments:
//
// Return Value:
//
// ***************************************************************************
LPCTSTR QuoteMeta( LPCTSTR pszText, DWORD dwQuoteIndex )
{
// local variables
DWORD dw = 0;
DWORD dwIndex = 0;
DWORD dwLength = 0;
LPCTSTR pszTemp = NULL;
LPTSTR pszQuoteText = NULL;
TCHAR pszQuoteChars[] = _T( "%" );
// check the inputs
if ( pszText == NULL || dwQuoteIndex == 0 )
return NULL_STRING;
// create the quote data storage location
if ( g_arrQuotes == NULL )
{
g_arrQuotes = CreateDynamicArray();
if ( g_arrQuotes == NULL )
{
SetLastError( E_OUTOFMEMORY );
SaveLastError();
return NULL_STRING;
}
}
// check whether needed indexes exist or not
dwIndex = DynArrayGetCount( g_arrQuotes );
if ( dwIndex < dwQuoteIndex )
{
// add the needed no. of columns
dw = DynArrayAddColumns( g_arrQuotes, dwQuoteIndex - dwIndex + 1 );
// check whether columns were added or not
if ( dw != dwQuoteIndex - dwIndex + 1 )
{
SetLastError( E_OUTOFMEMORY );
SaveLastError();
return NULL_STRING;
}
}
// check whether the special chacters do exist in the text or not
// if not, simply return
if ( FindOneOf( pszText, pszQuoteChars, 0 ) == NULL )
return pszText;
// determine the length of the text that needs to be quoted
dwLength = lstrlen( pszText );
if ( dwLength == 0 )
return pszText;
// allocate the buffer ... it should twice the original
pszQuoteText = __calloc( (dwLength + 5) * 2, sizeof( TCHAR ) );
if ( pszQuoteText == NULL )
{
SetLastError( E_OUTOFMEMORY );
SaveLastError();
return NULL_STRING;
}
// do the quoting ...
dwIndex = 0;
for( dw = 0; dw < dwLength; dw++ )
{
// check whether the current character is quote char or not
// NOTE: for time being this function only suppresses the '%' character escape sequences
if ( FindChar( pszQuoteChars, pszText[ dw ], 0 ) != NULL )
pszQuoteText[ dwIndex++ ] = _T( '%' );
// copy the character
pszQuoteText[ dwIndex++ ] = pszText[ dw ];
}
// put the null character
pszQuoteText[ dwIndex ] = _T( '\0' );
// save the quoted text in dynamic array
if ( DynArraySetString( g_arrQuotes, dwQuoteIndex, pszQuoteText, 0 ) == FALSE )
{
SetLastError( E_OUTOFMEMORY );
SaveLastError();
__free( pszQuoteText );
return NULL_STRING;
}
// release the memory allocated for quoted text
__free( pszQuoteText );
// get the text from the array
pszTemp = DynArrayItemAsString( g_arrQuotes, dwQuoteIndex );
if ( pszTemp == NULL )
{
SetLastError( STG_E_UNKNOWN );
SaveLastError();
return NULL_STRING;
}
// return
return pszTemp;
}
// ***************************************************************************
// Routine Description:
//
// Complex scripts cannot be rendered in the console, so we
// force the English (US) resource.
//
// Arguments:
// [ in ] dwReserved => must be zero
//
// Return Value:
// TRUE / FALSE
//
// ***************************************************************************
BOOL SetThreadUILanguage0( DWORD dwReserved )
{
// local variables
HMODULE hKernel32Lib = NULL;
const CHAR cstrFunctionName[] = "SetThreadUILanguage";
typedef BOOLEAN (WINAPI * FUNC_SetThreadUILanguage)( DWORD dwReserved );
FUNC_SetThreadUILanguage pfnSetThreadUILanguage = NULL;
// try loading the kernel32 dynamic link library
hKernel32Lib = LoadLibrary( _T( "kernel32.dll" ) );
if ( hKernel32Lib != NULL )
{
// library loaded successfully ... now load the addresses of functions
pfnSetThreadUILanguage = (FUNC_SetThreadUILanguage) GetProcAddress( hKernel32Lib, cstrFunctionName );
// we will keep the library loaded in memory only if all the functions were loaded successfully
if ( pfnSetThreadUILanguage == NULL )
{
// some (or) all of the functions were not loaded ... unload the library
FreeLibrary( hKernel32Lib );
hKernel32Lib = NULL;
pfnSetThreadUILanguage = NULL;
return FALSE;
}
}
// call the function
((FUNC_SetThreadUILanguage) pfnSetThreadUILanguage)( dwReserved );
// unload the library and return success
FreeLibrary( hKernel32Lib );
hKernel32Lib = NULL;
pfnSetThreadUILanguage = NULL;
return TRUE;
}
// ***************************************************************************
// Routine Description:
//
// Releases all the global values that are used.
//
// Arguments:
//
// None.
//
// Return Value:
//
// VOID
//
// ***************************************************************************
VOID ReleaseGlobals()
{
// local variables
DWORD dw = 0;
//
// memory is allocated then free memory
// free memory for variable that holds the reason for failure
if ( g_pszInfo != NULL )
{
__free( g_pszInfo );
}
// free memory for variable that used to get the string in resource table
if ( g_pszString != NULL )
{
__free( g_pszString );
}
// free memory for variable that used to get the string in resource table in UNICODE
if ( g_pwszResourceString != NULL )
{
__free( g_pwszResourceString );
}
// free the memory allocs for quote metas
DestroyDynamicArray( &g_arrQuotes );
// if winsock module is loaded, release it
if ( g_bWinsockLoaded == TRUE )
WSACleanup();
}