Leaked source code of windows server 2003
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.

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