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.

2204 lines
60 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. protocol.c
  5. Abstract:
  6. NDIS wrapper functions used by protocol modules
  7. Author:
  8. Adam Barr (adamba) 11-Jul-1990
  9. Environment:
  10. Kernel mode, FSD
  11. Revision History:
  12. 26-Feb-1991 JohnsonA Added Debugging Code
  13. 10-Jul-1991 JohnsonA Implement revised Ndis Specs
  14. 01-Jun-1995 JameelH Re-organization/optimization
  15. --*/
  16. #define GLOBALS
  17. #include <precomp.h>
  18. #pragma hdrstop
  19. #include <stdarg.h>
  20. //
  21. // Define the module number for debug code.
  22. //
  23. #define MODULE_NUMBER MODULE_PROTOCOL
  24. //
  25. // Requests used by protocol modules
  26. //
  27. //
  28. VOID
  29. NdisRegisterProtocol(
  30. OUT PNDIS_STATUS pStatus,
  31. OUT PNDIS_HANDLE NdisProtocolHandle,
  32. IN PNDIS_PROTOCOL_CHARACTERISTICS ProtocolCharacteristics,
  33. IN UINT CharacteristicsLength
  34. )
  35. /*++
  36. Routine Description:
  37. Register an NDIS protocol.
  38. Arguments:
  39. Status - Returns the final status.
  40. NdisProtocolHandle - Returns a handle referring to this protocol.
  41. ProtocolCharacteritics - The NDIS_PROTOCOL_CHARACTERISTICS table.
  42. CharacteristicsLength - The length of ProtocolCharacteristics.
  43. Return Value:
  44. None.
  45. Comments:
  46. Called at passive level
  47. --*/
  48. {
  49. PNDIS_PROTOCOL_BLOCK Protocol;
  50. NDIS_STATUS Status;
  51. KIRQL OldIrql;
  52. USHORT size;
  53. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  54. ("==>NdisRegisterProtocol\n"));
  55. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  56. (" Protocol: "));
  57. DBGPRINT_UNICODE(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  58. &ProtocolCharacteristics->Name);
  59. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  60. ("\n"));
  61. PnPReferencePackage();
  62. ProtocolReferencePackage();
  63. IF_DBG(DBG_COMP_PROTOCOL, DBG_LEVEL_ERR)
  64. {
  65. BOOLEAN f = FALSE;
  66. if (DbgIsNull(ProtocolCharacteristics->OpenAdapterCompleteHandler))
  67. {
  68. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  69. ("RegisterProtocol: OpenAdapterCompleteHandler Null\n"));
  70. f = TRUE;
  71. }
  72. if (DbgIsNull(ProtocolCharacteristics->CloseAdapterCompleteHandler))
  73. {
  74. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  75. ("RegisterProtocol: CloseAdapterCompleteHandler Null\n"));
  76. f = TRUE;
  77. }
  78. if (DbgIsNull(ProtocolCharacteristics->SendCompleteHandler))
  79. {
  80. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  81. ("RegisterProtocol: SendCompleteHandler Null\n"));
  82. f = TRUE;
  83. }
  84. if (DbgIsNull(ProtocolCharacteristics->TransferDataCompleteHandler))
  85. {
  86. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  87. ("RegisterProtocol: TransferDataCompleteHandler Null\n"));
  88. f = TRUE;
  89. }
  90. if (DbgIsNull(ProtocolCharacteristics->ResetCompleteHandler))
  91. {
  92. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  93. ("RegisterProtocol: ResetCompleteHandler Null\n"));
  94. f = TRUE;
  95. }
  96. if (DbgIsNull(ProtocolCharacteristics->RequestCompleteHandler))
  97. {
  98. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  99. ("RegisterProtocol: RequestCompleteHandler Null\n"));
  100. f = TRUE;
  101. }
  102. if (DbgIsNull(ProtocolCharacteristics->ReceiveHandler))
  103. {
  104. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  105. ("RegisterProtocol: ReceiveHandler Null\n"));
  106. f = TRUE;
  107. }
  108. if (DbgIsNull(ProtocolCharacteristics->ReceiveCompleteHandler))
  109. {
  110. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  111. ("RegisterProtocol: ReceiveCompleteHandler Null\n"));
  112. f = TRUE;
  113. }
  114. if (DbgIsNull(ProtocolCharacteristics->StatusHandler))
  115. {
  116. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  117. ("RegisterProtocol: StatusHandler Null\n"));
  118. f = TRUE;
  119. }
  120. if (DbgIsNull(ProtocolCharacteristics->StatusCompleteHandler))
  121. {
  122. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  123. ("RegisterProtocol: StatusCompleteHandler Null\n"));
  124. f = TRUE;
  125. }
  126. if (f)
  127. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  128. }
  129. do
  130. {
  131. //
  132. // Check version numbers and CharacteristicsLength.
  133. //
  134. size = 0; // Used to indicate bad version below
  135. if (ProtocolCharacteristics->MajorNdisVersion < 4)
  136. {
  137. DbgPrint("Ndis: NdisRegisterProtocol Ndis 3.0 protocols are not supported.\n");
  138. }
  139. else if ((ProtocolCharacteristics->MajorNdisVersion == 4) &&
  140. (ProtocolCharacteristics->MinorNdisVersion == 0))
  141. {
  142. size = sizeof(NDIS40_PROTOCOL_CHARACTERISTICS);
  143. }
  144. else if ((ProtocolCharacteristics->MajorNdisVersion == 5) &&
  145. (ProtocolCharacteristics->MinorNdisVersion <= 1))
  146. {
  147. size = sizeof(NDIS50_PROTOCOL_CHARACTERISTICS);
  148. }
  149. //
  150. // Check that this is an NDIS 4.0/5.0/5.1 protocol.
  151. //
  152. if (size == 0)
  153. {
  154. Status = NDIS_STATUS_BAD_VERSION;
  155. break;
  156. }
  157. if ((ProtocolCharacteristics->BindAdapterHandler == NULL) ||
  158. (ProtocolCharacteristics->UnbindAdapterHandler == NULL))
  159. {
  160. DbgPrint("Ndis: NdisRegisterProtocol protocol does not have Bind/UnbindAdapterHandler and it is not supported.\n");
  161. Status = NDIS_STATUS_BAD_VERSION;
  162. break;
  163. }
  164. //
  165. // Check that CharacteristicsLength is enough.
  166. //
  167. if (CharacteristicsLength < size)
  168. {
  169. Status = NDIS_STATUS_BAD_CHARACTERISTICS;
  170. break;
  171. }
  172. //
  173. // Allocate memory for the NDIS protocol block.
  174. //
  175. Protocol = (PNDIS_PROTOCOL_BLOCK)ALLOC_FROM_POOL(sizeof(NDIS_PROTOCOL_BLOCK) +
  176. ProtocolCharacteristics->Name.Length + sizeof(WCHAR),
  177. NDIS_TAG_PROT_BLK);
  178. if (Protocol == (PNDIS_PROTOCOL_BLOCK)NULL)
  179. {
  180. Status = NDIS_STATUS_RESOURCES;
  181. break;
  182. }
  183. ZeroMemory(Protocol, sizeof(NDIS_PROTOCOL_BLOCK) + sizeof(WCHAR) + ProtocolCharacteristics->Name.Length);
  184. INITIALIZE_MUTEX(&Protocol->Mutex);
  185. //
  186. // Copy over the characteristics table.
  187. //
  188. CopyMemory(&Protocol->ProtocolCharacteristics,
  189. ProtocolCharacteristics,
  190. size);
  191. // Upcase the name in the characteristics table before saving it.
  192. Protocol->ProtocolCharacteristics.Name.Buffer = (PWCHAR)((PUCHAR)Protocol +
  193. sizeof(NDIS_PROTOCOL_BLOCK));
  194. Protocol->ProtocolCharacteristics.Name.Length = ProtocolCharacteristics->Name.Length;
  195. Protocol->ProtocolCharacteristics.Name.MaximumLength = ProtocolCharacteristics->Name.Length;
  196. RtlUpcaseUnicodeString(&Protocol->ProtocolCharacteristics.Name,
  197. &ProtocolCharacteristics->Name,
  198. FALSE);
  199. //
  200. // No opens for this protocol yet.
  201. //
  202. Protocol->OpenQueue = (PNDIS_OPEN_BLOCK)NULL;
  203. ndisInitializeRef(&Protocol->Ref);
  204. *NdisProtocolHandle = (NDIS_HANDLE)Protocol;
  205. Status = NDIS_STATUS_SUCCESS;
  206. //
  207. // Link the protocol into the list.
  208. //
  209. ACQUIRE_SPIN_LOCK(&ndisProtocolListLock, &OldIrql);
  210. Protocol->NextProtocol = ndisProtocolList;
  211. ndisProtocolList = Protocol;
  212. RELEASE_SPIN_LOCK(&ndisProtocolListLock, OldIrql);
  213. REF_NDIS_DRIVER_OBJECT();
  214. if (ndisReferenceProtocol(Protocol))
  215. {
  216. //
  217. // Start a worker thread to notify the protocol of any existing drivers
  218. //
  219. INITIALIZE_WORK_ITEM(&Protocol->WorkItem, ndisCheckProtocolBindings, Protocol);
  220. QUEUE_WORK_ITEM(&Protocol->WorkItem, CriticalWorkQueue);
  221. }
  222. } while (FALSE);
  223. *pStatus = Status;
  224. if (Status != NDIS_STATUS_SUCCESS)
  225. {
  226. ProtocolDereferencePackage();
  227. }
  228. PnPDereferencePackage();
  229. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  230. ("<==NdisRegisterProtocol\n"));
  231. }
  232. VOID
  233. NdisDeregisterProtocol(
  234. OUT PNDIS_STATUS Status,
  235. IN NDIS_HANDLE NdisProtocolHandle
  236. )
  237. /*++
  238. Routine Description:
  239. Deregisters an NDIS protocol.
  240. Arguments:
  241. Status - Returns the final status.
  242. NdisProtocolHandle - The handle returned by NdisRegisterProtocol.
  243. Return Value:
  244. None.
  245. Note:
  246. This will kill all the opens for this protocol.
  247. Called at PASSIVE level
  248. --*/
  249. {
  250. PNDIS_PROTOCOL_BLOCK Protocol = (PNDIS_PROTOCOL_BLOCK)NdisProtocolHandle;
  251. KEVENT DeregEvent;
  252. PNDIS_PROTOCOL_BLOCK tProtocol;
  253. KIRQL OldIrql;
  254. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  255. ("==>NdisDeregisterProtocol\n"));
  256. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  257. (" Protocol: "));
  258. DBGPRINT_UNICODE(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  259. &Protocol->ProtocolCharacteristics.Name);
  260. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  261. ("\n"));
  262. IF_DBG(DBG_COMP_PROTOCOL, DBG_LEVEL_ERR)
  263. {
  264. if (DbgIsNull(NdisProtocolHandle))
  265. {
  266. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  267. ("DeregisterProtocol: Null Handle\n"));
  268. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  269. }
  270. if (!DbgIsNonPaged(NdisProtocolHandle))
  271. {
  272. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  273. ("DeregisterProtocol: Handle not in NonPaged Memory\n"));
  274. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  275. }
  276. }
  277. //
  278. // first to check if the protcol exist. some buggy drivers deregister
  279. // even though registeration did not go through
  280. //
  281. PnPReferencePackage();
  282. ACQUIRE_SPIN_LOCK(&ndisProtocolListLock, &OldIrql);
  283. for (tProtocol = ndisProtocolList;
  284. tProtocol != NULL;
  285. tProtocol = tProtocol->NextProtocol)
  286. {
  287. if (tProtocol == Protocol)
  288. {
  289. break;
  290. }
  291. }
  292. RELEASE_SPIN_LOCK(&ndisProtocolListLock, OldIrql);
  293. PnPDereferencePackage();
  294. ASSERT(tProtocol == Protocol);
  295. if (tProtocol == NULL)
  296. {
  297. //
  298. // if a driver is so broken to send a bogus handle to deregister
  299. // better not bother to fail the call. they can mess up even more
  300. //
  301. *Status = NDIS_STATUS_SUCCESS;
  302. return;
  303. }
  304. do
  305. {
  306. //
  307. // If the protocol is already closing, return.
  308. //
  309. if (!ndisCloseRef(&Protocol->Ref))
  310. {
  311. DBGPRINT(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  312. ("<==NdisDeregisterProtocol\n"));
  313. *Status = NDIS_STATUS_FAILURE;
  314. break;
  315. }
  316. if (Protocol->AssociatedMiniDriver)
  317. {
  318. Protocol->AssociatedMiniDriver->AssociatedProtocol = NULL;
  319. Protocol->AssociatedMiniDriver = NULL;
  320. }
  321. INITIALIZE_EVENT(&DeregEvent);
  322. Protocol->DeregEvent = &DeregEvent;
  323. ndisCloseAllBindingsOnProtocol(Protocol);
  324. ndisDereferenceProtocol(Protocol);
  325. WAIT_FOR_PROTOCOL(Protocol, &DeregEvent);
  326. *Status = NDIS_STATUS_SUCCESS;
  327. } while (FALSE);
  328. ProtocolDereferencePackage();
  329. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  330. ("<==NdisDeregisterProtocol, Status %lx\n", *Status));
  331. }
  332. VOID
  333. NdisOpenAdapter(
  334. OUT PNDIS_STATUS Status,
  335. OUT PNDIS_STATUS OpenErrorStatus,
  336. OUT PNDIS_HANDLE NdisBindingHandle,
  337. OUT PUINT SelectedMediumIndex,
  338. IN PNDIS_MEDIUM MediumArray,
  339. IN UINT MediumArraySize,
  340. IN NDIS_HANDLE NdisProtocolHandle,
  341. IN NDIS_HANDLE ProtocolBindingContext,
  342. IN PNDIS_STRING AdapterName,
  343. IN UINT OpenOptions,
  344. IN PSTRING AddressingInformation OPTIONAL
  345. )
  346. /*++
  347. Routine Description:
  348. Opens a connection between a protocol and an adapter (Miniport).
  349. Arguments:
  350. Status - Returns the final status.
  351. NdisBindingHandle - Returns a handle referring to this open.
  352. SelectedMediumIndex - Index in MediumArray of the medium type that
  353. the MAC wishes to be viewed as.
  354. MediumArray - Array of medium types which a protocol supports.
  355. MediumArraySize - Number of elements in MediumArray.
  356. NdisProtocolHandle - The handle returned by NdisRegisterProtocol.
  357. ProtocolBindingContext - A context for indications.
  358. AdapterName - The name of the adapter to open.
  359. OpenOptions - bit mask.
  360. AddressingInformation - Information passed to MacOpenAdapter.
  361. Return Value:
  362. None.
  363. Note:
  364. Called at PASSIVE level
  365. --*/
  366. {
  367. PNDIS_OPEN_BLOCK NewOpenP = NULL;
  368. PNDIS_PROTOCOL_BLOCK Protocol;
  369. PNDIS_MINIPORT_BLOCK Miniport;
  370. PWORK_QUEUE_ITEM pWorkItem;
  371. PNDIS_POST_OPEN_PROCESSING PostOpen = NULL;
  372. PNDIS_STRING BindDeviceName, RootDeviceName;
  373. KIRQL OldIrql;
  374. BOOLEAN UsingEncapsulation = FALSE;
  375. BOOLEAN DerefProtocol = FALSE;
  376. BOOLEAN DeQueueFromGlobalList = FALSE;
  377. ULONG i, SizeOpen;
  378. //
  379. // Allocate memory for the NDIS open block.
  380. //
  381. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  382. ("==>NdisOpenAdapter\n"));
  383. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  384. (" Protocol: "));
  385. DBGPRINT_UNICODE(DBG_COMP_BIND, DBG_LEVEL_INFO,
  386. &((PNDIS_PROTOCOL_BLOCK)NdisProtocolHandle)->ProtocolCharacteristics.Name);
  387. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  388. (" is opening Adapter: "));
  389. DBGPRINT_UNICODE(DBG_COMP_BIND, DBG_LEVEL_INFO,
  390. AdapterName);
  391. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  392. ("\n"));
  393. IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR)
  394. {
  395. BOOLEAN f = FALSE;
  396. if (DbgIsNull(NdisProtocolHandle))
  397. {
  398. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  399. ("OpenAdapter: Null ProtocolHandle\n"));
  400. f = TRUE;
  401. }
  402. if (!DbgIsNonPaged(NdisProtocolHandle))
  403. {
  404. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  405. ("OpenAdapter: ProtocolHandle not in NonPaged Memory\n"));
  406. f = TRUE;
  407. }
  408. if (DbgIsNull(ProtocolBindingContext))
  409. {
  410. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  411. ("OpenAdapter: Null Context\n"));
  412. f = TRUE;
  413. }
  414. if (!DbgIsNonPaged(ProtocolBindingContext))
  415. {
  416. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  417. ("OpenAdapter: Context not in NonPaged Memory\n"));
  418. f = TRUE;
  419. }
  420. if (f)
  421. DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
  422. }
  423. PnPReferencePackage();
  424. do
  425. {
  426. *NdisBindingHandle = NULL;
  427. ASSERT (NdisProtocolHandle != NULL);
  428. Protocol = (PNDIS_PROTOCOL_BLOCK)NdisProtocolHandle;
  429. //
  430. // Increment the protocol's reference count.
  431. //
  432. if (!ndisReferenceProtocol(Protocol))
  433. {
  434. //
  435. // The protocol is closing.
  436. //
  437. *Status = NDIS_STATUS_CLOSING;
  438. break;
  439. }
  440. DerefProtocol = TRUE;
  441. if ((BindDeviceName = Protocol->BindDeviceName) != NULL)
  442. {
  443. //
  444. // This is a PnP transport. We know what we want.
  445. //
  446. RootDeviceName = Protocol->RootDeviceName;
  447. Miniport = Protocol->BindingAdapter;
  448. ASSERT(Miniport != NULL);
  449. }
  450. else
  451. {
  452. BOOLEAN fTester;
  453. //
  454. // This is a legacy transport and it has not come via a Bind upto the protocol.
  455. // Or it can be a IP arp module who wants to defeat this whole scheme.
  456. // Find the root of the filter chain. Sigh !!!
  457. //
  458. fTester = ((Protocol->ProtocolCharacteristics.Flags & NDIS_PROTOCOL_TESTER) != 0);
  459. ndisFindRootDevice(AdapterName,
  460. fTester,
  461. &BindDeviceName,
  462. &RootDeviceName,
  463. &Miniport);
  464. }
  465. if (Miniport == NULL)
  466. {
  467. *Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  468. break;
  469. }
  470. SizeOpen = MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO) ?
  471. sizeof(NDIS_OPEN_BLOCK) : (sizeof(NDIS_OPEN_BLOCK) - sizeof(struct _NDIS_OPEN_CO));
  472. NewOpenP = (PNDIS_OPEN_BLOCK)ALLOC_FROM_POOL(SizeOpen, NDIS_TAG_M_OPEN_BLK);
  473. if (NewOpenP == (PNDIS_OPEN_BLOCK)NULL)
  474. {
  475. *Status = NDIS_STATUS_RESOURCES;
  476. break;
  477. }
  478. ZeroMemory(NewOpenP, SizeOpen);
  479. //
  480. // queue the open on the global list
  481. //
  482. ACQUIRE_SPIN_LOCK(&ndisGlobalOpenListLock, &OldIrql);
  483. NewOpenP->NextGlobalOpen = ndisGlobalOpenList;
  484. ndisGlobalOpenList = NewOpenP;
  485. DeQueueFromGlobalList = TRUE;
  486. RELEASE_SPIN_LOCK(&ndisGlobalOpenListLock, OldIrql);
  487. //
  488. // Set the name in the Open to the name passed, not the name opened !!!
  489. //
  490. NewOpenP->BindDeviceName = BindDeviceName;
  491. NewOpenP->RootDeviceName = RootDeviceName;
  492. NewOpenP->MiniportHandle = Miniport;
  493. NewOpenP->ProtocolHandle = Protocol;
  494. NewOpenP->ProtocolBindingContext = ProtocolBindingContext;
  495. //
  496. // set this now just in case we end up calling the protocol for this binding
  497. // before returning from NdisOpenAdapter
  498. //
  499. *NdisBindingHandle = NewOpenP;
  500. //
  501. //
  502. // Is this the ndiswan miniport wrapper?
  503. //
  504. if ((Miniport->MacOptions & NDISWAN_OPTIONS) == NDISWAN_OPTIONS)
  505. {
  506. //
  507. // Yup. We want the binding to think that this is an ndiswan link.
  508. //
  509. for (i = 0; i < MediumArraySize; i++)
  510. {
  511. if (MediumArray[i] == NdisMediumWan)
  512. {
  513. break;
  514. }
  515. }
  516. }
  517. else
  518. {
  519. //
  520. // Select the medium to use
  521. //
  522. for (i = 0; i < MediumArraySize; i++)
  523. {
  524. if (MediumArray[i] == Miniport->MediaType)
  525. {
  526. break;
  527. }
  528. }
  529. }
  530. if (i == MediumArraySize)
  531. {
  532. //
  533. // Check for ethernet encapsulation on Arcnet as
  534. // a possible combination.
  535. //
  536. #if ARCNET
  537. if (Miniport->MediaType == NdisMediumArcnet878_2)
  538. {
  539. for (i = 0; i < MediumArraySize; i++)
  540. {
  541. if (MediumArray[i] == NdisMedium802_3)
  542. {
  543. break;
  544. }
  545. }
  546. if (i == MediumArraySize)
  547. {
  548. *Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  549. break;
  550. }
  551. UsingEncapsulation = TRUE;
  552. }
  553. else
  554. #endif
  555. {
  556. *Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  557. break;
  558. }
  559. }
  560. *SelectedMediumIndex = i;
  561. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  562. //
  563. // Lock the miniport in case it is not serialized
  564. //
  565. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  566. {
  567. BLOCK_LOCK_MINIPORT_DPC_L(Miniport);
  568. }
  569. ndisMOpenAdapter(Status,
  570. NewOpenP,
  571. UsingEncapsulation);
  572. if (*Status == NDIS_STATUS_SUCCESS)
  573. {
  574. //
  575. // If the media is disconnected, swap handlers
  576. //
  577. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_MEDIA_CONNECTED))
  578. {
  579. ndisMSwapOpenHandlers(Miniport,
  580. NDIS_STATUS_NO_CABLE,
  581. fMINIPORT_STATE_MEDIA_DISCONNECTED);
  582. }
  583. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO) &&
  584. (NewOpenP->ProtocolHandle->ProtocolCharacteristics.CoAfRegisterNotifyHandler != NULL))
  585. {
  586. PostOpen = (PNDIS_POST_OPEN_PROCESSING)ALLOC_FROM_POOL(sizeof(NDIS_POST_OPEN_PROCESSING), NDIS_TAG_WORK_ITEM);
  587. if (PostOpen != NULL)
  588. {
  589. OPEN_INCREMENT_AF_NOTIFICATION(NewOpenP);
  590. PostOpen->Open = NewOpenP;
  591. //
  592. // Prepare a work item to send AF notifications.
  593. // Don't queue it yet.
  594. //
  595. INITIALIZE_WORK_ITEM(&PostOpen->WorkItem,
  596. ndisMFinishQueuedPendingOpen,
  597. PostOpen);
  598. }
  599. }
  600. }
  601. if (!MINIPORT_TEST_FLAG(Miniport, fMINIPORT_DESERIALIZE))
  602. {
  603. //
  604. // Unlock the miniport.
  605. //
  606. UNLOCK_MINIPORT_L(Miniport);
  607. }
  608. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  609. if (*Status != NDIS_STATUS_SUCCESS)
  610. {
  611. break;
  612. }
  613. //
  614. // For SWENUM miniports, reference it so it won't go away
  615. //
  616. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_SWENUM))
  617. {
  618. PBUS_INTERFACE_REFERENCE BusInterface;
  619. BusInterface = (PBUS_INTERFACE_REFERENCE)(Miniport->BusInterface);
  620. ASSERT(BusInterface != NULL);
  621. if (BusInterface)
  622. {
  623. BusInterface->ReferenceDeviceObject(BusInterface->Interface.Context);
  624. }
  625. }
  626. if (PostOpen != NULL)
  627. {
  628. //
  629. // Complete the Open before queueing AF notifications
  630. //
  631. (((PNDIS_PROTOCOL_BLOCK)NewOpenP->ProtocolHandle)->ProtocolCharacteristics.OpenAdapterCompleteHandler)(
  632. NewOpenP->ProtocolBindingContext,
  633. *Status,
  634. *Status);
  635. QUEUE_WORK_ITEM(&PostOpen->WorkItem, DelayedWorkQueue);
  636. *Status = NDIS_STATUS_PENDING;
  637. }
  638. } while (FALSE);
  639. if ((*Status != NDIS_STATUS_SUCCESS) && (*Status != NDIS_STATUS_PENDING))
  640. {
  641. if (DerefProtocol)
  642. {
  643. ndisDereferenceProtocol(Protocol);
  644. }
  645. if (DeQueueFromGlobalList)
  646. {
  647. ndisRemoveOpenFromGlobalList(NewOpenP);
  648. }
  649. if (NewOpenP != NULL)
  650. {
  651. FREE_POOL(NewOpenP);
  652. }
  653. *NdisBindingHandle = NULL;
  654. }
  655. PnPDereferencePackage();
  656. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  657. ("<==NdisOpenAdapter\n"));
  658. }
  659. VOID
  660. NdisCloseAdapter(
  661. OUT PNDIS_STATUS Status,
  662. IN NDIS_HANDLE NdisBindingHandle
  663. )
  664. /*++
  665. Routine Description:
  666. Closes a connection between a protocol and an adapter (MAC).
  667. Arguments:
  668. Status - Returns the final status.
  669. NdisBindingHandle - The handle returned by NdisOpenAdapter.
  670. Return Value:
  671. None.
  672. Note:
  673. Called at PASSIVE level
  674. --*/
  675. {
  676. PNDIS_OPEN_BLOCK Open = ((PNDIS_OPEN_BLOCK)NdisBindingHandle);
  677. PNDIS_OPEN_BLOCK tOpen;
  678. PNDIS_MINIPORT_BLOCK Miniport;
  679. KIRQL OldIrql;
  680. PnPReferencePackage();
  681. //
  682. // find the open on global open list
  683. //
  684. ACQUIRE_SPIN_LOCK(&ndisGlobalOpenListLock, &OldIrql);
  685. for (tOpen = ndisGlobalOpenList; tOpen != NULL; tOpen = tOpen->NextGlobalOpen)
  686. {
  687. if (tOpen == Open)
  688. {
  689. break;
  690. }
  691. }
  692. RELEASE_SPIN_LOCK(&ndisGlobalOpenListLock, OldIrql);
  693. #if DBG
  694. if (tOpen)
  695. {
  696. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  697. ("==>NdisCloseAdapter\n"));
  698. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  699. (" Protocol: "));
  700. DBGPRINT_UNICODE(DBG_COMP_BIND, DBG_LEVEL_INFO,
  701. &Open->ProtocolHandle->ProtocolCharacteristics.Name);
  702. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  703. (" is closing Adapter: "));
  704. DBGPRINT_UNICODE(DBG_COMP_BIND, DBG_LEVEL_INFO,
  705. &Open->MiniportHandle->MiniportName);
  706. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  707. ("\n"));
  708. }
  709. #endif
  710. IF_DBG(DBG_COMP_CONFIG, DBG_LEVEL_ERR)
  711. {
  712. if (DbgIsNull(NdisBindingHandle))
  713. {
  714. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  715. ("OpenAdapter: Null BindingHandle\n"));
  716. DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
  717. }
  718. if (!DbgIsNonPaged(NdisBindingHandle))
  719. {
  720. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  721. ("OpenAdapter: BindingHandle not in NonPaged Memory\n"));
  722. DBGBREAK(DBG_COMP_CONFIG, DBG_LEVEL_ERR);
  723. }
  724. }
  725. do
  726. {
  727. if (tOpen == NULL)
  728. {
  729. *Status = NDIS_STATUS_SUCCESS;
  730. PnPDereferencePackage();
  731. break;
  732. }
  733. Miniport = Open->MiniportHandle;
  734. ASSERT(Miniport != NULL);
  735. //
  736. // For SWENUM miniports, dereference it
  737. //
  738. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_SWENUM))
  739. {
  740. PBUS_INTERFACE_REFERENCE BusInterface;
  741. BusInterface = (PBUS_INTERFACE_REFERENCE)(Miniport->BusInterface);
  742. ASSERT(BusInterface != NULL);
  743. if (BusInterface)
  744. {
  745. BusInterface->DereferenceDeviceObject(BusInterface->Interface.Context);
  746. }
  747. }
  748. //
  749. // This returns TRUE if it finished synchronously.
  750. //
  751. if (ndisMKillOpen(Open))
  752. {
  753. *Status = NDIS_STATUS_SUCCESS;
  754. PnPDereferencePackage();
  755. }
  756. else
  757. {
  758. //
  759. // will complete later. ndisMQueuedFinishClose routine will dereference
  760. // the PnP package. we need to have the pnp package referenced because
  761. // a couple of routines called during completing the close, run at DPC
  762. // ex. ndisMFinishClose, ndisDeQueueOpenOnProtocol and ndisDeQueueOpenOnMiniport
  763. // and they are in pnp package
  764. //
  765. *Status = NDIS_STATUS_PENDING;
  766. }
  767. } while (FALSE);
  768. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  769. ("<==NdisCloseAdapter\n"));
  770. }
  771. VOID
  772. NdisSetProtocolFilter(
  773. OUT PNDIS_STATUS Status,
  774. IN NDIS_HANDLE NdisBindingHandle,
  775. IN RECEIVE_HANDLER ReceiveHandler,
  776. IN RECEIVE_PACKET_HANDLER ReceivePacketHandler,
  777. IN NDIS_MEDIUM Medium,
  778. IN UINT Offset,
  779. IN UINT Size,
  780. IN PUCHAR Pattern
  781. )
  782. /*++
  783. Routine Description:
  784. Sets a protocol filter.
  785. Arguments:
  786. Status Returns the final status.
  787. NdisProtocolHandle The handle returned by NdisRegisterProtocol.
  788. ReceiveHandler This will be invoked instead of the default receivehandler
  789. when the pattern match happens.
  790. ReceivePacketHandler This will be invoked instead of the default receivepackethandler
  791. when the pattern match happens.
  792. Size Size of pattern
  793. Pattern This must match
  794. Return Value:
  795. None.
  796. Note:
  797. --*/
  798. {
  799. *Status = NDIS_STATUS_NOT_SUPPORTED;
  800. }
  801. VOID
  802. NdisGetDriverHandle(
  803. IN NDIS_HANDLE NdisBindingHandle,
  804. OUT PNDIS_HANDLE NdisDriverHandle
  805. )
  806. /*++
  807. Routine Description:
  808. This routine will return the driver handle for the miniport identified by a binding
  809. Arguments:
  810. NdisBindingHandle
  811. NdisDriverHandle: on return from this function, this will be set to the driver handle
  812. Return Value:
  813. None.
  814. Note:
  815. --*/
  816. {
  817. PNDIS_OPEN_BLOCK OpenBlock = (PNDIS_OPEN_BLOCK)NdisBindingHandle;
  818. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  819. ("==>NdisGetDriverHandle\n"));
  820. *NdisDriverHandle = OpenBlock->MiniportHandle->DriverHandle;
  821. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  822. ("<==NdisGetDriverHandle\n"));
  823. }
  824. VOID
  825. NdisReEnumerateProtocolBindings(
  826. IN NDIS_HANDLE NdisProtocolHandle
  827. )
  828. /*++
  829. Routine Description:
  830. Arguments:
  831. Return Value:
  832. None.
  833. Note:
  834. --*/
  835. {
  836. if (ndisReferenceProtocol((PNDIS_PROTOCOL_BLOCK)NdisProtocolHandle))
  837. {
  838. ndisCheckProtocolBindings((PNDIS_PROTOCOL_BLOCK)NdisProtocolHandle);
  839. }
  840. else
  841. {
  842. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  843. ("NdisReEnumerateProtocolBindings: Reference failed for %Z\n",
  844. &((PNDIS_PROTOCOL_BLOCK)NdisProtocolHandle)->ProtocolCharacteristics.Name));
  845. }
  846. }
  847. NTSTATUS
  848. FASTCALL
  849. ndisReferenceProtocolByName(
  850. IN PUNICODE_STRING ProtocolName,
  851. IN OUT PNDIS_PROTOCOL_BLOCK *Protocol,
  852. IN BOOLEAN fPartialMatch
  853. )
  854. /*++
  855. Routine Description:
  856. Arguments:
  857. Return Value:
  858. None.
  859. Note:
  860. --*/
  861. {
  862. KIRQL OldIrql;
  863. UNICODE_STRING UpcaseProtocol;
  864. PNDIS_PROTOCOL_BLOCK TmpProtocol;
  865. NTSTATUS Status = STATUS_OBJECT_NAME_NOT_FOUND, NtStatus;
  866. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  867. ("==>ndisReferenceProtocolByName\n"));
  868. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  869. (" Protocol: "));
  870. DBGPRINT_UNICODE(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  871. ProtocolName);
  872. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  873. ("\n"));
  874. do
  875. {
  876. UpcaseProtocol.Length = ProtocolName->Length;
  877. UpcaseProtocol.MaximumLength = ProtocolName->Length + sizeof(WCHAR);
  878. UpcaseProtocol.Buffer = ALLOC_FROM_POOL(UpcaseProtocol.MaximumLength, NDIS_TAG_STRING);
  879. if (UpcaseProtocol.Buffer == NULL)
  880. {
  881. //
  882. // return null if we fail
  883. //
  884. *Protocol = NULL;
  885. Status = STATUS_INSUFFICIENT_RESOURCES;
  886. break;
  887. }
  888. NtStatus = RtlUpcaseUnicodeString(&UpcaseProtocol, ProtocolName, FALSE);
  889. ASSERT (NT_SUCCESS(NtStatus));
  890. ACQUIRE_SPIN_LOCK(&ndisProtocolListLock, &OldIrql);
  891. for (TmpProtocol = (*Protocol == NULL) ? ndisProtocolList : (*Protocol)->NextProtocol;
  892. TmpProtocol != NULL;
  893. TmpProtocol = TmpProtocol->NextProtocol)
  894. {
  895. if ((fPartialMatch && (TmpProtocol != *Protocol) &&
  896. NDIS_PARTIAL_MATCH_UNICODE_STRING(&UpcaseProtocol, &TmpProtocol->ProtocolCharacteristics.Name)) ||
  897. (!fPartialMatch &&
  898. NDIS_EQUAL_UNICODE_STRING(&UpcaseProtocol, &TmpProtocol->ProtocolCharacteristics.Name)))
  899. {
  900. if (ndisReferenceProtocol(TmpProtocol))
  901. {
  902. Status = STATUS_SUCCESS;
  903. }
  904. else
  905. {
  906. TmpProtocol = NULL;
  907. }
  908. break;
  909. }
  910. }
  911. RELEASE_SPIN_LOCK(&ndisProtocolListLock, OldIrql);
  912. *Protocol = TmpProtocol;
  913. FREE_POOL(UpcaseProtocol.Buffer);
  914. } while (FALSE);
  915. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  916. ("<==ndisReferenceProtocolByName\n"));
  917. return Status;
  918. }
  919. VOID
  920. FASTCALL
  921. ndisDereferenceProtocol(
  922. IN PNDIS_PROTOCOL_BLOCK Protocol
  923. )
  924. /*++
  925. Routine Description:
  926. Arguments:
  927. Return Value:
  928. None.
  929. Note:
  930. --*/
  931. {
  932. BOOLEAN rc;
  933. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  934. ("==>ndisDereferenceProtocol\n"));
  935. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  936. (" Protocol: "));
  937. DBGPRINT_UNICODE(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  938. &Protocol->ProtocolCharacteristics.Name);
  939. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  940. (", RefCount: %ld\n", Protocol->Ref.ReferenceCount -1 ));
  941. rc = ndisDereferenceRef(&Protocol->Ref);
  942. if (rc)
  943. {
  944. KIRQL OldIrql;
  945. PNDIS_PROTOCOL_BLOCK *pProtocol;
  946. ACQUIRE_SPIN_LOCK(&ndisProtocolListLock, &OldIrql);
  947. for (pProtocol = &ndisProtocolList;
  948. *pProtocol != NULL;
  949. pProtocol = &(*pProtocol)->NextProtocol)
  950. {
  951. if (*pProtocol == Protocol)
  952. {
  953. *pProtocol = Protocol->NextProtocol;
  954. DEREF_NDIS_DRIVER_OBJECT();
  955. break;
  956. }
  957. }
  958. ASSERT (*pProtocol == Protocol->NextProtocol);
  959. ASSERT (Protocol->OpenQueue == NULL);
  960. RELEASE_SPIN_LOCK(&ndisProtocolListLock, OldIrql);
  961. if (Protocol->DeregEvent != NULL)
  962. SET_EVENT(Protocol->DeregEvent);
  963. FREE_POOL(Protocol);
  964. }
  965. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  966. ("<==ndisDereferenceProtocol\n"));
  967. }
  968. VOID
  969. ndisCheckProtocolBindings(
  970. IN PNDIS_PROTOCOL_BLOCK Protocol
  971. )
  972. /*++
  973. Routine Description:
  974. Arguments:
  975. Return Value:
  976. None.
  977. Note:
  978. --*/
  979. {
  980. KIRQL OldIrql;
  981. PNDIS_M_DRIVER_BLOCK MiniBlock, NextMiniBlock;
  982. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  983. ("==>ndisCheckProtocolBindings\n"));
  984. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  985. (" Protocol: "));
  986. DBGPRINT_UNICODE(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  987. &Protocol->ProtocolCharacteristics.Name);
  988. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  989. ("\n"));
  990. //
  991. // Check again if reference is allowed i.e. if the protocol called NdisDeregisterProtocol
  992. // before this thread had a chance to run.
  993. //
  994. if (!ndisReferenceProtocol(Protocol))
  995. {
  996. ndisDereferenceProtocol(Protocol);
  997. return;
  998. }
  999. PnPReferencePackage();
  1000. ACQUIRE_SPIN_LOCK(&ndisMiniDriverListLock, &OldIrql);
  1001. //
  1002. // First walk the list of miniports
  1003. //
  1004. for (MiniBlock = ndisMiniDriverList;
  1005. MiniBlock != NULL;
  1006. MiniBlock = NextMiniBlock)
  1007. {
  1008. PNDIS_MINIPORT_BLOCK Miniport, NM;
  1009. NextMiniBlock = MiniBlock->NextDriver;
  1010. if (ndisReferenceDriver(MiniBlock))
  1011. {
  1012. RELEASE_SPIN_LOCK(&ndisMiniDriverListLock, OldIrql);
  1013. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  1014. for (Miniport = MiniBlock->MiniportQueue;
  1015. Miniport != NULL;
  1016. Miniport = NM)
  1017. {
  1018. NM = Miniport->NextMiniport;
  1019. if (!MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_ORPHANED) &&
  1020. MINIPORT_INCREMENT_REF(Miniport))
  1021. {
  1022. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  1023. ndisCheckAdapterBindings(Miniport, Protocol);
  1024. NM = Miniport->NextMiniport;
  1025. MINIPORT_DECREMENT_REF(Miniport);
  1026. ACQUIRE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, &OldIrql);
  1027. }
  1028. }
  1029. RELEASE_SPIN_LOCK(&MiniBlock->Ref.SpinLock, OldIrql);
  1030. ACQUIRE_SPIN_LOCK(&ndisMiniDriverListLock, &OldIrql);
  1031. NextMiniBlock = MiniBlock->NextDriver;
  1032. ndisDereferenceDriver(MiniBlock, TRUE);
  1033. }
  1034. }
  1035. RELEASE_SPIN_LOCK(&ndisMiniDriverListLock, OldIrql);
  1036. //
  1037. // Now inform this protocol that we are done for now
  1038. //
  1039. if (Protocol->ProtocolCharacteristics.PnPEventHandler != NULL)
  1040. {
  1041. NET_PNP_EVENT NetPnpEvent;
  1042. KEVENT Event;
  1043. NDIS_STATUS Status;
  1044. INITIALIZE_EVENT(&Event);
  1045. NdisZeroMemory(&NetPnpEvent, sizeof(NetPnpEvent));
  1046. NetPnpEvent.NetEvent = NetEventBindsComplete;
  1047. //
  1048. // Initialize and save the local event with the PnP event.
  1049. //
  1050. PNDIS_PNP_EVENT_RESERVED_FROM_NET_PNP_EVENT(&NetPnpEvent)->pEvent = &Event;
  1051. WAIT_FOR_PROTO_MUTEX(Protocol);
  1052. //
  1053. // Indicate the event to the protocol.
  1054. //
  1055. Status = (Protocol->ProtocolCharacteristics.PnPEventHandler)(NULL, &NetPnpEvent);
  1056. if (NDIS_STATUS_PENDING == Status)
  1057. {
  1058. //
  1059. // Wait for completion.
  1060. //
  1061. WAIT_FOR_PROTOCOL(Protocol, &Event);
  1062. }
  1063. RELEASE_PROT_MUTEX(Protocol);
  1064. }
  1065. //
  1066. // Dereference twice - one for reference by caller and one for reference at the beginning
  1067. // of this routine.
  1068. //
  1069. ndisDereferenceProtocol(Protocol);
  1070. ndisDereferenceProtocol(Protocol);
  1071. PnPDereferencePackage();
  1072. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1073. ("<==ndisCheckProtocolBindings\n"));
  1074. }
  1075. VOID
  1076. NdisOpenProtocolConfiguration(
  1077. OUT PNDIS_STATUS Status,
  1078. OUT PNDIS_HANDLE ConfigurationHandle,
  1079. IN PNDIS_STRING ProtocolSection
  1080. )
  1081. /*++
  1082. Routine Description:
  1083. Arguments:
  1084. Return Value:
  1085. None.
  1086. Note:
  1087. --*/
  1088. {
  1089. PNDIS_CONFIGURATION_HANDLE HandleToReturn;
  1090. PNDIS_WRAPPER_CONFIGURATION_HANDLE ConfigHandle;
  1091. UINT Size;
  1092. #define PQueryTable ConfigHandle->ParametersQueryTable
  1093. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1094. ("==>NdisOpenProtocolConfiguration\n"));
  1095. do
  1096. {
  1097. //
  1098. // Allocate the space for configuration handle
  1099. //
  1100. Size = sizeof(NDIS_CONFIGURATION_HANDLE) +
  1101. sizeof(NDIS_WRAPPER_CONFIGURATION_HANDLE) +
  1102. ProtocolSection->MaximumLength + sizeof(WCHAR);
  1103. HandleToReturn = ALLOC_FROM_POOL(Size, NDIS_TAG_PROTOCOL_CONFIGURATION);
  1104. *Status = (HandleToReturn != NULL) ? NDIS_STATUS_SUCCESS : NDIS_STATUS_RESOURCES;
  1105. if (*Status != NDIS_STATUS_SUCCESS)
  1106. {
  1107. *ConfigurationHandle = (NDIS_HANDLE)NULL;
  1108. break;
  1109. }
  1110. ZeroMemory(HandleToReturn, Size);
  1111. ConfigHandle = (PNDIS_WRAPPER_CONFIGURATION_HANDLE)((PUCHAR)HandleToReturn + sizeof(NDIS_CONFIGURATION_HANDLE));
  1112. HandleToReturn->KeyQueryTable = ConfigHandle->ParametersQueryTable;
  1113. HandleToReturn->ParameterList = NULL;
  1114. PQueryTable[0].QueryRoutine = NULL;
  1115. PQueryTable[0].Flags = RTL_QUERY_REGISTRY_SUBKEY;
  1116. PQueryTable[0].Name = L"";
  1117. //
  1118. // 1.
  1119. // Call ndisSaveParameter for a parameter, which will allocate storage for it.
  1120. //
  1121. PQueryTable[1].QueryRoutine = ndisSaveParameters;
  1122. PQueryTable[1].Flags = RTL_QUERY_REGISTRY_REQUIRED | RTL_QUERY_REGISTRY_NOEXPAND;
  1123. PQueryTable[1].DefaultType = REG_NONE;
  1124. //
  1125. // PQueryTable[0].Name and PQueryTable[0].EntryContext
  1126. // are filled in inside ReadConfiguration, in preparation
  1127. // for the callback.
  1128. //
  1129. // PQueryTable[0].Name = KeywordBuffer;
  1130. // PQueryTable[0].EntryContext = ParameterValue;
  1131. //
  1132. // 2.
  1133. // Stop
  1134. //
  1135. PQueryTable[2].QueryRoutine = NULL;
  1136. PQueryTable[2].Flags = 0;
  1137. PQueryTable[2].Name = NULL;
  1138. //
  1139. // NOTE: Some fields in ParametersQueryTable[3] are used to store information for later retrieval.
  1140. //
  1141. PQueryTable[3].QueryRoutine = NULL;
  1142. PQueryTable[3].Name = (PWSTR)((PUCHAR)HandleToReturn +
  1143. sizeof(NDIS_CONFIGURATION_HANDLE) +
  1144. sizeof(NDIS_WRAPPER_CONFIGURATION_HANDLE));
  1145. CopyMemory(PQueryTable[3].Name, ProtocolSection->Buffer, ProtocolSection->Length);
  1146. PQueryTable[3].EntryContext = NULL;
  1147. PQueryTable[3].DefaultData = NULL;
  1148. *ConfigurationHandle = (NDIS_HANDLE)HandleToReturn;
  1149. *Status = NDIS_STATUS_SUCCESS;
  1150. } while (FALSE);
  1151. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1152. ("<==NdisOpenProtocolConfiguration\n"));
  1153. }
  1154. BOOLEAN
  1155. FASTCALL
  1156. ndisQueueOpenOnProtocol(
  1157. IN PNDIS_OPEN_BLOCK OpenP,
  1158. IN PNDIS_PROTOCOL_BLOCK Protocol
  1159. )
  1160. /*++
  1161. Routine Description:
  1162. Attaches an open block to the list of opens for a protocol.
  1163. Arguments:
  1164. OpenP - The open block to be queued.
  1165. Protocol - The protocol block to queue it to.
  1166. NOTE: can be called at raised IRQL.
  1167. Return Value:
  1168. TRUE if the operation is successful.
  1169. FALSE if the protocol is closing.
  1170. --*/
  1171. {
  1172. KIRQL OldIrql;
  1173. BOOLEAN rc;
  1174. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1175. ("==>ndisQueueOpenOnProtocol\n"));
  1176. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1177. (" Protocol: "));
  1178. DBGPRINT_UNICODE(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1179. &Protocol->ProtocolCharacteristics.Name);
  1180. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1181. ("\n"));
  1182. IF_DBG(DBG_COMP_PROTOCOL, DBG_LEVEL_ERR)
  1183. {
  1184. BOOLEAN f = FALSE;
  1185. if (DbgIsNull(OpenP))
  1186. {
  1187. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1188. ("ndisQueueOpenOnProtocol: Null Open Block\n"));
  1189. f = TRUE;
  1190. }
  1191. if (!DbgIsNonPaged(OpenP))
  1192. {
  1193. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1194. ("ndisQueueOpenOnProtocol: Open Block not in NonPaged Memory\n"));
  1195. f = TRUE;
  1196. }
  1197. if (DbgIsNull(Protocol))
  1198. {
  1199. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1200. ("ndisQueueOpenOnProtocol: Null Protocol Block\n"));
  1201. f = TRUE;
  1202. }
  1203. if (!DbgIsNonPaged(Protocol))
  1204. {
  1205. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1206. ("ndisQueueOpenOnProtocol: Protocol Block not in NonPaged Memory\n"));
  1207. f = TRUE;
  1208. }
  1209. if (f)
  1210. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  1211. }
  1212. do
  1213. {
  1214. //
  1215. // we can not reference the package here because this routine can
  1216. // be called at raised IRQL.
  1217. // make sure the PNP package has been referenced already
  1218. //
  1219. ASSERT(ndisPkgs[NPNP_PKG].ReferenceCount > 0);
  1220. ACQUIRE_SPIN_LOCK(&Protocol->Ref.SpinLock, &OldIrql);
  1221. //
  1222. // Make sure the protocol is not closing.
  1223. //
  1224. if (Protocol->Ref.Closing)
  1225. {
  1226. rc = FALSE;
  1227. break;
  1228. }
  1229. //
  1230. // Attach this open at the head of the queue.
  1231. //
  1232. OpenP->ProtocolNextOpen = Protocol->OpenQueue;
  1233. Protocol->OpenQueue = OpenP;
  1234. rc = TRUE;
  1235. } while (FALSE);
  1236. RELEASE_SPIN_LOCK(&Protocol->Ref.SpinLock, OldIrql);
  1237. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1238. ("<==ndisQueueOpenOnProtocol\n"));
  1239. return rc;
  1240. }
  1241. VOID
  1242. FASTCALL
  1243. ndisDeQueueOpenOnProtocol(
  1244. IN PNDIS_OPEN_BLOCK OpenP,
  1245. IN PNDIS_PROTOCOL_BLOCK Protocol
  1246. )
  1247. /*++
  1248. Routine Description:
  1249. Detaches an open block from the list of opens for a protocol.
  1250. Arguments:
  1251. OpenP - The open block to be dequeued.
  1252. Protocol - The protocol block to dequeue it from.
  1253. NOTE: can be called at raised IRQL
  1254. Return Value:
  1255. None.
  1256. --*/
  1257. {
  1258. KIRQL OldIrql;
  1259. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1260. ("==>ndisDeQueueOpenOnProtocol\n"));
  1261. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1262. (" Protocol: "));
  1263. DBGPRINT_UNICODE(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1264. &Protocol->ProtocolCharacteristics.Name);
  1265. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1266. ("\n"));
  1267. IF_DBG(DBG_COMP_PROTOCOL, DBG_LEVEL_ERR)
  1268. {
  1269. BOOLEAN f = FALSE;
  1270. if (DbgIsNull(OpenP))
  1271. {
  1272. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1273. ("ndisDeQueueOpenOnProtocol: Null Open Block\n"));
  1274. f = TRUE;
  1275. }
  1276. if (!DbgIsNonPaged(OpenP))
  1277. {
  1278. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1279. ("ndisDeQueueOpenOnProtocol: Open Block not in NonPaged Memory\n"));
  1280. f = TRUE;
  1281. }
  1282. if (DbgIsNull(Protocol))
  1283. {
  1284. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1285. ("ndisDeQueueOpenOnProtocol: Null Protocol Block\n"));
  1286. f = TRUE;
  1287. }
  1288. if (!DbgIsNonPaged(Protocol))
  1289. {
  1290. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1291. ("ndisDeQueueOpenOnProtocol: Protocol Block not in NonPaged Memory\n"));
  1292. f = TRUE;
  1293. }
  1294. if (f)
  1295. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  1296. }
  1297. //
  1298. // we can not reference the package here because this routine can
  1299. // be claled at raised IRQL.
  1300. // make sure the PNP package has been referenced already
  1301. //
  1302. ASSERT(ndisPkgs[NPNP_PKG].ReferenceCount > 0);
  1303. ACQUIRE_SPIN_LOCK(&Protocol->Ref.SpinLock, &OldIrql);
  1304. //
  1305. // Find the open on the queue, and remove it.
  1306. //
  1307. if (OpenP == (PNDIS_OPEN_BLOCK)(Protocol->OpenQueue))
  1308. {
  1309. Protocol->OpenQueue = OpenP->ProtocolNextOpen;
  1310. }
  1311. else
  1312. {
  1313. PNDIS_OPEN_BLOCK PP = Protocol->OpenQueue;
  1314. while ((PP != NULL) && (OpenP != (PNDIS_OPEN_BLOCK)(PP->ProtocolNextOpen)))
  1315. {
  1316. PP = PP->ProtocolNextOpen;
  1317. }
  1318. if (PP == NULL)
  1319. {
  1320. #if TRACK_MOPEN_REFCOUNTS
  1321. DbgPrint("Ndis:ndisDeQueueOpenOnProtocol Open %p is -not- on Protocol %p\n", OpenP, Protocol);
  1322. DbgBreakPoint();
  1323. #endif
  1324. }
  1325. else
  1326. {
  1327. PP->ProtocolNextOpen = PP->ProtocolNextOpen->ProtocolNextOpen;
  1328. }
  1329. }
  1330. RELEASE_SPIN_LOCK(&Protocol->Ref.SpinLock, OldIrql);
  1331. DBGPRINT_RAW(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1332. ("<==ndisDeQueueOpenOnProtocol\n"));
  1333. }
  1334. NDIS_STATUS
  1335. NdisWriteEventLogEntry(
  1336. IN PVOID LogHandle,
  1337. IN NDIS_STATUS EventCode,
  1338. IN ULONG UniqueEventValue,
  1339. IN USHORT NumStrings,
  1340. IN PVOID StringsList OPTIONAL,
  1341. IN ULONG DataSize,
  1342. IN PVOID Data OPTIONAL
  1343. )
  1344. /*++
  1345. Routine Description:
  1346. This function allocates an I/O error log record, fills it in and writes it
  1347. to the I/O error log on behalf of a NDIS Protocol.
  1348. Arguments:
  1349. LogHandle - Pointer to the driver object logging this event.
  1350. EventCode - Identifies the error message.
  1351. UniqueEventValue - Identifies this instance of a given error message.
  1352. NumStrings - Number of unicode strings in strings list.
  1353. DataSize - Number of bytes of data.
  1354. Strings - Array of pointers to unicode strings (PWCHAR).
  1355. Data - Binary dump data for this message, each piece being
  1356. aligned on word boundaries.
  1357. Return Value:
  1358. NDIS_STATUS_SUCCESS - The error was successfully logged.
  1359. NDIS_STATUS_BUFFER_TOO_SHORT - The error data was too large to be logged.
  1360. NDIS_STATUS_RESOURCES - Unable to allocate memory.
  1361. Notes:
  1362. This code is paged and may not be called at raised IRQL.
  1363. --*/
  1364. {
  1365. PIO_ERROR_LOG_PACKET ErrorLogEntry;
  1366. ULONG PaddedDataSize;
  1367. ULONG PacketSize;
  1368. ULONG TotalStringsSize = 0;
  1369. USHORT i;
  1370. PWCHAR *Strings;
  1371. PWCHAR Tmp;
  1372. NDIS_STATUS Status;
  1373. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1374. ("==>NdisWriteEventLogEntry\n"));
  1375. do
  1376. {
  1377. Strings = (PWCHAR *)StringsList;
  1378. //
  1379. // Sum up the length of the strings
  1380. //
  1381. for (i = 0; i < NumStrings; i++)
  1382. {
  1383. PWCHAR currentString;
  1384. ULONG stringSize;
  1385. stringSize = sizeof(UNICODE_NULL);
  1386. currentString = Strings[i];
  1387. while (*currentString++ != UNICODE_NULL)
  1388. {
  1389. stringSize += sizeof(WCHAR);
  1390. }
  1391. TotalStringsSize += stringSize;
  1392. }
  1393. if (DataSize % sizeof(ULONG))
  1394. {
  1395. PaddedDataSize = DataSize + (sizeof(ULONG) - (DataSize % sizeof(ULONG)));
  1396. }
  1397. else
  1398. {
  1399. PaddedDataSize = DataSize;
  1400. }
  1401. PacketSize = TotalStringsSize + PaddedDataSize;
  1402. if (PacketSize > NDIS_MAX_EVENT_LOG_DATA_SIZE)
  1403. {
  1404. Status = NDIS_STATUS_BUFFER_TOO_SHORT; // Too much error data
  1405. break;
  1406. }
  1407. //
  1408. // Now add in the size of the log packet, but subtract 4 from the data
  1409. // since the packet struct contains a ULONG for data.
  1410. //
  1411. if (PacketSize > sizeof(ULONG))
  1412. {
  1413. PacketSize += sizeof(IO_ERROR_LOG_PACKET) - sizeof(ULONG);
  1414. }
  1415. else
  1416. {
  1417. PacketSize += sizeof(IO_ERROR_LOG_PACKET);
  1418. }
  1419. ASSERT(PacketSize <= ERROR_LOG_MAXIMUM_SIZE);
  1420. ErrorLogEntry = (PIO_ERROR_LOG_PACKET) IoAllocateErrorLogEntry((PDRIVER_OBJECT)LogHandle,
  1421. (UCHAR) PacketSize);
  1422. if (ErrorLogEntry == NULL)
  1423. {
  1424. Status = NDIS_STATUS_RESOURCES;
  1425. break;
  1426. }
  1427. //
  1428. // Fill in the necessary log packet fields.
  1429. //
  1430. ErrorLogEntry->UniqueErrorValue = UniqueEventValue;
  1431. ErrorLogEntry->ErrorCode = EventCode;
  1432. ErrorLogEntry->NumberOfStrings = NumStrings;
  1433. ErrorLogEntry->StringOffset = (USHORT) (sizeof(IO_ERROR_LOG_PACKET) + PaddedDataSize - sizeof(ULONG));
  1434. ErrorLogEntry->DumpDataSize = (USHORT) PaddedDataSize;
  1435. //
  1436. // Copy the Dump Data to the packet
  1437. //
  1438. if (DataSize > 0)
  1439. {
  1440. RtlMoveMemory((PVOID) ErrorLogEntry->DumpData,
  1441. Data,
  1442. DataSize);
  1443. }
  1444. //
  1445. // Copy the strings to the packet.
  1446. //
  1447. Tmp = (PWCHAR)((PUCHAR)ErrorLogEntry + ErrorLogEntry->StringOffset);
  1448. for (i = 0; i < NumStrings; i++)
  1449. {
  1450. PWCHAR wchPtr = Strings[i];
  1451. while( (*Tmp++ = *wchPtr++) != UNICODE_NULL)
  1452. NOTHING;
  1453. }
  1454. IoWriteErrorLogEntry(ErrorLogEntry);
  1455. Status = NDIS_STATUS_SUCCESS;
  1456. } while (FALSE);
  1457. DBGPRINT_RAW(DBG_COMP_CONFIG, DBG_LEVEL_INFO,
  1458. ("<==NdisWriteEventLogEntry\n"));
  1459. return Status;
  1460. }
  1461. #if DBG
  1462. BOOLEAN
  1463. ndisReferenceProtocol(
  1464. IN PNDIS_PROTOCOL_BLOCK Protocol
  1465. )
  1466. {
  1467. BOOLEAN rc;
  1468. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1469. ("==>ndisReferenceProtocol\n"));
  1470. rc = ndisReferenceRef(&Protocol->Ref);
  1471. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1472. (" Protocol: "));
  1473. DBGPRINT_UNICODE(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1474. &Protocol->ProtocolCharacteristics.Name);
  1475. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1476. (", RefCount: %ld\n", Protocol->Ref.ReferenceCount));
  1477. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1478. ("<==ndisReferenceProtocol\n"));
  1479. return rc;
  1480. }
  1481. #endif
  1482. NDIS_STATUS
  1483. NdisQueryBindInstanceName(
  1484. OUT PNDIS_STRING pAdapterInstanceName,
  1485. IN NDIS_HANDLE BindingContext
  1486. )
  1487. {
  1488. PNDIS_BIND_CONTEXT BindContext = (NDIS_HANDLE)BindingContext;
  1489. PNDIS_MINIPORT_BLOCK Miniport;
  1490. USHORT cbSize;
  1491. PVOID ptmp = NULL;
  1492. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1493. NTSTATUS NtStatus;
  1494. PNDIS_STRING pAdapterName;
  1495. DBGPRINT(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1496. ("==>NdisQueryBindInstanceName\n"));
  1497. Miniport = BindContext->Miniport;
  1498. pAdapterName = Miniport->pAdapterInstanceName;
  1499. //
  1500. // If we failed to create the adapter instance name then fail the call.
  1501. //
  1502. if (NULL != pAdapterName)
  1503. {
  1504. //
  1505. // Allocate storage for the copy of the adapter instance name.
  1506. //
  1507. cbSize = pAdapterName->MaximumLength;
  1508. //
  1509. // Allocate storage for the new string.
  1510. //
  1511. ptmp = ALLOC_FROM_POOL(cbSize, NDIS_TAG_NAME_BUF);
  1512. if (NULL != ptmp)
  1513. {
  1514. RtlZeroMemory(ptmp, cbSize);
  1515. pAdapterInstanceName->Buffer = ptmp;
  1516. pAdapterInstanceName->Length = 0;
  1517. pAdapterInstanceName->MaximumLength = cbSize;
  1518. NtStatus = RtlAppendUnicodeStringToString(pAdapterInstanceName, pAdapterName);
  1519. if (NT_SUCCESS(NtStatus))
  1520. {
  1521. Status = NDIS_STATUS_SUCCESS;
  1522. }
  1523. }
  1524. else
  1525. {
  1526. Status = NDIS_STATUS_RESOURCES;
  1527. }
  1528. }
  1529. if (NDIS_STATUS_SUCCESS != Status)
  1530. {
  1531. if (NULL != ptmp)
  1532. {
  1533. FREE_POOL(ptmp);
  1534. }
  1535. }
  1536. DBGPRINT(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1537. ("<==NdisQueryBindInstanceName: 0x%x\n", Status));
  1538. return(Status);
  1539. }
  1540. NDIS_STATUS
  1541. NdisQueryAdapterInstanceName(
  1542. OUT PNDIS_STRING pAdapterInstanceName,
  1543. IN NDIS_HANDLE NdisBindingHandle
  1544. )
  1545. {
  1546. PNDIS_OPEN_BLOCK pOpen = (PNDIS_OPEN_BLOCK)NdisBindingHandle;
  1547. PNDIS_MINIPORT_BLOCK Miniport= (PNDIS_MINIPORT_BLOCK)pOpen->MiniportHandle;
  1548. USHORT cbSize;
  1549. PVOID ptmp = NULL;
  1550. NDIS_STATUS Status = NDIS_STATUS_FAILURE;
  1551. NTSTATUS NtStatus;
  1552. PNDIS_STRING pAdapterName;
  1553. DBGPRINT(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1554. ("==>NdisQueryAdapterInstanceName\n"));
  1555. pAdapterName = Miniport->pAdapterInstanceName;
  1556. //
  1557. // If we failed to create the adapter instance name then fail the call.
  1558. //
  1559. if (NULL != pAdapterName)
  1560. {
  1561. //
  1562. // Allocate storage for the copy of the adapter instance name.
  1563. //
  1564. cbSize = pAdapterName->MaximumLength;
  1565. //
  1566. // Allocate storage for the new string.
  1567. //
  1568. ptmp = ALLOC_FROM_POOL(cbSize, NDIS_TAG_NAME_BUF);
  1569. if (NULL != ptmp)
  1570. {
  1571. RtlZeroMemory(ptmp, cbSize);
  1572. pAdapterInstanceName->Buffer = ptmp;
  1573. pAdapterInstanceName->Length = 0;
  1574. pAdapterInstanceName->MaximumLength = cbSize;
  1575. NtStatus = RtlAppendUnicodeStringToString(pAdapterInstanceName, pAdapterName);
  1576. if (NT_SUCCESS(NtStatus))
  1577. {
  1578. Status = NDIS_STATUS_SUCCESS;
  1579. }
  1580. }
  1581. else
  1582. {
  1583. Status = NDIS_STATUS_RESOURCES;
  1584. }
  1585. }
  1586. if (NDIS_STATUS_SUCCESS != Status)
  1587. {
  1588. if (NULL != ptmp)
  1589. {
  1590. FREE_POOL(ptmp);
  1591. }
  1592. }
  1593. DBGPRINT(DBG_COMP_BIND, DBG_LEVEL_INFO,
  1594. ("<==NdisQueryAdapterInstanceName: 0x%x\n", Status));
  1595. return(Status);
  1596. }
  1597. NDIS_STATUS
  1598. ndisCloseAllBindingsOnProtocol(
  1599. PNDIS_PROTOCOL_BLOCK Protocol
  1600. )
  1601. {
  1602. PNDIS_OPEN_BLOCK Open, TmpOpen;
  1603. KIRQL OldIrql;
  1604. NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
  1605. BOOLEAN MoreOpen = TRUE;
  1606. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1607. ("==>ndisCloseAllBindingsOnProtocol: Protocol %p\n", Protocol));
  1608. PnPReferencePackage();
  1609. //
  1610. // loop through all opens on the protocol and find the first one that is
  1611. // not already tagged as getting unbound
  1612. //
  1613. ACQUIRE_SPIN_LOCK(&Protocol->Ref.SpinLock, &OldIrql);
  1614. next:
  1615. for (Open = Protocol->OpenQueue;
  1616. Open != NULL;
  1617. Open = Open->ProtocolNextOpen)
  1618. {
  1619. ACQUIRE_SPIN_LOCK_DPC(&Open->SpinLock);
  1620. if (!MINIPORT_TEST_FLAG(Open, (fMINIPORT_OPEN_CLOSING | fMINIPORT_OPEN_PROCESSING)))
  1621. {
  1622. MINIPORT_SET_FLAG(Open, fMINIPORT_OPEN_PROCESSING);
  1623. if (!MINIPORT_TEST_FLAG(Open, fMINIPORT_OPEN_UNBINDING))
  1624. {
  1625. MINIPORT_SET_FLAG(Open, fMINIPORT_OPEN_UNBINDING | fMINIPORT_OPEN_DONT_FREE);
  1626. RELEASE_SPIN_LOCK_DPC(&Open->SpinLock);
  1627. break;
  1628. }
  1629. #if DBG
  1630. else
  1631. {
  1632. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1633. ("ndisCloseAllBindingsOnProtocol: Open %p is already Closing, Flags %lx\n",
  1634. Open, Open->Flags));
  1635. }
  1636. #endif
  1637. }
  1638. RELEASE_SPIN_LOCK_DPC(&Open->SpinLock);
  1639. }
  1640. if (Open)
  1641. {
  1642. //
  1643. // close the adapter
  1644. //
  1645. RELEASE_SPIN_LOCK(&Protocol->Ref.SpinLock, OldIrql);
  1646. Status = ndisUnbindProtocol(Open, FALSE);
  1647. ASSERT(Status == NDIS_STATUS_SUCCESS);
  1648. ACQUIRE_SPIN_LOCK(&Protocol->Ref.SpinLock, &OldIrql);
  1649. goto next;
  1650. }
  1651. //
  1652. // if we reached the end of the list but there are still some opens
  1653. // that are not marked for closing (can happen if we skip an open only because of
  1654. // processign flag being set) release the spinlocks, give whoever set the
  1655. // processing flag time to release the open. then go back and try again
  1656. // ultimately, all opens should either be marked for Unbinding or be gone
  1657. // by themselves
  1658. //
  1659. for (TmpOpen = Protocol->OpenQueue;
  1660. TmpOpen != NULL;
  1661. TmpOpen = TmpOpen->ProtocolNextOpen)
  1662. {
  1663. if (!MINIPORT_TEST_FLAG(TmpOpen, fMINIPORT_OPEN_UNBINDING))
  1664. break;
  1665. }
  1666. if (TmpOpen != NULL)
  1667. {
  1668. RELEASE_SPIN_LOCK(&Protocol->Ref.SpinLock, OldIrql);
  1669. NDIS_INTERNAL_STALL(50);
  1670. ACQUIRE_SPIN_LOCK(&Protocol->Ref.SpinLock, &OldIrql);
  1671. goto next;
  1672. }
  1673. RELEASE_SPIN_LOCK(&Protocol->Ref.SpinLock, OldIrql);
  1674. PnPDereferencePackage();
  1675. DBGPRINT_RAW(DBG_COMP_PROTOCOL, DBG_LEVEL_INFO,
  1676. ("<==ndisCloseAllBindingsOnProtocol: Protocol %p, Status %lx\n", Protocol, Status));
  1677. return Status;
  1678. }
  1679. VOID
  1680. NdisSetPacketCancelId(
  1681. IN PNDIS_PACKET Packet,
  1682. IN PVOID CancelId
  1683. )
  1684. {
  1685. NDIS_SET_PACKET_CANCEL_ID(Packet, CancelId);
  1686. return;
  1687. }
  1688. PVOID
  1689. NdisGetPacketCancelId(
  1690. IN PNDIS_PACKET Packet
  1691. )
  1692. {
  1693. return NDIS_GET_PACKET_CANCEL_ID(Packet);
  1694. }
  1695. VOID
  1696. NdisCancelSendPackets(
  1697. IN NDIS_HANDLE NdisBindingHandle,
  1698. IN PVOID CancelId
  1699. )
  1700. {
  1701. PNDIS_OPEN_BLOCK Open = (PNDIS_OPEN_BLOCK)NdisBindingHandle;
  1702. KIRQL OldIrql;
  1703. ASSERT(CancelId != NULL);
  1704. //
  1705. // call Miniport's CancelSendPackets handler
  1706. //
  1707. if (!MINIPORT_TEST_FLAG(Open->MiniportHandle, fMINIPORT_DESERIALIZE))
  1708. {
  1709. //
  1710. // for serialized miniports, check our send queue and cancel the packets
  1711. //
  1712. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Open->MiniportHandle, &OldIrql);
  1713. ndisMAbortPackets(Open->MiniportHandle, Open, CancelId);
  1714. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Open->MiniportHandle, OldIrql);
  1715. }
  1716. else if (Open->CancelSendPacketsHandler != NULL)
  1717. {
  1718. Open->CancelSendPacketsHandler(Open->MiniportAdapterContext, CancelId);
  1719. }
  1720. return;
  1721. }
  1722. NDIS_STATUS
  1723. NdisQueryPendingIOCount(
  1724. IN PVOID NdisBindingHandle,
  1725. IN OUT PULONG IoCount
  1726. )
  1727. {
  1728. PNDIS_OPEN_BLOCK Open = (PNDIS_OPEN_BLOCK)NdisBindingHandle;
  1729. PNDIS_MINIPORT_BLOCK Miniport = Open->MiniportHandle;
  1730. ULONG RefCount;
  1731. NDIS_STATUS Status;
  1732. KIRQL OldIrql;
  1733. ACQUIRE_SPIN_LOCK(&Open->SpinLock, &OldIrql);
  1734. if (MINIPORT_TEST_FLAG(Open, fMINIPORT_OPEN_CLOSING))
  1735. {
  1736. RefCount = 0;
  1737. Status = NDIS_STATUS_CLOSING;
  1738. }
  1739. else
  1740. {
  1741. RefCount = Open->References - Open->AfReferences -1;
  1742. Status = NDIS_STATUS_SUCCESS;
  1743. }
  1744. *IoCount = RefCount;
  1745. RELEASE_SPIN_LOCK(&Open->SpinLock, OldIrql);
  1746. return Status;
  1747. }
  1748. UCHAR
  1749. NdisGeneratePartialCancelId(
  1750. VOID
  1751. )
  1752. {
  1753. return (UCHAR)(InterlockedIncrement(&ndisCancelId) & 0xFF);
  1754. }