Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

workaround for MSTSC window minimization curse

248 views
Skip to first unread message

Andrey

unread,
Nov 27, 2008, 1:29:05 PM11/27/08
to
I have studied the specs for RDP (which are open and available for
download from microsoft website) - and it seems that there is a
virtual possibility to workaround the well-known problem of minimizing
RDP window (which might cause application failures due to the fact
that server secures remote desktop state disallowing Input-related
APIs like GetCursorPos - actually I think it's just a bug, minimizing
client windows must not have negative impact on remote session).

From protocol description in MS-RDPBCGR.pdf and from rdesktop sources
it seems that when client window minimizes mstsc.exe sends window
update control message to server to say that it is not interested in
screen updates - this is called "output suppression". In this case
server becomes silent unless client window restores and output
suppression is disabled. My guess is that output suppression
implementation on server somehow changes desktop (impact is similar to
screen-lock) and that causes some APIs to stop working for
applications in this session. So, disabling output suppression
capability (either on client, or on the server) might be the cure.

Server defines a set of capabilities - and "Output Suppression" is one
of them. I think that mstsc reads them during session initialization.
Thus theoretically if server exposes that capability to be configured
- disabling it might be a workaround.

I searched through Terminal Services config in gpedit.msc, WMI and
registry but was not able to find this setting.Does anyone know
whether such setting exists and how to access it? Maybe
programatically?

And there is a registry value HKEY_LOCAL_MACHINE\SYSTEM
\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\CfgDll
that is set to RDPCFGEX.DLL. This library exports the following
methods:

1 0 000012B7 ExGetCfgVersionInfo
2 1 000012C2 ExtEncryptionLevels
3 2 0000115A ExtEnd
4 3 000012DC ExtGetCapabilities
5 4 000011B6 ExtGetEncryptionLevelAndDescrEx
6 5 00001160 ExtGetEncryptionLevelDescr
7 6 0000139E ExtGetSecurityLayerDescrString
8 7 00001308 ExtGetSecurityLayerName
9 8 000012E5 ExtSecurityLayers
10 9 00001152 ExtStart

I though this might be used to control caps, but it is not documented.

-- Andrey

jolteroli

unread,
Nov 27, 2008, 4:26:42 PM11/27/08
to
"Andrey" <andrey.f...@gmail.com> schrieb im Newsbeitrag
news:205f891d-ae0e-4f7e...@h20g2000yqn.googlegroups.com...

>I have studied the specs for RDP (which are open and available for
> download from microsoft website) - and it seems that there is a
> virtual possibility to workaround the well-known problem of minimizing
> RDP window (which might cause application failures due to the fact
> that server secures remote desktop state disallowing Input-related
> APIs like GetCursorPos - actually I think it's just a bug, minimizing
> client windows must not have negative impact on remote session).

Just curious: Does GetCursorPos return false in a "minimized session"?


unsigned long ExtGetCapabilities()
{
return 0x7F;
}

> 5 4 000011B6 ExtGetEncryptionLevelAndDescrEx
> 6 5 00001160 ExtGetEncryptionLevelDescr
> 7 6 0000139E ExtGetSecurityLayerDescrString
> 8 7 00001308 ExtGetSecurityLayerName
> 9 8 000012E5 ExtSecurityLayers
> 10 9 00001152 ExtStart
>
> I though this might be used to control caps, but it is not documented.

The capabilities are well known when compiling the terminal server component
binaries, so I guess they are builtin.
Also, the exports seem to Get the configuration, not to Set them. No file in
the system32 contains the string "rdpcfgex.dll". Hence the library isn't use
(anymore). Guess it's there for a legacy reason still.

strings -f -a -e S * | grep rdpcfgex.dll

But hey, rdesktop is gpl'ed, you could comment off the calls to
rdp_send_client_window_status in rdesktop-1.6.0/xwin.c:2549:

case MapNotify:
if (!g_seamless_active)
rdp_send_client_window_status(1);
break;
case UnmapNotify:
if (!g_seamless_active)
rdp_send_client_window_status(0);
break;

so the RDP_DATA_PDU_CLIENT_WINDOW_STATUS isn't send. Test the application
behaviour with this new rdesktop.

-jolt

Andrey

unread,
Nov 28, 2008, 7:59:29 AM11/28/08
to
On Nov 27, 11:26 pm, "jolteroli" <jolt1...@gmx.net> wrote:
> "Andrey" <andrey.fedyas...@gmail.com> schrieb im Newsbeitragnews:205f891d-ae0e-4f7e...@h20g2000yqn.googlegroups.com...

>
> >I have studied the specs for RDP (which are open and available for
> > download from microsoft website) - and it seems that there is a
> > virtual possibility to workaround the well-known problem of minimizing
> > RDP window (which might cause application failures due to the fact
> > that server secures remote desktop state disallowing Input-related
> > APIs like GetCursorPos - actually I think it's just a bug, minimizing
> > client windows must not have negative impact on remote session).
>
> Just curious: Does GetCursorPos return false in a "minimized session"?
>

Yes, it does; and GetLastError() is 0.
In general - remote session's behavior in case of mstsc's minimization
is similar to as if the desktop became locked. Any idea why TS server
does so?
On a locked session those APIs also do not work - and the
justification is that winlogon desktop takes over which is protected
(weird thing is that SetCursorPos works under lock; so what is the
difference between SetCursorPos and GetCursorPos from security point
of view?)

Discussion groups have many posts related to this RDP minimization
issue:
http://rubyforge.org/pipermail/wtr-general/2006-December/008472.html
http://groups.google.com/group/microsoft.public.win2000.termserv.clients/browse_thread/thread/45252f2b81ed3dd8?hl=ru&q=RDP+minimize
http://groups.google.com/group/watir-general/browse_thread/thread/8e3b4af91a667683?hl=ru&q=RDP+minimize
http://groups.google.com/group/microsoft.public.dotnet.framework.windowsforms/browse_thread/thread/189b4f58aa2bbc82?hl=ru&q=RDP+minimize

Currently, I personally met with two APIs that stop doing their job:
GetCursorPos and mouse_event.

Possibly, it is loaded dynamically. After posting my question I did
some investigation about this DLL
and understood that it is not what I wanted. Thanks for clarifying it
further.

> But hey, rdesktop is gpl'ed, you could comment off the calls to
> rdp_send_client_window_status in rdesktop-1.6.0/xwin.c:2549:
>
>     case MapNotify:
>         if (!g_seamless_active)
>             rdp_send_client_window_status(1);
>         break;
>     case UnmapNotify:
>         if (!g_seamless_active)
>             rdp_send_client_window_status(0);
>         break;
>
> so the RDP_DATA_PDU_CLIENT_WINDOW_STATUS isn't send. Test the application
> behaviour with this new rdesktop.
>
> -jolt

Sure, you are right. Others were already doing similar changes:
http://osdir.com/ml/network.rdesktop.devel/2007-10/msg00000.html
This is a very good alternative (and the only thing I can do in this
circumstances); but in the first place we are interested in having
similar possibility in MSTSC.
I also tried to workaround it in code (avoid using GetCursorPos, try
GetCursorInfo instead) - but it is rather difficult as there is no
list of functions that do not work.

-- Andrey

jolteroli

unread,
Nov 28, 2008, 12:06:46 PM11/28/08
to
Im not sure, but i think GetCursorPos fails, because the Terminalserver
maintains 3 desktops:

1.) Logon
2.) Interactive Desktop
3.) Disconnected Desktop

For sure when disconnected and perhaps when output suppression is active,
the server switches to the "disconnected desktop".

Have a look here:
http://www.microsoft.com/msj/1298/terminalserver/terminalserver.aspx
(Windowstations and Desktops )

Again curious: What kinda application does use Get/SetCursorPos? In my early
days, we have coded4fun with the Glide API for the 3Dfx Voodoo Cards. We
have hidden the cursor and got the mouse dx/dy only by the Get/Set calls, so
we had the free look with the mouse, like in Quake3 and such games.

Shouldn't workarounding the "bug" this way work?

// current and center coordinates.
// where mpt is already set to the center and is updated on WM_RESIZE
msgs.
POINT pt, mpt;

if (!GetCursorPos(pt)) {
// Error means no mouse movement happend!
dx = dy = 0;
} else {
// Get deltas'n'update
dx = pt.x - mpt.x;
dy = pt.y - mpt.y;
// set cursor back into the center for next delta.
SetCursorPos(mpt);
}

// Go on with dx,dy...

-jolt

Andrey

unread,
Nov 30, 2008, 12:23:32 PM11/30/08
to
On Nov 28, 7:06 pm, "jolteroli" <jolt1...@gmx.net> wrote:
> Im not sure, but i think GetCursorPos fails, because the Terminalserver
> maintains 3 desktops:
>
> 1.) Logon
> 2.) Interactive Desktop
> 3.) Disconnected Desktop
>
> For sure when disconnected and perhaps when output suppression is active,
> the server switches to the "disconnected desktop".
>

I think that if this is something that breaks applications running in
this session - then server shouldn't have done that. Why would apps
have to depend on whether remote user has minimized his client screen
or disconnected?

> Have a look here:http://www.microsoft.com/msj/1298/terminalserver/terminalserver.aspx
> (Windowstations and Desktops )
>
> Again curious: What kinda application does use Get/SetCursorPos? In my early
> days, we have coded4fun with the Glide API for the 3Dfx Voodoo Cards. We
> have hidden the cursor and got the mouse dx/dy only by the Get/Set calls, so
> we had the free look with the mouse, like in Quake3 and such games.

I think the answer is quite simple - GetCursorPos is an easy to use
function that tells the cursor position on the screen.
Also I can add that it is a must have function for applications
performing mouse and keyboard input generation (like for example
automated functional/UI testing tools).
I am trying to see whether GetCursorInfo can be used as a workaround -
but not sure whether it works reliably in the same conditions.

>
> Shouldn't workarounding the "bug" this way work?
>
>     // current and center coordinates.
>     // where mpt is already set to the center and is updated on WM_RESIZE
> msgs.
>     POINT pt, mpt;
>
>     if (!GetCursorPos(pt)) {
>         // Error means no mouse movement happend!
>         dx = dy = 0;
>     } else {
>         // Get deltas'n'update
>         dx = pt.x - mpt.x;
>         dy = pt.y - mpt.y;
>         // set cursor back into the center for next delta.
>         SetCursorPos(mpt);
>     }
>
>     // Go on with dx,dy...
>
> -jolt

I didn't quite understand this workaround.. You assume that
GetCursorPos failure indicates that there was no mouse movement? Why?

jolteroli

unread,
Dec 1, 2008, 1:07:04 PM12/1/08
to

"Andrey" <andrey.f...@gmail.com> schrieb im Newsbeitrag
news:6ff3c5a5-b75e-49d4...@k19g2000yqg.googlegroups.com...

> On Nov 28, 7:06 pm, "jolteroli" <jolt1...@gmx.net> wrote:
>> Im not sure, but i think GetCursorPos fails, because the Terminalserver
>> maintains 3 desktops:
>>
>> 1.) Logon
>> 2.) Interactive Desktop
>> 3.) Disconnected Desktop
>>
>> For sure when disconnected and perhaps when output suppression is active,
>> the server switches to the "disconnected desktop".
>>
>
> I think that if this is something that breaks applications running in
> this session - then server shouldn't have done that. Why would apps
> have to depend on whether remote user has minimized his client screen
> or disconnected?

Actually the whole design of gui programs in Windows is to be event driven.
On user action, the program will get the message and act on that. This won't
happen if the mstsc window is minimized, so it should not be a problem when
the session switches to the discon-desktop, FOR USUAL APPLICATIONS. No
event, no action. Guess the disconnected desktop doesn't have a cursor...

>> Have a look
>> here:http://www.microsoft.com/msj/1298/terminalserver/terminalserver.aspx
>> (Windowstations and Desktops )
>>
>> Again curious: What kinda application does use Get/SetCursorPos? In my
>> early
>> days, we have coded4fun with the Glide API for the 3Dfx Voodoo Cards. We
>> have hidden the cursor and got the mouse dx/dy only by the Get/Set calls,
>> so
>> we had the free look with the mouse, like in Quake3 and such games.
>
> I think the answer is quite simple - GetCursorPos is an easy to use
> function that tells the cursor position on the screen.
> Also I can add that it is a must have function for applications
> performing mouse and keyboard input generation (like for example
> automated functional/UI testing tools).
> I am trying to see whether GetCursorInfo can be used as a workaround -
> but not sure whether it works reliably in the same conditions.

Aha, ok. May be the GetCursorInfo succeed... it's worth a try, anyway!

>> Shouldn't workarounding the "bug" this way work?
>>
>> // current and center coordinates.
>> // where mpt is already set to the center and is updated on WM_RESIZE
>> msgs.
>> POINT pt, mpt;
>>
>> if (!GetCursorPos(pt)) {
>> // Error means no mouse movement happend!
>> dx = dy = 0;
>> } else {
>> // Get deltas'n'update
>> dx = pt.x - mpt.x;
>> dy = pt.y - mpt.y;
>> // set cursor back into the center for next delta.
>> SetCursorPos(mpt);
>> }
>>
>> // Go on with dx,dy...
>>
>> -jolt
>
> I didn't quite understand this workaround.. You assume that
> GetCursorPos failure indicates that there was no mouse movement? Why?

This were a workaround for playing Q3-like games on the disconnected desktop
:D If there is no cursor, it can't have moved! But this example has nothing
to do with your program design. You rely on getting the exact position.

May be you are better off, when you contact microsoft support.

-jolt

Andrey

unread,
Dec 10, 2008, 10:22:11 AM12/10/08
to
On Dec 1, 8:07 pm, "jolteroli" <jolt1...@gmx.net> wrote:
> "Andrey" <andrey.fedyas...@gmail.com> schrieb im Newsbeitragnews:6ff3c5a5-b75e-49d4...@k19g2000yqg.googlegroups.com...

>
>
>
> > On Nov 28, 7:06 pm, "jolteroli" <jolt1...@gmx.net> wrote:
> >> Im not sure, but i think GetCursorPos fails, because the Terminalserver
> >> maintains 3 desktops:
>
> >> 1.) Logon
> >> 2.) Interactive Desktop
> >> 3.) Disconnected Desktop
>
> >> For sure when disconnected and perhaps when output suppression is active,
> >> the server switches to the "disconnected desktop".
>
> > I think that if this is something that breaks applications running in
> > this session - then server shouldn't have done that. Why would apps
> > have to depend on whether remote user has minimized his client screen
> > or disconnected?
>
> Actually the whole design of gui programs in Windows is to be event driven.
> On user action, the program will get the message and act on that. This won't
> happen if the mstsc window is minimized, so it should not be a problem when
> the session switches to the discon-desktop, FOR USUAL APPLICATIONS. No
> event, no action. Guess the disconnected desktop doesn't have a cursor...
>

Sure, but usual applications might also have a timer and use
GetCursorPos on WM_TIMER messages.

I understood, it allows player to connect and disconnect without
leaving the game - the player just stands still and probably dies from
a headshot :)

>
> May be you are better off, when you contact microsoft support.
>
> -jolt

I found this link which summarizes information that I've collected
this far:
http://www.mjtnet.com/msfaq171.htm
seems like those guys had the same issues with tools that generate
mouse/keyboard input.

-- Andrey

jolteroli

unread,
Dec 10, 2008, 4:39:39 PM12/10/08
to
> Sure, but usual applications might also have a timer and
> use GetCursorPos on WM_TIMER messages.

Such coders probably take a lot of drugs, like they do in Fear & Loathing in
Las Vegas.

> I understood, it allows player to connect and disconnect
> without leaving the game - the player just stands still and
> probably dies from a headshot :)

Certainly, the player is protected while that. I'm currently in negotiations
with EA, no details on that ;)

And anyway gd' luck with the "bug"

-jolt

0 new messages