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.

503 lines
13 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: C O M P . C P P
  7. //
  8. // Contents: The module implements the operations that are valid on
  9. // network component datatypes.
  10. //
  11. // Notes:
  12. //
  13. // Author: shaunco 15 Jan 1999
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.h>
  17. #pragma hdrstop
  18. #include "comp.h"
  19. #include "icomp.h"
  20. #include "ncreg.h"
  21. #include "ncsetup.h"
  22. #include "ncstring.h"
  23. #include "util.h"
  24. // NULL entries means we don't use the network subtree for that class.
  25. //
  26. const PCWSTR MAP_NETCLASS_TO_NETWORK_SUBTREE[] =
  27. {
  28. L"System\\CurrentControlSet\\Control\\Network\\{4d36e972-e325-11ce-bfc1-08002be10318}",
  29. L"System\\CurrentControlSet\\Control\\Network\\{6BDD1FC5-810F-11D0-BEC7-08002BE2092F}",
  30. L"System\\CurrentControlSet\\Control\\Network\\{4d36e975-e325-11ce-bfc1-08002be10318}",
  31. L"System\\CurrentControlSet\\Control\\Network\\{4d36e973-e325-11ce-bfc1-08002be10318}",
  32. L"System\\CurrentControlSet\\Control\\Network\\{4d36e974-e325-11ce-bfc1-08002be10318}",
  33. NULL,
  34. NULL
  35. };
  36. // map of NETCLASS enum to GUIDs for class
  37. //
  38. const GUID* MAP_NETCLASS_TO_GUID[] =
  39. {
  40. &GUID_DEVCLASS_NET,
  41. &GUID_DEVCLASS_INFRARED,
  42. &GUID_DEVCLASS_NETTRANS,
  43. &GUID_DEVCLASS_NETCLIENT,
  44. &GUID_DEVCLASS_NETSERVICE,
  45. &GUID_DEVCLASS_UNKNOWN,
  46. &GUID_DEVCLASS_UNKNOWN
  47. };
  48. const WCHAR c_szTempNetcfgStorageForUninstalledEnumeratedComponent[] =
  49. L"System\\CurrentControlSet\\Control\\Network\\Uninstalled\\";
  50. //static
  51. HRESULT
  52. CComponent::HrCreateInstance (
  53. IN const BASIC_COMPONENT_DATA* pData,
  54. IN DWORD dwFlags,
  55. IN const OBO_TOKEN* pOboToken, OPTIONAL
  56. OUT CComponent** ppComponent)
  57. {
  58. ULONG cbInfId;
  59. ULONG cbPnpId;
  60. Assert (pData);
  61. Assert (pData->pszInfId && *pData->pszInfId);
  62. Assert (FIsValidNetClass(pData->Class));
  63. Assert (FImplies(FIsEnumerated(pData->Class),
  64. pData->pszPnpId && *pData->pszPnpId));
  65. Assert (FImplies(pData->pszPnpId, *pData->pszPnpId));
  66. Assert (FImplies(pData->dwDeipFlags, FIsEnumerated(pData->Class)));
  67. Assert ((CCI_DEFAULT == dwFlags) ||
  68. (CCI_ENSURE_EXTERNAL_DATA_LOADED == dwFlags));
  69. Assert (GUID_NULL != pData->InstanceGuid);
  70. cbInfId = CbOfSzAndTerm (pData->pszInfId);
  71. cbPnpId = CbOfSzAndTermSafe (pData->pszPnpId);
  72. HRESULT hr = E_OUTOFMEMORY;
  73. CComponent* pComponent = new(extrabytes, cbInfId + cbPnpId) CComponent;
  74. if (pComponent)
  75. {
  76. hr = S_OK;
  77. ZeroMemory (pComponent, sizeof(CComponent));
  78. pComponent->m_InstanceGuid = pData->InstanceGuid;
  79. pComponent->m_Class = pData->Class;
  80. pComponent->m_dwCharacter = pData->dwCharacter;
  81. pComponent->m_dwDeipFlags = pData->dwDeipFlags;
  82. pComponent->m_pszInfId = (PCWSTR)(pComponent + 1);
  83. wcscpy ((PWSTR)pComponent->m_pszInfId, pData->pszInfId);
  84. _wcslwr ((PWSTR)pComponent->m_pszInfId);
  85. AddOrRemoveDontExposeLowerCharacteristicIfNeeded (pComponent);
  86. if (cbPnpId)
  87. {
  88. pComponent->m_pszPnpId = (PCWSTR)((BYTE*)pComponent->m_pszInfId
  89. + cbInfId);
  90. wcscpy ((PWSTR)pComponent->m_pszPnpId, pData->pszPnpId);
  91. }
  92. if (dwFlags & CCI_ENSURE_EXTERNAL_DATA_LOADED)
  93. {
  94. // Let's ensure we can successfully read all of the external
  95. // data that the component's INF dumped under the instance
  96. // key. Failure here means the INF wasn't proper in some
  97. // way required for us to consider this a valid component.
  98. //
  99. hr = pComponent->Ext.HrEnsureExternalDataLoaded ();
  100. }
  101. if ((S_OK == hr) && pOboToken)
  102. {
  103. // Add a reference by the obo token if we were given one.
  104. //
  105. hr = pComponent->Refs.HrAddReferenceByOboToken (pOboToken);
  106. }
  107. if (S_OK != hr)
  108. {
  109. delete pComponent;
  110. pComponent = NULL;
  111. }
  112. }
  113. *ppComponent = pComponent;
  114. TraceHr (ttidError, FAL, hr, FALSE,
  115. "CComponent::HrCreateAndInitializeInstance");
  116. return hr;
  117. }
  118. CComponent::~CComponent()
  119. {
  120. // If we have a cached INetCfgComponent interface, we need to tell it
  121. // that we (as the component it represents) no longer exist. Then we
  122. // need to release the interface, of course.
  123. //
  124. ReleaseINetCfgComponentInterface ();
  125. if(m_hinf)
  126. {
  127. SetupCloseInfFile (m_hinf);
  128. }
  129. }
  130. VOID
  131. CComponent::ReleaseINetCfgComponentInterface ()
  132. {
  133. Assert (this);
  134. if (m_pIComp)
  135. {
  136. Assert (this == m_pIComp->m_pComponent);
  137. m_pIComp->m_pComponent = NULL;
  138. ReleaseObj (m_pIComp->GetUnknown());
  139. m_pIComp = NULL;
  140. }
  141. }
  142. INetCfgComponent*
  143. CComponent::GetINetCfgComponentInterface () const
  144. {
  145. Assert (this);
  146. Assert (m_pIComp);
  147. return m_pIComp;
  148. }
  149. BOOL
  150. CComponent::FCanDirectlyBindTo (
  151. IN const CComponent* pLower,
  152. OUT const WCHAR** ppStart,
  153. OUT ULONG* pcch) const
  154. {
  155. BOOL fCanBind;
  156. // If this component is a filter and the lower is an adapter,
  157. // they can bind (by definition) unless the adapter has an upper range
  158. // that is excluded by the filter.
  159. //
  160. if (FIsFilter() && FIsEnumerated(pLower->Class()))
  161. {
  162. fCanBind = TRUE;
  163. // If the filter has the FilterMediaTypes value specified,
  164. // then we can bind only if we have a match with the adapters
  165. // lower range.
  166. //
  167. if (Ext.PszFilterMediaTypes())
  168. {
  169. fCanBind = FSubstringMatch (Ext.PszFilterMediaTypes(),
  170. pLower->Ext.PszLowerRange(), NULL, NULL);
  171. }
  172. // If we (the filter) have a list of lower interface to exclude,
  173. // then we can bind only if we don't have a match.
  174. //
  175. if (fCanBind && Ext.PszLowerExclude())
  176. {
  177. fCanBind = !FSubstringMatch (Ext.PszLowerExclude(),
  178. pLower->Ext.PszUpperRange(), NULL, NULL);
  179. }
  180. // If the filter can bind to the adapter, and the caller wants
  181. // the interface name, it will be the first interface the adapter
  182. // supports.
  183. //
  184. if (fCanBind && ppStart && pcch)
  185. {
  186. PCWSTR pStart;
  187. PCWSTR pEnd;
  188. pStart = pLower->Ext.PszUpperRange();
  189. Assert (pStart);
  190. while (*pStart && (*pStart == L' ' || *pStart == L','))
  191. {
  192. pStart++;
  193. }
  194. pEnd = pStart;
  195. while (*pEnd && *pEnd != L' ' && *pEnd != L',')
  196. {
  197. pEnd++;
  198. }
  199. *ppStart = pStart;
  200. *pcch = pEnd - pStart;
  201. }
  202. }
  203. else
  204. {
  205. fCanBind = FSubstringMatch (
  206. Ext.PszLowerRange(),
  207. pLower->Ext.PszUpperRange(), ppStart, pcch);
  208. }
  209. return fCanBind;
  210. }
  211. BOOL
  212. CComponent::FIsBindable () const
  213. {
  214. return (0 != _wcsicmp(L"nolower", Ext.PszLowerRange())) ||
  215. (0 != _wcsicmp(L"noupper", Ext.PszUpperRange()));
  216. }
  217. BOOL
  218. CComponent::FIsWanAdapter () const
  219. {
  220. Assert (this);
  221. return (NC_NET == Class()) &&
  222. FSubstringMatch (Ext.PszLowerRange(), L"wan", NULL, NULL);
  223. }
  224. HRESULT
  225. CComponent::HrGetINetCfgComponentInterface (
  226. IN CImplINetCfg* pINetCfg,
  227. OUT INetCfgComponent** ppIComp)
  228. {
  229. HRESULT hr = S_OK;
  230. Assert (this);
  231. Assert (pINetCfg);
  232. Assert (ppIComp);
  233. // Caller's are responsible for ensuring that if an interface is about
  234. // to be handed out, and the external data has been loaded, that the
  235. // data has been loaded successfully. If we handed out an interface
  236. // and the data was NOT loaded successfully, it just means we are doomed
  237. // to fail later when the client of the interface calls a method that
  238. // requires that data.
  239. //
  240. Assert (Ext.FLoadedOkayIfLoadedAtAll());
  241. // If we don't yet have the cached INetCfgComponent for ourself,
  242. // create it and hang onto a reference.
  243. //
  244. if (!m_pIComp)
  245. {
  246. hr = CImplINetCfgComponent::HrCreateInstance (
  247. pINetCfg, this, &m_pIComp);
  248. }
  249. // AddRef and return a copy for the caller.
  250. //
  251. if (S_OK == hr)
  252. {
  253. AddRefObj (m_pIComp->GetUnknown());
  254. *ppIComp = m_pIComp;
  255. }
  256. TraceHr (ttidError, FAL, hr, FALSE,
  257. "CComponent::HrGetINetCfgComponentInterface");
  258. return hr;
  259. }
  260. HRESULT
  261. CComponent::HrOpenDeviceInfo (
  262. OUT HDEVINFO* phdiOut,
  263. OUT SP_DEVINFO_DATA* pdeidOut) const
  264. {
  265. HRESULT hr;
  266. Assert (this);
  267. Assert (phdiOut);
  268. Assert (pdeidOut);
  269. hr = ::HrOpenDeviceInfo (
  270. Class(),
  271. m_pszPnpId,
  272. phdiOut,
  273. pdeidOut);
  274. TraceHr (ttidError, FAL, hr, SPAPI_E_NO_SUCH_DEVINST == hr,
  275. "CComponent::HrOpenDeviceInfo (%S)", m_pszPnpId);
  276. return hr;
  277. }
  278. HRESULT
  279. CComponent::HrOpenInstanceKey (
  280. IN REGSAM samDesired,
  281. OUT HKEY* phkey,
  282. OUT HDEVINFO* phdiOut OPTIONAL,
  283. OUT SP_DEVINFO_DATA* pdeidOut OPTIONAL) const
  284. {
  285. HRESULT hr;
  286. Assert (this);
  287. Assert (phkey);
  288. hr = HrOpenComponentInstanceKey (
  289. Class(),
  290. m_InstanceGuid,
  291. m_pszPnpId,
  292. samDesired,
  293. phkey,
  294. phdiOut,
  295. pdeidOut);
  296. TraceHr (ttidError, FAL, hr,
  297. (SPAPI_E_NO_SUCH_DEVINST == hr),
  298. "CComponent::HrOpenInstanceKey (%S)", PszGetPnpIdOrInfId());
  299. return hr;
  300. }
  301. HRESULT
  302. CComponent::HrOpenServiceKey (
  303. IN REGSAM samDesired,
  304. OUT HKEY* phkey) const
  305. {
  306. HRESULT hr;
  307. WCHAR szServiceSubkey [_MAX_PATH];
  308. Assert (this);
  309. Assert (phkey);
  310. Assert (FHasService());
  311. *phkey = NULL;
  312. wcscpy (szServiceSubkey, REGSTR_PATH_SERVICES);
  313. wcscat (szServiceSubkey, L"\\");
  314. wcscat (szServiceSubkey, Ext.PszService());
  315. hr = HrRegOpenKeyEx (
  316. HKEY_LOCAL_MACHINE,
  317. szServiceSubkey,
  318. samDesired,
  319. phkey);
  320. TraceHr (ttidError, FAL, hr, FALSE,
  321. "CComponent::HrOpenServiceKey (%S)", Ext.PszService());
  322. return hr;
  323. }
  324. HRESULT
  325. CComponent::HrStartOrStopEnumeratedComponent (
  326. IN DWORD dwFlag /* DICS_START or DICS_STOP */) const
  327. {
  328. HRESULT hr;
  329. HDEVINFO hdi;
  330. SP_DEVINFO_DATA deid;
  331. Assert (this);
  332. Assert (FIsEnumerated(Class()));
  333. Assert ((DICS_START == dwFlag) || (DICS_STOP == dwFlag));
  334. hr = HrOpenDeviceInfo (&hdi, &deid);
  335. if (S_OK == hr)
  336. {
  337. if (m_dwDeipFlags)
  338. {
  339. TraceTag (ttidBeDiag,
  340. "Using SP_DEVINSTALL_PARAMS.Flags = 0x%08x for %S",
  341. m_dwDeipFlags,
  342. m_pszPnpId);
  343. (VOID) HrSetupDiSetDeipFlags (
  344. hdi, &deid,
  345. m_dwDeipFlags, SDDFT_FLAGS, SDFBO_OR);
  346. }
  347. // $HACK SetupDi does not honor the DI_DONOTCALLCONFIGMG flag
  348. // so we can't call it if it is set. If we don't start the device
  349. // we will return NETCFG_S_REBOOT.
  350. //
  351. hr = NETCFG_S_REBOOT;
  352. if (!(DI_DONOTCALLCONFIGMG & m_dwDeipFlags))
  353. {
  354. hr = HrSetupDiSendPropertyChangeNotification (
  355. hdi, &deid,
  356. dwFlag,
  357. DICS_FLAG_CONFIGSPECIFIC,
  358. 0);
  359. }
  360. SetupDiDestroyDeviceInfoList (hdi);
  361. }
  362. TraceHr (ttidError, FAL, hr, FALSE,
  363. "CComponent::HrStartOrStopEnumeratedComponent (%S)", m_pszPnpId);
  364. return hr;
  365. }
  366. //-----------------------------------------------------------------------
  367. // A convenience method to get the handle to the components inf file.
  368. // If the file has been opened previously, the cached handle is returned.
  369. // Otherwise, the file is opened and the handle is returned.
  370. HRESULT
  371. CComponent::HrOpenInfFile(
  372. OUT HINF* phinf) const
  373. {
  374. HRESULT hr = S_OK;
  375. HKEY hkeyInstance = NULL;
  376. WCHAR szInfPath[_MAX_PATH];
  377. DWORD cbPath = sizeof (szInfPath);
  378. Assert(phinf);
  379. *phinf = NULL;
  380. if (NULL == m_hinf)
  381. {
  382. hr = HrOpenInstanceKey (KEY_READ, &hkeyInstance, NULL, NULL);
  383. if (S_OK == hr)
  384. {
  385. hr = HrRegQuerySzBuffer (hkeyInstance, L"InfPath", szInfPath, &cbPath);
  386. if (S_OK == hr)
  387. {
  388. // open the component's inf file
  389. hr = HrSetupOpenInfFile (szInfPath, NULL, INF_STYLE_WIN4,
  390. NULL, &m_hinf);
  391. }
  392. RegSafeCloseKey (hkeyInstance);
  393. }
  394. }
  395. *phinf = m_hinf;
  396. TraceHr (ttidError, FAL, hr, FALSE,
  397. "CComponent::HrOpenInfFile (%S)", PszGetPnpIdOrInfId());
  398. return hr;
  399. }
  400. NETCLASS
  401. NetClassEnumFromGuid (
  402. const GUID& guidClass)
  403. {
  404. NETCLASS Class;
  405. if (GUID_DEVCLASS_NET == guidClass)
  406. {
  407. Class = NC_NET;
  408. }
  409. else if (GUID_DEVCLASS_INFRARED == guidClass)
  410. {
  411. Class = NC_INFRARED;
  412. }
  413. else if (GUID_DEVCLASS_NETTRANS == guidClass)
  414. {
  415. Class = NC_NETTRANS;
  416. }
  417. else if (GUID_DEVCLASS_NETCLIENT == guidClass)
  418. {
  419. Class = NC_NETCLIENT;
  420. }
  421. else if (GUID_DEVCLASS_NETSERVICE == guidClass)
  422. {
  423. Class = NC_NETSERVICE;
  424. }
  425. else
  426. {
  427. Class = NC_INVALID;
  428. }
  429. return Class;
  430. }