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.

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