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.

734 lines
19 KiB

  1. #include "testwmi.h"
  2. //
  3. // The function connects to the namespace.
  4. //
  5. IWbemServices *ConnectToNamespace (VOID)
  6. {
  7. IWbemServices *pIWbemServices = NULL;
  8. IWbemLocator *pIWbemLocator = NULL;
  9. HRESULT hr;
  10. //
  11. // Create an instance of WbemLocator interface.
  12. //
  13. hr = CoCreateInstance( CLSID_WbemLocator,
  14. NULL,
  15. CLSCTX_INPROC_SERVER,
  16. IID_IWbemLocator,
  17. (LPVOID *)&pIWbemLocator );
  18. if ( hr == S_OK ) {
  19. //
  20. // Using the locator, connect to COM in the given namespace.
  21. //
  22. hr = pIWbemLocator->ConnectServer( DEFAULT_NAMESPACE,
  23. NULL, // current account.
  24. NULL, // current password.
  25. 0L, // locale
  26. 0L, // securityFlags
  27. NULL, // domain for NTLM
  28. NULL, // context
  29. &pIWbemServices );
  30. if ( hr == WBEM_S_NO_ERROR) {
  31. //
  32. // Switch the security level to IMPERSONATE so that provider(s)
  33. // will grant access to system-level objects, and so that
  34. // CALL authorization will be used.
  35. //
  36. hr = CoSetProxyBlanket( (IUnknown *)pIWbemServices, // proxy
  37. RPC_C_AUTHN_WINNT, // authentication service
  38. RPC_C_AUTHZ_NONE, // authorization service
  39. NULL, // server principle name
  40. RPC_C_AUTHN_LEVEL_CALL, // authentication level
  41. RPC_C_IMP_LEVEL_IMPERSONATE, // impersonation
  42. NULL, // identity of the client
  43. EOAC_NONE ); // capability flags
  44. if ( hr != S_OK ) {
  45. pIWbemServices->Release();
  46. pIWbemServices = NULL;
  47. PrintError( hr,
  48. __LINE__,
  49. TEXT(__FILE__),
  50. TEXT("Couldn't impersonate, program exiting...") );
  51. }
  52. }
  53. else {
  54. PrintError( hr,
  55. __LINE__,
  56. TEXT(__FILE__),
  57. TEXT("Couldn't connect to root\\wmi, program exiting...") );
  58. }
  59. //
  60. // Done with IWbemLocator.
  61. //
  62. pIWbemLocator->Release();
  63. }
  64. else {
  65. PrintError( hr,
  66. __LINE__,
  67. TEXT(__FILE__),
  68. TEXT("Couldn't create an instance of ")
  69. TEXT("IWbemLocator interface, programm exiting...") );
  70. }
  71. return pIWbemServices;
  72. }
  73. //
  74. // Given a class name, the function populates the combo box with all
  75. // the instances of the class.
  76. //
  77. VOID EnumInstances (IWbemServices *pIWbemServices,
  78. LPTSTR lpszClass,
  79. HWND hwndInstTree)
  80. {
  81. IEnumWbemClassObject *pEnumInst;
  82. IWbemClassObject *pInst;
  83. VARIANT varInstanceName;
  84. BSTR bstrClass;
  85. LPTSTR lpszInstance;
  86. ULONG ulFound;
  87. HRESULT hr;
  88. bstrClass = StringToBstr( lpszClass,
  89. -1 );
  90. if ( !bstrClass ) {
  91. PrintError( HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY),
  92. __LINE__,
  93. TEXT(__FILE__),
  94. TEXT("Not enough memory to enumerate instances of %s"),
  95. lpszClass );
  96. return;
  97. }
  98. hr = pIWbemServices->CreateInstanceEnum(
  99. bstrClass, // Name of the root class.
  100. WBEM_FLAG_SHALLOW | // Enumerate at current root only.
  101. WBEM_FLAG_FORWARD_ONLY, // Forward-only enumeration.
  102. NULL, // Context.
  103. &pEnumInst ); // pointer to class enumerator
  104. if ( hr == WBEM_S_NO_ERROR ) {
  105. //
  106. // Begin enumerating instances.
  107. //
  108. ulFound = 0;
  109. hr = pEnumInst->Next( 2000, // two seconds timeout
  110. 1, // return just one instance.
  111. &pInst, // pointer to instance.
  112. &ulFound); // Number of instances returned.
  113. while ( (hr == WBEM_S_NO_ERROR) && (ulFound == 1) ) {
  114. VariantInit( &varInstanceName );
  115. //
  116. // Get the instance name stored in __RELPATH property.
  117. //
  118. hr = pInst->Get( L"__RELPATH", // property name
  119. 0L, // Reserved, must be zero.
  120. &varInstanceName, // property value returned.
  121. NULL, // CIM type not needed.
  122. NULL ); // Flavor not needed.
  123. if ( hr == WBEM_S_NO_ERROR ) {
  124. lpszInstance = BstrToString( V_BSTR(&varInstanceName),
  125. -1 );
  126. if ( lpszInstance ) {
  127. InsertItem( hwndInstTree,
  128. lpszInstance );
  129. SysFreeString( (BSTR)lpszInstance );
  130. }
  131. else {
  132. hr = HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  133. PrintError( hr,
  134. __LINE__,
  135. TEXT(__FILE__),
  136. TEXT("Out of memory while enumerating instaces of")
  137. TEXT(" %s, no more instances will")
  138. TEXT(" be listed."),
  139. lpszClass );
  140. }
  141. VariantClear( &varInstanceName );
  142. }
  143. else {
  144. PrintError( hr,
  145. __LINE__,
  146. TEXT(__FILE__),
  147. TEXT("Couldn't retrieve __RELPATH of an instance")
  148. TEXT(" of %s, no more instances will be listed."),
  149. lpszClass );
  150. }
  151. //
  152. // Done with this instance.
  153. //
  154. pInst->Release();
  155. if ( hr == WBEM_S_NO_ERROR ) {
  156. hr = pEnumInst->Next( 2000, // two seconds timeout.
  157. 1, // return just one class.
  158. &pInst, // pointer to returned class.
  159. &ulFound); // Number of classes returned.
  160. }
  161. }
  162. pEnumInst->Release();
  163. }
  164. else {
  165. PrintError( hr,
  166. __LINE__,
  167. TEXT(__FILE__),
  168. TEXT("Couldn't create an instance of ")
  169. TEXT("IEnumWbemClassObject interface, instances of %s ")
  170. TEXT("will not be listed."),
  171. lpszClass );
  172. }
  173. SysFreeString( bstrClass );
  174. return;
  175. }
  176. //
  177. // Given a class name and __RELPATH of an instance, the function lists all the
  178. // local non-system properties in a tree list.
  179. //
  180. VOID EnumProperties (IWbemServices *pIWbemServices,
  181. LPTSTR lpszClass,
  182. LPTSTR lpszInstance,
  183. HWND hwndPropTree)
  184. {
  185. IWbemClassObject *pInst;
  186. SAFEARRAY *psaPropNames;
  187. BSTR bstrProperty;
  188. long lLower;
  189. long lUpper;
  190. long i;
  191. HRESULT hr;
  192. LPTSTR lpszProperty;
  193. //
  194. // Get a pointer to the instance.
  195. //
  196. pInst = GetInstanceReference( pIWbemServices,
  197. lpszClass,
  198. lpszInstance );
  199. if ( pInst ) {
  200. //
  201. // psaPropNames must be null prior to making the call.
  202. //
  203. psaPropNames = NULL;
  204. //
  205. // Get all the properties.
  206. //
  207. hr = pInst->GetNames( NULL, // No qualifier names.
  208. WBEM_FLAG_ALWAYS | // All non-system properties
  209. WBEM_FLAG_LOCAL_ONLY,
  210. NULL, // No qualifier values.
  211. &psaPropNames); // Returned property names
  212. if ( hr == WBEM_S_NO_ERROR ) {
  213. //
  214. // Get the number of properties returned.
  215. //
  216. SafeArrayGetLBound( psaPropNames, 1, &lLower );
  217. SafeArrayGetUBound( psaPropNames, 1, &lUpper );
  218. //
  219. // List all properties or stop when encountered an error.
  220. //
  221. for (i=lLower; (hr == WBEM_S_NO_ERROR) && (i <= lUpper); i++) {
  222. //
  223. // Add the property name into the list box.
  224. //
  225. bstrProperty = NULL;
  226. hr = SafeArrayGetElement( psaPropNames,
  227. &i,
  228. &bstrProperty);
  229. if ( SUCCEEDED(hr) ) {
  230. lpszProperty = BstrToString( bstrProperty,
  231. -1 );
  232. if ( lpszProperty ) {
  233. InsertItem( hwndPropTree,
  234. lpszProperty );
  235. SysFreeString( (BSTR)lpszProperty );
  236. }
  237. else {
  238. PrintError( HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY),
  239. __LINE__,
  240. TEXT(__FILE__),
  241. TEXT("Out of memory while enumerating")
  242. TEXT(" properties of %s, no more properties")
  243. TEXT(" will be listed"),
  244. lpszInstance );
  245. }
  246. //
  247. // Done with the property name.
  248. //
  249. SysFreeString( bstrProperty );
  250. }
  251. else {
  252. PrintError( hr,
  253. __LINE__,
  254. TEXT(__FILE__),
  255. TEXT("Couldn't get the name of a property(%d). ")
  256. TEXT("No more properties will be listed."),
  257. i );
  258. }
  259. }
  260. //
  261. // Done with the array of properties.
  262. //
  263. SafeArrayDestroy( psaPropNames );
  264. }
  265. else {
  266. PrintError( hr,
  267. __LINE__,
  268. TEXT(__FILE__),
  269. TEXT("Couldn't retrieve the properties of %s, ")
  270. TEXT("an instance of class %s. Properties will not be ")
  271. TEXT("listed."),
  272. lpszInstance, lpszClass );
  273. }
  274. }
  275. else {
  276. PrintError( HRESULT_FROM_WIN32(ERROR_WMI_INSTANCE_NOT_FOUND),
  277. __LINE__,
  278. TEXT(__FILE__),
  279. TEXT("Couldn't retrieve a pointer to instance %s of class %s.")
  280. TEXT("Its properties will not be listed."),
  281. lpszInstance, lpszClass );
  282. }
  283. return;
  284. }
  285. //
  286. // Given a class name and __RELPATH of an instance, the function returns a
  287. // pointer to the instance.
  288. //
  289. IWbemClassObject *GetInstanceReference (IWbemServices *pIWbemServices,
  290. LPTSTR lpszClass,
  291. LPTSTR lpszInstance)
  292. {
  293. IWbemClassObject *pInst;
  294. IEnumWbemClassObject *pEnumInst;
  295. ULONG ulCount;
  296. BSTR bstrClass;
  297. BOOL bFound;
  298. HRESULT hr;
  299. hr = 0;
  300. bstrClass = StringToBstr( lpszClass,
  301. -1 );
  302. if ( !bstrClass ) {
  303. PrintError( HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY),
  304. __LINE__,
  305. TEXT(__FILE__),
  306. TEXT("Not enough memory to get a pointer to %s."),
  307. lpszInstance );
  308. return NULL;
  309. }
  310. //
  311. // pInst pointer must be NULL initially,
  312. //
  313. pInst = NULL;
  314. //
  315. // Get Instance Enumerator Interface.
  316. //
  317. pEnumInst = NULL;
  318. hr = pIWbemServices->CreateInstanceEnum(bstrClass,
  319. WBEM_FLAG_SHALLOW |
  320. WBEM_FLAG_FORWARD_ONLY,
  321. NULL,
  322. &pEnumInst );
  323. if ( hr == WBEM_S_NO_ERROR ) {
  324. //
  325. // Get a pointer to the instance.
  326. //
  327. // We enumerate all the instances and compare their __RELPATH with
  328. // the specified __RELPATH. If we find a match then, that is the one
  329. // we are looking for.
  330. //
  331. // The other more efficient way is to create a WQL query and execute
  332. // it.
  333. //
  334. hr = WBEM_S_NO_ERROR;
  335. bFound = FALSE;
  336. while ( (hr == WBEM_S_NO_ERROR) && (bFound == FALSE) ) {
  337. hr = pEnumInst->Next( 2000, // two seconds timeout
  338. 1, // return just one instance.
  339. &pInst, // pointer to instance.
  340. &ulCount); // Number of instances returned.
  341. if ( ulCount > 0 ) {
  342. bFound = IsInstance( pInst,
  343. lpszInstance );
  344. if ( bFound == FALSE ) {
  345. pInst->Release();
  346. }
  347. }
  348. }
  349. if ( bFound == FALSE )
  350. pInst = NULL;
  351. //
  352. // Done with the instance enumerator.
  353. //
  354. pEnumInst->Release();
  355. }
  356. SysFreeString( bstrClass );
  357. return pInst;
  358. }
  359. //
  360. // Given a pointer, the function returns TRUE if the pointer points to
  361. // the instance specified by lpszInstance.
  362. //
  363. BOOL IsInstance (IWbemClassObject *pInst,
  364. LPTSTR lpszInstance)
  365. {
  366. VARIANT varPropVal;
  367. LPTSTR lpInstance;
  368. BOOL bRet;
  369. bRet = GetPropertyValue( pInst,
  370. TEXT("__RELPATH"),
  371. &varPropVal,
  372. NULL );
  373. if ( bRet == TRUE ) {
  374. lpInstance = BstrToString( V_BSTR(&varPropVal),
  375. -1 );
  376. if ( !lpInstance ) {
  377. PrintError( HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY),
  378. __LINE__,
  379. TEXT(__FILE__),
  380. TEXT("Not enough memory to search for an instance.") );
  381. bRet = FALSE;
  382. }
  383. else {
  384. bRet = _tcsicmp( lpszInstance, lpInstance ) == 0;
  385. SysFreeString( (BSTR)lpInstance );
  386. }
  387. VariantClear( &varPropVal );
  388. }
  389. return bRet;
  390. }
  391. //
  392. // The function returns property value and its type of a given class/instance.
  393. //
  394. BOOL GetPropertyValue (IWbemClassObject *pRef,
  395. LPTSTR lpszProperty,
  396. VARIANT *pvaPropertyValue,
  397. LPTSTR *lppszPropertyType)
  398. {
  399. IWbemQualifierSet *pQual;
  400. VARIANT vaQual;
  401. BSTR bstrProperty;
  402. HRESULT hr;
  403. BOOL bRet;
  404. //
  405. // Get the property value.
  406. //
  407. bstrProperty = StringToBstr( lpszProperty,
  408. -1 );
  409. if ( !bstrProperty ) {
  410. return FALSE;
  411. }
  412. bRet = FALSE;
  413. if ( lppszPropertyType ) {
  414. //
  415. // Get the textual name of the property type.
  416. //
  417. hr = pRef->GetPropertyQualifierSet( bstrProperty,
  418. &pQual );
  419. if ( hr == WBEM_S_NO_ERROR ) {
  420. //
  421. // Get the textual name of the property type.
  422. //
  423. hr = pQual->Get( L"CIMTYPE",
  424. 0,
  425. &vaQual,
  426. NULL );
  427. if ( hr == WBEM_S_NO_ERROR ) {
  428. *lppszPropertyType = BstrToString( V_BSTR(&vaQual),
  429. -1 );
  430. VariantClear( &vaQual );
  431. }
  432. pQual->Release();
  433. }
  434. }
  435. VariantInit( pvaPropertyValue );
  436. hr = pRef->Get( bstrProperty,
  437. 0,
  438. pvaPropertyValue,
  439. NULL,
  440. NULL );
  441. if ( hr == WBEM_S_NO_ERROR ) {
  442. bRet = TRUE;
  443. }
  444. else {
  445. if ( lppszPropertyType && *lppszPropertyType ) {
  446. SysFreeString( (BSTR)*lppszPropertyType );
  447. }
  448. }
  449. SysFreeString( bstrProperty );
  450. return bRet;
  451. }
  452. //
  453. // Given a pointer to an instance, its property and and variant specifying
  454. // the value for the property, the function updates the property and the
  455. // instance.
  456. //
  457. HRESULT UpdatePropertyValue (IWbemServices *pIWbemServices,
  458. IWbemClassObject *pInstance,
  459. LPTSTR lpszProperty,
  460. LPVARIANT pvaNewValue)
  461. {
  462. BSTR bstrProperty;
  463. HRESULT hr;
  464. bstrProperty = StringToBstr( lpszProperty,
  465. -1 );
  466. if ( !bstrProperty ) {
  467. PrintError( HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY),
  468. __LINE__,
  469. TEXT(__FILE__),
  470. TEXT("Not enough memory to update %s."),
  471. lpszProperty );
  472. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  473. }
  474. hr = pInstance->Put( bstrProperty,
  475. 0,
  476. pvaNewValue,
  477. 0 );
  478. if ( hr == WBEM_S_NO_ERROR ) {
  479. hr = pIWbemServices->PutInstance( pInstance,
  480. WBEM_FLAG_UPDATE_ONLY,
  481. NULL,
  482. NULL );
  483. if ( hr != WBEM_S_NO_ERROR ) {
  484. PrintError( hr,
  485. __LINE__,
  486. TEXT(__FILE__),
  487. TEXT("Failed to save the instance,")
  488. TEXT(" %s will not be updated."),
  489. lpszProperty );
  490. }
  491. }
  492. else {
  493. PrintError( hr,
  494. __LINE__,
  495. TEXT(__FILE__),
  496. TEXT("Couldn't update %s."),
  497. lpszProperty );
  498. }
  499. SysFreeString( bstrProperty );
  500. return hr;
  501. }
  502. BSTR StringToBstr (LPTSTR lpSrc,
  503. int nLenSrc)
  504. {
  505. BSTR lpDest;
  506. //
  507. // In case of ANSI version, we need to change the ANSI string to UNICODE since
  508. // BSTRs are essentially UNICODE strings.
  509. //
  510. #if !defined(UNICODE) || !defined(_UNICODE)
  511. int nLenDest;
  512. nLenDest = MultiByteToWideChar( CP_ACP, 0, lpSrc, nLenSrc, NULL, 0);
  513. lpDest = SysAllocStringLen( NULL, nLenDest );
  514. if ( lpDest ) {
  515. MultiByteToWideChar( CP_ACP, 0, lpSrc, nLenSrc, lpDest, nLenDest );
  516. }
  517. //
  518. // In case of UNICODE version, we simply allocate memory and copy the string.
  519. //
  520. #else
  521. if ( lpSrc == NULL ) {
  522. nLenSrc = 0;
  523. }
  524. else {
  525. if ( nLenSrc == -1 ) {
  526. nLenSrc = _tcslen( lpSrc ) + sizeof(TCHAR);
  527. }
  528. }
  529. lpDest = SysAllocStringLen( lpSrc, nLenSrc );
  530. #endif
  531. return lpDest;
  532. }
  533. //
  534. // The function converts a BSTR string into ANSI and returns it in an allocated
  535. // memory. The memory must be freed by the caller using SysFreeString()
  536. // function. If nLenSrc is -1, the string is null terminated.
  537. //
  538. LPTSTR BstrToString (BSTR lpSrc,
  539. int nLenSrc)
  540. {
  541. LPTSTR lpDest;
  542. //
  543. // In case of ANSI version, we need to change BSTRs which are UNICODE strings
  544. // into ANSI version.
  545. //
  546. #if !defined(UNICODE) || !defined(_UNICODE)
  547. int nLenDest;
  548. nLenDest = WideCharToMultiByte( CP_ACP, 0, lpSrc, nLenSrc, NULL,
  549. 0, NULL, NULL );
  550. lpDest = (LPTSTR)SysAllocStringLen( NULL, (size_t)nLenDest );
  551. if ( lpDest ) {
  552. WideCharToMultiByte( CP_ACP, 0, lpSrc, nLenSrc, lpDest,
  553. nLenDest, NULL, NULL );
  554. }
  555. //
  556. // In case of UNICODE version, we simply allocate memory and copy the BSTR
  557. // into allocate memory and return its address.
  558. //
  559. #else
  560. if ( lpSrc ) {
  561. if ( nLenSrc == -1 ) {
  562. nLenSrc = _tcslen( lpSrc ) + sizeof(TCHAR);
  563. }
  564. }
  565. else {
  566. nLenSrc = 0;
  567. }
  568. lpDest = (LPTSTR)SysAllocStringLen( lpSrc, nLenSrc );
  569. #endif
  570. return lpDest;
  571. }