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.

239 lines
8.1 KiB

  1. /*************************************************************************
  2. *
  3. * command.c
  4. *
  5. * WinStation command channel handler
  6. *
  7. * Copyright (c) 1985 - 1999, Microsoft Corporation
  8. *
  9. * $Author:
  10. *************************************************************************/
  11. /*
  12. * Includes
  13. */
  14. #include "precomp.h"
  15. #pragma hdrstop
  16. #include "ntuser.h"
  17. #include <winsta.h>
  18. #include <wstmsg.h>
  19. #include <icadd.h>
  20. extern HANDLE WinStationIcaApiPort;
  21. extern HANDLE G_DupIcaVideoChannel;
  22. extern HANDLE G_DupIcaCommandChannel;
  23. extern HANDLE G_DupConsoleShadowVideoChannel;
  24. extern HANDLE G_DupConsoleShadowCommandChannel;
  25. extern NTSTATUS BrokenConnection(BROKENCLASS, BROKENSOURCECLASS);
  26. extern NTSTATUS ShadowHotkey(VOID);
  27. NTSTATUS
  28. Win32CommandChannelThread(
  29. PVOID ThreadParameter)
  30. {
  31. ICA_CHANNEL_COMMAND Command;
  32. ULONG ActualLength;
  33. NTSTATUS Status;
  34. ULONG Error;
  35. OVERLAPPED Overlapped;
  36. USERTHREAD_USEDESKTOPINFO utudi;
  37. BOOL bRestoreDesktop = FALSE;
  38. BOOL bShadowCommandChannel = (BOOL)PtrToUlong(ThreadParameter);
  39. HANDLE hChannel = bShadowCommandChannel ? G_DupConsoleShadowCommandChannel : G_DupIcaCommandChannel;
  40. HANDLE hChannelToClose = NULL;
  41. for ( ; ; ) {
  42. RtlZeroMemory(&Overlapped, sizeof(Overlapped));
  43. if (!ReadFile(hChannel,
  44. &Command,
  45. sizeof(Command),
  46. &ActualLength,
  47. &Overlapped)) {
  48. Error = GetLastError();
  49. if (Error == ERROR_IO_PENDING) {
  50. /*
  51. * check on the results of the asynchronous read
  52. */
  53. if (!GetOverlappedResult(hChannel, &Overlapped,
  54. &ActualLength, TRUE)) {
  55. // wait for result
  56. RIPMSG1(RIP_WARNING, "Command Channel: Error 0x%x from GetOverlappedResult", GetLastError());
  57. break;
  58. }
  59. } else {
  60. RIPMSG1(RIP_WARNING, "Command Channel: Error 0x%x from ReadFile", Error);
  61. break;
  62. }
  63. }
  64. if (ActualLength < sizeof(ICA_COMMAND_HEADER)) {
  65. RIPMSG1(RIP_WARNING, "Command Channel Thread bad length 0x%x",
  66. ActualLength);
  67. continue;
  68. }
  69. /*
  70. * This is a Csrss thread with no desktop. It needs to grab a temporary one
  71. * before calling into win32k.
  72. */
  73. Status = STATUS_SUCCESS;
  74. bRestoreDesktop = FALSE;
  75. if (Command.Header.Command != ICA_COMMAND_BROKEN_CONNECTION && Command.Header.Command != ICA_COMMAND_SHADOW_HOTKEY) {
  76. if (Command.Header.Command != ICA_COMMAND_DISPLAY_IOCTL || Command.DisplayIOCtl.DisplayIOCtlFlags & DISPLAY_IOCTL_FLAG_REDRAW) {
  77. utudi.hThread = NULL;
  78. utudi.drdRestore.pdeskRestore = NULL;
  79. bRestoreDesktop = TRUE;
  80. Status = NtUserSetInformationThread(NtCurrentThread(),
  81. UserThreadUseActiveDesktop,
  82. &utudi, sizeof(utudi));
  83. }
  84. }
  85. if (NT_SUCCESS(Status)) {
  86. switch (Command.Header.Command) {
  87. case ICA_COMMAND_BROKEN_CONNECTION:
  88. /*
  89. * broken procedure
  90. */
  91. Status = BrokenConnection(
  92. Command.BrokenConnection.Reason,
  93. Command.BrokenConnection.Source);
  94. if (!NT_SUCCESS(Status)) {
  95. RIPMSG1(RIP_WARNING, "BrokenConnection failed with Status 0x%x", Status);
  96. }
  97. break;
  98. case ICA_COMMAND_REDRAW_RECTANGLE:
  99. /*
  100. * setfocus ???
  101. */
  102. if (ActualLength < sizeof(ICA_COMMAND_HEADER) + sizeof(ICA_REDRAW_RECTANGLE)) {
  103. RIPMSG1(RIP_WARNING, "Command Channel: redraw rect bad length %d", ActualLength);
  104. break;
  105. }
  106. Status = NtUserRemoteRedrawRectangle(
  107. Command.RedrawRectangle.Rect.Left,
  108. Command.RedrawRectangle.Rect.Top,
  109. Command.RedrawRectangle.Rect.Right,
  110. Command.RedrawRectangle.Rect.Bottom);
  111. if (!NT_SUCCESS(Status)) {
  112. RIPMSG1(RIP_WARNING, "NtUserRemoteRedrawRectangle failed with Status 0x%x", Status);
  113. }
  114. break;
  115. case ICA_COMMAND_REDRAW_SCREEN: // setfocus
  116. Status = NtUserRemoteRedrawScreen();
  117. if (!NT_SUCCESS(Status)) {
  118. RIPMSG1(RIP_WARNING, "NtUserRemoteRedrawScreen failed with Status 0x%x", Status);
  119. }
  120. break;
  121. case ICA_COMMAND_STOP_SCREEN_UPDATES: // killfocus
  122. Status = NtUserRemoteStopScreenUpdates();
  123. if (!NT_SUCCESS(Status)) {
  124. RIPMSG1(RIP_WARNING, "NtUserRemoteStopScreenUpdates failed with Status 0x%x", Status);
  125. } else {
  126. IO_STATUS_BLOCK IoStatus;
  127. NtDeviceIoControlFile(
  128. bShadowCommandChannel ? G_DupConsoleShadowVideoChannel
  129. : G_DupIcaVideoChannel,
  130. NULL,
  131. NULL,
  132. NULL,
  133. &IoStatus,
  134. IOCTL_VIDEO_ICA_STOP_OK,
  135. NULL,
  136. 0,
  137. NULL,
  138. 0);
  139. }
  140. break;
  141. case ICA_COMMAND_SHADOW_HOTKEY: // shadow hotkey
  142. Status = ShadowHotkey();
  143. if (!NT_SUCCESS(Status)) {
  144. RIPMSG1(RIP_WARNING, "ShadowHotkey failed with Status 0x%x", Status);
  145. }
  146. break;
  147. case ICA_COMMAND_DISPLAY_IOCTL:
  148. Status = NtUserCtxDisplayIOCtl(
  149. Command.DisplayIOCtl.DisplayIOCtlFlags,
  150. &Command.DisplayIOCtl.DisplayIOCtlData[0],
  151. Command.DisplayIOCtl.cbDisplayIOCtlData);
  152. if (!NT_SUCCESS(Status)) {
  153. RIPMSG1(RIP_WARNING, "NtUserCtxDisplayIOCtl failed with Status 0x%x", Status);
  154. }
  155. break;
  156. default:
  157. RIPMSG1(RIP_WARNING, "Command Channel: Bad Command 0x%x", Command.Header.Command);
  158. break;
  159. }
  160. /*
  161. * Release the temporary desktop.
  162. */
  163. if (bRestoreDesktop) {
  164. NTSTATUS retStatus;
  165. retStatus = NtUserSetInformationThread(NtCurrentThread(),
  166. UserThreadUseDesktop,
  167. &utudi,
  168. sizeof(utudi));
  169. }
  170. }
  171. }
  172. if (!bShadowCommandChannel) {
  173. /*
  174. * Close command channel LPC port if there is one.
  175. */
  176. if (WinStationIcaApiPort) {
  177. NtClose(WinStationIcaApiPort);
  178. WinStationIcaApiPort = NULL;
  179. }
  180. }
  181. // We have to close the commandchannel handle here
  182. if (hChannel != NULL) {
  183. NtClose(hChannel);
  184. }
  185. // We have to close the relevant Video Channel here
  186. hChannelToClose = ( bShadowCommandChannel ? G_DupConsoleShadowVideoChannel : G_DupIcaVideoChannel );
  187. if (hChannelToClose != NULL) {
  188. NtClose(hChannelToClose);
  189. }
  190. UserExitWorkerThread(STATUS_SUCCESS);
  191. return STATUS_SUCCESS;
  192. }