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.

3897 lines
80 KiB

  1. //***************************************************************************
  2. //
  3. // TestInfo.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. // @@BEGIN_DDKSPLIT
  14. //
  15. // What is left to do:
  16. //
  17. // Finish reboot diagnostics - This involves persisting the pending
  18. // result in the schema and then trying to query for the actual
  19. // results later
  20. //
  21. // Keep more than 1 historical result instance. This involves
  22. // persisting the historical results in the schema and picking them
  23. // up from there
  24. // @@END_DDKSPLIT
  25. #include <objbase.h>
  26. #ifndef _MT
  27. #define _MT
  28. #endif
  29. #include <wbemidl.h>
  30. #include "debug.h"
  31. #include "testinfo.h"
  32. #include "wbemmisc.h"
  33. #include "cimmap.h"
  34. #include "reload.h"
  35. IWbemServices *pCimServices;
  36. IWbemServices *pWdmServices;
  37. HRESULT TestInfoInitialize(
  38. void
  39. )
  40. /*+++
  41. Routine Description:
  42. This routine will establishes a connection to the root\wmi and
  43. root\cimv2 namespaces in global memory
  44. Arguments:
  45. Return Value:
  46. HRESULT
  47. ---*/
  48. {
  49. HRESULT hr;
  50. WmipAssert(pCimServices == NULL);
  51. WmipAssert(pWdmServices == NULL);
  52. hr = WmiConnectToWbem(L"root\\cimv2",
  53. &pCimServices);
  54. if (hr == WBEM_S_NO_ERROR)
  55. {
  56. hr = WmiConnectToWbem(L"root\\wmi",
  57. &pWdmServices);
  58. if (hr != WBEM_S_NO_ERROR)
  59. {
  60. pCimServices->Release();
  61. pCimServices = NULL;
  62. }
  63. }
  64. return(hr);
  65. }
  66. void TestInfoDeinitialize(
  67. void
  68. )
  69. /*+++
  70. Routine Description:
  71. This routine will disestablish a connection to the root\wmi and
  72. root\cimv2 namespaces in global memory
  73. Arguments:
  74. Return Value:
  75. ---*/
  76. {
  77. WmipAssert(pCimServices != NULL);
  78. WmipAssert(pWdmServices != NULL);
  79. pCimServices->Release();
  80. pCimServices = NULL;
  81. pWdmServices->Release();
  82. pWdmServices = NULL;
  83. }
  84. CTestServices::CTestServices()
  85. /*+++
  86. Routine Description:
  87. Constructor for CTestServices class
  88. Arguments:
  89. Return Value:
  90. ---*/
  91. {
  92. WdmTestClassName = NULL;
  93. WdmSettingClassName = NULL;
  94. WdmSettingListClassName = NULL;
  95. WdmResultClassName = NULL;
  96. WdmOfflineResultClassName = NULL;
  97. CdmTestClassName = NULL;
  98. CdmTestRelPath = NULL;
  99. CdmResultClassName = NULL;
  100. CdmSettingClassName = NULL;
  101. CdmTestForMSEClassName = NULL;
  102. CdmTestForMSERelPath = NULL;
  103. CdmSettingForTestClassName = NULL;
  104. CdmSettingForTestRelPath = NULL;
  105. CdmResultForMSEClassName = NULL;
  106. CdmResultForTestClassName = NULL;
  107. CdmTestForSoftwareClassName = NULL;
  108. CdmTestForSoftwareRelPath = NULL;
  109. CdmTestInPackageClassName = NULL;
  110. CdmTestInPackageRelPath = NULL;
  111. CdmResultInPackageClassName = NULL;
  112. CdmResultInPackageRelPath = NULL;
  113. CimClassMappingClassName = NULL;
  114. CimRelPaths = NULL;
  115. WdmRelPaths = NULL;
  116. PnPDeviceIdsX = NULL;
  117. WdmInstanceNames = NULL;
  118. CdmSettingsList = NULL;
  119. CdmResultsList = NULL;
  120. Next = NULL;
  121. Prev = NULL;
  122. }
  123. CTestServices::~CTestServices()
  124. /*+++
  125. Routine Description:
  126. Destructor for CTestServices class
  127. Arguments:
  128. Return Value:
  129. ---*/
  130. {
  131. int i;
  132. if (WdmTestClassName != NULL)
  133. {
  134. SysFreeString(WdmTestClassName);
  135. }
  136. if (WdmSettingClassName != NULL)
  137. {
  138. SysFreeString(WdmSettingClassName);
  139. }
  140. if (WdmResultClassName != NULL)
  141. {
  142. SysFreeString(WdmResultClassName);
  143. }
  144. if (WdmOfflineResultClassName != NULL)
  145. {
  146. SysFreeString(WdmOfflineResultClassName);
  147. }
  148. if (WdmSettingListClassName != NULL)
  149. {
  150. SysFreeString(WdmSettingListClassName);
  151. }
  152. if (CdmTestClassName != NULL)
  153. {
  154. SysFreeString(CdmTestClassName);
  155. }
  156. if (CdmTestRelPath != NULL)
  157. {
  158. SysFreeString(CdmTestRelPath);
  159. }
  160. if (CdmResultClassName != NULL)
  161. {
  162. SysFreeString(CdmResultClassName);
  163. }
  164. if (CdmSettingClassName != NULL)
  165. {
  166. SysFreeString(CdmSettingClassName);
  167. }
  168. if (CdmTestForMSEClassName != NULL)
  169. {
  170. SysFreeString(CdmTestForMSEClassName);
  171. }
  172. FreeTheBSTRArray(CdmTestForMSERelPath, RelPathCount);
  173. if (CdmSettingForTestClassName != NULL)
  174. {
  175. SysFreeString(CdmSettingForTestClassName);
  176. }
  177. if (CdmSettingForTestRelPath != NULL)
  178. {
  179. for (i = 0; i < RelPathCount; i++)
  180. {
  181. delete CdmSettingForTestRelPath[i];
  182. }
  183. WmipFree(CdmSettingForTestRelPath);
  184. }
  185. if (CdmResultForMSEClassName != NULL)
  186. {
  187. SysFreeString(CdmResultForMSEClassName);
  188. }
  189. if (CdmResultForTestClassName != NULL)
  190. {
  191. SysFreeString(CdmResultForTestClassName);
  192. }
  193. if (CdmTestForSoftwareClassName != NULL)
  194. {
  195. SysFreeString(CdmTestForSoftwareClassName);
  196. }
  197. if (CdmTestForSoftwareRelPath != NULL)
  198. {
  199. SysFreeString(CdmTestForSoftwareRelPath);
  200. }
  201. if (CdmTestInPackageClassName != NULL)
  202. {
  203. SysFreeString(CdmTestInPackageClassName);
  204. }
  205. if (CdmTestInPackageRelPath != NULL)
  206. {
  207. SysFreeString(CdmTestInPackageRelPath);
  208. }
  209. if (CdmResultInPackageClassName != NULL)
  210. {
  211. SysFreeString(CdmResultInPackageClassName);
  212. }
  213. if (CdmResultInPackageRelPath != NULL)
  214. {
  215. SysFreeString(CdmResultInPackageRelPath);
  216. }
  217. if (CimClassMappingClassName != NULL)
  218. {
  219. SysFreeString(CimClassMappingClassName);
  220. }
  221. FreeTheBSTRArray(CimRelPaths, RelPathCount);
  222. FreeTheBSTRArray(WdmRelPaths, RelPathCount);
  223. FreeTheBSTRArray(WdmInstanceNames, RelPathCount);
  224. FreeTheBSTRArray(PnPDeviceIdsX, RelPathCount);
  225. if (CdmSettingsList != NULL)
  226. {
  227. for (i = 0; i < RelPathCount; i++)
  228. {
  229. delete CdmSettingsList[i];
  230. }
  231. WmipFree(CdmSettingsList);
  232. }
  233. if (CdmResultsList != NULL)
  234. {
  235. for (i = 0; i < RelPathCount; i++)
  236. {
  237. delete &CdmResultsList[i];
  238. }
  239. }
  240. }
  241. BOOLEAN ClassIsCdmBaseClass(
  242. BSTR ClassName,
  243. BOOLEAN *IsTestClass
  244. )
  245. /*+++
  246. Routine Description:
  247. This routine determines if the class name is a CDM base class name
  248. Arguments:
  249. ClassName is the name of the class
  250. *IsTestClass returns TRUE if the class name is CIM_DiagnosticTest
  251. Return Value:
  252. TRUE if class is a CDM base class else FALSE
  253. ---*/
  254. {
  255. WmipAssert(ClassName != NULL);
  256. WmipAssert(IsTestClass != NULL);
  257. if (_wcsicmp(ClassName, L"CIM_DiagnosticTest") == 0)
  258. {
  259. *IsTestClass = TRUE;
  260. return(TRUE);
  261. }
  262. if ((_wcsicmp(ClassName, L"CIM_DiagnosticResult") == 0) ||
  263. (_wcsicmp(ClassName, L"CIM_DiagnosticSetting") == 0) ||
  264. (_wcsicmp(ClassName, L"CIM_DiagnosticResultForMSE") == 0) ||
  265. (_wcsicmp(ClassName, L"CIM_DiagnosticResultForTest") == 0) ||
  266. (_wcsicmp(ClassName, L"CIM_DiagnosticTestForMSE") == 0) ||
  267. (_wcsicmp(ClassName, L"CIM_DiagnosticTestSoftware") == 0) ||
  268. (_wcsicmp(ClassName, L"CIM_DiagnosticTestInPackage") == 0) ||
  269. (_wcsicmp(ClassName, L"CIM_DiagnosticResultInPackage") == 0) ||
  270. (_wcsicmp(ClassName, L"CIM_DiagnosticResultForMSE") == 0) ||
  271. (_wcsicmp(ClassName, L"CIM_DiagnosticSettingForTest") == 0))
  272. {
  273. *IsTestClass = FALSE;
  274. return(TRUE);
  275. }
  276. return(FALSE);
  277. }
  278. HRESULT CTestServices::GetCdmClassNamesFromOne(
  279. PWCHAR CdmClass
  280. )
  281. /*+++
  282. Routine Description:
  283. This routine obtains the names of all of the CDM classes from the
  284. name of a single CDM class
  285. Arguments:
  286. CdmClass is the name of the CDM class
  287. Return Value:
  288. HRESULT
  289. ---*/
  290. {
  291. IWbemServices * pCdmServices = GetCdmServices();
  292. VARIANT v, vClass, vSuper;
  293. HRESULT hr, hrDontCare;
  294. BOOLEAN IsTestClass;
  295. BSTR SuperClass;
  296. BSTR CdmTestClass;
  297. //
  298. // First thing is that we need to do is figure out what kind of
  299. // class we have been handed. If it is a CIM_DiagnosticTest derived
  300. // class then we can proceed to obtain all of the other class names
  301. // via qualifiers. If not then we have to link back from the class
  302. // we have to the CIM_DiagnosticTest derived class via the
  303. // CdmDiagTest qualifier.
  304. //
  305. //
  306. // Get a class object for Cdm class passed and then check the
  307. // __SUPERCLASS property to see which CDM class it is derived from.
  308. //
  309. SuperClass = SysAllocString(CdmClass);
  310. if (SuperClass == NULL)
  311. {
  312. return(WBEM_E_OUT_OF_MEMORY);
  313. }
  314. v.vt = VT_BSTR;
  315. v.bstrVal = SuperClass;
  316. do
  317. {
  318. hr = WmiGetPropertyByName(pCdmServices,
  319. v.bstrVal,
  320. L"__SuperClass",
  321. CIM_STRING,
  322. &vSuper);
  323. if (hr == WBEM_S_NO_ERROR)
  324. {
  325. #ifdef VERBOSE_DEBUG
  326. WmipDebugPrint(("CDMPROV: Class %ws has superclass of %ws\n",
  327. SuperClass, vSuper.bstrVal));
  328. #endif
  329. if (_wcsicmp(v.bstrVal, vSuper.bstrVal) == 0)
  330. {
  331. //
  332. // When the superclass is the same as the base
  333. // class then we are at the top of the class tree
  334. // and so this class must not be in the CDM
  335. // heirarchy. In this case the cdm provider cannot
  336. // support it.
  337. //
  338. hr = WBEM_E_NOT_FOUND;
  339. VariantClear(&vSuper);
  340. } else if (ClassIsCdmBaseClass(vSuper.bstrVal, &IsTestClass)) {
  341. //
  342. // We have found a CDM base class
  343. //
  344. if (! IsTestClass)
  345. {
  346. //
  347. // The CDM base class was not the test class so
  348. // lookup the CdmDiagTest qualifier to find it
  349. //
  350. PWCHAR Name = L"CdmDiagTest";
  351. VARTYPE VarType = VT_BSTR;
  352. hr = WmiGetQualifierListByName(pCdmServices,
  353. CdmClass,
  354. NULL,
  355. 1,
  356. &Name,
  357. &VarType,
  358. &vClass);
  359. if (hr == WBEM_S_NO_ERROR)
  360. {
  361. CdmTestClass = vClass.bstrVal;
  362. #ifdef VERBOSE_DEBUG
  363. WmipDebugPrint(("CDMPROV: Class %ws has a CdmDiagTestClass %ws\n",
  364. CdmClass, CdmTestClass));
  365. #endif
  366. }
  367. } else {
  368. CdmTestClass = SysAllocString(CdmClass);
  369. if (CdmTestClass == NULL)
  370. {
  371. hr = WBEM_E_OUT_OF_MEMORY;
  372. }
  373. #ifdef VERBOSE_DEBUG
  374. WmipDebugPrint(("CDMPROV: Class %ws is already CdmDiagTestClass\n",
  375. CdmClass));
  376. #endif
  377. }
  378. VariantClear(&vSuper);
  379. } else {
  380. //
  381. // This is a more basic class, but is not the CDM base
  382. // class, so we need to continue up the derivation
  383. // chain
  384. //
  385. }
  386. }
  387. VariantClear(&v);
  388. v = vSuper;
  389. } while ((CdmTestClass == NULL) && (hr == WBEM_S_NO_ERROR));
  390. if (hr == WBEM_S_NO_ERROR)
  391. {
  392. PWCHAR Names[11];
  393. VARTYPE VarType[11];
  394. VARIANT Values[11];
  395. //
  396. // Now that we know the CDM Diagnostic test class name we can
  397. // go and discover the rest of the CDM class names via
  398. // the appropriate qualifiers on the Cdm Test class.
  399. //
  400. Names[0] = L"CimClassMapping";
  401. VarType[0] = VT_BSTR;
  402. VariantInit(&Values[0]);
  403. Names[1] = L"CdmDiagResult";
  404. VarType[1] = VT_BSTR;
  405. VariantInit(&Values[1]);
  406. Names[2] = L"CdmDiagSetting";
  407. VarType[2] = VT_BSTR;
  408. VariantInit(&Values[2]);
  409. Names[3] = L"CdmDiagTestForMSE";
  410. VarType[3] = VT_BSTR;
  411. VariantInit(&Values[3]);
  412. Names[4] = L"CdmDiagResultForMSE";
  413. VarType[4] = VT_BSTR;
  414. VariantInit(&Values[4]);
  415. Names[5] = L"CdmDiagResultForTest";
  416. VarType[5] = VT_BSTR;
  417. VariantInit(&Values[5]);
  418. Names[6] = L"CdmDiagTestSoftware";
  419. VarType[6] = VT_BSTR;
  420. VariantInit(&Values[6]);
  421. Names[7] = L"CdmDiagTestInPackage";
  422. VarType[7] = VT_BSTR;
  423. VariantInit(&Values[7]);
  424. Names[8] = L"CdmDiagResultInPackage";
  425. VarType[8] = VT_BSTR;
  426. VariantInit(&Values[8]);
  427. Names[9] = L"CdmDiagSettingForTest";
  428. VarType[9] = VT_BSTR;
  429. VariantInit(&Values[9]);
  430. Names[10] = L"WdmDiagTest";
  431. VarType[10] = VT_BSTR;
  432. VariantInit(&Values[10]);
  433. hr = WmiGetQualifierListByName(pCdmServices,
  434. CdmTestClass,
  435. NULL,
  436. 11,
  437. Names,
  438. VarType,
  439. Values);
  440. if (hr == WBEM_S_NO_ERROR)
  441. {
  442. //
  443. // Remember the class names
  444. //
  445. CimClassMappingClassName = Values[0].bstrVal;
  446. CdmResultClassName = Values[1].bstrVal;
  447. CdmSettingClassName = Values[2].bstrVal;
  448. CdmTestForMSEClassName = Values[3].bstrVal;
  449. CdmResultForMSEClassName = Values[4].bstrVal;
  450. CdmResultForTestClassName = Values[5].bstrVal;
  451. CdmTestForSoftwareClassName = Values[6].bstrVal;
  452. CdmTestInPackageClassName = Values[7].bstrVal;
  453. CdmResultInPackageClassName = Values[8].bstrVal;
  454. CdmSettingForTestClassName = Values[9].bstrVal;
  455. WdmTestClassName = Values[10].bstrVal;
  456. //
  457. // Now that we have got all of the Cdm class names we need
  458. // to get the WdmDiagResult, WdmDiagSetting and
  459. // WdmDiagSettingList classes
  460. //
  461. Names[0] = L"WdmDiagResult";
  462. VariantInit(&Values[0]);
  463. hr = WmiGetQualifierListByName(pCdmServices,
  464. CdmResultClassName,
  465. NULL,
  466. 1,
  467. Names,
  468. VarType,
  469. Values);
  470. if (hr == WBEM_S_NO_ERROR)
  471. {
  472. WdmResultClassName = Values[0].bstrVal;
  473. //
  474. // See if this is an offline diagnostic class
  475. //
  476. Names[0] = L"WdmDiagOfflineResult";
  477. VariantInit(&Values[0]);
  478. hrDontCare = WmiGetQualifierListByName(pCdmServices,
  479. CdmResultClassName,
  480. NULL,
  481. 1,
  482. Names,
  483. VarType,
  484. Values);
  485. if (hrDontCare == WBEM_S_NO_ERROR)
  486. {
  487. WdmOfflineResultClassName = Values[0].bstrVal;
  488. }
  489. Names[0] = L"WdmDiagSetting";
  490. VariantInit(&Values[0]);
  491. hr = WmiGetQualifierListByName(pCdmServices,
  492. CdmSettingClassName,
  493. NULL,
  494. 1,
  495. Names,
  496. VarType,
  497. Values);
  498. if (hr == WBEM_S_NO_ERROR)
  499. {
  500. WdmSettingClassName = Values[0].bstrVal;
  501. Names[0] = L"WdmDiagSettingList";
  502. VariantInit(&Values[0]);
  503. hr = WmiGetQualifierListByName(pCdmServices,
  504. CdmSettingClassName,
  505. NULL,
  506. 1,
  507. Names,
  508. VarType,
  509. Values);
  510. if (hr == WBEM_S_NO_ERROR)
  511. {
  512. //
  513. // Whew, we got all of our class names
  514. // successfully. Setup the CdmTestClassName which
  515. // denotes that we are all setup properly
  516. //
  517. WdmSettingListClassName = Values[0].bstrVal;
  518. CdmTestClassName = CdmTestClass;
  519. }
  520. }
  521. }
  522. }
  523. }
  524. return(hr);
  525. }
  526. HRESULT CTestServices::BuildResultRelPaths(
  527. IN int RelPathIndex,
  528. IN BSTR ExecutionId,
  529. OUT BSTR *ResultRelPath,
  530. OUT BSTR *ResultForMSERelPath,
  531. OUT BSTR *ResultForTestRelPath
  532. )
  533. /*+++
  534. Routine Description:
  535. This routine will create the string names for the CDM Result
  536. relative paths for a specific index. These are for the classes
  537. CIM_DiagnosticResult
  538. CIM_DiagnosticResultForMSE
  539. CIM_DiagnosticResultForTest
  540. Arguments:
  541. RelPathIndex is the index into the list of result objects
  542. ExecutionId is the unique id used for the execution
  543. ResultRelPath returns with the result relpath
  544. ResultForMSERelPath returns with the ResultForMSE association
  545. relpath
  546. ResultForTestRelPath returns with the ResultForTest association
  547. relpath
  548. Return Value:
  549. HRESULT
  550. ---*/
  551. {
  552. PWCHAR RelPath;
  553. HRESULT hr;
  554. ULONG AllocSize;
  555. WCHAR s1[2*MAX_PATH];
  556. WCHAR s2[2*MAX_PATH];
  557. RelPath = (PWCHAR)WmipAlloc(4096);
  558. if (RelPath != NULL)
  559. {
  560. //
  561. // Create the relpaths for the result classes and associations
  562. //
  563. wsprintfW(RelPath, L"%ws.DiagnosticCreationClassName=\"%ws\",DiagnosticName=\"%ws\",ExecutionID=\"%ws\"",
  564. CdmResultClassName,
  565. AddSlashesToStringExW(s1, WdmRelPaths[RelPathIndex]),
  566. CdmTestClassName,
  567. ExecutionId);
  568. *ResultRelPath = SysAllocString(RelPath);
  569. if (*ResultRelPath != NULL)
  570. {
  571. wsprintfW(RelPath, L"%ws.Result=\"%ws\",SystemElement=\"%ws\"",
  572. CdmResultForMSEClassName,
  573. AddSlashesToStringExW(s1, *ResultRelPath),
  574. AddSlashesToStringExW(s2, CimRelPaths[RelPathIndex]));
  575. *ResultForMSERelPath = SysAllocString(RelPath);
  576. wsprintfW(RelPath, L"%ws.DiagnosticResult=\"%ws\",DiagnosticTest=\"%ws\"",
  577. CdmResultForTestClassName,
  578. AddSlashesToStringExW(s1, *ResultRelPath),
  579. AddSlashesToStringExW(s2, CdmTestRelPath));
  580. *ResultForTestRelPath = SysAllocString(RelPath);
  581. if ((*ResultForMSERelPath == NULL) ||
  582. (*ResultForTestRelPath == NULL))
  583. {
  584. SysFreeString(*ResultRelPath);
  585. if (*ResultForMSERelPath != NULL)
  586. {
  587. SysFreeString(*ResultForMSERelPath);
  588. }
  589. if (*ResultForTestRelPath != NULL)
  590. {
  591. SysFreeString(*ResultForTestRelPath);
  592. }
  593. hr = WBEM_E_OUT_OF_MEMORY;
  594. } else {
  595. hr = WBEM_S_NO_ERROR;
  596. }
  597. } else {
  598. hr = WBEM_E_OUT_OF_MEMORY;
  599. }
  600. WmipFree(RelPath);
  601. } else {
  602. hr = WBEM_E_OUT_OF_MEMORY;
  603. }
  604. return(hr);
  605. }
  606. HRESULT CTestServices::BuildTestRelPaths(
  607. void
  608. )
  609. /*+++
  610. Routine Description:
  611. This routine will create the string names for the CDM Test
  612. relative paths for all index
  613. These are for the following classes:
  614. CIM_DiagnosticTest,
  615. CIM_DiagnosticTestForMSE
  616. Arguments:
  617. Return Value:
  618. HRESULT
  619. ---*/
  620. {
  621. PWCHAR RelPath;
  622. int i;
  623. HRESULT hr;
  624. WCHAR s1[MAX_PATH];
  625. WCHAR s2[MAX_PATH];
  626. ULONG AllocSize;
  627. RelPath = (PWCHAR)WmipAlloc(4096);
  628. if (RelPath != NULL)
  629. {
  630. wsprintfW(RelPath, L"%ws.Name=\"%ws\"",
  631. CdmTestClassName, CdmTestClassName);
  632. CdmTestRelPath = SysAllocString(RelPath);
  633. if (CdmTestRelPath != NULL)
  634. {
  635. AllocSize = RelPathCount * sizeof(BSTR);
  636. CdmTestForMSERelPath = (PWCHAR *)WmipAlloc(AllocSize);
  637. if (CdmTestForMSERelPath != NULL)
  638. {
  639. memset(CdmTestForMSERelPath, 0, AllocSize);
  640. hr = WBEM_S_NO_ERROR;
  641. for (i = 0; (i < RelPathCount) && (hr == WBEM_S_NO_ERROR); i++)
  642. {
  643. wsprintfW(RelPath, L"%ws.Antecedent=\"%ws\",Dependent=\"%ws\"",
  644. CdmTestForMSEClassName,
  645. AddSlashesToStringExW(s1, CimRelPaths[i]),
  646. AddSlashesToStringExW(s2, CdmTestRelPath));
  647. CdmTestForMSERelPath[i] = SysAllocString(RelPath);
  648. if (CdmTestForMSERelPath[i] == NULL)
  649. {
  650. SysFreeString(CdmTestRelPath);
  651. CdmTestRelPath = NULL;
  652. FreeTheBSTRArray(CdmTestForMSERelPath, RelPathCount);
  653. CdmTestForMSERelPath = NULL;
  654. hr = WBEM_E_OUT_OF_MEMORY;
  655. }
  656. }
  657. } else {
  658. SysFreeString(CdmTestRelPath);
  659. CdmTestRelPath = NULL;
  660. hr = WBEM_E_OUT_OF_MEMORY;
  661. }
  662. } else {
  663. hr = WBEM_E_OUT_OF_MEMORY;
  664. }
  665. WmipFree(RelPath);
  666. } else {
  667. hr = WBEM_E_OUT_OF_MEMORY;
  668. }
  669. return(hr);
  670. }
  671. HRESULT CTestServices::BuildSettingForTestRelPath(
  672. OUT BSTR *RelPath,
  673. IN IWbemClassObject *pCdmSettingInstance
  674. )
  675. {
  676. WCHAR *Buffer;
  677. VARIANT v;
  678. WCHAR s[MAX_PATH];
  679. HRESULT hr;
  680. WmipAssert(RelPath != NULL);
  681. WmipAssert(pCdmSettingInstance != NULL);
  682. WmipAssert(IsThisInitialized());
  683. Buffer = (WCHAR *)WmipAlloc(4096);
  684. if (Buffer != NULL)
  685. {
  686. hr = WmiGetProperty(pCdmSettingInstance,
  687. L"__RELPATH",
  688. CIM_REFERENCE,
  689. &v);
  690. if (hr == WBEM_S_NO_ERROR)
  691. {
  692. wsprintfW(Buffer, L"%ws.Element=\"%ws.Name=\\\"%ws\\\"\",Setting=\"%ws\"",
  693. CdmSettingForTestClassName,
  694. CdmTestClassName,
  695. CdmTestClassName,
  696. AddSlashesToStringExW(s, v.bstrVal));
  697. VariantClear(&v);
  698. *RelPath = SysAllocString(Buffer);
  699. if (*RelPath != NULL)
  700. {
  701. hr = WBEM_S_NO_ERROR;
  702. } else {
  703. hr = WBEM_E_OUT_OF_MEMORY;
  704. }
  705. }
  706. WmipFree(Buffer);
  707. } else {
  708. hr = WBEM_E_OUT_OF_MEMORY;
  709. }
  710. return(hr);
  711. }
  712. HRESULT CTestServices::ParseSettingList(
  713. VARIANT *SettingList,
  714. CWbemObjectList *CdmSettings,
  715. CBstrArray *CdmSettingForTestRelPath,
  716. int RelPathIndex
  717. )
  718. /*+++
  719. Routine Description:
  720. This routine will obtain all of the settings for a particular test
  721. and store them into a settings list object
  722. Arguments:
  723. SettingList points at a variant continaing an array of embedded
  724. WDM setting objects
  725. CdmSettings points at a WbemObjectList class
  726. CdmSettingForTestRelPath has the relpaths for the cdm settings for
  727. test classes
  728. RelPathIndex is the relpath index associated with the settings
  729. Return Value:
  730. HRESULT
  731. ---*/
  732. {
  733. HRESULT hr;
  734. IWbemClassObject *pWdmSettingInstance;
  735. IWbemClassObject *pCdmSettingInstance;
  736. LONG Index, UBound, LBound, NumberElements;
  737. LONG i;
  738. IUnknown *punk;
  739. BSTR s;
  740. WCHAR SettingId[MAX_PATH];
  741. VARIANT v;
  742. WmipAssert(SettingList != NULL);
  743. WmipAssert(CdmSettingForTestRelPath != NULL);
  744. WmipAssert(SettingList->vt == (CIM_OBJECT | CIM_FLAG_ARRAY));
  745. WmipAssert(CdmSettings != NULL);
  746. hr = WmiGetArraySize(SettingList->parray,
  747. &LBound,
  748. &UBound,
  749. &NumberElements);
  750. if (hr == WBEM_S_NO_ERROR)
  751. {
  752. hr = CdmSettingForTestRelPath->Initialize(NumberElements);
  753. if (hr == WBEM_S_NO_ERROR)
  754. {
  755. hr = CdmSettings->Initialize(NumberElements);
  756. for (i = 0, Index = LBound;
  757. (i < NumberElements) && (hr == WBEM_S_NO_ERROR);
  758. i++, Index++)
  759. {
  760. hr = SafeArrayGetElement(SettingList->parray,
  761. &Index,
  762. &punk);
  763. if (hr == WBEM_S_NO_ERROR)
  764. {
  765. hr = punk->QueryInterface(IID_IWbemClassObject,
  766. (PVOID *)&pWdmSettingInstance);
  767. if (hr == WBEM_S_NO_ERROR)
  768. {
  769. hr = CreateInst(GetCdmServices(),
  770. &pCdmSettingInstance,
  771. CdmSettingClassName,
  772. NULL);
  773. if (hr == WBEM_S_NO_ERROR)
  774. {
  775. hr = CopyBetweenCdmAndWdmClasses(pCdmSettingInstance,
  776. pWdmSettingInstance,
  777. TRUE);
  778. if (hr == WBEM_S_NO_ERROR)
  779. {
  780. //
  781. // Set CdmSetting.SettingId to a unique
  782. // setting id
  783. //
  784. wsprintfW(SettingId, L"%ws_%d_%d",
  785. CdmTestClassName,
  786. RelPathIndex,
  787. i);
  788. s = SysAllocString(SettingId);
  789. if (s != NULL)
  790. {
  791. VariantInit(&v);
  792. v.vt = VT_BSTR;
  793. v.bstrVal = s;
  794. hr = WmiSetProperty(pCdmSettingInstance,
  795. L"SettingId",
  796. &v);
  797. VariantClear(&v);
  798. if (hr == WBEM_S_NO_ERROR)
  799. {
  800. hr = BuildSettingForTestRelPath(&s,
  801. pCdmSettingInstance);
  802. if (hr == WBEM_S_NO_ERROR)
  803. {
  804. CdmSettingForTestRelPath->Set(i,
  805. s);
  806. CdmSettings->Set(i,
  807. pCdmSettingInstance,
  808. TRUE);
  809. }
  810. }
  811. } else {
  812. hr = WBEM_E_OUT_OF_MEMORY;
  813. }
  814. }
  815. if (hr != WBEM_S_NO_ERROR)
  816. {
  817. pCdmSettingInstance->Release();
  818. }
  819. }
  820. pWdmSettingInstance->Release();
  821. }
  822. punk->Release();
  823. }
  824. }
  825. }
  826. }
  827. return(hr);
  828. }
  829. HRESULT CTestServices::GetCdmTestSettings(
  830. void
  831. )
  832. /*+++
  833. Routine Description:
  834. This routine will obtain all of the CDM settings available for all
  835. instnaces of the test
  836. Arguments:
  837. Return Value:
  838. HRESULT
  839. ---*/
  840. {
  841. WCHAR Query[MAX_PATH * 2];
  842. WCHAR s[MAX_PATH];
  843. ULONG AllocSize;
  844. BSTR sWQL, sQuery;
  845. IEnumWbemClassObject *pWdmEnumInstances;
  846. IWbemClassObject *pWdmInstance;
  847. int i;
  848. ULONG Count;
  849. HRESULT hr;
  850. VARIANT SettingList;
  851. //
  852. // We need to get all of the settings exposed by the WDM class and
  853. // then convert them to Cdm classes.
  854. //
  855. sWQL = SysAllocString(L"WQL");
  856. if (sWQL != NULL)
  857. {
  858. AllocSize = RelPathCount * sizeof(CWbemObjectList *);
  859. CdmSettingsList = (CWbemObjectList **)WmipAlloc(AllocSize);
  860. if (CdmSettingsList != NULL)
  861. {
  862. memset(CdmSettingsList, 0, AllocSize);
  863. AllocSize = RelPathCount * sizeof(CBstrArray *);
  864. CdmSettingForTestRelPath = (CBstrArray **)WmipAlloc(AllocSize);
  865. if (CdmSettingForTestRelPath != NULL)
  866. {
  867. memset(CdmSettingForTestRelPath, 0, AllocSize);
  868. hr = WBEM_S_NO_ERROR;
  869. for (i = 0; (i < RelPathCount) && (hr == WBEM_S_NO_ERROR); i++)
  870. {
  871. CdmSettingsList[i] = new CWbemObjectList();
  872. CdmSettingForTestRelPath[i] = new CBstrArray;
  873. wsprintfW(Query, L"select * from %ws where InstanceName = \"%ws\"",
  874. WdmSettingListClassName,
  875. AddSlashesToStringW(s, WdmInstanceNames[i]));
  876. sQuery = SysAllocString(Query);
  877. if (sQuery != NULL)
  878. {
  879. hr = pWdmServices->ExecQuery(sWQL,
  880. sQuery,
  881. WBEM_FLAG_FORWARD_ONLY |
  882. WBEM_FLAG_ENSURE_LOCATABLE,
  883. NULL,
  884. &pWdmEnumInstances);
  885. if (hr == WBEM_S_NO_ERROR)
  886. {
  887. hr = pWdmEnumInstances->Next(WBEM_INFINITE,
  888. 1,
  889. &pWdmInstance,
  890. &Count);
  891. if ((hr == WBEM_S_NO_ERROR) &&
  892. (Count == 1))
  893. {
  894. hr = WmiGetProperty(pWdmInstance,
  895. L"SettingList",
  896. CIM_FLAG_ARRAY | CIM_OBJECT,
  897. &SettingList);
  898. if (hr == WBEM_S_NO_ERROR)
  899. {
  900. if (SettingList.vt & VT_ARRAY)
  901. {
  902. hr = ParseSettingList(&SettingList,
  903. CdmSettingsList[i],
  904. CdmSettingForTestRelPath[i],
  905. i);
  906. } else {
  907. hr = WBEM_E_FAILED;
  908. }
  909. VariantClear(&SettingList);
  910. }
  911. pWdmInstance->Release();
  912. }
  913. pWdmEnumInstances->Release();
  914. } else {
  915. //
  916. // There must not be any predefined settings
  917. //
  918. hr = CdmSettingsList[i]->Initialize(0);
  919. }
  920. SysFreeString(sQuery);
  921. } else {
  922. hr = WBEM_E_OUT_OF_MEMORY;
  923. }
  924. }
  925. } else {
  926. hr = WBEM_E_OUT_OF_MEMORY;
  927. }
  928. } else {
  929. hr = WBEM_E_OUT_OF_MEMORY;
  930. }
  931. SysFreeString(sWQL);
  932. } else {
  933. hr = WBEM_E_OUT_OF_MEMORY;
  934. }
  935. return(hr);
  936. }
  937. HRESULT CTestServices::InitializeCdmClasses(
  938. PWCHAR CdmClass
  939. )
  940. /*+++
  941. Routine Description:
  942. This routine will setup this class and initialize everything so
  943. that the provider can interact with the CDM and WDM classes
  944. Arguments:
  945. CdmClass is the name of the CDM class
  946. Return Value:
  947. HRESULT
  948. ---*/
  949. {
  950. HRESULT hr, hrDontCare;
  951. ULONG AllocSize;
  952. int i;
  953. WmipAssert(CdmClass != NULL);
  954. WmipAssert(! IsThisInitialized());
  955. //
  956. // We assume that this method will always be the first one called
  957. // by the class provider
  958. //
  959. if ((pCimServices == NULL) &&
  960. (pWdmServices == NULL))
  961. {
  962. hr = TestInfoInitialize();
  963. if (hr != WBEM_S_NO_ERROR)
  964. {
  965. return(hr);
  966. }
  967. }
  968. //
  969. // We are given a random CDM class name - it could be a test,
  970. // setting, association, etc so we need to go from that class name
  971. // and obtain all of the class names related to this diagnostic
  972. //
  973. hr = GetCdmClassNamesFromOne(CdmClass);
  974. if (hr == WBEM_S_NO_ERROR)
  975. {
  976. //
  977. // Use worker function to determine which
  978. // Wdm relpaths map to which Cdm relpaths
  979. //
  980. hr = MapWdmClassToCimClass(pWdmServices,
  981. pCimServices,
  982. WdmTestClassName,
  983. CimClassMappingClassName,
  984. &PnPDeviceIdsX,
  985. &WdmInstanceNames,
  986. &WdmRelPaths,
  987. &CimRelPaths,
  988. &RelPathCount);
  989. if (hr == WBEM_S_NO_ERROR)
  990. {
  991. //
  992. // Obtain all of the possible settings for this test
  993. //
  994. hr = GetCdmTestSettings();
  995. if (hr == WBEM_S_NO_ERROR)
  996. {
  997. //
  998. // Initialize the results object lists
  999. //
  1000. CdmResultsList = new CResultList[RelPathCount];
  1001. //
  1002. // Build the test class instance relpaths
  1003. //
  1004. hr = BuildTestRelPaths();
  1005. // @@BEGIN_DDKSPLIT
  1006. #ifdef REBOOT_DIAGNOSTICS
  1007. if (hr == WBEM_S_NO_ERROR)
  1008. {
  1009. hrDontCare = GatherRebootResults();
  1010. }
  1011. #else
  1012. //
  1013. // Reboot diagnostics are not yet supported
  1014. //
  1015. #endif
  1016. // @@END_DDKSPLIT
  1017. }
  1018. }
  1019. }
  1020. return(hr);
  1021. }
  1022. IWbemServices *CTestServices::GetWdmServices(
  1023. void
  1024. )
  1025. /*+++
  1026. Routine Description:
  1027. Accessor for the WDM namespace IWbemServices
  1028. Arguments:
  1029. Return Value:
  1030. IWbemServices
  1031. ---*/
  1032. {
  1033. WmipAssert(pWdmServices != NULL);
  1034. return(pWdmServices);
  1035. }
  1036. IWbemServices *CTestServices::GetCdmServices(
  1037. void
  1038. )
  1039. /*+++
  1040. Routine Description:
  1041. Accessor for the CIM namespace IWbemServices
  1042. Arguments:
  1043. Return Value:
  1044. IWbemServices
  1045. ---*/
  1046. {
  1047. WmipAssert(pCimServices != NULL);
  1048. return(pCimServices);
  1049. }
  1050. HRESULT CTestServices::WdmPropertyToCdmProperty(
  1051. IN IWbemClassObject *pCdmClassInstance,
  1052. IN IWbemClassObject *pWdmClassInstance,
  1053. IN BSTR PropertyName,
  1054. IN OUT VARIANT *PropertyValue,
  1055. IN CIMTYPE CdmCimType,
  1056. IN CIMTYPE WdmCimType
  1057. )
  1058. /*+++
  1059. Routine Description:
  1060. This routine will convert a property in a Wdm class into the form
  1061. required for the property in the Cdm class.
  1062. Arguments:
  1063. pCdmClassInstance is the instnace of the Cdm class that will get
  1064. the property value
  1065. pWdmClassInstance is the instance of the Wdm class that has the
  1066. property value
  1067. PropertyName is the name of the property in the Wdm and Cdm classes
  1068. PropertyValue on entry has the value of the property in the Wdm
  1069. instance and on return has the value to set in the Cdm instance
  1070. CdmCimType is the property type for the property in the Cdm
  1071. instance
  1072. WdmCimType is the property type for the property in the Wdm
  1073. instance
  1074. Return Value:
  1075. HRESULT
  1076. ---*/
  1077. {
  1078. HRESULT hr;
  1079. BSTR Mapped;
  1080. VARIANT vClassName;
  1081. CIMTYPE BaseWdmCimType, BaseCdmCimType;
  1082. CIMTYPE WdmCimArray, CdmCimArray;
  1083. LONG i;
  1084. WmipAssert(pCdmClassInstance != NULL);
  1085. WmipAssert(pWdmClassInstance != NULL);
  1086. WmipAssert(PropertyName != NULL);
  1087. WmipAssert(PropertyValue != NULL);
  1088. WmipAssert(IsThisInitialized());
  1089. //
  1090. // Rules for converting Wdm Classes into Cdm Classes
  1091. // Wdm Class Type Cdm Class Type Conversion Done
  1092. // enumeration string Build string from enum
  1093. //
  1094. BaseWdmCimType = WdmCimType & ~CIM_FLAG_ARRAY;
  1095. BaseCdmCimType = CdmCimType & ~CIM_FLAG_ARRAY;
  1096. WdmCimArray = WdmCimType & CIM_FLAG_ARRAY;
  1097. CdmCimArray = CdmCimType & CIM_FLAG_ARRAY;
  1098. if (((BaseWdmCimType == CIM_UINT32) ||
  1099. (BaseWdmCimType == CIM_UINT16) ||
  1100. (BaseWdmCimType == CIM_UINT8)) &&
  1101. (BaseCdmCimType == CIM_STRING) &&
  1102. (WdmCimArray == CdmCimArray) &&
  1103. (PropertyValue->vt != VT_NULL))
  1104. {
  1105. hr = WmiGetProperty(pWdmClassInstance,
  1106. L"__Class",
  1107. CIM_STRING,
  1108. &vClassName);
  1109. if (hr == WBEM_S_NO_ERROR)
  1110. {
  1111. if (WdmCimArray)
  1112. {
  1113. SAFEARRAYBOUND Bounds;
  1114. SAFEARRAY *Array;
  1115. ULONG Value;
  1116. LONG UBound, LBound, Elements, Index;
  1117. //
  1118. // We have an array of enumeration types to convert into an
  1119. // array of corresponding strings
  1120. //
  1121. hr = WmiGetArraySize(PropertyValue->parray,
  1122. &LBound,
  1123. &UBound,
  1124. &Elements);
  1125. if (hr == WBEM_S_NO_ERROR)
  1126. {
  1127. Bounds.lLbound = LBound;
  1128. Bounds.cElements = Elements;
  1129. Array = SafeArrayCreate(VT_BSTR,
  1130. 1,
  1131. &Bounds);
  1132. if (Array != NULL)
  1133. {
  1134. for (i = 0;
  1135. (i < Elements) && (hr == WBEM_S_NO_ERROR);
  1136. i++)
  1137. {
  1138. Index = i + LBound;
  1139. hr = SafeArrayGetElement(PropertyValue->parray,
  1140. &Index,
  1141. &Value);
  1142. if (hr == WBEM_S_NO_ERROR)
  1143. {
  1144. hr = LookupValueMap(GetWdmServices(),
  1145. vClassName.bstrVal,
  1146. PropertyName,
  1147. Value,
  1148. &Mapped);
  1149. if (hr == WBEM_S_NO_ERROR)
  1150. {
  1151. hr = SafeArrayPutElement(Array,
  1152. &Index,
  1153. Mapped);
  1154. }
  1155. }
  1156. }
  1157. if (hr == WBEM_S_NO_ERROR)
  1158. {
  1159. VariantClear(PropertyValue);
  1160. PropertyValue->vt = VT_BSTR | VT_ARRAY;
  1161. PropertyValue->parray = Array;
  1162. } else {
  1163. SafeArrayDestroy(Array);
  1164. }
  1165. } else {
  1166. hr = WBEM_E_OUT_OF_MEMORY;
  1167. }
  1168. }
  1169. } else {
  1170. //
  1171. // We need to convert a scalar enumeration type into the
  1172. // corresponding string. First we need to get the Wdm class
  1173. // object and from that get the Values and ValueMap qualifiers
  1174. // to determine the string we need to place into the cim class
  1175. //
  1176. hr = LookupValueMap(GetWdmServices(),
  1177. vClassName.bstrVal,
  1178. PropertyName,
  1179. PropertyValue->uiVal,
  1180. &Mapped);
  1181. if (hr == WBEM_S_NO_ERROR)
  1182. {
  1183. VariantClear(PropertyValue);
  1184. PropertyValue->vt = VT_BSTR;
  1185. PropertyValue->bstrVal = Mapped;
  1186. }
  1187. }
  1188. VariantClear(&vClassName);
  1189. }
  1190. } else {
  1191. //
  1192. // No conversion needs to occur
  1193. //
  1194. hr = WBEM_S_NO_ERROR;
  1195. }
  1196. return(hr);
  1197. }
  1198. HRESULT CTestServices::CdmPropertyToWdmProperty(
  1199. IN IWbemClassObject *pWdmClassInstance,
  1200. IN IWbemClassObject *pCdmClassInstance,
  1201. IN BSTR PropertyName,
  1202. IN OUT VARIANT *PropertyValue,
  1203. IN CIMTYPE WdmCimType,
  1204. IN CIMTYPE CdmCimType
  1205. )
  1206. /*+++
  1207. Routine Description:
  1208. This routine will convert a property in a Cdm class into the form
  1209. required for the property in the Wdm class.
  1210. Arguments:
  1211. pWdmClassInstance is the instance of the Wdm class that has the
  1212. property value
  1213. pCdmClassInstance is the instnace of the Cdm class that will get
  1214. the property value
  1215. PropertyName is the name of the property in the Wdm and Cdm classes
  1216. PropertyValue on entry has the value of the property in the Wdm
  1217. instance and on return has the value to set in the Cdm instance
  1218. WdmCimType is the property type for the property in the Wdm
  1219. instance
  1220. CdmCimType is the property type for the property in the Cdm
  1221. instance
  1222. Return Value:
  1223. HRESULT
  1224. ---*/
  1225. {
  1226. WmipAssert(pCdmClassInstance != NULL);
  1227. WmipAssert(pWdmClassInstance != NULL);
  1228. WmipAssert(PropertyName != NULL);
  1229. WmipAssert(PropertyValue != NULL);
  1230. WmipAssert(IsThisInitialized());
  1231. //
  1232. // Rules for converting Wdm Classes into Cdm Classes
  1233. // Wdm Class Type Cdm Class Type Conversion Done
  1234. //
  1235. //
  1236. // There are no conversion requirements when converting from Cdm to
  1237. // Wdm instances
  1238. //
  1239. return(WBEM_S_NO_ERROR);
  1240. }
  1241. HRESULT CTestServices::CopyBetweenCdmAndWdmClasses(
  1242. IN IWbemClassObject *pDestinationInstance,
  1243. IN IWbemClassObject *pSourceInstance,
  1244. IN BOOLEAN WdmToCdm
  1245. )
  1246. /*+++
  1247. Routine Description:
  1248. This routine will do the work to copy and convert all properties in
  1249. an instance of a Wdm or Cdm class to an instance of a Cdm or Wdm
  1250. class.
  1251. Note that properties from one instance are only copied to
  1252. properties of another instance when the property names are
  1253. identical. No assumption is ever made on the name of the
  1254. properties. The only info used to determine how to convert a
  1255. property is based upon the source and destination cim type.
  1256. Arguments:
  1257. pDestinationInstance is the class instance that the properties will
  1258. be copied into
  1259. pSourceInstance is the class instance that the properties will be
  1260. copied from
  1261. WdmToCdm is TRUE if copying from Wdm to Cdm, else FALSE
  1262. Return Value:
  1263. HRESULT
  1264. ---*/
  1265. {
  1266. HRESULT hr;
  1267. VARIANT PropertyValue;
  1268. BSTR PropertyName;
  1269. CIMTYPE SourceCimType, DestCimType;
  1270. HRESULT hrDontCare;
  1271. WmipAssert(pDestinationInstance != NULL);
  1272. WmipAssert(pSourceInstance != NULL);
  1273. WmipAssert(IsThisInitialized());
  1274. //
  1275. // Now we need to move over all of the properties from the source
  1276. // class into the destination class. Note that some properties need
  1277. // some special effort such as OtherCharacteristics which needs
  1278. // to be converted from an enumeration value (in wdm) to a
  1279. // string (in CDM).
  1280. //
  1281. // Our strategy is to enumerate all of the proeprties in the
  1282. // source class and then look for a property with the same name
  1283. // and type in the destination class. If so we just copy over the
  1284. // value. If the data type is different we need to do some
  1285. // conversion.
  1286. //
  1287. hr = pSourceInstance->BeginEnumeration(WBEM_FLAG_NONSYSTEM_ONLY);
  1288. if (hr == WBEM_S_NO_ERROR)
  1289. {
  1290. do
  1291. {
  1292. //
  1293. // Get a property from the source class
  1294. //
  1295. hr = pSourceInstance->Next(0,
  1296. &PropertyName,
  1297. &PropertyValue,
  1298. &SourceCimType,
  1299. NULL);
  1300. if (hr == WBEM_S_NO_ERROR)
  1301. {
  1302. //
  1303. // Try to get a property with the same name from the
  1304. // dest class. If the identically named property does
  1305. // not exist in the destination class then it is ignored
  1306. //
  1307. hrDontCare = pDestinationInstance->Get(PropertyName,
  1308. 0,
  1309. NULL,
  1310. &DestCimType,
  1311. NULL);
  1312. if (hrDontCare == WBEM_S_NO_ERROR)
  1313. {
  1314. if (WdmToCdm)
  1315. {
  1316. hr = WdmPropertyToCdmProperty(pDestinationInstance,
  1317. pSourceInstance,
  1318. PropertyName,
  1319. &PropertyValue,
  1320. DestCimType,
  1321. SourceCimType);
  1322. } else {
  1323. hr = CdmPropertyToWdmProperty(pDestinationInstance,
  1324. pSourceInstance,
  1325. PropertyName,
  1326. &PropertyValue,
  1327. DestCimType,
  1328. SourceCimType);
  1329. }
  1330. if (hr == WBEM_S_NO_ERROR)
  1331. {
  1332. //
  1333. // Try to place the transformed property into the
  1334. // destination class.
  1335. //
  1336. hr = pDestinationInstance->Put(PropertyName,
  1337. 0,
  1338. &PropertyValue,
  1339. 0);
  1340. }
  1341. }
  1342. SysFreeString(PropertyName);
  1343. VariantClear(&PropertyValue);
  1344. } else if (hr == WBEM_S_NO_MORE_DATA) {
  1345. //
  1346. // This signifies the end of the enumerations
  1347. //
  1348. hr = WBEM_S_NO_ERROR;
  1349. break;
  1350. }
  1351. } while (hr == WBEM_S_NO_ERROR);
  1352. pSourceInstance->EndEnumeration();
  1353. }
  1354. return(hr);
  1355. }
  1356. HRESULT CTestServices::QueryWdmTest(
  1357. OUT IWbemClassObject *pCdmTest,
  1358. IN int RelPathIndex
  1359. )
  1360. /*+++
  1361. Routine Description:
  1362. This routine will query the Wdm test class instance and copy the results
  1363. into the Cdm Test class instance
  1364. Arguments:
  1365. pCdmTest points at the Cdm Test class instance
  1366. RelPathIndex
  1367. Return Value:
  1368. HRESULT
  1369. ---*/
  1370. {
  1371. IWbemClassObject *pWdmTest;
  1372. HRESULT hr;
  1373. WmipAssert(pCdmTest != NULL);
  1374. WmipAssert(IsThisInitialized());
  1375. hr = ConnectToWdmClass(RelPathIndex,
  1376. &pWdmTest);
  1377. if (hr == WBEM_S_NO_ERROR)
  1378. {
  1379. hr = CopyBetweenCdmAndWdmClasses(pCdmTest,
  1380. pWdmTest,
  1381. TRUE);
  1382. pWdmTest->Release();
  1383. }
  1384. return(hr);
  1385. }
  1386. #define OBJECTCOLONSIZE (((sizeof(L"object:")/sizeof(WCHAR)))-1)
  1387. HRESULT CTestServices::FillTestInParams(
  1388. OUT IWbemClassObject *pInParamInstance,
  1389. IN IWbemClassObject *pCdmSettings,
  1390. IN BSTR ExecutionID
  1391. )
  1392. {
  1393. HRESULT hr;
  1394. IWbemServices *pWdmServices;
  1395. VARIANT v;
  1396. VARIANT PropertyValues[2];
  1397. PWCHAR PropertyNames[2];
  1398. PWCHAR ClassName;
  1399. IWbemClassObject *pRunTestIn;
  1400. IWbemClassObject *pWdmSettingsInstance;
  1401. IWbemQualifierSet *pQualSet;
  1402. WmipAssert(pInParamInstance != NULL);
  1403. pWdmServices = GetWdmServices();
  1404. pRunTestIn = NULL;
  1405. //
  1406. // Get the name of the embedded class for the RunTestIn input
  1407. // parameter. This should be an embedded class that contains all of
  1408. // the input parameters. We get this from the __CIMTYPE qualifier
  1409. // on the RunTestIn property.
  1410. //
  1411. // We need to do this since the wmiprov can't
  1412. // handle anything with an embedded object as an input parameter to
  1413. // a method
  1414. //
  1415. hr = pInParamInstance->GetPropertyQualifierSet(L"RunTestIn",
  1416. &pQualSet);
  1417. if (hr == WBEM_S_NO_ERROR)
  1418. {
  1419. hr = WmiGetQualifier(pQualSet,
  1420. L"CIMTYPE",
  1421. VT_BSTR,
  1422. &v);
  1423. if (hr == WBEM_S_NO_ERROR)
  1424. {
  1425. if (_wcsnicmp(v.bstrVal, L"object:", OBJECTCOLONSIZE) == 0)
  1426. {
  1427. ClassName = v.bstrVal + OBJECTCOLONSIZE;
  1428. hr = CreateInst(pWdmServices,
  1429. &pRunTestIn,
  1430. ClassName,
  1431. NULL);
  1432. if (hr == WBEM_S_NO_ERROR)
  1433. {
  1434. hr = CreateInst(pWdmServices,
  1435. &pWdmSettingsInstance,
  1436. WdmSettingClassName,
  1437. NULL);
  1438. if (hr == WBEM_S_NO_ERROR)
  1439. {
  1440. if (pCdmSettings != NULL)
  1441. {
  1442. hr = CopyBetweenCdmAndWdmClasses(pWdmSettingsInstance,
  1443. pCdmSettings,
  1444. FALSE);
  1445. }
  1446. if (hr == WBEM_S_NO_ERROR)
  1447. {
  1448. PWCHAR PropertyNames[2];
  1449. VARIANT PropertyValues[2];
  1450. PropertyNames[0] = L"DiagSettings";
  1451. PropertyValues[0].vt = VT_UNKNOWN;
  1452. PropertyValues[0].punkVal = pWdmSettingsInstance;
  1453. PropertyNames[1] = L"ExecutionID";
  1454. PropertyValues[1].vt = VT_BSTR;
  1455. PropertyValues[1].bstrVal = ExecutionID;
  1456. hr = WmiSetPropertyList(pRunTestIn,
  1457. 2,
  1458. PropertyNames,
  1459. PropertyValues);
  1460. if (hr == WBEM_S_NO_ERROR)
  1461. {
  1462. PropertyValues[0].vt = VT_UNKNOWN;
  1463. PropertyValues[0].punkVal = pRunTestIn;
  1464. hr = WmiSetProperty(pInParamInstance,
  1465. L"RunTestIn",
  1466. &PropertyValues[0]);
  1467. }
  1468. }
  1469. //
  1470. // We can release here since we know that wbem
  1471. // took a ref count when we set the property
  1472. //
  1473. pWdmSettingsInstance->Release();
  1474. }
  1475. }
  1476. }
  1477. VariantClear(&v);
  1478. }
  1479. pQualSet->Release();
  1480. }
  1481. if ((hr != WBEM_S_NO_ERROR) && (pRunTestIn != NULL))
  1482. {
  1483. pRunTestIn->Release();
  1484. }
  1485. return(hr);
  1486. }
  1487. HRESULT CTestServices::GetTestOutParams(
  1488. IN IWbemClassObject *OutParams,
  1489. OUT IWbemClassObject *pCdmResult,
  1490. OUT ULONG *Result
  1491. )
  1492. {
  1493. HRESULT hr;
  1494. VARIANT v;
  1495. IWbemClassObject *pRunTestOut;
  1496. IWbemClassObject *pWdmResult;
  1497. WmipAssert(OutParams != NULL);
  1498. WmipAssert(pCdmResult != NULL);
  1499. WmipAssert(Result != NULL);
  1500. hr = WmiGetProperty(OutParams,
  1501. L"RunTestOut",
  1502. CIM_OBJECT,
  1503. &v);
  1504. if (hr == WBEM_S_NO_ERROR)
  1505. {
  1506. hr = v.punkVal->QueryInterface(IID_IWbemClassObject,
  1507. (PVOID *)&pRunTestOut);
  1508. VariantClear(&v);
  1509. if (hr == WBEM_S_NO_ERROR)
  1510. {
  1511. hr = WmiGetProperty(pRunTestOut,
  1512. L"Result",
  1513. CIM_UINT32,
  1514. &v);
  1515. if (hr == WBEM_S_NO_ERROR)
  1516. {
  1517. *Result = v.ulVal;
  1518. VariantClear(&v);
  1519. hr = WmiGetProperty(pRunTestOut,
  1520. L"DiagResult",
  1521. CIM_OBJECT,
  1522. &v);
  1523. if (hr == WBEM_S_NO_ERROR)
  1524. {
  1525. if (v.vt != VT_NULL)
  1526. {
  1527. hr = v.punkVal->QueryInterface(IID_IWbemClassObject,
  1528. (PVOID *)&pWdmResult);
  1529. if (hr == WBEM_S_NO_ERROR)
  1530. {
  1531. hr = CopyBetweenCdmAndWdmClasses(pCdmResult,
  1532. pWdmResult,
  1533. TRUE);
  1534. pWdmResult->Release();
  1535. }
  1536. } else {
  1537. hr = WBEM_E_FAILED;
  1538. }
  1539. VariantClear(&v);
  1540. }
  1541. }
  1542. pRunTestOut->Release();
  1543. }
  1544. }
  1545. return(hr);
  1546. }
  1547. LONG GlobalExecutionID;
  1548. BSTR CTestServices::GetExecutionID(
  1549. void
  1550. )
  1551. {
  1552. BSTR s;
  1553. WCHAR x[MAX_PATH];
  1554. //
  1555. // We make up a unique execution ID for this test by using the
  1556. // current date and time plus a unique counter. The execution id
  1557. // must be unique.
  1558. //
  1559. s = GetCurrentDateTime();
  1560. if (s != NULL)
  1561. {
  1562. wsprintfW(x, L"%ws*%08x", s, InterlockedIncrement(&GlobalExecutionID));
  1563. SysFreeString(s);
  1564. s = SysAllocString(x);
  1565. }
  1566. return(s);
  1567. }
  1568. HRESULT CTestServices::ExecuteWdmTest(
  1569. IN IWbemClassObject *pCdmSettings,
  1570. OUT IWbemClassObject *pCdmResult,
  1571. IN int RelPathIndex,
  1572. OUT ULONG *Result,
  1573. OUT BSTR *ExecutionID
  1574. )
  1575. /*+++
  1576. Routine Description:
  1577. This routine will execute a test on the Wdm class instance and copy
  1578. the results back to the Cdm results instance, along with creating
  1579. all result instance relpaths
  1580. Arguments:
  1581. pCdmSettings is a CDM settings instance that is used to create the
  1582. wdm settings instance that is used to run the test. This may be
  1583. NULL if default test settings are assumed
  1584. pCdmResult is a CDM result instance that returns with the results
  1585. form the test
  1586. RelPathIndex
  1587. *Result returns with the return value result from the test
  1588. *ExecutionId returns with the unique execution id for the test
  1589. Return Value:
  1590. HRESULT
  1591. ---*/
  1592. {
  1593. HRESULT hr;
  1594. IWbemClassObject *pOutParams;
  1595. IWbemClassObject *pInParamInstance;
  1596. BSTR s;
  1597. WmipAssert(pCdmResult != NULL);
  1598. WmipAssert(Result != NULL);
  1599. WmipAssert(ExecutionID != NULL);
  1600. WmipAssert(IsThisInitialized());
  1601. //
  1602. // Run in the caller's context so that if he is not able to access
  1603. // the WDM classes, he can't
  1604. //
  1605. hr = CoImpersonateClient();
  1606. if (hr != WBEM_S_NO_ERROR)
  1607. {
  1608. return(hr);
  1609. }
  1610. *ExecutionID = GetExecutionID();
  1611. if (*ExecutionID != NULL)
  1612. {
  1613. s = SysAllocString(L"RunTest");
  1614. if (s != NULL)
  1615. {
  1616. hr = GetMethodInParamInstance(GetWdmServices(),
  1617. WdmTestClassName,
  1618. s,
  1619. &pInParamInstance);
  1620. if (hr == WBEM_S_NO_ERROR)
  1621. {
  1622. hr = FillTestInParams(pInParamInstance,
  1623. pCdmSettings,
  1624. *ExecutionID);
  1625. if (hr == WBEM_S_NO_ERROR)
  1626. {
  1627. hr = pWdmServices->ExecMethod(WdmRelPaths[RelPathIndex],
  1628. s,
  1629. 0,
  1630. NULL,
  1631. pInParamInstance,
  1632. &pOutParams,
  1633. NULL);
  1634. if (hr == WBEM_S_NO_ERROR)
  1635. {
  1636. hr = GetTestOutParams(pOutParams,
  1637. pCdmResult,
  1638. Result);
  1639. if (hr == WBEM_S_NO_ERROR)
  1640. {
  1641. //
  1642. // if the test requires the device being
  1643. // taken offline then do that now
  1644. //
  1645. hr = OfflineDeviceForTest(pCdmResult,
  1646. *ExecutionID,
  1647. RelPathIndex);
  1648. }
  1649. pOutParams->Release();
  1650. }
  1651. }
  1652. pInParamInstance->Release();
  1653. }
  1654. SysFreeString(s);
  1655. } else {
  1656. hr = WBEM_E_OUT_OF_MEMORY;
  1657. }
  1658. } else {
  1659. hr = WBEM_E_OUT_OF_MEMORY;
  1660. }
  1661. CoRevertToSelf();
  1662. return(hr);
  1663. }
  1664. HRESULT CTestServices::StopWdmTest(
  1665. IN int RelPathIndex,
  1666. OUT ULONG *Result,
  1667. OUT BOOLEAN *TestingStopped
  1668. )
  1669. /*+++
  1670. Routine Description:
  1671. This routine will attempt to stop an executing WDM test
  1672. Arguments:
  1673. RelPathIndex
  1674. *Result returns with the result value
  1675. *TestingStopped returns TRUE if testing was stopped successfully
  1676. Return Value:
  1677. HRESULT
  1678. ---*/
  1679. {
  1680. HRESULT hr;
  1681. IWbemClassObject *OutParams;
  1682. BSTR s;
  1683. IWbemServices *pWdmServices;
  1684. VARIANT Value;
  1685. WmipAssert(Result != NULL);
  1686. WmipAssert(TestingStopped != NULL);
  1687. WmipAssert(IsThisInitialized());
  1688. //
  1689. // Run in the caller's context so that if he is not able to access
  1690. // the WDM classes, he can't
  1691. //
  1692. hr = CoImpersonateClient();
  1693. if (hr != WBEM_S_NO_ERROR)
  1694. {
  1695. return(hr);
  1696. }
  1697. pWdmServices = GetWdmServices();
  1698. s = SysAllocString(L"DiscontinueTest");
  1699. if (s != NULL)
  1700. {
  1701. hr = pWdmServices->ExecMethod(WdmRelPaths[RelPathIndex],
  1702. s,
  1703. 0,
  1704. NULL,
  1705. NULL,
  1706. &OutParams,
  1707. NULL);
  1708. if (hr == WBEM_S_NO_ERROR)
  1709. {
  1710. hr = WmiGetProperty(OutParams,
  1711. L"Result",
  1712. CIM_UINT32,
  1713. &Value);
  1714. if (hr == WBEM_S_NO_ERROR)
  1715. {
  1716. *Result = Value.ulVal;
  1717. VariantClear(&Value);
  1718. hr = WmiGetProperty(OutParams,
  1719. L"TestingStopped",
  1720. CIM_BOOLEAN,
  1721. &Value);
  1722. if (hr == WBEM_S_NO_ERROR)
  1723. {
  1724. *TestingStopped = (Value.boolVal != 0) ? TRUE : FALSE;
  1725. VariantClear(&Value);
  1726. }
  1727. }
  1728. OutParams->Release();
  1729. }
  1730. SysFreeString(s);
  1731. } else {
  1732. hr = WBEM_E_OUT_OF_MEMORY;
  1733. }
  1734. CoRevertToSelf();
  1735. return(hr);
  1736. }
  1737. HRESULT CTestServices::GetRelPathIndex(
  1738. BSTR CimRelPath,
  1739. int *RelPathIndex
  1740. )
  1741. /*+++
  1742. Routine Description:
  1743. This routine will return the RelPathIndex for a specific Cim
  1744. Relpath
  1745. Arguments:
  1746. CimRelPath is the Cim relpath
  1747. *RelPathIndex returns with the relpath index
  1748. Return Value:
  1749. HRESULT
  1750. ---*/
  1751. {
  1752. int i;
  1753. WmipAssert(CimRelPath != NULL);
  1754. WmipAssert(CimRelPaths != NULL);
  1755. WmipAssert(WdmRelPaths != NULL);
  1756. WmipAssert(IsThisInitialized());
  1757. for (i = 0; i < RelPathCount; i++)
  1758. {
  1759. if (_wcsicmp(CimRelPath, CimRelPaths[i]) == 0)
  1760. {
  1761. *RelPathIndex = i;
  1762. return(WBEM_S_NO_ERROR);
  1763. }
  1764. }
  1765. return(WBEM_E_NOT_FOUND);
  1766. }
  1767. HRESULT CTestServices::ConnectToWdmClass(
  1768. IN int RelPathIndex,
  1769. OUT IWbemClassObject **ppWdmClassObject
  1770. )
  1771. /*+++
  1772. Routine Description:
  1773. This routine will return a IWbemClassObject pointer associated
  1774. with the RelPath index
  1775. Arguments:
  1776. RelPathIndex
  1777. *ppWdmClassObject returns with an instance for the relpaht
  1778. Return Value:
  1779. HRESULT
  1780. ---*/
  1781. {
  1782. HRESULT hr;
  1783. WmipAssert(ppWdmClassObject != NULL);
  1784. WmipAssert(IsThisInitialized());
  1785. //
  1786. // Run in the caller's context so that if he is not able to access
  1787. // the WDM classes, he can't
  1788. //
  1789. hr = CoImpersonateClient();
  1790. if (hr == WBEM_S_NO_ERROR)
  1791. {
  1792. *ppWdmClassObject = NULL;
  1793. hr = GetWdmServices()->GetObject(WdmRelPaths[RelPathIndex],
  1794. WBEM_FLAG_USE_AMENDED_QUALIFIERS,
  1795. NULL,
  1796. ppWdmClassObject,
  1797. NULL);
  1798. CoRevertToSelf();
  1799. }
  1800. return(hr);
  1801. }
  1802. HRESULT CTestServices::FillInCdmResult(
  1803. OUT IWbemClassObject *pCdmResult,
  1804. IN IWbemClassObject *pCdmSettings,
  1805. IN int RelPathIndex,
  1806. IN BSTR ExecutionID
  1807. )
  1808. /*+++
  1809. Routine Description:
  1810. This routine will fill in the various properties needed in a CDM
  1811. result instance
  1812. Arguments:
  1813. pCdmResult has its properties set
  1814. pCdmSettings has the settings used to execute the test. This can be
  1815. NULL
  1816. RelPathIndex
  1817. ExecutionID has a unique id used to execute the test
  1818. Return Value:
  1819. HRESULT
  1820. ---*/
  1821. {
  1822. HRESULT hr, hrDontCare;
  1823. WCHAR s[MAX_PATH];
  1824. PWCHAR PropertyNames[12];
  1825. VARIANT PropertyValues[12];
  1826. ULONG PropertyCount;
  1827. BSTR ss;
  1828. WmipAssert(pCdmResult != NULL);
  1829. WmipAssert(IsThisInitialized());
  1830. PropertyNames[0] = L"DiagnosticCreationClassName";
  1831. PropertyValues[0].vt = VT_BSTR;
  1832. PropertyValues[0].bstrVal = WdmRelPaths[RelPathIndex];
  1833. PropertyNames[1] = L"DiagnosticName";
  1834. PropertyValues[1].vt = VT_BSTR;
  1835. PropertyValues[1].bstrVal = CdmTestClassName;
  1836. PropertyNames[2] = L"ExecutionID";
  1837. PropertyValues[2].vt = VT_BSTR;
  1838. PropertyValues[2].bstrVal = ExecutionID;
  1839. PropertyNames[3] = L"TimeStamp";
  1840. PropertyValues[3].vt = VT_BSTR;
  1841. PropertyValues[3].bstrVal = GetCurrentDateTime();
  1842. PropertyNames[4] = L"TestCompletionTime";
  1843. PropertyValues[4].vt = VT_BSTR;
  1844. PropertyValues[4].bstrVal = GetCurrentDateTime();
  1845. PropertyNames[5] = L"IsPackage";
  1846. PropertyValues[5].vt = VT_BOOL;
  1847. PropertyValues[5].boolVal = VARIANT_FALSE;
  1848. //
  1849. // These properties are copied from pCdmSettings
  1850. //
  1851. if (pCdmSettings != NULL)
  1852. {
  1853. PropertyNames[6] = L"TestWarningLevel";
  1854. hrDontCare = WmiGetProperty(pCdmSettings,
  1855. L"TestWarningLevel",
  1856. CIM_UINT16,
  1857. &PropertyValues[6]);
  1858. PropertyNames[7] = L"ReportSoftErrors";
  1859. hrDontCare = WmiGetProperty(pCdmSettings,
  1860. L"ReportSoftErrors",
  1861. CIM_BOOLEAN,
  1862. &PropertyValues[7]);
  1863. PropertyNames[8] = L"ReportStatusMessages";
  1864. hrDontCare = WmiGetProperty(pCdmSettings,
  1865. L"ReportStatusMessages",
  1866. CIM_BOOLEAN,
  1867. &PropertyValues[8]);
  1868. PropertyNames[9] = L"HaltOnError";
  1869. hrDontCare = WmiGetProperty(pCdmSettings,
  1870. L"HaltOnError",
  1871. CIM_BOOLEAN,
  1872. &PropertyValues[9]);
  1873. PropertyNames[10] = L"QuickMode";
  1874. hrDontCare = WmiGetProperty(pCdmSettings,
  1875. L"QuickMode",
  1876. CIM_BOOLEAN,
  1877. &PropertyValues[10]);
  1878. PropertyNames[11] = L"PercentOfTestCoverage";
  1879. hrDontCare = WmiGetProperty(pCdmSettings,
  1880. L"PercentOfTestCoverage",
  1881. CIM_UINT8,
  1882. &PropertyValues[11]);
  1883. PropertyCount = 12;
  1884. } else {
  1885. PropertyCount = 6;
  1886. }
  1887. hr = WmiSetPropertyList(pCdmResult,
  1888. PropertyCount,
  1889. PropertyNames,
  1890. PropertyValues);
  1891. VariantClear(&PropertyValues[3]);
  1892. VariantClear(&PropertyValues[4]);
  1893. return(hr);
  1894. }
  1895. HRESULT CTestServices::QueryOfflineResult(
  1896. OUT IWbemClassObject *pCdmResult,
  1897. IN BSTR ExecutionID,
  1898. IN int RelPathIndex
  1899. )
  1900. {
  1901. WCHAR Query[MAX_PATH * 2];
  1902. WCHAR s[MAX_PATH];
  1903. BSTR sWQL, sQuery;
  1904. IEnumWbemClassObject *pWdmEnumInstances;
  1905. IWbemClassObject *pWdmResult, *pWdmInstance;
  1906. ULONG Count;
  1907. HRESULT hr;
  1908. VARIANT vResult;
  1909. WmipAssert(RelPathIndex < RelPathCount);
  1910. WmipAssert(IsThisInitialized());
  1911. WmipAssert(WdmOfflineResultClassName != NULL);
  1912. //
  1913. // Run in the caller's context so that if he is not able to access
  1914. // the WDM classes, he can't
  1915. //
  1916. hr = CoImpersonateClient();
  1917. if (hr != WBEM_S_NO_ERROR)
  1918. {
  1919. return(hr);
  1920. }
  1921. sWQL = SysAllocString(L"WQL");
  1922. if (sWQL != NULL)
  1923. {
  1924. wsprintfW(Query, L"select * from %ws where InstanceName = \"%ws\"",
  1925. WdmOfflineResultClassName,
  1926. AddSlashesToStringW(s, WdmInstanceNames[RelPathIndex]));
  1927. sQuery = SysAllocString(Query);
  1928. if (sQuery != NULL)
  1929. {
  1930. hr = GetWdmServices()->ExecQuery(sWQL,
  1931. sQuery,
  1932. WBEM_FLAG_FORWARD_ONLY |
  1933. WBEM_FLAG_ENSURE_LOCATABLE,
  1934. NULL,
  1935. &pWdmEnumInstances);
  1936. SysFreeString(sQuery);
  1937. if (hr == WBEM_S_NO_ERROR)
  1938. {
  1939. hr = pWdmEnumInstances->Next(WBEM_INFINITE,
  1940. 1,
  1941. &pWdmInstance,
  1942. &Count);
  1943. if ((hr == WBEM_S_NO_ERROR) &&
  1944. (Count == 1))
  1945. {
  1946. //
  1947. // Check that the result has the correct execution
  1948. // ID
  1949. //
  1950. hr = WmiGetProperty(pWdmInstance,
  1951. L"ExecutionID",
  1952. CIM_STRING,
  1953. &vResult);
  1954. if (hr == WBEM_S_NO_ERROR)
  1955. {
  1956. if (_wcsicmp(ExecutionID, vResult.bstrVal) != 0)
  1957. {
  1958. hr = WBEM_E_FAILED;
  1959. WmipDebugPrint(("CdmProv: Expected execution ID %ws, but got %ws\n",
  1960. ExecutionID, vResult.bstrVal));
  1961. }
  1962. VariantClear(&vResult);
  1963. if (hr == WBEM_S_NO_ERROR)
  1964. {
  1965. hr = WmiGetProperty(pWdmInstance,
  1966. L"TestResult",
  1967. CIM_OBJECT,
  1968. &vResult);
  1969. if (hr == WBEM_S_NO_ERROR)
  1970. {
  1971. hr = (vResult.punkVal)->QueryInterface(IID_IWbemClassObject,
  1972. (PVOID *)&pWdmResult);
  1973. VariantClear(&vResult);
  1974. if (hr == WBEM_S_NO_ERROR)
  1975. {
  1976. hr = CopyBetweenCdmAndWdmClasses(pCdmResult,
  1977. pWdmResult,
  1978. TRUE);
  1979. pWdmResult->Release();
  1980. }
  1981. }
  1982. }
  1983. }
  1984. pWdmInstance->Release();
  1985. }
  1986. pWdmEnumInstances->Release();
  1987. }
  1988. }
  1989. SysFreeString(sWQL);
  1990. } else {
  1991. hr = WBEM_E_OUT_OF_MEMORY;
  1992. }
  1993. CoRevertToSelf();
  1994. return(hr);
  1995. }
  1996. //@@BEGIN_DDKSPLIT
  1997. HRESULT CTestServices::GatherRebootResults(
  1998. void
  1999. )
  2000. /*+++
  2001. Routine Description:
  2002. This routine will check the schema to see if there were any tests
  2003. that were pending reboot for this DiagnosticTest and if so gather
  2004. the results of them.
  2005. When a test is pending reboot, it gets stored as an instance of the
  2006. static class CDMPROV_Result. The instance contains the Test class
  2007. name, the result class name, the PnPId of the device stack and the
  2008. result object. What we do is get all of the saved results for this
  2009. DiagTest and then see if they apply to any of the PnP Device Ids
  2010. for the WdmTest. If so then we call the device to retrieve the
  2011. results and build the result objects.
  2012. Arguments:
  2013. Return Value:
  2014. HRESULT
  2015. ---*/
  2016. {
  2017. #ifdef REBOOT_DIAGNOSTICS
  2018. HRESULT hr, hrDontCare;
  2019. WCHAR Query[2*MAX_PATH];
  2020. BSTR sQuery, sWQL;
  2021. IEnumWbemClassObject *pEnumInstances;
  2022. IWbemClassObject *pInstance;
  2023. IWbemClassObject *pCdmResult;
  2024. int i;
  2025. ULONG Count;
  2026. VARIANT vResult, vPnPId, vExecutionID;
  2027. BSTR ExecutionId;
  2028. hr = WBEM_S_NO_ERROR;
  2029. sWQL = SysAllocString(L"WQL");
  2030. if (sWQL != NULL)
  2031. {
  2032. wsprintfW(Query, L"select * from CdmProv_Result where CdmTestClass = \"%ws\"\n",
  2033. CdmTestClassName);
  2034. sQuery = SysAllocString(Query);
  2035. if (sQuery != NULL)
  2036. {
  2037. hrDontCare = GetCdmServices()->ExecQuery(sWQL,
  2038. sQuery,
  2039. WBEM_FLAG_FORWARD_ONLY |
  2040. WBEM_FLAG_ENSURE_LOCATABLE,
  2041. NULL,
  2042. &pEnumInstances);
  2043. SysFreeString(sQuery);
  2044. if (hrDontCare == WBEM_S_NO_ERROR)
  2045. {
  2046. hr = pEnumInstances->Next(WBEM_INFINITE,
  2047. 1,
  2048. &pInstance,
  2049. &Count);
  2050. if ((hr == WBEM_S_NO_ERROR) &&
  2051. (Count == 1))
  2052. {
  2053. hr = WmiGetProperty(pInstance,
  2054. L"PnPId",
  2055. CIM_STRING,
  2056. &vPnPId);
  2057. if (hr == WBEM_S_NO_ERROR)
  2058. {
  2059. for (i = 0; i < RelPathCount; i++)
  2060. {
  2061. if (_wcsicmp(vPnPId.bstrVal, PnPDeviceIdsX[i]) == 0)
  2062. {
  2063. //
  2064. // We found an instance for this class
  2065. // and PnPId. get out the stored
  2066. // result, assign it a new execution
  2067. // id, and then retrieve the active
  2068. // result from the driver
  2069. //
  2070. PWCHAR PropertyNames[2];
  2071. VARIANT Values[2];
  2072. CIMTYPE CimTypes[2];
  2073. PropertyNames[0] = L"CdmResult";
  2074. CimTypes[0] = CIM_OBJECT;
  2075. PropertyNames[1] = L"ResultTag";
  2076. CimTypes[1] = CIM_STRING;
  2077. hr = WmiGetPropertyList(pInstance,
  2078. PropertyNames,
  2079. CimTypes,
  2080. Values);
  2081. if (hr == WBEM_S_NO_ERROR)
  2082. {
  2083. hr = (Values[0].punkVal)->QueryInterface(IID_IWbemClassObject,
  2084. (PVOID *)&pCdmResult);
  2085. if (hr == WBEM_S_NO_ERROR)
  2086. {
  2087. hr = WmiGetProperty(pCdmResult,
  2088. L"ExecutionID",
  2089. CIM_STRING,
  2090. &vExecutionId);
  2091. WmipAssert(vExecutionId.vt != VT_NULL);
  2092. if (hr == WBEM_S_NO_ERROR)
  2093. {
  2094. hr = QueryOfflineResult(pCdmResult,
  2095. Values[1].bstrVal,
  2096. i);
  2097. if (hr == WBEM_S_NO_ERROR)
  2098. {
  2099. hr = SetResultObject(pCdmResult,
  2100. i,
  2101. vExecutionId.bstrVal);
  2102. if (hr == WBEM_S_NO_ERROR)
  2103. {
  2104. hr = FillInCdmResult(pCdmResult,
  2105. NULL,
  2106. i,
  2107. ExecutionId);
  2108. if (hr != WBEM_S_NO_ERROR)
  2109. {
  2110. hrDontCare = SetResultObject(NULL,
  2111. i,
  2112. 0);
  2113. }
  2114. }
  2115. }
  2116. }
  2117. }
  2118. VariantClear(&Values[0]);
  2119. VariantClear(&Values[1]);
  2120. }
  2121. }
  2122. }
  2123. VariantClear(&vPnPId);
  2124. }
  2125. }
  2126. pEnumInstances->Release();
  2127. }
  2128. }
  2129. SysFreeString(sWQL);
  2130. }
  2131. return(hr);
  2132. #else
  2133. return(WBEM_S_NO_ERROR);
  2134. #endif
  2135. }
  2136. HRESULT CTestServices::PersistResultInSchema(
  2137. IN IWbemClassObject *pCdmResult,
  2138. IN BSTR ExecutionID,
  2139. IN int RelPathIndex
  2140. )
  2141. /*+++
  2142. Routine Description:
  2143. This routine will persist a diagnostic result into the schema
  2144. Arguments:
  2145. Return Value:
  2146. HRESULT
  2147. ---*/
  2148. {
  2149. HRESULT hr;
  2150. IWbemClassObject *pPendingTest;
  2151. IUnknown *punk;
  2152. WCHAR *PropertyNames[5];
  2153. VARIANT PropertyValues[5];
  2154. WmipAssert(pCdmResult != NULL);
  2155. WmipAssert(IsThisInitialized());
  2156. hr = CreateInst(GetCdmServices(),
  2157. &pPendingTest,
  2158. L"CDMProv_Result",
  2159. NULL);
  2160. if (hr == WBEM_S_NO_ERROR)
  2161. {
  2162. hr = pCdmResult->QueryInterface(IID_IUnknown,
  2163. (PVOID *)&punk);
  2164. if (hr == WBEM_S_NO_ERROR)
  2165. {
  2166. PropertyNames[0] = L"PnPId";
  2167. PropertyValues[0].vt = VT_BSTR;
  2168. PropertyValues[0].bstrVal = PnPDeviceIdsX[RelPathIndex];
  2169. PropertyNames[1] = L"CdmTestClass";
  2170. PropertyValues[1].vt = VT_BSTR;
  2171. PropertyValues[1].bstrVal = CdmTestClassName;
  2172. PropertyNames[2] = L"CdmResultClass";
  2173. PropertyValues[2].vt = VT_BSTR;
  2174. PropertyValues[2].bstrVal = CdmResultClassName;
  2175. PropertyNames[3] = L"CdmResult";
  2176. PropertyValues[3].vt = VT_UNKNOWN;
  2177. PropertyValues[3].punkVal = punk;
  2178. PropertyNames[4] = L"ExecutionID";
  2179. PropertyValues[4].vt = VT_BSTR;
  2180. PropertyValues[4].bstrVal = ExecutionID;
  2181. hr = WmiSetPropertyList(pPendingTest,
  2182. 5,
  2183. PropertyNames,
  2184. PropertyValues);
  2185. if (hr == WBEM_S_NO_ERROR)
  2186. {
  2187. hr = GetCdmServices()->PutInstance(pPendingTest,
  2188. WBEM_FLAG_CREATE_OR_UPDATE,
  2189. NULL,
  2190. NULL);
  2191. }
  2192. punk->Release();
  2193. }
  2194. pPendingTest->Release();
  2195. }
  2196. return(hr);
  2197. }
  2198. //@@END_DDKSPLIT
  2199. HRESULT CTestServices::OfflineDeviceForTest(
  2200. IWbemClassObject *pCdmResult,
  2201. BSTR ExecutionID,
  2202. int RelPathIndex
  2203. )
  2204. {
  2205. HRESULT hr = WBEM_S_NO_ERROR;
  2206. ULONG Status;
  2207. VARIANT v;
  2208. WmipAssert(RelPathIndex < RelPathCount);
  2209. WmipAssert(IsThisInitialized());
  2210. //
  2211. // First determine if the test is one where it expects to be taken
  2212. // offline and that the result from the RunTest method indicates
  2213. // that an offline execution is pending
  2214. //
  2215. if (WdmOfflineResultClassName != NULL)
  2216. {
  2217. //
  2218. // The device expects to be taken offline since it had a
  2219. // WdmOfflineResultClass qualifier on the CIM_DiagnosticResult
  2220. // class. Now see if the OtherStateDescription property in the
  2221. // CIM_DiagnosticResult is set to "Offline Pending Execution"
  2222. //
  2223. hr = WmiGetProperty(pCdmResult,
  2224. L"OtherStateDescription",
  2225. CIM_STRING,
  2226. &v);
  2227. if (hr == WBEM_S_NO_ERROR)
  2228. {
  2229. if (_wcsicmp(v.bstrVal, L"Offline Pending Execution") == 0)
  2230. {
  2231. //
  2232. // Ok, the test is waiting for the device to be taken
  2233. // offline. Lets do this now and then when the device
  2234. // comes back, pickup the results from the
  2235. // OfflineResultClass
  2236. //
  2237. // @@BEGIN_DDKSPLIT
  2238. //#define FORCE_REBOOT_REQUIRED
  2239. #ifdef FORCE_REBOOT_REQUIRED
  2240. Status = ERROR_INVALID_PARAMETER;
  2241. #else
  2242. // @@END_DDKSPLIT
  2243. //
  2244. // Make sure to use the clients security context to try
  2245. // to bring the device offline.
  2246. //
  2247. hr = CoImpersonateClient();
  2248. if (hr == WBEM_S_NO_ERROR)
  2249. {
  2250. Status = RestartDevice(PnPDeviceIdsX[RelPathIndex]);
  2251. CoRevertToSelf();
  2252. }
  2253. // @@BEGIN_DDKSPLIT
  2254. #endif
  2255. // @@END_DDKSPLIT
  2256. if (Status == ERROR_SUCCESS)
  2257. {
  2258. hr = QueryOfflineResult(pCdmResult,
  2259. ExecutionID,
  2260. RelPathIndex);
  2261. } else {
  2262. //
  2263. // For some reason we were not able to bring the
  2264. // device offline. Most likely this is because the
  2265. // device is critical to the system and cannot be
  2266. // taken offline right now - for example a disk
  2267. // that is in the paging path.
  2268. //
  2269. // @@BEGIN_DDKSPLIT
  2270. #if REBOOT_DIAGNOSTICS
  2271. // What we'll need to do is to remember that
  2272. // this test is pending and so the next time the
  2273. // system is rebooted we can check for the results
  2274. // of this test and report them.
  2275. //
  2276. hr = PersistResultInSchema(pCdmResult,
  2277. RelPathIndex);
  2278. #else
  2279. //
  2280. // Reboot diagnostics are not currently supported.
  2281. //
  2282. // @@END_DDKSPLIT
  2283. hr = WBEM_E_FAILED;
  2284. // @@BEGIN_DDKSPLIT
  2285. #endif
  2286. // @@END_DDKSPLIT
  2287. }
  2288. }
  2289. VariantClear(&v);
  2290. } else {
  2291. //
  2292. // Since the OtherStateDescription was not set then we
  2293. // assume that the tests isn't setup to go offline and has
  2294. // already been completed
  2295. //
  2296. hr = WBEM_S_NO_ERROR;
  2297. }
  2298. }
  2299. return(hr);
  2300. }
  2301. BOOLEAN CTestServices::IsThisInitialized(
  2302. void
  2303. )
  2304. /*+++
  2305. Routine Description:
  2306. This routine determines if this class has been initialized to
  2307. access CDM and WDM classes
  2308. Arguments:
  2309. Return Value:
  2310. TRUE if initialiezed else FALSE
  2311. ---*/
  2312. {
  2313. return( (CdmTestClassName != NULL) );
  2314. }
  2315. HRESULT CTestServices::AddResultToList(
  2316. IN IWbemClassObject *ResultInstance,
  2317. IN BSTR ExecutionID,
  2318. IN int RelPathIndex
  2319. )
  2320. /*+++
  2321. Routine Description:
  2322. This routine will add a result object and the related association
  2323. relpaths to the list of result objects for the test
  2324. Arguments:
  2325. ResultInstance is an instance of CIM_DiagnosticResults
  2326. RelPathIndex
  2327. ExecutionID
  2328. Return Value:
  2329. Never fails
  2330. ---*/
  2331. {
  2332. HRESULT hr;
  2333. BSTR ResultRelPath;
  2334. BSTR ResultForMSERelPath;
  2335. BSTR ResultForTestRelPath;
  2336. WmipAssert(ResultInstance != NULL);
  2337. WmipAssert(RelPathIndex < RelPathCount);
  2338. WmipAssert(IsThisInitialized());
  2339. //
  2340. // If there is a new result object then establish the various
  2341. // result relpaths for it
  2342. //
  2343. hr = BuildResultRelPaths(RelPathIndex,
  2344. ExecutionID,
  2345. &ResultRelPath,
  2346. &ResultForMSERelPath,
  2347. &ResultForTestRelPath);
  2348. if (hr == WBEM_S_NO_ERROR)
  2349. {
  2350. hr = CdmResultsList[RelPathIndex].Add(ResultInstance,
  2351. ResultRelPath,
  2352. ResultForMSERelPath,
  2353. ResultForTestRelPath);
  2354. }
  2355. return(hr);
  2356. }
  2357. HRESULT CTestServices::GetResultsList(
  2358. IN int RelPathIndex,
  2359. OUT ULONG *ResultsCount,
  2360. OUT IWbemClassObject ***Results
  2361. )
  2362. {
  2363. WmipAssert(RelPathIndex < RelPathCount);
  2364. WmipAssert(IsThisInitialized());
  2365. return(CdmResultsList[RelPathIndex].GetResultsList(ResultsCount,
  2366. Results));
  2367. }
  2368. void CTestServices::ClearResultsList(
  2369. int RelPathIndex
  2370. )
  2371. {
  2372. WmipAssert(RelPathIndex < RelPathCount);
  2373. WmipAssert(IsThisInitialized());
  2374. CdmResultsList[RelPathIndex].Clear();
  2375. }
  2376. BSTR /* NOFREE */ CTestServices::GetCimRelPath(
  2377. int RelPathIndex
  2378. )
  2379. /*+++
  2380. Routine Description:
  2381. This routine will return the Cim relpath for a RelPathIndex
  2382. Arguments:
  2383. RelPathIndex
  2384. Return Value:
  2385. Cim RelPath. This should not be freed
  2386. ---*/
  2387. {
  2388. WmipAssert(CimRelPaths != NULL);
  2389. WmipAssert(RelPathIndex < RelPathCount);
  2390. WmipAssert(IsThisInitialized());
  2391. return(CimRelPaths[RelPathIndex]);
  2392. }
  2393. BSTR /* NOFREE */ CTestServices::GetCdmTestRelPath(
  2394. void
  2395. )
  2396. /*+++
  2397. Routine Description:
  2398. This routine will return the Cdm Test class relpath
  2399. Arguments:
  2400. Return Value:
  2401. Cdm Test Class RelPath. This should not be freed
  2402. ---*/
  2403. {
  2404. WmipAssert(IsThisInitialized());
  2405. return(CdmTestRelPath);
  2406. }
  2407. BSTR /* NOFREE */ CTestServices::GetCdmTestClassName(
  2408. void
  2409. )
  2410. /*+++
  2411. Routine Description:
  2412. This routine will return the Cdm Test class name
  2413. Arguments:
  2414. Return Value:
  2415. Cdm Test Class Name. This should not be freed
  2416. ---*/
  2417. {
  2418. WmipAssert(IsThisInitialized());
  2419. return(CdmTestClassName);
  2420. }
  2421. BSTR /* NOFREE */ CTestServices::GetCdmResultClassName(
  2422. void
  2423. )
  2424. /*+++
  2425. Routine Description:
  2426. This routine will return the Cdm Result class name
  2427. Arguments:
  2428. Return Value:
  2429. Cdm Result Class Name. This should not be freed
  2430. ---*/
  2431. {
  2432. WmipAssert(IsThisInitialized());
  2433. return(CdmResultClassName);
  2434. }
  2435. HRESULT CTestServices::GetCdmResultByResultRelPath(
  2436. IN int RelPathIndex,
  2437. IN PWCHAR ObjectPath,
  2438. OUT IWbemClassObject **ppCdmResult
  2439. )
  2440. /*+++
  2441. Routine Description:
  2442. This routine will return the Cdm Result object for a specific RelPath
  2443. Arguments:
  2444. RelPathIndex
  2445. Return Value:
  2446. Cdm Result RelPath or NULL of there is no ressult object for the
  2447. relpath. This should not be freed
  2448. ---*/
  2449. {
  2450. HRESULT hr;
  2451. WmipAssert(RelPathIndex < RelPathCount);
  2452. WmipAssert(IsThisInitialized());
  2453. hr = CdmResultsList[RelPathIndex].GetResultByResultRelPath(ObjectPath,
  2454. ppCdmResult);
  2455. return(hr);
  2456. }
  2457. HRESULT CTestServices::GetCdmResultByResultForMSERelPath(
  2458. IN int RelPathIndex,
  2459. IN PWCHAR ObjectPath,
  2460. OUT IWbemClassObject **ppCdmResult
  2461. )
  2462. /*+++
  2463. Routine Description:
  2464. This routine will return the Cdm Result object for a specific RelPath
  2465. Arguments:
  2466. RelPathIndex
  2467. Return Value:
  2468. Cdm Result RelPath or NULL of there is no ressult object for the
  2469. relpath. This should not be freed
  2470. ---*/
  2471. {
  2472. HRESULT hr;
  2473. WmipAssert(RelPathIndex < RelPathCount);
  2474. WmipAssert(IsThisInitialized());
  2475. hr = CdmResultsList[RelPathIndex].GetResultByResultForMSERelPath(ObjectPath,
  2476. ppCdmResult);
  2477. return(hr);
  2478. }
  2479. HRESULT CTestServices::GetCdmResultByResultForTestRelPath(
  2480. IN int RelPathIndex,
  2481. IN PWCHAR ObjectPath,
  2482. OUT IWbemClassObject **ppCdmResult
  2483. )
  2484. /*+++
  2485. Routine Description:
  2486. This routine will return the Cdm Result object for a specific RelPath
  2487. Arguments:
  2488. RelPathIndex
  2489. Return Value:
  2490. Cdm Result RelPath or NULL of there is no ressult object for the
  2491. relpath. This should not be freed
  2492. ---*/
  2493. {
  2494. HRESULT hr;
  2495. WmipAssert(RelPathIndex < RelPathCount);
  2496. WmipAssert(IsThisInitialized());
  2497. hr = CdmResultsList[RelPathIndex].GetResultByResultForTestRelPath(ObjectPath,
  2498. ppCdmResult);
  2499. return(hr);
  2500. }
  2501. BSTR /* NOFREE */ CTestServices::GetCdmSettingClassName(
  2502. void
  2503. )
  2504. /*+++
  2505. Routine Description:
  2506. This routine will return the Cdm settings class name
  2507. Arguments:
  2508. Return Value:
  2509. Cdm Settings class name. This should not be freed
  2510. ---*/
  2511. {
  2512. WmipAssert(IsThisInitialized());
  2513. return(CdmSettingClassName);
  2514. }
  2515. BSTR /* NOFREE */ CTestServices::GetCdmSettingRelPath(
  2516. int RelPathIndex,
  2517. ULONG SettingIndex
  2518. )
  2519. /*+++
  2520. Routine Description:
  2521. This routine will return the Cdm settings relpath by relpath index
  2522. and index with the settings for that relpath.
  2523. Arguments:
  2524. RelPathIndex
  2525. SettingIndex
  2526. Return Value:
  2527. Cdm Settings relpath. This should not be freed
  2528. ---*/
  2529. {
  2530. CWbemObjectList *CdmSettings;
  2531. WmipAssert(RelPathIndex < RelPathCount);
  2532. WmipAssert(CdmSettingsList != NULL);
  2533. WmipAssert(IsThisInitialized());
  2534. CdmSettings = CdmSettingsList[RelPathIndex];
  2535. return(CdmSettings->GetRelPath(SettingIndex));
  2536. }
  2537. IWbemClassObject *CTestServices::GetCdmSettingObject(
  2538. int RelPathIndex,
  2539. ULONG SettingIndex
  2540. )
  2541. {
  2542. CWbemObjectList *CdmSettings;
  2543. WmipAssert(RelPathIndex < RelPathCount);
  2544. WmipAssert(CdmSettingsList != NULL);
  2545. WmipAssert(IsThisInitialized());
  2546. CdmSettings = CdmSettingsList[RelPathIndex];
  2547. return(CdmSettings->Get(SettingIndex));
  2548. }
  2549. ULONG CTestServices::GetCdmSettingCount(
  2550. int RelPathIndex
  2551. )
  2552. {
  2553. WmipAssert(RelPathIndex < RelPathCount);
  2554. WmipAssert(CdmSettingsList != NULL);
  2555. WmipAssert(IsThisInitialized());
  2556. return(CdmSettingsList[RelPathIndex]->GetListSize());
  2557. }
  2558. BSTR /* NOFREE */ CTestServices::GetCdmTestForMSEClassName(
  2559. void
  2560. )
  2561. {
  2562. WmipAssert(IsThisInitialized());
  2563. return(CdmTestForMSEClassName);
  2564. }
  2565. BSTR /* NOFREE */ CTestServices::GetCdmTestForMSERelPath(
  2566. int RelPathIndex
  2567. )
  2568. {
  2569. WmipAssert(RelPathIndex < RelPathCount);
  2570. WmipAssert(IsThisInitialized());
  2571. return(CdmTestForMSERelPath[RelPathIndex]);
  2572. }
  2573. BSTR /* NOFREE */ CTestServices::GetCdmSettingForTestClassName(
  2574. void
  2575. )
  2576. {
  2577. WmipAssert(IsThisInitialized());
  2578. return(CdmSettingForTestClassName);
  2579. }
  2580. BSTR /* NOFREE */ CTestServices::GetCdmSettingForTestRelPath(
  2581. int RelPathIndex,
  2582. ULONG SettingIndex
  2583. )
  2584. {
  2585. CBstrArray *BstrArray;
  2586. BSTR s;
  2587. WmipAssert(RelPathIndex < RelPathCount);
  2588. WmipAssert(IsThisInitialized());
  2589. if (CdmSettingForTestRelPath != NULL)
  2590. {
  2591. BstrArray = CdmSettingForTestRelPath[RelPathIndex];
  2592. s = BstrArray->Get(SettingIndex);
  2593. } else {
  2594. s = NULL;
  2595. }
  2596. return(s);
  2597. }
  2598. BSTR /* NOFREE */ CTestServices::GetCdmResultForMSEClassName(
  2599. void
  2600. )
  2601. {
  2602. WmipAssert(IsThisInitialized());
  2603. return(CdmResultForMSEClassName);
  2604. }
  2605. BSTR /* NOFREE */ CTestServices::GetCdmResultForTestClassName(
  2606. void
  2607. )
  2608. {
  2609. WmipAssert(IsThisInitialized());
  2610. return(CdmResultForTestClassName);
  2611. }
  2612. BSTR /* NOFREE */ CTestServices::GetCdmTestForSoftwareClassName(
  2613. void
  2614. )
  2615. {
  2616. WmipAssert(IsThisInitialized());
  2617. return(CdmTestForSoftwareClassName);
  2618. }
  2619. BSTR /* NOFREE */ CTestServices::GetCdmTestForSoftwareRelPath(
  2620. void
  2621. )
  2622. {
  2623. WmipAssert(IsThisInitialized());
  2624. return(CdmTestForSoftwareRelPath);
  2625. }
  2626. BSTR /* NOFREE */ CTestServices::GetCdmTestInPackageClassName(
  2627. void
  2628. )
  2629. {
  2630. WmipAssert(IsThisInitialized());
  2631. return(CdmTestInPackageClassName);
  2632. }
  2633. BSTR /* NOFREE */CTestServices::GetCdmTestInPackageRelPath(
  2634. void
  2635. )
  2636. {
  2637. WmipAssert(IsThisInitialized());
  2638. return(CdmTestInPackageRelPath);
  2639. }
  2640. BSTR /* NOFREE */ CTestServices::GetCdmResultInPackageClassName(
  2641. void
  2642. )
  2643. {
  2644. WmipAssert(IsThisInitialized());
  2645. return(CdmResultInPackageClassName);
  2646. }
  2647. BSTR /* NOFREE */ CTestServices::GetCdmResultInPackageRelPath(
  2648. void
  2649. )
  2650. {
  2651. WmipAssert(IsThisInitialized());
  2652. return(CdmResultInPackageRelPath);
  2653. }
  2654. CWbemObjectList::CWbemObjectList()
  2655. {
  2656. //
  2657. // Constructor, init internal values
  2658. //
  2659. List = NULL;
  2660. RelPaths = NULL;
  2661. ListSize = 0xffffffff;
  2662. }
  2663. CWbemObjectList::~CWbemObjectList()
  2664. {
  2665. //
  2666. // Destructor, free memory held by this class
  2667. //
  2668. if (List != NULL)
  2669. {
  2670. WmipFree(List);
  2671. }
  2672. List = NULL;
  2673. if (RelPaths != NULL)
  2674. {
  2675. FreeTheBSTRArray(RelPaths, ListSize);
  2676. RelPaths = NULL;
  2677. }
  2678. ListSize = 0xffffffff;
  2679. }
  2680. HRESULT CWbemObjectList::Initialize(
  2681. ULONG NumberPointers
  2682. )
  2683. {
  2684. HRESULT hr;
  2685. ULONG AllocSize;
  2686. //
  2687. // Initialize class by allocating internal list array
  2688. //
  2689. WmipAssert(List == NULL);
  2690. if (NumberPointers != 0)
  2691. {
  2692. AllocSize = NumberPointers * sizeof(IWbemClassObject *);
  2693. List = (IWbemClassObject **)WmipAlloc(AllocSize);
  2694. if (List != NULL)
  2695. {
  2696. memset(List, 0, AllocSize);
  2697. AllocSize = NumberPointers * sizeof(BSTR);
  2698. RelPaths = (BSTR *)WmipAlloc(AllocSize);
  2699. if (RelPaths != NULL)
  2700. {
  2701. memset(RelPaths, 0, AllocSize);
  2702. ListSize = NumberPointers;
  2703. hr = WBEM_S_NO_ERROR;
  2704. } else {
  2705. WmipDebugPrint(("CDMProv: Could not alloc memory for CWbemObjectList RelPaths\n"));
  2706. hr = WBEM_E_OUT_OF_MEMORY;
  2707. }
  2708. } else {
  2709. WmipDebugPrint(("CDMProv: Could not alloc memory for CWbemObjectList\n"));
  2710. hr = WBEM_E_OUT_OF_MEMORY;
  2711. }
  2712. } else {
  2713. ListSize = NumberPointers;
  2714. hr = WBEM_S_NO_ERROR;
  2715. }
  2716. return(hr);
  2717. }
  2718. ULONG CWbemObjectList::GetListSize(
  2719. void
  2720. )
  2721. {
  2722. //
  2723. // Accessor for list size
  2724. //
  2725. WmipAssert(IsInitialized());
  2726. return(ListSize);
  2727. }
  2728. IWbemClassObject *CWbemObjectList::Get(
  2729. ULONG Index
  2730. )
  2731. { IWbemClassObject *Pointer;
  2732. WmipAssert(Index < ListSize);
  2733. WmipAssert(IsInitialized());
  2734. Pointer = List[Index];
  2735. return(Pointer);
  2736. }
  2737. HRESULT CWbemObjectList::Set(
  2738. IN ULONG Index,
  2739. IN IWbemClassObject *Pointer,
  2740. IN BOOLEAN KeepRelPath
  2741. )
  2742. {
  2743. HRESULT hr;
  2744. VARIANT v;
  2745. WmipAssert(Index < ListSize);
  2746. WmipAssert(IsInitialized());
  2747. if (Pointer != NULL)
  2748. {
  2749. hr = WmiGetProperty(Pointer,
  2750. L"__RelPath",
  2751. CIM_REFERENCE,
  2752. &v);
  2753. if (hr == WBEM_S_NO_ERROR)
  2754. {
  2755. RelPaths[Index] = v.bstrVal;
  2756. List[Index] = Pointer;
  2757. } else {
  2758. if (! KeepRelPath)
  2759. {
  2760. RelPaths[Index] = NULL;
  2761. List[Index] = Pointer;
  2762. }
  2763. }
  2764. } else {
  2765. if (RelPaths[Index] != NULL)
  2766. {
  2767. SysFreeString(RelPaths[Index]);
  2768. RelPaths[Index] = NULL;
  2769. hr = WBEM_S_NO_ERROR;
  2770. }
  2771. List[Index] = NULL;
  2772. }
  2773. return(hr);
  2774. }
  2775. BSTR /* NOFREE */ CWbemObjectList::GetRelPath(
  2776. IN ULONG Index
  2777. )
  2778. {
  2779. WmipAssert(Index < ListSize);
  2780. WmipAssert(IsInitialized());
  2781. return(RelPaths[Index]);
  2782. }
  2783. BOOLEAN CWbemObjectList::IsInitialized(
  2784. )
  2785. {
  2786. return((ListSize == 0) ||
  2787. ((List != NULL) && (RelPaths != NULL)));
  2788. }
  2789. //
  2790. // Linked list management routines
  2791. //
  2792. CTestServices *CTestServices::GetNext(
  2793. )
  2794. {
  2795. return(Next);
  2796. }
  2797. CTestServices *CTestServices::GetPrev(
  2798. )
  2799. {
  2800. return(Prev);
  2801. }
  2802. void CTestServices::InsertSelf(
  2803. CTestServices **Head
  2804. )
  2805. {
  2806. WmipAssert(Next == NULL);
  2807. WmipAssert(Prev == NULL);
  2808. if (*Head != NULL)
  2809. {
  2810. Next = (*Head);
  2811. (*Head)->Prev = this;
  2812. }
  2813. *Head = this;
  2814. }
  2815. BOOLEAN CTestServices::ClaimCdmClassName(
  2816. PWCHAR CdmClassName
  2817. )
  2818. {
  2819. if (_wcsicmp(CdmClassName, CdmTestClassName) == 0)
  2820. {
  2821. return(TRUE);
  2822. }
  2823. if (_wcsicmp(CdmClassName, CdmResultClassName) == 0)
  2824. {
  2825. return(TRUE);
  2826. }
  2827. if (_wcsicmp(CdmClassName, CdmSettingClassName) == 0)
  2828. {
  2829. return(TRUE);
  2830. }
  2831. if (_wcsicmp(CdmClassName, CdmTestForMSEClassName) == 0)
  2832. {
  2833. return(TRUE);
  2834. }
  2835. if (_wcsicmp(CdmClassName, CdmSettingForTestClassName) == 0)
  2836. {
  2837. return(TRUE);
  2838. }
  2839. if (_wcsicmp(CdmClassName, CdmResultForMSEClassName) == 0)
  2840. {
  2841. return(TRUE);
  2842. }
  2843. if (_wcsicmp(CdmClassName, CdmResultForTestClassName) == 0)
  2844. {
  2845. return(TRUE);
  2846. }
  2847. if (_wcsicmp(CdmClassName, CdmTestForSoftwareClassName) == 0)
  2848. {
  2849. return(TRUE);
  2850. }
  2851. if (_wcsicmp(CdmClassName, CdmTestInPackageClassName) == 0)
  2852. {
  2853. return(TRUE);
  2854. }
  2855. if (_wcsicmp(CdmClassName, CdmResultInPackageClassName) == 0)
  2856. {
  2857. return(TRUE);
  2858. }
  2859. return(FALSE);
  2860. }
  2861. CBstrArray::CBstrArray()
  2862. {
  2863. Array = NULL;
  2864. ListSize = 0xffffffff;
  2865. }
  2866. CBstrArray::~CBstrArray()
  2867. {
  2868. ULONG i;
  2869. if (Array != NULL)
  2870. {
  2871. for (i = 0; i < ListSize; i++)
  2872. {
  2873. if (Array[i] != NULL)
  2874. {
  2875. SysFreeString(Array[i]);
  2876. }
  2877. }
  2878. WmipFree(Array);
  2879. }
  2880. ListSize = 0xffffffff;
  2881. }
  2882. HRESULT CBstrArray::Initialize(
  2883. ULONG ListCount
  2884. )
  2885. {
  2886. HRESULT hr = WBEM_S_NO_ERROR;
  2887. ULONG AllocSize;
  2888. if (ListCount != 0)
  2889. {
  2890. AllocSize = ListCount * sizeof(BSTR *);
  2891. Array = (BSTR *)WmipAlloc(AllocSize);
  2892. if (Array != NULL)
  2893. {
  2894. memset(Array, 0, AllocSize);
  2895. ListSize = ListCount;
  2896. } else {
  2897. hr = WBEM_E_OUT_OF_MEMORY;
  2898. }
  2899. } else {
  2900. ListSize = ListCount;
  2901. }
  2902. return(hr);
  2903. }
  2904. BOOLEAN CBstrArray::IsInitialized(
  2905. )
  2906. {
  2907. return( (Array != NULL) || (ListSize == 0) );
  2908. }
  2909. BSTR CBstrArray::Get(
  2910. ULONG Index
  2911. )
  2912. {
  2913. WmipAssert(Index < ListSize);
  2914. WmipAssert(IsInitialized());
  2915. return(Array[Index]);
  2916. }
  2917. void CBstrArray::Set(
  2918. ULONG Index,
  2919. BSTR s
  2920. )
  2921. {
  2922. WmipAssert(Index < ListSize);
  2923. WmipAssert(IsInitialized());
  2924. Array[Index] = s;
  2925. }
  2926. ULONG CBstrArray::GetListSize(
  2927. )
  2928. {
  2929. WmipAssert(IsInitialized());
  2930. return(ListSize);
  2931. }
  2932. CResultList::CResultList()
  2933. {
  2934. ListSize = 0;
  2935. ListEntries = 0;
  2936. List = NULL;
  2937. }
  2938. CResultList::~CResultList()
  2939. {
  2940. ULONG i;
  2941. Clear();
  2942. if (List != NULL)
  2943. {
  2944. WmipFree(List);
  2945. }
  2946. }
  2947. void CResultList::Clear(
  2948. void
  2949. )
  2950. {
  2951. ULONG i;
  2952. PRESULTENTRY Entry;
  2953. if (List != NULL)
  2954. {
  2955. for (i = 0; i < ListEntries; i++)
  2956. {
  2957. Entry = &List[i];
  2958. if (Entry->ResultInstance != NULL)
  2959. {
  2960. Entry->ResultInstance->Release();
  2961. Entry->ResultInstance = NULL;
  2962. }
  2963. if (Entry->ResultRelPath != NULL)
  2964. {
  2965. SysFreeString(Entry->ResultRelPath);
  2966. Entry->ResultRelPath = NULL;
  2967. }
  2968. if (Entry->ResultForMSERelPath != NULL)
  2969. {
  2970. SysFreeString(Entry->ResultForMSERelPath);
  2971. Entry->ResultForMSERelPath = NULL;
  2972. }
  2973. if (Entry->ResultForTestRelPath != NULL)
  2974. {
  2975. SysFreeString(Entry->ResultForTestRelPath);
  2976. Entry->ResultForTestRelPath = NULL;
  2977. }
  2978. }
  2979. }
  2980. ListEntries = 0;
  2981. }
  2982. //
  2983. // The result list will grow itself this many entries at a time
  2984. //
  2985. #define RESULTLISTGROWSIZE 4
  2986. HRESULT CResultList::Add(
  2987. IWbemClassObject *CdmResultInstance,
  2988. BSTR CdmResultRelPath,
  2989. BSTR CdmResultForMSERelPath,
  2990. BSTR CdmResultForTestRelPath
  2991. )
  2992. {
  2993. ULONG AllocSize;
  2994. PRESULTENTRY NewList, Entry;
  2995. ULONG CurrentSize;
  2996. EnterCdmCritSection();
  2997. if (List == NULL)
  2998. {
  2999. //
  3000. // We are starting with an empty list
  3001. //
  3002. AllocSize = RESULTLISTGROWSIZE * sizeof(RESULTENTRY);
  3003. List = (PRESULTENTRY)WmipAlloc(AllocSize);
  3004. if (List == NULL)
  3005. {
  3006. LeaveCdmCritSection();
  3007. return(WBEM_E_OUT_OF_MEMORY);
  3008. }
  3009. memset(List, 0, AllocSize);
  3010. ListSize = RESULTLISTGROWSIZE;
  3011. ListEntries = 0;
  3012. } else if (ListEntries == ListSize) {
  3013. //
  3014. // The list needs to grow, so we allocate more memory and copy
  3015. // over the current list
  3016. //
  3017. CurrentSize = ListSize * sizeof(RESULTENTRY);
  3018. AllocSize = CurrentSize + (RESULTLISTGROWSIZE * sizeof(RESULTENTRY));
  3019. NewList = (PRESULTENTRY)WmipAlloc(AllocSize);
  3020. if (NewList == NULL)
  3021. {
  3022. LeaveCdmCritSection();
  3023. return(WBEM_E_OUT_OF_MEMORY);
  3024. }
  3025. memset(NewList, 0, AllocSize);
  3026. memcpy(NewList, List, CurrentSize);
  3027. WmipFree(List);
  3028. List = NewList;
  3029. ListSize += RESULTLISTGROWSIZE;
  3030. }
  3031. //
  3032. // We have room to add a new entry to the list
  3033. //
  3034. Entry = &List[ListEntries++];
  3035. Entry->ResultInstance = CdmResultInstance;
  3036. Entry->ResultInstance->AddRef();
  3037. Entry->ResultRelPath = CdmResultRelPath;
  3038. Entry->ResultForMSERelPath = CdmResultForMSERelPath;
  3039. Entry->ResultForTestRelPath = CdmResultForTestRelPath;
  3040. LeaveCdmCritSection();
  3041. return(WBEM_S_NO_ERROR);
  3042. }
  3043. HRESULT CResultList::GetResultsList(
  3044. OUT ULONG *Count,
  3045. OUT IWbemClassObject ***Objects
  3046. )
  3047. {
  3048. IWbemClassObject **Things;
  3049. HRESULT hr;
  3050. ULONG i;
  3051. EnterCdmCritSection();
  3052. *Count = ListEntries;
  3053. if (ListEntries != 0)
  3054. {
  3055. Things = (IWbemClassObject **)WmipAlloc( ListEntries *
  3056. sizeof(IWbemClassObject *));
  3057. if (Things != NULL)
  3058. {
  3059. *Objects = Things;
  3060. for (i = 0; i < ListEntries; i++)
  3061. {
  3062. Things[i] = List[i].ResultInstance;
  3063. Things[i]->AddRef();
  3064. }
  3065. hr = WBEM_S_NO_ERROR;
  3066. } else {
  3067. hr = WBEM_E_OUT_OF_MEMORY;
  3068. }
  3069. } else {
  3070. *Objects = NULL;
  3071. hr = WBEM_S_NO_ERROR;
  3072. }
  3073. LeaveCdmCritSection();
  3074. return(hr);
  3075. }
  3076. HRESULT CResultList::GetResultByResultRelPath(
  3077. PWCHAR ObjectPath,
  3078. IWbemClassObject **ppResult
  3079. )
  3080. {
  3081. HRESULT hr;
  3082. ULONG i;
  3083. hr = WBEM_E_NOT_FOUND;
  3084. EnterCdmCritSection();
  3085. for (i = 0; i < ListEntries; i++)
  3086. {
  3087. if (_wcsicmp(ObjectPath, List[i].ResultRelPath) == 0)
  3088. {
  3089. *ppResult = List[i].ResultInstance;
  3090. (*ppResult)->AddRef();
  3091. hr = WBEM_S_NO_ERROR;
  3092. break;
  3093. }
  3094. }
  3095. LeaveCdmCritSection();
  3096. return(hr);
  3097. }
  3098. HRESULT CResultList::GetResultByResultForMSERelPath(
  3099. PWCHAR ObjectPath,
  3100. IWbemClassObject **ppResult
  3101. )
  3102. {
  3103. HRESULT hr;
  3104. ULONG i;
  3105. hr = WBEM_E_NOT_FOUND;
  3106. EnterCdmCritSection();
  3107. for (i = 0; i < ListEntries; i++)
  3108. {
  3109. if (_wcsicmp(ObjectPath, List[i].ResultForMSERelPath) == 0)
  3110. {
  3111. *ppResult = List[i].ResultInstance;
  3112. (*ppResult)->AddRef();
  3113. hr = WBEM_S_NO_ERROR;
  3114. break;
  3115. }
  3116. }
  3117. LeaveCdmCritSection();
  3118. return(hr);
  3119. }
  3120. HRESULT CResultList::GetResultByResultForTestRelPath(
  3121. PWCHAR ObjectPath,
  3122. IWbemClassObject **ppResult
  3123. )
  3124. {
  3125. HRESULT hr;
  3126. ULONG i;
  3127. hr = WBEM_E_NOT_FOUND;
  3128. EnterCdmCritSection();
  3129. for (i = 0; i < ListEntries; i++)
  3130. {
  3131. if (_wcsicmp(ObjectPath, List[i].ResultForTestRelPath) == 0)
  3132. {
  3133. *ppResult = List[i].ResultInstance;
  3134. (*ppResult)->AddRef();
  3135. hr = WBEM_S_NO_ERROR;
  3136. break;
  3137. }
  3138. }
  3139. LeaveCdmCritSection();
  3140. return(hr);
  3141. }