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.

781 lines
23 KiB

  1. //*****************************************************************************
  2. //
  3. // Copyright (c) Microsoft Corporation
  4. //
  5. // Module Name:
  6. //
  7. // EventTriggers.cpp
  8. //
  9. // Abstract:
  10. //
  11. // This module implements the command-line parsing to create/delete/query
  12. // EventTriggers on current running on local and remote systems.
  13. //
  14. //
  15. // Author:
  16. //
  17. // Akhil V. Gokhale ([email protected])
  18. //
  19. // Revision History:
  20. //
  21. // Akhil V. Gokhale ([email protected])
  22. //
  23. //*****************************************************************************
  24. #include "pch.h"
  25. #include "ETCommon.h"
  26. #include "EventTriggers.h"
  27. #include "ShowError.h"
  28. #include "ETCreate.h"
  29. #include "ETDelete.h"
  30. #include "ETQuery.h"
  31. DWORD g_dwOptionFlag;
  32. // ***************************************************************************
  33. // Routine Description:
  34. // This module reads the input from commond line and calls appropriate
  35. // functions to achive to functionality of EventTrigger-Client.
  36. //
  37. // Arguments:
  38. // [ in ] argc : argument(s) count specified at the command prompt
  39. // [ in ] argv : argument(s) specified at the command prompt
  40. //
  41. // Return Value:
  42. // The below are actually not return values but are the exit values
  43. // returned to the OS by this application
  44. // 0 : utility is successfull
  45. // 1 : utility failed
  46. // ***************************************************************************
  47. DWORD __cdecl
  48. _tmain( DWORD argc, LPCTSTR argv[] )
  49. {
  50. // local variables
  51. CEventTriggers eventTriggers;
  52. BOOL bResult = DIRTY_EXIT; // Programs return value status variable.
  53. g_dwOptionFlag = 0;
  54. TCHAR szErrorMsg[(MAX_RES_STRING*2)+1];
  55. try
  56. {
  57. if(argc == 1)
  58. {
  59. if(IsWin2KOrLater()==FALSE)
  60. {
  61. TCHAR szErrorMsg[(MAX_RES_STRING*2)+1];
  62. TCHAR szErrorMsg1[(MAX_RES_STRING*2)+1];
  63. lstrcpy(szErrorMsg1,ERROR_OS_INCOMPATIBLE);
  64. DISPLAY_MESSAGE2( stderr, szErrorMsg, L"%s %s", TAG_ERROR,
  65. szErrorMsg1);
  66. }
  67. else
  68. {
  69. // If no command line parameter is given then -query option
  70. // will be taken as default.
  71. g_dwOptionFlag = 3;
  72. CETQuery etQuery(MAX_RES_STRING,
  73. FALSE);
  74. etQuery.Initialize();// Initializes variables.
  75. // execute query method to query EventTriggers in WMI.
  76. if(etQuery.ExecuteQuery () == TRUE)
  77. {
  78. // as ExecuteQuery routine returns with TRUE,
  79. // exit from program with error level CLEAN_EXIT
  80. bResult = CLEAN_EXIT;
  81. }
  82. }
  83. }
  84. else
  85. {
  86. // Calculates minimum memory required for allocating memory to
  87. // various variables.
  88. eventTriggers.CalcMinMemoryReq (argc,argv);
  89. // As commandline parameter is specified so command parscing will
  90. // required.
  91. // Initialize variables for eventTriggers object.
  92. eventTriggers.Initialize ();
  93. // Process command line parameters.
  94. eventTriggers.ProcessOption(argc,argv);
  95. if(eventTriggers.IsUsage () == TRUE) //if usage option is selected
  96. {
  97. if(eventTriggers.IsCreate () ==TRUE)
  98. {
  99. eventTriggers.ShowCreateUsage ();//Display create usage
  100. }
  101. else if(eventTriggers.IsDelete () ==TRUE)
  102. {
  103. eventTriggers.ShowDeleteUsage ();//Display delete usage
  104. }
  105. else if(eventTriggers.IsQuery () ==TRUE)
  106. {
  107. eventTriggers.ShowQueryUsage ();//Display query usage
  108. }
  109. else
  110. {
  111. eventTriggers.ShowMainUsage ();//Display main usage
  112. }
  113. bResult = CLEAN_EXIT;
  114. }
  115. else if(eventTriggers.IsCreate () == TRUE)//if user selected create
  116. {
  117. // creates a object of type CETCreate.
  118. g_dwOptionFlag = 1;//for create option
  119. CETCreate etCreate(eventTriggers.GetMinMemoryReq(),
  120. eventTriggers.GetNeedPassword());
  121. etCreate.Initialize ();// Initializes variables.
  122. // Process command line argument for -create option.
  123. etCreate.ProcessOption (argc,argv);
  124. // execute create method to create EventTriggers in WMI.
  125. if(etCreate.ExecuteCreate ()== TRUE)
  126. {
  127. // as ExecuteCreate routine returns with TRUE,
  128. // exit from program with error level CLEAN_EXIT
  129. bResult = CLEAN_EXIT;
  130. }
  131. }
  132. else if(eventTriggers.IsDelete () == TRUE)//if user selected delete
  133. {
  134. // creates a object of type CETDelete.
  135. g_dwOptionFlag = 2;//for create option
  136. CETDelete etDelete(eventTriggers.GetMinMemoryReq (),
  137. eventTriggers.GetNeedPassword());
  138. etDelete.Initialize ();// Initializes variables.
  139. // Process command line argument for -delete option.
  140. etDelete.ProcessOption (argc,argv);
  141. // execute delete method to delete EventTriggers in WMI.
  142. if(etDelete.ExecuteDelete ()==TRUE)
  143. {
  144. // as ExecuteDelete routine returns with TRUE,
  145. // exit from program with error level CLEAN_EXIT
  146. bResult = CLEAN_EXIT;
  147. }
  148. }
  149. else if(eventTriggers.IsQuery () == TRUE)//if user selected -query.
  150. {
  151. // creates a object of type CETQuery.
  152. g_dwOptionFlag = 3;//for create option
  153. CETQuery etQuery(eventTriggers.GetMinMemoryReq (),
  154. eventTriggers.GetNeedPassword ());
  155. etQuery.Initialize();// Initializes variables.
  156. // Process command line argument for -Query option.
  157. etQuery.ProcessOption(argc,argv);
  158. // execute query method to query EventTriggers in WMI.
  159. if(etQuery.ExecuteQuery ()== TRUE)
  160. {
  161. // as ExecuteQuery routine returns with TRUE,
  162. // exit from program with error level CLEAN_EXIT
  163. bResult = CLEAN_EXIT;
  164. }
  165. }
  166. else
  167. {
  168. // Although this condition will never occure, for safe side
  169. // show error message as "ERROR: Invalid Syntax.
  170. TCHAR szTemp[(MAX_RES_STRING*2)+1];
  171. wsprintf(szTemp,GetResString(IDS_INCORRECT_SYNTAX),argv[0]);
  172. SetReason(szTemp);
  173. throw CShowError(MK_E_SYNTAX);
  174. }
  175. } // End else
  176. }// try block
  177. catch(CShowError se)
  178. {
  179. // Show Error message on screen depending on value passed through
  180. // through machanism.
  181. DISPLAY_MESSAGE2( stderr, szErrorMsg, L"%s %s", TAG_ERROR,
  182. se.ShowReason());
  183. }
  184. catch(CHeap_Exception ch)
  185. {
  186. SetLastError( E_OUTOFMEMORY );
  187. SaveLastError();
  188. DISPLAY_MESSAGE2( stderr, szErrorMsg, L"%s %s", TAG_ERROR,
  189. GetReason());
  190. }
  191. // Returns from program with error level stored in bResult.
  192. ReleaseGlobals();
  193. return bResult;
  194. }
  195. // ***************************************************************************
  196. // Routine Description:
  197. // CEventTriggers contructor
  198. //
  199. // Arguments:
  200. // NONE
  201. //
  202. // Return Value:
  203. // NONE
  204. //
  205. // ***************************************************************************
  206. CEventTriggers::CEventTriggers()
  207. {
  208. // init to defaults
  209. m_pszServerNameToShow = NULL;
  210. m_bNeedDisconnect = FALSE;
  211. m_bNeedPassword = FALSE;
  212. m_bUsage = FALSE;
  213. m_bCreate = FALSE;
  214. m_bDelete = FALSE;
  215. m_bQuery = FALSE;
  216. m_arrTemp = NULL;
  217. m_lMinMemoryReq = MIN_MEMORY_REQUIRED;
  218. }
  219. // ***************************************************************************
  220. // Routine Description:
  221. // CEventTriggers destructor
  222. //
  223. // Arguments:
  224. // NONE
  225. //
  226. // Return Value:
  227. // NONE
  228. //
  229. // ***************************************************************************
  230. CEventTriggers::~CEventTriggers()
  231. {
  232. //
  233. // de-allocate memory allocations
  234. //
  235. DESTROY_ARRAY(m_arrTemp);
  236. }
  237. // ***************************************************************************
  238. // Routine Description:
  239. // initialize the EventTriggers utility
  240. //
  241. // Arguments:
  242. // NONE
  243. //
  244. // Return Value:
  245. // NONE
  246. //
  247. // ***************************************************************************
  248. void
  249. CEventTriggers::Initialize()
  250. {
  251. // local variables
  252. LONG lTemp = 0;
  253. // if at all any occurs, we know that is because of the
  254. // failure in memory allocation ... so set the error
  255. SetLastError( E_OUTOFMEMORY );
  256. SaveLastError();
  257. // Allocates memory
  258. m_arrTemp = CreateDynamicArray();
  259. if(m_arrTemp == NULL)
  260. {
  261. // error occures while allocating required memory, so throw
  262. // exception.
  263. throw CShowError(E_OUTOFMEMORY);
  264. }
  265. // initialization is successful
  266. SetLastError( NOERROR ); // clear the error
  267. SetReason( NULL_STRING ); // clear the reason
  268. }
  269. // ***************************************************************************
  270. // Routine Description:
  271. // This function will calculate minimum memory requirement value needed
  272. // to allocated for various string variables.
  273. //
  274. // Arguments:
  275. // [ in ] argc : argument(s) count specified at the command prompt
  276. // [ in ] argv : argument(s) specified at the command prompt
  277. //
  278. // Return Value:
  279. // NONE
  280. //
  281. // ***************************************************************************
  282. void
  283. CEventTriggers::CalcMinMemoryReq(DWORD argc, LPCTSTR argv[])
  284. {
  285. // local variables
  286. DWORD dwIndx = 0; // Index variable;
  287. DWORD dwStrLen = 0; // String length
  288. // Calculate minimum memory required based on length maximum of maximum
  289. // command line parameter passed.
  290. for(dwIndx = 0 ; dwIndx <argc; dwIndx++)
  291. {
  292. dwStrLen = lstrlen(argv [dwIndx]);
  293. if(m_lMinMemoryReq <lstrlen(argv [dwIndx]))
  294. m_lMinMemoryReq = lstrlen(argv [dwIndx]);
  295. }
  296. }
  297. // ***************************************************************************
  298. // Routine Description:
  299. // This function will process/parce the command line options.
  300. //
  301. // Arguments:
  302. // [ in ] argc : argument(s) count specified at the command prompt
  303. // [ in ] argv : argument(s) specified at the command prompt
  304. //
  305. // Return Value:
  306. // TRUE : On Successful
  307. // FALSE : On Error
  308. //
  309. // ***************************************************************************
  310. BOOL
  311. CEventTriggers::ProcessOption(DWORD argc, LPCTSTR argv[])
  312. {
  313. // local variable
  314. BOOL bReturn = TRUE;// stores return value of function.
  315. TCHAR szTemp[MAX_RES_STRING];
  316. TCHAR szStr [MAX_RES_STRING];
  317. lstrcpy(szStr,GetResString(IDS_UTILITY_NAME));
  318. wsprintf(szTemp,GetResString(IDS_INCORRECT_SYNTAX),
  319. szStr);
  320. PrepareCMDStruct();
  321. // do the actual parsing of the command line arguments and check the result
  322. bReturn = DoParseParam( argc, argv, MAX_COMMANDLINE_OPTION, cmdOptions );
  323. if(bReturn==FALSE)
  324. {
  325. // Command line contains invalid parameter(s) so throw exception for
  326. // invalid syntax.
  327. // Valid reason already set in DoParceParam,.
  328. throw CShowError(MK_E_SYNTAX);
  329. }
  330. if((m_bUsage==TRUE)&&argc>3)
  331. {
  332. // Only one option can be accepted along with -? option
  333. // Example: EvTrig.exe -? -query -nh should be invalid.
  334. SetReason(szTemp);
  335. throw CShowError(MK_E_SYNTAX);
  336. }
  337. if((m_bCreate+m_bDelete+m_bQuery)>1)
  338. {
  339. // Only ONE OF the -create -delete and -query can be given as
  340. // valid command line parameter.
  341. SetReason(szTemp);
  342. throw CShowError(MK_E_SYNTAX);
  343. }
  344. else if((argc == 2)&&(m_bUsage == TRUE))
  345. {
  346. // if -? alone given its a valid conmmand line
  347. bReturn = TRUE;
  348. }
  349. else if((argc>=2)&& (m_bCreate==FALSE)&&(m_bDelete==FALSE)&&(m_bQuery==FALSE))
  350. {
  351. // If command line argument is equals or greater than 2 atleast one
  352. // of -query OR -create OR -delete should be present in it.
  353. // (for "-?" previous condition already takes care)
  354. // This to prevent from following type of command line argument:
  355. // EvTrig.exe -nh ... Which is a invalid syntax.
  356. SetReason(szTemp);
  357. throw CShowError(MK_E_SYNTAX);
  358. }
  359. // Following checking done if user given command like
  360. // -? -nh OR -? -v , its an invalid syntax.
  361. else if((m_bUsage==TRUE)&&(m_bCreate == FALSE)&&
  362. (m_bDelete == FALSE)&&(m_bQuery == FALSE)&&
  363. (argc == 3))
  364. {
  365. SetReason(szTemp);
  366. throw CShowError(MK_E_SYNTAX);
  367. }
  368. // Any how following variables do not required.
  369. DESTROY_ARRAY(m_arrTemp);
  370. return bReturn;
  371. }
  372. // ***************************************************************************
  373. // Routine Description:
  374. // This function will prepare column structure for DoParseParam Function.
  375. //
  376. // Arguments:
  377. // none
  378. // Return Value:
  379. // none
  380. // ***************************************************************************
  381. void
  382. CEventTriggers::PrepareCMDStruct()
  383. {
  384. // Filling cmdOptions structure
  385. // -?
  386. lstrcpy(cmdOptions[ ID_HELP ].szOption,OPTION_HELP);
  387. cmdOptions[ ID_HELP ].dwFlags = CP_USAGE;
  388. cmdOptions[ ID_HELP ].dwCount = 1;
  389. cmdOptions[ ID_HELP ].dwActuals = 0;
  390. cmdOptions[ ID_HELP ].pValue = &m_bUsage;
  391. lstrcpy(cmdOptions[ ID_HELP ].szValues,NULL_STRING);
  392. cmdOptions[ ID_HELP ].pFunction = NULL;
  393. cmdOptions[ ID_HELP ].pFunctionData = NULL;
  394. // -create
  395. lstrcpy(cmdOptions[ ID_CREATE ].szOption,OPTION_CREATE);
  396. cmdOptions[ ID_CREATE ].dwFlags = 0;
  397. cmdOptions[ ID_CREATE ].dwCount = 1;
  398. cmdOptions[ ID_CREATE ].dwActuals = 0;
  399. cmdOptions[ ID_CREATE ].pValue = &m_bCreate;
  400. lstrcpy(cmdOptions[ ID_CREATE ].szValues,NULL_STRING);
  401. cmdOptions[ ID_CREATE ].pFunction = NULL;
  402. cmdOptions[ ID_CREATE ].pFunctionData = NULL;
  403. cmdOptions[ ID_CREATE ].pFunctionData = NULL;
  404. // -delete
  405. lstrcpy(cmdOptions[ ID_DELETE ].szOption,OPTION_DELETE);
  406. cmdOptions[ ID_DELETE ].dwFlags = 0;
  407. cmdOptions[ ID_DELETE ].dwCount = 1;
  408. cmdOptions[ ID_DELETE ].dwActuals = 0;
  409. cmdOptions[ ID_DELETE ].pValue = &m_bDelete;
  410. lstrcpy(cmdOptions[ ID_DELETE ].szValues,NULL_STRING);
  411. cmdOptions[ ID_DELETE ].pFunction = NULL;
  412. cmdOptions[ ID_DELETE ].pFunctionData = NULL;
  413. // -query
  414. lstrcpy(cmdOptions[ ID_QUERY ].szOption,OPTION_QUERY);
  415. cmdOptions[ ID_QUERY ].dwFlags = 0;
  416. cmdOptions[ ID_QUERY ].dwCount = 1;
  417. cmdOptions[ ID_QUERY ].dwActuals = 0;
  418. cmdOptions[ ID_QUERY ].pValue = &m_bQuery;
  419. lstrcpy(cmdOptions[ ID_QUERY ].szValues,NULL_STRING);
  420. cmdOptions[ ID_QUERY ].pFunction = NULL;
  421. cmdOptions[ ID_QUERY ].pFunctionData = NULL;
  422. // default ..
  423. // Although there is no default option for this utility...
  424. // At this moment all the switches other than specified above will be
  425. // treated as default parameter for Main DoParceParam.
  426. // Exact parcing depending on optins (-create -query or -delete) will be done
  427. // at that respective places.
  428. lstrcpy(cmdOptions[ ID_DEFAULT ].szOption,NULL_STRING);
  429. cmdOptions[ ID_DEFAULT ].dwFlags = CP_TYPE_TEXT | CP_MODE_ARRAY|CP_DEFAULT;
  430. cmdOptions[ ID_DEFAULT ].dwCount = 0;
  431. cmdOptions[ ID_DEFAULT ].dwActuals = 0;
  432. cmdOptions[ ID_DEFAULT ].pValue = &m_arrTemp;
  433. lstrcpy(cmdOptions[ ID_DEFAULT ].szValues,NULL_STRING);
  434. cmdOptions[ ID_DEFAULT ].pFunction = NULL;
  435. cmdOptions[ ID_DEFAULT ].pFunctionData = NULL;
  436. }
  437. //***************************************************************************
  438. // Routine Description:
  439. // Displays Eventriggers main usage
  440. //
  441. // Arguments:
  442. // None
  443. // Return Value:
  444. // None
  445. //
  446. //***************************************************************************
  447. void
  448. CEventTriggers::ShowMainUsage()
  449. {
  450. // Displaying main usage
  451. for(DWORD dwIndx=IDS_HELP_M1;dwIndx<=IDS_HELP_END;dwIndx++)
  452. {
  453. ShowMessage(stdout,GetResString(dwIndx));
  454. }
  455. }
  456. //***************************************************************************
  457. // Routine Description:
  458. // Returns Minimum memory required.
  459. //
  460. // Arguments:
  461. // None
  462. // Return Value:
  463. // LONG
  464. //
  465. //***************************************************************************
  466. LONG
  467. CEventTriggers::GetMinMemoryReq()
  468. {
  469. return m_lMinMemoryReq;
  470. }
  471. //***************************************************************************
  472. // Routine Description:
  473. // Returns whether to ask for password or not.
  474. //
  475. // Arguments:
  476. // None
  477. // Return Value:
  478. // BOOL
  479. //
  480. //***************************************************************************
  481. BOOL
  482. CEventTriggers::GetNeedPassword()
  483. {
  484. return m_bNeedPassword;
  485. }
  486. //***************************************************************************
  487. // Routine Description:
  488. // Returns if create option is selected.
  489. //
  490. // Arguments:
  491. // None
  492. // Return Value:
  493. // BOOL
  494. //
  495. //***************************************************************************
  496. BOOL
  497. CEventTriggers::IsCreate()
  498. {
  499. return m_bCreate;
  500. }
  501. //***************************************************************************
  502. // Routine Description:
  503. // Returns if usage option is selected.
  504. //
  505. // Arguments:
  506. // None
  507. // Return Value:
  508. // BOOL
  509. //
  510. //***************************************************************************
  511. BOOL
  512. CEventTriggers::IsUsage()
  513. {
  514. return m_bUsage;
  515. }
  516. //***************************************************************************
  517. // Routine Description:
  518. // Returns if delete option is selected.
  519. //
  520. // Arguments:
  521. // None
  522. // Return Value:
  523. // BOOL
  524. //
  525. //***************************************************************************
  526. BOOL
  527. CEventTriggers::IsDelete()
  528. {
  529. return m_bDelete;
  530. }
  531. //***************************************************************************
  532. // Routine Description:
  533. // Returns if Query option is selected.
  534. //
  535. // Arguments:
  536. // None
  537. // Return Value:
  538. // BOOL
  539. //
  540. //***************************************************************************
  541. BOOL
  542. CEventTriggers::IsQuery()
  543. {
  544. return m_bQuery;
  545. }
  546. /*****************************************************************************
  547. Routine Description
  548. This function shows help message for EventTriggers utility for
  549. -create operation
  550. Arguments:
  551. NONE
  552. Return Value
  553. None
  554. *****************************************************************************/
  555. void
  556. CEventTriggers::ShowCreateUsage()
  557. {
  558. // Displaying Create usage
  559. for(int iIndx=IDS_HELP_C1;iIndx<=IDS_HELP_CREATE_END;iIndx++)
  560. {
  561. ShowMessage(stdout,GetResString(iIndx));
  562. }
  563. }
  564. /*****************************************************************************
  565. Routine Description
  566. This function shows help message for EventTriggers utility for
  567. -delete operation
  568. Arguments:
  569. NONE
  570. Return Value
  571. None
  572. ******************************************************************************/
  573. void
  574. CEventTriggers::ShowDeleteUsage()
  575. {
  576. for(int iIndx=IDS_HELP_D1;iIndx<=IDS_HELP_DELETE_END;iIndx++)
  577. {
  578. ShowMessage(stdout,GetResString(iIndx));
  579. }
  580. }
  581. /*****************************************************************************
  582. Routine Description
  583. This function shows help message for EventTriggers utility for
  584. -query operation
  585. Arguments:
  586. NONE
  587. Return Value
  588. None
  589. ******************************************************************************/
  590. void
  591. CEventTriggers::ShowQueryUsage()
  592. {
  593. for(int iIndx=IDS_HELP_Q1;iIndx<=IDS_HELP_QUERY_END;iIndx++)
  594. {
  595. ShowMessage(stdout,GetResString(iIndx));
  596. }
  597. }
  598. //***************************************************************************
  599. // Routine Description:
  600. // Get the value of a property for the given instance .
  601. //
  602. // Arguments:
  603. // pWmiObject[in] - A pointer to wmi class.
  604. // szProperty [in] - property name whose value to be returned.
  605. // dwType [in] - Data Type of the property.
  606. // pValue [in/out] - Variable to hold the data.
  607. // dwSize [in] - size of the variable.
  608. //
  609. // Return Value:
  610. // HRESULT value.
  611. //***************************************************************************
  612. HRESULT PropertyGet1( IWbemClassObject* pWmiObject,
  613. LPCTSTR szProperty,
  614. DWORD dwType, LPVOID pValue, DWORD dwSize )
  615. {
  616. // local variables
  617. HRESULT hr = S_OK;
  618. VARIANT varValue;
  619. LPWSTR pwszValue = NULL;
  620. WCHAR wszProperty[ MAX_STRING_LENGTH ] = L"\0";
  621. // value should not be NULL
  622. if ( pValue == NULL )
  623. {
  624. return S_FALSE;
  625. }
  626. // initialize the values with zeros ... to be on safe side
  627. memset( pValue, 0, dwSize );
  628. memset( wszProperty, 0, MAX_STRING_LENGTH );
  629. // get the property name in UNICODE version
  630. GetAsUnicodeString( szProperty, wszProperty, MAX_STRING_LENGTH );
  631. // initialize the variant and then get the value of the specified property
  632. VariantInit( &varValue );
  633. hr = pWmiObject->Get( wszProperty, 0, &varValue, NULL, NULL );
  634. if ( FAILED( hr ) )
  635. {
  636. // clear the variant variable
  637. VariantClear( &varValue );
  638. // failed to get the value for the property
  639. return hr;
  640. }
  641. // get and put the value
  642. switch( varValue.vt )
  643. {
  644. case VT_EMPTY:
  645. case VT_NULL:
  646. break;
  647. case VT_I2:
  648. *( ( short* ) pValue ) = V_I2( &varValue );
  649. break;
  650. case VT_I4:
  651. *( ( long* ) pValue ) = V_I4( &varValue );
  652. break;
  653. case VT_R4:
  654. *( ( float* ) pValue ) = V_R4( &varValue );
  655. break;
  656. case VT_R8:
  657. *( ( double* ) pValue ) = V_R8( &varValue );
  658. break;
  659. case VT_UI1:
  660. *( ( UINT* ) pValue ) = V_UI1( &varValue );
  661. break;
  662. case VT_BSTR:
  663. {
  664. // get the unicode value
  665. pwszValue = V_BSTR( &varValue );
  666. // get the comptable string
  667. if(GetCompatibleStringFromUnicode( pwszValue, ( LPTSTR ) pValue, dwSize )==NULL)
  668. {
  669. return S_FALSE;
  670. }
  671. break;
  672. }
  673. }
  674. // clear the variant variable
  675. if(FAILED(VariantClear( &varValue )))
  676. {
  677. return S_FALSE;
  678. }
  679. // inform success
  680. return S_OK;
  681. }
  682. /*****************************************************************************
  683. Routine Description:
  684. Arguments:
  685. result.
  686. Return Value:
  687. ******************************************************************************/
  688. void PrintProgressMsg(HANDLE hOutput,LPCWSTR pwszMsg,const CONSOLE_SCREEN_BUFFER_INFO& csbi)
  689. {
  690. COORD coord;
  691. DWORD dwSize = 0;
  692. WCHAR wszSpaces[80] = L"";
  693. if(hOutput == NULL)
  694. return;
  695. coord.X = 0;
  696. coord.Y = csbi.dwCursorPosition.Y;
  697. ZeroMemory(wszSpaces,80);
  698. SetConsoleCursorPosition(hOutput,coord);
  699. WriteConsoleW(hOutput,Replicate(wszSpaces,L"",79),79,&dwSize,NULL);
  700. SetConsoleCursorPosition(hOutput,coord);
  701. if(pwszMsg!=NULL)
  702. WriteConsoleW(hOutput,pwszMsg,lstrlen(pwszMsg),&dwSize,NULL);
  703. }