Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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