Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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