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.

416 lines
12 KiB

  1. /////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // send
  7. //
  8. // Abstract:
  9. // This module contains code which deals with sending data
  10. //
  11. //////////////////////////////////////////////////////////
  12. #include "sysvars.h"
  13. //////////////////////////////////////////////////////////////
  14. // private constants, types, and prototypes
  15. //////////////////////////////////////////////////////////////
  16. const PCHAR strFunc1 = "TSSendDatagram";
  17. const PCHAR strFunc2 = "TSSend";
  18. const PCHAR strFuncP1 = "TSSendComplete";
  19. //
  20. // completion context
  21. //
  22. struct SEND_CONTEXT
  23. {
  24. PIRP pUpperIrp; // irp from dll to complete
  25. PMDL pLowerMdl; // mdl from lower irp
  26. PTDI_CONNECTION_INFORMATION
  27. pTdiConnectInfo;
  28. };
  29. typedef SEND_CONTEXT *PSEND_CONTEXT;
  30. //
  31. // completion function
  32. //
  33. TDI_STATUS
  34. TSSendComplete(
  35. PDEVICE_OBJECT DeviceObject,
  36. PIRP Irp,
  37. PVOID Context
  38. );
  39. //////////////////////////////////////////////////////////////
  40. // public functions
  41. //////////////////////////////////////////////////////////////
  42. // -----------------------------------------------------------------
  43. //
  44. // Function: TSSendDatagram
  45. //
  46. // Arguments: pAddressObject -- address object
  47. // pSendBuffer -- arguments from user dll
  48. // pIrp -- completion information
  49. //
  50. // Returns: NTSTATUS (normally pending)
  51. //
  52. // Descript: This function sends a datagram
  53. //
  54. // ---------------------------------------------------------------------------
  55. NTSTATUS
  56. TSSendDatagram(PADDRESS_OBJECT pAddressObject,
  57. PSEND_BUFFER pSendBuffer,
  58. PIRP pUpperIrp)
  59. {
  60. ULONG ulDataLength = pSendBuffer->COMMAND_ARGS.SendArgs.ulBufferLength;
  61. PUCHAR pucDataBuffer = pSendBuffer->COMMAND_ARGS.SendArgs.pucUserModeBuffer;
  62. PTRANSPORT_ADDRESS pTransportAddress
  63. = (PTRANSPORT_ADDRESS)&pSendBuffer->COMMAND_ARGS.SendArgs.TransAddr;
  64. //
  65. // show debug, if it is turned on
  66. //
  67. if (ulDebugLevel & ulDebugShowCommand)
  68. {
  69. DebugPrint2("\nCommand = ulSENDDATAGRAM\n"
  70. "FileObject = %p\n"
  71. "DataLength = %u\n",
  72. pAddressObject,
  73. ulDataLength);
  74. TSPrintTaAddress(pTransportAddress->Address);
  75. }
  76. //
  77. // allocate all the necessary structures
  78. //
  79. PSEND_CONTEXT pSendContext = NULL;
  80. PMDL pSendMdl = NULL;
  81. PTDI_CONNECTION_INFORMATION pTdiConnectInfo = NULL;
  82. //
  83. // our context
  84. //
  85. if ((TSAllocateMemory((PVOID *)&pSendContext,
  86. sizeof(SEND_CONTEXT),
  87. strFunc1,
  88. "SendContext")) != STATUS_SUCCESS)
  89. {
  90. goto cleanup;
  91. }
  92. //
  93. // the connection information structure
  94. //
  95. if ((TSAllocateMemory((PVOID *)&pTdiConnectInfo,
  96. sizeof(TDI_CONNECTION_INFORMATION)
  97. + sizeof(TRANSADDR),
  98. strFunc1,
  99. "TdiConnectionInformation")) == STATUS_SUCCESS)
  100. {
  101. PUCHAR pucTemp = (PUCHAR)pTdiConnectInfo;
  102. ULONG ulAddrLength
  103. = FIELD_OFFSET(TRANSPORT_ADDRESS, Address)
  104. + FIELD_OFFSET(TA_ADDRESS, Address)
  105. + pTransportAddress->Address[0].AddressLength;
  106. pucTemp += sizeof(TDI_CONNECTION_INFORMATION);
  107. pTdiConnectInfo->RemoteAddress = pucTemp;
  108. pTdiConnectInfo->RemoteAddressLength = ulAddrLength;
  109. RtlCopyMemory(pucTemp,
  110. pTransportAddress,
  111. ulAddrLength);
  112. }
  113. else
  114. {
  115. goto cleanup;
  116. }
  117. //
  118. // create the message "packet" to send
  119. //
  120. pSendMdl = TSMakeMdlForUserBuffer(pucDataBuffer,
  121. ulDataLength,
  122. IoReadAccess);
  123. if (pSendMdl)
  124. {
  125. //
  126. // set up the completion context
  127. //
  128. pSendContext->pUpperIrp = pUpperIrp;
  129. pSendContext->pLowerMdl = pSendMdl;
  130. pSendContext->pTdiConnectInfo = pTdiConnectInfo;
  131. //
  132. // finally, the irp itself
  133. //
  134. PIRP pLowerIrp = TSAllocateIrp(pAddressObject->GenHead.pDeviceObject,
  135. NULL);
  136. if (pLowerIrp)
  137. {
  138. //
  139. // if made it to here, everything is correctly allocated
  140. // set up the irp and call the tdi provider
  141. //
  142. #pragma warning(disable: CONSTANT_CONDITIONAL)
  143. TdiBuildSendDatagram(pLowerIrp,
  144. pAddressObject->GenHead.pDeviceObject,
  145. pAddressObject->GenHead.pFileObject,
  146. TSSendComplete,
  147. pSendContext,
  148. pSendMdl,
  149. ulDataLength,
  150. pTdiConnectInfo);
  151. #pragma warning(default: CONSTANT_CONDITIONAL)
  152. //
  153. // make the call to the tdi provider
  154. //
  155. pSendBuffer->pvLowerIrp = pLowerIrp; // so command can be cancelled
  156. NTSTATUS lStatus = IoCallDriver(pAddressObject->GenHead.pDeviceObject,
  157. pLowerIrp);
  158. if ((!NT_SUCCESS(lStatus)) && (ulDebugLevel & ulDebugShowCommand))
  159. {
  160. DebugPrint2("%s: unexpected status for IoCallDriver [0x%08x]\n",
  161. strFunc1,
  162. lStatus);
  163. }
  164. return STATUS_PENDING;
  165. }
  166. }
  167. //
  168. // get here if there was an allocation failure
  169. // need to clean up everything else...
  170. //
  171. cleanup:
  172. if (pSendContext)
  173. {
  174. TSFreeMemory(pSendContext);
  175. }
  176. if (pTdiConnectInfo)
  177. {
  178. TSFreeMemory(pTdiConnectInfo);
  179. }
  180. if (pSendMdl)
  181. {
  182. TSFreeUserBuffer(pSendMdl);
  183. }
  184. return STATUS_INSUFFICIENT_RESOURCES;
  185. }
  186. // -----------------------------------------------------------------
  187. //
  188. // Function: TSSend
  189. //
  190. // Arguments: pEndpointObject -- endpoint object
  191. // pSendBuffer -- arguments from user dll
  192. // pIrp -- completion information
  193. //
  194. // Returns: NTSTATUS (normally pending)
  195. //
  196. // Descript: This function sends data over a connection
  197. //
  198. // ----------------------------------------------------------------------------
  199. NTSTATUS
  200. TSSend(PENDPOINT_OBJECT pEndpoint,
  201. PSEND_BUFFER pSendBuffer,
  202. PIRP pUpperIrp)
  203. {
  204. ULONG ulDataLength = pSendBuffer->COMMAND_ARGS.SendArgs.ulBufferLength;
  205. PUCHAR pucDataBuffer = pSendBuffer->COMMAND_ARGS.SendArgs.pucUserModeBuffer;
  206. ULONG ulSendFlags = pSendBuffer->COMMAND_ARGS.SendArgs.ulFlags;
  207. //
  208. // currently only support TDI_SEND_EXPEDITED
  209. //
  210. ulSendFlags &= TDI_SEND_EXPEDITED;
  211. //
  212. // show debug, if it is turned on
  213. //
  214. if (ulDebugLevel & ulDebugShowCommand)
  215. {
  216. DebugPrint3("\nCommand = ulSEND\n"
  217. "Endpoint = %p\n"
  218. "DataLength = %u\n"
  219. "SendFlags = 0x%08x\n",
  220. pEndpoint,
  221. ulDataLength,
  222. ulSendFlags);
  223. }
  224. //
  225. // allocate all the necessary structures
  226. //
  227. PSEND_CONTEXT pSendContext = NULL;
  228. PMDL pSendMdl = NULL;
  229. //
  230. // our context
  231. //
  232. if ((TSAllocateMemory((PVOID *)&pSendContext,
  233. sizeof(SEND_CONTEXT),
  234. strFunc2,
  235. "SendContext")) != STATUS_SUCCESS)
  236. {
  237. goto cleanup;
  238. }
  239. pSendMdl = TSMakeMdlForUserBuffer(pucDataBuffer,
  240. ulDataLength,
  241. IoReadAccess);
  242. if (pSendMdl)
  243. {
  244. //
  245. // set up the completion context
  246. //
  247. pSendContext->pUpperIrp = pUpperIrp;
  248. pSendContext->pLowerMdl = pSendMdl;
  249. //
  250. // finally, the irp itself
  251. //
  252. PIRP pLowerIrp = TSAllocateIrp(pEndpoint->GenHead.pDeviceObject,
  253. NULL);
  254. if (pLowerIrp)
  255. {
  256. //
  257. // if made it to here, everything is correctly allocated
  258. // set up the irp for the call
  259. //
  260. #pragma warning(disable: CONSTANT_CONDITIONAL)
  261. TdiBuildSend(pLowerIrp,
  262. pEndpoint->GenHead.pDeviceObject,
  263. pEndpoint->GenHead.pFileObject,
  264. TSSendComplete,
  265. pSendContext,
  266. pSendMdl,
  267. ulSendFlags, // flags
  268. ulDataLength);
  269. #pragma warning(default: CONSTANT_CONDITIONAL)
  270. //
  271. // make the call to the tdi provider
  272. //
  273. pSendBuffer->pvLowerIrp = pLowerIrp; // so command can be cancelled
  274. NTSTATUS lStatus = IoCallDriver(pEndpoint->GenHead.pDeviceObject,
  275. pLowerIrp);
  276. if ((!NT_SUCCESS(lStatus)) && (ulDebugLevel & ulDebugShowCommand))
  277. {
  278. DebugPrint2("%s: unexpected status for IoCallDriver [0x%08x]\n",
  279. strFunc2,
  280. lStatus);
  281. }
  282. return STATUS_PENDING;
  283. }
  284. }
  285. //
  286. // get here if there was an allocation failure
  287. // need to clean up everything else...
  288. //
  289. cleanup:
  290. if (pSendContext)
  291. {
  292. TSFreeMemory(pSendContext);
  293. }
  294. if (pSendMdl)
  295. {
  296. TSFreeUserBuffer(pSendMdl);
  297. }
  298. return STATUS_INSUFFICIENT_RESOURCES;
  299. }
  300. /////////////////////////////////////////////////////////////
  301. // private functions
  302. /////////////////////////////////////////////////////////////
  303. // ---------------------------------------------------------
  304. //
  305. // Function: TSSendComplete
  306. //
  307. // Arguments: pDeviceObject -- device object that called protocol
  308. // pIrp -- IRP used in the call
  309. // pContext -- context used for the call
  310. //
  311. // Returns: status of operation (STATUS_MORE_PROCESSING_REQUIRED)
  312. //
  313. // Descript: Gets the result of the send, stuffs result into
  314. // receive buffer, completes the IRP from the dll, and
  315. // cleans up the Irp and associated data from the send
  316. //
  317. // ---------------------------------------------------------
  318. #pragma warning(disable: UNREFERENCED_PARAM)
  319. TDI_STATUS
  320. TSSendComplete(PDEVICE_OBJECT pDeviceObject,
  321. PIRP pLowerIrp,
  322. PVOID pvContext)
  323. {
  324. PSEND_CONTEXT pSendContext = (PSEND_CONTEXT)pvContext;
  325. NTSTATUS lStatus = pLowerIrp->IoStatus.Status;
  326. ULONG ulBytesSent = (ULONG)pLowerIrp->IoStatus.Information;
  327. PRECEIVE_BUFFER pReceiveBuffer = TSGetReceiveBuffer(pSendContext->pUpperIrp);
  328. pReceiveBuffer->lStatus = lStatus;
  329. if (ulDebugLevel & ulDebugShowCommand)
  330. {
  331. if (NT_SUCCESS(lStatus))
  332. {
  333. DebugPrint2("%s: BytesSent = 0x%08x\n",
  334. strFuncP1,
  335. ulBytesSent);
  336. }
  337. else
  338. {
  339. DebugPrint2("%s: Completed with status 0x%08x\n",
  340. strFuncP1,
  341. lStatus);
  342. }
  343. }
  344. TSCompleteIrp(pSendContext->pUpperIrp);
  345. //
  346. // now cleanup
  347. //
  348. TSFreeUserBuffer(pSendContext->pLowerMdl);
  349. if (pSendContext->pTdiConnectInfo)
  350. {
  351. TSFreeMemory(pSendContext->pTdiConnectInfo);
  352. }
  353. TSFreeMemory(pSendContext);
  354. TSFreeIrp(pLowerIrp, NULL);
  355. return TDI_MORE_PROCESSING;
  356. }
  357. #pragma warning(default: UNREFERENCED_PARAM)
  358. ///////////////////////////////////////////////////////////////////////////////
  359. // end of file send.cpp
  360. ///////////////////////////////////////////////////////////////////////////////