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.

1668 lines
45 KiB

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