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.

1718 lines
46 KiB

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