Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2210 lines
68 KiB

  1. /*****************************************************************************\
  2. Author: Corey Morgan (coreym)
  3. Copyright (c) Microsoft Corporation. All rights reserved.
  4. \*****************************************************************************/
  5. #include <windows.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <math.h>
  9. #include <conio.h>
  10. #include <tchar.h>
  11. #include <mbctype.h>
  12. #include "varg.h"
  13. LPTSTR g_strProg;
  14. HANDLE g_hConsole;
  15. WORD g_debug;
  16. WORD g_light;
  17. WORD g_dark;
  18. WORD g_normal;
  19. LPTSTR g_strVerbPrefix;
  20. LPTSTR g_strPrefix;
  21. LPTSTR g_strArgToken;
  22. SHORT g_X;
  23. SHORT g_Y;
  24. LONG g_nDebug = -1;
  25. LCID g_LCID = 0;
  26. #define COLORIZE( c ) (WORD)((Commands[c].fFlag & (VARG_FLAG_DARKEN|VARG_FLAG_HIDDEN)) ? g_dark : g_normal)
  27. #define HELP_INDENT 32
  28. #define VARG_LOCALE ( g_LCID ? g_LCID : LOCALE_USER_DEFAULT )
  29. BOOL varg_strlen( LPTSTR str, ULONG* pVisualSize, ULONG* pAcutalSize, BOOL* bCanBreak );
  30. void PrintParam( int idPrompt, int cmd, BOOL bEOL );
  31. BOOL FindString( LPTSTR strBuffer, LPTSTR strMatch );
  32. int varg_vprintf( WORD color, LPCTSTR mask, va_list args )
  33. {
  34. DWORD dwPrint;
  35. HANDLE hOut;
  36. hOut = GetStdHandle(STD_OUTPUT_HANDLE);
  37. SetConsoleTextAttribute( g_hConsole, color );
  38. __try {
  39. LPTSTR buffer = NULL;
  40. dwPrint = FormatMessage(
  41. FORMAT_MESSAGE_ALLOCATE_BUFFER|
  42. FORMAT_MESSAGE_FROM_STRING,
  43. mask,
  44. 0, 0,
  45. (LPTSTR)&buffer,
  46. 4096,
  47. &args
  48. );
  49. if( NULL != buffer ){
  50. BOOL bBreak;
  51. ULONG len,temp;
  52. if ((GetFileType(hOut) & ~FILE_TYPE_REMOTE) == FILE_TYPE_CHAR) {
  53. WriteConsole( hOut, buffer, dwPrint, &dwPrint, NULL );
  54. }else{
  55. LPSTR szAnsiBuffer = NULL;
  56. szAnsiBuffer = (LPSTR)VARG_ALLOC( (dwPrint+1) * sizeof(WCHAR) );
  57. if( NULL != szAnsiBuffer ){
  58. if( CharToOem( buffer, szAnsiBuffer ) ){
  59. WriteFile( hOut, szAnsiBuffer, strlen( szAnsiBuffer ), &temp, NULL );
  60. }
  61. }
  62. VARG_FREE( szAnsiBuffer );
  63. }
  64. if( varg_strlen( buffer, &len, &temp, &bBreak ) ){
  65. dwPrint = len;
  66. }
  67. LocalFree( buffer );
  68. }
  69. } __except (EXCEPTION_EXECUTE_HANDLER) {
  70. dwPrint = 0;
  71. }
  72. SetConsoleTextAttribute( g_hConsole, g_normal );
  73. return (int)dwPrint;
  74. }
  75. int varg_printf( WORD color, LPCTSTR mask, ... )
  76. {
  77. int nPrint;
  78. va_list args;
  79. va_start( args, mask );
  80. nPrint = varg_vprintf( color, mask, args );
  81. va_end( args );
  82. return nPrint;
  83. }
  84. _inline
  85. BOOL IsArg( LPTSTR str )
  86. {
  87. int i;
  88. if( str == NULL ){
  89. return FALSE;
  90. }
  91. for( i=0;i<g_strPrefix[i] != _T('\0');i++){
  92. if( str[0] == g_strPrefix[i] ){
  93. return TRUE;
  94. }
  95. }
  96. return FALSE;
  97. }
  98. _inline
  99. BOOL IsCmd( PVARG_RECORD arg, LPTSTR str, BOOL bIni )
  100. {
  101. BOOL bNegated = FALSE;
  102. if( !bIni ){
  103. if( IsArg(str) ){
  104. str++;
  105. }else{
  106. if( arg->fFlag & VARG_FLAG_NOFLAG ){
  107. if( arg->bDefined ){
  108. return FALSE;
  109. }else{
  110. return TRUE;
  111. }
  112. }
  113. if( !( (arg->fFlag & VARG_FLAG_VERB) || (arg->fFlag & VARG_FLAG_ADVERB)) ){
  114. return FALSE;
  115. }
  116. }
  117. }
  118. if( str[0] == _T('-') ){
  119. bNegated = TRUE;
  120. str++;
  121. }
  122. if( ( arg->strArg1 != NULL && !_tcsicmp( str, arg->strArg1 ) ) ||
  123. ( arg->strArg2 != NULL && !_tcsicmp( str, arg->strArg2 ) ) ){
  124. if( arg->fFlag & VARG_FLAG_NEGATE ){
  125. arg->bNegated = bNegated;
  126. }
  127. return TRUE;
  128. }
  129. return FALSE;
  130. }
  131. _inline
  132. BOOL ArgExpected( PVARG_RECORD arg )
  133. {
  134. switch(arg->fType){
  135. case VARG_TYPE_BOOL:
  136. case VARG_TYPE_HELP:
  137. return FALSE;
  138. }
  139. return TRUE;
  140. }
  141. _inline
  142. BOOL
  143. IsEmpty( LPTSTR str )
  144. {
  145. if( str == NULL ){
  146. return TRUE;
  147. }
  148. if( *str == _T('\0') ){
  149. return TRUE;
  150. }
  151. return FALSE;
  152. }
  153. void Chomp(LPTSTR pszLine)
  154. {
  155. size_t lLen;
  156. LPTSTR pszLineEnd;
  157. if( pszLine == NULL ){
  158. return;
  159. }
  160. lLen = _tcslen(pszLine);
  161. pszLineEnd = pszLine + lLen - 1;
  162. while( pszLineEnd >= pszLine &&
  163. (*pszLineEnd == _T(' ') ||
  164. *pszLineEnd == _T('\r') ||
  165. *pszLineEnd == _T('\n') ||
  166. *pszLineEnd == _T('\t')) ){
  167. pszLineEnd--;
  168. }
  169. pszLineEnd++;
  170. if (*pszLineEnd == _T(' ') || *pszLineEnd == _T('\n') || *pszLineEnd == _T('\t') ){
  171. *pszLineEnd = _T('\0');
  172. }
  173. }
  174. HRESULT
  175. ReadLong( LPTSTR strNumber, ULONG* pulNumber, ULONG nMax )
  176. {
  177. LPTSTR strBuffer = NULL;
  178. ULONG nValue;
  179. HRESULT hr = ERROR_INVALID_PARAMETER;
  180. if( NULL == strNumber ){
  181. *pulNumber = 0;
  182. hr = ERROR_SUCCESS;
  183. }else{
  184. ASSIGN_STRING( strBuffer, strNumber );
  185. if( NULL == strBuffer ){
  186. hr = ERROR_OUTOFMEMORY;
  187. }else{
  188. LPTSTR strEnd;
  189. LPTSTR strBegin;
  190. size_t count;
  191. nValue = (ULONG)_tcstod( strNumber, &strEnd );
  192. _stprintf( strBuffer, _T("%lu"), nValue );
  193. strBegin = strNumber;
  194. while( *strBegin == _T('0') && (strEnd - strBegin) > 1 ){ strBegin++; }
  195. count = (size_t)(strEnd - strBegin);
  196. if( (_tcsnicmp( strBuffer, strBegin, count ) == 0) ){
  197. if( nValue <= nMax ){
  198. *pulNumber = nValue;
  199. hr = ERROR_SUCCESS;
  200. }
  201. }
  202. }
  203. }
  204. VARG_FREE( strBuffer );
  205. return hr;
  206. }
  207. void SetUpColors()
  208. {
  209. CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
  210. HKEY hkey = NULL;
  211. HRESULT hr;
  212. DWORD dwColorize = 0;
  213. g_hConsole = GetStdHandle( STD_OUTPUT_HANDLE );
  214. GetConsoleScreenBufferInfo( g_hConsole, &ConsoleInfo );
  215. g_X = (SHORT)(ConsoleInfo.srWindow.Right - ConsoleInfo.srWindow.Left);
  216. g_Y = (SHORT)(ConsoleInfo.srWindow.Bottom - ConsoleInfo.srWindow.Top);
  217. hr = RegOpenKeyExW (
  218. HKEY_CURRENT_USER,
  219. L"Console",
  220. 0,
  221. KEY_ALL_ACCESS,
  222. &hkey
  223. );
  224. if( ERROR_SUCCESS == hr ){
  225. DWORD dwType;
  226. DWORD dwSize = sizeof(DWORD);
  227. hr = RegQueryValueExW (
  228. hkey,
  229. L"Colorize",
  230. NULL,
  231. &dwType,
  232. (LPBYTE)&dwColorize,
  233. &dwSize
  234. );
  235. }
  236. if( ERROR_SUCCESS == hr ){
  237. if( dwColorize == 0xff ){
  238. g_normal = ConsoleInfo.wAttributes;
  239. g_light = (USHORT)(ConsoleInfo.wAttributes | FOREGROUND_INTENSITY);
  240. g_debug = (USHORT)((ConsoleInfo.wAttributes & 0xF0) | FOREGROUND_INTENSITY | FOREGROUND_RED);
  241. g_dark = (USHORT)((ConsoleInfo.wAttributes & 0xF0) | FOREGROUND_INTENSITY);
  242. }else{
  243. g_normal = (USHORT)(dwColorize & 0x000000FF);
  244. g_debug = (USHORT)((dwColorize & 0x0000FF00) >> 8);
  245. g_light = (USHORT)((dwColorize & 0x00FF0000) >> 16);
  246. g_dark = (USHORT)((dwColorize & 0xFF000000) >> 24);
  247. }
  248. }else{
  249. g_normal = ConsoleInfo.wAttributes;
  250. g_debug = g_normal;
  251. g_light = g_normal;
  252. g_dark = g_normal;
  253. }
  254. if((g_dark & 0xF) == ((g_dark >> 4) & 0xF)) {
  255. g_dark = g_normal;
  256. }
  257. if((g_light & 0xF) == ((g_light >> 4) & 0xF)) {
  258. g_light = g_normal;
  259. }
  260. if((g_debug & 0xF) == ((g_debug >> 4) & 0xF)) {
  261. g_debug = g_normal;
  262. }
  263. if( NULL != hkey ){
  264. RegCloseKey ( hkey );
  265. }
  266. }
  267. void FreeCmd()
  268. {
  269. int i;
  270. for(i=0;Commands[i].fType != VARG_TYPE_LAST;i++){
  271. if( Commands[i].fType == VARG_TYPE_STR ||
  272. Commands[i].fType == VARG_TYPE_MSZ ||
  273. Commands[i].fType == VARG_TYPE_INI ){
  274. Commands[i].bDefined = FALSE;
  275. if( !(Commands[i].fFlag & VARG_FLAG_DODEFAULT) ){
  276. VARG_FREE( Commands[i].strValue );
  277. Commands[i].strValue = NULL;
  278. }
  279. }
  280. if( Commands[i].strArg1 != NULL ){
  281. VARG_FREE( Commands[i].strArg1 );
  282. }
  283. if( Commands[i].strArg2 != NULL ){
  284. VARG_FREE( Commands[i].strArg2 );
  285. }
  286. }
  287. VARG_FREE( g_strArgToken );
  288. VARG_FREE( g_strPrefix );
  289. VARG_FREE( g_strVerbPrefix );
  290. SetConsoleTextAttribute( g_hConsole, g_normal );
  291. }
  292. void LoadCmd()
  293. {
  294. int i;
  295. TCHAR buffer[MAXSTR];
  296. TCHAR param[MAXSTR];
  297. LPTSTR str;
  298. if( LoadString( NULL, IDS_ARG_TOKEN, buffer, MAXSTR ) ){
  299. ASSIGN_STRING( g_strArgToken, buffer );
  300. }else{
  301. str = _T("`");
  302. ASSIGN_STRING( g_strArgToken, str );
  303. }
  304. if( LoadString( NULL, IDS_ARG_PREFIX, buffer, MAXSTR ) ){
  305. ASSIGN_STRING( g_strPrefix, buffer );
  306. }else{
  307. str = _T("-/");
  308. ASSIGN_STRING( g_strPrefix, str );
  309. }
  310. if( LoadString( NULL, IDS_VERB_PREFIX, buffer, MAXSTR ) ){
  311. ASSIGN_STRING( g_strVerbPrefix, buffer );
  312. }else{
  313. str = _T("");
  314. ASSIGN_STRING( g_strVerbPrefix, str );
  315. }
  316. for( i=0; Commands[i].fType!=VARG_TYPE_LAST; i++ ){
  317. LPTSTR strArg1;
  318. LPTSTR strArg2;
  319. LPTSTR strParam;
  320. LPTSTR strHelp;
  321. LoadString( NULL, Commands[i].idParam, param, MAXSTR );
  322. strArg1 = _tcstok( param, g_strArgToken );
  323. strArg2 = _tcstok( NULL, g_strArgToken );
  324. strParam = _tcstok( NULL, g_strArgToken );
  325. strHelp = _tcstok( NULL, g_strArgToken );
  326. ASSIGN_STRING_RC( Commands[i].strArg1, strArg1, _T("*") );
  327. ASSIGN_STRING_RC( Commands[i].strArg2, strArg2, _T("*") );
  328. if( Commands[i].fFlag & VARG_FLAG_ARG_DATE ){
  329. TCHAR strDate[80];
  330. TCHAR strTime[80];
  331. TCHAR strAM[4];
  332. TCHAR strPM[4];
  333. GetLocaleInfo( VARG_LOCALE, LOCALE_SSHORTDATE, strDate, 80 );
  334. GetLocaleInfo( VARG_LOCALE, LOCALE_STIMEFORMAT, strTime, 80 );
  335. if( !GetLocaleInfo( VARG_LOCALE, LOCALE_S1159, strAM, 4 ) ){
  336. strAM[0] = _T('\0');
  337. }
  338. if( !GetLocaleInfo( VARG_LOCALE, LOCALE_S2359, strPM, 4 ) ){
  339. strPM[0] = _T('\0');
  340. }
  341. _tcstok( strTime, _T(" ") );
  342. if( _tcslen( strAM ) && _tcslen(strPM) ){
  343. if( Commands[i].fFlag & VARG_FLAG_DEFAULTABLE ){
  344. _stprintf( buffer, _T("[%s %s[%s|%s]]"), strDate, strTime, strAM, strPM );
  345. }else{
  346. _stprintf( buffer, _T("<%s %s[%s|%s]>"), strDate, strTime, strAM, strPM );
  347. }
  348. }else{
  349. if( Commands[i].fFlag & VARG_FLAG_DEFAULTABLE ){
  350. _stprintf( buffer, _T("[%s %s]"), strDate, strTime );
  351. }else{
  352. _stprintf( buffer, _T("<%s %s>"), strDate, strTime );
  353. }
  354. }
  355. ASSIGN_STRING_RC( Commands[i].strParam, buffer, _T("*") );
  356. }else{
  357. if( Commands[i].fFlag & VARG_FLAG_ARG_DEFAULT ){
  358. LoadString( NULL, IDS_ARG_DEFAULT, param, MAXSTR );
  359. strParam = param;
  360. }else if( Commands[i].fFlag & VARG_FLAG_ARG_FILENAME ){
  361. LoadString( NULL, IDS_ARG_FILENAME, param, MAXSTR );
  362. strParam = param;
  363. }else if( Commands[i].fFlag & VARG_FLAG_ARG_TIME ){
  364. LoadString( NULL, IDS_ARG_TIME, param, MAXSTR );
  365. strParam = param;
  366. }
  367. if( strParam != NULL && _tcslen( strParam ) && _tcscmp( strParam, _T("*") ) ){
  368. if( Commands[i].fFlag & VARG_FLAG_DEFAULTABLE ){
  369. if( Commands[i].fType == VARG_TYPE_MSZ && !(Commands[i].fFlag & VARG_FLAG_FLATHELP) ){
  370. _stprintf( buffer, _T("[%s [%s ...]]"), strParam, strParam );
  371. }else{
  372. _stprintf( buffer, _T("[%s]"), strParam );
  373. }
  374. }else{
  375. if( Commands[i].fType == VARG_TYPE_MSZ && !(Commands[i].fFlag & VARG_FLAG_FLATHELP)){
  376. _stprintf( buffer, _T("<%s [%s ...]>"), strParam, strParam );
  377. }else{
  378. _stprintf( buffer, _T("<%s>"), strParam );
  379. }
  380. }
  381. ASSIGN_STRING_RC( Commands[i].strParam, buffer, _T("*") );
  382. }else{
  383. strParam = NULL;
  384. ASSIGN_STRING_RC( Commands[i].strParam, strParam, _T("*") );
  385. }
  386. }
  387. }
  388. }
  389. ULONG MszStrLen( LPTSTR mszBuffer )
  390. {
  391. ULONG nLength = 0;
  392. ULONG nTotalLength = 0;
  393. LPTSTR strScan = mszBuffer;
  394. ULONG nTermSize = sizeof(TCHAR) * 2;
  395. while( strScan != NULL && *strScan != _T('\0') ){
  396. nLength = (_tcslen( strScan )+1);
  397. strScan += nLength;
  398. nTotalLength += nLength;
  399. }
  400. return (nTotalLength*sizeof(TCHAR) + nTermSize);
  401. }
  402. HRESULT
  403. AddStringToMsz( LPTSTR* mszBuffer, LPTSTR strValue )
  404. {
  405. ULONG nNewDataSize = 0;
  406. ULONG nOldDataSize = 0;
  407. LPTSTR strScan = *mszBuffer;
  408. LPTSTR mszNewBuffer;
  409. ULONG nLength;
  410. if( IsEmpty( strValue ) ){
  411. return ERROR_SUCCESS;
  412. }
  413. if( strScan != NULL ){
  414. while( *strScan != _T('\0') ){
  415. nLength = (_tcslen( strScan )+1);
  416. strScan += nLength;
  417. nOldDataSize += nLength;
  418. }
  419. }
  420. nNewDataSize = ( _tcslen( strValue )+1 ) * sizeof(TCHAR);
  421. mszNewBuffer = (LPTSTR)VARG_ALLOC( (nOldDataSize + nNewDataSize)*sizeof(TCHAR) + (sizeof(TCHAR)*2) );
  422. if( NULL == mszNewBuffer ){
  423. return ERROR_OUTOFMEMORY;
  424. }
  425. ZeroMemory( mszNewBuffer, (nOldDataSize + nNewDataSize)*sizeof(TCHAR) + (sizeof(TCHAR)*2) );
  426. if( nOldDataSize ){
  427. memcpy( mszNewBuffer, *mszBuffer, nOldDataSize*sizeof(TCHAR) );
  428. memcpy( (((PUCHAR)mszNewBuffer) + nOldDataSize*sizeof(TCHAR)), strValue, nNewDataSize );
  429. }else{
  430. memcpy( mszNewBuffer, strValue, nNewDataSize );
  431. }
  432. VARG_FREE( *mszBuffer );
  433. *mszBuffer = mszNewBuffer;
  434. return ERROR_SUCCESS;
  435. }
  436. void ParseIni( LPTSTR strFile )
  437. {
  438. TCHAR buffer[MAXSTR];
  439. FILE* f;
  440. LPTSTR str;
  441. TCHAR strCmd[MAXSTR];
  442. LPTSTR strValue;
  443. BOOL bFound;
  444. int i;
  445. ZeroMemory( strCmd, MAXSTR*sizeof(TCHAR) );
  446. if( strFile == NULL || _tcslen( strFile ) == 0 ){
  447. return;
  448. }
  449. f = _tfopen( strFile, _T("r") );
  450. if( NULL == f ){
  451. return;
  452. }
  453. while( _fgetts( buffer, MAXSTR, f ) ){
  454. if( buffer[0] == _T(';') || // comments
  455. buffer[0] == _T('#') ){
  456. continue;
  457. }
  458. Chomp( buffer );
  459. if( IsEmpty( buffer ) ){
  460. continue;
  461. }
  462. if( buffer[0] == _T('[') || _tcsstr( buffer, _T("=") ) ){
  463. str = _tcstok( buffer, _T("[]\n\t=") );
  464. if( str != NULL ){
  465. _tcscpy( strCmd, str );
  466. strValue = _tcstok( NULL, _T("]=\n ") );
  467. }else{
  468. strCmd[0] = _T('\0');
  469. strValue = NULL;
  470. }
  471. }else{
  472. strValue = _tcstok( buffer, _T("\n") );
  473. }
  474. bFound = FALSE;
  475. //
  476. // Check to see if it is a parameter that does not take a value
  477. //
  478. for(i=0; Commands[i].fType != VARG_TYPE_LAST && (!bFound);i++ ){
  479. if( IsCmd( &Commands[i], strCmd, TRUE ) ){
  480. switch( Commands[i].fType ){
  481. case VARG_TYPE_HELP:
  482. bFound = TRUE;
  483. break;
  484. case VARG_TYPE_BOOL:
  485. bFound = TRUE;
  486. Commands[i].bValue = Commands[i].bValue ? FALSE : TRUE;
  487. break;
  488. }
  489. if( bFound ){
  490. Commands[i].bDefined = TRUE;
  491. if( Commands[i].bDefined && Commands[i].fntValidation != NULL ){
  492. Commands[i].fntValidation(i);
  493. }
  494. }
  495. }
  496. }
  497. if( bFound || strValue == NULL || _tcslen( strCmd ) == 0 ){
  498. continue;
  499. }
  500. for(i=0; Commands[i].fType != VARG_TYPE_LAST && (!bFound);i++ ){
  501. if( IsCmd( &Commands[i], strCmd, TRUE ) ){
  502. bFound = TRUE;
  503. if( Commands[i].bDefined && Commands[i].fType != VARG_TYPE_MSZ ){
  504. continue;
  505. }
  506. switch( Commands[i].fType ){
  507. case VARG_TYPE_DEBUG:
  508. case VARG_TYPE_INT:
  509. {
  510. ULONG nValue;
  511. if( ERROR_SUCCESS == ReadLong( strValue, &nValue, MAXLONG ) ){
  512. Commands[i].nValue = nValue;
  513. if( Commands[i].fType == VARG_TYPE_DEBUG ){
  514. g_nDebug = nValue;
  515. }
  516. }
  517. }
  518. break;
  519. case VARG_TYPE_MSZ:
  520. if( !Commands[i].bDefined ){
  521. Commands[i].strValue = NULL;
  522. }
  523. if( Commands[i].fFlag & VARG_FLAG_CHOMP ){
  524. Chomp( strValue );
  525. }
  526. AddStringToMsz( &Commands[i].strValue, strValue );
  527. break;
  528. case VARG_TYPE_STR:
  529. if( Commands[i].fFlag & VARG_FLAG_CHOMP ){
  530. Chomp( strValue );
  531. }
  532. Commands[i].strValue = (LPTSTR)VARG_ALLOC( (_tcslen(strValue)+1) * sizeof(TCHAR) );
  533. if( Commands[i].strValue != NULL ){
  534. _tcscpy( Commands[i].strValue, strValue );
  535. }
  536. break;
  537. case VARG_TYPE_TIME:
  538. case VARG_TYPE_DATE:
  539. ParseTime( strValue, &Commands[i].stValue, (Commands[i].fType == VARG_TYPE_DATE) );
  540. break;
  541. }
  542. Commands[i].bDefined = TRUE;
  543. if( Commands[i].bDefined && Commands[i].fntValidation != NULL ){
  544. Commands[i].fntValidation(i);
  545. }
  546. }
  547. }
  548. }
  549. fclose(f);
  550. }
  551. void ParseCmd(int argc, LPTSTR argv[] )
  552. {
  553. int i;
  554. BOOL bFound;
  555. BOOL bHelp = FALSE;
  556. BOOL bBadSyntax = FALSE;
  557. int nIniIndex = (-1);
  558. g_LCID = VSetThreadUILanguage(0);
  559. VArgDeclareFormat();
  560. LoadCmd();
  561. SetUpColors();
  562. g_strProg = argv[0];
  563. argv++;argc--;
  564. while( argc > 0 ){
  565. bFound = FALSE;
  566. for(i=0; Commands[i].fType != VARG_TYPE_LAST && (!bFound);i++){
  567. if( IsCmd( &Commands[i], argv[0], FALSE ) ){
  568. if(Commands[i].bDefined){
  569. PrintMessage( g_debug, IDS_MESSAGE_ARG_DUP, Commands[i].strArg1, argv[0] );
  570. bBadSyntax = TRUE;
  571. }
  572. if( IsArg( argv[0] ) || Commands[i].fFlag & VARG_FLAG_VERB || Commands[i].fFlag & VARG_FLAG_ADVERB ){
  573. argv++;argc--;
  574. }
  575. bFound = TRUE;
  576. Commands[i].bDefined = TRUE;
  577. switch( Commands[i].fType ){
  578. case VARG_TYPE_HELP:
  579. Commands[i].bValue = TRUE;
  580. bHelp = TRUE;
  581. break;
  582. case VARG_TYPE_DEBUG:
  583. Commands[i].fFlag |= VARG_FLAG_DEFAULTABLE;
  584. g_nDebug = Commands[i].nValue;
  585. case VARG_TYPE_INT:
  586. if( argc > 0 && !IsArg( argv[0] ) ){
  587. ULONG nValue;
  588. HRESULT hr = ReadLong( argv[0], &nValue, MAXLONG );
  589. if( ERROR_SUCCESS == hr ){
  590. Commands[i].nValue = nValue;
  591. }else{
  592. Commands[i].fFlag |= VARG_FLAG_BADSYNTAX;
  593. }
  594. if( Commands[i].fType == VARG_TYPE_DEBUG ){
  595. g_nDebug = Commands[i].nValue;
  596. }
  597. argv++;argc--;
  598. }else if( !(Commands[i].fFlag & VARG_FLAG_DEFAULTABLE) ){
  599. if( !Commands[i].bNegated ){
  600. Commands[i].fFlag |= VARG_FLAG_BADSYNTAX;
  601. }
  602. }
  603. break;
  604. case VARG_TYPE_BOOL:
  605. Commands[i].bValue = Commands[i].bValue ? FALSE : TRUE;
  606. break;
  607. case VARG_TYPE_MSZ:
  608. if( argc > 0 && !IsArg( argv[0] ) ){
  609. ASSIGN_STRING( Commands[i].strValue, argv[0] );
  610. argv++;argc--;
  611. while( argc > 0 && ! IsArg( argv[0] ) ){
  612. if( Commands[i].fFlag & VARG_FLAG_CHOMP ){
  613. Chomp( argv[0] );
  614. }
  615. AddStringToMsz( &Commands[i].strValue, argv[0] );
  616. argv++;argc--;
  617. }
  618. }else if( Commands[i].fFlag & VARG_FLAG_DEFAULTABLE || Commands[i].bNegated ){
  619. Commands[i].fFlag |= VARG_FLAG_DODEFAULT;
  620. }else{
  621. Commands[i].fFlag |= VARG_FLAG_BADSYNTAX;
  622. }
  623. break;
  624. case VARG_TYPE_INI:
  625. nIniIndex = i;
  626. case VARG_TYPE_STR:
  627. if( argc > 0 && ! IsArg( argv[0] ) ){
  628. if( Commands[i].fFlag & VARG_FLAG_CHOMP ){
  629. Chomp( argv[0] );
  630. }
  631. Commands[i].strValue = (LPTSTR)VARG_ALLOC( (_tcslen(argv[0])+2) * sizeof(TCHAR) );
  632. if( Commands[i].strValue != NULL ){
  633. _tcscpy( Commands[i].strValue, argv[0] );
  634. }
  635. argv++;argc--;
  636. }else if( Commands[i].fFlag & VARG_FLAG_DEFAULTABLE || Commands[i].bNegated ){
  637. Commands[i].fFlag |= VARG_FLAG_DODEFAULT;
  638. }else{
  639. if( !(Commands[i].fFlag & VARG_FLAG_NEGATE) ){
  640. Commands[i].fFlag |= VARG_FLAG_BADSYNTAX;
  641. }
  642. }
  643. break;
  644. case VARG_TYPE_TIME:
  645. case VARG_TYPE_DATE:
  646. if( argc > 0 && !IsArg( argv[0] ) ){
  647. HRESULT hr;
  648. LPTSTR strDate = NULL;
  649. LPTSTR strTime = argv[0];
  650. argv++;argc--;
  651. if( Commands[i].fType == VARG_TYPE_DATE ){
  652. if( argc > 0 && !IsArg( argv[0] ) ){
  653. strDate = (LPTSTR)VARG_ALLOC( (_tcslen(strTime)+_tcslen(argv[0])+2)*sizeof(TCHAR) );
  654. if( NULL != strDate ){
  655. _stprintf( strDate, _T("%s %s"), strTime, argv[0] );
  656. strTime = strDate;
  657. }
  658. argv++;argc--;
  659. }
  660. }
  661. hr = ParseTime( strTime, &Commands[i].stValue, (Commands[i].fType == VARG_TYPE_DATE) );
  662. if( ERROR_SUCCESS != hr ){
  663. Commands[i].fFlag |= VARG_FLAG_BADSYNTAX;
  664. }
  665. VARG_FREE( strDate );
  666. }else if( !(Commands[i].fFlag & VARG_FLAG_DEFAULTABLE) && !(Commands[i].bNegated) ){
  667. Commands[i].fFlag |= VARG_FLAG_BADSYNTAX;
  668. }
  669. }
  670. if( Commands[i].fFlag & VARG_FLAG_EXPANDFILES ){
  671. ExpandFiles( &Commands[i].strValue, (Commands[i].fType == VARG_TYPE_MSZ) );
  672. }
  673. }
  674. }
  675. if (!bFound){
  676. PrintMessage( g_debug, IDS_MESSAGE_UNKNOWNPARAM, (*(argv)));
  677. argv++;argc--;
  678. bBadSyntax = TRUE;
  679. }
  680. }
  681. if( nIniIndex >= 0 ){
  682. if( Commands[nIniIndex].fType == VARG_TYPE_INI && Commands[nIniIndex].bDefined ){
  683. ParseIni( Commands[nIniIndex].strValue );
  684. }
  685. }
  686. for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){
  687. if( !bHelp && (Commands[i].bDefined && Commands[i].fntValidation != NULL ) ){
  688. Commands[i].fntValidation(i);
  689. }
  690. if( ( Commands[i].fType == VARG_TYPE_STR ||
  691. Commands[i].fType == VARG_TYPE_MSZ ||
  692. Commands[i].fType == VARG_TYPE_INI ) &&
  693. (!Commands[i].bDefined || Commands[i].fFlag & VARG_FLAG_DODEFAULT ) ){
  694. TCHAR buffer[MAXSTR];
  695. Commands[i].fFlag &= ~VARG_FLAG_DODEFAULT;
  696. if( Commands[i].fFlag & VARG_FLAG_RCDEFAULT ){
  697. LoadString( NULL, Commands[i].nValue, buffer, MAXSTR );
  698. ASSIGN_STRING( Commands[i].strValue, buffer );
  699. }else if( Commands[i].strValue != NULL ){
  700. ASSIGN_STRING( Commands[i].strValue, Commands[i].strValue );
  701. }
  702. }
  703. }
  704. if( bHelp ){
  705. DisplayCommandLineHelp();
  706. }
  707. if( g_nDebug >= 0 ){
  708. DisplayDebugInfo();
  709. }
  710. if( ERROR_SUCCESS != ValidateCommands() || bBadSyntax ){
  711. PrintMessage( g_debug, IDS_MESSAGE_INCORRECT );
  712. FreeCmd();
  713. exit(ERROR_BAD_FORMAT);
  714. }
  715. }
  716. void
  717. DisplayIniInfo()
  718. {
  719. int i;
  720. int nOut;
  721. BOOL bOpt;
  722. PrintMessage( g_normal, IDS_MESSAGE_INISYNT );
  723. for( i=0;i<35;i++){ varg_printf( g_normal, _T("-") ); }
  724. varg_printf( g_normal, _T("\n") );
  725. for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){
  726. if( Commands[i].fFlag & VARG_FLAG_HIDDEN && !(Commands[i].bDefined) ){
  727. continue;
  728. }
  729. bOpt = ( Commands[i].strArg2 != NULL && _tcslen( Commands[i].strArg2 ) );
  730. switch( Commands[i].fType ){
  731. case VARG_TYPE_DEBUG:
  732. case VARG_TYPE_BOOL:
  733. case VARG_TYPE_MSZ:
  734. case VARG_TYPE_STR:
  735. case VARG_TYPE_INT:
  736. case VARG_TYPE_TIME:
  737. case VARG_TYPE_DATE:
  738. nOut = varg_printf( g_normal,
  739. _T(" %1!-20s! %2!-20s!\n"),
  740. Commands[i].strArg1, bOpt ?
  741. Commands[i].strArg2 : _T("")
  742. );
  743. break;
  744. }
  745. }
  746. varg_printf( g_normal, _T("\n") );
  747. }
  748. void
  749. DisplayDebugInfo()
  750. {
  751. int i;
  752. int nOut;
  753. TCHAR strDefault[MAXSTR] = _T("");
  754. LoadString( NULL, IDS_MESSAGE_DEFAULT, strDefault, MAXSTR );
  755. for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){
  756. if( !(Commands[i].bDefined) && g_nDebug < 1 ){
  757. continue;
  758. }
  759. if( Commands[i].fType == VARG_TYPE_HELP ){
  760. continue;
  761. }
  762. if( Commands[i].fFlag & VARG_FLAG_HIDDEN && !(Commands[i].bDefined) ){
  763. continue;
  764. }
  765. nOut = varg_printf( g_debug, _T("%1!-16s! = "), Commands[i].strArg1 );
  766. switch( Commands[i].fType ){
  767. case VARG_TYPE_DEBUG:
  768. case VARG_TYPE_INT:
  769. varg_printf( g_debug, _T("%1!-20lu!"), Commands[i].nValue );
  770. break;
  771. case VARG_TYPE_BOOL:
  772. varg_printf( g_debug, _T("%1!-20s!"),
  773. Commands[i].bValue ? _T("TRUE") : _T("FALSE")
  774. );
  775. break;
  776. case VARG_TYPE_MSZ:
  777. if( !IsEmpty( Commands[i].strValue ) ){
  778. LPTSTR strValue = Commands[i].strValue;
  779. while( *strValue != _T('\0') ){
  780. if( strValue == Commands[i].strValue ){
  781. varg_printf( g_debug, _T("%1!-20s!"), strValue );
  782. }else{
  783. varg_printf( g_debug, _T("\n%1!19s!%2!-20s!"), _T(" "), strValue );
  784. }
  785. strValue += (_tcslen( strValue )+1);
  786. }
  787. }else{
  788. varg_printf( g_debug, _T("%1!-20s!"), _T("-") );
  789. }
  790. break;
  791. case VARG_TYPE_TIME:
  792. case VARG_TYPE_DATE:
  793. {
  794. int nOut;
  795. nOut = PrintDateEx( g_debug, &Commands[i].stValue );
  796. while( nOut++ < 20 ) { varg_printf( g_debug, _T(" ") ); }
  797. }
  798. break;
  799. case VARG_TYPE_INI:
  800. case VARG_TYPE_STR:
  801. varg_printf( g_debug, _T("%1!-20s!"),
  802. (Commands[i].strValue == NULL || !(_tcslen(Commands[i].strValue)) ) ?
  803. _T("-") : Commands[i].strValue
  804. );
  805. break;
  806. }
  807. if( !Commands[i].bDefined ){
  808. varg_printf( g_debug, _T(" (%1!s!)"), strDefault );
  809. }
  810. varg_printf( g_debug, _T("\n") );
  811. }
  812. varg_printf( g_debug, _T("\n") );
  813. }
  814. int PrintMessage( WORD color, LONG id, ... )
  815. {
  816. int nLoad;
  817. TCHAR buffer[MAXSTR];
  818. va_list args;
  819. va_start( args, id );
  820. nLoad = LoadString( NULL, id, buffer, MAXSTR );
  821. if( nLoad > 0 ){
  822. nLoad = varg_vprintf( color, buffer, args );
  823. }else{
  824. nLoad = FormatMessage(
  825. FORMAT_MESSAGE_FROM_HMODULE,
  826. GetModuleHandle(NULL),
  827. id,
  828. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
  829. buffer,
  830. MAXSTR,
  831. &args
  832. );
  833. varg_printf( color, buffer );
  834. }
  835. return nLoad;
  836. }
  837. BOOL varg_strlen( LPTSTR str, ULONG* pVisualSize, ULONG* pActualSize, BOOL* bCanBreak )
  838. {
  839. BOOL bResult;
  840. WORD wType[MAXSTR];
  841. ULONG i;
  842. *pActualSize = _tcslen(str);
  843. if( *pActualSize > MAXSTR ){
  844. return FALSE;
  845. }
  846. bResult = GetStringTypeEx( VARG_LOCALE, CT_CTYPE3, str, *pActualSize, (LPWORD)&wType );
  847. if( !bResult ){
  848. return FALSE;
  849. }
  850. *pVisualSize = 0;
  851. *bCanBreak = FALSE;
  852. for( i=0;i<*pActualSize;i++ ){
  853. if( wType[i] & (C3_KATAKANA|C3_HIRAGANA|C3_IDEOGRAPH|C3_FULLWIDTH) ){
  854. *pVisualSize += 2;
  855. *bCanBreak = TRUE;
  856. }else{
  857. *pVisualSize += 1;
  858. }
  859. }
  860. return TRUE;
  861. }
  862. HRESULT PrintHelpString( LONG id, LONG nStart, LONG nCol, LONG nMax, BOOL bSwitch )
  863. {
  864. int j,nLoad;
  865. TCHAR buffer[MAXSTR];
  866. LPTSTR strHelp;
  867. ULONG nOut;
  868. if( nMax <= nCol ){
  869. nMax = 79;
  870. }
  871. nLoad = LoadString( NULL, id, buffer, MAXSTR );
  872. strHelp = _tcstok( buffer, g_strArgToken );
  873. if( bSwitch ){
  874. _tcstok( NULL, g_strArgToken );
  875. _tcstok( NULL, g_strArgToken );
  876. strHelp = _tcstok( NULL, g_strArgToken );
  877. }
  878. nOut = nStart;
  879. for(j=nStart;j<nCol;j++){ nOut += varg_printf( g_normal, _T(" ") ); }
  880. if( nLoad > 0 && strHelp != NULL && _tcslen( strHelp ) ){
  881. LPTSTR str = strHelp;
  882. ULONG nChar = 0;
  883. ULONG nPrint = 0;
  884. BOOL bCanBreak;
  885. ULONG nVisualLength, nActualLength;
  886. LPTSTR strNewLine;
  887. LPTSTR strFailCheck = NULL;
  888. while( *str != _T('\0') ){
  889. nChar++;
  890. switch( *str ){
  891. case _T('\t'):
  892. case _T(' '):
  893. *str = _T('\0');
  894. }
  895. str++;
  896. }
  897. str = strHelp;
  898. nMax -= (nMax%2);
  899. while( nPrint < nChar ){
  900. varg_strlen( str, &nVisualLength, &nActualLength, &bCanBreak );
  901. strNewLine = _tcsstr( str, _T("\n") );
  902. if( ((SHORT)(nVisualLength+nOut) > (nMax-1)) || (NULL != strNewLine) ){
  903. if( NULL != strNewLine ){
  904. *strNewLine = _T('\0');
  905. nPrint += _tcslen( str );
  906. varg_printf( g_normal, str );
  907. strNewLine++;
  908. str = strNewLine;
  909. }else if(bCanBreak){
  910. TCHAR cSaveChar;
  911. ULONG nBreak = (ULONG)ceil(((double)(nMax - nOut))/2.0);
  912. if( nBreak < nActualLength ){
  913. cSaveChar = str[nBreak];
  914. str[nBreak] = _T('\0');
  915. nPrint += nBreak;
  916. varg_printf( g_normal, str );
  917. str[nBreak] = cSaveChar;
  918. str = str + nBreak;
  919. }else if( nBreak == nActualLength ){
  920. nPrint += nBreak;
  921. varg_printf( g_normal, str );
  922. str = str + nBreak;
  923. continue;
  924. }
  925. }
  926. if( str == strFailCheck ){
  927. varg_printf( g_normal, str );
  928. str += _tcslen(str)+1;
  929. nPrint++;
  930. }else{
  931. varg_printf( g_normal, _T("\n") );
  932. for(j=0,nOut=0;j<nCol;j++){ nOut += varg_printf( g_normal, _T(" ") ); }
  933. }
  934. strFailCheck = str;
  935. }else{
  936. nPrint += nActualLength;
  937. nOut += varg_printf( g_normal, str );
  938. if( (SHORT)(nOut) < nMax ){
  939. nOut += varg_printf( g_normal, _T(" ") );
  940. nPrint++;
  941. }
  942. str += _tcslen(str)+1;
  943. }
  944. }
  945. varg_printf( g_normal, _T("\n") );
  946. return ERROR_SUCCESS;
  947. }
  948. return ERROR_FILE_NOT_FOUND;
  949. }
  950. void DisplayVersionInfo()
  951. {
  952. TCHAR buffer[512];
  953. TCHAR strProgram[MAXSTR];
  954. TCHAR strMicrosoft[512];
  955. DWORD dw;
  956. BYTE* pVersionInfo;
  957. LPTSTR pVersion = NULL;
  958. LPTSTR pProduct = NULL;
  959. LPTSTR pCopyRight = NULL;
  960. dw = GetModuleFileName(NULL, strProgram, MAXSTR );
  961. LoadString( NULL, IDS_MESSAGE_MSR, strMicrosoft, 512 );
  962. if( dw>0 ){
  963. dw = GetFileVersionInfoSize( strProgram, &dw );
  964. if( dw > 0 ){
  965. pVersionInfo = (BYTE*)VARG_ALLOC(dw);
  966. if( NULL != pVersionInfo ){
  967. if(GetFileVersionInfo( strProgram, 0, dw, pVersionInfo )){
  968. LPDWORD lptr = NULL;
  969. VerQueryValue( pVersionInfo, _T("\\VarFileInfo\\Translation"), (void**)&lptr, (UINT*)&dw );
  970. if( lptr != NULL ){
  971. _stprintf( buffer, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD(*lptr), HIWORD(*lptr), _T("ProductVersion") );
  972. VerQueryValue( pVersionInfo, buffer, (void**)&pVersion, (UINT*)&dw );
  973. _stprintf( buffer, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD(*lptr), HIWORD(*lptr), _T("OriginalFilename") );
  974. VerQueryValue( pVersionInfo, buffer, (void**)&pProduct, (UINT*)&dw );
  975. _stprintf( buffer, _T("\\StringFileInfo\\%04x%04x\\%s"), LOWORD(*lptr), HIWORD(*lptr), _T("LegalCopyright") );
  976. VerQueryValue( pVersionInfo, buffer, (void**)&pCopyRight, (UINT*)&dw );
  977. }
  978. if( pProduct != NULL && pVersion != NULL && pCopyRight != NULL ){
  979. varg_printf( g_normal, _T("\n%1!s! %2!s! (%3!s!)\n%4!s!\n\n"), strMicrosoft, pProduct, pVersion, pCopyRight );
  980. }
  981. }
  982. VARG_FREE( pVersionInfo );
  983. }
  984. }
  985. }
  986. }
  987. void
  988. DisplayHelpEx( LONG id )
  989. {
  990. TCHAR buffer[8];
  991. DWORD dwSize = 8;
  992. dwSize = LoadString( NULL, id, buffer, dwSize );
  993. if( dwSize > 0 ){
  994. PrintMessage( g_normal, id );
  995. }
  996. }
  997. void
  998. DisplayCommandLineHelp()
  999. {
  1000. int i,j;
  1001. int nOut;
  1002. BOOL bOpt;
  1003. BOOL bVerbs = FALSE;
  1004. int nVerbs = 0;
  1005. int nCommands = 0;
  1006. BOOL bRequired = FALSE;
  1007. int nConditional = 0;
  1008. int nDefinedConditional = 0;
  1009. BOOL bFirst = TRUE;
  1010. BOOL bDisplayAll = FALSE;
  1011. DWORD dwVerbMask = 0;
  1012. UCHAR excl1 = 0;
  1013. LPTSTR strNegateHelp = NULL;
  1014. for( i=0; Commands[i].fType != VARG_TYPE_LAST;i++){
  1015. if( (Commands[i].dwSet & VARG_CONDITION) &&
  1016. !(Commands[i].fFlag & VARG_FLAG_VERB) ){
  1017. nConditional++;
  1018. if( Commands[i].bDefined ){
  1019. nDefinedConditional++;
  1020. }
  1021. }
  1022. if( Commands[i].fFlag & VARG_FLAG_VERB ){
  1023. bVerbs = TRUE;
  1024. }
  1025. if( Commands[i].bDefined ){
  1026. if( Commands[i].fFlag & VARG_FLAG_VERB || Commands[i].fFlag & VARG_FLAG_ADVERB){
  1027. nVerbs++;
  1028. dwVerbMask |= (Commands[i].dwVerb & 0x0000FFFF);
  1029. if( Commands[i].dwSet != 0 ){
  1030. excl1 = (UCHAR)(((Commands[i].dwSet & VARG_GROUPEXCL) >> 24) & 0x0F);
  1031. }
  1032. }else{
  1033. if( Commands[i].fType != VARG_TYPE_HELP &&
  1034. Commands[i].fType != VARG_TYPE_DEBUG ){
  1035. nCommands++;
  1036. }
  1037. }
  1038. }
  1039. }
  1040. if( nCommands == 0 && nVerbs == 0 ){
  1041. bDisplayAll = TRUE;
  1042. }
  1043. DisplayVersionInfo();
  1044. if( bDisplayAll ){
  1045. if( ERROR_SUCCESS == PrintHelpString( IDS_PROGRAM_DESCRIPTION, 0, 0, g_X, FALSE ) ){
  1046. varg_printf( g_normal, _T("\n") );
  1047. }
  1048. }
  1049. // Usage
  1050. PrintMessage( g_normal, IDS_MESSAGE_USAGE );
  1051. nOut = varg_printf( g_normal, _T("%1!s! "), g_strProg );
  1052. if( bVerbs ){
  1053. LONG nDispVerbs = 0;
  1054. if( !bDisplayAll ){
  1055. for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){
  1056. if( Commands[i].fFlag & VARG_FLAG_VERB && Commands[i].bDefined ){
  1057. nOut += varg_printf( g_normal, _T("%1!s! "), Commands[i].strArg1 );
  1058. nDispVerbs++;
  1059. }
  1060. }
  1061. }
  1062. if( bDisplayAll || !nDispVerbs ){
  1063. nOut += PrintMessage( g_normal, IDS_MESSAGE_VERB );
  1064. }
  1065. }
  1066. if( nConditional > 1 && nDefinedConditional == 0 ){
  1067. nOut += varg_printf( g_normal, _T("{ ") );
  1068. }
  1069. for( j=0;j<2;j++){
  1070. for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){
  1071. if( j==0 ){
  1072. // show conditional switches
  1073. if( Commands[i].fFlag & VARG_FLAG_HIDDEN ||
  1074. Commands[i].fFlag & VARG_FLAG_VERB ||
  1075. !(Commands[i].dwSet & VARG_CONDITION) ){
  1076. continue;
  1077. }
  1078. if( nDefinedConditional > 0 && !Commands[i].bDefined ){
  1079. continue;
  1080. }
  1081. }else{
  1082. // show required switches
  1083. if( Commands[i].fFlag & VARG_FLAG_HIDDEN ||
  1084. Commands[i].fFlag & VARG_FLAG_VERB ||
  1085. Commands[i].dwSet & VARG_CONDITION ||
  1086. Commands[i].fFlag & VARG_FLAG_OPTIONAL ){
  1087. continue;
  1088. }
  1089. }
  1090. if( (!bFirst) && nConditional && nDefinedConditional == 0 ){
  1091. nOut += varg_printf( g_normal, _T("| ") );
  1092. }
  1093. bFirst = FALSE;
  1094. if( Commands[i].fFlag & VARG_FLAG_NOFLAG ){
  1095. nOut += varg_printf( g_normal, _T("%1!s! "), Commands[i].strParam );
  1096. }else{
  1097. nOut += varg_printf( g_normal, _T("%1!c!%2!s!%3!s!%4!s!%5!s! "),
  1098. Commands[i].fFlag&VARG_FLAG_VERB ? g_strVerbPrefix[0] : g_strPrefix[0],
  1099. Commands[i].fFlag&VARG_FLAG_NEGATE ? _T("[-]"):_T(""),
  1100. Commands[i].strArg2,
  1101. ArgExpected( &Commands[i] ) ? _T(" "): _T(""),
  1102. Commands[i].strParam
  1103. );
  1104. }
  1105. if( nOut > (g_X - 15) ){
  1106. nOut = 0;
  1107. varg_printf( g_normal, _T("\n") );
  1108. while( nOut++ < HELP_INDENT){ varg_printf( g_normal, _T(" ") ); }
  1109. }
  1110. }
  1111. if( j == 0 && (nConditional>1) && nDefinedConditional == 0 ){
  1112. varg_printf( g_normal, _T("} ") );
  1113. }
  1114. }
  1115. PrintMessage( g_normal, IDS_MESSAGE_LINEOPT );
  1116. // Verbs
  1117. if( bVerbs ){
  1118. bFirst = TRUE;
  1119. for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){
  1120. if( Commands[i].fFlag & VARG_FLAG_HIDDEN && !(Commands[i].bDefined) ){
  1121. continue;
  1122. }
  1123. if( !(Commands[i].fFlag & VARG_FLAG_VERB ) ){
  1124. continue;
  1125. }
  1126. if( !bDisplayAll && !Commands[i].bDefined ){
  1127. continue;
  1128. }
  1129. if( bFirst ){
  1130. PrintMessage( g_normal, IDS_MESSAGE_VERBS );
  1131. bFirst = FALSE;
  1132. }
  1133. bOpt = ( Commands[i].strArg2 != NULL && _tcslen( Commands[i].strArg2 ) );
  1134. nOut = varg_printf( COLORIZE(i), _T(" %1!s!%2!s! %3!s! "),
  1135. g_strVerbPrefix,
  1136. (LPTSTR)(bOpt ? Commands[i].strArg2 : Commands[i].strArg1),
  1137. Commands[i].strParam
  1138. );
  1139. if( nOut > HELP_INDENT ){
  1140. nOut += varg_printf( g_normal, _T(" ") );
  1141. }
  1142. PrintHelpString( Commands[i].idParam, nOut, HELP_INDENT, g_X, TRUE );
  1143. }
  1144. if( !bFirst ){
  1145. varg_printf( g_normal, _T("\n") );
  1146. }
  1147. }
  1148. // Options
  1149. for(j=0;j<2;j++){
  1150. bFirst = TRUE;
  1151. for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){
  1152. if( j==0 ){
  1153. if( !(Commands[i].fFlag & VARG_FLAG_NOFLAG) ||
  1154. Commands[i].fFlag & (VARG_FLAG_VERB|VARG_FLAG_ADVERB) ){
  1155. continue;
  1156. }
  1157. }else{
  1158. if( Commands[i].fFlag & VARG_FLAG_NOFLAG ||
  1159. Commands[i].fFlag & (VARG_FLAG_VERB|VARG_FLAG_ADVERB) ){
  1160. continue;
  1161. }
  1162. }
  1163. if( ! bDisplayAll && (Commands[i].fType == VARG_TYPE_HELP) ){
  1164. continue;
  1165. }
  1166. if( Commands[i].fFlag & VARG_FLAG_HIDDEN && !(Commands[i].bDefined) ){
  1167. continue;
  1168. }
  1169. if( bDisplayAll ||
  1170. Commands[i].bDefined ||
  1171. (((Commands[i].dwVerb & 0x0000FFFF)& dwVerbMask) && nCommands < 1 ) ){
  1172. UCHAR excl2 = (UCHAR)((((Commands[i].dwSet & VARG_GROUPEXCL) >> 24) & 0xF0) >> 4 );
  1173. if( excl2 & excl1 ){
  1174. continue;
  1175. }
  1176. if( bFirst ){
  1177. switch( j ){
  1178. case 0:
  1179. PrintMessage( g_normal, IDS_MESSAGE_PARAMETERS );
  1180. bRequired = TRUE;
  1181. break;
  1182. case 1:
  1183. PrintMessage( g_normal, IDS_MESSAGE_OPTIONS, bRequired ? _T("\n") : _T("") );
  1184. break;
  1185. }
  1186. bFirst = FALSE;
  1187. }
  1188. bOpt = ( Commands[i].strArg2 != NULL && _tcslen( Commands[i].strArg2 ) );
  1189. if( Commands[i].fFlag & VARG_FLAG_NOFLAG ){
  1190. nOut = varg_printf( COLORIZE(i), _T(" %1!s! "),
  1191. Commands[i].strParam
  1192. );
  1193. }else{
  1194. nOut = varg_printf( COLORIZE(i), _T(" %1!c!%2!s!%3!s! %4!s! "),
  1195. g_strPrefix[0],
  1196. Commands[i].fFlag & VARG_FLAG_NEGATE ? _T("[-]") : _T(""),
  1197. bOpt ? Commands[i].strArg2 : Commands[i].strArg1,
  1198. Commands[i].strParam
  1199. );
  1200. }
  1201. if( nOut > HELP_INDENT ){
  1202. nOut += varg_printf( g_normal, _T(" ") );
  1203. }
  1204. if( Commands[i].fFlag & VARG_FLAG_NEGATE && NULL == strNegateHelp ){
  1205. strNegateHelp = bOpt ? Commands[i].strArg2 : Commands[i].strArg1;
  1206. }
  1207. PrintHelpString( Commands[i].idParam, nOut, HELP_INDENT, g_X, TRUE );
  1208. if( !bDisplayAll ){
  1209. if( Commands[i].fType == VARG_TYPE_INI ){
  1210. DisplayIniInfo();
  1211. }
  1212. }
  1213. }
  1214. }
  1215. }
  1216. if( NULL != strNegateHelp ){
  1217. PrintMessage( g_normal, IDS_MESSAGE_NEGATE, strNegateHelp, strNegateHelp );
  1218. }
  1219. // Notes
  1220. if( bDisplayAll ){
  1221. PrintMessage( g_normal, IDS_MESSAGE_HELPTEXT );
  1222. }
  1223. // Examples
  1224. bFirst = TRUE;
  1225. for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){
  1226. if( bDisplayAll || Commands[i].bDefined ){
  1227. if( (bDisplayAll && bVerbs ) &&
  1228. !(Commands[i].fFlag & (VARG_FLAG_VERB|VARG_FLAG_ADVERB) ) ){
  1229. continue;
  1230. }
  1231. if( Commands[i].fFlag & VARG_FLAG_EXHELP ){
  1232. if( bFirst ){
  1233. PrintMessage( g_normal, IDS_MESSAGE_EXAMPLES );
  1234. bFirst = FALSE;
  1235. }
  1236. PrintHelpString( Commands[i].idExHelp, 0, 2, 80, FALSE );
  1237. }
  1238. }
  1239. }
  1240. FreeCmd();
  1241. exit(0);
  1242. }
  1243. void PrintParam( int idPrompt, int cmd, BOOL bEOL )
  1244. {
  1245. BOOL bUseArg1;
  1246. TCHAR buffer[MAXSTR];
  1247. bUseArg1 = (Commands[cmd].fFlag & VARG_FLAG_VERB) ||
  1248. (Commands[cmd].fFlag & VARG_FLAG_ADVERB) ||
  1249. ( IsEmpty( Commands[cmd].strArg2 ) );
  1250. if( 0 != idPrompt ){
  1251. LoadString( NULL, idPrompt, buffer, MAXSTR );
  1252. varg_printf( g_debug, buffer );
  1253. }
  1254. if( Commands[cmd].fFlag & VARG_FLAG_NOFLAG ){
  1255. varg_printf( g_debug, _T("%1!s! "), Commands[cmd].strParam );
  1256. }else{
  1257. if( !(Commands[cmd].fFlag & (VARG_FLAG_VERB|VARG_FLAG_ADVERB)) ){
  1258. varg_printf( g_debug, _T("%1!c!"), g_strPrefix[0] );
  1259. }else if( !IsEmpty( g_strVerbPrefix ) ){
  1260. varg_printf( g_debug, _T("%1!c!"), g_strVerbPrefix[0] );
  1261. }
  1262. if( ArgExpected( &Commands[cmd] ) ){
  1263. varg_printf( g_debug, _T("%1!s!%2!s! %3!s! "),
  1264. Commands[cmd].fFlag&VARG_FLAG_NEGATE ? _T("[-]") : _T(""),
  1265. bUseArg1 ? Commands[cmd].strArg1 : Commands[cmd].strArg2,
  1266. Commands[cmd].strParam
  1267. );
  1268. }else{
  1269. varg_printf( g_debug, _T("%1!s!%2!s! "),
  1270. Commands[cmd].fFlag&VARG_FLAG_NEGATE ? _T("[-]") : _T(""),
  1271. bUseArg1 ? Commands[cmd].strArg1 : Commands[cmd].strArg2
  1272. );
  1273. }
  1274. }
  1275. if( bEOL ){
  1276. varg_printf( g_debug, _T("\n") );
  1277. }
  1278. }
  1279. HRESULT
  1280. ValidateCommands()
  1281. {
  1282. int i,j;
  1283. HRESULT hr = ERROR_SUCCESS;
  1284. BOOL bVerbs = FALSE;
  1285. BOOL nDefinedVerbs = 0;
  1286. for(i=0; Commands[i+1].fType != VARG_TYPE_LAST;i++){
  1287. UCHAR cond1 = (UCHAR)((Commands[i].dwSet & VARG_CONDITION) >> 16);
  1288. if( cond1 ){
  1289. BOOL bFound = FALSE;
  1290. for(j=0; Commands[j].fType != VARG_TYPE_LAST;j++){
  1291. UCHAR cond2 = (UCHAR)((Commands[j].dwSet & VARG_CONDITION) >> 16);
  1292. if( (cond1 & cond2) && Commands[j].bDefined ){
  1293. bFound = TRUE;
  1294. break;
  1295. }
  1296. }
  1297. if( ! bFound ){
  1298. for(j=0; Commands[j].fType != VARG_TYPE_LAST;j++){
  1299. UCHAR cond2 = (UCHAR)((Commands[j].dwSet & VARG_CONDITION) >> 16);
  1300. if( (cond1 & cond2) && !(Commands[j].fFlag & VARG_FLAG_VERB)){
  1301. Commands[j].fFlag |= VARG_FLAG_REQUIRED;
  1302. }
  1303. }
  1304. }
  1305. }
  1306. if( Commands[i].bDefined && (Commands[i].fFlag & VARG_FLAG_REQ_ADV) ){
  1307. BOOL bFound = FALSE;
  1308. WORD wVerb1 = (WORD)( Commands[i].dwVerb & 0x0000FFFF );
  1309. for(j=0; Commands[j].fType != VARG_TYPE_LAST;j++){
  1310. WORD wVerb2 = (WORD)(Commands[j].dwVerb & 0x0000FFFF);
  1311. if( Commands[j].bDefined && (wVerb1 == wVerb2) && (Commands[j].fFlag & VARG_FLAG_ADVERB) ){
  1312. bFound = TRUE;
  1313. break;
  1314. }
  1315. }
  1316. if( ! bFound ){
  1317. for(j=0; Commands[j].fType != VARG_TYPE_LAST;j++){
  1318. WORD wVerb2 = (WORD)(Commands[j].dwVerb & 0x0000FFFF);
  1319. if( wVerb1 == wVerb2 && Commands[j].fFlag & VARG_FLAG_ADVERB ){
  1320. Commands[j].fFlag |= VARG_FLAG_REQUIRED;
  1321. }
  1322. }
  1323. }
  1324. }
  1325. if( Commands[i].bDefined && Commands[i].dwSet ){
  1326. UCHAR excl1 = (UCHAR)((Commands[i].dwSet & VARG_EXCLUSIVE));
  1327. UCHAR incl1 = (UCHAR)((Commands[i].dwSet & VARG_INCLUSIVE) >> 8);
  1328. UCHAR grp_ex1 = (UCHAR)(((Commands[i].dwSet & VARG_GROUPEXCL) >> 24) & 0x0F);
  1329. for(j=i+1; Commands[j].fType != VARG_TYPE_LAST;j++){
  1330. if( Commands[j].dwSet ){
  1331. UCHAR excl2 = (UCHAR)((Commands[j].dwSet & VARG_EXCLUSIVE));
  1332. UCHAR incl2 = (UCHAR)((Commands[j].dwSet & VARG_INCLUSIVE) >> 8);
  1333. UCHAR grp_in2 = (UCHAR)((((Commands[j].dwSet & VARG_GROUPEXCL) >> 24) & 0xF0) >> 4 );
  1334. if( excl1 && (excl1 & excl2) && Commands[j].bDefined ){
  1335. PrintParam( 0, i, FALSE );
  1336. PrintParam( IDS_MESSAGE_AND, j, FALSE );
  1337. PrintMessage( g_debug, IDS_MESSAGE_EXCLUSIVE );
  1338. hr = ERROR_BAD_ARGUMENTS;
  1339. }
  1340. if( incl1 && (incl1 & incl2) && !Commands[j].bDefined){
  1341. PrintParam( 0, i, FALSE );
  1342. PrintParam( IDS_MESSAGE_REQUIRES, j, FALSE );
  1343. varg_printf( g_debug, _T("\n") );
  1344. hr = ERROR_BAD_ARGUMENTS;
  1345. }
  1346. if( grp_ex1 && (grp_in2 & grp_ex1) && Commands[j].bDefined ){
  1347. PrintParam( 0, i, FALSE );
  1348. PrintParam( IDS_MESSAGE_AND, j, FALSE );
  1349. PrintMessage( g_debug, IDS_MESSAGE_EXCLUSIVE );
  1350. hr = ERROR_BAD_ARGUMENTS;
  1351. }
  1352. }
  1353. }
  1354. }
  1355. if( Commands[i].bDefined && (Commands[i].fFlag & VARG_FLAG_LITERAL) ){
  1356. LPTSTR strValues;
  1357. LPTSTR strCheck;
  1358. LPTSTR strArg;
  1359. BOOL bFound = FALSE;
  1360. switch( Commands[i].fType ){
  1361. case VARG_TYPE_MSZ:
  1362. case VARG_TYPE_STR:
  1363. strArg = Commands[i].strValue;
  1364. while( strArg != NULL && !(Commands[i].fFlag & VARG_FLAG_BADSYNTAX) ){
  1365. ASSIGN_STRING( strValues, Commands[i].strParam );
  1366. if( NULL != strValues ){
  1367. strCheck = _tcstok( strValues, _T("<>[]|") );
  1368. while( !bFound && strCheck != NULL ){
  1369. if( _tcsicmp( strCheck, strArg ) == 0 ){
  1370. bFound = TRUE;
  1371. break;
  1372. }
  1373. strCheck = _tcstok( NULL, _T("<>[]|") );
  1374. }
  1375. }
  1376. VARG_FREE( strValues );
  1377. if( !bFound ){
  1378. Commands[i].fFlag |= VARG_FLAG_BADSYNTAX;
  1379. hr = ERROR_BAD_ARGUMENTS;
  1380. }
  1381. if( Commands[i].fType == VARG_TYPE_MSZ ){
  1382. strArg += _tcslen( strArg ) + 1;
  1383. bFound = FALSE;
  1384. if( *strArg == _T('\0') ){
  1385. strArg = NULL;
  1386. }
  1387. }else{
  1388. strArg = NULL;
  1389. }
  1390. }
  1391. break;
  1392. default:
  1393. hr = ERROR_INVALID_PARAMETER;
  1394. }
  1395. }
  1396. }
  1397. for(i=0; Commands[i].fType != VARG_TYPE_LAST;i++){
  1398. if( Commands[i].fFlag & VARG_FLAG_VERB ){
  1399. if( Commands[i].bDefined ){
  1400. nDefinedVerbs++;
  1401. }
  1402. bVerbs = TRUE;
  1403. }
  1404. if( (Commands[i].fFlag & VARG_FLAG_REQUIRED) && !Commands[i].bDefined){
  1405. PrintParam( IDS_MESSAGE_MISSING, i, TRUE );
  1406. hr = ERROR_BAD_ARGUMENTS;
  1407. }
  1408. if( Commands[i].fFlag & VARG_FLAG_BADSYNTAX ){
  1409. PrintParam( IDS_MESSAGE_BADSYNTAX, i, TRUE );
  1410. hr = ERROR_BAD_ARGUMENTS;
  1411. }
  1412. }
  1413. if( bVerbs && nDefinedVerbs == 0 ){
  1414. PrintMessage( g_debug, IDS_MESSAGE_NOVERB );
  1415. hr = ERROR_BAD_ARGUMENTS;
  1416. }
  1417. return hr;
  1418. }
  1419. /*****************************************************************************\
  1420. Utility Functions
  1421. \*****************************************************************************/
  1422. HRESULT GetUserInput( LPTSTR strBuffer, ULONG lSize, BOOL bEcho )
  1423. {
  1424. TCHAR c;
  1425. UCHAR a;
  1426. ULONG i = 0;
  1427. BOOL bDone = FALSE;
  1428. HANDLE hInput = NULL;
  1429. DWORD dwSize;
  1430. DWORD dwMode;
  1431. hInput = GetStdHandle( STD_INPUT_HANDLE );
  1432. GetConsoleMode( hInput, &dwMode);
  1433. SetConsoleMode( hInput, (~(ENABLE_ECHO_INPUT|ENABLE_LINE_INPUT)) & dwMode);
  1434. while( !bDone ){
  1435. if( (GetFileType(hInput) & ~FILE_TYPE_REMOTE) != FILE_TYPE_CHAR ){
  1436. BOOL bRead = ReadFile( hInput, &a, 1, &dwSize, NULL );
  1437. if( 0 == dwSize || !bRead ){
  1438. c = _T('\n');
  1439. }else{
  1440. MultiByteToChar( a, c );
  1441. if( _T('\r') == c ){
  1442. bRead = ReadFile( hInput, &a, 1, &dwSize, NULL );
  1443. }
  1444. }
  1445. }else{
  1446. ReadConsole( hInput, &c, 1, &dwSize, NULL );
  1447. }
  1448. switch( c ){
  1449. case 8:
  1450. if( i > 0 ){
  1451. strBuffer[i--] = _T('\0');
  1452. if(bEcho){
  1453. _tprintf( _T("%c %c"), c, c );
  1454. }
  1455. }
  1456. break;
  1457. case 3:
  1458. FreeCmd();
  1459. SetConsoleMode(hInput, dwMode);
  1460. exit(0);
  1461. case _T('\r'):
  1462. case _T('\n'):
  1463. bDone = TRUE;
  1464. varg_printf( g_normal, _T("\n") );
  1465. break;
  1466. default:
  1467. if( i < (lSize-1) ){
  1468. strBuffer[i++] = (TCHAR)c;
  1469. if( bEcho ){
  1470. varg_printf( g_normal, _T("%1!c!"), c );
  1471. }
  1472. }
  1473. }
  1474. }
  1475. SetConsoleMode(hInput, dwMode);
  1476. if( i > lSize ){
  1477. return ERROR_INSUFFICIENT_BUFFER;
  1478. }else{
  1479. strBuffer[i] = _T('\0');
  1480. }
  1481. return ERROR_SUCCESS;
  1482. }
  1483. HRESULT
  1484. CheckFile( LPTSTR strFile, DWORD dwFlags )
  1485. {
  1486. HRESULT hr = ERROR_SUCCESS;
  1487. HANDLE hFile;
  1488. hFile = CreateFile(
  1489. strFile,
  1490. GENERIC_READ,
  1491. FILE_SHARE_READ | FILE_SHARE_WRITE,
  1492. NULL,
  1493. OPEN_EXISTING,
  1494. FILE_ATTRIBUTE_NORMAL,
  1495. NULL
  1496. );
  1497. if( hFile == INVALID_HANDLE_VALUE){
  1498. hr = GetLastError();
  1499. }
  1500. CloseHandle(hFile);
  1501. if( dwFlags & VARG_CF_OVERWRITE ){
  1502. if( ERROR_FILE_NOT_FOUND == hr ){
  1503. hr = ERROR_SUCCESS;
  1504. }else if( ERROR_PATH_NOT_FOUND == hr){
  1505. return hr;
  1506. }else if( dwFlags & VARG_CF_PROMPT ){
  1507. TCHAR buffer[MAXSTR] = _T("");
  1508. TCHAR yes[16];
  1509. PrintMessage( g_normal, IDS_CF_OVERWRITE, strFile );
  1510. GetUserInput( buffer, MAXSTR, TRUE );
  1511. LoadString( NULL, IDS_ARG_YES, yes, 16 );
  1512. if( FindString( buffer, yes ) ){
  1513. hr = ERROR_SUCCESS;
  1514. }else{
  1515. hr = ERROR_ALREADY_EXISTS;
  1516. }
  1517. }
  1518. }
  1519. return hr;
  1520. }
  1521. HRESULT
  1522. ExpandFiles( LPTSTR* mszFiles, BOOL bMultiple )
  1523. {
  1524. LPTSTR strFiles = NULL;
  1525. LPTSTR strExpand;
  1526. TCHAR buffer[_MAX_PATH];
  1527. TCHAR drive[_MAX_DRIVE];
  1528. TCHAR dir[_MAX_DIR];
  1529. TCHAR fname[_MAX_FNAME];
  1530. TCHAR ext[_MAX_EXT];
  1531. HANDLE hFile = NULL;
  1532. strExpand = *mszFiles;
  1533. while( strExpand != NULL && *strExpand != _T('\0')){
  1534. WIN32_FIND_DATA file;
  1535. _tsplitpath( strExpand, drive, dir, fname, ext );
  1536. hFile = FindFirstFile( strExpand, &file );
  1537. if( hFile != INVALID_HANDLE_VALUE){
  1538. do{
  1539. if( !( !_tcscmp(file.cFileName, _T(".") ) || !_tcscmp(file.cFileName, _T("..")) ) ){
  1540. _tmakepath( buffer, drive, dir, file.cFileName, _T("") );
  1541. AddStringToMsz( &strFiles, buffer );
  1542. }
  1543. }while( FindNextFile( hFile, &file ) == TRUE );
  1544. FindClose( hFile );
  1545. }else{
  1546. return GetLastError();
  1547. }
  1548. if( bMultiple ){
  1549. strExpand += _tcslen( strExpand )+1;
  1550. }else{
  1551. break;
  1552. }
  1553. }
  1554. if( NULL != strFiles ){
  1555. VARG_FREE( *mszFiles );
  1556. *mszFiles = strFiles;
  1557. }
  1558. return ERROR_SUCCESS;
  1559. }
  1560. BOOL FindString( LPTSTR strBuffer, LPTSTR strMatch )
  1561. {
  1562. BOOL bReturn = FALSE;
  1563. LPTSTR buffer;
  1564. LPTSTR match;
  1565. ASSIGN_STRING( buffer, strBuffer );
  1566. ASSIGN_STRING( match, strMatch );
  1567. if( buffer != NULL && match != NULL ){
  1568. _tcslwr( buffer );
  1569. _tcslwr( match );
  1570. if( _tcsstr( buffer, match ) ){
  1571. bReturn = TRUE;
  1572. }
  1573. }
  1574. VARG_FREE( match );
  1575. VARG_FREE( buffer );
  1576. return bReturn;
  1577. }
  1578. HRESULT
  1579. ParseTime( LPTSTR strTime, SYSTEMTIME* pstTime, BOOL bDate )
  1580. {
  1581. TCHAR buffer[MAXSTR];
  1582. TCHAR PM[9] = _T("pm");
  1583. TCHAR AM[9] = _T("am");
  1584. TCHAR strDateSep[8] = _T("/");
  1585. TCHAR strTimeSep[8] = _T(":");
  1586. ULONG l;
  1587. LPTSTR str, str2;
  1588. int nDateFormat = 0;
  1589. BOOL bValid = TRUE;
  1590. FILETIME ft;
  1591. HRESULT hr = ERROR_SUCCESS;
  1592. ZeroMemory( pstTime, sizeof( SYSTEMTIME ) );
  1593. if( GetLocaleInfo( VARG_LOCALE, LOCALE_IDATE, buffer, MAXSTR ) > 0 ){
  1594. nDateFormat = _ttoi( buffer );
  1595. }
  1596. if( GetLocaleInfo( VARG_LOCALE, LOCALE_S1159, buffer, 9 ) > 0 ){
  1597. _tcsncpy( AM, buffer, 9 );
  1598. }
  1599. if( GetLocaleInfo( VARG_LOCALE, LOCALE_S2359, buffer, 9 ) > 0 ){
  1600. _tcsncpy( PM, buffer, 9 );
  1601. }
  1602. if( GetLocaleInfo( VARG_LOCALE, LOCALE_STIME, buffer, 8 ) > 0 ){
  1603. _tcsncpy( strTimeSep, buffer, 8 );
  1604. }
  1605. if( GetLocaleInfo( VARG_LOCALE, LOCALE_SDATE, buffer, 8 ) > 0 ){
  1606. _tcsncpy( strDateSep, buffer, 8 );
  1607. }
  1608. _tcsncpy( buffer, strTime, MAXSTR );
  1609. buffer[MAXSTR-1] = _T('\0');
  1610. str = _tcstok( buffer, _T(" \n\t") );
  1611. str2 = _tcstok( NULL, _T(" \n\t") );
  1612. while( str ){
  1613. if( _tcsstr( str, strDateSep ) ){
  1614. LPTSTR strMonth = NULL;
  1615. LPTSTR strDay = NULL;
  1616. LPTSTR strYear = NULL;
  1617. switch( nDateFormat ){
  1618. case 0:
  1619. strMonth = _tcstok( str, strDateSep );
  1620. strDay = _tcstok( NULL, strDateSep );
  1621. strYear = _tcstok( NULL, strDateSep );
  1622. break;
  1623. case 1:
  1624. strDay = _tcstok( NULL, strDateSep );
  1625. strMonth = _tcstok( str, strDateSep );
  1626. strYear = _tcstok( NULL, strDateSep );
  1627. break;
  1628. case 2:
  1629. strYear = _tcstok( NULL, strDateSep );
  1630. strMonth = _tcstok( str, strDateSep );
  1631. strDay = _tcstok( NULL, strDateSep );
  1632. break;
  1633. }
  1634. if( NULL != strMonth ){
  1635. hr = ReadLong( strMonth, &l, MAXWORD );
  1636. if( ERROR_SUCCESS == hr ){
  1637. pstTime->wMonth = (WORD)l;
  1638. }
  1639. }
  1640. if( NULL != strDay ){
  1641. hr = ReadLong( strDay, &l, MAXWORD );
  1642. if( ERROR_SUCCESS == hr ){
  1643. pstTime->wDay = (WORD)l;
  1644. }
  1645. }
  1646. if( NULL != strYear ){
  1647. hr = ReadLong( strYear, &l, MAXWORD );
  1648. if( ERROR_SUCCESS == hr ){
  1649. pstTime->wYear = (WORD)l;
  1650. }
  1651. }
  1652. }else{
  1653. LPTSTR tok1 = NULL;
  1654. LPTSTR tok2 = NULL;
  1655. LPTSTR tok3 = NULL;
  1656. UINT nTok = 0;
  1657. BOOL bPM = FALSE;
  1658. BOOL bAM = FALSE;
  1659. LPTSTR szZero = _T("0");
  1660. bPM = FindString( str, PM );
  1661. bAM = FindString( str, AM );
  1662. tok1 = _tcstok( str, strTimeSep );
  1663. if( NULL != tok1 ){
  1664. nTok++;
  1665. tok2 = _tcstok( NULL, strTimeSep );
  1666. }else{
  1667. tok1 = szZero;
  1668. }
  1669. if( NULL != tok2 ){
  1670. nTok++;
  1671. tok3 = _tcstok( NULL, strTimeSep );
  1672. }else{
  1673. tok2 = szZero;
  1674. }
  1675. if( NULL != tok3 ){
  1676. nTok++;
  1677. }else{
  1678. tok3 = szZero;
  1679. }
  1680. if( bDate ){
  1681. nTok = 3;
  1682. }
  1683. switch( nTok ){
  1684. case 1:
  1685. hr = ReadLong( tok1, &l, MAXWORD );
  1686. if( ERROR_SUCCESS == hr ){
  1687. pstTime->wSecond = (WORD)l;
  1688. }
  1689. break;
  1690. case 2:
  1691. hr = ReadLong( tok1, &l, MAXWORD );
  1692. if( ERROR_SUCCESS == hr ){
  1693. pstTime->wMinute = (WORD)l;
  1694. hr = ReadLong( tok2, &l, MAXWORD );
  1695. if( ERROR_SUCCESS == hr ){
  1696. pstTime->wSecond = (WORD)l;
  1697. }
  1698. }
  1699. break;
  1700. case 3:
  1701. hr = ReadLong( tok1, &l, MAXWORD );
  1702. if( ERROR_SUCCESS == hr ){
  1703. pstTime->wHour = (WORD)l;
  1704. hr = ReadLong( tok2, &l, MAXWORD );
  1705. if( ERROR_SUCCESS == hr ){
  1706. pstTime->wMinute = (WORD)l;
  1707. hr = ReadLong( tok3, &l, MAXWORD );
  1708. if( ERROR_SUCCESS == hr ){
  1709. pstTime->wSecond = (WORD)l;
  1710. }
  1711. }
  1712. }
  1713. break;
  1714. }
  1715. if( ERROR_SUCCESS == hr ){
  1716. if( bPM ){
  1717. if( pstTime->wHour < 12 ){
  1718. pstTime->wHour += 12;
  1719. }else if( pstTime->wHour > 12 ){
  1720. PrintMessage( g_debug, IDS_MESSAGE_BADTIME, PM );
  1721. }
  1722. }
  1723. if( bAM ){
  1724. if( pstTime->wHour > 12 ){
  1725. PrintMessage( g_debug, IDS_MESSAGE_BADTIME, AM );
  1726. }
  1727. }
  1728. }
  1729. }
  1730. str = str2;
  1731. str2 = NULL;
  1732. }
  1733. if( bDate && ERROR_SUCCESS == hr ){
  1734. bValid = SystemTimeToFileTime( pstTime, &ft );
  1735. if( !bValid ){
  1736. hr = GetLastError();
  1737. }
  1738. }
  1739. return hr;
  1740. }
  1741. void PrintError( HRESULT hr )
  1742. {
  1743. PrintErrorEx( hr, NULL );
  1744. }
  1745. void PrintErrorEx( HRESULT hr, LPTSTR strModule, ... )
  1746. {
  1747. LPVOID lpMsgBuf = NULL;
  1748. HINSTANCE hModule = NULL;
  1749. DWORD dwFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER;
  1750. va_list args;
  1751. va_start( args, strModule );
  1752. if(hr == 0){
  1753. hr = GetLastError();
  1754. }
  1755. if( strModule != NULL ){
  1756. hModule = LoadLibrary( strModule );
  1757. }
  1758. if ( NULL != hModule ) {
  1759. dwFlags |= FORMAT_MESSAGE_FROM_HMODULE;
  1760. }else{
  1761. dwFlags |= FORMAT_MESSAGE_FROM_SYSTEM;
  1762. }
  1763. FormatMessage(
  1764. dwFlags,
  1765. hModule,
  1766. hr,
  1767. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  1768. (LPTSTR)&lpMsgBuf,
  1769. MAXSTR,
  1770. &args
  1771. );
  1772. if ( NULL != hModule ) {
  1773. FreeLibrary( hModule );
  1774. }
  1775. if( g_nDebug >= 0 ){
  1776. PrintMessage( g_debug, IDS_MESSAGE_ERROR_DBG, hr );
  1777. }else{
  1778. PrintMessage( g_debug, IDS_MESSAGE_ERROR );
  1779. }
  1780. if( NULL == lpMsgBuf ){
  1781. PrintMessage( g_debug, IDS_MESSAGE_UNKNOWN );
  1782. }else{
  1783. varg_printf( g_debug, _T("%1!s!\n"), (LPTSTR)lpMsgBuf );
  1784. }
  1785. LocalFree( lpMsgBuf );
  1786. }
  1787. int
  1788. PrintDateEx( SHORT color, SYSTEMTIME* st )
  1789. {
  1790. TCHAR buffer[MAXSTR];
  1791. TCHAR strDateSep[8] = _T("/");
  1792. TCHAR strTimeSep[8] = _T(":");
  1793. int nDateFormat = 0;
  1794. int nOut = 0;
  1795. if( GetLocaleInfo( VARG_LOCALE, LOCALE_IDATE, buffer, MAXSTR ) > 0 ){
  1796. nDateFormat = _ttoi( buffer );
  1797. }
  1798. if( GetLocaleInfo( VARG_LOCALE, LOCALE_STIME, buffer, 8 ) > 0 ){
  1799. _tcscpy( strTimeSep, buffer );
  1800. }
  1801. if( GetLocaleInfo( VARG_LOCALE, LOCALE_SDATE, buffer, 8 ) > 0 ){
  1802. _tcscpy( strDateSep, buffer );
  1803. }
  1804. if( st->wMonth ){
  1805. switch( nDateFormat ){
  1806. case 0:
  1807. nOut = varg_printf( color, _T("%1!d!%2!s!%3!d!%4!s!%5!d! "),
  1808. st->wMonth,
  1809. strDateSep,
  1810. st->wDay,
  1811. strDateSep,
  1812. st->wYear
  1813. );
  1814. break;
  1815. case 1:
  1816. nOut = varg_printf( color, _T("%1!d!%2!s!%3!d!%4!s!%5!d! "),
  1817. st->wDay,
  1818. strDateSep,
  1819. st->wMonth,
  1820. strDateSep,
  1821. st->wYear
  1822. );
  1823. break;
  1824. case 2:
  1825. nOut = varg_printf( color, _T("%1!d!%2!s!%3!d!%4!s!%5!d! "),
  1826. st->wYear,
  1827. strDateSep,
  1828. st->wMonth,
  1829. strDateSep,
  1830. st->wDay
  1831. );
  1832. break;
  1833. }
  1834. }
  1835. nOut += varg_printf( color, _T("%1!d!%2!s!%3!02d!%4!s!%5!02d!"),
  1836. st->wHour,
  1837. strTimeSep,
  1838. st->wMinute,
  1839. strTimeSep,
  1840. st->wSecond
  1841. );
  1842. return nOut;
  1843. }
  1844. void PrintDate( SYSTEMTIME* st )
  1845. {
  1846. PrintDateEx( g_normal, st );
  1847. }
  1848. /*****************************************************************************\
  1849. VSetThreadUILanguage
  1850. This routine sets the thread UI language based on the console codepage.
  1851. 9-29-00 WeiWu Created.
  1852. 6-19-01 coreym Adapted from Base\Win32\Winnls so that it works in W2K
  1853. \*****************************************************************************/
  1854. LANGID WINAPI
  1855. VSetThreadUILanguage(WORD wReserved)
  1856. {
  1857. //
  1858. // Cache system locale and CP info
  1859. //
  1860. static LCID s_lidSystem = 0;
  1861. static UINT s_uiSysCp = 0;
  1862. static UINT s_uiSysOEMCp = 0;
  1863. ULONG uiUserUICp = 0;
  1864. ULONG uiUserUIOEMCp = 0;
  1865. TCHAR szData[16];
  1866. LANGID lidUserUI = GetUserDefaultUILanguage();
  1867. LCID lcidThreadOld = GetThreadLocale();
  1868. //
  1869. // Set default thread locale to EN-US
  1870. //
  1871. // This allow us to fall back to English UI to avoid trashed characters
  1872. // when console doesn't meet the criteria of rendering native UI.
  1873. //
  1874. LCID lcidThread = MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT);
  1875. UINT uiConsoleCp = GetConsoleOutputCP();
  1876. //
  1877. // Get cached system locale and CP info.
  1878. //
  1879. if (!s_uiSysCp) {
  1880. LCID lcidSystem = GetSystemDefaultLCID();
  1881. if (lcidSystem) {
  1882. //
  1883. // Get ANSI CP
  1884. //
  1885. GetLocaleInfo(lcidSystem, LOCALE_IDEFAULTANSICODEPAGE, szData, sizeof(szData)/sizeof(TCHAR));
  1886. uiUserUICp = _ttol(szData);
  1887. //
  1888. // Get OEM CP
  1889. //
  1890. GetLocaleInfo(lcidSystem, LOCALE_IDEFAULTCODEPAGE, szData, sizeof(szData)/sizeof(TCHAR));
  1891. s_uiSysOEMCp = _ttol(szData);
  1892. //
  1893. // Cache system primary langauge
  1894. //
  1895. s_lidSystem = PRIMARYLANGID(LANGIDFROMLCID(lcidSystem));
  1896. }
  1897. }
  1898. //
  1899. // Don't cache user UI language and CP info, UI language can be changed without system reboot.
  1900. //
  1901. if (lidUserUI) {
  1902. GetLocaleInfo(MAKELCID(lidUserUI,SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, szData, sizeof(szData)/sizeof(TCHAR));
  1903. uiUserUICp = _ttol(szData);
  1904. GetLocaleInfo(MAKELCID(lidUserUI,SORT_DEFAULT), LOCALE_IDEFAULTCODEPAGE, szData, sizeof(szData)/sizeof(TCHAR));
  1905. uiUserUIOEMCp = _ttol(szData);
  1906. }
  1907. //
  1908. // Complex scripts cannot be rendered in the console, so we
  1909. // force the English (US) resource.
  1910. //
  1911. if (uiConsoleCp &&
  1912. s_lidSystem != LANG_ARABIC &&
  1913. s_lidSystem != LANG_HEBREW &&
  1914. s_lidSystem != LANG_VIETNAMESE &&
  1915. s_lidSystem != LANG_THAI) {
  1916. //
  1917. // Use UI language for console only when console CP, system CP and UI language CP match.
  1918. //
  1919. if ((uiConsoleCp == s_uiSysCp || uiConsoleCp == s_uiSysOEMCp) &&
  1920. (uiConsoleCp == uiUserUICp || uiConsoleCp == uiUserUIOEMCp)) {
  1921. lcidThread = MAKELCID(lidUserUI, SORT_DEFAULT);
  1922. }
  1923. }
  1924. //
  1925. // Set the thread locale if it's different from the currently set
  1926. // thread locale.
  1927. //
  1928. if ((lcidThread != lcidThreadOld) && (!SetThreadLocale(lcidThread))) {
  1929. lcidThread = lcidThreadOld;
  1930. }
  1931. //
  1932. // Return the thread locale that was set.
  1933. //
  1934. return (LANGIDFROMLCID(lcidThread));
  1935. }