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.

684 lines
18 KiB

  1. // Copyright (c) Microsoft. All rights reserved.
  2. //
  3. // This is unpublished source code of Microsoft.
  4. // The copyright notice above does not evidence any
  5. // actual or intended publication of such source code.
  6. // OneLiner : Implementation of MWmiObject
  7. // DevUnit : wlbstest
  8. // Author : Murtaza Hakim
  9. // include files
  10. #include "MWmiObject.h"
  11. #include "MWmiError.h"
  12. #include "mtrace.h"
  13. using namespace std;
  14. // constructor
  15. //
  16. MWmiObject::MWmiObject( const _bstr_t& ipAddr,
  17. const _bstr_t& nameSpace,
  18. const _bstr_t& loginName,
  19. const _bstr_t& passWord )
  20. :
  21. _nameSpace( nameSpace )
  22. {
  23. HRESULT hr;
  24. hr = CoCreateInstance(CLSID_WbemLocator, 0,
  25. CLSCTX_INPROC_SERVER,
  26. IID_IWbemLocator,
  27. (LPVOID *) &pwl);
  28. if (FAILED(hr))
  29. {
  30. TRACE( MTrace::SEVERE_ERROR, "CoCreateInstance failure\n");
  31. throw _com_error( hr );
  32. }
  33. //
  34. _bstr_t serverPath;
  35. serverPath = _bstr_t(L"\\\\") + ipAddr + _bstr_t(L"\\") + nameSpace;
  36. betterConnectServer(
  37. serverPath,
  38. loginName,
  39. passWord,
  40. 0,
  41. NULL,
  42. 0,
  43. 0,
  44. &pws
  45. );
  46. // Set the proxy so that impersonation of the client occurs.
  47. //
  48. CoSetProxyBlanket(pws,
  49. RPC_C_AUTHN_WINNT,
  50. RPC_C_AUTHZ_DEFAULT, // RPC_C_AUTHZ_NAME,
  51. COLE_DEFAULT_PRINCIPAL, // NULL,
  52. RPC_C_AUTHN_LEVEL_DEFAULT,
  53. RPC_C_IMP_LEVEL_IMPERSONATE,
  54. COLE_DEFAULT_AUTHINFO, // NULL,
  55. EOAC_DEFAULT // EOAC_NONE
  56. );
  57. TRACE(MTrace::INFO, L"mwmiobject constructor\n" );
  58. }
  59. // constructor
  60. //
  61. MWmiObject::MWmiObject( const _bstr_t& nameSpace )
  62. :
  63. _nameSpace( nameSpace )
  64. {
  65. HRESULT hr;
  66. // hr = CoCreateInstance(CLSID_WbemLocator, 0,
  67. hr = CoCreateInstance(CLSID_WbemUnauthenticatedLocator, 0,
  68. CLSCTX_INPROC_SERVER,
  69. IID_IWbemLocator,
  70. (LPVOID *) &pwl);
  71. if (FAILED(hr))
  72. {
  73. TRACE( MTrace::SEVERE_ERROR, "CoCreateInstance failure\n");
  74. throw _com_error( hr );
  75. }
  76. betterConnectServer(
  77. nameSpace,
  78. NULL,
  79. NULL,
  80. 0,
  81. NULL,
  82. 0,
  83. 0,
  84. &pws
  85. );
  86. // Set the proxy so that impersonation of the client occurs.
  87. //
  88. CoSetProxyBlanket(pws,
  89. RPC_C_AUTHN_WINNT,
  90. RPC_C_AUTHZ_NAME,
  91. NULL,
  92. RPC_C_AUTHN_LEVEL_DEFAULT,
  93. RPC_C_IMP_LEVEL_IMPERSONATE,
  94. NULL,
  95. EOAC_NONE
  96. );
  97. TRACE(MTrace::INFO, L"mwmiobject constructor\n" );
  98. }
  99. // copy constructor
  100. //
  101. MWmiObject::MWmiObject( const MWmiObject& obj )
  102. : status( obj.status ),
  103. pwl( obj.pwl ),
  104. pws( obj.pws ),
  105. _nameSpace( obj._nameSpace )
  106. {
  107. TRACE(MTrace::INFO, L"mwmiobject copy constructor\n" );
  108. }
  109. // assignment operator
  110. //
  111. MWmiObject&
  112. MWmiObject::operator=(const MWmiObject& rhs )
  113. {
  114. status = rhs.status;
  115. _nameSpace = rhs._nameSpace;
  116. pwl = rhs.pwl;
  117. pws = rhs.pws;
  118. TRACE(MTrace::INFO, L"mwmiobject assignment operator\n" );
  119. return *this;
  120. }
  121. // destructor
  122. //
  123. MWmiObject::~MWmiObject()
  124. {
  125. TRACE(MTrace::INFO, L"mwmiobject destructor\n" );
  126. }
  127. // getInstances
  128. //
  129. MWmiObject::MWmiObject_Error
  130. MWmiObject::getInstances(
  131. const _bstr_t& objectToGetInstancesOf,
  132. vector< MWmiInstance >* instanceStore )
  133. {
  134. vector<_bstr_t> pathStore;
  135. // get paths to all instances.
  136. getPath( objectToGetInstancesOf,
  137. &pathStore );
  138. // form instances
  139. for( int i = 0; i < pathStore.size(); ++i )
  140. {
  141. instanceStore->push_back( MWmiInstance( objectToGetInstancesOf,
  142. pathStore[i],
  143. pwl,
  144. pws ) );
  145. }
  146. return MWmiObject_SUCCESS;
  147. }
  148. // getSpecificInstance
  149. //
  150. MWmiObject::MWmiObject_Error
  151. MWmiObject::getSpecificInstance(
  152. const _bstr_t& objectToGetInstancesOf,
  153. const _bstr_t& relPath,
  154. vector< MWmiInstance >* instanceStore )
  155. {
  156. vector<_bstr_t> pathStore;
  157. // get paths to all instances.
  158. getSpecificPath( objectToGetInstancesOf,
  159. relPath,
  160. &pathStore );
  161. // form instances
  162. for( int i = 0; i < pathStore.size(); ++i )
  163. {
  164. instanceStore->push_back( MWmiInstance( objectToGetInstancesOf,
  165. pathStore[i],
  166. pwl,
  167. pws ) );
  168. }
  169. return MWmiObject_SUCCESS;
  170. }
  171. // getQueriedInstances
  172. //
  173. MWmiObject::MWmiObject_Error
  174. MWmiObject::getQueriedInstances( const _bstr_t& objectToGetInstancesOf,
  175. const _bstr_t& query,
  176. vector< MWmiInstance >* instanceStore )
  177. {
  178. vector<_bstr_t> pathStore;
  179. // get paths to all instances.
  180. getQueriedPath( objectToGetInstancesOf,
  181. query,
  182. &pathStore );
  183. // form instances
  184. for( int i = 0; i < pathStore.size(); ++i )
  185. {
  186. instanceStore->push_back( MWmiInstance( objectToGetInstancesOf,
  187. pathStore[i],
  188. pwl,
  189. pws ) );
  190. }
  191. return MWmiObject_SUCCESS;
  192. }
  193. // getPath
  194. //
  195. MWmiObject::MWmiObject_Error
  196. MWmiObject::getPath( const _bstr_t& objectToRunMethodOn,
  197. vector<_bstr_t> *pathStore )
  198. {
  199. HRESULT hr;
  200. IEnumWbemClassObjectPtr pewco;
  201. IWbemClassObjectPtr pwco;
  202. _variant_t v_path;
  203. unsigned long count;
  204. // get instances of object
  205. //
  206. hr = pws->CreateInstanceEnum( objectToRunMethodOn,
  207. WBEM_FLAG_RETURN_IMMEDIATELY,
  208. NULL,
  209. &pewco );
  210. if ( FAILED(hr))
  211. {
  212. TRACE( MTrace::SEVERE_ERROR, "IWbemServices::CreateInstanceEnum failure\n" );
  213. throw _com_error( hr ) ;
  214. }
  215. // there may be multiple instances.
  216. #if 1
  217. // Set the proxy so that impersonation of the client occurs.
  218. //
  219. CoSetProxyBlanket(pewco,
  220. RPC_C_AUTHN_WINNT,
  221. RPC_C_AUTHZ_NAME,
  222. NULL,
  223. RPC_C_AUTHN_LEVEL_DEFAULT,
  224. RPC_C_IMP_LEVEL_IMPERSONATE,
  225. NULL,
  226. EOAC_NONE
  227. );
  228. count = 1;
  229. while ( (hr = pewco->Next( INFINITE,
  230. 1,
  231. &pwco,
  232. &count ) ) == S_OK )
  233. {
  234. hr = pwco->Get( _bstr_t(L"__RELPATH"), 0, &v_path, NULL, NULL );
  235. if( FAILED(hr) )
  236. {
  237. TRACE( MTrace::SEVERE_ERROR, "IWbemClassObject::Get failure\n" );
  238. throw _com_error( hr );
  239. }
  240. pathStore->push_back( _bstr_t(v_path) );
  241. count = 1;
  242. v_path.Clear();
  243. }
  244. #endif
  245. #if 0
  246. count = 1;
  247. hr = WBEM_S_NO_ERROR;
  248. while ( hr == WBEM_S_NO_ERROR )
  249. {
  250. hr = pewco->Next( INFINITE,
  251. 1,
  252. &pwco,
  253. &count );
  254. if( FAILED( hr ) )
  255. {
  256. TRACE( MTrace::SEVERE_ERROR, "IWbemClassObject::Get failure\n" );
  257. _bstr_t errText;
  258. GetErrorCodeText( hr, errText );
  259. throw _com_error( hr );
  260. }
  261. HRESULT hrGet;
  262. hrGet = pwco->Get( _bstr_t(L"__RELPATH"), 0, &v_path, NULL, NULL );
  263. if( FAILED(hrGet ) )
  264. {
  265. TRACE( MTrace::SEVERE_ERROR, "IWbemClassObject::Get failure\n" );
  266. throw _com_error( hrGet );
  267. }
  268. pathStore->push_back( _bstr_t(v_path) );
  269. count = 1;
  270. v_path.Clear();
  271. }
  272. #endif
  273. return MWmiObject_SUCCESS;
  274. }
  275. // getSpecificPath
  276. //
  277. MWmiObject::MWmiObject_Error
  278. MWmiObject::getSpecificPath( const _bstr_t& objectToRunMethodOn,
  279. const _bstr_t& relPath,
  280. vector<_bstr_t> *pathStore )
  281. {
  282. HRESULT hr;
  283. IWbemClassObjectPtr pwcoInstance;
  284. IEnumWbemClassObjectPtr pewco;
  285. IWbemClassObjectPtr pwco;
  286. unsigned long count;
  287. _variant_t v_path;
  288. bool found;
  289. int i;
  290. _variant_t v_value;
  291. hr = pws->GetObject( relPath,
  292. 0,
  293. NULL,
  294. &pwcoInstance,
  295. NULL );
  296. if( hr == 0x8004100c )
  297. {
  298. // this is for setting class instances.
  299. //
  300. TRACE(MTrace::INFO, L"as this is not supported, trying different mechanism\n");
  301. hr = pws->CreateInstanceEnum( objectToRunMethodOn,
  302. WBEM_FLAG_RETURN_IMMEDIATELY,
  303. NULL,
  304. &pewco );
  305. if ( FAILED(hr))
  306. {
  307. TRACE(MTrace::SEVERE_ERROR, L"IWbemServices::CreateInstanceEnum failure\n");
  308. throw _com_error( hr );
  309. }
  310. // there may be multiple instances.
  311. count = 1;
  312. while ( (hr = pewco->Next( INFINITE,
  313. 1,
  314. &pwco,
  315. &count ) ) == S_OK )
  316. {
  317. hr = pwco->Get( _bstr_t(L"__RELPATH"), 0, &v_path, NULL, NULL );
  318. if ( FAILED(hr))
  319. {
  320. TRACE(MTrace::SEVERE_ERROR, L"IWbemClassObject::Get failure\n");
  321. throw _com_error( hr );
  322. }
  323. if( _bstr_t( v_path ) == relPath )
  324. {
  325. // required instance found
  326. found = true;
  327. v_path.Clear();
  328. break;
  329. }
  330. count = 1;
  331. v_path.Clear();
  332. }
  333. if( found == false )
  334. {
  335. TRACE( MTrace::SEVERE_ERROR, "unable to find instance with path specified\n");
  336. throw _com_error( WBEM_E_INVALID_OBJECT_PATH );
  337. }
  338. }
  339. else if( FAILED (hr) )
  340. {
  341. TRACE( MTrace::SEVERE_ERROR, "IWbemServices::GetObject failure\n");
  342. throw _com_error( hr );
  343. }
  344. pathStore->push_back( relPath );
  345. return MWmiObject_SUCCESS;
  346. }
  347. // getQueriedPath
  348. //
  349. MWmiObject::MWmiObject_Error
  350. MWmiObject::getQueriedPath( const _bstr_t& objectToRunMethodOn,
  351. const _bstr_t& query,
  352. vector<_bstr_t>* pathStore )
  353. {
  354. HRESULT hr;
  355. IEnumWbemClassObjectPtr pewco;
  356. IWbemClassObjectPtr pwco;
  357. _variant_t v_path;
  358. unsigned long count;
  359. // get instances of object
  360. //
  361. hr = pws->ExecQuery( L"WQL",
  362. query,
  363. WBEM_FLAG_FORWARD_ONLY,
  364. NULL,
  365. &pewco );
  366. if ( FAILED(hr))
  367. {
  368. TRACE( MTrace::SEVERE_ERROR, "IWbemServices::CreateInstanceEnum failure\n" );
  369. throw _com_error( hr ) ;
  370. }
  371. // there may be multiple instances.
  372. count = 1;
  373. while ( (hr = pewco->Next( INFINITE,
  374. 1,
  375. &pwco,
  376. &count ) ) == S_OK )
  377. {
  378. hr = pwco->Get( _bstr_t(L"__RELPATH"), 0, &v_path, NULL, NULL );
  379. if( FAILED(hr) )
  380. {
  381. TRACE( MTrace::SEVERE_ERROR, "IWbemClassObject::Get failure\n" );
  382. throw _com_error( hr );
  383. }
  384. pathStore->push_back( _bstr_t(v_path) );
  385. count = 1;
  386. v_path.Clear();
  387. }
  388. return MWmiObject_SUCCESS;
  389. }
  390. // createInstance
  391. //
  392. MWmiObject::MWmiObject_Error
  393. MWmiObject::createInstance(
  394. const _bstr_t& objectToCreateInstancesOf,
  395. vector<MWmiParameter *>& instanceParameters )
  396. // MWmiInstance* instanceCreated )
  397. {
  398. HRESULT hr;
  399. IWbemStatusCodeText *pStatus = NULL;
  400. IWbemClassObjectPtr pwcoClass;
  401. IWbemClassObjectPtr pwcoInstance;
  402. // Get object required.
  403. hr = pws->GetObject( objectToCreateInstancesOf,
  404. 0,
  405. NULL,
  406. &pwcoClass,
  407. NULL );
  408. if( FAILED (hr) )
  409. {
  410. TRACE( MTrace::SEVERE_ERROR, "IWbemServices::GetObject failure\n");
  411. throw _com_error( hr );
  412. }
  413. hr = pwcoClass->SpawnInstance( 0, &pwcoInstance );
  414. if( FAILED (hr) )
  415. {
  416. TRACE( MTrace::SEVERE_ERROR, "IWbemClassObject::SpawnInstance failure\n");
  417. throw _com_error( hr );
  418. }
  419. for( int i = 0; i < instanceParameters.size(); ++i )
  420. {
  421. hr = pwcoInstance->Put( instanceParameters[i]->getName(),
  422. 0,
  423. &(instanceParameters[i]->getValue() ),
  424. 0 );
  425. if( FAILED( hr ) )
  426. {
  427. TRACE( MTrace::SEVERE_ERROR, "IWbemClassObject::Put failure\n");
  428. throw _com_error( hr );
  429. }
  430. }
  431. hr = pws->PutInstance( pwcoInstance,
  432. WBEM_FLAG_CREATE_OR_UPDATE,
  433. NULL,
  434. NULL );
  435. if( FAILED(hr) )
  436. {
  437. TRACE( MTrace::SEVERE_ERROR, "IWbemServices::PutInstance failure\n");
  438. throw _com_error( hr );
  439. }
  440. return MWmiObject_SUCCESS;
  441. }
  442. MWmiObject::MWmiObject_Error
  443. MWmiObject::deleteInstance( MWmiInstance& instanceToDelete )
  444. {
  445. HRESULT hr;
  446. IWbemCallResultPtr pwcr;
  447. hr = pws->DeleteInstance( instanceToDelete._path,
  448. WBEM_FLAG_RETURN_IMMEDIATELY,
  449. NULL,
  450. &pwcr );
  451. if( FAILED(hr) )
  452. {
  453. TRACE( MTrace::SEVERE_ERROR, "IWbemServices::DeleteInstance failure\n");
  454. throw _com_error( hr );
  455. }
  456. return MWmiObject_SUCCESS;
  457. }
  458. // getStatus
  459. //
  460. MWmiObject::MWmiObject_Error
  461. MWmiObject::getStatus()
  462. {
  463. return MWmiObject_SUCCESS;
  464. }
  465. // betterConnectServer
  466. //
  467. HRESULT
  468. MWmiObject::betterConnectServer(
  469. const BSTR strNetworkResource,
  470. const BSTR strUser,
  471. const BSTR strPassword,
  472. const BSTR strLocale,
  473. LONG lSecurityFlags,
  474. const BSTR strAuthority,
  475. IWbemContext *pCtx,
  476. IWbemServices **ppNamespace
  477. )
  478. {
  479. HRESULT hr;
  480. hr = pwl->ConnectServer(
  481. strNetworkResource,
  482. NULL, // strUser,
  483. NULL, // strPassword,
  484. strLocale,
  485. lSecurityFlags,
  486. strAuthority,
  487. pCtx,
  488. ppNamespace );
  489. // these have been found to be special cases where retrying may help.
  490. if( ( hr == 0x800706bf ) || ( hr == 0x80070767 ) || ( hr == 0x80070005 ) )
  491. {
  492. int delay = 250; // milliseconds
  493. for( int i = 0; i < timesToRetry; ++i )
  494. {
  495. Sleep(delay);
  496. TRACE( MTrace::SEVERE_ERROR, L"connectserver recoverable failure, retrying\n");
  497. hr = pwl->ConnectServer(
  498. strNetworkResource,
  499. NULL, // strUser,
  500. NULL, // strPassword,
  501. strLocale,
  502. lSecurityFlags,
  503. strAuthority,
  504. pCtx,
  505. ppNamespace );
  506. if( !FAILED( hr) )
  507. {
  508. break;
  509. }
  510. }
  511. }
  512. else if ( hr == 0x80041064 )
  513. {
  514. // trying to connect to local machine. Cannot use credentials.
  515. TRACE( MTrace::INFO, L"connecting to self. Retrying without using credentials\n");
  516. hr = pwl->ConnectServer(
  517. strNetworkResource,
  518. NULL,
  519. NULL,
  520. 0,
  521. NULL,
  522. 0,
  523. 0,
  524. ppNamespace
  525. );
  526. }
  527. else if( hr == 0x80004002 )
  528. {
  529. // being connected to by a provider itself.
  530. TRACE( MTrace::INFO, L"connecting client may be a wmi provider itself. Retrying\n");
  531. // we have to get a new wbemlocatar.
  532. //
  533. hr = CoCreateInstance(CLSID_WbemUnauthenticatedLocator, 0,
  534. CLSCTX_INPROC_SERVER,
  535. IID_IWbemLocator,
  536. (LPVOID *) &pwl);
  537. if (FAILED(hr))
  538. {
  539. TRACE(MTrace::SEVERE_ERROR, L"CoCreateInstance failure\n");
  540. throw _com_error( hr );
  541. }
  542. hr = pwl->ConnectServer(
  543. strNetworkResource,
  544. NULL, // strUser,
  545. NULL, // strPassword,
  546. strLocale,
  547. lSecurityFlags,
  548. strAuthority,
  549. pCtx,
  550. ppNamespace );
  551. }
  552. if (FAILED(hr))
  553. {
  554. // no hosts are in this cluster. Cannot proceed reliably.
  555. WCHAR hrValue[32];
  556. _bstr_t errText;
  557. wstring errString;
  558. wsprintfW(hrValue, L"hr=0x%08lx", hr);
  559. GetErrorCodeText(hr, errText );
  560. errString = L"betterConnectServer failure. " + wstring(hrValue);
  561. errString += " (" + errText + L").\n";
  562. TRACE( MTrace::SEVERE_ERROR, errString );
  563. throw _com_error( hr );
  564. }
  565. return hr;
  566. }