SetThreadDesktopMFC

In einem Programm von mir muss ein Service mit dem User kommunizieren. In Windows Vista verhindert die Isolierung der Sitzung NULL das Darstellen der Benutzeroberfläche eines Treibers.

Auf meiner (erfolglosen 🙁 ) Suche, das zu umgehen experimenzierte ich mit den Windows API Funktionen SetProcessWindowStation und SetThreadDesktop.

Dabei fiel mir auf, das SetThreadDesktop immer mit Fehler „The requested resource is in use“ (ERROR_BUSY == 170) abbrach. In der Dokumentation von SetThreadDesktop schreibt Microsoft, dass die Funktion fehschlägt, wenn der Thread bereits ein GDI Objekt oder einen Hook im aktiven Desktop hat.

Mein Programm rief SetThreadDesktop direkt am Start der AFX_THREADPROC auf. Zu dem Zeitpunkt hatte es weder GDI-Objekte noch Hooks angelegt. 😕 Nach ewigem Suchen fand ich hier die Ursache des Problems.

Die MFC installiert bei Erstellen eines neuen Threads mittels SetWindowsHookEx in der Funktion AfxInitThread einen Message Filter Hook. Der ist bei Aufruf der Thread Start Routine bereits aktiv und verhindert den Erfolg von SetThreadDesktop.

Ich habe darauf hin folgenden SetThreadDesktop Wrapper für die MFC geschrieben:

//////////////////////////////////////////////////////////////////////////////
// SetThreadDesktop fails in MFC because _AfxMsgFilterHook is used in every
// Thread. SetThreadDesktopMFC unhooks, calls SetThreadDesktop and then
// Sets the Hook again to MsgFilter that is the same as _AfxMsgFilterHook
// (VC6 to VS2005)
//////////////////////////////////////////////////////////////////////////////

#include "Ddeml.h"
LRESULT CALLBACK MsgFilter(int code, WPARAM wParam, LPARAM lParam)
{

  CWinThread* pThread;
  if (
afxContextIsDLL || (code < 0 && code != MSGF_DDEMGR) ||
    (
pThread = AfxGetThread()) == NULL)
  {
    return ::
CallNextHookEx(_afxThreadState->m_hHookOldMsgFilter, code,
                            wParam, lParam);
  }

  ASSERT(pThread != NULL);
  return (
LRESULT)pThread->ProcessMessageFilter(code, (LPMSG)lParam);
}


//////////////////////////////////////////////////////////////////////////////
// SetThreadDesktopMFC
//////////////////////////////////////////////////////////////////////////////

BOOL SetThreadDesktopMFC(HDESK hDesk)
{

  _AFX_THREAD_STATE *pState = AfxGetThreadState();
  BOOL bReHook = UnhookWindowsHookEx(pState->m_hHookOldMsgFilter);
  pState->m_hHookOldMsgFilter = NULL;
  BOOL bRet=SetThreadDesktop(hDesk);
  if (!
bRet)
    DBGTrace1("SetThreadDesktopMFC failed: %s",GetLastErrorName());
  if (
bReHook)
    pState->m_hHookOldMsgFilter = SetWindowsHookEx(WH_MSGFILTER, MsgFilter,
                                                   NULL, GetCurrentThreadId());
  return
bRet;
}

SetThreadDesktopMFC entfernt den vorhandenen Hook, ruft SetThreadDesktop auf und setzt den Hook wieder.

Die originale _AfxMsgFilterHook Funktion musste ich CopyPasten, weil MFC die nicht exportiert. _AfxMsgFilterHook hat sich seit Visual Studio 6 nicht geändert.

DBGTrace1 ist ein MACRO, das mir eine Meldung in den Debug-Log schreibt. GetLastErrorName liefert einen String für den Wert den GetLastError() liefert.

8 Reaktionen zu “SetThreadDesktopMFC”

  1. Sven

    Lässt sich die Codeansicht dazu überreden, die größer/kleiner-Zeichen normal anzuzeigen und nicht als html-Code?

  2. Kay

    Scheint nicht so! 🙁 WYSIWYNG 😉
    Wordpress murkelt im <pre>-Block leider kräftig rum.
    Ich muss wohl weiter nach einem guten Syntax-Highlighter suchen…

    UPDATE: Ich habe den Syntax-Highlighter rausgeworfen und stelle per CSS <pre>…</pre> Blöcke jetzt in eigenem Stil mit „overflow: auto;“ dar. Damit geht’s, wenn auch ohne Syntax-Farben. :mrgreen:

  3. Sven

    Bei mir ist der CodeViewer im Einsatz. Guck‘ Dir mal die Beiträge vom Januar 2005 an, da siehst Du ihn. 🙂

  4. Kay

    WordPress 2.1 oder TinyMCE schmeißen die CodeViewer HTML-Tags raus. So wird aus ‚<viewcode src=“Code.cpp“ />‘, automatisch ‚<viewcode> <viewcode/>‘. 🙁
    Ich habe momentan zu wenig Zeit, dem auf den Grund zu gehen und belasse den Krams bei der <pre> <pre/> Lösung.
    Nachtrag: Ich habe einen Weg gefunden, die mit VisualAssist verschönerten Farben meines VC6 von RTF nach HTML zu wandeln, wie oben zu sehen…Das werde ich so lassen 🙂

  5. Sven

    Wenn ich mich recht erinnere, dann hattest Du auch schon in TPW recht außergewöhnliche Farben für das Syntaxhighlighting. 😀

  6. Kay

    Ja, manche Sachen ändern sich nie! 😀

  7. Håkan Carlström

    I have modified the CodeViewer to version 1.4.3 now and it works with WYSIWYG-editors and offers highlighing too.
    Take a look at http://www.familjencarlstrom.se/WordPress/?p=141

    /Håkan C

  8. Kay

    Thanks for the Hint! 🙂
    I’ll try it out on my next post that includes source code.

Einen Kommentar schreiben

Time limit is exhausted. Please reload the CAPTCHA.