Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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