Desktops on Windows ultimately broken by every other application using IsWorkstationLocked
Sunday, March 21, 2010 3:05:04 AM
There is a nice few particularly EPIC FAILures in Windows API applications ecosystem that make use of a certain features a pain in the arse, but this one just completely disables the feature of multiple desktops for each and every session.
Symptoms
You have decided to use some software that uses separated desktop. Attempt to switch to desktop other than "default" (the one with TaskBar) succeeds. But only for a fraction of second, or just a few seconds. Then the default desktop restores for no apparent reason... Unfortunately this problem affects not only my recently released Supervisor application, but also tools like Desktops from Mark Russinovich himself.
Two years ago I traced this issue to Miranda IM. A simple patch which I contributed was almost immediately accepted, and for a while it was all good. Few days ago I found out that on my new Windows 7 computer, with many applications installed, I am yet again unable to use desktops. First step was to shutdown Miranda, then other program, and another, but the problem remains. Today, I still don't know, what program causes the problem. I'll let you know when I find out, but I bet you are curious about something else.
Cause
The original WRONG code appeared at some point in 2001 and might be even older. From that point almost every programmer, who wanted to determine whether the workstation is locked, copied, pasted and used the following code:
function IsWorkstationLocked: Boolean;
var
hDesktop: HDESK;
begin
Result := False;
hDesktop := OpenDesktop('defualt', 0, False, DESKTOP_SWITCHDESKTOP);
if hDesktop <> 0 then
begin
Result := not SwitchDesktop(hDesktop);
CloseDesktop(hDesktop);
end;
end;
This code is WRONG. Do not use it! See better solution below!Please, take a few seconds and look at the code. Do you see what exactly is wrong? You probably do because of the context of this article. The original author probably thought to himself: Workstation locks down to Logon desktop. And SwitchDesktop fails when on Logon desktop. Thus when SwitchDesktop fails, the workstation must be locked. This reasoning is flawed. It misses the important fact, which you now definitely see, that the workstation could be switched to different desktop than "default". Although it still returns the correct value, as a side effect, it switches back to default desktop.
Intermezzo: I was going to list here a lot of links where someone advises to use that wrong code, but if you are interested, just google for "IsWorkstationLocked", almost ALL have it wrong. You will find it even on the stackoverflow.com. Who knows how many applications use this code.
Fix
The CORRECT code is similar in nature to the first one. But instead of opening "default" desktop and trying to switch to it, we just try to open current desktop. And since the Logon desktop is secured, the system won't let us open it. The corrected version of IsWorkstationLocked has thus one less function call and is even simpler.
bool IsWorkstationLocked () {
if (HDESK hDesk = OpenInputDesktop (0, FALSE, DESKTOP_SWITCHDESKTOP)) {
CloseDesktop (hDesk);
return false;
} else
return true;
}
This is the CORRECT code. Fix your application if you have been using the previous one!Solution
But. Presenting correct code and sending patches to open-source applications may help improve future development, it won't fix the current state. And the current state is that tools that create/use other desktops are unusable if you are not lucky enough.
I really don't see how could be this mess fixed without intervention from Microsoft. There are few options I can think of, each and every having its pros and cons.
- Add a AllowSwitchToDefaultDesktop API function, which would have an application have to call, before it would be able to switch to default desktop. The con is obviously the backward compatibility. But the cost is not that great since there is only a few applications that use SwitchDesktop for its intended purpose.
- Add a compatibility shim that would cause SwitchDesktop not to switch yet still return the expected value. But this way, the compatibility team would have to examine all the applications that use SwitchDesktop whether they do it right or wrong.
- Do nothing. Which will most likely be done.
Conclusion
...is that I don't really have one. If you really need the IsWorkstationLocked function or know someone who does, make sure that you/they use the correct version. Otherwise you might be later unable to use some cool application.
Update 27.3.2010
As I finally found out, the problem was caused by DisplayFusion (3.1.8 version only) ...great program by the way, with great support. The second day after I reported this bug, Jon Tackabury posted a fixed beta version. As if it were just for me :)

