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.

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