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.

265 lines
7.7 KiB

  1. /*++
  2. Copyright (c) 1989-2001 Microsoft Corporation
  3. Module Name:
  4. receive.c
  5. Abstract:
  6. Implement the TDI_RECEIVE for session service
  7. Author:
  8. Jiandong Ruan
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "receive.tmh"
  13. VOID
  14. SmbCancelReceive(
  15. IN PDEVICE_OBJECT Device,
  16. IN PIRP Irp
  17. )
  18. {
  19. PIO_STACK_LOCATION IrpSp;
  20. PSMB_CONNECT ConnectObject;
  21. PLIST_ENTRY Entry;
  22. PIRP RcvIrp;
  23. KIRQL Irql;
  24. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  25. if (IrpSp->FileObject->FsContext2 != UlongToPtr(SMB_TDI_CONNECT)) {
  26. ASSERT(0);
  27. return;
  28. }
  29. ConnectObject = (PSMB_CONNECT)IrpSp->FileObject->FsContext;
  30. IoSetCancelRoutine(Irp, NULL);
  31. IoReleaseCancelSpinLock(Irp->CancelIrql);
  32. SmbTrace(SMB_TRACE_TCP, ("Cancel Receive Irp %p ConnectObject=%p ClientObject=%p",
  33. Irp, ConnectObject, ConnectObject->ClientObject));
  34. PUSH_LOCATION(ConnectObject, 0x800000);
  35. SMB_ACQUIRE_SPINLOCK(ConnectObject, Irql);
  36. Entry = ConnectObject->RcvList.Flink;
  37. while (Entry != &ConnectObject->RcvList) {
  38. RcvIrp = CONTAINING_RECORD(Entry, IRP, Tail.Overlay.ListEntry);
  39. if (RcvIrp == Irp) {
  40. RemoveEntryList(Entry);
  41. InitializeListHead(Entry);
  42. SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
  43. Irp->IoStatus.Status = STATUS_CANCELLED;
  44. Irp->IoStatus.Information = 0;
  45. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  46. PUSH_LOCATION(ConnectObject, 0x800010);
  47. SmbDereferenceConnect(ConnectObject, SMB_REF_RECEIVE);
  48. return;
  49. }
  50. Entry = Entry->Flink;
  51. }
  52. SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
  53. ASSERT(0);
  54. }
  55. NTSTATUS
  56. SmbPullDataFromXport(
  57. PSMB_CONNECT ConnectObject
  58. )
  59. {
  60. return STATUS_SUCCESS;
  61. }
  62. int SmbReceivePassNumber = 0;
  63. NTSTATUS
  64. SmbReceive(
  65. PSMB_DEVICE Device,
  66. PIRP Irp
  67. )
  68. /*++
  69. Routine Description:
  70. TDI_RECEIVE
  71. Arguments:
  72. Return Value:
  73. --*/
  74. {
  75. PIO_STACK_LOCATION IrpSp = NULL;
  76. PSMB_CONNECT ConnectObject = NULL;
  77. KIRQL Irql;
  78. NTSTATUS status = STATUS_PENDING;
  79. LONG BytesTaken, ClientBufferSize;
  80. PDEVICE_OBJECT TcpDeviceObject = NULL;
  81. PFILE_OBJECT TcpFileObject = NULL;
  82. PTDI_REQUEST_KERNEL_RECEIVE ClientRcvParams;
  83. //
  84. // Since I never see this code path covered in my test,
  85. // I put an assert here to get a chance to take a look
  86. // when it is really taken.
  87. //
  88. // Srv.sys does call this function.
  89. SmbReceivePassNumber++;
  90. SmbPrint(SMB_TRACE_CALL, ("SmbReceive\n"));
  91. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  92. ClientRcvParams = (PTDI_REQUEST_KERNEL_RECEIVE)&IrpSp->Parameters;
  93. ConnectObject = SmbVerifyAndReferenceConnect(IrpSp->FileObject, SMB_REF_RECEIVE);
  94. if (NULL == ConnectObject) {
  95. ASSERT(0);
  96. return STATUS_INVALID_HANDLE;
  97. }
  98. PUSH_LOCATION(ConnectObject, 0x900000);
  99. if (ConnectObject->State != SMB_CONNECTED) {
  100. PUSH_LOCATION(ConnectObject, 0x900020);
  101. ASSERT(0);
  102. SmbDereferenceConnect(ConnectObject, SMB_REF_RECEIVE);
  103. return STATUS_INVALID_DEVICE_REQUEST;
  104. }
  105. //
  106. // Sanity check
  107. //
  108. ClientBufferSize = ClientRcvParams->ReceiveLength;
  109. if ((ClientRcvParams->ReceiveFlags & (TDI_RECEIVE_EXPEDITED | TDI_RECEIVE_PEEK)) ||
  110. Irp->MdlAddress == NULL || ClientBufferSize == 0) {
  111. Irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
  112. Irp->IoStatus.Information = 0;
  113. IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
  114. SmbDereferenceConnect(ConnectObject, SMB_REF_RECEIVE);
  115. return status;
  116. }
  117. PUSH_LOCATION(ConnectObject, 0x900030);
  118. SMB_ACQUIRE_SPINLOCK(ConnectObject, Irql);
  119. if (NULL == ConnectObject->TcpContext) {
  120. SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
  121. return STATUS_CONNECTION_RESET;
  122. }
  123. if (ConnectObject->StateRcvHandler != SmbPartialRcv || ConnectObject->ClientIrp != NULL) {
  124. BREAK_WHEN_TAKE();
  125. //
  126. // Queue the IRP
  127. //
  128. IoAcquireCancelSpinLock(&Irp->CancelIrql);
  129. if (!Irp->Cancel) {
  130. IoMarkIrpPending(Irp);
  131. status = STATUS_PENDING;
  132. InsertTailList(&ConnectObject->RcvList, &Irp->Tail.Overlay.ListEntry);
  133. IoSetCancelRoutine(Irp, SmbCancelReceive);
  134. PUSH_LOCATION(ConnectObject, 0x900040);
  135. } else {
  136. status = STATUS_CANCELLED;
  137. PUSH_LOCATION(ConnectObject, 0x900050);
  138. }
  139. IoReleaseCancelSpinLock(Irp->CancelIrql);
  140. SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
  141. if (status != STATUS_PENDING) {
  142. PUSH_LOCATION(ConnectObject, 0x900060);
  143. SmbDereferenceConnect(ConnectObject, SMB_REF_RECEIVE);
  144. }
  145. return status;
  146. }
  147. //
  148. // Client has backlog either in us or in TCP
  149. //
  150. ASSERT(ConnectObject->BytesRemaining > 0);
  151. ASSERT(ConnectObject->BytesRemaining <= ConnectObject->CurrentPktLength);
  152. ConnectObject->ClientIrp = Irp;
  153. ConnectObject->ClientMdl = Irp->MdlAddress;
  154. ConnectObject->ClientBufferSize = ClientBufferSize;
  155. ConnectObject->FreeBytesInMdl = ConnectObject->ClientBufferSize;
  156. //
  157. // First, we need to copy the remaining data in the IndicateBuffer if any
  158. //
  159. if (ConnectObject->BytesInIndicate > 0) {
  160. PUSH_LOCATION(ConnectObject, 0x900070);
  161. // BREAK_WHEN_TAKE();
  162. BytesTaken = 0;
  163. IoMarkIrpPending(Irp);
  164. status = SmbFillIrp(ConnectObject, ConnectObject->IndicateBuffer,
  165. ConnectObject->BytesInIndicate, &BytesTaken);
  166. ASSERT(BytesTaken <= ConnectObject->BytesInIndicate);
  167. ConnectObject->BytesInIndicate -= BytesTaken;
  168. if (status == STATUS_SUCCESS) {
  169. PUSH_LOCATION(ConnectObject, 0x900080);
  170. if (ConnectObject->BytesInIndicate) {
  171. PUSH_LOCATION(ConnectObject, 0x900090);
  172. //
  173. // The buffer is too small
  174. //
  175. ASSERT(ConnectObject->ClientIrp == NULL);
  176. ASSERT(ConnectObject->ClientMdl == NULL);
  177. RtlMoveMemory(
  178. ConnectObject->IndicateBuffer + BytesTaken,
  179. ConnectObject->IndicateBuffer,
  180. ConnectObject->BytesInIndicate
  181. );
  182. }
  183. //
  184. // The IRP has been completed by SmbFillIrp. Returning STATUS_PENDING to avoid
  185. // double completion
  186. //
  187. status = STATUS_PENDING;
  188. goto cleanup;
  189. }
  190. ASSERT (status == STATUS_MORE_PROCESSING_REQUIRED);
  191. }
  192. ASSERT (ConnectObject->BytesInIndicate == 0);
  193. ASSERT (ConnectObject->ClientIrp);
  194. ASSERT (ConnectObject->ClientMdl);
  195. ASSERT (IsValidPartialRcvState(ConnectObject));
  196. SmbPrepareReceiveIrp(ConnectObject);
  197. TcpFileObject = ConnectObject->TcpContext->Connect.ConnectObject;
  198. TcpDeviceObject = IoGetRelatedDeviceObject(TcpFileObject);
  199. ObReferenceObject(TcpFileObject);
  200. SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
  201. ConnectObject->PendingIRPs[SMB_PENDING_RECEIVE] = ConnectObject->ClientIrp;
  202. IoMarkIrpPending(Irp);
  203. status = IoCallDriver(TcpDeviceObject, ConnectObject->ClientIrp);
  204. ObDereferenceObject(TcpFileObject);
  205. return STATUS_PENDING;
  206. cleanup:
  207. SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
  208. return status;
  209. }