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.

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