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.

182 lines
5.8 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. /*
  50. * Extract the IOCTL control code and process the request.
  51. */
  52. code = IrpSp->Parameters.DeviceIoControl.IoControlCode;
  53. TRACECHANNEL(( pChannel, TC_ICADD, TT_API1, "ICADD: IcaDeviceControlVirtual, fc %d, ref %u (enter)\n",
  54. (code & 0x3fff) >> 2, pChannel->RefCount ));
  55. /*
  56. * Process ioctl request
  57. */
  58. switch ( code ) {
  59. case IOCTL_ICA_VIRTUAL_LOAD_FILTER :
  60. case IOCTL_ICA_VIRTUAL_UNLOAD_FILTER :
  61. case IOCTL_ICA_VIRTUAL_ENABLE_FILTER :
  62. case IOCTL_ICA_VIRTUAL_DISABLE_FILTER :
  63. Status = STATUS_INVALID_DEVICE_REQUEST;
  64. break;
  65. case IOCTL_ICA_VIRTUAL_BOUND :
  66. Status = (pChannel->VirtualClass == UNBOUND_CHANNEL) ?
  67. STATUS_INVALID_DEVICE_REQUEST : STATUS_SUCCESS;
  68. break;
  69. case IOCTL_ICA_VIRTUAL_QUERY_MODULE_DATA :
  70. IcaLockConnection( pChannel->pConnect );
  71. if ( IsListEmpty( &pChannel->pConnect->StackHead ) ) {
  72. IcaUnlockConnection( pChannel->pConnect );
  73. return( STATUS_INVALID_DEVICE_REQUEST );
  74. }
  75. pStack = CONTAINING_RECORD( pChannel->pConnect->StackHead.Flink,
  76. ICA_STACK, StackEntry );
  77. if( (pStack->StackClass != Stack_Console) &&
  78. (pStack->StackClass != Stack_Primary) ) {
  79. IcaUnlockConnection( pChannel->pConnect );
  80. return( STATUS_INVALID_DEVICE_REQUEST );
  81. }
  82. IcaReferenceStack( pStack );
  83. IcaUnlockConnection( pChannel->pConnect );
  84. if ( pChannel->VirtualClass == UNBOUND_CHANNEL ) {
  85. IcaDereferenceStack( pStack );
  86. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, channel not bound\n" ));
  87. return( STATUS_INVALID_DEVICE_REQUEST );
  88. }
  89. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IOCTL_ICA_VIRTUAL_QUERY_MODULE_DATA begin\n" ));
  90. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, pStack 0x%x\n", pStack ));
  91. SdIoctl.IoControlCode = code;
  92. SdIoctl.InputBuffer = &pChannel->VirtualClass;
  93. SdIoctl.InputBufferLength = sizeof(pChannel->VirtualClass);
  94. SdIoctl.OutputBuffer = Irp->UserBuffer;
  95. SdIoctl.OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  96. Status = _IcaCallStack( pStack, SD$IOCTL, &SdIoctl );
  97. Irp->IoStatus.Information = SdIoctl.BytesReturned;
  98. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, Status 0x%x\n", Status ));
  99. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IOCTL_ICA_VIRTUAL_QUERY_MODULE_DATA end\n" ));
  100. IcaDereferenceStack( pStack );
  101. break;
  102. case IOCTL_ICA_VIRTUAL_CANCEL_INPUT :
  103. Status = IcaFlushChannel( pChannel, Irp, IrpSp );
  104. if ( !NT_SUCCESS(Status) )
  105. break;
  106. /* fall through */
  107. default :
  108. /*
  109. * Make sure virtual channel is bound to a virtual channel number
  110. */
  111. if ( pChannel->VirtualClass == UNBOUND_CHANNEL ) {
  112. TRACECHANNEL(( pChannel, TC_ICADD, TT_ERROR, "ICADD: IcaDeviceControlVirtual, channel not bound\n" ));
  113. return( STATUS_INVALID_DEVICE_REQUEST );
  114. }
  115. /*
  116. * Save virtual class in first 4 bytes of the input buffer
  117. * - this is used by the wd
  118. */
  119. if ( IrpSp->Parameters.DeviceIoControl.InputBufferLength < sizeof(VIRTUALCHANNELCLASS) ) {
  120. SdIoctl.InputBuffer = &pChannel->VirtualClass;
  121. SdIoctl.InputBufferLength = sizeof(pChannel->VirtualClass);
  122. } else {
  123. SdIoctl.InputBuffer = IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
  124. SdIoctl.InputBufferLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
  125. RtlCopyMemory( SdIoctl.InputBuffer, &pChannel->VirtualClass, sizeof(pChannel->VirtualClass) );
  126. }
  127. /*
  128. * Send request to WD
  129. */
  130. SdIoctl.IoControlCode = code;
  131. SdIoctl.OutputBuffer = Irp->UserBuffer;
  132. SdIoctl.OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
  133. Status = IcaCallDriver( pChannel, SD$IOCTL, &SdIoctl );
  134. Irp->IoStatus.Information = SdIoctl.BytesReturned;
  135. break;
  136. }
  137. TRACECHANNEL(( pChannel, TC_ICADD, TT_API1, "ICADD: IcaDeviceControlVirtual, fc %d, ref %u, 0x%x\n",
  138. (code & 0x3fff) >> 2, pChannel->RefCount, Status ));
  139. return( Status );
  140. }