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.

667 lines
18 KiB

  1. /*++
  2. Copyright (c) 2000-2002 Microsoft Corporation
  3. Module Name:
  4. httptdi.c
  5. Abstract:
  6. This module implements the TDI/MUX/SSL component that is common between
  7. ultdi and uctdi
  8. Author:
  9. Rajesh Sundaram (rajeshsu)
  10. Revision History:
  11. --*/
  12. #include "precomp.h"
  13. #ifdef ALLOC_PRAGMA
  14. #pragma alloc_text( PAGE, UxInitializeTdi )
  15. #pragma alloc_text( PAGE, UxTerminateTdi )
  16. #pragma alloc_text( PAGE, UxOpenTdiAddressObject )
  17. #pragma alloc_text( PAGE, UxOpenTdiConnectionObject )
  18. #pragma alloc_text( PAGE, UxpOpenTdiObjectHelper )
  19. #pragma alloc_text( PAGE, UxSetEventHandler )
  20. #endif
  21. #if 0
  22. NOT PAGEABLE - UxCreateDisconnectIrp
  23. NOT PAGEABLE - UxInitializeDisconnectIrp
  24. #endif
  25. //
  26. // Timeout for disconnects. This cannot be a stack-based local,
  27. // so we make it a global.
  28. //
  29. BOOLEAN g_UxTdiInitialized;
  30. UNICODE_STRING g_TCPDeviceName; // global transport device name (IP)
  31. UNICODE_STRING g_TCP6DeviceName; // global transport device name (IPv6)
  32. LARGE_INTEGER g_TdiDisconnectTimeout;
  33. /***************************************************************************++
  34. Routine Description:
  35. Performs global initialization of this module.
  36. Return Value:
  37. NTSTATUS - Completion status.
  38. --***************************************************************************/
  39. NTSTATUS
  40. UxInitializeTdi(
  41. VOID
  42. )
  43. {
  44. NTSTATUS status = STATUS_SUCCESS;
  45. //
  46. // Sanity check.
  47. //
  48. PAGED_CODE();
  49. ASSERT( !g_UxTdiInitialized );
  50. status = UlInitUnicodeStringEx(&g_TCPDeviceName, DD_TCP_DEVICE_NAME);
  51. if (NT_SUCCESS(status))
  52. {
  53. status = UlInitUnicodeStringEx(&g_TCP6DeviceName, DD_TCPV6_DEVICE_NAME);
  54. }
  55. if (NT_SUCCESS(status))
  56. {
  57. g_TdiDisconnectTimeout = RtlConvertLongToLargeInteger( -1 );
  58. g_UxTdiInitialized = TRUE;
  59. }
  60. return status;
  61. }
  62. /***************************************************************************++
  63. Routine Description:
  64. Performs global termination of this module.
  65. --***************************************************************************/
  66. VOID
  67. UxTerminateTdi(
  68. VOID
  69. )
  70. {
  71. //
  72. // Sanity check.
  73. //
  74. PAGED_CODE();
  75. if (g_UxTdiInitialized)
  76. {
  77. }
  78. } // UxTerminateTdi
  79. /***************************************************************************++
  80. Routine Description:
  81. Opens a TDI address object.
  82. Arguments:
  83. pTransportDeviceName - Supplies the device name of the TDI transport
  84. to open.
  85. pLocalAddress - Supplies the local address to bind to.
  86. LocalAddressLength - Supplies the length of pLocalAddress.
  87. pTdiObject - Receives the file handle, referenced FILE_OBJECT
  88. pointer, and corresponding DEVICE_OBJECT pointer.
  89. Return Value:
  90. NTSTATUS - Completion status.
  91. --***************************************************************************/
  92. NTSTATUS
  93. UxOpenTdiAddressObject(
  94. IN PTRANSPORT_ADDRESS pLocalAddress,
  95. IN ULONG LocalAddressLength,
  96. OUT PUX_TDI_OBJECT pTdiObject
  97. )
  98. {
  99. NTSTATUS status;
  100. PFILE_FULL_EA_INFORMATION pEaInfo;
  101. ULONG eaLength;
  102. UCHAR eaBuffer[MAX_ADDRESS_EA_BUFFER_LENGTH];
  103. PUNICODE_STRING pTransportDeviceName;
  104. //
  105. // Sanity check.
  106. //
  107. PAGED_CODE();
  108. eaLength = sizeof(FILE_FULL_EA_INFORMATION) - 1 +
  109. TDI_TRANSPORT_ADDRESS_LENGTH + 1 +
  110. LocalAddressLength;
  111. ASSERT( eaLength <= sizeof(eaBuffer) );
  112. ASSERT( LocalAddressLength == sizeof(TA_IP_ADDRESS) ||
  113. LocalAddressLength == sizeof(TA_IP6_ADDRESS));
  114. ASSERT( pLocalAddress->TAAddressCount == 1 );
  115. ASSERT( pLocalAddress->Address[0].AddressLength == sizeof(TDI_ADDRESS_IP)
  116. || pLocalAddress->Address[0].AddressLength == sizeof(TDI_ADDRESS_IP6));
  117. ASSERT( pLocalAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IP
  118. || pLocalAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IP6);
  119. //
  120. // Initialize the EA buffer. See UxpOpenTdiObjectHelper() for the
  121. // gory details.
  122. //
  123. pEaInfo = (PFILE_FULL_EA_INFORMATION)eaBuffer;
  124. pEaInfo->NextEntryOffset = 0;
  125. pEaInfo->Flags = 0;
  126. pEaInfo->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
  127. pEaInfo->EaValueLength = (USHORT)LocalAddressLength;
  128. RtlMoveMemory(
  129. pEaInfo->EaName,
  130. TdiTransportAddress,
  131. pEaInfo->EaNameLength + 1
  132. );
  133. RtlMoveMemory(
  134. &pEaInfo->EaName[pEaInfo->EaNameLength + 1],
  135. pLocalAddress,
  136. LocalAddressLength
  137. );
  138. //
  139. // Initialize pTransportDeviceName
  140. //
  141. pTransportDeviceName =
  142. (pLocalAddress->Address[0].AddressType == TDI_ADDRESS_TYPE_IP)?
  143. &g_TCPDeviceName : &g_TCP6DeviceName;
  144. //
  145. // Let the helper do the dirty work.
  146. //
  147. status = UxpOpenTdiObjectHelper(
  148. pTransportDeviceName,
  149. eaBuffer,
  150. eaLength,
  151. pTdiObject
  152. );
  153. if (NT_SUCCESS(status))
  154. {
  155. //
  156. // Enable Optimize for Interrupt Moderation if needed
  157. //
  158. if ( DEFAULT_OPT_FOR_INTR_MOD != g_UlOptForIntrMod )
  159. {
  160. status = UlpOptimizeForInterruptModeration( pTdiObject, g_UlOptForIntrMod );
  161. if (!NT_SUCCESS(status))
  162. {
  163. UxCloseTdiObject( pTdiObject );
  164. }
  165. }
  166. }
  167. return status;
  168. } // UxpOpenTdiAddressObject
  169. /***************************************************************************++
  170. Routine Description:
  171. Opens a TDI connection object.
  172. Arguments:
  173. pTransportDeviceName - Supplies the device name of the TDI transport
  174. to open.
  175. pConnectionContext - Supplies the context to associate with the
  176. new connection.
  177. pTdiObject - Receives the file handle, referenced FILE_OBJECT
  178. pointer, and corresponding DEVICE_OBJECT pointer.
  179. Return Value:
  180. NTSTATUS - Completion status.
  181. --***************************************************************************/
  182. NTSTATUS
  183. UxOpenTdiConnectionObject(
  184. IN USHORT AddressType,
  185. IN CONNECTION_CONTEXT pConnectionContext,
  186. OUT PUX_TDI_OBJECT pTdiObject
  187. )
  188. {
  189. NTSTATUS status;
  190. PFILE_FULL_EA_INFORMATION pEaInfo;
  191. ULONG eaLength;
  192. UCHAR eaBuffer[MAX_CONNECTION_EA_BUFFER_LENGTH];
  193. PUNICODE_STRING pTransportDeviceName;
  194. //
  195. // Sanity check.
  196. //
  197. PAGED_CODE();
  198. ASSERT(AddressType == TDI_ADDRESS_TYPE_IP ||
  199. AddressType == TDI_ADDRESS_TYPE_IP6);
  200. pTransportDeviceName = (AddressType == TDI_ADDRESS_TYPE_IP)?
  201. &g_TCPDeviceName : &g_TCP6DeviceName;
  202. eaLength = sizeof(FILE_FULL_EA_INFORMATION) - 1 +
  203. TDI_CONNECTION_CONTEXT_LENGTH + 1 +
  204. sizeof(pConnectionContext);
  205. ASSERT( eaLength <= sizeof(eaBuffer) );
  206. ASSERT( pConnectionContext != NULL );
  207. //
  208. // Initialize the EA buffer. See UxpOpenTdiObjectHelper() for the
  209. // gory details.
  210. //
  211. pEaInfo = (PFILE_FULL_EA_INFORMATION)eaBuffer;
  212. pEaInfo->NextEntryOffset = 0;
  213. pEaInfo->Flags = 0;
  214. pEaInfo->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
  215. pEaInfo->EaValueLength = (USHORT)sizeof(CONNECTION_CONTEXT);
  216. RtlMoveMemory(
  217. pEaInfo->EaName,
  218. TdiConnectionContext,
  219. pEaInfo->EaNameLength + 1
  220. );
  221. RtlMoveMemory(
  222. &pEaInfo->EaName[pEaInfo->EaNameLength + 1],
  223. &pConnectionContext,
  224. sizeof(pConnectionContext)
  225. );
  226. //
  227. // Let the helper do the dirty work.
  228. //
  229. status = UxpOpenTdiObjectHelper(
  230. pTransportDeviceName,
  231. eaBuffer,
  232. eaLength,
  233. pTdiObject
  234. );
  235. if (NT_SUCCESS(status))
  236. {
  237. //
  238. // Enable/disable Nagle's Algorithm as appropriate.
  239. //
  240. status = UlpSetNagling( pTdiObject, g_UlEnableNagling );
  241. if (!NT_SUCCESS(status))
  242. {
  243. UxCloseTdiObject( pTdiObject );
  244. }
  245. }
  246. return status;
  247. } // UxpOpenTdiConnectionObject
  248. /***************************************************************************++
  249. Routine Description:
  250. Helper routine for UxpOpenTdiAddressObject and
  251. UxpOpenTdiConnectionObject.
  252. Arguments:
  253. pTransportDeviceName - Supplies the device name of the TDI transport
  254. to open.
  255. pEaBuffer - Supplies a pointer to the EA to use when opening
  256. the object. This buffer consists of a FILE_FULL_EA_INFORMATION
  257. structure, followed by the EA Name, followed by the EA Value.
  258. The EA Name and Value are use as follows:
  259. Address Object:
  260. Ea Name = TdiTransportAddress ("TransportAddress")
  261. Ea Value = The local TRANSPORT_ADDRESS to bind to
  262. Connection Object:
  263. Ea Name = TdiConnectionContext ("ConnectionContext")
  264. Ea Value = The connection context (basically a PVOID)
  265. EaLength - Supplies the length of pEaBuffer.
  266. pTdiObject - Receives the file handle, referenced FILE_OBJECT
  267. pointer, and corresponding DEVICE_OBJECT pointer.
  268. Return Value:
  269. NTSTATUS - Completion status.
  270. --***************************************************************************/
  271. NTSTATUS
  272. UxpOpenTdiObjectHelper(
  273. IN PUNICODE_STRING pTransportDeviceName,
  274. IN PVOID pEaBuffer,
  275. IN ULONG EaLength,
  276. OUT PUX_TDI_OBJECT pTdiObject
  277. )
  278. {
  279. NTSTATUS status;
  280. IO_STATUS_BLOCK ioStatusBlock;
  281. OBJECT_ATTRIBUTES objectAttributes;
  282. //
  283. // Sanity check.
  284. //
  285. PAGED_CODE();
  286. //
  287. // Open the TDI object.
  288. //
  289. InitializeObjectAttributes(
  290. &objectAttributes, // ObjectAttributes
  291. pTransportDeviceName, // ObjectName
  292. OBJ_CASE_INSENSITIVE | // Attributes
  293. OBJ_KERNEL_HANDLE,
  294. NULL, // RootHandle
  295. NULL // SecurityDescriptor
  296. );
  297. status = IoCreateFile(
  298. &pTdiObject->Handle, // FileHandle
  299. GENERIC_READ | // DesiredAccess
  300. GENERIC_WRITE |
  301. SYNCHRONIZE,
  302. &objectAttributes, // ObjectAttributes
  303. &ioStatusBlock, // IoStatusBlock
  304. NULL, // AllocationSize
  305. 0, // FileAttributes
  306. 0, // ShareAccess
  307. 0, // Disposition
  308. 0, // CreateOptions
  309. pEaBuffer, // EaBuffer
  310. EaLength, // EaLength
  311. CreateFileTypeNone, // CreateFileType
  312. NULL, // ExtraCreateParameters
  313. IO_NO_PARAMETER_CHECKING // Options
  314. );
  315. if (NT_SUCCESS(status))
  316. {
  317. //
  318. // Now that we have an open handle to the transport,
  319. // reference it so we can get the file & device object
  320. // pointers.
  321. //
  322. status = ObReferenceObjectByHandle(
  323. pTdiObject->Handle, // Handle
  324. FILE_READ_ACCESS, // DesiredAccess
  325. *IoFileObjectType, // ObjectType
  326. KernelMode, // AccessMode
  327. (PVOID *)&pTdiObject->pFileObject, // Object
  328. NULL // HandleInformation
  329. );
  330. if (NT_SUCCESS(status))
  331. {
  332. //
  333. // Chase down the appropriate device object for the file
  334. // object.
  335. //
  336. pTdiObject->pDeviceObject =
  337. IoGetRelatedDeviceObject( pTdiObject->pFileObject );
  338. return status;
  339. }
  340. //
  341. // The ObReferenceObjectByHandle() failed, so close the handle
  342. // we managed to open & fail the call.
  343. //
  344. ZwClose( pTdiObject->Handle );
  345. }
  346. RtlZeroMemory(
  347. pTdiObject,
  348. sizeof(*pTdiObject)
  349. );
  350. return status;
  351. } // UxpOpenTdiObjectHelper
  352. /***************************************************************************++
  353. Routine Description:
  354. Establishes a TDI event handler for the specified endpoint.
  355. Arguments:
  356. pEndpoint - Supplies the endpoint for which to set the event handler.
  357. EventType - Supplies the type of event to set. This should be one
  358. of the TDI_EVENT_* values.
  359. pEventHandler - Supplies a pointer to the indication handler function
  360. to be invoked for the specified event type.
  361. Return Value:
  362. NTSTATUS - Completion status.
  363. --***************************************************************************/
  364. NTSTATUS
  365. UxSetEventHandler(
  366. IN PUX_TDI_OBJECT pUlTdiObject,
  367. IN ULONG EventType,
  368. IN ULONG_PTR pEventHandler,
  369. IN PVOID pEventContext
  370. )
  371. {
  372. NTSTATUS status;
  373. TDI_REQUEST_KERNEL_SET_EVENT eventParams;
  374. //
  375. // Sanity check.
  376. //
  377. PAGED_CODE();
  378. //
  379. // Build the parameter block.
  380. //
  381. eventParams.EventType = EventType;
  382. eventParams.EventHandler = (PVOID) pEventHandler;
  383. eventParams.EventContext = pEventContext;
  384. //
  385. // Make the call.
  386. //
  387. status = UlIssueDeviceControl(
  388. pUlTdiObject, // pTdiObject
  389. &eventParams, // pIrpParameters
  390. sizeof(eventParams), // IrpParamtersLength
  391. NULL, // pMdlBuffer
  392. 0, // MdlBufferLength
  393. TDI_SET_EVENT_HANDLER // MinorFunction
  394. );
  395. return status;
  396. } // UxSetEventHandler
  397. /***************************************************************************++
  398. Routine Description:
  399. Allocates & initializes a new disconnect IRP.
  400. Arguments:
  401. pConnection - Supplies the UC_CONNECTION to be disconnected.
  402. Flags - Supplies the TDI_DISCONNECT_* flags for the IRP.
  403. pCompletionRoutine - Supplies the completion routine for the IRP.
  404. pCompletionContext - Supplies an uninterpreted context for the
  405. completion routine.
  406. Return Value:
  407. PIRP - Pointer to the IRP if successful, NULL otherwise.
  408. --***************************************************************************/
  409. PIRP
  410. UxCreateDisconnectIrp(
  411. IN PUX_TDI_OBJECT pTdiObject,
  412. IN ULONG_PTR Flags,
  413. IN PIO_COMPLETION_ROUTINE pCompletionRoutine,
  414. IN PVOID pCompletionContext
  415. )
  416. {
  417. PIRP pIrp;
  418. ASSERT( IS_VALID_TDI_OBJECT( pTdiObject ) );
  419. //
  420. // Allocate an IRP for the disconnect.
  421. //
  422. pIrp = UlAllocateIrp(
  423. pTdiObject->pDeviceObject->StackSize, // StackSize
  424. FALSE // ChargeQuota
  425. );
  426. if (pIrp != NULL)
  427. {
  428. UxInitializeDisconnectIrp(
  429. pIrp,
  430. pTdiObject,
  431. Flags,
  432. pCompletionRoutine,
  433. pCompletionContext
  434. );
  435. }
  436. return pIrp;
  437. } // UxCreateDisconnectIrp
  438. /***************************************************************************++
  439. Routine Description:
  440. Initializes a disconnect IRP.
  441. Arguments:
  442. pIrp - Supplies the disconnect IRP.
  443. pConnection - Supplies the UC_CONNECTION to be disconnected.
  444. Flags - Supplies the TDI_DISCONNECT_* flags for the IRP.
  445. pCompletionRoutine - Supplies the completion routine for the IRP.
  446. pCompletionContext - Supplies an uninterpreted context for the
  447. completion routine.
  448. Return Value:
  449. None
  450. --***************************************************************************/
  451. VOID
  452. UxInitializeDisconnectIrp(
  453. IN PIRP pIrp,
  454. IN PUX_TDI_OBJECT pTdiObject,
  455. IN ULONG_PTR Flags,
  456. IN PIO_COMPLETION_ROUTINE pCompletionRoutine,
  457. IN PVOID pCompletionContext
  458. )
  459. {
  460. ASSERT( IS_VALID_TDI_OBJECT( pTdiObject ) );
  461. ASSERT( pIrp != NULL );
  462. //
  463. // Initialize the IRP. Note that IRPs are always zero-initialized
  464. // when allocated. Therefore, we don't need to explicitly set
  465. // the zeroed fields.
  466. //
  467. pIrp->RequestorMode = KernelMode;
  468. pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
  469. pIrp->Tail.Overlay.OriginalFileObject = pTdiObject->pFileObject;
  470. TdiBuildDisconnect(
  471. pIrp, // Irp
  472. pTdiObject->pDeviceObject, // DeviceObject
  473. pTdiObject->pFileObject, // FileObject
  474. pCompletionRoutine, // CompletionRoutine
  475. pCompletionContext, // CompletionContext
  476. &g_TdiDisconnectTimeout, // Timeout
  477. Flags, // Flags
  478. NULL, // RequestConnectionInfo
  479. NULL // ReturnConnectionInfo
  480. );
  481. } // UxInitializeDisconnectIrp