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

/*************************************************************************
*
* command.c
*
* WinStation command channel handler
*
* Copyright (c) 1985 - 1999, Microsoft Corporation
*
* $Author:
*************************************************************************/
/*
* Includes
*/
#include "precomp.h"
#pragma hdrstop
#include "ntuser.h"
#include <winsta.h>
#include <wstmsg.h>
#include <icadd.h>
extern HANDLE WinStationIcaApiPort;
extern HANDLE G_DupIcaVideoChannel;
extern HANDLE G_DupIcaCommandChannel;
extern HANDLE G_DupConsoleShadowVideoChannel;
extern HANDLE G_DupConsoleShadowCommandChannel;
extern NTSTATUS BrokenConnection(BROKENCLASS, BROKENSOURCECLASS);
extern NTSTATUS ShadowHotkey(VOID);
NTSTATUS
Win32CommandChannelThread(
PVOID ThreadParameter)
{
ICA_CHANNEL_COMMAND Command;
ULONG ActualLength;
NTSTATUS Status;
ULONG Error;
OVERLAPPED Overlapped;
USERTHREAD_USEDESKTOPINFO utudi;
BOOL bRestoreDesktop = FALSE;
BOOL bShadowCommandChannel = (BOOL)PtrToUlong(ThreadParameter);
HANDLE hChannel = bShadowCommandChannel ? G_DupConsoleShadowCommandChannel : G_DupIcaCommandChannel;
HANDLE hChannelToClose = NULL;
for ( ; ; ) {
RtlZeroMemory(&Overlapped, sizeof(Overlapped));
if (!ReadFile(hChannel,
&Command,
sizeof(Command),
&ActualLength,
&Overlapped)) {
Error = GetLastError();
if (Error == ERROR_IO_PENDING) {
/*
* check on the results of the asynchronous read
*/
if (!GetOverlappedResult(hChannel, &Overlapped,
&ActualLength, TRUE)) {
// wait for result
RIPMSG1(RIP_WARNING, "Command Channel: Error 0x%x from GetOverlappedResult", GetLastError());
break;
}
} else {
RIPMSG1(RIP_WARNING, "Command Channel: Error 0x%x from ReadFile", Error);
break;
}
}
if (ActualLength < sizeof(ICA_COMMAND_HEADER)) {
RIPMSG1(RIP_WARNING, "Command Channel Thread bad length 0x%x",
ActualLength);
continue;
}
/*
* This is a Csrss thread with no desktop. It needs to grab a temporary one
* before calling into win32k.
*/
Status = STATUS_SUCCESS;
bRestoreDesktop = FALSE;
if (Command.Header.Command != ICA_COMMAND_BROKEN_CONNECTION && Command.Header.Command != ICA_COMMAND_SHADOW_HOTKEY) {
if (Command.Header.Command != ICA_COMMAND_DISPLAY_IOCTL || Command.DisplayIOCtl.DisplayIOCtlFlags & DISPLAY_IOCTL_FLAG_REDRAW) {
utudi.hThread = NULL;
utudi.drdRestore.pdeskRestore = NULL;
bRestoreDesktop = TRUE;
Status = NtUserSetInformationThread(NtCurrentThread(),
UserThreadUseActiveDesktop,
&utudi, sizeof(utudi));
}
}
if (NT_SUCCESS(Status)) {
switch (Command.Header.Command) {
case ICA_COMMAND_BROKEN_CONNECTION:
/*
* broken procedure
*/
Status = BrokenConnection(
Command.BrokenConnection.Reason,
Command.BrokenConnection.Source);
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING, "BrokenConnection failed with Status 0x%x", Status);
}
break;
case ICA_COMMAND_REDRAW_RECTANGLE:
/*
* setfocus ???
*/
if (ActualLength < sizeof(ICA_COMMAND_HEADER) + sizeof(ICA_REDRAW_RECTANGLE)) {
RIPMSG1(RIP_WARNING, "Command Channel: redraw rect bad length %d", ActualLength);
break;
}
Status = NtUserRemoteRedrawRectangle(
Command.RedrawRectangle.Rect.Left,
Command.RedrawRectangle.Rect.Top,
Command.RedrawRectangle.Rect.Right,
Command.RedrawRectangle.Rect.Bottom);
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING, "NtUserRemoteRedrawRectangle failed with Status 0x%x", Status);
}
break;
case ICA_COMMAND_REDRAW_SCREEN: // setfocus
Status = NtUserRemoteRedrawScreen();
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING, "NtUserRemoteRedrawScreen failed with Status 0x%x", Status);
}
break;
case ICA_COMMAND_STOP_SCREEN_UPDATES: // killfocus
Status = NtUserRemoteStopScreenUpdates();
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING, "NtUserRemoteStopScreenUpdates failed with Status 0x%x", Status);
} else {
IO_STATUS_BLOCK IoStatus;
NtDeviceIoControlFile(
bShadowCommandChannel ? G_DupConsoleShadowVideoChannel
: G_DupIcaVideoChannel,
NULL,
NULL,
NULL,
&IoStatus,
IOCTL_VIDEO_ICA_STOP_OK,
NULL,
0,
NULL,
0);
}
break;
case ICA_COMMAND_SHADOW_HOTKEY: // shadow hotkey
Status = ShadowHotkey();
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING, "ShadowHotkey failed with Status 0x%x", Status);
}
break;
case ICA_COMMAND_DISPLAY_IOCTL:
Status = NtUserCtxDisplayIOCtl(
Command.DisplayIOCtl.DisplayIOCtlFlags,
&Command.DisplayIOCtl.DisplayIOCtlData[0],
Command.DisplayIOCtl.cbDisplayIOCtlData);
if (!NT_SUCCESS(Status)) {
RIPMSG1(RIP_WARNING, "NtUserCtxDisplayIOCtl failed with Status 0x%x", Status);
}
break;
default:
RIPMSG1(RIP_WARNING, "Command Channel: Bad Command 0x%x", Command.Header.Command);
break;
}
/*
* Release the temporary desktop.
*/
if (bRestoreDesktop) {
NTSTATUS retStatus;
retStatus = NtUserSetInformationThread(NtCurrentThread(),
UserThreadUseDesktop,
&utudi,
sizeof(utudi));
}
}
}
if (!bShadowCommandChannel) {
/*
* Close command channel LPC port if there is one.
*/
if (WinStationIcaApiPort) {
NtClose(WinStationIcaApiPort);
WinStationIcaApiPort = NULL;
}
}
// We have to close the commandchannel handle here
if (hChannel != NULL) {
NtClose(hChannel);
}
// We have to close the relevant Video Channel here
hChannelToClose = ( bShadowCommandChannel ? G_DupConsoleShadowVideoChannel : G_DupIcaVideoChannel );
if (hChannelToClose != NULL) {
NtClose(hChannelToClose);
}
UserExitWorkerThread(STATUS_SUCCESS);
return STATUS_SUCCESS;
}