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.

1736 lines
44 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. schemadynamic.cpp
  5. Abstract:
  6. This file contains the implementation of the CDynSchema class.
  7. This class contains the dynamic schema structures.
  8. It also contains the rules for populating the schema structures.
  9. Author:
  10. Mohit Srivastava 28-Nov-00
  11. Revision History:
  12. --*/
  13. #include "iisprov.h"
  14. #define USE_DEFAULT_VALUES
  15. #define USE_DEFAULT_BINARY_VALUES
  16. CDynSchema* g_pDynSch = NULL;
  17. HRESULT CDynSchema::Initialize()
  18. /*++
  19. Synopsis:
  20. If fails, object must be destroyed.
  21. If succeeds, object is ready for use.
  22. Return Value:
  23. --*/
  24. {
  25. DBG_ASSERT(m_bInitCalled == false);
  26. DBG_ASSERT(m_bInitSuccessful == false);
  27. HRESULT hr = WBEM_S_NO_ERROR;
  28. m_bInitCalled = true;
  29. hr = m_hashProps.Wmi_Initialize();
  30. if(FAILED(hr))
  31. {
  32. goto exit;
  33. }
  34. hr = m_hashClasses.Wmi_Initialize();
  35. if(FAILED(hr))
  36. {
  37. goto exit;
  38. }
  39. hr = m_hashAssociations.Wmi_Initialize();
  40. if(FAILED(hr))
  41. {
  42. goto exit;
  43. }
  44. hr = m_hashKeyTypes.Wmi_Initialize();
  45. if(FAILED(hr))
  46. {
  47. goto exit;
  48. }
  49. hr = m_poolAssociations.Initialize(10);
  50. if(FAILED(hr))
  51. {
  52. goto exit;
  53. }
  54. hr = m_poolClasses.Initialize(10);
  55. if(FAILED(hr))
  56. {
  57. goto exit;
  58. }
  59. hr = m_poolProps.Initialize(10);
  60. if(FAILED(hr))
  61. {
  62. goto exit;
  63. }
  64. hr = m_poolKeyTypes.Initialize(10);
  65. if(FAILED(hr))
  66. {
  67. goto exit;
  68. }
  69. hr = m_poolKeyTypeNodes.Initialize(10);
  70. if(FAILED(hr))
  71. {
  72. goto exit;
  73. }
  74. hr = m_spoolStrings.Initialize();
  75. if(FAILED(hr))
  76. {
  77. goto exit;
  78. }
  79. hr = m_apoolPMbp.Initialize();
  80. if(FAILED(hr))
  81. {
  82. goto exit;
  83. }
  84. hr = m_apoolBytes.Initialize();
  85. if(FAILED(hr))
  86. {
  87. goto exit;
  88. }
  89. exit:
  90. if(SUCCEEDED(hr))
  91. {
  92. m_bInitSuccessful = true;
  93. }
  94. return hr;
  95. }
  96. HRESULT CDynSchema::RulePopulateFromStatic()
  97. /*++
  98. Synopsis:
  99. Populates hashtables with pointers to hardcoded schema.
  100. Return Value:
  101. --*/
  102. {
  103. DBG_ASSERT(m_bInitCalled == true);
  104. DBG_ASSERT(m_bInitSuccessful == true);
  105. HRESULT hr = WBEM_S_NO_ERROR;
  106. //
  107. // Populate Properties
  108. //
  109. if(METABASE_PROPERTY_DATA::s_MetabaseProperties != NULL)
  110. {
  111. METABASE_PROPERTY* pStatMbpCurrent;
  112. for(ULONG i = 0; ; i++)
  113. {
  114. pStatMbpCurrent = METABASE_PROPERTY_DATA::s_MetabaseProperties[i];
  115. if(pStatMbpCurrent == NULL)
  116. {
  117. break;
  118. }
  119. hr = m_hashProps.Wmi_Insert(pStatMbpCurrent->pszPropName, pStatMbpCurrent);
  120. if(FAILED(hr))
  121. {
  122. goto exit;
  123. }
  124. }
  125. }
  126. //
  127. // Populate KeyTypes
  128. //
  129. METABASE_KEYTYPE** apMetabaseKeyTypes;
  130. apMetabaseKeyTypes = METABASE_KEYTYPE_DATA::s_MetabaseKeyTypes;
  131. for(ULONG i = 0; apMetabaseKeyTypes[i] != NULL; i++)
  132. {
  133. if( apMetabaseKeyTypes[i]->m_pszName != NULL )
  134. {
  135. apMetabaseKeyTypes[i]->m_pKtListInverseCCL = NULL;
  136. hr = m_hashKeyTypes.Wmi_Insert(apMetabaseKeyTypes[i]->m_pszName,
  137. apMetabaseKeyTypes[i]);
  138. if(FAILED(hr))
  139. {
  140. goto exit;
  141. }
  142. }
  143. }
  144. exit:
  145. return hr;
  146. }
  147. HRESULT CDynSchema::Rule2PopulateFromStatic()
  148. /*++
  149. Synopsis:
  150. Populates hashtables with pointers to hardcoded schema.
  151. Return Value:
  152. --*/
  153. {
  154. DBG_ASSERT(m_bInitCalled == true);
  155. DBG_ASSERT(m_bInitSuccessful == true);
  156. HRESULT hr = S_OK;
  157. int i;
  158. //
  159. // Populate Classes
  160. //
  161. WMI_CLASS* pStatWmiClassCurrent;
  162. for(i = 0; ; i++)
  163. {
  164. pStatWmiClassCurrent = WMI_CLASS_DATA::s_WmiClasses[i];
  165. if(pStatWmiClassCurrent == NULL)
  166. {
  167. break;
  168. }
  169. hr = m_hashClasses.Wmi_Insert(
  170. pStatWmiClassCurrent->pszClassName,
  171. pStatWmiClassCurrent);
  172. if(FAILED(hr))
  173. {
  174. goto exit;
  175. }
  176. }
  177. //
  178. // Populate Associations
  179. //
  180. WMI_ASSOCIATION* pStatWmiAssocCurrent;
  181. for(i = 0; ; i++)
  182. {
  183. pStatWmiAssocCurrent = WMI_ASSOCIATION_DATA::s_WmiAssociations[i];
  184. if(pStatWmiAssocCurrent == NULL)
  185. {
  186. break;
  187. }
  188. hr = m_hashAssociations.Wmi_Insert(
  189. pStatWmiAssocCurrent->pszAssociationName,
  190. pStatWmiAssocCurrent);
  191. if(FAILED(hr))
  192. {
  193. goto exit;
  194. }
  195. }
  196. exit:
  197. return hr;
  198. }
  199. HRESULT CDynSchema::RuleKeyType(
  200. const CTableMeta *i_pTableMeta)
  201. /*++
  202. Synopsis:
  203. If not already in hashtable of keytypes, a keytype structure
  204. is allocated thru the keytype pool. Then, a pointer to it is inserted
  205. in hashtable.
  206. Arguments: [i_pTableMeta] -
  207. Return Value:
  208. --*/
  209. {
  210. DBG_ASSERT(m_bInitCalled == true);
  211. DBG_ASSERT(m_bInitSuccessful == true);
  212. DBG_ASSERT(i_pTableMeta != NULL);
  213. HRESULT hr = WBEM_S_NO_ERROR;
  214. HRESULT hrTemp = WBEM_S_NO_ERROR;
  215. METABASE_KEYTYPE* pktNew;
  216. LPWSTR wszNew;
  217. hrTemp = m_hashKeyTypes.Wmi_GetByKey(
  218. i_pTableMeta->TableMeta.pInternalName,
  219. &pktNew);
  220. if(FAILED(hrTemp))
  221. {
  222. hr = m_spoolStrings.GetNewString(i_pTableMeta->TableMeta.pInternalName, &wszNew);
  223. if(FAILED(hr))
  224. {
  225. goto exit;
  226. }
  227. hr = m_poolKeyTypes.GetNewElement(&pktNew);
  228. if(FAILED(hr))
  229. {
  230. goto exit;
  231. }
  232. pktNew->m_pszName = wszNew;
  233. pktNew->m_pKtListInverseCCL = NULL;
  234. m_hashKeyTypes.Wmi_Insert(wszNew, pktNew);
  235. if(FAILED(hr))
  236. {
  237. goto exit;
  238. }
  239. }
  240. exit:
  241. return hr;
  242. }
  243. HRESULT CDynSchema::RuleWmiClassDescription(
  244. const CTableMeta* i_pTableMeta,
  245. WMI_CLASS* i_pElementClass,
  246. WMI_CLASS* i_pSettingClass) const
  247. /*++
  248. Synopsis:
  249. Sets WMI_CLASS::pDescription if needed.
  250. This pointer will be invalid after initialization since it points to
  251. catalog.
  252. Arguments: [i_pTableMeta] -
  253. [i_pElementClass] -
  254. [i_pSettingClass] -
  255. Return Value:
  256. --*/
  257. {
  258. DBG_ASSERT(m_bInitCalled == true);
  259. DBG_ASSERT(m_bInitSuccessful == true);
  260. DBG_ASSERT(i_pTableMeta != NULL);
  261. DBG_ASSERT(i_pElementClass != NULL);
  262. DBG_ASSERT(i_pSettingClass != NULL);
  263. HRESULT hr = WBEM_S_NO_ERROR;
  264. if(i_pTableMeta->TableMeta.pDescription != NULL)
  265. {
  266. i_pElementClass->pszDescription = i_pTableMeta->TableMeta.pDescription;
  267. i_pSettingClass->pszDescription = i_pTableMeta->TableMeta.pDescription;
  268. }
  269. return hr;
  270. }
  271. HRESULT CDynSchema::RuleWmiClass(
  272. const CTableMeta* i_pTableMeta,
  273. WMI_CLASS** o_ppElementClass,
  274. WMI_CLASS** o_ppSettingClass,
  275. DWORD io_adwIgnoredProps[])
  276. /*++
  277. Synopsis:
  278. Creates an Element and Setting class based on
  279. i_pTableMeta->TableMeta.pInternalName. If not in hashtable of classes,
  280. these classes are inserted.
  281. At bottom,
  282. RuleProperties is called to set up list of properties for each class.
  283. Arguments: [i_pTableMeta] -
  284. [o_ppElementClass] - can be NULL
  285. [o_ppSettingClass] - can be NULL
  286. Return Value:
  287. --*/
  288. {
  289. DBG_ASSERT(m_bInitCalled == true);
  290. DBG_ASSERT(m_bInitSuccessful == true);
  291. DBG_ASSERT(i_pTableMeta != NULL);
  292. WMI_CLASS* pWmiClass = NULL;
  293. WMI_CLASS* pWmiSettingsClass = NULL;
  294. LPWSTR wszClassName, wszSettingsClassName;
  295. LPWSTR wszParentClassName, wszParentSettingsClassName;
  296. HRESULT hr = WBEM_S_NO_ERROR;
  297. HRESULT hrTemp = WBEM_S_NO_ERROR;
  298. ULONG cPropsAndTagsRW = 0;
  299. ULONG cPropsAndTagsRO = 0;
  300. ULONG iShipped = 0;
  301. CColumnMeta* pColumnMeta;
  302. ULONG cchTable;
  303. //
  304. // Ignore table if it has no name
  305. //
  306. if(i_pTableMeta->TableMeta.pInternalName == NULL)
  307. {
  308. hr = WBEM_S_NO_ERROR;
  309. goto exit;
  310. }
  311. //
  312. // Determine iShipped and Parent Classes
  313. //
  314. if(fTABLEMETA_USERDEFINED & *i_pTableMeta->TableMeta.pSchemaGeneratorFlags)
  315. {
  316. iShipped = USER_DEFINED_TO_REPOSITORY;
  317. DBG_ASSERT(iShipped != USER_DEFINED_NOT_TO_REPOSITORY);
  318. wszParentClassName = g_wszExtElementParent;
  319. wszParentSettingsClassName = g_wszExtSettingParent;
  320. }
  321. else
  322. {
  323. if(fTABLEMETA_EXTENDED & *i_pTableMeta->TableMeta.pSchemaGeneratorFlags)
  324. {
  325. iShipped = EXTENDED;
  326. }
  327. else
  328. {
  329. iShipped = SHIPPED_TO_MOF;
  330. }
  331. wszParentClassName = g_wszElementParent;
  332. wszParentSettingsClassName = g_wszSettingParent;
  333. }
  334. //
  335. // Determine number of RO and RW properties
  336. //
  337. for(ULONG idxProps = 0; idxProps < i_pTableMeta->ColCount(); idxProps++)
  338. {
  339. pColumnMeta = i_pTableMeta->paColumns[idxProps];
  340. if(*pColumnMeta->ColumnMeta.pSchemaGeneratorFlags &
  341. fCOLUMNMETA_CACHE_PROPERTY_MODIFIED)
  342. {
  343. cPropsAndTagsRW += pColumnMeta->cNrTags + 1;
  344. }
  345. else
  346. {
  347. cPropsAndTagsRO += pColumnMeta->cNrTags + 1;
  348. }
  349. }
  350. cchTable = wcslen(i_pTableMeta->TableMeta.pInternalName);
  351. //
  352. // The keytype should already exist.
  353. //
  354. METABASE_KEYTYPE* pktTemp;
  355. hrTemp = m_hashKeyTypes.Wmi_GetByKey(i_pTableMeta->TableMeta.pInternalName, &pktTemp);
  356. if( FAILED(hrTemp) )
  357. {
  358. goto exit;
  359. }
  360. //
  361. // The Element class (named PrefixC)
  362. //
  363. hr = m_spoolStrings.GetNewArray(g_cchIIs_+cchTable+1, &wszClassName);
  364. if(FAILED(hr))
  365. {
  366. goto exit;
  367. }
  368. memcpy(wszClassName, g_wszIIs_, sizeof(WCHAR)*g_cchIIs_);
  369. memcpy(&wszClassName[g_cchIIs_],
  370. i_pTableMeta->TableMeta.pInternalName,
  371. sizeof(WCHAR)*(cchTable+1));
  372. if(FAILED(m_hashClasses.Wmi_GetByKey(wszClassName, &pWmiClass)))
  373. {
  374. hr = m_poolClasses.GetNewElement(&pWmiClass);
  375. if(FAILED(hr))
  376. {
  377. goto exit;
  378. }
  379. pWmiClass->pkt = pktTemp;
  380. pWmiClass->pszClassName = wszClassName;
  381. pWmiClass->pszMetabaseKey = L"/LM";
  382. pWmiClass->pszKeyName = L"Name";
  383. pWmiClass->ppMethod = NULL;
  384. pWmiClass->pszParentClass = wszParentClassName;
  385. pWmiClass->bCreateAllowed = true;
  386. pWmiClass->pszDescription = NULL;
  387. hr = m_hashClasses.Wmi_Insert(wszClassName, pWmiClass);
  388. if(FAILED(hr))
  389. {
  390. goto exit;
  391. }
  392. }
  393. pWmiClass->ppmbp = NULL;
  394. pWmiClass->dwExtended = iShipped;
  395. //
  396. // The Settings class (named PrefixCSetting)
  397. //
  398. hr = m_spoolStrings.GetNewArray(g_cchIIs_+cchTable+g_cchSettings+1, &wszSettingsClassName);
  399. if(FAILED(hr))
  400. {
  401. goto exit;
  402. }
  403. memcpy(wszSettingsClassName, g_wszIIs_, sizeof(WCHAR)*g_cchIIs_);
  404. memcpy(&wszSettingsClassName[g_cchIIs_],
  405. i_pTableMeta->TableMeta.pInternalName,
  406. sizeof(WCHAR)*cchTable);
  407. memcpy(&wszSettingsClassName[g_cchIIs_+cchTable],
  408. g_wszSettings,
  409. sizeof(WCHAR)*(g_cchSettings+1));
  410. if(FAILED(m_hashClasses.Wmi_GetByKey(wszSettingsClassName, &pWmiSettingsClass)))
  411. {
  412. hr = m_poolClasses.GetNewElement(&pWmiSettingsClass);
  413. if(FAILED(hr))
  414. {
  415. goto exit;
  416. }
  417. pWmiSettingsClass->pkt = pktTemp;
  418. pWmiSettingsClass->pszClassName = wszSettingsClassName;
  419. pWmiSettingsClass->pszMetabaseKey = L"/LM";
  420. pWmiSettingsClass->pszKeyName = L"Name";
  421. pWmiSettingsClass->ppMethod = NULL;
  422. pWmiSettingsClass->pszParentClass = wszParentSettingsClassName;
  423. pWmiSettingsClass->bCreateAllowed = true;
  424. pWmiSettingsClass->pszDescription = NULL;
  425. hr = m_hashClasses.Wmi_Insert(wszSettingsClassName, pWmiSettingsClass);
  426. if(FAILED(hr))
  427. {
  428. goto exit;
  429. }
  430. }
  431. pWmiSettingsClass->ppmbp = NULL;
  432. pWmiSettingsClass->dwExtended = iShipped;
  433. //
  434. // Fill in the ppmbp field
  435. //
  436. hr = RuleProperties(
  437. i_pTableMeta,
  438. cPropsAndTagsRO,
  439. pWmiClass,
  440. cPropsAndTagsRW,
  441. pWmiSettingsClass,
  442. io_adwIgnoredProps);
  443. if(FAILED(hr))
  444. {
  445. goto exit;
  446. }
  447. exit:
  448. if(SUCCEEDED(hr))
  449. {
  450. if(o_ppElementClass != NULL)
  451. {
  452. *o_ppElementClass = pWmiClass;
  453. }
  454. if(o_ppSettingClass != NULL)
  455. {
  456. *o_ppSettingClass = pWmiSettingsClass;
  457. }
  458. }
  459. return hr;
  460. }
  461. HRESULT CDynSchema::RuleProperties(
  462. const CTableMeta* i_pTableMeta,
  463. ULONG i_cPropsAndTagsRO,
  464. WMI_CLASS* io_pWmiClass,
  465. ULONG i_cPropsAndTagsRW,
  466. WMI_CLASS* io_pWmiSettingsClass,
  467. DWORD io_adwIgnoredProps[])
  468. /*++
  469. Synopsis:
  470. Given i_pTableMeta, puts the properties either under the Element class
  471. or under the Setting class.
  472. Arguments: [i_pTableMeta] -
  473. [i_cPropsAndTagsRO] -
  474. [o_papMbp] -
  475. [i_cPropsAndTagsRW] -
  476. [o_papMbpSettings] -
  477. Return Value:
  478. --*/
  479. {
  480. DBG_ASSERT(m_bInitCalled == true);
  481. DBG_ASSERT(m_bInitSuccessful == true);
  482. DBG_ASSERT(i_pTableMeta != NULL);
  483. DBG_ASSERT(io_pWmiClass != NULL);
  484. DBG_ASSERT(io_pWmiSettingsClass != NULL);
  485. // DBG_ASSERT(sizeof(io_awszIgnoredProps) >= sizeof(g_awszPropIgnoreList));
  486. HRESULT hr = WBEM_S_NO_ERROR;
  487. CColumnMeta* pColumnMeta = NULL;
  488. METABASE_PROPERTY* pMbp;
  489. ULONG idxProps = 0;
  490. ULONG idxTags = 0;
  491. ULONG idxPropsAndTagsRO = 0;
  492. ULONG idxPropsAndTagsRW = 0;
  493. METABASE_PROPERTY*** papMbp = &io_pWmiClass->ppmbp;
  494. METABASE_PROPERTY*** papMbpSettings = &io_pWmiSettingsClass->ppmbp;
  495. //
  496. // Allocate enough memory for the RO properties
  497. //
  498. if(i_cPropsAndTagsRO > 0)
  499. {
  500. hr = m_apoolPMbp.GetNewArray(i_cPropsAndTagsRO+1, papMbp);
  501. if(FAILED(hr))
  502. {
  503. goto exit;
  504. }
  505. memset(*papMbp, 0, (1+i_cPropsAndTagsRO)*sizeof(METABASE_PROPERTY*));
  506. }
  507. //
  508. // Allocate enough memory for the RW properties
  509. //
  510. if(i_cPropsAndTagsRW > 0)
  511. {
  512. hr = m_apoolPMbp.GetNewArray(i_cPropsAndTagsRW+1, papMbpSettings);
  513. if(FAILED(hr))
  514. {
  515. goto exit;
  516. }
  517. memset(*papMbpSettings, 0, (1+i_cPropsAndTagsRW)*sizeof(METABASE_PROPERTY*));
  518. }
  519. //
  520. // Walk thru all the properties
  521. //
  522. for (idxProps=0, idxPropsAndTagsRO = 0, idxPropsAndTagsRW = 0;
  523. idxProps < i_pTableMeta->ColCount();
  524. ++idxProps)
  525. {
  526. pColumnMeta = i_pTableMeta->paColumns[idxProps];
  527. //
  528. // Ignore property if its in g_adwPropIgnoreList and store the prop in
  529. // io_adwIgnoredProps
  530. //
  531. if( (*pColumnMeta->ColumnMeta.pSchemaGeneratorFlags & fCOLUMNMETA_HIDDEN) ||
  532. IgnoreProperty(io_pWmiClass->pkt, *(pColumnMeta->ColumnMeta.pID), io_adwIgnoredProps) )
  533. {
  534. continue;
  535. }
  536. //
  537. // Call RulePropertiesHelper if Property is not already in the
  538. // properties hashtable
  539. //
  540. if(FAILED(m_hashProps.Wmi_GetByKey(pColumnMeta->ColumnMeta.pInternalName, &pMbp)))
  541. {
  542. hr = RulePropertiesHelper(pColumnMeta, &pMbp, NULL);
  543. if(FAILED(hr))
  544. {
  545. goto exit;
  546. }
  547. }
  548. //
  549. // If RW, put pointer to property in Setting class, else in Element
  550. // class.
  551. //
  552. if(*pColumnMeta->ColumnMeta.pSchemaGeneratorFlags &
  553. fCOLUMNMETA_CACHE_PROPERTY_MODIFIED)
  554. {
  555. (*papMbpSettings)[idxPropsAndTagsRW] = pMbp;
  556. idxPropsAndTagsRW++;
  557. }
  558. else
  559. {
  560. (*papMbp)[idxPropsAndTagsRO] = pMbp;
  561. idxPropsAndTagsRO++;
  562. }
  563. //
  564. // Same steps as above, except for the tags.
  565. //
  566. for(idxTags=0; idxTags < pColumnMeta->cNrTags; idxTags++)
  567. {
  568. if(FAILED(m_hashProps.Wmi_GetByKey(pColumnMeta->paTags[idxTags]->pInternalName, &pMbp)))
  569. {
  570. hr = RulePropertiesHelper(pColumnMeta, &pMbp, &idxTags);
  571. if(FAILED(hr))
  572. {
  573. goto exit;
  574. }
  575. }
  576. if(*pColumnMeta->ColumnMeta.pSchemaGeneratorFlags &
  577. fCOLUMNMETA_CACHE_PROPERTY_MODIFIED)
  578. {
  579. (*papMbpSettings)[idxPropsAndTagsRW] = pMbp;
  580. idxPropsAndTagsRW++;
  581. }
  582. else
  583. {
  584. (*papMbp)[idxPropsAndTagsRO] = pMbp;
  585. idxPropsAndTagsRO++;
  586. }
  587. }
  588. }
  589. exit:
  590. return hr;
  591. }
  592. HRESULT CDynSchema::RulePropertiesHelper(
  593. const CColumnMeta* i_pColumnMeta,
  594. METABASE_PROPERTY** o_ppMbp,
  595. ULONG* i_idxTag)
  596. /*++
  597. Synopsis:
  598. This class creates a property and inserts it into the hashtable of props.
  599. PRECONDITION: The property does not exist in the hashtable yet.
  600. i_idxTag is null if you want to insert the property. else you want to
  601. insert a tag, and *i_idxTag is the index of the tag
  602. Arguments: [i_pColumnMeta] -
  603. [o_ppMbp] -
  604. [i_idxTag] -
  605. Return Value:
  606. --*/
  607. {
  608. DBG_ASSERT(m_bInitCalled == true);
  609. DBG_ASSERT(m_bInitSuccessful == true);
  610. DBG_ASSERT(i_pColumnMeta != NULL);
  611. DBG_ASSERT(o_ppMbp != NULL);
  612. HRESULT hr = WBEM_S_NO_ERROR;
  613. METABASE_PROPERTY* pMbp = NULL;
  614. hr = m_poolProps.GetNewElement(&pMbp);
  615. if(FAILED(hr))
  616. {
  617. goto exit;
  618. }
  619. if(i_idxTag == NULL)
  620. {
  621. pMbp->dwMDMask = 0;
  622. hr = m_spoolStrings.GetNewString(
  623. i_pColumnMeta->ColumnMeta.pInternalName,
  624. &(pMbp->pszPropName));
  625. if(FAILED(hr))
  626. {
  627. goto exit;
  628. }
  629. }
  630. else
  631. {
  632. pMbp->dwMDMask = *(i_pColumnMeta->paTags[*i_idxTag]->pValue);
  633. hr = m_spoolStrings.GetNewString(
  634. i_pColumnMeta->paTags[*i_idxTag]->pInternalName,
  635. &(pMbp->pszPropName));
  636. if(FAILED(hr))
  637. {
  638. goto exit;
  639. }
  640. }
  641. pMbp->dwMDIdentifier = *(i_pColumnMeta->ColumnMeta.pID);
  642. pMbp->dwMDUserType = *(i_pColumnMeta->ColumnMeta.pUserType);
  643. switch(*(i_pColumnMeta->ColumnMeta.pType))
  644. {
  645. case eCOLUMNMETA_int32:
  646. if(fCOLUMNMETA_BOOL & *(i_pColumnMeta->ColumnMeta.pMetaFlags))
  647. {
  648. if(pMbp->dwMDMask == 0)
  649. {
  650. pMbp->dwMDMask = ALL_BITS_ON;
  651. }
  652. }
  653. pMbp->dwMDDataType = DWORD_METADATA;
  654. pMbp->pDefaultValue = NULL;
  655. #ifdef USE_DEFAULT_VALUES
  656. if(i_pColumnMeta->ColumnMeta.pDefaultValue != NULL)
  657. {
  658. pMbp->dwDefaultValue = *i_pColumnMeta->ColumnMeta.pDefaultValue;
  659. pMbp->pDefaultValue = &pMbp->dwDefaultValue;
  660. }
  661. #endif
  662. break;
  663. case eCOLUMNMETA_String:
  664. if(fCOLUMNMETA_MULTISTRING & *(i_pColumnMeta->ColumnMeta.pMetaFlags))
  665. {
  666. pMbp->dwMDDataType = MULTISZ_METADATA;
  667. }
  668. else if(fCOLUMNMETA_EXPANDSTRING & *(i_pColumnMeta->ColumnMeta.pMetaFlags))
  669. {
  670. pMbp->dwMDDataType = EXPANDSZ_METADATA;
  671. }
  672. else
  673. {
  674. pMbp->dwMDDataType = STRING_METADATA;
  675. }
  676. //
  677. // Default values.
  678. //
  679. pMbp->pDefaultValue = NULL;
  680. #ifdef USE_DEFAULT_VALUES
  681. if(i_pColumnMeta->ColumnMeta.pDefaultValue != NULL)
  682. {
  683. if(pMbp->dwMDDataType != MULTISZ_METADATA)
  684. {
  685. hr = m_spoolStrings.GetNewString(
  686. (LPWSTR)i_pColumnMeta->ColumnMeta.pDefaultValue,
  687. (LPWSTR*)&pMbp->pDefaultValue);
  688. if(FAILED(hr))
  689. {
  690. goto exit;
  691. }
  692. }
  693. else
  694. {
  695. bool bLastCharNull = false;
  696. ULONG idx = 0;
  697. ULONG iLen = 0;
  698. LPWSTR msz = (LPWSTR)i_pColumnMeta->ColumnMeta.pDefaultValue;
  699. do
  700. {
  701. bLastCharNull = msz[idx] == L'\0' ? true : false;
  702. }
  703. while( !(msz[++idx] == L'\0' && bLastCharNull) );
  704. iLen = idx+1;
  705. hr = m_spoolStrings.GetNewArray(
  706. iLen,
  707. (LPWSTR*)&pMbp->pDefaultValue);
  708. if(FAILED(hr))
  709. {
  710. goto exit;
  711. }
  712. memcpy(
  713. pMbp->pDefaultValue,
  714. i_pColumnMeta->ColumnMeta.pDefaultValue,
  715. sizeof(WCHAR)*iLen);
  716. }
  717. }
  718. #endif
  719. break;
  720. case eCOLUMNMETA_BYTES:
  721. pMbp->dwMDDataType = BINARY_METADATA;
  722. pMbp->pDefaultValue = NULL;
  723. #ifdef USE_DEFAULT_VALUES
  724. #ifdef USE_DEFAULT_BINARY_VALUES
  725. if( i_pColumnMeta->ColumnMeta.pDefaultValue != NULL )
  726. {
  727. hr = m_apoolBytes.GetNewArray(
  728. i_pColumnMeta->cbDefaultValue,
  729. (BYTE**)&pMbp->pDefaultValue);
  730. if(FAILED(hr))
  731. {
  732. goto exit;
  733. }
  734. memcpy(
  735. pMbp->pDefaultValue,
  736. i_pColumnMeta->ColumnMeta.pDefaultValue,
  737. i_pColumnMeta->cbDefaultValue);
  738. //
  739. // Use dwDefaultValue to store the length.
  740. //
  741. pMbp->dwDefaultValue = i_pColumnMeta->cbDefaultValue;
  742. }
  743. #endif
  744. #endif
  745. break;
  746. default:
  747. pMbp->dwMDDataType = -1;
  748. pMbp->pDefaultValue = NULL;
  749. break;
  750. }
  751. pMbp->dwMDAttributes = *(i_pColumnMeta->ColumnMeta.pAttributes);
  752. if(*i_pColumnMeta->ColumnMeta.pSchemaGeneratorFlags &
  753. fCOLUMNMETA_CACHE_PROPERTY_MODIFIED)
  754. {
  755. pMbp->fReadOnly = FALSE;
  756. }
  757. else
  758. {
  759. pMbp->fReadOnly = TRUE;
  760. }
  761. hr = m_hashProps.Wmi_Insert(pMbp->pszPropName, pMbp);
  762. if(FAILED(hr))
  763. {
  764. goto exit;
  765. }
  766. exit:
  767. if(SUCCEEDED(hr))
  768. {
  769. *o_ppMbp = pMbp;
  770. }
  771. return hr;
  772. }
  773. bool CDynSchema::IgnoreProperty(
  774. METABASE_KEYTYPE* io_pkt,
  775. DWORD i_dwPropId,
  776. DWORD io_adwIgnored[])
  777. /*++
  778. Synopsis:
  779. Checks to see if i_wszProp is in g_adwPropIgnoreList.
  780. If it is, sets next free element in io_adwIgnored to point to this.
  781. Arguments: [i_wszProp] -
  782. [io_adwIgnored] - Must be as big as g_adwPropIgnoreList.
  783. Allocated AND must be memset to 0 by caller.
  784. Return Value:
  785. true if property is in the ignore list.
  786. false otherwise.
  787. --*/
  788. {
  789. DBG_ASSERT(io_pkt);
  790. if(g_adwPropIgnoreList == NULL)
  791. {
  792. return false;
  793. }
  794. if( io_pkt == &METABASE_KEYTYPE_DATA::s_IIsObject &&
  795. i_dwPropId == MD_KEY_TYPE )
  796. {
  797. return false;
  798. }
  799. for(ULONG i = 0; i < g_cElemPropIgnoreList; i++)
  800. {
  801. if(i_dwPropId == g_adwPropIgnoreList[i])
  802. {
  803. for(ULONG j = 0; j < g_cElemPropIgnoreList; j++)
  804. {
  805. if(io_adwIgnored[j] == NULL)
  806. {
  807. io_adwIgnored[j] = g_adwPropIgnoreList[i];
  808. break;
  809. }
  810. }
  811. return true;
  812. }
  813. }
  814. return false;
  815. }
  816. #if 0
  817. bool CDynSchema::IgnoreProperty(LPCWSTR i_wszProp)
  818. /*++
  819. Synopsis:
  820. Checks to see if i_wszProp is in g_adwPropIgnoreList
  821. Arguments: [i_wszProp] -
  822. Return Value:
  823. --*/
  824. {
  825. DBG_ASSERT(i_wszProp != NULL);
  826. if(g_adwPropIgnoreList == NULL)
  827. {
  828. return false;
  829. }
  830. for(ULONG i = 0; i < g_cElemPropIgnoreList; i++)
  831. {
  832. if(_wcsicmp(i_wszProp, g_adwPropIgnoreList[i]) == 0)
  833. {
  834. return true;
  835. }
  836. }
  837. return false;
  838. }
  839. #endif
  840. HRESULT CDynSchema::RuleGenericAssociations(
  841. WMI_CLASS* i_pcElement,
  842. WMI_CLASS* i_pcSetting,
  843. WMI_ASSOCIATION_TYPE* i_pAssocType,
  844. ULONG i_iShipped)
  845. /*++
  846. Synopsis:
  847. Create the Element/Setting association.
  848. Arguments: [i_pcElement] -
  849. [i_pcSetting] -
  850. [i_iShipped] -
  851. Return Value:
  852. --*/
  853. {
  854. DBG_ASSERT(m_bInitCalled == true);
  855. DBG_ASSERT(m_bInitSuccessful == true);
  856. DBG_ASSERT(i_pcElement != NULL);
  857. DBG_ASSERT(i_pcSetting != NULL);
  858. DBG_ASSERT(i_pAssocType != NULL);
  859. HRESULT hr = WBEM_S_NO_ERROR;
  860. LPWSTR wszElement = i_pcElement->pszClassName;
  861. LPWSTR wszSetting = i_pcSetting->pszClassName;
  862. LPWSTR wszParent = NULL;
  863. LPWSTR wszAssocName;
  864. WMI_ASSOCIATION* pWmiAssoc;
  865. ULONG cchElement = wcslen(wszElement);
  866. ULONG cchSetting = wcslen(wszSetting);
  867. hr = m_spoolStrings.GetNewArray(cchElement+cchSetting+2+1, &wszAssocName);
  868. if(FAILED(hr))
  869. {
  870. goto exit;
  871. }
  872. wcscpy(wszAssocName, wszElement);
  873. wcscat(wszAssocName, L"_");
  874. wcscat(wszAssocName, wszSetting);
  875. hr = m_poolAssociations.GetNewElement(&pWmiAssoc);
  876. if(FAILED(hr))
  877. {
  878. goto exit;
  879. }
  880. if(i_iShipped == USER_DEFINED_TO_REPOSITORY ||
  881. i_iShipped == USER_DEFINED_NOT_TO_REPOSITORY)
  882. {
  883. wszParent = i_pAssocType->pszExtParent;
  884. }
  885. else
  886. {
  887. wszParent = i_pAssocType->pszParent;
  888. }
  889. pWmiAssoc->pszAssociationName = wszAssocName;
  890. pWmiAssoc->pcLeft = i_pcElement;
  891. pWmiAssoc->pcRight = i_pcSetting;
  892. pWmiAssoc->pType = i_pAssocType;
  893. pWmiAssoc->fFlags = 0;
  894. pWmiAssoc->pszParentClass = wszParent;
  895. pWmiAssoc->dwExtended = i_iShipped;
  896. hr = m_hashAssociations.Wmi_Insert(wszAssocName, pWmiAssoc);
  897. if(FAILED(hr))
  898. {
  899. goto exit;
  900. }
  901. exit:
  902. return hr;
  903. }
  904. void CDynSchema::RuleWmiClassServices(
  905. WMI_CLASS* i_pElement,
  906. WMI_CLASS* i_pSetting)
  907. /*++
  908. Synopsis:
  909. Sets the bCreateAllowed fields to false if necessary.
  910. i_pSetting must be the corresponding Setting class to i_pElement.
  911. Also sets i_pElement->pszParentClass
  912. Arguments: [i_pElement] -
  913. [i_pSetting] -
  914. Return Value:
  915. --*/
  916. {
  917. DBG_ASSERT(i_pElement != NULL);
  918. DBG_ASSERT(i_pSetting != NULL);
  919. DBG_ASSERT(m_bInitSuccessful == true);
  920. //
  921. // Element Class Suffixes for which Create will be disallowed
  922. //
  923. static LPCWSTR const wszService = L"Service";
  924. static const ULONG cchService = wcslen(wszService);
  925. //
  926. // We only care about shipped classes
  927. //
  928. if( i_pElement->dwExtended != SHIPPED_TO_MOF &&
  929. i_pElement->dwExtended != SHIPPED_NOT_TO_MOF )
  930. {
  931. return;
  932. }
  933. ULONG cchElement = wcslen(i_pElement->pszClassName);
  934. if( cchElement >= cchService &&
  935. _wcsicmp(wszService, &i_pElement->pszClassName[cchElement-cchService]) == 0 )
  936. {
  937. i_pElement->bCreateAllowed = false;
  938. i_pElement->pszParentClass = L"Win32_Service";
  939. i_pSetting->bCreateAllowed = false;
  940. }
  941. }
  942. HRESULT CDynSchema::RuleWmiClassInverseCCL(
  943. const METABASE_KEYTYPE* pktGroup,
  944. METABASE_KEYTYPE* pktPart)
  945. /*++
  946. Synopsis:
  947. Adds pktGroup to pktPart's inverse container class list
  948. Arguments: [pktGroup] -
  949. [pktPart] -
  950. Return Value:
  951. --*/
  952. {
  953. DBG_ASSERT(m_bInitCalled == true);
  954. DBG_ASSERT(m_bInitSuccessful == true);
  955. DBG_ASSERT(pktGroup != NULL);
  956. DBG_ASSERT(pktPart != NULL);
  957. HRESULT hr = WBEM_S_NO_ERROR;
  958. METABASE_KEYTYPE_NODE* pktnode = NULL;
  959. hr = m_poolKeyTypeNodes.GetNewElement(&pktnode);
  960. if(FAILED(hr))
  961. {
  962. goto exit;
  963. }
  964. pktnode->m_pKt = pktGroup;
  965. pktnode->m_pKtNext = pktPart->m_pKtListInverseCCL;
  966. pktPart->m_pKtListInverseCCL = pktnode;
  967. exit:
  968. return hr;
  969. }
  970. HRESULT CDynSchema::RuleGroupPartAssociations(
  971. const CTableMeta *i_pTableMeta)
  972. /*++
  973. Synopsis:
  974. Walks thru container class list to create Group/Part associations.
  975. Also calls RuleWmiClassInverseCCL for each contained class to create inverse
  976. container class list.
  977. Arguments: [i_pTableMeta] -
  978. Return Value:
  979. --*/
  980. {
  981. DBG_ASSERT(m_bInitCalled == true);
  982. DBG_ASSERT(m_bInitSuccessful == true);
  983. DBG_ASSERT(i_pTableMeta != NULL);
  984. HRESULT hr = WBEM_S_NO_ERROR;
  985. WMI_ASSOCIATION *pWmiAssoc;
  986. WMI_CLASS *pWmiClassLeft;
  987. WMI_CLASS *pWmiClassRight;
  988. LPWSTR wszCCL = NULL; // Needs to be cleaned up
  989. LPWSTR wszGroupClass = NULL; // Ptr to catalog
  990. LPWSTR wszPartClass = NULL; // Ptr to catalog
  991. LPWSTR wszAssocName = NULL; // Ptr to pool
  992. LPWSTR wszTemp = NULL; // Needs to be cleaned up
  993. static LPCWSTR wszSeps = L", ";
  994. ULONG cchGroupClass = 0;
  995. ULONG cchPartClass = 0;
  996. ULONG cchCCL = 0;
  997. wszGroupClass = i_pTableMeta->TableMeta.pInternalName;
  998. cchGroupClass = wcslen(wszGroupClass);
  999. hr = m_hashClasses.Wmi_GetByKey(wszGroupClass, &pWmiClassLeft);
  1000. if(FAILED(hr))
  1001. {
  1002. goto exit;
  1003. }
  1004. if(i_pTableMeta->TableMeta.pContainerClassList &&
  1005. i_pTableMeta->TableMeta.pContainerClassList[0] != L'\0')
  1006. {
  1007. //
  1008. // Make copy of CCL so we can wcstok
  1009. //
  1010. cchCCL = wcslen(i_pTableMeta->TableMeta.pContainerClassList);
  1011. wszCCL = new WCHAR[cchCCL+1];
  1012. if(wszCCL == NULL)
  1013. {
  1014. hr = WBEM_E_OUT_OF_MEMORY;
  1015. goto exit;
  1016. }
  1017. memcpy(wszCCL, i_pTableMeta->TableMeta.pContainerClassList, sizeof(WCHAR)*(cchCCL+1));
  1018. //
  1019. // we will use wszTemp to construct assoc name (GroupClass_PartClass)
  1020. //
  1021. wszTemp = new WCHAR[cchGroupClass+1+cchCCL+1];
  1022. if(wszTemp == NULL)
  1023. {
  1024. hr = WBEM_E_OUT_OF_MEMORY;
  1025. goto exit;
  1026. }
  1027. for(wszPartClass = wcstok(wszCCL, wszSeps);
  1028. wszPartClass != NULL;
  1029. wszPartClass = wcstok(NULL, wszSeps))
  1030. {
  1031. hr = m_hashClasses.Wmi_GetByKey(wszPartClass, &pWmiClassRight);
  1032. if(FAILED(hr))
  1033. {
  1034. //
  1035. // This just means there is a class in the container list that
  1036. // doesn't exist.
  1037. //
  1038. hr = WBEM_S_NO_ERROR;
  1039. continue;
  1040. }
  1041. //
  1042. // Construct association name
  1043. //
  1044. cchPartClass = wcslen(wszPartClass);
  1045. memcpy(wszTemp, wszGroupClass, sizeof(WCHAR)*cchGroupClass);
  1046. memcpy(wszTemp+cchGroupClass, L"_", sizeof(WCHAR));
  1047. memcpy(
  1048. wszTemp + cchGroupClass + 1,
  1049. wszPartClass,
  1050. sizeof(WCHAR)*(cchPartClass+1));
  1051. hr = m_hashAssociations.Wmi_GetByKey(wszTemp, &pWmiAssoc);
  1052. if(SUCCEEDED(hr))
  1053. {
  1054. if( pWmiClassLeft->dwExtended != USER_DEFINED_TO_REPOSITORY &&
  1055. pWmiClassLeft->dwExtended != USER_DEFINED_NOT_TO_REPOSITORY &&
  1056. pWmiClassRight->dwExtended != USER_DEFINED_TO_REPOSITORY &&
  1057. pWmiClassRight->dwExtended != USER_DEFINED_NOT_TO_REPOSITORY )
  1058. {
  1059. //
  1060. // This means we already put this shipped association in, but it is
  1061. // not a conflict.
  1062. // We need this because this method is called twice for each
  1063. // group class.
  1064. //
  1065. continue;
  1066. }
  1067. }
  1068. hr = WBEM_S_NO_ERROR;
  1069. //
  1070. // TODO: Move this outside?
  1071. //
  1072. hr = RuleWmiClassInverseCCL(pWmiClassLeft->pkt, pWmiClassRight->pkt);
  1073. if(FAILED(hr))
  1074. {
  1075. goto exit;
  1076. }
  1077. hr = m_spoolStrings.GetNewString(
  1078. wszTemp,
  1079. cchGroupClass+1+cchPartClass, // cch
  1080. &wszAssocName);
  1081. if(FAILED(hr))
  1082. {
  1083. goto exit;
  1084. }
  1085. hr = m_poolAssociations.GetNewElement(&pWmiAssoc);
  1086. if(FAILED(hr))
  1087. {
  1088. goto exit;
  1089. }
  1090. pWmiAssoc->pszAssociationName = wszAssocName;
  1091. pWmiAssoc->pcLeft = pWmiClassLeft;
  1092. pWmiAssoc->pcRight = pWmiClassRight;
  1093. pWmiAssoc->pType = &WMI_ASSOCIATION_TYPE_DATA::s_Component;
  1094. pWmiAssoc->fFlags = 0;
  1095. if( pWmiClassLeft->dwExtended == EXTENDED ||
  1096. pWmiClassLeft->dwExtended == USER_DEFINED_TO_REPOSITORY ||
  1097. pWmiClassRight->dwExtended == EXTENDED ||
  1098. pWmiClassRight->dwExtended == USER_DEFINED_TO_REPOSITORY)
  1099. {
  1100. pWmiAssoc->pszParentClass = g_wszExtGroupPartAssocParent;
  1101. pWmiAssoc->dwExtended = USER_DEFINED_TO_REPOSITORY;
  1102. }
  1103. else
  1104. {
  1105. pWmiAssoc->pszParentClass = g_wszGroupPartAssocParent;
  1106. pWmiAssoc->dwExtended = SHIPPED_TO_MOF;
  1107. }
  1108. hr = m_hashAssociations.Wmi_Insert(wszAssocName, pWmiAssoc);
  1109. if(FAILED(hr))
  1110. {
  1111. goto exit;
  1112. }
  1113. }
  1114. }
  1115. exit:
  1116. delete [] wszCCL;
  1117. delete [] wszTemp;
  1118. return hr;
  1119. }
  1120. HRESULT CDynSchema::RuleSpecialAssociations(
  1121. DWORD i_adwIgnoredProps[],
  1122. WMI_CLASS* i_pElement)
  1123. /*++
  1124. Synopsis:
  1125. Creates IPSecurity and AdminACL associations
  1126. Arguments: [i_adwIgnoredProps[]] -
  1127. [i_pElement] -
  1128. Return Value:
  1129. --*/
  1130. {
  1131. DBG_ASSERT(i_pElement != NULL);
  1132. HRESULT hr = WBEM_S_NO_ERROR;
  1133. bool bCreateIPSecAssoc = false;
  1134. bool bCreateAdminACLAssoc = false;
  1135. if(i_pElement->dwExtended != SHIPPED_TO_MOF && i_pElement->dwExtended != EXTENDED)
  1136. {
  1137. return hr;
  1138. }
  1139. for(ULONG i = 0;
  1140. i < g_cElemPropIgnoreList && i_adwIgnoredProps[i] != 0;
  1141. i++)
  1142. {
  1143. if(i_adwIgnoredProps[i] == MD_IP_SEC)
  1144. {
  1145. bCreateIPSecAssoc = true;
  1146. }
  1147. else if(i_adwIgnoredProps[i] == MD_ADMIN_ACL)
  1148. {
  1149. bCreateAdminACLAssoc = true;
  1150. }
  1151. }
  1152. if(bCreateIPSecAssoc)
  1153. {
  1154. hr = RuleGenericAssociations(
  1155. i_pElement,
  1156. &WMI_CLASS_DATA::s_IPSecurity,
  1157. &WMI_ASSOCIATION_TYPE_DATA::s_IPSecurity,
  1158. SHIPPED_TO_MOF);
  1159. if(FAILED(hr))
  1160. {
  1161. return hr;
  1162. }
  1163. }
  1164. if(bCreateAdminACLAssoc)
  1165. {
  1166. hr = RuleGenericAssociations(
  1167. i_pElement,
  1168. &WMI_CLASS_DATA::s_AdminACL,
  1169. &WMI_ASSOCIATION_TYPE_DATA::s_AdminACL,
  1170. SHIPPED_TO_MOF);
  1171. if(FAILED(hr))
  1172. {
  1173. return hr;
  1174. }
  1175. }
  1176. return hr;
  1177. }
  1178. HRESULT CDynSchema::ConstructFlatInverseContainerList()
  1179. /*++
  1180. Synopsis:
  1181. Constructs an "inverse flat container class list".
  1182. This list is stored in m_abKtContainers, an array of size iNumKeys*iNumKeys.
  1183. The first iNumKeys entries are for Key #1 and then so on. Let's call this row 1.
  1184. In row 1, entry i corresponds to Key #i.
  1185. This entry [1,i] is set to true if Key #1 can be contained somewhere under Key #i.
  1186. For instance, [IIsWebDirectory, IIsWebService] is true since an IIsWebService
  1187. can contain an IIsWebServer which can contain an IIsWebDirectory.
  1188. Return Value:
  1189. --*/
  1190. {
  1191. DBG_ASSERT(m_bInitCalled == true);
  1192. DBG_ASSERT(m_bInitSuccessful == true);
  1193. ULONG iNumKeys = m_hashKeyTypes.Wmi_GetNumElements();
  1194. m_abKtContainers = new bool[iNumKeys * iNumKeys];
  1195. if(m_abKtContainers == NULL)
  1196. {
  1197. return WBEM_E_OUT_OF_MEMORY;
  1198. }
  1199. memset(m_abKtContainers, 0, iNumKeys * iNumKeys * sizeof(bool));
  1200. CHashTable<METABASE_KEYTYPE*>::iterator iter;
  1201. CHashTable<METABASE_KEYTYPE*>::iterator iterEnd = m_hashKeyTypes.end();
  1202. for (iter = m_hashKeyTypes.begin(); iter != iterEnd; ++iter)
  1203. {
  1204. CHashTable<METABASE_KEYTYPE*>::Record* pRec = iter.Record();
  1205. ConstructFlatInverseContainerListHelper(
  1206. pRec->m_data,
  1207. &m_abKtContainers[pRec->m_idx * iNumKeys]);
  1208. }
  1209. return WBEM_S_NO_ERROR;
  1210. }
  1211. //
  1212. // TODO: Prove this will always terminate.
  1213. //
  1214. void CDynSchema::ConstructFlatInverseContainerListHelper(
  1215. const METABASE_KEYTYPE* i_pkt,
  1216. bool* io_abList)
  1217. /*++
  1218. Synopsis:
  1219. This walks the inverse container class list of i_pkt.
  1220. For each entry, we call ConstructFlatInverseContainerListHelper and mark all the keytypes
  1221. we see on the way.
  1222. We terminate when we hit a keytype we've already seen or if there are no more keytypes
  1223. in the inverse container class list.
  1224. Arguments: [i_pkt] -
  1225. [io_abList] -
  1226. --*/
  1227. {
  1228. DBG_ASSERT(m_bInitCalled == true);
  1229. DBG_ASSERT(m_bInitSuccessful == true);
  1230. DBG_ASSERT(i_pkt != NULL);
  1231. DBG_ASSERT(io_abList != NULL);
  1232. ULONG idx;
  1233. METABASE_KEYTYPE* pktDummy;
  1234. HRESULT hr = WBEM_S_NO_ERROR;
  1235. hr = m_hashKeyTypes.Wmi_GetByKey(i_pkt->m_pszName, &pktDummy, &idx);
  1236. if(FAILED(hr))
  1237. {
  1238. DBG_ASSERT(false && "Keytype should be in hashtable of keytypes");
  1239. return;
  1240. }
  1241. if(io_abList[idx] == true) return;
  1242. io_abList[idx] = true;
  1243. METABASE_KEYTYPE_NODE* pktnode = i_pkt->m_pKtListInverseCCL;
  1244. while(pktnode != NULL)
  1245. {
  1246. ConstructFlatInverseContainerListHelper(pktnode->m_pKt, io_abList);
  1247. pktnode = pktnode->m_pKtNext;
  1248. }
  1249. }
  1250. bool CDynSchema::IsContainedUnder(METABASE_KEYTYPE* i_pktParent, METABASE_KEYTYPE* i_pktChild)
  1251. /*++
  1252. Synopsis:
  1253. Uses m_abKtContainers described above to determine whether i_pktChild can
  1254. be contained somewhere under i_pktParent.
  1255. Arguments: [i_pktParent] -
  1256. [i_pktChild] -
  1257. Return Value:
  1258. --*/
  1259. {
  1260. DBG_ASSERT(m_bInitCalled == true);
  1261. DBG_ASSERT(m_bInitSuccessful == true);
  1262. DBG_ASSERT(i_pktParent != NULL);
  1263. DBG_ASSERT(i_pktChild != NULL);
  1264. HRESULT hr = WBEM_S_NO_ERROR;
  1265. METABASE_KEYTYPE* pktDummy;
  1266. ULONG idxParent;
  1267. ULONG idxChild;
  1268. hr = m_hashKeyTypes.Wmi_GetByKey(i_pktParent->m_pszName, &pktDummy, &idxParent);
  1269. if(FAILED(hr))
  1270. {
  1271. return false;
  1272. }
  1273. hr = m_hashKeyTypes.Wmi_GetByKey(i_pktChild->m_pszName, &pktDummy, &idxChild);
  1274. if(FAILED(hr))
  1275. {
  1276. return false;
  1277. }
  1278. return m_abKtContainers[idxChild * m_hashKeyTypes.Wmi_GetNumElements() + idxParent];
  1279. }
  1280. void CDynSchema::ToConsole()
  1281. {
  1282. DBG_ASSERT(m_bInitCalled == true);
  1283. DBG_ASSERT(m_bInitSuccessful == true);
  1284. /*CHashTableElement<WMI_CLASS *>* pElement;
  1285. m_hashClasses.Enum(NULL, &pElement);
  1286. while(pElement != NULL)
  1287. {
  1288. wprintf(L"%s\n", pElement->m_data->pszClassName);
  1289. // wprintf(L"\tShipped: %d\n", pElement->m_iShipped);
  1290. wprintf(L"\tKT: %s\n", pElement->m_data->pkt->m_pszName);
  1291. wprintf(L"\tKN: %s\n", pElement->m_data->pszKeyName);
  1292. wprintf(L"\tMK: %s\n", pElement->m_data->pszMetabaseKey);
  1293. METABASE_PROPERTY** ppmbp = pElement->m_data->ppmbp;
  1294. for(ULONG q = 0; ppmbp != NULL && ppmbp[q] != NULL; q++)
  1295. {
  1296. wprintf(L"\tProp: %s\n", ppmbp[q]->pszPropName);
  1297. }
  1298. pElement = pElement->m_pNext;
  1299. }
  1300. ULONG i;
  1301. m_hashKeyTypes.ToConsole();
  1302. WMI_CLASS *pWmiClass;
  1303. for(i = 0; i < m_poolClasses.GetUsed(); i++)
  1304. {
  1305. pWmiClass = m_poolClasses.Lookup(i);
  1306. wprintf( L"%s KT: %d\n", pWmiClass->pszClassName, pWmiClass->pkt );
  1307. for(ULONG j = 0; ; j++)
  1308. {
  1309. if(pWmiClass->ppmbp[j] == NULL)
  1310. {
  1311. break;
  1312. }
  1313. wprintf(L"\t%s\tId: %d\tUT: %d\tDT: %d\tMSK: %d\tAttr: %d\tRO: %d\n",
  1314. pWmiClass->ppmbp[j]->pszPropName,
  1315. pWmiClass->ppmbp[j]->dwMDIdentifier,
  1316. pWmiClass->ppmbp[j]->dwMDUserType,
  1317. pWmiClass->ppmbp[j]->dwMDDataType,
  1318. pWmiClass->ppmbp[j]->dwMDMask,
  1319. pWmiClass->ppmbp[j]->dwMDAttributes,
  1320. pWmiClass->ppmbp[j]->fReadOnly);
  1321. }
  1322. }
  1323. WMI_ASSOCIATION *pWmiAssoc;
  1324. for(i = 0; i < m_poolAssociations.GetUsed(); i++)
  1325. {
  1326. pWmiAssoc = m_poolAssociations.Lookup(i);
  1327. wprintf(L"%s\n", pWmiAssoc->pszAssociationName);
  1328. wprintf(L"\t%s\n\t%s\n",
  1329. pWmiAssoc->pcLeft->pszClassName,
  1330. pWmiAssoc->pcRight->pszClassName);
  1331. }
  1332. for(unsigned int q = 0; q < m_poolProps.GetUsed(); q++)
  1333. {
  1334. METABASE_PROPERTY* qt = m_poolProps.Lookup(q);
  1335. wprintf(L"%s\n", qt->pszPropName);
  1336. }*/
  1337. }
  1338. HRESULT CDynSchema::RulePopulateFromDynamic(
  1339. CSchemaExtensions* i_pCatalog,
  1340. BOOL i_bUserDefined)
  1341. {
  1342. DBG_ASSERT(m_bInitSuccessful == true);
  1343. DBG_ASSERT(i_pCatalog != NULL);
  1344. HRESULT hr = WBEM_S_NO_ERROR;
  1345. ULONG i = 0;
  1346. CTableMeta* pTableMeta = NULL;
  1347. WMI_CLASS* pElementClass = NULL;
  1348. WMI_CLASS* pSettingClass = NULL;
  1349. DWORD adwIgnoredProps[g_cElemPropIgnoreList];
  1350. DWORD dwUserDefined = 0;
  1351. while(pTableMeta = i_pCatalog->EnumTables(&i))
  1352. {
  1353. dwUserDefined =
  1354. (fTABLEMETA_USERDEFINED & *pTableMeta->TableMeta.pSchemaGeneratorFlags);
  1355. if( (i_bUserDefined && !dwUserDefined) || (!i_bUserDefined && dwUserDefined) )
  1356. {
  1357. continue;
  1358. }
  1359. memset(adwIgnoredProps, 0, g_cElemPropIgnoreList*sizeof(DWORD));
  1360. pElementClass = NULL;
  1361. pSettingClass = NULL;
  1362. hr = RuleKeyType(pTableMeta);
  1363. if(FAILED(hr))
  1364. {
  1365. return hr;
  1366. }
  1367. DBG_ASSERT(pTableMeta->TableMeta.pInternalName);
  1368. hr = RuleWmiClass(
  1369. pTableMeta,
  1370. &pElementClass,
  1371. &pSettingClass,
  1372. adwIgnoredProps);
  1373. if(FAILED(hr))
  1374. {
  1375. return hr;
  1376. }
  1377. DBG_ASSERT(pElementClass != NULL);
  1378. DBG_ASSERT(pSettingClass != NULL);
  1379. hr = RuleGenericAssociations(
  1380. pElementClass,
  1381. pSettingClass,
  1382. &WMI_ASSOCIATION_TYPE_DATA::s_ElementSetting,
  1383. pElementClass->dwExtended);
  1384. if(FAILED(hr))
  1385. {
  1386. return hr;
  1387. }
  1388. hr = RuleSpecialAssociations(
  1389. adwIgnoredProps,
  1390. pElementClass);
  1391. if(FAILED(hr))
  1392. {
  1393. return hr;
  1394. }
  1395. RuleWmiClassServices(pElementClass, pSettingClass);
  1396. hr = RuleWmiClassDescription(pTableMeta, pElementClass, pSettingClass);
  1397. if(FAILED(hr))
  1398. {
  1399. return hr;
  1400. }
  1401. }
  1402. i = 0;
  1403. while(pTableMeta = i_pCatalog->EnumTables(&i))
  1404. {
  1405. dwUserDefined =
  1406. (fTABLEMETA_USERDEFINED & *pTableMeta->TableMeta.pSchemaGeneratorFlags);
  1407. if( (i_bUserDefined && !dwUserDefined) || (!i_bUserDefined && dwUserDefined) )
  1408. {
  1409. continue;
  1410. }
  1411. hr = RuleGroupPartAssociations(pTableMeta);
  1412. if(FAILED(hr))
  1413. {
  1414. return hr;
  1415. }
  1416. }
  1417. return hr;
  1418. }
  1419. HRESULT CDynSchema::RunRules(
  1420. CSchemaExtensions* i_pCatalog,
  1421. bool i_bUseExtensions)
  1422. /*++
  1423. Synopsis:
  1424. Does all the work
  1425. Arguments: [i_pCatalog] - This function calls Initialize.
  1426. Don't call Init outside this function.
  1427. Return Value:
  1428. --*/
  1429. {
  1430. DBG_ASSERT(m_bInitCalled == true);
  1431. DBG_ASSERT(m_bInitSuccessful == true);
  1432. DBG_ASSERT(i_pCatalog != NULL);
  1433. HRESULT hr = S_OK;
  1434. ULONG i = 0;
  1435. //
  1436. // TODO: Don't think I need this
  1437. //
  1438. if(m_bRulesRun)
  1439. {
  1440. return hr;
  1441. }
  1442. hr = RulePopulateFromStatic();
  1443. if(FAILED(hr))
  1444. {
  1445. return hr;
  1446. }
  1447. hr = Rule2PopulateFromStatic();
  1448. if(FAILED(hr))
  1449. {
  1450. return hr;
  1451. }
  1452. hr = i_pCatalog->Initialize(i_bUseExtensions);
  1453. if(FAILED(hr))
  1454. {
  1455. return hr;
  1456. }
  1457. hr = RulePopulateFromDynamic(
  1458. i_pCatalog,
  1459. false); // shipped schema
  1460. if(FAILED(hr))
  1461. {
  1462. return hr;
  1463. }
  1464. hr = RulePopulateFromDynamic(
  1465. i_pCatalog,
  1466. true); // user-defined schema
  1467. if(FAILED(hr))
  1468. {
  1469. return hr;
  1470. }
  1471. hr = ConstructFlatInverseContainerList();
  1472. if(SUCCEEDED(hr))
  1473. {
  1474. m_bRulesRun = true;
  1475. }
  1476. return hr;
  1477. }