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.

485 lines
11 KiB

  1. /*************************************************************************
  2. * CD.C
  3. *
  4. * Copyright 1996, Citrix Systems Inc.
  5. * Copyright (C) 1997-1999 Microsoft Corp.
  6. *
  7. * Author: Marc Bloomfield
  8. * Terry Treder
  9. * Brad Pedersen
  10. *************************************************************************/
  11. #include "precomp.h"
  12. #pragma hdrstop
  13. /*=============================================================================
  14. == External procedures defined
  15. =============================================================================*/
  16. NTSTATUS IcaCdIoControl( HANDLE pContext, ULONG, PVOID, ULONG, PVOID, ULONG, PULONG );
  17. NTSTATUS IcaCdWaitForSingleObject( HANDLE pContext, HANDLE, LONG );
  18. NTSTATUS IcaCdWaitForMultipleObjects( HANDLE pContext, ULONG, HANDLE *, BOOL, LONG );
  19. HANDLE IcaCdCreateThread( HANDLE pContext, PVOID, PVOID, PULONG );
  20. /*=============================================================================
  21. == Internal procedures defined
  22. =============================================================================*/
  23. NTSTATUS _CdOpen( PSTACK pStack, PWINSTATIONCONFIG2 );
  24. VOID _CdClose( PSTACK pStack );
  25. /*=============================================================================
  26. == Procedures used
  27. =============================================================================*/
  28. void _DecrementStackRef( IN PSTACK pStack );
  29. /****************************************************************************
  30. *
  31. * IcaCdIoControl
  32. *
  33. * Generic interface to an ICA stack (for use by Connection Driver)
  34. *
  35. * ENTRY:
  36. * pContext (input)
  37. * pointer to ICA stack context
  38. * IoControlCode (input)
  39. * I/O control code
  40. * pInBuffer (input)
  41. * Pointer to input parameters
  42. * InBufferSize (input)
  43. * Size of pInBuffer
  44. * pOutBuffer (output)
  45. * Pointer to output buffer
  46. * OutBufferSize (input)
  47. * Size of pOutBuffer
  48. * pBytesReturned (output)
  49. * Pointer to number of bytes returned
  50. *
  51. * EXIT:
  52. * STATUS_SUCCESS - Success
  53. * other - Error return code
  54. *
  55. ****************************************************************************/
  56. NTSTATUS
  57. IcaCdIoControl( IN HANDLE pContext,
  58. IN ULONG IoControlCode,
  59. IN PVOID pInBuffer,
  60. IN ULONG InBufferSize,
  61. OUT PVOID pOutBuffer,
  62. IN ULONG OutBufferSize,
  63. OUT PULONG pBytesReturned )
  64. {
  65. NTSTATUS Status;
  66. PSTACK pStack;
  67. pStack = (PSTACK) pContext;
  68. ASSERTLOCK( &pStack->CritSec );
  69. /*
  70. * Unlock critical section
  71. */
  72. pStack->RefCount++;
  73. UNLOCK( &pStack->CritSec );
  74. /*
  75. * Call ICA Device driver
  76. */
  77. Status = IcaIoControl( pStack->hStack,
  78. IoControlCode,
  79. pInBuffer,
  80. InBufferSize,
  81. pOutBuffer,
  82. OutBufferSize,
  83. pBytesReturned );
  84. /*
  85. * Re-lock critical section
  86. */
  87. LOCK( &pStack->CritSec );
  88. _DecrementStackRef( pStack );
  89. if ( pStack->fClosing && (IoControlCode != IOCTL_ICA_STACK_POP) )
  90. Status = STATUS_CTX_CLOSE_PENDING;
  91. return( Status );
  92. }
  93. /****************************************************************************
  94. *
  95. * IcaCdWaitForSingleObject
  96. *
  97. * Wait for handle to be signaled
  98. *
  99. * ENTRY:
  100. * pContext (input)
  101. * pointer to ICA stack context
  102. * hHandle (input)
  103. * handle to wait on
  104. * Timeout (input)
  105. * timeout in milliseconds
  106. *
  107. * EXIT:
  108. * STATUS_SUCCESS - Success
  109. * other - Error return code
  110. *
  111. ****************************************************************************/
  112. NTSTATUS
  113. IcaCdWaitForSingleObject( HANDLE pContext,
  114. HANDLE hHandle,
  115. LONG Timeout )
  116. {
  117. NTSTATUS Status;
  118. PSTACK pStack;
  119. pStack = (PSTACK) pContext;
  120. ASSERTLOCK( &pStack->CritSec );
  121. /*
  122. * Unlock critical section
  123. */
  124. pStack->RefCount++;
  125. UNLOCK( &pStack->CritSec );
  126. /*
  127. * Call ICA Device driver
  128. */
  129. Status = WaitForSingleObject( hHandle, Timeout );
  130. /*
  131. * Re-lock critical section
  132. */
  133. LOCK( &pStack->CritSec );
  134. _DecrementStackRef( pStack );
  135. if ( pStack->fClosing )
  136. Status = STATUS_CTX_CLOSE_PENDING;
  137. return( Status );
  138. }
  139. /****************************************************************************
  140. *
  141. * IcaCdWaitForMultipleObjects
  142. *
  143. * Wait for one or more handles to be signaled
  144. *
  145. * ENTRY:
  146. * pContext (input)
  147. * pointer to ICA stack context
  148. * Count (input)
  149. * count of handles
  150. * phHandle (input)
  151. * pointer to array of handles
  152. * bWaitAll (input)
  153. * wait for all flag
  154. * Timeout (input)
  155. * timeout in milliseconds
  156. *
  157. * EXIT:
  158. * STATUS_SUCCESS - Success
  159. * other - Error return code
  160. *
  161. ****************************************************************************/
  162. NTSTATUS
  163. IcaCdWaitForMultipleObjects( HANDLE pContext,
  164. ULONG Count,
  165. HANDLE * phHandle,
  166. BOOL bWaitAll,
  167. LONG Timeout )
  168. {
  169. NTSTATUS Status;
  170. PSTACK pStack;
  171. pStack = (PSTACK) pContext;
  172. ASSERTLOCK( &pStack->CritSec );
  173. /*
  174. * Unlock critical section
  175. */
  176. pStack->RefCount++;
  177. UNLOCK( &pStack->CritSec );
  178. /*
  179. * Call ICA Device driver
  180. */
  181. Status = WaitForMultipleObjects( Count, phHandle, bWaitAll, Timeout );
  182. /*
  183. * Re-lock critical section
  184. */
  185. LOCK( &pStack->CritSec );
  186. _DecrementStackRef( pStack );
  187. if ( pStack->fClosing )
  188. Status = STATUS_CTX_CLOSE_PENDING;
  189. return( Status );
  190. }
  191. /****************************************************************************
  192. *
  193. * IcaCdCreateThread
  194. *
  195. * Create a thread
  196. *
  197. * ENTRY:
  198. * pContext (input)
  199. * pointer to ICA stack context
  200. * pProc (input)
  201. * pointer to thread procedure
  202. * pParam (input)
  203. * parameter for thread procedure
  204. * pThreadId (output)
  205. * address to return thread id
  206. *
  207. * EXIT:
  208. * thread handle (null on error)
  209. *
  210. ****************************************************************************/
  211. typedef NTSTATUS (*PTHREAD_ROUTINE) ( PVOID );
  212. typedef struct _CDCREATETHREADINFO {
  213. PTHREAD_ROUTINE pProc;
  214. PVOID pParam;
  215. PSTACK pStack;
  216. } CDCREATETHREADINFO, *PCDCREATETHREADINFO;
  217. NTSTATUS _CdThread( IN PCDCREATETHREADINFO pThreadInfo );
  218. HANDLE
  219. IcaCdCreateThread( HANDLE pContext,
  220. PVOID pProc,
  221. PVOID pParam,
  222. PULONG pThreadId )
  223. {
  224. CDCREATETHREADINFO ThreadInfo;
  225. HANDLE Handle;
  226. PSTACK pStack;
  227. pStack = (PSTACK) pContext;
  228. ASSERTLOCK( &pStack->CritSec );
  229. /*
  230. * Initialize thread info
  231. */
  232. ThreadInfo.pProc = pProc;
  233. ThreadInfo.pParam = pParam;
  234. ThreadInfo.pStack = pStack;
  235. /*
  236. * Increment reference
  237. * - this will be decremented when the thread exits
  238. */
  239. pStack->RefCount++;
  240. /*
  241. * Create thread
  242. */
  243. Handle = CreateThread( NULL,
  244. 5000,
  245. (LPTHREAD_START_ROUTINE)
  246. _CdThread,
  247. &ThreadInfo,
  248. 0,
  249. pThreadId );
  250. return( Handle );
  251. }
  252. NTSTATUS
  253. _CdThread( IN PCDCREATETHREADINFO pThreadInfo )
  254. {
  255. PSTACK pStack = pThreadInfo->pStack;
  256. /*
  257. * Lock critical section
  258. */
  259. LOCK( &pStack->CritSec );
  260. /*
  261. * Call thread procedure in CD driver
  262. */
  263. (void) (pThreadInfo->pProc)( pThreadInfo->pParam );
  264. /*
  265. * Decrement reference made in IcaCdCreateThread when thread exits
  266. */
  267. _DecrementStackRef( pStack );
  268. /*
  269. * Unlock critical section
  270. */
  271. UNLOCK( &pStack->CritSec );
  272. return( STATUS_SUCCESS );
  273. }
  274. /*******************************************************************************
  275. *
  276. * _CdOpen
  277. *
  278. * Load and open connection driver dll
  279. *
  280. * ENTRY:
  281. * pStack (input)
  282. * pointer to ICA stack structure
  283. * pWinStationConfig (input)
  284. * pointer to winstation config structure
  285. *
  286. * EXIT:
  287. * STATUS_SUCCESS - no error
  288. *
  289. ******************************************************************************/
  290. NTSTATUS
  291. _CdOpen( IN PSTACK pStack,
  292. IN PWINSTATIONCONFIG2 pWinStationConfig )
  293. {
  294. PCDCONFIG pCdConfig;
  295. HANDLE Handle;
  296. NTSTATUS Status;
  297. ASSERTLOCK( &pStack->CritSec );
  298. pCdConfig = &pWinStationConfig->Cd;
  299. /*
  300. * Return if there is no connection driver to load
  301. */
  302. if ( pCdConfig->CdClass == CdNone ) {
  303. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _CdOpen, no dll\n" ));
  304. return( STATUS_SUCCESS );
  305. }
  306. /*
  307. * load CD DLL
  308. */
  309. Handle = LoadLibrary( pCdConfig->CdDLL );
  310. if ( Handle == NULL ) {
  311. Status = STATUS_CTX_PD_NOT_FOUND;
  312. goto badload;
  313. }
  314. /*
  315. * get connection driver entry points
  316. */
  317. pStack->pCdOpen = (PCDOPEN) GetProcAddress( Handle, "CdOpen" );
  318. pStack->pCdClose = (PCDCLOSE) GetProcAddress( Handle, "CdClose" );
  319. pStack->pCdIoControl = (PCDIOCONTROL) GetProcAddress( Handle, "CdIoControl" );
  320. if ( pStack->pCdOpen == NULL ||
  321. pStack->pCdClose == NULL ||
  322. pStack->pCdIoControl == NULL ) {
  323. Status = STATUS_CTX_INVALID_PD;
  324. goto badproc;
  325. }
  326. /*
  327. * Open CD driver
  328. */
  329. Status = (*pStack->pCdOpen)( pStack,
  330. &pWinStationConfig->Pd[0], // td parameters
  331. &pStack->pCdContext
  332. );
  333. if ( !NT_SUCCESS(Status) )
  334. goto badopen;
  335. /*
  336. * Save CD handle
  337. */
  338. pStack->hCdDLL = Handle;
  339. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _CdOpen, %S, success\n",
  340. pCdConfig->CdDLL ));
  341. return( STATUS_SUCCESS );
  342. /*=============================================================================
  343. == Error returns
  344. =============================================================================*/
  345. /*
  346. * Open failed
  347. * get proc address failed
  348. */
  349. badopen:
  350. badproc:
  351. pStack->pCdOpen = NULL;
  352. pStack->pCdClose = NULL;
  353. pStack->pCdIoControl = NULL;
  354. FreeLibrary( Handle );
  355. /*
  356. * CD DLL load failed
  357. */
  358. badload:
  359. pStack->pCdContext = NULL;
  360. TRACESTACK(( pStack, TC_ICAAPI, TT_ERROR, "TSAPI: _CdOpen, %S, 0x%x\n", pCdConfig->CdDLL, Status ));
  361. return( Status );
  362. }
  363. /*******************************************************************************
  364. *
  365. * _CdClose
  366. *
  367. * Free local context structure
  368. *
  369. * ENTRY:
  370. * pStack (input)
  371. * pointer to ICA stack structure
  372. *
  373. * EXIT:
  374. * nothing
  375. *
  376. ******************************************************************************/
  377. VOID
  378. _CdClose( IN PSTACK pStack )
  379. {
  380. ASSERTLOCK( &pStack->CritSec );
  381. /*
  382. * Close CD driver
  383. */
  384. if ( pStack->pCdClose ) {
  385. (void) (*pStack->pCdClose)( pStack->pCdContext );
  386. }
  387. /*
  388. * Clear procedure pointers
  389. */
  390. pStack->pCdOpen = NULL;
  391. pStack->pCdClose = NULL;
  392. pStack->pCdIoControl = NULL;
  393. /*
  394. * Unload dll
  395. */
  396. if ( pStack->hCdDLL ) {
  397. FreeLibrary( pStack->hCdDLL );
  398. pStack->hCdDLL = NULL;
  399. }
  400. TRACESTACK(( pStack, TC_ICAAPI, TT_API1, "TSAPI: _CdClose\n" ));
  401. }