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.

2197 lines
58 KiB

  1. /*++
  2. Copyright (c) 1990-1995 Microsoft Corporation
  3. Module Name:
  4. mac.c
  5. Abstract:
  6. NDIS wrapper functions for full mac drivers
  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-organized
  15. --*/
  16. #include <precomp.h>
  17. #pragma hdrstop
  18. #include <stdarg.h>
  19. //
  20. // Define the module number for debug code.
  21. //
  22. #define MODULE_NUMBER MODULE_MAC
  23. IO_ALLOCATION_ACTION
  24. ndisDmaExecutionRoutine(
  25. IN PDEVICE_OBJECT DeviceObject,
  26. IN PIRP Irp,
  27. IN PVOID MapRegisterBase,
  28. IN PVOID Context
  29. )
  30. /*++
  31. Routine Description:
  32. This routine is an execution routine for AllocateAdapterChannel,
  33. if is called when an adapter channel allocated by
  34. NdisAllocateDmaChannel is available.
  35. Arguments:
  36. DeviceObject - The device object of the adapter.
  37. Irp - ??.
  38. MapRegisterBase - The address of the first translation table
  39. assigned to us.
  40. Context - A pointer to the NDIS_DMA_BLOCK in question.
  41. Return Value:
  42. None.
  43. --*/
  44. {
  45. PNDIS_DMA_BLOCK DmaBlock = (PNDIS_DMA_BLOCK)Context;
  46. UNREFERENCED_PARAMETER (Irp);
  47. UNREFERENCED_PARAMETER (DeviceObject);
  48. //
  49. // Save the map register base.
  50. //
  51. DmaBlock->MapRegisterBase = MapRegisterBase;
  52. //
  53. // This will free the thread that is waiting for this callback.
  54. //
  55. SET_EVENT(&DmaBlock->AllocationEvent);
  56. return KeepObject;
  57. }
  58. IO_ALLOCATION_ACTION
  59. ndisAllocationExecutionRoutine(
  60. IN PDEVICE_OBJECT DeviceObject,
  61. IN PIRP Irp,
  62. IN PVOID MapRegisterBase,
  63. IN PVOID Context
  64. )
  65. /*++
  66. Routine Description:
  67. This routine is the execution routine for AllocateAdapterChannel,
  68. if is called when the map registers have been assigned.
  69. Arguments:
  70. DeviceObject - The device object of the adapter.
  71. Irp - ??.
  72. MapRegisterBase - The address of the first translation table
  73. assigned to us.
  74. Context - A pointer to the Adapter in question.
  75. Return Value:
  76. None.
  77. --*/
  78. {
  79. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)Context;
  80. UNREFERENCED_PARAMETER(DeviceObject);
  81. UNREFERENCED_PARAMETER(Irp);
  82. //
  83. // Save this translation entry in the correct spot.
  84. //
  85. Miniport->MapRegisters[Miniport->CurrentMapRegister].MapRegister = MapRegisterBase;
  86. //
  87. // This will free the thread that is waiting for this callback.
  88. //
  89. SET_EVENT(Miniport->AllocationEvent);
  90. return DeallocateObjectKeepRegisters;
  91. }
  92. VOID __cdecl
  93. NdisWriteErrorLogEntry(
  94. IN NDIS_HANDLE NdisAdapterHandle,
  95. IN NDIS_ERROR_CODE ErrorCode,
  96. IN ULONG NumberOfErrorValues,
  97. ...
  98. )
  99. /*++
  100. Routine Description:
  101. This function allocates an I/O error log record, fills it in and writes it
  102. to the I/O error log.
  103. Arguments:
  104. NdisAdapterHandle - points to the adapter block.
  105. ErrorCode - Ndis code mapped to a string.
  106. NumberOfErrorValues - number of ULONGS to store for the error.
  107. Return Value:
  108. None.
  109. --*/
  110. {
  111. va_list ArgumentPointer;
  112. PIO_ERROR_LOG_PACKET errorLogEntry;
  113. PNDIS_MINIPORT_BLOCK Miniport = (PNDIS_MINIPORT_BLOCK)NdisAdapterHandle;
  114. UINT i, StringSize;
  115. PWCH baseFileName;
  116. ULONG ulErrorLogSize = 0;
  117. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  118. ("==>NdisWriteErrorLogEntry\n"));
  119. if (Miniport == NULL)
  120. {
  121. return;
  122. }
  123. baseFileName = Miniport->pAdapterInstanceName->Buffer;
  124. StringSize = Miniport->pAdapterInstanceName->MaximumLength;
  125. ulErrorLogSize = sizeof(IO_ERROR_LOG_PACKET) + NumberOfErrorValues * sizeof(ULONG) + StringSize;
  126. //
  127. // If the size is too large , use the MiniportName instead (\Device\{GUID} )
  128. //
  129. if (ulErrorLogSize > ERROR_LOG_MAXIMUM_SIZE )
  130. {
  131. baseFileName = Miniport->MiniportName.Buffer;
  132. StringSize = Miniport->MiniportName.MaximumLength;
  133. ulErrorLogSize = sizeof(IO_ERROR_LOG_PACKET) + NumberOfErrorValues * sizeof(ULONG) + StringSize;
  134. }
  135. if (ulErrorLogSize > ERROR_LOG_MAXIMUM_SIZE )
  136. {
  137. return;
  138. }
  139. errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(Miniport->DeviceObject, (UCHAR)ulErrorLogSize);
  140. if (errorLogEntry != NULL)
  141. {
  142. errorLogEntry->ErrorCode = ErrorCode;
  143. //
  144. // store the time
  145. //
  146. errorLogEntry->MajorFunctionCode = 0;
  147. errorLogEntry->RetryCount = 0;
  148. errorLogEntry->UniqueErrorValue = 0;
  149. errorLogEntry->FinalStatus = 0;
  150. errorLogEntry->SequenceNumber = 0;
  151. errorLogEntry->IoControlCode = 0;
  152. //
  153. // Store Data
  154. //
  155. errorLogEntry->DumpDataSize = (USHORT)(NumberOfErrorValues * sizeof(ULONG));
  156. va_start(ArgumentPointer, NumberOfErrorValues);
  157. for (i = 0; i < NumberOfErrorValues; i++)
  158. {
  159. errorLogEntry->DumpData[i] = va_arg(ArgumentPointer, ULONG);
  160. }
  161. va_end(ArgumentPointer);
  162. //
  163. // Set string information
  164. //
  165. if (StringSize != 0)
  166. {
  167. errorLogEntry->NumberOfStrings = 1;
  168. errorLogEntry->StringOffset = (USHORT)(sizeof(IO_ERROR_LOG_PACKET) + NumberOfErrorValues * sizeof(ULONG));
  169. CopyMemory(((PUCHAR)errorLogEntry) + (sizeof(IO_ERROR_LOG_PACKET) +
  170. NumberOfErrorValues * sizeof(ULONG)),
  171. baseFileName,
  172. StringSize);
  173. }
  174. else
  175. {
  176. errorLogEntry->NumberOfStrings = 0;
  177. }
  178. //
  179. // write it out
  180. //
  181. IoWriteErrorLogEntry(errorLogEntry);
  182. }
  183. DBGPRINT_RAW(DBG_COMP_INIT, DBG_LEVEL_INFO,
  184. ("<==NdisWriteErrorLogEntry\n"));
  185. }
  186. VOID
  187. NdisSend(
  188. OUT PNDIS_STATUS Status,
  189. IN NDIS_HANDLE NdisBindingHandle,
  190. IN PNDIS_PACKET Packet
  191. )
  192. {
  193. *Status = (((PNDIS_OPEN_BLOCK)NdisBindingHandle)->SendHandler)(
  194. (PNDIS_OPEN_BLOCK)NdisBindingHandle,
  195. Packet);
  196. }
  197. VOID
  198. NdisSendPackets(
  199. IN NDIS_HANDLE NdisBindingHandle,
  200. IN PPNDIS_PACKET PacketArray,
  201. IN UINT NumberOfPackets
  202. )
  203. {
  204. (((PNDIS_OPEN_BLOCK)NdisBindingHandle)->SendPacketsHandler)(
  205. (PNDIS_OPEN_BLOCK)NdisBindingHandle,
  206. PacketArray,
  207. NumberOfPackets);
  208. }
  209. VOID
  210. NdisTransferData(
  211. OUT PNDIS_STATUS Status,
  212. IN NDIS_HANDLE NdisBindingHandle,
  213. IN NDIS_HANDLE MacReceiveContext,
  214. IN UINT ByteOffset,
  215. IN UINT BytesToTransfer,
  216. OUT PNDIS_PACKET Packet,
  217. OUT PUINT BytesTransferred
  218. )
  219. {
  220. *Status = (((PNDIS_OPEN_BLOCK)NdisBindingHandle)->TransferDataHandler)(
  221. (PNDIS_OPEN_BLOCK)NdisBindingHandle,
  222. MacReceiveContext,
  223. ByteOffset,
  224. BytesToTransfer,
  225. Packet,
  226. BytesTransferred);
  227. }
  228. VOID
  229. NdisReset(
  230. OUT PNDIS_STATUS Status,
  231. IN NDIS_HANDLE NdisBindingHandle
  232. )
  233. {
  234. *Status = NDIS_STATUS_NOT_RESETTABLE;
  235. if (((PNDIS_OPEN_BLOCK)NdisBindingHandle)->ResetHandler != NULL)
  236. {
  237. *Status = (((PNDIS_OPEN_BLOCK)NdisBindingHandle)->ResetHandler)(
  238. (PNDIS_OPEN_BLOCK)NdisBindingHandle);
  239. }
  240. }
  241. VOID
  242. NdisRequest(
  243. OUT PNDIS_STATUS Status,
  244. IN NDIS_HANDLE NdisBindingHandle,
  245. IN PNDIS_REQUEST NdisRequest
  246. )
  247. {
  248. *Status = (((PNDIS_OPEN_BLOCK)NdisBindingHandle)->RequestHandler)(
  249. (PNDIS_OPEN_BLOCK)NdisBindingHandle,
  250. NdisRequest);
  251. }
  252. BOOLEAN
  253. FASTCALL
  254. ndisReferenceRef(
  255. IN PREFERENCE RefP
  256. )
  257. /*++
  258. Routine Description:
  259. Adds a reference to an object.
  260. Arguments:
  261. RefP - A pointer to the REFERENCE portion of the object.
  262. Return Value:
  263. TRUE if the reference was added.
  264. FALSE if the object was closing.
  265. --*/
  266. {
  267. BOOLEAN rc = TRUE;
  268. KIRQL OldIrql;
  269. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  270. ("==>ndisReferenceRef\n"));
  271. IF_DBG(DBG_COMP_PROTOCOL, DBG_LEVEL_ERR)
  272. {
  273. if (DbgIsNull(RefP))
  274. {
  275. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  276. ("ndisReferenceRef: NULL Reference address\n"));
  277. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  278. }
  279. if (!DbgIsNonPaged(RefP))
  280. {
  281. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  282. ("ndisReferenceRef: Reference not in NonPaged Memory\n"));
  283. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  284. }
  285. }
  286. ACQUIRE_SPIN_LOCK(&RefP->SpinLock, &OldIrql);
  287. if (RefP->Closing)
  288. {
  289. rc = FALSE;
  290. }
  291. else
  292. {
  293. ++(RefP->ReferenceCount);
  294. if (RefP->ReferenceCount == 0)
  295. {
  296. --(RefP->ReferenceCount);
  297. rc = FALSE;
  298. }
  299. }
  300. RELEASE_SPIN_LOCK(&RefP->SpinLock, OldIrql);
  301. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  302. ("<==ndisReferenceRef\n"));
  303. return(rc);
  304. }
  305. BOOLEAN
  306. FASTCALL
  307. ndisDereferenceRef(
  308. IN PREFERENCE RefP
  309. )
  310. /*++
  311. Routine Description:
  312. Removes a reference to an object.
  313. Arguments:
  314. RefP - A pointer to the REFERENCE portion of the object.
  315. Return Value:
  316. TRUE if the reference count is now 0.
  317. FALSE otherwise.
  318. --*/
  319. {
  320. BOOLEAN rc = FALSE;
  321. KIRQL OldIrql;
  322. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  323. ("==>ndisDereferenceRef\n"));
  324. IF_DBG(DBG_COMP_PROTOCOL, DBG_LEVEL_ERR)
  325. {
  326. if (DbgIsNull(RefP))
  327. {
  328. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  329. ("ndisDereferenceRef: NULL Reference address\n"));
  330. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  331. }
  332. if (!DbgIsNonPaged(RefP))
  333. {
  334. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  335. ("ndisDereferenceRef: Reference not in NonPaged Memory\n"));
  336. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  337. }
  338. }
  339. ACQUIRE_SPIN_LOCK(&RefP->SpinLock, &OldIrql);
  340. --(RefP->ReferenceCount);
  341. if (RefP->ReferenceCount == 0)
  342. {
  343. rc = TRUE;
  344. }
  345. RELEASE_SPIN_LOCK(&RefP->SpinLock, OldIrql);
  346. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  347. ("<==ndisDereferenceRef\n"));
  348. return(rc);
  349. }
  350. VOID
  351. FASTCALL
  352. ndisInitializeRef(
  353. IN PREFERENCE RefP
  354. )
  355. /*++
  356. Routine Description:
  357. Initialize a reference count structure.
  358. Arguments:
  359. RefP - The structure to be initialized.
  360. Return Value:
  361. None.
  362. --*/
  363. {
  364. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  365. ("==>ndisInitializeRef\n"));
  366. IF_DBG(DBG_COMP_PROTOCOL, DBG_LEVEL_ERR)
  367. {
  368. if (DbgIsNull(RefP))
  369. {
  370. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  371. ("ndisInitializeRef: NULL Reference address\n"));
  372. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  373. }
  374. if (!DbgIsNonPaged(RefP))
  375. {
  376. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  377. ("ndisInitializeRef: Reference not in NonPaged Memory\n"));
  378. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  379. }
  380. }
  381. RefP->Closing = FALSE;
  382. RefP->ReferenceCount = 1;
  383. INITIALIZE_SPIN_LOCK(&RefP->SpinLock);
  384. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  385. ("<==ndisInitializeRef\n"));
  386. }
  387. BOOLEAN
  388. FASTCALL
  389. ndisCloseRef(
  390. IN PREFERENCE RefP
  391. )
  392. /*++
  393. Routine Description:
  394. Closes a reference count structure.
  395. Arguments:
  396. RefP - The structure to be closed.
  397. Return Value:
  398. FALSE if it was already closing.
  399. TRUE otherwise.
  400. --*/
  401. {
  402. KIRQL OldIrql;
  403. BOOLEAN rc = TRUE;
  404. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  405. ("==>ndisCloseRef\n"));
  406. ACQUIRE_SPIN_LOCK(&RefP->SpinLock, &OldIrql);
  407. if (RefP->Closing)
  408. {
  409. rc = FALSE;
  410. }
  411. else RefP->Closing = TRUE;
  412. RELEASE_SPIN_LOCK(&RefP->SpinLock, OldIrql);
  413. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  414. ("<==ndisCloseRef\n"));
  415. return(rc);
  416. }
  417. BOOLEAN
  418. FASTCALL
  419. ndisReferenceULongRef(
  420. IN PULONG_REFERENCE RefP
  421. )
  422. /*++
  423. Routine Description:
  424. Adds a reference to an object.
  425. Arguments:
  426. RefP - A pointer to the REFERENCE portion of the object.
  427. Return Value:
  428. TRUE if the reference was added.
  429. FALSE if the object was closing.
  430. --*/
  431. {
  432. BOOLEAN rc = TRUE;
  433. KIRQL OldIrql;
  434. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  435. ("==>ndisReferenceULongRef\n"));
  436. ACQUIRE_SPIN_LOCK(&RefP->SpinLock, &OldIrql);
  437. if (RefP->Closing)
  438. {
  439. rc = FALSE;
  440. }
  441. else
  442. {
  443. ++(RefP->ReferenceCount);
  444. if (RefP->ReferenceCount == 0)
  445. {
  446. --(RefP->ReferenceCount);
  447. rc = FALSE;
  448. }
  449. }
  450. RELEASE_SPIN_LOCK(&RefP->SpinLock, OldIrql);
  451. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  452. ("<==ndisReferenceULongRef\n"));
  453. return(rc);
  454. }
  455. VOID
  456. FASTCALL
  457. ndisReferenceULongRefNoCheck(
  458. IN PULONG_REFERENCE RefP
  459. )
  460. /*++
  461. Routine Description:
  462. Adds a reference to an object.
  463. Arguments:
  464. RefP - A pointer to the REFERENCE portion of the object.
  465. Return Value:
  466. None
  467. --*/
  468. {
  469. KIRQL OldIrql;
  470. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  471. ("==>ndisReferenceULongRefNoCheck\n"));
  472. ACQUIRE_SPIN_LOCK(&RefP->SpinLock, &OldIrql);
  473. ++(RefP->ReferenceCount);
  474. RELEASE_SPIN_LOCK(&RefP->SpinLock, OldIrql);
  475. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  476. ("<==ndisReferenceULongRefNoCheck\n"));
  477. }
  478. BOOLEAN
  479. FASTCALL
  480. ndisDereferenceULongRef(
  481. IN PULONG_REFERENCE RefP
  482. )
  483. /*++
  484. Routine Description:
  485. Removes a reference to an object.
  486. Arguments:
  487. RefP - A pointer to the REFERENCE portion of the object.
  488. Return Value:
  489. TRUE if the reference count is now 0.
  490. FALSE otherwise.
  491. --*/
  492. {
  493. BOOLEAN rc = FALSE;
  494. KIRQL OldIrql;
  495. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  496. ("==>ndisDereferenceULongRef\n"));
  497. ACQUIRE_SPIN_LOCK(&RefP->SpinLock, &OldIrql);
  498. --(RefP->ReferenceCount);
  499. if (RefP->ReferenceCount == 0)
  500. {
  501. rc = TRUE;
  502. }
  503. RELEASE_SPIN_LOCK(&RefP->SpinLock, OldIrql);
  504. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  505. ("<==ndisDereferenceULongRef\n"));
  506. return(rc);
  507. }
  508. VOID
  509. FASTCALL
  510. ndisInitializeULongRef(
  511. IN PULONG_REFERENCE RefP
  512. )
  513. /*++
  514. Routine Description:
  515. Initialize a reference count structure.
  516. Arguments:
  517. RefP - The structure to be initialized.
  518. Return Value:
  519. None.
  520. --*/
  521. {
  522. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  523. ("==>ndisInitializeULongRef\n"));
  524. RefP->Closing = FALSE;
  525. RefP->ReferenceCount = 1;
  526. INITIALIZE_SPIN_LOCK(&RefP->SpinLock);
  527. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  528. ("<==ndisInitializeULongRef\n"));
  529. }
  530. BOOLEAN
  531. FASTCALL
  532. ndisCloseULongRef(
  533. IN PULONG_REFERENCE RefP
  534. )
  535. /*++
  536. Routine Description:
  537. Closes a reference count structure.
  538. Arguments:
  539. RefP - The structure to be closed.
  540. Return Value:
  541. FALSE if it was already closing.
  542. TRUE otherwise.
  543. --*/
  544. {
  545. KIRQL OldIrql;
  546. BOOLEAN rc = TRUE;
  547. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  548. ("==>ndisCloseULongRef\n"));
  549. ACQUIRE_SPIN_LOCK(&RefP->SpinLock, &OldIrql);
  550. if (RefP->Closing)
  551. {
  552. rc = FALSE;
  553. }
  554. else RefP->Closing = TRUE;
  555. RELEASE_SPIN_LOCK(&RefP->SpinLock, OldIrql);
  556. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  557. ("<==ndisCloseULongRef\n"));
  558. return(rc);
  559. }
  560. NTSTATUS
  561. ndisCreateIrpHandler(
  562. IN PDEVICE_OBJECT DeviceObject,
  563. IN PIRP Irp
  564. )
  565. /*++
  566. Routine Description:
  567. The handle for IRP_MJ_CREATE IRPs.
  568. Arguments:
  569. DeviceObject - The adapter's device object.
  570. Irp - The IRP.
  571. Return Value:
  572. STATUS_SUCCESS if it should be.
  573. --*/
  574. {
  575. PIO_STACK_LOCATION IrpSp;
  576. PNDIS_USER_OPEN_CONTEXT OpenContext = NULL;
  577. NTSTATUS Status = STATUS_SUCCESS, SecurityStatus;
  578. PNDIS_MINIPORT_BLOCK Miniport;
  579. KIRQL OldIrql;
  580. BOOLEAN fRef = FALSE;
  581. BOOLEAN fWait;
  582. BOOLEAN fUserModeRef = FALSE;
  583. BOOLEAN AdminAccessAllowed = FALSE;
  584. BOOLEAN DerefAdminOpenCount = FALSE, DerefUserOpenCount = FALSE;
  585. DBGPRINT_RAW(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
  586. ("==>ndisCreateIrpHandler\n"));
  587. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  588. if (IrpSp->FileObject == NULL)
  589. {
  590. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  591. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  592. return(STATUS_UNSUCCESSFUL);
  593. }
  594. Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  595. if (Miniport->Signature != (PVOID)MINIPORT_DEVICE_MAGIC_VALUE)
  596. {
  597. return (ndisDummyIrpHandler(DeviceObject, Irp));
  598. }
  599. AdminAccessAllowed = ndisCheckAccess(Irp,
  600. IrpSp,
  601. &SecurityStatus,
  602. Miniport->SecurityDescriptor);
  603. do
  604. {
  605. ACQUIRE_SPIN_LOCK(&Miniport->Ref.SpinLock, &OldIrql);
  606. if ((AdminAccessAllowed && (Miniport->NumAdminOpens >= NDIS_MAX_ADMIN_OPEN_HANDLES)) ||
  607. ((!AdminAccessAllowed) && (Miniport->NumUserOpens >= NDIS_MAX_USER_OPEN_HANDLES)))
  608. {
  609. Status = STATUS_INSUFFICIENT_RESOURCES;
  610. RELEASE_SPIN_LOCK(&Miniport->Ref.SpinLock, OldIrql);
  611. break;
  612. }
  613. if (AdminAccessAllowed)
  614. {
  615. Miniport->NumAdminOpens++;
  616. DerefAdminOpenCount = TRUE;;
  617. }
  618. else
  619. {
  620. Miniport->NumUserOpens++;
  621. DerefUserOpenCount = TRUE;
  622. }
  623. RELEASE_SPIN_LOCK(&Miniport->Ref.SpinLock, OldIrql);
  624. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_DEVICE_FAILED |
  625. fMINIPORT_REJECT_REQUESTS))
  626. {
  627. Status = STATUS_UNSUCCESSFUL;
  628. break;
  629. }
  630. fWait = NdisWaitEvent(&Miniport->OpenReadyEvent, NDIS_USER_OPEN_WAIT_TIME);
  631. if (fWait)
  632. {
  633. fRef = MINIPORT_INCREMENT_REF_CREATE(Miniport, Irp);
  634. }
  635. if (!fWait || !fRef)
  636. {
  637. if (!fWait && (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_SYSTEM_SLEEPING) ||
  638. !MINIPORT_TEST_FLAG(Miniport, fMINIPORT_MEDIA_CONNECTED)))
  639. {
  640. Status = STATUS_DEVICE_POWERED_OFF;
  641. }
  642. else
  643. {
  644. Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  645. }
  646. break;
  647. }
  648. //
  649. // Lock down this code since we are about to take a spinlock.
  650. //
  651. PnPReferencePackage();
  652. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  653. if (Miniport->PnPDeviceState == NdisPnPDeviceQueryStopped)
  654. {
  655. Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
  656. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  657. PnPDereferencePackage();
  658. break;
  659. }
  660. Miniport->UserModeOpenReferences++;
  661. fUserModeRef = TRUE;
  662. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  663. PnPDereferencePackage();
  664. OpenContext = (PNDIS_USER_OPEN_CONTEXT)ALLOC_FROM_POOL(sizeof(NDIS_USER_OPEN_CONTEXT),
  665. NDIS_TAG_OPEN_CONTEXT);
  666. if (OpenContext == NULL)
  667. {
  668. Status = STATUS_INSUFFICIENT_RESOURCES;
  669. }
  670. else
  671. {
  672. OpenContext->DeviceObject = DeviceObject;
  673. OpenContext->Miniport = Miniport;
  674. OpenContext->OidList = NULL;
  675. OpenContext->AdminAccessAllowed = AdminAccessAllowed;
  676. IrpSp->FileObject->FsContext = OpenContext;
  677. //
  678. // Checked if we already cached OidList, if so just set it here.
  679. //
  680. if (Miniport->OidList != NULL)
  681. {
  682. OpenContext->OidList = Miniport->OidList;
  683. Status = NDIS_STATUS_SUCCESS;
  684. }
  685. if (OpenContext->OidList == NULL)
  686. {
  687. Status = ndisQueryOidList(OpenContext);
  688. }
  689. if (Status != NDIS_STATUS_SUCCESS)
  690. {
  691. if (NT_SUCCESS(Status))
  692. {
  693. //
  694. // Some drivers return some bogus non-zero error
  695. //
  696. Status = STATUS_UNSUCCESSFUL;
  697. }
  698. }
  699. }
  700. } while (FALSE);
  701. if (NT_SUCCESS(Status) && MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_SWENUM))
  702. {
  703. PBUS_INTERFACE_REFERENCE BusInterface;
  704. BusInterface = (PBUS_INTERFACE_REFERENCE)(Miniport->BusInterface);
  705. ASSERT(BusInterface != NULL);
  706. if (BusInterface)
  707. {
  708. BusInterface->ReferenceDeviceObject(BusInterface->Interface.Context);
  709. }
  710. else
  711. {
  712. Status = STATUS_UNSUCCESSFUL;
  713. }
  714. }
  715. if (!NT_SUCCESS(Status))
  716. {
  717. if (DerefAdminOpenCount)
  718. {
  719. ACQUIRE_SPIN_LOCK(&Miniport->Ref.SpinLock, &OldIrql);
  720. Miniport->NumAdminOpens--;
  721. RELEASE_SPIN_LOCK(&Miniport->Ref.SpinLock, OldIrql);
  722. }
  723. if (DerefUserOpenCount)
  724. {
  725. ACQUIRE_SPIN_LOCK(&Miniport->Ref.SpinLock, &OldIrql);
  726. Miniport->NumUserOpens--;
  727. RELEASE_SPIN_LOCK(&Miniport->Ref.SpinLock, OldIrql);
  728. }
  729. if (fUserModeRef)
  730. {
  731. PnPReferencePackage();
  732. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  733. Miniport->UserModeOpenReferences--;
  734. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  735. PnPDereferencePackage();
  736. }
  737. if (fRef)
  738. {
  739. MINIPORT_DECREMENT_REF_CLOSE(Miniport, Irp);
  740. }
  741. if (OpenContext)
  742. {
  743. FREE_POOL(OpenContext);
  744. }
  745. }
  746. Irp->IoStatus.Status = Status;
  747. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  748. DBGPRINT_RAW(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
  749. ("<==NdisCreateIrplHandler\n"));
  750. return Status;
  751. }
  752. NDIS_STATUS
  753. FASTCALL
  754. ndisQueryOidList(
  755. IN PNDIS_USER_OPEN_CONTEXT OpenContext
  756. )
  757. /*++
  758. Routine Description:
  759. This routine will take care of querying the complete OID list for the MAC and filling in
  760. OpenContext->OidList->OidArray with the ones that are statistics. It blocks when the
  761. MAC pends and so is synchronous.
  762. NOTE: We also handle co-ndis miniports here.
  763. Arguments:
  764. OpenContext - The open context.
  765. Return Value:
  766. STATUS_SUCCESS if it should be.
  767. --*/
  768. {
  769. NDIS_REQUEST Request;
  770. NDIS_STATUS Status;
  771. PNDIS_OID Buffer;
  772. ULONG BufferLength;
  773. Status = ndisQueryDeviceOid(OpenContext,
  774. &Request,
  775. OID_GEN_SUPPORTED_LIST,
  776. NULL,
  777. 0);
  778. if ((Status != NDIS_STATUS_INVALID_LENGTH) && (Status != NDIS_STATUS_BUFFER_TOO_SHORT))
  779. {
  780. return Status;
  781. }
  782. //
  783. // Now we know how much is needed, allocate temp storage...
  784. //
  785. BufferLength = Request.DATA.QUERY_INFORMATION.BytesNeeded;
  786. Buffer = ALLOC_FROM_POOL(BufferLength, NDIS_TAG_DEFAULT);
  787. if (Buffer == NULL)
  788. {
  789. return STATUS_INSUFFICIENT_RESOURCES;
  790. }
  791. Status = ndisQueryDeviceOid(OpenContext,
  792. &Request,
  793. OID_GEN_SUPPORTED_LIST,
  794. Buffer,
  795. BufferLength);
  796. if (Status == NDIS_STATUS_SUCCESS)
  797. {
  798. Status = ndisSplitStatisticsOids(OpenContext,
  799. Buffer,
  800. BufferLength/sizeof(NDIS_OID));
  801. }
  802. FREE_POOL(Buffer);
  803. return Status;
  804. }
  805. NDIS_STATUS
  806. FASTCALL
  807. ndisSplitStatisticsOids(
  808. IN PNDIS_USER_OPEN_CONTEXT OpenContext,
  809. IN PNDIS_OID OidList,
  810. IN ULONG NumOids
  811. )
  812. {
  813. ULONG i, j;
  814. ULONG StatsOids;
  815. //
  816. // Go through the buffer, counting the statistics OIDs.
  817. // Ignore all the custom oids which match the statistics
  818. // criteria
  819. //
  820. for (i = StatsOids = 0; i < NumOids; i++)
  821. {
  822. if (((OidList[i] & 0x00ff0000) == 0x00020000) &&
  823. ((OidList[i] & 0xff000000) != 0xff000000))
  824. {
  825. StatsOids++;
  826. }
  827. }
  828. //
  829. // Now allocate storage for the stat and non-stat OID arrays.
  830. //
  831. OpenContext->OidList = (POID_LIST)ALLOC_FROM_POOL(sizeof(OID_LIST) + ((StatsOids + NumOids)*sizeof(NDIS_OID)),
  832. NDIS_TAG_OID_ARRAY);
  833. if (OpenContext->OidList == NULL)
  834. {
  835. return STATUS_INSUFFICIENT_RESOURCES;
  836. }
  837. OpenContext->OidList->FullOidCount = NumOids;
  838. OpenContext->OidList->FullOidArray = (PNDIS_OID)(OpenContext->OidList + 1);
  839. OpenContext->OidList->StatsOidCount = StatsOids;
  840. OpenContext->OidList->StatsOidArray = OpenContext->OidList->FullOidArray + NumOids;
  841. //
  842. // Now go through the buffer, copying the statistics and non-stat OIDs separately.
  843. //
  844. for (i = j = 0; i < NumOids; i++)
  845. {
  846. if (((OidList[i] & 0x00ff0000) == 0x00020000) &&
  847. ((OidList[i] & 0xff000000) != 0xff000000))
  848. {
  849. OpenContext->OidList->StatsOidArray[j++] = OidList[i];
  850. }
  851. OpenContext->OidList->FullOidArray[i] = OidList[i];
  852. }
  853. ASSERT (j == OpenContext->OidList->StatsOidCount);
  854. //
  855. // Save it in the miniport
  856. //
  857. OpenContext->Miniport->OidList = OpenContext->OidList;
  858. return NDIS_STATUS_SUCCESS;
  859. }
  860. VOID
  861. ndisCancelLogIrp(
  862. IN PDEVICE_OBJECT DeviceObject,
  863. IN PIRP Irp
  864. )
  865. /*++
  866. Routine Description:
  867. Arguments:
  868. DeviceObject - The adapter's device object.
  869. Irp - The IRP.
  870. Return Value:
  871. STATUS_SUCCESS if it should be.
  872. --*/
  873. {
  874. PIO_STACK_LOCATION IrpSp;
  875. PNDIS_USER_OPEN_CONTEXT OpenContext;
  876. PNDIS_MINIPORT_BLOCK Miniport;
  877. KIRQL OldIrql;
  878. UNREFERENCED_PARAMETER(DeviceObject);
  879. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  880. OpenContext = IrpSp->FileObject->FsContext;
  881. ASSERT(OpenContext != NULL);
  882. Miniport = OpenContext->Miniport;
  883. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  884. ASSERT (Miniport->Log != NULL);
  885. ASSERT (Miniport->Log->Irp == Irp);
  886. Miniport->Log->Irp = NULL;
  887. Irp->IoStatus.Status = STATUS_REQUEST_ABORTED;
  888. Irp->IoStatus.Information = 0;
  889. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  890. IoReleaseCancelSpinLock(Irp->CancelIrql);
  891. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  892. }
  893. NTSTATUS
  894. ndisDeviceControlIrpHandler(
  895. IN PDEVICE_OBJECT DeviceObject,
  896. IN PIRP Irp
  897. )
  898. /*++
  899. Routine Description:
  900. The handle for IRP_MJ_DEVICE_CONTROL IRPs.
  901. Arguments:
  902. DeviceObject - The adapter's device object.
  903. Irp - The IRP.
  904. Return Value:
  905. STATUS_SUCCESS if it should be.
  906. --*/
  907. {
  908. PIO_STACK_LOCATION IrpSp;
  909. PNDIS_USER_OPEN_CONTEXT OpenContext;
  910. NDIS_REQUEST Request;
  911. PNDIS_MINIPORT_BLOCK Miniport;
  912. NDIS_STATUS NdisStatus = NDIS_STATUS_FAILURE;
  913. UINT OidCount;
  914. PNDIS_OID OidArray;
  915. PUCHAR OidBuffer = NULL;
  916. ULONG BytesWritten = 0;
  917. PUCHAR Buffer;
  918. ULONG BufferLength;
  919. NTSTATUS Status = STATUS_SUCCESS;
  920. BOOLEAN fWaitComplete = FALSE;
  921. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  922. ("==>ndisDeviceControlIrpHandler\n"));
  923. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  924. if (IrpSp->FileObject == NULL)
  925. {
  926. return(STATUS_UNSUCCESSFUL);
  927. }
  928. Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  929. if (Miniport->Signature != (PVOID)MINIPORT_DEVICE_MAGIC_VALUE)
  930. {
  931. return (ndisDummyIrpHandler(DeviceObject, Irp));
  932. }
  933. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_REMOVE_IN_PROGRESS | fMINIPORT_PM_HALTED))
  934. {
  935. Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
  936. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  937. return STATUS_UNSUCCESSFUL;
  938. }
  939. IoMarkIrpPending (Irp);
  940. Irp->IoStatus.Status = STATUS_PENDING;
  941. Irp->IoStatus.Information = 0;
  942. OpenContext = IrpSp->FileObject->FsContext;
  943. switch (IrpSp->Parameters.DeviceIoControl.IoControlCode)
  944. {
  945. case IOCTL_NDIS_GET_LOG_DATA:
  946. if (Irp->MdlAddress == NULL)
  947. {
  948. Status = STATUS_INVALID_PARAMETER;
  949. break;
  950. }
  951. NdisStatus = Status = ndisMGetLogData(Miniport, Irp);
  952. if (Status != STATUS_PENDING)
  953. {
  954. fWaitComplete = TRUE;
  955. }
  956. break;
  957. //1this actually lets all the OIDs (set and query) to go to
  958. //1 miniport's QueryInformationHandler and not only
  959. //1 stats or query OIDs.
  960. case IOCTL_NDIS_QUERY_GLOBAL_STATS:
  961. //
  962. // check for a minimum length, alignment and valid OIDs
  963. //
  964. if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(NDIS_OID)) ||
  965. ((ULONG_PTR)Irp->AssociatedIrp.SystemBuffer & (sizeof(NDIS_OID)-1)) ||
  966. !ndisValidOid(OpenContext,
  967. *((PULONG)(Irp->AssociatedIrp.SystemBuffer))))
  968. {
  969. Status = STATUS_INVALID_PARAMETER;
  970. break;
  971. }
  972. Buffer = (Irp->MdlAddress != NULL) ? MDL_ADDRESS_SAFE(Irp->MdlAddress, LowPagePriority) : NULL;
  973. if ((Irp->MdlAddress != NULL) && (Buffer == NULL))
  974. {
  975. NdisStatus = NDIS_STATUS_RESOURCES;
  976. break;
  977. }
  978. //
  979. // check for alignment on output buffer
  980. //
  981. if ((ULONG_PTR)Buffer & (MAX_NATURAL_ALIGNMENT -1))
  982. {
  983. Status = STATUS_INVALID_PARAMETER;
  984. break;
  985. }
  986. //1 we can potentially send a set OID down with requestType = RequestTypeQueryInformation
  987. NdisStatus = ndisQueryDeviceOid(OpenContext,
  988. &Request,
  989. *((PNDIS_OID)Irp->AssociatedIrp.SystemBuffer),
  990. Buffer,
  991. (Irp->MdlAddress != NULL) ? MDL_SIZE(Irp->MdlAddress) : 0);
  992. BytesWritten = Request.DATA.QUERY_INFORMATION.BytesWritten;
  993. Irp->IoStatus.Information = BytesWritten;
  994. fWaitComplete = TRUE;
  995. break;
  996. case IOCTL_NDIS_QUERY_ALL_STATS:
  997. OidCount = OpenContext->OidList->StatsOidCount;
  998. OidArray = OpenContext->OidList->StatsOidArray;
  999. goto common;
  1000. break;
  1001. case IOCTL_NDIS_QUERY_SELECTED_STATS:
  1002. //
  1003. // This is essentially a combination of QUERY_ALL_STATS and QUERY_GLOBAL_STATS.
  1004. // Start off by verifying input parameters.
  1005. //
  1006. if ((IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(NDIS_OID)) ||
  1007. ((IrpSp->Parameters.DeviceIoControl.InputBufferLength % sizeof(NDIS_OID)) != 0) ||
  1008. ((ULONG_PTR)Irp->AssociatedIrp.SystemBuffer & (sizeof(NDIS_OID)-1)))
  1009. {
  1010. Status = STATUS_INVALID_PARAMETER;
  1011. break;
  1012. }
  1013. OidCount = IrpSp->Parameters.DeviceIoControl.InputBufferLength / sizeof(NDIS_OID);
  1014. OidArray = (PNDIS_OID)(Irp->AssociatedIrp.SystemBuffer);
  1015. OidBuffer = (PUCHAR)ALLOC_FROM_POOL(OidCount * sizeof(NDIS_OID), NDIS_TAG_ALLOC_MEM);
  1016. if (OidBuffer == NULL)
  1017. {
  1018. NdisStatus = NDIS_STATUS_RESOURCES;
  1019. break;
  1020. }
  1021. NdisMoveMemory(OidBuffer, (PUCHAR)OidArray, OidCount * sizeof(NDIS_OID));
  1022. OidArray = (PNDIS_OID)OidBuffer;
  1023. common:
  1024. BufferLength = (Irp->MdlAddress != NULL) ? MDL_SIZE(Irp->MdlAddress) : 0;
  1025. Buffer = (BufferLength != 0) ? (PUCHAR)MDL_ADDRESS_SAFE (Irp->MdlAddress, LowPagePriority) : NULL;
  1026. if (Buffer == NULL)
  1027. {
  1028. NdisStatus = NDIS_STATUS_RESOURCES;
  1029. break;
  1030. }
  1031. if ((ULONG_PTR)Buffer & (MAX_NATURAL_ALIGNMENT-1))
  1032. {
  1033. DBGPRINT_RAW(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
  1034. ("ndisDeviceControlIrpHandler: Misaligned data.\n"));
  1035. Status = STATUS_INVALID_PARAMETER;
  1036. break;
  1037. }
  1038. NdisStatus = ndisQueryStatisticsOids(Miniport,
  1039. OpenContext,
  1040. OidArray,
  1041. OidCount,
  1042. Buffer,
  1043. BufferLength,
  1044. &BytesWritten,
  1045. FALSE);
  1046. Irp->IoStatus.Information = BytesWritten;
  1047. fWaitComplete = TRUE;
  1048. break;
  1049. default:
  1050. Status = STATUS_NOT_IMPLEMENTED;
  1051. break;
  1052. }
  1053. if (fWaitComplete)
  1054. {
  1055. if (NdisStatus == NDIS_STATUS_INVALID_LENGTH)
  1056. {
  1057. Status = STATUS_BUFFER_OVERFLOW;
  1058. }
  1059. else if (NdisStatus == NDIS_STATUS_RESOURCES)
  1060. {
  1061. Status = STATUS_INSUFFICIENT_RESOURCES;
  1062. }
  1063. else if (NdisStatus == NDIS_STATUS_NOT_SUPPORTED)
  1064. {
  1065. Status = STATUS_SUCCESS;
  1066. }
  1067. else if (NdisStatus != NDIS_STATUS_SUCCESS)
  1068. {
  1069. Status = STATUS_UNSUCCESSFUL;
  1070. }
  1071. }
  1072. if (Status != STATUS_PENDING)
  1073. {
  1074. IrpSp->Control &= ~SL_PENDING_RETURNED;
  1075. Irp->IoStatus.Status = Status;
  1076. IoCompleteRequest (Irp, IO_NETWORK_INCREMENT);
  1077. }
  1078. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  1079. ("<==ndisDeviceControlIrpHandler\n"));
  1080. if (OidBuffer)
  1081. {
  1082. FREE_POOL(OidBuffer);
  1083. }
  1084. return Status;
  1085. }
  1086. NDIS_STATUS
  1087. FASTCALL
  1088. ndisQueryDeviceOid(
  1089. IN PNDIS_USER_OPEN_CONTEXT OpenContext,
  1090. IN PNDIS_REQUEST Request,
  1091. IN NDIS_OID Oid,
  1092. IN PVOID Buffer,
  1093. IN UINT BufferLength
  1094. )
  1095. /*++
  1096. Routine Description:
  1097. Arguments:
  1098. Return Value:
  1099. Status of operation
  1100. --*/
  1101. {
  1102. NDIS_STATUS NdisStatus;
  1103. PNDIS_MINIPORT_BLOCK Miniport;
  1104. do
  1105. {
  1106. Miniport = OpenContext->Miniport;
  1107. Request->RequestType = NdisRequestQueryStatistics;
  1108. Request->DATA.QUERY_INFORMATION.Oid = Oid;
  1109. Request->DATA.QUERY_INFORMATION.InformationBufferLength = BufferLength;
  1110. Request->DATA.QUERY_INFORMATION.InformationBuffer = Buffer;
  1111. Request->DATA.QUERY_INFORMATION.BytesWritten = 0;
  1112. Request->DATA.QUERY_INFORMATION.BytesNeeded = 0;
  1113. NdisStatus = ndisQuerySetMiniport(Miniport,
  1114. NULL,
  1115. FALSE,
  1116. Request,
  1117. NULL);
  1118. } while (FALSE);
  1119. return NdisStatus;
  1120. }
  1121. BOOLEAN
  1122. FASTCALL
  1123. ndisValidOid(
  1124. IN PNDIS_USER_OPEN_CONTEXT OpenContext,
  1125. IN NDIS_OID Oid
  1126. )
  1127. /*++
  1128. Routine Description:
  1129. Arguments:
  1130. Return Value:
  1131. TRUE if OID is valid, FALSE otherwise
  1132. --*/
  1133. {
  1134. UINT i;
  1135. //
  1136. // Always allow this range since it is vendor specific
  1137. //
  1138. //1 replace with (Oid & 0xFF000000) == 0xff000000
  1139. //1 this seems unnecessary
  1140. if ((Oid & 0xFF000000) != 0)
  1141. return(TRUE);
  1142. for (i = 0; i < OpenContext->OidList->FullOidCount; i++)
  1143. {
  1144. if (OpenContext->OidList->FullOidArray[i] == Oid)
  1145. {
  1146. break;
  1147. }
  1148. }
  1149. return (i < OpenContext->OidList->FullOidCount);
  1150. }
  1151. NTSTATUS
  1152. ndisCloseIrpHandler(
  1153. IN PDEVICE_OBJECT DeviceObject,
  1154. IN PIRP Irp
  1155. )
  1156. /*++
  1157. Routine Description:
  1158. The handle for IRP_MJ_CLOSE IRPs.
  1159. Arguments:
  1160. DeviceObject - The adapter's device object.
  1161. Irp - The IRP.
  1162. Return Value:
  1163. STATUS_SUCCESS if it should be.
  1164. --*/
  1165. {
  1166. PNDIS_MINIPORT_BLOCK Miniport;
  1167. PIO_STACK_LOCATION IrpSp;
  1168. PNDIS_USER_OPEN_CONTEXT OpenContext;
  1169. KIRQL OldIrql;
  1170. //1 investigate moving this to CLEAN_UP IRP
  1171. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  1172. ("==>ndisCloseIrpHandler\n"));
  1173. IF_DBG(DBG_COMP_PROTOCOL, DBG_LEVEL_ERR)
  1174. {
  1175. if (DbgIsNull(Irp))
  1176. {
  1177. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1178. (": Null Irp\n"));
  1179. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  1180. }
  1181. if (!DbgIsNonPaged(Irp))
  1182. {
  1183. DBGPRINT(DBG_COMP_ALL, DBG_LEVEL_ERR,
  1184. (": Irp not in NonPaged Memory\n"));
  1185. DBGBREAK(DBG_COMP_ALL, DBG_LEVEL_ERR);
  1186. }
  1187. }
  1188. Miniport = (PNDIS_MINIPORT_BLOCK)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  1189. if (Miniport->Signature != (PVOID)MINIPORT_DEVICE_MAGIC_VALUE)
  1190. {
  1191. return (ndisDummyIrpHandler(DeviceObject, Irp));
  1192. }
  1193. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  1194. OpenContext = IrpSp->FileObject->FsContext;
  1195. IrpSp->FileObject->FsContext = NULL;
  1196. ACQUIRE_SPIN_LOCK(&Miniport->Ref.SpinLock, &OldIrql);
  1197. if (OpenContext->AdminAccessAllowed)
  1198. {
  1199. Miniport->NumAdminOpens--;
  1200. }
  1201. else
  1202. {
  1203. Miniport->NumUserOpens--;
  1204. }
  1205. RELEASE_SPIN_LOCK(&Miniport->Ref.SpinLock, OldIrql);
  1206. FREE_POOL(OpenContext);
  1207. PnPReferencePackage();
  1208. NDIS_ACQUIRE_MINIPORT_SPIN_LOCK(Miniport, &OldIrql);
  1209. Miniport->UserModeOpenReferences--;
  1210. NDIS_RELEASE_MINIPORT_SPIN_LOCK(Miniport, OldIrql);
  1211. PnPDereferencePackage();
  1212. MINIPORT_DECREMENT_REF_CLOSE(Miniport, Irp);
  1213. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_SWENUM))
  1214. {
  1215. PBUS_INTERFACE_REFERENCE BusInterface;
  1216. BusInterface = (PBUS_INTERFACE_REFERENCE)(Miniport->BusInterface);
  1217. ASSERT(BusInterface != NULL);
  1218. if (BusInterface)
  1219. {
  1220. BusInterface->DereferenceDeviceObject(BusInterface->Interface.Context);
  1221. }
  1222. }
  1223. Irp->IoStatus.Status = STATUS_SUCCESS;
  1224. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1225. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  1226. ("<==NdisCloseIrpHandler\n"));
  1227. return STATUS_SUCCESS;
  1228. }
  1229. NTSTATUS
  1230. ndisDummyIrpHandler(
  1231. IN PDEVICE_OBJECT DeviceObject,
  1232. IN PIRP Irp
  1233. )
  1234. /*++
  1235. Routine Description:
  1236. Default handler. If this is a NDIS device, then we simply succeed. If not and we have a
  1237. custom handler, we pass it on. Else we succeed.
  1238. Arguments:
  1239. DeviceObject - The adapter's device object.
  1240. Irp - The IRP.
  1241. Return Value:
  1242. Always STATUS_SUCCESS.
  1243. --*/
  1244. {
  1245. PNDIS_DEVICE_LIST DeviceList;
  1246. PNDIS_MINIPORT_BLOCK Miniport;
  1247. PIO_STACK_LOCATION IrpSp;
  1248. NTSTATUS Status;
  1249. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  1250. ("==>ndisDummyIrpHandler\n"));
  1251. IrpSp = IoGetCurrentIrpStackLocation (Irp);
  1252. DeviceList = (PNDIS_DEVICE_LIST)((PNDIS_WRAPPER_CONTEXT)DeviceObject->DeviceExtension + 1);
  1253. Miniport = (PNDIS_MINIPORT_BLOCK)DeviceList;
  1254. do
  1255. {
  1256. //
  1257. // This is a miniport
  1258. //
  1259. if (Miniport->Signature == (PVOID)MINIPORT_DEVICE_MAGIC_VALUE)
  1260. {
  1261. if (IrpSp->MajorFunction == IRP_MJ_CLEANUP)
  1262. {
  1263. Status = STATUS_SUCCESS;
  1264. }
  1265. else
  1266. {
  1267. Status = STATUS_NOT_SUPPORTED;
  1268. }
  1269. break;
  1270. }
  1271. else if (DeviceList->Signature == (PVOID)CUSTOM_DEVICE_MAGIC_VALUE)
  1272. {
  1273. if (DeviceList->MajorFunctions[IrpSp->MajorFunction] == NULL)
  1274. {
  1275. Status = STATUS_NOT_SUPPORTED;
  1276. break;
  1277. }
  1278. else
  1279. {
  1280. return((*DeviceList->MajorFunctions[IrpSp->MajorFunction])(DeviceObject, Irp));
  1281. }
  1282. }
  1283. else
  1284. {
  1285. Status = STATUS_NOT_SUPPORTED;
  1286. }
  1287. } while (FALSE);
  1288. Irp->IoStatus.Status = Status;
  1289. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  1290. DBGPRINT_RAW(DBG_COMP_ALL, DBG_LEVEL_INFO,
  1291. ("<==ndisDummyIrpHandler\n"));
  1292. return Status;
  1293. }
  1294. NDIS_STATUS
  1295. ndisQueryStatisticsOids(
  1296. IN PNDIS_MINIPORT_BLOCK Miniport,
  1297. IN PNDIS_USER_OPEN_CONTEXT OpenContext,
  1298. IN PNDIS_OID OidArray,
  1299. IN UINT OidCount,
  1300. IN PUCHAR Buffer,
  1301. IN ULONG BufferLength,
  1302. IN PULONG pBytesWritten,
  1303. IN BOOLEAN AlignOutput
  1304. )
  1305. {
  1306. NDIS_STATUS NdisStatus;
  1307. ULONG CurrentOid;
  1308. NDIS_OID Oid;
  1309. NDIS_REQUEST Request;
  1310. ULONG DataLength;
  1311. ULONG BufferLengthRemained = BufferLength;
  1312. ULONG BytesWrittenThisOid = 0;
  1313. // ULONG BytesWrittenAlignedThisOid = 0;
  1314. ULONG NdisStatisticsHeaderSize;
  1315. ULONG BytesWritten = 0;
  1316. PNDIS_STATISTICS_VALUE StatisticsValue;
  1317. // PNDIS_STATISTICS_VALUE_EX StatisticsValueEx;
  1318. PUCHAR DoubleBuffer = NULL;
  1319. PVOID SourceBuffer;
  1320. ULONG SourceLength;
  1321. ULONG GenericULong;
  1322. TIME CurrTicks;
  1323. ULONG InfoFlags = 0;
  1324. BOOLEAN fPrv, fInt;
  1325. DBGPRINT_RAW(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
  1326. ("==>ndisQueryStatisticsOids\n"));
  1327. *pBytesWritten = 0;
  1328. NdisStatus = NDIS_STATUS_SUCCESS;
  1329. if (AlignOutput)
  1330. {
  1331. //
  1332. // activate for longhorn
  1333. //
  1334. ASSERT(FALSE);
  1335. return NDIS_STATUS_FAILURE;
  1336. // NdisStatisticsHeaderSize = NDIS_STATISTICS_EX_HEADER_SIZE;
  1337. // ZeroMemory(Buffer, BufferLength);
  1338. }
  1339. else
  1340. {
  1341. DoubleBuffer = (PUCHAR)ALLOC_FROM_POOL(BufferLength, NDIS_TAG_ALLOC_MEM);
  1342. if (DoubleBuffer == NULL)
  1343. {
  1344. return NDIS_STATUS_RESOURCES;
  1345. }
  1346. NdisStatisticsHeaderSize = NDIS_STATISTICS_HEADER_SIZE;
  1347. }
  1348. for (CurrentOid = 0; CurrentOid < OidCount; CurrentOid++)
  1349. {
  1350. SourceLength = 0;
  1351. SourceBuffer = NULL;
  1352. NdisZeroMemory(&Request, sizeof(NDIS_REQUEST));
  1353. //
  1354. // We need room for an NDIS_STATISTICS_VALUE (OID, Length, Data).
  1355. //
  1356. //1 check to see if having room for a ULONG is not good enough.
  1357. if (BufferLengthRemained < (ULONG)(NdisStatisticsHeaderSize + sizeof(ULONG)))
  1358. {
  1359. NdisStatus = NDIS_STATUS_INVALID_LENGTH;
  1360. break;
  1361. }
  1362. DataLength = BufferLengthRemained - NdisStatisticsHeaderSize;
  1363. //
  1364. // Check if the OID is part of supported list - if not do not
  1365. // error out but ignore
  1366. //
  1367. Oid = OidArray[CurrentOid];
  1368. //1 choose another name for NDIS_OID_PRIVATE. This is here
  1369. //1 to be backward compatible for those apps that send statistics
  1370. //1 OIDs with 0x80000000 bit set.
  1371. fPrv = ((Oid & NDIS_OID_MASK) == NDIS_OID_PRIVATE);
  1372. if (fPrv)
  1373. {
  1374. Oid &= ~NDIS_OID_PRIVATE;
  1375. }
  1376. //1 find a better way to find out if an OID is internal or not.
  1377. fInt = (
  1378. (Oid == OID_GEN_DIRECTED_FRAMES_RCV) ||
  1379. (Oid == OID_GEN_DIRECTED_FRAMES_XMIT) ||
  1380. (Oid == OID_GEN_MEDIA_IN_USE) ||
  1381. (Oid == OID_GEN_PHYSICAL_MEDIUM) ||
  1382. (Oid == OID_GEN_INIT_TIME_MS) ||
  1383. (Oid == OID_GEN_RESET_COUNTS) ||
  1384. (Oid == OID_GEN_MEDIA_SENSE_COUNTS) ||
  1385. (Oid == OID_GEN_ELAPSED_TIME) ||
  1386. (Oid == OID_GEN_RESET_VERIFY_PARAMETERS) ||
  1387. (Oid == OID_GEN_MINIPORT_INFO) ||
  1388. (Oid == OID_PNP_ENABLE_WAKE_UP));
  1389. if (fInt)
  1390. {
  1391. NdisStatus = NDIS_STATUS_SUCCESS;
  1392. switch (Oid)
  1393. {
  1394. case OID_GEN_DIRECTED_FRAMES_RCV:
  1395. SourceBuffer = &Miniport->NdisStats.DirectedPacketsIn;
  1396. if (DataLength >= sizeof(ULONG64))
  1397. {
  1398. SourceLength = sizeof(ULONG64);
  1399. }
  1400. else
  1401. {
  1402. SourceLength = sizeof(ULONG);
  1403. }
  1404. break;
  1405. case OID_GEN_DIRECTED_FRAMES_XMIT:
  1406. SourceBuffer = &Miniport->NdisStats.DirectedPacketsOut;
  1407. if (DataLength >= sizeof(ULONG64))
  1408. {
  1409. SourceLength = sizeof(ULONG64);
  1410. }
  1411. else
  1412. {
  1413. SourceLength = sizeof(ULONG);
  1414. }
  1415. break;
  1416. case OID_GEN_MEDIA_IN_USE:
  1417. SourceBuffer = &Miniport->MediaType;
  1418. SourceLength = sizeof(ULONG);
  1419. break;
  1420. case OID_PNP_ENABLE_WAKE_UP:
  1421. SourceBuffer = &Miniport->WakeUpEnable;
  1422. SourceLength = sizeof(ULONG);
  1423. break;
  1424. case OID_GEN_PHYSICAL_MEDIUM:
  1425. SourceBuffer = &Miniport->PhysicalMediumType;
  1426. SourceLength = sizeof(ULONG);
  1427. break;
  1428. case OID_GEN_INIT_TIME_MS:
  1429. SourceBuffer = &Miniport->InitTimeMs;
  1430. SourceLength = sizeof(ULONG);
  1431. break;
  1432. case OID_GEN_RESET_COUNTS:
  1433. GenericULong = (Miniport->InternalResetCount + Miniport->MiniportResetCount);
  1434. SourceBuffer = &GenericULong;
  1435. SourceLength = sizeof(ULONG);
  1436. break;
  1437. case OID_GEN_MEDIA_SENSE_COUNTS:
  1438. GenericULong = (Miniport->MediaSenseDisconnectCount + (Miniport->MediaSenseConnectCount << 16));
  1439. SourceBuffer = &GenericULong;
  1440. SourceLength = sizeof(ULONG);
  1441. break;
  1442. case OID_GEN_ELAPSED_TIME:
  1443. {
  1444. KeQueryTickCount(&CurrTicks);
  1445. CurrTicks.QuadPart -= Miniport->NdisStats.StartTicks.QuadPart;
  1446. CurrTicks.QuadPart = CurrTicks.QuadPart*KeQueryTimeIncrement()/(10*1000*1000);
  1447. SourceBuffer = &CurrTicks.LowPart;
  1448. SourceLength = sizeof(ULONG);
  1449. }
  1450. break;
  1451. case OID_GEN_RESET_VERIFY_PARAMETERS:
  1452. MoveMemory((PUCHAR)&ndisFlags, Buffer + NdisStatisticsHeaderSize, sizeof(ULONG));
  1453. SourceBuffer = NULL;
  1454. SourceLength = sizeof(ULONG);
  1455. ndisVerifierInitialization();
  1456. //
  1457. // when ndisFlags is set by ndis tester vs. reading it from
  1458. // registry, let it -clear- the verifier flags if necessary
  1459. // ndisVerifierInit takes care of -setting- them if necessary
  1460. //
  1461. if (!(ndisFlags & NDIS_GFLAG_INJECT_ALLOCATION_FAILURE))
  1462. ndisVerifierLevel &= ~DRIVER_VERIFIER_INJECT_ALLOCATION_FAILURES;
  1463. if (!(ndisFlags & NDIS_GFLAG_SPECIAL_POOL_ALLOCATION))
  1464. ndisVerifierLevel &= ~DRIVER_VERIFIER_SPECIAL_POOLING;
  1465. Request.DATA.SET_INFORMATION.BytesRead = sizeof(ULONG);
  1466. break;
  1467. case OID_GEN_MINIPORT_INFO:
  1468. {
  1469. InfoFlags = Miniport->InfoFlags;
  1470. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_64BITS_DMA))
  1471. InfoFlags |= NDIS_MINIPORT_64BITS_DMA;
  1472. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_IS_CO))
  1473. InfoFlags |= NDIS_MINIPORT_IS_CO;
  1474. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_REQUIRES_MEDIA_POLLING))
  1475. InfoFlags |= NDIS_MINIPORT_REQUIRES_MEDIA_POLLING;
  1476. if (MINIPORT_TEST_FLAG(Miniport, fMINIPORT_SUPPORTS_MEDIA_SENSE))
  1477. InfoFlags |= NDIS_MINIPORT_SUPPORTS_MEDIA_SENSE;
  1478. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_PM_SUPPORTED))
  1479. InfoFlags |= NDIS_MINIPORT_PM_SUPPORTED;
  1480. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_HIDDEN))
  1481. InfoFlags |= NDIS_MINIPORT_HIDDEN;
  1482. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_SWENUM))
  1483. InfoFlags |= NDIS_MINIPORT_SWENUM;
  1484. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_HARDWARE_DEVICE))
  1485. InfoFlags |= NDIS_MINIPORT_HARDWARE_DEVICE;
  1486. if (MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_NDIS_WDM_DRIVER))
  1487. InfoFlags |= NDIS_MINIPORT_WDM_DRIVER;
  1488. if (Miniport->DriverHandle->MiniportCharacteristics.CancelSendPacketsHandler)
  1489. {
  1490. InfoFlags |= NDIS_MINIPORT_SUPPORTS_CANCEL_SEND_PACKETS;
  1491. }
  1492. SourceBuffer = &InfoFlags;
  1493. SourceLength = sizeof(ULONG);
  1494. break;
  1495. }
  1496. default:
  1497. continue;
  1498. }
  1499. }
  1500. else
  1501. {
  1502. //
  1503. // not an "internal" OID
  1504. //
  1505. if (!ndisValidOid(OpenContext, Oid))
  1506. {
  1507. //
  1508. // not a valid OID either
  1509. //
  1510. continue;
  1511. }
  1512. //
  1513. // Transform OID based on media-type
  1514. //
  1515. if (Oid == OID_802_3_CURRENT_ADDRESS)
  1516. {
  1517. switch (Miniport->MediaType)
  1518. {
  1519. case NdisMedium802_5:
  1520. Oid = OID_802_5_CURRENT_ADDRESS;
  1521. break;
  1522. case NdisMediumFddi:
  1523. Oid = OID_FDDI_LONG_CURRENT_ADDR;
  1524. break;
  1525. case NdisMediumAtm:
  1526. Oid = OID_ATM_HW_CURRENT_ADDRESS;
  1527. break;
  1528. case NdisMediumWan:
  1529. Oid = OID_WAN_CURRENT_ADDRESS;
  1530. break;
  1531. #if ARCNET
  1532. case NdisMediumArcnetRaw:
  1533. Oid = OID_ARCNET_CURRENT_ADDRESS;
  1534. break;
  1535. #endif
  1536. }
  1537. }
  1538. else if (Oid == OID_802_3_PERMANENT_ADDRESS)
  1539. {
  1540. switch (Miniport->MediaType)
  1541. {
  1542. case NdisMedium802_5:
  1543. Oid = OID_802_5_PERMANENT_ADDRESS;
  1544. break;
  1545. case NdisMediumFddi:
  1546. Oid = OID_FDDI_LONG_PERMANENT_ADDR;
  1547. break;
  1548. case NdisMediumAtm:
  1549. Oid = OID_ATM_HW_CURRENT_ADDRESS;
  1550. break;
  1551. case NdisMediumWan:
  1552. Oid = OID_WAN_PERMANENT_ADDRESS;
  1553. break;
  1554. #if ARCNET
  1555. case NdisMediumArcnetRaw:
  1556. Oid = OID_ARCNET_PERMANENT_ADDRESS;
  1557. break;
  1558. #endif
  1559. }
  1560. }
  1561. if (!MINIPORT_PNP_TEST_FLAG(Miniport, fMINIPORT_SYSTEM_SLEEPING))
  1562. {
  1563. //1 eventually we need to find a way to check for the length ourselves
  1564. if (AlignOutput)
  1565. {
  1566. SourceBuffer = Buffer + NdisStatisticsHeaderSize;
  1567. }
  1568. else
  1569. {
  1570. SourceBuffer = DoubleBuffer;
  1571. }
  1572. NdisStatus = ndisQueryDeviceOid(OpenContext,
  1573. &Request,
  1574. Oid,
  1575. SourceBuffer,
  1576. BufferLengthRemained - NdisStatisticsHeaderSize);
  1577. if (NdisStatus == NDIS_STATUS_SUCCESS)
  1578. {
  1579. SourceLength = Request.DATA.QUERY_INFORMATION.BytesWritten;
  1580. }
  1581. else
  1582. {
  1583. SourceLength = 0;
  1584. }
  1585. if (AlignOutput)
  1586. {
  1587. SourceBuffer = NULL; // to avoid the copy since the data is already at the right place
  1588. }
  1589. }
  1590. else
  1591. {
  1592. NdisStatus = NDIS_STATUS_ADAPTER_NOT_FOUND;
  1593. }
  1594. }
  1595. if (NdisStatus == NDIS_STATUS_SUCCESS)
  1596. {
  1597. if ((SourceLength > 0) && (SourceBuffer != NULL))
  1598. {
  1599. MoveMemory(Buffer + NdisStatisticsHeaderSize, SourceBuffer, SourceLength);
  1600. }
  1601. //
  1602. // Advance our pointers.
  1603. //
  1604. BytesWrittenThisOid = SourceLength + NdisStatisticsHeaderSize;
  1605. if (AlignOutput)
  1606. {
  1607. //
  1608. // activate for longhorn
  1609. //
  1610. ASSERT(FALSE);
  1611. NdisStatus = NDIS_STATUS_FAILURE;
  1612. break;
  1613. #if 0
  1614. //
  1615. // Create the equivalent of an NDIS_STATISTICS_VALUE element for this OID value
  1616. // (the data itself was already written in the right place.
  1617. //
  1618. StatisticsValueEx = (PNDIS_STATISTICS_VALUE_EX)Buffer;
  1619. StatisticsValueEx->Oid = OidArray[CurrentOid]; // Not Oid since we map some
  1620. StatisticsValueEx->DataLength = SourceLength;
  1621. BytesWrittenAlignedThisOid = ALIGN_UP_MAX_NATURAL_ALIGNMENT_LENGTH(BytesWrittenThisOid);
  1622. if ((BufferLengthRemained - BytesWrittenAlignedThisOid) < (ULONG)(NdisStatisticsHeaderSize + sizeof(ULONG)))
  1623. {
  1624. //
  1625. // this is the last statistics we can report.
  1626. // report the Length without any padding
  1627. //
  1628. StatisticsValueEx->Length = BytesWrittenThisOid;
  1629. BufferLengthRemained -= BytesWrittenThisOid;
  1630. Buffer += BytesWrittenThisOid;
  1631. BytesWritten += BytesWrittenThisOid;
  1632. }
  1633. else
  1634. {
  1635. StatisticsValueEx->Length = BytesWrittenAlignedThisOid;
  1636. BufferLengthRemained -= BytesWrittenAlignedThisOid;
  1637. Buffer += BytesWrittenAlignedThisOid;
  1638. BytesWritten += BytesWrittenAlignedThisOid;
  1639. }
  1640. #endif
  1641. }
  1642. else
  1643. {
  1644. //
  1645. // Create the equivalent of an NDIS_STATISTICS_VALUE element for this OID value
  1646. // (the data itself was already written in the right place.
  1647. //
  1648. StatisticsValue = (PNDIS_STATISTICS_VALUE)Buffer;
  1649. StatisticsValue->Oid = OidArray[CurrentOid]; // Not Oid since we map some
  1650. StatisticsValue->DataLength = SourceLength;
  1651. BufferLengthRemained -= BytesWrittenThisOid;
  1652. Buffer += BytesWrittenThisOid;
  1653. BytesWritten += BytesWrittenThisOid;
  1654. }
  1655. }
  1656. else
  1657. {
  1658. break;
  1659. }
  1660. }
  1661. *pBytesWritten = BytesWritten;
  1662. if (NdisStatus == NDIS_STATUS_NOT_SUPPORTED)
  1663. {
  1664. NdisStatus = NDIS_STATUS_SUCCESS;
  1665. }
  1666. if (DoubleBuffer)
  1667. {
  1668. FREE_POOL(DoubleBuffer);
  1669. }
  1670. DBGPRINT_RAW(DBG_COMP_REQUEST, DBG_LEVEL_INFO,
  1671. ("<==ndisQueryStatisticsOids\n"));
  1672. return NdisStatus;
  1673. }