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.

222 lines
5.6 KiB

  1. /*++
  2. Copyright (c) 1995 Microsoft Corporation
  3. Module Name:
  4. ntos\tdi\isn\fwd\ddreqs.c
  5. Abstract:
  6. Management of demand dial request queues
  7. Author:
  8. Vadim Eydelman
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. LIST_ENTRY ConnectionIrpQueue;
  13. LIST_ENTRY ConnectionRequestQueue;
  14. /*++
  15. Q u e u e C o n n e c t i o n R e q u e s t
  16. Routine Description:
  17. Adds request to connected the interface to the queue
  18. Arguments:
  19. ifCB - control block of the interface that needs to be
  20. connected
  21. packet - packet that prompted the connection request
  22. data - pointer to actual data in the packet
  23. oldIRQL - IRQL at which interface lock was acquired
  24. Return Value:
  25. None
  26. Note that interface lock must be acquired before calling this
  27. routine which will release it
  28. --*/
  29. VOID
  30. QueueConnectionRequest (
  31. PINTERFACE_CB ifCB,
  32. PNDIS_PACKET packet,
  33. PUCHAR data,
  34. KIRQL oldIRQL
  35. ) {
  36. KIRQL cancelIRQL;
  37. IoAcquireCancelSpinLock (&cancelIRQL);
  38. SET_IF_CONNECTING (ifCB);
  39. if (!IsListEmpty (&ConnectionIrpQueue)) {
  40. ULONG ulBytes = 0;
  41. PIRP irp = CONTAINING_RECORD (
  42. ConnectionIrpQueue.Flink,
  43. IRP,
  44. Tail.Overlay.ListEntry);
  45. PIO_STACK_LOCATION irpStack=IoGetCurrentIrpStackLocation(irp);
  46. RemoveEntryList (&irp->Tail.Overlay.ListEntry);
  47. ASSERT (irpStack->Parameters.DeviceIoControl.IoControlCode
  48. ==IOCTL_FWD_GET_DIAL_REQUEST);
  49. ASSERT ((irpStack->Parameters.DeviceIoControl.IoControlCode&3)
  50. ==METHOD_BUFFERED);
  51. IoSetCancelRoutine (irp, NULL);
  52. IoReleaseCancelSpinLock (cancelIRQL);
  53. FillConnectionRequest (
  54. ifCB->ICB_Index,
  55. packet,
  56. data,
  57. (PFWD_DIAL_REQUEST)irp->AssociatedIrp.SystemBuffer,
  58. irpStack->Parameters.DeviceIoControl.OutputBufferLength,
  59. &ulBytes);
  60. irp->IoStatus.Information = ulBytes;
  61. irp->IoStatus.Status = STATUS_SUCCESS;
  62. KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
  63. IpxFwdDbgPrint (DBG_DIALREQS, DBG_WARNING,
  64. ("IpxFwd: Passing dial request for if %ld (icb:%08lx) with %d bytes of data.\n",
  65. ifCB->ICB_Index, ifCB, irp->IoStatus.Information));
  66. IoCompleteRequest (irp, IO_NO_INCREMENT);
  67. }
  68. else {
  69. InsertTailList (&ConnectionRequestQueue, &ifCB->ICB_ConnectionLink);
  70. IoReleaseCancelSpinLock (cancelIRQL);
  71. ifCB->ICB_ConnectionPacket = packet;
  72. ifCB->ICB_ConnectionData = data;
  73. KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
  74. }
  75. }
  76. /*++
  77. D e q u e u e C o n n e c t i o n R e q u e s t
  78. Routine Description:
  79. Removes conection requset for the interface from the queue
  80. Arguments:
  81. ifCB - control block of the interface that needs to be
  82. removed
  83. Return Value:
  84. None
  85. --*/
  86. VOID
  87. DequeueConnectionRequest (
  88. PINTERFACE_CB ifCB
  89. ) {
  90. KIRQL cancelIRQL;
  91. IoAcquireCancelSpinLock (&cancelIRQL);
  92. if (IsListEntry (&ifCB->ICB_ConnectionLink)) {
  93. RemoveEntryList (&ifCB->ICB_ConnectionLink);
  94. InitializeListEntry (&ifCB->ICB_ConnectionLink);
  95. }
  96. IoReleaseCancelSpinLock (cancelIRQL);
  97. }
  98. /*++
  99. F i l l C o n n e c t i o n R e q u e s t
  100. Routine Description:
  101. Fills the provided buffer with index of interface that needs
  102. to be connected and packet that prompted the request
  103. Arguments:
  104. index - if index
  105. packet - packet that prompted the request
  106. data - pointer to IPX data (IPX header) inside of the packet
  107. request - request buffer to fill
  108. reqSize - size of request buffer
  109. bytesCopied - bytesCopied into the request buffer
  110. Return Value:
  111. STATUS_SUCCESS - array was filled successfully
  112. This routine assumes that there it is called only when there
  113. are outstanding requests in the request queue
  114. --*/
  115. VOID
  116. FillConnectionRequest (
  117. IN ULONG index,
  118. IN PNDIS_PACKET packet,
  119. IN PUCHAR data,
  120. IN OUT PFWD_DIAL_REQUEST request,
  121. IN ULONG reqSize,
  122. OUT PULONG bytesCopied
  123. ) {
  124. PNDIS_BUFFER buf;
  125. *bytesCopied = 0;
  126. request->IfIndex = index;
  127. NdisQueryPacket (packet, NULL, NULL, &buf, NULL);
  128. do {
  129. PVOID va;
  130. UINT length;
  131. NdisQueryBuffer (buf, &va, &length);
  132. if (((PUCHAR)va<=data)
  133. && ((PUCHAR)va+length>data)) {
  134. TdiCopyMdlToBuffer (buf,
  135. (ULONG)(data-(PUCHAR)va),
  136. request,
  137. FIELD_OFFSET (FWD_DIAL_REQUEST, Packet),
  138. reqSize,
  139. bytesCopied);
  140. *bytesCopied += FIELD_OFFSET (FWD_DIAL_REQUEST, Packet);
  141. break;
  142. }
  143. NdisGetNextBuffer (buf, &buf);
  144. }
  145. while (buf!=NULL);
  146. }
  147. /*++
  148. F a i l C o n n e c t i o n R e q u e s t s
  149. Routine Description:
  150. Cleans up on connection request failure
  151. Arguments:
  152. InterfaceIndex - index of interface that could not be connected
  153. Return Value:
  154. STATUS_SUCCESS - clean up was successfull
  155. STATUS_UNSUCCESSFUL - interface with this index does not exist
  156. --*/
  157. NTSTATUS
  158. FailConnectionRequest (
  159. IN ULONG InterfaceIndex
  160. ) {
  161. PINTERFACE_CB ifCB;
  162. KIRQL oldIRQL;
  163. ASSERT (InterfaceIndex!=FWD_INTERNAL_INTERFACE_INDEX);
  164. ifCB = GetInterfaceReference (InterfaceIndex);
  165. if (ifCB!=NULL) {
  166. IpxFwdDbgPrint (DBG_DIALREQS, DBG_WARNING,
  167. ("IpxFwd: Dial request failed for if %ld (icb:%08lx).\n",
  168. ifCB->ICB_Index, ifCB));
  169. ProcessInternalQueue (ifCB);
  170. ProcessExternalQueue (ifCB);
  171. KeAcquireSpinLock (&ifCB->ICB_Lock, &oldIRQL);
  172. if (IS_IF_CONNECTING (ifCB)) {
  173. SET_IF_NOT_CONNECTING (ifCB);
  174. DequeueConnectionRequest (ifCB);
  175. }
  176. KeReleaseSpinLock (&ifCB->ICB_Lock, oldIRQL);
  177. ReleaseInterfaceReference (ifCB);
  178. return STATUS_SUCCESS;
  179. }
  180. else
  181. return STATUS_UNSUCCESSFUL;
  182. }