VBoxVRDP.cpp revision 74804912a237136f06d0b49682a119577135902b
/* $Id$ */
/** @file
* VBoxVRDP - VBox VRDP connection notification
*/
/*
* Copyright (C) 2006-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/* 0x0501 for SPI_SETDROPSHADOW */
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include "VBoxTray.h"
#include "VBoxHelpers.h"
#include "VBoxVRDP.h"
#include <VBoxGuestInternal.h>
/* The guest receives VRDP_ACTIVE/VRDP_INACTIVE notifications.
*
* When VRDP_ACTIVE is received, the guest asks host about the experience level.
* The experience level is an integer value, different values disable some GUI effects.
*
* On VRDP_INACTIVE the original values are restored.
*
* Note: that this is not controlled from the client, that is a per VM settings.
*
* Note: theming is disabled separately by EnableTheming.
*/
#define VBOX_SPI_STRING 0
#define VBOX_SPI_BOOL_PTR 1
#define VBOX_SPI_BOOL 2
#define VBOX_SPI_PTR 3
static ANIMATIONINFO animationInfoDisable =
{
sizeof (ANIMATIONINFO),
};
typedef struct _VBoxExperienceParameter
{
const char *name;
int type;
void *pvDisable;
static VBoxExperienceParameter parameters[] =
{
};
{
int i;
for (i = 0; i < RT_ELEMENTS(parameters); i++)
{
{
/*
* The parameter has to be disabled.
*/
/* Save the current value. */
switch (parameters[i].type)
{
case VBOX_SPI_STRING:
{
/* The 2nd parameter is size in characters of the buffer.
* The 3rd parameter points to the buffer.
*/
0);
} break;
case VBOX_SPI_BOOL:
case VBOX_SPI_BOOL_PTR:
{
/* The 3rd parameter points to BOOL. */
0,
0);
} break;
case VBOX_SPI_PTR:
{
/* The 3rd parameter points to the structure.
* The cbSize member of this structure must be set.
* The uiParam parameter must alos be set.
*/
{
Log(("VBoxTray: vboxExperienceSet: Not enough space %d > %d\n", parameters[i].cbSavedValue, sizeof (parameters[i].achSavedValue)));
break;
}
0);
} break;
default:
break;
}
/* Disable the feature. */
switch (parameters[i].type)
{
case VBOX_SPI_STRING:
{
/* The 3rd parameter points to the string. */
0,
parameters[i].pvDisable,
} break;
case VBOX_SPI_BOOL:
{
/* The 2nd parameter is BOOL. */
NULL,
} break;
case VBOX_SPI_BOOL_PTR:
{
/* The 3rd parameter is NULL to disable. */
0,
NULL,
} break;
case VBOX_SPI_PTR:
{
/* The 3rd parameter points to the structure. */
0,
parameters[i].pvDisable,
} break;
default:
break;
}
}
}
}
{
int i;
for (i = 0; i < RT_ELEMENTS(parameters); i++)
{
{
/* Restore the feature. */
switch (parameters[i].type)
{
case VBOX_SPI_STRING:
{
/* The 3rd parameter points to the string. */
0,
} break;
case VBOX_SPI_BOOL:
{
/* The 2nd parameter is BOOL. */
NULL,
} break;
case VBOX_SPI_BOOL_PTR:
{
/* The 3rd parameter is NULL to disable. */
0,
} break;
case VBOX_SPI_PTR:
{
/* The 3rd parameter points to the structure. */
0,
} break;
default:
break;
}
}
}
}
typedef struct _VBOXVRDPCONTEXT
{
const VBOXSERVICEENV *pEnv;
static VBOXVRDPCONTEXT gCtx = {0};
{
Log(("VBoxTray: VBoxVRDPInit\n"));
{
}
else
{
gCtx.pfnEnableTheming = 0;
}
*pfStartThread = true;
*ppInstance = &gCtx;
return VINF_SUCCESS;
}
{
Log(("VBoxTray: VBoxVRDPDestroy\n"));
return;
}
/**
* Thread function to wait for and process mode change requests
*/
{
bool fTerminate = false;
maskInfo.u32NotMask = 0;
if (DeviceIoControl (gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL))
{
Log(("VBoxTray: VBoxVRDPThread: DeviceIOControl(CtlMask - or) succeeded\n"));
}
else
{
Log(("VBoxTray: VBoxVRDPThread: DeviceIOControl(CtlMask) failed\n"));
return 0;
}
do
{
/* wait for the event */
if (DeviceIoControl(gVBoxDriver, VBOXGUEST_IOCTL_WAITEVENT, &waitEvent, sizeof(waitEvent), &waitEvent, sizeof(waitEvent), &cbReturned, NULL))
{
Log(("VBoxTray: VBoxVRDPThread: DeviceIOControl succeeded\n"));
/* are we supposed to stop? */
break;
Log(("VBoxTray: VBoxVRDPThread: checking event\n"));
/* did we get the right event? */
{
/* Call the host to get VRDP status and the experience level. */
if (DeviceIoControl (gVBoxDriver,
sizeof(VMMDevVRDPChangeRequest),
sizeof(VMMDevVRDPChangeRequest),
&cbReturned, NULL))
{
Log(("VBoxTray: VBoxVRDPThread: u8VRDPActive = %d, level %d\n", vrdpChangeRequest.u8VRDPActive, vrdpChangeRequest.u32VRDPExperienceLevel));
{
&& pCtx->pfnEnableTheming
&& pCtx->pfnIsThemeActive)
{
if (pCtx->fSavedThemeEnabled)
{
}
}
}
else
{
&& pCtx->pfnEnableTheming
&& pCtx->pfnIsThemeActive)
{
if (pCtx->fSavedThemeEnabled)
{
/* @todo the call returns S_OK but theming remains disabled. */
}
}
}
}
else
{
Log(("VBoxTray: VBoxVRDPThread: Error from DeviceIoControl VBOXGUEST_IOCTL_VMMREQUEST\n"));
/* sleep a bit to not eat too much CPU in case the above call always fails */
{
fTerminate = true;
break;
}
}
}
}
else
{
Log(("VBoxTray: VBoxVRDPThread: Error from DeviceIoControl VBOXGUEST_IOCTL_WAITEVENT\n"));
/* sleep a bit to not eat too much CPU in case the above call always fails */
{
fTerminate = true;
break;
}
}
} while (!fTerminate);
if (DeviceIoControl (gVBoxDriver, VBOXGUEST_IOCTL_CTL_FILTER_MASK, &maskInfo, sizeof (maskInfo), NULL, 0, &cbReturned, NULL))
{
Log(("VBoxTray: VBoxVRDPThread: DeviceIOControl(CtlMask - not) succeeded\n"));
}
else
{
Log(("VBoxTray: VBoxVRDPThread: DeviceIOControl(CtlMask) failed\n"));
}
Log(("VBoxTray: VBoxVRDPThread: Finished VRDP change request thread\n"));
return 0;
}