views:

563

answers:

2

I asked this in http://stackoverflow.com/questions/1188396/createdesktop-with-vista-uac-c-windows I set a bounty but in trying to vote down the only answer the "accept" was pressed by mistake (i've been awake for more than 48 hs). so I am asking it again.

I'm using CreateDesktop() to create a temporary desktop where an application will run, perform a cleanup action (while remaining out of the way) and terminate. I'm closing that desktop once the application is gone. Everything is fine when using Windows XP and even Vista. The problem arises when you enable the (annoying) UAC.

Everything is OK when you create a desktop, but when you call CreateProcess() to open a program on that desktop it causes the opened application to crash with an exception on User32.dll.

I've been reading a lot about the different desktops and layers on Windows and the restrictions of memory. However, most of the programs I open (as test scenarios) are OK, but a few (like IE, Notepad, Calc and my own application) cause the crash.

Anyone has any idea why this happen on Vista with UAC, or more specifically for those specific programs? and how to fix this?

Anyone has a good solid example on how to create a desktop and open an application there without switching to it under Vista with UAC on?

Code is appreciated.

Thanks

The code used is

SECURITY_ATTRIBUTES sa;

HDESK dOld;
HDESK dNew;

BOOL switchdesk, switchdesk2, closedesk;
int AppPid;

sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = NULL;
sa.nLength = sizeof(SECURITY_ATTRIBUTES);

//Get handle to current desktop
dOld = OpenDesktopA("default", 0, TRUE, DESKTOP_SWITCHDESKTOP| 
                                        DESKTOP_WRITEOBJECTS|
                                        DESKTOP_READOBJECTS|
                                        DESKTOP_ENUMERATE|
                                        DESKTOP_CREATEWINDOW|
                                        DESKTOP_CREATEMENU);
if(!dOld)
{
    printf("Failed to get current desktop handle !!\n\n");
    return 0;
}

//Make a new desktop
dNew = CreateDesktopA("kaka", 0, 0, 0, DESKTOP_SWITCHDESKTOP|
                                          DESKTOP_WRITEOBJECTS|
                                          DESKTOP_READOBJECTS|
                                          DESKTOP_ENUMERATE|
                                          DESKTOP_CREATEWINDOW|
                                          DESKTOP_CREATEMENU, &sa);

if(!dNew)
{
    printf("Failed to create new desktop !!\n\n");
    return 0;
}

AppPid = PerformOpenApp(SomeAppPath);
if(AppPid == 0)
{
    printf("failed to open app, err = %d\n", GetLastError());
}
else
{
    printf("App pid = %d\n", AppPid);
}


closedesk = CloseDesktop(dNew);

if(!closedesk)
{
    printf("Failed to close new desktop !!\n\n");
    return 0;
}


return 0;

EDIT: Just for the sake of completeness this question was awarded the answer automatically when the bounty was done. It is NOT an answer. I didn't set it as the answer.

A: 

What does your code inside of PerformOpenApp() actually look like? Are you filling in the lpDesktop field of the STARTUP structure? Are you calling SwitchDesktop()? Do you have the same problem if you use CreateProcessAsUser() or other CreateProcess...() function?

Remy Lebeau - TeamB
@Remy Lebeau - This is not an answer. Use **Comment** feature! ;)
Isaac
it uses CreateProcess to open the program. Yes, I pass the name of the desktop to the STARTUP struct and not, I am not calling SwitchDesktop since I DON'T want to switch to the new desktop. I just want to open a program there. that's all
wonderer
+2  A: 

You appear to have come across a bug in IE as it interacts with UAC. If protected mode is set to on you cannot run IE as an ordinary user in any desktop except the default one. In order to run IE in an alternate desktop you must be running as administrator or have protected mode set to off. This is true for Vista, W2K8 and Win7.

As to the other programs that you cannot run, unfortunately I can't confirm anything. I tried upwards of thirty different programs including notepad, calc, all the office apps, visual studio 2005, 2008 and 2010, MSDN help and a number of others and all worked as expected with the noted exception of IE. Is there something truly unusual about your app that might make it behave in an unexpected manner?

One note - if you attempt to run an application like this that needs elevation (such as regedit, etc.) it will fail in CreateProcess with the last error set to ERROR_ELEVATION_REQUIRED.

For your reference, in case I'm doing something different from you, the code I used is:

#ifndef _WIN32_WINNT            // Specifies that the minimum required platform is Windows Vista.
#define _WIN32_WINNT 0x0600     // Change this to the appropriate value to target other versions of Windows.
#endif

#include <stdio.h>
#include <tchar.h>

#include "windows.h"

HANDLE PerformOpenApp(TCHAR* appPath);

int _tmain(int argc, _TCHAR* argv[])
{
    HDESK dNew;
    BOOL closedesk;
    HANDLE hApp;

    //Make a new desktop
    dNew = CreateDesktop(_T("kaka"), 0, 0, 0, DESKTOP_SWITCHDESKTOP|
                                              DESKTOP_WRITEOBJECTS|
                                              DESKTOP_READOBJECTS|
                                              DESKTOP_ENUMERATE|
                                              DESKTOP_CREATEWINDOW|
                                              DESKTOP_CREATEMENU, NULL);

    if(!dNew)
    {
        _tprintf(_T("Failed to create new desktop !!\n\n"));
        return 0;
    }

    TCHAR path[MAX_PATH];
    _putts(_T("Enter the path of a program to run in the new desktop:\n"));
    _getts(path);

    while(_tcslen(path) > 0)
    {
        hApp = PerformOpenApp(path);
        if(hApp == 0)
        {
            _tprintf(_T("Failed to open app, err = %d\n"), GetLastError());
        }
        else
        {
            _tprintf(_T("App pid = %d\n"), GetProcessId(hApp));
            _putts(_T("Press any key to close the app.\n"));
            _gettchar();
            TerminateProcess(hApp, 0);
            CloseHandle(hApp);
         }
         _putts(_T("Enter the path of a program to run in the new desktop:\n"));
         _getts(path);
    }

    closedesk = CloseDesktop(dNew);

    if(!closedesk)
    {
        _tprintf(_T("Failed to close new desktop !!\n\n"));
        return 0;
    }
    return 0;
}

HANDLE PerformOpenApp(TCHAR* appPath)
{
    STARTUPINFO si = {0};
    PROCESS_INFORMATION pi;

    si.cb = sizeof(si);
    si.lpDesktop = _T("kaka");

    BOOL retVal = CreateProcess(NULL, appPath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL,
        NULL, &si, &pi);

    if (retVal)
    {
        CloseHandle(pi.hThread);
    }
    return pi.hProcess;
}
Stephen Martin
This is strange since I have no problem with windows 7, not IE, not my app not any app with a full UAC ON
wonderer
I double checked Win7 with a couple of different configurations and I still couldn't run IE on another desktop. Though on Win7 the process simply disappeared, there was no crash dialog or app crash event log entry.
Stephen Martin
Just for the sake of completeness this question was awarded the answer automatically. It is NOT an answer. I didn't set it as the answer.
wonderer
This may not be the answer that you *want* but it certainly is an answer and is the best answer you are likely to get without more information. I recreated your environment as stated and tried to reproduce your problem. The problem with IE was recreated and the reason was given. The problem with other programs could not be reproduced - therefore you are either mistaken about the problem or the environment isn't really as stated. I would be happy to help you solve this but you need to give more information. In particular, a small program that reproduces the problem would be invaluable.
Stephen Martin
The desktop must have a security descriptor that allows access to lower integrity level like IE has. Otherwise the GUI cannot access the desktop.
ChristianWimmer