1866 lines
48 KiB
C
1866 lines
48 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();
|
|
}
|