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.

534 lines
15 KiB

  1. /*******************************************************************************
  2. * virtual.c
  3. *
  4. * Published Terminal Server Virtual Channel APIs
  5. *
  6. * Copyright 1998, Citrix Systems Inc.
  7. * Copyright (C) 1997-1999 Microsoft Corp.
  8. ******************************************************************************/
  9. #include <nt.h>
  10. #include <ntrtl.h>
  11. #include <nturtl.h>
  12. #include <ntddkbd.h>
  13. #include <ntddmou.h>
  14. #include <windows.h>
  15. #include <winbase.h>
  16. #include <winerror.h>
  17. #if(WINVER >= 0x0500)
  18. #include <ntstatus.h>
  19. #include <winsta.h>
  20. #include <icadd.h>
  21. #else
  22. #include <citrix\cxstatus.h>
  23. #include <citrix\winsta.h>
  24. #include <citrix\icadd.h>
  25. #endif
  26. #include <utildll.h>
  27. #include <stdio.h>
  28. #include <stdarg.h>
  29. #include <wtsapi32.h>
  30. /*
  31. * Virtual Channel Name
  32. */
  33. #define VIRTUALNAME_LENGTH 7
  34. typedef CHAR VIRTUALNAME[ VIRTUALNAME_LENGTH + 1 ]; // includes null
  35. typedef CHAR * PVIRTUALNAME;
  36. // Handle structure used internally
  37. typedef struct _VCHANDLE {
  38. ULONG Signature;
  39. HANDLE hServer;
  40. DWORD SessionId;
  41. HANDLE hChannel;
  42. VIRTUALNAME VirtualName;
  43. } VCHANDLE, *PVCHANDLE;
  44. #define VCHANDLE_SIGNATURE ('V' | ('C' << 8) | ('H' << 16) | ('D' << 24))
  45. #define ValidVCHandle(hVC) ((hVC) && ((hVC)->Signature == VCHANDLE_SIGNATURE))
  46. /****************************************************************************
  47. *
  48. * WTSVirtualChannelOpen
  49. *
  50. * Open the specified virtual channel
  51. *
  52. * ENTRY:
  53. * hServer (input)
  54. * Terminal Server handle (or WTS_CURRENT_SERVER)
  55. * SessionId (input)
  56. * Server Session Id (or WTS_CURRENT_SESSION)
  57. * pVirtualName (input)
  58. * Pointer to virtual channel name
  59. *
  60. * EXIT:
  61. *
  62. * Handle to specified virtual channel (NULL on error)
  63. *
  64. ****************************************************************************/
  65. HANDLE
  66. WINAPI
  67. WTSVirtualChannelOpen(
  68. IN HANDLE hServer,
  69. IN DWORD SessionId,
  70. IN LPSTR pVirtualName /* ascii name */
  71. )
  72. {
  73. PVCHANDLE pChannelHandle;
  74. HANDLE hChannel;
  75. if (hChannel = WinStationVirtualOpen( hServer, SessionId, pVirtualName)) {
  76. // Allocate the Handle
  77. if (!(pChannelHandle = (PVCHANDLE) LocalAlloc(LPTR,
  78. sizeof(VCHANDLE)))) {
  79. CloseHandle(hChannel);
  80. SetLastError(ERROR_NOT_ENOUGH_MEMORY);
  81. return(NULL);
  82. }
  83. pChannelHandle->Signature = VCHANDLE_SIGNATURE;
  84. pChannelHandle->hServer = hServer;
  85. pChannelHandle->SessionId = SessionId;
  86. pChannelHandle->hChannel = hChannel;
  87. memcpy(pChannelHandle->VirtualName, pVirtualName, sizeof(VIRTUALNAME));
  88. return((HANDLE)pChannelHandle);
  89. }
  90. return(NULL);
  91. }
  92. /****************************************************************************
  93. *
  94. * WTSVirtualChannelClose
  95. *
  96. * Close the specified virtual channel
  97. *
  98. * ENTRY:
  99. * hChannel (input)
  100. * Virtual Channel handle previously returned by WTSVirtualChannelOpen.
  101. * EXIT:
  102. *
  103. * Returns TRUE if successful otherwise FALSE.
  104. *
  105. ****************************************************************************/
  106. BOOL
  107. WINAPI
  108. WTSVirtualChannelClose(HANDLE hChannel)
  109. {
  110. PVCHANDLE VCHandle = (PVCHANDLE) hChannel;
  111. BOOL RetVal = FALSE;
  112. if(!hChannel || IsBadReadPtr(hChannel,sizeof(HANDLE)))
  113. {
  114. SetLastError(ERROR_INVALID_PARAMETER);
  115. return (FALSE);
  116. }
  117. if (!ValidVCHandle(VCHandle)) {
  118. SetLastError(ERROR_INVALID_PARAMETER);
  119. goto BadParam;
  120. }
  121. if (CloseHandle(VCHandle->hChannel))
  122. RetVal = TRUE;
  123. VCHandle->Signature = 0;
  124. LocalFree(VCHandle);
  125. BadParam:
  126. return(RetVal);
  127. }
  128. /****************************************************************************
  129. *
  130. * WTSVirtualChannelWrite
  131. *
  132. * Write data to a virtual channel
  133. *
  134. * ENTRY:
  135. * ChannelHandle (input)
  136. * Virtual Channel handle previously returned by WTSVirtualChannelOpen.
  137. * Buffer (input)
  138. * Buffer containing data to write.
  139. * Length (input)
  140. * Length of data to write (bytes)
  141. * pBytesWritten (output)
  142. * Returns the amount of data written.
  143. * EXIT:
  144. *
  145. * Returns TRUE if successful otherwise FALSE.
  146. *
  147. ****************************************************************************/
  148. BOOL
  149. WINAPI
  150. WTSVirtualChannelWrite(HANDLE hChannel, PCHAR pBuffer, ULONG Length, PULONG pBytesWritten)
  151. {
  152. PVCHANDLE VCHandle = (PVCHANDLE)hChannel;
  153. OVERLAPPED Overlapped;
  154. if (!ValidVCHandle(VCHandle)) {
  155. SetLastError(ERROR_INVALID_PARAMETER);
  156. return (FALSE);
  157. }
  158. Overlapped.hEvent = NULL;
  159. Overlapped.Offset = 0;
  160. Overlapped.OffsetHigh = 0;
  161. if (!WriteFile(VCHandle->hChannel,
  162. pBuffer,
  163. Length,
  164. pBytesWritten,
  165. &Overlapped)) {
  166. if (GetLastError() == ERROR_IO_PENDING)
  167. // check on the results of the asynchronous write
  168. return (GetOverlappedResult(VCHandle->hChannel,
  169. &Overlapped,
  170. pBytesWritten,
  171. TRUE));
  172. else
  173. return(FALSE);
  174. }
  175. return(TRUE);
  176. }
  177. /****************************************************************************
  178. *
  179. * WTSVirtualChannelRead
  180. *
  181. * Read data from a virtual channel
  182. *
  183. * ENTRY:
  184. * ChannelHandle (input)
  185. * Virtual Channel handle previously returned by WTSVirtualChannelOpen.
  186. * Timeout (input)
  187. * The amount of time to wait for the read to complete.
  188. * Buffer (input)
  189. * Buffer which receive the data read.
  190. * BufferLength (input)
  191. * Length of the read buffer.
  192. * pBytesRead (output)
  193. * Returns the amount of data read.
  194. *
  195. * EXIT:
  196. *
  197. * Returns TRUE if successful otherwise FALSE.
  198. *
  199. ****************************************************************************/
  200. BOOL
  201. WINAPI
  202. WTSVirtualChannelRead(HANDLE hChannel, ULONG Timeout, PCHAR pBuffer, ULONG BufferLength, PULONG pBytesRead)
  203. {
  204. PVCHANDLE VCHandle = (PVCHANDLE)hChannel;
  205. OVERLAPPED Overlapped;
  206. if (!ValidVCHandle(VCHandle)) {
  207. SetLastError(ERROR_INVALID_PARAMETER);
  208. return (FALSE);
  209. }
  210. Overlapped.hEvent = NULL;
  211. Overlapped.Offset = 0;
  212. Overlapped.OffsetHigh = 0;
  213. if (!ReadFile(VCHandle->hChannel,
  214. pBuffer,
  215. BufferLength,
  216. pBytesRead,
  217. &Overlapped)) {
  218. if (GetLastError() == ERROR_IO_PENDING) {
  219. if (!Timeout) {
  220. // Read with no timeout - cancel IO and return success.
  221. // This matches the behavior in WTS 1.7. This is required for
  222. // Wyse firmware download software.
  223. CancelIo(VCHandle->hChannel);
  224. *pBytesRead = 0;
  225. return(TRUE);
  226. }
  227. if (WaitForSingleObject(VCHandle->hChannel, Timeout) == WAIT_TIMEOUT) {
  228. CancelIo(VCHandle->hChannel);
  229. SetLastError(ERROR_IO_INCOMPLETE);
  230. return(FALSE);
  231. }
  232. // check on the results of the asynchronous read
  233. return(GetOverlappedResult(VCHandle->hChannel,
  234. &Overlapped,
  235. pBytesRead,
  236. FALSE));
  237. } else {
  238. return(FALSE);
  239. }
  240. }
  241. return(TRUE);
  242. }
  243. /****************************************************************************
  244. *
  245. * VirtualChannelIoctl
  246. *
  247. * Issues an Ioctl to a virtual channel. This routine was replicated from
  248. * icaapi so that OEMs don't need to link with icaapi.dll.
  249. *
  250. * ENTRY:
  251. * hChannelHandle (input)
  252. * Virtual Channel handle previously returned by WTSVirtualChannelOpen.
  253. * IoctlCode (input)
  254. * The type of ioctl to do.
  255. * pInBuf (input)
  256. * Input data required for the Ioctl.
  257. * InBufLength (input)
  258. * Length of input data.
  259. *
  260. * pOutBuf (output)
  261. * Buffer to receive output data.
  262. * OutBufLength (input)
  263. * Length of the output buffer.
  264. * pBytesReturned (output)
  265. * Number of bytes returned in OutputBuffer.
  266. * EXIT:
  267. *
  268. * Returns TRUE if successful, otherwise FALSE.
  269. *
  270. ****************************************************************************/
  271. BOOL
  272. VirtualChannelIoctl (HANDLE hChannel,
  273. ULONG IoctlCode,
  274. PCHAR pInBuf,
  275. ULONG InBufLength,
  276. PCHAR pOutBuf,
  277. ULONG OutBufLength,
  278. PULONG pBytesReturned)
  279. {
  280. IO_STATUS_BLOCK Iosb;
  281. NTSTATUS Status;
  282. PVCHANDLE VCHandle = (PVCHANDLE)hChannel;
  283. if (!ValidVCHandle(VCHandle)) {
  284. SetLastError(ERROR_INVALID_PARAMETER);
  285. return (FALSE);
  286. }
  287. /*
  288. * Issue ioctl
  289. */
  290. Status = NtDeviceIoControlFile( VCHandle->hChannel,
  291. NULL,
  292. NULL,
  293. NULL,
  294. &Iosb,
  295. IoctlCode,
  296. pInBuf,
  297. InBufLength,
  298. pOutBuf,
  299. OutBufLength );
  300. /*
  301. * Wait for ioctl to complete
  302. */
  303. if ( Status == STATUS_PENDING ) {
  304. Status = NtWaitForSingleObject( VCHandle->hChannel, FALSE, NULL );
  305. if ( NT_SUCCESS(Status))
  306. Status = Iosb.Status;
  307. }
  308. /*
  309. * Convert warning into error
  310. */
  311. if ( Status == STATUS_BUFFER_OVERFLOW )
  312. Status = STATUS_BUFFER_TOO_SMALL;
  313. /*
  314. * Initialize bytes returned
  315. */
  316. if ( pBytesReturned )
  317. *pBytesReturned = (ULONG)Iosb.Information;
  318. /* Return success/failure indication */
  319. if (NT_SUCCESS(Status)) {
  320. return(TRUE);
  321. } else {
  322. SetLastError(RtlNtStatusToDosError(Status));
  323. return(FALSE);
  324. }
  325. }
  326. /****************************************************************************
  327. *
  328. * WTSVirtualChannelPurgeInput
  329. *
  330. * Purge all queued input data on a virtual channel.
  331. *
  332. * ENTRY:
  333. * ChannelHandle (input)
  334. * Virtual Channel handle previously returned by WTSVirtualChannelOpen.
  335. *
  336. * EXIT:
  337. *
  338. * Returns TRUE if successful otherwise FALSE.
  339. *
  340. ****************************************************************************/
  341. BOOL
  342. WINAPI
  343. WTSVirtualChannelPurgeInput(IN HANDLE hChannelHandle)
  344. {
  345. PVCHANDLE VCHandle = (PVCHANDLE) hChannelHandle;
  346. return(VirtualChannelIoctl(VCHandle,
  347. IOCTL_ICA_VIRTUAL_CANCEL_INPUT,
  348. (PCHAR) NULL,
  349. 0,
  350. (PCHAR) NULL,
  351. 0,
  352. (PULONG) NULL));
  353. }
  354. /****************************************************************************
  355. *
  356. * WTSVirtualChannelPurgeOutput
  357. *
  358. * Purge all queued output data on a virtual channel.
  359. *
  360. * ENTRY:
  361. * ChannelHandle (input)
  362. * Virtual Channel handle previously returned by WTSVirtualChannelOpen.
  363. *
  364. * EXIT:
  365. *
  366. * Returns TRUE if successful otherwise FALSE.
  367. *
  368. ****************************************************************************/
  369. BOOL
  370. WINAPI
  371. WTSVirtualChannelPurgeOutput(IN HANDLE hChannelHandle)
  372. {
  373. PVCHANDLE VCHandle = (PVCHANDLE)hChannelHandle;
  374. return(VirtualChannelIoctl(VCHandle,
  375. IOCTL_ICA_VIRTUAL_CANCEL_OUTPUT,
  376. (PCHAR) NULL,
  377. 0,
  378. (PCHAR) NULL,
  379. 0,
  380. (PULONG) NULL));
  381. }
  382. /****************************************************************************
  383. *
  384. * WTSVirtualChannelQuery
  385. *
  386. * Query data related to a virtual channel.
  387. *
  388. * ENTRY:
  389. * hChannelHandle (input)
  390. * Virtual Channel handle previously returned by WTSVirtualChannelOpen.
  391. * VirtualClass (input)
  392. * The type of information requested.
  393. * ppBuffer (output)
  394. * Pointer to a buffer pointer, which is allocated upon successful
  395. * return.
  396. * pBytesReturned (output)
  397. * Pointer to a DWORD which is updated with the length of the data
  398. * returned in the allocated buffer upon successful return.
  399. * EXIT:
  400. *
  401. * Returns TRUE if successful otherwise FALSE.
  402. * If successful, the caller is responsible for deallocating the
  403. * buffer returned.
  404. *
  405. ****************************************************************************/
  406. BOOL
  407. WINAPI
  408. WTSVirtualChannelQuery(IN HANDLE hChannelHandle,IN WTS_VIRTUAL_CLASS VirtualClass,
  409. OUT PVOID *ppBuffer,OUT DWORD *pBytesReturned)
  410. {
  411. PVCHANDLE VCHandle = (PVCHANDLE) hChannelHandle;
  412. PVOID DataBuffer;
  413. DWORD DataBufferLen;
  414. if (!hChannelHandle || IsBadReadPtr(hChannelHandle,sizeof(HANDLE)))
  415. {
  416. SetLastError(ERROR_INVALID_PARAMETER);
  417. return(FALSE);
  418. }
  419. if (!ValidVCHandle(VCHandle)) {
  420. SetLastError(ERROR_INVALID_PARAMETER);
  421. return(FALSE);
  422. }
  423. if (!ppBuffer || IsBadWritePtr(ppBuffer, sizeof(PVOID)))
  424. {
  425. SetLastError(ERROR_INVALID_PARAMETER);
  426. return(FALSE);
  427. }
  428. if (!pBytesReturned || IsBadWritePtr(pBytesReturned, sizeof(DWORD)))
  429. {
  430. SetLastError(ERROR_INVALID_PARAMETER);
  431. return(FALSE);
  432. }
  433. switch (VirtualClass) {
  434. case WTSVirtualFileHandle:
  435. DataBuffer = LocalAlloc( LPTR, sizeof(HANDLE) );
  436. if ( DataBuffer == NULL ) {
  437. return(FALSE);
  438. }
  439. memcpy(DataBuffer, &VCHandle->hChannel, sizeof(HANDLE) );
  440. *ppBuffer = DataBuffer;
  441. *pBytesReturned = sizeof(HANDLE);
  442. return(TRUE);
  443. break;
  444. case WTSVirtualClientData:
  445. DataBufferLen = sizeof(VIRTUALNAME) + 1024;
  446. for (;;) {
  447. DataBuffer = LocalAlloc( LPTR, DataBufferLen );
  448. if ( DataBuffer == NULL ) {
  449. return(FALSE);
  450. }
  451. memcpy( DataBuffer,VCHandle->VirtualName,sizeof(VIRTUALNAME));
  452. if (WinStationQueryInformationW( VCHandle->hServer,
  453. VCHandle->SessionId,
  454. WinStationVirtualData,
  455. DataBuffer,
  456. DataBufferLen,
  457. &DataBufferLen)) {
  458. *ppBuffer = DataBuffer;
  459. *pBytesReturned = DataBufferLen;
  460. return(TRUE);
  461. }
  462. if ((GetLastError() != ERROR_INSUFFICIENT_BUFFER) ||
  463. (DataBufferLen < sizeof(VIRTUALNAME))) {
  464. LocalFree(DataBuffer);
  465. return(FALSE);
  466. }
  467. LocalFree(DataBuffer);
  468. }
  469. break;
  470. default:
  471. SetLastError(ERROR_INVALID_PARAMETER);
  472. return(FALSE);
  473. }
  474. }