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.

550 lines
12 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000
  6. //
  7. // File: cimmap.cpp
  8. //
  9. //
  10. // This file contains routines that will establish a mapping between
  11. // Wdm class instances and Cdm class instances. See
  12. // MapWdmClassToCimClass for more information.
  13. //
  14. //--------------------------------------------------------------------------
  15. #include <windows.h>
  16. #include <wbemidl.h>
  17. #include "wbemmisc.h"
  18. #include "debug.h"
  19. #include "cimmap.h"
  20. HRESULT WdmInstanceNameToPnPId(
  21. IWbemServices *pWdmServices,
  22. BSTR WdmInstanceName,
  23. VARIANT /* FREE */ *PnPId
  24. )
  25. /*+++
  26. Routine Description:
  27. This routine will convert a Wdm instance name into its
  28. corresponding pnp id
  29. Arguments:
  30. pWdmServices is the pointer to the root\wmi namespace
  31. WdmInstanceName
  32. *PnPId returns with the pnp id
  33. Return Value:
  34. HRESULT
  35. ---*/
  36. {
  37. WCHAR Query[2 * MAX_PATH];
  38. WCHAR s[MAX_PATH];
  39. BSTR sQuery;
  40. HRESULT hr;
  41. IEnumWbemClassObject *pWdmEnumInstances;
  42. IWbemClassObject *pWdmInstance;
  43. ULONG Count;
  44. BSTR sWQL;
  45. WmipAssert(pWdmServices != NULL);
  46. WmipAssert(WdmInstanceName != NULL);
  47. WmipAssert(PnPId != NULL);
  48. sWQL = SysAllocString(L"WQL");
  49. if (sWQL != NULL)
  50. {
  51. //
  52. // First get PnP id from Instance name from the MSWmi_PnPDeviceId
  53. // class (select * from MSWMI_PnPDeviceId where InstanceName =
  54. // "<WdmInstanceName>"
  55. //
  56. wsprintfW(Query,
  57. L"select * from MSWmi_PnPDeviceId where InstanceName = \"%ws\"",
  58. AddSlashesToStringW(s, WdmInstanceName));
  59. sQuery = SysAllocString(Query);
  60. if (sQuery != NULL)
  61. {
  62. hr = pWdmServices->ExecQuery(sWQL,
  63. sQuery,
  64. WBEM_FLAG_FORWARD_ONLY |
  65. WBEM_FLAG_ENSURE_LOCATABLE,
  66. NULL,
  67. &pWdmEnumInstances);
  68. if (hr == WBEM_S_NO_ERROR)
  69. {
  70. hr = pWdmEnumInstances->Next(WBEM_INFINITE,
  71. 1,
  72. &pWdmInstance,
  73. &Count);
  74. if ((hr == WBEM_S_NO_ERROR) &&
  75. (Count == 1))
  76. {
  77. hr = WmiGetProperty(pWdmInstance,
  78. L"PnPDeviceId",
  79. CIM_STRING,
  80. PnPId);
  81. pWdmInstance->Release();
  82. }
  83. pWdmEnumInstances->Release();
  84. } else {
  85. WmipDebugPrint(("CDMPROV: Query %ws failed %x\n",
  86. sQuery, hr));
  87. }
  88. SysFreeString(sQuery);
  89. } else {
  90. hr = WBEM_E_OUT_OF_MEMORY;
  91. }
  92. SysFreeString(sWQL);
  93. } else {
  94. hr = WBEM_E_OUT_OF_MEMORY;
  95. }
  96. return(hr);
  97. }
  98. HRESULT FindCimClassByWdmInstanceName(
  99. IN IWbemServices *pWdmServices,
  100. IN IWbemServices *pCimServices,
  101. IN BSTR CimClassName,
  102. IN BSTR WdmInstanceName,
  103. OUT BSTR *PnPId,
  104. OUT BSTR /* FREE */ *CimRelPath
  105. )
  106. /*+++
  107. Routine Description:
  108. This routine will find the Cim class instance that corresponds to a
  109. particular Wdm class instance
  110. Arguments:
  111. pWdmServices is the pointer to the root\wmi namespace
  112. pCdmServices is the pointer to the root\cimv2 namespace
  113. CimClassName is the name of the cim class that the wdm instance
  114. would map to
  115. WdmInstanceName
  116. *PnPId returns with the PnP id for the device stack
  117. *CimRelPath returns with the relpath for the Cim instance
  118. Return Value:
  119. HRESULT
  120. ---*/
  121. {
  122. HRESULT hr;
  123. VARIANT v;
  124. IEnumWbemClassObject *pCimEnumInstances;
  125. IWbemClassObject *pCimInstance;
  126. ULONG Count;
  127. BSTR sWQL;
  128. WmipAssert(pWdmServices != NULL);
  129. WmipAssert(pCimServices != NULL);
  130. WmipAssert(CimClassName != NULL);
  131. WmipAssert(WdmInstanceName != NULL);
  132. WmipAssert(CimRelPath != NULL);
  133. sWQL = SysAllocString(L"WQL");
  134. if (sWQL != NULL)
  135. {
  136. // ****************************************************************
  137. // Note: Net cards need to do something similar. We get the
  138. // netcard address in class MSNDIS_???? and then get the CIM class
  139. // by matching the netcard addresses.
  140. // ****************************************************************
  141. //
  142. // First thing is to convert from an instance name to a pnpid
  143. //
  144. hr = WdmInstanceNameToPnPId(pWdmServices,
  145. WdmInstanceName,
  146. &v);
  147. if (hr == WBEM_S_NO_ERROR)
  148. {
  149. //
  150. // Next select * from CimClassName where PnPDeviceId = "<PnPDevice
  151. // Id from above>".
  152. //
  153. WCHAR Query[2 * MAX_PATH];
  154. WCHAR s[MAX_PATH];
  155. BSTR sQuery;
  156. wsprintfW(Query,
  157. L"select * from %ws where PnPDeviceId = \"%ws\"",
  158. CimClassName,
  159. AddSlashesToStringW(s, v.bstrVal));
  160. *PnPId = v.bstrVal;
  161. sQuery = SysAllocString(Query);
  162. if (sQuery != NULL)
  163. {
  164. hr = pCimServices->ExecQuery(sWQL,
  165. sQuery,
  166. WBEM_FLAG_FORWARD_ONLY |
  167. WBEM_FLAG_ENSURE_LOCATABLE,
  168. NULL,
  169. &pCimEnumInstances);
  170. SysFreeString(sQuery);
  171. if (hr == WBEM_S_NO_ERROR)
  172. {
  173. hr = pCimEnumInstances->Next(WBEM_INFINITE,
  174. 1,
  175. &pCimInstance,
  176. &Count);
  177. if ((hr == WBEM_S_NO_ERROR) &&
  178. (Count == 1))
  179. {
  180. //
  181. // Finally grab the relpath from cim class and we're done
  182. //
  183. hr = WmiGetProperty(pCimInstance,
  184. L"__RELPATH",
  185. CIM_STRING,
  186. &v);
  187. if (hr == WBEM_S_NO_ERROR)
  188. {
  189. *CimRelPath = SysAllocString(v.bstrVal);
  190. if (*CimRelPath == NULL)
  191. {
  192. hr = WBEM_E_OUT_OF_MEMORY;
  193. }
  194. VariantClear(&v);
  195. }
  196. pCimInstance->Release();
  197. }
  198. pCimEnumInstances->Release();
  199. } else {
  200. WmipDebugPrint(("CDMPROV: Query %ws failed %x\n",
  201. Query, hr));
  202. }
  203. } else {
  204. hr = WBEM_E_OUT_OF_MEMORY;
  205. }
  206. }
  207. SysFreeString(sWQL);
  208. } else {
  209. hr = WBEM_E_OUT_OF_MEMORY;
  210. }
  211. return(hr);
  212. }
  213. HRESULT GetEnumCount(
  214. IN IEnumWbemClassObject *pEnumInstances,
  215. OUT int *RelPathCount
  216. )
  217. /*+++
  218. Routine Description:
  219. This routine will return the count of instances in the enumeration
  220. Arguments:
  221. pEnumInstance is the instance enumerator
  222. *RelPathCount returns the number of instances in the enumeration
  223. Return Value:
  224. HRESULT
  225. ---*/
  226. {
  227. ULONG Count;
  228. HRESULT hr;
  229. IWbemClassObject *pInstance;
  230. WmipAssert(pEnumInstances != NULL);
  231. WmipAssert(RelPathCount != NULL);
  232. *RelPathCount = 0;
  233. do
  234. {
  235. hr = pEnumInstances->Next(WBEM_INFINITE,
  236. 1,
  237. &pInstance,
  238. &Count);
  239. if ((hr == WBEM_S_NO_ERROR) &&
  240. (Count == 1))
  241. {
  242. (*RelPathCount)++;
  243. pInstance->Release();
  244. } else {
  245. if (hr == WBEM_S_FALSE)
  246. {
  247. hr = WBEM_S_NO_ERROR;
  248. }
  249. break;
  250. }
  251. } while (TRUE);
  252. return(hr);
  253. }
  254. HRESULT MapWdmClassToCimClass(
  255. IN IWbemServices *pWdmServices,
  256. IN IWbemServices *pCimServices,
  257. IN BSTR WdmClassName,
  258. IN BSTR CimClassName,
  259. OUT BSTR /* FREE */ **PnPDeviceIds,
  260. OUT BSTR /* FREE */ **WdmInstanceNames,
  261. OUT BSTR /* FREE */ **WdmRelPaths,
  262. OUT BSTR /* FREE */ **CimRelPaths,
  263. OUT int *RelPathCount
  264. )
  265. /*+++
  266. Routine Description:
  267. This routine will perform a mapping between the instances of WDM
  268. classes and Cim Classes
  269. Arguments:
  270. pWdmServices
  271. pCdmServices
  272. WdmClassName
  273. CimClassName
  274. *PnPDeviceIds return with the an array of PnP device ids
  275. *WdmInstanceNames returns with an array of Wdm instnace names
  276. *WdmRelPaths returns with an array of relpaths to Wdm instances
  277. *CimRelpaths returns with an array of relapaths to Cim instance
  278. *RelPathCount returns with the count of instances that are mapped
  279. Return Value:
  280. HRESULT
  281. ---*/
  282. {
  283. IWbemClassObject *pWdmInstance;
  284. IEnumWbemClassObject *pWdmEnumInstances;
  285. HRESULT hr;
  286. int i, NumberWdmInstances;
  287. VARIANT v;
  288. ULONG Count;
  289. ULONG AllocSize;
  290. WmipAssert(pWdmServices != NULL);
  291. WmipAssert(pCimServices != NULL);
  292. WmipAssert(WdmClassName != NULL);
  293. WmipAssert(CimClassName != NULL);
  294. WmipAssert(PnPDeviceIds != NULL);
  295. WmipAssert(WdmInstanceNames != NULL);
  296. WmipAssert(CimRelPaths != NULL);
  297. WmipAssert(RelPathCount != NULL);
  298. WmipDebugPrint(("CDMPROV: Mapping Wdm %ws to CIM %ws\n",
  299. WdmClassName,
  300. CimClassName));
  301. *PnPDeviceIds = NULL;
  302. *WdmInstanceNames = NULL;
  303. *WdmRelPaths = NULL;
  304. *CimRelPaths = NULL;
  305. //
  306. // Get all instances of the Wdm Class
  307. //
  308. hr = pWdmServices->CreateInstanceEnum(WdmClassName,
  309. WBEM_FLAG_USE_AMENDED_QUALIFIERS |
  310. WBEM_FLAG_SHALLOW,
  311. NULL,
  312. &pWdmEnumInstances);
  313. if (hr == WBEM_S_NO_ERROR)
  314. {
  315. hr = GetEnumCount(pWdmEnumInstances,
  316. RelPathCount);
  317. NumberWdmInstances = *RelPathCount;
  318. if (hr == WBEM_S_NO_ERROR)
  319. {
  320. AllocSize = NumberWdmInstances * sizeof(BSTR *);
  321. *WdmRelPaths = (BSTR *)WmipAlloc(AllocSize);
  322. *CimRelPaths = (BSTR *)WmipAlloc(AllocSize);
  323. *WdmInstanceNames = (BSTR *)WmipAlloc(AllocSize);
  324. *PnPDeviceIds = (BSTR *)WmipAlloc(AllocSize);
  325. if ((*WdmRelPaths != NULL) &&
  326. (*CimRelPaths != NULL) &&
  327. (*WdmInstanceNames != NULL) &&
  328. (*PnPDeviceIds != NULL))
  329. {
  330. memset(*WdmRelPaths, 0, AllocSize);
  331. memset(*CimRelPaths, 0, AllocSize);
  332. memset(*WdmInstanceNames, 0, AllocSize);
  333. memset(*PnPDeviceIds, 0, AllocSize);
  334. pWdmEnumInstances->Reset();
  335. i = 0;
  336. do
  337. {
  338. hr = pWdmEnumInstances->Next(WBEM_INFINITE,
  339. 1,
  340. &pWdmInstance,
  341. &Count);
  342. if ((hr == WBEM_S_NO_ERROR) &&
  343. (Count == 1) &&
  344. (i < NumberWdmInstances))
  345. {
  346. //
  347. // Lets get the instance name and then lookup the pnp
  348. // id for it
  349. //
  350. hr = WmiGetProperty(pWdmInstance,
  351. L"InstanceName",
  352. CIM_STRING,
  353. &v);
  354. if (hr == WBEM_S_NO_ERROR)
  355. {
  356. //
  357. // Remember wdm instnace name
  358. //
  359. WmipDebugPrint(("CDMPROV: Wdm InstanceName is %ws\n",
  360. v.bstrVal));
  361. (*WdmInstanceNames)[i] = v.bstrVal;
  362. hr = FindCimClassByWdmInstanceName(pWdmServices,
  363. pCimServices,
  364. CimClassName,
  365. v.bstrVal,
  366. &((*PnPDeviceIds)[i]),
  367. &((*CimRelPaths)[i]));
  368. if (hr == WBEM_S_NO_ERROR)
  369. {
  370. //
  371. // Remember Wdm class relative path
  372. //
  373. WmipDebugPrint(("CDMPROV: Found CimRelPath %ws for Wdm class %ws\n",
  374. ((*CimRelPaths)[i]), WdmClassName));
  375. hr = WmiGetProperty(pWdmInstance,
  376. L"__RELPATH",
  377. CIM_STRING,
  378. &v);
  379. if (hr == WBEM_S_NO_ERROR)
  380. {
  381. (*WdmRelPaths)[i] = SysAllocString(v.bstrVal);
  382. if ((*WdmRelPaths)[i] == NULL)
  383. {
  384. hr = WBEM_E_OUT_OF_MEMORY;
  385. }
  386. VariantClear(&v);
  387. i++;
  388. }
  389. } else {
  390. //
  391. // We did not find a CIM class
  392. // to match our Wdm instance
  393. // names, so we decrement our
  394. // relpath count and continue
  395. // searching
  396. (*RelPathCount)--;
  397. if (*RelPathCount == 0)
  398. {
  399. hr = WBEM_E_NOT_FOUND;
  400. } else {
  401. hr = WBEM_S_NO_ERROR;
  402. }
  403. }
  404. }
  405. pWdmInstance->Release();
  406. } else {
  407. if (hr == WBEM_S_FALSE)
  408. {
  409. hr = WBEM_S_NO_ERROR;
  410. }
  411. break;
  412. }
  413. } while (hr == WBEM_S_NO_ERROR);
  414. } else {
  415. hr = WBEM_E_OUT_OF_MEMORY;
  416. }
  417. }
  418. pWdmEnumInstances->Release();
  419. }
  420. //
  421. // If mapping was unsuccessful then be sure to clean up any
  422. // allocated instance names and relpaths
  423. //
  424. if (hr != WBEM_S_NO_ERROR)
  425. {
  426. if (*PnPDeviceIds != NULL)
  427. {
  428. FreeTheBSTRArray(*WdmRelPaths,
  429. NumberWdmInstances);
  430. *WdmRelPaths = NULL;
  431. }
  432. if (*WdmRelPaths != NULL)
  433. {
  434. FreeTheBSTRArray(*WdmRelPaths,
  435. NumberWdmInstances);
  436. *WdmRelPaths = NULL;
  437. }
  438. if (*CimRelPaths != NULL)
  439. {
  440. FreeTheBSTRArray(*CimRelPaths,
  441. NumberWdmInstances);
  442. *CimRelPaths = NULL;
  443. }
  444. if (*WdmInstanceNames != NULL)
  445. {
  446. FreeTheBSTRArray(*WdmInstanceNames,
  447. NumberWdmInstances);
  448. *WdmInstanceNames = NULL;
  449. }
  450. }
  451. return(hr);
  452. }