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.

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