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.

408 lines
12 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: P N P B I N D . C P P
  7. //
  8. // Contents: This module is responsible for sending BIND, UNBIND, UNLOAD
  9. // and RECONFIGURE PnP notifications to NDIS and TDI drivers.
  10. //
  11. // Notes:
  12. //
  13. // Author: shaunco 17 Feb 1999
  14. //
  15. //----------------------------------------------------------------------------
  16. #include "pch.h"
  17. #pragma hdrstop
  18. #include "nceh.h"
  19. #include "ncras.h"
  20. #include "ndispnp.h"
  21. #include "netcfg.h"
  22. UINT
  23. GetPnpLayerForBindPath (
  24. IN const CBindPath* pBindPath)
  25. {
  26. const CComponent* pComponent;
  27. UINT Layer;
  28. // Get the component below the component we would be sending the
  29. // BIND or UNBIND to.
  30. //
  31. Assert (pBindPath->CountComponents() > 1);
  32. pComponent = *(pBindPath->begin() + 1);
  33. if (FIsEnumerated(pComponent->Class()))
  34. {
  35. Layer = NDIS;
  36. }
  37. else
  38. {
  39. Layer = TDI;
  40. }
  41. Assert ((NDIS == Layer) || (TDI == Layer));
  42. return Layer;
  43. }
  44. HRESULT
  45. HrPnpBindOrUnbind (
  46. IN UINT Layer,
  47. IN UINT Operation,
  48. IN PCWSTR pszComponentBindName,
  49. IN PCWSTR pszBindString)
  50. {
  51. HRESULT hr;
  52. UNICODE_STRING LowerString;
  53. UNICODE_STRING UpperString;
  54. UNICODE_STRING BindList;
  55. Assert ((NDIS == Layer) || (TDI == Layer));
  56. Assert ((BIND == Operation) || (UNBIND == Operation));
  57. Assert (pszComponentBindName && *pszComponentBindName);
  58. Assert (pszBindString && *pszBindString);
  59. hr = S_OK;
  60. TraceTag (ttidNetCfgPnp, "PnP Event: %s %s %S - %S",
  61. (NDIS == Layer) ? "NDIS" : "TDI",
  62. (BIND == Operation) ? "BIND" : "UNBIND",
  63. pszComponentBindName,
  64. pszBindString);
  65. g_pDiagCtx->Printf (ttidBeDiag, " PnP Event: %s %s %S - %S\n",
  66. (NDIS == Layer) ? "NDIS" : "TDI",
  67. (BIND == Operation) ? "BIND" : "UNBIND",
  68. pszComponentBindName,
  69. pszBindString);
  70. RtlInitUnicodeString (&LowerString, pszBindString);
  71. RtlInitUnicodeString (&UpperString, pszComponentBindName);
  72. // Special case for NetBIOS until it can change its bind handler.
  73. // It blindly dereferences the bind list so we need to make sure it
  74. // gets down there with a valid (but empty) buffer. For some reason,
  75. // the buffer doesn't make it down to kernel mode unless .Length is
  76. // non-zero. .MaximumLength is the same as .Length in this case which
  77. // seems odd. (The old binding engine sent it this way.)
  78. //
  79. // RtlInitUnicodeString (&BindList, L""); (doesn't work because it
  80. // sets .Length to zero.)
  81. //
  82. BindList.Buffer = L"";
  83. BindList.Length = sizeof(WCHAR);
  84. BindList.MaximumLength = sizeof(WCHAR);
  85. NC_TRY
  86. {
  87. if (!(g_pDiagCtx->Flags() & DF_DONT_DO_PNP_BINDS) ||
  88. (BIND != Operation))
  89. {
  90. BOOL fOk;
  91. fOk = NdisHandlePnPEvent (
  92. Layer,
  93. Operation,
  94. &LowerString,
  95. &UpperString,
  96. &BindList,
  97. NULL, 0);
  98. if (!fOk)
  99. {
  100. DWORD dwError = GetLastError();
  101. // Map TDI's version of file not found to the right error.
  102. //
  103. if ((TDI == Layer) && (ERROR_GEN_FAILURE == dwError))
  104. {
  105. dwError = ERROR_FILE_NOT_FOUND;
  106. }
  107. // ERROR_FILE_NOT_FOUND for UNBIND means it it wasn't
  108. // bound to begin with. This is okay.
  109. //
  110. // ERROR_FILE_NOT_FOUND for BIND means one of the drivers
  111. // (above or below) wasn't started. This is okay too.
  112. //
  113. if (ERROR_FILE_NOT_FOUND == dwError)
  114. {
  115. Assert (S_OK == hr);
  116. }
  117. else
  118. {
  119. g_pDiagCtx->Printf (ttidBeDiag, " ^^^ Error = %d\n", dwError);
  120. hr = HRESULT_FROM_WIN32(dwError);
  121. }
  122. }
  123. }
  124. }
  125. NC_CATCH_ALL
  126. {
  127. hr = E_UNEXPECTED;
  128. }
  129. TraceHr (ttidError, FAL, hr, FALSE,
  130. "HrPnpBindOrUnbind: %s %s %S - %S\n",
  131. (NDIS == Layer) ? "NDIS" : "TDI",
  132. (BIND == Operation) ? "BIND" : "UNBIND",
  133. pszComponentBindName,
  134. pszBindString);
  135. return hr;
  136. }
  137. HRESULT
  138. HrPnpUnloadDriver (
  139. IN UINT Layer,
  140. IN PCWSTR pszComponentBindName)
  141. {
  142. HRESULT hr;
  143. UNICODE_STRING LowerString;
  144. UNICODE_STRING UpperString;
  145. UNICODE_STRING BindList;
  146. Assert ((NDIS == Layer) || (TDI == Layer));
  147. Assert (pszComponentBindName && *pszComponentBindName);
  148. hr = S_OK;
  149. TraceTag (ttidNetCfgPnp, "PnP Event: UNLOAD %S",
  150. pszComponentBindName);
  151. g_pDiagCtx->Printf (ttidBeDiag, " PnP Event: UNLOAD %S\n",
  152. pszComponentBindName);
  153. RtlInitUnicodeString (&LowerString, NULL);
  154. RtlInitUnicodeString (&UpperString, pszComponentBindName);
  155. RtlInitUnicodeString (&BindList, NULL);
  156. NC_TRY
  157. {
  158. BOOL fOk;
  159. fOk = NdisHandlePnPEvent (
  160. Layer,
  161. UNLOAD,
  162. &LowerString,
  163. &UpperString,
  164. &BindList,
  165. NULL, 0);
  166. if (!fOk)
  167. {
  168. DWORD dwError = GetLastError();
  169. // ERROR_GEN_FAILURE for UNLOAD means the driver does not
  170. // support UNLOAD. This is okay.
  171. //
  172. if (ERROR_GEN_FAILURE == dwError)
  173. {
  174. g_pDiagCtx->Printf (ttidBeDiag, " %S does not support UNLOAD. "
  175. "(Okay)\n",
  176. pszComponentBindName);
  177. Assert (S_OK == hr);
  178. }
  179. else
  180. {
  181. g_pDiagCtx->Printf (ttidBeDiag, " ^^^ Error = %d\n", dwError);
  182. hr = HRESULT_FROM_WIN32(dwError);
  183. }
  184. }
  185. }
  186. NC_CATCH_ALL
  187. {
  188. hr = E_UNEXPECTED;
  189. }
  190. // UNLOADs are informational, so we do not trace any errors.
  191. //
  192. //TraceHr (ttidError, FAL, hr, FALSE,
  193. // "HrPnpUnloadDriver: UNLOAD %S\n",
  194. // pszComponentBindName);
  195. return hr;
  196. }
  197. VOID
  198. CRegistryBindingsContext::PnpBindOrUnbindBindPaths (
  199. IN UINT Operation,
  200. IN const CBindingSet* pBindSet,
  201. OUT BOOL* pfRebootNeeded)
  202. {
  203. HRESULT hr;
  204. const CBindPath* pBindPath;
  205. CBindPath::const_iterator iter;
  206. const CComponent* pComponent;
  207. WCHAR szBind [_MAX_BIND_LENGTH];
  208. UINT Layer;
  209. Assert ((BIND == Operation) || (UNBIND == Operation));
  210. Assert (pBindSet);
  211. Assert (pfRebootNeeded);
  212. *pfRebootNeeded = FALSE;
  213. for (pBindPath = pBindSet->begin();
  214. pBindPath != pBindSet->end();
  215. pBindPath++)
  216. {
  217. Assert (pBindPath->CountComponents() > 1);
  218. // Special case for multiple interfaces. Unless this is the
  219. // length 2 bindpath of protocol to adapter (e.g. tcpip->ndiswanip),
  220. // check to see if the adapter on this bindpath expose multiple
  221. // interfaces from its protocol. If it does, we're going to skip
  222. // sending bind notifications.
  223. //
  224. // The reason we only do this for bindpaths of length greater than
  225. // two is because the protocol exposes multiple-interfaces but does
  226. // not deal with them in its direct binding (i.e. length 2) to the
  227. // adapter.
  228. //
  229. // Note: in future versions, we may not want to skip it. We do so
  230. // for now because the legacy binding engine skips them and these
  231. // bindings aren't active until RAS calls are made anyhow.
  232. //
  233. if (pBindPath->CountComponents() > 2)
  234. {
  235. const CComponent* pAdapter;
  236. DWORD cInterfaces;
  237. // Get the last component in the bindpath and the component
  238. // just above that. The last component is the adapter,
  239. // and the one above the adapter is the protocol.
  240. //
  241. iter = pBindPath->end();
  242. Assert (iter - 2 > pBindPath->begin());
  243. pComponent = *(iter - 2);
  244. pAdapter = *(iter - 1);
  245. Assert (pComponent);
  246. Assert (pAdapter);
  247. Assert (pAdapter == pBindPath->PLastComponent());
  248. // Calling HrGetInterfaceIdsForAdapter requires the INetCfgComponent
  249. // interface for the adapter. If we don't have it, it is likely
  250. // because the adapter has been removed in which case we don't
  251. // need to bother asking about how many interfaces it supports.
  252. //
  253. if (pComponent->m_pIComp && pAdapter->m_pIComp)
  254. {
  255. hr = pComponent->Notify.HrGetInterfaceIdsForAdapter (
  256. m_pNetConfig->Notify.PINetCfg(),
  257. pAdapter,
  258. &cInterfaces,
  259. NULL);
  260. // If multiple interfaces supported for the adapter,
  261. // continue to the next bindpath.
  262. //
  263. if (S_OK == hr)
  264. {
  265. continue;
  266. }
  267. // On S_FALSE or an error, continue below.
  268. hr = S_OK;
  269. }
  270. }
  271. wcscpy (szBind, L"\\Device\\");
  272. // Skip the first component in each path because it is the
  273. // component we are issuing the BIND/UNBIND for.
  274. //
  275. for (iter = pBindPath->begin() + 1;
  276. iter != pBindPath->end();
  277. iter++)
  278. {
  279. pComponent = *iter;
  280. Assert (pComponent);
  281. // Assert there is enough room in the bind buffer.
  282. //
  283. Assert (wcslen(szBind) + 1 + wcslen(pComponent->Ext.PszBindName())
  284. < celems(szBind));
  285. // If this isn't the first component to come after \Device\,
  286. // add underscores to seperate the components.
  287. //
  288. if (iter != (pBindPath->begin() + 1))
  289. {
  290. wcscat (szBind, L"_");
  291. }
  292. wcscat (szBind, pComponent->Ext.PszBindName());
  293. }
  294. Layer = GetPnpLayerForBindPath (pBindPath);
  295. hr = HrPnpBindOrUnbind (
  296. Layer,
  297. Operation,
  298. pBindPath->POwner()->Ext.PszBindName(),
  299. szBind);
  300. if (S_OK != hr)
  301. {
  302. *pfRebootNeeded = TRUE;
  303. }
  304. }
  305. }
  306. VOID
  307. PruneNdisWanBindPathsIfActiveRasConnections (
  308. IN CBindingSet* pBindSet,
  309. OUT BOOL* pfRebootNeeded)
  310. {
  311. CBindPath* pBindPath;
  312. UINT Layer;
  313. BOOL fExistActiveRasConnections;
  314. Assert (pBindSet);
  315. Assert (pfRebootNeeded);
  316. *pfRebootNeeded = FALSE;
  317. // Special case for binding/unbinding from ndiswan miniports while
  318. // active RAS connections exist. (Don't do it.) (BUG 344504)
  319. // (Binding will be to the NDIS layer, the bindpath will have two
  320. // components, and the service of the last component will be NdisWan.
  321. // (These are ndiswan miniport devices that behave badly if we
  322. // unbind them while active connections exist. Binding them also
  323. // can disconnect any connections they might be running.)
  324. // Order of the if is to do the inexpensive checks first.
  325. //
  326. if (!FExistActiveRasConnections ())
  327. {
  328. return;
  329. }
  330. pBindPath = pBindSet->begin();
  331. while (pBindPath != pBindSet->end())
  332. {
  333. Assert (pBindPath->CountComponents() > 1);
  334. Layer = GetPnpLayerForBindPath (pBindPath);
  335. if ((2 == pBindPath->CountComponents()) &&
  336. (NDIS == Layer) &&
  337. (0 == _wcsicmp (L"NdisWan", pBindPath->back()->Ext.PszService())))
  338. {
  339. g_pDiagCtx->Printf (ttidBeDiag, " Skipping PnP BIND/UNBIND for %S -> %S (active RAS connections)\n",
  340. pBindPath->POwner()->Ext.PszBindName(),
  341. pBindPath->back()->Ext.PszBindName());
  342. *pfRebootNeeded = TRUE;
  343. pBindSet->erase (pBindPath);
  344. }
  345. else
  346. {
  347. pBindPath++;
  348. }
  349. }
  350. }