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.

2792 lines
76 KiB

  1. /*********************************************************************************************
  2. Copyright (c) Microsoft Corporation
  3. Module Name:
  4. WMI.cpp
  5. Abstract:
  6. Common functionlity for dealing with WMI.
  7. Author:
  8. Wipro Technologies
  9. Revision History:
  10. 22-Dec-2000 : Created It.
  11. 24-Apr-2001 : Closing the review comments given by client.
  12. *********************************************************************************************/
  13. #include "pch.h"
  14. #include "wmi.h"
  15. #include "resource.h"
  16. //
  17. // messages
  18. //
  19. #define INPUT_PASSWORD GetResString( IDS_STR_INPUT_PASSWORD )
  20. #define INPUT_PASSWORD_LEN 256
  21. // error constants
  22. #define E_SERVER_NOTFOUND 0x800706ba
  23. //
  24. // private function prototype(s)
  25. //
  26. BOOL IsValidUserEx( LPCWSTR pwszUser );
  27. HRESULT GetSecurityArguments( IUnknown* pInterface,
  28. DWORD& dwAuthorization, DWORD& dwAuthentication );
  29. HRESULT SetInterfaceSecurity( IUnknown* pInterface,
  30. LPCWSTR pwszUser,
  31. LPCWSTR pwszPassword, COAUTHIDENTITY** ppAuthIdentity );
  32. HRESULT WINAPI SetProxyBlanket( IUnknown* pInterface,
  33. DWORD dwAuthnSvc, DWORD dwAuthzSvc,
  34. LPWSTR pwszPrincipal, DWORD dwAuthLevel, DWORD dwImpLevel,
  35. RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities );
  36. HRESULT WINAPI WbemAllocAuthIdentity( LPCWSTR pwszUser, LPCWSTR pwszPassword,
  37. LPCWSTR pwszDomain, COAUTHIDENTITY** ppAuthIdent );
  38. HRESULT RegQueryValueWMI( IWbemServices* pWbemServices,
  39. LPCWSTR pwszMethod, DWORD dwHDefKey,
  40. LPCWSTR pwszSubKeyName, LPCWSTR pwszValueName, _variant_t& varValue );
  41. BOOL
  42. IsValidUserEx(
  43. LPCWSTR pwszUser
  44. )
  45. /*++
  46. Routine Description:
  47. Checks wether the User name is a valid one or not
  48. Arguments:
  49. [in] LPCWSTR : String containing the user name
  50. Return Value:
  51. TRUE on success
  52. FALSE on failure
  53. --*/
  54. {
  55. // local variables
  56. CHString strUser;
  57. LONG lPos = 0;
  58. if ( ( NULL == pwszUser ) || ( 0 == StringLength( pwszUser, 0 ) ) )
  59. {
  60. return TRUE;
  61. }
  62. try
  63. {
  64. // get user into local memory
  65. strUser = pwszUser;
  66. // user name should not be just '\'
  67. if ( strUser.CompareNoCase( L"\\" ) == 0 )
  68. {
  69. return FALSE;
  70. }
  71. // user name should not contain invalid characters
  72. if ( strUser.FindOneOf( L"/[]:|<>+=;,?*" ) != -1 )
  73. {
  74. return FALSE;
  75. }
  76. // SPECIAL CHECK
  77. // check for multiple '\' characters in the user name
  78. lPos = strUser.Find( L'\\' );
  79. if ( -1 != lPos )
  80. {
  81. // '\' character exists in the user name
  82. // strip off the user info upto first '\' character
  83. // check for one more '\' in the remaining string
  84. // if it exists, invalid user
  85. strUser = strUser.Mid( lPos + 1 );
  86. lPos = strUser.Find( L'\\' );
  87. if ( -1 != lPos )
  88. {
  89. return FALSE;
  90. }
  91. }
  92. }
  93. catch( CHeap_Exception )
  94. {
  95. WMISaveError( WBEM_E_OUT_OF_MEMORY );
  96. return FALSE;
  97. }
  98. // user name is valid
  99. return TRUE;
  100. }
  101. BOOL
  102. IsValidServerEx(
  103. LPCWSTR pwszServer,
  104. BOOL& bLocalSystem
  105. )
  106. /*++
  107. Routine Description:
  108. Checks wether the Server name is a valid one or not
  109. Arguments:
  110. [in] LPCWSTR : String containing the user name
  111. [out] BOOL : Is set to TRUE if the local system is being queried.
  112. Return Value:
  113. TRUE on success
  114. FALSE on failure
  115. --*/
  116. {
  117. // local variables
  118. CHString strTemp;
  119. // Validate input arguments.
  120. if ( ( NULL == pwszServer ) || ( 0 == StringLength( pwszServer, 0 ) ) )
  121. {
  122. bLocalSystem = TRUE;
  123. return TRUE;
  124. }
  125. try
  126. {
  127. // kick-off
  128. bLocalSystem = FALSE;
  129. if( IsNumeric( pwszServer, 10, FALSE ) == TRUE )
  130. {
  131. return FALSE;
  132. }
  133. // get a local copy
  134. strTemp = pwszServer;
  135. // remove the forward slashes (UNC) if exist in the begining of the server name
  136. if ( IsUNCFormat( strTemp ) == TRUE )
  137. {
  138. strTemp = strTemp.Mid( 2 );
  139. if ( strTemp.GetLength() == 0 )
  140. {
  141. return FALSE;
  142. }
  143. }
  144. if ( strTemp.FindOneOf( L"`~!@#$^&*()+=[]{}|\\<>,?/\"':;" ) != -1 )
  145. {
  146. return FALSE;
  147. }
  148. // now check if any '\' character appears in the server name. If so error
  149. if ( strTemp.Find( L'\\' ) != -1 )
  150. {
  151. return FALSE;
  152. }
  153. // now check if server name is '.' only which represent local system in WMI
  154. // else determine whether this is a local system or not
  155. if ( strTemp.CompareNoCase( L"." ) == 0 )
  156. {
  157. bLocalSystem = TRUE;
  158. }
  159. else
  160. {
  161. bLocalSystem = IsLocalSystem( strTemp );
  162. }
  163. }
  164. catch( CHeap_Exception )
  165. {
  166. WMISaveError( WBEM_E_OUT_OF_MEMORY );
  167. return FALSE;
  168. }
  169. // inform that server name is valid
  170. return TRUE;
  171. }
  172. BOOL
  173. InitializeCom(
  174. IWbemLocator** ppLocator
  175. )
  176. /*++
  177. Routine Description:
  178. Initializes the COM library
  179. Arguments:
  180. [in] IWbemLocator : pointer to the IWbemLocator
  181. Return Value:
  182. TRUE on success
  183. FALSE on failure
  184. NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
  185. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  186. --*/
  187. {
  188. // local variables
  189. HRESULT hr = S_OK;
  190. BOOL bResult = FALSE;
  191. try
  192. {
  193. // Validate input arguments.
  194. if( ( NULL == ppLocator ) ||
  195. ( NULL != *ppLocator ) )
  196. {
  197. _com_issue_error( WBEM_E_INVALID_PARAMETER );
  198. }
  199. // initialize the COM library
  200. SAFE_EXECUTE( CoInitializeEx( NULL, COINIT_MULTITHREADED ) );
  201. // initialize the security
  202. SAFE_EXECUTE( CoInitializeSecurity( NULL, -1, NULL, NULL,
  203. RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0 ) );
  204. // create the locator and get the pointer to the interface of IWbemLocator
  205. SAFE_EXECUTE( CoCreateInstance( CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
  206. IID_IWbemLocator, ( LPVOID* ) ppLocator ) );
  207. // initialization successful
  208. bResult = TRUE;
  209. }
  210. catch( _com_error& e )
  211. {
  212. // save the WMI error
  213. WMISaveError( e );
  214. // Error is returned. Release any interface pointers.
  215. SAFE_RELEASE( *ppLocator );
  216. }
  217. // return the result;
  218. return bResult;
  219. }
  220. BOOL
  221. ConnectWmi(
  222. IWbemLocator* pLocator,
  223. IWbemServices** ppServices,
  224. LPCWSTR pwszServer,
  225. LPCWSTR pwszUser,
  226. LPCWSTR pwszPassword,
  227. COAUTHIDENTITY** ppAuthIdentity,
  228. BOOL bCheckWithNullPwd,
  229. LPCWSTR pwszNamespace,
  230. HRESULT* phr,
  231. BOOL* pbLocalSystem,
  232. IWbemContext* pWbemContext
  233. )
  234. /*++
  235. Routine Description:
  236. This function makes a connection to WMI.
  237. Arguments:
  238. [in] IWbemLocator : pointer to the IWbemLocator
  239. [in] IWbemServices : pointer to the IWbemServices
  240. [in] LPCWSTR : string containing the server name
  241. [in] LPCWSTR : string containing the User name
  242. [in] LPCWSTR : string containing the password
  243. [in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
  244. [in] BOOL : set to TRUE if we should try to connect with
  245. current credentials
  246. [in] LPCWSTR : string containing the namespace to connect to
  247. [out] HRESULT : the hResult value returned
  248. [out] BOOL : set to TRUE if we are querying for the local system
  249. Return Value:
  250. TRUE on success
  251. FALSE on failure
  252. NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
  253. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  254. --*/
  255. {
  256. // local variables
  257. HRESULT hr = S_OK;
  258. BOOL bResult = FALSE;
  259. BOOL bLocalSystem = FALSE;
  260. _bstr_t bstrServer;
  261. _bstr_t bstrNamespace;
  262. _bstr_t bstrUser, bstrPassword;
  263. // clear the error
  264. SetLastError( WBEM_S_NO_ERROR );
  265. // check whether locator object exists or not
  266. // if not exists, return
  267. if ( ( NULL == pLocator ) ||
  268. ( NULL == ppServices ) ||
  269. ( NULL != *ppServices ) ||
  270. ( NULL == pwszNamespace ) )
  271. {
  272. if ( NULL != phr )
  273. {
  274. *phr = WBEM_E_INVALID_PARAMETER;
  275. }
  276. // return failure
  277. return FALSE;
  278. }
  279. // kick-off
  280. if ( NULL != pbLocalSystem )
  281. {
  282. *pbLocalSystem = FALSE;
  283. }
  284. // ...
  285. if ( NULL != phr )
  286. {
  287. *phr = WBEM_S_NO_ERROR;
  288. }
  289. try
  290. {
  291. // assume that connection to WMI namespace is failed
  292. bResult = FALSE;
  293. // validate the server name
  294. // NOTE: The error being raised in custom define for '0x800706ba' value
  295. // The message that will be displayed in "The RPC server is unavailable."
  296. if ( IsValidServerEx( pwszServer, bLocalSystem ) == FALSE )
  297. {
  298. _com_issue_error( E_SERVER_NOTFOUND );
  299. }
  300. // validate the user name
  301. if ( IsValidUserEx( pwszUser ) == FALSE )
  302. {
  303. _com_issue_error( ERROR_NO_SUCH_USER );
  304. }
  305. // prepare namespace
  306. bstrNamespace = pwszNamespace; // name space
  307. if ( ( NULL != pwszServer ) && ( FALSE == bLocalSystem ) )
  308. {
  309. // get the server name
  310. bstrServer = pwszServer;
  311. // prepare the namespace
  312. // NOTE: check for the UNC naming format of the server and do
  313. if ( IsUNCFormat( pwszServer ) == TRUE )
  314. {
  315. bstrNamespace = bstrServer + L"\\" + pwszNamespace;
  316. }
  317. else
  318. {
  319. bstrNamespace = L"\\\\" + bstrServer + L"\\" + pwszNamespace;
  320. }
  321. // user credentials
  322. if ( ( NULL != pwszUser ) && ( 0 != StringLength( pwszUser, 0 ) ) )
  323. {
  324. // copy the user name
  325. bstrUser = pwszUser;
  326. // if password is empty string and if we need to check with
  327. // null password, then do not set the password and try
  328. bstrPassword = pwszPassword;
  329. if ( ( TRUE == bCheckWithNullPwd ) && ( 0 == bstrPassword.length() ) )
  330. {
  331. bstrPassword = (LPWSTR) NULL;
  332. }
  333. }
  334. }
  335. else
  336. { // Display warning message, credentials not required for local system.
  337. if( ( TRUE == bLocalSystem ) && ( NULL != pwszUser ) &&
  338. ( 0 != StringLength( pwszUser, 0 ) ) )
  339. {
  340. // got the credentials for the local system
  341. if ( NULL != phr )
  342. {
  343. *phr = WBEM_E_LOCAL_CREDENTIALS;
  344. }
  345. }
  346. }
  347. // connect to the remote system's WMI
  348. // there is a twist here ...
  349. // do not trap the ConnectServer function failure into exception
  350. // instead handle that action manually
  351. // by default try the ConnectServer function as the information which we have
  352. // in our hands at this point. If the ConnectServer is failed,
  353. // check whether password variable has any contents are not ... if no contents
  354. // check with "" (empty) password ... this might pass in this situation ..
  355. // if this call is also failed ... nothing is there that we can do ... throw the exception
  356. hr = pLocator->ConnectServer( bstrNamespace,
  357. bstrUser, bstrPassword, 0L, 0L, NULL, pWbemContext, ppServices );
  358. if ( FAILED( hr ) )
  359. {
  360. //
  361. // special case ...
  362. // check whether password exists or not
  363. // NOTE: do not check for 'WBEM_E_ACCESS_DENIED'
  364. // this error code says that user with the current credentials is not
  365. // having access permisions to the 'namespace'
  366. if ( hr == E_ACCESSDENIED )
  367. {
  368. // check if we tried to connect to the system using null password
  369. // if so, then try connecting to the remote system with empty string
  370. if ( bCheckWithNullPwd == TRUE &&
  371. bstrUser.length() != 0 && bstrPassword.length() == 0 )
  372. {
  373. // now invoke with ...
  374. hr = pLocator->ConnectServer( bstrNamespace,
  375. bstrUser, _bstr_t( L"" ), 0L, 0L, NULL, pWbemContext, ppServices );
  376. }
  377. }
  378. else
  379. {
  380. if ( WBEM_E_LOCAL_CREDENTIALS == hr )
  381. {
  382. // credentials were passed to the local system.
  383. // So ignore the credentials and try to reconnect
  384. bLocalSystem = TRUE;
  385. bstrUser = (LPWSTR) NULL;
  386. bstrPassword = (LPWSTR) NULL;
  387. bstrNamespace = pwszNamespace; // name space
  388. hr = pLocator->ConnectServer( bstrNamespace,
  389. NULL, NULL, 0L, 0L, NULL, pWbemContext, ppServices );
  390. }
  391. }
  392. // now check the result again .. if failed .. ummmm..
  393. if ( FAILED( hr ) )
  394. {
  395. _com_issue_error( hr );
  396. }
  397. else
  398. {
  399. bstrPassword = L"";
  400. }
  401. }
  402. // set the security at the interface level also
  403. SAFE_EXECUTE( SetInterfaceSecurity( *ppServices,
  404. bstrUser, bstrPassword, ppAuthIdentity ) );
  405. // ...
  406. if ( NULL != pbLocalSystem )
  407. {
  408. *pbLocalSystem = bLocalSystem;
  409. }
  410. // connection to WMI is successful
  411. bResult = TRUE;
  412. }
  413. catch( _com_error& e )
  414. {
  415. // save the error
  416. WMISaveError( e );
  417. // save the hr value if needed by the caller
  418. if ( NULL != phr )
  419. {
  420. *phr = e.Error();
  421. }
  422. SAFE_RELEASE( *ppServices );
  423. bResult = FALSE;
  424. }
  425. // return the result
  426. return bResult;
  427. }
  428. BOOL
  429. ConnectWmiEx(
  430. IWbemLocator* pLocator,
  431. IWbemServices** ppServices,
  432. LPCWSTR pwszServer,
  433. CHString& strUserName,
  434. CHString& strPassword,
  435. COAUTHIDENTITY** ppAuthIdentity,
  436. BOOL bNeedPassword,
  437. LPCWSTR pwszNamespace,
  438. BOOL* pbLocalSystem,
  439. DWORD dwPasswordLen,
  440. IWbemContext* pWbemContext
  441. )
  442. /*++
  443. Routine Description:
  444. This function is a wrapper function for the ConnectWmi function.
  445. Arguments:
  446. [in] IWbemLocator : pointer to the IWbemLocator
  447. [in] IWbemServices : pointer to the IWbemServices
  448. [in] LPCWSTR : string containing the server name
  449. [in] LPCWSTR : string containing the User name
  450. [in] LPCWSTR : string containing the password
  451. [in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
  452. [in] BOOL : set to TRUE if we should try to connect with
  453. current credentials
  454. [in] LPCWSTR : string containing the namespace to connect to
  455. [out] HRESULT : the hResult value returned
  456. [out] BOOL : set to TRUE if we are querying for the local system
  457. [ in ] DWORD : Contains maximum password buffer length.
  458. Return Value:
  459. TRUE on success
  460. FALSE on failure
  461. NOTE: 'dwPasswordLen' WILL BE TAKEN AS 'MAX_STRING_LENGTH' IF NOT SPECIFIED.
  462. IT IS USER RESPOSIBILITY TO SET THIS PARAMETER TO LIMITING VALUE.
  463. --*/
  464. {
  465. // local variables
  466. HRESULT hr = S_OK;
  467. DWORD dwSize = 0;
  468. BOOL bResult = FALSE;
  469. LPWSTR pwszPassword = NULL;
  470. CHString strBuffer;
  471. // clear the error .. if any
  472. SetLastError( WBEM_S_NO_ERROR );
  473. try
  474. {
  475. // sometime users want the utility to prompt for the password
  476. // check what user wants the utility to do
  477. if ( ( TRUE == bNeedPassword ) &&
  478. ( 0 == strPassword.Compare( L"*" ) ) )
  479. {
  480. // user wants the utility to prompt for the password
  481. // so skip this part and let the flow directly jump the password acceptance part
  482. }
  483. else
  484. {
  485. // try to establish connection to the remote system with the credentials supplied
  486. if ( 0 == strUserName.GetLength() )
  487. {
  488. // user name is empty
  489. // so, it is obvious that password will also be empty
  490. // even if password is specified, we have to ignore that
  491. bResult = ConnectWmi( pLocator, ppServices,
  492. pwszServer, NULL, NULL, ppAuthIdentity, FALSE, pwszNamespace, &hr, pbLocalSystem, pWbemContext );
  493. }
  494. else
  495. {
  496. // credentials were supplied
  497. // but password might not be specified ... so check and act accordingly
  498. LPCWSTR pwszTemp = NULL;
  499. BOOL bCheckWithNull = TRUE;
  500. if ( bNeedPassword == FALSE )
  501. {
  502. pwszTemp = strPassword;
  503. bCheckWithNull = FALSE;
  504. }
  505. // ...
  506. bResult = ConnectWmi( pLocator, ppServices, pwszServer,
  507. strUserName, pwszTemp, ppAuthIdentity, bCheckWithNull, pwszNamespace, &hr, pbLocalSystem, pWbemContext );
  508. }
  509. SetLastError (hr);
  510. // check the result ... if successful in establishing connection ... return
  511. if ( TRUE == bResult )
  512. {
  513. return TRUE;
  514. }
  515. // now check the kind of error occurred
  516. switch( hr )
  517. {
  518. case E_ACCESSDENIED:
  519. SetLastError( hr );
  520. break;
  521. case WBEM_E_LOCAL_CREDENTIALS:
  522. SetLastError( hr );
  523. // needs to do special processing
  524. break;
  525. case WBEM_E_ACCESS_DENIED:
  526. default:
  527. // NOTE: do not check for 'WBEM_E_ACCESS_DENIED'
  528. // this error code says that user with the current credentials is not
  529. // having access permisions to the 'namespace'
  530. WMISaveError( hr );
  531. return FALSE; // no use of accepting the password .. return failure
  532. break;
  533. }
  534. // if failed in establishing connection to the remote terminal
  535. // even if the password is specifed, then there is nothing to do ... simply return failure
  536. if ( bNeedPassword == FALSE )
  537. {
  538. return FALSE;
  539. }
  540. }
  541. // check whether user name is specified or not
  542. // if not, get the local system's current user name under whose credentials, the process
  543. // is running
  544. if ( 0 == strUserName.GetLength() )
  545. {
  546. // sub-local variables
  547. LPWSTR pwszUserName = NULL;
  548. DWORD dwUserLength = 0; // Username buffer length.
  549. // Retrieve the buffer length need to store username.
  550. GetUserNameEx( NameSamCompatible, pwszUserName, &dwUserLength );
  551. // get the required buffer
  552. pwszUserName = strUserName.GetBufferSetLength( dwUserLength );
  553. if ( FALSE == GetUserNameEx( NameSamCompatible, pwszUserName, &dwUserLength ) )
  554. {
  555. // error occured while trying to get the current user info
  556. SaveLastError();
  557. return FALSE;
  558. }
  559. // No need to call 'ReleaseBuffer' since only sufficient memory is allocated.
  560. }
  561. // get the required buffer
  562. if( 0 == dwPasswordLen )
  563. {
  564. dwPasswordLen = INPUT_PASSWORD_LEN;
  565. }
  566. pwszPassword = strPassword.GetBufferSetLength( dwPasswordLen );
  567. // accept the password from the user
  568. strBuffer.Format( INPUT_PASSWORD, strUserName );
  569. WriteConsoleW( GetStdHandle( STD_OUTPUT_HANDLE ),
  570. strBuffer, strBuffer.GetLength(), &dwSize, NULL );
  571. bResult = GetPassword( pwszPassword, dwPasswordLen );
  572. if ( TRUE != bResult )
  573. {
  574. return FALSE;
  575. }
  576. // release the buffer allocated for password
  577. strPassword.ReleaseBuffer();
  578. // now again try to establish the connection using the currently
  579. // supplied credentials
  580. bResult = ConnectWmi( pLocator, ppServices, pwszServer,
  581. strUserName, strPassword, ppAuthIdentity, FALSE, pwszNamespace,
  582. NULL, pbLocalSystem, pWbemContext );
  583. }
  584. catch( CHeap_Exception )
  585. {
  586. WMISaveError( WBEM_E_OUT_OF_MEMORY );
  587. return FALSE;
  588. }
  589. // return the failure
  590. return bResult;
  591. }
  592. HRESULT
  593. GetSecurityArguments(
  594. IUnknown* pInterface,
  595. DWORD& dwAuthorization,
  596. DWORD& dwAuthentication
  597. )
  598. /*++
  599. Routine Description:
  600. This function gets the values for the security services.
  601. Arguments:
  602. [in] IUnknown : pointer to the IUnkown interface
  603. [out] DWORD : to hold the authentication service value
  604. [out] DWORD : to hold the authorization service value
  605. Return Value:
  606. HRESULT
  607. --*/
  608. {
  609. // local variables
  610. HRESULT hr = S_OK;
  611. DWORD dwAuthnSvc = 0, dwAuthzSvc = 0;
  612. IClientSecurity* pClientSecurity = NULL;
  613. if ( NULL == pInterface )
  614. {
  615. return WBEM_E_INVALID_PARAMETER;
  616. }
  617. // try to get the client security services values if possible
  618. hr = pInterface->QueryInterface( IID_IClientSecurity, (void**) &pClientSecurity );
  619. if ( SUCCEEDED( hr ) )
  620. {
  621. // got the client security interface
  622. // now try to get the security services values
  623. hr = pClientSecurity->QueryBlanket( pInterface,
  624. &dwAuthnSvc, &dwAuthzSvc, NULL, NULL, NULL, NULL, NULL );
  625. if ( SUCCEEDED( hr ) )
  626. {
  627. // we've got the values from the interface
  628. dwAuthentication = dwAuthnSvc;
  629. dwAuthorization = dwAuthzSvc;
  630. }
  631. // release the client security interface
  632. SAFE_RELEASE( pClientSecurity );
  633. }
  634. // return always success
  635. return hr;
  636. }
  637. HRESULT
  638. SetInterfaceSecurity(
  639. IUnknown* pInterface,
  640. LPCWSTR pwszUser,
  641. LPCWSTR pwszPassword,
  642. COAUTHIDENTITY** ppAuthIdentity
  643. )
  644. /*++
  645. Routine Description:
  646. This function sets the interface security parameters.
  647. Arguments:
  648. [in] IUnknown : pointer to the IUnkown interface
  649. [in] LPCWSTR : string containing the User name
  650. [in] LPCWSTR : string containing the password
  651. [in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
  652. Return Value:
  653. HRESULT
  654. --*/
  655. {
  656. // local variables
  657. HRESULT hr = S_OK;
  658. CHString strUser;
  659. CHString strDomain;
  660. LPCWSTR pwszUserArg = NULL;
  661. LPCWSTR pwszDomainArg = NULL;
  662. DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
  663. DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
  664. try
  665. {
  666. // check the interface
  667. if ( NULL == pInterface )
  668. {
  669. return WBEM_E_INVALID_PARAMETER;
  670. }
  671. // check the authentity strcuture ... if authentity structure is already ready
  672. // simply invoke the 2nd version of SetInterfaceSecurity
  673. if ( NULL != *ppAuthIdentity )
  674. {
  675. return SetInterfaceSecurity( pInterface, *ppAuthIdentity );
  676. }
  677. // If we are doing trivial case, just pass in a null authenication structure
  678. // for which the current logged in user's credentials will be considered
  679. if ( ( NULL == pwszUser ) &&
  680. ( NULL == pwszPassword ) )
  681. {
  682. // set the security
  683. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization,
  684. NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY , RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
  685. // return the result
  686. return hr;
  687. }
  688. // if authority srtucture is NULL then no need to proceed
  689. if ( NULL == ppAuthIdentity )
  690. {
  691. return WBEM_E_INVALID_PARAMETER;
  692. }
  693. // check if authenication info is available or not ...
  694. // initialize the security authenication information ... UNICODE VERSION STRUCTURE
  695. if ( NULL == *ppAuthIdentity )
  696. {
  697. // parse and find out if the user name contains the domain name
  698. // if contains, extract the domain value from it
  699. LONG lPos = -1;
  700. strDomain = L"";
  701. strUser = pwszUser;
  702. if ( -1 != ( lPos = strUser.Find( L'\\' ) ) )
  703. {
  704. // user name contains domain name ... domain\user format
  705. strDomain = strUser.Left( lPos );
  706. strUser = strUser.Mid( lPos + 1 );
  707. }
  708. else
  709. {
  710. if ( -1 != ( lPos = strUser.Find( L'@' ) ) )
  711. {
  712. // NEED TO IMPLEMENT THIS ... IF NEEDED
  713. // This implementation needs to be done if WMI does not support
  714. // UPN name formats directly and if we have to split the
  715. // name(user@domain)
  716. }
  717. else
  718. {
  719. // server itself is the domain
  720. // NOTE: NEED TO DO SOME R & D ON BELOW COMMENTED LINE
  721. // strDomain = pwszServer;
  722. }
  723. }
  724. // get the domain info if it exists only
  725. if ( 0 != strDomain.GetLength() )
  726. {
  727. pwszDomainArg = strDomain;
  728. }
  729. // get the user info if it exists only
  730. if ( 0 != strUser.GetLength() )
  731. {
  732. pwszUserArg = strUser;
  733. }
  734. hr = WbemAllocAuthIdentity( pwszUserArg, pwszPassword, pwszDomainArg, ppAuthIdentity );
  735. if ( FAILED(hr) )
  736. {
  737. return hr;
  738. }
  739. }
  740. // set the security information to the interface
  741. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
  742. RPC_C_AUTHN_LEVEL_PKT_PRIVACY , RPC_C_IMP_LEVEL_IMPERSONATE, *ppAuthIdentity, EOAC_NONE );
  743. }
  744. catch( CHeap_Exception )
  745. {
  746. hr = WBEM_E_OUT_OF_MEMORY;
  747. }
  748. // return the result
  749. return hr;
  750. }
  751. HRESULT
  752. SetInterfaceSecurity(
  753. IUnknown* pInterface,
  754. COAUTHIDENTITY* pAuthIdentity
  755. )
  756. /*++
  757. Routine Description:
  758. This function sets the interface security parameters.
  759. Arguments:
  760. [in] IUnknown : pointer to the IUnkown interface
  761. [in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
  762. Return Value:
  763. HRESULT
  764. --*/
  765. {
  766. // local variables
  767. HRESULT hr = S_OK;
  768. DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
  769. DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
  770. // check the interface
  771. // 'pAuthIdentity' can be NULL or not, so need to check.
  772. if ( NULL == pInterface )
  773. {
  774. return WBEM_E_INVALID_PARAMETER;
  775. }
  776. // get the current security argument value
  777. hr = GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication );
  778. if ( FAILED( hr ) )
  779. {
  780. return hr;
  781. }
  782. // set the security information to the interface
  783. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
  784. RPC_C_AUTHN_LEVEL_PKT_PRIVACY , RPC_C_IMP_LEVEL_IMPERSONATE, pAuthIdentity, EOAC_NONE );
  785. // return the result
  786. return hr;
  787. }
  788. HRESULT
  789. WINAPI SetProxyBlanket(
  790. IUnknown* pInterface,
  791. DWORD dwAuthnSvc,
  792. DWORD dwAuthzSvc,
  793. LPWSTR pwszPrincipal,
  794. DWORD dwAuthLevel,
  795. DWORD dwImpLevel,
  796. RPC_AUTH_IDENTITY_HANDLE pAuthInfo,
  797. DWORD dwCapabilities
  798. )
  799. /*++
  800. Routine Description:
  801. This function sets the authentication information (the security blanket)
  802. that will be used to make calls.
  803. Arguments:
  804. [in] IUnknown : pointer to the IUnkown interface
  805. [in] DWORD : contains the authentication service to use
  806. [in] DWORD : contains the authorization service to use
  807. [in] LPWSTR : the server principal name to use
  808. [in] DWORD : contains the authentication level to use
  809. [in] DWORD : contains the impersonation level to use
  810. [in] RPC_AUTH_IDENTITY_HANDLE : pointer to the identity of the client
  811. [in] DWORD : contains the capability flags
  812. Return Value:
  813. HRESULT
  814. --*/
  815. {
  816. // local variables
  817. HRESULT hr = S_OK;
  818. IUnknown * pUnknown = NULL;
  819. IClientSecurity * pClientSecurity = NULL;
  820. // Validate input arguments.
  821. //
  822. // Can't set pAuthInfo if cloaking requested, as cloaking implies
  823. // that the current proxy identity in the impersonated thread (rather
  824. // than the credentials supplied explicitly by the RPC_AUTH_IDENTITY_HANDLE)
  825. // is to be used.
  826. // See MSDN info on CoSetProxyBlanket for more details.
  827. //
  828. if( ( NULL == pInterface ) ||
  829. ( ( dwCapabilities & (EOAC_STATIC_CLOAKING | EOAC_DYNAMIC_CLOAKING) ) &&
  830. ( NULL != pAuthInfo ) )
  831. )
  832. {
  833. return( WBEM_E_INVALID_PARAMETER );
  834. }
  835. // get the IUnknown interface ... to check whether this is a valid interface or not
  836. hr = pInterface->QueryInterface( IID_IUnknown, (void **) &pUnknown );
  837. if ( FAILED(hr) )
  838. {
  839. return hr;
  840. }
  841. // now get the client security interface
  842. hr = pInterface->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
  843. if ( FAILED(hr) )
  844. {
  845. SAFE_RELEASE( pUnknown );
  846. return hr;
  847. }
  848. // now set the security
  849. hr = pClientSecurity->SetBlanket( pInterface, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
  850. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
  851. if( FAILED( hr ) )
  852. {
  853. SAFE_RELEASE( pUnknown );
  854. SAFE_RELEASE( pClientSecurity );
  855. return hr;
  856. }
  857. // release the security interface
  858. SAFE_RELEASE( pClientSecurity );
  859. // we should check the auth identity structure. if exists .. set for IUnknown also
  860. if ( NULL != pAuthInfo )
  861. {
  862. hr = pUnknown->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
  863. if ( SUCCEEDED(hr) )
  864. {
  865. // set security authentication
  866. hr = pClientSecurity->SetBlanket( pUnknown, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
  867. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
  868. // release
  869. SAFE_RELEASE( pClientSecurity );
  870. }
  871. else
  872. {
  873. if ( E_NOINTERFACE == hr )
  874. {
  875. hr = S_OK; // ignore no interface errors
  876. }
  877. }
  878. }
  879. // release the IUnknown
  880. SAFE_RELEASE( pUnknown );
  881. // return the result
  882. return hr;
  883. }
  884. HRESULT
  885. WINAPI WbemAllocAuthIdentity(
  886. LPCWSTR pwszUser,
  887. LPCWSTR pwszPassword,
  888. LPCWSTR pwszDomain,
  889. COAUTHIDENTITY** ppAuthIdent
  890. )
  891. /*++
  892. Routine Description:
  893. This function allocates memory for the AUTHIDENTITY structure.
  894. Arguments:
  895. [in] LPCWSTR : string containing the user name
  896. [in] LPCWSTR : string containing the password
  897. [in] LPCWSTR : string containing the domain name
  898. [out] COAUTHIDENTITY : pointer to the pointer to AUTHIDENTITY structure
  899. Return Value:
  900. HRESULT
  901. NOTE: 'ppAuthIdent' should be freed by calling 'WbemFreeAuthIdentity' by the user after
  902. their work is done.
  903. --*/
  904. {
  905. // local variables
  906. COAUTHIDENTITY* pAuthIdent = NULL;
  907. // validate the input parameter
  908. if ( NULL == ppAuthIdent )
  909. {
  910. return WBEM_E_INVALID_PARAMETER;
  911. }
  912. // allocation thru COM API
  913. pAuthIdent = ( COAUTHIDENTITY* ) CoTaskMemAlloc( sizeof( COAUTHIDENTITY ) );
  914. if ( NULL == pAuthIdent )
  915. {
  916. return WBEM_E_OUT_OF_MEMORY;
  917. }
  918. // init with 0's
  919. SecureZeroMemory( ( void* ) pAuthIdent, sizeof( COAUTHIDENTITY ) );
  920. //
  921. // Allocate needed memory and copy in data. Cleanup if anything goes wrong
  922. // user
  923. if ( NULL != pwszUser )
  924. {
  925. // allocate memory for user
  926. LONG lLength = StringLength( pwszUser, 0 );
  927. pAuthIdent->User = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  928. if ( NULL == pAuthIdent->User )
  929. {
  930. WbemFreeAuthIdentity( &pAuthIdent );
  931. return WBEM_E_OUT_OF_MEMORY;
  932. }
  933. // set the length and do copy contents
  934. pAuthIdent->UserLength = lLength;
  935. StringCopy( pAuthIdent->User, pwszUser, (lLength + 1) );
  936. }
  937. // domain
  938. if ( NULL != pwszDomain )
  939. {
  940. // allocate memory for domain
  941. LONG lLength = StringLength( pwszDomain, 0 );
  942. pAuthIdent->Domain = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  943. if ( NULL == pAuthIdent->Domain )
  944. {
  945. WbemFreeAuthIdentity( &pAuthIdent );
  946. return WBEM_E_OUT_OF_MEMORY;
  947. }
  948. // set the length and do copy contents
  949. pAuthIdent->DomainLength = lLength;
  950. StringCopy( pAuthIdent->Domain, pwszDomain, (lLength + 1) );
  951. }
  952. // passsord
  953. if ( NULL != pwszPassword )
  954. {
  955. // allocate memory for passsord
  956. LONG lLength = StringLength( pwszPassword, 0 );
  957. pAuthIdent->Password = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  958. if ( NULL == pAuthIdent->Password )
  959. {
  960. WbemFreeAuthIdentity( &pAuthIdent );
  961. return WBEM_E_OUT_OF_MEMORY;
  962. }
  963. // set the length and do copy contents
  964. pAuthIdent->PasswordLength = lLength;
  965. StringCopy( pAuthIdent->Password, pwszPassword, (lLength + 1) );
  966. }
  967. // type of the structure
  968. pAuthIdent->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  969. // final set the address to out parameter
  970. *ppAuthIdent = pAuthIdent;
  971. // return result
  972. return S_OK;
  973. }
  974. VOID
  975. WINAPI WbemFreeAuthIdentity(
  976. COAUTHIDENTITY** ppAuthIdentity
  977. )
  978. /*++
  979. Routine Description:
  980. This function releases the memory allocated for the AUTHIDENTITY structure.
  981. Arguments:
  982. [in] COAUTHIDENTITY : pointer to the pointer to AUTHIDENTITY structure
  983. Return Value:
  984. None
  985. --*/
  986. {
  987. // make sure we have a pointer, then walk the structure members and cleanup.
  988. if ( *ppAuthIdentity != NULL )
  989. {
  990. // free the memory allocated for user
  991. if ( NULL != (*ppAuthIdentity)->User )
  992. {
  993. CoTaskMemFree( (*ppAuthIdentity)->User );
  994. (*ppAuthIdentity)->User = NULL;
  995. }
  996. // free the memory allocated for password
  997. if ( NULL != (*ppAuthIdentity)->Password )
  998. {
  999. CoTaskMemFree( (*ppAuthIdentity)->Password );
  1000. (*ppAuthIdentity)->Password = NULL;
  1001. }
  1002. // free the memory allocated for domain
  1003. if ( NULL != (*ppAuthIdentity)->Domain )
  1004. {
  1005. CoTaskMemFree( (*ppAuthIdentity)->Domain );
  1006. (*ppAuthIdentity)->Domain = NULL;
  1007. }
  1008. // final the structure
  1009. CoTaskMemFree( *ppAuthIdentity );
  1010. *ppAuthIdentity = NULL;
  1011. }
  1012. }
  1013. VOID
  1014. WMISaveError(
  1015. HRESULT hrError
  1016. )
  1017. /*++
  1018. Routine Description:
  1019. This function saves the description of the last error returned by WMI
  1020. Arguments:
  1021. HRESULT : The last return value from WMI
  1022. Return Value:
  1023. NONE
  1024. --*/
  1025. {
  1026. // local variables
  1027. HRESULT hr = S_OK;
  1028. IWbemStatusCodeText* pWbemStatus = NULL;
  1029. _bstr_t bstrErrorString;
  1030. try
  1031. {
  1032. // Set error to different value.
  1033. if ( E_ACCESSDENIED == hrError )
  1034. {
  1035. // change the error message to "Logon failure: unknown user name or bad password."
  1036. hrError = ERROR_LOGON_FAILURE;
  1037. }
  1038. //Set the reason to incompatible os when no class is registered on remote mechine
  1039. if( 0x80040154 == hrError )
  1040. {
  1041. bstrErrorString = _bstr_t( GetResString(IDS_ERROR_REMOTE_INCOMPATIBLE));
  1042. SetReason( bstrErrorString );
  1043. return;
  1044. }
  1045. else
  1046. { // Get error string.
  1047. hr = CoCreateInstance( CLSID_WbemStatusCodeText,
  1048. NULL, CLSCTX_INPROC_SERVER,
  1049. IID_IWbemStatusCodeText,
  1050. (LPVOID*) &pWbemStatus );
  1051. if( SUCCEEDED( hr ) )
  1052. {
  1053. BSTR bstrString = NULL;
  1054. // Get error string from error code.
  1055. hr = pWbemStatus->GetErrorCodeText( hrError, 0, 0,
  1056. &bstrString );
  1057. if( NULL != bstrString )
  1058. {
  1059. bstrErrorString = _bstr_t( bstrString );
  1060. SysFreeString( bstrString );
  1061. }
  1062. if( FAILED( hr ) )
  1063. {
  1064. _com_issue_error( hrError );
  1065. }
  1066. }
  1067. else
  1068. {
  1069. _com_issue_error( hrError );
  1070. }
  1071. }
  1072. }
  1073. catch( _com_error& e )
  1074. { // We have got the error. Needs to handle carefully.
  1075. LPWSTR lpwszGetString = NULL;
  1076. try
  1077. { // ErrorMessage() can throw an exception.
  1078. DWORD dwLength = StringLength( e.ErrorMessage(), 0 ) + 5 ;
  1079. lpwszGetString = ( LPWSTR )AllocateMemory( dwLength * sizeof( WCHAR ) );
  1080. if( NULL != lpwszGetString )
  1081. {
  1082. StringCopy( lpwszGetString, e.ErrorMessage(), dwLength );
  1083. StringConcat( lpwszGetString, L"\n", dwLength );
  1084. SetReason( ( LPCWSTR )lpwszGetString );
  1085. FreeMemory( (LPVOID*) &lpwszGetString );
  1086. }
  1087. else
  1088. { // Failed to know the exact error occured
  1089. // due to insufficient memory.
  1090. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  1091. SaveLastError();
  1092. }
  1093. }
  1094. catch( ... )
  1095. {
  1096. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  1097. SaveLastError();
  1098. }
  1099. return;
  1100. }
  1101. SetReason( (LPCWSTR) bstrErrorString );
  1102. return;
  1103. }
  1104. HRESULT
  1105. PropertyGet(
  1106. IWbemClassObject* pWmiObject,
  1107. LPCWSTR pwszProperty,
  1108. _variant_t& varValue
  1109. )
  1110. /*++
  1111. Routine Description:
  1112. Gets the value of the property from the WMI class object
  1113. Arguments:
  1114. [in] IWbemClassObject : pointer to the WBEM class object
  1115. [in] LPCWSTR : property name
  1116. [out] _variant_t : value of the property
  1117. Return Value:
  1118. HRESULT
  1119. --*/
  1120. {
  1121. // local variables
  1122. HRESULT hr = S_OK;
  1123. VARIANT vtValue;
  1124. // Validate input arguments.
  1125. if ( ( NULL == pWmiObject ) ||
  1126. ( NULL == pwszProperty ) )
  1127. {
  1128. return WBEM_E_INVALID_PARAMETER;
  1129. }
  1130. try
  1131. {
  1132. // initialize the variant and then get the value of the specified property
  1133. VariantInit( &vtValue );
  1134. // Call 'Get' method to retireve the value from WMI.
  1135. hr = pWmiObject->Get( _bstr_t( pwszProperty ), 0, &vtValue, NULL, NULL );
  1136. if ( FAILED( hr ) )
  1137. {
  1138. // Clear the variant variable
  1139. VariantClear( &vtValue );
  1140. // Return error.
  1141. return hr;
  1142. }
  1143. // set the value
  1144. varValue = vtValue;
  1145. }
  1146. catch( _com_error& e )
  1147. {
  1148. hr = e.Error();
  1149. }
  1150. // Clear the variables.
  1151. VariantClear( &vtValue );
  1152. // Return.
  1153. return hr;
  1154. }
  1155. HRESULT PropertyGet(
  1156. IWbemClassObject* pWmiObject,
  1157. LPCWSTR pwszProperty,
  1158. VARIANT* pvarValue )
  1159. /*++
  1160. // Routine Description:
  1161. // Gets the value of the property from the WMI class object
  1162. //
  1163. // Arguments:
  1164. // [ in ] pWmiObject : pointer to the WBEM class object
  1165. // [ in ] szProperty : property name
  1166. // [ out ] varValue : value of the property
  1167. //
  1168. // Return Value:
  1169. // HRESULT - result of the operation
  1170. //
  1171. --*/
  1172. {
  1173. // local variables
  1174. HRESULT hr;
  1175. // check with object and property passed to the function are valid or not
  1176. // if not, return failure
  1177. if ( pWmiObject == NULL || pwszProperty == NULL || pvarValue == NULL )
  1178. return WBEM_E_INVALID_PARAMETER;
  1179. try
  1180. {
  1181. // initialize the variant and then get the value of the specified property
  1182. hr = pWmiObject->Get( _bstr_t( pwszProperty ), 0, pvarValue, NULL, NULL );
  1183. if ( FAILED( hr ) )
  1184. {
  1185. // clear the variant variable
  1186. VariantClear( pvarValue );
  1187. // failed to get the value for the property
  1188. return hr;
  1189. }
  1190. }
  1191. catch( _com_error& e )
  1192. {
  1193. WMISaveError( e );
  1194. return e.Error();
  1195. }
  1196. // inform success
  1197. return S_OK;
  1198. }
  1199. BOOL PropertyGet(
  1200. IWbemClassObject* pWmiObject,
  1201. LPCWSTR pwszProperty,
  1202. TARRAY arr )
  1203. /*++
  1204. Routine Description:
  1205. Gets the value of the property from the WMI class object in string format
  1206. Arguments:
  1207. [in] IWbemClassObject : pointer to the WBEM class object
  1208. [in] LPCWSTR : property name
  1209. [out] arr : value of the property
  1210. Return Value:
  1211. BOOL
  1212. --*/
  1213. {
  1214. // local variables
  1215. HRESULT hr;
  1216. VARIANT vtValue;
  1217. LONG lIndex = 0;
  1218. LONG lLBound = 0;
  1219. LONG lUBound = 0;
  1220. VARTYPE vartype;
  1221. SAFEARRAY* pSafeArray = NULL;
  1222. // check the inputs
  1223. if ( pWmiObject == NULL || pwszProperty == NULL || arr == NULL )
  1224. return FALSE;
  1225. // initialize the variant
  1226. VariantInit( &vtValue );
  1227. // now get the property value
  1228. hr = PropertyGet( pWmiObject, pwszProperty, &vtValue );
  1229. if ( FAILED( hr ) )
  1230. return FALSE;
  1231. if ( V_VT( &vtValue ) == VT_NULL )
  1232. return TRUE;
  1233. // confirm that the propety value is of array type .. if not return
  1234. if ( ( V_VT( &vtValue ) & VT_ARRAY ) == 0 )
  1235. return FALSE;
  1236. // get the safearray value
  1237. pSafeArray = V_ARRAY( &vtValue );
  1238. // get the bounds of the array
  1239. SafeArrayGetLBound( pSafeArray, 1, &lLBound );
  1240. SafeArrayGetUBound( pSafeArray, 1, &lUBound );
  1241. // get the type of the elements in the safe array
  1242. vartype = (VARTYPE) (V_VT( &vtValue ) & ~VT_ARRAY);
  1243. try
  1244. {
  1245. // traverse thru the values in the safe array and update into dynamic array
  1246. for( lIndex = lLBound; lIndex <= lUBound; lIndex++ )
  1247. {
  1248. // sub-local variables
  1249. VARIANT var;
  1250. CHString strValue;
  1251. // get the value
  1252. V_VT( &var ) = vartype;
  1253. SafeArrayGetElement( pSafeArray, &lIndex, &V_UI1( &var ) );
  1254. // add the information to the dynamic array
  1255. switch( vartype )
  1256. {
  1257. case VT_BSTR:
  1258. strValue = V_BSTR( &var );
  1259. DynArrayAppendString( arr, strValue, 0 );
  1260. break;
  1261. }
  1262. }
  1263. }
  1264. catch( ... )
  1265. {
  1266. // clear the variant
  1267. VariantClear( &vtValue );
  1268. return FALSE; // failure
  1269. }
  1270. // clear the variant
  1271. VariantClear( &vtValue );
  1272. // return
  1273. return TRUE;
  1274. }
  1275. BOOL
  1276. PropertyGet(
  1277. IWbemClassObject* pWmiObject,
  1278. LPCWSTR pwszProperty,
  1279. CHString& strValue,
  1280. LPCWSTR pwszDefault
  1281. )
  1282. /*++
  1283. Routine Description:
  1284. Gets the value of the property from the WMI class object in string format
  1285. Arguments:
  1286. [in] IWbemClassObject : pointer to the WBEM class object
  1287. [in] LPCWSTR : the name of the property to retrieve
  1288. [out] CHString : variable to hold the retrieved property
  1289. [in] LPCWSTR : string containing the default value for the property
  1290. Return Value:
  1291. TRUE on success
  1292. FALSE on failure
  1293. NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
  1294. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  1295. --*/
  1296. {
  1297. // local variables
  1298. HRESULT hr = S_OK;
  1299. _variant_t var;
  1300. // Clear any errors.
  1301. SetLastError( WBEM_S_NO_ERROR );
  1302. strValue.Empty();
  1303. try
  1304. {
  1305. // first copy the default value
  1306. strValue = pwszDefault;
  1307. // Validate input arguments.
  1308. if ( ( NULL == pWmiObject ) ||
  1309. ( NULL == pwszProperty ) )
  1310. {
  1311. _com_issue_error( WBEM_E_INVALID_PARAMETER );
  1312. }
  1313. // get the property value
  1314. hr = PropertyGet( pWmiObject, pwszProperty, var );
  1315. if ( FAILED( hr ) )
  1316. {
  1317. _com_issue_error( hr );
  1318. }
  1319. // Get the value
  1320. // If 'var' does not contain value of requested type
  1321. // then default value is returned.
  1322. if ( VT_BSTR == V_VT( &var ) )
  1323. {
  1324. strValue = (LPCWSTR) _bstr_t( var );
  1325. }
  1326. }
  1327. catch( _com_error& e )
  1328. {
  1329. WMISaveError( e );
  1330. return FALSE;
  1331. }
  1332. catch( CHeap_Exception )
  1333. {
  1334. WMISaveError( WBEM_E_OUT_OF_MEMORY );
  1335. return FALSE;
  1336. }
  1337. // return
  1338. return TRUE;
  1339. }
  1340. BOOL
  1341. PropertyGet(
  1342. IWbemClassObject* pWmiObject,
  1343. LPCWSTR pwszProperty,
  1344. DWORD& dwValue,
  1345. DWORD dwDefault
  1346. )
  1347. /*++
  1348. Routine Description:
  1349. Gets the value of the property from the WMI class object in dword format
  1350. Arguments:
  1351. [in] IWbemClassObject : pointer to the WBEM class object
  1352. [in] LPCWSTR : the name of the property to retrieve
  1353. [out] DWORD : variable to hold the retrieved property
  1354. [in] DWORD : dword containing the default value for the property
  1355. Return Value:
  1356. TRUE on success
  1357. FALSE on failure
  1358. NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
  1359. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  1360. --*/
  1361. {
  1362. // local variables
  1363. HRESULT hr;
  1364. _variant_t var;
  1365. // first set the defaul value
  1366. dwValue = dwDefault;
  1367. // check with object and property passed to the function are valid or not
  1368. // if not, return failure
  1369. if ( pWmiObject == NULL || pwszProperty == NULL )
  1370. return FALSE;
  1371. // get the value of the property
  1372. hr = PropertyGet( pWmiObject, pwszProperty, var );
  1373. if ( FAILED( hr ) )
  1374. return FALSE;
  1375. // get the process id from the variant
  1376. if ( var.vt != VT_NULL && var.vt != VT_EMPTY )
  1377. dwValue = (LONG) var;
  1378. // return
  1379. return TRUE;
  1380. }
  1381. BOOL
  1382. PropertyGet(
  1383. IWbemClassObject* pWmiObject,
  1384. LPCWSTR pwszProperty,
  1385. BOOL& bValue,
  1386. BOOL bDefault
  1387. )
  1388. /*++
  1389. Routine Description:
  1390. Gets the value of the property from the WMI class object in bool format
  1391. Arguments:
  1392. [in] IWbemClassObject : pointer to the WBEM class object
  1393. [in] LPCWSTR : the name of the property to retrieve
  1394. [out] BOOL : variable to hold the retrieved property
  1395. [in] BOOL : bool containing the default value for the property
  1396. Return Value:
  1397. TRUE on success
  1398. FALSE on failure
  1399. NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
  1400. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  1401. --*/
  1402. {
  1403. // local variables
  1404. HRESULT hr = S_OK;
  1405. _variant_t var;
  1406. // Clear any errors.
  1407. SetLastError( WBEM_S_NO_ERROR );
  1408. try
  1409. {
  1410. // first set the default value
  1411. bValue = bDefault;
  1412. // Validate input arguments.
  1413. if ( ( NULL == pWmiObject ) ||
  1414. ( NULL == pwszProperty ) )
  1415. {
  1416. _com_issue_error( WBEM_E_INVALID_PARAMETER );
  1417. }
  1418. // get the value of the property
  1419. hr = PropertyGet( pWmiObject, pwszProperty, var );
  1420. if ( FAILED( hr ) )
  1421. {
  1422. _com_issue_error( hr );
  1423. }
  1424. // Save value obtained.
  1425. // If 'var' does not contain value of requested type
  1426. // then default value is returned.
  1427. if ( VT_BOOL == V_VT( &var ) )
  1428. {
  1429. bValue = var.boolVal;
  1430. }
  1431. }
  1432. catch( _com_error& e )
  1433. {
  1434. WMISaveError( e );
  1435. return FALSE;
  1436. }
  1437. // return
  1438. return TRUE;
  1439. }
  1440. BOOL
  1441. PropertyGet(
  1442. IWbemClassObject* pWmiObject,
  1443. LPCWSTR pwszProperty,
  1444. ULONGLONG& ullValue
  1445. )
  1446. /*++
  1447. Routine Description:
  1448. Gets the value of the property from the WMI class object in ulongulong format
  1449. Arguments:
  1450. [in] IWbemClassObject : pointer to the WBEM class object
  1451. [in] LPCWSTR : the name of the property to retrieve
  1452. [out] ULONGULONG : variable to hold the retrieved property
  1453. Return Value:
  1454. TRUE on success
  1455. FALSE on failure
  1456. NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
  1457. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  1458. --*/
  1459. {
  1460. // Local variables
  1461. CHString str;
  1462. // Clear any errors.
  1463. SetLastError( WBEM_S_NO_ERROR );
  1464. str.Empty();
  1465. try
  1466. {
  1467. // first set the default value
  1468. ullValue = 1;
  1469. // Validate input arguments.
  1470. if ( ( NULL == pWmiObject ) ||
  1471. ( NULL == pwszProperty ) )
  1472. {
  1473. WMISaveError( WBEM_E_INVALID_PARAMETER );
  1474. return FALSE;
  1475. }
  1476. // get the value of the property
  1477. if ( FALSE == PropertyGet( pWmiObject, pwszProperty, str, _T( "0" ) ) )
  1478. { // Error is already set in 'PropertyGet' function.
  1479. return FALSE;
  1480. }
  1481. // get the 64-bit value
  1482. ullValue = _wtoi64( str );
  1483. // Check for error condition.
  1484. if( 0 == ullValue )
  1485. {
  1486. ullValue = 1;
  1487. WMISaveError( WBEM_E_INVALID_PARAMETER );
  1488. return FALSE;
  1489. }
  1490. }
  1491. catch( CHeap_Exception )
  1492. {
  1493. WMISaveError( WBEM_E_OUT_OF_MEMORY );
  1494. return FALSE;
  1495. }
  1496. // return
  1497. return TRUE;
  1498. }
  1499. BOOL
  1500. PropertyGet(
  1501. IWbemClassObject* pWmiObject,
  1502. LPCWSTR pwszProperty,
  1503. WBEMTime& wbemtime )
  1504. /*++
  1505. Routine Description:
  1506. Gets the value of the property from the WMI class object in wbemtime format
  1507. Arguments:
  1508. [in] IWbemClassObject : pointer to the WBEM class object
  1509. [in] LPCWSTR : the name of the property to retrieve
  1510. [out] WBEMTime : variable to hold the retrieved property
  1511. Return Value:
  1512. TRUE on success
  1513. FALSE on failure
  1514. NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
  1515. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  1516. --*/
  1517. {
  1518. // local variables
  1519. CHString str;
  1520. // Clear any errors.
  1521. SetLastError( WBEM_S_NO_ERROR );
  1522. // Clear method sets the time in the WBEMTime object to an invalid time.
  1523. wbemtime.Clear();
  1524. try
  1525. {
  1526. // Validate input arguments.
  1527. if ( ( NULL == pWmiObject ) ||
  1528. ( NULL == pwszProperty ) )
  1529. {
  1530. WMISaveError( WBEM_E_INVALID_PARAMETER );
  1531. return FALSE;
  1532. }
  1533. // get the value of the property
  1534. if ( FALSE == PropertyGet( pWmiObject, pwszProperty, str, _T( "0" ) ) )
  1535. { // Error is already set in 'PropertyGet' function.
  1536. return FALSE;
  1537. }
  1538. // convert into the time value
  1539. wbemtime = _bstr_t( str );
  1540. }
  1541. catch( _com_error& e )
  1542. {
  1543. WMISaveError( e );
  1544. return FALSE;
  1545. }
  1546. catch( CHeap_Exception )
  1547. {
  1548. WMISaveError( WBEM_E_OUT_OF_MEMORY );
  1549. return FALSE;
  1550. }
  1551. // return
  1552. return TRUE;
  1553. }
  1554. BOOL
  1555. PropertyGet(
  1556. IWbemClassObject* pWmiObject,
  1557. LPCWSTR pwszProperty,
  1558. SYSTEMTIME& systime )
  1559. /*++
  1560. Routine Description:
  1561. Gets the value of the property from the WMI class object in systemtime format
  1562. Arguments:
  1563. [in] IWbemClassObject : pointer to the WBEM class object
  1564. [in] LPCWSTR : the name of the property to retrieve
  1565. [out] WBEMTime : variable to hold the retrieved property
  1566. Return Value:
  1567. TRUE on success
  1568. FALSE on failure
  1569. NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
  1570. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  1571. --*/
  1572. {
  1573. // local variables
  1574. CHString strTime;
  1575. // Validate input arguments.
  1576. if ( ( NULL == pWmiObject ) ||
  1577. ( NULL == pwszProperty ) )
  1578. {
  1579. WMISaveError( WBEM_E_INVALID_PARAMETER );
  1580. return FALSE;
  1581. }
  1582. try
  1583. {
  1584. // get the value of the property
  1585. // 16010101000000.000000+000 is the default time
  1586. if ( FALSE == PropertyGet( pWmiObject, pwszProperty, strTime, _T( "16010101000000.000000+000" ) ) )
  1587. { // Error is already set.
  1588. return FALSE;
  1589. }
  1590. // prepare the systemtime structure
  1591. // yyyymmddHHMMSS.mmmmmmsUUU
  1592. // NOTE: NO NEED CALL 'IsNumeric()' BEFORE 'AsLong'.
  1593. // Left and MID methods can throw an exception.
  1594. systime.wYear = (WORD) AsLong( strTime.Left( 4 ), 10 );
  1595. systime.wMonth = (WORD) AsLong( strTime.Mid( 4, 2 ), 10 );
  1596. systime.wDayOfWeek = 0;
  1597. systime.wDay = (WORD) AsLong( strTime.Mid( 6, 2 ), 10 );
  1598. systime.wHour = (WORD) AsLong( strTime.Mid( 8, 2 ), 10 );
  1599. systime.wMinute = (WORD) AsLong( strTime.Mid( 10, 2 ), 10 );
  1600. systime.wSecond = (WORD) AsLong( strTime.Mid( 12, 2 ), 10 );
  1601. systime.wMilliseconds = (WORD) AsLong( strTime.Mid( 15, 6 ), 10 );
  1602. }
  1603. catch( _com_error& e )
  1604. {
  1605. WMISaveError( e );
  1606. return FALSE;
  1607. }
  1608. catch( CHeap_Exception )
  1609. {
  1610. WMISaveError( WBEM_E_OUT_OF_MEMORY );
  1611. return FALSE;
  1612. }
  1613. // return
  1614. return TRUE;
  1615. }
  1616. HRESULT
  1617. PropertyPut(
  1618. IWbemClassObject* pWmiObject,
  1619. LPCWSTR pwszProperty,
  1620. _variant_t& varValue
  1621. )
  1622. /*++
  1623. Routine Description:
  1624. Sets the value of the property to the WMI class object
  1625. Arguments:
  1626. [in] IWbemClassObject : pointer to the WBEM class object
  1627. [in] LPCWSTR : the name of the property to retrieve
  1628. [in] WBEMTime : variable holding the property to set
  1629. Return Value:
  1630. TRUE on success
  1631. FALSE on failure
  1632. --*/
  1633. {
  1634. // local variables
  1635. VARIANT var;
  1636. HRESULT hr = S_OK;
  1637. // check the input value
  1638. if ( ( NULL == pWmiObject ) ||
  1639. ( NULL == pwszProperty ) )
  1640. {
  1641. return WBEM_E_INVALID_PARAMETER;
  1642. }
  1643. try
  1644. {
  1645. // put the value
  1646. var = varValue;
  1647. hr = pWmiObject->Put( _bstr_t( pwszProperty ), 0, &var, 0 );
  1648. }
  1649. catch( _com_error& e )
  1650. {
  1651. hr = e.Error();
  1652. }
  1653. // return the result
  1654. return hr;
  1655. }
  1656. HRESULT
  1657. PropertyPut(
  1658. IWbemClassObject* pWmiObject,
  1659. LPCWSTR pwszProperty,
  1660. LPCWSTR pwszValue
  1661. )
  1662. /*++
  1663. Routine Description:
  1664. Sets the string value of the property to the WMI class object
  1665. Arguments:
  1666. [in] IWbemClassObject : pointer to the WBEM class object
  1667. [in] LPCWSTR : the name of the property to retrieve
  1668. [in] LPCWSTR : variable holding the property to set
  1669. Return Value:
  1670. TRUE on success
  1671. FALSE on failure
  1672. --*/
  1673. {
  1674. // local variables
  1675. _variant_t varValue;
  1676. HRESULT hr = S_OK;
  1677. // check the input value
  1678. if ( ( NULL == pWmiObject ) ||
  1679. ( NULL == pwszProperty ) ||
  1680. ( NULL == pwszValue ) )
  1681. {
  1682. return WBEM_E_INVALID_PARAMETER;
  1683. }
  1684. try
  1685. {
  1686. varValue = pwszValue;
  1687. SAFE_EXECUTE( PropertyPut( pWmiObject, pwszProperty, varValue ) );
  1688. }
  1689. catch( _com_error& e )
  1690. {
  1691. hr = e.Error();
  1692. }
  1693. // return
  1694. return hr;
  1695. }
  1696. HRESULT
  1697. PropertyPut(
  1698. IWbemClassObject* pWmiObject,
  1699. LPCWSTR pwszProperty,
  1700. DWORD dwValue
  1701. )
  1702. /*++
  1703. Routine Description:
  1704. Sets the dword value of the property to the WMI class object.
  1705. Arguments:
  1706. [in] IWbemClassObject : pointer to the WBEM class object
  1707. [in] LPCWSTR : the name of the property to retrieve
  1708. [in] DWORD : variable holding the property to set
  1709. Return Value:
  1710. TRUE on success
  1711. FALSE on failure
  1712. --*/
  1713. {
  1714. // local variables
  1715. _variant_t varValue;
  1716. HRESULT hr = S_OK;
  1717. // check the input value
  1718. if ( ( NULL == pWmiObject ) ||
  1719. ( NULL == pwszProperty ) )
  1720. {
  1721. return WBEM_E_INVALID_PARAMETER;
  1722. }
  1723. try
  1724. {
  1725. varValue = ( LONG )dwValue;
  1726. SAFE_EXECUTE( PropertyPut( pWmiObject, pwszProperty, varValue ) );
  1727. }
  1728. catch( _com_error& e )
  1729. {
  1730. return e.Error();
  1731. }
  1732. // return
  1733. return S_OK;
  1734. }
  1735. HRESULT
  1736. RegQueryValueWMI(
  1737. IWbemServices* pWbemServices,
  1738. LPCWSTR pwszMethod,
  1739. DWORD dwHDefKey,
  1740. LPCWSTR pwszSubKeyName,
  1741. LPCWSTR pwszValueName,
  1742. _variant_t& varValue
  1743. )
  1744. /*++
  1745. Routine Description:
  1746. This function retrieves the value of the property from the specified registry key.
  1747. Arguments:
  1748. [in] IWbemServices : pointer to the IWbemServices object
  1749. [in] LPCWSTR : the name of the method to execute
  1750. [in] DWORD : the key in the registry whose value has to be retrieved
  1751. [in] LPCWSTR : the name of the subkey to retrieve
  1752. [in] LPCWSTR : the name of the value to retrieve
  1753. [in] _variant_t : variable holding the property value retrieved
  1754. Return Value:
  1755. TRUE on success
  1756. FALSE on failure
  1757. NOTE: Pass arguments of type mentioned in declaration of this function.
  1758. EX: Don't pass 'CHString' argument if 'LPWSTR' is expected.
  1759. Reason: 'CHString' can throw an exception of type 'CHEAP_EXCEPTION'
  1760. which is not handled by this function.
  1761. --*/
  1762. {
  1763. // local variables
  1764. HRESULT hr = S_OK;
  1765. BOOL bResult = FALSE;
  1766. DWORD dwReturnValue = 0;
  1767. IWbemClassObject* pClass = NULL;
  1768. IWbemClassObject* pMethod = NULL;
  1769. IWbemClassObject* pInParams = NULL;
  1770. IWbemClassObject* pInParamsInstance = NULL;
  1771. IWbemClassObject* pOutParamsInstance = NULL;
  1772. // Clear any errors.
  1773. SetLastError( WBEM_S_NO_ERROR );
  1774. // check the input value
  1775. if ( ( NULL == pWbemServices ) ||
  1776. ( NULL == pwszMethod ) ||
  1777. ( NULL == pwszSubKeyName ) ||
  1778. ( NULL == pwszValueName ) )
  1779. {
  1780. return WBEM_E_INVALID_PARAMETER;
  1781. }
  1782. // NOTE: If SAFE_EXECUTE( pWbemServices->GetObject(
  1783. // _bstr_t( WMI_REGISTRY ), WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &pClass, NULL ) );
  1784. // is executed then,
  1785. // NO NEED TO CHECK FOR ( PCLASS == NULL ) SINCE IN ALL CASES
  1786. // OF ERROR THIS VARIABLE WILL BE NULL.
  1787. try
  1788. {
  1789. // get the registry class object
  1790. SAFE_EXECUTE( pWbemServices->GetObject(
  1791. _bstr_t( WMI_REGISTRY ), WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &pClass, NULL ) );
  1792. // get the method reference required
  1793. SAFE_EXECUTE( pClass->GetMethod( pwszMethod, 0, &pInParams, NULL ) );
  1794. // create the instance for the in parameters
  1795. SAFE_EXECUTE( pInParams->SpawnInstance( 0, &pInParamsInstance ) );
  1796. // set the input values
  1797. SAFE_EXECUTE(PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_HDEFKEY ), dwHDefKey ) );
  1798. SAFE_EXECUTE(PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_SUBKEY ), pwszSubKeyName ) );
  1799. SAFE_EXECUTE(PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_VALUENAME ), pwszValueName ) );
  1800. // now execute the method
  1801. SAFE_EXECUTE( pWbemServices->ExecMethod( _bstr_t( WMI_REGISTRY ),
  1802. _bstr_t( pwszMethod ), 0, NULL, pInParamsInstance, &pOutParamsInstance, NULL ) );
  1803. if ( NULL == pOutParamsInstance ) // check the object .. safety sake
  1804. {
  1805. _com_issue_error( STG_E_UNKNOWN );
  1806. }
  1807. // now check the return value of the method from the output params object
  1808. bResult = PropertyGet( pOutParamsInstance,
  1809. _bstr_t( WMI_REGISTRY_OUT_RETURNVALUE ), dwReturnValue );
  1810. if ( ( FALSE == bResult ) ||
  1811. ( 0 != dwReturnValue ) )
  1812. {
  1813. _com_issue_error( STG_E_UNKNOWN );
  1814. }
  1815. // Comapre string and take appropriate action.
  1816. if ( 0 == StringCompare( pwszMethod, WMI_REGISTRY_M_DWORDVALUE, TRUE, 0 ) )
  1817. {
  1818. SAFE_EXECUTE( PropertyGet( pOutParamsInstance,
  1819. _bstr_t( WMI_REGISTRY_OUT_VALUE_DWORD ), varValue ) );
  1820. }
  1821. else
  1822. {
  1823. SAFE_EXECUTE( PropertyGet( pOutParamsInstance,
  1824. _bstr_t( WMI_REGISTRY_OUT_VALUE ), varValue ) );
  1825. }
  1826. }
  1827. catch( _com_error& e )
  1828. {
  1829. hr = e.Error();
  1830. }
  1831. // release the interfaces
  1832. SAFE_RELEASE( pClass );
  1833. SAFE_RELEASE( pMethod );
  1834. SAFE_RELEASE( pInParams );
  1835. SAFE_RELEASE( pInParamsInstance );
  1836. SAFE_RELEASE( pOutParamsInstance );
  1837. // return success
  1838. return hr;
  1839. }
  1840. BOOL
  1841. RegQueryValueWMI(
  1842. IWbemServices* pWbemServices,
  1843. DWORD dwHDefKey,
  1844. LPCWSTR pwszSubKeyName,
  1845. LPCWSTR pwszValueName,
  1846. CHString& strValue,
  1847. LPCWSTR pwszDefault
  1848. )
  1849. /*++
  1850. Routine Description:
  1851. This function retrieves the string value of the property from the specified registry key.
  1852. Arguments:
  1853. [in] IWbemServices : pointer to the IWbemServices object
  1854. [in] DWORD : the key in the registry whose value has to be retrieved
  1855. [in] LPCWSTR : the name of the subkey to retrieve
  1856. [in] LPCWSTR : the name of the value to retrieve
  1857. [out] CHString : variable holding the property value retrieved
  1858. [in] LPCWSTR : the default value for this property
  1859. Return Value:
  1860. TRUE on success
  1861. FALSE on failure
  1862. NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF '0' IS RETURNED THEN ERROR
  1863. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  1864. This function won't return values if they are obtained as reference
  1865. from WMI.
  1866. EX: 'VARTYPE' recieved is of type 'VT_BSTR | VT_BYREF' then FALSE is
  1867. returned.
  1868. --*/
  1869. {
  1870. // local variables
  1871. HRESULT hr = S_OK;
  1872. _variant_t varValue;
  1873. // Clear any errors.
  1874. SetLastError( WBEM_S_NO_ERROR );
  1875. // Check the input
  1876. if ( ( NULL == pWbemServices ) ||
  1877. ( NULL == pwszSubKeyName ) ||
  1878. ( NULL == pwszValueName ) )
  1879. {
  1880. WMISaveError( WBEM_E_INVALID_PARAMETER );
  1881. return FALSE;
  1882. }
  1883. try
  1884. {
  1885. // Set the default value
  1886. if ( NULL != pwszDefault )
  1887. {
  1888. strValue = pwszDefault;
  1889. }
  1890. // Get the value
  1891. hr = RegQueryValueWMI( pWbemServices,
  1892. WMI_REGISTRY_M_STRINGVALUE, dwHDefKey, pwszSubKeyName, pwszValueName, varValue );
  1893. if ( FAILED( hr ) )
  1894. {
  1895. WMISaveError( hr );
  1896. return FALSE;
  1897. }
  1898. // Get the value from the variant
  1899. // Get the value
  1900. if ( VT_BSTR == V_VT( &varValue ) )
  1901. {
  1902. strValue = (LPCWSTR)_bstr_t( varValue );
  1903. }
  1904. else
  1905. {
  1906. // Requested type is not found.
  1907. WMISaveError( WBEM_E_INVALID_PARAMETER );
  1908. return FALSE;
  1909. }
  1910. }
  1911. catch( _com_error& e )
  1912. { // Exception throw by '_variant_t'.
  1913. WMISaveError( e );
  1914. return FALSE;
  1915. }
  1916. // return success
  1917. return TRUE;
  1918. }
  1919. BOOL
  1920. RegQueryValueWMI(
  1921. IWbemServices* pWbemServices,
  1922. DWORD dwHDefKey,
  1923. LPCWSTR pwszSubKeyName,
  1924. LPCWSTR pwszValueName,
  1925. DWORD& dwValue,
  1926. DWORD dwDefault
  1927. )
  1928. /*++
  1929. Routine Description:
  1930. This function retrieves the dword value of the property from the specified registry key.
  1931. Arguments:
  1932. [in] IWbemServices : pointer to the IWbemServices object
  1933. [in] DWORD : the key in the registry whose value has to be retrieved
  1934. [in] LPCWSTR : the name of the subkey to retrieve
  1935. [in] LPCWSTR : the name of the value to retrieve
  1936. [out] DWORD : variable holding the property value retrieved
  1937. [in] DWORD : the default value for this property
  1938. Return Value:
  1939. TRUE on success
  1940. FALSE on failure
  1941. NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF '0' IS RETURNED THEN ERROR
  1942. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  1943. This function won't return values if they are obtained as reference
  1944. from WMI.
  1945. EX: 'VARTYPE' recieved is of type 'VT_I4 | VT_BYREF' then FALSE is
  1946. returned.
  1947. --*/
  1948. {
  1949. // local variables
  1950. HRESULT hr = S_OK;
  1951. _variant_t varValue;
  1952. // Clear any errors.
  1953. SetLastError( WBEM_S_NO_ERROR );
  1954. // Check the input.
  1955. if ( ( NULL == pWbemServices ) ||
  1956. ( NULL == pwszSubKeyName ) ||
  1957. ( NULL == pwszValueName ) ||
  1958. ( NULL == dwValue ) )
  1959. {
  1960. WMISaveError( WBEM_E_INVALID_PARAMETER );
  1961. return FALSE;
  1962. }
  1963. try
  1964. {
  1965. // Set the default value.
  1966. dwValue = dwDefault;
  1967. // Get the value.
  1968. hr = RegQueryValueWMI( pWbemServices, WMI_REGISTRY_M_DWORDVALUE, dwHDefKey,
  1969. pwszSubKeyName, pwszValueName, varValue );
  1970. if ( FAILED( hr ) )
  1971. {
  1972. WMISaveError( hr );
  1973. return FALSE;
  1974. }
  1975. // get the value from the variant
  1976. switch( V_VT( &varValue ) )
  1977. {
  1978. case VT_I2:
  1979. dwValue = V_I2( &varValue );
  1980. break;
  1981. case VT_I4:
  1982. dwValue = V_I4( &varValue );
  1983. break;
  1984. case VT_UI2:
  1985. dwValue = V_UI2( &varValue );
  1986. break;
  1987. case VT_UI4:
  1988. dwValue = V_UI4( &varValue );
  1989. break;
  1990. case VT_INT:
  1991. dwValue = V_INT( &varValue );
  1992. break;
  1993. case VT_UINT:
  1994. dwValue = V_UINT( &varValue );
  1995. break;
  1996. default:
  1997. // Requested type is not found.
  1998. WMISaveError( WBEM_E_INVALID_PARAMETER );
  1999. return FALSE;
  2000. }
  2001. }
  2002. catch( _com_error& e )
  2003. { // Exception thrown by _variant_t
  2004. WMISaveError( e );
  2005. return FALSE;
  2006. }
  2007. // return success
  2008. return TRUE;
  2009. }
  2010. DWORD
  2011. GetTargetVersionEx(
  2012. IWbemServices* pWbemServices,
  2013. COAUTHIDENTITY* pAuthIdentity
  2014. )
  2015. /*++
  2016. Routine Description:
  2017. This function gets the version of the system from which we are trying to retrieve
  2018. information from.
  2019. Arguments:
  2020. [in] IWbemServices : pointer to the IWbemServices object
  2021. [in] COAUTHIDENTITY : pointer to the pointer to AUTHIDENTITY structure
  2022. Return Value:
  2023. DWORD - Target version of the machine if found else 0.
  2024. NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF '0' IS RETURNED THEN ERROR
  2025. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  2026. --*/
  2027. {
  2028. // local variables
  2029. HRESULT hr = S_OK;
  2030. LONG lPos = 0;
  2031. DWORD dwMajor = 0;
  2032. DWORD dwMinor = 0;
  2033. DWORD dwVersion = 0;
  2034. ULONG ulReturned = 0;
  2035. CHString strVersion;
  2036. IWbemClassObject* pWbemObject = NULL;
  2037. IEnumWbemClassObject* pWbemInstances = NULL;
  2038. // Clear any errors.
  2039. SetLastError( WBEM_S_NO_ERROR );
  2040. // Check the input value
  2041. if ( NULL == pWbemServices )
  2042. {
  2043. WMISaveError( WBEM_E_INVALID_PARAMETER );
  2044. return 0;
  2045. }
  2046. try
  2047. {
  2048. // get the OS information
  2049. SAFE_EXECUTE( pWbemServices->CreateInstanceEnum(
  2050. _bstr_t( CLASS_CIMV2_Win32_OperatingSystem ),
  2051. WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, &pWbemInstances ) );
  2052. // set the security on the enumerated object
  2053. SAFE_EXECUTE( SetInterfaceSecurity( pWbemInstances, pAuthIdentity ) );
  2054. // get the enumerated objects information
  2055. // NOTE: This needs to be traversed only one time.
  2056. SAFE_EXECUTE( pWbemInstances->Next( WBEM_INFINITE, 1, &pWbemObject, &ulReturned ) );
  2057. // to be on safer side ... check the count of objects returned
  2058. if ( 0 == ulReturned )
  2059. {
  2060. // release the interfaces
  2061. WMISaveError( WBEM_S_FALSE );
  2062. SAFE_RELEASE( pWbemObject );
  2063. SAFE_RELEASE( pWbemInstances );
  2064. return 0;
  2065. }
  2066. // now get the os version value
  2067. if ( FALSE == PropertyGet( pWbemObject, L"Version", strVersion ) )
  2068. {
  2069. // release the interfaces
  2070. // Error is already set in the called function.
  2071. SAFE_RELEASE( pWbemObject );
  2072. SAFE_RELEASE( pWbemInstances );
  2073. return 0;
  2074. }
  2075. // release the interfaces .. we dont need them furthur
  2076. SAFE_RELEASE( pWbemObject );
  2077. SAFE_RELEASE( pWbemInstances );
  2078. //
  2079. // now determine the os version
  2080. dwMajor = dwMinor = 0;
  2081. // Get the major version
  2082. lPos = strVersion.Find( L'.' );
  2083. if ( -1 == lPos )
  2084. {
  2085. // The version string itself is version ... THIS WILL NEVER HAPPEN
  2086. if( FALSE == IsNumeric( strVersion, 10, FALSE ) )
  2087. {
  2088. return 0;
  2089. }
  2090. dwMajor = AsLong( strVersion, 10 );
  2091. }
  2092. else
  2093. {
  2094. // major version
  2095. if( FALSE == IsNumeric( strVersion.Mid( 0, lPos ), 10, FALSE ) )
  2096. {
  2097. return 0;
  2098. }
  2099. dwMajor = AsLong( strVersion.Mid( 0, lPos ), 10 );
  2100. // get the minor version
  2101. strVersion = strVersion.Mid( lPos + 1 );
  2102. lPos = strVersion.Find( L'.' );
  2103. if ( -1 == lPos)
  2104. {
  2105. if( FALSE == IsNumeric( strVersion, 10, FALSE ) )
  2106. {
  2107. return 0;
  2108. }
  2109. dwMinor = AsLong( strVersion, 10 );
  2110. }
  2111. else
  2112. {
  2113. if( FALSE == IsNumeric( strVersion.Mid( 0, lPos ), 10, FALSE ) )
  2114. {
  2115. return 0;
  2116. }
  2117. dwMinor = AsLong( strVersion.Mid( 0, lPos ), 10 );
  2118. }
  2119. }
  2120. // mix the version info
  2121. dwVersion = dwMajor * 1000 + dwMinor;
  2122. }
  2123. catch( _com_error& e )
  2124. {
  2125. WMISaveError( e );
  2126. SAFE_RELEASE( pWbemObject );
  2127. SAFE_RELEASE( pWbemInstances );
  2128. return 0;
  2129. }
  2130. catch( CHeap_Exception )
  2131. {
  2132. WMISaveError( WBEM_E_OUT_OF_MEMORY );
  2133. SAFE_RELEASE( pWbemObject );
  2134. SAFE_RELEASE( pWbemInstances );
  2135. return 0;
  2136. }
  2137. // If successful then 'pWbemObject' and 'pWbemInstances' are already released.
  2138. // return
  2139. return dwVersion;
  2140. }
  2141. BOOL
  2142. GetPropertyFromSafeArray(
  2143. SAFEARRAY *pSafeArray,
  2144. LONG lIndex,
  2145. CHString& strValue,
  2146. VARTYPE vartype
  2147. )
  2148. /*++
  2149. Routine Description:
  2150. This function retrieves a property from the safe array.
  2151. Arguments:
  2152. [in] SAFEARRAY : pointer to the array of elements
  2153. [in] LONG : index to retrieve the data from
  2154. [out] CHString : variable to hold the return value
  2155. [in] VARTYPE : The type of variable to retrieve from the array
  2156. Return Value:
  2157. TRUE on success
  2158. FALSE on failure
  2159. NOTE: THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
  2160. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  2161. --*/
  2162. {
  2163. // Local variables.
  2164. VARIANT var;
  2165. HRESULT hRes = S_OK;
  2166. // Clear any errors.
  2167. SetLastError( WBEM_S_NO_ERROR );
  2168. // Check the inputs.
  2169. if ( NULL == pSafeArray )
  2170. {
  2171. WMISaveError( WBEM_E_INVALID_PARAMETER );
  2172. return FALSE;
  2173. }
  2174. // Initialize variant.
  2175. VariantInit( &var );
  2176. try
  2177. {
  2178. // get the value
  2179. V_VT( &var ) = vartype;
  2180. hRes = SafeArrayGetElement( pSafeArray, &lIndex, &V_UI1( &var ) );
  2181. if( FAILED( hRes ) )
  2182. { // Set error occured.
  2183. WMISaveError( hRes );
  2184. VariantClear( &var );
  2185. return FALSE;
  2186. }
  2187. // Store requested information in
  2188. switch( vartype )
  2189. {
  2190. case VT_BSTR:
  2191. strValue = (LPCWSTR)_bstr_t( var );
  2192. break;
  2193. default:
  2194. WMISaveError( WBEM_E_INVALID_PARAMETER );
  2195. VariantClear( &var );
  2196. return FALSE;
  2197. }
  2198. }
  2199. catch( CHeap_Exception )
  2200. { // Exception thrown from 'strValue'.
  2201. WMISaveError( WBEM_E_OUT_OF_MEMORY );
  2202. VariantClear( &var );
  2203. return FALSE; // failure
  2204. }
  2205. // Clean-Up and return.
  2206. VariantClear( &var );
  2207. return TRUE;
  2208. }
  2209. BOOL
  2210. GetPropertyFromSafeArray(
  2211. SAFEARRAY *pSafeArray,
  2212. LONG lIndex,
  2213. IWbemClassObject **pScriptObject,
  2214. VARTYPE vartype
  2215. )
  2216. /*++
  2217. Routine Description:
  2218. This function retrieves a property from the safe array.
  2219. Arguments:
  2220. [in] SAFEARRAY : pointer to the array of elements
  2221. [in] LONG : index to retrieve the data from
  2222. [out] IWbemClassObject : variable to hold the return value
  2223. [in] VARTYPE : The type of variable to retrieve from the array
  2224. Return Value:
  2225. TRUE on success
  2226. FALSE on failure
  2227. NOTE: CALLED FUNCTION HAS TO MAKE SURE THAT '*pScriptObject' DOES NOT CONTAIN ANY
  2228. VALUE WHICH MAY CAUSE MEMORY LEAK.
  2229. THIS FUNCTION SAVES LAST ERROR OCCURED. IF FALSE IS RETURNED THEN ERROR
  2230. OCCURED STRING CAN BE RETRIEVED BY CALLING 'GetReason()'.
  2231. NOTE: If TRUE is returned then 'VariantClear' is not called over 'var' since if
  2232. a call is made to 'Variantcler' we will loose Interface pointer. Not calling
  2233. 'VariantClear' will free 'var' when its out of scope and leaving
  2234. the interface pointer in memory which can be used by the called function.
  2235. IT IS CALLING FUNCTION RESPONSIBILITY TO RELEASE THE INTERFACE POINTER.
  2236. --*/
  2237. {
  2238. // Local variables.
  2239. VARIANT var;
  2240. HRESULT hRes = S_OK;
  2241. // Clear any errors.
  2242. SetLastError( WBEM_S_NO_ERROR );
  2243. // Validate the inputs
  2244. if ( ( NULL == pSafeArray ) ||
  2245. ( NULL == pScriptObject ) )
  2246. {
  2247. WMISaveError( WBEM_E_INVALID_PARAMETER );
  2248. return FALSE;
  2249. }
  2250. // Initialize variant.
  2251. VariantInit( &var );
  2252. // Set type of value expected.
  2253. V_VT( &var ) = vartype;
  2254. hRes = SafeArrayGetElement( pSafeArray, &lIndex, &V_UI1( &var ) );
  2255. // check for return value.
  2256. if( FAILED( hRes ) )
  2257. { // Set error occured.
  2258. WMISaveError( hRes );
  2259. VariantClear( &var );
  2260. return FALSE;
  2261. }
  2262. // Store information requested.
  2263. switch( vartype )
  2264. {
  2265. case VT_UNKNOWN:
  2266. *pScriptObject = (IWbemClassObject *) var.punkVal;
  2267. break;
  2268. default:
  2269. WMISaveError( WBEM_E_INVALID_PARAMETER );
  2270. VariantClear( &var );
  2271. return FALSE;
  2272. }
  2273. // return
  2274. return TRUE;
  2275. }