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.

476 lines
12 KiB

  1. //=================================================================
  2. //
  3. // assoc.cpp -- Generic association class
  4. //
  5. // Copyright 1999 Microsoft Corporation
  6. //
  7. //=================================================================
  8. #include <stdafx.h>
  9. #include "precomp.h"
  10. #include <assertbreak.h>
  11. #include "Assoc.h"
  12. CAssociation::CAssociation(
  13. LPCWSTR pwszClassName,
  14. LPCWSTR pwszNamespaceName,
  15. LPCWSTR pwszLeftClassName,
  16. LPCWSTR pwszRightClassName,
  17. LPCWSTR pwszLeftPropertyName,
  18. LPCWSTR pwszRightPropertyName
  19. ) : Provider(pwszClassName, pwszNamespaceName)
  20. {
  21. ASSERT_BREAK( ( pwszClassName != NULL ) &&
  22. ( pwszLeftClassName != NULL ) &&
  23. ( pwszRightClassName != NULL) &&
  24. ( pwszLeftPropertyName != NULL ) &&
  25. ( pwszRightPropertyName != NULL) );
  26. m_pwszLeftClassName = pwszLeftClassName;
  27. m_pwszRightClassName = pwszRightClassName;
  28. m_pwszLeftPropertyName = pwszLeftPropertyName;
  29. m_pwszRightPropertyName = pwszRightPropertyName;
  30. }
  31. CAssociation::~CAssociation()
  32. {
  33. }
  34. HRESULT CAssociation::ExecQuery(
  35. MethodContext* pMethodContext,
  36. CFrameworkQuery &pQuery,
  37. long lFlags
  38. )
  39. {
  40. HRESULT hr = WBEM_S_NO_ERROR;
  41. TRefPointerCollection<CInstance> lefts;
  42. CHStringArray sLeftPaths, sRightPaths;
  43. pQuery.GetValuesForProp ( m_pwszLeftPropertyName, sLeftPaths ) ;
  44. pQuery.GetValuesForProp ( m_pwszRightPropertyName, sRightPaths ) ;
  45. if (sLeftPaths.GetSize() == 0)
  46. {
  47. // GetLeftInstances populates lefts
  48. hr = GetLeftInstances(pMethodContext, lefts);
  49. }
  50. else
  51. {
  52. // For each sLeftPaths that is valid, create an entry in lefts
  53. hr = ValidateLeftObjectPaths(pMethodContext, sLeftPaths, lefts);
  54. }
  55. if (SUCCEEDED(hr) && lefts.GetSize() > 0)
  56. {
  57. if (sRightPaths.GetSize() == 0)
  58. {
  59. // GetRightInstances takes the 'lefts' and rubs all the
  60. // rights against them creating instances where appropriate
  61. hr = GetRightInstances(pMethodContext, &lefts);
  62. }
  63. else
  64. {
  65. TRefPointerCollection<CInstance> rights;
  66. // For each sRightPaths that is valid, create an instance
  67. hr = ValidateRightObjectPaths(pMethodContext, sRightPaths, lefts);
  68. }
  69. }
  70. return hr;
  71. }
  72. HRESULT CAssociation::GetObject(
  73. CInstance* pInstance,
  74. long lFlags,
  75. CFrameworkQuery &pQuery
  76. )
  77. {
  78. HRESULT hr = WBEM_E_NOT_FOUND;
  79. CHString sLeftPath, sRightPath;
  80. // Get the two endpoints
  81. if (pInstance->GetCHString(m_pwszLeftPropertyName, sLeftPath ) &&
  82. pInstance->GetCHString(m_pwszRightPropertyName, sRightPath ) )
  83. {
  84. CInstancePtr pLeft, pRight;
  85. // Try to get the objects
  86. if (SUCCEEDED(hr = RetrieveLeftInstance(sLeftPath, &pLeft, pInstance->GetMethodContext())) &&
  87. SUCCEEDED(hr = RetrieveRightInstance(sRightPath, &pRight, pInstance->GetMethodContext())) )
  88. {
  89. hr = WBEM_E_NOT_FOUND;
  90. // So, the end points exist. Are they derived from or equal to the classes we are working with?
  91. CHString sLeftClass, sRightClass;
  92. pLeft->GetCHString(L"__CLASS", sLeftClass);
  93. pRight->GetCHString(L"__CLASS", sRightClass);
  94. BOOL bDerived = _wcsicmp(m_pwszLeftClassName, sLeftClass) == 0;
  95. if (!bDerived)
  96. {
  97. bDerived = CWbemProviderGlue::IsDerivedFrom(m_pwszLeftClassName, sLeftClass, pInstance->GetMethodContext());
  98. }
  99. if (bDerived)
  100. {
  101. // Left side was correct, now let's check the right
  102. bDerived = _wcsicmp(m_pwszRightClassName, sRightClass) == 0;
  103. if (!bDerived)
  104. {
  105. bDerived = CWbemProviderGlue::IsDerivedFrom(m_pwszRightClassName, sRightClass, pInstance->GetMethodContext());
  106. }
  107. }
  108. if (bDerived)
  109. {
  110. // Just because two instances are valid and derive from the right class, doesn't mean they are related. Do
  111. // any other checks.
  112. if (AreRelated(pLeft, pRight))
  113. {
  114. hr = LoadPropertyValues(pInstance, pLeft, pRight);
  115. }
  116. }
  117. }
  118. }
  119. return hr;
  120. }
  121. HRESULT CAssociation::EnumerateInstances(
  122. MethodContext *pMethodContext,
  123. long lFlags /*= 0L*/
  124. )
  125. {
  126. HRESULT hr = WBEM_S_NO_ERROR;
  127. TRefPointerCollection<CInstance> lefts;
  128. // GetLeftInstances populates lefts
  129. if (SUCCEEDED(hr = GetLeftInstances(pMethodContext, lefts)))
  130. {
  131. // GetRightInstances takes the 'lefts' and rubs all the
  132. // rights against them
  133. hr = GetRightInstances(pMethodContext, &lefts);
  134. }
  135. return hr;
  136. }
  137. HRESULT CAssociation::GetRightInstances(
  138. MethodContext *pMethodContext,
  139. TRefPointerCollection<CInstance> *lefts
  140. )
  141. {
  142. CHString sQuery;
  143. sQuery.Format(L"SELECT __RELPATH FROM %s", m_pwszRightClassName);
  144. // 'StaticEnumerationCallback' will get called once for each instance
  145. // returned from the query
  146. HRESULT hr = CWbemProviderGlue::GetInstancesByQueryAsynch(
  147. sQuery,
  148. this,
  149. StaticEnumerationCallback,
  150. NULL,
  151. pMethodContext,
  152. lefts);
  153. return hr;
  154. }
  155. HRESULT WINAPI CAssociation::StaticEnumerationCallback(
  156. Provider* pThat,
  157. CInstance* pInstance,
  158. MethodContext* pContext,
  159. void* pUserData
  160. )
  161. {
  162. HRESULT hr;
  163. CAssociation *pThis = (CAssociation *) pThat;
  164. ASSERT_BREAK(pThis != NULL);
  165. if (pThis)
  166. {
  167. hr = pThis->EnumerationCallback(pInstance, pContext, pUserData);
  168. }
  169. else
  170. {
  171. hr = WBEM_S_NO_ERROR;
  172. }
  173. return hr;
  174. }
  175. HRESULT CAssociation::EnumerationCallback(
  176. CInstance *pRight,
  177. MethodContext *pMethodContext,
  178. void *pUserData
  179. )
  180. {
  181. HRESULT hr = WBEM_E_FAILED;
  182. CInstancePtr pLeft;
  183. REFPTRCOLLECTION_POSITION posLeft;
  184. CHString sLeftPath, sRightPath;
  185. // Cast for userdata back to what it is
  186. TRefPointerCollection<CInstance> *pLefts = (TRefPointerCollection<CInstance> *)pUserData;
  187. if (pLefts->BeginEnum(posLeft))
  188. {
  189. hr = WBEM_S_NO_ERROR;
  190. // Walk all the pLefts
  191. for (pLeft.Attach(pLefts->GetNext(posLeft)) ;
  192. (SUCCEEDED(hr)) && (pLeft != NULL) ;
  193. pLeft.Attach(pLefts->GetNext(posLeft)) )
  194. {
  195. // Compare it to the current pRight
  196. if(AreRelated(pLeft, pRight))
  197. {
  198. // We have a winner. Populate the properties and send it in.
  199. if (GetLocalInstancePath(pLeft, sLeftPath) &&
  200. GetLocalInstancePath(pRight, sRightPath))
  201. {
  202. CInstancePtr pNewAssoc(CreateNewInstance(pMethodContext), false);
  203. if (pNewAssoc->SetCHString(m_pwszLeftPropertyName, sLeftPath) &&
  204. pNewAssoc->SetCHString(m_pwszRightPropertyName, sRightPath) )
  205. {
  206. if (SUCCEEDED(hr = LoadPropertyValues(pNewAssoc, pLeft, pRight)))
  207. {
  208. hr = pNewAssoc->Commit();
  209. }
  210. }
  211. else
  212. {
  213. ASSERT_BREAK(0);
  214. }
  215. }
  216. }
  217. }
  218. pLefts->EndEnum();
  219. }
  220. return hr;
  221. }
  222. HRESULT CAssociation::ValidateLeftObjectPaths(
  223. MethodContext *pMethodContext,
  224. const CHStringArray &sPaths,
  225. TRefPointerCollection<CInstance> &lefts
  226. )
  227. {
  228. CInstancePtr pInstance;
  229. // Walk the object paths
  230. for (DWORD x=0; x < sPaths.GetSize(); x++)
  231. {
  232. ParsedObjectPath *pParsedPath = NULL;
  233. CObjectPathParser objpathParser;
  234. int nStatus = objpathParser.Parse( sPaths[x], &pParsedPath );
  235. if ( 0 == nStatus )
  236. {
  237. BOOL bDerived;
  238. try
  239. {
  240. bDerived = _wcsicmp(m_pwszLeftClassName, pParsedPath->m_pClass) == 0;
  241. if (!bDerived)
  242. {
  243. bDerived = CWbemProviderGlue::IsDerivedFrom(m_pwszLeftClassName, pParsedPath->m_pClass, pMethodContext);
  244. }
  245. }
  246. catch ( ... )
  247. {
  248. objpathParser.Free( pParsedPath );
  249. throw;
  250. }
  251. objpathParser.Free( pParsedPath );
  252. if (bDerived)
  253. {
  254. // See if it is valid
  255. if (SUCCEEDED(RetrieveLeftInstance(sPaths[x], &pInstance, pMethodContext)))
  256. {
  257. // Yup, add it to the list
  258. lefts.Add(pInstance);
  259. }
  260. }
  261. }
  262. }
  263. return WBEM_S_NO_ERROR;
  264. }
  265. HRESULT CAssociation::ValidateRightObjectPaths(
  266. MethodContext *pMethodContext,
  267. const CHStringArray &sPaths,
  268. TRefPointerCollection<CInstance> &lefts
  269. )
  270. {
  271. HRESULT hr = WBEM_S_NO_ERROR;;
  272. CInstancePtr pInstance;
  273. // Walk the object paths
  274. for (DWORD x=0;
  275. (x < sPaths.GetSize()) && SUCCEEDED(hr);
  276. x++)
  277. {
  278. ParsedObjectPath *pParsedPath = NULL;
  279. CObjectPathParser objpathParser;
  280. int nStatus = objpathParser.Parse( sPaths[x], &pParsedPath );
  281. if ( 0 == nStatus )
  282. {
  283. BOOL bDerived;
  284. try
  285. {
  286. bDerived = _wcsicmp(m_pwszRightClassName, pParsedPath->m_pClass) == 0;
  287. if (!bDerived)
  288. {
  289. bDerived = CWbemProviderGlue::IsDerivedFrom(m_pwszRightClassName, pParsedPath->m_pClass, pMethodContext);
  290. }
  291. }
  292. catch ( ... )
  293. {
  294. objpathParser.Free( pParsedPath );
  295. throw;
  296. }
  297. objpathParser.Free( pParsedPath );
  298. if (bDerived)
  299. {
  300. // See if it is valid
  301. if (SUCCEEDED(RetrieveRightInstance(sPaths[x], &pInstance, pMethodContext)))
  302. {
  303. hr = EnumerationCallback(pInstance, pMethodContext, &lefts);
  304. }
  305. }
  306. }
  307. }
  308. return hr;
  309. }
  310. HRESULT CAssociation::GetLeftInstances(
  311. MethodContext *pMethodContext,
  312. TRefPointerCollection<CInstance> &lefts
  313. )
  314. {
  315. CHString sQuery;
  316. sQuery.Format(L"SELECT __RELPATH FROM %s", m_pwszLeftClassName);
  317. return CWbemProviderGlue::GetInstancesByQuery(sQuery, &lefts, pMethodContext);
  318. }
  319. HRESULT CAssociation::RetrieveLeftInstance(
  320. LPCWSTR lpwszObjPath,
  321. CInstance **ppInstance,
  322. MethodContext *pMethodContext
  323. )
  324. {
  325. return CWbemProviderGlue::GetInstanceKeysByPath(lpwszObjPath, ppInstance, pMethodContext);
  326. }
  327. HRESULT CAssociation::RetrieveRightInstance(
  328. LPCWSTR lpwszObjPath,
  329. CInstance **ppInstance,
  330. MethodContext *pMethodContext
  331. )
  332. {
  333. return CWbemProviderGlue::GetInstanceKeysByPath(lpwszObjPath, ppInstance, pMethodContext);
  334. }
  335. /*
  336. //========================
  337. CAssocSystemToOS::CAssocSystemToOS(
  338. LPCWSTR pwszClassName,
  339. LPCWSTR pwszNamespaceName,
  340. LPCWSTR pwszLeftClassName,
  341. LPCWSTR pwszRightClassName,
  342. LPCWSTR pwszLeftPropertyName,
  343. LPCWSTR pwszRightPropertyName
  344. ) : CAssociation (
  345. pwszClassName,
  346. pwszNamespaceName,
  347. pwszLeftClassName,
  348. pwszRightClassName,
  349. pwszLeftPropertyName,
  350. pwszRightPropertyName
  351. )
  352. {
  353. }
  354. CAssocSystemToOS::~CAssocSystemToOS()
  355. {
  356. }
  357. HRESULT CAssocSystemToOS::LoadPropertyValues(
  358. CInstance *pInstance,
  359. const CInstance *pLeft,
  360. const CInstance *pRight
  361. )
  362. {
  363. CAssociation::LoadPropertyValues(pInstance, pLeft, pRight);
  364. // This will work... until win32_os returns more than one instance.
  365. pInstance->Setbool(L"PrimaryOS", true);
  366. return WBEM_S_NO_ERROR;
  367. }
  368. CAssocSystemToOS MySystemToOperatingSystem(
  369. L"Win32_SystemOperatingSystem",
  370. L"root\\cimv2",
  371. L"Win32_ComputerSystem",
  372. L"Win32_OperatingSystem",
  373. IDS_GroupComponent,
  374. IDS_PartComponent
  375. ) ;
  376. */
  377. bool CAssociation::IsInstance(const CInstance *pInstance)
  378. {
  379. DWORD dwGenus = 0;
  380. pInstance->GetDWORD(L"__Genus", dwGenus);
  381. return dwGenus == WBEM_GENUS_INSTANCE;
  382. }