Вопрос по uac, windows-vista, windows, c – CreateDesktop () с Vista и UAC на (C, Windows)

5

Я спросил это вCreateDesktop () с Vista UAC (C Windows) Я назначил вознаграждение, но, пытаясь отклонить единственный ответ, «принять» было нажата по ошибке (я проснулся более 48 часов). поэтому я спрашиваю это снова.

Я использую CreateDesktop (), чтобы создать временный рабочий стол, на котором будет работать приложение, выполнить очистку (оставаясь в стороне) и завершить работу. Я закрываю этот рабочий стол, как только приложение исчезло. Все хорошо при использовании Windows XP и даже Vista. Проблема возникает, когда вы включаете (раздражает) UAC.

Все в порядке, когда вы создаете рабочий стол, но когда вы вызываете CreateProcess (), чтобы открыть программу на этом рабочем столе, это вызывает сбой открытого приложения с исключением на User32.dll.

Я много читал о различных рабочих столах и слоях в Windows и ограничениях памяти. Тем не менее, большинство программ, которые я открываю (в качестве тестовых сценариев), в порядке, но некоторые (такие как IE, Notepad, Calc и мое собственное приложение) вызывают сбой.

У кого-нибудь есть идеи, почему это происходит в Vista с UAC или, более конкретно, для этих конкретных программ? и как это исправить?

У кого-нибудь есть хороший убедительный пример того, как создать рабочий стол и открыть там приложение, не переключаясь на него в 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;
Смысл? Я имею в виду, я звоню CreateDesktop из основного потока приложения wonderer
Вы делаете это в потоке пользовательского интерфейса? Isaac
Трассировка стека также была бы очень полезна jcopenha
Как я отмечаю в комментариях к моему ответу, это может быть не тот ответ, который вы хотите, но это, безусловно, совершенно правильный ответ. Если вам нужна дополнительная помощь, я был бы рад ее оказать, но вместо того, чтобы раздраженно заявлять о своем разочаровании полученным ответом (ответами), вам было бы лучше использовать их, чтобы глубже изучить проблему. Stephen Martin
ну, во-первых, спасибо. причина, по которой я спросил здесь, в первую очередь, в том, что я уже потратил впустую несколько недель, пытаясь найти ответ сам. Иначе я бы не спросил. Я не хочу быть грубым, но 9 из 10 раз я видел людей, задающих вопросы на форумах по программированию, они никогда не получали прямого ответа. Все, что нужно, это «попробуй X и попробуй Y», а затем «возможно, ты сможешь попробовать Z» Подобные ответы ТОЛЬКО приведут человека в замешательство. wonderer

Ваш Ответ

2   ответа
4

вы столкнулись с ошибкой в IE, когда он взаимодействует с UAC. Если защищенный режим включен, вы не можете запускать IE как обычный пользователь на любом рабочем столе, кроме стандартного. Чтобы запустить IE на альтернативном рабочем столе, вы должны работать от имени администратора или отключить защищенный режим. Это верно для Vista, W2K8 и Win7.

Что касается других программ, которые вы не можете запустить, к сожалению, я не могу ничего подтвердить. Я пробовал свыше тридцати различных программ, включая блокнот, калькулятор, все офисные приложения, 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;
}
Я дважды проверил Win7 с несколькими различными конфигурациями, и я все еще не мог запустить IE на другом рабочем столе. Хотя на Win7 процесс просто исчез, не было диалогового окна сбоя или записи в журнале событий сбоя приложения. Stephen Martin
Просто для полноты ответа на этот вопрос был дан ответ автоматически. Это НЕ ответ. Я не установил это как ответ. wonderer
Рабочий стол должен иметь дескриптор безопасности, который обеспечивает доступ к более низкому уровню целостности, как в IE. В противном случае графический интерфейс не может получить доступ к рабочему столу. ChristianWimmer
Это странно, поскольку у меня нет проблем с Windows 7, а не с IE, ни с моим приложением, ни с любым приложением с включенным UAC. wonderer
Это может быть не тот ответ, который выхотеть но это, безусловно, ответ и лучший ответ, который вы, скорее всего, получите без дополнительной информации. Я воссоздал вашу среду, как указано, и попытался воспроизвести вашу проблему. Проблема с IE была воссоздана, и причина была дана. Проблема с другими программами не может быть воспроизведена - поэтому вы либо ошибаетесь в проблеме, либо среда действительно не соответствует заявленной. Я был бы рад помочь вам решить эту проблему, но вам нужно дать больше информации. В частности, небольшая программа, которая воспроизводит проблему, была бы неоценима. Stephen Martin
9

е:

Рабочий стол должен иметь дескриптор безопасности, который обеспечивает доступ к более низкому уровню целостности, как в IE. В противном случае графический интерфейс не может получить доступ к рабочему столу. - ChristianWimmer 22 июля 2010 года в 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);
}

@CristianWimmer: Спасибо за подсказку к правильному решению. Это сэкономило мне много времени !!

Похожие вопросы