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.

270 lines
6.8 KiB

  1. /*++
  2. Copyright (c) 1989-2001 Microsoft Corporation
  3. Module Name:
  4. send.c
  5. Abstract:
  6. Implement TDI_SEND
  7. Author:
  8. Jiandong Ruan
  9. Revision History:
  10. --*/
  11. #include "precomp.h"
  12. #include "send.tmh"
  13. PMDL
  14. SmbAllocateNetBuffer(
  15. ULONG uNumOfBytes
  16. )
  17. {
  18. PVOID pvBuf = NULL;
  19. PVOID pvMappedBuf = NULL;
  20. PMDL pMdl = NULL;
  21. pvBuf = ExAllocatePoolWithTag(
  22. NonPagedPool,
  23. uNumOfBytes,
  24. NBT_HEADER_TAG
  25. );
  26. if (NULL == pvBuf) {
  27. goto error;
  28. }
  29. pMdl = IoAllocateMdl(pvBuf, uNumOfBytes, FALSE, FALSE, NULL);
  30. if (NULL == pMdl) {
  31. ExFreePool(pvBuf);
  32. goto error;
  33. }
  34. MmBuildMdlForNonPagedPool(pMdl);
  35. //
  36. // Verify the mapped system address == pvBuf
  37. // SmbFreeNetBuffer depends on this assumption.
  38. //
  39. pvMappedBuf = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority);
  40. if (pvMappedBuf != pvBuf) {
  41. ExFreePool(pvBuf);
  42. IoFreeMdl(pMdl);
  43. ASSERT(0);
  44. pMdl = NULL;
  45. }
  46. error:
  47. return pMdl;
  48. }
  49. VOID
  50. SmbFreeNetBuffer(
  51. PMDL pMdl
  52. )
  53. {
  54. PVOID pvBuf = NULL;
  55. if (NULL == pMdl) {
  56. goto error;
  57. }
  58. pvBuf = MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority);
  59. if (NULL != pvBuf) {
  60. ExFreePool(pvBuf);
  61. pvBuf = NULL;
  62. }
  63. IoFreeMdl(pMdl);
  64. pMdl = NULL;
  65. error:
  66. return;
  67. }
  68. NTSTATUS
  69. SmbSendCompletion(
  70. IN PDEVICE_OBJECT DeviceObject,
  71. IN PIRP Irp,
  72. IN PSMB_CONNECT ConnectObject
  73. )
  74. /*++
  75. Routine Description:
  76. This the completion routine of sending a packet
  77. Arguments:
  78. Return Value:
  79. --*/
  80. {
  81. PMDL Mdl;
  82. if (Irp->PendingReturned) {
  83. IoMarkIrpPending(Irp);
  84. }
  85. Mdl = Irp->MdlAddress;
  86. if (Mdl->MdlFlags & MDL_NETWORK_HEADER) {
  87. (PUCHAR)Mdl->MappedSystemVa += SMB_SESSION_HEADER_SIZE;
  88. Mdl->ByteOffset += SMB_SESSION_HEADER_SIZE;
  89. Mdl->ByteCount -= SMB_SESSION_HEADER_SIZE;
  90. } else {
  91. ASSERT(NULL != Mdl->Next);
  92. Irp->MdlAddress = Mdl->Next;
  93. ASSERT(MmGetMdlByteCount(Mdl) == SMB_SESSION_HEADER_SIZE);
  94. SmbFreeNetBuffer(Mdl);
  95. Mdl = NULL;
  96. }
  97. if (Irp->IoStatus.Status == STATUS_SUCCESS && Irp->IoStatus.Information >= SMB_SESSION_HEADER_SIZE) {
  98. SmbPrint(SMB_TRACE_TCP, ("SmbSendCompletion: Send %d bytes\n", Irp->IoStatus.Information));
  99. Irp->IoStatus.Information -= SMB_SESSION_HEADER_SIZE;
  100. ConnectObject->BytesSent += (ULONG)(Irp->IoStatus.Information);
  101. } else {
  102. Irp->IoStatus.Information = 0;
  103. SmbPrint(SMB_TRACE_TCP, ("SmbSendCompletion: status=0x%08lx\n", Irp->IoStatus.Status));
  104. ASSERT (Irp->IoStatus.Status != STATUS_CONNECTION_ACTIVE);
  105. }
  106. ConnectObject->PendingIRPs[SMB_PENDING_SEND] = NULL;
  107. SmbDereferenceConnect(ConnectObject, SMB_REF_SEND);
  108. return STATUS_SUCCESS;
  109. }
  110. NTSTATUS
  111. SmbSend(
  112. PSMB_DEVICE Device,
  113. PIRP Irp
  114. )
  115. /*++
  116. Routine Description:
  117. TDI_SEND
  118. RDR/SRV is using backfill mode only at this time. So non-backfill mode is postponed.
  119. Arguments:
  120. Return Value:
  121. --*/
  122. {
  123. PIO_STACK_LOCATION IrpSp = NULL;
  124. NTSTATUS status = STATUS_UNSUCCESSFUL;
  125. PTDI_REQUEST_KERNEL_SEND TdiRequest = NULL;
  126. PMDL Mdl = NULL;
  127. PSMB_CONNECT ConnectObject = NULL;
  128. PULONG SmbHdr = NULL;
  129. PDEVICE_OBJECT DeviceObject = NULL;
  130. PFILE_OBJECT FileObject = NULL;
  131. DWORD SendLength = 0;
  132. KIRQL Irql;
  133. PMDL pMdlNbtHdr = NULL;
  134. IrpSp = IoGetCurrentIrpStackLocation(Irp);
  135. TdiRequest = (PTDI_REQUEST_KERNEL_SEND)&IrpSp->Parameters;
  136. Mdl = Irp->MdlAddress;
  137. if (NULL == Mdl) {
  138. return STATUS_INVALID_PARAMETER;
  139. }
  140. SendLength = TdiRequest->SendLength;
  141. if (SendLength > SMB_MAX_SESSION_PACKET) {
  142. //
  143. // Shouldn't happen, in case ......
  144. //
  145. ASSERT(0);
  146. return STATUS_INVALID_PARAMETER;
  147. }
  148. ConnectObject = SmbVerifyAndReferenceConnect(IrpSp->FileObject, SMB_REF_SEND);
  149. if (NULL == ConnectObject) {
  150. ASSERT(0);
  151. return STATUS_INVALID_HANDLE;
  152. }
  153. SMB_ACQUIRE_SPINLOCK(ConnectObject, Irql);
  154. if (ConnectObject->State != SMB_CONNECTED || ConnectObject->TcpContext == NULL) {
  155. SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
  156. SmbDereferenceConnect(ConnectObject, SMB_REF_SEND);
  157. return STATUS_INVALID_DEVICE_REQUEST;
  158. }
  159. FileObject = ConnectObject->TcpContext->Connect.ConnectObject;
  160. ASSERT(FileObject != NULL);
  161. ConnectObject->PendingIRPs[SMB_PENDING_SEND] = Irp;
  162. //
  163. // Reference the FileObject in case that it is closed and freed.
  164. //
  165. ObReferenceObject(FileObject);
  166. SMB_RELEASE_SPINLOCK(ConnectObject, Irql);
  167. DeviceObject = IoGetRelatedDeviceObject(FileObject);
  168. if (Mdl->MdlFlags & MDL_NETWORK_HEADER) {
  169. //
  170. // Backfill mode
  171. //
  172. (PUCHAR)Mdl->MappedSystemVa -= SMB_SESSION_HEADER_SIZE;
  173. Mdl->ByteOffset -= SMB_SESSION_HEADER_SIZE;
  174. Mdl->ByteCount += SMB_SESSION_HEADER_SIZE;
  175. SmbHdr = (PULONG)Mdl->MappedSystemVa;
  176. *SmbHdr = htonl(SendLength);
  177. } else {
  178. //
  179. // we need to attach our own header
  180. //
  181. pMdlNbtHdr = SmbAllocateNetBuffer(SMB_SESSION_HEADER_SIZE);
  182. if (NULL == pMdlNbtHdr) {
  183. ConnectObject->PendingIRPs[SMB_PENDING_SEND] = NULL;
  184. SmbDereferenceConnect(ConnectObject, SMB_REF_SEND);
  185. ObDereferenceObject(FileObject);
  186. return STATUS_INSUFFICIENT_RESOURCES;
  187. }
  188. ASSERT(0 == (pMdlNbtHdr->MdlFlags & MDL_NETWORK_HEADER));
  189. SmbHdr = (PULONG)pMdlNbtHdr->MappedSystemVa;
  190. *SmbHdr = htonl(SendLength);
  191. pMdlNbtHdr->Next = Irp->MdlAddress;
  192. Irp->MdlAddress = pMdlNbtHdr;
  193. }
  194. TdiBuildSend(
  195. Irp,
  196. DeviceObject,
  197. FileObject,
  198. (PVOID)SmbSendCompletion,
  199. ConnectObject,
  200. Irp->MdlAddress,
  201. 0,
  202. SendLength + 4
  203. );
  204. IoMarkIrpPending(Irp);
  205. if (ConnectObject->FastSend) {
  206. IoSetNextIrpStackLocation(Irp);
  207. status = ConnectObject->FastSend(Irp, IoGetCurrentIrpStackLocation(Irp));
  208. SmbPrint(SMB_TRACE_TCP, ("SmbSend: FastSend %d bytes IoCallDriver return 0x%08lx\n", SendLength + 4, status));
  209. } else {
  210. status = IoCallDriver(DeviceObject, Irp);
  211. SmbPrint(SMB_TRACE_TCP, ("SmbSend: Send %d bytes IoCallDriver return 0x%08lx\n", SendLength + 4, status));
  212. }
  213. ObDereferenceObject(FileObject);
  214. return STATUS_PENDING;
  215. }