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.

1117 lines
27 KiB

  1. /*************************************************************************
  2. * tdlib.c
  3. *
  4. * TDI library functions.
  5. *
  6. * Copyright 1998 Microsoft
  7. *************************************************************************/
  8. /*
  9. * Includes
  10. */
  11. #include <ntddk.h>
  12. #include <tdi.h>
  13. #include <tdikrnl.h>
  14. #include "tdtdi.h"
  15. #include <winstaw.h>
  16. #define _DEFCHARINFO_
  17. #include <icadd.h>
  18. #include <ctxdd.h>
  19. #include <sdapi.h>
  20. #include <td.h>
  21. #define _TDI_POLL_TIMEOUT (30 * 1000) // 30 seconds
  22. #define _TDI_CONNECT_TIMEOUT 45
  23. #define _TDI_DISCONNECT_TIMEOUT 60
  24. #if DBG
  25. ULONG
  26. DbgPrint(
  27. PCH Format,
  28. ...
  29. );
  30. #define DBGPRINT(x) DbgPrint x
  31. #if DBGTRACE
  32. #define TRACE0(x) DbgPrint x
  33. #define TRACE1(x) DbgPrint x
  34. #else
  35. #define TRACE0(x)
  36. #define TRACE1(x)
  37. #endif
  38. #else
  39. #define DBGPRINT(x)
  40. #define TRACE0(x)
  41. #define TRACE1(x)
  42. #endif
  43. /*
  44. * To use TDI:
  45. *
  46. * To connect to a remote server:
  47. *
  48. * Create Address EndPoint
  49. *
  50. * Create Connection Object
  51. *
  52. * Associate the Address EndPoint with the Connection Object
  53. *
  54. * Do a Connect
  55. *
  56. * To receive connections:
  57. *
  58. * Create Address EndPoint
  59. *
  60. * Create Connection Object
  61. *
  62. * Associate the Address EndPoint with the Connection Object
  63. *
  64. * Listen for a connection.
  65. *
  66. * Return connection
  67. */
  68. /*
  69. * Global data
  70. */
  71. //
  72. // Wait for xx seconds before polling on thread deletion.
  73. //
  74. ULONG
  75. _TdiPollTimeout = _TDI_POLL_TIMEOUT;
  76. /*
  77. * Forward references
  78. */
  79. PIRP
  80. _TdiAllocateIrp(
  81. IN PFILE_OBJECT FileObject,
  82. IN PDEVICE_OBJECT DeviceObject OPTIONAL
  83. );
  84. NTSTATUS
  85. _TdiRequestComplete (
  86. IN PDEVICE_OBJECT DeviceObject,
  87. IN PIRP Irp,
  88. IN PVOID Ctx
  89. );
  90. NTSTATUS
  91. _TdiSetEventHandler (
  92. IN PTD pTd,
  93. IN PDEVICE_OBJECT DeviceObject,
  94. IN PFILE_OBJECT FileObject,
  95. IN ULONG EventType,
  96. IN PVOID EventHandler,
  97. IN PVOID EventContext
  98. );
  99. NTSTATUS
  100. _TdiSubmitRequest (
  101. IN PTD pTd,
  102. IN PDEVICE_OBJECT DeviceObject,
  103. IN PIRP Irp,
  104. IN BOOLEAN bKeepLock
  105. );
  106. /*
  107. * External references
  108. */
  109. NTSTATUS MemoryAllocate( ULONG, PVOID * );
  110. VOID MemoryFree( PVOID );
  111. BOOLEAN
  112. PsIsThreadTerminating(
  113. IN PETHREAD Thread
  114. );
  115. /*
  116. * Functions
  117. */
  118. NTSTATUS
  119. _TdiCreateAddress (
  120. IN PUNICODE_STRING pTransportName,
  121. IN PVOID TdiAddress,
  122. IN ULONG TdiAddressLength,
  123. OUT PHANDLE pHandle,
  124. OUT PFILE_OBJECT *ppFileObject,
  125. OUT PDEVICE_OBJECT *ppDeviceObject
  126. )
  127. {
  128. NTSTATUS Status = STATUS_SUCCESS;
  129. OBJECT_ATTRIBUTES AddressAttributes;
  130. IO_STATUS_BLOCK IoStatusBlock;
  131. PFILE_FULL_EA_INFORMATION EABuffer;
  132. PDEVICE_OBJECT DeviceObject;
  133. HANDLE TdiHandle = NULL;
  134. PFILE_OBJECT FileObject = NULL;
  135. /*
  136. * The TDI interfaces uses an EA of name "TdiTransportName"
  137. * to specify the structure TA_ADDRESS.
  138. */
  139. Status = MemoryAllocate( (sizeof(FILE_FULL_EA_INFORMATION)-1 +
  140. TDI_TRANSPORT_ADDRESS_LENGTH + 1 +
  141. TdiAddressLength), &EABuffer);
  142. if ( !NT_SUCCESS(Status) ) {
  143. return(STATUS_INSUFFICIENT_RESOURCES);
  144. }
  145. EABuffer->NextEntryOffset = 0;
  146. EABuffer->Flags = 0;
  147. EABuffer->EaNameLength = TDI_TRANSPORT_ADDRESS_LENGTH;
  148. EABuffer->EaValueLength = (USHORT)TdiAddressLength;
  149. // Copy in the EA name
  150. RtlCopyMemory(EABuffer->EaName, TdiTransportAddress, EABuffer->EaNameLength+1);
  151. // Copy the TA_ADDRESS parameter
  152. RtlCopyMemory(&EABuffer->EaName[TDI_TRANSPORT_ADDRESS_LENGTH+1], TdiAddress,
  153. EABuffer->EaValueLength);
  154. TRACE0(("TdiCreateAddress Create endpoint of %wZ\n",pTransportName));
  155. InitializeObjectAttributes (
  156. &AddressAttributes,
  157. pTransportName,
  158. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE ,
  159. NULL, // RootDirectory
  160. NULL // SecurityDescriptor
  161. );
  162. Status = ZwCreateFile(
  163. &TdiHandle, // Handle
  164. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  165. &AddressAttributes, // Object Attributes
  166. &IoStatusBlock, // Final I/O status block
  167. NULL, // Allocation Size
  168. FILE_ATTRIBUTE_NORMAL, // Normal attributes
  169. 0, // Sharing attributes
  170. FILE_OPEN_IF, // Create disposition
  171. 0, // CreateOptions
  172. EABuffer, // EA Buffer
  173. FIELD_OFFSET(FILE_FULL_EA_INFORMATION, EaName) +
  174. TDI_TRANSPORT_ADDRESS_LENGTH + 1 +
  175. TdiAddressLength // EA length
  176. );
  177. MemoryFree(EABuffer);
  178. if (!NT_SUCCESS(Status)) {
  179. DBGPRINT(("TdiCreateAddress: Error Status 0x%x from function\n",Status));
  180. return( Status );
  181. }
  182. if (!NT_SUCCESS(Status = IoStatusBlock.Status)) {
  183. DBGPRINT(("TdiCreateAddress: Error Status 0x%x from Iosb\n",Status));
  184. return( Status );
  185. }
  186. //
  187. // Obtain a referenced pointer to the file object.
  188. //
  189. Status = ObReferenceObjectByHandle (
  190. TdiHandle,
  191. 0,
  192. *IoFileObjectType,
  193. KernelMode,
  194. (PVOID *)&FileObject,
  195. NULL
  196. );
  197. if (!NT_SUCCESS(Status)) {
  198. DBGPRINT(("TdiCreateAddress: Error Status 0x%x Referencing FileObject\n",Status));
  199. goto error_cleanup;
  200. }
  201. //
  202. // Get the address of the device object for the endpoint.
  203. //
  204. DeviceObject = IoGetRelatedDeviceObject(FileObject);
  205. // Copy the out parameters
  206. *pHandle = TdiHandle;
  207. *ppFileObject = FileObject;
  208. *ppDeviceObject = DeviceObject;
  209. return STATUS_SUCCESS;
  210. error_cleanup:
  211. if ( FileObject != NULL ) {
  212. ObDereferenceObject( FileObject );
  213. }
  214. if ( TdiHandle != NULL ) {
  215. ZwClose( TdiHandle );
  216. }
  217. return Status;
  218. }
  219. NTSTATUS
  220. _TdiOpenConnection (
  221. IN PUNICODE_STRING pTransportName,
  222. IN PVOID ConnectionContext,
  223. OUT PHANDLE pHandle,
  224. OUT PFILE_OBJECT *ppFileObject,
  225. OUT PDEVICE_OBJECT *ppDeviceObject
  226. )
  227. {
  228. NTSTATUS Status = STATUS_SUCCESS;
  229. OBJECT_ATTRIBUTES AddressAttributes;
  230. IO_STATUS_BLOCK IoStatusBlock;
  231. PFILE_FULL_EA_INFORMATION EABuffer;
  232. CONNECTION_CONTEXT UNALIGNED *ContextPointer;
  233. PDEVICE_OBJECT DeviceObject;
  234. HANDLE ConnHandle = NULL;
  235. PFILE_OBJECT FileObject = NULL;
  236. Status = MemoryAllocate( (sizeof(FILE_FULL_EA_INFORMATION)-1 +
  237. TDI_CONNECTION_CONTEXT_LENGTH+1 +
  238. sizeof(CONNECTION_CONTEXT)), &EABuffer);
  239. if( !NT_SUCCESS(Status) ) {
  240. return( Status );
  241. }
  242. EABuffer->NextEntryOffset = 0;
  243. EABuffer->Flags = 0;
  244. EABuffer->EaNameLength = TDI_CONNECTION_CONTEXT_LENGTH;
  245. EABuffer->EaValueLength = sizeof(CONNECTION_CONTEXT);
  246. // Copy in the EA name
  247. RtlCopyMemory(EABuffer->EaName, TdiConnectionContext, TDI_CONNECTION_CONTEXT_LENGTH+1);
  248. // Copy in the EA data
  249. ContextPointer =
  250. (CONNECTION_CONTEXT UNALIGNED *)&EABuffer->EaName[TDI_CONNECTION_CONTEXT_LENGTH+1];
  251. *ContextPointer = ConnectionContext;
  252. TRACE0(("_TdiOpenConnection: Create connection object on transport %wZ\n",pTransportName));
  253. InitializeObjectAttributes (&AddressAttributes,
  254. pTransportName, // Name
  255. OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE , // Attributes
  256. NULL, // RootDirectory
  257. NULL); // SecurityDescriptor
  258. Status = ZwCreateFile(&ConnHandle, // Handle
  259. GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
  260. &AddressAttributes, // Object Attributes
  261. &IoStatusBlock, // Final I/O status block
  262. NULL, // Allocation Size
  263. FILE_ATTRIBUTE_NORMAL, // Normal attributes
  264. FILE_SHARE_READ | FILE_SHARE_WRITE, // Sharing attributes
  265. FILE_OPEN_IF, // Create disposition
  266. 0, // CreateOptions
  267. EABuffer, // EA Buffer
  268. sizeof(FILE_FULL_EA_INFORMATION) +
  269. TDI_CONNECTION_CONTEXT_LENGTH + 1 +
  270. sizeof(CONNECTION_CONTEXT));
  271. MemoryFree(EABuffer);
  272. if (!NT_SUCCESS(Status)) {
  273. DBGPRINT(("_TdiOpenConnection: Error 0x%x Creating Connection object\n",Status));
  274. return(Status);
  275. }
  276. Status = IoStatusBlock.Status;
  277. if (!NT_SUCCESS(Status)) {
  278. DBGPRINT(("_TdiOpenConnection: Error 0x%x Creating Connection object in Iosb\n",Status));
  279. return(Status);
  280. }
  281. TRACE0(("_TdiOpenConnection: Returning connection handle %lx\n", ConnHandle));
  282. //
  283. // Obtain a referenced pointer to the file object.
  284. //
  285. Status = ObReferenceObjectByHandle (
  286. ConnHandle,
  287. 0,
  288. *IoFileObjectType,
  289. KernelMode,
  290. (PVOID *)&FileObject,
  291. NULL
  292. );
  293. if (!NT_SUCCESS(Status)) {
  294. DBGPRINT(("_TdiOpenConnection: Error Status 0x%x Referencing FileObject\n",Status));
  295. ZwClose( ConnHandle );
  296. return(Status);
  297. }
  298. //
  299. // Get the address of the device object for the endpoint.
  300. //
  301. DeviceObject = IoGetRelatedDeviceObject(FileObject);
  302. // Copy the out parameters
  303. *pHandle = ConnHandle;
  304. *ppFileObject = FileObject;
  305. *ppDeviceObject = DeviceObject;
  306. return(Status);
  307. }
  308. NTSTATUS
  309. _TdiListen(
  310. IN PTD pTd,
  311. IN PIRP Irp OPTIONAL,
  312. IN PFILE_OBJECT ConnectionFileObject,
  313. IN PDEVICE_OBJECT ConnectionDeviceObject
  314. )
  315. {
  316. NTSTATUS Status;
  317. BOOLEAN IrpAllocated = FALSE;
  318. TDI_CONNECTION_INFORMATION RequestInfo;
  319. TDI_CONNECTION_INFORMATION ReturnInfo;
  320. if (!ARGUMENT_PRESENT(Irp)) {
  321. Irp = _TdiAllocateIrp( ConnectionFileObject, ConnectionDeviceObject );
  322. if (Irp == NULL) {
  323. Status = STATUS_INSUFFICIENT_RESOURCES;
  324. return Status;
  325. }
  326. IrpAllocated = TRUE;
  327. }
  328. RtlZeroMemory( &RequestInfo, sizeof(RequestInfo) );
  329. RtlZeroMemory( &ReturnInfo, sizeof(ReturnInfo) );
  330. TdiBuildListen(
  331. Irp,
  332. ConnectionDeviceObject,
  333. ConnectionFileObject,
  334. NULL, // Completion routine
  335. NULL, // Context
  336. 0, // Flags
  337. &RequestInfo,
  338. &ReturnInfo
  339. );
  340. Status = _TdiSubmitRequest(pTd, ConnectionDeviceObject, Irp, FALSE);
  341. TRACE0(("_TdiListen: Status 0x%x\n",Status));
  342. if (IrpAllocated) {
  343. IoFreeIrp( Irp );
  344. }
  345. return(Status);
  346. }
  347. NTSTATUS
  348. _TdiAccept(
  349. IN PTD pTd,
  350. IN PIRP Irp OPTIONAL,
  351. IN PFILE_OBJECT ConnectionFileObject,
  352. IN PDEVICE_OBJECT ConnectionDeviceObject
  353. )
  354. {
  355. NTSTATUS Status;
  356. BOOLEAN IrpAllocated = FALSE;
  357. TDI_CONNECTION_INFORMATION RequestInfo;
  358. TDI_CONNECTION_INFORMATION ReturnInfo;
  359. if (!ARGUMENT_PRESENT(Irp)) {
  360. Irp = _TdiAllocateIrp( ConnectionFileObject, ConnectionDeviceObject );
  361. if (Irp == NULL) {
  362. Status = STATUS_INSUFFICIENT_RESOURCES;
  363. return Status;
  364. }
  365. IrpAllocated = TRUE;
  366. }
  367. RtlZeroMemory( &RequestInfo, sizeof(RequestInfo) );
  368. RtlZeroMemory( &ReturnInfo, sizeof(ReturnInfo) );
  369. TdiBuildAccept(
  370. Irp,
  371. ConnectionDeviceObject,
  372. ConnectionFileObject,
  373. NULL, // Completion routine
  374. NULL, // Context
  375. &RequestInfo,
  376. &ReturnInfo
  377. );
  378. Status = _TdiSubmitRequest(pTd, ConnectionDeviceObject, Irp, FALSE);
  379. if (IrpAllocated) {
  380. IoFreeIrp( Irp );
  381. }
  382. return(Status);
  383. }
  384. NTSTATUS
  385. _TdiConnect(
  386. IN PTD pTd,
  387. IN PIRP Irp OPTIONAL,
  388. IN PLARGE_INTEGER pTimeout OPTIONAL,
  389. IN PFILE_OBJECT ConnectionFileObject,
  390. IN PDEVICE_OBJECT ConnectionDeviceObject,
  391. IN ULONG RemoteTransportAddressLength,
  392. IN PTRANSPORT_ADDRESS pRemoteTransportAddress
  393. )
  394. {
  395. NTSTATUS Status;
  396. BOOLEAN IrpAllocated = FALSE;
  397. TDI_CONNECTION_INFORMATION RequestInfo;
  398. TDI_CONNECTION_INFORMATION ReturnInfo;
  399. if (!ARGUMENT_PRESENT(Irp)) {
  400. Irp = _TdiAllocateIrp( ConnectionFileObject, ConnectionDeviceObject );
  401. if (Irp == NULL) {
  402. Status = STATUS_INSUFFICIENT_RESOURCES;
  403. return Status;
  404. }
  405. IrpAllocated = TRUE;
  406. }
  407. RtlZeroMemory( &RequestInfo, sizeof(RequestInfo) );
  408. RtlZeroMemory( &ReturnInfo, sizeof(ReturnInfo) );
  409. RequestInfo.RemoteAddressLength = RemoteTransportAddressLength;
  410. RequestInfo.RemoteAddress = pRemoteTransportAddress;
  411. TdiBuildConnect(
  412. Irp,
  413. ConnectionDeviceObject,
  414. ConnectionFileObject,
  415. NULL, // Completion routine
  416. NULL, // Context
  417. pTimeout,
  418. &RequestInfo,
  419. &ReturnInfo
  420. );
  421. Status = _TdiSubmitRequest(pTd, ConnectionDeviceObject, Irp, TRUE);
  422. if (IrpAllocated) {
  423. IoFreeIrp( Irp );
  424. }
  425. return(Status);
  426. }
  427. NTSTATUS
  428. _TdiAssociateAddress(
  429. IN PTD pTd,
  430. IN PIRP Irp OPTIONAL,
  431. IN PFILE_OBJECT ConnectionFileObject,
  432. IN HANDLE AddressHandle,
  433. IN PDEVICE_OBJECT AddressDeviceObject
  434. )
  435. {
  436. NTSTATUS Status;
  437. BOOLEAN IrpAllocated = FALSE;
  438. if (!ARGUMENT_PRESENT(Irp)) {
  439. Irp = _TdiAllocateIrp( ConnectionFileObject, AddressDeviceObject );
  440. if (Irp == NULL) {
  441. Status = STATUS_INSUFFICIENT_RESOURCES;
  442. return Status;
  443. }
  444. IrpAllocated = TRUE;
  445. }
  446. TdiBuildAssociateAddress(
  447. Irp,
  448. AddressDeviceObject,
  449. ConnectionFileObject,
  450. NULL, // Completion routine
  451. NULL, // Context
  452. AddressHandle
  453. );
  454. Status = _TdiSubmitRequest(pTd, AddressDeviceObject, Irp, FALSE);
  455. if (IrpAllocated) {
  456. IoFreeIrp( Irp );
  457. }
  458. return(Status);
  459. }
  460. NTSTATUS
  461. _TdiDisconnect(
  462. IN PTD pTd,
  463. IN PFILE_OBJECT ConnectionFileObject,
  464. IN PDEVICE_OBJECT ConnectionDeviceObject
  465. )
  466. {
  467. PIRP Irp;
  468. NTSTATUS Status;
  469. BOOLEAN IrpAllocated = FALSE;
  470. Irp = _TdiAllocateIrp( ConnectionFileObject, ConnectionDeviceObject );
  471. if (Irp == NULL) {
  472. Status = STATUS_INSUFFICIENT_RESOURCES;
  473. return Status;
  474. }
  475. TdiBuildDisconnect(
  476. Irp,
  477. ConnectionDeviceObject,
  478. ConnectionFileObject,
  479. NULL, // Completion routine
  480. NULL, // Context
  481. 0,
  482. TDI_DISCONNECT_ABORT,
  483. NULL,
  484. NULL
  485. );
  486. Status = _TdiSubmitRequest(pTd, ConnectionDeviceObject, Irp, TRUE);
  487. IoFreeIrp( Irp );
  488. return(Status);
  489. }
  490. NTSTATUS
  491. _TdiSetEventHandler (
  492. IN PTD pTd,
  493. IN PDEVICE_OBJECT DeviceObject,
  494. IN PFILE_OBJECT FileObject,
  495. IN ULONG EventType,
  496. IN PVOID EventHandler,
  497. IN PVOID EventContext
  498. )
  499. /*++
  500. Routine Description:
  501. This routine registers an event handler with a TDI transport provider.
  502. Arguments:
  503. IN PDEVICE_OBJECT DeviceObject - Supplies the device object of the transport provider.
  504. IN PFILE_OBJECT FileObject - Supplies the address object's file object.
  505. IN ULONG EventType, - Supplies the type of event.
  506. IN PVOID EventHandler - Supplies the event handler.
  507. IN PVOID EventContext - Supplies the context for the event handler.
  508. Return Value:
  509. NTSTATUS - Final status of the set event operation
  510. --*/
  511. {
  512. NTSTATUS Status;
  513. PIRP Irp;
  514. Irp = _TdiAllocateIrp( FileObject, NULL );
  515. if (Irp == NULL) {
  516. return(STATUS_INSUFFICIENT_RESOURCES);
  517. }
  518. TdiBuildSetEventHandler(Irp, DeviceObject, FileObject,
  519. NULL, NULL,
  520. EventType, EventHandler, EventContext);
  521. Status = _TdiSubmitRequest(pTd, DeviceObject, Irp, FALSE);
  522. IoFreeIrp( Irp );
  523. return Status;
  524. }
  525. NTSTATUS
  526. _TdiSubmitRequest (
  527. IN PTD pTd,
  528. IN PDEVICE_OBJECT DeviceObject,
  529. IN PIRP Irp,
  530. IN BOOLEAN bKeepLock
  531. )
  532. /*++
  533. Routine Description:
  534. This routine submits a request to TDI and waits for it to complete.
  535. Arguments:
  536. IN PFILE_OBJECT FileObject - Connection or Address handle for TDI request
  537. IN PIRP Irp - TDI request to submit.
  538. Return Value:
  539. NTSTATUS - Final status of request.
  540. --*/
  541. {
  542. NTSTATUS Status;
  543. PKEVENT Event;
  544. Status = MemoryAllocate( sizeof(KEVENT), &Event );
  545. if( !NT_SUCCESS(Status) ) {
  546. return( Status );
  547. }
  548. KeInitializeEvent (Event, NotificationEvent, FALSE);
  549. IoSetCompletionRoutine(Irp, _TdiRequestComplete, Event, TRUE, TRUE, TRUE);
  550. //
  551. // Submit the request
  552. //
  553. Status = IoCallDriver(DeviceObject, Irp);
  554. //
  555. // If it failed immediately, return now, otherwise wait.
  556. //
  557. if (!NT_SUCCESS(Status)) {
  558. DBGPRINT(("_TdiSubmitRequest: submit request. Status = %X", Status));
  559. MemoryFree( Event );
  560. return Status;
  561. }
  562. if (Status == STATUS_PENDING) {
  563. TRACE0(("TDI request issued, waiting..."));
  564. do {
  565. //
  566. // Wait for a couple of seconds for the request to complete
  567. //
  568. // If it times out, and the thread is terminating, cancel the
  569. // request and unwind that way.
  570. //
  571. if ( !bKeepLock ) {
  572. Status = IcaWaitForSingleObject(
  573. pTd->pContext,
  574. Event,
  575. _TdiPollTimeout
  576. );
  577. } else {
  578. LARGE_INTEGER WaitTimeout;
  579. PLARGE_INTEGER pWaitTimeout = NULL;
  580. WaitTimeout = RtlEnlargedIntegerMultiply( _TdiPollTimeout, -10000 );
  581. pWaitTimeout = &WaitTimeout;
  582. Status = KeWaitForSingleObject(
  583. Event,
  584. UserRequest,
  585. UserMode,
  586. FALSE,
  587. pWaitTimeout
  588. );
  589. }
  590. TRACE0(("_TdiSubmitRequest: Status 0x%x from IcaWaitForSingleObject\n",Status));
  591. //
  592. // If we timed out the wait, and the thread is terminating,
  593. // give up and cancel the IRP.
  594. //
  595. if ( (Status == STATUS_TIMEOUT)
  596. &&
  597. ARGUMENT_PRESENT(Irp)
  598. &&
  599. PsIsThreadTerminating( Irp->Tail.Overlay.Thread ) ) {
  600. //
  601. // Ask the I/O system to cancel this IRP. This will cause
  602. // everything to unwind properly.
  603. //
  604. DBGPRINT(("_TdiSubmitRequest: Irp being canceled\n"));
  605. IoCancelIrp(Irp);
  606. }
  607. } while ( Status == STATUS_TIMEOUT );
  608. if (!NT_SUCCESS(Status)) {
  609. DBGPRINT(("Could not wait for connection to complete\n"));
  610. MemoryFree( Event );
  611. return Status;
  612. }
  613. Status = Irp->IoStatus.Status;
  614. }
  615. TRACE0(("TDI request complete Status 0x%x\n",Status));
  616. MemoryFree( Event );
  617. return(Status);
  618. }
  619. NTSTATUS
  620. _TdiRequestComplete (
  621. IN PDEVICE_OBJECT DeviceObject,
  622. IN PIRP Irp,
  623. IN PVOID Ctx
  624. )
  625. /*++
  626. Routine Description:
  627. Completion routine for _TdiRequestSubmit operation.
  628. Arguments:
  629. IN PDEVICE_OBJECT DeviceObject, - Supplies a pointer to the device object
  630. IN PIRP Irp, - Supplies the IRP submitted
  631. IN PVOID Context - Supplies a pointer to the kernel event to release
  632. Return Value:
  633. NTSTATUS - Status of KeSetEvent
  634. We return STATUS_MORE_PROCESSING_REQUIRED to prevent the IRP completion
  635. code from processing this puppy any more.
  636. --*/
  637. {
  638. UNREFERENCED_PARAMETER(Irp);
  639. UNREFERENCED_PARAMETER(DeviceObject);
  640. TRACE0(("_TdiRequestComplete: Context %lx\n", Ctx));
  641. //
  642. // Set the event to the Signalled state with 0 priority increment and
  643. // indicate that we will not be blocking soon.
  644. //
  645. KeSetEvent((PKEVENT) Ctx, 0, FALSE);
  646. return STATUS_MORE_PROCESSING_REQUIRED;
  647. }
  648. PIRP
  649. _TdiAllocateIrp(
  650. IN PFILE_OBJECT FileObject,
  651. IN PDEVICE_OBJECT DeviceObject OPTIONAL
  652. )
  653. /*++
  654. Routine Description:
  655. This function allocates and builds an I/O request packet.
  656. Arguments:
  657. FileObject - Supplies a pointer to the file object for which this
  658. request is directed. This pointer is copied into the IRP, so
  659. that the called driver can find its file-based context. NOTE
  660. THAT THIS IS NOT A REFERENCED POINTER. The caller must ensure
  661. that the file object is not deleted while the I/O operation is
  662. in progress. The redir accomplishes this by incrementing a
  663. reference count in a local block to account for the I/O; the
  664. local block in turn references the file object.
  665. DeviceObject - Supplies a pointer to a device object to direct this
  666. request to. If this is not supplied, it uses the file object to
  667. determine the device object.
  668. Return Value:
  669. PIRP - Returns a pointer to the constructed IRP.
  670. --*/
  671. {
  672. PIRP Irp;
  673. if (ARGUMENT_PRESENT(DeviceObject)) {
  674. Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
  675. } else {
  676. Irp = IoAllocateIrp(IoGetRelatedDeviceObject(FileObject)->StackSize, FALSE);
  677. }
  678. if (Irp == NULL) {
  679. return(NULL);
  680. }
  681. Irp->Tail.Overlay.OriginalFileObject = FileObject;
  682. Irp->Tail.Overlay.Thread = PsGetCurrentThread();
  683. Irp->RequestorMode = KernelMode;
  684. return Irp;
  685. }
  686. NTSTATUS
  687. _TdiReceiveDatagram(
  688. IN PTD pTd,
  689. IN PIRP Irp OPTIONAL,
  690. IN PFILE_OBJECT FileObject,
  691. IN PDEVICE_OBJECT DeviceObject,
  692. IN PTRANSPORT_ADDRESS pRemoteAddress,
  693. IN ULONG RemoteAddressLength,
  694. IN ULONG RecvFlags,
  695. IN PVOID pBuffer,
  696. IN ULONG BufferLength,
  697. OUT PULONG pReturnLength
  698. )
  699. {
  700. PMDL pMdl;
  701. NTSTATUS Status;
  702. BOOLEAN IrpAllocated = FALSE;
  703. TDI_CONNECTION_INFORMATION RequestInfo;
  704. TDI_CONNECTION_INFORMATION ReturnInfo;
  705. if (!ARGUMENT_PRESENT(Irp)) {
  706. Irp = _TdiAllocateIrp( FileObject, DeviceObject );
  707. if (Irp == NULL) {
  708. Status = STATUS_INSUFFICIENT_RESOURCES;
  709. return Status;
  710. }
  711. IrpAllocated = TRUE;
  712. }
  713. RtlZeroMemory( &RequestInfo, sizeof(RequestInfo) );
  714. RtlZeroMemory( &ReturnInfo, sizeof(ReturnInfo) );
  715. // Copy in info to return remote address
  716. ReturnInfo.RemoteAddress = pRemoteAddress;
  717. ReturnInfo.RemoteAddressLength = RemoteAddressLength;
  718. // Build MDL for buffer
  719. pMdl = IoAllocateMdl(
  720. pBuffer,
  721. BufferLength,
  722. FALSE,
  723. FALSE,
  724. (PIRP)NULL
  725. );
  726. if( pMdl == NULL ) {
  727. if (IrpAllocated) {
  728. IoFreeIrp( Irp );
  729. }
  730. return( STATUS_INSUFFICIENT_RESOURCES );
  731. }
  732. MmBuildMdlForNonPagedPool ( pMdl );
  733. TdiBuildReceiveDatagram(
  734. Irp,
  735. DeviceObject,
  736. FileObject,
  737. NULL, // Completion routine
  738. NULL, // Context
  739. pMdl, // Mdl address
  740. BufferLength,
  741. &RequestInfo,
  742. &ReturnInfo,
  743. RecvFlags // InFlags
  744. );
  745. Status = _TdiSubmitRequest(pTd, DeviceObject, Irp, FALSE);
  746. IoFreeMdl( pMdl );
  747. if ( NT_SUCCESS(Status) ) {
  748. // Packet length returned is in the Iosb
  749. *pReturnLength = (ULONG)Irp->IoStatus.Information;
  750. TRACE0(("_TdiReceiveDatagram: Irp DataLength 0x%x UserDataLength 0x%x, "
  751. "OptionsLength 0x%x, RemoteAddressLength 0x%x\n", *pReturnLength,
  752. ReturnInfo.UserDataLength, ReturnInfo.OptionsLength,
  753. ReturnInfo.RemoteAddressLength));
  754. }
  755. if (IrpAllocated) {
  756. IoFreeIrp( Irp );
  757. }
  758. return(Status);
  759. }
  760. NTSTATUS
  761. _TdiSendDatagram(
  762. IN PTD pTd,
  763. IN PIRP Irp OPTIONAL,
  764. IN PFILE_OBJECT FileObject,
  765. IN PDEVICE_OBJECT DeviceObject,
  766. IN PTRANSPORT_ADDRESS pRemoteAddress,
  767. IN ULONG RemoteAddressLength,
  768. IN PVOID pBuffer,
  769. IN ULONG BufferLength
  770. )
  771. {
  772. PMDL pMdl;
  773. NTSTATUS Status;
  774. BOOLEAN IrpAllocated = FALSE;
  775. TDI_CONNECTION_INFORMATION SendInfo;
  776. if (!ARGUMENT_PRESENT(Irp)) {
  777. Irp = _TdiAllocateIrp( FileObject, DeviceObject );
  778. if (Irp == NULL) {
  779. Status = STATUS_INSUFFICIENT_RESOURCES;
  780. return Status;
  781. }
  782. IrpAllocated = TRUE;
  783. }
  784. RtlZeroMemory( &SendInfo, sizeof(SendInfo) );
  785. // We must fill in our destination address
  786. SendInfo.RemoteAddress = pRemoteAddress;
  787. SendInfo.RemoteAddressLength = RemoteAddressLength;
  788. // Build MDL for buffer
  789. pMdl = IoAllocateMdl(
  790. pBuffer,
  791. BufferLength,
  792. FALSE,
  793. FALSE,
  794. (PIRP)NULL
  795. );
  796. if( pMdl == NULL ) {
  797. if (IrpAllocated) {
  798. IoFreeIrp( Irp );
  799. }
  800. return( STATUS_INSUFFICIENT_RESOURCES );
  801. }
  802. MmBuildMdlForNonPagedPool ( pMdl );
  803. TdiBuildSendDatagram(
  804. Irp,
  805. DeviceObject,
  806. FileObject,
  807. NULL, // Completion routine
  808. NULL, // Context
  809. pMdl, // Mdl address
  810. BufferLength,
  811. &SendInfo
  812. );
  813. Status = _TdiSubmitRequest(pTd, DeviceObject, Irp, FALSE);
  814. IoFreeMdl( pMdl );
  815. if (IrpAllocated) {
  816. IoFreeIrp( Irp );
  817. }
  818. return(Status);
  819. }
  820. NTSTATUS
  821. _TdiQueryAddressInfo(
  822. IN PTD pTd,
  823. IN PIRP Irp OPTIONAL,
  824. IN PFILE_OBJECT FileObject,
  825. IN PDEVICE_OBJECT DeviceObject,
  826. IN PTDI_ADDRESS_INFO pAddressInfo,
  827. IN ULONG AddressInfoLength
  828. )
  829. {
  830. PMDL pMdl;
  831. NTSTATUS Status;
  832. BOOLEAN IrpAllocated = FALSE;
  833. if (!ARGUMENT_PRESENT(Irp)) {
  834. Irp = _TdiAllocateIrp( FileObject, DeviceObject );
  835. if (Irp == NULL) {
  836. Status = STATUS_INSUFFICIENT_RESOURCES;
  837. return Status;
  838. }
  839. IrpAllocated = TRUE;
  840. }
  841. // Build MDL for buffer
  842. pMdl = IoAllocateMdl(
  843. pAddressInfo,
  844. AddressInfoLength,
  845. FALSE,
  846. FALSE,
  847. (PIRP)NULL
  848. );
  849. if( pMdl == NULL ) {
  850. if (IrpAllocated) {
  851. IoFreeIrp( Irp );
  852. }
  853. return( STATUS_INSUFFICIENT_RESOURCES );
  854. }
  855. MmBuildMdlForNonPagedPool ( pMdl );
  856. TdiBuildQueryInformation(
  857. Irp,
  858. DeviceObject,
  859. FileObject,
  860. NULL, // Completion routine
  861. NULL, // Context
  862. TDI_QUERY_ADDRESS_INFO,
  863. pMdl
  864. );
  865. Status = _TdiSubmitRequest(pTd, DeviceObject, Irp, FALSE);
  866. IoFreeMdl( pMdl );
  867. if (IrpAllocated) {
  868. IoFreeIrp( Irp );
  869. }
  870. return(Status);
  871. }