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

2153 lines
64 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. // error constants
  21. #define E_SERVER_NOTFOUND 0x800706ba
  22. //
  23. // private function prototype(s)
  24. //
  25. BOOL IsValidUserEx( LPCWSTR pwszUser );
  26. HRESULT GetSecurityArguments( IUnknown* pInterface,
  27. DWORD& dwAuthorization, DWORD& dwAuthentication );
  28. HRESULT SetInterfaceSecurity( IUnknown* pInterface,
  29. LPCWSTR pwszServer, LPCWSTR pwszUser,
  30. LPCWSTR pwszPassword, COAUTHIDENTITY** ppAuthIdentity );
  31. HRESULT WINAPI SetProxyBlanket( IUnknown* pInterface,
  32. DWORD dwAuthnSvc, DWORD dwAuthzSvc,
  33. LPWSTR pwszPrincipal, DWORD dwAuthLevel, DWORD dwImpLevel,
  34. RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities );
  35. HRESULT WINAPI WbemAllocAuthIdentity( LPCWSTR pwszUser, LPCWSTR pwszPassword,
  36. LPCWSTR pwszDomain, COAUTHIDENTITY** ppAuthIdent );
  37. HRESULT RegQueryValueWMI( IWbemServices* pWbemServices,
  38. LPCWSTR pwszMethod, DWORD dwHDefKey,
  39. LPCWSTR pwszSubKeyName, LPCWSTR pwszValueName, _variant_t& varValue );
  40. /*********************************************************************************************
  41. Routine Description:
  42. Checks wether the User name is a valid one or not
  43. Arguments:
  44. [in] LPCWSTR : String containing the user name
  45. Return Value:
  46. TRUE on success
  47. FALSE on failure
  48. *********************************************************************************************/
  49. BOOL IsValidUserEx( LPCWSTR pwszUser )
  50. {
  51. // local variables
  52. CHString strUser;
  53. LONG lPos = 0;
  54. if ( pwszUser == NULL )
  55. {
  56. return TRUE;
  57. }
  58. try
  59. {
  60. // get user into local memory
  61. strUser = pwszUser;
  62. // user name should not be just '\'
  63. if ( strUser.CompareNoCase( L"\\" ) == 0 )
  64. {
  65. return FALSE;
  66. }
  67. // user name should not contain invalid characters
  68. if ( strUser.FindOneOf( L"/[]:|<>+=;,?*" ) != -1 )
  69. {
  70. return FALSE;
  71. }
  72. // SPECIAL CHECK
  73. // check for multiple '\' characters in the user name
  74. lPos = strUser.Find( L'\\' );
  75. if ( lPos != -1 )
  76. {
  77. // '\' character exists in the user name
  78. // strip off the user info upto first '\' character
  79. // check for one more '\' in the remaining string
  80. // if it exists, invalid user
  81. strUser = strUser.Mid( lPos + 1 );
  82. lPos = strUser.Find( L'\\' );
  83. if ( lPos != -1 )
  84. {
  85. return FALSE;
  86. }
  87. }
  88. }
  89. catch( ... )
  90. {
  91. SetLastError( E_OUTOFMEMORY );
  92. return FALSE;
  93. }
  94. // user name is valid
  95. return TRUE;
  96. }
  97. /*********************************************************************************************
  98. Routine Description:
  99. Checks wether the Server name is a valid one or not
  100. Arguments:
  101. [in] LPCWSTR : String containing the user name
  102. [out] BOOL : Is set to TRUE if the local system is being queried.
  103. Return Value:
  104. TRUE on success
  105. FALSE on failure
  106. *********************************************************************************************/
  107. BOOL IsValidServerEx( LPCWSTR pwszServer, BOOL& bLocalSystem )
  108. {
  109. // local variables
  110. CHString strTemp;
  111. if ( pwszServer == NULL )
  112. {
  113. return FALSE;
  114. }
  115. // kick-off
  116. bLocalSystem = FALSE;
  117. // get a local copy
  118. strTemp = pwszServer;
  119. // remove the forward slashes (UNC) if exist in the begining of the server name
  120. if ( IsUNCFormat( strTemp ) == TRUE )
  121. {
  122. strTemp = strTemp.Mid( 2 );
  123. if ( strTemp.GetLength() == 0 )
  124. {
  125. return FALSE;
  126. }
  127. }
  128. // now check if any '\' character appears in the server name. If so error
  129. if ( strTemp.Find( L'\\' ) != -1 )
  130. {
  131. return FALSE;
  132. }
  133. // now check if server name is '.' only which represent local system in WMI
  134. // else determine whether this is a local system or not
  135. if ( strTemp.CompareNoCase( L"." ) == 0 )
  136. {
  137. bLocalSystem = TRUE;
  138. }
  139. else
  140. {
  141. bLocalSystem = IsLocalSystem( strTemp );
  142. }
  143. // inform that server name is valid
  144. return TRUE;
  145. }
  146. /*********************************************************************************************
  147. Routine Description:
  148. Initializes the COM library
  149. Arguments:
  150. [in] IWbemLocator : pointer to the IWbemLocator
  151. Return Value:
  152. TRUE on success
  153. FALSE on failure
  154. *********************************************************************************************/
  155. BOOL InitializeCom( IWbemLocator** ppLocator )
  156. {
  157. // local variables
  158. HRESULT hr;
  159. BOOL bResult = FALSE;
  160. try
  161. {
  162. // assume that connection to WMI namespace is failed
  163. bResult = FALSE;
  164. // initialize the COM library
  165. SAFE_EXECUTE( CoInitializeEx( NULL, COINIT_APARTMENTTHREADED ) );
  166. // initialize the security
  167. SAFE_EXECUTE( CoInitializeSecurity( NULL, -1, NULL, NULL,
  168. RPC_C_AUTHN_LEVEL_NONE, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, 0 ) );
  169. // create the locator and get the pointer to the interface of IWbemLocator
  170. SAFE_RELEASE( *ppLocator ); // safe side
  171. SAFE_EXECUTE( CoCreateInstance( CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
  172. IID_IWbemLocator, ( LPVOID* ) ppLocator ) );
  173. // initialization successful
  174. bResult = TRUE;
  175. }
  176. catch( _com_error& e )
  177. {
  178. // save the WMI error
  179. WMISaveError( e );
  180. }
  181. // return the result;
  182. return bResult;
  183. }
  184. /*********************************************************************************************
  185. Routine Description:
  186. This function makes a connection to WMI.
  187. Arguments:
  188. [in] IWbemLocator : pointer to the IWbemLocator
  189. [in] IWbemServices : pointer to the IWbemServices
  190. [in] LPCWSTR : string containing the server name
  191. [in] LPCWSTR : string containing the User name
  192. [in] LPCWSTR : string containing the password
  193. [in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
  194. [in] BOOL : set to TRUE if we should try to connect with
  195. current credentials
  196. [in] LPCWSTR : string containing the namespace to connect to
  197. [out] HRESULT : the hResult value returned
  198. [out] BOOL : set to TRUE if we are querying for the local system
  199. Return Value:
  200. TRUE on success
  201. FALSE on failure
  202. *********************************************************************************************/
  203. BOOL ConnectWmi( IWbemLocator* pLocator,
  204. IWbemServices** ppServices,
  205. LPCWSTR pwszServer, LPCWSTR pwszUser, LPCWSTR pwszPassword,
  206. COAUTHIDENTITY** ppAuthIdentity, BOOL bCheckWithNullPwd,
  207. LPCWSTR pwszNamespace, HRESULT* phr, BOOL* pbLocalSystem )
  208. {
  209. // local variables
  210. HRESULT hr;
  211. BOOL bResult = FALSE;
  212. BOOL bLocalSystem = FALSE;
  213. _bstr_t bstrServer;
  214. _bstr_t bstrNamespace;
  215. _bstr_t bstrUser, bstrPassword;
  216. // kick-off
  217. if ( pbLocalSystem != NULL )
  218. {
  219. *pbLocalSystem = FALSE;
  220. }
  221. // ...
  222. if ( phr != NULL )
  223. {
  224. *phr = NO_ERROR;
  225. }
  226. try
  227. {
  228. // clear the error
  229. SetLastError( WBEM_S_NO_ERROR );
  230. // assume that connection to WMI namespace is failed
  231. bResult = FALSE;
  232. // check whether locator object exists or not
  233. // if not exists, return
  234. if ( pLocator == NULL )
  235. {
  236. if ( phr != NULL )
  237. {
  238. *phr = WBEM_E_INVALID_PARAMETER;
  239. }
  240. // return failure
  241. return FALSE;
  242. }
  243. // validate the server name
  244. // NOTE: The error being raised in custom define for '0x800706ba' value
  245. // The message that will be displayed in "The RPC server is unavailable."
  246. if ( IsValidServerEx( pwszServer, bLocalSystem ) == FALSE )
  247. {
  248. _com_issue_error( E_SERVER_NOTFOUND );
  249. }
  250. // validate the user name
  251. if ( IsValidUserEx( pwszUser ) == FALSE )
  252. {
  253. _com_issue_error( ERROR_NO_SUCH_USER );
  254. }
  255. // prepare namespace
  256. bstrNamespace = pwszNamespace; // name space
  257. if ( pwszServer != NULL && bLocalSystem == FALSE )
  258. {
  259. // get the server name
  260. bstrServer = pwszServer;
  261. // prepare the namespace
  262. // NOTE: check for the UNC naming format of the server and do
  263. if ( IsUNCFormat( pwszServer ) == TRUE )
  264. {
  265. bstrNamespace = bstrServer + L"\\" + pwszNamespace;
  266. }
  267. else
  268. {
  269. bstrNamespace = L"\\\\" + bstrServer + L"\\" + pwszNamespace;
  270. }
  271. // user credentials
  272. if ( pwszUser != NULL && lstrlen( pwszUser ) != 0 )
  273. {
  274. // copy the user name
  275. bstrUser = pwszUser;
  276. // if password is empty string and if we need to check with
  277. // null password, then do not set the password and try
  278. bstrPassword = pwszPassword;
  279. if ( bCheckWithNullPwd == TRUE && bstrPassword.length() == 0 )
  280. {
  281. bstrPassword = (LPWSTR) NULL;
  282. }
  283. }
  284. }
  285. // release the existing services object ( to be in safer side )
  286. SAFE_RELEASE( *ppServices );
  287. // connect to the remote system's WMI
  288. // there is a twist here ...
  289. // do not trap the ConnectServer function failure into exception
  290. // instead handle that action manually
  291. // by default try the ConnectServer function as the information which we have
  292. // in our hands at this point. If the ConnectServer is failed,
  293. // check whether password variable has any contents are not ... if no contents
  294. // check with "" (empty) password ... this might pass in this situation ..
  295. // if this call is also failed ... nothing is there that we can do ... throw the exception
  296. hr = pLocator->ConnectServer( bstrNamespace,
  297. bstrUser, bstrPassword, 0L, 0L, NULL, NULL, ppServices );
  298. if ( FAILED( hr ) )
  299. {
  300. //
  301. // special case ...
  302. // check whether password exists or not
  303. // NOTE: do not check for 'WBEM_E_ACCESS_DENIED'
  304. // this error code says that user with the current credentials is not
  305. // having access permisions to the 'namespace'
  306. if ( hr == E_ACCESSDENIED )
  307. {
  308. // check if we tried to connect to the system using null password
  309. // if so, then try connecting to the remote system with empty string
  310. if ( bCheckWithNullPwd == TRUE &&
  311. bstrUser.length() != 0 && bstrPassword.length() == 0 )
  312. {
  313. // now invoke with ...
  314. hr = pLocator->ConnectServer( bstrNamespace,
  315. bstrUser, _bstr_t( L"" ), 0L, 0L, NULL, NULL, ppServices );
  316. }
  317. }
  318. else if ( hr == WBEM_E_LOCAL_CREDENTIALS )
  319. {
  320. // credentials were passed to the local system.
  321. // So ignore the credentials and try to reconnect
  322. bLocalSystem = TRUE;
  323. bstrUser = (LPWSTR) NULL;
  324. bstrPassword = (LPWSTR) NULL;
  325. bstrNamespace = pwszNamespace; // name space
  326. hr = pLocator->ConnectServer( bstrNamespace,
  327. NULL, NULL, 0L, 0L, NULL, NULL, ppServices );
  328. }
  329. // now check the result again .. if failed .. ummmm..
  330. if ( FAILED( hr ) )
  331. {
  332. _com_issue_error( hr );
  333. }
  334. else
  335. {
  336. bstrPassword = L"";
  337. }
  338. }
  339. // set the security at the interface level also
  340. SAFE_EXECUTE( SetInterfaceSecurity( *ppServices,
  341. pwszServer, bstrUser, bstrPassword, ppAuthIdentity ) );
  342. // connection to WMI is successful
  343. bResult = TRUE;
  344. // save the hr value if needed by the caller
  345. if ( phr != NULL )
  346. {
  347. *phr = WBEM_S_NO_ERROR;
  348. }
  349. }
  350. catch( _com_error& e )
  351. {
  352. // save the error
  353. WMISaveError( e );
  354. // save the hr value if needed by the caller
  355. if ( phr != NULL )
  356. {
  357. *phr = e.Error();
  358. }
  359. }
  360. // ...
  361. if ( pbLocalSystem != NULL )
  362. {
  363. *pbLocalSystem = bLocalSystem;
  364. }
  365. // return the result
  366. return bResult;
  367. }
  368. /*********************************************************************************************
  369. Routine Description:
  370. This function is a wrapper function for the ConnectWmi function.
  371. Arguments:
  372. [in] IWbemLocator : pointer to the IWbemLocator
  373. [in] IWbemServices : pointer to the IWbemServices
  374. [in] LPCWSTR : string containing the server name
  375. [in] LPCWSTR : string containing the User name
  376. [in] LPCWSTR : string containing the password
  377. [in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
  378. [in] BOOL : set to TRUE if we should try to connect with
  379. current credentials
  380. [in] LPCWSTR : string containing the namespace to connect to
  381. [out] HRESULT : the hResult value returned
  382. [out] BOOL : set to TRUE if we are querying for the local system
  383. Return Value:
  384. TRUE on success
  385. FALSE on failure
  386. *********************************************************************************************/
  387. BOOL ConnectWmiEx( IWbemLocator* pLocator,
  388. IWbemServices** ppServices,
  389. LPCWSTR pwszServer, CHString& strUserName, CHString& strPassword,
  390. COAUTHIDENTITY** ppAuthIdentity,
  391. BOOL bNeedPassword, LPCWSTR pwszNamespace, BOOL* pbLocalSystem )
  392. {
  393. // local variables
  394. HRESULT hr;
  395. DWORD dwSize = 0;
  396. BOOL bResult = FALSE;
  397. LPWSTR pwszPassword = NULL;
  398. CHString strBuffer = NULL_STRING;
  399. // clear the error .. if any
  400. SetLastError( WBEM_S_NO_ERROR );
  401. // sometime users want the utility to prompt for the password
  402. // check what user wants the utility to do
  403. if ( bNeedPassword == TRUE && strPassword.Compare( L"*" ) == 0 )
  404. {
  405. // user wants the utility to prompt for the password
  406. // so skip this part and let the flow directly jump the password acceptance part
  407. }
  408. else
  409. {
  410. // try to establish connection to the remote system with the credentials supplied
  411. if ( strUserName.GetLength() == 0 )
  412. {
  413. // user name is empty
  414. // so, it is obvious that password will also be empty
  415. // even if password is specified, we have to ignore that
  416. bResult = ConnectWmi( pLocator, ppServices,
  417. pwszServer, NULL, NULL, ppAuthIdentity, FALSE, pwszNamespace, &hr, pbLocalSystem );
  418. }
  419. else
  420. {
  421. // credentials were supplied
  422. // but password might not be specified ... so check and act accordingly
  423. LPCWSTR pwszTemp = NULL;
  424. BOOL bCheckWithNull = TRUE;
  425. if ( bNeedPassword == FALSE )
  426. {
  427. pwszTemp = strPassword;
  428. bCheckWithNull = FALSE;
  429. }
  430. // ...
  431. bResult = ConnectWmi( pLocator, ppServices, pwszServer,
  432. strUserName, pwszTemp, ppAuthIdentity, bCheckWithNull, pwszNamespace, &hr, pbLocalSystem );
  433. }
  434. // check the result ... if successful in establishing connection ... return
  435. if ( bResult == TRUE )
  436. {
  437. return TRUE;
  438. }
  439. // now check the kind of error occurred
  440. switch( hr )
  441. {
  442. case E_ACCESSDENIED:
  443. break;
  444. case WBEM_E_LOCAL_CREDENTIALS:
  445. // needs to do special processing
  446. break;
  447. case WBEM_E_ACCESS_DENIED:
  448. default:
  449. // NOTE: do not check for 'WBEM_E_ACCESS_DENIED'
  450. // this error code says that user with the current credentials is not
  451. // having access permisions to the 'namespace'
  452. WMISaveError( hr );
  453. return FALSE; // no use of accepting the password .. return failure
  454. break;
  455. }
  456. // if failed in establishing connection to the remote terminal
  457. // even if the password is specifed, then there is nothing to do ... simply return failure
  458. if ( bNeedPassword == FALSE )
  459. {
  460. return FALSE;
  461. }
  462. }
  463. // check whether user name is specified or not
  464. // if not, get the local system's current user name under whose credentials, the process
  465. // is running
  466. if ( strUserName.GetLength() == 0 )
  467. {
  468. // sub-local variables
  469. LPWSTR pwszUserName = NULL;
  470. try
  471. {
  472. // get the required buffer
  473. pwszUserName = strUserName.GetBufferSetLength( MAX_STRING_LENGTH );
  474. }
  475. catch( ... )
  476. {
  477. SetLastError( E_OUTOFMEMORY );
  478. SaveLastError();
  479. return FALSE;
  480. }
  481. // get the user name
  482. DWORD dwUserLength = MAX_STRING_LENGTH;
  483. if ( GetUserNameEx( NameSamCompatible, pwszUserName, &dwUserLength ) == FALSE )
  484. {
  485. // error occured while trying to get the current user info
  486. SaveLastError();
  487. return FALSE;
  488. }
  489. // release the extra buffer allocated
  490. strUserName.ReleaseBuffer();
  491. }
  492. try
  493. {
  494. // get the required buffer
  495. pwszPassword = strPassword.GetBufferSetLength( MAX_STRING_LENGTH );
  496. }
  497. catch( ... )
  498. {
  499. SetLastError( E_OUTOFMEMORY );
  500. SaveLastError();
  501. return FALSE;
  502. }
  503. // accept the password from the user
  504. strBuffer.Format( INPUT_PASSWORD, strUserName );
  505. WriteConsoleW( GetStdHandle( STD_ERROR_HANDLE ),
  506. strBuffer, strBuffer.GetLength(), &dwSize, NULL );
  507. bResult = GetPassword( pwszPassword, MAX_PASSWORD_LENGTH );
  508. if ( bResult != TRUE )
  509. {
  510. return FALSE;
  511. }
  512. // release the buffer allocated for password
  513. strPassword.ReleaseBuffer();
  514. // now again try to establish the connection using the currently
  515. // supplied credentials
  516. bResult = ConnectWmi( pLocator, ppServices, pwszServer,
  517. strUserName, strPassword, ppAuthIdentity, FALSE, pwszNamespace, NULL, pbLocalSystem );
  518. // return the failure
  519. return bResult;
  520. }
  521. /*********************************************************************************************
  522. Routine Description:
  523. This function gets the values for the security services.
  524. Arguments:
  525. [in] IUnknown : pointer to the IUnkown interface
  526. [out] DWORD : to hold the authentication service value
  527. [out] DWORD : to hold the authorization service value
  528. Return Value:
  529. HRESULT
  530. *********************************************************************************************/
  531. HRESULT GetSecurityArguments( IUnknown* pInterface,
  532. DWORD& dwAuthorization, DWORD& dwAuthentication )
  533. {
  534. // local variables
  535. HRESULT hr;
  536. DWORD dwAuthnSvc = 0, dwAuthzSvc = 0;
  537. IClientSecurity* pClientSecurity = NULL;
  538. // try to get the client security services values if possible
  539. hr = pInterface->QueryInterface( IID_IClientSecurity, (void**) &pClientSecurity );
  540. if ( SUCCEEDED( hr ) )
  541. {
  542. // got the client security interface
  543. // now try to get the security services values
  544. hr = pClientSecurity->QueryBlanket( pInterface,
  545. &dwAuthnSvc, &dwAuthzSvc, NULL, NULL, NULL, NULL, NULL );
  546. if ( SUCCEEDED( hr ) )
  547. {
  548. // we've got the values from the interface
  549. dwAuthentication = dwAuthnSvc;
  550. dwAuthorization = dwAuthzSvc;
  551. }
  552. // release the client security interface
  553. SAFE_RELEASE( pClientSecurity );
  554. }
  555. // return always success
  556. return S_OK;
  557. }
  558. /*********************************************************************************************
  559. Routine Description:
  560. This function sets the interface security parameters.
  561. Arguments:
  562. [in] IUnknown : pointer to the IUnkown interface
  563. [in] LPCWSTR : string containing the server name
  564. [in] LPCWSTR : string containing the User name
  565. [in] LPCWSTR : string containing the password
  566. [in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
  567. Return Value:
  568. HRESULT
  569. *********************************************************************************************/
  570. HRESULT SetInterfaceSecurity( IUnknown* pInterface,
  571. LPCWSTR pwszServer, LPCWSTR pwszUser,
  572. LPCWSTR pwszPassword, COAUTHIDENTITY** ppAuthIdentity )
  573. {
  574. // local variables
  575. HRESULT hr;
  576. CHString strUser;
  577. CHString strDomain;
  578. LPCWSTR pwszUserArg = NULL;
  579. LPCWSTR pwszDomainArg = NULL;
  580. DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
  581. DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
  582. // check the interface
  583. if ( pInterface == NULL )
  584. {
  585. return WBEM_E_INVALID_PARAMETER;
  586. }
  587. // check the authentity strcuture ... if authentity structure is already ready
  588. // simply invoke the 2nd version of SetInterfaceSecurity
  589. if ( *ppAuthIdentity != NULL )
  590. {
  591. return SetInterfaceSecurity( pInterface, *ppAuthIdentity );
  592. }
  593. // get the current security argument value
  594. /*hr = GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication );
  595. if ( FAILED( hr ) )
  596. {
  597. return hr;
  598. }*/
  599. // If we are doing trivial case, just pass in a null authenication structure
  600. // for which the current logged in user's credentials will be considered
  601. if ( pwszUser == NULL && pwszPassword == NULL )
  602. {
  603. // set the security
  604. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization,
  605. NULL, RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
  606. // return the result
  607. return hr;
  608. }
  609. // parse and find out if the user name contains the domain name
  610. // if contains, extract the domain value from it
  611. LONG lPos = -1;
  612. strDomain = L"";
  613. strUser = pwszUser;
  614. if ( ( lPos = strUser.Find( L'\\' ) ) != -1 )
  615. {
  616. // user name contains domain name ... domain\user format
  617. strDomain = strUser.Left( lPos );
  618. strUser = strUser.Mid( lPos + 1 );
  619. }
  620. else if ( ( lPos = strUser.Find( L'@' ) ) != -1 )
  621. {
  622. // NEED TO IMPLEMENT THIS ... IF NEEDED
  623. // This implementation needs to be done if WMI does not support
  624. // UPN name formats directly and if we have to split the
  625. // name(user@domain)
  626. }
  627. else
  628. {
  629. // server itself is the domain
  630. // NOTE: NEED TO DO SOME R & D ON BELOW COMMENTED LINE
  631. // strDomain = pwszServer;
  632. }
  633. // get the domain info if it exists only
  634. if ( strDomain.GetLength() != 0 )
  635. {
  636. pwszDomainArg = strDomain;
  637. }
  638. // get the user info if it exists only
  639. if ( strUser.GetLength() != 0 )
  640. {
  641. pwszUserArg = strUser;
  642. }
  643. // check if authenication info is available or not ...
  644. // initialize the security authenication information ... UNICODE VERSION STRUCTURE
  645. if ( ppAuthIdentity == NULL )
  646. {
  647. return WBEM_E_INVALID_PARAMETER;
  648. }
  649. else if ( *ppAuthIdentity == NULL )
  650. {
  651. hr = WbemAllocAuthIdentity( pwszUserArg, pwszPassword, pwszDomainArg, ppAuthIdentity );
  652. if ( hr != S_OK )
  653. {
  654. return hr;
  655. }
  656. }
  657. // set the security information to the interface
  658. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
  659. RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, *ppAuthIdentity, EOAC_NONE );
  660. // return the result
  661. return hr;
  662. }
  663. /*********************************************************************************************
  664. Routine Description:
  665. This function sets the interface security parameters.
  666. Arguments:
  667. [in] IUnknown : pointer to the IUnkown interface
  668. [in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
  669. Return Value:
  670. HRESULT
  671. *********************************************************************************************/
  672. HRESULT SetInterfaceSecurity( IUnknown* pInterface, COAUTHIDENTITY* pAuthIdentity )
  673. {
  674. // local variables
  675. HRESULT hr;
  676. LPWSTR pwszDomain = NULL;
  677. DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
  678. DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
  679. // check the interface
  680. if ( pInterface == NULL )
  681. {
  682. return WBEM_E_INVALID_PARAMETER;
  683. }
  684. // get the current security argument value
  685. hr = GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication );
  686. if ( FAILED( hr ) )
  687. {
  688. return hr;
  689. }
  690. // set the security information to the interface
  691. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
  692. RPC_C_AUTHN_LEVEL_DEFAULT, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthIdentity, EOAC_NONE );
  693. // return the result
  694. return hr;
  695. }
  696. /*********************************************************************************************
  697. Routine Description:
  698. This function sets the authentication information (the security blanket)
  699. that will be used to make calls.
  700. Arguments:
  701. [in] IUnknown : pointer to the IUnkown interface
  702. [in] DWORD : contains the authentication service to use
  703. [in] DWORD : contains the authorization service to use
  704. [in] LPWSTR : the server principal name to use
  705. [in] DWORD : contains the authentication level to use
  706. [in] DWORD : contains the impersonation level to use
  707. [in] RPC_AUTH_IDENTITY_HANDLE : pointer to the identity of the client
  708. [in] DWORD : contains the capability flags
  709. Return Value:
  710. HRESULT
  711. *********************************************************************************************/
  712. HRESULT WINAPI SetProxyBlanket( IUnknown* pInterface,
  713. DWORD dwAuthnSvc, DWORD dwAuthzSvc,
  714. LPWSTR pwszPrincipal, DWORD dwAuthLevel, DWORD dwImpLevel,
  715. RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities )
  716. {
  717. // local variables
  718. HRESULT hr;
  719. IUnknown * pUnknown = NULL;
  720. IClientSecurity * pClientSecurity = NULL;
  721. // get the IUnknown interface ... to check whether this is a valid interface or not
  722. hr = pInterface->QueryInterface( IID_IUnknown, (void **) &pUnknown );
  723. if ( hr != S_OK )
  724. {
  725. return hr;
  726. }
  727. // now get the client security interface
  728. hr = pInterface->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
  729. if ( hr != S_OK )
  730. {
  731. SAFE_RELEASE( pUnknown );
  732. return hr;
  733. }
  734. //
  735. // Can't set pAuthInfo if cloaking requested, as cloaking implies
  736. // that the current proxy identity in the impersonated thread (rather
  737. // than the credentials supplied explicitly by the RPC_AUTH_IDENTITY_HANDLE)
  738. // is to be used.
  739. // See MSDN info on CoSetProxyBlanket for more details.
  740. //
  741. if ( dwCapabilities & (EOAC_STATIC_CLOAKING | EOAC_DYNAMIC_CLOAKING) )
  742. {
  743. pAuthInfo = NULL;
  744. }
  745. // now set the security
  746. hr = pClientSecurity->SetBlanket( pInterface, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
  747. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
  748. if( FAILED( hr ) )
  749. {
  750. SAFE_RELEASE( pUnknown );
  751. SAFE_RELEASE( pClientSecurity );
  752. return hr;
  753. }
  754. // release the security interface
  755. SAFE_RELEASE( pClientSecurity );
  756. // we should check the auth identity structure. if exists .. set for IUnknown also
  757. if ( pAuthInfo != NULL )
  758. {
  759. hr = pUnknown->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
  760. if ( hr == S_OK )
  761. {
  762. // set security authentication
  763. hr = pClientSecurity->SetBlanket( pUnknown, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
  764. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
  765. // release
  766. SAFE_RELEASE( pClientSecurity );
  767. }
  768. else if ( hr == E_NOINTERFACE )
  769. {
  770. hr = S_OK; // ignore no interface errors
  771. }
  772. }
  773. // release the IUnknown
  774. SAFE_RELEASE( pUnknown );
  775. // return the result
  776. return hr;
  777. }
  778. /*********************************************************************************************
  779. Routine Description:
  780. This function allocates memory for the AUTHIDENTITY structure.
  781. Arguments:
  782. [in] LPCWSTR : string containing the user name
  783. [in] LPCWSTR : string containing the password
  784. [in] LPCWSTR : string containing the domain name
  785. [out] COAUTHIDENTITY : pointer to the pointer to AUTHIDENTITY structure
  786. Return Value:
  787. HRESULT
  788. *********************************************************************************************/
  789. HRESULT WINAPI WbemAllocAuthIdentity( LPCWSTR pwszUser, LPCWSTR pwszPassword,
  790. LPCWSTR pwszDomain, COAUTHIDENTITY** ppAuthIdent )
  791. {
  792. // local variables
  793. COAUTHIDENTITY* pAuthIdent = NULL;
  794. // validate the input parameter
  795. if ( ppAuthIdent == NULL )
  796. {
  797. return WBEM_E_INVALID_PARAMETER;
  798. }
  799. // allocation thru COM API
  800. pAuthIdent = ( COAUTHIDENTITY* ) CoTaskMemAlloc( sizeof( COAUTHIDENTITY ) );
  801. if ( NULL == pAuthIdent )
  802. {
  803. return WBEM_E_OUT_OF_MEMORY;
  804. }
  805. // init with 0's
  806. ZeroMemory( ( void* ) pAuthIdent, sizeof( COAUTHIDENTITY ) );
  807. //
  808. // Allocate needed memory and copy in data. Cleanup if anything goes wrong
  809. // user
  810. if ( pwszUser != NULL )
  811. {
  812. // allocate memory for user
  813. LONG lLength = wcslen( pwszUser );
  814. pAuthIdent->User = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  815. if ( pAuthIdent->User == NULL )
  816. {
  817. WbemFreeAuthIdentity( &pAuthIdent );
  818. return WBEM_E_OUT_OF_MEMORY;
  819. }
  820. // set the length and do copy contents
  821. pAuthIdent->UserLength = lLength;
  822. wcscpy( pAuthIdent->User, pwszUser );
  823. }
  824. // domain
  825. if ( pwszDomain != NULL )
  826. {
  827. // allocate memory for domain
  828. LONG lLength = wcslen( pwszDomain );
  829. pAuthIdent->Domain = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  830. if ( pAuthIdent->Domain == NULL )
  831. {
  832. WbemFreeAuthIdentity( &pAuthIdent );
  833. return WBEM_E_OUT_OF_MEMORY;
  834. }
  835. // set the length and do copy contents
  836. pAuthIdent->DomainLength = lLength;
  837. wcscpy( pAuthIdent->Domain, pwszDomain );
  838. }
  839. // passsord
  840. if ( pwszPassword != NULL )
  841. {
  842. // allocate memory for passsord
  843. LONG lLength = wcslen( pwszPassword );
  844. pAuthIdent->Password = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  845. if ( pAuthIdent->Password == NULL )
  846. {
  847. WbemFreeAuthIdentity( &pAuthIdent );
  848. return WBEM_E_OUT_OF_MEMORY;
  849. }
  850. // set the length and do copy contents
  851. pAuthIdent->PasswordLength = lLength;
  852. wcscpy( pAuthIdent->Password, pwszPassword );
  853. }
  854. // type of the structure
  855. pAuthIdent->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  856. // final set the address to out parameter
  857. *ppAuthIdent = pAuthIdent;
  858. // return result
  859. return S_OK;
  860. }
  861. /*********************************************************************************************
  862. Routine Description:
  863. This function releases the memory allocated for the AUTHIDENTITY structure.
  864. Arguments:
  865. [in] COAUTHIDENTITY : pointer to the pointer to AUTHIDENTITY structure
  866. Return Value:
  867. None
  868. *********************************************************************************************/
  869. VOID WINAPI WbemFreeAuthIdentity( COAUTHIDENTITY** ppAuthIdentity )
  870. {
  871. // make sure we have a pointer, then walk the structure members and cleanup.
  872. if ( *ppAuthIdentity != NULL )
  873. {
  874. // free the memory allocated for user
  875. if ( (*ppAuthIdentity)->User != NULL )
  876. {
  877. CoTaskMemFree( (*ppAuthIdentity)->User );
  878. }
  879. // free the memory allocated for password
  880. if ( (*ppAuthIdentity)->Password != NULL )
  881. {
  882. CoTaskMemFree( (*ppAuthIdentity)->Password );
  883. }
  884. // free the memory allocated for domain
  885. if ( (*ppAuthIdentity)->Domain != NULL )
  886. {
  887. CoTaskMemFree( (*ppAuthIdentity)->Domain );
  888. }
  889. // final the structure
  890. CoTaskMemFree( *ppAuthIdentity );
  891. }
  892. // set to NULL
  893. *ppAuthIdentity = NULL;
  894. }
  895. /*********************************************************************************************
  896. Routine Description:
  897. This function saves the description of the last error returned by WMI
  898. Arguments:
  899. HRESULT : The last return value from WMI
  900. Return Value:
  901. NONE
  902. *********************************************************************************************/
  903. VOID WMISaveError( HRESULT hrError )
  904. {
  905. // local variables
  906. HRESULT hr;
  907. CHString strBuffer = NULL_STRING;
  908. IWbemStatusCodeText* pWbemStatus = NULL;
  909. // if the error is win32 based, choose FormatMessage to get the message
  910. switch( hrError )
  911. {
  912. case E_ACCESSDENIED: // Message: "Access Denied"
  913. case ERROR_NO_SUCH_USER: // Message: "The specified user does not exist."
  914. {
  915. // change the error message to "Logon failure: unknown user name or bad password."
  916. if ( hrError == E_ACCESSDENIED )
  917. {
  918. hrError = ERROR_LOGON_FAILURE;
  919. }
  920. // ...
  921. SetLastError( hrError );
  922. SaveLastError();
  923. return;
  924. }
  925. }
  926. try
  927. {
  928. // get the pointer to buffer
  929. LPWSTR pwszBuffer = NULL;
  930. pwszBuffer = strBuffer.GetBufferSetLength( MAX_STRING_LENGTH );
  931. // get the wbem specific status code text
  932. hr = CoCreateInstance( CLSID_WbemStatusCodeText,
  933. NULL, CLSCTX_INPROC_SERVER, IID_IWbemStatusCodeText, (LPVOID*) &pWbemStatus );
  934. // check whether we got the interface or not
  935. if ( SUCCEEDED( hr ) )
  936. {
  937. // get the error message
  938. BSTR bstr = NULL;
  939. hr = pWbemStatus->GetErrorCodeText( hrError, 0, 0, &bstr );
  940. if ( SUCCEEDED( hr ) )
  941. {
  942. // get the error message in proper format
  943. GetCompatibleStringFromUnicode( bstr, pwszBuffer, MAX_STRING_LENGTH );
  944. //
  945. // supress all the new-line characters and add '.' at the end ( if not exists )
  946. LPWSTR pwszTemp = NULL;
  947. pwszTemp = wcstok( pwszBuffer, L"\r\n" );
  948. if ( *( pwszTemp + lstrlenW( pwszTemp ) - 1 ) != L'.' )
  949. {
  950. lstrcatW( pwszTemp, L"." );
  951. }
  952. // free the BSTR
  953. SysFreeString( bstr );
  954. bstr = NULL;
  955. // now release status code interface
  956. SAFE_RELEASE( pWbemStatus );
  957. }
  958. else
  959. {
  960. // failed to get the error message ... get the com specific error message
  961. _com_issue_error( hrError );
  962. }
  963. }
  964. else
  965. {
  966. // failed to get the error message ... get the com specific error message
  967. _com_issue_error( hrError );
  968. }
  969. // release the buffer
  970. strBuffer.ReleaseBuffer();
  971. }
  972. catch( _com_error& e )
  973. {
  974. try
  975. {
  976. // get the error message
  977. strBuffer.ReleaseBuffer();
  978. if ( e.ErrorMessage() != NULL )
  979. strBuffer = e.ErrorMessage();
  980. }
  981. catch( ... )
  982. {
  983. SetLastError( E_OUTOFMEMORY );
  984. SaveLastError();
  985. }
  986. }
  987. catch( ... )
  988. {
  989. SetLastError( E_OUTOFMEMORY );
  990. SaveLastError();
  991. return;
  992. }
  993. // set the reason
  994. strBuffer += L"\n";
  995. SetReason( strBuffer );
  996. }
  997. /*********************************************************************************************
  998. Routine Description:
  999. Gets the value of the property from the WMI class object
  1000. Arguments:
  1001. [in] IWbemClassObject : pointer to the WBEM class object
  1002. [in] LPCWSTR : property name
  1003. [out] _variant_t : value of the property
  1004. Return Value:
  1005. HRESULT
  1006. *********************************************************************************************/
  1007. HRESULT PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, _variant_t& varValue )
  1008. {
  1009. // local variables
  1010. HRESULT hr;
  1011. VARIANT vtValue;
  1012. // check with object and property passed to the function are valid or not
  1013. // if not, return failure
  1014. if ( pWmiObject == NULL || pwszProperty == NULL )
  1015. {
  1016. return WBEM_E_INVALID_PARAMETER;
  1017. }
  1018. try
  1019. {
  1020. // initialize the variant and then get the value of the specified property
  1021. VariantInit( &vtValue );
  1022. hr = pWmiObject->Get( _bstr_t( pwszProperty ), 0, &vtValue, NULL, NULL );
  1023. if ( FAILED( hr ) )
  1024. {
  1025. // clear the variant variable
  1026. VariantClear( &vtValue );
  1027. // failed to get the value for the property
  1028. return hr;
  1029. }
  1030. // set the value
  1031. varValue = vtValue;
  1032. // clear the variant variable
  1033. VariantClear( &vtValue );
  1034. }
  1035. catch( _com_error& e )
  1036. {
  1037. WMISaveError( e );
  1038. return e.Error();
  1039. }
  1040. // inform success
  1041. return S_OK;
  1042. }
  1043. /*********************************************************************************************
  1044. Routine Description:
  1045. Gets the value of the property from the WMI class object in string format
  1046. Arguments:
  1047. [in] IWbemClassObject : pointer to the WBEM class object
  1048. [in] LPCWSTR : the name of the property to retrieve
  1049. [out] CHString : variable to hold the retrieved property
  1050. [in] LPCWSTR : string containing the default value for the property
  1051. Return Value:
  1052. TRUE on success
  1053. FALSE on failure
  1054. *********************************************************************************************/
  1055. BOOL PropertyGet( IWbemClassObject* pWmiObject,
  1056. LPCWSTR pwszProperty, CHString& strValue, LPCWSTR pwszDefault )
  1057. {
  1058. // local variables
  1059. HRESULT hr;
  1060. _variant_t var;
  1061. // first copy the default value
  1062. strValue = pwszDefault;
  1063. // check with object and property passed to the function are valid or not
  1064. // if not, return failure
  1065. if ( pWmiObject == NULL || pwszProperty == NULL )
  1066. {
  1067. return FALSE;
  1068. }
  1069. // get the property value
  1070. hr = PropertyGet( pWmiObject, pwszProperty, var );
  1071. if ( FAILED( hr ) )
  1072. {
  1073. return FALSE;
  1074. }
  1075. try
  1076. {
  1077. // get the value
  1078. if ( var.vt != VT_NULL && var.vt != VT_EMPTY )
  1079. {
  1080. strValue = (LPCWSTR) _bstr_t( var );
  1081. }
  1082. }
  1083. catch( ... )
  1084. {
  1085. SetLastError( E_OUTOFMEMORY );
  1086. SaveLastError();
  1087. return FALSE;
  1088. }
  1089. // return
  1090. return TRUE;
  1091. }
  1092. /*********************************************************************************************
  1093. Routine Description:
  1094. Gets the value of the property from the WMI class object in dword format
  1095. Arguments:
  1096. [in] IWbemClassObject : pointer to the WBEM class object
  1097. [in] LPCWSTR : the name of the property to retrieve
  1098. [out] DWORD : variable to hold the retrieved property
  1099. [in] DWORD : dword containing the default value for the property
  1100. Return Value:
  1101. TRUE on success
  1102. FALSE on failure
  1103. *********************************************************************************************/
  1104. BOOL PropertyGet( IWbemClassObject* pWmiObject,
  1105. LPCWSTR pwszProperty, DWORD& dwValue, DWORD dwDefault )
  1106. {
  1107. // local variables
  1108. HRESULT hr;
  1109. _variant_t var;
  1110. // first set the defaul value
  1111. dwValue = dwDefault;
  1112. // check with object and property passed to the function are valid or not
  1113. // if not, return failure
  1114. if ( pWmiObject == NULL || pwszProperty == NULL )
  1115. {
  1116. return FALSE;
  1117. }
  1118. // get the value of the property
  1119. hr = PropertyGet( pWmiObject, pwszProperty, var );
  1120. if ( FAILED( hr ) )
  1121. {
  1122. return FALSE;
  1123. }
  1124. // get the process id from the variant
  1125. if ( var.vt != VT_NULL && var.vt != VT_EMPTY )
  1126. {
  1127. dwValue = (LONG) var;
  1128. }
  1129. // return
  1130. return TRUE;
  1131. }
  1132. /*********************************************************************************************
  1133. Routine Description:
  1134. Gets the value of the property from the WMI class object in bool format
  1135. Arguments:
  1136. [in] IWbemClassObject : pointer to the WBEM class object
  1137. [in] LPCWSTR : the name of the property to retrieve
  1138. [out] BOOL : variable to hold the retrieved property
  1139. [in] BOOL : bool containing the default value for the property
  1140. Return Value:
  1141. TRUE on success
  1142. FALSE on failure
  1143. *********************************************************************************************/
  1144. BOOL PropertyGet( IWbemClassObject* pWmiObject,
  1145. LPCWSTR pwszProperty, BOOL& bValue, BOOL bDefault )
  1146. {
  1147. // local variables
  1148. HRESULT hr;
  1149. _variant_t var;
  1150. // first set the default value
  1151. bValue = bDefault;
  1152. // check with object and property passed to the function are valid or not
  1153. // if not, return failure
  1154. if ( pWmiObject == NULL || pwszProperty == NULL )
  1155. {
  1156. return FALSE;
  1157. }
  1158. // get the value of the property
  1159. hr = PropertyGet( pWmiObject, pwszProperty, var );
  1160. if ( FAILED( hr ) )
  1161. {
  1162. return FALSE;
  1163. }
  1164. // get the process id from the variant
  1165. if ( var.vt != VT_NULL && var.vt != VT_EMPTY )
  1166. {
  1167. bValue = var.boolVal;
  1168. }
  1169. // return
  1170. return TRUE;
  1171. }
  1172. /*********************************************************************************************
  1173. Routine Description:
  1174. Gets the value of the property from the WMI class object in ulongulong format
  1175. Arguments:
  1176. [in] IWbemClassObject : pointer to the WBEM class object
  1177. [in] LPCWSTR : the name of the property to retrieve
  1178. [out] ULONGULONG : variable to hold the retrieved property
  1179. Return Value:
  1180. TRUE on success
  1181. FALSE on failure
  1182. *********************************************************************************************/
  1183. BOOL PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, ULONGLONG& ullValue )
  1184. {
  1185. // local variables
  1186. CHString str;
  1187. // first set the default value
  1188. ullValue = 1;
  1189. // check with object and property passed to the function are valid or not
  1190. // if not, return failure
  1191. if ( pWmiObject == NULL || pwszProperty == NULL )
  1192. {
  1193. return FALSE;
  1194. }
  1195. // get the value of the property
  1196. if ( PropertyGet( pWmiObject, pwszProperty, str, _T( "0" ) ) == FALSE )
  1197. {
  1198. return FALSE;
  1199. }
  1200. // get the 64-bit value
  1201. ullValue = _wtoi64( str );
  1202. // return
  1203. return TRUE;
  1204. }
  1205. /*********************************************************************************************
  1206. Routine Description:
  1207. Gets the value of the property from the WMI class object in wbemtime format
  1208. Arguments:
  1209. [in] IWbemClassObject : pointer to the WBEM class object
  1210. [in] LPCWSTR : the name of the property to retrieve
  1211. [out] WBEMTime : variable to hold the retrieved property
  1212. Return Value:
  1213. TRUE on success
  1214. FALSE on failure
  1215. *********************************************************************************************/
  1216. BOOL PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, WBEMTime& wbemtime )
  1217. {
  1218. // local variables
  1219. CHString str;
  1220. // Clear method sets the time in the WBEMTime object to an invalid time.
  1221. wbemtime.Clear();
  1222. // check with object and property passed to the function are valid or not
  1223. // if not, return failure
  1224. if ( pWmiObject == NULL || pwszProperty == NULL )
  1225. {
  1226. return FALSE;
  1227. }
  1228. // get the value of the property
  1229. if ( PropertyGet( pWmiObject, pwszProperty, str, _T( "0" ) ) == FALSE )
  1230. {
  1231. return FALSE;
  1232. }
  1233. try
  1234. {
  1235. // convert into the time value
  1236. wbemtime = _bstr_t( str );
  1237. }
  1238. catch( _com_error& e )
  1239. {
  1240. WMISaveError( e );
  1241. return FALSE;
  1242. }
  1243. // return
  1244. return TRUE;
  1245. }
  1246. /*********************************************************************************************
  1247. Routine Description:
  1248. Gets the value of the property from the WMI class object in systemtime format
  1249. Arguments:
  1250. [in] IWbemClassObject : pointer to the WBEM class object
  1251. [in] LPCWSTR : the name of the property to retrieve
  1252. [out] WBEMTime : variable to hold the retrieved property
  1253. Return Value:
  1254. TRUE on success
  1255. FALSE on failure
  1256. *********************************************************************************************/
  1257. BOOL PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, SYSTEMTIME& systime )
  1258. {
  1259. // local variables
  1260. CHString strTime;
  1261. // check with object and property passed to the function are valid or not
  1262. // if not, return failure
  1263. if ( pWmiObject == NULL || pwszProperty == NULL )
  1264. {
  1265. return FALSE;
  1266. }
  1267. // get the value of the property
  1268. // 16010101000000.000000+000 is the default time
  1269. if ( PropertyGet( pWmiObject, pwszProperty, strTime, _T( "16010101000000.000000+000" ) ) == FALSE )
  1270. {
  1271. return FALSE;
  1272. }
  1273. // prepare the systemtime structure
  1274. // yyyymmddHHMMSS.mmmmmmsUUU
  1275. systime.wYear = (WORD) AsLong( strTime.Left( 4 ), 10 );
  1276. systime.wMonth = (WORD) AsLong( strTime.Mid( 4, 2 ), 10 );
  1277. systime.wDayOfWeek = 0;
  1278. systime.wDay = (WORD) AsLong( strTime.Mid( 6, 2 ), 10 );
  1279. systime.wHour = (WORD) AsLong( strTime.Mid( 8, 2 ), 10 );
  1280. systime.wMinute = (WORD) AsLong( strTime.Mid( 10, 2 ), 10 );
  1281. systime.wSecond = (WORD) AsLong( strTime.Mid( 12, 2 ), 10 );
  1282. systime.wMilliseconds = (WORD) AsLong( strTime.Mid( 15, 6 ), 10 );
  1283. // return
  1284. return TRUE;
  1285. }
  1286. /*********************************************************************************************
  1287. Routine Description:
  1288. Sets the value of the property to the WMI class object
  1289. Arguments:
  1290. [in] IWbemClassObject : pointer to the WBEM class object
  1291. [in] LPCWSTR : the name of the property to retrieve
  1292. [in] WBEMTime : variable holding the property to set
  1293. Return Value:
  1294. TRUE on success
  1295. FALSE on failure
  1296. *********************************************************************************************/
  1297. HRESULT PropertyPut( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, _variant_t& varValue )
  1298. {
  1299. // local variables
  1300. HRESULT hr;
  1301. VARIANT var;
  1302. // check the input value
  1303. if ( pWmiObject == NULL || pwszProperty == NULL )
  1304. {
  1305. return WBEM_E_INVALID_PARAMETER;
  1306. }
  1307. try
  1308. {
  1309. // put the value
  1310. var = varValue;
  1311. hr = pWmiObject->Put( _bstr_t( pwszProperty ), 0, &var, 0 );
  1312. }
  1313. catch( _com_error& e )
  1314. {
  1315. WMISaveError( e );
  1316. hr = e.Error();
  1317. }
  1318. // return the result
  1319. return hr;
  1320. }
  1321. /*********************************************************************************************
  1322. Routine Description:
  1323. Sets the string value of the property to the WMI class object
  1324. Arguments:
  1325. [in] IWbemClassObject : pointer to the WBEM class object
  1326. [in] LPCWSTR : the name of the property to retrieve
  1327. [in] LPCWSTR : variable holding the property to set
  1328. Return Value:
  1329. TRUE on success
  1330. FALSE on failure
  1331. *********************************************************************************************/
  1332. HRESULT PropertyPut( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, LPCWSTR pwszValue )
  1333. {
  1334. // local variables
  1335. HRESULT hr = S_OK;
  1336. _variant_t varValue;
  1337. // check the input value
  1338. if ( pWmiObject == NULL || pwszProperty == NULL || pwszValue == NULL )
  1339. {
  1340. return WBEM_E_INVALID_PARAMETER;
  1341. }
  1342. try
  1343. {
  1344. varValue = pwszValue;
  1345. PropertyPut( pWmiObject, pwszProperty, varValue );
  1346. }
  1347. catch( _com_error& e )
  1348. {
  1349. WMISaveError( e );
  1350. hr = e.Error();
  1351. }
  1352. // return
  1353. return hr;
  1354. }
  1355. /*********************************************************************************************
  1356. Routine Description:
  1357. Sets the dword value of the property to the WMI class object
  1358. Arguments:
  1359. [in] IWbemClassObject : pointer to the WBEM class object
  1360. [in] LPCWSTR : the name of the property to retrieve
  1361. [in] DWORD : variable holding the property to set
  1362. Return Value:
  1363. TRUE on success
  1364. FALSE on failure
  1365. *********************************************************************************************/
  1366. HRESULT PropertyPut( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, DWORD dwValue )
  1367. {
  1368. // local variables
  1369. HRESULT hr;
  1370. _variant_t varValue;
  1371. // check the input value
  1372. if ( pWmiObject == NULL || pwszProperty == NULL )
  1373. {
  1374. return WBEM_E_INVALID_PARAMETER;
  1375. }
  1376. try
  1377. {
  1378. varValue = ( LONG ) dwValue;
  1379. PropertyPut( pWmiObject, pwszProperty, varValue );
  1380. }
  1381. catch( _com_error& e )
  1382. {
  1383. WMISaveError( e );
  1384. hr = e.Error();
  1385. }
  1386. // return
  1387. return hr;
  1388. }
  1389. /*********************************************************************************************
  1390. Routine Description:
  1391. This function retrieves the value of the property from the specified registry key.
  1392. Arguments:
  1393. [in] IWbemServices : pointer to the IWbemServices object
  1394. [in] LPCWSTR : the name of the method to execute
  1395. [in] DWORD : the key in the registry whose value has to be retrieved
  1396. [in] LPCWSTR : the name of the subkey to retrieve
  1397. [in] LPCWSTR : the name of the value to retrieve
  1398. [in] _variant_t : variable holding the property value retrieved
  1399. Return Value:
  1400. TRUE on success
  1401. FALSE on failure
  1402. *********************************************************************************************/
  1403. HRESULT RegQueryValueWMI( IWbemServices* pWbemServices,
  1404. LPCWSTR pwszMethod, DWORD dwHDefKey,
  1405. LPCWSTR pwszSubKeyName, LPCWSTR pwszValueName, _variant_t& varValue )
  1406. {
  1407. // local variables
  1408. HRESULT hr;
  1409. BOOL bResult = FALSE;
  1410. DWORD dwReturnValue = 0;
  1411. IWbemClassObject* pClass = NULL;
  1412. IWbemClassObject* pMethod = NULL;
  1413. IWbemClassObject* pInParams = NULL;
  1414. IWbemClassObject* pInParamsInstance = NULL;
  1415. IWbemClassObject* pOutParamsInstance = NULL;
  1416. // check the input value
  1417. if (pWbemServices == NULL || pwszMethod == NULL || pwszSubKeyName == NULL || pwszValueName == NULL)
  1418. {
  1419. return WBEM_E_INVALID_PARAMETER;
  1420. }
  1421. try
  1422. {
  1423. // get the registry class object
  1424. SAFE_EXECUTE( pWbemServices->GetObject(
  1425. _bstr_t( WMI_REGISTRY ), WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &pClass, NULL ) );
  1426. if ( pClass == NULL ) // check the object .. safety sake
  1427. {
  1428. _com_issue_error( STG_E_UNKNOWN );
  1429. }
  1430. // get the method reference required
  1431. SAFE_EXECUTE( pClass->GetMethod( pwszMethod, 0, &pInParams, NULL ) );
  1432. if ( pInParams == NULL ) // check the object .. safety sake
  1433. {
  1434. _com_issue_error( STG_E_UNKNOWN );
  1435. }
  1436. // create the instance for the in parameters
  1437. SAFE_EXECUTE( pInParams->SpawnInstance( 0, &pInParamsInstance ) );
  1438. if ( pInParamsInstance == NULL )
  1439. {
  1440. _com_issue_error( STG_E_UNKNOWN );
  1441. }
  1442. // set the input values
  1443. PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_HDEFKEY ), dwHDefKey );
  1444. PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_SUBKEY ), pwszSubKeyName );
  1445. PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_VALUENAME ), pwszValueName );
  1446. // now execute the method
  1447. SAFE_EXECUTE( pWbemServices->ExecMethod( _bstr_t( WMI_REGISTRY ),
  1448. _bstr_t( pwszMethod ), 0, NULL, pInParamsInstance, &pOutParamsInstance, NULL ) );
  1449. if ( pOutParamsInstance == NULL ) // check the object .. safety sake
  1450. {
  1451. _com_issue_error( STG_E_UNKNOWN );
  1452. }
  1453. // now check the return value of the method from the output params object
  1454. bResult = PropertyGet( pOutParamsInstance,
  1455. _bstr_t( WMI_REGISTRY_OUT_RETURNVALUE ), dwReturnValue );
  1456. if ( bResult == FALSE || dwReturnValue != 0 )
  1457. {
  1458. _com_issue_error( STG_E_UNKNOWN );
  1459. }
  1460. // now everything is sucess .. get the required value
  1461. if ( lstrcmp( pwszMethod, WMI_REGISTRY_M_DWORDVALUE ) == 0 )
  1462. {
  1463. PropertyGet( pOutParamsInstance, _bstr_t( WMI_REGISTRY_OUT_VALUE_DWORD ), varValue );
  1464. }
  1465. else
  1466. {
  1467. PropertyGet( pOutParamsInstance, _bstr_t( WMI_REGISTRY_OUT_VALUE ), varValue );
  1468. }
  1469. }
  1470. catch( _com_error& e )
  1471. {
  1472. WMISaveError( e );
  1473. return e.Error();
  1474. }
  1475. // release the interfaces
  1476. SAFE_RELEASE( pClass );
  1477. SAFE_RELEASE( pMethod );
  1478. SAFE_RELEASE( pInParams );
  1479. SAFE_RELEASE( pInParamsInstance );
  1480. SAFE_RELEASE( pOutParamsInstance );
  1481. // return success
  1482. return S_OK;
  1483. }
  1484. /*********************************************************************************************
  1485. Routine Description:
  1486. This function retrieves the string value of the property from the specified registry key.
  1487. Arguments:
  1488. [in] IWbemServices : pointer to the IWbemServices object
  1489. [in] DWORD : the key in the registry whose value has to be retrieved
  1490. [in] LPCWSTR : the name of the subkey to retrieve
  1491. [in] LPCWSTR : the name of the value to retrieve
  1492. [out] CHString : variable holding the property value retrieved
  1493. [in] LPCWSTR : the default value for this property
  1494. Return Value:
  1495. TRUE on success
  1496. FALSE on failure
  1497. *********************************************************************************************/
  1498. BOOL RegQueryValueWMI( IWbemServices* pWbemServices,
  1499. DWORD dwHDefKey, LPCWSTR pwszSubKeyName,
  1500. LPCWSTR pwszValueName, CHString& strValue, LPCWSTR pwszDefault )
  1501. {
  1502. // local variables
  1503. HRESULT hr;
  1504. _variant_t varValue;
  1505. try
  1506. {
  1507. // set the default value
  1508. if ( pwszDefault != NULL )
  1509. {
  1510. strValue = pwszDefault;
  1511. }
  1512. // check the input
  1513. if ( pWbemServices == NULL || pwszSubKeyName == NULL || pwszValueName == NULL )
  1514. {
  1515. return FALSE;
  1516. }
  1517. // get the value
  1518. hr = RegQueryValueWMI( pWbemServices,
  1519. WMI_REGISTRY_M_STRINGVALUE, dwHDefKey, pwszSubKeyName, pwszValueName, varValue );
  1520. if ( FAILED( hr ) )
  1521. {
  1522. return FALSE;
  1523. }
  1524. // get the value from the variant
  1525. // get the value
  1526. if ( varValue.vt != VT_NULL && varValue.vt != VT_EMPTY )
  1527. {
  1528. strValue = (LPCWSTR) _bstr_t( varValue );
  1529. }
  1530. }
  1531. catch( ... )
  1532. {
  1533. SetLastError( E_OUTOFMEMORY );
  1534. SaveLastError();
  1535. return FALSE;
  1536. }
  1537. // return success
  1538. return TRUE;
  1539. }
  1540. /*********************************************************************************************
  1541. Routine Description:
  1542. This function retrieves the dword value of the property from the specified registry key.
  1543. Arguments:
  1544. [in] IWbemServices : pointer to the IWbemServices object
  1545. [in] DWORD : the key in the registry whose value has to be retrieved
  1546. [in] LPCWSTR : the name of the subkey to retrieve
  1547. [in] LPCWSTR : the name of the value to retrieve
  1548. [out] DWORD : variable holding the property value retrieved
  1549. [in] DWORD : the default value for this property
  1550. Return Value:
  1551. TRUE on success
  1552. FALSE on failure
  1553. *********************************************************************************************/
  1554. BOOL RegQueryValueWMI( IWbemServices* pWbemServices,
  1555. DWORD dwHDefKey, LPCWSTR pwszSubKeyName,
  1556. LPCWSTR pwszValueName, DWORD& dwValue, DWORD dwDefault )
  1557. {
  1558. // local variables
  1559. HRESULT hr;
  1560. _variant_t varValue;
  1561. try
  1562. {
  1563. // set the default value
  1564. dwValue = dwDefault;
  1565. // check the input
  1566. if ( pWbemServices == NULL || pwszSubKeyName == NULL || pwszValueName == NULL )
  1567. {
  1568. return FALSE;
  1569. }
  1570. // get the value
  1571. hr = RegQueryValueWMI( pWbemServices, WMI_REGISTRY_M_DWORDVALUE, dwHDefKey,
  1572. pwszSubKeyName, pwszValueName, varValue );
  1573. if ( FAILED( hr ) )
  1574. {
  1575. return FALSE;
  1576. }
  1577. // get the value from the variant
  1578. // get the value
  1579. if ( varValue.vt != VT_NULL && varValue.vt != VT_EMPTY )
  1580. {
  1581. dwValue = (LONG) varValue;
  1582. }
  1583. }
  1584. catch( ... )
  1585. {
  1586. SetLastError( E_OUTOFMEMORY );
  1587. SaveLastError();
  1588. return FALSE;
  1589. }
  1590. // return success
  1591. return TRUE;
  1592. }
  1593. /*********************************************************************************************
  1594. Routine Description:
  1595. This function gets the version of the system from which we are trying to retrieve
  1596. information from.
  1597. Arguments:
  1598. [in] IWbemServices : pointer to the IWbemServices object
  1599. [in] COAUTHIDENTITY : pointer to the pointer to AUTHIDENTITY structure
  1600. Return Value:
  1601. DWORD - Target version of the machine
  1602. *********************************************************************************************/
  1603. DWORD GetTargetVersionEx( IWbemServices* pWbemServices, COAUTHIDENTITY* pAuthIdentity )
  1604. {
  1605. // local variables
  1606. HRESULT hr;
  1607. LONG lPos = 0;
  1608. DWORD dwMajor = 0;
  1609. DWORD dwMinor = 0;
  1610. DWORD dwVersion = 0;
  1611. ULONG ulReturned = 0;
  1612. CHString strVersion;
  1613. IWbemClassObject* pWbemObject = NULL;
  1614. IEnumWbemClassObject* pWbemInstances = NULL;
  1615. // check the input value
  1616. if ( pWbemServices == NULL )
  1617. {
  1618. return 0;
  1619. }
  1620. try
  1621. {
  1622. // get the OS information
  1623. SAFE_EXECUTE( pWbemServices->CreateInstanceEnum(
  1624. _bstr_t( CLASS_CIMV2_Win32_OperatingSystem ), 0, NULL, &pWbemInstances ) );
  1625. // set the security on the enumerated object
  1626. SAFE_EXECUTE( SetInterfaceSecurity( pWbemInstances, pAuthIdentity ) );
  1627. // get the enumerated objects information
  1628. // NOTE: This needs to be traversed only one time.
  1629. SAFE_EXECUTE( pWbemInstances->Next( WBEM_INFINITE, 1, &pWbemObject, &ulReturned ) );
  1630. // to be on safer side ... check the count of objects returned
  1631. if ( ulReturned == 0 )
  1632. {
  1633. // release the interfaces
  1634. SAFE_RELEASE( pWbemObject );
  1635. SAFE_RELEASE( pWbemInstances );
  1636. return 0;
  1637. }
  1638. // now get the os version value
  1639. if ( PropertyGet( pWbemObject, L"Version", strVersion ) == FALSE )
  1640. {
  1641. // release the interfaces
  1642. SAFE_RELEASE( pWbemObject );
  1643. SAFE_RELEASE( pWbemInstances );
  1644. return 0;
  1645. }
  1646. // release the interfaces .. we dont need them furthur
  1647. SAFE_RELEASE( pWbemObject );
  1648. SAFE_RELEASE( pWbemInstances );
  1649. //
  1650. // now determine the os version
  1651. dwMajor = dwMinor = 0;
  1652. // get the major version
  1653. lPos = strVersion.Find( L'.' );
  1654. if ( lPos == -1 )
  1655. {
  1656. // the version string itself is version ... THIS WILL NEVER HAPPEN
  1657. dwMajor = AsLong( strVersion, 10 );
  1658. }
  1659. else
  1660. {
  1661. // major version
  1662. dwMajor = AsLong( strVersion.Mid( 0, lPos ), 10 );
  1663. // get the minor version
  1664. strVersion = strVersion.Mid( lPos + 1 );
  1665. lPos = strVersion.Find( L'.' );
  1666. if ( lPos == -1 )
  1667. {
  1668. dwMinor = AsLong( strVersion, 10 );
  1669. }
  1670. else
  1671. {
  1672. dwMinor = AsLong( strVersion.Mid( 0, lPos ), 10 );
  1673. }
  1674. }
  1675. // mix the version info
  1676. dwVersion = dwMajor * 1000 + dwMinor;
  1677. }
  1678. catch( _com_error& e )
  1679. {
  1680. WMISaveError( e );
  1681. return 0;
  1682. }
  1683. // return
  1684. return dwVersion;
  1685. }
  1686. /*********************************************************************************************
  1687. Routine Description:
  1688. This function retrieves a property from the safe array.
  1689. Arguments:
  1690. [in] SAFEARRAY : pointer to the array of elements
  1691. [in] LONG : index to retrieve the data from
  1692. [out] CHString : variable to hold the return value
  1693. [in] VARTYPE : The type of variable to retrieve from the array
  1694. Return Value:
  1695. TRUE on success
  1696. FALSE on failure
  1697. *********************************************************************************************/
  1698. BOOL GetPropertyFromSafeArray( SAFEARRAY *pSafeArray, LONG lIndex, CHString& strValue,
  1699. VARTYPE vartype )
  1700. {
  1701. // check the inputs
  1702. if ( pSafeArray == NULL )
  1703. {
  1704. return FALSE;
  1705. }
  1706. try
  1707. {
  1708. // sub-local variables
  1709. VARIANT var;
  1710. // get the value
  1711. V_VT( &var ) = vartype;
  1712. SafeArrayGetElement( pSafeArray, &lIndex, &V_UI1( &var ) );
  1713. // add the information to the dynamic array
  1714. switch( vartype )
  1715. {
  1716. case VT_BSTR:
  1717. strValue = V_BSTR( &var );
  1718. break;
  1719. default:
  1720. return FALSE;
  1721. }
  1722. }
  1723. catch( ... )
  1724. {
  1725. return FALSE; // failure
  1726. }
  1727. // return
  1728. return TRUE;
  1729. }
  1730. /*********************************************************************************************
  1731. Routine Description:
  1732. This function retrieves a property from the safe array.
  1733. Arguments:
  1734. [in] SAFEARRAY : pointer to the array of elements
  1735. [in] LONG : index to retrieve the data from
  1736. [out] IWbemClassObject : variable to hold the return value
  1737. [in] VARTYPE : The type of variable to retrieve from the array
  1738. Return Value:
  1739. TRUE on success
  1740. FALSE on failure
  1741. *********************************************************************************************/
  1742. BOOL GetPropertyFromSafeArray( SAFEARRAY *pSafeArray, LONG lIndex,
  1743. IWbemClassObject **pScriptObject, VARTYPE vartype )
  1744. {
  1745. // check the inputs
  1746. if ( pSafeArray == NULL )
  1747. {
  1748. return FALSE;
  1749. }
  1750. try
  1751. {
  1752. // sub-local variables
  1753. VARIANT var;
  1754. // get the value
  1755. V_VT( &var ) = vartype;
  1756. SafeArrayGetElement( pSafeArray, &lIndex, &V_UI1( &var ) );
  1757. // add the information to the dynamic array
  1758. switch( vartype )
  1759. {
  1760. case VT_UNKNOWN:
  1761. *pScriptObject = (IWbemClassObject *) var.punkVal;
  1762. break;
  1763. default:
  1764. return FALSE;
  1765. }
  1766. }
  1767. catch( ... )
  1768. {
  1769. return FALSE; // failure
  1770. }
  1771. // return
  1772. return TRUE;
  1773. }