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.

715 lines
23 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. Timeout.c
  5. Abstract:
  6. This file implements the parsing of the command line for the arguments and also the
  7. wait functionality.
  8. Author:
  9. EricB
  10. Revision History:
  11. 26-Aug-1991 Created by EricB.
  12. 10-Mar-1992 Added the _getch() call to flush the hit key.
  13. 17-Apr-1992 Added countdown display.
  14. 03-Oct-1992 Ported to NT/Win32
  15. 23-May-1995 Added Sleep call
  16. 14-Jun-2001 localization added by Wipro Technologies
  17. 01-Aug-2001 Added /nobreak option by Wipro Technologies
  18. --*/
  19. #include "pch.h"
  20. #include "Timeout.h"
  21. #include "Resource.h"
  22. DWORD _cdecl
  23. wmain(
  24. IN DWORD argc,
  25. IN LPCWSTR argv[]
  26. )
  27. /*++
  28. Routine Description:
  29. This is main entry point to this utility. Different function calls are made
  30. from here to achieve the required functionality.
  31. Arguments:
  32. [in] argc : Number of Command line arguments.
  33. [in] argv : Pointer to Command line arguments.
  34. Return Value:
  35. 0 on success
  36. 1 on failure.
  37. --*/
  38. {
  39. //local variables
  40. CONSOLE_SCREEN_BUFFER_INFO csbi;
  41. time_t tWait = 0L;
  42. time_t tLast = 0L;
  43. time_t tNow = 0L;
  44. time_t tEnd = 0L;
  45. DWORD dwTimeActuals = 0;
  46. BOOL bNBActuals = 0;
  47. BOOL bUsage = FALSE;
  48. BOOL bResult = FALSE;
  49. BOOL bStatus = FALSE;
  50. WCHAR wszProgressMsg[ MAX_STRING_LENGTH ] = NULL_U_STRING ;
  51. DWORD dwWidth = 0;
  52. WCHAR wszBackup[12] = NULL_U_STRING;
  53. WCHAR wszTimeout[ MAX_RES_STRING] = NULL_U_STRING;
  54. LPWSTR pszStopString = NULL;
  55. COORD coord = {0};
  56. HANDLE hOutput = NULL;
  57. HANDLE hStdIn = NULL;
  58. DWORD dwMode = 0L;
  59. DWORD dwRead = 0L;
  60. INPUT_RECORD InputBuffer[ MAX_NUM_RECS ] = {0};
  61. HRESULT hr = S_OK;
  62. if ( NULL == argv )
  63. {
  64. SetLastError (ERROR_INVALID_PARAMETER );
  65. SaveLastError();
  66. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  67. return EXIT_FAILURE;
  68. }
  69. // Parse the command line and get the actual values
  70. bResult = ProcessOptions( argc, argv, &bUsage, &dwTimeActuals, wszTimeout , &bNBActuals );
  71. if( FALSE == bResult )
  72. {
  73. // display an error message with respect to the GetReason()
  74. ShowLastErrorEx ( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  75. ReleaseGlobals();
  76. return( EXIT_FAILURE );
  77. }
  78. // check for invalid syntax
  79. // 1. check for the case c:\>timeout.exe
  80. // 2. check for the case c:\>timeout.exe /nobreak
  81. // 3. check for the case c:\>timeout.exe /? /?
  82. if ( ( ( 0 == dwTimeActuals ) && ( FALSE == bNBActuals ) && ( FALSE == bUsage ) ) ||
  83. ( ( 0 == dwTimeActuals ) && ( TRUE == bNBActuals ) ) || ( ( TRUE == bUsage ) && (argc > 2 )) )
  84. {
  85. // display an error message as specified syntax is invalid
  86. ShowMessage ( stderr, GetResString (IDS_INVALID_SYNTAX) );
  87. ReleaseGlobals();
  88. return( EXIT_FAILURE );
  89. }
  90. // Check whether the usage(/?) is specified
  91. if( TRUE == bUsage )
  92. {
  93. // Display the help/usage for the tool
  94. DisplayUsage();
  95. ReleaseGlobals();
  96. return( EXIT_SUCCESS );
  97. }
  98. // get the value for timeout (/T)
  99. tWait = ( time_t ) wcstol(wszTimeout,&pszStopString,BASE_TEN);
  100. //check whether any non-numeric value specified for timeout value
  101. // if so, display appropriate error message as invalid timeout value specified.
  102. // Also, check for overflow and underflow conds
  103. if( ((NULL != pszStopString) && ( StringLength( pszStopString, 0 ) != 0 )) ||
  104. (errno == ERANGE) ||
  105. ( tWait < MIN_TIME_VAL ) || ( tWait >= MAX_TIME_VAL ) )
  106. {
  107. ShowMessage ( stderr, GetResString (IDS_ERROR_TIME_VALUE) );
  108. ReleaseGlobals();
  109. return( EXIT_FAILURE );
  110. }
  111. // Get the time elapsed in secs since midnight (00:00:00), January 1, 1970
  112. bResult = GetTimeInSecs( &tNow );
  113. if( FALSE == bResult )
  114. {
  115. ReleaseGlobals();
  116. // could not get the time so exit...
  117. return( EXIT_FAILURE );
  118. }
  119. // check for /nobreak option is specified
  120. if ( TRUE == bNBActuals )
  121. {
  122. // set console handler to capture the keys like CTRL+BREAK or CRTL+C
  123. bStatus = SetConsoleCtrlHandler( &HandlerRoutine, TRUE );
  124. if ( FALSE == bStatus )
  125. {
  126. // Format an error message accroding to GetLastError() return by API.
  127. ShowLastErrorEx( stderr, SLE_TYPE_ERROR| SLE_SYSTEM );
  128. ReleaseGlobals();
  129. // to remove the handle
  130. SetConsoleCtrlHandler( NULL, FALSE );
  131. return( EXIT_FAILURE );
  132. }
  133. }
  134. hStdIn = GetStdHandle( STD_INPUT_HANDLE );
  135. // check for the input redirection on console and telnet session
  136. if( ( hStdIn != (HANDLE)0x0000000F ) &&
  137. ( hStdIn != (HANDLE)0x00000003 ) &&
  138. ( hStdIn != INVALID_HANDLE_VALUE ) )
  139. {
  140. ShowMessage( stderr, GetResString (IDS_INVALID_INPUT_REDIRECT) );
  141. ReleaseGlobals();
  142. // to remove the handle
  143. SetConsoleCtrlHandler( NULL, FALSE );
  144. return EXIT_FAILURE;
  145. }
  146. #ifdef WIN32
  147. // Set input mode so that a single key hit can be detected.
  148. if ( GetConsoleMode( hStdIn, &dwMode ) == FALSE )
  149. {
  150. // Format an error message accroding to GetLastError() return by API.
  151. ShowLastErrorEx( stderr, SLE_TYPE_ERROR| SLE_SYSTEM );
  152. ReleaseGlobals();
  153. // to remove the handle
  154. SetConsoleCtrlHandler( NULL, FALSE );
  155. return( EXIT_FAILURE );
  156. }
  157. // Turn off the following modes:
  158. dwMode &= ~( ENABLE_LINE_INPUT | // Don't wait for CR.
  159. ENABLE_ECHO_INPUT | // Don't echo input.
  160. ENABLE_WINDOW_INPUT | // Don't record window events.
  161. ENABLE_MOUSE_INPUT // Don't record mouse events.
  162. );
  163. // set the input mode of a console's input buffer
  164. if ( SetConsoleMode( hStdIn, dwMode ) == FALSE )
  165. {
  166. // Format an error message accroding to GetLastError() return by API.
  167. ShowLastErrorEx( stderr, SLE_TYPE_ERROR| SLE_SYSTEM );
  168. ReleaseGlobals();
  169. // to remove the handle
  170. SetConsoleCtrlHandler( NULL, FALSE );
  171. return( EXIT_FAILURE );
  172. }
  173. // retrieve number of unread input records in the console's input buffer.
  174. if( GetNumberOfConsoleInputEvents( hStdIn, &dwRead ) == FALSE )
  175. {
  176. // Format an error message accroding to GetLastError() return by API.
  177. ShowLastErrorEx( stderr, SLE_TYPE_ERROR| SLE_SYSTEM );
  178. ReleaseGlobals();
  179. // to remove the handle
  180. SetConsoleCtrlHandler( NULL, FALSE );
  181. return( EXIT_FAILURE );
  182. }
  183. // clear the console input buffer
  184. if ( FALSE == FlushConsoleInputBuffer (hStdIn))
  185. {
  186. // Format an error message accroding to GetLastError() return by API.
  187. ShowLastErrorEx( stderr, SLE_TYPE_ERROR| SLE_SYSTEM );
  188. ReleaseGlobals();
  189. // to remove the handle
  190. SetConsoleCtrlHandler( NULL, FALSE );
  191. return( EXIT_FAILURE );
  192. }
  193. #endif
  194. // check whether /T value is -1. If so, need to wait indefinitely for a key press..
  195. if( -1 == tWait )
  196. {
  197. // check whether /nobreak is specified
  198. if ( FALSE == bNBActuals )
  199. {
  200. // Wait until a key hit.
  201. ShowMessage( stdout, GetResString( IDS_WAIT_MSG ) );
  202. }
  203. else // /nobreak option is not specified
  204. {
  205. // Wait until a CTRL+C key hit.
  206. ShowMessage( stdout, GetResString( IDS_NO_BREAK_MSG ) );
  207. }
  208. // Ensure infinite do loop.
  209. tEnd = tNow + 1;
  210. }
  211. else
  212. {
  213. // Wait with a timeout period.
  214. // Compute end time.
  215. tEnd = tNow + tWait;
  216. // Figure the time display dwWidth.
  217. // Need to decrement the time factor (/T) specified at a specified
  218. // location. To get the position where it needs to be decremented,
  219. // get the width of the /T value
  220. if (tWait < 10)
  221. {
  222. // if the /T value is less than 10 then set the width as 1
  223. dwWidth = 1;
  224. }
  225. else
  226. {
  227. if (tWait < 100)
  228. {
  229. // if the /T value is less than 100 then set width as 2
  230. dwWidth = 2;
  231. }
  232. else
  233. {
  234. if (tWait < 1000)
  235. {
  236. // if the /T value is less than 1000 then set width as 3
  237. dwWidth = 3;
  238. }
  239. else
  240. {
  241. if (tWait < 10000)
  242. {
  243. // if the /T value is less than 10000 then set width as 4
  244. dwWidth = 4;
  245. }
  246. else
  247. {
  248. // if the /T value is less than 100000 then set width as 5
  249. dwWidth = 5;
  250. }
  251. }
  252. }
  253. }
  254. if ( FALSE == Replicate ( wszBackup, ONE_BACK_SPACE, dwWidth, SIZE_OF_ARRAY(wszBackup)))
  255. {
  256. // Format an error message accroding to GetLastError() return by API.
  257. ShowLastErrorEx( stderr, SLE_TYPE_ERROR| SLE_INTERNAL );
  258. ReleaseGlobals();
  259. // to remove the handle
  260. SetConsoleCtrlHandler( NULL, FALSE );
  261. return( EXIT_FAILURE );
  262. }
  263. //
  264. // Initialize the console screen buffer structure to zero's
  265. // and then get the console handle and screen buffer information
  266. //
  267. SecureZeroMemory( wszProgressMsg, sizeof( WCHAR ) * MAX_STRING_LENGTH );
  268. // display the message as ..Waiting for...
  269. //ShowMessage ( stdout, GetResString (IDS_WAIT_MSG_TIME1 ) );
  270. //format the message as .. n seconds...for wait time
  271. //_snwprintf( wszProgressMsg, SIZE_OF_ARRAY(wszProgressMsg), WAIT_TIME , dwWidth, tWait );
  272. hr = StringCchPrintf( wszProgressMsg, SIZE_OF_ARRAY(wszProgressMsg), GetResString(IDS_WAIT_MSG_TIME1) , dwWidth, tWait );
  273. if ( FAILED (hr))
  274. {
  275. SetLastError (HRESULT_CODE (hr));
  276. SaveLastError();
  277. ShowLastErrorEx( stderr, SLE_TYPE_ERROR| SLE_SYSTEM );
  278. ReleaseGlobals();
  279. // to remove the handle
  280. SetConsoleCtrlHandler( NULL, FALSE );
  281. return( EXIT_FAILURE );
  282. }
  283. // print the message.
  284. ShowMessage ( stdout, wszProgressMsg );
  285. //
  286. // Initialize the console screen buffer structure to zero's
  287. // and then get the console handle and screen buffer information
  288. //
  289. SecureZeroMemory( &csbi, sizeof( CONSOLE_SCREEN_BUFFER_INFO ) );
  290. hOutput = GetStdHandle( STD_OUTPUT_HANDLE );
  291. if ( NULL != hOutput )
  292. {
  293. // Get the info of screen buffer.
  294. GetConsoleScreenBufferInfo( hOutput, &csbi );
  295. }
  296. // set the cursor position
  297. coord.X = csbi.dwCursorPosition.X;
  298. coord.Y = csbi.dwCursorPosition.Y;
  299. // check whether /nobreak is specified or not
  300. if ( FALSE == bNBActuals )
  301. {
  302. // display the message as ...press a key to continue ...
  303. ShowMessage ( stdout, GetResString (IDS_WAIT_MSG_TIME2) );
  304. }
  305. else
  306. {
  307. // display the message as ...press CTRL+C to quit...
  308. ShowMessage ( stdout, GetResString (IDS_NB_MSG_TIME) );
  309. }
  310. }
  311. do
  312. {
  313. // Break out if a key is pressed.
  314. #ifdef WIN32
  315. //reads data from the specified console input buffer without removing it from the buffer.
  316. if( PeekConsoleInput( hStdIn, InputBuffer, MAX_NUM_RECS, &dwRead ) == FALSE )
  317. {
  318. // Format an error message accroding to GetLastError() return by API.
  319. ShowLastErrorEx( stderr, SLE_TYPE_ERROR| SLE_SYSTEM );
  320. ReleaseGlobals();
  321. // to remove the handle
  322. SetConsoleCtrlHandler( NULL, FALSE );
  323. return( EXIT_FAILURE );
  324. }
  325. if (dwRead > 0)
  326. {
  327. //reads data from a console input buffer and removes it from the buffer
  328. if( ReadConsoleInput(hStdIn, InputBuffer, MAX_NUM_RECS, &dwRead ) == FALSE )
  329. {
  330. // Format an error message accroding to GetLastError() return by API.
  331. ShowLastErrorEx( stderr, SLE_TYPE_ERROR| SLE_SYSTEM );
  332. ReleaseGlobals();
  333. // to remove the handle
  334. SetConsoleCtrlHandler( NULL, FALSE );
  335. return( EXIT_FAILURE );
  336. }
  337. // Filter the input so that ctrl-c can be generated and passed on.
  338. // Also, ignore alt key presses and window focus events.
  339. if( (FOCUS_EVENT != InputBuffer[0].EventType)
  340. && (VK_CONTROL != InputBuffer[0].Event.KeyEvent.wVirtualKeyCode)
  341. && (VK_CONTROL != InputBuffer[0].Event.KeyEvent.wVirtualScanCode)
  342. && (MOUSE_MOVED != InputBuffer[0].Event.MouseEvent.dwEventFlags)
  343. && (MOUSE_WHEELED != InputBuffer[0].Event.MouseEvent.dwEventFlags)
  344. && (FALSE != InputBuffer[0].Event.KeyEvent.bKeyDown)
  345. && (VK_MENU != InputBuffer[0].Event.KeyEvent.wVirtualKeyCode)
  346. && ( FALSE == bNBActuals ) )
  347. {
  348. // exit from the loop
  349. break;
  350. }
  351. }
  352. #else
  353. //Checks the console for keyboard input.
  354. if( ( _kbhit() ) && ( FALSE == bNBActuals ) )
  355. {
  356. // get characters from the console without echo
  357. _getch();
  358. // exit from the loop
  359. break;
  360. }
  361. #endif
  362. // check if /T value is other than -1
  363. if( -1 != tWait )
  364. {
  365. // Update the time and time value display.
  366. tLast = tNow;
  367. // call the function GetTimeInSecs to get the current time in seconds
  368. bResult = GetTimeInSecs( &tNow );
  369. if( FALSE == bResult )
  370. {
  371. // Format an error message accroding to GetLastError() return by API.
  372. ReleaseGlobals();
  373. // to remove the handle
  374. SetConsoleCtrlHandler( NULL, FALSE );
  375. // could not get the time so exit...
  376. return( EXIT_FAILURE );
  377. }
  378. // check if tLast value is same as tNow.. if not, display the
  379. // message with tEnd-tNow as a wait value
  380. if (tLast != tNow)
  381. {
  382. // Print the message.
  383. SecureZeroMemory( wszProgressMsg, sizeof( WCHAR ) * MAX_STRING_LENGTH );
  384. // fromat the message
  385. //_snwprintf( wszProgressMsg, SIZE_OF_ARRAY(wszProgressMsg), STRING_FORMAT2 , wszBackup, dwWidth, tEnd - tNow );
  386. hr = StringCchPrintf( wszProgressMsg, SIZE_OF_ARRAY(wszProgressMsg), STRING_FORMAT2 , wszBackup, dwWidth, tEnd - tNow );
  387. if ( FAILED (hr))
  388. {
  389. SetLastError (HRESULT_CODE (hr));
  390. SaveLastError();
  391. ShowLastErrorEx( stderr, SLE_TYPE_ERROR| SLE_SYSTEM );
  392. ReleaseGlobals();
  393. // to remove the handle
  394. SetConsoleCtrlHandler( NULL, FALSE );
  395. return( EXIT_FAILURE );
  396. }
  397. // set the cursor position
  398. SetConsoleCursorPosition( hOutput, coord );
  399. // display the message as ..tEnd - tNow seconds.. at the current cursor location
  400. ShowMessage ( stdout, wszProgressMsg );
  401. }
  402. }
  403. #ifdef WIN32
  404. // Sleep for sometime...
  405. Sleep( 100 );
  406. #endif
  407. }while( tNow < tEnd ); //check till tNow is less than tEnd value
  408. ShowMessage ( stdout, L"\n" );
  409. // release global variables
  410. ReleaseGlobals();
  411. // to remove the handle
  412. SetConsoleCtrlHandler( NULL, FALSE );
  413. // return 0
  414. return( EXIT_SUCCESS );
  415. }
  416. BOOL
  417. GetTimeInSecs(
  418. OUT time_t *ptTime
  419. )
  420. /*++
  421. Routine Description
  422. This function calculates the time elapsed in secs since
  423. midnight (00:00:00), January 1, 1970
  424. Arguments:
  425. [out] time_t ptTime : variable to hold the time in secs
  426. Return Value
  427. TRUE on success
  428. FALSE on failure
  429. --*/
  430. {
  431. #ifdef YANK
  432. //local variables
  433. SYSTEMTIME st = {0};
  434. FILETIME ft = {0};
  435. // check for NULL
  436. if ( NULL == ptTime )
  437. {
  438. SetLastError (ERROR_INVALID_PARAMETER );
  439. SaveLastError();
  440. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  441. return FALSE;
  442. }
  443. // get the system time
  444. GetSystemTime( &st );
  445. // convert system time to file time
  446. if( SystemTimeToFileTime( &st, &ft ) == FALSE )
  447. {
  448. // Format an error message accroding to GetLastError() return by API.
  449. ShowLastErrorEx( stderr, SLE_TYPE_ERROR| SLE_SYSTEM );
  450. return( FALSE );
  451. }
  452. // need to check for LowDateTime rollover...
  453. *ptTime = ft.dwLowDateTime / LOW_DATE_TIME_ROLL_OVER;
  454. #else
  455. // This function returns the time elapsed in secs since midnight (00:00:00), January 1, 1970
  456. time( ptTime );
  457. #endif
  458. // return 0
  459. return( TRUE );
  460. }
  461. VOID
  462. DisplayUsage(
  463. VOID
  464. )
  465. /*++
  466. Routine Description
  467. This function displays the usage of this utility
  468. Arguments:
  469. NONE
  470. Return Value
  471. NONE
  472. --*/
  473. {
  474. // local variable
  475. DWORD dwIndex = 0;
  476. // Displaying main usage
  477. for( dwIndex = IDS_HELP_START; dwIndex <= IDS_HELP_END; dwIndex++ )
  478. {
  479. ShowMessage( stdout, GetResString( dwIndex ) );
  480. }
  481. return;
  482. }
  483. BOOL ProcessOptions(
  484. IN DWORD argc,
  485. IN LPCWSTR argv[],
  486. OUT BOOL *pbUsage,
  487. OUT DWORD *pwTimeActuals,
  488. OUT LPWSTR wszTimeout,
  489. OUT BOOL *pbNBActuals
  490. )
  491. /*++
  492. Routine Description
  493. This function processes the command line for the main options
  494. Arguments:
  495. [in] argc : Number of Command line arguments.
  496. [in] argv : Pointer to Command line arguments.
  497. [out] pbUsage : Flag that indicates whether the usage is to be displayed or not.
  498. [out] plTimeoutVal : contains the timeout value specified on the command line
  499. Return Value
  500. TRUE on success
  501. FALSE on failure
  502. --*/
  503. {
  504. // sub-local variables
  505. TCMDPARSER2* pcmdParser = NULL;
  506. TCMDPARSER2 cmdParserOptions[MAX_COMMANDLINE_OPTIONS];
  507. BOOL bReturn = FALSE;
  508. // command line options
  509. const WCHAR szTimeoutOpt[] = L"t";
  510. const WCHAR szNoBreakOpt[] = L"nobreak";
  511. const WCHAR szHelpOpt[] = L"?";
  512. // -? help/usage
  513. pcmdParser = cmdParserOptions + OI_USAGE;
  514. StringCopyA( pcmdParser->szSignature, "PARSER2\0", 8 );
  515. pcmdParser->dwType = CP_TYPE_BOOLEAN;
  516. pcmdParser->pwszOptions = szHelpOpt;
  517. pcmdParser->pwszFriendlyName = NULL;
  518. pcmdParser->pwszValues = NULL;
  519. pcmdParser->dwFlags = CP2_USAGE;
  520. pcmdParser->dwCount = 1;
  521. pcmdParser->dwActuals = 0;
  522. pcmdParser->pValue = pbUsage;
  523. pcmdParser->dwLength = MAX_STRING_LENGTH;
  524. pcmdParser->pFunction = NULL;
  525. pcmdParser->pFunctionData = NULL;
  526. pcmdParser->dwReserved = 0;
  527. pcmdParser->pReserved1 = NULL;
  528. pcmdParser->pReserved2 = NULL;
  529. pcmdParser->pReserved3 = NULL;
  530. // -T <timeout>
  531. pcmdParser = cmdParserOptions + OI_TIME_OUT;
  532. StringCopyA( pcmdParser->szSignature, "PARSER2\0", 8 );
  533. pcmdParser->dwType = CP_TYPE_TEXT;
  534. pcmdParser->pwszOptions = szTimeoutOpt;
  535. pcmdParser->pwszFriendlyName = NULL;
  536. pcmdParser->pwszValues = NULL;
  537. pcmdParser->dwFlags = CP2_DEFAULT|CP2_VALUE_TRIMINPUT|CP2_VALUE_NONULL;
  538. pcmdParser->dwCount = 1;
  539. pcmdParser->dwActuals = 0;
  540. pcmdParser->pValue = wszTimeout;
  541. pcmdParser->dwLength = MAX_STRING_LENGTH;
  542. pcmdParser->pFunction = NULL;
  543. pcmdParser->pFunctionData = NULL;
  544. pcmdParser->dwReserved = 0;
  545. pcmdParser->pReserved1 = NULL;
  546. pcmdParser->pReserved2 = NULL;
  547. pcmdParser->pReserved3 = NULL;
  548. // -NOBREAK
  549. pcmdParser = cmdParserOptions + OI_NB_OUT;
  550. StringCopyA( pcmdParser->szSignature, "PARSER2\0", 8 );
  551. pcmdParser->dwType = CP_TYPE_BOOLEAN;
  552. pcmdParser->pwszOptions = szNoBreakOpt;
  553. pcmdParser->pwszFriendlyName = NULL;
  554. pcmdParser->pwszValues = NULL;
  555. pcmdParser->dwFlags = 0;
  556. pcmdParser->dwCount = 1;
  557. pcmdParser->dwActuals = 0;
  558. pcmdParser->pValue = pbNBActuals;
  559. pcmdParser->dwLength = MAX_STRING_LENGTH;
  560. pcmdParser->pFunction = NULL;
  561. pcmdParser->pFunctionData = NULL;
  562. pcmdParser->dwReserved = 0;
  563. pcmdParser->pReserved1 = NULL;
  564. pcmdParser->pReserved2 = NULL;
  565. pcmdParser->pReserved3 = NULL;
  566. //
  567. // do the command line parsing and get the appropriate values
  568. //
  569. bReturn = DoParseParam2( argc, argv, -1, SIZE_OF_ARRAY(cmdParserOptions), cmdParserOptions, 0);
  570. if( FALSE == bReturn) // Invalid commandline
  571. {
  572. // Reason is already set by DoParseParam2
  573. return FALSE;
  574. }
  575. pcmdParser = cmdParserOptions + OI_TIME_OUT;
  576. // get the value for /T value
  577. *pwTimeActuals = pcmdParser->dwActuals;
  578. //return 0
  579. return TRUE;
  580. }
  581. BOOL WINAPI
  582. HandlerRoutine(
  583. IN DWORD dwCtrlType // control signal type
  584. )
  585. /*++
  586. Routine Description:
  587. This function handles the control key CTRL+C.
  588. Arguments:
  589. IN dwCtrlType : Error code value
  590. Return Value:
  591. TRUE on success and FALSE on failure
  592. --*/
  593. {
  594. // check for CTRL+C key
  595. if ( dwCtrlType == CTRL_C_EVENT )
  596. {
  597. ShowMessage ( stdout, L"\n" );
  598. // release globals
  599. ReleaseGlobals ();
  600. // to remove the handle
  601. SetConsoleCtrlHandler( NULL, FALSE );
  602. // exit 0
  603. ExitProcess ( TRUE );
  604. }
  605. // for remaining keys return false
  606. return FALSE;
  607. }