Leaked source code of windows server 2003
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.

703 lines
17 KiB

  1. //***************************************************************************
  2. //
  3. // CLASSPRO.CPP
  4. //
  5. // Module: CDM Provider
  6. //
  7. // Purpose: Defines the CClassPro class. An object of this class is
  8. // created by the class factory for each connection.
  9. //
  10. // Copyright (c) 2000 Microsoft Corporation
  11. //
  12. //***************************************************************************
  13. #include <objbase.h>
  14. #include <wbemprov.h>
  15. #include <process.h>
  16. #include <unknwn.h>
  17. #include "debug.h"
  18. #include "wbemmisc.h"
  19. #include "useful.h"
  20. #include "testinfo.h"
  21. #include "sample.h"
  22. // CONSIDER: Does this really need to stay a global ???
  23. //
  24. // This is the global list of all of the CIM classes and their
  25. // corresponsing WDM classes that are managed by the provider.
  26. //
  27. // It is maintained as a global since WinMgmt is aggressive in
  28. // releasing the CClassProv, but we really want to maintain the result
  29. // objects and do not want to be unloaded unless all result objects are
  30. // cleared.
  31. //
  32. CWdmClass *WdmClassHead;
  33. void CleanupAllClasses(
  34. )
  35. {
  36. CWdmClass *WdmClass;
  37. CWdmClass *WdmClassNext;
  38. //
  39. // Loop over all classes that were supported by the provider and
  40. // clean them up
  41. //
  42. WdmClass = WdmClassHead;
  43. while (WdmClass != NULL)
  44. {
  45. WdmClassNext = WdmClass->GetNext();
  46. delete WdmClass;
  47. }
  48. }
  49. //***************************************************************************
  50. //
  51. // CClassPro::CClassPro
  52. // CClassPro::~CClassPro
  53. //
  54. //***************************************************************************
  55. CClassPro::CClassPro(
  56. BSTR ObjectPath,
  57. BSTR User,
  58. BSTR Password,
  59. IWbemContext * pCtx
  60. )
  61. {
  62. m_pCimServices = NULL;
  63. m_cRef=0;
  64. InterlockedIncrement(&g_cObj);
  65. return;
  66. }
  67. CClassPro::~CClassPro(void)
  68. {
  69. if(m_pCimServices)
  70. {
  71. m_pCimServices->Release();
  72. }
  73. InterlockedDecrement(&g_cObj);
  74. return;
  75. }
  76. //***************************************************************************
  77. //
  78. // CClassPro::QueryInterface
  79. // CClassPro::AddRef
  80. // CClassPro::Release
  81. //
  82. // Purpose: IUnknown members for CClassPro object.
  83. //***************************************************************************
  84. STDMETHODIMP CClassPro::QueryInterface(REFIID riid, PPVOID ppv)
  85. {
  86. HRESULT hr;
  87. *ppv=NULL;
  88. // Since we have dual inheritance, it is necessary to cast the return type
  89. if(riid== IID_IWbemServices)
  90. {
  91. *ppv=(IWbemServices*)this;
  92. }
  93. if(IID_IUnknown==riid || riid== IID_IWbemProviderInit)
  94. {
  95. *ppv=(IWbemProviderInit*)this;
  96. }
  97. if (NULL!=*ppv)
  98. {
  99. AddRef();
  100. hr = NOERROR;
  101. }
  102. else {
  103. hr = E_NOINTERFACE;
  104. }
  105. return(hr);
  106. }
  107. STDMETHODIMP_(ULONG) CClassPro::AddRef(void)
  108. {
  109. return(++m_cRef);
  110. }
  111. STDMETHODIMP_(ULONG) CClassPro::Release(void)
  112. {
  113. ULONG nNewCount = InterlockedDecrement((long *)&m_cRef);
  114. if (0L == nNewCount)
  115. {
  116. delete this;
  117. }
  118. return(nNewCount);
  119. }
  120. /***********************************************************************
  121. * *
  122. * CClassPro::Initialize *
  123. * *
  124. * Purpose: This is the implementation of IWbemProviderInit. The method *
  125. * is need to initialize with CIMOM. *
  126. * *
  127. ***********************************************************************/
  128. STDMETHODIMP CClassPro::Initialize(LPWSTR pszUser, LONG lFlags,
  129. LPWSTR pszNamespace, LPWSTR pszLocale,
  130. IWbemServices *pNamespace,
  131. IWbemContext *pCtx,
  132. IWbemProviderInitSink *pInitSink)
  133. {
  134. if (pNamespace)
  135. {
  136. pNamespace->AddRef();
  137. }
  138. m_pCimServices = pNamespace;
  139. //
  140. // Let CIMOM know you are initialized
  141. //
  142. pInitSink->SetStatus(WBEM_S_INITIALIZED, 0);
  143. return(WBEM_S_NO_ERROR);
  144. }
  145. //***************************************************************************
  146. //
  147. // CClassPro::CreateClassEnumAsync
  148. //
  149. // Purpose: Asynchronously enumerates the classes this provider supports.
  150. // Note that this sample only supports one.
  151. //
  152. //***************************************************************************
  153. SCODE CClassPro::CreateClassEnumAsync(
  154. const BSTR Superclass, long lFlags,
  155. IWbemContext *pCtx,
  156. IWbemObjectSink *pHandler
  157. )
  158. {
  159. return(WBEM_E_NOT_SUPPORTED);
  160. }
  161. //***************************************************************************
  162. //
  163. // CClassPro::CreateInstanceEnumAsync
  164. //
  165. // Purpose: Asynchronously enumerates the instances.
  166. //
  167. //***************************************************************************
  168. SCODE CClassPro::CreateInstanceEnumAsync(
  169. const BSTR ClassName,
  170. long lFlags,
  171. IWbemContext *pCtx,
  172. IWbemObjectSink FAR* pHandler
  173. )
  174. {
  175. HRESULT hr;
  176. ULONG i, Count;
  177. IWbemClassObject *pCimInstance;
  178. CWdmClass *WdmClass;
  179. WmipDebugPrint(("CDMPROV: Enumerate instances of class %ws\n",
  180. ClassName));
  181. //
  182. // Do a check of arguments and make sure we have pointer to Namespace
  183. //
  184. if (pHandler == NULL || m_pCimServices == NULL)
  185. {
  186. return WBEM_E_INVALID_PARAMETER;
  187. }
  188. //
  189. // Obtain a wdm class object that represents this class
  190. //
  191. hr = LookupWdmClass(pCtx,
  192. ClassName,
  193. &WdmClass);
  194. if (hr == WBEM_S_NO_ERROR)
  195. {
  196. if (WdmClass->IsInstancesAvailable())
  197. {
  198. Count = WdmClass->GetInstanceCount();
  199. for (i = 0; i < Count; i++)
  200. {
  201. pCimInstance = WdmClass->GetCimInstance(i);
  202. //
  203. // Send the object to the caller
  204. //
  205. hr = pHandler->Indicate(1, &pCimInstance);
  206. }
  207. }
  208. }
  209. //
  210. // TODO: Create extended error object with more info about the
  211. // error that occured. The object is created by
  212. // CreateInst("__ExtendedStatus")
  213. //
  214. pHandler->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
  215. return(hr);
  216. }
  217. //***************************************************************************
  218. //
  219. // CClassPro::GetObjectByPathAsync
  220. //
  221. // Purpose: Returns either an instance or a class.
  222. //
  223. //***************************************************************************
  224. SCODE CClassPro::GetObjectAsync(
  225. const BSTR ObjectPath,
  226. long lFlags,
  227. IWbemContext *pCtx,
  228. IWbemObjectSink FAR* pHandler
  229. )
  230. {
  231. HRESULT hr;
  232. IWbemClassObject FAR* Instance;
  233. // Do a check of arguments and make sure we have pointer to Namespace
  234. if (ObjectPath == NULL || pHandler == NULL || m_pCimServices == NULL)
  235. {
  236. return WBEM_E_INVALID_PARAMETER;
  237. }
  238. hr = GetByPath(pCtx, ObjectPath, &Instance);
  239. if (hr == WBEM_S_NO_ERROR)
  240. {
  241. WmipDebugPrint(("CDMProv: Found instance %p for relpath %ws\n",
  242. Instance, ObjectPath));
  243. hr = pHandler->Indicate(1, &Instance);
  244. } else {
  245. WmipDebugPrint(("CDMProv: Did not find instance for relpath %ws\n",
  246. ObjectPath));
  247. hr = WBEM_E_NOT_FOUND;
  248. }
  249. // Set Status
  250. pHandler->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL, NULL);
  251. return(hr);
  252. }
  253. //***************************************************************************
  254. //
  255. // CClassPro::GetByPath
  256. //
  257. // Purpose: Creates an instance given a particular Path value.
  258. //
  259. // All objects returned are assumed to be AddRefed
  260. //
  261. //***************************************************************************
  262. HRESULT CClassPro::GetByPath(
  263. IWbemContext *pCtx,
  264. BSTR ObjectPath,
  265. IWbemClassObject **Instance
  266. )
  267. {
  268. HRESULT hr = WBEM_S_NO_ERROR;
  269. WCHAR ClassName[MAX_PATH+1];
  270. WCHAR *p;
  271. int iNumQuotes = 0;
  272. int i, Count;
  273. CWdmClass *WdmClass;
  274. BSTR s;
  275. //
  276. // This is where we are queried for a class based upon its relpath.
  277. // We need to parse the relpath to get the class name and then look
  278. // at the relpath to determine which instance of the class we are
  279. // interested in and then build up the instance and return it
  280. //
  281. //
  282. //
  283. // Obtain the class name by copying up to the .
  284. //
  285. for (p = ObjectPath, i = 0;
  286. (*p != 0) && (*p != L'.') && (i < MAX_PATH);
  287. p++, i++)
  288. {
  289. ClassName[i] = *p;
  290. }
  291. if (*p != L'.')
  292. {
  293. //
  294. // If we did end our loop with a . then we failed to parse
  295. // properly
  296. //
  297. WmipDebugPrint(("CDMPROV: Unable to parse relpath %ws at %ws, i = %d\n",
  298. ObjectPath, p, i));
  299. }
  300. ClassName[i] = 0;
  301. WmipDebugPrint(("CDMPROV: Class %ws looking for relpath %ws\n",
  302. ClassName, ObjectPath));
  303. //
  304. // Obtain a Wdm class that represents this classname
  305. //
  306. hr = LookupWdmClass(pCtx,
  307. ClassName,
  308. &WdmClass);
  309. if (hr == WBEM_S_NO_ERROR)
  310. {
  311. if (WdmClass->IsInstancesAvailable())
  312. {
  313. //
  314. // Assume that we will not find the object instance
  315. //
  316. hr = WBEM_E_NOT_FOUND;
  317. Count = WdmClass->GetInstanceCount();
  318. for (i = 0; i < Count; i++)
  319. {
  320. if (_wcsicmp(ObjectPath,
  321. WdmClass->GetCimRelPath(i)) == 0)
  322. {
  323. *Instance = WdmClass->GetCimInstance(i);
  324. hr = WBEM_S_NO_ERROR;
  325. break;
  326. }
  327. }
  328. } else {
  329. hr = WBEM_E_FAILED;
  330. }
  331. }
  332. return(hr);
  333. }
  334. /************************************************************************
  335. * *
  336. *CMethodPro::ExecMethodAsync *
  337. * *
  338. *Purpose: This is the Async function implementation. *
  339. * The only method supported in this sample is named Echo. It *
  340. * takes an input string, copies it to the output and returns the*
  341. * length. *
  342. * *
  343. * *
  344. ************************************************************************/
  345. STDMETHODIMP CClassPro::ExecMethodAsync(
  346. const BSTR ObjectPath,
  347. const BSTR MethodName,
  348. long lFlags,
  349. IWbemContext* pCtx,
  350. IWbemClassObject* pInParams,
  351. IWbemObjectSink* pResultSink
  352. )
  353. {
  354. HRESULT hr, hrDontCare;
  355. IWbemClassObject * pMethodClass = NULL;
  356. IWbemClassObject * pOutClass = NULL;
  357. IWbemClassObject* pOutParams = NULL;
  358. WCHAR ClassName[MAX_PATH];
  359. WCHAR *p;
  360. VARIANT v, vRetVal;
  361. int RelPathIndex;
  362. CWdmClass *WdmClass;
  363. BSTR WdmObjectPath;
  364. VariantInit(&v);
  365. VariantInit(&vRetVal);
  366. //
  367. // Extract this class name from the object path
  368. //
  369. wcscpy(ClassName, ObjectPath);
  370. p = ClassName;
  371. while ((*p != 0) && (*p != L'.'))
  372. {
  373. p++;
  374. }
  375. *p = 0;
  376. WmipDebugPrint(("CDMPROV: Exec method %ws for instanec %ws\n",
  377. MethodName, ObjectPath));
  378. //
  379. // Obtain a Wdm class that represents this ClassName
  380. //
  381. hr = LookupWdmClass(pCtx,
  382. ClassName,
  383. &WdmClass);
  384. if (hr == WBEM_S_NO_ERROR)
  385. {
  386. if (WdmClass->IsInstancesAvailable())
  387. {
  388. hr = WdmClass->GetIndexByCimRelPath(ObjectPath, &RelPathIndex);
  389. if (hr == WBEM_S_NO_ERROR)
  390. {
  391. WdmObjectPath = WdmClass->GetWdmRelPath(RelPathIndex);
  392. //
  393. // CONSIDER: Do we need to do any processing on the input
  394. // or output parameter objects ??
  395. //
  396. hr = WdmClass->GetWdmServices()->ExecMethod(WdmObjectPath,
  397. MethodName,
  398. lFlags,
  399. pCtx,
  400. pInParams,
  401. &pOutParams,
  402. NULL);
  403. if ((hr == WBEM_S_NO_ERROR) && (pOutParams != NULL))
  404. {
  405. pResultSink->Indicate(1, &pOutParams);
  406. pOutParams->Release();
  407. }
  408. }
  409. }
  410. }
  411. pResultSink->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL,NULL);
  412. return(hr);
  413. }
  414. //
  415. // TODO: Implement setting and deletion
  416. //
  417. SCODE CClassPro::PutClassAsync(
  418. /* [in] */ IWbemClassObject __RPC_FAR *pObject,
  419. /* [in] */ long lFlags,
  420. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  421. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
  422. {
  423. return(WBEM_E_NOT_SUPPORTED);
  424. }
  425. SCODE CClassPro::DeleteClassAsync(
  426. /* [in] */ const BSTR Class,
  427. /* [in] */ long lFlags,
  428. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  429. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
  430. {
  431. return(WBEM_E_NOT_SUPPORTED);
  432. }
  433. SCODE CClassPro::PutInstanceAsync(
  434. /* [in] */ IWbemClassObject __RPC_FAR *pInst,
  435. /* [in] */ long lFlags,
  436. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  437. /* [in] */ IWbemObjectSink __RPC_FAR *pResultsSink)
  438. {
  439. HRESULT hr;
  440. CWdmClass *WdmClass;
  441. VARIANT Values[2];
  442. PWCHAR Names[2];
  443. CIMTYPE Types[2];
  444. int RelPathIndex;
  445. if (pInst == NULL || pResultsSink == NULL )
  446. {
  447. return WBEM_E_INVALID_PARAMETER;
  448. }
  449. //
  450. // Get the class name
  451. //
  452. Names[0] = L"__CLASS";
  453. Types[0] = CIM_STRING;
  454. Names[1] = L"__RELPATH";
  455. Types[1] = CIM_REFERENCE;
  456. hr = WmiGetPropertyList(pInst,
  457. 2,
  458. Names,
  459. Types,
  460. Values);
  461. if (hr == WBEM_S_NO_ERROR)
  462. {
  463. hr = LookupWdmClass(pCtx,
  464. Values[0].bstrVal,
  465. &WdmClass);
  466. if (hr == WBEM_S_NO_ERROR)
  467. {
  468. //
  469. // We need to pull out the properties from the instance
  470. // passed to us, do any mapping to WDM properties and then
  471. // set them in the WDM instance
  472. //
  473. hr = WdmClass->GetIndexByCimRelPath(Values[1].bstrVal,
  474. &RelPathIndex);
  475. if (hr == WBEM_S_NO_ERROR)
  476. {
  477. hr = WdmClass->PutInstance(pCtx,
  478. RelPathIndex,
  479. pInst);
  480. }
  481. }
  482. VariantClear(&Values[0]);
  483. VariantClear(&Values[1]);
  484. }
  485. pResultsSink->SetStatus(WBEM_STATUS_COMPLETE, hr, NULL,NULL);
  486. return(hr);
  487. }
  488. SCODE CClassPro::DeleteInstanceAsync(
  489. /* [in] */ const BSTR ObjectPath,
  490. /* [in] */ long lFlags,
  491. /* [in] */ IWbemContext __RPC_FAR *pCtx,
  492. /* [in] */ IWbemObjectSink __RPC_FAR *pResponseHandler)
  493. {
  494. return(WBEM_E_NOT_SUPPORTED);
  495. }
  496. CWdmClass *CClassPro::FindExistingWdmClass(
  497. PWCHAR CimClassName
  498. )
  499. {
  500. CWdmClass *WdmClass;
  501. //
  502. // This routine assumes any sync mechanism has been done outside of
  503. // this routine
  504. //
  505. WdmClass = WdmClassHead;
  506. while (WdmClass != NULL)
  507. {
  508. if (WdmClass->ClaimCimClassName(CimClassName))
  509. {
  510. //
  511. // We found an existing test services for this class.
  512. //
  513. return(WdmClass);
  514. }
  515. WdmClass = WdmClass->GetNext();
  516. }
  517. return(NULL);
  518. }
  519. HRESULT CClassPro::LookupWdmClass(
  520. IWbemContext *pCtx,
  521. const BSTR CimClassName,
  522. CWdmClass **WdmClassPtr
  523. )
  524. {
  525. HRESULT hr;
  526. CWdmClass *WdmClass, *OtherWdmClass;
  527. WmipAssert(CimClassName != NULL);
  528. WmipAssert(WdmClassPtr != NULL);
  529. //
  530. // Look up the class name and find the Wdm Test Services
  531. // class that represents it.
  532. //
  533. EnterCritSection();
  534. WdmClass = FindExistingWdmClass(CimClassName);
  535. LeaveCritSection();
  536. if (WdmClass != NULL)
  537. {
  538. //
  539. // CONSIDER: Refresh instances from WDM back into CIM
  540. //
  541. *WdmClassPtr = WdmClass;
  542. return(WBEM_S_NO_ERROR);
  543. }
  544. //
  545. // If the WDM test services has not yet been initialized for this
  546. // CDM diagnostic classes then go ahead and do so
  547. //
  548. WdmClass = new CWdmClass();
  549. hr = WdmClass->InitializeSelf(pCtx, CimClassName);
  550. if (hr == WBEM_S_NO_ERROR)
  551. {
  552. //
  553. // Now check to see if another thread created and inserted the
  554. // test services for the class while we were trying to
  555. // initialize it. Since we want only one test services we throw
  556. // ours away and use the other
  557. //
  558. EnterCritSection();
  559. OtherWdmClass = FindExistingWdmClass(CimClassName);
  560. if (OtherWdmClass == NULL)
  561. {
  562. //
  563. // Horray, we win do insert our own test into list
  564. //
  565. WdmClass->InsertSelf(&WdmClassHead);
  566. LeaveCritSection();
  567. hr = WdmClass->RemapToCimClass(pCtx);
  568. //
  569. // Decrement the counter to indicate that instances are
  570. // available. This refcount was assigned in the constructor
  571. //
  572. WdmClass->DecrementMappingInProgress();
  573. if (hr != WBEM_S_NO_ERROR)
  574. {
  575. WmipDebugPrint(("CDMPROV: Inited failed %x for %p for %ws\n",
  576. hr, WdmClass, CimClassName));
  577. }
  578. } else {
  579. //
  580. // We lost, so use existing test services
  581. //
  582. WmipDebugPrint(("CDMPROV: WdmClass %p lost insertion race to %p\n",
  583. WdmClass, OtherWdmClass));
  584. LeaveCritSection();
  585. delete WdmClass;
  586. WdmClass = OtherWdmClass;
  587. }
  588. *WdmClassPtr = WdmClass;
  589. }
  590. return(hr);
  591. }