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.

2156 lines
66 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((DWORD) 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((DWORD)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((DWORD) 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_OUTPUT_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. //for the time being
  583. UNREFERENCED_PARAMETER( pwszServer );
  584. // check the interface
  585. if ( pInterface == NULL )
  586. {
  587. return WBEM_E_INVALID_PARAMETER;
  588. }
  589. // check the authentity strcuture ... if authentity structure is already ready
  590. // simply invoke the 2nd version of SetInterfaceSecurity
  591. if ( *ppAuthIdentity != NULL )
  592. {
  593. return SetInterfaceSecurity( pInterface, *ppAuthIdentity );
  594. }
  595. // get the current security argument value
  596. /*hr = GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication );
  597. if ( FAILED( hr ) )
  598. {
  599. return hr;
  600. }*/
  601. // If we are doing trivial case, just pass in a null authenication structure
  602. // for which the current logged in user's credentials will be considered
  603. if ( pwszUser == NULL && pwszPassword == NULL )
  604. {
  605. // set the security
  606. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization,
  607. NULL, RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE );
  608. // return the result
  609. return hr;
  610. }
  611. // parse and find out if the user name contains the domain name
  612. // if contains, extract the domain value from it
  613. LONG lPos = -1;
  614. strDomain = L"";
  615. strUser = pwszUser;
  616. if ( ( lPos = strUser.Find( L'\\' ) ) != -1 )
  617. {
  618. // user name contains domain name ... domain\user format
  619. strDomain = strUser.Left( lPos );
  620. strUser = strUser.Mid( lPos + 1 );
  621. }
  622. else if ( ( lPos = strUser.Find( L'@' ) ) != -1 )
  623. {
  624. // NEED TO IMPLEMENT THIS ... IF NEEDED
  625. // This implementation needs to be done if WMI does not support
  626. // UPN name formats directly and if we have to split the
  627. // name(user@domain)
  628. }
  629. else
  630. {
  631. // server itself is the domain
  632. // NOTE: NEED TO DO SOME R & D ON BELOW COMMENTED LINE
  633. // strDomain = pwszServer;
  634. }
  635. // get the domain info if it exists only
  636. if ( strDomain.GetLength() != 0 )
  637. {
  638. pwszDomainArg = strDomain;
  639. }
  640. // get the user info if it exists only
  641. if ( strUser.GetLength() != 0 )
  642. {
  643. pwszUserArg = strUser;
  644. }
  645. // check if authenication info is available or not ...
  646. // initialize the security authenication information ... UNICODE VERSION STRUCTURE
  647. if ( ppAuthIdentity == NULL )
  648. {
  649. return WBEM_E_INVALID_PARAMETER;
  650. }
  651. else if ( *ppAuthIdentity == NULL )
  652. {
  653. hr = WbemAllocAuthIdentity( pwszUserArg, pwszPassword, pwszDomainArg, ppAuthIdentity );
  654. if ( hr != S_OK )
  655. {
  656. return hr;
  657. }
  658. }
  659. // set the security information to the interface
  660. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
  661. RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, *ppAuthIdentity, EOAC_NONE );
  662. // return the result
  663. return hr;
  664. }
  665. /*********************************************************************************************
  666. Routine Description:
  667. This function sets the interface security parameters.
  668. Arguments:
  669. [in] IUnknown : pointer to the IUnkown interface
  670. [in] COAUTHIDENTITY : pointer to AUTHIDENTITY structure
  671. Return Value:
  672. HRESULT
  673. *********************************************************************************************/
  674. HRESULT SetInterfaceSecurity( IUnknown* pInterface, COAUTHIDENTITY* pAuthIdentity )
  675. {
  676. // local variables
  677. HRESULT hr;
  678. DWORD dwAuthorization = RPC_C_AUTHZ_NONE;
  679. DWORD dwAuthentication = RPC_C_AUTHN_WINNT;
  680. // check the interface
  681. if ( pInterface == NULL )
  682. {
  683. return WBEM_E_INVALID_PARAMETER;
  684. }
  685. // get the current security argument value
  686. hr = GetSecurityArguments( pInterface, dwAuthorization, dwAuthentication );
  687. if ( FAILED( hr ) )
  688. {
  689. return hr;
  690. }
  691. // set the security information to the interface
  692. hr = SetProxyBlanket( pInterface, dwAuthentication, dwAuthorization, NULL,
  693. RPC_C_AUTHN_LEVEL_PKT_PRIVACY, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthIdentity, EOAC_NONE );
  694. // return the result
  695. return hr;
  696. }
  697. /*********************************************************************************************
  698. Routine Description:
  699. This function sets the authentication information (the security blanket)
  700. that will be used to make calls.
  701. Arguments:
  702. [in] IUnknown : pointer to the IUnkown interface
  703. [in] DWORD : contains the authentication service to use
  704. [in] DWORD : contains the authorization service to use
  705. [in] LPWSTR : the server principal name to use
  706. [in] DWORD : contains the authentication level to use
  707. [in] DWORD : contains the impersonation level to use
  708. [in] RPC_AUTH_IDENTITY_HANDLE : pointer to the identity of the client
  709. [in] DWORD : contains the capability flags
  710. Return Value:
  711. HRESULT
  712. *********************************************************************************************/
  713. HRESULT WINAPI SetProxyBlanket( IUnknown* pInterface,
  714. DWORD dwAuthnSvc, DWORD dwAuthzSvc,
  715. LPWSTR pwszPrincipal, DWORD dwAuthLevel, DWORD dwImpLevel,
  716. RPC_AUTH_IDENTITY_HANDLE pAuthInfo, DWORD dwCapabilities )
  717. {
  718. // local variables
  719. HRESULT hr;
  720. IUnknown * pUnknown = NULL;
  721. IClientSecurity * pClientSecurity = NULL;
  722. // get the IUnknown interface ... to check whether this is a valid interface or not
  723. hr = pInterface->QueryInterface( IID_IUnknown, (void **) &pUnknown );
  724. if ( hr != S_OK )
  725. {
  726. return hr;
  727. }
  728. // now get the client security interface
  729. hr = pInterface->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
  730. if ( hr != S_OK )
  731. {
  732. SAFE_RELEASE( pUnknown );
  733. return hr;
  734. }
  735. //
  736. // Can't set pAuthInfo if cloaking requested, as cloaking implies
  737. // that the current proxy identity in the impersonated thread (rather
  738. // than the credentials supplied explicitly by the RPC_AUTH_IDENTITY_HANDLE)
  739. // is to be used.
  740. // See MSDN info on CoSetProxyBlanket for more details.
  741. //
  742. if ( dwCapabilities & (EOAC_STATIC_CLOAKING | EOAC_DYNAMIC_CLOAKING) )
  743. {
  744. pAuthInfo = NULL;
  745. }
  746. // now set the security
  747. hr = pClientSecurity->SetBlanket( pInterface, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
  748. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
  749. if( FAILED( hr ) )
  750. {
  751. SAFE_RELEASE( pUnknown );
  752. SAFE_RELEASE( pClientSecurity );
  753. return hr;
  754. }
  755. // release the security interface
  756. SAFE_RELEASE( pClientSecurity );
  757. // we should check the auth identity structure. if exists .. set for IUnknown also
  758. if ( pAuthInfo != NULL )
  759. {
  760. hr = pUnknown->QueryInterface( IID_IClientSecurity, (void **) &pClientSecurity );
  761. if ( hr == S_OK )
  762. {
  763. // set security authentication
  764. hr = pClientSecurity->SetBlanket( pUnknown, dwAuthnSvc, dwAuthzSvc, pwszPrincipal,
  765. dwAuthLevel, dwImpLevel, pAuthInfo, dwCapabilities );
  766. // release
  767. SAFE_RELEASE( pClientSecurity );
  768. }
  769. else if ( hr == E_NOINTERFACE )
  770. {
  771. hr = S_OK; // ignore no interface errors
  772. }
  773. }
  774. // release the IUnknown
  775. SAFE_RELEASE( pUnknown );
  776. // return the result
  777. return hr;
  778. }
  779. /*********************************************************************************************
  780. Routine Description:
  781. This function allocates memory for the AUTHIDENTITY structure.
  782. Arguments:
  783. [in] LPCWSTR : string containing the user name
  784. [in] LPCWSTR : string containing the password
  785. [in] LPCWSTR : string containing the domain name
  786. [out] COAUTHIDENTITY : pointer to the pointer to AUTHIDENTITY structure
  787. Return Value:
  788. HRESULT
  789. *********************************************************************************************/
  790. HRESULT WINAPI WbemAllocAuthIdentity( LPCWSTR pwszUser, LPCWSTR pwszPassword,
  791. LPCWSTR pwszDomain, COAUTHIDENTITY** ppAuthIdent )
  792. {
  793. // local variables
  794. COAUTHIDENTITY* pAuthIdent = NULL;
  795. // validate the input parameter
  796. if ( ppAuthIdent == NULL )
  797. {
  798. return WBEM_E_INVALID_PARAMETER;
  799. }
  800. // allocation thru COM API
  801. pAuthIdent = ( COAUTHIDENTITY* ) CoTaskMemAlloc( sizeof( COAUTHIDENTITY ) );
  802. if ( NULL == pAuthIdent )
  803. {
  804. return WBEM_E_OUT_OF_MEMORY;
  805. }
  806. // init with 0's
  807. SecureZeroMemory( ( void* ) pAuthIdent, sizeof( COAUTHIDENTITY ) );
  808. //
  809. // Allocate needed memory and copy in data. Cleanup if anything goes wrong
  810. // user
  811. if ( pwszUser != NULL )
  812. {
  813. // allocate memory for user
  814. LONG lLength = StringLengthW( pwszUser, 0 );
  815. pAuthIdent->User = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  816. if ( pAuthIdent->User == NULL )
  817. {
  818. WbemFreeAuthIdentity( &pAuthIdent );
  819. return WBEM_E_OUT_OF_MEMORY;
  820. }
  821. // set the length and do copy contents
  822. pAuthIdent->UserLength = lLength;
  823. StringCopy( pAuthIdent->User, pwszUser, StringLengthW(pwszUser, 0)+1 );
  824. }
  825. // domain
  826. if ( pwszDomain != NULL )
  827. {
  828. // allocate memory for domain
  829. LONG lLength = StringLengthW( pwszDomain, 0 );
  830. pAuthIdent->Domain = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  831. if ( pAuthIdent->Domain == NULL )
  832. {
  833. WbemFreeAuthIdentity( &pAuthIdent );
  834. return WBEM_E_OUT_OF_MEMORY;
  835. }
  836. // set the length and do copy contents
  837. pAuthIdent->DomainLength = lLength;
  838. StringCopy( pAuthIdent->Domain, pwszDomain, StringLengthW(pwszDomain,0)+1 );
  839. }
  840. // passsord
  841. if ( pwszPassword != NULL )
  842. {
  843. // allocate memory for passsord
  844. LONG lLength = StringLengthW( pwszPassword,0 );
  845. pAuthIdent->Password = ( LPWSTR ) CoTaskMemAlloc( (lLength + 1) * sizeof( WCHAR ) );
  846. if ( pAuthIdent->Password == NULL )
  847. {
  848. WbemFreeAuthIdentity( &pAuthIdent );
  849. return WBEM_E_OUT_OF_MEMORY;
  850. }
  851. // set the length and do copy contents
  852. pAuthIdent->PasswordLength = lLength;
  853. StringCopy( pAuthIdent->Password, pwszPassword, StringLengthW(pwszPassword,0)+1 );
  854. }
  855. // type of the structure
  856. pAuthIdent->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
  857. // final set the address to out parameter
  858. *ppAuthIdent = pAuthIdent;
  859. // return result
  860. return S_OK;
  861. }
  862. /*********************************************************************************************
  863. Routine Description:
  864. This function releases the memory allocated for the AUTHIDENTITY structure.
  865. Arguments:
  866. [in] COAUTHIDENTITY : pointer to the pointer to AUTHIDENTITY structure
  867. Return Value:
  868. None
  869. *********************************************************************************************/
  870. VOID WINAPI WbemFreeAuthIdentity( COAUTHIDENTITY** ppAuthIdentity )
  871. {
  872. // make sure we have a pointer, then walk the structure members and cleanup.
  873. if ( *ppAuthIdentity != NULL )
  874. {
  875. // free the memory allocated for user
  876. if ( (*ppAuthIdentity)->User != NULL )
  877. {
  878. CoTaskMemFree( (*ppAuthIdentity)->User );
  879. }
  880. // free the memory allocated for password
  881. if ( (*ppAuthIdentity)->Password != NULL )
  882. {
  883. CoTaskMemFree( (*ppAuthIdentity)->Password );
  884. }
  885. // free the memory allocated for domain
  886. if ( (*ppAuthIdentity)->Domain != NULL )
  887. {
  888. CoTaskMemFree( (*ppAuthIdentity)->Domain );
  889. }
  890. // final the structure
  891. CoTaskMemFree( *ppAuthIdentity );
  892. }
  893. // set to NULL
  894. *ppAuthIdentity = NULL;
  895. }
  896. /*********************************************************************************************
  897. Routine Description:
  898. This function saves the description of the last error returned by WMI
  899. Arguments:
  900. HRESULT : The last return value from WMI
  901. Return Value:
  902. NONE
  903. *********************************************************************************************/
  904. VOID WMISaveError( HRESULT hrError )
  905. {
  906. // local variables
  907. HRESULT hr;
  908. CHString strBuffer = NULL_STRING;
  909. IWbemStatusCodeText* pWbemStatus = NULL;
  910. // if the error is win32 based, choose FormatMessage to get the message
  911. switch( hrError )
  912. {
  913. case E_ACCESSDENIED: // Message: "Access Denied"
  914. case ERROR_NO_SUCH_USER: // Message: "The specified user does not exist."
  915. {
  916. // change the error message to "Logon failure: unknown user name or bad password."
  917. if ( hrError == E_ACCESSDENIED )
  918. {
  919. hrError = ERROR_LOGON_FAILURE;
  920. }
  921. // ...
  922. SetLastError( hrError );
  923. SaveLastError();
  924. return;
  925. }
  926. }
  927. try
  928. {
  929. // get the pointer to buffer
  930. LPWSTR pwszBuffer = NULL;
  931. pwszBuffer = strBuffer.GetBufferSetLength( MAX_STRING_LENGTH );
  932. //set the reason to incompatible os when no class is registered on remote mechine
  933. if( 0x80040154 == hrError )
  934. {
  935. StringCopy( pwszBuffer, GetResString(IDS_ERROR_REMOTE_INCOMPATIBLE), MAX_STRING_LENGTH );
  936. SetReason( strBuffer );
  937. return;
  938. }
  939. else
  940. {
  941. // get the wbem specific status code text
  942. hr = CoCreateInstance( CLSID_WbemStatusCodeText,
  943. NULL, CLSCTX_INPROC_SERVER, IID_IWbemStatusCodeText, (LPVOID*) &pWbemStatus );
  944. // check whether we got the interface or not
  945. if ( SUCCEEDED( hr ) )
  946. {
  947. // get the error message
  948. BSTR bstr = NULL;
  949. hr = pWbemStatus->GetErrorCodeText( hrError, 0, 0, &bstr );
  950. if ( SUCCEEDED( hr ) )
  951. {
  952. // get the error message in proper format
  953. GetCompatibleStringFromUnicode( bstr, pwszBuffer, MAX_STRING_LENGTH );
  954. // free the BSTR
  955. SysFreeString( bstr );
  956. bstr = NULL;
  957. // now release status code interface
  958. SAFE_RELEASE( pWbemStatus );
  959. }
  960. else
  961. {
  962. // failed to get the error message ... get the com specific error message
  963. _com_issue_error( hrError );
  964. }
  965. }
  966. else
  967. {
  968. // failed to get the error message ... get the com specific error message
  969. _com_issue_error( hrError );
  970. }
  971. }
  972. // release the buffer
  973. strBuffer.ReleaseBuffer();
  974. }
  975. catch( _com_error& e )
  976. {
  977. try
  978. {
  979. // get the error message
  980. strBuffer.ReleaseBuffer();
  981. if ( e.ErrorMessage() != NULL )
  982. strBuffer = e.ErrorMessage();
  983. }
  984. catch( ... )
  985. {
  986. SetLastError((DWORD) E_OUTOFMEMORY );
  987. SaveLastError();
  988. }
  989. }
  990. catch( ... )
  991. {
  992. SetLastError((DWORD) E_OUTOFMEMORY );
  993. SaveLastError();
  994. return;
  995. }
  996. // set the reason
  997. strBuffer += L"\n";
  998. SetReason( strBuffer );
  999. }
  1000. /*********************************************************************************************
  1001. Routine Description:
  1002. Gets the value of the property from the WMI class object
  1003. Arguments:
  1004. [in] IWbemClassObject : pointer to the WBEM class object
  1005. [in] LPCWSTR : property name
  1006. [out] _variant_t : value of the property
  1007. Return Value:
  1008. HRESULT
  1009. *********************************************************************************************/
  1010. HRESULT PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, _variant_t& varValue )
  1011. {
  1012. // local variables
  1013. HRESULT hr;
  1014. VARIANT vtValue;
  1015. // check with object and property passed to the function are valid or not
  1016. // if not, return failure
  1017. if ( pWmiObject == NULL || pwszProperty == NULL )
  1018. {
  1019. return WBEM_E_INVALID_PARAMETER;
  1020. }
  1021. try
  1022. {
  1023. // initialize the variant and then get the value of the specified property
  1024. VariantInit( &vtValue );
  1025. hr = pWmiObject->Get( _bstr_t( pwszProperty ), 0, &vtValue, NULL, NULL );
  1026. if ( FAILED( hr ) )
  1027. {
  1028. // clear the variant variable
  1029. VariantClear( &vtValue );
  1030. // failed to get the value for the property
  1031. return hr;
  1032. }
  1033. // set the value
  1034. varValue = vtValue;
  1035. // clear the variant variable
  1036. VariantClear( &vtValue );
  1037. }
  1038. catch( _com_error& e )
  1039. {
  1040. WMISaveError( e );
  1041. return e.Error();
  1042. }
  1043. // inform success
  1044. return S_OK;
  1045. }
  1046. /*********************************************************************************************
  1047. Routine Description:
  1048. Gets the value of the property from the WMI class object in string format
  1049. Arguments:
  1050. [in] IWbemClassObject : pointer to the WBEM class object
  1051. [in] LPCWSTR : the name of the property to retrieve
  1052. [out] CHString : variable to hold the retrieved property
  1053. [in] LPCWSTR : string containing the default value for the property
  1054. Return Value:
  1055. TRUE on success
  1056. FALSE on failure
  1057. *********************************************************************************************/
  1058. BOOL PropertyGet( IWbemClassObject* pWmiObject,
  1059. LPCWSTR pwszProperty, CHString& strValue, LPCWSTR pwszDefault )
  1060. {
  1061. // local variables
  1062. HRESULT hr;
  1063. _variant_t var;
  1064. // first copy the default value
  1065. strValue = pwszDefault;
  1066. // check with object and property passed to the function are valid or not
  1067. // if not, return failure
  1068. if ( pWmiObject == NULL || pwszProperty == NULL )
  1069. {
  1070. return FALSE;
  1071. }
  1072. // get the property value
  1073. hr = PropertyGet( pWmiObject, pwszProperty, var );
  1074. if ( FAILED( hr ) )
  1075. {
  1076. return FALSE;
  1077. }
  1078. try
  1079. {
  1080. // get the value
  1081. if ( var.vt != VT_NULL && var.vt != VT_EMPTY )
  1082. {
  1083. strValue = (LPCWSTR) _bstr_t( var );
  1084. }
  1085. }
  1086. catch( ... )
  1087. {
  1088. SetLastError((DWORD) E_OUTOFMEMORY );
  1089. SaveLastError();
  1090. return FALSE;
  1091. }
  1092. // return
  1093. return TRUE;
  1094. }
  1095. /*********************************************************************************************
  1096. Routine Description:
  1097. Gets the value of the property from the WMI class object in dword format
  1098. Arguments:
  1099. [in] IWbemClassObject : pointer to the WBEM class object
  1100. [in] LPCWSTR : the name of the property to retrieve
  1101. [out] DWORD : variable to hold the retrieved property
  1102. [in] DWORD : dword containing the default value for the property
  1103. Return Value:
  1104. TRUE on success
  1105. FALSE on failure
  1106. *********************************************************************************************/
  1107. BOOL PropertyGet( IWbemClassObject* pWmiObject,
  1108. LPCWSTR pwszProperty, DWORD& dwValue, DWORD dwDefault )
  1109. {
  1110. // local variables
  1111. HRESULT hr;
  1112. _variant_t var;
  1113. // first set the defaul value
  1114. dwValue = dwDefault;
  1115. // check with object and property passed to the function are valid or not
  1116. // if not, return failure
  1117. if ( pWmiObject == NULL || pwszProperty == NULL )
  1118. {
  1119. return FALSE;
  1120. }
  1121. // get the value of the property
  1122. hr = PropertyGet( pWmiObject, pwszProperty, var );
  1123. if ( FAILED( hr ) )
  1124. {
  1125. return FALSE;
  1126. }
  1127. // get the process id from the variant
  1128. if ( var.vt != VT_NULL && var.vt != VT_EMPTY )
  1129. {
  1130. dwValue = (LONG) var;
  1131. }
  1132. // return
  1133. return TRUE;
  1134. }
  1135. /*********************************************************************************************
  1136. Routine Description:
  1137. Gets the value of the property from the WMI class object in bool format
  1138. Arguments:
  1139. [in] IWbemClassObject : pointer to the WBEM class object
  1140. [in] LPCWSTR : the name of the property to retrieve
  1141. [out] BOOL : variable to hold the retrieved property
  1142. [in] BOOL : bool containing the default value for the property
  1143. Return Value:
  1144. TRUE on success
  1145. FALSE on failure
  1146. *********************************************************************************************/
  1147. BOOL PropertyGet( IWbemClassObject* pWmiObject,
  1148. LPCWSTR pwszProperty, BOOL& bValue, BOOL bDefault )
  1149. {
  1150. // local variables
  1151. HRESULT hr;
  1152. _variant_t var;
  1153. // first set the default value
  1154. bValue = bDefault;
  1155. // check with object and property passed to the function are valid or not
  1156. // if not, return failure
  1157. if ( pWmiObject == NULL || pwszProperty == NULL )
  1158. {
  1159. return FALSE;
  1160. }
  1161. // get the value of the property
  1162. hr = PropertyGet( pWmiObject, pwszProperty, var );
  1163. if ( FAILED( hr ) )
  1164. {
  1165. return FALSE;
  1166. }
  1167. // get the process id from the variant
  1168. if ( var.vt != VT_NULL && var.vt != VT_EMPTY )
  1169. {
  1170. bValue = var.boolVal;
  1171. }
  1172. // return
  1173. return TRUE;
  1174. }
  1175. /*********************************************************************************************
  1176. Routine Description:
  1177. Gets the value of the property from the WMI class object in ulongulong format
  1178. Arguments:
  1179. [in] IWbemClassObject : pointer to the WBEM class object
  1180. [in] LPCWSTR : the name of the property to retrieve
  1181. [out] ULONGULONG : variable to hold the retrieved property
  1182. Return Value:
  1183. TRUE on success
  1184. FALSE on failure
  1185. *********************************************************************************************/
  1186. BOOL PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, ULONGLONG& ullValue )
  1187. {
  1188. // local variables
  1189. CHString str;
  1190. // first set the default value
  1191. ullValue = 1;
  1192. // check with object and property passed to the function are valid or not
  1193. // if not, return failure
  1194. if ( pWmiObject == NULL || pwszProperty == NULL )
  1195. {
  1196. return FALSE;
  1197. }
  1198. // get the value of the property
  1199. if ( PropertyGet( pWmiObject, pwszProperty, str, _T( "0" ) ) == FALSE )
  1200. {
  1201. return FALSE;
  1202. }
  1203. // get the 64-bit value
  1204. ullValue = _wtoi64( str );
  1205. // return
  1206. return TRUE;
  1207. }
  1208. /*********************************************************************************************
  1209. Routine Description:
  1210. Gets the value of the property from the WMI class object in wbemtime format
  1211. Arguments:
  1212. [in] IWbemClassObject : pointer to the WBEM class object
  1213. [in] LPCWSTR : the name of the property to retrieve
  1214. [out] WBEMTime : variable to hold the retrieved property
  1215. Return Value:
  1216. TRUE on success
  1217. FALSE on failure
  1218. *********************************************************************************************/
  1219. BOOL PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, WBEMTime& wbemtime )
  1220. {
  1221. // local variables
  1222. CHString str;
  1223. // Clear method sets the time in the WBEMTime object to an invalid time.
  1224. wbemtime.Clear();
  1225. // check with object and property passed to the function are valid or not
  1226. // if not, return failure
  1227. if ( pWmiObject == NULL || pwszProperty == NULL )
  1228. {
  1229. return FALSE;
  1230. }
  1231. // get the value of the property
  1232. if ( PropertyGet( pWmiObject, pwszProperty, str, _T( "0" ) ) == FALSE )
  1233. {
  1234. return FALSE;
  1235. }
  1236. try
  1237. {
  1238. // convert into the time value
  1239. wbemtime = _bstr_t( str );
  1240. }
  1241. catch( _com_error& e )
  1242. {
  1243. WMISaveError( e );
  1244. return FALSE;
  1245. }
  1246. // return
  1247. return TRUE;
  1248. }
  1249. /*********************************************************************************************
  1250. Routine Description:
  1251. Gets the value of the property from the WMI class object in systemtime format
  1252. Arguments:
  1253. [in] IWbemClassObject : pointer to the WBEM class object
  1254. [in] LPCWSTR : the name of the property to retrieve
  1255. [out] WBEMTime : variable to hold the retrieved property
  1256. Return Value:
  1257. TRUE on success
  1258. FALSE on failure
  1259. *********************************************************************************************/
  1260. BOOL PropertyGet( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, SYSTEMTIME& systime )
  1261. {
  1262. // local variables
  1263. CHString strTime;
  1264. // check with object and property passed to the function are valid or not
  1265. // if not, return failure
  1266. if ( pWmiObject == NULL || pwszProperty == NULL )
  1267. {
  1268. return FALSE;
  1269. }
  1270. // get the value of the property
  1271. // 16010101000000.000000+000 is the default time
  1272. if ( PropertyGet( pWmiObject, pwszProperty, strTime, _T( "16010101000000.000000+000" ) ) == FALSE )
  1273. {
  1274. return FALSE;
  1275. }
  1276. // prepare the systemtime structure
  1277. // yyyymmddHHMMSS.mmmmmmsUUU
  1278. systime.wYear = (WORD) AsLong( strTime.Left( 4 ), 10 );
  1279. systime.wMonth = (WORD) AsLong( strTime.Mid( 4, 2 ), 10 );
  1280. systime.wDayOfWeek = 0;
  1281. systime.wDay = (WORD) AsLong( strTime.Mid( 6, 2 ), 10 );
  1282. systime.wHour = (WORD) AsLong( strTime.Mid( 8, 2 ), 10 );
  1283. systime.wMinute = (WORD) AsLong( strTime.Mid( 10, 2 ), 10 );
  1284. systime.wSecond = (WORD) AsLong( strTime.Mid( 12, 2 ), 10 );
  1285. systime.wMilliseconds = (WORD) AsLong( strTime.Mid( 15, 6 ), 10 );
  1286. // return
  1287. return TRUE;
  1288. }
  1289. /*********************************************************************************************
  1290. Routine Description:
  1291. Sets the value of the property to the WMI class object
  1292. Arguments:
  1293. [in] IWbemClassObject : pointer to the WBEM class object
  1294. [in] LPCWSTR : the name of the property to retrieve
  1295. [in] WBEMTime : variable holding the property to set
  1296. Return Value:
  1297. TRUE on success
  1298. FALSE on failure
  1299. *********************************************************************************************/
  1300. HRESULT PropertyPut( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, _variant_t& varValue )
  1301. {
  1302. // local variables
  1303. HRESULT hr;
  1304. VARIANT var;
  1305. // check the input value
  1306. if ( pWmiObject == NULL || pwszProperty == NULL )
  1307. {
  1308. return WBEM_E_INVALID_PARAMETER;
  1309. }
  1310. try
  1311. {
  1312. // put the value
  1313. var = varValue;
  1314. hr = pWmiObject->Put( _bstr_t( pwszProperty ), 0, &var, 0 );
  1315. }
  1316. catch( _com_error& e )
  1317. {
  1318. WMISaveError( e );
  1319. hr = e.Error();
  1320. }
  1321. // return the result
  1322. return hr;
  1323. }
  1324. /*********************************************************************************************
  1325. Routine Description:
  1326. Sets the string value of the property to the WMI class object
  1327. Arguments:
  1328. [in] IWbemClassObject : pointer to the WBEM class object
  1329. [in] LPCWSTR : the name of the property to retrieve
  1330. [in] LPCWSTR : variable holding the property to set
  1331. Return Value:
  1332. TRUE on success
  1333. FALSE on failure
  1334. *********************************************************************************************/
  1335. HRESULT PropertyPut( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, LPCWSTR pwszValue )
  1336. {
  1337. // local variables
  1338. HRESULT hr = S_OK;
  1339. _variant_t varValue;
  1340. // check the input value
  1341. if ( pWmiObject == NULL || pwszProperty == NULL || pwszValue == NULL )
  1342. {
  1343. return WBEM_E_INVALID_PARAMETER;
  1344. }
  1345. try
  1346. {
  1347. varValue = pwszValue;
  1348. PropertyPut( pWmiObject, pwszProperty, varValue );
  1349. }
  1350. catch( _com_error& e )
  1351. {
  1352. WMISaveError( e );
  1353. hr = e.Error();
  1354. }
  1355. // return
  1356. return hr;
  1357. }
  1358. /*********************************************************************************************
  1359. Routine Description:
  1360. Sets the dword value of the property to the WMI class object
  1361. Arguments:
  1362. [in] IWbemClassObject : pointer to the WBEM class object
  1363. [in] LPCWSTR : the name of the property to retrieve
  1364. [in] DWORD : variable holding the property to set
  1365. Return Value:
  1366. TRUE on success
  1367. FALSE on failure
  1368. *********************************************************************************************/
  1369. HRESULT PropertyPut( IWbemClassObject* pWmiObject, LPCWSTR pwszProperty, DWORD dwValue )
  1370. {
  1371. // local variables
  1372. HRESULT hr=S_OK;
  1373. _variant_t varValue;
  1374. // check the input value
  1375. if ( pWmiObject == NULL || pwszProperty == NULL )
  1376. {
  1377. return WBEM_E_INVALID_PARAMETER;
  1378. }
  1379. try
  1380. {
  1381. varValue = ( LONG ) dwValue;
  1382. PropertyPut( pWmiObject, pwszProperty, varValue );
  1383. }
  1384. catch( _com_error& e )
  1385. {
  1386. WMISaveError( e );
  1387. hr = e.Error();
  1388. }
  1389. // return
  1390. return hr;
  1391. }
  1392. /*********************************************************************************************
  1393. Routine Description:
  1394. This function retrieves the value of the property from the specified registry key.
  1395. Arguments:
  1396. [in] IWbemServices : pointer to the IWbemServices object
  1397. [in] LPCWSTR : the name of the method to execute
  1398. [in] DWORD : the key in the registry whose value has to be retrieved
  1399. [in] LPCWSTR : the name of the subkey to retrieve
  1400. [in] LPCWSTR : the name of the value to retrieve
  1401. [in] _variant_t : variable holding the property value retrieved
  1402. Return Value:
  1403. TRUE on success
  1404. FALSE on failure
  1405. *********************************************************************************************/
  1406. HRESULT RegQueryValueWMI( IWbemServices* pWbemServices,
  1407. LPCWSTR pwszMethod, DWORD dwHDefKey,
  1408. LPCWSTR pwszSubKeyName, LPCWSTR pwszValueName, _variant_t& varValue )
  1409. {
  1410. // local variables
  1411. HRESULT hr;
  1412. BOOL bResult = FALSE;
  1413. DWORD dwReturnValue = 0;
  1414. IWbemClassObject* pClass = NULL;
  1415. IWbemClassObject* pMethod = NULL;
  1416. IWbemClassObject* pInParams = NULL;
  1417. IWbemClassObject* pInParamsInstance = NULL;
  1418. IWbemClassObject* pOutParamsInstance = NULL;
  1419. // check the input value
  1420. if (pWbemServices == NULL || pwszMethod == NULL || pwszSubKeyName == NULL || pwszValueName == NULL)
  1421. {
  1422. return WBEM_E_INVALID_PARAMETER;
  1423. }
  1424. try
  1425. {
  1426. // get the registry class object
  1427. SAFE_EXECUTE( pWbemServices->GetObject(
  1428. _bstr_t( WMI_REGISTRY ), WBEM_FLAG_RETURN_WBEM_COMPLETE, NULL, &pClass, NULL ) );
  1429. if ( pClass == NULL ) // check the object .. safety sake
  1430. {
  1431. _com_issue_error( STG_E_UNKNOWN );
  1432. }
  1433. // get the method reference required
  1434. SAFE_EXECUTE( pClass->GetMethod( pwszMethod, 0, &pInParams, NULL ) );
  1435. if ( pInParams == NULL ) // check the object .. safety sake
  1436. {
  1437. _com_issue_error( STG_E_UNKNOWN );
  1438. }
  1439. // create the instance for the in parameters
  1440. SAFE_EXECUTE( pInParams->SpawnInstance( 0, &pInParamsInstance ) );
  1441. if ( pInParamsInstance == NULL )
  1442. {
  1443. _com_issue_error( STG_E_UNKNOWN );
  1444. }
  1445. // set the input values
  1446. PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_HDEFKEY ), dwHDefKey );
  1447. PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_SUBKEY ), pwszSubKeyName );
  1448. PropertyPut( pInParamsInstance, _bstr_t( WMI_REGISTRY_IN_VALUENAME ), pwszValueName );
  1449. // now execute the method
  1450. SAFE_EXECUTE( pWbemServices->ExecMethod( _bstr_t( WMI_REGISTRY ),
  1451. _bstr_t( pwszMethod ), 0, NULL, pInParamsInstance, &pOutParamsInstance, NULL ) );
  1452. if ( pOutParamsInstance == NULL ) // check the object .. safety sake
  1453. {
  1454. _com_issue_error( STG_E_UNKNOWN );
  1455. }
  1456. // now check the return value of the method from the output params object
  1457. bResult = PropertyGet( pOutParamsInstance,
  1458. _bstr_t( WMI_REGISTRY_OUT_RETURNVALUE ), dwReturnValue );
  1459. if ( bResult == FALSE || dwReturnValue != 0 )
  1460. {
  1461. _com_issue_error( STG_E_UNKNOWN );
  1462. }
  1463. // now everything is sucess .. get the required value
  1464. if ( StringCompare( pwszMethod, WMI_REGISTRY_M_DWORDVALUE, TRUE, 0 ) == 0 )
  1465. {
  1466. PropertyGet( pOutParamsInstance, _bstr_t( WMI_REGISTRY_OUT_VALUE_DWORD ), varValue );
  1467. }
  1468. else
  1469. {
  1470. PropertyGet( pOutParamsInstance, _bstr_t( WMI_REGISTRY_OUT_VALUE ), varValue );
  1471. }
  1472. }
  1473. catch( _com_error& e )
  1474. {
  1475. WMISaveError( e );
  1476. return e.Error();
  1477. }
  1478. // release the interfaces
  1479. SAFE_RELEASE( pClass );
  1480. SAFE_RELEASE( pMethod );
  1481. SAFE_RELEASE( pInParams );
  1482. SAFE_RELEASE( pInParamsInstance );
  1483. SAFE_RELEASE( pOutParamsInstance );
  1484. // return success
  1485. return S_OK;
  1486. }
  1487. /*********************************************************************************************
  1488. Routine Description:
  1489. This function retrieves the string value of the property from the specified registry key.
  1490. Arguments:
  1491. [in] IWbemServices : pointer to the IWbemServices object
  1492. [in] DWORD : the key in the registry whose value has to be retrieved
  1493. [in] LPCWSTR : the name of the subkey to retrieve
  1494. [in] LPCWSTR : the name of the value to retrieve
  1495. [out] CHString : variable holding the property value retrieved
  1496. [in] LPCWSTR : the default value for this property
  1497. Return Value:
  1498. TRUE on success
  1499. FALSE on failure
  1500. *********************************************************************************************/
  1501. BOOL RegQueryValueWMI( IWbemServices* pWbemServices,
  1502. DWORD dwHDefKey, LPCWSTR pwszSubKeyName,
  1503. LPCWSTR pwszValueName, CHString& strValue, LPCWSTR pwszDefault )
  1504. {
  1505. // local variables
  1506. HRESULT hr;
  1507. _variant_t varValue;
  1508. try
  1509. {
  1510. // set the default value
  1511. if ( pwszDefault != NULL )
  1512. {
  1513. strValue = pwszDefault;
  1514. }
  1515. // check the input
  1516. if ( pWbemServices == NULL || pwszSubKeyName == NULL || pwszValueName == NULL )
  1517. {
  1518. return FALSE;
  1519. }
  1520. // get the value
  1521. hr = RegQueryValueWMI( pWbemServices,
  1522. WMI_REGISTRY_M_STRINGVALUE, dwHDefKey, pwszSubKeyName, pwszValueName, varValue );
  1523. if ( FAILED( hr ) )
  1524. {
  1525. return FALSE;
  1526. }
  1527. // get the value from the variant
  1528. // get the value
  1529. if ( varValue.vt != VT_NULL && varValue.vt != VT_EMPTY )
  1530. {
  1531. strValue = (LPCWSTR) _bstr_t( varValue );
  1532. }
  1533. }
  1534. catch( ... )
  1535. {
  1536. SetLastError((DWORD) E_OUTOFMEMORY );
  1537. SaveLastError();
  1538. return FALSE;
  1539. }
  1540. // return success
  1541. return TRUE;
  1542. }
  1543. /*********************************************************************************************
  1544. Routine Description:
  1545. This function retrieves the dword value of the property from the specified registry key.
  1546. Arguments:
  1547. [in] IWbemServices : pointer to the IWbemServices object
  1548. [in] DWORD : the key in the registry whose value has to be retrieved
  1549. [in] LPCWSTR : the name of the subkey to retrieve
  1550. [in] LPCWSTR : the name of the value to retrieve
  1551. [out] DWORD : variable holding the property value retrieved
  1552. [in] DWORD : the default value for this property
  1553. Return Value:
  1554. TRUE on success
  1555. FALSE on failure
  1556. *********************************************************************************************/
  1557. BOOL RegQueryValueWMI( IWbemServices* pWbemServices,
  1558. DWORD dwHDefKey, LPCWSTR pwszSubKeyName,
  1559. LPCWSTR pwszValueName, DWORD& dwValue, DWORD dwDefault )
  1560. {
  1561. // local variables
  1562. HRESULT hr;
  1563. _variant_t varValue;
  1564. try
  1565. {
  1566. // set the default value
  1567. dwValue = dwDefault;
  1568. // check the input
  1569. if ( pWbemServices == NULL || pwszSubKeyName == NULL || pwszValueName == NULL )
  1570. {
  1571. return FALSE;
  1572. }
  1573. // get the value
  1574. hr = RegQueryValueWMI( pWbemServices, WMI_REGISTRY_M_DWORDVALUE, dwHDefKey,
  1575. pwszSubKeyName, pwszValueName, varValue );
  1576. if ( FAILED( hr ) )
  1577. {
  1578. return FALSE;
  1579. }
  1580. // get the value from the variant
  1581. // get the value
  1582. if ( varValue.vt != VT_NULL && varValue.vt != VT_EMPTY )
  1583. {
  1584. dwValue = (LONG) varValue;
  1585. }
  1586. }
  1587. catch( ... )
  1588. {
  1589. SetLastError((DWORD) E_OUTOFMEMORY );
  1590. SaveLastError();
  1591. return FALSE;
  1592. }
  1593. // return success
  1594. return TRUE;
  1595. }
  1596. /*********************************************************************************************
  1597. Routine Description:
  1598. This function gets the version of the system from which we are trying to retrieve
  1599. information from.
  1600. Arguments:
  1601. [in] IWbemServices : pointer to the IWbemServices object
  1602. [in] COAUTHIDENTITY : pointer to the pointer to AUTHIDENTITY structure
  1603. Return Value:
  1604. DWORD - Target version of the machine
  1605. *********************************************************************************************/
  1606. DWORD GetTargetVersionEx( IWbemServices* pWbemServices, COAUTHIDENTITY* pAuthIdentity )
  1607. {
  1608. // local variables
  1609. HRESULT hr;
  1610. LONG lPos = 0;
  1611. DWORD dwMajor = 0;
  1612. DWORD dwMinor = 0;
  1613. DWORD dwVersion = 0;
  1614. ULONG ulReturned = 0;
  1615. CHString strVersion;
  1616. IWbemClassObject* pWbemObject = NULL;
  1617. IEnumWbemClassObject* pWbemInstances = NULL;
  1618. // check the input value
  1619. if ( pWbemServices == NULL )
  1620. {
  1621. return 0;
  1622. }
  1623. try
  1624. {
  1625. // get the OS information
  1626. SAFE_EXECUTE( pWbemServices->CreateInstanceEnum(
  1627. _bstr_t( CLASS_CIMV2_Win32_OperatingSystem ), 0, NULL, &pWbemInstances ) );
  1628. // set the security on the enumerated object
  1629. SAFE_EXECUTE( SetInterfaceSecurity( pWbemInstances, pAuthIdentity ) );
  1630. // get the enumerated objects information
  1631. // NOTE: This needs to be traversed only one time.
  1632. SAFE_EXECUTE( pWbemInstances->Next( WBEM_INFINITE, 1, &pWbemObject, &ulReturned ) );
  1633. // to be on safer side ... check the count of objects returned
  1634. if ( ulReturned == 0 )
  1635. {
  1636. // release the interfaces
  1637. SAFE_RELEASE( pWbemObject );
  1638. SAFE_RELEASE( pWbemInstances );
  1639. return 0;
  1640. }
  1641. // now get the os version value
  1642. if ( PropertyGet( pWbemObject, L"Version", strVersion ) == FALSE )
  1643. {
  1644. // release the interfaces
  1645. SAFE_RELEASE( pWbemObject );
  1646. SAFE_RELEASE( pWbemInstances );
  1647. return 0;
  1648. }
  1649. // release the interfaces .. we dont need them furthur
  1650. SAFE_RELEASE( pWbemObject );
  1651. SAFE_RELEASE( pWbemInstances );
  1652. //
  1653. // now determine the os version
  1654. dwMajor = dwMinor = 0;
  1655. // get the major version
  1656. lPos = strVersion.Find( L'.' );
  1657. if ( lPos == -1 )
  1658. {
  1659. // the version string itself is version ... THIS WILL NEVER HAPPEN
  1660. dwMajor = AsLong( strVersion, 10 );
  1661. }
  1662. else
  1663. {
  1664. // major version
  1665. dwMajor = AsLong( strVersion.Mid( 0, lPos ), 10 );
  1666. // get the minor version
  1667. strVersion = strVersion.Mid( lPos + 1 );
  1668. lPos = strVersion.Find( L'.' );
  1669. if ( lPos == -1 )
  1670. {
  1671. dwMinor = AsLong( strVersion, 10 );
  1672. }
  1673. else
  1674. {
  1675. dwMinor = AsLong( strVersion.Mid( 0, lPos ), 10 );
  1676. }
  1677. }
  1678. // mix the version info
  1679. dwVersion = dwMajor * 1000 + dwMinor;
  1680. }
  1681. catch( _com_error& e )
  1682. {
  1683. WMISaveError( e );
  1684. return 0;
  1685. }
  1686. // return
  1687. return dwVersion;
  1688. }
  1689. /*********************************************************************************************
  1690. Routine Description:
  1691. This function retrieves a property from the safe array.
  1692. Arguments:
  1693. [in] SAFEARRAY : pointer to the array of elements
  1694. [in] LONG : index to retrieve the data from
  1695. [out] CHString : variable to hold the return value
  1696. [in] VARTYPE : The type of variable to retrieve from the array
  1697. Return Value:
  1698. TRUE on success
  1699. FALSE on failure
  1700. *********************************************************************************************/
  1701. BOOL GetPropertyFromSafeArray( SAFEARRAY *pSafeArray, LONG lIndex, CHString& strValue,
  1702. VARTYPE vartype )
  1703. {
  1704. // check the inputs
  1705. if ( pSafeArray == NULL )
  1706. {
  1707. return FALSE;
  1708. }
  1709. try
  1710. {
  1711. // sub-local variables
  1712. VARIANT var;
  1713. // get the value
  1714. V_VT( &var ) = vartype;
  1715. SafeArrayGetElement( pSafeArray, &lIndex, &V_UI1( &var ) );
  1716. // add the information to the dynamic array
  1717. switch( vartype )
  1718. {
  1719. case VT_BSTR:
  1720. strValue = V_BSTR( &var );
  1721. break;
  1722. default:
  1723. return FALSE;
  1724. }
  1725. }
  1726. catch( ... )
  1727. {
  1728. return FALSE; // failure
  1729. }
  1730. // return
  1731. return TRUE;
  1732. }
  1733. /*********************************************************************************************
  1734. Routine Description:
  1735. This function retrieves a property from the safe array.
  1736. Arguments:
  1737. [in] SAFEARRAY : pointer to the array of elements
  1738. [in] LONG : index to retrieve the data from
  1739. [out] IWbemClassObject : variable to hold the return value
  1740. [in] VARTYPE : The type of variable to retrieve from the array
  1741. Return Value:
  1742. TRUE on success
  1743. FALSE on failure
  1744. *********************************************************************************************/
  1745. BOOL GetPropertyFromSafeArray( SAFEARRAY *pSafeArray, LONG lIndex,
  1746. IWbemClassObject **pScriptObject, VARTYPE vartype )
  1747. {
  1748. // check the inputs
  1749. if ( pSafeArray == NULL )
  1750. {
  1751. return FALSE;
  1752. }
  1753. try
  1754. {
  1755. // sub-local variables
  1756. VARIANT var;
  1757. // get the value
  1758. V_VT( &var ) = vartype;
  1759. SafeArrayGetElement( pSafeArray, &lIndex, &V_UI1( &var ) );
  1760. // add the information to the dynamic array
  1761. switch( vartype )
  1762. {
  1763. case VT_UNKNOWN:
  1764. *pScriptObject = (IWbemClassObject *) var.punkVal;
  1765. break;
  1766. default:
  1767. return FALSE;
  1768. }
  1769. }
  1770. catch( ... )
  1771. {
  1772. return FALSE; // failure
  1773. }
  1774. // return
  1775. return TRUE;
  1776. }