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.

921 lines
25 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. tunmp.c
  5. Abstract:
  6. Microsoft Tunnel interface Miniport driver
  7. Environment:
  8. Kernel mode only.
  9. Revision History:
  10. alid 10/22/2001
  11. --*/
  12. #include "precomp.h"
  13. #define __FILENUMBER 'MUNT'
  14. NTSTATUS
  15. DriverEntry(
  16. IN PDRIVER_OBJECT DriverObject,
  17. IN PUNICODE_STRING RegistryPath
  18. )
  19. /*++
  20. Routine Description:
  21. Arguments:
  22. Return Value:
  23. --*/
  24. {
  25. NDIS_STATUS Status;
  26. NDIS_MINIPORT_CHARACTERISTICS MChars;
  27. NDIS_STRING Name;
  28. DEBUGP(DL_INFO, ("Tunmp: ==>DriverEntry\n"));
  29. //
  30. // Register the miniport with NDIS.
  31. //
  32. NdisMInitializeWrapper(&NdisWrapperHandle, DriverObject, RegistryPath, NULL);
  33. if (NdisWrapperHandle == NULL)
  34. {
  35. Status = NDIS_STATUS_FAILURE;
  36. return Status;
  37. }
  38. TUN_ZERO_MEM(&MChars, sizeof(NDIS_MINIPORT_CHARACTERISTICS));
  39. MChars.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION;
  40. MChars.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION;
  41. MChars.InitializeHandler = TunMpInitialize;
  42. MChars.QueryInformationHandler = TunMpQueryInformation;
  43. MChars.SetInformationHandler = TunMpSetInformation;
  44. MChars.ResetHandler = NULL;
  45. MChars.ReturnPacketHandler = TunMpReturnPacket;
  46. MChars.SendPacketsHandler = TunMpSendPackets;
  47. MChars.HaltHandler = TunMpHalt;
  48. MChars.CheckForHangHandler = NULL;
  49. MChars.CancelSendPacketsHandler = NULL;
  50. MChars.PnPEventNotifyHandler = NULL;
  51. MChars.AdapterShutdownHandler = TunMpShutdown;
  52. Status = NdisMRegisterMiniport(NdisWrapperHandle,
  53. &MChars,
  54. sizeof(MChars));
  55. if (Status != NDIS_STATUS_SUCCESS)
  56. {
  57. NdisTerminateWrapper(NdisWrapperHandle, NULL);
  58. }
  59. TUN_INIT_LOCK(&TunGlobalLock);
  60. TUN_INIT_LIST_HEAD(&TunAdapterList);
  61. DEBUGP(DL_INFO, ("Tunmp: <==DriverEntry Status %lx\n", Status));
  62. return(Status);
  63. }
  64. NDIS_STATUS
  65. TunMpInitialize(
  66. OUT PNDIS_STATUS OpenErrorStatus,
  67. OUT PUINT SelectedMediumIndex,
  68. IN PNDIS_MEDIUM MediumArray,
  69. IN UINT MediumArraySize,
  70. IN NDIS_HANDLE MiniportAdapterHandle,
  71. IN NDIS_HANDLE ConfigurationContext
  72. )
  73. /*++
  74. Routine Description:
  75. This is the initialize handler.
  76. Arguments:
  77. OpenErrorStatus Not used by us.
  78. SelectedMediumIndex Place-holder for what media we are using
  79. MediumArray Array of ndis media passed down to us to pick from
  80. MediumArraySize Size of the array
  81. MiniportAdapterHandle The handle NDIS uses to refer to us
  82. WrapperConfigurationContext For use by NdisOpenConfiguration
  83. Return Value:
  84. NDIS_STATUS_SUCCESS unless something goes wrong
  85. --*/
  86. {
  87. UINT i, Length;
  88. PTUN_ADAPTER pAdapter = NULL;
  89. NDIS_MEDIUM AdapterMedium;
  90. NDIS_HANDLE ConfigHandle = NULL;
  91. PNDIS_CONFIGURATION_PARAMETER Parameter;
  92. PUCHAR NetworkAddress;
  93. NDIS_STATUS Status;
  94. NDIS_STRING MiniportNameStr = NDIS_STRING_CONST("MiniportName");
  95. DEBUGP(DL_INFO, ("==>TunMpInitialize: MiniportAdapterHandle %p\n", MiniportAdapterHandle));
  96. do
  97. {
  98. TUN_ALLOC_MEM(pAdapter, sizeof(TUN_ADAPTER));
  99. if (pAdapter == NULL)
  100. {
  101. break;
  102. }
  103. TUN_ZERO_MEM(pAdapter, sizeof(TUN_ADAPTER));
  104. TUN_SET_SIGNATURE(pAdapter, mc);
  105. pAdapter->MiniportHandle = MiniportAdapterHandle;
  106. //1 no need to specify NDIS_ATTRIBUTE_IGNORE...
  107. NdisMSetAttributesEx(MiniportAdapterHandle,
  108. pAdapter,
  109. 0,
  110. NDIS_ATTRIBUTE_IGNORE_TOKEN_RING_ERRORS |
  111. NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
  112. NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT |
  113. NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND |
  114. NDIS_ATTRIBUTE_SURPRISE_REMOVE_OK |
  115. NDIS_ATTRIBUTE_USES_SAFE_BUFFER_APIS |
  116. NDIS_ATTRIBUTE_DESERIALIZE,
  117. 0);
  118. NdisOpenConfiguration(&Status,
  119. &ConfigHandle,
  120. ConfigurationContext);
  121. if (Status != NDIS_STATUS_SUCCESS)
  122. {
  123. DEBUGP(DL_ERROR, ("TunMpInitialize: NdisOpenConfiguration failed. Status %lx\n", Status));
  124. break;
  125. }
  126. AdapterMedium = NdisMedium802_3; // Default
  127. TUN_COPY_MEM(pAdapter->PermanentAddress,
  128. TUN_CARD_ADDRESS,
  129. TUN_MAC_ADDR_LEN);
  130. TUN_COPY_MEM(pAdapter->CurrentAddress,
  131. TUN_CARD_ADDRESS,
  132. TUN_MAC_ADDR_LEN);
  133. pAdapter->Medium = AdapterMedium;
  134. pAdapter->MediumLinkSpeed = MediaParams[(UINT)AdapterMedium].LinkSpeed;
  135. pAdapter->MediumMinPacketLen = MediaParams[(UINT)AdapterMedium].MacHeaderLen;
  136. pAdapter->MediumMaxPacketLen = MediaParams[(UINT)AdapterMedium].MacHeaderLen+
  137. MediaParams[(UINT)AdapterMedium].MaxFrameLen;
  138. pAdapter->MediumMacHeaderLen = MediaParams[(UINT)AdapterMedium].MacHeaderLen;
  139. pAdapter->MediumMaxFrameLen = MediaParams[(UINT)AdapterMedium].MaxFrameLen;
  140. pAdapter->MaxLookAhead = MediaParams[(UINT)AdapterMedium].MaxFrameLen;
  141. //Get the software-configurable network address that was stored in the
  142. //registry when the adapter was installed in the machine.
  143. NdisReadNetworkAddress(&Status,
  144. &NetworkAddress,
  145. &Length,
  146. ConfigHandle);
  147. if (Status == NDIS_STATUS_SUCCESS)
  148. {
  149. #if TUN_ALLOW_ANY_MAC_ADDRESS
  150. if ((Length == ETH_LENGTH_OF_ADDRESS) &&
  151. (!ETH_IS_MULTICAST(NetworkAddress)))
  152. #else
  153. if ((Length == ETH_LENGTH_OF_ADDRESS) &&
  154. (!ETH_IS_MULTICAST(NetworkAddress)) &&
  155. (NetworkAddress[0] & 0x02))
  156. #endif
  157. {
  158. TUN_COPY_MEM(pAdapter->CurrentAddress,
  159. NetworkAddress,
  160. Length);
  161. }
  162. }
  163. //
  164. // read the miniport name
  165. //
  166. //1 make sure miniport name is really used
  167. NdisReadConfiguration(&Status,
  168. &Parameter,
  169. ConfigHandle,
  170. &MiniportNameStr,
  171. NdisParameterString);
  172. if (Status == NDIS_STATUS_SUCCESS)
  173. {
  174. TUN_ALLOC_MEM(pAdapter->MiniportName.Buffer,
  175. Parameter->ParameterData.StringData.Length);
  176. if (pAdapter->MiniportName.Buffer == NULL)
  177. {
  178. DEBUGP(DL_ERROR, ("TunMpInitialize: failed to allocate memory for miniport name.\n"));
  179. Status = NDIS_STATUS_RESOURCES;
  180. break;
  181. }
  182. pAdapter->MiniportName.Length = pAdapter->MiniportName.MaximumLength =
  183. Parameter->ParameterData.StringData.Length;
  184. TUN_COPY_MEM(pAdapter->MiniportName.Buffer,
  185. Parameter->ParameterData.StringData.Buffer,
  186. Parameter->ParameterData.StringData.Length);
  187. }
  188. else
  189. {
  190. DEBUGP(DL_ERROR, ("TunMpInitialize: NdisReadConfiguration failed to read miniport name. Status %lx\n", Status));
  191. break;
  192. }
  193. NdisCloseConfiguration(ConfigHandle);
  194. ConfigHandle = NULL;
  195. //
  196. //Make sure the medium saved is one of the ones being offered
  197. //
  198. for (i = 0; i < MediumArraySize; i++)
  199. {
  200. if (MediumArray[i] == AdapterMedium)
  201. {
  202. *SelectedMediumIndex = i;
  203. break;
  204. }
  205. }
  206. if (i == MediumArraySize)
  207. {
  208. Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
  209. DEBUGP(DL_ERROR, ("TunMpInitialize: Status %lx, AdapterMedium %lx\n",
  210. Status, AdapterMedium));
  211. break;
  212. }
  213. Status = TunMpCreateDevice(pAdapter);
  214. if (Status != NDIS_STATUS_SUCCESS)
  215. {
  216. DEBUGP(DL_ERROR, ("TunMpInitialize: TunMpCreateDevice failed. Status %lx\n",
  217. Status));
  218. break;
  219. }
  220. pAdapter->RefCount = 1;
  221. //Initialize the adapter spin lock
  222. TUN_INIT_LOCK(&pAdapter->Lock);
  223. //
  224. //Get the list heads for the pended read/write IRPS and received
  225. //packets (from the NDIS) initialized
  226. //
  227. InitializeListHead(&pAdapter->PendedReads); //read IRPs
  228. InitializeListHead(&pAdapter->PendedWrites); //writes IRPs
  229. InitializeListHead(&pAdapter->RecvPktQueue); //received packets
  230. NdisAllocatePacketPoolEx(&Status,
  231. &pAdapter->SendPacketPool,
  232. MIN_SEND_PACKET_POOL_SIZE,
  233. MAX_SEND_PACKET_POOL_SIZE
  234. - MIN_SEND_PACKET_POOL_SIZE,
  235. 4 * sizeof(PVOID)
  236. );
  237. if (Status != NDIS_STATUS_SUCCESS)
  238. {
  239. DEBUGP(DL_ERROR, ("TunMpInitialize: NdisAllocatePacketPoolEx for Send failed. Status %lx\n",
  240. Status));
  241. break;
  242. }
  243. //
  244. //Get the adapter listed in the tun global list of adapters
  245. //
  246. TUN_ACQUIRE_LOCK(&TunGlobalLock);
  247. TUN_INSERT_HEAD_LIST(&TunAdapterList, &pAdapter->Link);
  248. TUN_RELEASE_LOCK(&TunGlobalLock);
  249. } while (FALSE);
  250. if (Status != NDIS_STATUS_SUCCESS)
  251. {
  252. if (pAdapter != NULL)
  253. {
  254. if (ConfigHandle)
  255. {
  256. NdisCloseConfiguration(ConfigHandle);
  257. }
  258. if (pAdapter->NdisDeviceHandle)
  259. {
  260. NdisMDeregisterDevice(pAdapter->NdisDeviceHandle);
  261. }
  262. if (pAdapter->SendPacketPool)
  263. {
  264. NdisFreePacketPool(pAdapter->SendPacketPool);
  265. }
  266. TUN_FREE_MEM(pAdapter);
  267. }
  268. }
  269. DEBUGP(DL_INFO, ("<==TunMpInitialize: MiniportAdapterHandle %p, Status\n",
  270. MiniportAdapterHandle, Status));
  271. return Status;
  272. }
  273. NDIS_STATUS
  274. TunMpCreateDevice(
  275. IN PTUN_ADAPTER pAdapter
  276. )
  277. {
  278. LONG DeviceInstanceNumber;
  279. UNICODE_STRING usDeviceID;
  280. WCHAR TempBuffer[4] = {0};
  281. WCHAR DeviceNameBuffer[sizeof(DEVICE_NAME)+4] = {0};
  282. WCHAR SymbolicNameBuffer[sizeof(SYMBOLIC_NAME)+4] = {0};
  283. UNICODE_STRING DeviceName, SymbolicName;
  284. PDRIVER_DISPATCH MajorFunctions[IRP_MJ_MAXIMUM_FUNCTION+1];
  285. NTSTATUS NtStatus;
  286. NDIS_STATUS Status;
  287. UINT i;
  288. PDEVICE_OBJECT DeviceObject = NULL;
  289. NDIS_HANDLE NdisDeviceHandle = NULL;
  290. DEBUGP(DL_INFO, ("==>TunMpCreateDevice, pAdapter %p\n", pAdapter));
  291. do
  292. {
  293. DeviceInstanceNumber = InterlockedIncrement(&GlobalDeviceInstanceNumber);
  294. //
  295. // for the time being, allow one device only
  296. //
  297. // if (DeviceInstanceNumber > 99)
  298. if (DeviceInstanceNumber > 0)
  299. {
  300. Status = NDIS_STATUS_RESOURCES;
  301. break;
  302. }
  303. pAdapter->DeviceInstanceNumber = (ULONG)DeviceInstanceNumber;
  304. //
  305. //Initiallize a unicode string
  306. //
  307. usDeviceID.Buffer = TempBuffer;
  308. usDeviceID.Length = 0;
  309. usDeviceID.MaximumLength = sizeof(TempBuffer);
  310. NtStatus = RtlIntegerToUnicodeString ((ULONG)DeviceInstanceNumber, 10, &usDeviceID);
  311. if (!NT_SUCCESS(NtStatus))
  312. {
  313. //1 GlobalDeviceInstanceNumber is not protected properly
  314. InterlockedDecrement(&GlobalDeviceInstanceNumber);
  315. Status = NDIS_STATUS_RESOURCES;
  316. DEBUGP(DL_ERROR, ("TunMpCreateDevice: RtlIntegerToUnicodeString failed. NtStatus %lx\n",
  317. NtStatus));
  318. break;
  319. }
  320. wcscpy(DeviceNameBuffer, DEVICE_NAME);
  321. RtlInitUnicodeString(&DeviceName, DeviceNameBuffer);
  322. RtlAppendUnicodeStringToString(&DeviceName, &usDeviceID);
  323. wcscpy(SymbolicNameBuffer, SYMBOLIC_NAME);
  324. RtlInitUnicodeString(&SymbolicName, SymbolicNameBuffer);
  325. RtlAppendUnicodeStringToString(&SymbolicName, &usDeviceID);
  326. for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
  327. {
  328. MajorFunctions[i] = NULL;
  329. }
  330. MajorFunctions[IRP_MJ_CREATE] = TunFOpen;
  331. MajorFunctions[IRP_MJ_CLOSE] = TunFClose;
  332. MajorFunctions[IRP_MJ_READ] = TunRead;
  333. MajorFunctions[IRP_MJ_WRITE] = TunWrite;
  334. MajorFunctions[IRP_MJ_CLEANUP] = TunFCleanup;
  335. MajorFunctions[IRP_MJ_DEVICE_CONTROL] = TunFIoControl;
  336. Status = NdisMRegisterDevice(
  337. NdisWrapperHandle,
  338. &DeviceName,
  339. &SymbolicName,
  340. MajorFunctions,
  341. &DeviceObject,
  342. &NdisDeviceHandle
  343. );
  344. if (Status != NDIS_STATUS_SUCCESS)
  345. {
  346. DEBUGP(DL_ERROR, ("TunMpCreateDevice: NdisMRegisterDevice failed. Status %lx\n",
  347. Status));
  348. InterlockedDecrement(&GlobalDeviceInstanceNumber);
  349. break;
  350. }
  351. DeviceObject->Flags |= DO_DIRECT_IO;
  352. pAdapter->DeviceObject = DeviceObject;
  353. pAdapter->NdisDeviceHandle = NdisDeviceHandle;
  354. }while (FALSE);
  355. DEBUGP(DL_INFO, ("<==TunMpCreateDevice, pAdapter %p, Status %lx\n", pAdapter, Status));
  356. return Status;
  357. }
  358. VOID
  359. TunMpHalt(
  360. IN NDIS_HANDLE MiniportAdapterContext
  361. )
  362. /*++
  363. Routine Description:
  364. Halt handler. It frees the adapter object and corresponding device object.
  365. Arguments:
  366. MiniportAdapterContext Pointer to the Adapter
  367. Return Value:
  368. None.
  369. --*/
  370. {
  371. PTUN_ADAPTER pAdapter = (PTUN_ADAPTER)MiniportAdapterContext;
  372. NDIS_EVENT HaltReadyEvent;
  373. DEBUGP(DL_INFO, ("==>TunMpHalt, pAdapter %p\n", pAdapter));
  374. NdisInitializeEvent(&HaltReadyEvent);
  375. //
  376. // let's wait for the app to close all the handles
  377. //
  378. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  379. if (TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_CANT_HALT))
  380. {
  381. pAdapter->HaltEvent = &HaltReadyEvent;
  382. }
  383. TUN_RELEASE_LOCK(&pAdapter->Lock);
  384. if (pAdapter->HaltEvent)
  385. {
  386. NdisWaitEvent(pAdapter->HaltEvent, 0);
  387. }
  388. pAdapter->HaltEvent = 0;
  389. //
  390. // we should not have any pending NDIS sends
  391. //
  392. ASSERT(pAdapter->PendedReadCount == 0);
  393. //
  394. // Free the resources now
  395. //
  396. if (pAdapter->NdisDeviceHandle)
  397. {
  398. NdisMDeregisterDevice(pAdapter->NdisDeviceHandle);
  399. }
  400. InterlockedDecrement(&GlobalDeviceInstanceNumber);
  401. if (pAdapter->SendPacketPool)
  402. {
  403. NdisFreePacketPool(pAdapter->SendPacketPool);
  404. }
  405. //
  406. // remove it from the global queue
  407. //
  408. TUN_ACQUIRE_LOCK(&TunGlobalLock);
  409. TUN_REMOVE_ENTRY_LIST(&pAdapter->Link);
  410. TUN_RELEASE_LOCK(&TunGlobalLock);
  411. TUN_FREE_MEM(pAdapter);
  412. DEBUGP(DL_INFO, ("<==TunMpHalt, pAdapter %p\n", pAdapter));
  413. }
  414. VOID
  415. TunMpShutdown(
  416. IN NDIS_HANDLE MiniportAdapterContext
  417. )
  418. {
  419. DEBUGP(DL_INFO, ("==>TunMpShutdown, pAdapter %p\n", MiniportAdapterContext));
  420. //
  421. // nothing to do here
  422. //
  423. DEBUGP(DL_INFO, ("<==TunMpShutdown, pAdapter %p\n", MiniportAdapterContext));
  424. }
  425. VOID
  426. TunMpSendPackets(
  427. IN NDIS_HANDLE MiniportAdapterContext,
  428. IN PPNDIS_PACKET PacketArray,
  429. IN UINT NumberOfPackets
  430. )
  431. /*++
  432. Routine Description:
  433. Send packets handler. Just queues packets in the list of pended received packets.
  434. And then calls TunServiceReads to process packets.
  435. Arguments:
  436. MiniportAdapterContext Pointer to the adapter
  437. Packet Packet to send
  438. Flags Unused, passed down below
  439. Return Value:
  440. Return code from NdisSend
  441. --*/
  442. {
  443. PTUN_ADAPTER pAdapter = (PTUN_ADAPTER)MiniportAdapterContext;
  444. NDIS_STATUS NdisStatus;
  445. UINT Index;
  446. UINT BytesToSend;
  447. PLIST_ENTRY pRcvPacketEntry;
  448. PNDIS_PACKET pOldRcvPacket;
  449. DEBUGP(DL_LOUD, ("==>TunMpSendPackets, pAdapter %p, PacketArray %p, NumberOfPackets\n",
  450. MiniportAdapterContext, PacketArray, NumberOfPackets));
  451. TUN_REF_ADAPTER(pAdapter); // queued rcv packet
  452. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  453. if ((!TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_OPEN)) ||
  454. TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_OFF))
  455. {
  456. pAdapter->XmitError += NumberOfPackets;
  457. TUN_RELEASE_LOCK(&pAdapter->Lock);
  458. if (!TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_OPEN))
  459. {
  460. DEBUGP(DL_WARN, ("TunMpSendPackets, pAdapter %p, Adapter not open\n",
  461. pAdapter));
  462. NdisStatus = NDIS_STATUS_NO_CABLE;
  463. }
  464. else
  465. {
  466. DEBUGP(DL_WARN, ("TunMpSendPackets, pAdapter %p, Adapter off.\n",
  467. pAdapter));
  468. NdisStatus = NDIS_STATUS_ADAPTER_NOT_READY;
  469. }
  470. for(Index = 0; Index < NumberOfPackets; Index++)
  471. {
  472. NDIS_SET_PACKET_STATUS(PacketArray[Index], NdisStatus);
  473. NdisMSendComplete(pAdapter->MiniportHandle,
  474. PacketArray[Index],
  475. NdisStatus);
  476. }
  477. TUN_DEREF_ADAPTER(pAdapter);
  478. DEBUGP(DL_LOUD, ("<==TunMpSendPackets, pAdapter %p\n",
  479. MiniportAdapterContext));
  480. return;
  481. }
  482. for(Index = 0; Index < NumberOfPackets; Index++)
  483. {
  484. NdisQueryPacket(PacketArray[Index], NULL, NULL, NULL, &BytesToSend);
  485. //
  486. //if the packet size is invalid or no data buffer associated with it,
  487. //inform NDIS about the invalidity
  488. //
  489. if ((BytesToSend == 0) || (BytesToSend > pAdapter->MediumMaxPacketLen))
  490. {
  491. NDIS_SET_PACKET_STATUS(PacketArray[Index], NDIS_STATUS_FAILURE);
  492. pAdapter->XmitError++;
  493. TUN_RELEASE_LOCK(&pAdapter->Lock);
  494. NdisMSendComplete(pAdapter->MiniportHandle,
  495. PacketArray[Index],
  496. NDIS_STATUS_FAILURE);
  497. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  498. continue;
  499. }
  500. //
  501. //if there are already MAX_PEND packets in miniport's pended packet queue,
  502. // refuse the new ones with NDIS_STATUS_RESOURCES
  503. //
  504. else if(pAdapter->RecvPktCount >= MAX_RECV_QUEUE_SIZE)
  505. {
  506. pAdapter->XmitError += NumberOfPackets - Index;
  507. pAdapter->XmitErrorNoReadIrps += NumberOfPackets - Index;
  508. TUN_RELEASE_LOCK(&pAdapter->Lock);
  509. for (;Index < NumberOfPackets; Index++)
  510. {
  511. NDIS_SET_PACKET_STATUS(PacketArray[Index], NDIS_STATUS_RESOURCES);
  512. NdisMSendComplete(pAdapter->MiniportHandle,
  513. PacketArray[Index],
  514. NDIS_STATUS_RESOURCES);
  515. }
  516. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  517. break;
  518. }
  519. //
  520. //queue the new packet, and set the packet status to pending
  521. //
  522. TUN_INSERT_TAIL_LIST(&pAdapter->RecvPktQueue, TUN_RCV_PKT_TO_LIST_ENTRY(PacketArray[Index]));
  523. //need to make sure the packet pointer in this statement
  524. pAdapter->RecvPktCount++;
  525. TUN_REF_ADAPTER(pAdapter); // pended send
  526. NDIS_SET_PACKET_STATUS(PacketArray[Index], NDIS_STATUS_PENDING);
  527. }
  528. TUN_RELEASE_LOCK(&pAdapter->Lock);
  529. //
  530. // Run the receive queue service routine now.
  531. //
  532. TunServiceReads(pAdapter);
  533. TUN_DEREF_ADAPTER(pAdapter);
  534. DEBUGP(DL_LOUD, ("<==TunMpSendPackets, pAdapter %p\n",
  535. MiniportAdapterContext));
  536. return;
  537. }
  538. VOID
  539. TunMpReturnPacket(
  540. IN NDIS_HANDLE MiniportAdapterContext,
  541. IN PNDIS_PACKET NdisPacket
  542. )
  543. /*++
  544. Routine Description:
  545. NDIS entry point called to signify completion of a packet send.
  546. We pick up and complete the Write IRP corresponding to this packet.
  547. NDIS 5.1:
  548. Arguments:
  549. ProtocolBindingContext - pointer to open context
  550. pNdisPacket - packet that completed send
  551. Status - status of send
  552. Return Value:
  553. None
  554. --*/
  555. {
  556. PIRP pIrp;
  557. PIO_STACK_LOCATION pIrpSp;
  558. PTUN_ADAPTER pAdapter;
  559. pAdapter = (PTUN_ADAPTER)MiniportAdapterContext;
  560. DEBUGP(DL_LOUD, ("==>TunMpReturnPacket, pAdapter %p\n",
  561. pAdapter));
  562. //1 get rid of this
  563. TUN_STRUCT_ASSERT(pAdapter, mc);
  564. pIrp = TUN_IRP_FROM_SEND_PKT(NdisPacket);
  565. //
  566. // We are done with the NDIS_PACKET:
  567. //
  568. TUN_DEREF_SEND_PKT(NdisPacket);
  569. //
  570. // Complete the Write IRP with the right status.
  571. //
  572. pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
  573. pIrp->IoStatus.Information = pIrpSp->Parameters.Write.Length;
  574. pIrp->IoStatus.Status = STATUS_SUCCESS;
  575. DEBUGP(DL_VERY_LOUD, ("SendComplete: packet %p/IRP %p/Length %d "
  576. "completed with status %x\n",
  577. NdisPacket, pIrp, pIrp->IoStatus.Information, pIrp->IoStatus.Status));
  578. IoCompleteRequest(pIrp, IO_NO_INCREMENT);
  579. TUN_ACQUIRE_LOCK(&pAdapter->Lock);
  580. pAdapter->PendedSendCount--;
  581. pAdapter->RcvPackets++;
  582. if ((!TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_ACTIVE)) &&
  583. (pAdapter->PendedSendCount == 0) &&
  584. (TUN_TEST_FLAG(pAdapter, TUN_COMPLETE_REQUEST)) &&
  585. ((!TUN_TEST_FLAG(pAdapter, TUN_ADAPTER_OFF)) ||
  586. (pAdapter->PendedReadCount == 0)))
  587. {
  588. TUN_CLEAR_FLAG(pAdapter, TUN_COMPLETE_REQUEST);
  589. TUN_RELEASE_LOCK(&pAdapter->Lock);
  590. NdisMSetInformationComplete(&pAdapter->MiniportHandle,
  591. NDIS_STATUS_SUCCESS);
  592. }
  593. else
  594. {
  595. TUN_RELEASE_LOCK(&pAdapter->Lock);
  596. }
  597. TUN_DEREF_ADAPTER(pAdapter); // send complete - dequeued send IRP
  598. DEBUGP(DL_LOUD, ("<==TunMpReturnPacket, pAdapter %p\n",
  599. pAdapter));
  600. }
  601. VOID
  602. TunMpRefAdapter(
  603. IN PTUN_ADAPTER pAdapter
  604. )
  605. /*++
  606. Routine Description:
  607. Reference the given open context.
  608. NOTE: Can be called with or without holding the opencontext lock.
  609. Arguments:
  610. pOpenContext - pointer to open context
  611. Return Value:
  612. None
  613. --*/
  614. {
  615. NdisInterlockedIncrement(&pAdapter->RefCount);
  616. }
  617. VOID
  618. TunMpDerefAdapter(
  619. IN PTUN_ADAPTER pAdapter
  620. )
  621. /*++
  622. Routine Description:
  623. Dereference the given open context. If the ref count goes to zero,
  624. free it.
  625. NOTE: called without holding the opencontext lock
  626. Arguments:
  627. pAdapter - pointer to open context
  628. Return Value:
  629. None
  630. --*/
  631. {
  632. //1 how do we protect against ref count going to zero and back up again?
  633. if (NdisInterlockedDecrement(&pAdapter->RefCount) == 0)
  634. {
  635. DEBUGP(DL_INFO, ("DerefAdapter: Adapter %p, Flags %x, ref count is zero!\n",
  636. pAdapter, pAdapter->Flags));
  637. TUN_ASSERT(pAdapter->MiniportHandle == NULL);
  638. TUN_ASSERT(pAdapter->RefCount == 0);
  639. TUN_ASSERT(pAdapter->pFileObject == NULL);
  640. pAdapter->mc_sig++;
  641. //
  642. // Free it.
  643. //
  644. TUN_FREE_MEM(pAdapter);
  645. }
  646. }
  647. #if DBG
  648. VOID
  649. TunMpDbgRefAdapter(
  650. IN PTUN_ADAPTER pAdapter,
  651. IN ULONG FileNumber,
  652. IN ULONG LineNumber
  653. )
  654. {
  655. DEBUGP(DL_VERY_LOUD, (" RefAdapter: Adapter %p, old ref %d, File %c%c%c%c, line %d\n",
  656. pAdapter,
  657. pAdapter->RefCount,
  658. (CHAR)(FileNumber),
  659. (CHAR)(FileNumber >> 8),
  660. (CHAR)(FileNumber >> 16),
  661. (CHAR)(FileNumber >> 24),
  662. LineNumber));
  663. TunMpRefAdapter(pAdapter);
  664. }
  665. VOID
  666. TunMpDbgDerefAdapter(
  667. IN PTUN_ADAPTER pAdapter,
  668. IN ULONG FileNumber,
  669. IN ULONG LineNumber
  670. )
  671. {
  672. DEBUGP(DL_VERY_LOUD, ("DerefAdapter: Adapter %p, old ref %d, File %c%c%c%c, line %d\n",
  673. pAdapter,
  674. pAdapter->RefCount,
  675. (CHAR)(FileNumber),
  676. (CHAR)(FileNumber >> 8),
  677. (CHAR)(FileNumber >> 16),
  678. (CHAR)(FileNumber >> 24),
  679. LineNumber));
  680. TunMpDerefAdapter(pAdapter);
  681. }
  682. #endif // DBG