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.

2472 lines
70 KiB

  1. /*************************************************************************
  2. * STACK.C
  3. *
  4. * Copyright (C) 1997-1999 Microsoft Corp.
  5. *************************************************************************/
  6. #include "precomp.h"
  7. #pragma hdrstop
  8. /*=============================================================================
  9. == Internal procedures defined
  10. =============================================================================*/
  11. NTSTATUS _IcaStackOpen( HANDLE hIca, HANDLE * phStack, ICA_OPEN_TYPE, PICA_TYPE_INFO );
  12. NTSTATUS _IcaStackIoControlWorker( PSTACK pStack, ULONG, PVOID, ULONG, PVOID, ULONG, PULONG );
  13. NTSTATUS _IcaPushStackAndCreateEndpoint( PSTACK pStack, PWINSTATIONNAME,
  14. PWINSTATIONCONFIG2, PICA_STACK_ADDRESS,
  15. PICA_STACK_ADDRESS );
  16. NTSTATUS _IcaPushStackAndOpenEndpoint( PSTACK pStack, PWINSTATIONNAME,
  17. PWINSTATIONCONFIG2, PVOID, ULONG );
  18. NTSTATUS _IcaPushStack( PSTACK pStack, PWINSTATIONNAME, PWINSTATIONCONFIG2 );
  19. NTSTATUS _IcaPushPd( PSTACK pStack, PWINSTATIONNAME, PWINSTATIONCONFIG2,
  20. PDLLNAME, PPDCONFIG );
  21. NTSTATUS _IcaPushWd( PSTACK pStack, PWINSTATIONNAME, PWINSTATIONCONFIG2 );
  22. VOID _IcaPopStack( PSTACK pStack );
  23. NTSTATUS _IcaPopSd( PSTACK pStack );
  24. NTSTATUS _IcaStackWaitForIca( PSTACK pStack, PWINSTATIONCONFIG2, BOOLEAN * );
  25. void _DecrementStackRef( IN PSTACK pStack );
  26. /*=============================================================================
  27. == Procedures used
  28. =============================================================================*/
  29. NTSTATUS IcaMemoryAllocate( ULONG, PVOID * );
  30. VOID IcaMemoryFree( PVOID );
  31. NTSTATUS _IcaOpen( PHANDLE hIca, PVOID, ULONG );
  32. NTSTATUS _CdOpen( PSTACK pStack, PWINSTATIONCONFIG2 );
  33. VOID _CdClose( PSTACK pStack );
  34. /****************************************************************************
  35. *
  36. * IcaStackOpen
  37. *
  38. * Open an ICA stack
  39. *
  40. * ENTRY:
  41. * hIca (input)
  42. * ICA instance handle
  43. * Class (input)
  44. * class (type) of stack
  45. * pStackIoControlCallback (input)
  46. * Pointer to StackIoControl callback procedure
  47. * pCallbackContext (input)
  48. * StackIoControl callback context value
  49. * ppContext (output)
  50. * Pointer to ICA stack context
  51. *
  52. * EXIT:
  53. * STATUS_SUCCESS - Success
  54. * other - Error return code
  55. *
  56. ****************************************************************************/
  57. NTSTATUS
  58. IcaStackOpen( IN HANDLE hIca,
  59. IN STACKCLASS Class,
  60. IN PROC pStackIoControlCallback,
  61. IN PVOID pCallbackContext,
  62. OUT HANDLE * ppContext )
  63. {
  64. ICA_TYPE_INFO TypeInfo;
  65. PSTACK pStack;
  66. NTSTATUS Status;
  67. /*
  68. * Allocate Memory for stack context data structure
  69. */
  70. Status = IcaMemoryAllocate( sizeof(STACK), &pStack );
  71. if ( !NT_SUCCESS(Status) )
  72. goto badalloc;
  73. /*
  74. * Zero STACK data structure
  75. */
  76. RtlZeroMemory( pStack, sizeof(STACK) );
  77. /*
  78. * Initialize critical section
  79. */
  80. INITLOCK( &pStack->CritSec, Status );
  81. if ( !NT_SUCCESS( Status ) )
  82. goto badcritsec;
  83. /*
  84. * Open stack handle to ica device driver
  85. */
  86. RtlZeroMemory( &TypeInfo, sizeof(TypeInfo) );
  87. TypeInfo.StackClass = Class;
  88. Status = _IcaStackOpen( hIca, &pStack->hStack, IcaOpen_Stack, &TypeInfo );
  89. if ( !NT_SUCCESS(Status) )
  90. goto badopen;
  91. /*
  92. * Save StackIoControl and Context callback values
  93. */
  94. pStack->pCallbackContext = pCallbackContext;
  95. pStack->pStackIoControlCallback = (PSTACKIOCONTROLCALLBACK)pStackIoControlCallback;
  96. *ppContext = pStack;
  97. TRACE(( hIca, TC_ICAAPI, TT_API1, "TSAPI: IcaStackOpen, type %u, success\n", Class ));
  98. return( STATUS_SUCCESS );
  99. /*=============================================================================
  100. == Error returns
  101. =============================================================================*/
  102. badopen:
  103. DELETELOCK( &pStack->CritSec );
  104. badcritsec:
  105. IcaMemoryFree( pStack );
  106. badalloc:
  107. TRACE(( hIca, TC_ICAAPI, TT_ERROR, "TSAPI: IcaStackOpen, type %u, 0x%x\n", Class, Status ));
  108. *ppContext = NULL;
  109. return( Status );
  110. }
  111. /****************************************************************************
  112. *
  113. * IcaStackClose
  114. *
  115. * Close an ICA stack
  116. *
  117. * ENTRY:
  118. * pContext (input)
  119. * pointer to ICA stack context
  120. *
  121. * EXIT:
  122. * STATUS_SUCCESS - Success
  123. * other - Error return code
  124. *
  125. ****************************************************************************/
  126. NTSTATUS
  127. IcaStackClose( IN HANDLE pContext )
  128. {
  129. NTSTATUS Status;
  130. PSTACK pStack;
  131. pStack = (PSTACK) pContext;
  132. /*
  133. * Lock critical section
  134. */
  135. LOCK( &pStack->CritSec );
  136. TRACESTACK(( pContext, TC_ICAAPI, TT_API1, "TSAPI: IcaStackClose\n" ));
  137. /*
  138. * Set closing flag
  139. */
  140. pStack->fClosing = TRUE;
  141. /*
  142. * Unload stack
  143. */
  144. _IcaPopStack( pContext );
  145. /*
  146. * Wait for reference count to go to zero before we continue
  147. */
  148. while ( pStack->RefCount > 0 ) {
  149. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaPopStack: waiting for refcount %d\n", pStack->RefCount ));
  150. pStack->hCloseEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  151. ASSERT( pStack->hCloseEvent );
  152. UNLOCK( &pStack->CritSec );
  153. (void) WaitForSingleObject( pStack->hCloseEvent, INFINITE );
  154. LOCK( &pStack->CritSec );
  155. CloseHandle( pStack->hCloseEvent );
  156. pStack->hCloseEvent = NULL;
  157. }
  158. /*
  159. * Close the ICA device driver stack instance
  160. */
  161. Status = NtClose( pStack->hStack );
  162. pStack->hStack = NULL;
  163. /*
  164. * Unlock critical section
  165. */
  166. UNLOCK( &pStack->CritSec );
  167. DELETELOCK( &pStack->CritSec );
  168. /*
  169. * Free stack context memory
  170. */
  171. IcaMemoryFree( pContext );
  172. ASSERT( NT_SUCCESS(Status) );
  173. return( Status );
  174. }
  175. /****************************************************************************
  176. *
  177. * IcaStackUnlock
  178. *
  179. * Unlocks an ICA stack
  180. *
  181. * ENTRY:
  182. * pContext (input)
  183. * pointer to ICA stack context
  184. *
  185. * EXIT:
  186. * STATUS_SUCCESS - Success
  187. * other - Error return code
  188. *
  189. ****************************************************************************/
  190. NTSTATUS
  191. IcaStackUnlock( IN HANDLE pContext )
  192. {
  193. NTSTATUS Status;
  194. PSTACK pStack;
  195. pStack = (PSTACK) pContext;
  196. /*
  197. * Lock critical section
  198. */
  199. UNLOCK( &pStack->CritSec );
  200. return( STATUS_SUCCESS );
  201. }
  202. /****************************************************************************
  203. *
  204. * IcaStackTerminate
  205. *
  206. * Prepare to close an ICA stack
  207. * (unloads all stack drivers and marks stack as being closed)
  208. *
  209. * ENTRY:
  210. * pContext (input)
  211. * pointer to ICA stack context
  212. *
  213. * EXIT:
  214. * STATUS_SUCCESS - Success
  215. * other - Error return code
  216. *
  217. ****************************************************************************/
  218. NTSTATUS
  219. IcaStackTerminate( IN HANDLE pContext )
  220. {
  221. PSTACK pStack;
  222. NTSTATUS Status = STATUS_SUCCESS;
  223. pStack = (PSTACK) pContext;
  224. /*
  225. * Lock critical section
  226. */
  227. LOCK( &pStack->CritSec );
  228. TRACESTACK(( pContext, TC_ICAAPI, TT_API1, "TSAPI: IcaStackTerminate\n" ));
  229. /*
  230. * Set closing flag
  231. */
  232. pStack->fClosing = TRUE;
  233. /*
  234. * Unload stack
  235. */
  236. _IcaPopStack( pContext );
  237. /*
  238. * Unlock critical section
  239. */
  240. UNLOCK( &pStack->CritSec );
  241. ASSERT( NT_SUCCESS(Status) );
  242. return( Status );
  243. }
  244. /****************************************************************************
  245. *
  246. * IcaStackConnectionWait
  247. *
  248. * Load template stack and wait for a connection
  249. *
  250. * NOTE: On an error the endpoint is closed and the stack is unloaded
  251. *
  252. *
  253. * ENTRY:
  254. * pContext (input)
  255. * pointer to ICA stack context
  256. * pWinStationName (input)
  257. * registry name of WinStation
  258. * pWinStationConfig (input)
  259. * pointer to WinStation registry configuration data
  260. * pAddress (input)
  261. * Pointer to optional local address to wait on (or null)
  262. * pEndpoint (output)
  263. * Pointer to buffer to return connection endpoint (optional)
  264. * BufferLength (input)
  265. * length of endpoint data buffer
  266. * pEndpointLength (output)
  267. * pointer to return actual length of endpoint
  268. *
  269. * EXIT:
  270. * STATUS_SUCCESS - Success
  271. * STATUS_BUFFER_TOO_SMALL - endpoint buffer is too small (use *pEndpointLength)
  272. * other - Error return code
  273. *
  274. ****************************************************************************/
  275. NTSTATUS
  276. IcaStackConnectionWait( IN HANDLE pContext,
  277. IN PWINSTATIONNAME pWinStationName,
  278. IN PWINSTATIONCONFIG2 pWinStationConfig,
  279. IN PICA_STACK_ADDRESS pAddress,
  280. OUT PVOID pEndpoint,
  281. IN ULONG BufferLength,
  282. OUT PULONG pEndpointLength )
  283. {
  284. NTSTATUS Status;
  285. PSTACK pStack;
  286. BOOLEAN fStackLoaded;
  287. pStack = (PSTACK) pContext;
  288. /*
  289. * Lock critical section
  290. */
  291. LOCK( &pStack->CritSec );
  292. /*
  293. * load template stack and create stack endpoint
  294. */
  295. if ( !(fStackLoaded = (BOOLEAN)pStack->fStackLoaded) ) {
  296. Status = _IcaPushStackAndCreateEndpoint( pStack,
  297. pWinStationName,
  298. pWinStationConfig,
  299. pAddress,
  300. NULL );
  301. if ( !NT_SUCCESS(Status) )
  302. goto badcreate;
  303. }
  304. /*
  305. * Now wait for a connection.
  306. */
  307. Status = _IcaStackIoControl( pStack,
  308. IOCTL_ICA_STACK_CONNECTION_WAIT,
  309. NULL,
  310. 0,
  311. pEndpoint,
  312. BufferLength,
  313. pEndpointLength );
  314. if ( !NT_SUCCESS(Status) )
  315. goto badwait;
  316. TRACESTACK(( pContext, TC_ICAAPI, TT_API1, "TSAPI: IcaStackConnectionWait, success\n" ));
  317. /*
  318. * Unlock critical section
  319. */
  320. UNLOCK( &pStack->CritSec );
  321. return( STATUS_SUCCESS );
  322. /*=============================================================================
  323. == Error returns
  324. =============================================================================*/
  325. /*
  326. * If the stack wasn't already loaded,
  327. * then pop all stack drivers now.
  328. */
  329. badwait:
  330. if ( !fStackLoaded ) {
  331. _IcaPopStack( pContext );
  332. }
  333. badcreate:
  334. *pEndpointLength = 0;
  335. memset( pEndpoint, 0, BufferLength );
  336. TRACESTACK(( pContext, TC_ICAAPI, TT_ERROR, "TSAPI: IcaStackConnectionWait, 0x%x\n", Status ));
  337. UNLOCK( &pStack->CritSec );
  338. return( Status );
  339. }
  340. /****************************************************************************
  341. *
  342. * IcaStackQueryLocalAddress
  343. *
  344. * Load template stack and query RDP-Enabled local IP Address
  345. *
  346. *
  347. *
  348. * ENTRY:
  349. * pContext (input)
  350. * pointer to ICA stack context
  351. * pWinStationName (input)
  352. * registry name of WinStation
  353. * pWinStationConfig (input)
  354. * pointer to WinStation registry configuration data
  355. * pAddress (input)
  356. * Pointer to optional local address to wait on (or null)
  357. * pLocalIPAddress (output)
  358. * Pointer to buffer to return RDP-Enabled Local IP Address
  359. * BufferLength (input)
  360. * length of input data buffer
  361. * pEndpointLength (output)
  362. * pointer to return actual length of LocaIPAddress
  363. *
  364. * EXIT:
  365. * STATUS_SUCCESS - Success
  366. * other - Error return code
  367. *
  368. ****************************************************************************/
  369. NTSTATUS
  370. IcaStackQueryLocalAddress( IN HANDLE pContext,
  371. IN PWINSTATIONNAME pWinStationName,
  372. IN PWINSTATIONCONFIG2 pWinStationConfig,
  373. IN PICA_STACK_ADDRESS pAddress,
  374. OUT PVOID pLocalIPAddress,
  375. IN ULONG BufferLength,
  376. OUT PULONG pLocalIPAddressLength )
  377. {
  378. NTSTATUS Status;
  379. PSTACK pStack;
  380. BOOLEAN fStackLoaded;
  381. pStack = (PSTACK) pContext;
  382. /*
  383. * Lock critical section
  384. */
  385. LOCK( &pStack->CritSec );
  386. /*
  387. * load template stack and create stack endpoint
  388. */
  389. if ( !(fStackLoaded = (BOOLEAN)pStack->fStackLoaded) ) {
  390. Status = _IcaPushStackAndCreateEndpoint( pStack,
  391. pWinStationName,
  392. pWinStationConfig,
  393. pAddress,
  394. NULL );
  395. if ( !NT_SUCCESS(Status) )
  396. goto badcreate;
  397. }
  398. Status = _IcaStackIoControl( pStack,
  399. IOCTL_ICA_STACK_QUERY_LOCALADDRESS,
  400. NULL,
  401. 0,
  402. pLocalIPAddress,
  403. BufferLength,
  404. pLocalIPAddressLength );
  405. if ( !NT_SUCCESS(Status) )
  406. goto badquery;
  407. TRACESTACK(( pContext, TC_ICAAPI, TT_API1, "TSAPI: IcaStackQueryLocalAddress, success\n" ));
  408. /*
  409. * Unlock critical section
  410. */
  411. UNLOCK( &pStack->CritSec );
  412. return( STATUS_SUCCESS );
  413. /*=============================================================================
  414. == Error returns
  415. =============================================================================*/
  416. /*
  417. * If the stack wasn't already loaded,
  418. * then pop all stack drivers now.
  419. */
  420. badquery:
  421. if ( !fStackLoaded ) {
  422. _IcaPopStack( pContext );
  423. }
  424. badcreate:
  425. *pLocalIPAddressLength = 0;
  426. memset( pLocalIPAddress, 0, BufferLength );
  427. TRACESTACK(( pContext, TC_ICAAPI, TT_ERROR, "TSAPI: IcaStackQueryLocalAddress, 0x%x\n", Status ));
  428. UNLOCK( &pStack->CritSec );
  429. return( Status );
  430. }
  431. /****************************************************************************
  432. *
  433. * IcaStackConnectionRequest
  434. *
  435. * Load query stack and try to make a connection with the client
  436. *
  437. * NOTE: On an error the endpoint is NOT closed and the stack is unloaded
  438. *
  439. *
  440. * ENTRY:
  441. * pContext (input)
  442. * pointer to ICA stack context
  443. * pWinStationConfig (input)
  444. * pointer to winstation registry configuration data
  445. * pAddress (input)
  446. * address to connect to (remote address)
  447. * pEndpoint (output)
  448. * Pointer to buffer to return connection endpoint (optional)
  449. * BufferLength (input)
  450. * length of endpoint data buffer
  451. * pEndpointLength (output)
  452. * pointer to return actual length of endpoint
  453. *
  454. *
  455. * EXIT:
  456. * STATUS_SUCCESS - Success
  457. * STATUS_BUFFER_TOO_SMALL - endpoint buffer is too small (use *pEndpointLength)
  458. * other - Error return code
  459. *
  460. ****************************************************************************/
  461. NTSTATUS
  462. IcaStackConnectionRequest( IN HANDLE pContext,
  463. IN PWINSTATIONNAME pWinStationName,
  464. IN PWINSTATIONCONFIG2 pWinStationConfig,
  465. IN PICA_STACK_ADDRESS pAddress,
  466. OUT PVOID pEndpoint,
  467. IN ULONG BufferLength,
  468. OUT PULONG pEndpointLength )
  469. {
  470. ULONG ReturnLength;
  471. NTSTATUS Status;
  472. PSTACK pStack;
  473. pStack = (PSTACK) pContext;
  474. /*
  475. * Lock critical section
  476. */
  477. LOCK( &pStack->CritSec );
  478. /*
  479. * Load template Stack
  480. */
  481. Status = _IcaPushStack( pContext, pWinStationName, pWinStationConfig );
  482. if ( !NT_SUCCESS(Status) )
  483. goto badpush;
  484. /*
  485. * Now initiate a connection to the specified address
  486. */
  487. Status = _IcaStackIoControl( pStack,
  488. IOCTL_ICA_STACK_CONNECTION_REQUEST,
  489. pAddress,
  490. sizeof(*pAddress),
  491. pEndpoint,
  492. BufferLength,
  493. pEndpointLength );
  494. if ( !NT_SUCCESS(Status) )
  495. goto badrequest;
  496. TRACESTACK(( pContext, TC_ICAAPI, TT_API1, "TSAPI: IcaStackConnectionRequest, success\n" ));
  497. /*
  498. * Unlock critical section
  499. */
  500. UNLOCK( &pStack->CritSec );
  501. return( STATUS_SUCCESS );
  502. /*=============================================================================
  503. == Error returns
  504. =============================================================================*/
  505. badrequest:
  506. /* pop all stack drivers */
  507. _IcaPopStack( pContext );
  508. badpush:
  509. *pEndpointLength = 0;
  510. memset( pEndpoint, 0, BufferLength );
  511. TRACESTACK(( pContext, TC_ICAAPI, TT_ERROR, "TSAPI: IcaStackConnectionRequest, 0x%x\n", Status ));
  512. UNLOCK( &pStack->CritSec );
  513. return( Status );
  514. }
  515. /****************************************************************************
  516. *
  517. * IcaStackConnectionAccept
  518. *
  519. * Load final stack and complete the connection
  520. *
  521. * ENTRY:
  522. *
  523. * pContext (input)
  524. * pointer to ICA stack context
  525. * - this can be different from the initially connecting stack
  526. * pWinStationName (input)
  527. * registry name of WinStation
  528. * pWinStationConfig (input)
  529. * pointer to winstation registry configuration data
  530. * pEndpoint (input)
  531. * pointer to endpoint data
  532. * EndpointLength (input)
  533. * Length of endpoint
  534. * pStackState (input) (optional)
  535. * Set if this Accept is for a re-connection
  536. * Points to ICA_STACK_STATE_HEADER buffer returned by IcaStackQueryState
  537. * BufferLength (input)
  538. * Length of pStackState buffer
  539. *
  540. * EXIT:
  541. * STATUS_SUCCESS - Success
  542. * other - Error return code
  543. *
  544. ****************************************************************************/
  545. NTSTATUS
  546. IcaStackConnectionAccept( IN HANDLE hIca,
  547. IN HANDLE pContext,
  548. IN PWINSTATIONNAME pWinStationName,
  549. IN PWINSTATIONCONFIG2 pWinStationConfig,
  550. IN PVOID pEndpoint,
  551. IN ULONG EndpointLength,
  552. IN PICA_STACK_STATE_HEADER pStackState,
  553. IN ULONG BufferLength,
  554. IN PICA_TRACE pTrace )
  555. {
  556. NTSTATUS Status;
  557. ULONG cbReturned;
  558. ICA_STACK_CONFIG IcaStackConfig;
  559. BOOLEAN fQueryAgain;
  560. BOOLEAN fStackModified;
  561. ULONG i;
  562. PSTACK pStack;
  563. pStack = (PSTACK) pContext;
  564. /*
  565. * Verify parameters
  566. */
  567. if ( pEndpoint == NULL )
  568. return( STATUS_INVALID_PARAMETER );
  569. /*
  570. * Lock critical section
  571. */
  572. LOCK( &pStack->CritSec );
  573. /*
  574. * Check if we need to load and open the template stack again
  575. */
  576. if ( !pStack->fStackLoaded ) {
  577. Status = _IcaPushStackAndOpenEndpoint( pContext,
  578. pWinStationName,
  579. pWinStationConfig,
  580. pEndpoint,
  581. EndpointLength );
  582. if ( !NT_SUCCESS(Status) ) {
  583. goto badaccept;
  584. }
  585. /*
  586. * Enable trace now that the WD is loaded
  587. */
  588. IcaIoControl( hIca,
  589. IOCTL_ICA_SET_TRACE,
  590. pTrace,
  591. sizeof ( ICA_TRACE ),
  592. NULL,
  593. 0,
  594. NULL );
  595. }
  596. /*
  597. * If this is a reconnect, then issue set stack state call
  598. * now that we have loaded the required PDs.
  599. */
  600. if ( pStackState ) {
  601. Status = _IcaStackIoControl( pStack,
  602. IOCTL_ICA_STACK_SET_STATE,
  603. pStackState,
  604. BufferLength,
  605. NULL,
  606. 0,
  607. NULL );
  608. if ( !NT_SUCCESS(Status) ) {
  609. goto badaccept;
  610. }
  611. /*
  612. * If this is not a re-connect of a previous session, then
  613. * prepare the stack for initial negotiation with the client.
  614. */
  615. } else {
  616. ICA_STACK_CONFIG_DATA ConfigData;
  617. memset(&ConfigData, 0, sizeof(ICA_STACK_CONFIG_DATA));
  618. ConfigData.colorDepth = pWinStationConfig->Config.User.ColorDepth;
  619. ConfigData.fDisableEncryption = pWinStationConfig->Config.User.fDisableEncryption;
  620. ConfigData.encryptionLevel = pWinStationConfig->Config.User.MinEncryptionLevel;
  621. ConfigData.fDisableAutoReconnect = pWinStationConfig->Config.User.fDisableAutoReconnect;
  622. /*
  623. * Send the config data to stack driver
  624. */
  625. _IcaStackIoControl( pStack,
  626. IOCTL_ICA_STACK_SET_CONFIG,
  627. &ConfigData,
  628. sizeof(ICA_STACK_CONFIG_DATA),
  629. NULL,
  630. 0,
  631. NULL);
  632. /*
  633. * Wait for ICA Detect string from client
  634. */
  635. Status = _IcaStackWaitForIca( pContext,
  636. pWinStationConfig,
  637. &fStackModified );
  638. if ( !NT_SUCCESS(Status) ) {
  639. goto badaccept;
  640. }
  641. /*
  642. * Check if the query stack is different than the template stack
  643. */
  644. if ( fStackModified ) {
  645. TRACESTACK(( pContext, TC_ICAAPI, TT_API1, "TSAPI: IcaStackConnectionAccept, load query stack\n"));
  646. ASSERT(FALSE);
  647. #ifdef notdef
  648. /*
  649. * Unload all stack drivers except the transport
  650. * and connection drivers
  651. * -- we can not pop the td or cd
  652. * -- we can not issue a cancel i/o
  653. */
  654. _IcaPopStack( pContext );
  655. /*
  656. * Load and open the new query stack
  657. */
  658. Status = _IcaPushStackAndOpenEndpoint( pContext,
  659. pWinStationName,
  660. pWinStationConfig,
  661. pEndpoint,
  662. EndpointLength );
  663. if ( !NT_SUCCESS(Status) ) {
  664. goto badaccept;
  665. }
  666. #endif
  667. }
  668. }
  669. /*
  670. * At this point the stack is now set up (again). The client is
  671. * now queried for any configuration changes.
  672. *
  673. * - repeat this loop until WD does not change
  674. */
  675. do {
  676. /*
  677. * Clear query again flag
  678. */
  679. fQueryAgain = FALSE;
  680. /*
  681. * Query the client for the optional PD's
  682. */
  683. Status = _IcaStackIoControl( pStack,
  684. IOCTL_ICA_STACK_CONNECTION_QUERY,
  685. NULL,
  686. 0,
  687. &IcaStackConfig,
  688. sizeof(IcaStackConfig),
  689. &cbReturned );
  690. if ( !NT_SUCCESS(Status) ) {
  691. TRACESTACK(( pContext, TC_ICAAPI, TT_ERROR, "TSAPI: IcaStackConnectionAccept: IOCTL_ICA_STACK_CONNECTION_QUERY, 0x%x\n", Status ));
  692. goto badaccept;
  693. }
  694. if ( cbReturned != sizeof(IcaStackConfig) ) {
  695. TRACESTACK(( pContext, TC_ICAAPI, TT_ERROR, "TSAPI: IcaStackConnectionAccept: Bad size %d from IOCTL_ICA_STACK_CONNECTION_QUERY\n", cbReturned ));
  696. Status = STATUS_INVALID_BUFFER_SIZE;
  697. goto badaccept;
  698. }
  699. TRACESTACK(( pContext, TC_ICAAPI, TT_API1, "TSAPI: IcaStackConnectionAccept: IOCTL_ICA_STACK_CONNECTION_QUERY success\n" ));
  700. /*
  701. * If the WD changed we must load it (and the rest of the stack) and
  702. * reissue the query.
  703. */
  704. if ( _wcsnicmp( IcaStackConfig.WdDLL,
  705. pWinStationConfig->Wd.WdDLL,
  706. DLLNAME_LENGTH ) ) {
  707. TRACESTACK(( pContext, TC_ICAAPI, TT_API1, "TSAPI: IcaStackConnectionAccept WD changing from %S to %S\n", pWinStationConfig->Wd.WdDLL, IcaStackConfig.WdDLL ));
  708. memcpy( pWinStationConfig->Wd.WdDLL,
  709. IcaStackConfig.WdDLL,
  710. sizeof( pWinStationConfig->Wd.WdDLL ) );
  711. fQueryAgain = TRUE;
  712. }
  713. /*
  714. * If no new modules were requested, we are done querying
  715. */
  716. if ( !fQueryAgain && (IcaStackConfig.SdClass[0] == SdNone) )
  717. break;
  718. /*
  719. * Pop the WD to load new PD's underneath.
  720. */
  721. Status = _IcaPopSd( pContext );
  722. if ( !NT_SUCCESS(Status) ) {
  723. goto badaccept;
  724. }
  725. /*
  726. * Push Optional PD's
  727. */
  728. for ( i=0; i < SdClass_Maximum; i++ ) {
  729. if ( IcaStackConfig.SdClass[i] == SdNone )
  730. break;
  731. Status = _IcaPushPd( pContext,
  732. pWinStationName,
  733. pWinStationConfig,
  734. IcaStackConfig.SdDLL[i],
  735. &pWinStationConfig->Pd[0] );
  736. /*
  737. * If the PD driver is not found, the client is using an optional
  738. * PD that is not supported by the host. Continue loading and let
  739. * the client and server negoatiate the connection.
  740. */
  741. if ( !NT_SUCCESS(Status) && (Status != STATUS_OBJECT_NAME_NOT_FOUND) ) {
  742. goto badaccept;
  743. }
  744. }
  745. /*
  746. * Re-push the WD
  747. */
  748. Status = _IcaPushWd( pContext, pWinStationName, pWinStationConfig );
  749. if ( !NT_SUCCESS(Status) ) {
  750. goto badaccept;
  751. }
  752. /*
  753. * Re-Enable trace now that the WD is loaded
  754. */
  755. IcaIoControl( hIca,
  756. IOCTL_ICA_SET_TRACE,
  757. pTrace,
  758. sizeof ( ICA_TRACE ),
  759. NULL,
  760. 0,
  761. NULL );
  762. } while ( fQueryAgain );
  763. /*
  764. * If this is a reconnect, then issue set stack state call
  765. * now that we have loaded the optional PDs.
  766. */
  767. if ( pStackState ) {
  768. Status = _IcaStackIoControl( pStack,
  769. IOCTL_ICA_STACK_SET_STATE,
  770. pStackState,
  771. BufferLength,
  772. NULL,
  773. 0,
  774. NULL );
  775. if ( !NT_SUCCESS(Status) ) {
  776. goto badaccept;
  777. }
  778. }
  779. /*
  780. * Send host module data to client
  781. */
  782. Status = _IcaStackIoControl( pStack,
  783. IOCTL_ICA_STACK_CONNECTION_SEND,
  784. NULL,
  785. 0,
  786. NULL,
  787. 0,
  788. NULL );
  789. if ( !NT_SUCCESS(Status) )
  790. goto badaccept;
  791. TRACESTACK(( pContext, TC_ICAAPI, TT_API1, "TSAPI: IcaStackConnectionAccept, success\n" ));
  792. /*
  793. * Leave the critical section locked because the protocol sequence has
  794. * not been finished. The sequence will be finished by the licensing core
  795. * in termsrv.exe, and the critical section will be unlocked at that point.
  796. */
  797. //UNLOCK( &pStack->CritSec );
  798. return( STATUS_SUCCESS );
  799. /*=============================================================================
  800. == Error returns
  801. =============================================================================*/
  802. badaccept:
  803. /* pop all stack drivers */
  804. _IcaPopStack( pContext );
  805. TRACESTACK(( pContext, TC_ICAAPI, TT_ERROR, "TSAPI: IcaStackConnectionAccept, 0x%x\n", Status ));
  806. UNLOCK( &pStack->CritSec );
  807. return( Status );
  808. }
  809. /****************************************************************************
  810. *
  811. * IcaStackQueryState
  812. *
  813. * Query stack driver state information
  814. *
  815. * ENTRY:
  816. * pContext (input)
  817. * pointer to ICA stack context
  818. * - this can be different from the initially connecting stack
  819. *
  820. * pStackState (output)
  821. * pointer to buffer to return stack state information
  822. *
  823. * BufferLength (input)
  824. * Length of pStackState buffer
  825. *
  826. * pStateLength (output)
  827. * length of returned stack state information
  828. *
  829. * EXIT:
  830. * STATUS_SUCCESS - Success
  831. * other - Error return code
  832. *
  833. ****************************************************************************/
  834. NTSTATUS
  835. IcaStackQueryState( IN HANDLE pContext,
  836. OUT PICA_STACK_STATE_HEADER pStackState,
  837. IN ULONG BufferLength,
  838. OUT PULONG pStateLength )
  839. {
  840. NTSTATUS Status;
  841. PSTACK pStack;
  842. pStack = (PSTACK) pContext;
  843. /*
  844. * Lock critical section
  845. */
  846. LOCK( &pStack->CritSec );
  847. /*
  848. * Query state
  849. */
  850. Status = _IcaStackIoControl( pContext,
  851. IOCTL_ICA_STACK_QUERY_STATE,
  852. NULL,
  853. 0,
  854. pStackState,
  855. BufferLength,
  856. pStateLength );
  857. TRACESTACK(( pContext, TC_ICAAPI, TT_API1, "TSAPI: IcaStackQueryState, 0x%x\n", Status ));
  858. /*
  859. * Unlock critical section
  860. */
  861. UNLOCK( &pStack->CritSec );
  862. return( Status );
  863. }
  864. /****************************************************************************
  865. *
  866. * IcaStackCreateShadowEndpoint
  867. *
  868. * Load template stack and create the endpoint
  869. *
  870. *
  871. * ENTRY:
  872. * pContext (input)
  873. * pointer to ICA stack context
  874. * pWinStationConfig (input)
  875. * pointer to winstation registry configuration data
  876. * pAddressIn (input)
  877. * Pointer to local address of endpoint to create
  878. * pAddressOut (output)
  879. * Pointer to location to return address of endpoint created
  880. *
  881. * EXIT:
  882. * STATUS_SUCCESS - Success
  883. * STATUS_BUFFER_TOO_SMALL - endpoint buffer is too small (use *pEndpointLength)
  884. * other - Error return code
  885. *
  886. ****************************************************************************/
  887. NTSTATUS
  888. IcaStackCreateShadowEndpoint( HANDLE pContext,
  889. PWINSTATIONNAME pWinStationName,
  890. PWINSTATIONCONFIG2 pWinStationConfig,
  891. PICA_STACK_ADDRESS pAddressIn,
  892. PICA_STACK_ADDRESS pAddressOut )
  893. {
  894. NTSTATUS Status;
  895. PSTACK pStack;
  896. pStack = (PSTACK) pContext;
  897. /*
  898. * Lock critical section
  899. */
  900. LOCK( &pStack->CritSec );
  901. /*
  902. * load template stack and create stack endpoint
  903. */
  904. if ( pStack->fStackLoaded ) {
  905. Status = STATUS_ADDRESS_ALREADY_ASSOCIATED;
  906. } else {
  907. Status = _IcaPushStackAndCreateEndpoint( pStack,
  908. pWinStationName,
  909. pWinStationConfig,
  910. pAddressIn,
  911. pAddressOut );
  912. }
  913. /*
  914. * Unlock critical section
  915. */
  916. UNLOCK( &pStack->CritSec );
  917. if ( !NT_SUCCESS( Status ) ) {
  918. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: IcaStackCreateShadowEndpoint, success\n" ));
  919. } else {
  920. TRACESTACK(( pStack, TC_ICAAPI, TT_ERROR, "TSAPI: IcaStackCreateShadowEndpoint, 0x%x\n", Status ));
  921. }
  922. return( Status );
  923. }
  924. /****************************************************************************
  925. *
  926. * IcaStackConnectionClose
  927. *
  928. * Close the connection endpoint
  929. *
  930. * This is the only way to close the connecting connection.
  931. *
  932. * ENTRY:
  933. * pContext (input)
  934. * pointer to ICA stack context
  935. * pWinStationConfig (input)
  936. * pointer to winstation registry configuration data
  937. * pEndpoint (input)
  938. * Structure defining connection endpoint
  939. * EndpointLength (input)
  940. * Length of endpoint
  941. *
  942. * EXIT:
  943. * STATUS_SUCCESS - Success
  944. * other - Error return code
  945. *
  946. ****************************************************************************/
  947. NTSTATUS
  948. IcaStackConnectionClose( IN HANDLE pContext,
  949. IN PWINSTATIONCONFIG2 pWinStationConfig,
  950. IN PVOID pEndpoint,
  951. IN ULONG EndpointLength
  952. )
  953. {
  954. ULONG cbReturned;
  955. NTSTATUS Status;
  956. PSTACK pStack;
  957. BOOLEAN fPopStack = FALSE;
  958. pStack = (PSTACK) pContext;
  959. /*
  960. * Lock critical section
  961. */
  962. LOCK( &pStack->CritSec );
  963. /*
  964. * If necessary, load the template stack
  965. * - we can't issue ioctls without a stack
  966. */
  967. if ( !pStack->fStackLoaded ) {
  968. /*
  969. * Load and open the template stack
  970. */
  971. Status = _IcaPushStackAndOpenEndpoint( pContext,
  972. TEXT(""),
  973. pWinStationConfig,
  974. pEndpoint,
  975. EndpointLength );
  976. if ( !NT_SUCCESS(Status) ) {
  977. goto badclose;
  978. }
  979. fPopStack = TRUE; // remember we have to pop the stack below
  980. }
  981. /*
  982. * Close endpoint
  983. */
  984. Status = _IcaStackIoControl( pStack,
  985. IOCTL_ICA_STACK_CLOSE_ENDPOINT,
  986. NULL,
  987. 0,
  988. NULL,
  989. 0,
  990. NULL );
  991. /*
  992. * Pop stack drivers if we loaded them above
  993. */
  994. if ( fPopStack )
  995. _IcaPopStack( pContext );
  996. badclose:
  997. TRACESTACK(( pContext, TC_ICAAPI, TT_API1, "TSAPI: IcaStackConnectionClose, 0x%x\n", Status ));
  998. UNLOCK( &pStack->CritSec );
  999. return( Status );
  1000. }
  1001. /****************************************************************************
  1002. *
  1003. * IcaStackCallback
  1004. *
  1005. * dial specified phone number and make connection to client
  1006. *
  1007. * NOTE: On an error the endpoint is NOT closed and the stack is unloaded
  1008. *
  1009. *
  1010. * ENTRY:
  1011. *
  1012. * pContext (input)
  1013. * pointer to ICA stack context
  1014. * pWinStationConfig (input)
  1015. * pointer to winstation registry configuration data
  1016. * pPhoneNumber (input)
  1017. * pointer to client phone number
  1018. * pEndpoint (output)
  1019. * Pointer to buffer to return connection endpoint
  1020. * BufferLength (input)
  1021. * length of endpoint data buffer
  1022. * pEndpointLength (output)
  1023. * pointer to return actual length of endpoint
  1024. *
  1025. *
  1026. * EXIT:
  1027. * STATUS_SUCCESS - Success
  1028. * STATUS_BUFFER_TOO_SMALL - endpoint buffer is too small (use *pEndpointLength)
  1029. * other - Error return code
  1030. *
  1031. ****************************************************************************/
  1032. NTSTATUS
  1033. IcaStackCallback( IN HANDLE pContext,
  1034. IN PWINSTATIONCONFIG2 pWinStationConfig,
  1035. IN WCHAR * pPhoneNumber,
  1036. OUT PVOID pEndpoint,
  1037. IN ULONG BufferLength,
  1038. OUT PULONG pEndpointLength )
  1039. {
  1040. NTSTATUS Status;
  1041. ICA_STACK_CALLBACK Cb;
  1042. PSTACK pStack;
  1043. pStack = (PSTACK) pContext;
  1044. /*
  1045. * Lock critical section
  1046. */
  1047. LOCK( &pStack->CritSec );
  1048. wcscpy( Cb.PhoneNumber, pPhoneNumber );
  1049. Status = _IcaStackIoControl( pContext,
  1050. IOCTL_ICA_STACK_CALLBACK_INITIATE,
  1051. &Cb,
  1052. sizeof(Cb),
  1053. pEndpoint,
  1054. BufferLength,
  1055. pEndpointLength );
  1056. TRACESTACK(( pContext, TC_ICAAPI, TT_API1,
  1057. "TSAPI: IcaStackCallback: %S, 0x%x\n",
  1058. pPhoneNumber, Status ));
  1059. UNLOCK( &pStack->CritSec );
  1060. return( Status );
  1061. }
  1062. /****************************************************************************
  1063. *
  1064. * IcaStackDisconnect
  1065. *
  1066. * Disconnect the specified stack from its ICA connection
  1067. *
  1068. *
  1069. * ENTRY:
  1070. *
  1071. * pContext (input)
  1072. * pointer to ICA stack context
  1073. * hIca (input)
  1074. * handle to temp ICA connection
  1075. * pCallbackContext (input)
  1076. * New StackIoControl callback context value
  1077. *
  1078. *
  1079. * EXIT:
  1080. * STATUS_SUCCESS - Success
  1081. * other - Error return code
  1082. *
  1083. ****************************************************************************/
  1084. NTSTATUS
  1085. IcaStackDisconnect(
  1086. HANDLE pContext,
  1087. HANDLE hIca,
  1088. PVOID pCallbackContext
  1089. )
  1090. {
  1091. PSTACK pStack;
  1092. ICA_STACK_RECONNECT IoctlReconnect;
  1093. NTSTATUS Status;
  1094. pStack = (PSTACK) pContext;
  1095. /*
  1096. * Lock critical section
  1097. */
  1098. LOCK( &pStack->CritSec );
  1099. IoctlReconnect.hIca = hIca;
  1100. Status = _IcaStackIoControl( pContext,
  1101. IOCTL_ICA_STACK_DISCONNECT,
  1102. &IoctlReconnect,
  1103. sizeof(IoctlReconnect),
  1104. NULL,
  1105. 0,
  1106. NULL );
  1107. if ( NT_SUCCESS( Status ) ) {
  1108. pStack->pCallbackContext = pCallbackContext;
  1109. }
  1110. UNLOCK( &pStack->CritSec );
  1111. return( Status );
  1112. }
  1113. /****************************************************************************
  1114. *
  1115. * IcaStackReconnect
  1116. *
  1117. * Reconnect the specified stack to a new ICA connection
  1118. *
  1119. *
  1120. * ENTRY:
  1121. *
  1122. * pContext (input)
  1123. * pointer to ICA stack context
  1124. * hIca (input)
  1125. * handle to temp ICA connection
  1126. * pCallbackContext (input)
  1127. * New StackIoControl callback context value
  1128. * sessionId (input)
  1129. * Session ID of the Winstation we are reconnecting to
  1130. *
  1131. *
  1132. * EXIT:
  1133. * STATUS_SUCCESS - Success
  1134. * other - Error return code
  1135. *
  1136. ****************************************************************************/
  1137. NTSTATUS
  1138. IcaStackReconnect(
  1139. HANDLE pContext,
  1140. HANDLE hIca,
  1141. PVOID pCallbackContext,
  1142. ULONG sessionId
  1143. )
  1144. {
  1145. PSTACK pStack;
  1146. ICA_STACK_RECONNECT IoctlReconnect;
  1147. PVOID SaveContext;
  1148. NTSTATUS Status;
  1149. pStack = (PSTACK) pContext;
  1150. /*
  1151. * Lock critical section
  1152. */
  1153. LOCK( &pStack->CritSec );
  1154. SaveContext = pStack->pCallbackContext;
  1155. pStack->pCallbackContext = pCallbackContext;
  1156. IoctlReconnect.hIca = hIca;
  1157. IoctlReconnect.sessionId = sessionId;
  1158. Status = _IcaStackIoControl( pContext,
  1159. IOCTL_ICA_STACK_RECONNECT,
  1160. &IoctlReconnect,
  1161. sizeof(IoctlReconnect),
  1162. NULL,
  1163. 0,
  1164. NULL );
  1165. if ( !NT_SUCCESS( Status ) ) {
  1166. pStack->pCallbackContext = SaveContext;
  1167. }
  1168. UNLOCK( &pStack->CritSec );
  1169. return( Status );
  1170. }
  1171. /*******************************************************************************
  1172. *
  1173. * IcaStackTrace
  1174. *
  1175. * Write a trace record to the winstation trace file
  1176. *
  1177. * ENTRY:
  1178. * pContext (input)
  1179. * pointer to ICA stack context
  1180. * TraceClass (input)
  1181. * trace class bit mask
  1182. * TraceEnable (input)
  1183. * trace type bit mask
  1184. * Format (input)
  1185. * format string
  1186. * ... (input)
  1187. * enough arguments to satisfy format string
  1188. *
  1189. * EXIT:
  1190. * nothing
  1191. *
  1192. ******************************************************************************/
  1193. VOID cdecl
  1194. IcaStackTrace( IN HANDLE pContext,
  1195. IN ULONG TraceClass,
  1196. IN ULONG TraceEnable,
  1197. IN char * Format,
  1198. IN ... )
  1199. {
  1200. ICA_TRACE_BUFFER Buffer;
  1201. va_list arg_marker;
  1202. ULONG Length;
  1203. PSTACK pStack;
  1204. pStack = (PSTACK) pContext;
  1205. va_start( arg_marker, Format );
  1206. Length = (ULONG) _vsnprintf( Buffer.Data, sizeof(Buffer.Data), Format, arg_marker ) + 1;
  1207. Buffer.TraceClass = TraceClass;
  1208. Buffer.TraceEnable = TraceEnable;
  1209. Buffer.DataLength = Length;
  1210. if (pStack->hStack != NULL) {
  1211. (void) IcaIoControl( pStack->hStack,
  1212. IOCTL_ICA_STACK_TRACE,
  1213. &Buffer,
  1214. sizeof(Buffer) - sizeof(Buffer.Data) + Length,
  1215. NULL,
  1216. 0,
  1217. NULL );
  1218. }
  1219. }
  1220. /****************************************************************************
  1221. *
  1222. * IcaStackIoControl
  1223. *
  1224. * Generic interface to an ICA stack (with locking)
  1225. *
  1226. * ENTRY:
  1227. * pContext (input)
  1228. * pointer to ICA stack context
  1229. * IoControlCode (input)
  1230. * I/O control code
  1231. * pInBuffer (input)
  1232. * Pointer to input parameters
  1233. * InBufferSize (input)
  1234. * Size of pInBuffer
  1235. * pOutBuffer (output)
  1236. * Pointer to output buffer
  1237. * OutBufferSize (input)
  1238. * Size of pOutBuffer
  1239. * pBytesReturned (output)
  1240. * Pointer to number of bytes returned
  1241. *
  1242. * EXIT:
  1243. * STATUS_SUCCESS - Success
  1244. * other - Error return code
  1245. *
  1246. ****************************************************************************/
  1247. NTSTATUS
  1248. IcaStackIoControl( IN HANDLE pContext,
  1249. IN ULONG IoControlCode,
  1250. IN PVOID pInBuffer,
  1251. IN ULONG InBufferSize,
  1252. OUT PVOID pOutBuffer,
  1253. IN ULONG OutBufferSize,
  1254. OUT PULONG pBytesReturned )
  1255. {
  1256. NTSTATUS Status;
  1257. PSTACK pStack;
  1258. pStack = (PSTACK) pContext;
  1259. /*
  1260. * Lock critical section
  1261. */
  1262. LOCK( &pStack->CritSec );
  1263. /*
  1264. * Call worker routine
  1265. */
  1266. Status = _IcaStackIoControlWorker( pContext,
  1267. IoControlCode,
  1268. pInBuffer,
  1269. InBufferSize,
  1270. pOutBuffer,
  1271. OutBufferSize,
  1272. pBytesReturned );
  1273. /*
  1274. * Unlock critical section
  1275. */
  1276. UNLOCK( &pStack->CritSec );
  1277. return( Status );
  1278. }
  1279. /****************************************************************************
  1280. *
  1281. * IcaPushConsoleStack
  1282. *
  1283. * Load initial stack
  1284. *
  1285. * stack push for each stack driver
  1286. * in order td - pd - wd
  1287. *
  1288. * ENTRY:
  1289. * pStack (input)
  1290. * pointer to ICA stack structure
  1291. * pWinStationName (input)
  1292. * registry name of WinStation
  1293. * pWinStationConfig (input)
  1294. * pointer to winstation registry configuration data
  1295. *
  1296. * EXIT:
  1297. * STATUS_SUCCESS - Success
  1298. * other - Error return code
  1299. *
  1300. ****************************************************************************/
  1301. NTSTATUS
  1302. IcaPushConsoleStack( IN HANDLE pContext,
  1303. IN PWINSTATIONNAME pWinStationName,
  1304. IN PWINSTATIONCONFIG2 pWinStationConfig,
  1305. IN PVOID pModuleData,
  1306. IN ULONG ModuleDataLength )
  1307. {
  1308. NTSTATUS Status;
  1309. PSTACK pStack;
  1310. ULONG cbReturned;
  1311. ULONG i;
  1312. pStack = (PSTACK) pContext;
  1313. LOCK( &pStack->CritSec );
  1314. /*
  1315. * build the stack
  1316. */
  1317. Status = _IcaPushStack( pStack,
  1318. pWinStationName,
  1319. pWinStationConfig);
  1320. if ( !NT_SUCCESS(Status) ) {
  1321. KdPrintEx((DPFLTR_TERMSRV_ID, DPFLTR_ERROR_LEVEL, "IcaPushConsoleStack _IcaPushStack failed\n"));
  1322. goto failure;
  1323. }
  1324. /*
  1325. * and now set up the connection to the console
  1326. */
  1327. Status = _IcaStackIoControl( pStack,
  1328. IOCTL_ICA_STACK_CONSOLE_CONNECT,
  1329. pModuleData,
  1330. ModuleDataLength,
  1331. NULL,
  1332. 0,
  1333. &cbReturned );
  1334. if ( !NT_SUCCESS(Status) )
  1335. {
  1336. KdPrintEx((DPFLTR_TERMSRV_ID, DPFLTR_ERROR_LEVEL, "IcaPushConsoleStack - stack wait failed\n"));
  1337. goto failure;
  1338. }
  1339. KdPrintEx((DPFLTR_TERMSRV_ID, DPFLTR_INFO_LEVEL, "IcaPushConsoleStack - done stack wait\n"));
  1340. failure:
  1341. UNLOCK( &pStack->CritSec );
  1342. return( Status );
  1343. }
  1344. /****************************************************************************
  1345. *
  1346. * _IcaStackOpen
  1347. *
  1348. * Open an ICA stack or an ICA channel
  1349. *
  1350. * ENTRY:
  1351. * hIca (input)
  1352. * ICA instance handle
  1353. *
  1354. * phStack (output)
  1355. * Pointer to ICA stack or channel handle
  1356. *
  1357. * OpenType (input)
  1358. * ICA open type
  1359. *
  1360. * pTypeInfo (input)
  1361. * Pointer to ICA type info
  1362. *
  1363. * EXIT:
  1364. * STATUS_SUCCESS - Success
  1365. * other - Error return code
  1366. *
  1367. ****************************************************************************/
  1368. NTSTATUS
  1369. _IcaStackOpen( HANDLE hIca,
  1370. HANDLE * phStack,
  1371. ICA_OPEN_TYPE OpenType,
  1372. PICA_TYPE_INFO pTypeInfo )
  1373. {
  1374. NTSTATUS Status;
  1375. PFILE_FULL_EA_INFORMATION pEa = NULL;
  1376. ICA_OPEN_PACKET UNALIGNED * pIcaOpenPacket;
  1377. ULONG cbEa = sizeof( FILE_FULL_EA_INFORMATION )
  1378. + ICA_OPEN_PACKET_NAME_LENGTH
  1379. + sizeof( ICA_OPEN_PACKET );
  1380. /*
  1381. * Allocate some memory for the EA buffer
  1382. */
  1383. Status = IcaMemoryAllocate( cbEa, &pEa );
  1384. if ( !NT_SUCCESS(Status) )
  1385. goto done;
  1386. /*
  1387. * Initialize the EA buffer
  1388. */
  1389. pEa->NextEntryOffset = 0;
  1390. pEa->Flags = 0;
  1391. pEa->EaNameLength = ICA_OPEN_PACKET_NAME_LENGTH;
  1392. memcpy( pEa->EaName, ICAOPENPACKET, ICA_OPEN_PACKET_NAME_LENGTH + 1 );
  1393. pEa->EaValueLength = sizeof( ICA_OPEN_PACKET );
  1394. pIcaOpenPacket = (ICA_OPEN_PACKET UNALIGNED *)(pEa->EaName +
  1395. pEa->EaNameLength + 1);
  1396. /*
  1397. * Now put the open packe parameters into the EA buffer
  1398. */
  1399. pIcaOpenPacket->IcaHandle = hIca;
  1400. pIcaOpenPacket->OpenType = OpenType;
  1401. pIcaOpenPacket->TypeInfo = *pTypeInfo;
  1402. Status = _IcaOpen( phStack, pEa, cbEa );
  1403. done:
  1404. if ( pEa ) {
  1405. IcaMemoryFree( pEa );
  1406. }
  1407. return( Status );
  1408. }
  1409. /****************************************************************************
  1410. *
  1411. * _IcaStackIoControl
  1412. *
  1413. * Local (ICAAPI) interface to an ICA stack through callback routine
  1414. *
  1415. * ENTRY:
  1416. * pStack (input)
  1417. * pointer to ICA stack structure
  1418. * IoControlCode (input)
  1419. * I/O control code
  1420. * pInBuffer (input)
  1421. * Pointer to input parameters
  1422. * InBufferSize (input)
  1423. * Size of pInBuffer
  1424. * pOutBuffer (output)
  1425. * Pointer to output buffer
  1426. * OutBufferSize (input)
  1427. * Size of pOutBuffer
  1428. * pBytesReturned (output)
  1429. * Pointer to number of bytes returned
  1430. *
  1431. * EXIT:
  1432. * STATUS_SUCCESS - Success
  1433. * other - Error return code
  1434. *
  1435. ****************************************************************************/
  1436. NTSTATUS
  1437. _IcaStackIoControl( IN HANDLE pContext,
  1438. IN ULONG IoControlCode,
  1439. IN PVOID pInBuffer,
  1440. IN ULONG InBufferSize,
  1441. OUT PVOID pOutBuffer,
  1442. IN ULONG OutBufferSize,
  1443. OUT PULONG pBytesReturned )
  1444. {
  1445. NTSTATUS Status;
  1446. PSTACK pStack;
  1447. pStack = (PSTACK) pContext;
  1448. /*
  1449. * Call callback function to handle StackIoControl
  1450. */
  1451. if ( pStack->pStackIoControlCallback ) {
  1452. /*
  1453. * Unlock critical section
  1454. */
  1455. pStack->RefCount++;
  1456. UNLOCK( &pStack->CritSec );
  1457. Status = pStack->pStackIoControlCallback(
  1458. pStack->pCallbackContext,
  1459. pStack,
  1460. IoControlCode,
  1461. pInBuffer,
  1462. InBufferSize,
  1463. pOutBuffer,
  1464. OutBufferSize,
  1465. pBytesReturned );
  1466. /*
  1467. * Re-lock critical section
  1468. */
  1469. LOCK( &pStack->CritSec );
  1470. _DecrementStackRef( pStack );
  1471. } else {
  1472. Status = _IcaStackIoControlWorker( pStack,
  1473. IoControlCode,
  1474. pInBuffer,
  1475. InBufferSize,
  1476. pOutBuffer,
  1477. OutBufferSize,
  1478. pBytesReturned );
  1479. }
  1480. return( Status );
  1481. }
  1482. /****************************************************************************
  1483. *
  1484. * _IcaStackIoControlWorker
  1485. *
  1486. * Private worker interface to an ICA stack
  1487. *
  1488. * ENTRY:
  1489. * pStack (input)
  1490. * pointer to ICA stack structure
  1491. * IoControlCode (input)
  1492. * I/O control code
  1493. * pInBuffer (input)
  1494. * Pointer to input parameters
  1495. * InBufferSize (input)
  1496. * Size of pInBuffer
  1497. * pOutBuffer (output)
  1498. * Pointer to output buffer
  1499. * OutBufferSize (input)
  1500. * Size of pOutBuffer
  1501. * pBytesReturned (output)
  1502. * Pointer to number of bytes returned
  1503. *
  1504. * EXIT:
  1505. * STATUS_SUCCESS - Success
  1506. * other - Error return code
  1507. *
  1508. ****************************************************************************/
  1509. NTSTATUS
  1510. _IcaStackIoControlWorker( IN PSTACK pStack,
  1511. IN ULONG IoControlCode,
  1512. IN PVOID pInBuffer,
  1513. IN ULONG InBufferSize,
  1514. OUT PVOID pOutBuffer,
  1515. IN ULONG OutBufferSize,
  1516. OUT PULONG pBytesReturned )
  1517. {
  1518. NTSTATUS Status;
  1519. if ( pStack->pCdIoControl ) {
  1520. /*
  1521. * Call connection driver, CD will call ICA device driver
  1522. */
  1523. Status = (*pStack->pCdIoControl)( pStack->pCdContext,
  1524. IoControlCode,
  1525. pInBuffer,
  1526. InBufferSize,
  1527. pOutBuffer,
  1528. OutBufferSize,
  1529. pBytesReturned );
  1530. if ( pStack->fClosing && (IoControlCode != IOCTL_ICA_STACK_POP) )
  1531. Status = STATUS_CTX_CLOSE_PENDING;
  1532. } else {
  1533. /*
  1534. * Unlock critical section
  1535. */
  1536. pStack->RefCount++;
  1537. UNLOCK( &pStack->CritSec );
  1538. /*
  1539. * Call ICA device driver directly
  1540. * - this stack does not have a connection driver
  1541. */
  1542. Status = IcaIoControl( pStack->hStack,
  1543. IoControlCode,
  1544. pInBuffer,
  1545. InBufferSize,
  1546. pOutBuffer,
  1547. OutBufferSize,
  1548. pBytesReturned );
  1549. /*
  1550. * Re-lock critical section
  1551. */
  1552. LOCK( &pStack->CritSec );
  1553. _DecrementStackRef( pStack );
  1554. }
  1555. return( Status );
  1556. }
  1557. /****************************************************************************
  1558. *
  1559. * _IcaPushStackAndCreateEndpoint
  1560. *
  1561. * Load and create stack endpoint
  1562. *
  1563. *
  1564. * ENTRY:
  1565. * pStack (input)
  1566. * pointer to ICA stack structure
  1567. * pWinStationName (input)
  1568. * registry name of WinStation
  1569. * pWinStationConfig (input)
  1570. * pointer to winstation registry configuration data
  1571. * pInAddress (input)
  1572. * pointer to address to use (optional)
  1573. * pOutAddress (output)
  1574. * pointer to location to return final address (optional)
  1575. *
  1576. *
  1577. * EXIT:
  1578. * STATUS_SUCCESS - Success
  1579. * other - Error return code
  1580. *
  1581. ****************************************************************************/
  1582. NTSTATUS
  1583. _IcaPushStackAndCreateEndpoint( IN PSTACK pStack,
  1584. IN PWINSTATIONNAME pWinStationName,
  1585. IN PWINSTATIONCONFIG2 pWinStationConfig,
  1586. IN PICA_STACK_ADDRESS pInAddress,
  1587. OUT PICA_STACK_ADDRESS pOutAddress )
  1588. {
  1589. ULONG BytesReturned;
  1590. NTSTATUS Status;
  1591. ASSERTLOCK( &pStack->CritSec );
  1592. /*
  1593. * Load template Stack
  1594. */
  1595. Status = _IcaPushStack( pStack, pWinStationName, pWinStationConfig );
  1596. if ( !NT_SUCCESS(Status) ) {
  1597. goto badpush;
  1598. }
  1599. /*
  1600. * Open the transport driver endpoint
  1601. */
  1602. Status = _IcaStackIoControl( pStack,
  1603. IOCTL_ICA_STACK_CREATE_ENDPOINT,
  1604. pInAddress,
  1605. pInAddress ? sizeof(*pInAddress) : 0,
  1606. pOutAddress,
  1607. pOutAddress ? sizeof(*pOutAddress) : 0,
  1608. &BytesReturned );
  1609. if ( !NT_SUCCESS(Status) ) {
  1610. goto badendpoint;
  1611. }
  1612. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaPushStackAndCreateEndpoint, success\n" ));
  1613. return( STATUS_SUCCESS );
  1614. /*=============================================================================
  1615. == Error returns
  1616. =============================================================================*/
  1617. badendpoint:
  1618. /* pop all stack drivers */
  1619. _IcaPopStack( pStack );
  1620. badpush:
  1621. TRACESTACK(( pStack, TC_ICAAPI, TT_ERROR, "TSAPI: _IcaPushStackAndCreateEndpoint, 0x%x\n", Status ));
  1622. return( Status );
  1623. }
  1624. /****************************************************************************
  1625. *
  1626. * _IcaPushStackAndOpenEndpoint
  1627. *
  1628. * Load and open stack endpoint
  1629. *
  1630. *
  1631. * ENTRY:
  1632. *
  1633. * pStack (input)
  1634. * pointer to ICA stack structure
  1635. * pWinStationName (input)
  1636. * registry name of WinStation
  1637. * pWinStationConfig (input)
  1638. * pointer to winstation registry configuration data
  1639. * pEndpoint (input)
  1640. * Structure defining connection endpoint
  1641. * EndpointLength (input)
  1642. * Length of endpoint
  1643. *
  1644. * EXIT:
  1645. * STATUS_SUCCESS - Success
  1646. * other - Error return code
  1647. *
  1648. ****************************************************************************/
  1649. NTSTATUS
  1650. _IcaPushStackAndOpenEndpoint( IN PSTACK pStack,
  1651. IN PWINSTATIONNAME pWinStationName,
  1652. IN PWINSTATIONCONFIG2 pWinStationConfig,
  1653. IN PVOID pEndpoint,
  1654. IN ULONG EndpointLength )
  1655. {
  1656. NTSTATUS Status;
  1657. ASSERTLOCK( &pStack->CritSec );
  1658. /*
  1659. * Load the template stack again
  1660. */
  1661. Status = _IcaPushStack( pStack, pWinStationName, pWinStationConfig );
  1662. if ( !NT_SUCCESS(Status) ) {
  1663. goto badpush;
  1664. }
  1665. /*
  1666. * Give open endpoint to the transport driver
  1667. */
  1668. Status = _IcaStackIoControl( pStack,
  1669. IOCTL_ICA_STACK_OPEN_ENDPOINT,
  1670. pEndpoint,
  1671. EndpointLength,
  1672. NULL,
  1673. 0,
  1674. NULL );
  1675. if ( !NT_SUCCESS(Status) ) {
  1676. goto badendpoint;
  1677. }
  1678. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaPushStackAndOpenEndpoint, success\n" ));
  1679. return( STATUS_SUCCESS );
  1680. /*=============================================================================
  1681. == Error returns
  1682. =============================================================================*/
  1683. badendpoint:
  1684. /* pop all stack drivers */
  1685. _IcaPopStack( pStack );
  1686. badpush:
  1687. TRACESTACK(( pStack, TC_ICAAPI, TT_ERROR, "TSAPI: _IcaPushStackAndOpenEndpoint, 0x%x\n", Status ));
  1688. return( Status );
  1689. }
  1690. /****************************************************************************
  1691. *
  1692. * _IcaPushStack
  1693. *
  1694. * Load initial stack
  1695. *
  1696. * stack push for each stack driver
  1697. * in order td - pd - wd
  1698. *
  1699. * ENTRY:
  1700. * pStack (input)
  1701. * pointer to ICA stack structure
  1702. * pWinStationName (input)
  1703. * registry name of WinStation
  1704. * pWinStationConfig (input)
  1705. * pointer to winstation registry configuration data
  1706. *
  1707. * EXIT:
  1708. * STATUS_SUCCESS - Success
  1709. * other - Error return code
  1710. *
  1711. ****************************************************************************/
  1712. NTSTATUS
  1713. _IcaPushStack( IN PSTACK pStack,
  1714. IN PWINSTATIONNAME pWinStationName,
  1715. IN PWINSTATIONCONFIG2 pWinStationConfig )
  1716. {
  1717. PPDCONFIG pPdConfig;
  1718. NTSTATUS Status;
  1719. ULONG i;
  1720. ASSERTLOCK( &pStack->CritSec );
  1721. /*
  1722. * Load and open connection driver
  1723. */
  1724. Status = _CdOpen( pStack, pWinStationConfig );
  1725. if ( !NT_SUCCESS(Status) )
  1726. goto badcdopen;
  1727. /*
  1728. * Load PD(s)
  1729. */
  1730. pPdConfig = &pWinStationConfig->Pd[0];
  1731. for ( i = 0; i < MAX_PDCONFIG; i++, pPdConfig++ ) {
  1732. if ( pPdConfig->Create.SdClass == SdNone )
  1733. break;
  1734. /*
  1735. * Do the push.
  1736. */
  1737. Status = _IcaPushPd( pStack,
  1738. pWinStationName,
  1739. pWinStationConfig,
  1740. pPdConfig->Create.PdDLL,
  1741. pPdConfig );
  1742. if ( !NT_SUCCESS( Status ) ) {
  1743. goto badpdpush;
  1744. }
  1745. if ( pStack->fClosing ) {
  1746. goto stackclosing;
  1747. }
  1748. }
  1749. /*
  1750. * Push the WD.
  1751. */
  1752. Status = _IcaPushWd( pStack, pWinStationName, pWinStationConfig );
  1753. if ( !NT_SUCCESS(Status) )
  1754. goto badwdpush;
  1755. if ( pStack->fClosing ) {
  1756. goto stackclosing;
  1757. }
  1758. /*
  1759. * Set stack loaded flag
  1760. */
  1761. pStack->fStackLoaded = TRUE;
  1762. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaPushStack, success\n" ));
  1763. return( STATUS_SUCCESS );
  1764. /*=============================================================================
  1765. == Error returns
  1766. =============================================================================*/
  1767. badwdpush:
  1768. badpdpush:
  1769. /* pop all stack drivers */
  1770. _IcaPopStack( pStack );
  1771. badcdopen:
  1772. TRACESTACK(( pStack, TC_ICAAPI, TT_ERROR, "TSAPI: _IcaPushStack, 0x%x\n", Status ));
  1773. return( Status );
  1774. stackclosing:
  1775. /*
  1776. * Unload all stack drivers
  1777. */
  1778. while ( _IcaPopSd( pStack ) == STATUS_SUCCESS ) {;}
  1779. return( STATUS_CTX_CLOSE_PENDING );
  1780. }
  1781. /****************************************************************************
  1782. *
  1783. * _IcaPushPd
  1784. *
  1785. * Push a PD module.
  1786. *
  1787. * ENTRY:
  1788. * pStack (input)
  1789. * pointer to ICA stack structure
  1790. * pWinStationName (input)
  1791. * registry name of WinStation
  1792. * pWinStationConfig (input)
  1793. * pointer to winstation registry configuration data
  1794. * pDllName (input)
  1795. * Name of module to push
  1796. * pPdConfig (input)
  1797. * pointer to configuration data
  1798. *
  1799. * EXIT:
  1800. * STATUS_SUCCESS - Success
  1801. * other - Error return code
  1802. *
  1803. ****************************************************************************/
  1804. NTSTATUS
  1805. _IcaPushPd( IN PSTACK pStack,
  1806. IN PWINSTATIONNAME pWinStationName,
  1807. IN PWINSTATIONCONFIG2 pWinStationConfig,
  1808. IN PDLLNAME pDllName,
  1809. IN PPDCONFIG pPdConfig )
  1810. {
  1811. ICA_STACK_PUSH IcaStackPush;
  1812. NTSTATUS Status;
  1813. ASSERTLOCK( &pStack->CritSec );
  1814. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaPushPd, %S\n", pDllName ));
  1815. memset( &IcaStackPush, 0, sizeof(IcaStackPush) );
  1816. IcaStackPush.StackModuleType = Stack_Module_Pd;
  1817. ASSERT( pDllName[0] );
  1818. memcpy( IcaStackPush.StackModuleName, pDllName,
  1819. sizeof( IcaStackPush.StackModuleName ) );
  1820. #ifndef _HYDRA_
  1821. // wcscat( IcaStackPush.StackModuleName, ICA_SD_MODULE_EXTENTION );
  1822. #endif
  1823. memcpy( IcaStackPush.OEMId,
  1824. pWinStationConfig->Config.OEMId,
  1825. sizeof(pWinStationConfig->Config.OEMId) );
  1826. IcaStackPush.WdConfig = pWinStationConfig->Wd;
  1827. IcaStackPush.PdConfig = *pPdConfig;
  1828. memcpy( IcaStackPush.WinStationRegName,
  1829. pWinStationName,
  1830. sizeof(IcaStackPush.WinStationRegName) );
  1831. Status = _IcaStackIoControl( pStack,
  1832. IOCTL_ICA_STACK_PUSH,
  1833. &IcaStackPush,
  1834. sizeof( IcaStackPush ),
  1835. NULL,
  1836. 0,
  1837. NULL );
  1838. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaPushPd, %S, 0x%x\n", pDllName, Status ));
  1839. return( Status );
  1840. }
  1841. /****************************************************************************
  1842. *
  1843. * _IcaPushWd
  1844. *
  1845. * Push a WD module.
  1846. *
  1847. * ENTRY:
  1848. * pStack (input)
  1849. * pointer to ICA stack structure
  1850. * pWinStationName (input)
  1851. * registry name of WinStation
  1852. * pWinStationConfig (input)
  1853. * pointer to winstation registry configuration data
  1854. *
  1855. * EXIT:
  1856. * STATUS_SUCCESS - Success
  1857. * other - Error return code
  1858. *
  1859. ****************************************************************************/
  1860. NTSTATUS
  1861. _IcaPushWd( IN PSTACK pStack,
  1862. IN PWINSTATIONNAME pWinStationName,
  1863. IN PWINSTATIONCONFIG2 pWinStationConfig )
  1864. {
  1865. ICA_STACK_PUSH IcaStackPush;
  1866. NTSTATUS Status;
  1867. ASSERTLOCK( &pStack->CritSec );
  1868. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaPushWd, %S\n", pWinStationConfig->Wd.WdDLL ));
  1869. memset( &IcaStackPush, 0, sizeof(IcaStackPush) );
  1870. IcaStackPush.StackModuleType = Stack_Module_Wd;
  1871. memcpy( IcaStackPush.StackModuleName, pWinStationConfig->Wd.WdDLL,
  1872. sizeof( IcaStackPush.StackModuleName ) );
  1873. #ifndef _HYDRA_
  1874. //wcscat( IcaStackPush.StackModuleName, ICA_SD_MODULE_EXTENTION );
  1875. #endif
  1876. memcpy( IcaStackPush.OEMId,
  1877. pWinStationConfig->Config.OEMId,
  1878. sizeof(pWinStationConfig->Config.OEMId) );
  1879. IcaStackPush.WdConfig = pWinStationConfig->Wd;
  1880. IcaStackPush.PdConfig = pWinStationConfig->Pd[0];
  1881. memcpy( IcaStackPush.WinStationRegName,
  1882. pWinStationName,
  1883. sizeof(IcaStackPush.WinStationRegName) );
  1884. Status = _IcaStackIoControl( pStack,
  1885. IOCTL_ICA_STACK_PUSH,
  1886. &IcaStackPush,
  1887. sizeof( IcaStackPush ),
  1888. NULL,
  1889. 0,
  1890. NULL );
  1891. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaPushWd, %S, 0x%x\n", pWinStationConfig->Wd.WdDLL, Status ));
  1892. return( Status );
  1893. }
  1894. /****************************************************************************
  1895. *
  1896. * _IcaPopStack
  1897. *
  1898. * Pop all the stack drivers
  1899. *
  1900. * ENTRY:
  1901. * pStack (input)
  1902. * pointer to ICA stack structure
  1903. *
  1904. * EXIT:
  1905. * nothing
  1906. *
  1907. ****************************************************************************/
  1908. void
  1909. _IcaPopStack( IN PSTACK pStack )
  1910. {
  1911. ASSERTLOCK( &pStack->CritSec );
  1912. /*
  1913. * If another thread is doing the unload, then nothing else to do.
  1914. */
  1915. if ( pStack->fUnloading )
  1916. return;
  1917. pStack->fUnloading = TRUE;
  1918. /*
  1919. * Unload all stack drivers
  1920. */
  1921. while ( _IcaPopSd( pStack ) == STATUS_SUCCESS ) {
  1922. ;
  1923. }
  1924. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaPopStack all stack drivers unloaded\n" ));
  1925. /*
  1926. * Release CD threads
  1927. */
  1928. (void) _IcaStackIoControl( pStack,
  1929. IOCTL_ICA_STACK_CD_CANCEL_IO,
  1930. NULL, 0, NULL, 0, NULL );
  1931. /*
  1932. * Wait for all other references (besides our own) to go away
  1933. */
  1934. pStack->RefCount++;
  1935. waitagain:
  1936. while ( pStack->RefCount > 1 ) {
  1937. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaPopStack: waiting for refcount %d\n", pStack->RefCount ));
  1938. pStack->hUnloadEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
  1939. ASSERT( pStack->hUnloadEvent );
  1940. UNLOCK( &pStack->CritSec );
  1941. (void) WaitForSingleObject( pStack->hUnloadEvent, INFINITE );
  1942. LOCK( &pStack->CritSec );
  1943. // NOTE: seems to me that between being notified and locking the
  1944. // stack, some other thread could have locked the stack and bumped
  1945. // the ref count. no breaks have ever been hit, though.
  1946. if (pStack->RefCount > 1) {
  1947. goto waitagain;
  1948. }
  1949. CloseHandle( pStack->hUnloadEvent );
  1950. pStack->hUnloadEvent = NULL;
  1951. }
  1952. _DecrementStackRef( pStack );
  1953. /*
  1954. * Unload connection driver
  1955. */
  1956. _CdClose( pStack );
  1957. /*
  1958. * Clear stack loaded flag
  1959. */
  1960. pStack->fStackLoaded = FALSE;
  1961. pStack->fUnloading = FALSE;
  1962. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaPopStack\n" ));
  1963. }
  1964. /****************************************************************************
  1965. *
  1966. * _IcaPopSd
  1967. *
  1968. * Pop a stack driver module (wd or pd)
  1969. *
  1970. * ENTRY:
  1971. * pStack (input)
  1972. * pointer to ICA stack structure
  1973. *
  1974. * EXIT:
  1975. * STATUS_SUCCESS - Success
  1976. * other - Error return code
  1977. *
  1978. ****************************************************************************/
  1979. NTSTATUS
  1980. _IcaPopSd( IN PSTACK pStack )
  1981. {
  1982. NTSTATUS Status;
  1983. ASSERTLOCK( &pStack->CritSec );
  1984. Status = _IcaStackIoControl( pStack,
  1985. IOCTL_ICA_STACK_POP,
  1986. NULL,
  1987. 0,
  1988. NULL,
  1989. 0,
  1990. NULL );
  1991. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaPopSd, 0x%x\n", Status ));
  1992. return( Status );
  1993. }
  1994. /****************************************************************************
  1995. *
  1996. * _IcaStackWaitForIca
  1997. *
  1998. * Wait for ICA Detect string
  1999. *
  2000. * ENTRY:
  2001. * pStack (input)
  2002. * pointer to ICA stack structure
  2003. * pWinStationConfig (input/output)
  2004. * pointer to winstation registry configuration data
  2005. * pfStackModified (output)
  2006. * Pointer to stack modified flag
  2007. *
  2008. * EXIT:
  2009. * STATUS_SUCCESS - Success
  2010. * other - Error return code
  2011. *
  2012. ****************************************************************************/
  2013. NTSTATUS
  2014. _IcaStackWaitForIca( IN PSTACK pStack,
  2015. IN OUT PWINSTATIONCONFIG2 pWinStationConfig,
  2016. OUT BOOLEAN * pfStackModified )
  2017. {
  2018. ICA_STACK_CONFIG IcaStackConfig;
  2019. PPDCONFIG pPdConfig;
  2020. NTSTATUS Status;
  2021. ULONG cbReturned;
  2022. ULONG i;
  2023. ASSERTLOCK( &pStack->CritSec );
  2024. /*
  2025. * Initialize flag
  2026. */
  2027. *pfStackModified = FALSE;
  2028. /*
  2029. * Wait for ICA Detect string from client
  2030. */
  2031. Status = _IcaStackIoControl( pStack,
  2032. IOCTL_ICA_STACK_WAIT_FOR_ICA,
  2033. NULL,
  2034. 0,
  2035. &IcaStackConfig,
  2036. sizeof(IcaStackConfig),
  2037. &cbReturned );
  2038. if ( !NT_SUCCESS(Status) ) {
  2039. goto baddetect;
  2040. }
  2041. /*
  2042. * If ICA Detect returned any stack information, then update it
  2043. */
  2044. if ( cbReturned > 0 ) {
  2045. ASSERT( FALSE );
  2046. #ifdef notdef
  2047. /*
  2048. * this path has not been tested
  2049. *
  2050. * Return configuration data
  2051. * -- skip transport driver (index 0)
  2052. */
  2053. for ( i = 0; i < (MAX_PDCONFIG-1); i++ ) {
  2054. pPdConfig = &pWinStationConfig->Pd[i+1];
  2055. memset( pPdConfig, 0, sizeof(PDCONFIG) );
  2056. if ( IcaStackConfig.SdClass[i] == SdNone )
  2057. break;
  2058. pPdConfig->Create.SdClass = IcaStackConfig.SdClass[i];
  2059. memcpy( pPdConfig->Create.PdDLL, IcaStackConfig.SdDLL[i], sizeof(DLLNAME) );
  2060. }
  2061. if ( IcaStackConfig.WdDLL[0] )
  2062. memcpy( pWinStationConfig->Wd.WdDLL, IcaStackConfig.WdDLL, sizeof(DLLNAME) );
  2063. /*
  2064. * Set modify flag
  2065. */
  2066. *pfStackModified = TRUE;
  2067. #endif
  2068. }
  2069. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _IcaWaitForIca, success\n" ));
  2070. return( STATUS_SUCCESS );
  2071. /*=============================================================================
  2072. == Error returns
  2073. =============================================================================*/
  2074. baddetect:
  2075. TRACESTACK(( pStack, TC_ICAAPI, TT_ERROR, "TSAPI: _IcaWaitForIca, 0x%x\n", Status ));
  2076. return( Status );
  2077. }
  2078. /****************************************************************************
  2079. *
  2080. * _DecrementStackRef
  2081. *
  2082. * decrement stack reference
  2083. *
  2084. * ENTRY:
  2085. * pStack (input)
  2086. * pointer to ICA stack structure
  2087. *
  2088. * EXIT:
  2089. * nothing
  2090. *
  2091. ****************************************************************************/
  2092. void
  2093. _DecrementStackRef( IN PSTACK pStack )
  2094. {
  2095. pStack->RefCount--;
  2096. if ( pStack->RefCount == 1 && pStack->hUnloadEvent ) {
  2097. SetEvent( pStack->hUnloadEvent );
  2098. } else if ( pStack->RefCount == 0 && pStack->hCloseEvent ) {
  2099. SetEvent( pStack->hCloseEvent );
  2100. }
  2101. }