Kiosk Applications & Private Desktops for Windows XP
by Stephen Lardieri

Listing One
// Desktop Demo.cpp
#include "stdafx.h"
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                                         LPSTR lpCmdLine, int nCmdShow)
{
   HDESK hdeskOriginalThread = GetThreadDesktop(GetCurrentThreadId());
   HDESK hdeskOriginalInput = OpenInputDesktop(0,FALSE,DESKTOP_SWITCHDESKTOP);
   HDESK hdeskNewDesktop = CreateDesktop(TEXT("MyDesktop"), NULL, NULL, 0, GENERIC_ALL, NULL);
    SetThreadDesktop(hdeskNewDesktop);
    SwitchDesktop(hdeskNewDesktop);
    MessageBox(NULL, TEXT("This message is appearing on a new desktop!"), TEXT("Desktop Demo"),MB_OK);
    SwitchDesktop(hdeskOriginalInput);
    SetThreadDesktop(hdeskOriginalThread);
    CloseDesktop(hdeskNewDesktop);
    return 0;
}

Listing Two
// Watchdog.cpp
#include "stdafx.h"
BOOL CALLBACK EnumWindowsProc(HWND hwnd, LPARAM lParam)
{
    bool * pFound = (bool *)lParam;
    *pFound = true;
    return FALSE;
}
bool IsInputDesktopEmpty()
{
    HDESK hdesk = OpenInputDesktop(0, FALSE, DESKTOP_READOBJECTS);
    if (hdesk == NULL)
    {
        // This almost always means the Winlogon desktop is active.
        return false;
    }
    bool found = false;
    EnumDesktopWindows(hdesk, EnumWindowsProc, (LPARAM)&found);
    CloseDesktop(hdesk);
    return !found;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    while (true)
    {
        if (!IsInputDesktopEmpty())
        {
            Sleep(10000);
        }
        else
        {
            // Wait 2 secs and test again, just to be sure.
            Sleep(2000);
            if (!IsInputDesktopEmpty())
                continue;
            // Try switching to the watchdog's desktop.
            HDESK hdeskMine = GetThreadDesktop(GetCurrentThreadId());
            SwitchDesktop(hdeskMine);
            // Backup plan:  switch to the default desktop.
            if (IsInputDesktopEmpty())
            {
                HDESK hdeskDefault = OpenDesktop(TEXT("Default"), 0, FALSE, DESKTOP_SWITCHDESKTOP);
                SwitchDesktop(hdeskDefault);
                CloseDesktop(hdeskDefault);
            }
        }
    }
    return 0;
}

Listing Three
// From Desk Jockey.cpp. Entry point for threads other than the main thread.
DWORD WINAPI MyThreadProc(LPVOID lpv)
{
    // Save handle to original desktop.
    HDESK hdeskOriginal = GetThreadDesktop(GetCurrentThreadId());
    // Start working with private desktop.
    HDESK hdesk = static_cast<HDESK>(lpv);
    if (SetThreadDesktop(hdesk))
    {
        CreateMyMainWindow();
        MSG msg;
        while (GetMessage(&msg, NULL, 0, 0) > 0)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    // Restore original desktop, which must still be alive
    // precisely because it is this process's original desktop.
    SetThreadDesktop(hdeskOriginal);
    // Release private desktop. Will be destroyed now, unless
    // some other process is still using it.
    CloseDesktop(hdesk);
    return 0;
}

Listing Four
// From Desk Jockey.cpp. Start a command prompt on any named desktop.
// Called by MainWindowProc() upon WM_COMMAND from Run button.
void CreateNewShell(LPTSTR desktop)
{
    TCHAR path[MAX_PATH + 1];
    GetSystemDirectory(path, MAX_PATH);
    PathAppend(path, TEXT("cmd.exe")); // useful func in shlwapi.dll
    PROCESS_INFORMATION pi = {0};
    STARTUPINFO si = {0};
    si.cb = sizeof(si);
    si.lpTitle = desktop;
    si.lpDesktop = desktop; // here's the important line!
    if (CreateProcess(path, TEXT("cmd"), NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi))
    {
        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }
    else
    {
        DisplayError(NULL, TEXT("CreateProcess"));
    }
}






2


