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.

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