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.

4076 lines
93 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ipinip\adapter.c
  5. Abstract:
  6. The file contains the section interface of WANARP to the TCP/IP stack
  7. that is involved with Binding Notification and Querying/Setting
  8. information for interfaces
  9. Revision History:
  10. AmritanR
  11. --*/
  12. #define __FILE_SIG__ ADAPTER_SIG
  13. #include "inc.h"
  14. #pragma hdrstop
  15. NDIS_HANDLE g_nhUnbindContext;
  16. NDIS_HANDLE g_nhBindContext;
  17. NDIS_STATUS g_nsStatus = 0;
  18. NDIS_STATUS g_nsError = 0;
  19. BOOLEAN g_bRemovalInProgress;
  20. WORK_QUEUE_ITEM g_wqiWorkItem;
  21. WORK_QUEUE_ITEM g_wqiNdisWorkItem;
  22. const GUID ServerInterfaceGuid = {0x6e06f030, 0x7526, 0x11d2, {0xba, 0xf4, 0x00, 0x60, 0x08, 0x15, 0xa4, 0xbd}};
  23. extern
  24. VOID
  25. IPDelayedNdisReEnumerateBindings(
  26. CTEEvent *Event,
  27. PVOID Context
  28. );
  29. BOOLEAN
  30. IsBindingPresent(
  31. IN GUID *pGuid
  32. );
  33. VOID
  34. WanNdisBindAdapter(
  35. PNDIS_STATUS pnsRetStatus,
  36. NDIS_HANDLE nhBindContext,
  37. PNDIS_STRING nsAdapterName,
  38. PVOID pvSystemSpecific1,
  39. PVOID pvSystemSpecific2
  40. )
  41. {
  42. RtAssert(FALSE);
  43. }
  44. INT
  45. WanIpBindAdapter(
  46. IN PNDIS_STATUS pnsRetStatus,
  47. IN NDIS_HANDLE nhBindContext,
  48. IN PNDIS_STRING pnsAdapterName,
  49. IN PVOID pvSS1,
  50. IN PVOID pvSS2
  51. )
  52. /*++
  53. Routine Description:
  54. Called by IP to bind an adapter. We open the binding and then do
  55. all the other work in complete handler
  56. Locks:
  57. The routine acquires the global adapter list lock, so it is not
  58. PAGEABLE.
  59. Arguments:
  60. Return Value:
  61. --*/
  62. {
  63. NDIS_STATUS nsStatus;
  64. KIRQL kiIrql;
  65. LONG lResult;
  66. #if DBG
  67. ANSI_STRING asTempAnsiString;
  68. #endif
  69. TraceEnter(ADPT, "WanIpBindAdapter");
  70. //
  71. // Serialize Bind, Unbind code
  72. //
  73. WanpAcquireResource(&g_wrBindMutex);
  74. RtAcquireSpinLock(&g_rlStateLock,
  75. &kiIrql);
  76. //
  77. // See if we have already received a BIND call or are in the process
  78. // of servicing a bind
  79. //
  80. if(g_lBindRcvd isnot 0)
  81. {
  82. //
  83. // We have already received a bind call
  84. //
  85. RtAssert(g_lBindRcvd is 1);
  86. RtReleaseSpinLock(&g_rlStateLock,
  87. kiIrql);
  88. WanpReleaseResource(&g_wrBindMutex);
  89. Trace(ADPT,ERROR,
  90. ("WanIpBindAdapter: Duplicate bind call\n"));
  91. *pnsRetStatus = NDIS_STATUS_SUCCESS;
  92. TraceLeave(ADPT, "WanIpBindAdapter");
  93. return FALSE;
  94. }
  95. //
  96. // Set BindRcvd to 1 so that we dont service any binds till we
  97. // get done
  98. //
  99. g_lBindRcvd = 1;
  100. RtReleaseSpinLock(&g_rlStateLock,
  101. kiIrql);
  102. Trace(ADPT, INFO,
  103. ("WanIpBindAdapter: IP called to bind to adapter %S\n",
  104. pnsAdapterName->Buffer));
  105. //
  106. // We need to open this adapter as our NDISWAN binding
  107. //
  108. g_nhBindContext = nhBindContext;
  109. nsStatus = WanpOpenNdisWan(pnsAdapterName,
  110. (PNDIS_STRING)pvSS1);
  111. if((nsStatus isnot NDIS_STATUS_SUCCESS) and
  112. (nsStatus isnot NDIS_STATUS_PENDING))
  113. {
  114. RtAcquireSpinLock(&g_rlStateLock,
  115. &kiIrql);
  116. g_lBindRcvd = 0;
  117. RtReleaseSpinLock(&g_rlStateLock,
  118. kiIrql);
  119. Trace(ADPT, ERROR,
  120. ("WanIpBindAdapter: Error %x opening NDISWAN on %S\n",
  121. nsStatus,
  122. pnsAdapterName->Buffer));
  123. }
  124. *pnsRetStatus = nsStatus;
  125. //
  126. // At this point we are done. If the operation finished synchronously
  127. // then our OpenAdapterComplete handler has already been called
  128. // Otherwise stuff will happen later
  129. //
  130. TraceLeave(ADPT, "WanIpBindAdapter");
  131. return TRUE;
  132. }
  133. #pragma alloc_text(PAGE, WanpOpenNdisWan)
  134. NDIS_STATUS
  135. WanpOpenNdisWan(
  136. PNDIS_STRING pnsAdapterName,
  137. PNDIS_STRING pnsSystemSpecific1
  138. )
  139. /*++
  140. Routine Description:
  141. This routine opens the ndiswan adapter. It also stores the SS1 string
  142. in a global for use by the completion routine
  143. Locks:
  144. Called with the g_wrBindMutex held exclusively
  145. Arguments:
  146. pusBindName Name of the bindings
  147. pnsSystemSpecific1 The SS1 passed in the bind call from IP
  148. Return Value:
  149. --*/
  150. {
  151. NDIS_STATUS nsStatus, nsError;
  152. UINT i;
  153. NDIS_MEDIUM MediaArray[] = {NdisMediumWan};
  154. PWCHAR pwcNameBuffer, pwcStringBuffer;
  155. PBYTE pbyBuffer;
  156. PAGED_CODE();
  157. TraceEnter(ADPT,"OpenNdiswan");
  158. //
  159. // Save a copy of the NDIS binding name
  160. // Increase the length by 1 so that we can NULL terminate it for
  161. // easy printing
  162. //
  163. pnsAdapterName->Length += sizeof(WCHAR);
  164. g_usNdiswanBindName.Buffer = RtAllocate(NonPagedPool,
  165. pnsAdapterName->Length,
  166. WAN_STRING_TAG);
  167. if(g_usNdiswanBindName.Buffer is NULL)
  168. {
  169. Trace(GLOBAL, ERROR,
  170. ("OpenNdiswan: Unable to allocate %d bytes\n",
  171. pnsAdapterName->Length));
  172. g_nhBindContext = NULL;
  173. WanpReleaseResource(&g_wrBindMutex);
  174. return STATUS_INSUFFICIENT_RESOURCES;
  175. }
  176. g_usNdiswanBindName.MaximumLength = pnsAdapterName->Length;
  177. RtlUpcaseUnicodeString(&g_usNdiswanBindName,
  178. pnsAdapterName,
  179. FALSE);
  180. pnsAdapterName->Length -= sizeof(WCHAR);
  181. g_usNdiswanBindName.Length -= sizeof(WCHAR);
  182. //
  183. // NULL terminate
  184. //
  185. g_usNdiswanBindName.Buffer[g_usNdiswanBindName.MaximumLength/sizeof(WCHAR) - 1] = UNICODE_NULL;
  186. //
  187. // Save a copy of SS1
  188. //
  189. pwcStringBuffer = RtAllocate(NonPagedPool,
  190. pnsSystemSpecific1->MaximumLength,
  191. WAN_STRING_TAG);
  192. if(pwcStringBuffer is NULL)
  193. {
  194. RtFree(g_usNdiswanBindName.Buffer);
  195. g_usNdiswanBindName.Buffer = NULL;
  196. g_usNdiswanBindName.MaximumLength = 0;
  197. g_usNdiswanBindName.Length = 0;
  198. g_nhBindContext = NULL;
  199. WanpReleaseResource(&g_wrBindMutex);
  200. return NDIS_STATUS_RESOURCES;
  201. }
  202. RtlZeroMemory(pwcStringBuffer,
  203. pnsSystemSpecific1->MaximumLength);
  204. //
  205. // Save a copy of the SS1 string
  206. //
  207. g_nsSystemSpecific1.MaximumLength = pnsSystemSpecific1->MaximumLength;
  208. g_nsSystemSpecific1.Length = pnsSystemSpecific1->Length;
  209. g_nsSystemSpecific1.Buffer = pwcStringBuffer;
  210. RtlCopyMemory(g_nsSystemSpecific1.Buffer,
  211. pnsSystemSpecific1->Buffer,
  212. pnsSystemSpecific1->Length);
  213. //
  214. // Open the NDIS adapter.
  215. //
  216. Trace(ADPT, INFO,
  217. ("OpenNdiswan: Opening %S\n", g_usNdiswanBindName.Buffer));
  218. //
  219. // Medium index
  220. //
  221. i = 0;
  222. #define MAX_MEDIA 1
  223. NdisOpenAdapter(&nsStatus,
  224. &nsError,
  225. &g_nhNdiswanBinding,
  226. &i,
  227. MediaArray,
  228. MAX_MEDIA,
  229. g_nhWanarpProtoHandle,
  230. (NDIS_HANDLE)0x0CABB1E5,
  231. pnsAdapterName,
  232. 0,
  233. NULL);
  234. #undef MAX_MEDIA
  235. if(nsStatus isnot NDIS_STATUS_PENDING)
  236. {
  237. //
  238. // we always return PENDING to NDIS because we need to
  239. // do a switch to system thread when we are done setting OIDS to
  240. // NDISWAN. So call out completion routine here
  241. //
  242. WanNdisOpenAdapterComplete((NDIS_HANDLE)0x0CABB1E5,
  243. nsStatus,
  244. nsError);
  245. nsStatus = NDIS_STATUS_PENDING;
  246. }
  247. TraceLeave(ADPT, "OpenNdiswan");
  248. return nsStatus;
  249. }
  250. #pragma alloc_text (PAGE, WanNdisOpenAdapterComplete)
  251. VOID
  252. WanNdisOpenAdapterComplete(
  253. NDIS_HANDLE nhHandle,
  254. NDIS_STATUS nsStatus,
  255. NDIS_STATUS nsError
  256. )
  257. /*++
  258. Routine Description:
  259. Completion routine called by NDIS when it is done opening the NDISWAN
  260. binding
  261. If the open was successful, we start the train of requests
  262. Locks:
  263. Called either synchronously or off a worker thread with the g_wrBindMutex
  264. This routine needs to release the resource and set g_lBindRcvd
  265. Arguments:
  266. nhHandle
  267. nsStatus
  268. nsError
  269. Return Value:
  270. None
  271. --*/
  272. {
  273. NDIS_STATUS nsResult;
  274. BYTE rgbyProtocolId[ARP_802_ADDR_LENGTH] = {0x80,
  275. 0x00,
  276. 0x00,
  277. 0x00,
  278. 0x08,
  279. 0x00};
  280. PWANARP_NDIS_REQUEST_CONTEXT pRequestContext;
  281. TraceEnter(ADPT,"NdisOpenAdapterComplete");
  282. PAGED_CODE();
  283. RtAssert(nhHandle is (NDIS_HANDLE)0x0CABB1E5);
  284. //
  285. // If we couldnt open the NDIS wan binding, free all the resources
  286. // and return
  287. //
  288. if(nsStatus isnot NDIS_STATUS_SUCCESS)
  289. {
  290. Trace(ADPT, ERROR,
  291. ("OpenAdapterComplete: Status %x\n", nsStatus));
  292. RtAssert(g_nhBindContext isnot NULL);
  293. NdisCompleteBindAdapter(g_nhBindContext,
  294. nsStatus,
  295. nsError);
  296. g_nhBindContext = NULL;
  297. WanpFreeBindResourcesAndReleaseLock();
  298. return;
  299. }
  300. //
  301. // From here on, the NDISWAN adapter is opened, so to cleanup resources
  302. // we must call CloseNdisWan()
  303. //
  304. pRequestContext = RtAllocate(NonPagedPool,
  305. sizeof(WANARP_NDIS_REQUEST_CONTEXT),
  306. WAN_REQUEST_TAG);
  307. if(pRequestContext is NULL)
  308. {
  309. RtAssert(g_nhBindContext isnot NULL);
  310. #if 0
  311. NdisCompleteBindAdapter(g_nhBindContext,
  312. nsStatus,
  313. nsError);
  314. g_nhBindContext = NULL;
  315. #endif
  316. g_nsStatus = g_nsError = NDIS_STATUS_RESOURCES;
  317. ExInitializeWorkItem(&g_wqiNdisWorkItem,
  318. WanpCloseNdisWan,
  319. NULL);
  320. ExQueueWorkItem(&g_wqiNdisWorkItem,
  321. DelayedWorkQueue);
  322. // WanpCloseNdisWan(NULL);
  323. Trace(ADPT, ERROR,
  324. ("NdisOpenAdapterComplete: Couldnt allocate memory for request context\n"));
  325. return;
  326. }
  327. //
  328. // Set protocol type
  329. //
  330. RtlCopyMemory(pRequestContext->rgbyProtocolId,
  331. rgbyProtocolId,
  332. sizeof(rgbyProtocolId));
  333. nsResult = WanpDoNdisRequest(NdisRequestSetInformation,
  334. OID_WAN_PROTOCOL_TYPE,
  335. pRequestContext->rgbyProtocolId,
  336. sizeof(pRequestContext->rgbyProtocolId),
  337. pRequestContext,
  338. WanpSetProtocolTypeComplete);
  339. if(nsResult isnot NDIS_STATUS_PENDING)
  340. {
  341. //
  342. // No need to call the completion routine, since DoNdisRequest
  343. // always calls it
  344. //
  345. Trace(ADPT, ERROR,
  346. ("NdisOpenAdapterComplete: %x from OID_WAN_PROTOCOL_TYPE\n",
  347. nsResult));
  348. }
  349. TraceLeave(ADPT,"NdisOpenAdapterComplete");
  350. }
  351. VOID
  352. WanpSetProtocolTypeComplete(
  353. NDIS_HANDLE nhHandle,
  354. struct _WANARP_NDIS_REQUEST_CONTEXT *pRequestContext,
  355. NDIS_STATUS nsStatus
  356. )
  357. /*++
  358. Routine Description:
  359. Completion handler called when we are done with setting
  360. OID_WAN_PROTOCOL_TYPE
  361. Locks:
  362. None
  363. Arguments:
  364. nhHandle Binding for the adapter to which the request was sent
  365. pRequestContext Pointer to the request context
  366. nsStatus Result of the request
  367. Return Value:
  368. None
  369. --*/
  370. {
  371. NDIS_STATUS nsResult;
  372. TraceEnter(ADPT,"SetProtocolTypeComplete");
  373. if(nsStatus isnot NDIS_STATUS_SUCCESS)
  374. {
  375. Trace(ADPT, ERROR,
  376. ("SetProtocolTypeComplete: Status %x\n", nsStatus));
  377. WanpLastOidComplete(nhHandle,
  378. pRequestContext,
  379. nsStatus);
  380. return;
  381. }
  382. //
  383. // Set lookahead size
  384. //
  385. pRequestContext->ulLookahead = WANARP_LOOKAHEAD_SIZE;
  386. nsResult = WanpDoNdisRequest(NdisRequestSetInformation,
  387. OID_GEN_CURRENT_LOOKAHEAD,
  388. &(pRequestContext->ulLookahead),
  389. sizeof(pRequestContext->ulLookahead),
  390. pRequestContext,
  391. WanpSetLookaheadComplete);
  392. if(nsResult isnot NDIS_STATUS_PENDING)
  393. {
  394. Trace(ADPT, ERROR,
  395. ("SetProtocolTypeComplete: %x from OID_GEN_CURRENT_LOOKAHEAD\n",
  396. nsResult));
  397. }
  398. TraceLeave(ADPT,"SetProtocolTypeComplete");
  399. }
  400. VOID
  401. WanpSetLookaheadComplete(
  402. NDIS_HANDLE nhHandle,
  403. struct _WANARP_NDIS_REQUEST_CONTEXT *pRequestContext,
  404. NDIS_STATUS nsStatus
  405. )
  406. /*++
  407. Routine Description:
  408. Completion handler called when we are done with setting
  409. OID_GEN_CURRENT_LOOKAHEAD
  410. Locks:
  411. None
  412. Arguments:
  413. nhHandle Binding for the adapter to which the request was sent
  414. pRequestContext Pointer to the request context
  415. nsStatus Result of the request
  416. Return Value:
  417. None
  418. --*/
  419. {
  420. NDIS_STATUS nsResult;
  421. TraceEnter(ADPT,"SetLookaheadComplete");
  422. if(nsStatus isnot NDIS_STATUS_SUCCESS)
  423. {
  424. Trace(ADPT, ERROR,
  425. ("SetLookaheadComplete: Status %x\n", nsStatus));
  426. WanpLastOidComplete(nhHandle,
  427. pRequestContext,
  428. nsStatus);
  429. return;
  430. }
  431. //
  432. // Set packet filters
  433. //
  434. pRequestContext->ulPacketFilter =
  435. NDIS_PACKET_TYPE_BROADCAST | NDIS_PACKET_TYPE_DIRECTED;
  436. nsResult = WanpDoNdisRequest(NdisRequestSetInformation,
  437. OID_GEN_CURRENT_PACKET_FILTER,
  438. &(pRequestContext->ulPacketFilter),
  439. sizeof(pRequestContext->ulPacketFilter),
  440. pRequestContext,
  441. WanpSetPacketFilterComplete);
  442. if(nsResult isnot NDIS_STATUS_PENDING)
  443. {
  444. Trace(ADPT, ERROR,
  445. ("SetLookaheadComplete: %x from OID_GEN_CURRENT_PACKET_FILTER\n",
  446. nsResult));
  447. }
  448. TraceLeave(ADPT,"SetLookaheadComplete");
  449. }
  450. VOID
  451. WanpSetPacketFilterComplete(
  452. NDIS_HANDLE nhHandle,
  453. struct _WANARP_NDIS_REQUEST_CONTEXT *pRequestContext,
  454. NDIS_STATUS nsStatus
  455. )
  456. /*++
  457. Routine Description:
  458. Completion handler called when we are done with setting
  459. OID_GEN_CURRENT_PACKET_FILTER
  460. Locks:
  461. None
  462. Arguments:
  463. nhHandle Binding for the adapter to which the request was sent
  464. pRequestContext Pointer to the request context
  465. nsStatus Result of the request
  466. Return Value:
  467. None
  468. --*/
  469. {
  470. NDIS_STATUS nsResult;
  471. BYTE byHeaderSize;
  472. TraceEnter(ADPT,"SetPacketFilterComplete");
  473. if(nsStatus isnot NDIS_STATUS_SUCCESS)
  474. {
  475. Trace(ADPT, ERROR,
  476. ("SetPacketFilterComplete: Status %x\n", nsStatus));
  477. WanpLastOidComplete(nhHandle,
  478. pRequestContext,
  479. nsStatus);
  480. return;
  481. }
  482. //
  483. // Set packet filters
  484. //
  485. pRequestContext->TransportHeaderOffset.ProtocolType =
  486. NDIS_PROTOCOL_ID_TCP_IP;
  487. pRequestContext->TransportHeaderOffset.HeaderOffset =
  488. (USHORT)sizeof(ETH_HEADER);
  489. nsResult = WanpDoNdisRequest(NdisRequestSetInformation,
  490. OID_GEN_TRANSPORT_HEADER_OFFSET,
  491. &(pRequestContext->TransportHeaderOffset),
  492. sizeof(pRequestContext->TransportHeaderOffset),
  493. pRequestContext,
  494. WanpLastOidComplete);
  495. if(nsResult isnot NDIS_STATUS_PENDING)
  496. {
  497. Trace(ADPT, ERROR,
  498. ("SetPacketFilterComplete: %x from OID_GEN_TRANSPORT_HEADER_OFFSET\n",
  499. nsResult));
  500. }
  501. TraceLeave(ADPT,"SetPacketFilterComplete");
  502. }
  503. VOID
  504. WanpLastOidComplete(
  505. NDIS_HANDLE nhHandle,
  506. struct _WANARP_NDIS_REQUEST_CONTEXT *pRequestContext,
  507. NDIS_STATUS nsStatus
  508. )
  509. /*++
  510. Routine Description:
  511. Completion handler called when we are done with setting the last OID
  512. Currently that is OID_GEN_TRANSPORT_HEADER_OFFSET,
  513. If everything went, well we initialize our adapters
  514. Locks:
  515. None
  516. Arguments:
  517. nhHandle Binding for the adapter to which the request was sent
  518. pRequestContext Pointer to the request context
  519. nsStatus Result of the request
  520. Return Value:
  521. None
  522. --*/
  523. {
  524. NDIS_STATUS nsResult;
  525. TraceEnter(ADPT,"LastOidComplete");
  526. RtFree(pRequestContext);
  527. RtAssert(g_wrBindMutex.lWaitCount >= 1);
  528. if(nsStatus isnot STATUS_SUCCESS)
  529. {
  530. RtAssert(g_nhBindContext isnot NULL);
  531. #if 0
  532. //
  533. // BindContext being NON-NULL means we are being called
  534. // asynchronously, hence call NdisCompleteBindAdapter
  535. //
  536. NdisCompleteBindAdapter(g_nhBindContext,
  537. nsStatus,
  538. nsStatus);
  539. g_nhBindContext = NULL;
  540. #endif
  541. Trace(ADPT, ERROR,
  542. ("LastOidComplete: Status %x\n", nsStatus));
  543. g_nsStatus = g_nsError = nsStatus;
  544. ExInitializeWorkItem(&g_wqiNdisWorkItem,
  545. WanpCloseNdisWan,
  546. NULL);
  547. ExQueueWorkItem(&g_wqiNdisWorkItem,
  548. DelayedWorkQueue);
  549. // WanpCloseNdisWan(NULL);
  550. return;
  551. }
  552. //
  553. // This needs to be put in when the multiple adapters stuff is done
  554. //
  555. //
  556. // The OpenNdiswan call would have setup the system specific
  557. // Since the WanpInitializeAdapters must be called at PASSIVE, we
  558. // fire of a work item here to call the function.
  559. //
  560. ExInitializeWorkItem(&g_wqiWorkItem,
  561. WanpInitializeAdapters,
  562. NULL);
  563. ExQueueWorkItem(&g_wqiWorkItem,
  564. DelayedWorkQueue);
  565. //
  566. // Dont release the mutex here
  567. //
  568. TraceLeave(ADPT,"LastOidComplete");
  569. }
  570. //
  571. // When this is used, remember NOT to use NdisUnbindAdapter as a clean
  572. // up routine because of the way the resource is held
  573. //
  574. #pragma alloc_text(PAGE, WanpInitializeAdapters)
  575. NTSTATUS
  576. WanpInitializeAdapters(
  577. PVOID pvContext
  578. )
  579. /*++
  580. Routine Description:
  581. This routine uses the stored SS1 and opens the IP config for the
  582. binding. It then loops through the multi_sz and creates one adapter
  583. for every sz.
  584. Locks:
  585. Called with the bind mutex held.
  586. This function releases the mutex
  587. Arguments:
  588. None
  589. Return Value:
  590. --*/
  591. {
  592. NDIS_STRING IPConfigName = NDIS_STRING_CONST("IPConfig");
  593. NDIS_STATUS nsStatus;
  594. NDIS_HANDLE nhConfigHandle;
  595. USHORT i;
  596. PADAPTER pNewAdapter;
  597. NTSTATUS nStatus, nReturnStatus;
  598. PWCHAR pwszDeviceBuffer;
  599. PNDIS_CONFIGURATION_PARAMETER pParam;
  600. TraceEnter(ADPT, "InitializeAdapters");
  601. PAGED_CODE();
  602. UNREFERENCED_PARAMETER(pvContext);
  603. RtAssert(g_nhBindContext isnot NULL);
  604. do
  605. {
  606. //
  607. // Open the key for this "adapter"
  608. //
  609. NdisOpenProtocolConfiguration(&nsStatus,
  610. &nhConfigHandle,
  611. &g_nsSystemSpecific1);
  612. if(nsStatus isnot NDIS_STATUS_SUCCESS)
  613. {
  614. Trace(ADPT, ERROR,
  615. ("InitializeAdapters: Unable to Open Protocol Config %x\n",
  616. nsStatus));
  617. break;
  618. }
  619. //
  620. // Read in the IPConfig string. If this is not present,
  621. // fail this call.
  622. //
  623. NdisReadConfiguration(&nsStatus,
  624. &pParam,
  625. nhConfigHandle,
  626. &IPConfigName,
  627. NdisParameterMultiString);
  628. if((nsStatus isnot NDIS_STATUS_SUCCESS) or
  629. (pParam->ParameterType isnot NdisParameterMultiString))
  630. {
  631. Trace(ADPT, ERROR,
  632. ("InitializeAdapters: Unable to read IPConfig. Status %x \n",
  633. nsStatus));
  634. NdisCloseConfiguration(nhConfigHandle);
  635. nsStatus = STATUS_UNSUCCESSFUL;
  636. break;
  637. }
  638. //
  639. // Allocate memory for the max length device name - used later
  640. //
  641. pwszDeviceBuffer =
  642. RtAllocate(NonPagedPool,
  643. (WANARP_MAX_DEVICE_NAME_LEN + 1) * sizeof(WCHAR),
  644. WAN_STRING_TAG);
  645. if(pwszDeviceBuffer is NULL)
  646. {
  647. NdisCloseConfiguration(nhConfigHandle);
  648. Trace(ADPT, ERROR,
  649. ("InitializeAdapters: Couldnt alloc %d bytes for dev name\n",
  650. (WANARP_MAX_DEVICE_NAME_LEN + 1) * sizeof(WCHAR)));
  651. nsStatus = STATUS_INSUFFICIENT_RESOURCES;
  652. break;
  653. }
  654. }while(FALSE);
  655. if(nsStatus isnot STATUS_SUCCESS)
  656. {
  657. //
  658. // Tell NDIS that the bind is done but it failed
  659. //
  660. g_nsStatus = g_nsError = nsStatus;
  661. #if 0
  662. NdisCompleteBindAdapter(g_nhBindContext,
  663. nsStatus,
  664. nsStatus);
  665. g_nhBindContext = NULL;
  666. #endif
  667. WanpCloseNdisWan(NULL);
  668. TraceLeave(ADPT, "InitializeAdapters");
  669. return nsStatus;
  670. }
  671. //
  672. // Now walk through the each of the string
  673. // Since the string must end with two \0's we only walk Len/2 - 1
  674. //
  675. i = 0;
  676. nReturnStatus = STATUS_UNSUCCESSFUL;
  677. RtAssert((pParam->ParameterData.StringData.Length % sizeof(WCHAR)) is 0);
  678. //
  679. // The IPConfigString is a MULTI_SZ with each SZ being the relative key
  680. // for an interfaces IP configuration. It is thus something like
  681. // TCPIP\PARAMETERS\INTERFACES\<device_name>
  682. // Being a MULTI_SZ it is terminated by 2 NULL characters. So we
  683. // walk till the last but one character while parsing out the SZ from
  684. // the multi_sz
  685. //
  686. while(i < (pParam->ParameterData.StringData.Length/sizeof(WCHAR)) - 1)
  687. {
  688. USHORT j, usConfigLen, usDevLen;
  689. UNICODE_STRING usTempString, usUpcaseString, usDevString;
  690. PADAPTER pNewAdapter;
  691. GUID Guid;
  692. if(pParam->ParameterData.StringData.Buffer[i] is UNICODE_NULL)
  693. {
  694. if(pParam->ParameterData.StringData.Buffer[i + 1] is UNICODE_NULL)
  695. {
  696. //
  697. // Two nulls - end of string
  698. //
  699. break;
  700. }
  701. //
  702. // only one null, just move on to the next character
  703. //
  704. i++;
  705. continue;
  706. }
  707. RtAssert(pParam->ParameterData.StringData.Buffer[i] isnot UNICODE_NULL);
  708. //
  709. // Now i points to the start of an SZ. Figure out the length of this
  710. //
  711. usConfigLen =
  712. (USHORT)wcslen(&(pParam->ParameterData.StringData.Buffer[i]));
  713. //
  714. // Make usTempString point to this config. Also increase
  715. // the size by one so one can print this nicely
  716. //
  717. usTempString.MaximumLength = (usConfigLen + 1) * sizeof(WCHAR);
  718. usTempString.Length = (usConfigLen + 1) * sizeof(WCHAR);
  719. usTempString.Buffer = &(pParam->ParameterData.StringData.Buffer[i]);
  720. usUpcaseString.Buffer = RtAllocate(NonPagedPool,
  721. usTempString.MaximumLength,
  722. WAN_STRING_TAG);
  723. if(usUpcaseString.Buffer is NULL)
  724. {
  725. Trace(ADPT, ERROR,
  726. ("InitializeAdapters: Unable to allocate %d bytes\n",
  727. usTempString.MaximumLength));
  728. usUpcaseString.MaximumLength = 0;
  729. usUpcaseString.Length = 0;
  730. i += usConfigLen;
  731. continue;
  732. }
  733. usUpcaseString.MaximumLength = usTempString.MaximumLength;
  734. RtlUpcaseUnicodeString(&usUpcaseString,
  735. &usTempString,
  736. FALSE);
  737. //
  738. // Set the last wchar to null
  739. //
  740. usUpcaseString.Buffer[usConfigLen] = UNICODE_NULL;
  741. //
  742. // Set the length back to what it was
  743. //
  744. usUpcaseString.Length -= sizeof(WCHAR);
  745. RtAssert((usUpcaseString.Length % sizeof(WCHAR)) is 0);
  746. //
  747. // The device name is the last thing in the '\' separated path.
  748. // So walk the SZ backwards looking for '\'
  749. // NOTE one could use wcsrchr, but it would be inefficient since
  750. // it doesnt know the end of the buffer
  751. //
  752. for(j = usUpcaseString.Length/sizeof(WCHAR) - 1;
  753. j >= 0;
  754. j--)
  755. {
  756. if(usUpcaseString.Buffer[j] is L'\\')
  757. {
  758. break;
  759. }
  760. }
  761. //
  762. // So at this point j is the index to the last '\'
  763. //
  764. //
  765. // First off, make this a GUID
  766. //
  767. nStatus = ConvertStringToGuid(&(usUpcaseString.Buffer[j + 1]),
  768. wcslen(&(usUpcaseString.Buffer[j + 1])) * sizeof(WCHAR),
  769. &Guid);
  770. if(nStatus isnot STATUS_SUCCESS)
  771. {
  772. //
  773. // Hmm - not a GUID?
  774. //
  775. Trace(ADPT, ERROR,
  776. ("InitializeAdapters: String %S is not a GUID\n",
  777. &(usUpcaseString.Buffer[j + 1])));
  778. //
  779. // Free the upcase string and move to the next SZ in IPConfig
  780. //
  781. RtFree(usUpcaseString.Buffer);
  782. usUpcaseString.Buffer = NULL;
  783. usUpcaseString.MaximumLength = 0;
  784. usUpcaseString.Length = 0;
  785. i += usConfigLen;
  786. continue;
  787. }
  788. //
  789. // Make sure this binding is not present
  790. //
  791. if(IsBindingPresent(&Guid))
  792. {
  793. Trace(ADPT, WARN,
  794. ("InitializeAdapters: %S already present\n",
  795. &(usUpcaseString.Buffer[j + 1])));
  796. //
  797. // Free the upcase string and move to the next SZ in IPConfig
  798. //
  799. RtFree(usUpcaseString.Buffer);
  800. usUpcaseString.Buffer = NULL;
  801. usUpcaseString.MaximumLength = 0;
  802. usUpcaseString.Length = 0;
  803. i += usConfigLen;
  804. continue;
  805. }
  806. //
  807. // We need to tack on a \DEVICE in front of Guid string
  808. //
  809. usDevLen = wcslen(TCPIP_IF_PREFIX) +
  810. wcslen(&(usUpcaseString.Buffer[j]));
  811. //
  812. // make sure we can fit in the space we have allocated
  813. //
  814. RtAssert(usDevLen <= WANARP_MAX_DEVICE_NAME_LEN);
  815. pwszDeviceBuffer[usDevLen] = UNICODE_NULL;
  816. usDevString.MaximumLength = usDevLen * sizeof(WCHAR);
  817. usDevString.Length = usDevLen * sizeof(WCHAR);
  818. usDevString.Buffer = pwszDeviceBuffer;
  819. //
  820. // Copy over the \Device part
  821. //
  822. RtlCopyMemory(pwszDeviceBuffer,
  823. TCPIP_IF_PREFIX,
  824. wcslen(TCPIP_IF_PREFIX) * sizeof(WCHAR));
  825. //
  826. // Cat the \<Name> part
  827. //
  828. RtlCopyMemory(&(pwszDeviceBuffer[wcslen(TCPIP_IF_PREFIX)]),
  829. &usUpcaseString.Buffer[j],
  830. wcslen(&(usUpcaseString.Buffer[j])) * sizeof(WCHAR));
  831. //
  832. // Create an adapter with this name and config
  833. //
  834. pNewAdapter = NULL;
  835. Trace(ADPT, INFO,
  836. ("InitializeAdapters: Calling create adapter for %S %S\n",
  837. usUpcaseString.Buffer,
  838. usDevString.Buffer));
  839. nStatus = WanpCreateAdapter(&Guid,
  840. &usUpcaseString,
  841. &usDevString,
  842. &pNewAdapter);
  843. if(nStatus isnot STATUS_SUCCESS)
  844. {
  845. Trace(ADPT, ERROR,
  846. ("InitializeAdapters: Err %x creating adapter for %S (%S)\n",
  847. nStatus,
  848. usUpcaseString.Buffer,
  849. pwszDeviceBuffer));
  850. }
  851. else
  852. {
  853. //
  854. // If even one succeeds, we return success
  855. //
  856. nReturnStatus = STATUS_SUCCESS;
  857. }
  858. //
  859. // Done with the upcased string
  860. //
  861. RtFree(usUpcaseString.Buffer);
  862. usUpcaseString.Buffer = NULL;
  863. usUpcaseString.MaximumLength = 0;
  864. usUpcaseString.Length = 0;
  865. //
  866. // Go to the next SZ in the MULTI_SZ
  867. //
  868. i += usConfigLen;
  869. }
  870. NdisCloseConfiguration(nhConfigHandle);
  871. RtFree(pwszDeviceBuffer);
  872. NdisCompleteBindAdapter(g_nhBindContext,
  873. nReturnStatus,
  874. nReturnStatus);
  875. g_nhBindContext = NULL;
  876. if(nReturnStatus isnot STATUS_SUCCESS)
  877. {
  878. WanpCloseNdisWan(NULL);
  879. }
  880. else
  881. {
  882. g_lBindRcvd = 1;
  883. WanpReleaseResource(&g_wrBindMutex);
  884. }
  885. TraceLeave(ADPT, "InitializeAdapters");
  886. return nReturnStatus;
  887. }
  888. NTSTATUS
  889. WanpCreateAdapter(
  890. IN GUID *pAdapterGuid,
  891. IN PUNICODE_STRING pusConfigName,
  892. IN PUNICODE_STRING pusDeviceName,
  893. OUT ADAPTER **ppNewAdapter
  894. )
  895. /*++
  896. Routine Description:
  897. Creates and initializes an ADAPTER structure
  898. If this is the first adapter, it is used as the server adapter.
  899. For that case, it also creates and initializes the server interface.
  900. The server adapter is added to IP
  901. Locks:
  902. Called at passive, however it acquires the adapter list lock since it
  903. sets g_pServerAdapter/Interface
  904. Arguments:
  905. pusConfigName Name of config key
  906. pusDeviceName The device name for the adapter
  907. ppNewAdapter Pointer to storage for the pointer to newly created adapter
  908. Return Value:
  909. STATUS_SUCCESS
  910. STATUS_INSUFFICIENT_RESOURCES
  911. --*/
  912. {
  913. ULONG ulSize;
  914. PVOID pvBuffer;
  915. PADAPTER pAdapter;
  916. USHORT i;
  917. NTSTATUS nStatus;
  918. KIRQL kiIrql;
  919. PASSIVE_ENTRY();
  920. TraceEnter(ADPT, "CreateAdapter");
  921. Trace(ADPT, TRACE,
  922. ("CreateAdapter: \n\t%S\n\t%S\n",
  923. pusConfigName->Buffer,
  924. pusDeviceName->Buffer));
  925. *ppNewAdapter = NULL;
  926. //
  927. // The size that one needs is the size of the adapter + the length of the
  928. // name. Add a WCHAR to get a easily printtable string.
  929. // Align everything on a 4 byte boundary
  930. //
  931. ulSize = ALIGN_UP(sizeof(ADAPTER), ULONG) +
  932. ALIGN_UP((pusConfigName->Length + sizeof(WCHAR)), ULONG) +
  933. ALIGN_UP((pusDeviceName->Length + sizeof(WCHAR)), ULONG);
  934. #if DBG
  935. //
  936. // For debug code we also store the adapter name in ANSI
  937. // We use 2 * sizeof(CHAR) because RtlUnicodeToAnsiString needs
  938. // MaximumLength + 1
  939. //
  940. ulSize += pusDeviceName->Length/sizeof(WCHAR) + (2 * sizeof(CHAR));
  941. #endif
  942. pAdapter = RtAllocate(NonPagedPool,
  943. ulSize,
  944. WAN_ADAPTER_TAG);
  945. if(pAdapter is NULL)
  946. {
  947. Trace(ADPT, ERROR,
  948. ("CreateAdapter: Failed to allocate memory\n"));
  949. TraceLeave(ADPT, "CreateAdapter");
  950. return STATUS_INSUFFICIENT_RESOURCES;
  951. }
  952. //
  953. // Clear all the fields out
  954. //
  955. RtlZeroMemory(pAdapter,
  956. ulSize);
  957. //
  958. // The config name buffer starts at the end of the adapter structure.
  959. //
  960. pvBuffer = (PVOID)((ULONG_PTR)pAdapter + sizeof(ADAPTER));
  961. //
  962. // We DWORD align it for better compare/copy
  963. //
  964. pvBuffer = ALIGN_UP_POINTER(pvBuffer, ULONG);
  965. pAdapter->usConfigKey.Length = pusConfigName->Length;
  966. pAdapter->usConfigKey.MaximumLength = pusConfigName->Length;
  967. pAdapter->usConfigKey.Buffer = (PWCHAR)pvBuffer;
  968. RtlCopyMemory(pAdapter->usConfigKey.Buffer,
  969. pusConfigName->Buffer,
  970. pusConfigName->Length);
  971. //
  972. // The device name comes after this
  973. //
  974. pvBuffer = (PVOID)((ULONG_PTR)pvBuffer +
  975. pusConfigName->Length +
  976. sizeof(WCHAR));
  977. pvBuffer = ALIGN_UP_POINTER(pvBuffer, ULONG);
  978. pAdapter->usDeviceNameW.Length = pusDeviceName->Length;
  979. pAdapter->usDeviceNameW.MaximumLength = pusDeviceName->Length;
  980. pAdapter->usDeviceNameW.Buffer = (PWCHAR)pvBuffer;
  981. RtlCopyMemory(pAdapter->usDeviceNameW.Buffer,
  982. pusDeviceName->Buffer,
  983. pusDeviceName->Length);
  984. #if DBG
  985. //
  986. // The debug string comes after the UNICODE device name buffer
  987. //
  988. pvBuffer = (PVOID)((ULONG_PTR)pvBuffer +
  989. pusDeviceName->Length +
  990. sizeof(WCHAR));
  991. pvBuffer = ALIGN_UP_POINTER(pvBuffer, ULONG);
  992. pAdapter->asDeviceNameA.Buffer = (PCHAR)pvBuffer;
  993. //
  994. // Apparently, the unicode to ansi function wants length + 1
  995. //
  996. pAdapter->asDeviceNameA.MaximumLength = pusDeviceName->Length/sizeof(WCHAR) + 1;
  997. RtlUnicodeStringToAnsiString(&pAdapter->asDeviceNameA,
  998. &pAdapter->usDeviceNameW,
  999. FALSE);
  1000. #endif // DBG
  1001. //
  1002. // Structure copy
  1003. //
  1004. pAdapter->Guid = *pAdapterGuid;
  1005. //
  1006. // Must be set to INVALID so that GetEntityList can work
  1007. //
  1008. pAdapter->dwATInstance = INVALID_ENTITY_INSTANCE;
  1009. pAdapter->dwIfInstance = INVALID_ENTITY_INSTANCE;
  1010. //
  1011. // Set the state
  1012. //
  1013. pAdapter->byState = AS_FREE;
  1014. //
  1015. // This hardware index is needed to generate the Unique ID that
  1016. // DHCP uses.
  1017. // NOTE - we dont have an index so all hardware addrs will be the same
  1018. //
  1019. BuildHardwareAddrFromIndex(pAdapter->rgbyHardwareAddr,
  1020. pAdapter->dwAdapterIndex);
  1021. //
  1022. // Initialize the lock for the adapter
  1023. //
  1024. RtInitializeSpinLock(&(pAdapter->rlLock));
  1025. InitializeListHead(&(pAdapter->lePendingPktList));
  1026. InitializeListHead(&(pAdapter->lePendingHdrList));
  1027. InitializeListHead(&(pAdapter->leEventList));
  1028. //
  1029. // Set the Refcount to 1 because it will either lie on some list
  1030. // or be pointed to by g_pServerAdapter
  1031. //
  1032. InitAdapterRefCount(pAdapter);
  1033. if(g_pServerAdapter is NULL)
  1034. {
  1035. PUMODE_INTERFACE pInterface;
  1036. //
  1037. // We use the first adapter adapter as the server adapter
  1038. // We also create the server interface right here
  1039. //
  1040. RtAssert(g_pServerInterface is NULL);
  1041. pInterface = RtAllocate(NonPagedPool,
  1042. sizeof(UMODE_INTERFACE),
  1043. WAN_INTERFACE_TAG);
  1044. if(pInterface is NULL)
  1045. {
  1046. Trace(ADPT, ERROR,
  1047. ("CreateAdapter: Couldnt allocate %d bytes for server i/f\n",
  1048. sizeof(UMODE_INTERFACE)));
  1049. RtFree(pAdapter);
  1050. *ppNewAdapter = NULL;
  1051. return STATUS_INSUFFICIENT_RESOURCES;
  1052. }
  1053. RtlZeroMemory(pInterface,
  1054. sizeof(UMODE_INTERFACE));
  1055. //
  1056. // Get an index from IP
  1057. // If this fails, it sets the value to INVALID_IF_INDEX
  1058. //
  1059. nStatus = WanpGetNewIndex(&(pInterface->dwRsvdAdapterIndex));
  1060. if(nStatus isnot STATUS_SUCCESS)
  1061. {
  1062. Trace(ADPT, ERROR,
  1063. ("CreateAdapter: Couldnt get index for server interface\n"));
  1064. RtFree(pAdapter);
  1065. RtFree(pInterface);
  1066. *ppNewAdapter = NULL;
  1067. return STATUS_INSUFFICIENT_RESOURCES;
  1068. }
  1069. Trace(ADPT, TRACE,
  1070. ("CreateAdapter: Server Index is %d\n",
  1071. pInterface->dwRsvdAdapterIndex));
  1072. RtInitializeSpinLock(&(pInterface->rlLock));
  1073. InitInterfaceRefCount(pInterface);
  1074. pInterface->dwIfIndex = INVALID_IF_INDEX;
  1075. pInterface->dwAdminState = IF_ADMIN_STATUS_UP;
  1076. pInterface->duUsage = DU_CALLIN;
  1077. //
  1078. // Structure copy
  1079. //
  1080. pInterface->Guid = ServerInterfaceGuid;
  1081. EnterWriter(&g_rwlAdapterLock,
  1082. &kiIrql);
  1083. pAdapter->byState = AS_FREE;
  1084. pInterface->dwOperState = IF_OPER_STATUS_DISCONNECTED;
  1085. pInterface->dwLastChange = GetTimeTicks();
  1086. //
  1087. // We dont cross ref the structures here. That is done
  1088. // we have added the server interface to IP.
  1089. //
  1090. g_pServerAdapter = pAdapter;
  1091. g_pServerInterface = pInterface;
  1092. ExitWriter(&g_rwlAdapterLock,
  1093. kiIrql);
  1094. Trace(ADPT, INFO,
  1095. ("CreateAdapter: %S is server adapter\n",
  1096. pAdapter->usDeviceNameW.Buffer));
  1097. }
  1098. else
  1099. {
  1100. EnterWriter(&g_rwlAdapterLock,
  1101. &kiIrql);
  1102. InsertHeadList(&g_leFreeAdapterList,
  1103. &(pAdapter->leAdapterLink));
  1104. g_ulNumFreeAdapters++;
  1105. ExitWriter(&g_rwlAdapterLock,
  1106. kiIrql);
  1107. }
  1108. InterlockedIncrement(&g_ulNumAdapters);
  1109. *ppNewAdapter = pAdapter;
  1110. TraceLeave(ADPT, "CreateAdapter");
  1111. return STATUS_SUCCESS;
  1112. }
  1113. #pragma alloc_text(PAGE, WanNdisUnbindAdapter)
  1114. VOID
  1115. WanNdisUnbindAdapter(
  1116. PNDIS_STATUS pnsRetStatus,
  1117. NDIS_HANDLE nhProtocolContext,
  1118. NDIS_HANDLE nhUnbindContext
  1119. )
  1120. /*++
  1121. Routine Description:
  1122. Called by NDIS to unbind an open adapter. Since we only open one adapter
  1123. we get this only once.
  1124. Locks:
  1125. The function acquires the g_wrBindMutex. This is released in
  1126. WanpFreeBindResourcesAndReleaseLock
  1127. Arguments:
  1128. pnsRetStatus
  1129. nhProtocolContext
  1130. nhUnbindContext
  1131. Return Value:
  1132. NDIS_STATUS_PENDING
  1133. --*/
  1134. {
  1135. NDIS_STATUS nsStatus;
  1136. TraceEnter(ADPT,"NdisUnbindAdapter");
  1137. PAGED_CODE();
  1138. RtAssert(nhProtocolContext is (NDIS_HANDLE)0x0CABB1E5);
  1139. //
  1140. // Get into the critical section
  1141. //
  1142. WanpAcquireResource(&g_wrBindMutex);
  1143. //
  1144. // Mark all the adapters as down so that we dont process anything
  1145. // from IP on them
  1146. //
  1147. //
  1148. // Close the adapter if we havent already done so.
  1149. // This will stop us getting stuff from NDISWAN
  1150. //
  1151. if(g_nhNdiswanBinding isnot NULL)
  1152. {
  1153. g_nhUnbindContext = nhUnbindContext;
  1154. WanpCloseNdisWan(NULL);
  1155. //
  1156. // If we call CloseNdisWan then we DONT release the resource here.
  1157. // It is released by CloseAdapterComplete
  1158. //
  1159. *pnsRetStatus = NDIS_STATUS_PENDING;
  1160. }
  1161. else
  1162. {
  1163. WanpReleaseResource(&g_wrBindMutex);
  1164. *pnsRetStatus = NDIS_STATUS_SUCCESS;
  1165. }
  1166. TraceLeave(ADPT, "NdisUnbindAdapter");
  1167. }
  1168. VOID
  1169. WanpCloseNdisWan(
  1170. PVOID pvContext
  1171. )
  1172. /*++
  1173. Routine Description:
  1174. This function cleans all the resources of an open adapter
  1175. Locks:
  1176. The function is called with the g_wrBindMutex held.
  1177. Arguments:
  1178. None
  1179. Return Value:
  1180. None
  1181. --*/
  1182. {
  1183. NDIS_STATUS nsStatus;
  1184. TraceEnter(ADPT, "WanpCloseNdisWan");
  1185. RtAssert(g_nhNdiswanBinding isnot NULL);
  1186. RtAssert(g_wrBindMutex.lWaitCount >= 1);
  1187. NdisCloseAdapter(&nsStatus,
  1188. g_nhNdiswanBinding);
  1189. g_nhNdiswanBinding = NULL;
  1190. //
  1191. // If our completion routine will not be called, do it here
  1192. //
  1193. if(nsStatus isnot NDIS_STATUS_PENDING)
  1194. {
  1195. WanNdisCloseAdapterComplete((NDIS_HANDLE)0x0CABB1E5,
  1196. nsStatus);
  1197. }
  1198. //
  1199. // We DONT release the resource here. It is released by
  1200. // CloseAdapterComplete
  1201. //
  1202. TraceLeave(ADPT, "WanpCloseNdisWan");
  1203. return;
  1204. }
  1205. #pragma alloc_text(PAGE, WanNdisCloseAdapterComplete)
  1206. VOID
  1207. WanNdisCloseAdapterComplete(
  1208. NDIS_HANDLE nhBindHandle,
  1209. NDIS_STATUS nsStatus
  1210. )
  1211. /*++
  1212. Routine Description:
  1213. Called by NDIS when it is done closing the NDISWAN adapter
  1214. The close adapter can be done either because we failed somewhere (after
  1215. successfully opening our adapter) and in the process of cleanup are
  1216. closing our adapter (in which case the unbind context will be null) or
  1217. because we got an unbind and were cleaning up all adapter related stuff
  1218. Locks:
  1219. Called the g_wrBindMutex held.
  1220. The resource was acquired either in the Unbind handler or was acquired
  1221. before the failure code was called
  1222. Arguments:
  1223. nhBindHandle
  1224. nsStatus
  1225. Return Value:
  1226. None
  1227. --*/
  1228. {
  1229. KIRQL kiIrql;
  1230. NDIS_HANDLE nhUnbind;
  1231. NDIS_HANDLE nhBind;
  1232. NDIS_STATUS tnsStatus, tnsError;
  1233. TraceEnter(ADPT, "NdisCloseAdapterComplete");
  1234. PAGED_CODE();
  1235. nhUnbind = g_nhUnbindContext;
  1236. nhBind = g_nhBindContext;
  1237. tnsStatus = g_nsStatus;
  1238. tnsError = g_nsError;
  1239. RtAssert(g_wrBindMutex.lWaitCount >= 1);
  1240. g_nhUnbindContext = NULL;
  1241. g_nhBindContext = NULL;
  1242. WanpFreeBindResourcesAndReleaseLock();
  1243. if(nhBind isnot NULL)
  1244. {
  1245. RtAssert(nhUnbind == NULL);
  1246. //
  1247. // Tell NDIS that the bind is done but it failed
  1248. //
  1249. NdisCompleteBindAdapter(nhBind,
  1250. tnsStatus,
  1251. tnsError);
  1252. }
  1253. //
  1254. // If this is being triggered from an unbind..
  1255. //
  1256. if(nhUnbind isnot NULL)
  1257. {
  1258. RtAssert(nhBind == NULL);
  1259. NdisCompleteUnbindAdapter(nhUnbind,
  1260. NDIS_STATUS_SUCCESS);
  1261. }
  1262. }
  1263. VOID
  1264. WanpFreeBindResourcesAndReleaseLock(
  1265. VOID
  1266. )
  1267. {
  1268. RtAssert(g_wrBindMutex.lWaitCount >= 1);
  1269. RtFree(g_usNdiswanBindName.Buffer);
  1270. g_usNdiswanBindName.Buffer = NULL;
  1271. RtFree(g_nsSystemSpecific1.Buffer);
  1272. g_nsSystemSpecific1.Buffer = NULL;
  1273. WanpRemoveAllAdapters();
  1274. //
  1275. // There could be turds in the connection table if this was not
  1276. // a clean shutdown
  1277. //
  1278. WanpRemoveAllConnections();
  1279. //
  1280. // Done, set the global event
  1281. //
  1282. KeSetEvent(&g_keCloseEvent,
  1283. 0,
  1284. FALSE);
  1285. //
  1286. // Finally done, set g_lBindRcvd and release the resource
  1287. //
  1288. g_lBindRcvd = 0;
  1289. WanpReleaseResource(&g_wrBindMutex);
  1290. PASSIVE_EXIT();
  1291. }
  1292. PADAPTER
  1293. WanpFindAdapterToMap(
  1294. IN DIAL_USAGE duUsage,
  1295. OUT PKIRQL pkiIrql,
  1296. IN DWORD dwAdapterIndex,
  1297. IN PUNICODE_STRING pusNewIfName
  1298. )
  1299. /*++
  1300. Routine Description:
  1301. Finds a free adapter to map to an interface.
  1302. The adapter, if found is locked and referenced. Its state is set to
  1303. AS_MAPPING and it is put on the mapped list.
  1304. Locks:
  1305. Must be called at PASSIVE
  1306. Acquires g_rwlAdapterLock as WRITER
  1307. If it returns a mapped adapter, then the function returns at DPC and
  1308. the original IRQL is in pkiIrql
  1309. Arguments:
  1310. duUsage The usage for which the adapter needs to be found
  1311. pkiIrql
  1312. dwAdapterIndex
  1313. pusNewIfName
  1314. Return Value:
  1315. Pointer to adapter if successful
  1316. --*/
  1317. {
  1318. PADAPTER pAdapter;
  1319. KIRQL kiIrql;
  1320. PLIST_ENTRY pleNode;
  1321. NTSTATUS nStatus;
  1322. KEVENT keChangeEvent;
  1323. WAN_EVENT_NODE TempEvent;
  1324. //
  1325. // Find a free adapter
  1326. //
  1327. EnterWriter(&g_rwlAdapterLock,
  1328. &kiIrql);
  1329. if(duUsage is DU_CALLIN)
  1330. {
  1331. if(g_pServerAdapter is NULL)
  1332. {
  1333. Trace(CONN, ERROR,
  1334. ("FindAdapterToMap: No server adapter\n"));
  1335. ExitWriter(&g_rwlAdapterLock,
  1336. kiIrql);
  1337. return NULL;
  1338. }
  1339. RtAssert(g_pServerInterface);
  1340. //
  1341. // Lock out the adapter
  1342. //
  1343. RtAcquireSpinLockAtDpcLevel(&(g_pServerAdapter->rlLock));
  1344. //
  1345. // Reference it because we are going to return it. Also we need the
  1346. // reference when we let go of the lock if we need to wait
  1347. //
  1348. ReferenceAdapter(g_pServerAdapter);
  1349. //
  1350. // See if the adapter has been added to IP
  1351. // rasiphlp has to call us to map the server adapter before
  1352. // doing a line up
  1353. //
  1354. if(g_pServerAdapter->byState isnot AS_MAPPED)
  1355. {
  1356. RtAssert(g_pServerAdapter->byState is AS_ADDING);
  1357. if(g_pServerAdapter->byState is AS_ADDING)
  1358. {
  1359. KeInitializeEvent(&(TempEvent.keEvent),
  1360. SynchronizationEvent,
  1361. FALSE);
  1362. InsertTailList(&(g_pServerAdapter->leEventList),
  1363. &(TempEvent.leEventLink));
  1364. //
  1365. // Let go of the lock and wait on the event
  1366. //
  1367. RtReleaseSpinLockFromDpcLevel(&(g_pServerAdapter->rlLock));
  1368. ExitWriter(&g_rwlAdapterLock,
  1369. kiIrql);
  1370. nStatus = KeWaitForSingleObject(&(TempEvent.keEvent),
  1371. Executive,
  1372. KernelMode,
  1373. FALSE,
  1374. NULL);
  1375. RtAssert(nStatus is STATUS_SUCCESS);
  1376. EnterWriter(&g_rwlAdapterLock,
  1377. &kiIrql);
  1378. RtAcquireSpinLockAtDpcLevel(&(g_pServerAdapter->rlLock));
  1379. RemoveEntryList(&(TempEvent.leEventLink));
  1380. }
  1381. }
  1382. if(g_pServerAdapter->byState isnot AS_MAPPED)
  1383. {
  1384. PADAPTER pTempAdapter;
  1385. //
  1386. // Couldnt add the adapter because of some reason,
  1387. //
  1388. pTempAdapter = g_pServerAdapter;
  1389. Trace(CONN, ERROR,
  1390. ("FindAdapterToMap: Unable to get mapped server adapter\n"));
  1391. RtReleaseSpinLockFromDpcLevel(&(g_pServerAdapter->rlLock));
  1392. ExitWriter(&g_rwlAdapterLock,
  1393. kiIrql);
  1394. DereferenceAdapter(pTempAdapter);
  1395. return NULL;
  1396. }
  1397. RtAssert(g_pServerAdapter->byState is AS_MAPPED);
  1398. ExitWriterFromDpcLevel(&g_rwlAdapterLock);
  1399. *pkiIrql = kiIrql;
  1400. return g_pServerAdapter;
  1401. }
  1402. //
  1403. // Non dial in case. First try and see if there is an adapter with the
  1404. // index we want already added to IP
  1405. //
  1406. pAdapter = NULL;
  1407. for(pleNode = g_leAddedAdapterList.Flink;
  1408. pleNode isnot &g_leAddedAdapterList;
  1409. pleNode = pleNode->Flink)
  1410. {
  1411. PADAPTER pTempAdapter;
  1412. pTempAdapter = CONTAINING_RECORD(pleNode,
  1413. ADAPTER,
  1414. leAdapterLink);
  1415. RtAssert(pTempAdapter->byState is AS_ADDED);
  1416. if(pTempAdapter->dwAdapterIndex is dwAdapterIndex)
  1417. {
  1418. RemoveEntryList(&(pTempAdapter->leAdapterLink));
  1419. g_ulNumAddedAdapters--;
  1420. pAdapter = pTempAdapter;
  1421. break;
  1422. }
  1423. }
  1424. if(pAdapter isnot NULL)
  1425. {
  1426. //
  1427. // So we found an added adapter (it has been removed from the
  1428. // added adapter list). Add it to the mapped list
  1429. //
  1430. InsertTailList(&g_leMappedAdapterList,
  1431. &(pAdapter->leAdapterLink));
  1432. g_ulNumMappedAdapters++;
  1433. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  1434. ExitWriterFromDpcLevel(&g_rwlAdapterLock);
  1435. ReferenceAdapter(pAdapter);
  1436. pAdapter->byState = AS_MAPPING;
  1437. *pkiIrql = kiIrql;
  1438. #if DBG
  1439. Trace(CONN, INFO,
  1440. ("FindAdapterToMap: Found %s already added\n",
  1441. pAdapter->asDeviceNameA.Buffer));
  1442. #endif
  1443. return pAdapter;
  1444. }
  1445. //
  1446. // Didnt find an added adapter
  1447. // See if the adapter is on the change list. We want to wait for this
  1448. // because IP doesnt like to have to interfaces with the same index, even
  1449. // if one is in the process of being removed
  1450. //
  1451. for(pleNode = g_leChangeAdapterList.Flink;
  1452. pleNode isnot &g_leChangeAdapterList;
  1453. pleNode = pleNode->Flink)
  1454. {
  1455. PADAPTER pTempAdapter;
  1456. pTempAdapter = CONTAINING_RECORD(pleNode,
  1457. ADAPTER,
  1458. leAdapterLink);
  1459. if(pTempAdapter->dwAdapterIndex is dwAdapterIndex)
  1460. {
  1461. //
  1462. // Wait for the change to complete
  1463. //
  1464. KeInitializeEvent(&(TempEvent.keEvent),
  1465. SynchronizationEvent,
  1466. FALSE);
  1467. RtAcquireSpinLockAtDpcLevel(&(pTempAdapter->rlLock));
  1468. InsertTailList(&(pTempAdapter->leEventList),
  1469. &(TempEvent.leEventLink));
  1470. //
  1471. // Reference the adapter, let go of the lock and wait on the event
  1472. //
  1473. ReferenceAdapter(pTempAdapter);
  1474. RtReleaseSpinLockFromDpcLevel(&(pTempAdapter->rlLock));
  1475. ExitWriter(&g_rwlAdapterLock,
  1476. kiIrql);
  1477. nStatus = KeWaitForSingleObject(&(TempEvent.keEvent),
  1478. Executive,
  1479. KernelMode,
  1480. FALSE,
  1481. NULL);
  1482. RtAssert(nStatus is STATUS_SUCCESS);
  1483. EnterWriter(&g_rwlAdapterLock,
  1484. &kiIrql);
  1485. RtAcquireSpinLockAtDpcLevel(&(pTempAdapter->rlLock));
  1486. RemoveEntryList(&(TempEvent.leEventLink));
  1487. RtReleaseSpinLockFromDpcLevel(&(pTempAdapter->rlLock));
  1488. DereferenceAdapter(pTempAdapter);
  1489. break;
  1490. }
  1491. }
  1492. if(!IsListEmpty(&g_leFreeAdapterList))
  1493. {
  1494. pleNode = RemoveHeadList(&g_leFreeAdapterList);
  1495. pAdapter = CONTAINING_RECORD(pleNode,
  1496. ADAPTER,
  1497. leAdapterLink);
  1498. g_ulNumFreeAdapters--;
  1499. #if DBG
  1500. Trace(CONN, INFO,
  1501. ("FindAdapterToMap: Found free adapter %s\n",
  1502. pAdapter->asDeviceNameA.Buffer));
  1503. #endif // DBG
  1504. }
  1505. else
  1506. {
  1507. //
  1508. // Couldnt find an adapter. That is bad
  1509. // TODO - if the added adapter list is not empty, we could call
  1510. // RemoveSomeAddedAdapter... at this point
  1511. //
  1512. Trace(ADPT, ERROR,
  1513. ("FindAdapterToMap: Couldnt find free adapter\n"));
  1514. ExitWriter(&g_rwlAdapterLock,
  1515. kiIrql);
  1516. return NULL;
  1517. }
  1518. //
  1519. // Lock and refcount the adapter.
  1520. //
  1521. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  1522. ReferenceAdapter(pAdapter);
  1523. //
  1524. // The adapter better not be mapped
  1525. //
  1526. RtAssert(pAdapter->pInterface is NULL);
  1527. RtAssert(pAdapter->byState is AS_FREE);
  1528. //
  1529. // Set the state to ADDING
  1530. //
  1531. pAdapter->byState = AS_ADDING;
  1532. //
  1533. // Since we are changing the state, no one else should be also
  1534. // changing the state
  1535. //
  1536. RtAssert(pAdapter->pkeChangeEvent is NULL);
  1537. KeInitializeEvent(&keChangeEvent,
  1538. SynchronizationEvent,
  1539. FALSE);
  1540. pAdapter->pkeChangeEvent = &keChangeEvent;
  1541. //
  1542. // Insert into the change list
  1543. //
  1544. InsertTailList(&g_leChangeAdapterList,
  1545. &(pAdapter->leAdapterLink));
  1546. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  1547. ExitWriter(&g_rwlAdapterLock,
  1548. kiIrql);
  1549. //
  1550. // Add the adapter to IP
  1551. //
  1552. nStatus = WanpAddAdapterToIp(pAdapter,
  1553. FALSE,
  1554. dwAdapterIndex,
  1555. pusNewIfName,
  1556. IF_TYPE_PPP,
  1557. IF_ACCESS_POINTTOPOINT,
  1558. IF_CONNECTION_DEMAND);
  1559. if(nStatus isnot STATUS_SUCCESS)
  1560. {
  1561. Trace(ADPT, ERROR,
  1562. ("FindAdapterToMap: %x adding %x to IP\n",
  1563. nStatus, pAdapter));
  1564. EnterWriter(&g_rwlAdapterLock,
  1565. &kiIrql);
  1566. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  1567. #if DBG
  1568. RtAssert(IsEntryOnList(&g_leChangeAdapterList,
  1569. &(pAdapter->leAdapterLink)));
  1570. #endif
  1571. pAdapter->pkeChangeEvent = NULL;
  1572. RemoveEntryList(&(pAdapter->leAdapterLink));
  1573. pAdapter->byState = AS_FREE;
  1574. InsertTailList(&g_leFreeAdapterList,
  1575. &(pAdapter->leAdapterLink));
  1576. g_ulNumFreeAdapters++;
  1577. //
  1578. // If anyone is waiting on a state change, notify them
  1579. //
  1580. for(pleNode = pAdapter->leEventList.Flink;
  1581. pleNode isnot &(pAdapter->leEventList);
  1582. pleNode = pleNode->Flink)
  1583. {
  1584. PWAN_EVENT_NODE pTempEvent;
  1585. pTempEvent = CONTAINING_RECORD(pleNode,
  1586. WAN_EVENT_NODE,
  1587. leEventLink);
  1588. KeSetEvent(&(pTempEvent->keEvent),
  1589. 0,
  1590. FALSE);
  1591. }
  1592. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  1593. ExitWriter(&g_rwlAdapterLock,
  1594. kiIrql);
  1595. DereferenceAdapter(pAdapter);
  1596. return NULL;
  1597. }
  1598. //
  1599. // Wait till the OpenAdapter is called
  1600. //
  1601. nStatus = KeWaitForSingleObject(&keChangeEvent,
  1602. Executive,
  1603. KernelMode,
  1604. FALSE,
  1605. NULL);
  1606. RtAssert(nStatus is STATUS_SUCCESS);
  1607. Trace(ADPT, TRACE,
  1608. ("FindAdapterToMap: IPAddInterface succeeded for adapter %w\n",
  1609. pAdapter->usDeviceNameW.Buffer));
  1610. //
  1611. // Lock the adapter, insert into the added list
  1612. //
  1613. EnterWriter(&g_rwlAdapterLock,
  1614. &kiIrql);
  1615. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  1616. #if DBG
  1617. RtAssert(IsEntryOnList(&g_leChangeAdapterList,
  1618. &(pAdapter->leAdapterLink)));
  1619. #endif
  1620. RemoveEntryList(&(pAdapter->leAdapterLink));
  1621. pAdapter->pkeChangeEvent = NULL;
  1622. InsertHeadList(&g_leMappedAdapterList,
  1623. &(pAdapter->leAdapterLink));
  1624. g_ulNumMappedAdapters++;
  1625. //
  1626. // If anyone is waiting on a state change, notify them
  1627. //
  1628. for(pleNode = pAdapter->leEventList.Flink;
  1629. pleNode isnot &(pAdapter->leEventList);
  1630. pleNode = pleNode->Flink)
  1631. {
  1632. PWAN_EVENT_NODE pTempEvent;
  1633. pTempEvent = CONTAINING_RECORD(pleNode,
  1634. WAN_EVENT_NODE,
  1635. leEventLink);
  1636. KeSetEvent(&(pTempEvent->keEvent),
  1637. 0,
  1638. FALSE);
  1639. }
  1640. ExitWriterFromDpcLevel(&g_rwlAdapterLock);
  1641. *pkiIrql = kiIrql;
  1642. return pAdapter;
  1643. }
  1644. NTSTATUS
  1645. WanpAddAdapterToIp(
  1646. IN PADAPTER pAdapter,
  1647. IN BOOLEAN bServerAdapter,
  1648. IN DWORD dwAdapterIndex, OPTIONAL
  1649. IN PUNICODE_STRING pusNewIfName, OPTIONAL
  1650. IN DWORD dwMediaType,
  1651. IN BYTE byAccessType,
  1652. IN BYTE byConnectionType
  1653. )
  1654. /*++
  1655. Routine Description:
  1656. This routine adds the interface to IP
  1657. Locks:
  1658. MUST BE CALLED AT PASSIVE, but acquires a spinlock so cant be paged out
  1659. Arguments:
  1660. pAdapter The adapter to add
  1661. bServerAdapter Set to TRUE if this is a server adapter
  1662. dwAdapterIndex
  1663. pusNewIfName
  1664. Return Value:
  1665. STATUS_SUCCESS
  1666. --*/
  1667. {
  1668. LLIPBindInfo BindInfo;
  1669. IP_STATUS IPStatus;
  1670. UNICODE_STRING usName;
  1671. NTSTATUS nStatus;
  1672. KIRQL kiIrql;
  1673. PASSIVE_ENTRY();
  1674. TraceEnter(ADPT, "AddAdapterToIp");
  1675. RtlZeroMemory(&BindInfo, sizeof(LLIPBindInfo));
  1676. BindInfo.lip_context = pAdapter;
  1677. BindInfo.lip_mss = WANARP_DEFAULT_MTU;
  1678. BindInfo.lip_speed = WANARP_DEFAULT_SPEED;
  1679. BindInfo.lip_txspace = sizeof(ETH_HEADER);
  1680. BindInfo.lip_transmit = WanIpTransmit;
  1681. BindInfo.lip_transfer = WanIpTransferData;
  1682. BindInfo.lip_returnPkt = WanIpReturnPacket;
  1683. BindInfo.lip_close = WanIpCloseAdapter;
  1684. BindInfo.lip_addaddr = WanIpAddAddress;
  1685. BindInfo.lip_deladdr = WanIpDeleteAddress;
  1686. BindInfo.lip_invalidate = WanIpInvalidateRce;
  1687. BindInfo.lip_open = WanIpOpenAdapter;
  1688. BindInfo.lip_qinfo = WanIpQueryInfo;
  1689. BindInfo.lip_setinfo = WanIpSetInfo;
  1690. BindInfo.lip_getelist = WanIpGetEntityList;
  1691. BindInfo.lip_flags = LIP_COPY_FLAG;
  1692. if(bServerAdapter)
  1693. {
  1694. BindInfo.lip_flags |= (LIP_P2MP_FLAG | LIP_NOLINKBCST_FLAG);
  1695. BindInfo.lip_closelink = WanIpCloseLink;
  1696. }
  1697. else
  1698. {
  1699. BindInfo.lip_flags |= (LIP_P2P_FLAG | LIP_NOIPADDR_FLAG);
  1700. }
  1701. BindInfo.lip_addrlen = ARP_802_ADDR_LENGTH;
  1702. BindInfo.lip_addr = pAdapter->rgbyHardwareAddr;
  1703. BindInfo.lip_OffloadFlags = 0;
  1704. BindInfo.lip_dowakeupptrn = NULL;
  1705. BindInfo.lip_pnpcomplete = NULL;
  1706. BindInfo.lip_arpflushate = NULL;
  1707. BindInfo.lip_arpflushallate = NULL;
  1708. BindInfo.lip_setndisrequest = WanIpSetRequest;
  1709. RtlInitUnicodeString(&usName,
  1710. pAdapter->usConfigKey.Buffer);
  1711. #if DBG
  1712. //
  1713. // Only set while adding or deleting the interface, which is serialized
  1714. //
  1715. pAdapter->dwRequestedIndex = dwAdapterIndex;
  1716. #endif
  1717. IPStatus = g_pfnIpAddInterface(&(pAdapter->usDeviceNameW),
  1718. pusNewIfName,
  1719. &(pAdapter->usConfigKey),
  1720. NULL,
  1721. pAdapter,
  1722. WanIpDynamicRegister,
  1723. &BindInfo,
  1724. dwAdapterIndex,
  1725. dwMediaType,
  1726. byAccessType,
  1727. byConnectionType);
  1728. if(IPStatus isnot IP_SUCCESS)
  1729. {
  1730. Trace(ADPT, ERROR,
  1731. ("AddAdapterToIp: IPAddInterface failed for adapter %w\n",
  1732. pAdapter->usDeviceNameW.Buffer));
  1733. TraceLeave(ADPT, "AddAdapterToIp");
  1734. return STATUS_UNSUCCESSFUL;
  1735. }
  1736. TraceLeave(ADPT, "AddAdapterToIp");
  1737. return STATUS_SUCCESS;
  1738. }
  1739. VOID
  1740. WanIpOpenAdapter(
  1741. IN PVOID pvContext
  1742. )
  1743. /*++
  1744. Routine Description:
  1745. Called by IP when the adapter from its IPAddInterface() call
  1746. Locks:
  1747. Arguments:
  1748. pvContext Pointer to the ADAPTER structure
  1749. Return Value:
  1750. None
  1751. --*/
  1752. {
  1753. PADAPTER pAdapter;
  1754. KIRQL kiIrql;
  1755. PLIST_ENTRY pleNode;
  1756. TraceEnter(ADPT, "WanOpenAdapter");
  1757. pAdapter = (PADAPTER)pvContext;
  1758. RtAcquireSpinLock(&(pAdapter->rlLock),
  1759. &kiIrql);
  1760. //
  1761. // Set the state to added
  1762. //
  1763. pAdapter->byState = AS_ADDED;
  1764. //
  1765. // One reference for the fact that we added the adapter to IP
  1766. //
  1767. ReferenceAdapter(pAdapter);
  1768. //
  1769. // Wake up the thread that caused this
  1770. //
  1771. RtAssert(pAdapter->pkeChangeEvent);
  1772. KeSetEvent(pAdapter->pkeChangeEvent,
  1773. 0,
  1774. FALSE);
  1775. RtReleaseSpinLock(&(pAdapter->rlLock),
  1776. kiIrql);
  1777. TraceLeave(ADPT, "WanOpenAdapter");
  1778. }
  1779. VOID
  1780. WanpUnmapAdapter(
  1781. PADAPTER pAdapter
  1782. )
  1783. /*++
  1784. Routine Description:
  1785. This function moves an adapter from the mapped list and puts it on
  1786. the free list
  1787. Locks:
  1788. Called with no locks held, but not necessarily at PASSIVE.
  1789. The adapter and adapter list locks are acquired
  1790. Arguments:
  1791. pAdapter
  1792. Return Value:
  1793. None
  1794. --*/
  1795. {
  1796. KIRQL kiIrql;
  1797. #if DBG
  1798. //
  1799. // Make sure the adapter is on the mapped list
  1800. //
  1801. RtAssert(IsEntryOnList(&g_leMappedAdapterList,
  1802. &(pAdapter->leAdapterLink)));
  1803. #endif
  1804. EnterWriter(&g_rwlAdapterLock,
  1805. &kiIrql);
  1806. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  1807. RemoveEntryList(&(pAdapter->leAdapterLink));
  1808. g_ulNumMappedAdapters--;
  1809. InsertHeadList(&g_leAddedAdapterList,
  1810. &(pAdapter->leAdapterLink));
  1811. g_ulNumAddedAdapters++;
  1812. pAdapter->byState = AS_ADDED;
  1813. pAdapter->pInterface = NULL;
  1814. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  1815. //
  1816. // Queue a work item if there is none queued, and we are not
  1817. // shutting down
  1818. //
  1819. RtAcquireSpinLockAtDpcLevel(&g_rlStateLock);
  1820. if((g_bRemovalInProgress isnot TRUE) and
  1821. (g_dwDriverState is DRIVER_STARTED))
  1822. {
  1823. g_bRemovalInProgress = TRUE;
  1824. ExInitializeWorkItem(&g_wqiWorkItem,
  1825. WanpRemoveSomeAddedAdaptersFromIp,
  1826. (PVOID)FALSE);
  1827. ExQueueWorkItem(&g_wqiWorkItem,
  1828. DelayedWorkQueue);
  1829. }
  1830. RtReleaseSpinLockFromDpcLevel(&g_rlStateLock);
  1831. ExitWriter(&g_rwlAdapterLock,
  1832. kiIrql);
  1833. return;
  1834. }
  1835. VOID
  1836. WanpRemoveSomeAddedAdaptersFromIp(
  1837. PVOID pvContext
  1838. )
  1839. /*++
  1840. Routine Description:
  1841. We queue this function to a work item to delete adapter(s) from IP when
  1842. the connection is torn down. Unlike the next function, this
  1843. (i) only removes added (but unmapped) adapters and
  1844. (ii) removes the adapters one at a time.
  1845. This allows another connection to move an adapter from the added list
  1846. to the free list while we are deleting another adapter from IP
  1847. Locks:
  1848. Must be called at passive
  1849. Acquires the adapter list lock as WRITER and the lock for each adapter
  1850. Arguments:
  1851. pvContext
  1852. Return Value:
  1853. None
  1854. --*/
  1855. {
  1856. PADAPTER pAdapter;
  1857. KIRQL kiIrql;
  1858. PLIST_ENTRY pleNode;
  1859. NTSTATUS nStatus;
  1860. KEVENT keChangeEvent;
  1861. PASSIVE_ENTRY();
  1862. UNREFERENCED_PARAMETER(pvContext);
  1863. KeInitializeEvent(&keChangeEvent,
  1864. SynchronizationEvent,
  1865. FALSE);
  1866. EnterWriter(&g_rwlAdapterLock,
  1867. &kiIrql);
  1868. while(!IsListEmpty(&g_leAddedAdapterList))
  1869. {
  1870. pleNode = RemoveHeadList(&g_leAddedAdapterList);
  1871. g_ulNumAddedAdapters--;
  1872. pAdapter = CONTAINING_RECORD(pleNode,
  1873. ADAPTER,
  1874. leAdapterLink);
  1875. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  1876. pAdapter->byState = AS_REMOVING;
  1877. //
  1878. // Since we are changing the state, no one else should be also
  1879. // changing the state
  1880. //
  1881. RtAssert(pAdapter->pkeChangeEvent is NULL);
  1882. pAdapter->pkeChangeEvent = &keChangeEvent;
  1883. //
  1884. // Insert it into the change list
  1885. //
  1886. InsertHeadList(&g_leChangeAdapterList,
  1887. &(pAdapter->leAdapterLink));
  1888. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  1889. ExitWriter(&g_rwlAdapterLock,
  1890. kiIrql);
  1891. //
  1892. // Delete from IP but dont clear the index
  1893. //
  1894. g_pfnIpDeleteInterface(pAdapter->pvIpContext,
  1895. FALSE);
  1896. //
  1897. // Wait till the CloseAdapter completes
  1898. //
  1899. nStatus = KeWaitForSingleObject(&keChangeEvent,
  1900. Executive,
  1901. KernelMode,
  1902. FALSE,
  1903. NULL);
  1904. RtAssert(nStatus is STATUS_SUCCESS);
  1905. Trace(ADPT, INFO,
  1906. ("RemoveSomeAddedAdaptersFromIp: Removed %S from Ip\n",
  1907. pAdapter->usDeviceNameW.Buffer));
  1908. //
  1909. // Remove from the change list and put on the free list
  1910. //
  1911. EnterWriter(&g_rwlAdapterLock,
  1912. &kiIrql);
  1913. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  1914. #if DBG
  1915. RtAssert(IsEntryOnList(&g_leChangeAdapterList,
  1916. &(pAdapter->leAdapterLink)));
  1917. #endif
  1918. RemoveEntryList(&(pAdapter->leAdapterLink));
  1919. pAdapter->byState = AS_FREE;
  1920. pAdapter->pkeChangeEvent = NULL;
  1921. InsertHeadList(&g_leFreeAdapterList,
  1922. &(pAdapter->leAdapterLink));
  1923. g_ulNumFreeAdapters++;
  1924. //
  1925. // If anyone is waiting on a state change, notify them
  1926. //
  1927. for(pleNode = pAdapter->leEventList.Flink;
  1928. pleNode isnot &(pAdapter->leEventList);
  1929. pleNode = pleNode->Flink)
  1930. {
  1931. PWAN_EVENT_NODE pTempEvent;
  1932. pTempEvent = CONTAINING_RECORD(pleNode,
  1933. WAN_EVENT_NODE,
  1934. leEventLink);
  1935. KeSetEvent(&(pTempEvent->keEvent),
  1936. 0,
  1937. FALSE);
  1938. }
  1939. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  1940. }
  1941. //
  1942. // We are done with the APC
  1943. //
  1944. g_bRemovalInProgress = FALSE;
  1945. ExitWriter(&g_rwlAdapterLock,
  1946. kiIrql);
  1947. return;
  1948. }
  1949. VOID
  1950. WanpRemoveAllAdaptersFromIp(
  1951. VOID
  1952. )
  1953. /*++
  1954. Routine Description:
  1955. This is a cleanup function called to remove all adapters (added and
  1956. mapped) from IP.
  1957. Locks:
  1958. Acquired the g_rwlAdapterLock as WRITER
  1959. Also acquire each adapter's lock when changing state
  1960. Arguments:
  1961. None
  1962. Return Value:
  1963. None
  1964. --*/
  1965. {
  1966. PADAPTER pAdapter;
  1967. KIRQL kiIrql;
  1968. LIST_ENTRY leTempHead, *pleNode;
  1969. NTSTATUS nStatus;
  1970. KEVENT keChangeEvent;
  1971. WAN_EVENT_NODE TempEvent;
  1972. PASSIVE_ENTRY();
  1973. KeInitializeEvent(&keChangeEvent,
  1974. SynchronizationEvent,
  1975. FALSE);
  1976. KeInitializeEvent(&(TempEvent.keEvent),
  1977. SynchronizationEvent,
  1978. FALSE);
  1979. InitializeListHead(&leTempHead);
  1980. EnterWriter(&g_rwlAdapterLock,
  1981. &kiIrql);
  1982. //
  1983. // First wait on any adapter in the change list to get out
  1984. // of the change state. Once that is done it is either added to ip
  1985. // or not, and we can deal with those two cases. This is to handle
  1986. // the case where we get an unbind in the middle of a status indication
  1987. //
  1988. while(!IsListEmpty(&g_leChangeAdapterList))
  1989. {
  1990. pleNode = g_leChangeAdapterList.Flink;
  1991. pAdapter = CONTAINING_RECORD(pleNode,
  1992. ADAPTER,
  1993. leAdapterLink);
  1994. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  1995. InsertTailList(&(pAdapter->leEventList),
  1996. &(TempEvent.leEventLink));
  1997. ReferenceAdapter(pAdapter);
  1998. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  1999. ExitWriter(&g_rwlAdapterLock,
  2000. kiIrql);
  2001. nStatus = KeWaitForSingleObject(&(TempEvent.keEvent),
  2002. Executive,
  2003. KernelMode,
  2004. FALSE,
  2005. NULL);
  2006. RtAssert(nStatus is STATUS_SUCCESS);
  2007. EnterWriter(&g_rwlAdapterLock,
  2008. &kiIrql);
  2009. #if DBG
  2010. RtAssert(!IsEntryOnList(&g_leChangeAdapterList,
  2011. &(pAdapter->leAdapterLink)));
  2012. #endif
  2013. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  2014. RemoveEntryList(&(TempEvent.leEventLink));
  2015. DereferenceAdapter(pAdapter);
  2016. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  2017. }
  2018. //
  2019. // Set the state of all the adapters to removing...
  2020. //
  2021. while(!IsListEmpty(&g_leMappedAdapterList))
  2022. {
  2023. pleNode = RemoveHeadList(&g_leMappedAdapterList);
  2024. g_ulNumMappedAdapters--;
  2025. pAdapter = CONTAINING_RECORD(pleNode,
  2026. ADAPTER,
  2027. leAdapterLink);
  2028. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  2029. pAdapter->byState = AS_REMOVING;
  2030. InsertHeadList(&leTempHead,
  2031. pleNode);
  2032. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  2033. }
  2034. RtAssert(IsListEmpty(&g_leMappedAdapterList));
  2035. while(!IsListEmpty(&g_leAddedAdapterList))
  2036. {
  2037. pleNode = RemoveHeadList(&g_leAddedAdapterList);
  2038. g_ulNumAddedAdapters--;
  2039. pAdapter = CONTAINING_RECORD(pleNode,
  2040. ADAPTER,
  2041. leAdapterLink);
  2042. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  2043. pAdapter->byState = AS_REMOVING;
  2044. InsertHeadList(&leTempHead,
  2045. pleNode);
  2046. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  2047. }
  2048. RtAssert(IsListEmpty(&g_leAddedAdapterList));
  2049. ExitWriter(&g_rwlAdapterLock,
  2050. kiIrql);
  2051. //
  2052. // No go through the list of adapters to remove from IP
  2053. //
  2054. while(!IsListEmpty(&leTempHead))
  2055. {
  2056. pleNode = RemoveHeadList(&leTempHead);
  2057. pAdapter = CONTAINING_RECORD(pleNode,
  2058. ADAPTER,
  2059. leAdapterLink);
  2060. EnterWriter(&g_rwlAdapterLock,
  2061. &kiIrql);
  2062. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  2063. //
  2064. // Since we are changing the state, no one else should be also
  2065. // changing the state
  2066. //
  2067. RtAssert(pAdapter->pkeChangeEvent is NULL);
  2068. pAdapter->pkeChangeEvent = &keChangeEvent;
  2069. //
  2070. // Insert it into the change list
  2071. //
  2072. InsertHeadList(&g_leChangeAdapterList,
  2073. &(pAdapter->leAdapterLink));
  2074. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  2075. ExitWriter(&g_rwlAdapterLock,
  2076. kiIrql);
  2077. //
  2078. // Delete from IP but dont clear the index
  2079. //
  2080. g_pfnIpDeleteInterface(pAdapter->pvIpContext,
  2081. FALSE);
  2082. //
  2083. // Wait till the CloseAdapter completes
  2084. //
  2085. nStatus = KeWaitForSingleObject(&keChangeEvent,
  2086. Executive,
  2087. KernelMode,
  2088. FALSE,
  2089. NULL);
  2090. RtAssert(nStatus is STATUS_SUCCESS);
  2091. Trace(ADPT, INFO,
  2092. ("RemoveAllAdaptersFromIp: Removed %S from Ip\n",
  2093. pAdapter->usDeviceNameW.Buffer));
  2094. //
  2095. // Remove from the change list and put on the free list
  2096. //
  2097. EnterWriter(&g_rwlAdapterLock,
  2098. &kiIrql);
  2099. #if DBG
  2100. RtAssert(IsEntryOnList(&g_leChangeAdapterList,
  2101. &(pAdapter->leAdapterLink)));
  2102. #endif
  2103. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  2104. RemoveEntryList(&(pAdapter->leAdapterLink));
  2105. pAdapter->byState = AS_FREE;
  2106. pAdapter->pkeChangeEvent = NULL;
  2107. InsertHeadList(&g_leFreeAdapterList,
  2108. &(pAdapter->leAdapterLink));
  2109. g_ulNumFreeAdapters++;
  2110. //
  2111. // If anyone is waiting on a state change, notify them
  2112. //
  2113. for(pleNode = pAdapter->leEventList.Flink;
  2114. pleNode isnot &(pAdapter->leEventList);
  2115. pleNode = pleNode->Flink)
  2116. {
  2117. PWAN_EVENT_NODE pTempEvent;
  2118. pTempEvent = CONTAINING_RECORD(pleNode,
  2119. WAN_EVENT_NODE,
  2120. leEventLink);
  2121. KeSetEvent(&(pTempEvent->keEvent),
  2122. 0,
  2123. FALSE);
  2124. }
  2125. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  2126. ExitWriter(&g_rwlAdapterLock,
  2127. kiIrql);
  2128. }
  2129. //
  2130. // The write is atomic so we dont need to
  2131. // acquire a lock
  2132. //
  2133. g_bRemovalInProgress = FALSE;
  2134. return;
  2135. }
  2136. VOID
  2137. WanIpCloseAdapter(
  2138. IN PVOID pvContext
  2139. )
  2140. /*++
  2141. Routine Description:
  2142. Called by IP when it wants to close an adapter. Currently this is done
  2143. from CloseNets() and IPDelInterface().
  2144. Locks:
  2145. Acquires the adapter lock
  2146. Arguments:
  2147. pvContext Pointer to the ADAPTER
  2148. Return Value:
  2149. None
  2150. --*/
  2151. {
  2152. PADAPTER pAdapter;
  2153. KIRQL kiIrql;
  2154. PLIST_ENTRY pleNode;
  2155. TraceEnter(ADPT, "IpCloseAdapter");
  2156. pAdapter = (PADAPTER)pvContext;
  2157. RtAcquireSpinLock(&(pAdapter->rlLock),
  2158. &kiIrql);
  2159. pAdapter->pvIpContext = NULL;
  2160. //
  2161. // Wake up the thread that caused this
  2162. //
  2163. RtAssert(pAdapter->pkeChangeEvent);
  2164. KeSetEvent(pAdapter->pkeChangeEvent,
  2165. 0,
  2166. FALSE);
  2167. RtReleaseSpinLock(&(pAdapter->rlLock),
  2168. kiIrql);
  2169. DereferenceAdapter(pAdapter);
  2170. TraceLeave(ADPT, "IpCloseAdapter");
  2171. }
  2172. VOID
  2173. WanpRemoveAllAdapters(
  2174. VOID
  2175. )
  2176. /*++
  2177. Routine Description:
  2178. Locks:
  2179. Arguments:
  2180. Return Value:
  2181. --*/
  2182. {
  2183. LIST_ENTRY leTempHead, *pleNode;
  2184. KIRQL kiIrql;
  2185. NTSTATUS nStatus;
  2186. TraceEnter(ADPT, "RemoveAllAdapters");
  2187. //
  2188. // We can have mapped adapters.
  2189. //
  2190. //RtAssert(IsListEmpty(&g_leMappedAdapterList));
  2191. //
  2192. // Just call RemoveAllAdaptersFromIp()
  2193. //
  2194. WanpRemoveAllAdaptersFromIp();
  2195. //
  2196. // At this point the movement from one list to another is frozen
  2197. // because we dont accept LinkUp's from Ndiswan
  2198. //
  2199. RtAssert(IsListEmpty(&g_leAddedAdapterList));
  2200. //RtAssert(IsListEmpty(&g_leMappedAdapterList));
  2201. //RtAssert(IsListEmpty(&g_leChangeAdapterList));
  2202. EnterWriter(&g_rwlAdapterLock,
  2203. &kiIrql);
  2204. //
  2205. // First clean out the free adapters
  2206. //
  2207. while(!IsListEmpty(&g_leFreeAdapterList))
  2208. {
  2209. PLIST_ENTRY pleNode;
  2210. PADAPTER pAdapter;
  2211. pleNode = RemoveHeadList(&g_leFreeAdapterList);
  2212. g_ulNumFreeAdapters--;
  2213. pAdapter = CONTAINING_RECORD(pleNode,
  2214. ADAPTER,
  2215. leAdapterLink);
  2216. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  2217. RtAssert(pAdapter->byState is AS_FREE);
  2218. pAdapter->byState = 0xFF;
  2219. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  2220. DereferenceAdapter(pAdapter);
  2221. }
  2222. //
  2223. // At the end of this, also remove the server adapter
  2224. //
  2225. if(g_pServerAdapter)
  2226. {
  2227. PADAPTER pAdapter;
  2228. PUMODE_INTERFACE pInterface;
  2229. BOOLEAN bCrossRefed;
  2230. RtAcquireSpinLockAtDpcLevel(&(g_pServerAdapter->rlLock));
  2231. RtAcquireSpinLockAtDpcLevel(&(g_pServerInterface->rlLock));
  2232. pAdapter = g_pServerAdapter;
  2233. pInterface = g_pServerInterface;
  2234. if(g_pServerAdapter->byState is AS_MAPPED)
  2235. {
  2236. RtAssert(g_pServerAdapter->pInterface is g_pServerInterface);
  2237. RtAssert(g_pServerInterface->pAdapter is g_pServerAdapter);
  2238. bCrossRefed = TRUE;
  2239. }
  2240. else
  2241. {
  2242. RtAssert(g_pServerAdapter->pInterface is NULL);
  2243. RtAssert(g_pServerInterface->pAdapter is NULL);
  2244. RtAssert(g_pServerAdapter->byState is AS_FREE);
  2245. bCrossRefed = FALSE;
  2246. }
  2247. //
  2248. // Remove the global pointers
  2249. //
  2250. g_pServerInterface = NULL;
  2251. g_pServerAdapter = NULL;
  2252. //
  2253. // Remove the mapping from interface
  2254. //
  2255. pInterface->pAdapter = NULL;
  2256. pAdapter->pInterface = NULL;
  2257. pAdapter->byState = AS_REMOVING;
  2258. RtReleaseSpinLockFromDpcLevel(&(pInterface->rlLock));
  2259. if(bCrossRefed)
  2260. {
  2261. //
  2262. // Deref because the cross mapping is removed
  2263. //
  2264. DereferenceAdapter(pAdapter);
  2265. DereferenceInterface(pInterface);
  2266. }
  2267. if(pAdapter->pvIpContext)
  2268. {
  2269. KEVENT keChangeEvent;
  2270. KeInitializeEvent(&keChangeEvent,
  2271. SynchronizationEvent,
  2272. FALSE);
  2273. //
  2274. // Since we are changing the state, no one else should be also
  2275. // changing the state
  2276. //
  2277. RtAssert(pAdapter->pkeChangeEvent is NULL);
  2278. pAdapter->pkeChangeEvent = &keChangeEvent;
  2279. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  2280. ExitWriter(&g_rwlAdapterLock,
  2281. kiIrql);
  2282. //
  2283. // Delete from IP, but dont clear the index
  2284. //
  2285. g_pfnIpDeleteInterface(pAdapter->pvIpContext,
  2286. FALSE);
  2287. nStatus = KeWaitForSingleObject(&keChangeEvent,
  2288. Executive,
  2289. KernelMode,
  2290. FALSE,
  2291. NULL);
  2292. RtAssert(nStatus is STATUS_SUCCESS);
  2293. Trace(ADPT, INFO,
  2294. ("RemoveAllAdapters: Removed %S (server adapter) from Ip\n",
  2295. pAdapter->usDeviceNameW.Buffer));
  2296. EnterWriter(&g_rwlAdapterLock,
  2297. &kiIrql);
  2298. RtAcquireSpinLockAtDpcLevel(&(pAdapter->rlLock));
  2299. pAdapter->byState = AS_FREE;
  2300. pAdapter->pkeChangeEvent = NULL;
  2301. //
  2302. // If anyone is waiting on a state change, notify them
  2303. //
  2304. for(pleNode = pAdapter->leEventList.Flink;
  2305. pleNode isnot &(pAdapter->leEventList);
  2306. pleNode = pleNode->Flink)
  2307. {
  2308. PWAN_EVENT_NODE pTempEvent;
  2309. pTempEvent = CONTAINING_RECORD(pleNode,
  2310. WAN_EVENT_NODE,
  2311. leEventLink);
  2312. KeSetEvent(&(pTempEvent->keEvent),
  2313. 0,
  2314. FALSE);
  2315. }
  2316. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  2317. } else {
  2318. RtReleaseSpinLockFromDpcLevel(&(pAdapter->rlLock));
  2319. }
  2320. //
  2321. // Deref because the global pointers are null
  2322. //
  2323. DereferenceAdapter(pAdapter);
  2324. DereferenceInterface(pInterface);
  2325. }
  2326. ExitWriter(&g_rwlAdapterLock,
  2327. kiIrql);
  2328. TraceLeave(ADPT, "RemoveAllAdapters");
  2329. }
  2330. INT
  2331. WanIpDynamicRegister(
  2332. IN PNDIS_STRING InterfaceName,
  2333. IN PVOID pvIpInterfaceContext,
  2334. IN struct _IP_HANDLERS * IpHandlers,
  2335. IN struct LLIPBindInfo * ARPBindInfo,
  2336. IN UINT uiInterfaceNumber
  2337. )
  2338. {
  2339. PADAPTER pAdapter;
  2340. KIRQL irql;
  2341. TraceEnter(ADPT, "IpDynamicRegister");
  2342. pAdapter = (PADAPTER)(ARPBindInfo->lip_context);
  2343. RtAcquireSpinLock(&(pAdapter->rlLock),
  2344. &irql);
  2345. #if DBG
  2346. Trace(ADPT, INFO,
  2347. ("IpDynamicRegister: IP called out to dynamically register %s\n",
  2348. pAdapter->asDeviceNameA.Buffer));
  2349. #endif
  2350. pAdapter->pvIpContext = pvIpInterfaceContext;
  2351. pAdapter->dwAdapterIndex = uiInterfaceNumber;
  2352. #if DBG
  2353. RtAssert(pAdapter->dwAdapterIndex is pAdapter->dwRequestedIndex);
  2354. #endif
  2355. if(g_pfnIpRcv is NULL)
  2356. {
  2357. g_pfnIpRcv = IpHandlers->IpRcvHandler;
  2358. g_pfnIpRcvComplete = IpHandlers->IpRcvCompleteHandler;
  2359. g_pfnIpSendComplete = IpHandlers->IpTxCompleteHandler;
  2360. g_pfnIpTDComplete = IpHandlers->IpTransferCompleteHandler;
  2361. g_pfnIpStatus = IpHandlers->IpStatusHandler;
  2362. g_pfnIpRcvPkt = IpHandlers->IpRcvPktHandler;
  2363. g_pfnIpPnp = IpHandlers->IpPnPHandler;
  2364. }
  2365. RtReleaseSpinLock(&(pAdapter->rlLock),
  2366. irql);
  2367. TraceLeave(ADPT, "IpDynamicRegister");
  2368. return TRUE;
  2369. }
  2370. NDIS_STATUS
  2371. WanpDoNdisRequest(
  2372. IN NDIS_REQUEST_TYPE RequestType,
  2373. IN NDIS_OID Oid,
  2374. IN PVOID pvInfo,
  2375. IN UINT uiInBufferLen,
  2376. IN PWANARP_NDIS_REQUEST_CONTEXT pRequestContext,
  2377. IN PFNWANARP_REQUEST_COMPLETION_HANDLER pfnCompletionHandler OPTIONAL
  2378. )
  2379. /*++
  2380. Routine Description:
  2381. Wrapper for the NdisRequest call. We create a request context and submit
  2382. the call to NDIS. If it returns synchronously, we fake asynchronous
  2383. behaviour by call the completion routine.
  2384. Locks:
  2385. None. The ndiswan binding must be valid for the duration of the call
  2386. Arguments:
  2387. RequestType Type of NDIS request
  2388. Oid Ndis OID to set or get
  2389. pvInfo Opaque OID specific info
  2390. pRequestContext A context for this request
  2391. pfnCompletionHandler Completion handler for this request
  2392. Return Value:
  2393. STATUS_INVALID_PARAMETER
  2394. NDIS_STATUS_RESOURCES
  2395. NDIS_STATUS_PENDING
  2396. other error
  2397. --*/
  2398. {
  2399. PNDIS_REQUEST pRequest;
  2400. NDIS_STATUS nsStatus;
  2401. if((RequestType isnot NdisRequestSetInformation) and
  2402. (RequestType isnot NdisRequestQueryInformation))
  2403. {
  2404. return STATUS_INVALID_PARAMETER;
  2405. }
  2406. pRequestContext->pfnCompletionRoutine = pfnCompletionHandler;
  2407. pRequest = &(pRequestContext->NdisRequest);
  2408. pRequest->RequestType = RequestType;
  2409. if(RequestType is NdisRequestSetInformation)
  2410. {
  2411. pRequest->DATA.SET_INFORMATION.Oid = Oid;
  2412. pRequest->DATA.SET_INFORMATION.InformationBuffer = pvInfo;
  2413. pRequest->DATA.SET_INFORMATION.InformationBufferLength = uiInBufferLen;
  2414. }
  2415. else
  2416. {
  2417. pRequest->DATA.QUERY_INFORMATION.Oid = Oid;
  2418. pRequest->DATA.QUERY_INFORMATION.InformationBuffer = pvInfo;
  2419. pRequest->DATA.QUERY_INFORMATION.InformationBufferLength = uiInBufferLen;
  2420. }
  2421. //
  2422. // Submit the request.
  2423. //
  2424. NdisRequest(&nsStatus,
  2425. g_nhNdiswanBinding,
  2426. pRequest);
  2427. if(nsStatus isnot NDIS_STATUS_PENDING)
  2428. {
  2429. //
  2430. // If it finished synchronously, call the handler
  2431. //
  2432. if(pfnCompletionHandler)
  2433. {
  2434. (pfnCompletionHandler)(g_nhNdiswanBinding,
  2435. pRequestContext,
  2436. nsStatus);
  2437. }
  2438. if(nsStatus is NDIS_STATUS_SUCCESS)
  2439. {
  2440. //
  2441. // Always make this look asynchronous
  2442. //
  2443. nsStatus = NDIS_STATUS_PENDING;
  2444. }
  2445. }
  2446. return nsStatus;
  2447. }
  2448. VOID
  2449. WanNdisRequestComplete(
  2450. IN NDIS_HANDLE nhHandle,
  2451. IN PNDIS_REQUEST pRequest,
  2452. IN NDIS_STATUS nsStatus
  2453. )
  2454. /*++
  2455. Routine Description:
  2456. Handler called by NDIS when it is done processing our request
  2457. Locks:
  2458. None
  2459. Arguments:
  2460. nhHandle NdisHandle of the adapter to which the request was submitted
  2461. pRequest The original request
  2462. nsStatus The status returned by the adapter
  2463. Return Value:
  2464. None
  2465. --*/
  2466. {
  2467. PWANARP_NDIS_REQUEST_CONTEXT pRequestContext;
  2468. //
  2469. // Get a pointer to the context
  2470. //
  2471. pRequestContext = CONTAINING_RECORD(pRequest,
  2472. WANARP_NDIS_REQUEST_CONTEXT,
  2473. NdisRequest);
  2474. if(pRequestContext->pfnCompletionRoutine is NULL)
  2475. {
  2476. //
  2477. // No more handlers to call, we are done
  2478. //
  2479. RtFree(pRequestContext);
  2480. return;
  2481. }
  2482. //
  2483. // If the request is OID_GEN_TRANSPORT_HEADER_OFFSET, ignore the error
  2484. //
  2485. RtAssert(pRequest is &(pRequestContext->NdisRequest));
  2486. if((pRequest->RequestType is NdisRequestSetInformation) and
  2487. (pRequest->DATA.SET_INFORMATION.Oid is OID_GEN_TRANSPORT_HEADER_OFFSET))
  2488. {
  2489. nsStatus = NDIS_STATUS_SUCCESS;
  2490. }
  2491. //
  2492. // Call the request complete handler
  2493. //
  2494. (pRequestContext->pfnCompletionRoutine)(nhHandle,
  2495. pRequestContext,
  2496. nsStatus);
  2497. }
  2498. PUMODE_INTERFACE
  2499. WanpFindInterfaceGivenIndex(
  2500. DWORD dwIfIndex
  2501. )
  2502. {
  2503. PLIST_ENTRY pleNode;
  2504. PUMODE_INTERFACE pIf;
  2505. for(pleNode = g_leIfList.Flink;
  2506. pleNode isnot &g_leIfList;
  2507. pleNode = pleNode->Flink)
  2508. {
  2509. pIf = CONTAINING_RECORD(pleNode,
  2510. UMODE_INTERFACE,
  2511. leIfLink);
  2512. if(pIf->dwIfIndex is dwIfIndex)
  2513. {
  2514. RtAcquireSpinLockAtDpcLevel(&(pIf->rlLock));
  2515. ReferenceInterface(pIf);
  2516. return pIf;
  2517. }
  2518. }
  2519. return NULL;
  2520. }
  2521. VOID
  2522. WanpDeleteAdapter(
  2523. IN PADAPTER pAdapter
  2524. )
  2525. {
  2526. #if DBG
  2527. Trace(ADPT, TRACE,
  2528. ("DeleteAdapter: Deleting %x %s\n",
  2529. pAdapter, pAdapter->asDeviceNameA.Buffer));
  2530. #else
  2531. Trace(ADPT, TRACE,
  2532. ("DeleteAdapter: Deleting %x\n",
  2533. pAdapter));
  2534. #endif
  2535. InterlockedDecrement(&g_ulNumAdapters);
  2536. RtFree(pAdapter);
  2537. }
  2538. NDIS_STATUS
  2539. WanNdisIpPnPEventHandler(
  2540. IN PNET_PNP_EVENT pNetPnPEvent
  2541. )
  2542. {
  2543. PWANARP_RECONFIGURE_INFO pInfo;
  2544. NTSTATUS nStatus = NDIS_STATUS_FAILURE;
  2545. RtAssert(pNetPnPEvent->NetEvent is NetEventReconfigure);
  2546. pInfo = (PWANARP_RECONFIGURE_INFO) pNetPnPEvent->Buffer;
  2547. switch (pInfo->wrcOperation)
  2548. {
  2549. case WRC_TCP_WINDOW_SIZE_UPDATE:
  2550. {
  2551. PLIST_ENTRY pleNode;
  2552. KIRQL kirql;
  2553. PADAPTER pAdapter;
  2554. RtAssert(pInfo->ulNumInterfaces is 1);
  2555. if(pInfo->ulNumInterfaces isnot 1)
  2556. {
  2557. break;
  2558. }
  2559. EnterReader(&g_rwlAdapterLock, &kirql);
  2560. for(pleNode = g_leMappedAdapterList.Flink;
  2561. pleNode != &g_leMappedAdapterList;
  2562. pleNode = pleNode->Flink)
  2563. {
  2564. pAdapter = CONTAINING_RECORD(pleNode, ADAPTER, leAdapterLink);
  2565. if(IsEqualGUID(&(pAdapter->Guid),
  2566. &pInfo->rgInterfaces[0]))
  2567. {
  2568. break;
  2569. }
  2570. }
  2571. if(pleNode is &g_leMappedAdapterList)
  2572. {
  2573. ExitReader(&g_rwlAdapterLock, kirql);
  2574. break;
  2575. }
  2576. if( (pAdapter->byState is AS_MAPPED)
  2577. && (pAdapter->pInterface)
  2578. && (pAdapter->pInterface->duUsage is DU_CALLOUT))
  2579. {
  2580. NET_PNP_EVENT pnpEvent;
  2581. IP_PNP_RECONFIG_REQUEST Request;
  2582. RtlZeroMemory(&pnpEvent, sizeof(pnpEvent));
  2583. RtlZeroMemory(&Request, sizeof(Request));
  2584. Request.version = IP_PNP_RECONFIG_VERSION;
  2585. Request.Flags = IP_PNP_FLAG_INTERFACE_TCP_PARAMETER_UPDATE;
  2586. pnpEvent.NetEvent = NetEventReconfigure;
  2587. pnpEvent.Buffer = &Request;
  2588. pnpEvent.BufferLength = sizeof(Request);
  2589. ReferenceAdapter(pAdapter);
  2590. ExitReader(&g_rwlAdapterLock, kirql);
  2591. nStatus = g_pfnIpPnp(pAdapter->pvIpContext,
  2592. &pnpEvent);
  2593. DereferenceAdapter(pAdapter);
  2594. }
  2595. else
  2596. {
  2597. ExitReader(&g_rwlAdapterLock, kirql);
  2598. }
  2599. break;
  2600. }
  2601. default:
  2602. {
  2603. RtAssert(FALSE);
  2604. nStatus = NDIS_STATUS_NOT_RECOGNIZED;
  2605. break;
  2606. }
  2607. }
  2608. return nStatus;
  2609. }
  2610. //
  2611. // Misc ndis interface functions
  2612. //
  2613. NDIS_STATUS
  2614. WanNdisPnPEvent(
  2615. IN NDIS_HANDLE nhProtocolBindingContext,
  2616. IN PNET_PNP_EVENT pNetPnPEvent
  2617. )
  2618. {
  2619. ULONG ulNumGuids, i;
  2620. NTSTATUS nStatus, nRetStatus;
  2621. PWANARP_RECONFIGURE_INFO pInfo;
  2622. TraceEnter(ADPT, "NdisPnPEvent");
  2623. if(nhProtocolBindingContext isnot (NDIS_HANDLE)0x0CABB1E5)
  2624. {
  2625. return NDIS_STATUS_NOT_RECOGNIZED;
  2626. }
  2627. if(pNetPnPEvent->NetEvent isnot NetEventReconfigure)
  2628. {
  2629. return NDIS_STATUS_SUCCESS;
  2630. }
  2631. pInfo = (PWANARP_RECONFIGURE_INFO)(pNetPnPEvent->Buffer);
  2632. if(pNetPnPEvent->BufferLength < FIELD_OFFSET(WANARP_RECONFIGURE_INFO, rgInterfaces))
  2633. {
  2634. return NDIS_STATUS_BUFFER_TOO_SHORT;
  2635. }
  2636. pInfo = (PWANARP_RECONFIGURE_INFO)(pNetPnPEvent->Buffer);
  2637. if(pInfo->wrcOperation isnot WRC_ADD_INTERFACES)
  2638. {
  2639. nStatus = WanNdisIpPnPEventHandler(pNetPnPEvent);
  2640. return nStatus;
  2641. }
  2642. //
  2643. // Make sure the length and matches with whats in the info
  2644. //
  2645. ulNumGuids = pNetPnPEvent->BufferLength -
  2646. FIELD_OFFSET(WANARP_RECONFIGURE_INFO, rgInterfaces);
  2647. ulNumGuids /= sizeof(GUID);
  2648. if(ulNumGuids < pInfo->ulNumInterfaces)
  2649. {
  2650. return STATUS_INVALID_PARAMETER;
  2651. }
  2652. //
  2653. // Now go through each guid, and if it isnt present, add it
  2654. // If we get a list of only duplicates, return SUCCESS (334575)
  2655. //
  2656. nRetStatus = STATUS_SUCCESS;
  2657. for(i = 0; i < pInfo->ulNumInterfaces; i++)
  2658. {
  2659. WCHAR rgwcDeviceBuffer[GUID_STR_LEN + 7 + 2];
  2660. WCHAR rgwcConfigBuffer[GUID_STR_LEN + 29 + 2];
  2661. PADAPTER pNewAdapter;
  2662. UNICODE_STRING usDevice;
  2663. UNICODE_STRING usConfig;
  2664. if(IsBindingPresent(&(pInfo->rgInterfaces[i])))
  2665. {
  2666. continue;
  2667. }
  2668. RtlZeroMemory(rgwcDeviceBuffer,
  2669. sizeof(rgwcDeviceBuffer));
  2670. RtlZeroMemory(rgwcConfigBuffer,
  2671. sizeof(rgwcConfigBuffer));
  2672. //
  2673. // Make sure no problems with people changing the string
  2674. //
  2675. RtAssert(((wcslen(TCPIP_IF_PREFIX) + 1 + GUID_STR_LEN) * sizeof(WCHAR)) < sizeof(rgwcDeviceBuffer));
  2676. RtAssert(((wcslen(TCPIP_REG_PREFIX) + 1 + GUID_STR_LEN) * sizeof(WCHAR)) < sizeof(rgwcConfigBuffer));
  2677. //
  2678. // Copy over the \Device part
  2679. //
  2680. RtlCopyMemory(rgwcDeviceBuffer,
  2681. TCPIP_IF_PREFIX,
  2682. wcslen(TCPIP_IF_PREFIX) * sizeof(WCHAR));
  2683. //
  2684. // Tack on a '\'
  2685. //
  2686. rgwcDeviceBuffer[wcslen(TCPIP_IF_PREFIX)] = L'\\';
  2687. //
  2688. // Convert the guid to a string. Just pass the buffer starting
  2689. // after the '\' we just catted. The conversion function returns
  2690. // an upcase string - so thats good.
  2691. //
  2692. ConvertGuidToString(&(pInfo->rgInterfaces[i]),
  2693. &(rgwcDeviceBuffer[wcslen(TCPIP_IF_PREFIX) + 1]));
  2694. //
  2695. // Create the config
  2696. //
  2697. RtlCopyMemory(rgwcConfigBuffer,
  2698. TCPIP_REG_PREFIX,
  2699. wcslen(TCPIP_REG_PREFIX) * sizeof(WCHAR));
  2700. //
  2701. // Put the device guid at the end
  2702. //
  2703. ConvertGuidToString(&(pInfo->rgInterfaces[i]),
  2704. &(rgwcConfigBuffer[wcslen(TCPIP_REG_PREFIX)]));
  2705. //
  2706. // Set up the strings
  2707. //
  2708. usDevice.Length = wcslen(rgwcDeviceBuffer) * sizeof(WCHAR);
  2709. usDevice.MaximumLength = usDevice.Length;
  2710. usDevice.Buffer = rgwcDeviceBuffer;
  2711. usConfig.Length = wcslen(rgwcConfigBuffer) * sizeof(WCHAR);
  2712. usConfig.MaximumLength = usConfig.Length;
  2713. usConfig.Buffer = rgwcConfigBuffer;
  2714. //
  2715. // Create an adapter with this name and config
  2716. //
  2717. pNewAdapter = NULL;
  2718. Trace(ADPT, INFO,
  2719. ("NdisPnPEvent: Calling create adapter for %S %S\n",
  2720. usConfig.Buffer,
  2721. usDevice.Buffer));
  2722. nStatus = WanpCreateAdapter(&(pInfo->rgInterfaces[i]),
  2723. &usConfig,
  2724. &usDevice,
  2725. &pNewAdapter);
  2726. if(nStatus isnot STATUS_SUCCESS)
  2727. {
  2728. Trace(ADPT, ERROR,
  2729. ("NdisPnPEvent: Err %x creating adapter for %S (%S)\n",
  2730. nStatus,
  2731. usConfig.Buffer,
  2732. usDevice.Buffer));
  2733. }
  2734. else
  2735. {
  2736. //
  2737. // If even one succeeds, we return success
  2738. //
  2739. nRetStatus = STATUS_SUCCESS;
  2740. }
  2741. }
  2742. return nRetStatus;
  2743. }
  2744. VOID
  2745. WanNdisResetComplete(
  2746. NDIS_HANDLE Handle,
  2747. NDIS_STATUS Status
  2748. )
  2749. {
  2750. // We dont do anything here.
  2751. }
  2752. BOOLEAN
  2753. IsBindingPresent(
  2754. IN GUID *pGuid
  2755. )
  2756. /*++
  2757. Routine Description:
  2758. Code to catch duplicate bind notifications
  2759. Locks:
  2760. Must be called with the AdapterList lock held
  2761. Arguments:
  2762. pGuid Guid of the adapter
  2763. Return Value:
  2764. NO_ERROR
  2765. --*/
  2766. {
  2767. BOOLEAN bFound;
  2768. PADAPTER pAdapter;
  2769. PLIST_ENTRY pleNode;
  2770. for(pleNode = g_leAddedAdapterList.Flink;
  2771. pleNode != &g_leAddedAdapterList;
  2772. pleNode = pleNode->Flink)
  2773. {
  2774. pAdapter = CONTAINING_RECORD(pleNode, ADAPTER, leAdapterLink);
  2775. if(IsEqualGUID(&(pAdapter->Guid),
  2776. pGuid))
  2777. {
  2778. return TRUE;
  2779. }
  2780. }
  2781. for(pleNode = g_leMappedAdapterList.Flink;
  2782. pleNode != &g_leMappedAdapterList;
  2783. pleNode = pleNode->Flink)
  2784. {
  2785. pAdapter = CONTAINING_RECORD(pleNode, ADAPTER, leAdapterLink);
  2786. if(IsEqualGUID(&(pAdapter->Guid),
  2787. pGuid))
  2788. {
  2789. return TRUE;
  2790. }
  2791. }
  2792. for(pleNode = g_leFreeAdapterList.Flink;
  2793. pleNode != &g_leFreeAdapterList;
  2794. pleNode = pleNode->Flink)
  2795. {
  2796. pAdapter = CONTAINING_RECORD(pleNode, ADAPTER, leAdapterLink);
  2797. if(IsEqualGUID(&(pAdapter->Guid),
  2798. pGuid))
  2799. {
  2800. return TRUE;
  2801. }
  2802. }
  2803. for(pleNode = g_leChangeAdapterList.Flink;
  2804. pleNode != &g_leChangeAdapterList;
  2805. pleNode = pleNode->Flink)
  2806. {
  2807. pAdapter = CONTAINING_RECORD(pleNode, ADAPTER, leAdapterLink);
  2808. if(IsEqualGUID(&(pAdapter->Guid),
  2809. pGuid))
  2810. {
  2811. return TRUE;
  2812. }
  2813. }
  2814. if(g_pServerAdapter)
  2815. {
  2816. if(IsEqualGUID(&(g_pServerAdapter->Guid),
  2817. pGuid))
  2818. {
  2819. return TRUE;
  2820. }
  2821. }
  2822. return FALSE;
  2823. }