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

824 lines
20 KiB

  1. /******************************************************************************
  2. Copyright(c) Microsoft Corporation
  3. Module Name:
  4. delete.cpp
  5. Abstract:
  6. This module deletes the task(s) present in the system
  7. Author:
  8. Hari 10-Sep-2000
  9. Revision History:
  10. Hari 10-Sep-2000 : Created it
  11. G.Surender Reddy 25-Sep-2000 : Modified it [added error checking]
  12. G.Surender Reddy 31-Oct-2000 : Modified it
  13. [Moved strings to resource file]
  14. G.Surender Reddy 18-Nov-2000 : Modified it
  15. [Modified usage help to be displayed]
  16. G.Surender Reddy 15-Dec-2000 : Modified it
  17. [Removed getch() fn.& used Console API
  18. to read characters]
  19. G.Surender Reddy 22-Dec-2000 : Modified it
  20. [Rewrote the DisplayDeleteUsage() fn.]
  21. G.Surender Reddy 08-Jan-2001 : Modified it
  22. [Deleted the unused variables.]
  23. ******************************************************************************/
  24. //common header files needed for this file
  25. #include "pch.h"
  26. #include "CommonHeaderFiles.h"
  27. #include <xpsp1res.h>
  28. // Function declaration for the Usage function.
  29. VOID DisplayDeleteUsage();
  30. BOOL ConfirmDelete( LPCTSTR szTaskName , PBOOL pbFalg );
  31. LPWSTR GetSpResString( UINT uID , LPWSTR lpwszBuffer);
  32. /*****************************************************************************
  33. Routine Description:
  34. This routine deletes a specified scheduled task(s)
  35. Arguments:
  36. [ in ] argc : Number of command line arguments
  37. [ in ] argv : Array containing command line arguments
  38. Return Value :
  39. A DWORD value indicating EXIT_SUCCESS on success else
  40. EXIT_FAILURE on failure
  41. *****************************************************************************/
  42. DWORD
  43. DeleteScheduledTask( DWORD argc, LPCTSTR argv[] )
  44. {
  45. // Variables used to find whether Delete main option, Usage option
  46. // or the force option is specified or not
  47. BOOL bDelete = FALSE;
  48. BOOL bUsage = FALSE;
  49. BOOL bForce = FALSE;
  50. // Set the TaskSchduler object as NULL
  51. ITaskScheduler *pITaskScheduler = NULL;
  52. // Return value
  53. HRESULT hr = S_OK;
  54. // Initialising the variables that are passed to TCMDPARSER structure
  55. _TCHAR szServer[ MAX_STRING_LENGTH ] = NULL_STRING;
  56. _TCHAR szTaskName[ MAX_STRING_LENGTH ] = NULL_STRING;
  57. _TCHAR szUser[ MAX_STRING_LENGTH ] = NULL_STRING;
  58. _TCHAR szPassword[ MAX_STRING_LENGTH ] = NULL_STRING;
  59. // For each task in all the tasks.
  60. LPCTSTR szEachTaskName = NULL;
  61. BOOL bWrongValue = FALSE;
  62. // Dynamic Array contaning array of jobs
  63. TARRAY arrJobs = NULL;
  64. // Task name or the job name which is to be deleted
  65. WCHAR wszJobName[MAX_STRING_LENGTH] ;
  66. wcscpy(wszJobName,NULL_U_STRING);
  67. // Loop Variable.
  68. DWORD dwJobCount = 0;
  69. //buffer for displaying error message
  70. TCHAR szMessage[MAX_STRING_LENGTH] = NULL_STRING;
  71. BOOL bNeedPassword = FALSE;
  72. BOOL bResult = FALSE;
  73. BOOL bCloseConnection = TRUE;
  74. lstrcpy( szPassword, ASTERIX);
  75. // Builiding the TCMDPARSER structure
  76. TCMDPARSER cmdOptions[] =
  77. {
  78. {
  79. CMDOPTION_DELETE,
  80. CP_MAIN_OPTION,
  81. 1,
  82. 0,
  83. &bDelete,
  84. NULL_STRING,
  85. NULL,
  86. NULL
  87. },
  88. {
  89. SWITCH_SERVER,
  90. CP_TYPE_TEXT | CP_VALUE_MANDATORY,
  91. 1,
  92. 0,
  93. &szServer,
  94. NULL_STRING,
  95. NULL,
  96. NULL
  97. },
  98. {
  99. SWITCH_TASKNAME,
  100. CP_TYPE_TEXT | CP_VALUE_MANDATORY | CP_MANDATORY ,
  101. 1,
  102. 0,
  103. &szTaskName,
  104. NULL_STRING,
  105. NULL,
  106. NULL
  107. },
  108. {
  109. SWITCH_FORCE,
  110. 0,
  111. 1,
  112. 0,
  113. &bForce,
  114. NULL_STRING,
  115. NULL,
  116. NULL
  117. },
  118. {
  119. CMDOPTION_USAGE,
  120. CP_USAGE ,
  121. 1,
  122. 0,
  123. &bUsage,
  124. NULL_STRING,
  125. NULL,
  126. NULL
  127. },
  128. {
  129. SWITCH_USER,
  130. CP_TYPE_TEXT | CP_VALUE_MANDATORY,
  131. OPTION_COUNT,
  132. 0,
  133. &szUser,
  134. NULL_STRING,
  135. NULL,
  136. NULL
  137. },
  138. {
  139. SWITCH_PASSWORD,
  140. CP_TYPE_TEXT | CP_VALUE_OPTIONAL,
  141. OPTION_COUNT,
  142. 0,
  143. &szPassword,
  144. NULL_STRING,
  145. NULL,
  146. NULL
  147. }
  148. };
  149. // Parsing the delete option switches
  150. if ( DoParseParam( argc, argv, SIZE_OF_ARRAY(cmdOptions), cmdOptions ) == FALSE)
  151. {
  152. DISPLAY_MESSAGE( stderr, GetResString(IDS_LOGTYPE_ERROR ));
  153. DISPLAY_MESSAGE( stderr, GetReason() );
  154. //DISPLAY_MESSAGE(stderr,GetResString(IDS_DELETE_SYNERROR));
  155. return EXIT_FAILURE;
  156. }
  157. // triming the null spaces
  158. StrTrim(szServer, TRIM_SPACES );
  159. StrTrim(szTaskName, TRIM_SPACES );
  160. StrTrim(szUser, TRIM_SPACES );
  161. //StrTrim(szPassword, TRIM_SPACES );
  162. // check whether password (-p) specified in the command line or not.
  163. if ( cmdOptions[OI_DELPASSWORD].dwActuals == 0 )
  164. {
  165. lstrcpy( szPassword, NULL_STRING );
  166. }
  167. // Displaying delete usage if user specified -? with -delete option
  168. if( bUsage == TRUE )
  169. {
  170. DisplayDeleteUsage();
  171. return EXIT_SUCCESS;
  172. }
  173. // check for the invalid server name
  174. if( ( cmdOptions[OI_DELSERVER].dwActuals == 1 ) && ( lstrlen( szServer ) == 0 ) )
  175. {
  176. DISPLAY_MESSAGE(stderr,GetResString(IDS_NO_SERVER));
  177. return RETVAL_FAIL;
  178. }
  179. // check for invalid user name
  180. if( ( cmdOptions[OI_DELSERVER].dwActuals == 0 ) && ( cmdOptions[OI_DELUSERNAME].dwActuals == 1 ) )
  181. {
  182. DISPLAY_MESSAGE(stderr, GetResString(IDS_DELETE_USER_BUT_NOMACHINE));
  183. return RETVAL_FAIL;
  184. }
  185. // check for the length of user name
  186. if( ( cmdOptions[OI_DELSERVER].dwActuals == 1 ) && ( cmdOptions[OI_DELUSERNAME].dwActuals == 1 ) &&
  187. ( lstrlen( szUser ) == 0 ) )
  188. {
  189. DISPLAY_MESSAGE(stderr, GetResString(IDS_INVALID_USERNAME));
  190. return RETVAL_FAIL;
  191. }
  192. // check whether username is specified or not along with the password
  193. if ( cmdOptions[ OI_DELUSERNAME ].dwActuals == 0 && cmdOptions[OI_DELPASSWORD].dwActuals == 1 )
  194. {
  195. // invalid syntax
  196. DISPLAY_MESSAGE(stderr, GetResString(IDS_DPASSWORD_BUT_NOUSERNAME));
  197. return RETVAL_FAIL;
  198. }
  199. // check for the length of the taskname
  200. if( ( lstrlen( szTaskName ) > MAX_JOB_LEN ) || ( lstrlen(szTaskName) == 0 ) )
  201. {
  202. DISPLAY_MESSAGE(stderr,GetResString(IDS_INVALID_TASKLENGTH));
  203. return EXIT_FAILURE;
  204. }
  205. // check for the length of username
  206. if( lstrlen( szUser ) > MAX_USERNAME_LENGTH )
  207. {
  208. DISPLAY_MESSAGE(stderr,GetResString(IDS_INVALID_UNAME ));
  209. return EXIT_FAILURE;
  210. }
  211. // check for the length of username
  212. if( lstrlen( szPassword ) > MAX_PASSWORD_LENGTH )
  213. {
  214. DISPLAY_MESSAGE(stderr,GetResString(IDS_INVALID_PASSWORD));
  215. return EXIT_FAILURE;
  216. }
  217. // check whether the password (-p) specified in the command line or not
  218. // and also check whether '*' or empty is given for -p or not
  219. if( ( IsLocalSystem( szServer ) == FALSE ) &&
  220. ( ( cmdOptions[OI_DELPASSWORD].dwActuals == 0 ) || ( lstrcmpi ( szPassword, ASTERIX ) == 0 ) ))
  221. {
  222. bNeedPassword = TRUE;
  223. }
  224. if( ( IsLocalSystem( szServer ) == FALSE ) || ( cmdOptions[OI_DELUSERNAME].dwActuals == 1 ) )
  225. {
  226. // Establish the connection on a remote machine
  227. bResult = EstablishConnection(szServer,szUser,SIZE_OF_ARRAY(szUser),szPassword,SIZE_OF_ARRAY(szPassword), bNeedPassword );
  228. if (bResult == FALSE)
  229. {
  230. DISPLAY_MESSAGE( stderr, GetResString(IDS_ERROR_STRING) );
  231. DISPLAY_MESSAGE( stderr, GetReason());
  232. return EXIT_FAILURE ;
  233. }
  234. else
  235. {
  236. // though the connection is successfull, some conflict might have occured
  237. switch( GetLastError() )
  238. {
  239. case I_NO_CLOSE_CONNECTION:
  240. bCloseConnection = FALSE;
  241. break;
  242. // for mismatched credentials
  243. case E_LOCAL_CREDENTIALS:
  244. case ERROR_SESSION_CREDENTIAL_CONFLICT:
  245. {
  246. bCloseConnection = FALSE;
  247. DISPLAY_MESSAGE( stderr, GetResString(IDS_ERROR_STRING) );
  248. DISPLAY_MESSAGE( stderr, GetReason());
  249. return EXIT_FAILURE;
  250. }
  251. }
  252. }
  253. }
  254. // Get the task Scheduler object for the machine.
  255. pITaskScheduler = GetTaskScheduler( szServer );
  256. // If the Task Scheduler is not defined then give the error message.
  257. if ( pITaskScheduler == NULL )
  258. {
  259. // close the connection that was established by the utility
  260. if ( bCloseConnection == TRUE )
  261. CloseConnection( szServer );
  262. Cleanup(pITaskScheduler);
  263. return EXIT_FAILURE;
  264. }
  265. //for holding values of parameters in FormatMessage()
  266. _TCHAR* szValues[1] = {szTaskName};
  267. // Validate the Given Task and get as TARRAY in case of taskname
  268. // as *.
  269. arrJobs = ValidateAndGetTasks( pITaskScheduler, szTaskName);
  270. if( arrJobs == NULL )
  271. {
  272. if(lstrcmpi(szTaskName,ASTERIX) == 0)
  273. {
  274. DISPLAY_MESSAGE(stdout,GetResString(IDS_TASKNAME_NOTASKS));
  275. // close the connection that was established by the utility
  276. if ( bCloseConnection == TRUE )
  277. CloseConnection( szServer );
  278. Cleanup(pITaskScheduler);
  279. return EXIT_SUCCESS;
  280. }
  281. else
  282. {
  283. _stprintf( szMessage , GetResString(IDS_TASKNAME_NOTEXIST), szTaskName);
  284. DISPLAY_MESSAGE(stderr, szMessage);
  285. }
  286. // close the connection that was established by the utility
  287. if ( bCloseConnection == TRUE )
  288. CloseConnection( szServer );
  289. Cleanup(pITaskScheduler);
  290. return EXIT_FAILURE;
  291. }
  292. // Confirm whether delete operation is to be perfromed
  293. if( !bForce && !ConfirmDelete( szTaskName , &bWrongValue ) )
  294. {
  295. // close the connection that was established by the utility
  296. if ( bCloseConnection == TRUE )
  297. CloseConnection( szServer );
  298. Cleanup(pITaskScheduler);
  299. if ( bWrongValue == TRUE )
  300. {
  301. return EXIT_FAILURE;
  302. }
  303. else
  304. {
  305. return EXIT_SUCCESS;
  306. }
  307. }
  308. // Loop through all the Jobs.
  309. for( dwJobCount = 0; dwJobCount < DynArrayGetCount(arrJobs); dwJobCount++ )
  310. {
  311. // Get Each TaskName in the Array.
  312. szEachTaskName = DynArrayItemAsString( arrJobs, dwJobCount );
  313. // Convert the task name specified by the user to wide char or unicode format
  314. if ( GetAsUnicodeString(szEachTaskName,wszJobName,SIZE_OF_ARRAY(wszJobName)) == NULL )
  315. {
  316. // close the connection that was established by the utility
  317. if ( bCloseConnection == TRUE )
  318. CloseConnection( szServer );
  319. return EXIT_FAILURE;
  320. }
  321. // Calling the delete method of ITaskScheduler interface
  322. hr = pITaskScheduler->Delete(wszJobName);
  323. szValues[0] = (_TCHAR*) szEachTaskName;
  324. // Based on the return value
  325. switch (hr)
  326. {
  327. case S_OK:
  328. FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
  329. GetResString(IDS_SUCCESS_DELETED),0,MAKELANGID(LANG_NEUTRAL,
  330. SUBLANG_DEFAULT),szMessage,
  331. MAX_STRING_LENGTH,(va_list*)szValues
  332. );
  333. DISPLAY_MESSAGE(stdout,szMessage);
  334. break;
  335. case E_INVALIDARG:
  336. DISPLAY_MESSAGE(stderr,GetResString(IDS_INVALID_ARG));
  337. // close the connection that was established by the utility
  338. if ( bCloseConnection == TRUE )
  339. CloseConnection( szServer );
  340. Cleanup(pITaskScheduler);
  341. return EXIT_FAILURE;
  342. case E_OUTOFMEMORY:
  343. DISPLAY_MESSAGE(stderr,GetResString(IDS_NO_MEMORY));
  344. // close the connection that was established by the utility
  345. if ( bCloseConnection == TRUE )
  346. CloseConnection( szServer );
  347. Cleanup(pITaskScheduler);
  348. return EXIT_FAILURE;
  349. default:
  350. DisplayErrorMsg( hr );
  351. // close the connection that was established by the utility
  352. if ( bCloseConnection == TRUE )
  353. CloseConnection( szServer );
  354. Cleanup(pITaskScheduler);
  355. return EXIT_FAILURE;
  356. }
  357. }
  358. // close the connection that was established by the utility
  359. if ( bCloseConnection == TRUE )
  360. CloseConnection( szServer );
  361. Cleanup(pITaskScheduler);
  362. return EXIT_SUCCESS;
  363. }
  364. /*****************************************************************************
  365. Routine Description:
  366. This routine displays the usage of -delete option
  367. Arguments:
  368. None
  369. Return Value :
  370. VOID
  371. ******************************************************************************/
  372. VOID
  373. DisplayDeleteUsage()
  374. {
  375. // Displaying delete usage
  376. DisplayUsage( IDS_DEL_HLP1, IDS_DEL_HLP23);
  377. }
  378. /******************************************************************************
  379. Routine Description:
  380. This function validates whether the tasks to be deleted are present
  381. in system & are valid.
  382. Arguments:
  383. [ in ] pITaskScheduler : Pointer to the ITaskScheduler Interface
  384. [ in ] szTaskName : Array containing Task name
  385. Return Value :
  386. Array of type TARRAY containing tasks
  387. ******************************************************************************/
  388. TARRAY
  389. ValidateAndGetTasks( ITaskScheduler *pITaskScheduler, LPCTSTR szTaskName)
  390. {
  391. // Dynamic Array of Jobs
  392. TARRAY arrJobs = NULL;
  393. // Enumerating WorkItems
  394. IEnumWorkItems *pIEnum = NULL;
  395. if( (pITaskScheduler == NULL ) || ( szTaskName == NULL ) )
  396. {
  397. return NULL;
  398. }
  399. // Create a Dynamic Array
  400. arrJobs = CreateDynamicArray();
  401. // Enumerate the Work Items
  402. HRESULT hr = pITaskScheduler->Enum(&pIEnum);
  403. if( FAILED( hr) )
  404. {
  405. if( pIEnum )
  406. pIEnum->Release();
  407. DestroyDynamicArray(&arrJobs);
  408. return NULL;
  409. }
  410. // Names and Tasks fetches.
  411. LPWSTR *lpwszNames = NULL;
  412. DWORD dwFetchedTasks = 0;
  413. // Task found or not
  414. BOOL blnFound = FALSE;
  415. // array containing the Actual Taskname .
  416. TCHAR szActualTask[MAX_STRING_LENGTH] = NULL_STRING;
  417. // Enumerate all the Work Items
  418. while (SUCCEEDED(pIEnum->Next(TASKS_TO_RETRIEVE,
  419. &lpwszNames,
  420. &dwFetchedTasks))
  421. && (dwFetchedTasks != 0))
  422. {
  423. while (dwFetchedTasks)
  424. {
  425. // If the Task Name is * then get parse the tokens
  426. // and append the jobs.
  427. if(lstrcmpi( szTaskName , ASTERIX) == 0 )
  428. {
  429. // Convert the Wide Charater to Multi Byte value.
  430. if ( GetCompatibleStringFromUnicode(lpwszNames[--dwFetchedTasks],
  431. szActualTask ,
  432. SIZE_OF_ARRAY(szActualTask)) == NULL )
  433. {
  434. CoTaskMemFree(lpwszNames[dwFetchedTasks]);
  435. if( pIEnum )
  436. {
  437. pIEnum->Release();
  438. }
  439. return NULL;
  440. }
  441. // Parse the Task so that .job is removed.
  442. if ( ParseTaskName( szActualTask ) )
  443. {
  444. CoTaskMemFree(lpwszNames[dwFetchedTasks]);
  445. if( pIEnum )
  446. {
  447. pIEnum->Release();
  448. }
  449. return NULL;
  450. }
  451. // Append the task in the job array
  452. DynArrayAppendString( arrJobs, szActualTask, lstrlen( szActualTask ) );
  453. // Set the found flag as True.
  454. blnFound = TRUE;
  455. // Free the Named Task Memory.
  456. CoTaskMemFree(lpwszNames[dwFetchedTasks]);
  457. }
  458. else
  459. {
  460. // Check whether the TaskName is present, if present
  461. // then return arrJobs.
  462. // Convert the Wide Charater to Multi Byte value.
  463. if ( GetCompatibleStringFromUnicode(lpwszNames[--dwFetchedTasks],
  464. szActualTask ,
  465. SIZE_OF_ARRAY(szActualTask)) == NULL )
  466. {
  467. CoTaskMemFree(lpwszNames[dwFetchedTasks]);
  468. if( pIEnum )
  469. {
  470. pIEnum->Release();
  471. }
  472. return NULL;
  473. }
  474. // Parse the TaskName to remove the .job extension.
  475. if ( ParseTaskName( szActualTask ) )
  476. {
  477. CoTaskMemFree(lpwszNames[dwFetchedTasks]);
  478. if( pIEnum )
  479. {
  480. pIEnum->Release();
  481. }
  482. return NULL;
  483. }
  484. StrTrim(szActualTask, TRIM_SPACES);
  485. // If the given Task matches with the TaskName present then form
  486. // the TARRAY with this task and return.
  487. if( lstrcmpi( szActualTask, szTaskName ) == 0 )
  488. {
  489. CoTaskMemFree(lpwszNames[dwFetchedTasks]);
  490. DynArrayAppendString( arrJobs, szTaskName,
  491. lstrlen( szTaskName ) );
  492. if( pIEnum )
  493. pIEnum->Release();
  494. return arrJobs;
  495. }
  496. }
  497. }//end while
  498. }
  499. CoTaskMemFree(lpwszNames);
  500. if( pIEnum )
  501. pIEnum->Release();
  502. if( !blnFound )
  503. {
  504. DestroyDynamicArray(&arrJobs);
  505. return NULL;
  506. }
  507. // return the TARRAY object.
  508. return arrJobs;
  509. }
  510. /******************************************************************************
  511. Routine Description:
  512. This function confirms from the user really to delete the task(s).
  513. Arguments:
  514. [ in ] szTaskName : Array containing Task name
  515. [ out ] pbFalg : Boolean flag to check whether wrong information entered
  516. in the console or not.
  517. Return Value :
  518. TRUE on success else FALSE
  519. ******************************************************************************/
  520. BOOL
  521. ConfirmDelete( LPCTSTR szTaskName , PBOOL pbFalg )
  522. {
  523. // Ch variable to hold the read character
  524. TCHAR ch = NULL_CHAR;
  525. TCHAR chTmp = NULL_CHAR;
  526. // Buffer for the message.
  527. TCHAR szMessage[MAX_STRING_LENGTH] = NULL_STRING;
  528. DWORD dwCharsRead = 0;
  529. DWORD dwPrevConsoleMode = 0;
  530. HANDLE hInputConsole = NULL;
  531. HANDLE hOutputConsole = NULL;
  532. _TCHAR* szValues[1] = {NULL};//for holding values of parameters in FormatMessage()
  533. BOOL bIndirectionInput = FALSE;
  534. FILE *fpInputFile = NULL;
  535. TCHAR szBuffer[MAX_BUF_SIZE] = NULL_STRING;
  536. WORD wCount = 0;
  537. TCHAR SpResString[500] = NULL_STRING;
  538. if ( szTaskName == NULL )
  539. {
  540. return FALSE;
  541. }
  542. // Get the handle for the standard input
  543. hInputConsole = GetStdHandle( STD_INPUT_HANDLE );
  544. if ( hInputConsole == NULL )
  545. {
  546. // could not get the handle so return failure
  547. return FALSE;
  548. }
  549. // Check for the input redirect
  550. if( ( hInputConsole != (HANDLE)0x00000003 ) && ( hInputConsole != INVALID_HANDLE_VALUE ) )
  551. {
  552. bIndirectionInput = TRUE;
  553. }
  554. if ( bIndirectionInput == FALSE )
  555. {
  556. // Get the current input mode of the input buffer
  557. GetConsoleMode( hInputConsole, &dwPrevConsoleMode );
  558. // Set the mode such that the control keys are processed by the system
  559. if ( SetConsoleMode( hInputConsole, ENABLE_PROCESSED_INPUT ) == 0 )
  560. {
  561. // could not set the mode, return failure
  562. return FALSE;
  563. }
  564. }
  565. hOutputConsole = GetStdHandle( STD_OUTPUT_HANDLE );
  566. do
  567. {
  568. // Print the warning message.accoring to the taskname
  569. if( lstrcmpi( szTaskName , ASTERIX ) == 0 )
  570. {
  571. DISPLAY_MESSAGE(stdout,GetResString(IDS_WARN_DELETEALL));
  572. }
  573. else
  574. {
  575. szValues[0] = (_TCHAR*) szTaskName;
  576. FormatMessage(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ARGUMENT_ARRAY,
  577. GetResString(IDS_WARN_DELETE),0,MAKELANGID(LANG_NEUTRAL,
  578. SUBLANG_DEFAULT),szMessage,
  579. MAX_STRING_LENGTH,(va_list*)szValues
  580. );
  581. DISPLAY_MESSAGE(stdout,szMessage);
  582. }
  583. // redirect the data from StdIn.txt file into the console
  584. if ( bIndirectionInput == TRUE )
  585. {
  586. do {
  587. //read the contents of file
  588. if ( ReadFile(hInputConsole, &chTmp, 1, &dwCharsRead, NULL) == FALSE )
  589. {
  590. return FALSE;
  591. }
  592. if ( dwCharsRead == 0 || chTmp == CARRIAGE_RETURN )
  593. {
  594. break;
  595. }
  596. WriteConsole ( hOutputConsole, &chTmp, 1, &dwCharsRead, NULL );
  597. ch = chTmp;
  598. wCount++;
  599. } while (TRUE);
  600. FORMAT_STRING( szBuffer, L"%c", ch );
  601. if ( wCount == 1 && ( lstrcmpi ( szBuffer, GetSpResString(IDS_UPPER_YES, SpResString) ) == 0 ) )
  602. {
  603. DISPLAY_MESSAGE(stdout, _T("\n") );
  604. SetConsoleMode( hInputConsole, dwPrevConsoleMode );
  605. return TRUE;
  606. }
  607. if ( wCount == 1 && ( lstrcmpi ( szBuffer, GetSpResString(IDS_UPPER_NO , SpResString) ) == 0 ) )
  608. {
  609. DISPLAY_MESSAGE(stdout, _T("\n") );
  610. SetConsoleMode( hInputConsole, dwPrevConsoleMode );
  611. return FALSE;
  612. }
  613. else if ( wCount > 1)
  614. {
  615. DISPLAY_MESSAGE(stdout, _T("\n") );
  616. DISPLAY_MESSAGE(stderr, GetResString( IDS_WRONG_INPUT_DELETE ));
  617. SetConsoleMode( hInputConsole, dwPrevConsoleMode );
  618. return FALSE;
  619. }
  620. }
  621. else
  622. {
  623. // Get the Character and loop accordingly.
  624. if ( ReadConsole( hInputConsole, &ch, 1, &dwCharsRead, NULL ) == 0 )
  625. {
  626. // Set the original console settings
  627. SetConsoleMode( hInputConsole, dwPrevConsoleMode );
  628. // return failure
  629. return FALSE;
  630. }
  631. }
  632. WriteConsole ( hOutputConsole, &ch, 1, &dwCharsRead, NULL );
  633. FORMAT_STRING( szBuffer, L"%c", ch );
  634. if( lstrcmpi ( szBuffer, GetSpResString(IDS_UPPER_YES, SpResString) ) == 0 )
  635. {
  636. //Set the original console settings
  637. DISPLAY_MESSAGE(stdout,_T("\n") );
  638. SetConsoleMode( hInputConsole, dwPrevConsoleMode );
  639. return TRUE;
  640. }
  641. else if( lstrcmpi ( szBuffer, GetSpResString(IDS_UPPER_NO, SpResString) ) == 0 )
  642. {
  643. DISPLAY_MESSAGE(stdout,_T("\n") );
  644. SetConsoleMode( hInputConsole, dwPrevConsoleMode );
  645. return FALSE;
  646. }
  647. else
  648. {
  649. DISPLAY_MESSAGE(stdout, _T("\n") );
  650. DISPLAY_MESSAGE(stderr, GetResString( IDS_WRONG_INPUT_DELETE ));
  651. SetConsoleMode( hInputConsole, dwPrevConsoleMode );
  652. *pbFalg = TRUE;
  653. return FALSE;
  654. }
  655. }while( TRUE );
  656. //Set the original console settings
  657. SetConsoleMode( hInputConsole, dwPrevConsoleMode );
  658. return TRUE;
  659. }
  660. LPWSTR GetSpResString( UINT uID , LPWSTR lpwszBuffer)
  661. {
  662. static const TCHAR gszResourceDLL[] = L"xpsp1res.dll";
  663. HINSTANCE hResourceDLL = LoadLibrary(gszResourceDLL);
  664. int iNum = 0;
  665. if ( hResourceDLL )
  666. {
  667. iNum = LoadString ( hResourceDLL, uID, lpwszBuffer, sizeof( lpwszBuffer )/sizeof( TCHAR ));
  668. FreeLibrary( hResourceDLL );
  669. }
  670. if (iNum != 0 )
  671. return lpwszBuffer;
  672. return NULL_STRING;
  673. }