/*****************************************************************************\ Author: Corey Morgan (coreym) Copyright (c) Microsoft Corporation. All rights reserved. \*****************************************************************************/ #include #include #include #include #include #include #include #include "varg.h" LPTSTR g_strProg; HANDLE g_hConsole; WORD g_debug; WORD g_light; WORD g_dark; WORD g_normal; LPTSTR g_strVerbPrefix; LPTSTR g_strPrefix; LPTSTR g_strArgToken; SHORT g_X; SHORT g_Y; LONG g_nDebug = -1; LCID g_LCID = 0; #define COLORIZE( c ) (WORD)((Commands[c].fFlag & (VARG_FLAG_DARKEN|VARG_FLAG_HIDDEN)) ? g_dark : g_normal) #define HELP_INDENT 32 #define VARG_LOCALE ( g_LCID ? g_LCID : LOCALE_USER_DEFAULT ) BOOL varg_strlen( LPTSTR str, ULONG* pVisualSize, ULONG* pAcutalSize, BOOL* bCanBreak ); void PrintParam( int idPrompt, int cmd, BOOL bEOL ); BOOL FindString( LPTSTR strBuffer, LPTSTR strMatch ); int varg_vprintf( WORD color, LPCTSTR mask, va_list args ) { DWORD dwPrint; HANDLE hOut; hOut = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute( g_hConsole, color ); __try { LPTSTR buffer = NULL; dwPrint = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER| FORMAT_MESSAGE_FROM_STRING, mask, 0, 0, (LPTSTR)&buffer, 4096, &args ); if( NULL != buffer ){ BOOL bBreak; ULONG len,temp; if ((GetFileType(hOut) & ~FILE_TYPE_REMOTE) == FILE_TYPE_CHAR) { WriteConsole( hOut, buffer, dwPrint, &dwPrint, NULL ); }else{ LPSTR szAnsiBuffer = NULL; szAnsiBuffer = (LPSTR)VARG_ALLOC( (dwPrint+1) * sizeof(WCHAR) ); if( NULL != szAnsiBuffer ){ if( CharToOem( buffer, szAnsiBuffer ) ){ WriteFile( hOut, szAnsiBuffer, strlen( szAnsiBuffer ), &temp, NULL ); } } VARG_FREE( szAnsiBuffer ); } if( varg_strlen( buffer, &len, &temp, &bBreak ) ){ dwPrint = len; } LocalFree( buffer ); } } __except (EXCEPTION_EXECUTE_HANDLER) { dwPrint = 0; } SetConsoleTextAttribute( g_hConsole, g_normal ); return (int)dwPrint; } int varg_printf( WORD color, LPCTSTR mask, ... ) { int nPrint; va_list args; va_start( args, mask ); nPrint = varg_vprintf( color, mask, args ); va_end( args ); return nPrint; } _inline BOOL IsArg( LPTSTR str ) { int i; if( str == NULL ){ return FALSE; } for( i=0;ifFlag & VARG_FLAG_NOFLAG ){ if( arg->bDefined ){ return FALSE; }else{ return TRUE; } } if( !( (arg->fFlag & VARG_FLAG_VERB) || (arg->fFlag & VARG_FLAG_ADVERB)) ){ return FALSE; } } } if( str[0] == _T('-') ){ bNegated = TRUE; str++; } if( ( arg->strArg1 != NULL && !_tcsicmp( str, arg->strArg1 ) ) || ( arg->strArg2 != NULL && !_tcsicmp( str, arg->strArg2 ) ) ){ if( arg->fFlag & VARG_FLAG_NEGATE ){ arg->bNegated = bNegated; } return TRUE; } return FALSE; } _inline BOOL ArgExpected( PVARG_RECORD arg ) { switch(arg->fType){ case VARG_TYPE_BOOL: case VARG_TYPE_HELP: return FALSE; } return TRUE; } _inline BOOL IsEmpty( LPTSTR str ) { if( str == NULL ){ return TRUE; } if( *str == _T('\0') ){ return TRUE; } return FALSE; } void Chomp(LPTSTR pszLine) { size_t lLen; LPTSTR pszLineEnd; if( pszLine == NULL ){ return; } lLen = _tcslen(pszLine); pszLineEnd = pszLine + lLen - 1; while( pszLineEnd >= pszLine && (*pszLineEnd == _T(' ') || *pszLineEnd == _T('\r') || *pszLineEnd == _T('\n') || *pszLineEnd == _T('\t')) ){ pszLineEnd--; } pszLineEnd++; if (*pszLineEnd == _T(' ') || *pszLineEnd == _T('\n') || *pszLineEnd == _T('\t') ){ *pszLineEnd = _T('\0'); } } HRESULT ReadLong( LPTSTR strNumber, ULONG* pulNumber, ULONG nMax ) { LPTSTR strBuffer = NULL; ULONG nValue; HRESULT hr = ERROR_INVALID_PARAMETER; if( NULL == strNumber ){ *pulNumber = 0; hr = ERROR_SUCCESS; }else{ ASSIGN_STRING( strBuffer, strNumber ); if( NULL == strBuffer ){ hr = ERROR_OUTOFMEMORY; }else{ LPTSTR strEnd; LPTSTR strBegin; size_t count; nValue = (ULONG)_tcstod( strNumber, &strEnd ); _stprintf( strBuffer, _T("%lu"), nValue ); strBegin = strNumber; while( *strBegin == _T('0') && (strEnd - strBegin) > 1 ){ strBegin++; } count = (size_t)(strEnd - strBegin); if( (_tcsnicmp( strBuffer, strBegin, count ) == 0) ){ if( nValue <= nMax ){ *pulNumber = nValue; hr = ERROR_SUCCESS; } } } } VARG_FREE( strBuffer ); return hr; } void SetUpColors() { CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo; HKEY hkey = NULL; HRESULT hr; DWORD dwColorize = 0; g_hConsole = GetStdHandle( STD_OUTPUT_HANDLE ); GetConsoleScreenBufferInfo( g_hConsole, &ConsoleInfo ); g_X = (SHORT)(ConsoleInfo.srWindow.Right - ConsoleInfo.srWindow.Left); g_Y = (SHORT)(ConsoleInfo.srWindow.Bottom - ConsoleInfo.srWindow.Top); hr = RegOpenKeyExW ( HKEY_CURRENT_USER, L"Console", 0, KEY_ALL_ACCESS, &hkey ); if( ERROR_SUCCESS == hr ){ DWORD dwType; DWORD dwSize = sizeof(DWORD); hr = RegQueryValueExW ( hkey, L"Colorize", NULL, &dwType, (LPBYTE)&dwColorize, &dwSize ); } if( ERROR_SUCCESS == hr ){ if( dwColorize == 0xff ){ g_normal = ConsoleInfo.wAttributes; g_light = (USHORT)(ConsoleInfo.wAttributes | FOREGROUND_INTENSITY); g_debug = (USHORT)((ConsoleInfo.wAttributes & 0xF0) | FOREGROUND_INTENSITY | FOREGROUND_RED); g_dark = (USHORT)((ConsoleInfo.wAttributes & 0xF0) | FOREGROUND_INTENSITY); }else{ g_normal = (USHORT)(dwColorize & 0x000000FF); g_debug = (USHORT)((dwColorize & 0x0000FF00) >> 8); g_light = (USHORT)((dwColorize & 0x00FF0000) >> 16); g_dark = (USHORT)((dwColorize & 0xFF000000) >> 24); } }else{ g_normal = ConsoleInfo.wAttributes; g_debug = g_normal; g_light = g_normal; g_dark = g_normal; } if((g_dark & 0xF) == ((g_dark >> 4) & 0xF)) { g_dark = g_normal; } if((g_light & 0xF) == ((g_light >> 4) & 0xF)) { g_light = g_normal; } if((g_debug & 0xF) == ((g_debug >> 4) & 0xF)) { g_debug = g_normal; } if( NULL != hkey ){ RegCloseKey ( hkey ); } } void FreeCmd() { int i; for(i=0;Commands[i].fType != VARG_TYPE_LAST;i++){ if( Commands[i].fType == VARG_TYPE_STR || Commands[i].fType == VARG_TYPE_MSZ || Commands[i].fType == VARG_TYPE_INI ){ Commands[i].bDefined = FALSE; if( !(Commands[i].fFlag & VARG_FLAG_DODEFAULT) ){ VARG_FREE( Commands[i].strValue ); Commands[i].strValue = NULL; } } if( Commands[i].strArg1 != NULL ){ VARG_FREE( Commands[i].strArg1 ); } if( Commands[i].strArg2 != NULL ){ VARG_FREE( Commands[i].strArg2 ); } } VARG_FREE( g_strArgToken ); VARG_FREE( g_strPrefix ); VARG_FREE( g_strVerbPrefix ); SetConsoleTextAttribute( g_hConsole, g_normal ); } void LoadCmd() { int i; TCHAR buffer[MAXSTR]; TCHAR param[MAXSTR]; LPTSTR str; if( LoadString( NULL, IDS_ARG_TOKEN, buffer, MAXSTR ) ){ ASSIGN_STRING( g_strArgToken, buffer ); }else{ str = _T("`"); ASSIGN_STRING( g_strArgToken, str ); } if( LoadString( NULL, IDS_ARG_PREFIX, buffer, MAXSTR ) ){ ASSIGN_STRING( g_strPrefix, buffer ); }else{ str = _T("-/"); ASSIGN_STRING( g_strPrefix, str ); } if( LoadString( NULL, IDS_VERB_PREFIX, buffer, MAXSTR ) ){ ASSIGN_STRING( g_strVerbPrefix, buffer ); }else{ str = _T(""); ASSIGN_STRING( g_strVerbPrefix, str ); } for( i=0; Commands[i].fType!=VARG_TYPE_LAST; i++ ){ LPTSTR strArg1; LPTSTR strArg2; LPTSTR strParam; LPTSTR strHelp; LoadString( NULL, Commands[i].idParam, param, MAXSTR ); strArg1 = _tcstok( param, g_strArgToken ); strArg2 = _tcstok( NULL, g_strArgToken ); strParam = _tcstok( NULL, g_strArgToken ); strHelp = _tcstok( NULL, g_strArgToken ); ASSIGN_STRING_RC( Commands[i].strArg1, strArg1, _T("*") ); ASSIGN_STRING_RC( Commands[i].strArg2, strArg2, _T("*") ); if( Commands[i].fFlag & VARG_FLAG_ARG_DATE ){ TCHAR strDate[80]; TCHAR strTime[80]; TCHAR strAM[4]; TCHAR strPM[4]; GetLocaleInfo( VARG_LOCALE, LOCALE_SSHORTDATE, strDate, 80 ); GetLocaleInfo( VARG_LOCALE, LOCALE_STIMEFORMAT, strTime, 80 ); if( !GetLocaleInfo( VARG_LOCALE, LOCALE_S1159, strAM, 4 ) ){ strAM[0] = _T('\0'); } if( !GetLocaleInfo( VARG_LOCALE, LOCALE_S2359, strPM, 4 ) ){ strPM[0] = _T('\0'); } _tcstok( strTime, _T(" ") ); if( _tcslen( strAM ) && _tcslen(strPM) ){ if( Commands[i].fFlag & VARG_FLAG_DEFAULTABLE ){ _stprintf( buffer, _T("[%s %s[%s|%s]]"), strDate, strTime, strAM, strPM ); }else{ _stprintf( buffer, _T("<%s %s[%s|%s]>"), strDate, strTime, strAM, strPM ); } }else{ if( Commands[i].fFlag & VARG_FLAG_DEFAULTABLE ){ _stprintf( buffer, _T("[%s %s]"), strDate, strTime ); }else{ _stprintf( buffer, _T("<%s %s>"), strDate, strTime ); } } ASSIGN_STRING_RC( Commands[i].strParam, buffer, _T("*") ); }else{ if( Commands[i].fFlag & VARG_FLAG_ARG_DEFAULT ){ LoadString( NULL, IDS_ARG_DEFAULT, param, MAXSTR ); strParam = param; }else if( Commands[i].fFlag & VARG_FLAG_ARG_FILENAME ){ LoadString( NULL, IDS_ARG_FILENAME, param, MAXSTR ); strParam = param; }else if( Commands[i].fFlag & VARG_FLAG_ARG_TIME ){ LoadString( NULL, IDS_ARG_TIME, param, MAXSTR ); strParam = param; } if( strParam != NULL && _tcslen( strParam ) && _tcscmp( strParam, _T("*") ) ){ if( Commands[i].fFlag & VARG_FLAG_DEFAULTABLE ){ if( Commands[i].fType == VARG_TYPE_MSZ && !(Commands[i].fFlag & VARG_FLAG_FLATHELP) ){ _stprintf( buffer, _T("[%s [%s ...]]"), strParam, strParam ); }else{ _stprintf( buffer, _T("[%s]"), strParam ); } }else{ if( Commands[i].fType == VARG_TYPE_MSZ && !(Commands[i].fFlag & VARG_FLAG_FLATHELP)){ _stprintf( buffer, _T("<%s [%s ...]>"), strParam, strParam ); }else{ _stprintf( buffer, _T("<%s>"), strParam ); } } ASSIGN_STRING_RC( Commands[i].strParam, buffer, _T("*") ); }else{ strParam = NULL; ASSIGN_STRING_RC( Commands[i].strParam, strParam, _T("*") ); } } } } ULONG MszStrLen( LPTSTR mszBuffer ) { ULONG nLength = 0; ULONG nTotalLength = 0; LPTSTR strScan = mszBuffer; ULONG nTermSize = sizeof(TCHAR) * 2; while( strScan != NULL && *strScan != _T('\0') ){ nLength = (_tcslen( strScan )+1); strScan += nLength; nTotalLength += nLength; } return (nTotalLength*sizeof(TCHAR) + nTermSize); } HRESULT AddStringToMsz( LPTSTR* mszBuffer, LPTSTR strValue ) { ULONG nNewDataSize = 0; ULONG nOldDataSize = 0; LPTSTR strScan = *mszBuffer; LPTSTR mszNewBuffer; ULONG nLength; if( IsEmpty( strValue ) ){ return ERROR_SUCCESS; } if( strScan != NULL ){ while( *strScan != _T('\0') ){ nLength = (_tcslen( strScan )+1); strScan += nLength; nOldDataSize += nLength; } } nNewDataSize = ( _tcslen( strValue )+1 ) * sizeof(TCHAR); mszNewBuffer = (LPTSTR)VARG_ALLOC( (nOldDataSize + nNewDataSize)*sizeof(TCHAR) + (sizeof(TCHAR)*2) ); if( NULL == mszNewBuffer ){ return ERROR_OUTOFMEMORY; } ZeroMemory( mszNewBuffer, (nOldDataSize + nNewDataSize)*sizeof(TCHAR) + (sizeof(TCHAR)*2) ); if( nOldDataSize ){ memcpy( mszNewBuffer, *mszBuffer, nOldDataSize*sizeof(TCHAR) ); memcpy( (((PUCHAR)mszNewBuffer) + nOldDataSize*sizeof(TCHAR)), strValue, nNewDataSize ); }else{ memcpy( mszNewBuffer, strValue, nNewDataSize ); } VARG_FREE( *mszBuffer ); *mszBuffer = mszNewBuffer; return ERROR_SUCCESS; } void ParseIni( LPTSTR strFile ) { TCHAR buffer[MAXSTR]; FILE* f; LPTSTR str; TCHAR strCmd[MAXSTR]; LPTSTR strValue; BOOL bFound; int i; ZeroMemory( strCmd, MAXSTR*sizeof(TCHAR) ); if( strFile == NULL || _tcslen( strFile ) == 0 ){ return; } f = _tfopen( strFile, _T("r") ); if( NULL == f ){ return; } while( _fgetts( buffer, MAXSTR, f ) ){ if( buffer[0] == _T(';') || // comments buffer[0] == _T('#') ){ continue; } Chomp( buffer ); if( IsEmpty( buffer ) ){ continue; } if( buffer[0] == _T('[') || _tcsstr( buffer, _T("=") ) ){ str = _tcstok( buffer, _T("[]\n\t=") ); if( str != NULL ){ _tcscpy( strCmd, str ); strValue = _tcstok( NULL, _T("]=\n ") ); }else{ strCmd[0] = _T('\0'); strValue = NULL; } }else{ strValue = _tcstok( buffer, _T("\n") ); } bFound = FALSE; // // Check to see if it is a parameter that does not take a value // for(i=0; Commands[i].fType != VARG_TYPE_LAST && (!bFound);i++ ){ if( IsCmd( &Commands[i], strCmd, TRUE ) ){ switch( Commands[i].fType ){ case VARG_TYPE_HELP: bFound = TRUE; break; case VARG_TYPE_BOOL: bFound = TRUE; Commands[i].bValue = Commands[i].bValue ? FALSE : TRUE; break; } if( bFound ){ Commands[i].bDefined = TRUE; if( Commands[i].bDefined && Commands[i].fntValidation != NULL ){ Commands[i].fntValidation(i); } } } } if( bFound || strValue == NULL || _tcslen( strCmd ) == 0 ){ continue; } for(i=0; Commands[i].fType != VARG_TYPE_LAST && (!bFound);i++ ){ if( IsCmd( &Commands[i], strCmd, TRUE ) ){ bFound = TRUE; if( Commands[i].bDefined && Commands[i].fType != VARG_TYPE_MSZ ){ continue; } switch( Commands[i].fType ){ case VARG_TYPE_DEBUG: case VARG_TYPE_INT: { ULONG nValue; if( ERROR_SUCCESS == ReadLong( strValue, &nValue, MAXLONG ) ){ Commands[i].nValue = nValue; if( Commands[i].fType == VARG_TYPE_DEBUG ){ g_nDebug = nValue; } } } break; case VARG_TYPE_MSZ: if( !Commands[i].bDefined ){ Commands[i].strValue = NULL; } if( Commands[i].fFlag & VARG_FLAG_CHOMP ){ Chomp( strValue ); } AddStringToMsz( &Commands[i].strValue, strValue ); break; case VARG_TYPE_STR: if( Commands[i].fFlag & VARG_FLAG_CHOMP ){ Chomp( strValue ); } Commands[i].strValue = (LPTSTR)VARG_ALLOC( (_tcslen(strValue)+1) * sizeof(TCHAR) ); if( Commands[i].strValue != NULL ){ _tcscpy( Commands[i].strValue, strValue ); } break; case VARG_TYPE_TIME: case VARG_TYPE_DATE: ParseTime( strValue, &Commands[i].stValue, (Commands[i].fType == VARG_TYPE_DATE) ); break; } Commands[i].bDefined = TRUE; if( Commands[i].bDefined && Commands[i].fntValidation != NULL ){ Commands[i].fntValidation(i); } } } } fclose(f); } void ParseCmd(int argc, LPTSTR argv[] ) { int i; BOOL bFound; BOOL bHelp = FALSE; BOOL bBadSyntax = FALSE; int nIniIndex = (-1); g_LCID = VSetThreadUILanguage(0); VArgDeclareFormat(); LoadCmd(); SetUpColors(); g_strProg = argv[0]; argv++;argc--; while( argc > 0 ){ bFound = FALSE; for(i=0; Commands[i].fType != VARG_TYPE_LAST && (!bFound);i++){ if( IsCmd( &Commands[i], argv[0], FALSE ) ){ if(Commands[i].bDefined){ PrintMessage( g_debug, IDS_MESSAGE_ARG_DUP, Commands[i].strArg1, argv[0] ); bBadSyntax = TRUE; } if( IsArg( argv[0] ) || Commands[i].fFlag & VARG_FLAG_VERB || Commands[i].fFlag & VARG_FLAG_ADVERB ){ argv++;argc--; } bFound = TRUE; Commands[i].bDefined = TRUE; switch( Commands[i].fType ){ case VARG_TYPE_HELP: Commands[i].bValue = TRUE; bHelp = TRUE; break; case VARG_TYPE_DEBUG: Commands[i].fFlag |= VARG_FLAG_DEFAULTABLE; g_nDebug = Commands[i].nValue; case VARG_TYPE_INT: if( argc > 0 && !IsArg( argv[0] ) ){ ULONG nValue; HRESULT hr = ReadLong( argv[0], &nValue, MAXLONG ); if( ERROR_SUCCESS == hr ){ Commands[i].nValue = nValue; }else{ Commands[i].fFlag |= VARG_FLAG_BADSYNTAX; } if( Commands[i].fType == VARG_TYPE_DEBUG ){ g_nDebug = Commands[i].nValue; } argv++;argc--; }else if( !(Commands[i].fFlag & VARG_FLAG_DEFAULTABLE) ){ if( !Commands[i].bNegated ){ Commands[i].fFlag |= VARG_FLAG_BADSYNTAX; } } break; case VARG_TYPE_BOOL: Commands[i].bValue = Commands[i].bValue ? FALSE : TRUE; break; case VARG_TYPE_MSZ: if( argc > 0 && !IsArg( argv[0] ) ){ ASSIGN_STRING( Commands[i].strValue, argv[0] ); argv++;argc--; while( argc > 0 && ! IsArg( argv[0] ) ){ if( Commands[i].fFlag & VARG_FLAG_CHOMP ){ Chomp( argv[0] ); } AddStringToMsz( &Commands[i].strValue, argv[0] ); argv++;argc--; } }else if( Commands[i].fFlag & VARG_FLAG_DEFAULTABLE || Commands[i].bNegated ){ Commands[i].fFlag |= VARG_FLAG_DODEFAULT; }else{ Commands[i].fFlag |= VARG_FLAG_BADSYNTAX; } break; case VARG_TYPE_INI: nIniIndex = i; case VARG_TYPE_STR: if( argc > 0 && ! IsArg( argv[0] ) ){ if( Commands[i].fFlag & VARG_FLAG_CHOMP ){ Chomp( argv[0] ); } Commands[i].strValue = (LPTSTR)VARG_ALLOC( (_tcslen(argv[0])+2) * sizeof(TCHAR) ); if( Commands[i].strValue != NULL ){ _tcscpy( Commands[i].strValue, argv[0] ); } argv++;argc--; }else if( Commands[i].fFlag & VARG_FLAG_DEFAULTABLE || Commands[i].bNegated ){ Commands[i].fFlag |= VARG_FLAG_DODEFAULT; }else{ if( !(Commands[i].fFlag & VARG_FLAG_NEGATE) ){ Commands[i].fFlag |= VARG_FLAG_BADSYNTAX; } } break; case VARG_TYPE_TIME: case VARG_TYPE_DATE: if( argc > 0 && !IsArg( argv[0] ) ){ HRESULT hr; LPTSTR strDate = NULL; LPTSTR strTime = argv[0]; argv++;argc--; if( Commands[i].fType == VARG_TYPE_DATE ){ if( argc > 0 && !IsArg( argv[0] ) ){ strDate = (LPTSTR)VARG_ALLOC( (_tcslen(strTime)+_tcslen(argv[0])+2)*sizeof(TCHAR) ); if( NULL != strDate ){ _stprintf( strDate, _T("%s %s"), strTime, argv[0] ); strTime = strDate; } argv++;argc--; } } hr = ParseTime( strTime, &Commands[i].stValue, (Commands[i].fType == VARG_TYPE_DATE) ); if( ERROR_SUCCESS != hr ){ Commands[i].fFlag |= VARG_FLAG_BADSYNTAX; } VARG_FREE( strDate ); }else if( !(Commands[i].fFlag & VARG_FLAG_DEFAULTABLE) && !(Commands[i].bNegated) ){ Commands[i].fFlag |= VARG_FLAG_BADSYNTAX; } } if( Commands[i].fFlag & VARG_FLAG_EXPANDFILES ){ ExpandFiles( &Commands[i].strValue, (Commands[i].fType == VARG_TYPE_MSZ) ); } } } if (!bFound){ PrintMessage( g_debug, IDS_MESSAGE_UNKNOWNPARAM, (*(argv))); argv++;argc--; bBadSyntax = TRUE; } } if( nIniIndex >= 0 ){ if( Commands[nIniIndex].fType == VARG_TYPE_INI && Commands[nIniIndex].bDefined ){ ParseIni( Commands[nIniIndex].strValue ); } } for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){ if( !bHelp && (Commands[i].bDefined && Commands[i].fntValidation != NULL ) ){ Commands[i].fntValidation(i); } if( ( Commands[i].fType == VARG_TYPE_STR || Commands[i].fType == VARG_TYPE_MSZ || Commands[i].fType == VARG_TYPE_INI ) && (!Commands[i].bDefined || Commands[i].fFlag & VARG_FLAG_DODEFAULT ) ){ TCHAR buffer[MAXSTR]; Commands[i].fFlag &= ~VARG_FLAG_DODEFAULT; if( Commands[i].fFlag & VARG_FLAG_RCDEFAULT ){ LoadString( NULL, Commands[i].nValue, buffer, MAXSTR ); ASSIGN_STRING( Commands[i].strValue, buffer ); }else if( Commands[i].strValue != NULL ){ ASSIGN_STRING( Commands[i].strValue, Commands[i].strValue ); } } } if( bHelp ){ DisplayCommandLineHelp(); } if( g_nDebug >= 0 ){ DisplayDebugInfo(); } if( ERROR_SUCCESS != ValidateCommands() || bBadSyntax ){ PrintMessage( g_debug, IDS_MESSAGE_INCORRECT ); FreeCmd(); exit(ERROR_BAD_FORMAT); } } void DisplayIniInfo() { int i; int nOut; BOOL bOpt; PrintMessage( g_normal, IDS_MESSAGE_INISYNT ); for( i=0;i<35;i++){ varg_printf( g_normal, _T("-") ); } varg_printf( g_normal, _T("\n") ); for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){ if( Commands[i].fFlag & VARG_FLAG_HIDDEN && !(Commands[i].bDefined) ){ continue; } bOpt = ( Commands[i].strArg2 != NULL && _tcslen( Commands[i].strArg2 ) ); switch( Commands[i].fType ){ case VARG_TYPE_DEBUG: case VARG_TYPE_BOOL: case VARG_TYPE_MSZ: case VARG_TYPE_STR: case VARG_TYPE_INT: case VARG_TYPE_TIME: case VARG_TYPE_DATE: nOut = varg_printf( g_normal, _T(" %1!-20s! %2!-20s!\n"), Commands[i].strArg1, bOpt ? Commands[i].strArg2 : _T("") ); break; } } varg_printf( g_normal, _T("\n") ); } void DisplayDebugInfo() { int i; int nOut; TCHAR strDefault[MAXSTR] = _T(""); LoadString( NULL, IDS_MESSAGE_DEFAULT, strDefault, MAXSTR ); for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){ if( !(Commands[i].bDefined) && g_nDebug < 1 ){ continue; } if( Commands[i].fType == VARG_TYPE_HELP ){ continue; } if( Commands[i].fFlag & VARG_FLAG_HIDDEN && !(Commands[i].bDefined) ){ continue; } nOut = varg_printf( g_debug, _T("%1!-16s! = "), Commands[i].strArg1 ); switch( Commands[i].fType ){ case VARG_TYPE_DEBUG: case VARG_TYPE_INT: varg_printf( g_debug, _T("%1!-20lu!"), Commands[i].nValue ); break; case VARG_TYPE_BOOL: varg_printf( g_debug, _T("%1!-20s!"), Commands[i].bValue ? _T("TRUE") : _T("FALSE") ); break; case VARG_TYPE_MSZ: if( !IsEmpty( Commands[i].strValue ) ){ LPTSTR strValue = Commands[i].strValue; while( *strValue != _T('\0') ){ if( strValue == Commands[i].strValue ){ varg_printf( g_debug, _T("%1!-20s!"), strValue ); }else{ varg_printf( g_debug, _T("\n%1!19s!%2!-20s!"), _T(" "), strValue ); } strValue += (_tcslen( strValue )+1); } }else{ varg_printf( g_debug, _T("%1!-20s!"), _T("-") ); } break; case VARG_TYPE_TIME: case VARG_TYPE_DATE: { int nOut; nOut = PrintDateEx( g_debug, &Commands[i].stValue ); while( nOut++ < 20 ) { varg_printf( g_debug, _T(" ") ); } } break; case VARG_TYPE_INI: case VARG_TYPE_STR: varg_printf( g_debug, _T("%1!-20s!"), (Commands[i].strValue == NULL || !(_tcslen(Commands[i].strValue)) ) ? _T("-") : Commands[i].strValue ); break; } if( !Commands[i].bDefined ){ varg_printf( g_debug, _T(" (%1!s!)"), strDefault ); } varg_printf( g_debug, _T("\n") ); } varg_printf( g_debug, _T("\n") ); } int PrintMessage( WORD color, LONG id, ... ) { int nLoad; TCHAR buffer[MAXSTR]; va_list args; va_start( args, id ); nLoad = LoadString( NULL, id, buffer, MAXSTR ); if( nLoad > 0 ){ nLoad = varg_vprintf( color, buffer, args ); }else{ nLoad = FormatMessage( FORMAT_MESSAGE_FROM_HMODULE, GetModuleHandle(NULL), id, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), buffer, MAXSTR, &args ); varg_printf( color, buffer ); } return nLoad; } BOOL varg_strlen( LPTSTR str, ULONG* pVisualSize, ULONG* pActualSize, BOOL* bCanBreak ) { BOOL bResult; WORD wType[MAXSTR]; ULONG i; *pActualSize = _tcslen(str); if( *pActualSize > MAXSTR ){ return FALSE; } bResult = GetStringTypeEx( VARG_LOCALE, CT_CTYPE3, str, *pActualSize, (LPWORD)&wType ); if( !bResult ){ return FALSE; } *pVisualSize = 0; *bCanBreak = FALSE; for( i=0;i<*pActualSize;i++ ){ if( wType[i] & (C3_KATAKANA|C3_HIRAGANA|C3_IDEOGRAPH|C3_FULLWIDTH) ){ *pVisualSize += 2; *bCanBreak = TRUE; }else{ *pVisualSize += 1; } } return TRUE; } HRESULT PrintHelpString( LONG id, LONG nStart, LONG nCol, LONG nMax, BOOL bSwitch ) { int j,nLoad; TCHAR buffer[MAXSTR]; LPTSTR strHelp; ULONG nOut; if( nMax <= nCol ){ nMax = 79; } nLoad = LoadString( NULL, id, buffer, MAXSTR ); strHelp = _tcstok( buffer, g_strArgToken ); if( bSwitch ){ _tcstok( NULL, g_strArgToken ); _tcstok( NULL, g_strArgToken ); strHelp = _tcstok( NULL, g_strArgToken ); } nOut = nStart; for(j=nStart;j 0 && strHelp != NULL && _tcslen( strHelp ) ){ LPTSTR str = strHelp; ULONG nChar = 0; ULONG nPrint = 0; BOOL bCanBreak; ULONG nVisualLength, nActualLength; LPTSTR strNewLine; LPTSTR strFailCheck = NULL; while( *str != _T('\0') ){ nChar++; switch( *str ){ case _T('\t'): case _T(' '): *str = _T('\0'); } str++; } str = strHelp; nMax -= (nMax%2); while( nPrint < nChar ){ varg_strlen( str, &nVisualLength, &nActualLength, &bCanBreak ); strNewLine = _tcsstr( str, _T("\n") ); if( ((SHORT)(nVisualLength+nOut) > (nMax-1)) || (NULL != strNewLine) ){ if( NULL != strNewLine ){ *strNewLine = _T('\0'); nPrint += _tcslen( str ); varg_printf( g_normal, str ); strNewLine++; str = strNewLine; }else if(bCanBreak){ TCHAR cSaveChar; ULONG nBreak = (ULONG)ceil(((double)(nMax - nOut))/2.0); if( nBreak < nActualLength ){ cSaveChar = str[nBreak]; str[nBreak] = _T('\0'); nPrint += nBreak; varg_printf( g_normal, str ); str[nBreak] = cSaveChar; str = str + nBreak; }else if( nBreak == nActualLength ){ nPrint += nBreak; varg_printf( g_normal, str ); str = str + nBreak; continue; } } if( str == strFailCheck ){ varg_printf( g_normal, str ); str += _tcslen(str)+1; nPrint++; }else{ varg_printf( g_normal, _T("\n") ); for(j=0,nOut=0;j0 ){ dw = GetFileVersionInfoSize( strProgram, &dw ); if( dw > 0 ){ pVersionInfo = (BYTE*)VARG_ALLOC(dw); if( NULL != pVersionInfo ){ if(GetFileVersionInfo( strProgram, 0, dw, pVersionInfo )){ LPDWORD lptr = NULL; VerQueryValue( pVersionInfo, _T("\\VarFileInfo\\Translation"), (void**)&lptr, (UINT*)&dw ); if( lptr != NULL ){ _stprintf( buffer, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD(*lptr), HIWORD(*lptr), _T("ProductVersion") ); VerQueryValue( pVersionInfo, buffer, (void**)&pVersion, (UINT*)&dw ); _stprintf( buffer, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD(*lptr), HIWORD(*lptr), _T("OriginalFilename") ); VerQueryValue( pVersionInfo, buffer, (void**)&pProduct, (UINT*)&dw ); _stprintf( buffer, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD(*lptr), HIWORD(*lptr), _T("LegalCopyright") ); VerQueryValue( pVersionInfo, buffer, (void**)&pCopyRight, (UINT*)&dw ); } if( pProduct != NULL && pVersion != NULL && pCopyRight != NULL ){ varg_printf( g_normal, _T("\n%1!s! %2!s! (%3!s!)\n%4!s!\n\n"), strMicrosoft, pProduct, pVersion, pCopyRight ); } } VARG_FREE( pVersionInfo ); } } } } void DisplayHelpEx( LONG id ) { TCHAR buffer[8]; DWORD dwSize = 8; dwSize = LoadString( NULL, id, buffer, dwSize ); if( dwSize > 0 ){ PrintMessage( g_normal, id ); } } void DisplayCommandLineHelp() { int i,j; int nOut; BOOL bOpt; BOOL bVerbs = FALSE; int nVerbs = 0; int nCommands = 0; BOOL bRequired = FALSE; int nConditional = 0; int nDefinedConditional = 0; BOOL bFirst = TRUE; BOOL bDisplayAll = FALSE; DWORD dwVerbMask = 0; UCHAR excl1 = 0; LPTSTR strNegateHelp = NULL; for( i=0; Commands[i].fType != VARG_TYPE_LAST;i++){ if( (Commands[i].dwSet & VARG_CONDITION) && !(Commands[i].fFlag & VARG_FLAG_VERB) ){ nConditional++; if( Commands[i].bDefined ){ nDefinedConditional++; } } if( Commands[i].fFlag & VARG_FLAG_VERB ){ bVerbs = TRUE; } if( Commands[i].bDefined ){ if( Commands[i].fFlag & VARG_FLAG_VERB || Commands[i].fFlag & VARG_FLAG_ADVERB){ nVerbs++; dwVerbMask |= (Commands[i].dwVerb & 0x0000FFFF); if( Commands[i].dwSet != 0 ){ excl1 = (UCHAR)(((Commands[i].dwSet & VARG_GROUPEXCL) >> 24) & 0x0F); } }else{ if( Commands[i].fType != VARG_TYPE_HELP && Commands[i].fType != VARG_TYPE_DEBUG ){ nCommands++; } } } } if( nCommands == 0 && nVerbs == 0 ){ bDisplayAll = TRUE; } DisplayVersionInfo(); if( bDisplayAll ){ if( ERROR_SUCCESS == PrintHelpString( IDS_PROGRAM_DESCRIPTION, 0, 0, g_X, FALSE ) ){ varg_printf( g_normal, _T("\n") ); } } // Usage PrintMessage( g_normal, IDS_MESSAGE_USAGE ); nOut = varg_printf( g_normal, _T("%1!s! "), g_strProg ); if( bVerbs ){ LONG nDispVerbs = 0; if( !bDisplayAll ){ for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){ if( Commands[i].fFlag & VARG_FLAG_VERB && Commands[i].bDefined ){ nOut += varg_printf( g_normal, _T("%1!s! "), Commands[i].strArg1 ); nDispVerbs++; } } } if( bDisplayAll || !nDispVerbs ){ nOut += PrintMessage( g_normal, IDS_MESSAGE_VERB ); } } if( nConditional > 1 && nDefinedConditional == 0 ){ nOut += varg_printf( g_normal, _T("{ ") ); } for( j=0;j<2;j++){ for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){ if( j==0 ){ // show conditional switches if( Commands[i].fFlag & VARG_FLAG_HIDDEN || Commands[i].fFlag & VARG_FLAG_VERB || !(Commands[i].dwSet & VARG_CONDITION) ){ continue; } if( nDefinedConditional > 0 && !Commands[i].bDefined ){ continue; } }else{ // show required switches if( Commands[i].fFlag & VARG_FLAG_HIDDEN || Commands[i].fFlag & VARG_FLAG_VERB || Commands[i].dwSet & VARG_CONDITION || Commands[i].fFlag & VARG_FLAG_OPTIONAL ){ continue; } } if( (!bFirst) && nConditional && nDefinedConditional == 0 ){ nOut += varg_printf( g_normal, _T("| ") ); } bFirst = FALSE; if( Commands[i].fFlag & VARG_FLAG_NOFLAG ){ nOut += varg_printf( g_normal, _T("%1!s! "), Commands[i].strParam ); }else{ nOut += varg_printf( g_normal, _T("%1!c!%2!s!%3!s!%4!s!%5!s! "), Commands[i].fFlag&VARG_FLAG_VERB ? g_strVerbPrefix[0] : g_strPrefix[0], Commands[i].fFlag&VARG_FLAG_NEGATE ? _T("[-]"):_T(""), Commands[i].strArg2, ArgExpected( &Commands[i] ) ? _T(" "): _T(""), Commands[i].strParam ); } if( nOut > (g_X - 15) ){ nOut = 0; varg_printf( g_normal, _T("\n") ); while( nOut++ < HELP_INDENT){ varg_printf( g_normal, _T(" ") ); } } } if( j == 0 && (nConditional>1) && nDefinedConditional == 0 ){ varg_printf( g_normal, _T("} ") ); } } PrintMessage( g_normal, IDS_MESSAGE_LINEOPT ); // Verbs if( bVerbs ){ bFirst = TRUE; for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){ if( Commands[i].fFlag & VARG_FLAG_HIDDEN && !(Commands[i].bDefined) ){ continue; } if( !(Commands[i].fFlag & VARG_FLAG_VERB ) ){ continue; } if( !bDisplayAll && !Commands[i].bDefined ){ continue; } if( bFirst ){ PrintMessage( g_normal, IDS_MESSAGE_VERBS ); bFirst = FALSE; } bOpt = ( Commands[i].strArg2 != NULL && _tcslen( Commands[i].strArg2 ) ); nOut = varg_printf( COLORIZE(i), _T(" %1!s!%2!s! %3!s! "), g_strVerbPrefix, (LPTSTR)(bOpt ? Commands[i].strArg2 : Commands[i].strArg1), Commands[i].strParam ); if( nOut > HELP_INDENT ){ nOut += varg_printf( g_normal, _T(" ") ); } PrintHelpString( Commands[i].idParam, nOut, HELP_INDENT, g_X, TRUE ); } if( !bFirst ){ varg_printf( g_normal, _T("\n") ); } } // Options for(j=0;j<2;j++){ bFirst = TRUE; for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){ if( j==0 ){ if( !(Commands[i].fFlag & VARG_FLAG_NOFLAG) || Commands[i].fFlag & (VARG_FLAG_VERB|VARG_FLAG_ADVERB) ){ continue; } }else{ if( Commands[i].fFlag & VARG_FLAG_NOFLAG || Commands[i].fFlag & (VARG_FLAG_VERB|VARG_FLAG_ADVERB) ){ continue; } } if( ! bDisplayAll && (Commands[i].fType == VARG_TYPE_HELP) ){ continue; } if( Commands[i].fFlag & VARG_FLAG_HIDDEN && !(Commands[i].bDefined) ){ continue; } if( bDisplayAll || Commands[i].bDefined || (((Commands[i].dwVerb & 0x0000FFFF)& dwVerbMask) && nCommands < 1 ) ){ UCHAR excl2 = (UCHAR)((((Commands[i].dwSet & VARG_GROUPEXCL) >> 24) & 0xF0) >> 4 ); if( excl2 & excl1 ){ continue; } if( bFirst ){ switch( j ){ case 0: PrintMessage( g_normal, IDS_MESSAGE_PARAMETERS ); bRequired = TRUE; break; case 1: PrintMessage( g_normal, IDS_MESSAGE_OPTIONS, bRequired ? _T("\n") : _T("") ); break; } bFirst = FALSE; } bOpt = ( Commands[i].strArg2 != NULL && _tcslen( Commands[i].strArg2 ) ); if( Commands[i].fFlag & VARG_FLAG_NOFLAG ){ nOut = varg_printf( COLORIZE(i), _T(" %1!s! "), Commands[i].strParam ); }else{ nOut = varg_printf( COLORIZE(i), _T(" %1!c!%2!s!%3!s! %4!s! "), g_strPrefix[0], Commands[i].fFlag & VARG_FLAG_NEGATE ? _T("[-]") : _T(""), bOpt ? Commands[i].strArg2 : Commands[i].strArg1, Commands[i].strParam ); } if( nOut > HELP_INDENT ){ nOut += varg_printf( g_normal, _T(" ") ); } if( Commands[i].fFlag & VARG_FLAG_NEGATE && NULL == strNegateHelp ){ strNegateHelp = bOpt ? Commands[i].strArg2 : Commands[i].strArg1; } PrintHelpString( Commands[i].idParam, nOut, HELP_INDENT, g_X, TRUE ); if( !bDisplayAll ){ if( Commands[i].fType == VARG_TYPE_INI ){ DisplayIniInfo(); } } } } } if( NULL != strNegateHelp ){ PrintMessage( g_normal, IDS_MESSAGE_NEGATE, strNegateHelp, strNegateHelp ); } // Notes if( bDisplayAll ){ PrintMessage( g_normal, IDS_MESSAGE_HELPTEXT ); } // Examples bFirst = TRUE; for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){ if( bDisplayAll || Commands[i].bDefined ){ if( (bDisplayAll && bVerbs ) && !(Commands[i].fFlag & (VARG_FLAG_VERB|VARG_FLAG_ADVERB) ) ){ continue; } if( Commands[i].fFlag & VARG_FLAG_EXHELP ){ if( bFirst ){ PrintMessage( g_normal, IDS_MESSAGE_EXAMPLES ); bFirst = FALSE; } PrintHelpString( Commands[i].idExHelp, 0, 2, 80, FALSE ); } } } FreeCmd(); exit(0); } void PrintParam( int idPrompt, int cmd, BOOL bEOL ) { BOOL bUseArg1; TCHAR buffer[MAXSTR]; bUseArg1 = (Commands[cmd].fFlag & VARG_FLAG_VERB) || (Commands[cmd].fFlag & VARG_FLAG_ADVERB) || ( IsEmpty( Commands[cmd].strArg2 ) ); if( 0 != idPrompt ){ LoadString( NULL, idPrompt, buffer, MAXSTR ); varg_printf( g_debug, buffer ); } if( Commands[cmd].fFlag & VARG_FLAG_NOFLAG ){ varg_printf( g_debug, _T("%1!s! "), Commands[cmd].strParam ); }else{ if( !(Commands[cmd].fFlag & (VARG_FLAG_VERB|VARG_FLAG_ADVERB)) ){ varg_printf( g_debug, _T("%1!c!"), g_strPrefix[0] ); }else if( !IsEmpty( g_strVerbPrefix ) ){ varg_printf( g_debug, _T("%1!c!"), g_strVerbPrefix[0] ); } if( ArgExpected( &Commands[cmd] ) ){ varg_printf( g_debug, _T("%1!s!%2!s! %3!s! "), Commands[cmd].fFlag&VARG_FLAG_NEGATE ? _T("[-]") : _T(""), bUseArg1 ? Commands[cmd].strArg1 : Commands[cmd].strArg2, Commands[cmd].strParam ); }else{ varg_printf( g_debug, _T("%1!s!%2!s! "), Commands[cmd].fFlag&VARG_FLAG_NEGATE ? _T("[-]") : _T(""), bUseArg1 ? Commands[cmd].strArg1 : Commands[cmd].strArg2 ); } } if( bEOL ){ varg_printf( g_debug, _T("\n") ); } } HRESULT ValidateCommands() { int i,j; HRESULT hr = ERROR_SUCCESS; BOOL bVerbs = FALSE; BOOL nDefinedVerbs = 0; for(i=0; Commands[i+1].fType != VARG_TYPE_LAST;i++){ UCHAR cond1 = (UCHAR)((Commands[i].dwSet & VARG_CONDITION) >> 16); if( cond1 ){ BOOL bFound = FALSE; for(j=0; Commands[j].fType != VARG_TYPE_LAST;j++){ UCHAR cond2 = (UCHAR)((Commands[j].dwSet & VARG_CONDITION) >> 16); if( (cond1 & cond2) && Commands[j].bDefined ){ bFound = TRUE; break; } } if( ! bFound ){ for(j=0; Commands[j].fType != VARG_TYPE_LAST;j++){ UCHAR cond2 = (UCHAR)((Commands[j].dwSet & VARG_CONDITION) >> 16); if( (cond1 & cond2) && !(Commands[j].fFlag & VARG_FLAG_VERB)){ Commands[j].fFlag |= VARG_FLAG_REQUIRED; } } } } if( Commands[i].bDefined && (Commands[i].fFlag & VARG_FLAG_REQ_ADV) ){ BOOL bFound = FALSE; WORD wVerb1 = (WORD)( Commands[i].dwVerb & 0x0000FFFF ); for(j=0; Commands[j].fType != VARG_TYPE_LAST;j++){ WORD wVerb2 = (WORD)(Commands[j].dwVerb & 0x0000FFFF); if( Commands[j].bDefined && (wVerb1 == wVerb2) && (Commands[j].fFlag & VARG_FLAG_ADVERB) ){ bFound = TRUE; break; } } if( ! bFound ){ for(j=0; Commands[j].fType != VARG_TYPE_LAST;j++){ WORD wVerb2 = (WORD)(Commands[j].dwVerb & 0x0000FFFF); if( wVerb1 == wVerb2 && Commands[j].fFlag & VARG_FLAG_ADVERB ){ Commands[j].fFlag |= VARG_FLAG_REQUIRED; } } } } if( Commands[i].bDefined && Commands[i].dwSet ){ UCHAR excl1 = (UCHAR)((Commands[i].dwSet & VARG_EXCLUSIVE)); UCHAR incl1 = (UCHAR)((Commands[i].dwSet & VARG_INCLUSIVE) >> 8); UCHAR grp_ex1 = (UCHAR)(((Commands[i].dwSet & VARG_GROUPEXCL) >> 24) & 0x0F); for(j=i+1; Commands[j].fType != VARG_TYPE_LAST;j++){ if( Commands[j].dwSet ){ UCHAR excl2 = (UCHAR)((Commands[j].dwSet & VARG_EXCLUSIVE)); UCHAR incl2 = (UCHAR)((Commands[j].dwSet & VARG_INCLUSIVE) >> 8); UCHAR grp_in2 = (UCHAR)((((Commands[j].dwSet & VARG_GROUPEXCL) >> 24) & 0xF0) >> 4 ); if( excl1 && (excl1 & excl2) && Commands[j].bDefined ){ PrintParam( 0, i, FALSE ); PrintParam( IDS_MESSAGE_AND, j, FALSE ); PrintMessage( g_debug, IDS_MESSAGE_EXCLUSIVE ); hr = ERROR_BAD_ARGUMENTS; } if( incl1 && (incl1 & incl2) && !Commands[j].bDefined){ PrintParam( 0, i, FALSE ); PrintParam( IDS_MESSAGE_REQUIRES, j, FALSE ); varg_printf( g_debug, _T("\n") ); hr = ERROR_BAD_ARGUMENTS; } if( grp_ex1 && (grp_in2 & grp_ex1) && Commands[j].bDefined ){ PrintParam( 0, i, FALSE ); PrintParam( IDS_MESSAGE_AND, j, FALSE ); PrintMessage( g_debug, IDS_MESSAGE_EXCLUSIVE ); hr = ERROR_BAD_ARGUMENTS; } } } } if( Commands[i].bDefined && (Commands[i].fFlag & VARG_FLAG_LITERAL) ){ LPTSTR strValues; LPTSTR strCheck; LPTSTR strArg; BOOL bFound = FALSE; switch( Commands[i].fType ){ case VARG_TYPE_MSZ: case VARG_TYPE_STR: strArg = Commands[i].strValue; while( strArg != NULL && !(Commands[i].fFlag & VARG_FLAG_BADSYNTAX) ){ ASSIGN_STRING( strValues, Commands[i].strParam ); if( NULL != strValues ){ strCheck = _tcstok( strValues, _T("<>[]|") ); while( !bFound && strCheck != NULL ){ if( _tcsicmp( strCheck, strArg ) == 0 ){ bFound = TRUE; break; } strCheck = _tcstok( NULL, _T("<>[]|") ); } } VARG_FREE( strValues ); if( !bFound ){ Commands[i].fFlag |= VARG_FLAG_BADSYNTAX; hr = ERROR_BAD_ARGUMENTS; } if( Commands[i].fType == VARG_TYPE_MSZ ){ strArg += _tcslen( strArg ) + 1; bFound = FALSE; if( *strArg == _T('\0') ){ strArg = NULL; } }else{ strArg = NULL; } } break; default: hr = ERROR_INVALID_PARAMETER; } } } for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){ if( Commands[i].fFlag & VARG_FLAG_VERB ){ if( Commands[i].bDefined ){ nDefinedVerbs++; } bVerbs = TRUE; } if( (Commands[i].fFlag & VARG_FLAG_REQUIRED) && !Commands[i].bDefined){ PrintParam( IDS_MESSAGE_MISSING, i, TRUE ); hr = ERROR_BAD_ARGUMENTS; } if( Commands[i].fFlag & VARG_FLAG_BADSYNTAX ){ PrintParam( IDS_MESSAGE_BADSYNTAX, i, TRUE ); hr = ERROR_BAD_ARGUMENTS; } } if( bVerbs && nDefinedVerbs == 0 ){ PrintMessage( g_debug, IDS_MESSAGE_NOVERB ); hr = ERROR_BAD_ARGUMENTS; } return hr; } /*****************************************************************************\ Utility Functions \*****************************************************************************/ HRESULT GetUserInput( LPTSTR strBuffer, ULONG lSize, BOOL bEcho ) { TCHAR c; UCHAR a; ULONG i = 0; BOOL bDone = FALSE; HANDLE hInput = NULL; DWORD dwSize; DWORD dwMode; hInput = GetStdHandle( STD_INPUT_HANDLE ); GetConsoleMode( hInput, &dwMode); SetConsoleMode( hInput, (~(ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT)) & dwMode); while( !bDone ){ if( (GetFileType(hInput) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR ){ BOOL bRead = ReadFile( hInput, &a, 1, &dwSize, NULL ); if( 0 == dwSize || !bRead ){ c = _T('\n'); }else{ MultiByteToChar( a, c ); if( _T('\r') == c ){ bRead = ReadFile( hInput, &a, 1, &dwSize, NULL ); } } }else{ ReadConsole( hInput, &c, 1, &dwSize, NULL ); } switch( c ){ case 8: if( i > 0 ){ strBuffer[i--] = _T('\0'); if(bEcho){ _tprintf( _T("%c %c"), c, c ); } } break; case 3: FreeCmd(); SetConsoleMode(hInput, dwMode); exit(0); case _T('\r'): case _T('\n'): bDone = TRUE; varg_printf( g_normal, _T("\n") ); break; default: if( i < (lSize-1) ){ strBuffer[i++] = (TCHAR)c; if( bEcho ){ varg_printf( g_normal, _T("%1!c!"), c ); } } } } SetConsoleMode(hInput, dwMode); if( i > lSize ){ return ERROR_INSUFFICIENT_BUFFER; }else{ strBuffer[i] = _T('\0'); } return ERROR_SUCCESS; } HRESULT CheckFile( LPTSTR strFile, DWORD dwFlags ) { HRESULT hr = ERROR_SUCCESS; HANDLE hFile; hFile = CreateFile( strFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); if( hFile == INVALID_HANDLE_VALUE){ hr = GetLastError(); } CloseHandle(hFile); if( dwFlags & VARG_CF_OVERWRITE ){ if( ERROR_FILE_NOT_FOUND == hr ){ hr = ERROR_SUCCESS; }else if( ERROR_PATH_NOT_FOUND == hr){ return hr; }else if( dwFlags & VARG_CF_PROMPT ){ TCHAR buffer[MAXSTR] = _T(""); TCHAR yes[16]; PrintMessage( g_normal, IDS_CF_OVERWRITE, strFile ); GetUserInput( buffer, MAXSTR, TRUE ); LoadString( NULL, IDS_ARG_YES, yes, 16 ); if( FindString( buffer, yes ) ){ hr = ERROR_SUCCESS; }else{ hr = ERROR_ALREADY_EXISTS; } } } return hr; } HRESULT ExpandFiles( LPTSTR* mszFiles, BOOL bMultiple ) { LPTSTR strFiles = NULL; LPTSTR strExpand; TCHAR buffer[_MAX_PATH]; TCHAR drive[_MAX_DRIVE]; TCHAR dir[_MAX_DIR]; TCHAR fname[_MAX_FNAME]; TCHAR ext[_MAX_EXT]; HANDLE hFile = NULL; strExpand = *mszFiles; while( strExpand != NULL && *strExpand != _T('\0')){ WIN32_FIND_DATA file; _tsplitpath( strExpand, drive, dir, fname, ext ); hFile = FindFirstFile( strExpand, &file ); if( hFile != INVALID_HANDLE_VALUE){ do{ if( !( !_tcscmp(file.cFileName, _T(".") ) || !_tcscmp(file.cFileName, _T("..")) ) ){ _tmakepath( buffer, drive, dir, file.cFileName, _T("") ); AddStringToMsz( &strFiles, buffer ); } }while( FindNextFile( hFile, &file ) == TRUE ); FindClose( hFile ); }else{ return GetLastError(); } if( bMultiple ){ strExpand += _tcslen( strExpand )+1; }else{ break; } } if( NULL != strFiles ){ VARG_FREE( *mszFiles ); *mszFiles = strFiles; } return ERROR_SUCCESS; } BOOL FindString( LPTSTR strBuffer, LPTSTR strMatch ) { BOOL bReturn = FALSE; LPTSTR buffer; LPTSTR match; ASSIGN_STRING( buffer, strBuffer ); ASSIGN_STRING( match, strMatch ); if( buffer != NULL && match != NULL ){ _tcslwr( buffer ); _tcslwr( match ); if( _tcsstr( buffer, match ) ){ bReturn = TRUE; } } VARG_FREE( match ); VARG_FREE( buffer ); return bReturn; } HRESULT ParseTime( LPTSTR strTime, SYSTEMTIME* pstTime, BOOL bDate ) { TCHAR buffer[MAXSTR]; TCHAR PM[9] = _T("pm"); TCHAR AM[9] = _T("am"); TCHAR strDateSep[8] = _T("/"); TCHAR strTimeSep[8] = _T(":"); ULONG l; LPTSTR str, str2; int nDateFormat = 0; BOOL bValid = TRUE; FILETIME ft; HRESULT hr = ERROR_SUCCESS; ZeroMemory( pstTime, sizeof( SYSTEMTIME ) ); if( GetLocaleInfo( VARG_LOCALE, LOCALE_IDATE, buffer, MAXSTR ) > 0 ){ nDateFormat = _ttoi( buffer ); } if( GetLocaleInfo( VARG_LOCALE, LOCALE_S1159, buffer, 9 ) > 0 ){ _tcsncpy( AM, buffer, 9 ); } if( GetLocaleInfo( VARG_LOCALE, LOCALE_S2359, buffer, 9 ) > 0 ){ _tcsncpy( PM, buffer, 9 ); } if( GetLocaleInfo( VARG_LOCALE, LOCALE_STIME, buffer, 8 ) > 0 ){ _tcsncpy( strTimeSep, buffer, 8 ); } if( GetLocaleInfo( VARG_LOCALE, LOCALE_SDATE, buffer, 8 ) > 0 ){ _tcsncpy( strDateSep, buffer, 8 ); } _tcsncpy( buffer, strTime, MAXSTR ); buffer[MAXSTR-1] = _T('\0'); str = _tcstok( buffer, _T(" \n\t") ); str2 = _tcstok( NULL, _T(" \n\t") ); while( str ){ if( _tcsstr( str, strDateSep ) ){ LPTSTR strMonth = NULL; LPTSTR strDay = NULL; LPTSTR strYear = NULL; switch( nDateFormat ){ case 0: strMonth = _tcstok( str, strDateSep ); strDay = _tcstok( NULL, strDateSep ); strYear = _tcstok( NULL, strDateSep ); break; case 1: strDay = _tcstok( NULL, strDateSep ); strMonth = _tcstok( str, strDateSep ); strYear = _tcstok( NULL, strDateSep ); break; case 2: strYear = _tcstok( NULL, strDateSep ); strMonth = _tcstok( str, strDateSep ); strDay = _tcstok( NULL, strDateSep ); break; } if( NULL != strMonth ){ hr = ReadLong( strMonth, &l, MAXWORD ); if( ERROR_SUCCESS == hr ){ pstTime->wMonth = (WORD)l; } } if( NULL != strDay ){ hr = ReadLong( strDay, &l, MAXWORD ); if( ERROR_SUCCESS == hr ){ pstTime->wDay = (WORD)l; } } if( NULL != strYear ){ hr = ReadLong( strYear, &l, MAXWORD ); if( ERROR_SUCCESS == hr ){ pstTime->wYear = (WORD)l; } } }else{ LPTSTR tok1 = NULL; LPTSTR tok2 = NULL; LPTSTR tok3 = NULL; UINT nTok = 0; BOOL bPM = FALSE; BOOL bAM = FALSE; LPTSTR szZero = _T("0"); bPM = FindString( str, PM ); bAM = FindString( str, AM ); tok1 = _tcstok( str, strTimeSep ); if( NULL != tok1 ){ nTok++; tok2 = _tcstok( NULL, strTimeSep ); }else{ tok1 = szZero; } if( NULL != tok2 ){ nTok++; tok3 = _tcstok( NULL, strTimeSep ); }else{ tok2 = szZero; } if( NULL != tok3 ){ nTok++; }else{ tok3 = szZero; } if( bDate ){ nTok = 3; } switch( nTok ){ case 1: hr = ReadLong( tok1, &l, MAXWORD ); if( ERROR_SUCCESS == hr ){ pstTime->wSecond = (WORD)l; } break; case 2: hr = ReadLong( tok1, &l, MAXWORD ); if( ERROR_SUCCESS == hr ){ pstTime->wMinute = (WORD)l; hr = ReadLong( tok2, &l, MAXWORD ); if( ERROR_SUCCESS == hr ){ pstTime->wSecond = (WORD)l; } } break; case 3: hr = ReadLong( tok1, &l, MAXWORD ); if( ERROR_SUCCESS == hr ){ pstTime->wHour = (WORD)l; hr = ReadLong( tok2, &l, MAXWORD ); if( ERROR_SUCCESS == hr ){ pstTime->wMinute = (WORD)l; hr = ReadLong( tok3, &l, MAXWORD ); if( ERROR_SUCCESS == hr ){ pstTime->wSecond = (WORD)l; } } } break; } if( ERROR_SUCCESS == hr ){ if( bPM ){ if( pstTime->wHour < 12 ){ pstTime->wHour += 12; }else if( pstTime->wHour > 12 ){ PrintMessage( g_debug, IDS_MESSAGE_BADTIME, PM ); } } if( bAM ){ if( pstTime->wHour > 12 ){ PrintMessage( g_debug, IDS_MESSAGE_BADTIME, AM ); } } } } str = str2; str2 = NULL; } if( bDate && ERROR_SUCCESS == hr ){ bValid = SystemTimeToFileTime( pstTime, &ft ); if( !bValid ){ hr = GetLastError(); } } return hr; } void PrintError( HRESULT hr ) { PrintErrorEx( hr, NULL ); } void PrintErrorEx( HRESULT hr, LPTSTR strModule, ... ) { LPVOID lpMsgBuf = NULL; HINSTANCE hModule = NULL; DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER; va_list args; va_start( args, strModule ); if(hr == 0){ hr = GetLastError(); } if( strModule != NULL ){ hModule = LoadLibrary( strModule ); } if ( NULL != hModule ) { dwFlags |= FORMAT_MESSAGE_FROM_HMODULE; }else{ dwFlags |= FORMAT_MESSAGE_FROM_SYSTEM; } FormatMessage( dwFlags, hModule, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR)&lpMsgBuf, MAXSTR, &args ); if ( NULL != hModule ) { FreeLibrary( hModule ); } if( g_nDebug >= 0 ){ PrintMessage( g_debug, IDS_MESSAGE_ERROR_DBG, hr ); }else{ PrintMessage( g_debug, IDS_MESSAGE_ERROR ); } if( NULL == lpMsgBuf ){ PrintMessage( g_debug, IDS_MESSAGE_UNKNOWN ); }else{ varg_printf( g_debug, _T("%1!s!\n"), (LPTSTR)lpMsgBuf ); } LocalFree( lpMsgBuf ); } int PrintDateEx( SHORT color, SYSTEMTIME* st ) { TCHAR buffer[MAXSTR]; TCHAR strDateSep[8] = _T("/"); TCHAR strTimeSep[8] = _T(":"); int nDateFormat = 0; int nOut = 0; if( GetLocaleInfo( VARG_LOCALE, LOCALE_IDATE, buffer, MAXSTR ) > 0 ){ nDateFormat = _ttoi( buffer ); } if( GetLocaleInfo( VARG_LOCALE, LOCALE_STIME, buffer, 8 ) > 0 ){ _tcscpy( strTimeSep, buffer ); } if( GetLocaleInfo( VARG_LOCALE, LOCALE_SDATE, buffer, 8 ) > 0 ){ _tcscpy( strDateSep, buffer ); } if( st->wMonth ){ switch( nDateFormat ){ case 0: nOut = varg_printf( color, _T("%1!d!%2!s!%3!d!%4!s!%5!d! "), st->wMonth, strDateSep, st->wDay, strDateSep, st->wYear ); break; case 1: nOut = varg_printf( color, _T("%1!d!%2!s!%3!d!%4!s!%5!d! "), st->wDay, strDateSep, st->wMonth, strDateSep, st->wYear ); break; case 2: nOut = varg_printf( color, _T("%1!d!%2!s!%3!d!%4!s!%5!d! "), st->wYear, strDateSep, st->wMonth, strDateSep, st->wDay ); break; } } nOut += varg_printf( color, _T("%1!d!%2!s!%3!02d!%4!s!%5!02d!"), st->wHour, strTimeSep, st->wMinute, strTimeSep, st->wSecond ); return nOut; } void PrintDate( SYSTEMTIME* st ) { PrintDateEx( g_normal, st ); } /*****************************************************************************\ VSetThreadUILanguage This routine sets the thread UI language based on the console codepage. 9-29-00 WeiWu Created. 6-19-01 coreym Adapted from Base\Win32\Winnls so that it works in W2K \*****************************************************************************/ LANGID WINAPI VSetThreadUILanguage(WORD wReserved) { // // Cache system locale and CP info // static LCID s_lidSystem = 0; static UINT s_uiSysCp = 0; static UINT s_uiSysOEMCp = 0; ULONG uiUserUICp = 0; ULONG uiUserUIOEMCp = 0; TCHAR szData[16]; LANGID lidUserUI = GetUserDefaultUILanguage(); LCID lcidThreadOld = GetThreadLocale(); // // Set default thread locale to EN-US // // This allow us to fall back to English UI to avoid trashed characters // when console doesn't meet the criteria of rendering native UI. // LCID lcidThread = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT); UINT uiConsoleCp = GetConsoleOutputCP(); // // Get cached system locale and CP info. // if (!s_uiSysCp) { LCID lcidSystem = GetSystemDefaultLCID(); if (lcidSystem) { // // Get ANSI CP // GetLocaleInfo(lcidSystem, LOCALE_IDEFAULTANSICODEPAGE, szData, sizeof(szData)/sizeof(TCHAR)); uiUserUICp = _ttol(szData); // // Get OEM CP // GetLocaleInfo(lcidSystem, LOCALE_IDEFAULTCODEPAGE, szData, sizeof(szData)/sizeof(TCHAR)); s_uiSysOEMCp = _ttol(szData); // // Cache system primary langauge // s_lidSystem = PRIMARYLANGID(LANGIDFROMLCID(lcidSystem)); } } // // Don't cache user UI language and CP info, UI language can be changed without system reboot. // if (lidUserUI) { GetLocaleInfo(MAKELCID(lidUserUI,SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, szData, sizeof(szData)/sizeof(TCHAR)); uiUserUICp = _ttol(szData); GetLocaleInfo(MAKELCID(lidUserUI,SORT_DEFAULT), LOCALE_IDEFAULTCODEPAGE, szData, sizeof(szData)/sizeof(TCHAR)); uiUserUIOEMCp = _ttol(szData); } // // Complex scripts cannot be rendered in the console, so we // force the English (US) resource. // if (uiConsoleCp && s_lidSystem != LANG_ARABIC && s_lidSystem != LANG_HEBREW && s_lidSystem != LANG_VIETNAMESE && s_lidSystem != LANG_THAI) { // // Use UI language for console only when console CP, system CP and UI language CP match. // if ((uiConsoleCp == s_uiSysCp || uiConsoleCp == s_uiSysOEMCp) && (uiConsoleCp == uiUserUICp || uiConsoleCp == uiUserUIOEMCp)) { lcidThread = MAKELCID(lidUserUI, SORT_DEFAULT); } } // // Set the thread locale if it's different from the currently set // thread locale. // if ((lcidThread != lcidThreadOld) && (!SetThreadLocale(lcidThread))) { lcidThread = lcidThreadOld; } // // Return the thread locale that was set. // return (LANGIDFROMLCID(lcidThread)); }