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.

1475 lines
43 KiB

  1. /*++
  2. Copyright (c) 2000-2000 Microsoft Corporation
  3. Module Name:
  4. PnP.c
  5. Abstract:
  6. This module contains the various PnP handlers
  7. Author:
  8. Mohammad Shabbir Alam (MAlam) 3-30-2000
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include <ipinfo.h> // for IPInterfaceInfo
  13. #include "ntddip.h" // Needed for IP_INTERFACE_INFO
  14. #include <tcpinfo.h> // for AO_OPTION_xxx, TCPSocketOption
  15. //******************* Pageable Routine Declarations ****************
  16. #ifdef ALLOC_PRAGMA
  17. #pragma alloc_text(PAGE, SetTdiHandlers)
  18. #endif
  19. //******************* Pageable Routine Declarations ****************
  20. HANDLE TdiClientHandle = NULL;
  21. //----------------------------------------------------------------------------
  22. BOOLEAN
  23. SrcIsUs(
  24. tIPADDRESS IpAddress
  25. )
  26. /*++
  27. Routine Description:
  28. This routine determines if the IP address passed in is a
  29. local address
  30. Arguments:
  31. IN IpAddress -- IpAddress to verify
  32. Return Value:
  33. TRUE if IpAddress is local, FALSE otherwise
  34. --*/
  35. {
  36. LIST_ENTRY *pEntry;
  37. LIST_ENTRY *pEntry2;
  38. PGMLockHandle OldIrq;
  39. tLOCAL_INTERFACE *pLocalInterface;
  40. tADDRESS_ON_INTERFACE *pLocalAddress;
  41. PgmLock (&PgmDynamicConfig, OldIrq);
  42. pEntry = &PgmDynamicConfig.LocalInterfacesList;
  43. while ((pEntry = pEntry->Flink) != &PgmDynamicConfig.LocalInterfacesList)
  44. {
  45. pLocalInterface = CONTAINING_RECORD (pEntry, tLOCAL_INTERFACE, Linkage);
  46. pEntry2 = &pLocalInterface->Addresses;
  47. while ((pEntry2 = pEntry2->Flink) != &pLocalInterface->Addresses)
  48. {
  49. pLocalAddress = CONTAINING_RECORD (pEntry2, tADDRESS_ON_INTERFACE, Linkage);
  50. if (pLocalAddress->IpAddress == IpAddress)
  51. {
  52. PgmUnlock (&PgmDynamicConfig, OldIrq);
  53. return (TRUE);
  54. }
  55. }
  56. }
  57. PgmUnlock (&PgmDynamicConfig, OldIrq);
  58. return (FALSE);
  59. }
  60. //----------------------------------------------------------------------------
  61. NTSTATUS
  62. GetIpInterfaceContextFromAddress(
  63. IN tIPADDRESS IpAddr,
  64. OUT ULONG *pIPInterfaceContext
  65. )
  66. /*++
  67. Routine Description:
  68. Given an IP address, this routine determines will return the
  69. Ip interface context that address is registered on
  70. Arguments:
  71. IN IpAddress -- IpAddress
  72. OUT IpInterfaceContext -- IpInterfaceContext for the IP address passed
  73. Return Value:
  74. STATUS_SUCCESS if IpAddress was matched to interface,
  75. STATUS_UNSUCCESSFUL otherwise
  76. The DynamicConfig lock is held on entry and exit from this routine
  77. --*/
  78. {
  79. LIST_ENTRY *pEntry;
  80. LIST_ENTRY *pEntry2;
  81. tLOCAL_INTERFACE *pLocalInterface;
  82. tADDRESS_ON_INTERFACE *pLocalAddress;
  83. ASSERT (IpAddr);
  84. pEntry = &PgmDynamicConfig.LocalInterfacesList;
  85. while ((pEntry = pEntry->Flink) != &PgmDynamicConfig.LocalInterfacesList)
  86. {
  87. pLocalInterface = CONTAINING_RECORD (pEntry, tLOCAL_INTERFACE, Linkage);
  88. pEntry2 = &pLocalInterface->Addresses;
  89. while ((pEntry2 = pEntry2->Flink) != &pLocalInterface->Addresses)
  90. {
  91. pLocalAddress = CONTAINING_RECORD (pEntry2, tADDRESS_ON_INTERFACE, Linkage);
  92. if (pLocalAddress->IpAddress == IpAddr)
  93. {
  94. *pIPInterfaceContext = pLocalInterface->IpInterfaceContext;
  95. return (STATUS_SUCCESS);
  96. }
  97. }
  98. }
  99. return (STATUS_UNSUCCESSFUL);
  100. }
  101. //----------------------------------------------------------------------------
  102. NTSTATUS
  103. GetIpInterfaceContextFromDeviceName(
  104. IN tIPADDRESS NetIpAddr,
  105. IN PUNICODE_STRING pucBindString,
  106. OUT ULONG *pIPInterfaceContext,
  107. IN ULONG BufferLength,
  108. OUT UCHAR *pBuffer,
  109. IN BOOLEAN fGetInterfaceInfo
  110. )
  111. /*++
  112. Routine Description:
  113. Given a Unicode device name string, this routine will query Ip
  114. and return the IpInterfaceContext for that device
  115. Arguments:
  116. IN NetIpAddr -- IpAddress on Device
  117. IN pucBindString -- Pointer to unicode device name string
  118. OUT IpInterfaceContext -- IpInterfaceContext for the device name
  119. IN BufferLength -- Length of Output buffer passed
  120. OUT pBuffer -- Output buffer passed for Interface properties
  121. IN fGetInterfaceInfo -- Whether to return Interface properties or not
  122. Return Value:
  123. STATUS_SUCCESS if IpInterfaceContext was found, and properties
  124. successfully queried, STATUS_UNSUCCESSFUL otherwise
  125. --*/
  126. {
  127. LONG i;
  128. NTSTATUS status;
  129. PVOID *pIPInfo;
  130. PIP_INTERFACE_INFO pIPIfInfo;
  131. UNICODE_STRING ucDeviceName;
  132. ULONG BufferLen = 2 * sizeof(IP_ADAPTER_INDEX_MAP); // assume
  133. status = PgmProcessIPRequest (IOCTL_IP_INTERFACE_INFO,
  134. NULL, // No Input buffer
  135. 0,
  136. &pIPIfInfo,
  137. &BufferLen);
  138. if (!NT_SUCCESS(status))
  139. {
  140. PgmLog (PGM_LOG_ERROR, DBG_PNP, "GetInterfaceContext",
  141. "PgmProcessIPRequest returned status=<%x> for IOCTL_IP_INTERFACE_INFO, pDevice=<%wZ>!\n",
  142. status, pucBindString);
  143. return (status);
  144. }
  145. status = STATUS_UNSUCCESSFUL;
  146. for (i=0; i < pIPIfInfo->NumAdapters; i++)
  147. {
  148. ucDeviceName.Buffer = pIPIfInfo->Adapter[i].Name;
  149. ucDeviceName.Length = sizeof (WCHAR) * wcslen (pIPIfInfo->Adapter[i].Name);
  150. ucDeviceName.MaximumLength = ucDeviceName.Length + sizeof (WCHAR);
  151. PgmLog (PGM_LOG_INFORM_PATH, DBG_PNP, "GetInterfaceContext",
  152. "[%d/%d]\t<%wZ>\n",
  153. i+1, pIPIfInfo->NumAdapters, &ucDeviceName);
  154. if (RtlCompareUnicodeString (&ucDeviceName, pucBindString, TRUE) == 0)
  155. {
  156. *pIPInterfaceContext = pIPIfInfo->Adapter[i].Index;
  157. status = STATUS_SUCCESS;
  158. break;
  159. }
  160. }
  161. PgmFreeMem (pIPIfInfo);
  162. if (!NT_SUCCESS (status))
  163. {
  164. PgmLog (PGM_LOG_ERROR, DBG_PNP, "GetInterfaceContext",
  165. "Could not find IPInterfaceContext for Device=<%wZ>\n", pucBindString);
  166. return (status);
  167. }
  168. status = PgmQueryTcpInfo (pgPgmDevice->hControl,
  169. IP_INTFC_INFO_ID,
  170. &NetIpAddr,
  171. sizeof (tIPADDRESS),
  172. pBuffer,
  173. BufferLength);
  174. if (!NT_SUCCESS (status))
  175. {
  176. PgmLog (PGM_LOG_ERROR, DBG_PNP, "GetInterfaceContext",
  177. "PgmQueryTcpInfo returned <%x>\n", status);
  178. return (status);
  179. }
  180. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "GetInterfaceContext",
  181. "IPInterfaceContext=<%x> for Device=<%wZ>\n",
  182. *pIPInterfaceContext, pucBindString);
  183. return (status);
  184. }
  185. //----------------------------------------------------------------------------
  186. ULONG
  187. StopListeningOnInterface(
  188. #ifdef IP_FIX
  189. IN ULONG IpInterfaceContext,
  190. #else
  191. IN tIPADDRESS IpAddress, // Host format
  192. #endif // IP_FIX
  193. IN PGMLockHandle *pOldIrqDynamicConfig
  194. )
  195. /*++
  196. Routine Description:
  197. Given an IPInterfaceContext, this routine traverses the list of
  198. all Receivers, and if any are determined to be listening on that
  199. interface, stops them from listening on all the addresses on this
  200. interface. In the case that the listener is part of an active
  201. session, the routine will also change the state of the Receiver
  202. to start listening on all interfaces
  203. Arguments:
  204. IN IpInterfaceContext -- IpInterfaceContext to stop listening on
  205. IN pOldIrqDynamicConfig-- OldIrq for DynamicConfig lock held
  206. The DynamicConfig lock is held on entry and exit from this routine
  207. Return Value:
  208. Number of receivers found listening on this interface
  209. --*/
  210. {
  211. NTSTATUS status;
  212. tRECEIVE_SESSION *pReceive;
  213. tADDRESS_CONTEXT *pAddress;
  214. LIST_ENTRY *pEntry;
  215. LIST_ENTRY *pEntry2;
  216. PGMLockHandle OldIrq1, OldIrq2;
  217. USHORT i;
  218. tMCAST_INFO MCastInfo;
  219. ULONG NumDisconnected = 0;
  220. tADDRESS_CONTEXT *pAddressToDeref = NULL;
  221. #ifdef IP_FIX
  222. MCastInfo.MCastInIf = IpInterfaceContext;
  223. #else
  224. MCastInfo.MCastInIf = htonl (IpAddress);
  225. #endif // IP_FIX
  226. pEntry = &PgmDynamicConfig.ReceiverAddressHead;
  227. while ((pEntry = pEntry->Flink) != &PgmDynamicConfig.ReceiverAddressHead)
  228. {
  229. pAddress = CONTAINING_RECORD (pEntry, tADDRESS_CONTEXT, Linkage);
  230. PgmLock (pAddress, OldIrq1);
  231. if (!(pAddress->Flags & PGM_ADDRESS_LISTEN_ON_ALL_INTERFACES))
  232. {
  233. //
  234. // If the app had specified interfaces to listen on,
  235. // then don't manage interfaces!
  236. //
  237. PgmUnlock (pAddress, OldIrq1);
  238. continue;
  239. }
  240. //
  241. // See if this address was listening on this interface
  242. //
  243. for (i=0; i<pAddress->NumReceiveInterfaces; i++)
  244. {
  245. #ifdef IP_FIX
  246. if (pAddress->ReceiverInterfaceList[i] == IpInterfaceContext)
  247. #else
  248. if (pAddress->ReceiverInterfaceList[i] == IpAddress)
  249. #endif // IP_FIX
  250. {
  251. break;
  252. }
  253. }
  254. if (i >= pAddress->NumReceiveInterfaces)
  255. {
  256. PgmUnlock (pAddress, OldIrq1);
  257. continue;
  258. }
  259. //
  260. // Remove this Interface from the list of listening interfaces
  261. //
  262. pAddress->NumReceiveInterfaces--;
  263. while (i < pAddress->NumReceiveInterfaces)
  264. {
  265. pAddress->ReceiverInterfaceList[i] = pAddress->ReceiverInterfaceList[i+1];
  266. i++;
  267. }
  268. PGM_REFERENCE_ADDRESS (pAddress, REF_ADDRESS_STOP_LISTENING, TRUE);
  269. //
  270. // If this were the only interface we were listening on
  271. // for an active session (or waiting for a session), ensure
  272. // that we go back into listening mode!
  273. //
  274. if ((pAddress->Flags & PGM_ADDRESS_LISTEN_ON_ALL_INTERFACES) &&
  275. (!pAddress->NumReceiveInterfaces))
  276. {
  277. pAddress->Flags |= PGM_ADDRESS_WAITING_FOR_NEW_INTERFACE;
  278. if (!IsListEmpty (&PgmDynamicConfig.LocalInterfacesList))
  279. {
  280. status = ListenOnAllInterfaces (pAddress, pOldIrqDynamicConfig, &OldIrq1);
  281. if (NT_SUCCESS (status))
  282. {
  283. PgmLog (PGM_LOG_INFORM_STATUS, DBG_ADDRESS, "StopListeningOnInterface",
  284. "ListenOnAllInterfaces for pAddress=<%x> succeeded\n", pAddress);
  285. }
  286. else
  287. {
  288. PgmLog (PGM_LOG_ERROR, DBG_ADDRESS, "StopListeningOnInterface",
  289. "ListenOnAllInterfaces for pAddress=<%x> returned <%x>\n",
  290. pAddress, status);
  291. }
  292. }
  293. }
  294. PgmUnlock (pAddress, OldIrq1);
  295. PgmUnlock (&PgmDynamicConfig, *pOldIrqDynamicConfig);
  296. if (pAddressToDeref)
  297. {
  298. PGM_DEREFERENCE_ADDRESS (pAddressToDeref, REF_ADDRESS_STOP_LISTENING);
  299. }
  300. pAddressToDeref = pAddress;
  301. //
  302. // So, stop listening on this interface
  303. //
  304. MCastInfo.MCastIpAddr = htonl (pAddress->ReceiverMCastAddr);
  305. #ifdef IP_FIX
  306. status = PgmSetTcpInfo (pAddress->FileHandle,
  307. AO_OPTION_INDEX_DEL_MCAST,
  308. &MCastInfo,
  309. sizeof (tMCAST_INFO));
  310. #else
  311. status = PgmSetTcpInfo (pAddress->FileHandle,
  312. AO_OPTION_DEL_MCAST,
  313. &MCastInfo,
  314. sizeof (tMCAST_INFO));
  315. #endif // IP_FIX
  316. if (NT_SUCCESS (status))
  317. {
  318. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "\tStopListeningOnInterface",
  319. "Stopped pAddress=<%x> from listening on Interface=<%x>\n",
  320. pAddress, MCastInfo.MCastInIf);
  321. }
  322. else
  323. {
  324. //
  325. // We failed to stop listening on this interface -- don't so anything!
  326. //
  327. PgmLog (PGM_LOG_ERROR, DBG_PNP, "\tStopListeningOnInterface",
  328. "AO_OPTION_INDEX_DEL_MCAST for If=<%x> on Address=<%x> returned <%x>\n",
  329. MCastInfo.MCastInIf, pAddress, status);
  330. }
  331. PgmLock (&PgmDynamicConfig, *pOldIrqDynamicConfig);
  332. }
  333. if (pAddressToDeref)
  334. {
  335. PGM_DEREFERENCE_ADDRESS (pAddressToDeref, REF_ADDRESS_STOP_LISTENING);
  336. }
  337. return (NumDisconnected);
  338. }
  339. //----------------------------------------------------------------------------
  340. VOID
  341. StopListeningOnAllInterfacesExcept(
  342. IN tADDRESS_CONTEXT *pAddress,
  343. IN PVOID Data1,
  344. IN PVOID Unused
  345. )
  346. /*++
  347. Routine Description:
  348. Given an Address Context and IPInterfaceContext (Data1), this routine
  349. stops the Address from listening on all the addresses except on this
  350. interface.
  351. Arguments:
  352. IN pAddress -- Address Context
  353. IN Data1 -- IpInterfaceContext to stop listening on
  354. Return Value:
  355. None
  356. --*/
  357. {
  358. NTSTATUS status;
  359. PGMLockHandle OldIrq;
  360. tMCAST_INFO MCastInfo;
  361. ULONG InterfacesToStop[MAX_RECEIVE_INTERFACES+1];
  362. USHORT NumInterfaces, i;
  363. ULONG InterfaceToKeep = PtrToUlong (Data1);
  364. #ifndef IP_FIX
  365. PGMLockHandle OldIrq0;
  366. LIST_ENTRY *pEntry;
  367. tLOCAL_INTERFACE *pLocalInterface;
  368. tADDRESS_ON_INTERFACE *pLocalAddress;
  369. USHORT j;
  370. #endif // !IP_FIX
  371. PgmLock (&PgmDynamicConfig, OldIrq0);
  372. PgmLock (pAddress, OldIrq);
  373. //
  374. // pAddress must be referenced before entering this routine
  375. //
  376. if (!(PGM_VERIFY_HANDLE (pAddress, PGM_VERIFY_ADDRESS)) ||
  377. (pAddress->Flags & PGM_ADDRESS_WAITING_FOR_NEW_INTERFACE))
  378. {
  379. //
  380. // Out state has changed -- deref and return immediately
  381. //
  382. PgmUnlock (pAddress, OldIrq);
  383. PgmUnlock (&PgmDynamicConfig, OldIrq0);
  384. PGM_DEREFERENCE_ADDRESS (pAddress, REF_ADDRESS_STOP_LISTENING);
  385. return;
  386. }
  387. #ifdef IP_FIX
  388. //
  389. // If this is the only interface we are listening on,
  390. // return success
  391. //
  392. if ((pAddress->NumReceiveInterfaces == 1) &&
  393. (pAddress->ReceiverInterfaceList[0] == InterfaceToKeep))
  394. {
  395. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "StopListeningOnAllInterfacesExcept",
  396. "pAddress=<%x> is only listening on 1 Interface=<%x>\n",
  397. pAddress, InterfaceToKeep);
  398. PgmUnlock (pAddress, OldIrq);
  399. return;
  400. }
  401. ASSERT (pAddress->NumReceiveInterfaces > 1);
  402. //
  403. // First, enumerate all interfaces to stop listening on
  404. //
  405. NumInterfaces = 0;
  406. for (i=0; i<pAddress->NumReceiveInterfaces; i++)
  407. {
  408. if (pAddress->ReceiverInterfaceList[i] != InterfaceToKeep)
  409. {
  410. InterfacesToStop[NumInterfaces++] = pAddress->ReceiverInterfaceList[i];
  411. }
  412. }
  413. pAddress->ReceiverInterfaceList[0] = InterfaceToKeep;
  414. pAddress->NumReceiveInterfaces = 1;
  415. //
  416. // Now, remove the remaining interfaces
  417. //
  418. #else
  419. //
  420. // First, make a copy of all addresses being listened on
  421. //
  422. NumInterfaces = 0;
  423. for (i=0; i<pAddress->NumReceiveInterfaces; i++)
  424. {
  425. InterfacesToStop[NumInterfaces++] = pAddress->ReceiverInterfaceList[i];
  426. }
  427. //
  428. // Zero out the current listening list on the address
  429. //
  430. pAddress->NumReceiveInterfaces = 0;
  431. //
  432. // Now, remove the addresses on this interface from this list
  433. //
  434. pEntry = &PgmDynamicConfig.LocalInterfacesList;
  435. while ((pEntry = pEntry->Flink) != &PgmDynamicConfig.LocalInterfacesList)
  436. {
  437. pLocalInterface = CONTAINING_RECORD (pEntry, tLOCAL_INTERFACE, Linkage);
  438. if (InterfaceToKeep == pLocalInterface->IpInterfaceContext)
  439. {
  440. //
  441. // Found the interface -- now save these addresses in the Address
  442. // list and remove from the stop list
  443. //
  444. pEntry = &pLocalInterface->Addresses;
  445. while ((pEntry = pEntry->Flink) != &pLocalInterface->Addresses)
  446. {
  447. pLocalAddress = CONTAINING_RECORD (pEntry, tADDRESS_ON_INTERFACE, Linkage);
  448. pAddress->ReceiverInterfaceList[pAddress->NumReceiveInterfaces++] = pLocalAddress->IpAddress;
  449. i = 0;
  450. while (i < NumInterfaces)
  451. {
  452. if (InterfacesToStop[i] == pLocalAddress->IpAddress)
  453. {
  454. j = i;
  455. NumInterfaces--;
  456. while (j < NumInterfaces)
  457. {
  458. InterfacesToStop[j] = InterfacesToStop[j+1];
  459. j++;
  460. }
  461. }
  462. else
  463. {
  464. i++;
  465. }
  466. }
  467. }
  468. break;
  469. }
  470. }
  471. #endif // IP_FIX
  472. PgmUnlock (pAddress, OldIrq);
  473. PgmUnlock (&PgmDynamicConfig, OldIrq0);
  474. MCastInfo.MCastIpAddr = htonl (pAddress->ReceiverMCastAddr);
  475. for (i=0; i<NumInterfaces; i++)
  476. {
  477. #ifdef IP_FIX
  478. MCastInfo.MCastInIf = InterfacesToStop[i];
  479. status = PgmSetTcpInfo (pAddress->FileHandle,
  480. AO_OPTION_INDEX_DEL_MCAST,
  481. &MCastInfo,
  482. sizeof (tMCAST_INFO));
  483. #else
  484. MCastInfo.MCastInIf = htonl (InterfacesToStop[i]);
  485. status = PgmSetTcpInfo (pAddress->FileHandle,
  486. AO_OPTION_DEL_MCAST,
  487. &MCastInfo,
  488. sizeof (tMCAST_INFO));
  489. #endif // IP_FIX
  490. if (NT_SUCCESS (status))
  491. {
  492. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "\tStopListeningOnAllInterfacesExcept",
  493. "Stopped pAddress=<%x> from listening on Interface=<%x>\n",
  494. pAddress, MCastInfo.MCastInIf);
  495. }
  496. else
  497. {
  498. //
  499. // We failed to stop this interface -- don't so anything!
  500. //
  501. PgmLog (PGM_LOG_ERROR, DBG_PNP, "\tStopListeningOnAllInterfacesExcept",
  502. "AO_OPTION_INDEX_DEL_MCAST for If=<%x> on Address=<%x> returned <%x>\n",
  503. MCastInfo.MCastInIf, pAddress, status);
  504. }
  505. }
  506. PGM_DEREFERENCE_ADDRESS (pAddress, REF_ADDRESS_STOP_LISTENING);
  507. return;
  508. }
  509. //----------------------------------------------------------------------------
  510. NTSTATUS
  511. ListenOnAllInterfaces(
  512. IN tADDRESS_CONTEXT *pAddress,
  513. IN PGMLockHandle *pOldIrqDynamicConfig,
  514. IN PGMLockHandle *pOldIrqAddress
  515. )
  516. /*++
  517. Routine Description:
  518. Given an Address Context, this routine enables the Address to
  519. start listening on all interfaces
  520. Arguments:
  521. IN pAddress -- Address Context
  522. IN pOldIrqDynamicConfig-- OldIrq for DynamicConfig lock held
  523. IN pOldIrqAddress -- OldIrq for Address lock held
  524. The DynamicConfig and Address locks are held on entry and exit
  525. from this routine
  526. Return Value:
  527. STATUS_SUCCESS
  528. --*/
  529. {
  530. NTSTATUS status;
  531. LIST_ENTRY *pEntry;
  532. tLOCAL_INTERFACE *pLocalInterface;
  533. tMCAST_INFO MCastInfo;
  534. ULONG InterfacesToAdd[MAX_RECEIVE_INTERFACES+1];
  535. USHORT NumInterfaces, i, j;
  536. #ifndef IP_FIX
  537. LIST_ENTRY *pEntry2;
  538. tADDRESS_ON_INTERFACE *pLocalAddress;
  539. #endif // !IP_FIX
  540. //
  541. // First, get the list of all active interfaces
  542. //
  543. NumInterfaces = 0;
  544. pEntry = &PgmDynamicConfig.LocalInterfacesList;
  545. while ((pEntry = pEntry->Flink) != &PgmDynamicConfig.LocalInterfacesList)
  546. {
  547. pLocalInterface = CONTAINING_RECORD (pEntry, tLOCAL_INTERFACE, Linkage);
  548. #ifdef IP_FIX
  549. InterfacesToAdd[NumInterfaces++] = pLocalInterface->IpInterfaceContext;
  550. #else
  551. pEntry2 = &pLocalInterface->Addresses;
  552. while ((pEntry2 = pEntry2->Flink) != &pLocalInterface->Addresses)
  553. {
  554. pLocalAddress = CONTAINING_RECORD (pEntry2, tADDRESS_ON_INTERFACE, Linkage);
  555. InterfacesToAdd[NumInterfaces++] = pLocalAddress->IpAddress;
  556. if (NumInterfaces >= MAX_RECEIVE_INTERFACES)
  557. {
  558. break;
  559. }
  560. }
  561. #endif // IP_FIX
  562. if (NumInterfaces >= MAX_RECEIVE_INTERFACES)
  563. {
  564. break;
  565. }
  566. }
  567. //
  568. // Remove all the interfaces we are already listening
  569. // on from the list of interfaces to be added
  570. //
  571. for (i=0; i<pAddress->NumReceiveInterfaces; i++)
  572. {
  573. for (j = 0; j < NumInterfaces; j++)
  574. {
  575. if (pAddress->ReceiverInterfaceList[i] == InterfacesToAdd[j])
  576. {
  577. NumInterfaces--;
  578. while (j < NumInterfaces)
  579. {
  580. InterfacesToAdd[j] = InterfacesToAdd[j+1];
  581. j++;
  582. }
  583. break;
  584. }
  585. }
  586. }
  587. if (!NumInterfaces)
  588. {
  589. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "ListenOnAllInterfaces",
  590. "No new interfaces to listen on for pAddress=<%x>, currently listening on <%x> Ifs\n",
  591. pAddress, pAddress->NumReceiveInterfaces);
  592. return (STATUS_SUCCESS);
  593. }
  594. //
  595. // Ensure that the complete list will not
  596. // exceed the maximum limit
  597. //
  598. if ((pAddress->NumReceiveInterfaces + NumInterfaces) > MAX_RECEIVE_INTERFACES)
  599. {
  600. NumInterfaces = MAX_RECEIVE_INTERFACES - pAddress->NumReceiveInterfaces;
  601. }
  602. //
  603. // Now, add the remaining interfaces
  604. //
  605. PgmUnlock (pAddress, *pOldIrqAddress);
  606. PgmUnlock (&PgmDynamicConfig, *pOldIrqDynamicConfig);
  607. MCastInfo.MCastIpAddr = htonl (pAddress->ReceiverMCastAddr);
  608. i = 0;
  609. while (i < NumInterfaces)
  610. {
  611. #ifdef IP_FIX
  612. MCastInfo.MCastInIf = InterfacesToAdd[i];
  613. status = PgmSetTcpInfo (pAddress->FileHandle,
  614. AO_OPTION_INDEX_ADD_MCAST,
  615. &MCastInfo,
  616. sizeof (tMCAST_INFO));
  617. #else
  618. MCastInfo.MCastInIf = htonl (InterfacesToAdd[i]);
  619. status = PgmSetTcpInfo (pAddress->FileHandle,
  620. AO_OPTION_ADD_MCAST,
  621. &MCastInfo,
  622. sizeof (tMCAST_INFO));
  623. #endif // IP_FIX
  624. if (NT_SUCCESS (status))
  625. {
  626. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "\tListenOnAllInterfaces",
  627. "pAddress=<%x> now also listening on If=<%x>\n",
  628. pAddress, MCastInfo.MCastInIf);
  629. i++;
  630. continue;
  631. }
  632. //
  633. // We failed to add this interface, so remove it from
  634. // the list
  635. //
  636. PgmLog (PGM_LOG_ERROR, DBG_PNP, "\tListenOnAllInterfaces",
  637. "pAddress=<%x> could not listen on If=<%x>\n",
  638. pAddress, MCastInfo.MCastInIf);
  639. j = i;
  640. NumInterfaces--;
  641. while (j < NumInterfaces)
  642. {
  643. InterfacesToAdd[j] = InterfacesToAdd[j+1];
  644. j++;
  645. }
  646. }
  647. PgmLock (&PgmDynamicConfig, *pOldIrqDynamicConfig);
  648. PgmLock (pAddress, *pOldIrqAddress);
  649. //
  650. // Now, append the new list to the Address context
  651. //
  652. for (i=0; i<NumInterfaces; i++)
  653. {
  654. if (pAddress->NumReceiveInterfaces > MAX_RECEIVE_INTERFACES)
  655. {
  656. ASSERT (0);
  657. break;
  658. }
  659. pAddress->ReceiverInterfaceList[pAddress->NumReceiveInterfaces] = InterfacesToAdd[i];
  660. pAddress->NumReceiveInterfaces++;
  661. }
  662. return (STATUS_SUCCESS);
  663. }
  664. //----------------------------------------------------------------------------
  665. VOID
  666. TdiAddressArrival(
  667. PTA_ADDRESS Addr,
  668. PUNICODE_STRING pDeviceName,
  669. PTDI_PNP_CONTEXT Context
  670. )
  671. /*++
  672. Routine Description:
  673. PnP TDI_ADD_ADDRESS_HANDLER
  674. This routine handles an IP address arriving.
  675. It is called by TDI when an address arrives.
  676. Arguments:
  677. IN Addr -- IP address that's coming.
  678. IN pDeviceName -- Unicode string Ptr for Device whose address is changing
  679. IN Context -- Tdi PnP context
  680. Return Value:
  681. Nothing!
  682. --*/
  683. {
  684. tIPADDRESS IpAddr, NetIpAddr;
  685. LIST_ENTRY *pEntry;
  686. PGMLockHandle OldIrq, OldIrq1;
  687. tLOCAL_INTERFACE *pLocalInterface = NULL;
  688. tADDRESS_ON_INTERFACE *pLocalAddress = NULL;
  689. ULONG BufferLength = 50;
  690. UCHAR pBuffer[50];
  691. IPInterfaceInfo *pIpIfInfo = (IPInterfaceInfo *) pBuffer;
  692. NTSTATUS status;
  693. tADDRESS_CONTEXT *pAddress;
  694. tADDRESS_CONTEXT *pAddressToDeref = NULL;
  695. ULONG IpInterfaceContext;
  696. BOOLEAN fFound;
  697. //
  698. // Proceed only if this is an IP address
  699. //
  700. if (Addr->AddressType != TDI_ADDRESS_TYPE_IP)
  701. {
  702. return;
  703. }
  704. //
  705. // First, verify that we are not getting unloaded
  706. //
  707. PgmLock (&PgmDynamicConfig, OldIrq);
  708. if (!PGM_VERIFY_HANDLE (pgPgmDevice, PGM_VERIFY_DEVICE))
  709. {
  710. //
  711. // The driver is most probably being unloaded now
  712. //
  713. PgmUnlock (&PgmDynamicConfig, OldIrq);
  714. return;
  715. }
  716. PGM_REFERENCE_DEVICE (pgPgmDevice, REF_DEV_ADDRESS_NOTIFICATION, FALSE);
  717. PgmUnlock (&PgmDynamicConfig, OldIrq);
  718. NetIpAddr = ((PTDI_ADDRESS_IP)&Addr->Address[0])->in_addr;
  719. IpAddr = ntohl (NetIpAddr);
  720. //
  721. // Now, get the interface context and other info from TcpIp
  722. //
  723. status = GetIpInterfaceContextFromDeviceName (NetIpAddr,
  724. pDeviceName,
  725. &IpInterfaceContext,
  726. BufferLength,
  727. pBuffer,
  728. TRUE);
  729. if (!NT_SUCCESS (status))
  730. {
  731. PgmLog (PGM_LOG_ERROR, DBG_PNP, "TdiAddressArrival",
  732. "GetIpInterfaceContext returned <%x>\n", status);
  733. PGM_DEREFERENCE_DEVICE (&pgPgmDevice, REF_DEV_ADDRESS_NOTIFICATION);
  734. return;
  735. }
  736. PgmLock (&PgmDynamicConfig, OldIrq);
  737. fFound = FALSE;
  738. pEntry = &PgmDynamicConfig.LocalInterfacesList;
  739. while ((pEntry = pEntry->Flink) != &PgmDynamicConfig.LocalInterfacesList)
  740. {
  741. pLocalInterface = CONTAINING_RECORD (pEntry, tLOCAL_INTERFACE, Linkage);
  742. if (pLocalInterface->IpInterfaceContext == IpInterfaceContext)
  743. {
  744. fFound = TRUE;
  745. break;
  746. }
  747. }
  748. if (fFound)
  749. {
  750. fFound = FALSE;
  751. pEntry = &pLocalInterface->Addresses;
  752. while ((pEntry = pEntry->Flink) != &pLocalInterface->Addresses)
  753. {
  754. pLocalAddress = CONTAINING_RECORD (pEntry, tADDRESS_ON_INTERFACE, Linkage);
  755. if (pLocalAddress->IpAddress == IpAddr)
  756. {
  757. PgmUnlock (&PgmDynamicConfig, OldIrq);
  758. PGM_DEREFERENCE_DEVICE (&pgPgmDevice, REF_DEV_ADDRESS_NOTIFICATION);
  759. PgmLog (PGM_LOG_ERROR, DBG_PNP, "TdiAddressArrival",
  760. "\tDUPLICATE address notification for [%d.%d.%d.%d] on <%wZ>\n",
  761. (IpAddr>>24)&0xFF,(IpAddr>>16)&0xFF,(IpAddr>>8)&0xFF,IpAddr&0xFF,
  762. pDeviceName);
  763. return;
  764. }
  765. }
  766. }
  767. else if (pLocalInterface = PgmAllocMem (sizeof(tLOCAL_INTERFACE), PGM_TAG('0')))
  768. {
  769. PgmZeroMemory (pLocalInterface, sizeof (tLOCAL_INTERFACE));
  770. InitializeListHead (&pLocalInterface->Addresses);
  771. pLocalInterface->IpInterfaceContext = IpInterfaceContext;
  772. pLocalInterface->MTU = pIpIfInfo->iii_mtu - (sizeof(IPV4Header) + ROUTER_ALERT_SIZE);
  773. pLocalInterface->Flags = pIpIfInfo->iii_flags;
  774. BufferLength = pIpIfInfo->iii_addrlength < sizeof(tMAC_ADDRESS) ?
  775. pIpIfInfo->iii_addrlength : sizeof(tMAC_ADDRESS);
  776. PgmCopyMemory (&pLocalInterface->MacAddress, pIpIfInfo->iii_addr, BufferLength);
  777. if (pLocalInterface->MTU > PgmDynamicConfig.MaxMTU)
  778. {
  779. PgmDynamicConfig.MaxMTU = pLocalInterface->MTU;
  780. }
  781. InsertTailList (&PgmDynamicConfig.LocalInterfacesList, &pLocalInterface->Linkage);
  782. }
  783. else
  784. {
  785. PgmUnlock (&PgmDynamicConfig, OldIrq);
  786. PgmLog (PGM_LOG_ERROR, DBG_PNP, "TdiAddressArrival",
  787. "STATUS_INSUFFICIENT_RESOURCES[Interface] for IP=<%x>, IfContext=<%x>\n",
  788. IpAddr, IpInterfaceContext);
  789. PGM_DEREFERENCE_DEVICE (&pgPgmDevice, REF_DEV_ADDRESS_NOTIFICATION);
  790. return;
  791. }
  792. //
  793. // Now, add this address to the interface
  794. //
  795. if (pLocalAddress = PgmAllocMem (sizeof(tADDRESS_ON_INTERFACE), PGM_TAG('0')))
  796. {
  797. PgmZeroMemory (pLocalAddress, sizeof (tADDRESS_ON_INTERFACE));
  798. pLocalAddress->IpAddress = IpAddr;
  799. InsertTailList (&pLocalInterface->Addresses, &pLocalAddress->Linkage);
  800. }
  801. else
  802. {
  803. //
  804. // If we had just added the interface, there is no point
  805. // in keeping an empty context around!
  806. //
  807. if (IsListEmpty (&pLocalInterface->Addresses))
  808. {
  809. RemoveEntryList (&pLocalInterface->Linkage);
  810. PgmFreeMem (pLocalInterface);
  811. }
  812. PgmUnlock (&PgmDynamicConfig, OldIrq);
  813. PgmLog (PGM_LOG_ERROR, DBG_PNP, "TdiAddressArrival",
  814. "STATUS_INSUFFICIENT_RESOURCES[Address] -- [%d.%d.%d.%d] on <%wZ>\n",
  815. (IpAddr>>24)&0xFF,(IpAddr>>16)&0xFF,(IpAddr>>8)&0xFF,IpAddr&0xFF,
  816. pDeviceName);
  817. PGM_DEREFERENCE_DEVICE (&pgPgmDevice, REF_DEV_ADDRESS_NOTIFICATION);
  818. return;
  819. }
  820. //
  821. // Now, check if we have any receivers waiting for an address
  822. //
  823. pEntry = &PgmDynamicConfig.ReceiverAddressHead;
  824. while ((pEntry = pEntry->Flink) != &PgmDynamicConfig.ReceiverAddressHead)
  825. {
  826. pAddress = CONTAINING_RECORD (pEntry, tADDRESS_CONTEXT, Linkage);
  827. PgmLock (pAddress, OldIrq1);
  828. if ((PGM_VERIFY_HANDLE (pAddress, PGM_VERIFY_ADDRESS)) &&
  829. (pAddress->Flags & PGM_ADDRESS_WAITING_FOR_NEW_INTERFACE) &&
  830. (pAddress->Flags & PGM_ADDRESS_LISTEN_ON_ALL_INTERFACES))
  831. {
  832. PGM_REFERENCE_ADDRESS (pAddress, REF_ADDRESS_SET_INFO, TRUE);
  833. if (pAddressToDeref)
  834. {
  835. PgmUnlock (pAddress, OldIrq1);
  836. PgmUnlock (&PgmDynamicConfig, OldIrq);
  837. PGM_DEREFERENCE_ADDRESS (pAddressToDeref, REF_ADDRESS_SET_INFO);
  838. PgmLock (&PgmDynamicConfig, OldIrq);
  839. PgmLock (pAddress, OldIrq1);
  840. }
  841. pAddressToDeref = pAddress;
  842. status = ReceiverAddMCastIf (pAddress, IpAddr, &OldIrq, &OldIrq1);
  843. if (NT_SUCCESS (status))
  844. {
  845. PgmLog (PGM_LOG_INFORM_STATUS, DBG_ADDRESS, "TdiAddressArrival",
  846. "ReceiverAddMCastIf for pAddress=<%x> succeeded for IP=<%x>\n",
  847. pAddress, IpAddr);
  848. }
  849. else
  850. {
  851. PgmLog (PGM_LOG_ERROR, DBG_ADDRESS, "TdiAddressArrival",
  852. "ReceiverAddMCastIf for pAddress=<%x> returned <%x>, IP=<%x>\n",
  853. pAddress, status, IpAddr);
  854. }
  855. }
  856. PgmUnlock (pAddress, OldIrq1);
  857. }
  858. PgmUnlock (&PgmDynamicConfig, OldIrq);
  859. if (pAddressToDeref)
  860. {
  861. PGM_DEREFERENCE_ADDRESS (pAddressToDeref, REF_ADDRESS_SET_INFO);
  862. }
  863. PGM_DEREFERENCE_DEVICE (&pgPgmDevice, REF_DEV_ADDRESS_NOTIFICATION);
  864. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "TdiAddressArrival",
  865. "\t[%d.%d.%d.%d] on <%wZ>\n",
  866. (IpAddr>>24)&0xFF,(IpAddr>>16)&0xFF,(IpAddr>>8)&0xFF,IpAddr&0xFF,
  867. pDeviceName);
  868. }
  869. //----------------------------------------------------------------------------
  870. VOID
  871. TdiAddressDeletion(
  872. PTA_ADDRESS Addr,
  873. PUNICODE_STRING pDeviceName,
  874. PTDI_PNP_CONTEXT Context
  875. )
  876. /*++
  877. Routine Description:
  878. This routine handles an IP address going away.
  879. It is called by TDI when an address is deleted.
  880. If it's an address we care about we'll clean up appropriately.
  881. Arguments:
  882. IN Addr -- IP address that's going.
  883. IN pDeviceName -- Unicode string Ptr for Device whose address is changing
  884. IN Context -- Tdi PnP context
  885. Return Value:
  886. Nothing!
  887. --*/
  888. {
  889. tIPADDRESS IpAddr;
  890. LIST_ENTRY *pEntry;
  891. LIST_ENTRY *pEntry2;
  892. PGMLockHandle OldIrq, OldIrq1;
  893. tSEND_SESSION *pSend;
  894. tADDRESS_CONTEXT *pAddress;
  895. NTSTATUS status;
  896. BOOLEAN fFound;
  897. tADDRESS_CONTEXT *pAddressToDeref = NULL;
  898. tLOCAL_INTERFACE *pLocalInterface = NULL;
  899. tADDRESS_ON_INTERFACE *pLocalAddress = NULL;
  900. ULONG IpInterfaceContext;
  901. if (Addr->AddressType != TDI_ADDRESS_TYPE_IP)
  902. {
  903. return;
  904. }
  905. IpAddr = ntohl(((PTDI_ADDRESS_IP)&Addr->Address[0])->in_addr);
  906. PgmLock (&PgmDynamicConfig, OldIrq);
  907. fFound = FALSE;
  908. pEntry = &PgmDynamicConfig.LocalInterfacesList;
  909. while ((pEntry = pEntry->Flink) != &PgmDynamicConfig.LocalInterfacesList)
  910. {
  911. pLocalInterface = CONTAINING_RECORD (pEntry, tLOCAL_INTERFACE, Linkage);
  912. pEntry2 = &pLocalInterface->Addresses;
  913. while ((pEntry2 = pEntry2->Flink) != &pLocalInterface->Addresses)
  914. {
  915. pLocalAddress = CONTAINING_RECORD (pEntry2, tADDRESS_ON_INTERFACE, Linkage);
  916. if (pLocalAddress->IpAddress == IpAddr)
  917. {
  918. IpInterfaceContext = pLocalInterface->IpInterfaceContext;
  919. RemoveEntryList (&pLocalAddress->Linkage);
  920. PgmFreeMem (pLocalAddress);
  921. //
  922. // If this is the last address on this interface, clean up!
  923. //
  924. if (IsListEmpty (&pLocalInterface->Addresses))
  925. {
  926. RemoveEntryList (&pLocalInterface->Linkage);
  927. PgmFreeMem (pLocalInterface);
  928. pLocalInterface = NULL;
  929. }
  930. fFound = TRUE;
  931. break;
  932. }
  933. }
  934. if (fFound)
  935. {
  936. break;
  937. }
  938. }
  939. if (!fFound)
  940. {
  941. PgmUnlock (&PgmDynamicConfig, OldIrq);
  942. PgmLog (PGM_LOG_ERROR, DBG_PNP, "TdiAddressDeletion",
  943. "\tAddress [%d.%d.%d.%d] NOT notified on <%wZ>\n",
  944. (IpAddr>>24)&0xFF,(IpAddr>>16)&0xFF,(IpAddr>>8)&0xFF,IpAddr&0xFF,
  945. pDeviceName);
  946. return;
  947. }
  948. pEntry = &PgmDynamicConfig.SenderAddressHead;
  949. while ((pEntry = pEntry->Flink) != &PgmDynamicConfig.SenderAddressHead)
  950. {
  951. pAddress = CONTAINING_RECORD (pEntry, tADDRESS_CONTEXT, Linkage);
  952. if (pAddress->SenderMCastOutIf == IpAddr)
  953. {
  954. PgmLock (pAddress, OldIrq1);
  955. pAddress->Flags |= PGM_ADDRESS_FLAG_INVALID_OUT_IF;
  956. pEntry2 = &pAddress->AssociatedConnections;
  957. while ((pEntry2 = pEntry2->Flink) != &pAddress->AssociatedConnections)
  958. {
  959. pSend = CONTAINING_RECORD (pEntry2, tSEND_SESSION, Linkage);
  960. if (!(pSend->SessionFlags & PGM_SESSION_TERMINATED_ABORT))
  961. {
  962. pSend->SessionFlags |= PGM_SESSION_TERMINATED_ABORT;
  963. if (pAddress->evDisconnect)
  964. {
  965. PGM_REFERENCE_ADDRESS (pAddress, REF_ADDRESS_DISCONNECT, TRUE);
  966. PGM_REFERENCE_SESSION_SEND (pSend, REF_SESSION_DISCONNECT, FALSE);
  967. PgmUnlock (pAddress, OldIrq1);
  968. PgmUnlock (&PgmDynamicConfig, OldIrq);
  969. if (pAddressToDeref)
  970. {
  971. PGM_DEREFERENCE_ADDRESS (pAddressToDeref, REF_ADDRESS_DISCONNECT);
  972. }
  973. pAddressToDeref = pAddress;
  974. status = (*pAddress->evDisconnect) (pAddress->DiscEvContext,
  975. pSend->ClientSessionContext,
  976. 0,
  977. NULL,
  978. 0,
  979. NULL,
  980. TDI_DISCONNECT_ABORT);
  981. PGM_DEREFERENCE_SESSION_SEND (pSend, REF_SESSION_DISCONNECT);
  982. PgmLock (&PgmDynamicConfig, OldIrq);
  983. PgmLock (pAddress, OldIrq1);
  984. pEntry = &PgmDynamicConfig.SenderAddressHead;
  985. break;
  986. }
  987. }
  988. }
  989. PgmUnlock (pAddress, OldIrq1);
  990. }
  991. }
  992. //
  993. // See which receivers were actively listening on this interface
  994. // If this was an interface for an active session, then we need to
  995. // restart listening on all interfaces if no interface(s) had been
  996. // specified by the user.
  997. //
  998. #ifdef IP_FIX
  999. if (!pLocalInterface)
  1000. {
  1001. StopListeningOnInterface (IpInterfaceContext, &OldIrq);
  1002. }
  1003. #else
  1004. StopListeningOnInterface (IpAddr, &OldIrq);
  1005. #endif // IP_FIX
  1006. PgmUnlock (&PgmDynamicConfig, OldIrq);
  1007. if (pAddressToDeref)
  1008. {
  1009. PGM_DEREFERENCE_ADDRESS (pAddress, REF_ADDRESS_DISCONNECT);
  1010. }
  1011. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "TdiAddressDeletion",
  1012. "\t[%d.%d.%d.%d] on <%wZ>\n",
  1013. (IpAddr>>24)&0xFF,(IpAddr>>16)&0xFF,(IpAddr>>8)&0xFF,IpAddr&0xFF,
  1014. pDeviceName);
  1015. }
  1016. //----------------------------------------------------------------------------
  1017. VOID
  1018. TdiBindHandler(
  1019. TDI_PNP_OPCODE PnPOpCode,
  1020. PUNICODE_STRING pDeviceName,
  1021. PWSTR MultiSZBindList
  1022. )
  1023. /*++
  1024. Routine Description:
  1025. This routine is the handler for TDI to notify clients of bind notifications
  1026. Arguments:
  1027. IN PnPOpCode -- Notification code
  1028. IN pDeviceName -- Unicode string Ptr for Device whose address is changing
  1029. IN MultiSZBindList -- Current list of bindings
  1030. Return Value:
  1031. NTSTATUS - Final status of the set event operation
  1032. --*/
  1033. {
  1034. PAGED_CODE();
  1035. switch (PnPOpCode)
  1036. {
  1037. case (TDI_PNP_OP_ADD):
  1038. {
  1039. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "TdiBindHandler",
  1040. "\t[ADD]: Device=<%wZ>\n", pDeviceName);
  1041. break;
  1042. }
  1043. case (TDI_PNP_OP_DEL):
  1044. {
  1045. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "TdiBindHandler",
  1046. "\t[DEL]: Device=<%wZ>\n", pDeviceName);
  1047. break;
  1048. }
  1049. case (TDI_PNP_OP_PROVIDERREADY):
  1050. {
  1051. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "TdiBindHandler",
  1052. "\t[PROVIDERREADY]: Device=<%wZ>\n", pDeviceName);
  1053. break;
  1054. }
  1055. case (TDI_PNP_OP_NETREADY):
  1056. {
  1057. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "TdiBindHandler",
  1058. "\t[NETREADY]: Device=<%wZ>\n", pDeviceName);
  1059. break;
  1060. }
  1061. default:
  1062. {
  1063. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "TdiBindHandler",
  1064. "\t[?=%x]: Device=<%wZ>\n", PnPOpCode, pDeviceName);
  1065. break;
  1066. }
  1067. }
  1068. }
  1069. //----------------------------------------------------------------------------
  1070. NTSTATUS
  1071. TdiPnPPowerHandler(
  1072. IN PUNICODE_STRING pDeviceName,
  1073. IN PNET_PNP_EVENT pPnPEvent,
  1074. IN PTDI_PNP_CONTEXT Context1,
  1075. IN PTDI_PNP_CONTEXT Context2
  1076. )
  1077. /*++
  1078. Routine Description:
  1079. This routine is the handler called by TDI notify its clients of Power notifications
  1080. Arguments:
  1081. IN pDeviceName -- Unicode string Ptr for Device whose address is changing
  1082. IN PnPEvent -- Event notification
  1083. IN Context1 --
  1084. IN Context2 --
  1085. Return Value:
  1086. NTSTATUS - Final status of the set event operation
  1087. --*/
  1088. {
  1089. PAGED_CODE();
  1090. switch (pPnPEvent->NetEvent)
  1091. {
  1092. case (NetEventQueryPower):
  1093. {
  1094. PgmLog (PGM_LOG_INFORM_PATH, DBG_PNP, "TdiPnPPowerHandler",
  1095. "[QueryPower]: Device=<%wZ>\n", pDeviceName);
  1096. break;
  1097. }
  1098. case (NetEventSetPower):
  1099. {
  1100. PgmLog (PGM_LOG_INFORM_PATH, DBG_PNP, "TdiPnPPowerHandler",
  1101. "[SetPower]: Device=<%wZ>\n", pDeviceName);
  1102. break;
  1103. }
  1104. case (NetEventQueryRemoveDevice):
  1105. {
  1106. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "TdiPnPPowerHandler",
  1107. "[QueryRemoveDevice]: Device=<%wZ>\n", pDeviceName);
  1108. break;
  1109. }
  1110. case (NetEventCancelRemoveDevice):
  1111. {
  1112. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "TdiPnPPowerHandler",
  1113. "[CancelRemoveDevice]: Device=<%wZ>\n", pDeviceName);
  1114. break;
  1115. }
  1116. case (NetEventReconfigure):
  1117. {
  1118. PgmLog (PGM_LOG_INFORM_PATH, DBG_PNP, "TdiPnPPowerHandler",
  1119. "[Reconfigure]: Device=<%wZ>\n", pDeviceName);
  1120. break;
  1121. }
  1122. case (NetEventBindList):
  1123. {
  1124. PgmLog (PGM_LOG_INFORM_PATH, DBG_PNP, "TdiPnPPowerHandler",
  1125. "[BindList]: Device=<%wZ>\n", pDeviceName);
  1126. break;
  1127. }
  1128. case (NetEventPnPCapabilities):
  1129. {
  1130. PgmLog (PGM_LOG_INFORM_PATH, DBG_PNP, "TdiPnPPowerHandler",
  1131. "[PnPCapabilities]: Device=<%wZ>\n", pDeviceName);
  1132. break;
  1133. }
  1134. default:
  1135. {
  1136. PgmLog (PGM_LOG_INFORM_STATUS, DBG_PNP, "TdiPnPPowerHandler",
  1137. "[?=%d]: Device=<%wZ>\n", (ULONG) pPnPEvent->NetEvent, pDeviceName);
  1138. break;
  1139. }
  1140. }
  1141. return (STATUS_SUCCESS);
  1142. }
  1143. //----------------------------------------------------------------------------
  1144. NTSTATUS
  1145. SetTdiHandlers(
  1146. )
  1147. /*++
  1148. Routine Description:
  1149. This routine is called at DriverEntry to register our handlers with TDI
  1150. Arguments:
  1151. IN
  1152. Return Value:
  1153. NTSTATUS - Final status of the set event operation
  1154. --*/
  1155. {
  1156. NTSTATUS status;
  1157. UNICODE_STRING ucPgmClientName;
  1158. TDI_CLIENT_INTERFACE_INFO TdiClientInterface;
  1159. PAGED_CODE();
  1160. //
  1161. // Register our Handlers with TDI
  1162. //
  1163. RtlInitUnicodeString (&ucPgmClientName, WC_PGM_CLIENT_NAME);
  1164. ucPgmClientName.MaximumLength = sizeof (WC_PGM_CLIENT_NAME);
  1165. PgmZeroMemory (&TdiClientInterface, sizeof(TdiClientInterface));
  1166. TdiClientInterface.MajorTdiVersion = TDI_CURRENT_MAJOR_VERSION;
  1167. TdiClientInterface.MinorTdiVersion = TDI_CURRENT_MINOR_VERSION;
  1168. TdiClientInterface.ClientName = &ucPgmClientName;
  1169. TdiClientInterface.AddAddressHandlerV2 = TdiAddressArrival;
  1170. TdiClientInterface.DelAddressHandlerV2 = TdiAddressDeletion;
  1171. TdiClientInterface.BindingHandler = TdiBindHandler;
  1172. TdiClientInterface.PnPPowerHandler = TdiPnPPowerHandler;
  1173. status = TdiRegisterPnPHandlers (&TdiClientInterface, sizeof(TdiClientInterface), &TdiClientHandle);
  1174. if (!NT_SUCCESS (status))
  1175. {
  1176. PgmLog (PGM_LOG_ERROR, DBG_PNP, "SetTdiHandlers",
  1177. "TdiRegisterPnPHandlers ==> <%x>\n", status);
  1178. return (status);
  1179. }
  1180. TdiEnumerateAddresses(TdiClientHandle);
  1181. PgmLog (PGM_LOG_INFORM_ALL_FUNCS, DBG_PNP, "SetTdiHandlers",
  1182. "\tSUCCEEDed\n");
  1183. return (status);
  1184. }