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.

1386 lines
44 KiB

  1. /*++
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. Choice.c
  5. Abstract:
  6. Choice is a Win32 console application designed to duplicate
  7. the functionality of the choice.com utility found in MSDOS version
  8. 6.0. Rather than simply using the C run-time routines, choice
  9. utilizes Win32 console routines and the signalling abilities of the
  10. file objects.
  11. Author:
  12. Wipro Technologies 2-July.-2001 (Created it)
  13. Revision History:
  14. --*/
  15. #include "pch.h"
  16. #include "choice.h"
  17. DWORD
  18. __cdecl wmain(
  19. IN DWORD argc,
  20. IN LPCWSTR argv[] )
  21. /*++
  22. Routine description : Main function which calls all the other main functions
  23. depending on the option specified by the user.
  24. Arguments:
  25. [in] argc : argument count specified at the command prompt.
  26. [in] argv : arguments specified at the command prompt.
  27. Return Value : DWORD
  28. 0 : If the utility successfully performs the operation.
  29. 1 : If the utility is unsuccessful in performing the specified
  30. operation.
  31. --*/
  32. {
  33. TCMDPARSER2 cmdOptions[ MAX_COMMANDLINE_OPTION ]; //command line options
  34. WCHAR szChoice[MAX_STRING_LENGTH] ; // to store options for /c
  35. WCHAR szMessage[256] ; // Message to be shown for
  36. WCHAR szPromptStr[512] ;//Message finaly prompted
  37. WCHAR szDefaultChoice[256] ; //default choice string
  38. WCHAR wszBuffer[2*MAX_RES_STRING] ;
  39. BOOL bShowChoice = FALSE;//choice to be shown or not
  40. BOOL bCaseSensitive = FALSE; // choice will be case sensitive or not
  41. BOOL bUsage = FALSE; // is help required
  42. LONG lTimeoutFactor = 0; //Time out factor
  43. BOOL bReturn = FALSE; // Stores the return value
  44. DWORD lReturnValue = EXIT__FAILURE; // Return value of application
  45. BOOL bErrorOnCarriageReturn = FALSE;
  46. HRESULT hr;
  47. SecureZeroMemory(szChoice, MAX_STRING_LENGTH * sizeof(WCHAR));
  48. SecureZeroMemory(szMessage, 256 * sizeof(WCHAR));
  49. SecureZeroMemory(szPromptStr, 512 * sizeof(WCHAR));
  50. SecureZeroMemory(szDefaultChoice, 256 * sizeof(WCHAR));
  51. SecureZeroMemory(wszBuffer, (2*MAX_RES_STRING) * sizeof(WCHAR));
  52. bReturn = ProcessCMDLine( argc,
  53. argv,
  54. &cmdOptions[ 0 ], // Command line struct
  55. &bUsage, // Is help
  56. szChoice, // Choice
  57. &bCaseSensitive, // Casesensitive
  58. &bShowChoice, // Show Choice
  59. &lTimeoutFactor, // Timeout factor
  60. szDefaultChoice, // Timeout choice
  61. szMessage // Message
  62. );
  63. if( FALSE == bReturn)
  64. {
  65. // Show Error message on screen depending on Reason Set
  66. ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
  67. // Release all global memory allocation. This allocation are done
  68. // by common functionality.
  69. ReleaseGlobals();
  70. return EXIT__FAILURE;
  71. }
  72. if ( TRUE == bUsage)
  73. {
  74. ShowUsage(); // Display Usage
  75. // Release all global memory allocation. This allocation are done
  76. // by common functionality.
  77. ReleaseGlobals();
  78. return EXIT_SUCCESS;
  79. }
  80. // Check if timeout factor is 0
  81. bReturn = BuildPrompt( cmdOptions,
  82. bShowChoice,
  83. szChoice,
  84. szMessage,
  85. szPromptStr); // Show message on Prompt.
  86. if (FALSE == bReturn)
  87. {
  88. // Release all global memory allocation. This allocation are done
  89. // by common functionality.
  90. ReleaseGlobals();
  91. return EXIT__FAILURE;
  92. }
  93. if((cmdOptions[ ID_TIMEOUT_FACTOR ].dwActuals > 0) &&
  94. ( 0 == lTimeoutFactor ))
  95. {
  96. // Release all global memory allocation. This allocation are done
  97. // by common functionality.
  98. // Safely return from utility
  99. SecureZeroMemory(wszBuffer, 2*MAX_STRING_LENGTH);
  100. hr = StringCchPrintf(wszBuffer, SIZE_OF_ARRAY(wszBuffer), L"%s%s\n", _X(szPromptStr), _X2(szDefaultChoice));
  101. if(FAILED(hr))
  102. {
  103. SetLastError(HRESULT_CODE(hr));
  104. return EXIT__FAILURE;
  105. }
  106. ShowMessage(stdout,wszBuffer);
  107. ReleaseGlobals();
  108. return UniStrChr( szChoice, szDefaultChoice[0] );
  109. }
  110. // Now wait for input OR expire of timeout
  111. lReturnValue = GetChoice( szPromptStr,
  112. lTimeoutFactor,
  113. bCaseSensitive,
  114. szChoice,
  115. szDefaultChoice,
  116. &bErrorOnCarriageReturn);
  117. if(EXIT__FAILURE == lReturnValue)
  118. {
  119. if(bErrorOnCarriageReturn == FALSE)
  120. {
  121. // Show Error message on screen depending on Reason Set
  122. StringCopyW( szPromptStr, GetReason(), 2*MAX_STRING_LENGTH );
  123. if(StringLengthW(szPromptStr, 0) == 0)
  124. {
  125. ShowMessage(stderr, szPromptStr);
  126. ShowMessage(stderr, GetResString(IDS_FILE_EMPTY));
  127. }
  128. else
  129. {
  130. hr = StringCchPrintf(szPromptStr, SIZE_OF_ARRAY(szPromptStr), L"\n%s %s", TAG_ERROR, GetReason());
  131. if(FAILED(hr))
  132. {
  133. SetLastError(HRESULT_CODE(hr));
  134. return EXIT__FAILURE;
  135. }
  136. ShowMessage(stderr, szPromptStr);
  137. }
  138. }
  139. else
  140. {
  141. ShowMessage(stderr, GetReason());
  142. }
  143. // Release all global memory allocation. This allocation are done
  144. // by common functionality.
  145. ReleaseGlobals();
  146. return EXIT__FAILURE;
  147. }
  148. // Release all global memory allocation. This allocation are done
  149. // by common functionality.
  150. ReleaseGlobals();
  151. return lReturnValue;
  152. }
  153. // End of function wmain
  154. BOOL
  155. ProcessCMDLine(
  156. IN DWORD argc,
  157. IN LPCWSTR argv[],
  158. OUT TCMDPARSER2 *pcmdParcerHead,
  159. OUT PBOOL pbUsage,
  160. OUT LPWSTR pszChoice,
  161. OUT PBOOL pbCaseSensitive,
  162. OUT PBOOL pbShowChoice,
  163. OUT PLONG plTimeOutFactor,
  164. OUT LPWSTR pszDefaultChoice,
  165. OUT LPWSTR pszMessage)
  166. /*++
  167. Routine Description:
  168. This function will prepare column structure for DoParseParam Function.
  169. Arguments:
  170. IN argc : Command line argument count
  171. IN argv : Command line argument
  172. OUT pcmdParcerHead : Pointer to Command line parcer structure
  173. OUT pbUsage : Stores the status if help required
  174. OUT pszChoice : Stores choices given
  175. OUT pbCaseSensitive : Stores the status if choices are case-sensitive
  176. OUT pbShowChoice : Stores the status if choices to be shown
  177. OUT plTimeOutFactor : Stores time out factor
  178. OUT pszDefaultChoice : Stores default choices
  179. OUT pszMessage : Stores message string
  180. Return Value:
  181. TRUE : Return successfully
  182. FALSE: Return due to error
  183. --*/
  184. {
  185. BOOL bReturn = FALSE;// strore return value
  186. WCHAR szErrorMsg[64] ;
  187. WCHAR szCharac[2] ;
  188. WCHAR szTemp[128] ;
  189. WCHAR szTimeFactor[MAX_STRING_LENGTH] ;
  190. TCMDPARSER2* pcmdParcer = NULL;
  191. TCMDPARSER2* pcmdTmp = NULL;
  192. DWORD dw =0;
  193. DWORD dwVal =0;
  194. DWORD dwcount = 0;
  195. DWORD dwLen = 0;
  196. WCHAR* pszStopTimeFactor = NULL;
  197. HRESULT hr;
  198. const WCHAR* wszOptionHelp = L"?"; //OPTION_HELP
  199. const WCHAR* wszOptionChoice = L"C" ; //OPTION_CHOICE
  200. const WCHAR* wszOptionPromptChoice = L"N" ; //OPTION_PROMPT_CHOICE
  201. const WCHAR* wszOptionCaseSensitive = L"CS" ; //OPTION_CASE_SENSITIVE
  202. const WCHAR* wszOptionDefaultChoice = L"D" ; //wszOptionDefaultChoice
  203. const WCHAR* wszOptionTimeoutFactor = L"T" ; //OPTION_TIMEOUT_FACTOR
  204. const WCHAR* wszOptionDefaultString = L"M" ; //OPTION_DEFAULT_STRING
  205. SecureZeroMemory(szErrorMsg, 64 * sizeof(WCHAR));
  206. SecureZeroMemory(szCharac, 2 * sizeof(WCHAR));
  207. SecureZeroMemory(szTemp, 128 * sizeof(WCHAR));
  208. SecureZeroMemory(szTimeFactor, MAX_STRING_LENGTH * sizeof(WCHAR));
  209. // Check validity of Pointer
  210. if( (NULL == pcmdParcerHead) ||
  211. (NULL == pbUsage) ||
  212. (NULL == pszChoice) ||
  213. (NULL == pbCaseSensitive) ||
  214. (NULL == pbShowChoice) ||
  215. (NULL == plTimeOutFactor) ||
  216. (NULL == pszDefaultChoice) ||
  217. (NULL == pszMessage))
  218. {
  219. SetLastError( RPC_X_NULL_REF_POINTER );
  220. SaveLastError();
  221. return bReturn;
  222. }
  223. // Filling m_cmdOptions structure
  224. // -?
  225. pcmdParcer = pcmdParcerHead + ID_HELP;
  226. StringCopyA( pcmdParcer->szSignature, "PARSER2\0", 8 );
  227. pcmdParcer-> dwType = CP_TYPE_BOOLEAN;
  228. pcmdParcer-> pwszOptions = wszOptionHelp;
  229. pcmdParcer-> pwszFriendlyName = NULL;
  230. pcmdParcer-> pwszValues = NULL;
  231. pcmdParcer->dwFlags = CP2_USAGE;
  232. pcmdParcer->dwCount = 1;
  233. pcmdParcer->dwActuals = 0;
  234. pcmdParcer->pValue = pbUsage;
  235. pcmdParcer->dwLength = MAX_STRING_LENGTH;
  236. pcmdParcer-> pFunction = NULL;
  237. pcmdParcer-> pFunctionData = NULL;
  238. pcmdParcer-> dwReserved = 0;
  239. pcmdParcer-> pReserved1 = NULL;
  240. pcmdParcer-> pReserved2 = NULL;
  241. pcmdParcer-> pReserved3 = NULL;
  242. // -c choices
  243. pcmdParcer = pcmdParcerHead + ID_CHOICE;
  244. StringCopyA( pcmdParcer-> szSignature, "PARSER2\0", 8 );
  245. pcmdParcer-> dwType = CP_TYPE_TEXT;
  246. pcmdParcer-> pwszOptions = wszOptionChoice;
  247. pcmdParcer-> pwszFriendlyName = NULL;
  248. pcmdParcer-> pwszValues = NULL;
  249. pcmdParcer->dwFlags = 0;
  250. pcmdParcer->dwCount = 1;
  251. pcmdParcer->dwActuals = 0;
  252. pcmdParcer->pValue = pszChoice;
  253. pcmdParcer->dwLength = MAX_STRING_LENGTH;
  254. pcmdParcer->pFunction = NULL;
  255. pcmdParcer->pFunctionData = NULL;
  256. pcmdParcer-> dwReserved = 0;
  257. pcmdParcer-> pReserved1 = NULL;
  258. pcmdParcer-> pReserved2 = NULL;
  259. pcmdParcer-> pReserved3 = NULL;
  260. //-n Show choice
  261. pcmdParcer = pcmdParcerHead + ID_PROMPT_CHOICE;
  262. StringCopyA( pcmdParcer-> szSignature, "PARSER2\0", 8 );
  263. pcmdParcer-> dwType = CP_TYPE_BOOLEAN;
  264. pcmdParcer-> pwszOptions = wszOptionPromptChoice;
  265. pcmdParcer-> pwszFriendlyName = NULL;
  266. pcmdParcer-> pwszValues = NULL;
  267. pcmdParcer->dwFlags = 0;
  268. pcmdParcer->dwCount = 1;
  269. pcmdParcer->dwActuals = 0;
  270. pcmdParcer->pValue = pbShowChoice;
  271. pcmdParcer->dwLength = MAX_STRING_LENGTH;
  272. pcmdParcer->pFunction = NULL;
  273. pcmdParcer->pFunctionData = NULL;
  274. pcmdParcer-> dwReserved = 0;
  275. pcmdParcer-> pReserved1 = NULL;
  276. pcmdParcer-> pReserved2 = NULL;
  277. pcmdParcer-> pReserved3 = NULL;
  278. // -cs case sensitive
  279. pcmdParcer = pcmdParcerHead + ID_CASE_SENSITIVE;
  280. StringCopyA( pcmdParcer-> szSignature, "PARSER2\0", 8 );
  281. pcmdParcer-> dwType = CP_TYPE_BOOLEAN;
  282. pcmdParcer-> pwszOptions = wszOptionCaseSensitive;
  283. pcmdParcer-> pwszFriendlyName = NULL;
  284. pcmdParcer-> pwszValues = NULL;
  285. pcmdParcer->dwFlags = 0;
  286. pcmdParcer->dwCount = 1;
  287. pcmdParcer->dwActuals = 0;
  288. pcmdParcer->pValue = pbCaseSensitive;
  289. pcmdParcer->dwLength = MAX_STRING_LENGTH;
  290. pcmdParcer->pFunction = NULL;
  291. pcmdParcer->pFunctionData = NULL;
  292. pcmdParcer-> dwReserved = 0;
  293. pcmdParcer-> pReserved1 = NULL;
  294. pcmdParcer-> pReserved2 = NULL;
  295. pcmdParcer-> pReserved3 = NULL;
  296. // -d default choice
  297. pcmdParcer = pcmdParcerHead + ID_DEFAULT_CHOICE;
  298. StringCopyA( pcmdParcer-> szSignature, "PARSER2\0", 8 );
  299. pcmdParcer-> dwType = CP_TYPE_TEXT;
  300. pcmdParcer-> pwszOptions = wszOptionDefaultChoice;
  301. pcmdParcer-> pwszFriendlyName = NULL;
  302. pcmdParcer-> pwszValues = NULL;
  303. pcmdParcer->dwFlags = CP2_VALUE_TRIMINPUT;
  304. pcmdParcer->dwCount = 1;
  305. pcmdParcer->dwActuals = 0;
  306. pcmdParcer->pValue = pszDefaultChoice;
  307. pcmdParcer->dwLength = MAX_STRING_LENGTH;
  308. pcmdParcer->pFunction = NULL;
  309. pcmdParcer->pFunctionData = NULL;
  310. pcmdParcer-> dwReserved = 0;
  311. pcmdParcer-> pReserved1 = NULL;
  312. pcmdParcer-> pReserved2 = NULL;
  313. pcmdParcer-> pReserved3 = NULL;
  314. // -t time-out factor
  315. pcmdParcer = pcmdParcerHead + ID_TIMEOUT_FACTOR;
  316. StringCopyA( pcmdParcer-> szSignature, "PARSER2\0", 8 );
  317. pcmdParcer-> dwType = CP_TYPE_TEXT;
  318. pcmdParcer-> pwszOptions = wszOptionTimeoutFactor;
  319. pcmdParcer-> pwszFriendlyName = NULL;
  320. pcmdParcer-> pwszValues = NULL;
  321. pcmdParcer->dwFlags = CP2_VALUE_TRIMINPUT;
  322. pcmdParcer->dwCount = 1;
  323. pcmdParcer->dwActuals = 0;
  324. pcmdParcer->pValue = szTimeFactor;
  325. pcmdParcer->dwLength = MAX_STRING_LENGTH;
  326. pcmdParcer->pFunction = NULL;
  327. pcmdParcer->pFunctionData = NULL;
  328. pcmdParcer-> dwReserved = 0;
  329. pcmdParcer-> pReserved1 = NULL;
  330. pcmdParcer-> pReserved2 = NULL;
  331. pcmdParcer-> pReserved3 = NULL;
  332. // -m message text
  333. pcmdParcer = pcmdParcerHead + ID_MESSAGE_STRING;
  334. StringCopyA( pcmdParcer-> szSignature, "PARSER2\0", 8 );
  335. pcmdParcer-> dwType = CP_TYPE_TEXT;
  336. pcmdParcer-> pwszOptions = wszOptionDefaultString;
  337. pcmdParcer-> pwszFriendlyName = NULL;
  338. pcmdParcer-> pwszValues = NULL;
  339. pcmdParcer->dwFlags = CP2_VALUE_TRIMINPUT;
  340. pcmdParcer->dwCount = 1;
  341. pcmdParcer->dwActuals = 0;
  342. pcmdParcer->pValue = pszMessage;
  343. pcmdParcer->dwLength = MAX_STRING_LENGTH;
  344. pcmdParcer->pFunction = NULL;
  345. pcmdParcer->pFunctionData = NULL;
  346. pcmdParcer-> dwReserved = 0;
  347. pcmdParcer-> pReserved1 = NULL;
  348. pcmdParcer-> pReserved2 = NULL;
  349. pcmdParcer-> pReserved3 = NULL;
  350. // re-assign it to head position
  351. pcmdParcer = pcmdParcerHead;
  352. bReturn = DoParseParam2( argc, argv, -1, MAX_COMMANDLINE_OPTION, pcmdParcer, 0);
  353. if( FALSE == bReturn) // Invalid commandline
  354. {
  355. // Reason is already set by DoParseParam
  356. return FALSE;
  357. }
  358. if( TRUE == *pbUsage )
  359. {
  360. if(2 == argc )
  361. {
  362. return( TRUE );
  363. }
  364. else
  365. {
  366. StringCopyW( szErrorMsg, GetResString( IDS_INCORRECT_SYNTAX ), SIZE_OF_ARRAY(szErrorMsg) );
  367. SetReason( szErrorMsg );
  368. return FALSE;
  369. }
  370. }
  371. // /d can be specified only if /t is specified.
  372. pcmdParcer = pcmdParcerHead + ID_DEFAULT_CHOICE;
  373. pcmdTmp = pcmdParcerHead + ID_TIMEOUT_FACTOR;
  374. if((pcmdParcer-> dwActuals > 0 ) &&( 0 == pcmdTmp-> dwActuals ))
  375. {
  376. // Error String will be ..
  377. //Invalid syntax. /D can be specified only when /T is
  378. //specified.
  379. //Type CHOICE /? for usage.
  380. StringCopyW( szTemp, GetResString( IDS_D_WITHOUT_T ), SIZE_OF_ARRAY(szTemp) );
  381. // Set the reason in memory
  382. SetReason(szTemp);
  383. return FALSE;
  384. }
  385. // /f should come if /d is given
  386. pcmdParcer = pcmdParcerHead + ID_DEFAULT_CHOICE;
  387. pcmdTmp = pcmdParcerHead + ID_TIMEOUT_FACTOR;
  388. if(( 0 == pcmdParcer-> dwActuals ) &&( pcmdTmp-> dwActuals > 0 ) )
  389. {
  390. // Error String will be ..
  391. // Invalid syntax. /D missing.
  392. // Type CHOICE /? for usage.
  393. StringCopyW( szTemp, GetResString( IDS_D_MISSING ), SIZE_OF_ARRAY(szTemp) );
  394. // Set the reason in memory
  395. SetReason(szTemp);
  396. return FALSE;
  397. }
  398. // Time factor value should be in range TIMEOUT_MIN - TIMEOUT_MAX
  399. pcmdParcer = pcmdParcerHead + ID_DEFAULT_CHOICE;
  400. if(pcmdParcer-> dwActuals > 0 && szTimeFactor != NULL && StringLengthW(szTimeFactor, 0) == 0)
  401. {
  402. StringCopyW( szTemp, GetResString( IDS_TFACTOR_NULL_STIRNG ), SIZE_OF_ARRAY(szTemp) );
  403. // Set the reason in memory
  404. SetReason(szTemp);
  405. return FALSE;
  406. }
  407. *plTimeOutFactor = wcstol(szTimeFactor,&pszStopTimeFactor,10);
  408. if((errno == ERANGE) || (NULL != pszStopTimeFactor && StringLengthW(pszStopTimeFactor, 0) != 0))
  409. {
  410. StringCopyW( szTemp, GetResString( IDS_INVALID_TIMEOUT_FACTOR ), SIZE_OF_ARRAY(szTemp) );
  411. SetReason(szTemp);
  412. return FALSE;
  413. }
  414. if( pcmdParcer-> dwActuals > 0 &&
  415. (( *plTimeOutFactor < TIMEOUT_MIN)||
  416. ( *plTimeOutFactor > TIMEOUT_MAX )))
  417. {
  418. // Error String will be ..
  419. // Invalid syntax. Valid range for /t is (0 - 99).
  420. // Type CHOICE /? for usage.
  421. hr = StringCchPrintf(szTemp, SIZE_OF_ARRAY(szTemp), GetResString(IDS_T_INVALID_VALUE),TIMEOUT_MIN,TIMEOUT_MAX);
  422. if(FAILED(hr))
  423. {
  424. SetLastError(HRESULT_CODE(hr));
  425. SaveLastError();
  426. return FALSE;
  427. }
  428. // Set the reason in memory
  429. SetReason(szTemp);
  430. return FALSE;
  431. }
  432. // if /c is specified then it cannot be empty
  433. pcmdParcer = pcmdParcerHead + ID_CHOICE;
  434. if( pcmdParcer-> dwActuals > 0 && (StringLengthW( pszChoice, 0 ) == 0))
  435. {
  436. // Error String will be ..
  437. // Invalid syntax. Choice cannot be empty.
  438. StringCopyW( szTemp, GetResString( IDS_C_EMPTY ), SIZE_OF_ARRAY(szTemp) );
  439. // Set the reason in memory
  440. SetReason(szTemp);
  441. return FALSE;
  442. }
  443. if( pcmdParcer-> dwActuals > 0)
  444. {
  445. dwVal = StringLengthW( pszChoice, 0 );
  446. for(dwcount;dwcount < dwVal;dwcount++)
  447. {
  448. szCharac[0] = pszChoice[dwcount];
  449. szCharac[1] = '\0';
  450. if((dwLen = StringLengthInBytes(szCharac)) > 1)
  451. {
  452. StringCopyW( szTemp, GetResString( IDS_TWO_BYTES_NOTALLOWED ), SIZE_OF_ARRAY(szTemp) );
  453. // Set the reason in memory
  454. SetReason(szTemp);
  455. return FALSE;
  456. }
  457. }
  458. for(dw;dw < dwVal;dw++)
  459. {
  460. if( ((DWORD)pszChoice[dw]) <= 47 ||
  461. (((DWORD)pszChoice[dw]) > 122 &&((DWORD)pszChoice[dw]) < 127)||
  462. (((DWORD)pszChoice[dw]) > 57 &&((DWORD)pszChoice[dw]) < 65 ) ||
  463. (((DWORD)pszChoice[dw]) > 90 &&((DWORD)pszChoice[dw]) < 97 ) ||
  464. ((DWORD)pszChoice[dw]) == 160)
  465. {
  466. StringCopyW( szTemp, GetResString( IDS_CHOICE_INVALID ), SIZE_OF_ARRAY(szTemp) );
  467. // Set the reason in memory
  468. SetReason(szTemp);
  469. return FALSE;
  470. }
  471. }
  472. }
  473. // if /c is not specified then make default choice as "YN"
  474. pcmdParcer = pcmdParcerHead + ID_CHOICE;
  475. if(0 == pcmdParcer-> dwActuals)
  476. {
  477. StringCopyW( pszChoice, DEFAULT_CHOICE, MAX_STRING_LENGTH);
  478. }
  479. pcmdParcer = pcmdParcerHead + ID_CHOICE;
  480. if((pcmdParcer-> dwActuals > 0 ) && ( FALSE == *pbCaseSensitive ))
  481. {
  482. dw = 0;
  483. for(dw;dw < dwVal;dw++)
  484. {
  485. if( ((DWORD)pszChoice[dw]) <= 127 )
  486. {
  487. if(0 == CharUpperBuff( pszChoice+dw, 1))
  488. {
  489. StringCopyW( szTemp, GetResString( IDS_ERR_CHARUPPER ), SIZE_OF_ARRAY(szTemp) );
  490. // Set the reason in memory
  491. SetReason(szTemp);
  492. return FALSE;
  493. }
  494. }
  495. }
  496. }
  497. //now check for duplicates in choice
  498. if(FALSE == CheckforDuplicates( pszChoice ) )
  499. {
  500. StringCopyW( szTemp, GetResString( IDS_DUPLICATE_CHOICE ), SIZE_OF_ARRAY(szTemp) );
  501. // Set the reason in memory
  502. SetReason(szTemp);
  503. return FALSE;
  504. }
  505. pcmdParcer = pcmdParcerHead + ID_DEFAULT_CHOICE;
  506. if( pcmdParcer-> dwActuals > 0 )
  507. {
  508. if(0 == StringLengthW( pszDefaultChoice, 0 ))
  509. {
  510. StringCopyW( szTemp, GetResString( IDS_DEFAULT_EMPTY ), SIZE_OF_ARRAY(szTemp) );
  511. // Set the reason in memory
  512. SetReason(szTemp);
  513. return FALSE;
  514. }
  515. if( FALSE == *pbCaseSensitive )
  516. {
  517. // Make the string to upper case
  518. if( ((DWORD)pszDefaultChoice[0]) <= 127 )
  519. {
  520. if( 0 == CharUpperBuff( pszDefaultChoice, StringLengthW( pszDefaultChoice, 0 )))
  521. {
  522. StringCopyW( szTemp, GetResString( IDS_ERR_CHARUPPER ), SIZE_OF_ARRAY(szTemp) );
  523. // Set the reason in memory
  524. SetReason(szTemp);
  525. return FALSE;
  526. }
  527. }
  528. }
  529. }
  530. // length of /d cannot be more than one character
  531. pcmdParcer = pcmdParcerHead + ID_DEFAULT_CHOICE;
  532. if(( pcmdParcer-> dwActuals > 0 ) &&(StringLengthW( pszDefaultChoice, 0 ) > 1 ))
  533. {
  534. // Error String will be ..
  535. // Invalid syntax. /D7/2/2001 accepts only single character.
  536. // Type CHOICE /? for usage.
  537. StringCopyW( szTemp, GetResString( IDS_D_BIG ), SIZE_OF_ARRAY(szTemp) );
  538. // Set the reason in memory
  539. SetReason(szTemp);
  540. return FALSE;
  541. }
  542. // check if timeout choice is given in choice list
  543. pcmdParcer = pcmdParcerHead + ID_DEFAULT_CHOICE;
  544. if (pcmdParcer-> dwActuals > 0 )
  545. {
  546. if(0 == UniStrChr( pszChoice, pszDefaultChoice[ 0 ] ))
  547. {
  548. // Error String will be ..
  549. // Invalid syntax. Time Factor choice not in specified choices.
  550. // Type CHOICE /? for usage.
  551. StringCopyW( szTemp, GetResString( IDS_D_NOT_MATCHED_TO_C ), SIZE_OF_ARRAY(szTemp) );
  552. // Set the reason in memory
  553. SetReason( szTemp );
  554. return FALSE;
  555. }
  556. }
  557. pcmdParcer = pcmdParcerHead + ID_MESSAGE_STRING;
  558. if(pcmdParcer-> dwActuals > 0)
  559. {
  560. if( StringLengthW(pszMessage, 0) > MAX_STRING_LENGTH )
  561. {
  562. StringCopyW( szTemp, GetResString( IDS_MESSAGE_OVERFLOW ), SIZE_OF_ARRAY(szTemp) );
  563. SetReason( szTemp );
  564. return FALSE;
  565. }
  566. }
  567. return TRUE;
  568. }
  569. // End of function ProcessCMDLine
  570. void
  571. ShowUsage( void )
  572. /*--
  573. Routine Description
  574. This function shows help message for CHOICE
  575. Arguments:
  576. NONE
  577. Return Value
  578. None
  579. --*/
  580. {
  581. DWORD dwIndx = 0; // Index Variable
  582. for(dwIndx = IDS_HELP1; dwIndx <= IDS_HELP_END; dwIndx++ )
  583. {
  584. ShowMessage( stdout, GetResString( dwIndx ) );
  585. }
  586. return;
  587. }
  588. // End of function ShowUsage
  589. BOOL
  590. BuildPrompt(
  591. IN TCMDPARSER2 *pcmdParcer,
  592. IN BOOL bShowChoice,
  593. IN LPWSTR pszChoice,
  594. IN LPWSTR pszMessage,
  595. OUT LPWSTR pszPromptStr)
  596. /*++
  597. Routine Description:
  598. This function will Build command message prompt
  599. Arguments:
  600. [IN] pcmdParcer : Pointer to Command line parcer structure
  601. [IN] bShowChoice : Stores the status, if choice to be shown
  602. [IN] pszChoice : Choice string
  603. [IN] pszMessage : Message String
  604. [OUT] pszPromptStr : Final String to be shown on screen
  605. Return Value:
  606. TRUE if success
  607. FALSE if failure
  608. --*/
  609. {
  610. WCHAR szChar[32] ;
  611. LPWSTR pszTemp = NULL; // Temp. string pointer
  612. SecureZeroMemory(szChar, 32 * sizeof(WCHAR));
  613. // Check for validity of pointer variables
  614. if (( NULL == pcmdParcer) ||
  615. ( NULL == pszPromptStr))
  616. {
  617. return FALSE;
  618. }
  619. szChar[1] = NULL_U_CHAR; // make second character as end of line
  620. // check if /M is given if given copy it to prompt string
  621. pcmdParcer += ID_MESSAGE_STRING;
  622. if( pcmdParcer-> dwActuals > 0 )
  623. {
  624. StringCopyW( pszPromptStr, pszMessage, 2*MAX_STRING_LENGTH );
  625. StringConcat(pszPromptStr, SPACE, 2*MAX_STRING_LENGTH);
  626. }
  627. if( TRUE == bShowChoice )
  628. {
  629. return TRUE;
  630. }
  631. // now append '[' to it
  632. StringConcat(pszPromptStr, OPEN_BRACKET, 2*MAX_STRING_LENGTH);
  633. // now append prompt characters to it
  634. pszTemp = pszChoice;
  635. do
  636. {
  637. szChar[ 0 ] = pszTemp[ 0 ]; // always assing first character of
  638. //m_pszChoice as first character is
  639. // changing in this loop
  640. StringConcat(pszPromptStr, szChar, 2*MAX_STRING_LENGTH);
  641. // now append a COMMA to this
  642. // comma will be appended only if length of m_pszChoise
  643. // is grester than 1
  644. if( StringLengthW( pszTemp, 0 ) > 1 )
  645. {
  646. StringConcat(pszPromptStr, COMMA, 2*MAX_STRING_LENGTH);
  647. }
  648. pszTemp = CharNext( pszTemp );
  649. }while( StringLengthW( pszTemp, 0 ) != 0);
  650. // now close the bracket
  651. StringConcat(pszPromptStr, CLOSED_BRACKET, 2*MAX_STRING_LENGTH);
  652. return TRUE;
  653. }
  654. // End of function BuildPrompt
  655. DWORD
  656. UniStrChr(
  657. IN LPWSTR pszBuf,
  658. IN WCHAR szChar
  659. )
  660. /*++
  661. Routine Description:
  662. This function finds the character in given string
  663. Arguments:
  664. [IN] pszBuf : Target String in which character is be find
  665. [IN] szChar : Character to be found
  666. Return Value:
  667. returned string pointer after the character found.
  668. --*/
  669. {
  670. LONG lPos = 0;
  671. // find the character in string
  672. while( NULL_U_CHAR != *pszBuf ) // Loop till string teminated character found
  673. // 0 is always teminated character
  674. {
  675. lPos++;
  676. if ( *(pszBuf++) == szChar )
  677. {
  678. return(lPos) ;
  679. }
  680. }
  681. return(0);
  682. }
  683. // End of function UniStrChr
  684. DWORD
  685. GetChoice(
  686. IN LPCWSTR pszPromptStr,
  687. IN LONG lTimeOutFactor,
  688. IN BOOL bCaseSensitive,
  689. IN LPWSTR pszChoice,
  690. IN LPCWSTR pszDefaultChoice,
  691. OUT PBOOL pbErrorOnCarriageReturn)
  692. /*++
  693. Routine Description:
  694. This function get choice from console OR wait for timeout
  695. Arguments:
  696. IN pszPromptStr : String to be shown as prompt
  697. IN lTimeOutFactor : Time out factor
  698. IN bCaseSensitive : Stores the state, if choice is case-sensitive
  699. IN pszChoice : Choice string
  700. IN pszDefaultChoice : Default choice character
  701. OUT pbErrorOnCarriageReturn : True, if there is an error on carriage return
  702. Return Value:
  703. DWORD
  704. --*/
  705. {
  706. //This function reads the keyboard and handles the I/O
  707. HANDLE hInput = 0;// Stores the input handle device
  708. HANDLE hOutput = 0;// Stores the output handle device
  709. DWORD dwSignal = 0;// Stores return value for WaitForSingleObject
  710. DWORD dwBytesRead = 0;// Stores number of byes read from console
  711. DWORD dwBytesRead2 = 0;// Stores number of byes read from console
  712. DWORD dwMode = 0;// Stores mode for input device
  713. DWORD lTimeBefore = 0;
  714. DWORD lTimeAfter = 0;
  715. DWORD lPosition = 0;
  716. DWORD dwRead = 0L;
  717. BOOL bSuccess = FALSE; // Stores return value
  718. BOOL bStatus = TRUE;
  719. BOOL bIndirectionInput = FALSE;
  720. BOOL bGetChoice = FALSE;
  721. WCHAR szTempChar = NULL_U_CHAR; // Temperory variable
  722. WCHAR szTempBuf[ MAX_RES_STRING ] = L"\0"; // Temp. string variable
  723. CHAR chTmp = '\0';
  724. WCHAR wchTmp = NULL_U_CHAR;
  725. CHAR szAnsiBuf[ 10 ] = "\0"; // buffer of two characters is enough -- but still
  726. INPUT_RECORD InputBuffer[ MAX_NUM_RECS ] = {0};
  727. SecureZeroMemory(szTempBuf, MAX_RES_STRING * sizeof(WCHAR));
  728. // Get handle for Input device
  729. hInput = GetStdHandle( STD_INPUT_HANDLE );
  730. if( INVALID_HANDLE_VALUE == hInput)
  731. {
  732. SaveLastError();
  733. return EXIT__FAILURE;
  734. }
  735. if( ( hInput != (HANDLE)0x0000000F )&&( hInput != (HANDLE)0x00000003 ) && ( hInput != INVALID_HANDLE_VALUE ) )
  736. {
  737. bIndirectionInput = TRUE;
  738. }
  739. // Get handle for Output device
  740. hOutput = GetStdHandle( STD_OUTPUT_HANDLE );
  741. if( INVALID_HANDLE_VALUE == hOutput )
  742. {
  743. SaveLastError();
  744. return EXIT__FAILURE;
  745. }
  746. // Get console mode, so we can change the input mode
  747. bSuccess = GetConsoleMode( hInput, &dwMode );
  748. if ( TRUE == bSuccess)
  749. {
  750. // turn off line input and echo
  751. dwMode &= ~( ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT );
  752. bSuccess = SetConsoleMode( hInput, dwMode );
  753. if (FALSE == bSuccess)
  754. {
  755. SaveLastError();
  756. return EXIT__FAILURE;
  757. }
  758. if ( FlushConsoleInputBuffer( hInput ) == FALSE )
  759. {
  760. SaveLastError();
  761. return EXIT__FAILURE;
  762. }
  763. }
  764. // Show prompt message on screen.....
  765. ShowMessage( stdout, _X(pszPromptStr) );
  766. bStatus = SetConsoleCtrlHandler( &HandlerRoutine, TRUE );
  767. if ( FALSE == bStatus )
  768. {
  769. SaveLastError();
  770. return EXIT__FAILURE;
  771. }
  772. // init the ANSI buffer with 0's in it
  773. ZeroMemory( szAnsiBuf, SIZE_OF_ARRAY( szAnsiBuf ) * sizeof( CHAR ) );
  774. while( FALSE == bGetChoice)
  775. {
  776. //The WaitForSingleObject function returns when one of the
  777. // following occurs:
  778. // 1. The specified object is in the signaled state i.e. Key press
  779. // from keyboard
  780. // 2.The time-out interval elapses.
  781. lTimeBefore = GetTickCount();
  782. dwSignal = WaitForSingleObject( hInput,
  783. ( lTimeOutFactor ) ?
  784. ( lTimeOutFactor * MILI_SEC_TO_SEC_FACTOR)
  785. : INFINITE );
  786. lTimeAfter = GetTickCount();
  787. switch(dwSignal)
  788. {
  789. case WAIT_OBJECT_0: // The input buffer has something
  790. { // get first character
  791. szTempBuf[ 1 ] = NULL_U_CHAR;
  792. // Get character from console
  793. if ( bIndirectionInput == FALSE )
  794. {
  795. if( PeekConsoleInput(hInput, InputBuffer, MAX_NUM_RECS, &dwRead ) == FALSE )
  796. {
  797. SaveLastError();
  798. ReleaseGlobals();
  799. return( EXIT__FAILURE );
  800. }
  801. //Ignore all the virtual keys like tab,break,scroll lock etc...
  802. if(((InputBuffer[0].Event.KeyEvent.wVirtualKeyCode >= VK_LEFT)
  803. && (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode <= VK_DOWN))
  804. || (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_HOME)
  805. || (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_END)
  806. || (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_INSERT)
  807. || (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_DELETE)
  808. ||(InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_PRIOR)
  809. ||(InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_NEXT)
  810. ||(InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_TAB)
  811. ||(InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_SPACE))
  812. {
  813. if( lTimeOutFactor )
  814. {
  815. lTimeOutFactor -= ( DWORD )(( lTimeAfter - lTimeBefore) / MILI_SEC_TO_SEC_FACTOR);
  816. }
  817. if(0 == Beep( FREQUENCY_IN_HERTZ, DURETION_IN_MILI_SEC ))
  818. {
  819. if(TRUE == IsConsoleFile(stdout))
  820. {
  821. ShowMessage(stdout, L"\a");
  822. }
  823. }
  824. if ( FlushConsoleInputBuffer( hInput ) == FALSE )
  825. {
  826. SaveLastError();
  827. return EXIT__FAILURE;
  828. }
  829. break;
  830. }
  831. else if((InputBuffer[0].Event.KeyEvent.wVirtualKeyCode >= VK_F1)
  832. && (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode <= VK_F16)
  833. || (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)
  834. || ((InputBuffer[0].Event.KeyEvent.wVirtualKeyCode >= VK_LBUTTON)
  835. && (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode <= VK_XBUTTON2))
  836. ||(InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_PAUSE)
  837. ||(InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_CAPITAL)
  838. ||(InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_NUMLOCK)
  839. ||(InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_SCROLL)
  840. || ((InputBuffer[0].Event.KeyEvent.wVirtualKeyCode >= VK_SELECT)
  841. && (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode <= VK_SNAPSHOT))
  842. || (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_HELP)
  843. || (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_LWIN)
  844. || (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_RWIN)
  845. || (InputBuffer[0].Event.KeyEvent.wVirtualKeyCode == VK_APPS)
  846. )
  847. {
  848. if( lTimeOutFactor )
  849. {
  850. lTimeOutFactor -= ( DWORD )(( lTimeAfter - lTimeBefore) / MILI_SEC_TO_SEC_FACTOR);
  851. }
  852. if ( FlushConsoleInputBuffer( hInput ) == FALSE )
  853. {
  854. SaveLastError();
  855. return EXIT__FAILURE;
  856. }
  857. break;
  858. }
  859. //Ignore changing the focus,doing alt+tab etc..
  860. if(FOCUS_EVENT == InputBuffer[0].EventType
  861. || (VK_MENU == InputBuffer[0].Event.KeyEvent.wVirtualKeyCode )
  862. ||(VK_CONTROL == InputBuffer[0].Event.KeyEvent.wVirtualKeyCode)
  863. ||(VK_SHIFT == InputBuffer[0].Event.KeyEvent.wVirtualKeyCode)
  864. ||WINDOW_BUFFER_SIZE_EVENT == InputBuffer[0].EventType
  865. ||MOUSE_EVENT == InputBuffer[0].EventType
  866. ||MENU_EVENT == InputBuffer[0].EventType
  867. ||(FALSE == InputBuffer[0].Event.KeyEvent.bKeyDown))
  868. {
  869. if( lTimeOutFactor )
  870. {
  871. lTimeOutFactor -= ( DWORD )(( lTimeAfter - lTimeBefore) / MILI_SEC_TO_SEC_FACTOR);
  872. }
  873. if ( FlushConsoleInputBuffer( hInput ) == FALSE )
  874. {
  875. SaveLastError();
  876. return EXIT__FAILURE;
  877. }
  878. break;
  879. }
  880. StringCopyW( szTempBuf, NULL_U_STRING, MAX_RES_STRING );
  881. bSuccess = ReadConsole(hInput,
  882. szTempBuf,
  883. MAX_RES_STRING,
  884. &dwBytesRead,
  885. NULL);
  886. if ( FALSE == bSuccess)
  887. {
  888. SaveLastError();
  889. return EXIT__FAILURE;
  890. }
  891. }
  892. else
  893. {
  894. //read the contents of file
  895. if ( ReadFile(hInput, &chTmp, 1, &dwBytesRead, NULL) == FALSE )
  896. {
  897. if(ERROR_BROKEN_PIPE == GetLastError())
  898. {
  899. // End of the pipe is reached, so inform the caller
  900. *pbErrorOnCarriageReturn = TRUE;
  901. StringCopyW( szTempBuf, GetResString(IDS_FILE_EMPTY), MAX_RES_STRING );
  902. SetReason( szTempBuf );
  903. }
  904. else
  905. {
  906. SaveLastError();
  907. }
  908. return EXIT__FAILURE;
  909. }
  910. else
  911. {
  912. szAnsiBuf[ 0 ] = chTmp;
  913. dwBytesRead2 = SIZE_OF_ARRAY( szTempBuf );
  914. GetAsUnicodeString2( szAnsiBuf, szTempBuf, &dwBytesRead2 );
  915. wchTmp = szTempBuf[ 0 ];
  916. }
  917. if ( (dwBytesRead == 0)) //|| wchTmp == CARRIAGE_RETURN))
  918. {
  919. if((StringLengthW((LPWSTR)pszDefaultChoice, 0)) != 0)
  920. {
  921. WaitForSingleObject( hInput,( lTimeOutFactor * MILI_SEC_TO_SEC_FACTOR));
  922. ShowMessage( stdout, _X(pszDefaultChoice) );
  923. ShowMessage( stdout, _X(END_OF_LINE) );
  924. return UniStrChr( pszChoice, pszDefaultChoice[0] );
  925. }
  926. else
  927. {
  928. *pbErrorOnCarriageReturn = TRUE;
  929. StringCopyW( szTempBuf, GetResString(IDS_FILE_EMPTY), MAX_RES_STRING );
  930. SetReason( szTempBuf );
  931. return EXIT__FAILURE;
  932. }
  933. }
  934. szTempBuf[0] = wchTmp;
  935. }
  936. //exit if non ascii character is given
  937. if( ((DWORD)szTempBuf[0]) <= 47 ||
  938. (((DWORD)szTempBuf[0])> 122 &&((DWORD)szTempBuf[0])< 127)||
  939. (((DWORD)szTempBuf[0])> 57 &&((DWORD)szTempBuf[0])< 65 ) ||
  940. (((DWORD)szTempBuf[0])> 90 &&((DWORD)szTempBuf[0])< 97 ) ||
  941. ((DWORD)szTempBuf[0])== 255)
  942. {
  943. if(0 == Beep( FREQUENCY_IN_HERTZ, DURETION_IN_MILI_SEC ))
  944. {
  945. if(TRUE == IsConsoleFile(stdout))
  946. {
  947. ShowMessage( stdout, L"\a" );
  948. }
  949. }
  950. if ( FALSE == bIndirectionInput && FlushConsoleInputBuffer( hInput ) == FALSE )
  951. {
  952. SaveLastError();
  953. return EXIT__FAILURE;
  954. }
  955. if( lTimeOutFactor )
  956. {
  957. lTimeOutFactor -= ( DWORD )( lTimeAfter - lTimeBefore) / MILI_SEC_TO_SEC_FACTOR;
  958. }
  959. break;
  960. }
  961. if ( FALSE == bCaseSensitive )
  962. {
  963. if( ((DWORD)szTempBuf[0]) <= 127 )
  964. {
  965. if(0 == CharUpperBuff( szTempBuf, 1 ))
  966. {
  967. StringCopyW( szTempBuf, GetResString(IDS_ERR_CHARUPPER), MAX_RES_STRING );
  968. // Set the reason in memory
  969. SetReason(szTempBuf);
  970. return EXIT__FAILURE;
  971. }
  972. }
  973. }
  974. szTempChar = szTempBuf[ 0 ]; // Get first character
  975. lPosition = UniStrChr( pszChoice, szTempChar );
  976. szTempBuf[ 1 ] = NULL_U_CHAR; // Make second character as NULL
  977. if (0 != lPosition)
  978. {
  979. StringCchPrintfW( szTempBuf,SIZE_OF_ARRAY(szTempBuf), L"%c\n", szTempChar );
  980. // show the input character on output console
  981. ShowMessage( stdout, _X(szTempBuf) );
  982. return lPosition;
  983. }
  984. else // Character enterted not matches with Specified choice
  985. {
  986. if(0 == Beep( FREQUENCY_IN_HERTZ, DURETION_IN_MILI_SEC ))
  987. {
  988. if(TRUE == IsConsoleFile(stdout))
  989. {
  990. ShowMessage( stdout, L"\a" );
  991. }
  992. }
  993. if ( FALSE == bIndirectionInput && FlushConsoleInputBuffer( hInput ) == FALSE )
  994. {
  995. SaveLastError();
  996. return EXIT__FAILURE;
  997. }
  998. if( lTimeOutFactor )
  999. {
  1000. lTimeOutFactor -= ( DWORD )( lTimeAfter - lTimeBefore) / MILI_SEC_TO_SEC_FACTOR;
  1001. }
  1002. }
  1003. }
  1004. break;
  1005. case WAIT_TIMEOUT: // The timeout exhausted
  1006. {
  1007. // Show timeout message on screen
  1008. ShowMessage( stdout, _X(pszDefaultChoice) );
  1009. ShowMessage( stdout, _X(END_OF_LINE) );
  1010. return UniStrChr( pszChoice, pszDefaultChoice[0] );
  1011. }
  1012. break;
  1013. default:
  1014. break;
  1015. }
  1016. }
  1017. return EXIT__FAILURE;
  1018. }
  1019. // End of function GetChoice
  1020. BOOL
  1021. CheckforDuplicates( IN LPWSTR lpszChoice
  1022. )
  1023. /*++
  1024. Routine Description:
  1025. This function checks for the duplicate choices
  1026. Arguments:
  1027. IN lpszChoice : The list of choices in which the duplication of choice is to be checked
  1028. Return Value:
  1029. TRUE on success and FALSE on failure
  1030. --*/
  1031. {
  1032. WCHAR wTemp = NULL_U_CHAR;
  1033. while( lpszChoice[0] )
  1034. {
  1035. wTemp = lpszChoice[0];
  1036. lpszChoice++;
  1037. if( NULL != wcschr( lpszChoice, wTemp ) )
  1038. return FALSE;
  1039. }
  1040. return TRUE;
  1041. }
  1042. //end of checkforDuplicate function
  1043. BOOL WINAPI HandlerRoutine(
  1044. DWORD dwCtrlType
  1045. )
  1046. /*++
  1047. Routine Description:
  1048. This function handles the control key CTRL+C and CTRL+BREAK.
  1049. Arguments:
  1050. IN dwCtrlType : Error control type
  1051. Return Value:
  1052. TRUE on success and FALSE on failure
  1053. --*/
  1054. {
  1055. // check for CTRL+C key
  1056. if ( ( dwCtrlType == CTRL_C_EVENT ) ||( dwCtrlType == CTRL_BREAK_EVENT ) )
  1057. {
  1058. exit ( FALSE);
  1059. }
  1060. // for remaining keys return false
  1061. return TRUE;
  1062. }