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.

961 lines
26 KiB

  1. /*************************************************************************
  2. *
  3. * stack.c
  4. *
  5. * ICA STACK IOCTLS
  6. *
  7. * Copyright Microsoft, 1998
  8. *
  9. *
  10. *************************************************************************/
  11. /*
  12. * Includes
  13. */
  14. #include <ntddk.h>
  15. #include <ntddvdeo.h>
  16. #include <ntddkbd.h>
  17. #include <ntddmou.h>
  18. #include <ntddbeep.h>
  19. #include <winstaw.h>
  20. #include <icadd.h>
  21. #include <sdapi.h>
  22. #include <td.h>
  23. /*=============================================================================
  24. == External procedures defined
  25. =============================================================================*/
  26. NTSTATUS StackCreateEndpoint( PTD, PSD_IOCTL );
  27. NTSTATUS StackCdCreateEndpoint( PTD, PSD_IOCTL );
  28. NTSTATUS StackCallbackInitiate( PTD, PSD_IOCTL );
  29. NTSTATUS StackCallbackComplete( PTD, PSD_IOCTL );
  30. NTSTATUS StackOpenEndpoint( PTD, PSD_IOCTL );
  31. NTSTATUS StackCloseEndpoint( PTD, PSD_IOCTL );
  32. NTSTATUS StackConnectionWait( PTD, PSD_IOCTL );
  33. NTSTATUS StackConnectionSend( PTD, PSD_IOCTL );
  34. NTSTATUS StackConnectionRequest( PTD, PSD_IOCTL );
  35. NTSTATUS StackQueryParams( PTD, PSD_IOCTL );
  36. NTSTATUS StackSetParams( PTD, PSD_IOCTL );
  37. NTSTATUS StackQueryLastError( PTD, PSD_IOCTL );
  38. NTSTATUS StackWaitForStatus( PTD, PSD_IOCTL );
  39. NTSTATUS StackCancelIo( PTD, PSD_IOCTL );
  40. NTSTATUS StackQueryRemoteAddress( PTD, PSD_IOCTL );
  41. /*=============================================================================
  42. == Internal procedures defined
  43. =============================================================================*/
  44. NTSTATUS _TdCreateInputThread( PTD );
  45. /*=============================================================================
  46. == Procedures used
  47. =============================================================================*/
  48. NTSTATUS DeviceCreateEndpoint( PTD, PICA_STACK_ADDRESS, PICA_STACK_ADDRESS );
  49. NTSTATUS DeviceOpenEndpoint( PTD, PVOID, ULONG );
  50. NTSTATUS DeviceCloseEndpoint( PTD );
  51. NTSTATUS DeviceConnectionWait( PTD, PVOID, ULONG, PULONG );
  52. NTSTATUS DeviceConnectionSend( PTD );
  53. NTSTATUS DeviceConnectionRequest( PTD, PICA_STACK_ADDRESS, PVOID, ULONG, PULONG );
  54. NTSTATUS DeviceGetLastError( PTD, PICA_STACK_LAST_ERROR );
  55. NTSTATUS DeviceWaitForStatus( PTD );
  56. NTSTATUS DeviceCancelIo( PTD );
  57. NTSTATUS DeviceSetParams( PTD );
  58. NTSTATUS DeviceIoctl( PTD, PSD_IOCTL );
  59. NTSTATUS DeviceQueryRemoteAddress( PTD, PVOID, ULONG, PVOID, ULONG, PULONG );
  60. NTSTATUS TdInputThread( PTD );
  61. NTSTATUS TdSyncWrite( PTD, PSD_SYNCWRITE );
  62. /*******************************************************************************
  63. *
  64. * StackCreateEndpoint IOCTL_ICA_STACK_CREATE_ENDPOINT
  65. *
  66. * Create new transport endpoint
  67. *
  68. * The endpoint structure contains everything necessary to preserve
  69. * a client connection across a transport driver unload and reload.
  70. *
  71. * This routine creates a new endpoint, using the optional local address.
  72. * In the case of a network connection, the actual endpoint cannot be
  73. * created until the client connection is established. What this routine
  74. * creates is an endpoint to listen on.
  75. *
  76. * DeviceConnectionWait and DeviceConnectionRequest return the endpoint.
  77. *
  78. * NOTE: The endpoint structure is an opaque, variable length data
  79. * structure whose length and contents are determined by the
  80. * transport driver.
  81. *
  82. *
  83. * ENTRY:
  84. * pTd (input)
  85. * Pointer to td data structure
  86. * pSdIoctl (input/output)
  87. * input - ICA_STACK_ADDRESS (or NULL)
  88. * output - nothing
  89. *
  90. * EXIT:
  91. * STATUS_SUCCESS - no error
  92. *
  93. ******************************************************************************/
  94. NTSTATUS
  95. StackCreateEndpoint( PTD pTd, PSD_IOCTL pSdIoctl )
  96. {
  97. PICA_STACK_ADDRESS pAddressIn;
  98. PICA_STACK_ADDRESS pAddressOut;
  99. NTSTATUS Status;
  100. if ( pSdIoctl->InputBufferLength < sizeof(ICA_STACK_ADDRESS) ) {
  101. /*
  102. * No address specified
  103. */
  104. pAddressIn = NULL;
  105. } else {
  106. /*
  107. * Get local address to use, if any
  108. */
  109. pAddressIn = pSdIoctl->InputBuffer;
  110. }
  111. if ( pSdIoctl->OutputBufferLength < sizeof(ICA_STACK_ADDRESS) ) {
  112. /*
  113. * No address specified
  114. */
  115. pAddressOut = NULL;
  116. } else {
  117. /*
  118. * Get local address to use, if any
  119. */
  120. pAddressOut = pSdIoctl->OutputBuffer;
  121. }
  122. /*
  123. * Initialize transport driver endpoint
  124. */
  125. Status = DeviceCreateEndpoint( pTd, pAddressIn, pAddressOut );
  126. if ( !NT_SUCCESS(Status) )
  127. goto badcreate;
  128. TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackCreateEndpoint: %x, success\n", pAddressIn ));
  129. return( STATUS_SUCCESS );
  130. /*=============================================================================
  131. == Error returns
  132. =============================================================================*/
  133. /*
  134. * endpoint create failed
  135. */
  136. badcreate:
  137. TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TD: StackCreateEndpoint: %x, Status=0x%x\n", pAddressIn, Status ));
  138. return( Status );
  139. }
  140. /*******************************************************************************
  141. *
  142. * StackCdCreateEndpoint IOCTL_ICA_STACK_CD_CREATE_ENDPOINT
  143. *
  144. * Create an endpoint based on a data provided by a connection driver.
  145. *
  146. * NOTE: The endpoint structure is an opaque, variable length data
  147. * structure whose length and contents are determined by the
  148. * transport driver.
  149. *
  150. * ENTRY:
  151. * pTd (input)
  152. * Pointer to td data structure
  153. * pSdIoctl (input/output)
  154. * input - <endpoint data)
  155. * output - <endpoint data>
  156. *
  157. * EXIT:
  158. * STATUS_SUCCESS - no error
  159. *
  160. ******************************************************************************/
  161. NTSTATUS
  162. StackCdCreateEndpoint( PTD pTd, PSD_IOCTL pSdIoctl )
  163. {
  164. NTSTATUS Status;
  165. TRACE(( pTd->pContext, TC_TD, TT_API1,
  166. "TD: StackCdCreateEndpoint: entry\n" ));
  167. pTd->fClosing = FALSE;
  168. /*
  169. * Initialize transport driver endpoint
  170. */
  171. Status = DeviceIoctl( pTd, pSdIoctl );
  172. if ( !NT_SUCCESS(Status) )
  173. goto badopen;
  174. TRACE(( pTd->pContext, TC_TD, TT_API1,
  175. "TD: StackCdCreateEndpoint: success\n" ));
  176. return( STATUS_SUCCESS );
  177. /*=============================================================================
  178. == Error returns
  179. =============================================================================*/
  180. /*
  181. * endpoint open failed
  182. */
  183. badopen:
  184. TRACE(( pTd->pContext, TC_TD, TT_ERROR,
  185. "TD: StackCdCreateEndpoint: Status=0x%x\n",
  186. Status ));
  187. return( Status );
  188. }
  189. /*******************************************************************************
  190. *
  191. * StackCallbackInitiate IOCTL_ICA_STACK_CALLBACK_INITIATE
  192. *
  193. *
  194. * ENTRY:
  195. * pTd (input)
  196. * Pointer to td data structure
  197. * pSdIoctl (input/output)
  198. * input - ICA_STACK_CALLBACK
  199. * output - nothing
  200. *
  201. * EXIT:
  202. * STATUS_SUCCESS - no error
  203. *
  204. ******************************************************************************/
  205. NTSTATUS
  206. StackCallbackInitiate( PTD pTd, PSD_IOCTL pSdIoctl )
  207. {
  208. NTSTATUS Status;
  209. TRACE(( pTd->pContext, TC_TD, TT_API1,
  210. "TD: StackCallbackInitiate: entry\n" ));
  211. pTd->fCallbackInProgress = TRUE;
  212. return( STATUS_SUCCESS );
  213. }
  214. /*******************************************************************************
  215. *
  216. * StackCallbackComplete IOCTL_ICA_STACK_CALLBACK_COMPLETE
  217. *
  218. *
  219. * ENTRY:
  220. * pTd (input)
  221. * Pointer to td data structure
  222. * pSdIoctl (input/output)
  223. * input - nothing
  224. * output - nothing
  225. *
  226. * EXIT:
  227. * STATUS_SUCCESS - no error
  228. *
  229. ******************************************************************************/
  230. NTSTATUS
  231. StackCallbackComplete( PTD pTd, PSD_IOCTL pSdIoctl )
  232. {
  233. NTSTATUS Status;
  234. TRACE(( pTd->pContext, TC_TD, TT_API1,
  235. "TD: StackCallbackComplete: entry\n" ));
  236. pTd->fCallbackInProgress = FALSE;
  237. /*
  238. * Create the input thread if one is not running.
  239. */
  240. if ( pTd->pInputThread ) {
  241. Status = IcaWaitForSingleObject( pTd->pContext,
  242. pTd->pInputThread, 0 );
  243. if ( Status != STATUS_TIMEOUT) { // if input thread not running
  244. /*
  245. * The old input thread has gone away, but hasn't
  246. * been cleaned up. Clean it up now.
  247. */
  248. ObDereferenceObject( pTd->pInputThread );
  249. pTd->pInputThread = NULL;
  250. }
  251. }
  252. if ( !pTd->pInputThread ) {
  253. Status = _TdCreateInputThread( pTd );
  254. if ( !NT_SUCCESS(Status) )
  255. goto badthreadcreate;
  256. }
  257. return( STATUS_SUCCESS );
  258. badthreadcreate:
  259. return( Status );
  260. }
  261. /*******************************************************************************
  262. *
  263. * StackOpenEndpoint IOCTL_ICA_STACK_OPEN_ENDPOINT
  264. *
  265. * Open an existing transport endpoint
  266. *
  267. * The endpoint structure contains everything necessary to preserve
  268. * a client connection across a transport driver unload and reload.
  269. *
  270. * This routine will bind to an existing endpoint which is passed as
  271. * the input parameter.
  272. *
  273. * NOTE: The endpoint structure is an opaque, variable length data
  274. * structure whose length and contents are determined by the
  275. * transport driver.
  276. *
  277. *
  278. * ENTRY:
  279. * pTd (input)
  280. * Pointer to td data structure
  281. * pSdIoctl (input/output)
  282. * input - <endpoint data>
  283. * output - nothing
  284. *
  285. * EXIT:
  286. * STATUS_SUCCESS - no error
  287. *
  288. ******************************************************************************/
  289. NTSTATUS
  290. StackOpenEndpoint( PTD pTd, PSD_IOCTL pSdIoctl )
  291. {
  292. NTSTATUS Status;
  293. /*
  294. * Initialize transport driver endpoint
  295. */
  296. Status = DeviceOpenEndpoint( pTd,
  297. pSdIoctl->InputBuffer,
  298. pSdIoctl->InputBufferLength );
  299. if ( !NT_SUCCESS(Status) )
  300. goto badopen;
  301. /*
  302. * Create the input thread now.
  303. */
  304. Status = _TdCreateInputThread( pTd );
  305. if ( !NT_SUCCESS(Status) )
  306. goto badthreadcreate;
  307. TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackOpenEndpoint, success\n" ));
  308. return( STATUS_SUCCESS );
  309. /*=============================================================================
  310. == Error returns
  311. =============================================================================*/
  312. /*
  313. * thread create failed - we used to close the endpoint, however TermSrv
  314. * does not expect this and would do a double free. Now we just rely on
  315. * TermSrv to turn around and close the endpoint.
  316. */
  317. badthreadcreate:
  318. // (void) DeviceCloseEndpoint( pTd );
  319. /*
  320. * endpoint open failed
  321. */
  322. badopen:
  323. TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TD: StackOpenEndpoint, Status=0x%x\n", Status ));
  324. return( Status );
  325. }
  326. /*******************************************************************************
  327. *
  328. * StackCloseEndpoint IOCTL_ICA_STACK_CLOSE_ENDPOINT
  329. *
  330. * Close transport endpoint
  331. *
  332. * This will terminate any client connection
  333. *
  334. *
  335. * ENTRY:
  336. * pTd (input)
  337. * Pointer to td data structure
  338. * pSdIoctl (input/output)
  339. * input - nothing
  340. * output - nothing
  341. *
  342. * EXIT:
  343. * STATUS_SUCCESS - no error
  344. *
  345. ******************************************************************************/
  346. NTSTATUS
  347. StackCloseEndpoint( PTD pTd, PSD_IOCTL pSdIoctl )
  348. {
  349. NTSTATUS Status;
  350. /*
  351. * Close transport driver endpoint
  352. */
  353. Status = DeviceCloseEndpoint( pTd );
  354. if ( !NT_SUCCESS(Status) )
  355. goto badclose;
  356. TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackCloseEndpoint: success\n" ));
  357. return( STATUS_SUCCESS );
  358. /*=============================================================================
  359. == Error returns
  360. =============================================================================*/
  361. /*
  362. * endpoint close failed
  363. */
  364. badclose:
  365. TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TD: StackCloseEndpoint: 0x%x\n", Status ));
  366. return( Status );
  367. }
  368. /*******************************************************************************
  369. *
  370. * StackConnectionWait IOCTL_ICA_STACK_CONNECTION_WAIT
  371. *
  372. * Waits for a new client connection
  373. *
  374. * After the transport driver is loaded and StackCreateEndpoint is called
  375. * this routine is called to wait for a new client connection.
  376. *
  377. * If an endpoint does not yet exist, DeviceConnectionWait will create one
  378. * when the client connects.
  379. *
  380. * Changed 02/18/97 JohnR:
  381. *
  382. * This routine returns an opaque 32 bit handle to a data structure that
  383. * is maintained by ICADD.SYS. This data structure allows the transport
  384. * driver to maintain specific state information in a secure manner.
  385. *
  386. * This state information is only known to the transport driver.
  387. *
  388. * ENTRY:
  389. * pTd (input)
  390. * Pointer to td data structure
  391. * pSdIoctl (input/output)
  392. * input - nothing
  393. * output - <endpoint data>
  394. *
  395. * EXIT:
  396. * STATUS_SUCCESS - no error
  397. *
  398. ******************************************************************************/
  399. NTSTATUS
  400. StackConnectionWait( PTD pTd, PSD_IOCTL pSdIoctl )
  401. {
  402. NTSTATUS Status;
  403. TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackConnectionWait: enter\n" ));
  404. /*
  405. * Initialize return byte count
  406. * - size of returned endpoint structure
  407. */
  408. pSdIoctl->BytesReturned = 0;
  409. /*
  410. * Wait for physical connection
  411. *
  412. * - DeviceConnectionWait should check OutputBufferLength to make
  413. * sure it's long enough to return an endpoint structure before
  414. * blocking.
  415. */
  416. Status = DeviceConnectionWait( pTd,
  417. pSdIoctl->OutputBuffer,
  418. pSdIoctl->OutputBufferLength,
  419. &pSdIoctl->BytesReturned );
  420. if ( !NT_SUCCESS(Status) )
  421. goto badwait;
  422. TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackConnectionWait: success\n" ));
  423. return( STATUS_SUCCESS );
  424. /*=============================================================================
  425. == Error returns
  426. =============================================================================*/
  427. /*
  428. * thread create failed
  429. * Wait failed
  430. */
  431. badwait:
  432. TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TD: StackConnectionWait: Status=0x%x\n", Status ));
  433. return( Status );
  434. }
  435. /*******************************************************************************
  436. *
  437. * StackConnectionSend IOCTL_ICA_STACK_CONNECTION_SEND
  438. *
  439. * Initialize transport driver module data to send to the client
  440. *
  441. *
  442. * ENTRY:
  443. * pTd (input)
  444. * Pointer to td data structure
  445. * pSdIoctl (input/output)
  446. * input - nothing
  447. * output - nothing
  448. *
  449. * EXIT:
  450. * STATUS_SUCCESS - no error
  451. *
  452. ******************************************************************************/
  453. NTSTATUS
  454. StackConnectionSend( PTD pTd, PSD_IOCTL pSdIoctl )
  455. {
  456. return( DeviceConnectionSend( pTd ) );
  457. }
  458. /*******************************************************************************
  459. *
  460. * StackConnectionRequest IOCTL_ICA_STACK_CONNECTION_REQUEST
  461. *
  462. * Initiate a connection to the specified remote address
  463. *
  464. * - this routine is only used by shadow
  465. *
  466. * DeviceConnectionRequest will create a new endpoint after establishing
  467. * a connection.
  468. *
  469. * This routine returns the endpoint data structure. The endpoint structure
  470. * contains everything necessary to preserve a connection across a transport
  471. * driver unload and reload.
  472. *
  473. * NOTE: The endpoint structure is an opaque, variable length data
  474. * structure whose length and contents are determined by the
  475. * transport driver.
  476. *
  477. *
  478. * typedef struct _ICA_STACK_ADDRESS {
  479. * BYTE Address[MAX_BR_ADDRESS]; // bytes 0,1 family, 2-n address
  480. * } ICA_STACK_ADDRESS, *PICA_STACK_ADDRESS;
  481. *
  482. *
  483. * ENTRY:
  484. * pTd (input)
  485. * Pointer to td data structure
  486. * pSdIoctl (input/output)
  487. * input - ICA_STACK_ADDRESS (remote address)
  488. * output - <endpoint data>
  489. *
  490. * EXIT:
  491. * STATUS_SUCCESS - no error
  492. *
  493. ******************************************************************************/
  494. NTSTATUS
  495. StackConnectionRequest( PTD pTd, PSD_IOCTL pSdIoctl )
  496. {
  497. NTSTATUS Status;
  498. if ( pSdIoctl->InputBufferLength < sizeof(ICA_STACK_ADDRESS) ) {
  499. Status = STATUS_BUFFER_TOO_SMALL;
  500. goto badbuffer;
  501. }
  502. /*
  503. * Establish physical connection
  504. *
  505. * - DeviceConnectionRequest should check OutputBufferLength to make
  506. * sure it is long enough to return an endpoint structure before
  507. * making a connection.
  508. */
  509. Status = DeviceConnectionRequest( pTd,
  510. pSdIoctl->InputBuffer,
  511. pSdIoctl->OutputBuffer,
  512. pSdIoctl->OutputBufferLength,
  513. &pSdIoctl->BytesReturned );
  514. if ( !NT_SUCCESS(Status) )
  515. goto badrequest;
  516. /*
  517. * Create input thread
  518. */
  519. Status = _TdCreateInputThread( pTd );
  520. if ( !NT_SUCCESS(Status) )
  521. goto badthreadcreate;
  522. TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackConnectionRequest: success\n" ));
  523. return( STATUS_SUCCESS );
  524. /*=============================================================================
  525. == Error returns
  526. =============================================================================*/
  527. /*
  528. * thread create failed
  529. * connection request failed
  530. * buffer too small
  531. */
  532. badthreadcreate:
  533. badrequest:
  534. badbuffer:
  535. TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TD: StackConnectionRequest: Status=0x%x\n", Status ));
  536. return( Status );
  537. }
  538. /*******************************************************************************
  539. *
  540. * StackQueryParams IOCTL_ICA_STACK_QUERY_PARAMS
  541. *
  542. * query transport driver parameters
  543. *
  544. *
  545. * ENTRY:
  546. * pTd (input)
  547. * Pointer to td data structure
  548. * pSdIoctl (input/output)
  549. * input - SDCLASS
  550. * output - PDPARAMS
  551. *
  552. * EXIT:
  553. * STATUS_SUCCESS - no error
  554. *
  555. ******************************************************************************/
  556. NTSTATUS
  557. StackQueryParams( PTD pTd, PSD_IOCTL pSdIoctl )
  558. {
  559. PPDPARAMS pParams;
  560. if ( pSdIoctl->InputBufferLength < sizeof(SDCLASS) ||
  561. pSdIoctl->OutputBufferLength < sizeof(PDPARAMS) ) {
  562. return( STATUS_BUFFER_TOO_SMALL );
  563. }
  564. pParams = pSdIoctl->OutputBuffer;
  565. *pParams = pTd->Params;
  566. pSdIoctl->BytesReturned = sizeof(PDPARAMS);
  567. return( STATUS_SUCCESS );
  568. }
  569. /*******************************************************************************
  570. *
  571. * StackQueryRemoteAddress IOCTL_TS_STACK_QUERY_REMOTEADDRESS
  572. *
  573. * query for the remote address
  574. *
  575. *
  576. * ENTRY:
  577. * pTd (input)
  578. * Pointer to td data structure
  579. * pSdIoctl (input/output)
  580. * input - endpoint data
  581. * output - sockaddr
  582. *
  583. * EXIT:
  584. * STATUS_SUCCESS - no error
  585. *
  586. ******************************************************************************/
  587. NTSTATUS
  588. StackQueryRemoteAddress( PTD pTd, PSD_IOCTL pSdIoctl )
  589. {
  590. NTSTATUS Status;
  591. Status = DeviceQueryRemoteAddress( pTd,
  592. pSdIoctl->InputBuffer,
  593. pSdIoctl->InputBufferLength,
  594. pSdIoctl->OutputBuffer,
  595. pSdIoctl->OutputBufferLength,
  596. &pSdIoctl->BytesReturned );
  597. if ( !NT_SUCCESS(Status) )
  598. {
  599. TRACE(( pTd->pContext, TC_TD, TT_ERROR, "TD: StackQueryRemoteAddress: 0x%\n", Status ));
  600. }
  601. return Status;
  602. }
  603. /*******************************************************************************
  604. *
  605. * StackSetParams IOCTL_ICA_STACK_SET_PARAMS
  606. *
  607. * set transport driver parameters
  608. *
  609. *
  610. * ENTRY:
  611. * pTd (input)
  612. * Pointer to td data structure
  613. * pSdIoctl (input/output)
  614. * input - PDPARAMS
  615. * output - nothing
  616. *
  617. * EXIT:
  618. * STATUS_SUCCESS - no error
  619. *
  620. ******************************************************************************/
  621. NTSTATUS
  622. StackSetParams( PTD pTd, PSD_IOCTL pSdIoctl )
  623. {
  624. PPDPARAMS pParams;
  625. if ( pSdIoctl->InputBufferLength < sizeof(PDPARAMS) ) {
  626. return( STATUS_BUFFER_TOO_SMALL );
  627. }
  628. pParams = pSdIoctl->InputBuffer;
  629. pTd->Params = *pParams;
  630. return( DeviceSetParams( pTd ) );
  631. }
  632. /*******************************************************************************
  633. *
  634. * StackQueryLastError IOCTL_ICA_STACK_QUERY_LAST_ERROR
  635. *
  636. * Query transport driver error code and message
  637. *
  638. * typedef struct _ICA_STACK_LAST_ERROR {
  639. * ULONG Error;
  640. * CHAR Message[ MAX_ERRORMESSAGE ];
  641. * } ICA_STACK_LAST_ERROR, *PICA_STACK_LAST_ERROR;
  642. *
  643. *
  644. * ENTRY:
  645. * pTd (input)
  646. * Pointer to td data structure
  647. * pSdIoctl (input/output)
  648. * input - nothing
  649. * output - ICA_STACK_LAST_ERROR
  650. *
  651. * EXIT:
  652. * STATUS_SUCCESS - no error
  653. *
  654. ******************************************************************************/
  655. NTSTATUS
  656. StackQueryLastError( PTD pTd, PSD_IOCTL pSdIoctl )
  657. {
  658. if ( pSdIoctl->OutputBufferLength < sizeof(ICA_STACK_LAST_ERROR) ) {
  659. return( STATUS_BUFFER_TOO_SMALL );
  660. }
  661. pSdIoctl->BytesReturned = sizeof(ICA_STACK_LAST_ERROR);
  662. return( DeviceGetLastError( pTd, pSdIoctl->OutputBuffer ) );
  663. }
  664. /*******************************************************************************
  665. *
  666. * StackWaitForStatus IOCTL_ICA_STACK_WAIT_FOR_STATUS
  667. *
  668. * Wait for transport driver status to change
  669. * - only supported by async transport driver to wait for rs232 signal change
  670. *
  671. *
  672. * ENTRY:
  673. * pTd (input)
  674. * Pointer to td data structure
  675. * pSdIoctl (input/output)
  676. * input - nothing
  677. * output - nothing
  678. *
  679. * EXIT:
  680. * STATUS_SUCCESS - no error
  681. *
  682. ******************************************************************************/
  683. NTSTATUS
  684. StackWaitForStatus( PTD pTd, PSD_IOCTL pSdIoctl )
  685. {
  686. /*
  687. * Check if driver is being closed
  688. */
  689. if ( pTd->fClosing )
  690. return( STATUS_CTX_CLOSE_PENDING );
  691. return( DeviceWaitForStatus( pTd ) );
  692. }
  693. /*******************************************************************************
  694. *
  695. * StackCancelIo IOCTL_ICA_STACK_CANCEL_IO
  696. *
  697. * cancel all current and future transport driver i/o
  698. *
  699. * NOTE: no more i/o can be done after StackCancelIo is called.
  700. * The transport driver must be unloaded and reloaded to
  701. * re-enable i/o.
  702. *
  703. *
  704. * ENTRY:
  705. * pTd (input)
  706. * Pointer to td data structure
  707. * pSdIoctl (input/output)
  708. * input - nothing
  709. * output - nothing
  710. *
  711. * EXIT:
  712. * STATUS_SUCCESS - no error
  713. *
  714. ******************************************************************************/
  715. NTSTATUS
  716. StackCancelIo( PTD pTd, PSD_IOCTL pSdIoctl )
  717. {
  718. PLIST_ENTRY Head, Next;
  719. NTSTATUS Status;
  720. TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackCancelIo (enter)\n" ));
  721. /*
  722. * Set stack closing flag
  723. */
  724. pTd->fClosing = TRUE;
  725. /*
  726. * Clear error thresholds now
  727. */
  728. pTd->ReadErrorThreshold = 0;
  729. pTd->WriteErrorThreshold = 0;
  730. /*
  731. * Call device specific cancel I/O routine
  732. */
  733. Status = DeviceCancelIo( pTd );
  734. ASSERT( Status == STATUS_SUCCESS );
  735. /*
  736. * Wait for all writes to complete
  737. */
  738. Status = TdSyncWrite( pTd, NULL );
  739. ASSERT( Status == STATUS_SUCCESS );
  740. TRACE(( pTd->pContext, TC_TD, TT_API1, "TD: StackCancelIo, %u (exit)\n", Status ));
  741. return( Status );
  742. }
  743. /*******************************************************************************
  744. *
  745. * StackSetBrokenReason IOCTL_ICA_STACK_SET_BROKENREASON
  746. *
  747. * Store a broken reason for later use (when reporting back up the stack)
  748. *
  749. * NOTE: Does not break the connection
  750. *
  751. *
  752. * ENTRY:
  753. * pTd (input)
  754. * Pointer to td data structure
  755. * pSdIoctl (input/output)
  756. * input - ICA_STACK_BROKENREASON
  757. * output - nothing
  758. *
  759. * EXIT:
  760. * STATUS_SUCCESS - no error
  761. *
  762. ******************************************************************************/
  763. NTSTATUS
  764. StackSetBrokenReason( PTD pTd, PSD_IOCTL pSdIoctl )
  765. {
  766. PICA_STACK_BROKENREASON pBrkReason;
  767. TRACE(( pTd->pContext, TC_TD, TT_API1,
  768. "TD: StackSetBrokenReason (enter)\n" ));
  769. if ( pSdIoctl->InputBufferLength < sizeof(ICA_STACK_BROKENREASON) ) {
  770. return( STATUS_BUFFER_TOO_SMALL );
  771. }
  772. pBrkReason = pSdIoctl->InputBuffer;
  773. pTd->UserBrokenReason = pBrkReason->BrokenReason;
  774. TRACE(( pTd->pContext, TC_TD, TT_API1,
  775. "TD: StackSetBrokenReason, %u (exit)\n", STATUS_SUCCESS ));
  776. return STATUS_SUCCESS;
  777. }
  778. /*******************************************************************************
  779. *
  780. * _TdCreateInputThread
  781. *
  782. * Start the input thread running.
  783. *
  784. *
  785. * ENTRY:
  786. * pTd (input)
  787. * Pointer to td data structure
  788. *
  789. * EXIT:
  790. * STATUS_SUCCESS - no error
  791. *
  792. ******************************************************************************/
  793. NTSTATUS
  794. _TdCreateInputThread( PTD pTd )
  795. {
  796. HANDLE hInputThread;
  797. NTSTATUS Status;
  798. /*
  799. * Create input thread
  800. */
  801. Status = IcaCreateThread( pTd->pContext,
  802. TdInputThread,
  803. pTd,
  804. ICALOCK_DRIVER,
  805. &hInputThread );
  806. if ( !NT_SUCCESS(Status) )
  807. return( Status );
  808. /*
  809. * Convert thread handle to pointer reference
  810. */
  811. Status = ObReferenceObjectByHandle( hInputThread,
  812. THREAD_ALL_ACCESS,
  813. NULL,
  814. KernelMode,
  815. &pTd->pInputThread,
  816. NULL );
  817. (VOID) ZwClose( hInputThread );
  818. if ( !NT_SUCCESS( Status ) ) {
  819. (VOID) StackCancelIo( pTd, NULL );
  820. }
  821. return( Status );
  822. }