带有vista和UAC的CreateDesktop()(C,windows)

won*_*rer 5 c windows uac windows-vista

我在使用Vista UAC(C Windows)的CreateDesktop()中询问了这一点 我设置了赏金,但是在试图拒绝唯一的答案时,"接受"被错误地按下了(我已经醒了超过48小时).所以我再问一遍.

我正在使用CreateDesktop()来创建一个临时桌面,其中应用程序将运行,执行清理操作(同时保持不受影响)并终止.一旦应用程序消失,我就关闭了桌面.使用Windows XP甚至Vista时,一切都很好.启用(恼人的)UAC时会出现问题.

创建桌面时一切正常,但是当您调用CreateProcess()在该桌面上打开程序时,会导致打开的应用程序崩溃,User32.dll上出现异常.

我一直在阅读很多关于Windows上不同桌面和图层以及内存限制的内容.但是,我打开的大多数程序(作为测试场景)都可以,但是一些程序(如IE,Notepad,Calc和我自己的应用程序)会导致崩溃.

任何人都知道为什么会在使用UAC的Vista上发生这种情况,或者更具体地针对这些特定程序?以及如何解决这个问题?

任何人都有一个很好的例子来说明如何创建一个桌面并在那里打开一个应用程序,而无需在Vista下使用UAC切换到它?

代码表示赞赏.

谢谢

使用的代码是

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;
Run Code Online (Sandbox Code Playgroud)

msp*_*msp 9

正确的解决方案由ChristianWimmer在上面作为简短评论给出:

桌面必须具有安全描述符,允许访问IE所具有的较低完整性级别.否则GUI无法访问桌面. - ChristianWimmer 2010年7月22日17:00

由于答案有点隐藏,并且没有源代码示例,请让我在此明确说明:

如果IE在受保护模式下运行,则浏览器选项卡将创建为低完整性进程.如果桌面没有低完整性强制标签,则低完整性选项卡进程将无法初始化.

因此,主IE流程也会终止.一个有趣的观察是,如果您启动IE从安全区域提供命令行URL,则IE将成功启动,因为默认情况下对安全区域禁用保护模式.

我检查了默认桌面的完整性级别,实际上我能够验证默认桌面的完整性级别是否很低!因此,解决该问题的最简单方法是(1)创建新桌面,(2)从默认桌面获取强制标签,以及(3)将其复制到新桌面.对于(2)和(3),您可以使用以下代码

PACL pSacl;
PSECURITY_DESCRIPTOR pSecurityDescriptor;
DWORD dwResult;

dwResult = GetSecurityInfo(hDefaultDesktop, SE_WINDOW_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, &pSacl, &pSecurityDescriptor);

if (dwResult == ERROR_SUCCESS) {
    if (pSacl != NULL) {
        dwResult = SetSecurityInfo(hNewDesktop, SE_WINDOW_OBJECT, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, pSacl);

        if (dwResult != ERROR_SUCCESS)
            _tprintf(_T("SetSecurityInfo(hNewDesktop) failed, error = %d"), dwResult);
    }

    LocalFree(pSecurityDescriptor);
} else {
    _tprintf(_T("GetSecurityInfo(hDefaultDesktop) failed, error = %d"), dwResult);
}
Run Code Online (Sandbox Code Playgroud)

@CristianWimmer:感谢您提供正确解决方案的提示.这节省了我很多时间!


Ste*_*tin 4

您似乎在 IE 与 UAC 交互时遇到了一个错误。如果保护模式设置为打开,则无法在默认桌面以外的任何桌面上以普通用户身份运行 IE。为了在备用桌面上运行 IE,您必须以管理员身份运行或将保护模式设置为关闭。Vista、W2K8 和 Win7 都是如此。

至于其他无法运行的程序,不幸的是我无法确认任何事情。我尝试了三十多个不同的程序,包括记事本、计算器、所有 Office 应用程序、Visual Studio 2005、2008 和 2010、MSDN 帮助和许多其他程序,除了 IE 之外,所有程序都按预期工作。您的应用程序是否存在真正不寻常的地方,可能会导致其行为异常?

需要注意的是,如果您尝试运行像这样需要提升的应用程序(例如 regedit 等),它将在 CreateProcess 中失败,并将最后一个错误设置为 ERROR_ELEVATION_REQUIRED。

供您参考,如果我做的事情与您不同,我使用的代码是:

#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;
}
Run Code Online (Sandbox Code Playgroud)