SwitchDesktop() verhindern

Ein SuRun Benutzer schrieb mir, das er den sicheren Desktop immer nur kurz zu sehen bekam. Nach wenigen Sekunden war der Windows Desktop wieder da. Er fand auch heraus, dass die Ursache „schedhlp.exe“ von Acronis True Image 11 Home ist. Ohne schedhlp lief SuRun problemlos.

Nach kurzem „hinsehen“ wurde mir klar, das schedhlp regelmäßig SwitchDesktop() benutzt.

Eine Suche nach „opendesktop default switchdesktop“ erstaunte mich arg! Microsoft selbst veröffentlicht Source Code, wie man herausfindet, ob Bildschirmschoner oder Anmeldebildschirm aktiviert sind. Die SuperNasen schlagen tatsächlich vor, folgendes zu benutzen:

bool IsNotLocked()
{
  IntPtr hdt = OpenDesktop("Default", 0, false, AccessUnlocked);
  // If we can make the switch, the desktop is not locked
  if (SwitchDesktop(hdt))
    return true;
  return false;
}

…immer, wenn man glaubt, dümmer wird’s nicht mehr… 👿

Dieser „Sample code“ hat wohl einen Programmierer bei Acronis veranlasst, sein Hirn abzuschalten und Ähnliches zu schreiben.

Bisher war ich begeistert von Acronis True Image…

Nun ja. Das Positive an Enttäuschung ist ja, das die Täuschung hinterher weg ist 😉

Desktop-Manager-Software könnte man so nicht benutzen, weil irgend ein Programm ständig auf den „Default“ Desktop schaltet, nur um herauszufinden, ob der Bildschirmschoner läuft.

Ich habe also selbst folgendes kleine Programm geschrieben, um SuRun zu ärgern:

#include <windows.h>

DWORD WINAPI MsgProc(LPVOID)
{
  MessageBox(0,
    "Wenn nicht mehr auf Desktop \\"Default\\"\\n"
    "geschaltet werden soll, drücken Sie OK.",
    "SwitchDesktop",MB_OK);
  ExitProcess(0);
  return 0;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
  CreateThread(0,0,MsgProc,0,0,0);
  HDESK d=OpenDesktop("Default",0,0,DESKTOP_SWITCHDESKTOP);
  for(;;Sleep(5000))
    SwitchDesktop(d);
  CloseDesktop(d);
  return 0;
}

Damit schalte ich alle fünf Sekunden auf den Standard-Desktop um.

SuRun sollte nun versuchen, dass zu verhindern.

Laut Microsoft braucht man zum Umschalten auf einen Desktop nicht viel. Der Prozess muss in der selben (sichtbaren!) WindowStation sein, Zugriff auf den Desktop haben und es dürfen weder Bildschirmschoner noch Anmeldebildschirm aktiv sein. All das ist normalerweise für jeden Benutzerprozess der Fall.

Leider verrät Microsoft nicht, wie Bildschirmschoner und Anmeldebildschirm verhindern, das SwitchDesktop funktioniert.

Auf meinem Irrweg zu einer Art Lösung entfernte den Logon-SID des angemeldeten Benutzers bei aktivem SuRun-Desktop einfach aus der DACL für den „Default“ Desktop. Damit war dem Benutzer der Zugriff auf „Default“ verwehrt… dachte ich. Aber mein kleines Programm schaltete weiterhin munter auf „Default“ zurück… HMMM! 😯

Der (Denk-)Fehler war leicht zu finden. Folgendes Programm konnte nicht auf „Default“ schalten:

#include <windows.h>

DWORD WINAPI MsgProc(LPVOID)
{
  MessageBox(0,
    "Wenn nicht mehr auf Desktop \\"Default\\"\\n"
    "geschaltet werden soll, drücken Sie OK.",
    "SwitchDesktop",MB_OK);
  ExitProcess(0);
  return 0;
}

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
  CreateThread(0,0,MsgProc,0,0,0);
  for(;;Sleep(5000))
  {
    HDESK d=OpenDesktop("Default",0,0,DESKTOP_SWITCHDESKTOP);
    SwitchDesktop(d);
    CloseDesktop(d);
  }
  return 0;
}

Der Unterschied liegt darin, dass das erste Programm sich das Desktop-Handle nur einmalig beim Start holt und während der Laufzeit nicht ändert. Das zweite Programm holt sich alle fünf Sekunden ein Desktop Handle.

Windows überprüft bei SwitchDesktop (und vielen anderen Funktionen die ein Handle benötigen) offensichtlich nur, ob das Handle mit den erforderlichen Rechten erzeugt wurde. Ist das der Fall, ist Wurscht, ob der Benutzer selbst Zugriff hat. Er hat ein Handle, also Zugriff.

DUMM! Damit ist SuRun draußen. Gegen vorhandene Handles kann ich nichts machen.

Ich habe bis jetzt keinen (dokumentierten) Weg gefunden, das Umschalten von SuRuns Desktop auf „Default“ zu verhindern. Also habe ich in SuRun ein Objekt eingebaut, das überwacht, ob der „Input Desktop“ SuRuns Namen trägt und das andernfalls auf SuRuns Desktop umschaltet.

class CStayOnDeskTop
{
public:
  CStayOnDeskTop(LPCTSTR DeskName)
  {
    m_DeskName=_tcsdup(DeskName);
    m_Thread=CreateThread(0,0,ThreadProc,this,0,0);
  }
  ~CStayOnDeskTop()
  {
    LPTSTR s=m_DeskName;
    m_DeskName=0;
    free(s);
    WaitForSingleObject(m_Thread,INFINITE);
  }
private:
  static DWORD WINAPI ThreadProc(void* p)
  {
    CStayOnDeskTop* t=(CStayOnDeskTop*)p;
    SetThreadPriority(t->m_Thread,THREAD_PRIORITY_IDLE);
    LPTSTR DeskName=_tcsdup(t->m_DeskName);
    while (t->m_DeskName)
    {
      HDESK d=OpenDesktop(t->m_DeskName,0,FALSE,DESKTOP_SWITCHDESKTOP);
      if (d!=0)
      {
        HDESK i=OpenInputDesktop(0,FALSE,DESKTOP_SWITCHDESKTOP);
        if (i!=0)
        {
          TCHAR n[MAX_PATH]={0};
          DWORD l=MAX_PATH;
          if (GetUserObjectInformation(i,UOI_NAME,n,l,&l))
            if (_tcscmp(n,DeskName))
              SwitchDesktop(d);
          CloseDesktop(i);
        }
        CloseDesktop(d);
      }
      Sleep(10);
    }
    free(DeskName);
    t->m_Thread=0;
    return 0;
  }
  LPTSTR m_DeskName;
  HANDLE m_Thread;
};

Das führt zwar zu einem evtl. flackernden Bildschirm, aber wenigstens kann man SuRun so benutzen.

Wenn ich mal wieder Zeit finde, werde ich versuchen, der WindowStation des Benutzers das Sichtbarkeits-Flag zu entziehen und SuRun auf einer eigenen WindowStation laufen zu lassen. Damit dürfte SwitchDesktop auf bei vorhandenem Desktop-Handle nicht funktionieren…aber wer weiß das schon genau…

Eine Reaktion zu “SwitchDesktop() verhindern”

  1. Rolf

    Der IBM Sametime-Client scheint ebenso von diesem Problem betroffen zu sein. Sie nutzen SwitchDesktop in ActivityMonitor.dll, um festzustellen ob der Desktop gesperrt ist.
    In Version 7.5 kann man sich behelfen, indem man die DLL umbenennt, in 8.x muss das Plugin com.ibm.collaboration.realtime.activitymonitor.win32.win32.x86_8.0.2.20090919-0400.jar gelöscht/in .jar.org umbenannt werden.

    Hier noch ein paar Suchbegriffe für englischsprachige Benutzer:
    Sametime forces default Desktop switch and steals focus

Einen Kommentar schreiben

Time limit is exhausted. Please reload the CAPTCHA.