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.

309 lines
12 KiB

  1. /*************************************************************************
  2. *
  3. * virtual.c
  4. *
  5. * This module contains routines for managing ICA virtual channels.
  6. *
  7. * Copyright 1998, Microsoft.
  8. *
  9. *
  10. *************************************************************************/
  11. /*
  12. * Includes
  13. */
  14. #include <precomp.h>
  15. #pragma hdrstop
  16. NTSTATUS
  17. _IcaCallStack(
  18. IN PICA_STACK pStack,
  19. IN ULONG ProcIndex,
  20. IN OUT PVOID pParms
  21. );
  22. NTSTATUS
  23. IcaFlushChannel (
  24. IN PICA_CHANNEL pChannel,
  25. IN PIRP Irp,
  26. IN PIO_STACK_LOCATION IrpSp
  27. );
  28. NTSTATUS
  29. IcaDeviceControlVirtual(
  30. IN PICA_CHANNEL pChannel,
  31. IN PIRP Irp,
  32. IN PIO_STACK_LOCATION IrpSp
  33. )
  34. /*++
  35. Routine Description:
  36. This is the device control routine for the ICA Virtual channel.
  37. Arguments:
  38. pChannel -- pointer to ICA_CHANNEL object
  39. Irp - Pointer to I/O request packet
  40. IrpSp - pointer to the stack location to use for this request.
  41. Return Value:
  42. NTSTATUS -- Indicates whether the request was successfully queued.
  43. --*/
  44. {
  45. ULONG code;
  46. SD_IOCTL SdIoctl;
  47. NTSTATUS Status;
  48. PICA_STACK pStack;
  49. PVOID pTempBuffer = NULL;
  50. PVOID pInputBuffer = NULL;
  51. PVOID pUserBuffer = NULL;
  52. BOOLEAN bStackIsReferenced = FALSE;
  53. ULONG i;
  54. // these are the set of ioctls that can be expected on non system created VCs.
  55. ULONG PublicIoctls[] =
  56. {
  57. IOCTL_ICA_VIRTUAL_LOAD_FILTER,
  58. IOCTL_ICA_VIRTUAL_UNLOAD_FILTER,
  59. IOCTL_ICA_VIRTUAL_ENABLE_FILTER,
  60. IOCTL_ICA_VIRTUAL_DISABLE_FILTER,
  61. IOCTL_ICA_VIRTUAL_BOUND,
  62. IOCTL_ICA_VIRTUAL_CANCEL_INPUT,
  63. IOCTL_ICA_VIRTUAL_CANCEL_OUTPUT
  64. };
  65. try{
  66. /*
  67. * Extract the IOCTL control code and process the request.
  68. */
  69. code = IrpSp->Parameters.DeviceIoControl.IoControlCode;
  70. TRACECHANNEL(( pChannel, TC_ICADD, TT_API1, "ICADD: IcaDeviceControlVirtual, fc %d, ref %u (enter)\n",
  71. (code & 0x3fff) >> 2, pChannel->RefCount ));
  72. if (!IrpSp->FileObject->FsContext2)
  73. {
  74. /*
  75. * if the object was not created by system. dont let it sent IOCTLS on VCs.
  76. * except for the public ioctls.
  77. */
  78. for ( i=0; i < sizeof(PublicIoctls) / sizeof(PublicIoctls[0]); i++)
  79. {
  80. if (code == PublicIoctls[i])
  81. break;
  82. }
  83. if (i == sizeof(PublicIoctls) / sizeof(PublicIoctls[0]))
  84. {
  85. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, denying IOCTL(0x%x) on non-system VC. \n" , code));
  86. return STATUS_ACCESS_DENIED;
  87. }
  88. }
  89. /*
  90. * Process ioctl request
  91. */
  92. switch ( code ) {
  93. case IOCTL_ICA_VIRTUAL_LOAD_FILTER :
  94. case IOCTL_ICA_VIRTUAL_UNLOAD_FILTER :
  95. case IOCTL_ICA_VIRTUAL_ENABLE_FILTER :
  96. case IOCTL_ICA_VIRTUAL_DISABLE_FILTER :
  97. Status = STATUS_INVALID_DEVICE_REQUEST;
  98. break;
  99. case IOCTL_ICA_VIRTUAL_BOUND :
  100. Status = (pChannel->VirtualClass == UNBOUND_CHANNEL) ?
  101. STATUS_INVALID_DEVICE_REQUEST : STATUS_SUCCESS;
  102. break;
  103. case IOCTL_ICA_VIRTUAL_QUERY_MODULE_DATA :
  104. IcaLockConnection( pChannel->pConnect );
  105. if ( IsListEmpty( &pChannel->pConnect->StackHead ) ) {
  106. IcaUnlockConnection( pChannel->pConnect );
  107. return( STATUS_INVALID_DEVICE_REQUEST );
  108. }
  109. pStack = CONTAINING_RECORD( pChannel->pConnect->StackHead.Flink,
  110. ICA_STACK, StackEntry );
  111. if( (pStack->StackClass != Stack_Console) &&
  112. (pStack->StackClass != Stack_Primary) ) {
  113. IcaUnlockConnection( pChannel->pConnect );
  114. return( STATUS_INVALID_DEVICE_REQUEST );
  115. }
  116. IcaReferenceStack( pStack );
  117. bStackIsReferenced = TRUE;
  118. IcaUnlockConnection( pChannel->pConnect );
  119. if ( pChannel->VirtualClass == UNBOUND_CHANNEL ) {
  120. IcaDereferenceStack( pStack );
  121. bStackIsReferenced = FALSE;
  122. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, channel not bound\n" ));
  123. return( STATUS_INVALID_DEVICE_REQUEST );
  124. }
  125. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IOCTL_ICA_VIRTUAL_QUERY_MODULE_DATA begin\n" ));
  126. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, pStack 0x%x\n", pStack ));
  127. if ( Irp->RequestorMode != KernelMode && IrpSp->Parameters.DeviceIoControl.OutputBufferLength != 0) {
  128. ProbeForWrite( Irp->UserBuffer,
  129. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  130. sizeof(BYTE) );
  131. }
  132. Status = CaptureUsermodeBuffer ( Irp,
  133. IrpSp,
  134. NULL,
  135. 0,
  136. &pUserBuffer,
  137. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  138. FALSE,
  139. &pTempBuffer);
  140. if (Status != STATUS_SUCCESS) {
  141. break;
  142. }
  143. SdIoctl.IoControlCode = code;
  144. SdIoctl.InputBuffer = &pChannel->VirtualClass;
  145. SdIoctl.InputBufferLength = sizeof(pChannel->VirtualClass);
  146. SdIoctl.OutputBuffer = pUserBuffer;
  147. SdIoctl.OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  148. Status = _IcaCallStack( pStack, SD$IOCTL, &SdIoctl );
  149. if (gCapture && (Status == STATUS_SUCCESS) && (IrpSp->Parameters.DeviceIoControl.OutputBufferLength != 0)) {
  150. RtlCopyMemory( Irp->UserBuffer,
  151. pUserBuffer,
  152. IrpSp->Parameters.DeviceIoControl.OutputBufferLength );
  153. }
  154. Irp->IoStatus.Information = SdIoctl.BytesReturned;
  155. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, Status 0x%x\n", Status ));
  156. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IOCTL_ICA_VIRTUAL_QUERY_MODULE_DATA end\n" ));
  157. IcaDereferenceStack( pStack );
  158. bStackIsReferenced = FALSE;
  159. break;
  160. case IOCTL_ICA_VIRTUAL_CANCEL_INPUT :
  161. Status = IcaFlushChannel( pChannel, Irp, IrpSp );
  162. if ( !NT_SUCCESS(Status) )
  163. break;
  164. /* fall through */
  165. default :
  166. /*
  167. * Make sure virtual channel is bound to a virtual channel number
  168. */
  169. if ( pChannel->VirtualClass == UNBOUND_CHANNEL ) {
  170. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, channel not bound\n" ));
  171. return( STATUS_INVALID_DEVICE_REQUEST );
  172. }
  173. /*
  174. * Save virtual class in first 4 bytes of the input buffer
  175. * - this is used by the wd
  176. */
  177. if ( Irp->RequestorMode != KernelMode && IrpSp->Parameters.DeviceIoControl.OutputBufferLength != 0) {
  178. ProbeForWrite( Irp->UserBuffer,
  179. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  180. sizeof(BYTE) );
  181. }
  182. if ( Irp->RequestorMode != KernelMode && IrpSp->Parameters.DeviceIoControl.InputBufferLength != 0) {
  183. ProbeForRead( IrpSp->Parameters.DeviceIoControl.Type3InputBuffer,
  184. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  185. sizeof(BYTE) );
  186. }
  187. if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(VIRTUALCHANNELCLASS) ) {
  188. SdIoctl.InputBuffer = &pChannel->VirtualClass;
  189. SdIoctl.InputBufferLength = sizeof(pChannel->VirtualClass);
  190. Status = CaptureUsermodeBuffer ( Irp,
  191. IrpSp,
  192. NULL,
  193. 0,
  194. &pUserBuffer,
  195. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  196. FALSE,
  197. &pTempBuffer);
  198. if (Status != STATUS_SUCCESS) {
  199. break;
  200. }
  201. } else {
  202. Status = CaptureUsermodeBuffer ( Irp,
  203. IrpSp,
  204. &pInputBuffer,
  205. IrpSp->Parameters.DeviceIoControl.InputBufferLength,
  206. &pUserBuffer,
  207. IrpSp->Parameters.DeviceIoControl.OutputBufferLength,
  208. FALSE,
  209. &pTempBuffer);
  210. if (Status != STATUS_SUCCESS) {
  211. break;
  212. }
  213. SdIoctl.InputBuffer = pInputBuffer;
  214. SdIoctl.InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
  215. RtlCopyMemory( SdIoctl.InputBuffer, &pChannel->VirtualClass, sizeof(pChannel->VirtualClass) );
  216. }
  217. /*
  218. * Send request to WD
  219. */
  220. SdIoctl.IoControlCode = code;
  221. SdIoctl.OutputBuffer = pUserBuffer;
  222. SdIoctl.OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  223. Status = IcaCallDriver( pChannel, SD$IOCTL, &SdIoctl );
  224. if (gCapture && (Status == STATUS_SUCCESS) && (IrpSp->Parameters.DeviceIoControl.OutputBufferLength != 0)) {
  225. RtlCopyMemory( Irp->UserBuffer,
  226. pUserBuffer,
  227. IrpSp->Parameters.DeviceIoControl.OutputBufferLength );
  228. }
  229. Irp->IoStatus.Information = SdIoctl.BytesReturned;
  230. break;
  231. }
  232. TRACECHANNEL(( pChannel, TC_ICADD, TT_API1, "ICADD: IcaDeviceControlVirtual, fc %d, ref %u, 0x%x\n",
  233. (code & 0x3fff) >> 2, pChannel->RefCount, Status ));
  234. } except(EXCEPTION_EXECUTE_HANDLER){
  235. Status = GetExceptionCode();
  236. if (bStackIsReferenced) {
  237. IcaDereferenceStack( pStack );
  238. }
  239. }
  240. if (pTempBuffer!= NULL) {
  241. ExFreePool(pTempBuffer);
  242. }
  243. return( Status );
  244. }