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.

594 lines
16 KiB

  1. // Copyright (c) 1997-1999 Microsoft Corporation
  2. // CWMIExtension.cpp : Implementation of the CWMIExtension class
  3. #include "precomp.h"
  4. extern ULONG g_ulObjCount;
  5. //#include "wmiextension_i.c"
  6. /////////////////////////////////////////////////////////////////////////////
  7. //
  8. /* Constructor */
  9. CWMIExtension::CWMIExtension()
  10. {
  11. HRESULT hr;
  12. ITypeLib *pITypeLib;
  13. m_cRef = 0;
  14. m_pUnkOuter = NULL;
  15. m_pDispOuter = NULL;
  16. m_pInner = NULL;
  17. m_pSWMILocator = NULL;
  18. m_bstrADsName = NULL;
  19. m_pSWMIServices = NULL;
  20. m_pSWMIObject = NULL;
  21. m_pTypeInfo = NULL;
  22. //Create inner object for controlling IUnknown implementation
  23. m_pInner = new CInner(this);
  24. if (m_pInner == NULL)
  25. return;
  26. hr = LoadRegTypeLib(LIBID_WMIEXTENSIONLib, 1,0,
  27. PRIMARYLANGID(GetSystemDefaultLCID()), &pITypeLib);
  28. if FAILED(hr)
  29. return;
  30. hr = pITypeLib->GetTypeInfoOfGuid(IID_IWMIExtension, &m_pTypeInfo);
  31. pITypeLib->Release();
  32. g_ulObjCount++; //global count for objects living in this DLL
  33. };
  34. CWMIExtension::~CWMIExtension()
  35. {
  36. if (m_pUnkOuter)
  37. m_pUnkOuter = NULL;
  38. if (m_pDispOuter)
  39. m_pDispOuter = NULL;
  40. if (m_pInner)
  41. {
  42. delete m_pInner;
  43. m_pInner = NULL;
  44. };
  45. if (m_bstrADsName)
  46. SysFreeString(m_bstrADsName);
  47. if (m_pSWMIObject)
  48. {
  49. m_pSWMIObject->Release();
  50. m_pSWMIObject = NULL;
  51. };
  52. if (m_pSWMIServices)
  53. {
  54. m_pSWMIServices->Release();
  55. m_pSWMIServices = NULL;
  56. };
  57. if (m_pSWMILocator)
  58. {
  59. m_pSWMILocator->Release();
  60. m_pSWMILocator = NULL;
  61. };
  62. if (m_pTypeInfo)
  63. {
  64. m_pTypeInfo->Release();
  65. m_pTypeInfo = NULL;
  66. };
  67. g_ulObjCount--; //global count for objects living in this DLL
  68. };
  69. HRESULT
  70. CWMIExtension::CreateExtension(IUnknown *pUnkOuter, void **ppv)
  71. {
  72. CWMIExtension FAR* pObj = NULL;
  73. HRESULT hr;
  74. IADs *pADs = NULL;
  75. BSTR bstrTempADSName = NULL;
  76. pObj = new CWMIExtension();
  77. if (pObj == NULL)
  78. return E_OUTOFMEMORY;
  79. //No addref needed for outer unknown
  80. pObj->m_pUnkOuter = pUnkOuter;
  81. /*
  82. //Due to the fact that ADSI instantiate us for every object, regardless of whether we're actually being used or not,
  83. //I am moving the code to obtain a locator pointer to the actual functions that need to use it...
  84. //Obtain a WMI Locator and store in member variable
  85. hr = CoCreateInstance(CLSID_SWbemLocator, NULL, CLSCTX_INPROC_SERVER,
  86. IID_ISWbemLocator, (void **)&pObj->m_pSWMILocator);
  87. if FAILED(hr)
  88. {
  89. delete pObj;
  90. return hr;
  91. }
  92. */
  93. /*
  94. //Due to a bug in the locator security object, we cannot set the security settings here,
  95. //but rather need to move this to the services pointer.
  96. //Setup the impersonation and authentication levels for this locator
  97. ISWbemSecurity *pSecurity = NULL;
  98. hr = pObj->m_pSWMILocator->get_Security_(&pSecurity);
  99. if FAILED(hr)
  100. {
  101. delete pObj;
  102. return hr;
  103. }
  104. hr = pSecurity->put_ImpersonationLevel(wbemImpersonationLevelImpersonate);
  105. hr = pSecurity->put_AuthenticationLevel(wbemAuthenticationLevelConnect);
  106. hr = pSecurity->Release();
  107. if FAILED(hr)
  108. {
  109. delete pObj;
  110. return hr;
  111. }
  112. */
  113. //Obtain the name of this object from ADSI and store in member :
  114. /* Moved to get_WMIObjectPath since here it doesn't work...
  115. //Get a pointer to the IADs interface of the outer object
  116. hr = pObj->m_pUnkOuter->QueryInterface(IID_IADs, (void **) &pADs );
  117. if FAILED(hr)
  118. return hr;
  119. //Get the name of the outer object
  120. // hr = pADs->get_Name(&bstrTempADSName);
  121. VARIANT var;
  122. VariantInit(&var);
  123. hr = pADs->Get(L"cn", &var);
  124. pObj->m_bstrADsName = SysAllocString(var.bstrVal);
  125. VariantClear(&var);
  126. pADs->Release();
  127. */
  128. //Since ADSI is adding a "CN=" prefix to the actual machine name, we need to remove it
  129. // pObj->m_bstrADsName = SysAllocString(wcschr(bstrTempADSName, L'=')+1);
  130. // pObj->m_bstrADsName = SysAllocString(bstrTempADSName);
  131. // SysFreeString(bstrTempADSName);
  132. // if FAILED(hr)
  133. // return hr;
  134. //Return the controlling unknown implementation pointer, and addref as required
  135. hr = pObj->m_pInner->QueryInterface(IID_IUnknown, ppv);
  136. return hr;
  137. };
  138. /* IUnknown Methods */
  139. STDMETHODIMP CWMIExtension::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  140. {
  141. return m_pUnkOuter->QueryInterface(riid, ppv);
  142. };
  143. STDMETHODIMP_(ULONG)
  144. CWMIExtension::AddRef(void)
  145. {
  146. ++m_cRef;
  147. return m_pUnkOuter->AddRef();
  148. };
  149. STDMETHODIMP_(ULONG)
  150. CWMIExtension::Release(void)
  151. {
  152. --m_cRef;
  153. return m_pUnkOuter->Release();
  154. }
  155. /* IDispatch methods */
  156. //IDispatch implementation delegates to the aggregator in this case
  157. STDMETHODIMP CWMIExtension::GetTypeInfoCount(unsigned int FAR* pctinfo)
  158. {
  159. IDispatch *pDisp;
  160. HRESULT hr;
  161. hr = m_pUnkOuter->QueryInterface(IID_IDispatch, (void **) &pDisp);
  162. if FAILED(hr)
  163. return hr;
  164. hr = pDisp->GetTypeInfoCount(pctinfo);
  165. pDisp->Release();
  166. return hr;
  167. }
  168. STDMETHODIMP CWMIExtension::GetTypeInfo(unsigned int itinfo, LCID lcid,
  169. ITypeInfo FAR* FAR* pptinfo)
  170. {
  171. IDispatch *pDisp;
  172. HRESULT hr;
  173. hr = m_pUnkOuter->QueryInterface(IID_IDispatch, (void **) &pDisp);
  174. if FAILED(hr)
  175. return hr;
  176. hr = pDisp->GetTypeInfo(itinfo, lcid, pptinfo);
  177. pDisp->Release();
  178. return hr;
  179. }
  180. STDMETHODIMP CWMIExtension::GetIDsOfNames(REFIID iid, LPWSTR FAR* rgszNames,
  181. unsigned int cNames, LCID lcid, DISPID FAR* rgdispid)
  182. {
  183. IDispatch *pDisp;
  184. HRESULT hr;
  185. hr = m_pUnkOuter->QueryInterface(IID_IDispatch, (void **) &pDisp);
  186. if FAILED(hr)
  187. return hr;
  188. hr = pDisp->GetIDsOfNames(iid, rgszNames, cNames, lcid, rgdispid);
  189. pDisp->Release();
  190. return hr;
  191. }
  192. STDMETHODIMP CWMIExtension::Invoke(DISPID dispidMember, REFIID iid, LCID lcid,
  193. unsigned short wFlags, DISPPARAMS FAR* pdispparams,
  194. VARIANT FAR* pvarResult, EXCEPINFO FAR* pexcepinfo,
  195. unsigned int FAR* puArgErr)
  196. {
  197. IDispatch *pDisp;
  198. HRESULT hr;
  199. hr = m_pUnkOuter->QueryInterface(IID_IDispatch, (void **) &pDisp);
  200. if FAILED(hr)
  201. return hr;
  202. hr = pDisp->Invoke(dispidMember,
  203. iid,
  204. lcid,
  205. wFlags,
  206. pdispparams,
  207. pvarResult,
  208. pexcepinfo,
  209. puArgErr
  210. );
  211. pDisp->Release();
  212. return hr;
  213. }
  214. /* IAdsExtension methods */
  215. STDMETHODIMP CWMIExtension::Operate(ULONG dwCode, VARIANT varData1,
  216. VARIANT varData2, VARIANT varData3)
  217. {
  218. HRESULT hr = S_OK;
  219. switch (dwCode)
  220. {
  221. case ADS_EXT_INITCREDENTIALS:
  222. // For debugging purpose you can prompt a dialog box
  223. // MessageBox(NULL, "INITCRED", "ADsExt", MB_OK);
  224. break;
  225. default:
  226. hr = E_FAIL;
  227. break;
  228. }
  229. return hr;
  230. }
  231. STDMETHODIMP CWMIExtension::PrivateGetIDsOfNames(REFIID riid, OLECHAR ** rgszNames,
  232. unsigned int cNames, LCID lcid, DISPID * rgdispid)
  233. {
  234. if (rgdispid == NULL)
  235. {
  236. return E_POINTER;
  237. }
  238. return DispGetIDsOfNames(m_pTypeInfo, rgszNames, cNames, rgdispid);
  239. }
  240. STDMETHODIMP CWMIExtension::PrivateInvoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags,
  241. DISPPARAMS * pdispparams, VARIANT * pvarResult,
  242. EXCEPINFO * pexcepinfo, UINT * puArgErr)
  243. {
  244. return DispInvoke( (IWMIExtension*)this,
  245. m_pTypeInfo,
  246. dispidMember,
  247. wFlags,
  248. pdispparams,
  249. pvarResult,
  250. pexcepinfo,
  251. puArgErr );
  252. }
  253. /* IWMIExtension methods */
  254. STDMETHODIMP CWMIExtension::get_WMIObjectPath(BSTR FAR *strWMIObjectPath)
  255. {
  256. WCHAR wcSWMIName[1024];
  257. HRESULT hr;
  258. //Validate parameter
  259. if (strWMIObjectPath == NULL)
  260. return wbemErrInvalidParameter; //scripting enum
  261. // Moved from CreateExtension() since it doesn't work there...
  262. if (!m_bstrADsName)
  263. {
  264. IADs *pADs = NULL;
  265. BSTR bstrTempADSName = NULL;
  266. hr = m_pUnkOuter->QueryInterface(IID_IADs, (void **) &pADs );
  267. if FAILED(hr)
  268. return hr;
  269. //Get the name of the outer object
  270. hr = pADs->get_Name(&bstrTempADSName);
  271. if FAILED(hr)
  272. {
  273. pADs->Release();
  274. return hr;
  275. }
  276. //Since ADSI is adding a "CN=" prefix to the actual machine name, we need to remove it
  277. m_bstrADsName = SysAllocString(wcschr(bstrTempADSName, L'=')+1);
  278. SysFreeString(bstrTempADSName);
  279. pADs->Release();
  280. }
  281. //Construct the path for matching (S)WMI object
  282. wcscpy(wcSWMIName, L"WINMGMTS:{impersonationLevel=impersonate}!//");
  283. wcscat(wcSWMIName, m_bstrADsName);
  284. wcscat(wcSWMIName, L"/root/cimv2:Win32_ComputerSystem.Name=\"");
  285. wcscat(wcSWMIName, m_bstrADsName);
  286. wcscat(wcSWMIName, L"\"");
  287. //Allocate out parameter and copy result to it
  288. *strWMIObjectPath = SysAllocString(wcSWMIName);
  289. return NOERROR;
  290. }; //get_WMIObjectPath
  291. STDMETHODIMP CWMIExtension::GetWMIObject(ISWbemObject FAR* FAR* objWMIObject)
  292. {
  293. HRESULT hr;
  294. BSTR bstrObjPath;
  295. //Validate parameter
  296. if (objWMIObject == NULL)
  297. return wbemErrInvalidParameter;
  298. // Moved from CreateExtension() since it doesn't work there...
  299. //Obtain the name of this object from ADSI and store in member, if not already there
  300. if (!m_bstrADsName)
  301. {
  302. IADs *pADs = NULL;
  303. BSTR bstrTempADSName = NULL;
  304. hr = m_pUnkOuter->QueryInterface(IID_IADs, (void **) &pADs );
  305. if FAILED(hr)
  306. return hr;
  307. //Get the name of the outer object
  308. hr = pADs->get_Name(&bstrTempADSName);
  309. if FAILED(hr)
  310. {
  311. pADs->Release();
  312. return hr;
  313. }
  314. //Since ADSI is adding a "CN=" prefix to the actual machine name, we need to remove it
  315. m_bstrADsName = SysAllocString(wcschr(bstrTempADSName, L'=')+1);
  316. SysFreeString(bstrTempADSName);
  317. pADs->Release();
  318. }
  319. //Obtain a WMI Locator and store in member variable, if not already there
  320. if (!m_pSWMILocator)
  321. {
  322. hr = CoCreateInstance(CLSID_SWbemLocator, NULL, CLSCTX_INPROC_SERVER,
  323. IID_ISWbemLocator, (void **)&m_pSWMILocator);
  324. if FAILED(hr)
  325. return hr;
  326. }
  327. //Get the respective SWMI services pointer if we don't have it already, and cache in member
  328. if (!m_pSWMIServices)
  329. {
  330. BSTR bstrNamespace = SysAllocString(L"root\\cimv2");
  331. hr = m_pSWMILocator->ConnectServer(m_bstrADsName, bstrNamespace, NULL, NULL, 0, NULL, 0, NULL, &m_pSWMIServices);
  332. SysFreeString(bstrNamespace);
  333. if FAILED(hr)
  334. return hr;
  335. //Setup the impersonation and authentication levels for this services pointer
  336. ISWbemSecurity *pSecurity = NULL;
  337. hr = m_pSWMIServices->get_Security_(&pSecurity);
  338. if FAILED(hr)
  339. return hr;
  340. hr = pSecurity->put_ImpersonationLevel(wbemImpersonationLevelImpersonate);
  341. hr = pSecurity->put_AuthenticationLevel(wbemAuthenticationLevelConnect);
  342. hr = pSecurity->Release();
  343. if FAILED(hr)
  344. return hr;
  345. };
  346. //Get the SWMI object using this services pointer, if we don't have it already, and cache in member
  347. if (!m_pSWMIObject)
  348. {
  349. WCHAR wcObjPath[256];
  350. //Construct the path of the object
  351. wcscpy(wcObjPath, L"Win32_ComputerSystem.Name=\"");
  352. wcscat(wcObjPath, m_bstrADsName);
  353. wcscat(wcObjPath, L"\"");
  354. bstrObjPath = SysAllocString(wcObjPath);
  355. hr = m_pSWMIServices->Get(bstrObjPath, 0, NULL, &m_pSWMIObject);
  356. SysFreeString(bstrObjPath);
  357. if FAILED(hr)
  358. return hr;
  359. };
  360. //AddRef the object pointer before we hand it out...
  361. m_pSWMIObject->AddRef();
  362. *objWMIObject = m_pSWMIObject;
  363. return NOERROR;
  364. }; //GetWMIObject
  365. STDMETHODIMP CWMIExtension::GetWMIServices(ISWbemServices FAR* FAR* objWMIServices)
  366. {
  367. HRESULT hr;
  368. //Validate parameter
  369. if (objWMIServices == NULL)
  370. return wbemErrInvalidParameter;
  371. // Moved from CreateExtension() since it doesn't work there...
  372. //Obtain the name of this object from ADSI and store in member, if not already there
  373. if (!m_bstrADsName)
  374. {
  375. IADs *pADs = NULL;
  376. BSTR bstrTempADSName = NULL;
  377. hr = m_pUnkOuter->QueryInterface(IID_IADs, (void **) &pADs );
  378. if FAILED(hr)
  379. return hr;
  380. //Get the name of the outer object
  381. hr = pADs->get_Name(&bstrTempADSName);
  382. if FAILED(hr)
  383. {
  384. pADs->Release();
  385. return hr;
  386. }
  387. //Since ADSI is adding a "CN=" prefix to the actual machine name, we need to remove it
  388. m_bstrADsName = SysAllocString(wcschr(bstrTempADSName, L'=')+1);
  389. SysFreeString(bstrTempADSName);
  390. pADs->Release();
  391. }
  392. //Obtain a WMI Locator and store in member variable, if not already there
  393. if (!m_pSWMILocator)
  394. {
  395. hr = CoCreateInstance(CLSID_SWbemLocator, NULL, CLSCTX_INPROC_SERVER,
  396. IID_ISWbemLocator, (void **)&m_pSWMILocator);
  397. if FAILED(hr)
  398. return hr;
  399. }
  400. //Get the respective SWMI services pointer if we don't have it already, and cache in member
  401. if (!m_pSWMIServices)
  402. {
  403. BSTR bstrNamespace = SysAllocString(L"root\\cimv2");
  404. hr = m_pSWMILocator->ConnectServer(m_bstrADsName, bstrNamespace, NULL, NULL, 0, NULL, 0, NULL, &m_pSWMIServices);
  405. SysFreeString(bstrNamespace);
  406. if FAILED(hr)
  407. return hr;
  408. //Setup the impersonation and authentication levels for this services pointer
  409. ISWbemSecurity *pSecurity = NULL;
  410. hr = m_pSWMIServices->get_Security_(&pSecurity);
  411. if FAILED(hr)
  412. return hr;
  413. hr = pSecurity->put_ImpersonationLevel(wbemImpersonationLevelImpersonate);
  414. hr = pSecurity->put_AuthenticationLevel(wbemAuthenticationLevelConnect);
  415. hr = pSecurity->Release();
  416. if FAILED(hr)
  417. return hr;
  418. };
  419. //AddRef the services pointer before we hand it out
  420. m_pSWMIServices->AddRef();
  421. *objWMIServices = m_pSWMIServices;
  422. return NOERROR;
  423. }; //GetWMIServices
  424. /* Implementation of CInner class which implements the controlling IUnknown for the object */
  425. //Constructor
  426. CInner::CInner(CWMIExtension *pOwner)
  427. {
  428. m_cRef = 0;
  429. m_pOwner = pOwner;
  430. };
  431. //Destructor
  432. CInner::~CInner()
  433. {
  434. };
  435. STDMETHODIMP CInner::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  436. {
  437. if (riid == IID_IUnknown)
  438. *ppv=(IUnknown *)this;
  439. else if (riid == IID_IDispatch)
  440. *ppv=(IDispatch *)m_pOwner;
  441. else if (riid == IID_IWMIExtension)
  442. *ppv=(IWMIExtension *)m_pOwner;
  443. else if (riid == IID_IADsExtension)
  444. *ppv=(IADsExtension *)m_pOwner;
  445. else
  446. {
  447. *ppv = NULL;
  448. return E_NOINTERFACE;
  449. }
  450. ((IUnknown *)*ppv)->AddRef();
  451. return NOERROR;
  452. };
  453. STDMETHODIMP_(ULONG)
  454. CInner::AddRef(void)
  455. {
  456. return ++m_cRef;
  457. };
  458. STDMETHODIMP_(ULONG)
  459. CInner::Release(void)
  460. {
  461. if (--m_cRef != 0)
  462. return m_cRef;
  463. delete m_pOwner;
  464. return 0;
  465. };
  466. // eof CWMIExtension.cpp