|
|
// *********************************************************************************
//
// 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 ([email protected]) 01-Sep-2000
//
// Revision History:
//
// Sunil G.V.N. Murali ([email protected]) 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(); }
|