PageRenderTime 49ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/kernel/win/ndisbind.c

https://github.com/daedalus/tcpcrypt
C | 2204 lines | 1122 code | 354 blank | 728 comment | 136 complexity | 2552dea1d61b3d2790b89b22ed1a08cb MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. ndisbind.c
  5. Abstract:
  6. NDIS protocol entry points and utility routines to handle binding
  7. and unbinding from adapters.
  8. Environment:
  9. Kernel mode only.
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #define __FILENUMBER 'DNIB'
  14. VOID
  15. NdisProtBindAdapter(
  16. OUT PNDIS_STATUS pStatus,
  17. IN NDIS_HANDLE BindContext,
  18. IN PNDIS_STRING pDeviceName,
  19. IN PVOID SystemSpecific1,
  20. IN PVOID SystemSpecific2
  21. )
  22. /*++
  23. Routine Description:
  24. Protocol Bind Handler entry point called when NDIS wants us
  25. to bind to an adapter. We go ahead and set up a binding.
  26. An OPEN_CONTEXT structure is allocated to keep state about
  27. this binding.
  28. Arguments:
  29. pStatus - place to return bind status
  30. BindContext - handle to use with NdisCompleteBindAdapter
  31. DeviceName - adapter to bind to
  32. SystemSpecific1 - used to access protocol-specific registry
  33. key for this binding
  34. SystemSpecific2 - unused
  35. Return Value:
  36. None
  37. --*/
  38. {
  39. PNDISPROT_OPEN_CONTEXT pOpenContext;
  40. NDIS_STATUS Status, ConfigStatus;
  41. NDIS_HANDLE ConfigHandle;
  42. UNREFERENCED_PARAMETER(BindContext);
  43. UNREFERENCED_PARAMETER(SystemSpecific2);
  44. do
  45. {
  46. //
  47. // Allocate our context for this open.
  48. //
  49. NPROT_ALLOC_MEM(pOpenContext, sizeof(NDISPROT_OPEN_CONTEXT));
  50. if (pOpenContext == NULL)
  51. {
  52. Status = NDIS_STATUS_RESOURCES;
  53. break;
  54. }
  55. //
  56. // Initialize it.
  57. //
  58. NPROT_ZERO_MEM(pOpenContext, sizeof(NDISPROT_OPEN_CONTEXT));
  59. NPROT_SET_SIGNATURE(pOpenContext, oc);
  60. NPROT_INIT_LOCK(&pOpenContext->Lock);
  61. NPROT_INIT_LIST_HEAD(&pOpenContext->PendedReads);
  62. NPROT_INIT_LIST_HEAD(&pOpenContext->PendedWrites);
  63. NPROT_INIT_LIST_HEAD(&pOpenContext->RecvPktQueue);
  64. NPROT_INIT_EVENT(&pOpenContext->PoweredUpEvent);
  65. //
  66. // Start off by assuming that the device below is powered up.
  67. //
  68. NPROT_SIGNAL_EVENT(&pOpenContext->PoweredUpEvent);
  69. //
  70. // Determine the platform we are running on.
  71. //
  72. pOpenContext->bRunningOnWin9x = TRUE;
  73. NdisOpenProtocolConfiguration(
  74. &ConfigStatus,
  75. &ConfigHandle,
  76. (PNDIS_STRING)SystemSpecific1);
  77. if (ConfigStatus == NDIS_STATUS_SUCCESS)
  78. {
  79. PNDIS_CONFIGURATION_PARAMETER pParameter;
  80. NDIS_STRING VersionKey = NDIS_STRING_CONST("Environment");
  81. NdisReadConfiguration(
  82. &ConfigStatus,
  83. &pParameter,
  84. ConfigHandle,
  85. &VersionKey,
  86. NdisParameterInteger);
  87. if ((ConfigStatus == NDIS_STATUS_SUCCESS) &&
  88. ((pParameter->ParameterType == NdisParameterInteger) ||
  89. (pParameter->ParameterType == NdisParameterHexInteger)))
  90. {
  91. pOpenContext->bRunningOnWin9x =
  92. (pParameter->ParameterData.IntegerData == NdisEnvironmentWindows);
  93. }
  94. NdisCloseConfiguration(ConfigHandle);
  95. }
  96. NPROT_REF_OPEN(pOpenContext); // Bind
  97. //
  98. // Add it to the global list.
  99. //
  100. NPROT_ACQUIRE_LOCK(&Globals.GlobalLock);
  101. NPROT_INSERT_TAIL_LIST(&Globals.OpenList,
  102. &pOpenContext->Link);
  103. NPROT_RELEASE_LOCK(&Globals.GlobalLock);
  104. //
  105. // Set up the NDIS binding.
  106. //
  107. Status = ndisprotCreateBinding(
  108. pOpenContext,
  109. (PUCHAR)pDeviceName->Buffer,
  110. pDeviceName->Length);
  111. if (Status != NDIS_STATUS_SUCCESS)
  112. {
  113. break;
  114. }
  115. }
  116. while (FALSE);
  117. *pStatus = Status;
  118. return;
  119. }
  120. VOID
  121. NdisProtOpenAdapterComplete(
  122. IN NDIS_HANDLE ProtocolBindingContext,
  123. IN NDIS_STATUS Status,
  124. IN NDIS_STATUS OpenErrorCode
  125. )
  126. /*++
  127. Routine Description:
  128. Completion routine called by NDIS if our call to NdisOpenAdapter
  129. pends. Wake up the thread that called NdisOpenAdapter.
  130. Arguments:
  131. ProtocolBindingContext - pointer to open context structure
  132. Status - status of the open
  133. OpenErrorCode - if unsuccessful, additional information
  134. Return Value:
  135. None
  136. --*/
  137. {
  138. PNDISPROT_OPEN_CONTEXT pOpenContext;
  139. UNREFERENCED_PARAMETER(OpenErrorCode);
  140. pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext;
  141. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  142. pOpenContext->BindStatus = Status;
  143. NPROT_SIGNAL_EVENT(&pOpenContext->BindEvent);
  144. }
  145. VOID
  146. NdisProtUnbindAdapter(
  147. OUT PNDIS_STATUS pStatus,
  148. IN NDIS_HANDLE ProtocolBindingContext,
  149. IN NDIS_HANDLE UnbindContext
  150. )
  151. /*++
  152. Routine Description:
  153. NDIS calls this when it wants us to close the binding to an adapter.
  154. Arguments:
  155. pStatus - place to return status of Unbind
  156. ProtocolBindingContext - pointer to open context structure
  157. UnbindContext - to use in NdisCompleteUnbindAdapter if we return pending
  158. Return Value:
  159. None
  160. --*/
  161. {
  162. PNDISPROT_OPEN_CONTEXT pOpenContext;
  163. UNREFERENCED_PARAMETER(UnbindContext);
  164. pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext;
  165. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  166. //
  167. // Mark this open as having seen an Unbind.
  168. //
  169. NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
  170. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_UNBIND_FLAGS, NUIOO_UNBIND_RECEIVED);
  171. //
  172. // In case we had threads blocked for the device below to be powered
  173. // up, wake them up.
  174. //
  175. NPROT_SIGNAL_EVENT(&pOpenContext->PoweredUpEvent);
  176. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  177. ndisprotShutdownBinding(pOpenContext);
  178. *pStatus = NDIS_STATUS_SUCCESS;
  179. return;
  180. }
  181. VOID
  182. NdisProtCloseAdapterComplete(
  183. IN NDIS_HANDLE ProtocolBindingContext,
  184. IN NDIS_STATUS Status
  185. )
  186. /*++
  187. Routine Description:
  188. Called by NDIS to complete a pended call to NdisCloseAdapter.
  189. We wake up the thread waiting for this completion.
  190. Arguments:
  191. ProtocolBindingContext - pointer to open context structure
  192. Status - Completion status of NdisCloseAdapter
  193. Return Value:
  194. None
  195. --*/
  196. {
  197. PNDISPROT_OPEN_CONTEXT pOpenContext;
  198. pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext;
  199. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  200. pOpenContext->BindStatus = Status;
  201. NPROT_SIGNAL_EVENT(&pOpenContext->BindEvent);
  202. }
  203. NDIS_STATUS
  204. NdisProtPnPEventHandler(
  205. IN NDIS_HANDLE ProtocolBindingContext,
  206. IN PNET_PNP_EVENT pNetPnPEvent
  207. )
  208. /*++
  209. Routine Description:
  210. Called by NDIS to notify us of a PNP event. The most significant
  211. one for us is power state change.
  212. Arguments:
  213. ProtocolBindingContext - pointer to open context structure
  214. this is NULL for global reconfig events.
  215. pNetPnPEvent - pointer to the PNP event
  216. Return Value:
  217. Our processing status for the PNP event.
  218. --*/
  219. {
  220. PNDISPROT_OPEN_CONTEXT pOpenContext;
  221. NDIS_STATUS Status;
  222. pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext;
  223. switch (pNetPnPEvent->NetEvent)
  224. {
  225. case NetEventSetPower:
  226. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  227. pOpenContext->PowerState = *(PNET_DEVICE_POWER_STATE)pNetPnPEvent->Buffer;
  228. if (pOpenContext->PowerState > NetDeviceStateD0)
  229. {
  230. //
  231. // The device below is transitioning to a low power state.
  232. // Block any threads attempting to query the device while
  233. // in this state.
  234. //
  235. NPROT_INIT_EVENT(&pOpenContext->PoweredUpEvent);
  236. //
  237. // Wait for any I/O in progress to complete.
  238. //
  239. ndisprotWaitForPendingIO(pOpenContext, FALSE);
  240. //
  241. // Return any receives that we had queued up.
  242. //
  243. ndisprotFlushReceiveQueue(pOpenContext);
  244. DEBUGP(DL_INFO, ("PnPEvent: Open %p, SetPower to %d\n",
  245. pOpenContext, pOpenContext->PowerState));
  246. }
  247. else
  248. {
  249. //
  250. // The device below is powered up.
  251. //
  252. DEBUGP(DL_INFO, ("PnPEvent: Open %p, SetPower ON: %d\n",
  253. pOpenContext, pOpenContext->PowerState));
  254. NPROT_SIGNAL_EVENT(&pOpenContext->PoweredUpEvent);
  255. }
  256. Status = NDIS_STATUS_SUCCESS;
  257. break;
  258. case NetEventQueryPower:
  259. Status = NDIS_STATUS_SUCCESS;
  260. break;
  261. case NetEventBindsComplete:
  262. NPROT_SIGNAL_EVENT(&Globals.BindsComplete);
  263. if(!ndisprotRegisterExCallBack()){
  264. DEBUGP(DL_ERROR, ("DriverEntry: ndisprotRegisterExCallBack failed\n"));
  265. }
  266. Status = NDIS_STATUS_SUCCESS;
  267. break;
  268. case NetEventQueryRemoveDevice:
  269. case NetEventCancelRemoveDevice:
  270. case NetEventReconfigure:
  271. case NetEventBindList:
  272. case NetEventPnPCapabilities:
  273. Status = NDIS_STATUS_SUCCESS;
  274. break;
  275. default:
  276. Status = NDIS_STATUS_NOT_SUPPORTED;
  277. break;
  278. }
  279. DEBUGP(DL_INFO, ("PnPEvent: Open %p, Event %d, Status %x\n",
  280. pOpenContext, pNetPnPEvent->NetEvent, Status));
  281. return (Status);
  282. }
  283. VOID
  284. NdisProtProtocolUnloadHandler(
  285. VOID
  286. )
  287. /*++
  288. Routine Description:
  289. NDIS calls this on a usermode request to uninstall us.
  290. Arguments:
  291. None
  292. Return Value:
  293. None
  294. --*/
  295. {
  296. ndisprotDoProtocolUnload();
  297. }
  298. NDIS_STATUS
  299. ndisprotCreateBinding(
  300. IN PNDISPROT_OPEN_CONTEXT pOpenContext,
  301. __in_bcount(BindingInfoLength) IN PUCHAR pBindingInfo,
  302. IN ULONG BindingInfoLength
  303. )
  304. /*++
  305. Routine Description:
  306. Utility function to create an NDIS binding to the indicated device,
  307. if no such binding exists.
  308. Here is where we also allocate additional resources (e.g. packet pool)
  309. for the binding.
  310. Things to take care of:
  311. 1. Is another thread doing this (or has finished binding) already?
  312. 2. Is the binding being closed at this time?
  313. 3. NDIS calls our Unbind handler while we are doing this.
  314. These precautions are not needed if this routine is only called from
  315. the context of our BindAdapter handler, but they are here in case
  316. we initiate binding from elsewhere (e.g. on processing a user command).
  317. NOTE: this function blocks and finishes synchronously.
  318. Arguments:
  319. pOpenContext - pointer to open context block
  320. pBindingInfo - pointer to unicode device name string
  321. BindingInfoLength - length in bytes of the above.
  322. Return Value:
  323. NDIS_STATUS_SUCCESS if a binding was successfully set up.
  324. NDIS_STATUS_XXX error code on any failure.
  325. --*/
  326. {
  327. NDIS_STATUS Status;
  328. NDIS_STATUS OpenErrorCode;
  329. NDIS_MEDIUM MediumArray[1] = {NdisMedium802_3};
  330. UINT SelectedMediumIndex;
  331. PNDISPROT_OPEN_CONTEXT pTmpOpenContext;
  332. BOOLEAN fDoNotDisturb = FALSE;
  333. BOOLEAN fOpenComplete = FALSE;
  334. ULONG BytesProcessed;
  335. ULONG GenericUlong = 0;
  336. DEBUGP(DL_LOUD, ("CreateBinding: open %p/%x, device [%s]\n",
  337. pOpenContext, pOpenContext->Flags, pBindingInfo));
  338. Status = NDIS_STATUS_SUCCESS;
  339. do
  340. {
  341. //
  342. // Check if we already have a binding to this device.
  343. //
  344. pTmpOpenContext = ndisprotLookupDevice(pBindingInfo, BindingInfoLength);
  345. if (pTmpOpenContext != NULL)
  346. {
  347. DEBUGP(DL_WARN,
  348. ("CreateBinding: Binding to device %ws already exists on open %p\n",
  349. pTmpOpenContext->DeviceName.Buffer, pTmpOpenContext));
  350. NPROT_DEREF_OPEN(pTmpOpenContext); // temp ref added by Lookup
  351. Status = NDIS_STATUS_FAILURE;
  352. break;
  353. }
  354. NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
  355. //
  356. // Check if this open context is already bound/binding/closing.
  357. //
  358. if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_IDLE) ||
  359. NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_UNBIND_FLAGS, NUIOO_UNBIND_RECEIVED))
  360. {
  361. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  362. Status = NDIS_STATUS_NOT_ACCEPTED;
  363. //
  364. // Make sure we don't abort this binding on failure cleanup.
  365. //
  366. fDoNotDisturb = TRUE;
  367. break;
  368. }
  369. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_OPENING);
  370. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  371. //
  372. // Copy in the device name. Add room for a NULL terminator.
  373. //
  374. NPROT_ALLOC_MEM(pOpenContext->DeviceName.Buffer, BindingInfoLength + sizeof(WCHAR));
  375. if (pOpenContext->DeviceName.Buffer == NULL)
  376. {
  377. DEBUGP(DL_WARN, ("CreateBinding: failed to alloc device name buf (%d bytes)\n",
  378. BindingInfoLength + sizeof(WCHAR)));
  379. Status = NDIS_STATUS_RESOURCES;
  380. break;
  381. }
  382. NPROT_COPY_MEM(pOpenContext->DeviceName.Buffer, pBindingInfo, BindingInfoLength);
  383. #pragma prefast(suppress: 12009, "DeviceName length will not cause overflow")
  384. *(PWCHAR)((PUCHAR)pOpenContext->DeviceName.Buffer + BindingInfoLength) = L'\0';
  385. NdisInitUnicodeString(&pOpenContext->DeviceName, pOpenContext->DeviceName.Buffer);
  386. //
  387. // Allocate packet pools.
  388. //
  389. NdisAllocatePacketPoolEx(
  390. &Status,
  391. &pOpenContext->SendPacketPool,
  392. MIN_SEND_PACKET_POOL_SIZE,
  393. MAX_SEND_PACKET_POOL_SIZE - MIN_SEND_PACKET_POOL_SIZE,
  394. sizeof(NPROT_SEND_PACKET_RSVD));
  395. if (Status != NDIS_STATUS_SUCCESS)
  396. {
  397. DEBUGP(DL_WARN, ("CreateBinding: failed to alloc"
  398. " send packet pool: %x\n", Status));
  399. break;
  400. }
  401. NdisAllocatePacketPoolEx(
  402. &Status,
  403. &pOpenContext->RecvPacketPool,
  404. MIN_RECV_PACKET_POOL_SIZE,
  405. MAX_RECV_PACKET_POOL_SIZE - MIN_RECV_PACKET_POOL_SIZE,
  406. sizeof(NPROT_RECV_PACKET_RSVD));
  407. if (Status != NDIS_STATUS_SUCCESS)
  408. {
  409. DEBUGP(DL_WARN, ("CreateBinding: failed to alloc"
  410. " recv packet pool: %x\n", Status));
  411. break;
  412. }
  413. //
  414. // Buffer pool for receives.
  415. //
  416. NdisAllocateBufferPool(
  417. &Status,
  418. &pOpenContext->RecvBufferPool,
  419. MAX_RECV_PACKET_POOL_SIZE);
  420. if (Status != NDIS_STATUS_SUCCESS)
  421. {
  422. DEBUGP(DL_WARN, ("CreateBinding: failed to alloc"
  423. " recv buffer pool: %x\n", Status));
  424. break;
  425. }
  426. //
  427. // If we are running on Win9X, allocate a buffer pool for sends
  428. // as well, since we can't simply cast MDLs to NDIS_BUFFERs.
  429. //
  430. if (pOpenContext->bRunningOnWin9x)
  431. {
  432. NdisAllocateBufferPool(
  433. &Status,
  434. &pOpenContext->SendBufferPool,
  435. MAX_SEND_PACKET_POOL_SIZE);
  436. if (Status != NDIS_STATUS_SUCCESS)
  437. {
  438. DEBUGP(DL_WARN, ("CreateBinding: failed to alloc"
  439. " send buffer pool: %x\n", Status));
  440. break;
  441. }
  442. }
  443. //
  444. // Assume that the device is powered up.
  445. //
  446. pOpenContext->PowerState = NetDeviceStateD0;
  447. //
  448. // Open the adapter.
  449. //
  450. NPROT_INIT_EVENT(&pOpenContext->BindEvent);
  451. NdisOpenAdapter(
  452. &Status,
  453. &OpenErrorCode,
  454. &pOpenContext->BindingHandle,
  455. &SelectedMediumIndex,
  456. &MediumArray[0],
  457. sizeof(MediumArray) / sizeof(NDIS_MEDIUM),
  458. Globals.NdisProtocolHandle,
  459. (NDIS_HANDLE)pOpenContext,
  460. &pOpenContext->DeviceName,
  461. 0,
  462. NULL);
  463. if (Status == NDIS_STATUS_PENDING)
  464. {
  465. NPROT_WAIT_EVENT(&pOpenContext->BindEvent, 0);
  466. Status = pOpenContext->BindStatus;
  467. }
  468. if (Status != NDIS_STATUS_SUCCESS)
  469. {
  470. DEBUGP(DL_WARN, ("CreateBinding: NdisOpenAdapter (%ws) failed: %x\n",
  471. pOpenContext->DeviceName.Buffer, Status));
  472. break;
  473. }
  474. //
  475. // Note down the fact that we have successfully bound.
  476. // We don't update the state on the open just yet - this
  477. // is to prevent other threads from shutting down the binding.
  478. //
  479. fOpenComplete = TRUE;
  480. //
  481. // Get the friendly name for the adapter. It is not fatal for this
  482. // to fail.
  483. //
  484. (VOID)NdisQueryAdapterInstanceName(
  485. &pOpenContext->DeviceDescr,
  486. pOpenContext->BindingHandle
  487. );
  488. //
  489. // Get Current address
  490. //
  491. Status = ndisprotDoRequest(
  492. pOpenContext,
  493. NdisRequestQueryInformation,
  494. OID_802_3_CURRENT_ADDRESS,
  495. &pOpenContext->CurrentAddress[0],
  496. NPROT_MAC_ADDR_LEN,
  497. &BytesProcessed
  498. );
  499. if (Status != NDIS_STATUS_SUCCESS)
  500. {
  501. DEBUGP(DL_WARN, ("CreateBinding: qry current address failed: %x\n",
  502. Status));
  503. break;
  504. }
  505. //
  506. // Get MAC options.
  507. //
  508. Status = ndisprotDoRequest(
  509. pOpenContext,
  510. NdisRequestQueryInformation,
  511. OID_GEN_MAC_OPTIONS,
  512. &pOpenContext->MacOptions,
  513. sizeof(pOpenContext->MacOptions),
  514. &BytesProcessed
  515. );
  516. if (Status != NDIS_STATUS_SUCCESS)
  517. {
  518. DEBUGP(DL_WARN, ("CreateBinding: qry MAC options failed: %x\n",
  519. Status));
  520. break;
  521. }
  522. //
  523. // Get the max frame size.
  524. //
  525. Status = ndisprotDoRequest(
  526. pOpenContext,
  527. NdisRequestQueryInformation,
  528. OID_GEN_MAXIMUM_FRAME_SIZE,
  529. &pOpenContext->MaxFrameSize,
  530. sizeof(pOpenContext->MaxFrameSize),
  531. &BytesProcessed
  532. );
  533. if (Status != NDIS_STATUS_SUCCESS)
  534. {
  535. DEBUGP(DL_WARN, ("CreateBinding: qry max frame failed: %x\n",
  536. Status));
  537. break;
  538. }
  539. //
  540. // Get the media connect status.
  541. //
  542. Status = ndisprotDoRequest(
  543. pOpenContext,
  544. NdisRequestQueryInformation,
  545. OID_GEN_MEDIA_CONNECT_STATUS,
  546. &GenericUlong,
  547. sizeof(GenericUlong),
  548. &BytesProcessed
  549. );
  550. if (Status != NDIS_STATUS_SUCCESS)
  551. {
  552. DEBUGP(DL_WARN, ("CreateBinding: qry media connect status failed: %x\n",
  553. Status));
  554. break;
  555. }
  556. if (GenericUlong == NdisMediaStateConnected)
  557. {
  558. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_MEDIA_FLAGS, NUIOO_MEDIA_CONNECTED);
  559. }
  560. else
  561. {
  562. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_MEDIA_FLAGS, NUIOO_MEDIA_DISCONNECTED);
  563. }
  564. //
  565. // Mark this open. Also check if we received an Unbind while
  566. // we were setting this up.
  567. //
  568. NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
  569. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE);
  570. //
  571. // Did an unbind happen in the meantime?
  572. //
  573. if (NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_UNBIND_FLAGS, NUIOO_UNBIND_RECEIVED))
  574. {
  575. Status = NDIS_STATUS_FAILURE;
  576. }
  577. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  578. }
  579. while (FALSE);
  580. if ((Status != NDIS_STATUS_SUCCESS) && !fDoNotDisturb)
  581. {
  582. NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
  583. //
  584. // Check if we had actually finished opening the adapter.
  585. //
  586. if (fOpenComplete)
  587. {
  588. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE);
  589. }
  590. else if (NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_OPENING))
  591. {
  592. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_FAILED);
  593. }
  594. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  595. ndisprotShutdownBinding(pOpenContext);
  596. }
  597. DEBUGP(DL_INFO, ("CreateBinding: OpenContext %p, Status %x\n",
  598. pOpenContext, Status));
  599. return (Status);
  600. }
  601. VOID
  602. ndisprotShutdownBinding(
  603. IN PNDISPROT_OPEN_CONTEXT pOpenContext
  604. )
  605. /*++
  606. Routine Description:
  607. Utility function to shut down the NDIS binding, if one exists, on
  608. the specified open. This is written to be called from:
  609. ndisprotCreateBinding - on failure
  610. NdisProtUnbindAdapter
  611. We handle the case where a binding is in the process of being set up.
  612. This precaution is not needed if this routine is only called from
  613. the context of our UnbindAdapter handler, but they are here in case
  614. we initiate unbinding from elsewhere (e.g. on processing a user command).
  615. NOTE: this blocks and finishes synchronously.
  616. Arguments:
  617. pOpenContext - pointer to open context block
  618. Return Value:
  619. None
  620. --*/
  621. {
  622. NDIS_STATUS Status;
  623. PVOID StatusBuffer;
  624. BOOLEAN DoCloseBinding = FALSE;
  625. do
  626. {
  627. NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
  628. if (NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_OPENING))
  629. {
  630. //
  631. // We are still in the process of setting up this binding.
  632. //
  633. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  634. break;
  635. }
  636. if (NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE))
  637. {
  638. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_CLOSING);
  639. DoCloseBinding = TRUE;
  640. }
  641. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  642. if (DoCloseBinding)
  643. {
  644. ULONG PacketFilter = 0;
  645. ULONG BytesRead = 0;
  646. //
  647. // Set Packet filter to 0 before closing the binding
  648. //
  649. Status = ndisprotDoRequest(
  650. pOpenContext,
  651. NdisRequestSetInformation,
  652. OID_GEN_CURRENT_PACKET_FILTER,
  653. &PacketFilter,
  654. sizeof(PacketFilter),
  655. &BytesRead);
  656. if (Status != NDIS_STATUS_SUCCESS)
  657. {
  658. DEBUGP(DL_WARN, ("ShutDownBinding: set packet filter failed: %x\n", Status));
  659. }
  660. //
  661. // Set multicast list to null before closing the binding
  662. //
  663. Status = ndisprotDoRequest(
  664. pOpenContext,
  665. NdisRequestSetInformation,
  666. OID_802_3_MULTICAST_LIST,
  667. NULL,
  668. 0,
  669. &BytesRead);
  670. if (Status != NDIS_STATUS_SUCCESS)
  671. {
  672. DEBUGP(DL_WARN, ("ShutDownBinding: set multicast list failed: %x\n", Status));
  673. }
  674. //
  675. // Cancel pending control irp for status indication.
  676. //
  677. StatusBuffer=NULL;
  678. ndisServiceIndicateStatusIrp(pOpenContext,
  679. 0,
  680. StatusBuffer,
  681. 0,
  682. TRUE);
  683. //
  684. // Wait for any pending sends or requests on
  685. // the binding to complete.
  686. //
  687. ndisprotWaitForPendingIO(pOpenContext, TRUE);
  688. //
  689. // Discard any queued receives.
  690. //
  691. ndisprotFlushReceiveQueue(pOpenContext);
  692. //
  693. // Close the binding now.
  694. //
  695. NPROT_INIT_EVENT(&pOpenContext->BindEvent);
  696. DEBUGP(DL_INFO, ("ShutdownBinding: Closing OpenContext %p,"
  697. " BindingHandle %p\n",
  698. pOpenContext, pOpenContext->BindingHandle));
  699. NdisCloseAdapter(&Status, pOpenContext->BindingHandle);
  700. if (Status == NDIS_STATUS_PENDING)
  701. {
  702. NPROT_WAIT_EVENT(&pOpenContext->BindEvent, 0);
  703. Status = pOpenContext->BindStatus;
  704. }
  705. NPROT_ASSERT(Status == NDIS_STATUS_SUCCESS);
  706. pOpenContext->BindingHandle = NULL;
  707. }
  708. if (DoCloseBinding)
  709. {
  710. NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
  711. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_IDLE);
  712. NPROT_SET_FLAGS(pOpenContext->Flags, NUIOO_UNBIND_FLAGS, 0);
  713. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  714. }
  715. //
  716. // Remove it from the global list.
  717. //
  718. NPROT_ACQUIRE_LOCK(&Globals.GlobalLock);
  719. NPROT_REMOVE_ENTRY_LIST(&pOpenContext->Link);
  720. NPROT_RELEASE_LOCK(&Globals.GlobalLock);
  721. //
  722. // Free any other resources allocated for this bind.
  723. //
  724. ndisprotFreeBindResources(pOpenContext);
  725. NPROT_DEREF_OPEN(pOpenContext); // Shutdown binding
  726. }
  727. while (FALSE);
  728. }
  729. VOID
  730. ndisprotFreeBindResources(
  731. IN PNDISPROT_OPEN_CONTEXT pOpenContext
  732. )
  733. /*++
  734. Routine Description:
  735. Free any resources set up for an NDIS binding.
  736. Arguments:
  737. pOpenContext - pointer to open context block
  738. Return Value:
  739. None
  740. --*/
  741. {
  742. if (pOpenContext->SendPacketPool != NULL)
  743. {
  744. NdisFreePacketPool(pOpenContext->SendPacketPool);
  745. pOpenContext->SendPacketPool = NULL;
  746. }
  747. if (pOpenContext->RecvPacketPool != NULL)
  748. {
  749. NdisFreePacketPool(pOpenContext->RecvPacketPool);
  750. pOpenContext->RecvPacketPool = NULL;
  751. }
  752. if (pOpenContext->RecvBufferPool != NULL)
  753. {
  754. NdisFreeBufferPool(pOpenContext->RecvBufferPool);
  755. pOpenContext->RecvBufferPool = NULL;
  756. }
  757. if (pOpenContext->SendBufferPool != NULL)
  758. {
  759. NdisFreeBufferPool(pOpenContext->SendBufferPool);
  760. pOpenContext->SendBufferPool = NULL;
  761. }
  762. if (pOpenContext->DeviceName.Buffer != NULL)
  763. {
  764. NPROT_FREE_MEM(pOpenContext->DeviceName.Buffer);
  765. pOpenContext->DeviceName.Buffer = NULL;
  766. pOpenContext->DeviceName.Length =
  767. pOpenContext->DeviceName.MaximumLength = 0;
  768. }
  769. if (pOpenContext->DeviceDescr.Buffer != NULL)
  770. {
  771. //
  772. // this would have been allocated by NdisQueryAdpaterInstanceName.
  773. //
  774. NdisFreeMemory(pOpenContext->DeviceDescr.Buffer, 0, 0);
  775. pOpenContext->DeviceDescr.Buffer = NULL;
  776. }
  777. }
  778. VOID
  779. ndisprotWaitForPendingIO(
  780. IN PNDISPROT_OPEN_CONTEXT pOpenContext,
  781. IN BOOLEAN DoCancelReads
  782. )
  783. /*++
  784. Routine Description:
  785. Utility function to wait for all outstanding I/O to complete
  786. on an open context. It is assumed that the open context
  787. won't go away while we are in this routine.
  788. Arguments:
  789. pOpenContext - pointer to open context structure
  790. DoCancelReads - do we wait for pending reads to go away (and cancel them)?
  791. Return Value:
  792. None
  793. --*/
  794. {
  795. NDIS_STATUS Status;
  796. ULONG LoopCount;
  797. ULONG PendingCount;
  798. #ifdef NDIS51
  799. //
  800. // Wait for any pending sends or requests on the binding to complete.
  801. //
  802. for (LoopCount = 0; LoopCount < 60; LoopCount++)
  803. {
  804. PendingCount=0;
  805. Status = NdisQueryPendingIOCount(
  806. pOpenContext->BindingHandle,
  807. &PendingCount);
  808. if ((Status != NDIS_STATUS_SUCCESS) ||
  809. (PendingCount == 0))
  810. {
  811. break;
  812. }
  813. DEBUGP(DL_INFO, ("WaitForPendingIO: Open %p, %d pending I/O at NDIS\n",
  814. pOpenContext, PendingCount));
  815. NPROT_SLEEP(2);
  816. }
  817. NPROT_ASSERT(LoopCount < 60);
  818. #endif // NDIS51
  819. //
  820. // Make sure any threads trying to send have finished.
  821. //
  822. for (LoopCount = 0; LoopCount < 60; LoopCount++)
  823. {
  824. if (pOpenContext->PendedSendCount == 0)
  825. {
  826. break;
  827. }
  828. DEBUGP(DL_WARN, ("WaitForPendingIO: Open %p, %d pended sends\n",
  829. pOpenContext, pOpenContext->PendedSendCount));
  830. NPROT_SLEEP(1);
  831. }
  832. NPROT_ASSERT(LoopCount < 60);
  833. if (DoCancelReads)
  834. {
  835. //
  836. // Wait for any pended reads to complete/cancel.
  837. //
  838. while (pOpenContext->PendedReadCount != 0)
  839. {
  840. DEBUGP(DL_INFO, ("WaitForPendingIO: Open %p, %d pended reads\n",
  841. pOpenContext, pOpenContext->PendedReadCount));
  842. //
  843. // Cancel any pending reads.
  844. //
  845. ndisprotCancelPendingReads(pOpenContext);
  846. NPROT_SLEEP(1);
  847. }
  848. }
  849. }
  850. VOID
  851. ndisprotDoProtocolUnload(
  852. VOID
  853. )
  854. /*++
  855. Routine Description:
  856. Utility routine to handle unload from the NDIS protocol side.
  857. Arguments:
  858. None
  859. Return Value:
  860. None
  861. --*/
  862. {
  863. NDIS_HANDLE ProtocolHandle;
  864. NDIS_STATUS Status;
  865. DEBUGP(DL_INFO, ("ProtocolUnload: ProtocolHandle %lp\n",
  866. Globals.NdisProtocolHandle));
  867. if (Globals.NdisProtocolHandle != NULL)
  868. {
  869. ProtocolHandle = Globals.NdisProtocolHandle;
  870. Globals.NdisProtocolHandle = NULL;
  871. NdisDeregisterProtocol(
  872. &Status,
  873. ProtocolHandle
  874. );
  875. if( Status != NDIS_STATUS_SUCCESS ){
  876. //you may do something
  877. }
  878. }
  879. }
  880. NDIS_STATUS
  881. ndisprotDoRequest(
  882. IN PNDISPROT_OPEN_CONTEXT pOpenContext,
  883. IN NDIS_REQUEST_TYPE RequestType,
  884. IN NDIS_OID Oid,
  885. IN PVOID InformationBuffer,
  886. IN ULONG InformationBufferLength,
  887. OUT PULONG pBytesProcessed
  888. )
  889. /*++
  890. Routine Description:
  891. Utility routine that forms and sends an NDIS_REQUEST to the
  892. miniport, waits for it to complete, and returns status
  893. to the caller.
  894. NOTE: this assumes that the calling routine ensures validity
  895. of the binding handle until this returns.
  896. Arguments:
  897. pOpenContext - pointer to our open context
  898. RequestType - NdisRequest[Set|Query]Information
  899. Oid - the object being set/queried
  900. InformationBuffer - data for the request
  901. InformationBufferLength - length of the above
  902. pBytesProcessed - place to return bytes read/written
  903. Return Value:
  904. Status of the set/query request
  905. --*/
  906. {
  907. NDISPROT_REQUEST ReqContext;
  908. PNDIS_REQUEST pNdisRequest = &ReqContext.Request;
  909. NDIS_STATUS Status;
  910. NPROT_INIT_EVENT(&ReqContext.ReqEvent);
  911. pNdisRequest->RequestType = RequestType;
  912. switch (RequestType)
  913. {
  914. case NdisRequestQueryInformation:
  915. pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
  916. pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer =
  917. InformationBuffer;
  918. pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength =
  919. InformationBufferLength;
  920. break;
  921. case NdisRequestSetInformation:
  922. pNdisRequest->DATA.SET_INFORMATION.Oid = Oid;
  923. pNdisRequest->DATA.SET_INFORMATION.InformationBuffer =
  924. InformationBuffer;
  925. pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength =
  926. InformationBufferLength;
  927. break;
  928. default:
  929. NPROT_ASSERT(FALSE);
  930. break;
  931. }
  932. NdisRequest(&Status,
  933. pOpenContext->BindingHandle,
  934. pNdisRequest);
  935. if (Status == NDIS_STATUS_PENDING)
  936. {
  937. NPROT_WAIT_EVENT(&ReqContext.ReqEvent, 0);
  938. Status = ReqContext.Status;
  939. }
  940. if (Status == NDIS_STATUS_SUCCESS)
  941. {
  942. *pBytesProcessed = (RequestType == NdisRequestQueryInformation)?
  943. pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten:
  944. pNdisRequest->DATA.SET_INFORMATION.BytesRead;
  945. //
  946. // The driver below should set the correct value to BytesWritten
  947. // or BytesRead. But now, we just truncate the value to InformationBufferLength
  948. //
  949. if (*pBytesProcessed > InformationBufferLength)
  950. {
  951. *pBytesProcessed = InformationBufferLength;
  952. }
  953. }
  954. return (Status);
  955. }
  956. NDIS_STATUS
  957. ndisprotValidateOpenAndDoRequest(
  958. IN PNDISPROT_OPEN_CONTEXT pOpenContext,
  959. IN NDIS_REQUEST_TYPE RequestType,
  960. IN NDIS_OID Oid,
  961. IN PVOID InformationBuffer,
  962. IN ULONG InformationBufferLength,
  963. OUT PULONG pBytesProcessed,
  964. IN BOOLEAN bWaitForPowerOn
  965. )
  966. /*++
  967. Routine Description:
  968. Utility routine to prevalidate and reference an open context
  969. before calling ndisprotDoRequest. This routine makes sure
  970. we have a valid binding.
  971. Arguments:
  972. pOpenContext - pointer to our open context
  973. RequestType - NdisRequest[Set|Query]Information
  974. Oid - the object being set/queried
  975. InformationBuffer - data for the request
  976. InformationBufferLength - length of the above
  977. pBytesProcessed - place to return bytes read/written
  978. bWaitForPowerOn - Wait for the device to be powered on if it isn't already.
  979. Return Value:
  980. Status of the set/query request
  981. --*/
  982. {
  983. NDIS_STATUS Status;
  984. do
  985. {
  986. if (pOpenContext == NULL)
  987. {
  988. DEBUGP(DL_WARN, ("ValidateOpenAndDoRequest: request on unassociated file object!\n"));
  989. Status = NDIS_STATUS_INVALID_DATA;
  990. break;
  991. }
  992. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  993. NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
  994. //
  995. // Proceed only if we have a binding.
  996. //
  997. if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE))
  998. {
  999. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  1000. Status = NDIS_STATUS_INVALID_DATA;
  1001. break;
  1002. }
  1003. NPROT_ASSERT(pOpenContext->BindingHandle != NULL);
  1004. //
  1005. // Make sure that the binding does not go away until we
  1006. // are finished with the request.
  1007. //
  1008. NdisInterlockedIncrement((PLONG)&pOpenContext->PendedSendCount);
  1009. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  1010. if (bWaitForPowerOn)
  1011. {
  1012. //
  1013. // Wait for the device below to be powered up.
  1014. // We don't wait indefinitely here - this is to avoid
  1015. // a PROCESS_HAS_LOCKED_PAGES bugcheck that could happen
  1016. // if the calling process terminates, and this IRP doesn't
  1017. // complete within a reasonable time. An alternative would
  1018. // be to explicitly handle cancellation of this IRP.
  1019. //
  1020. if ( NPROT_WAIT_EVENT(&pOpenContext->PoweredUpEvent, 4500) ){}
  1021. else{
  1022. // may do something
  1023. };
  1024. }
  1025. Status = ndisprotDoRequest(
  1026. pOpenContext,
  1027. RequestType,
  1028. Oid,
  1029. InformationBuffer,
  1030. InformationBufferLength,
  1031. pBytesProcessed);
  1032. //
  1033. // Let go of the binding.
  1034. //
  1035. NdisInterlockedDecrement((PLONG)&pOpenContext->PendedSendCount);
  1036. }
  1037. while (FALSE);
  1038. DEBUGP(DL_LOUD, ("ValidateOpenAndDoReq: Open %p/%x, OID %x, Status %x\n",
  1039. pOpenContext, pOpenContext->Flags, Oid, Status));
  1040. return (Status);
  1041. }
  1042. VOID
  1043. NdisProtResetComplete(
  1044. IN NDIS_HANDLE ProtocolBindingContext,
  1045. IN NDIS_STATUS Status
  1046. )
  1047. /*++
  1048. Routine Description:
  1049. NDIS entry point indicating that a protocol initiated reset
  1050. has completed. Since we never call NdisReset(), this should
  1051. never be called.
  1052. Arguments:
  1053. ProtocolBindingContext - pointer to open context
  1054. Status - status of reset completion
  1055. Return Value:
  1056. None
  1057. --*/
  1058. {
  1059. UNREFERENCED_PARAMETER(ProtocolBindingContext);
  1060. UNREFERENCED_PARAMETER(Status);
  1061. ASSERT(FALSE);
  1062. return;
  1063. }
  1064. VOID
  1065. NdisProtRequestComplete(
  1066. IN NDIS_HANDLE ProtocolBindingContext,
  1067. IN PNDIS_REQUEST pNdisRequest,
  1068. IN NDIS_STATUS Status
  1069. )
  1070. /*++
  1071. Routine Description:
  1072. NDIS entry point indicating completion of a pended NDIS_REQUEST.
  1073. Arguments:
  1074. ProtocolBindingContext - pointer to open context
  1075. pNdisRequest - pointer to NDIS request
  1076. Status - status of reset completion
  1077. Return Value:
  1078. None
  1079. --*/
  1080. {
  1081. PNDISPROT_OPEN_CONTEXT pOpenContext;
  1082. PNDISPROT_REQUEST pReqContext;
  1083. pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext;
  1084. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  1085. //
  1086. // Get at the request context.
  1087. //
  1088. pReqContext = CONTAINING_RECORD(pNdisRequest, NDISPROT_REQUEST, Request);
  1089. //
  1090. // Save away the completion status.
  1091. //
  1092. pReqContext->Status = Status;
  1093. //
  1094. // Wake up the thread blocked for this request to complete.
  1095. //
  1096. NPROT_SIGNAL_EVENT(&pReqContext->ReqEvent);
  1097. }
  1098. VOID
  1099. NdisProtStatus(
  1100. IN NDIS_HANDLE ProtocolBindingContext,
  1101. IN NDIS_STATUS GeneralStatus,
  1102. __in_bcount(StatusBufferSize) IN PVOID StatusBuffer,
  1103. IN UINT StatusBufferSize
  1104. )
  1105. /*++
  1106. Routine Description:
  1107. Protocol entry point called by NDIS to indicate a change
  1108. in status at the miniport.
  1109. We make note of reset and media connect status indications.
  1110. Arguments:
  1111. ProtocolBindingContext - pointer to open context
  1112. GeneralStatus - status code
  1113. StatusBuffer - status-specific additional information
  1114. StatusBufferSize - size of the above
  1115. Return Value:
  1116. None
  1117. --*/
  1118. {
  1119. PNDISPROT_OPEN_CONTEXT pOpenContext;
  1120. UNREFERENCED_PARAMETER(StatusBuffer);
  1121. UNREFERENCED_PARAMETER(StatusBufferSize);
  1122. pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext;
  1123. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  1124. DEBUGP(DL_INFO, ("Status: Open %p, Status %x\n",
  1125. pOpenContext, GeneralStatus));
  1126. ndisServiceIndicateStatusIrp(pOpenContext,
  1127. GeneralStatus,
  1128. StatusBuffer,
  1129. StatusBufferSize,
  1130. FALSE);
  1131. NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
  1132. do
  1133. {
  1134. if (pOpenContext->PowerState != NetDeviceStateD0)
  1135. {
  1136. //
  1137. // The device is in a low power state.
  1138. //
  1139. DEBUGP(DL_INFO, ("Status: Open %p in power state %d,"
  1140. " Status %x ignored\n", pOpenContext,
  1141. pOpenContext->PowerState, GeneralStatus));
  1142. //
  1143. // We continue and make note of status indications
  1144. //
  1145. // break;
  1146. //
  1147. //
  1148. // NOTE that any actions we take based on these
  1149. // status indications should take into account
  1150. // the current device power state.
  1151. //
  1152. }
  1153. switch(GeneralStatus)
  1154. {
  1155. case NDIS_STATUS_RESET_START:
  1156. NPROT_ASSERT(!NPROT_TEST_FLAGS(pOpenContext->Flags,
  1157. NUIOO_RESET_FLAGS,
  1158. NUIOO_RESET_IN_PROGRESS));
  1159. NPROT_SET_FLAGS(pOpenContext->Flags,
  1160. NUIOO_RESET_FLAGS,
  1161. NUIOO_RESET_IN_PROGRESS);
  1162. break;
  1163. case NDIS_STATUS_RESET_END:
  1164. NPROT_ASSERT(NPROT_TEST_FLAGS(pOpenContext->Flags,
  1165. NUIOO_RESET_FLAGS,
  1166. NUIOO_RESET_IN_PROGRESS));
  1167. NPROT_SET_FLAGS(pOpenContext->Flags,
  1168. NUIOO_RESET_FLAGS,
  1169. NUIOO_NOT_RESETTING);
  1170. break;
  1171. case NDIS_STATUS_MEDIA_CONNECT:
  1172. NPROT_SET_FLAGS(pOpenContext->Flags,
  1173. NUIOO_MEDIA_FLAGS,
  1174. NUIOO_MEDIA_CONNECTED);
  1175. break;
  1176. case NDIS_STATUS_MEDIA_DISCONNECT:
  1177. NPROT_SET_FLAGS(pOpenContext->Flags,
  1178. NUIOO_MEDIA_FLAGS,
  1179. NUIOO_MEDIA_DISCONNECTED);
  1180. break;
  1181. default:
  1182. break;
  1183. }
  1184. }
  1185. while (FALSE);
  1186. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  1187. }
  1188. VOID
  1189. NdisProtStatusComplete(
  1190. IN NDIS_HANDLE ProtocolBindingContext
  1191. )
  1192. /*++
  1193. Routine Description:
  1194. Protocol entry point called by NDIS. We ignore this.
  1195. Arguments:
  1196. ProtocolBindingContext - pointer to open context
  1197. Return Value:
  1198. None
  1199. --*/
  1200. {
  1201. PNDISPROT_OPEN_CONTEXT pOpenContext;
  1202. pOpenContext = (PNDISPROT_OPEN_CONTEXT)ProtocolBindingContext;
  1203. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  1204. return;
  1205. }
  1206. NDIS_STATUS
  1207. ndisprotQueryBinding(
  1208. IN PUCHAR pBuffer,
  1209. IN ULONG InputLength,
  1210. IN ULONG OutputLength,
  1211. OUT PULONG pBytesReturned
  1212. )
  1213. /*++
  1214. Routine Description:
  1215. Return information about the specified binding.
  1216. Arguments:
  1217. pBuffer - pointer to NDISPROT_QUERY_BINDING
  1218. InputLength - input buffer size
  1219. OutputLength - output buffer size
  1220. pBytesReturned - place to return copied byte count.
  1221. Return Value:
  1222. NDIS_STATUS_SUCCESS if successful, failure code otherwise.
  1223. --*/
  1224. {
  1225. PNDISPROT_QUERY_BINDING pQueryBinding;
  1226. PNDISPROT_OPEN_CONTEXT pOpenContext;
  1227. PLIST_ENTRY pEnt;
  1228. ULONG Remaining;
  1229. ULONG BindingIndex;
  1230. NDIS_STATUS Status;
  1231. do
  1232. {
  1233. if (InputLength < sizeof(NDISPROT_QUERY_BINDING))
  1234. {
  1235. Status = NDIS_STATUS_RESOURCES;
  1236. break;
  1237. }
  1238. if (OutputLength < sizeof(NDISPROT_QUERY_BINDING))
  1239. {
  1240. Status = NDIS_STATUS_BUFFER_OVERFLOW;
  1241. break;
  1242. }
  1243. Remaining = OutputLength - sizeof(NDISPROT_QUERY_BINDING);
  1244. pQueryBinding = (PNDISPROT_QUERY_BINDING)pBuffer;
  1245. BindingIndex = pQueryBinding->BindingIndex;
  1246. Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  1247. pOpenContext = NULL;
  1248. NPROT_ACQUIRE_LOCK(&Globals.GlobalLock);
  1249. for (pEnt = Globals.OpenList.Flink;
  1250. pEnt != &Globals.OpenList;
  1251. pEnt = pEnt->Flink)
  1252. {
  1253. pOpenContext = CONTAINING_RECORD(pEnt, NDISPROT_OPEN_CONTEXT, Link);
  1254. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  1255. NPROT_ACQUIRE_LOCK(&pOpenContext->Lock);
  1256. //
  1257. // Skip if not bound.
  1258. //
  1259. if (!NPROT_TEST_FLAGS(pOpenContext->Flags, NUIOO_BIND_FLAGS, NUIOO_BIND_ACTIVE))
  1260. {
  1261. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  1262. continue;
  1263. }
  1264. if (BindingIndex == 0)
  1265. {
  1266. //
  1267. // Got the binding we are looking for. Copy the device
  1268. // name and description strings to the output buffer.
  1269. //
  1270. DEBUGP(DL_INFO,
  1271. ("QueryBinding: found open %p\n", pOpenContext));
  1272. pQueryBinding->DeviceNameLength = pOpenContext->DeviceName.Length + sizeof(WCHAR);
  1273. pQueryBinding->DeviceDescrLength = pOpenContext->DeviceDescr.Length + sizeof(WCHAR);
  1274. if (Remaining < pQueryBinding->DeviceNameLength +
  1275. pQueryBinding->DeviceDescrLength)
  1276. {
  1277. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  1278. Status = NDIS_STATUS_BUFFER_OVERFLOW;
  1279. break;
  1280. }
  1281. NPROT_ZERO_MEM((PUCHAR)pBuffer + sizeof(NDISPROT_QUERY_BINDING),
  1282. pQueryBinding->DeviceNameLength +
  1283. pQueryBinding->DeviceDescrLength);
  1284. pQueryBinding->DeviceNameOffset = sizeof(NDISPROT_QUERY_BINDING);
  1285. NPROT_COPY_MEM((PUCHAR)pBuffer + pQueryBinding->DeviceNameOffset,
  1286. pOpenContext->DeviceName.Buffer,
  1287. pOpenContext->DeviceName.Length);
  1288. pQueryBinding->DeviceDescrOffset = pQueryBinding->DeviceNameOffset +
  1289. pQueryBinding->DeviceNameLength;
  1290. NPROT_COPY_MEM((PUCHAR)pBuffer + pQueryBinding->DeviceDescrOffset,
  1291. pOpenContext->DeviceDescr.Buffer,
  1292. pOpenContext->DeviceDescr.Length);
  1293. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  1294. *pBytesReturned = pQueryBinding->DeviceDescrOffset + pQueryBinding->DeviceDescrLength;
  1295. Status = NDIS_STATUS_SUCCESS;
  1296. break;
  1297. }
  1298. NPROT_RELEASE_LOCK(&pOpenContext->Lock);
  1299. BindingIndex--;
  1300. }
  1301. NPROT_RELEASE_LOCK(&Globals.GlobalLock);
  1302. }
  1303. while (FALSE);
  1304. return (Status);
  1305. }
  1306. PNDISPROT_OPEN_CONTEXT
  1307. ndisprotLookupDevice(
  1308. __in_bcount(BindingInfoLength) IN PUCHAR pBindingInfo,
  1309. IN ULONG BindingInfoLength
  1310. )
  1311. /*++
  1312. Routine Description:
  1313. Search our global list for an open context structure that
  1314. has a binding to the specified device, and return a pointer
  1315. to it.
  1316. NOTE: we reference the open that we return.
  1317. Arguments:
  1318. pBindingInfo - pointer to unicode device name string
  1319. BindingInfoLength - length in bytes of the above.
  1320. Return Value:
  1321. Pointer to the matching open context if found, else NULL
  1322. --*/
  1323. {
  1324. PNDISPROT_OPEN_CONTEXT pOpenContext;
  1325. PLIST_ENTRY pEnt;
  1326. pOpenContext = NULL;
  1327. NPROT_ACQUIRE_LOCK(&Globals.GlobalLock);
  1328. for (pEnt = Globals.OpenList.Flink;
  1329. pEnt != &Globals.OpenList;
  1330. pEnt = pEnt->Flink)
  1331. {
  1332. pOpenContext = CONTAINING_RECORD(pEnt, NDISPROT_OPEN_CONTEXT, Link);
  1333. NPROT_STRUCT_ASSERT(pOpenContext, oc);
  1334. //
  1335. // Check if this has the name we are looking for.
  1336. //
  1337. if ((pOpenContext->DeviceName.Length == BindingInfoLength) &&
  1338. NPROT_MEM_CMP(pOpenContext->DeviceName.Buffer, pBindingInfo, BindingInfoLength))
  1339. {
  1340. NPROT_REF_OPEN(pOpenContext); // ref added by LookupDevice…

Large files files are truncated, but you can click here to view the full file