2009-09-08 12 views
5

Pregunté esto en CreateDesktop() with Vista UAC (C Windows) Configuré una recompensa pero al tratar de rechazar la única respuesta, se presionó "aceptar" por error (estuve despierto por más de 48 hs). así que lo estoy preguntando de nuevo.CreateDesktop() con vista y UAC en (C, Windows)

Estoy usando CreateDesktop() para crear un escritorio temporal donde se ejecutará una aplicación, realizar una acción de limpieza (mientras se mantiene fuera del camino) y terminar. Estoy cerrando ese escritorio una vez que la aplicación se haya ido. Todo está bien cuando se usa Windows XP e incluso Vista. El problema surge cuando habilita el UAC (molesto).

Todo está bien cuando crea un escritorio, pero cuando llama a CreateProcess() para abrir un programa en ese escritorio provoca que la aplicación abierta se bloquee con una excepción en User32.dll.

He estado leyendo mucho sobre los diferentes escritorios y capas en Windows y las restricciones de memoria. Sin embargo, la mayoría de los programas que abro (como escenarios de prueba) están bien, pero algunos (como IE, Notepad, Calc y mi propia aplicación) provocan el bloqueo.

¿Alguien tiene alguna idea de por qué sucede esto en Vista con UAC, o más específicamente para esos programas específicos? y cómo arreglar esto?

¿Alguien tiene un buen ejemplo sólido sobre cómo crear un escritorio y abrir una aplicación allí sin cambiar a él en Vista con UAC activado?

Código es apreciado.

Gracias

El código utilizado es

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; 
+0

¿Estás haciendo esto en un hilo de interfaz de usuario? – Isaac

+0

Significado? Quiero decir, estoy llamando a CreateDesktop desde el hilo principal de la aplicación – wonderer

+0

Una traza de pila sería muy útil también – jcopenha

Respuesta

4

Usted parece haber encontrado un error en el IE, ya que interactúa con el UAC. Si el modo protegido está activado, no se puede ejecutar IE como un usuario ordinario en cualquier computadora de escritorio, excepto la predeterminada. Para ejecutar IE en un escritorio alternativo, debe estar ejecutándose como administrador o haber desactivado el modo protegido. Esto es cierto para Vista, W2K8 y Win7.

En cuanto a los otros programas que no se pueden ejecutar, desafortunadamente no puedo confirmar nada. Probé más de treinta programas diferentes, incluidos notepad, calc, todas las aplicaciones ofimáticas, visual studio 2005, 2008 y 2010, ayuda de MSDN y muchos otros, y todo funcionó como se esperaba con la notable excepción de IE. ¿Hay algo realmente inusual en tu aplicación que pueda hacer que se comporte de forma inesperada?

Una nota: si intenta ejecutar una aplicación como esta que necesita elevación (como regedit, etc.) fallará en CreateProcess con el último error configurado en ERROR_ELEVATION_REQUIRED.

Para su referencia, en caso de que estoy haciendo algo diferente de ti, el código que utiliza es:

#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; 
} 
+0

Esto es extraño ya que no tengo ningún problema con Windows 7, ni IE, ni mi aplicación ni ninguna aplicación con un UAC completo ON – wonderer

+0

Comprobé Win7 con un par de configuraciones diferentes y aún no podía ejecutar IE en otro escritorio. Aunque en Win7 el proceso simplemente desapareció, no hubo un cuadro de diálogo de bloqueo o una entrada de registro de evento de falla de la aplicación. –

+0

En aras de la exhaustividad, esta pregunta recibió la respuesta automáticamente. NO es una respuesta. No lo configuré como la respuesta. – wonderer

9

La solución correcta se da como un breve comentario por encima ChristianWimmer:

El escritorio debe tener un descriptor de seguridad que permita acceder a un nivel de integridad más bajo que IE. De lo contrario, la GUI no puede acceder al escritorio.- ChristianWimmer 22 jul '10 a 17:00

Dado que la respuesta es un poco escondido y no hay ejemplo de código fuente, permítanme decir claramente aquí:

Si IE se ejecuta en modo protegido a continuación, las pestañas del navegador se crean como procesos de baja integridad. El proceso de tabulación de baja integridad no se inicializará si el escritorio no tiene una etiqueta obligatoria de baja integridad.

Como consecuencia, el proceso de IE principal finaliza también. Una observación interesante es que si se inicia IE y se proporciona una URL de línea de comando desde la zona segura, entonces IE podrá iniciarse correctamente, ya que el modo protegido está deshabilitado de forma predeterminada para la zona segura.

Comprobé el nivel de integridad del escritorio predeterminado y, de hecho, pude verificar que el escritorio predeterminado tiene un nivel de integridad bajo. Así que la solución más fácil al problema es (1) crear el nuevo escritorio, (2) obtener la etiqueta obligatoria del escritorio predeterminado y (3) copiarla en el nuevo escritorio. Para (2) y (3), puede utilizar el siguiente código de

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: Gracias por proporcionar la indirecta a la solución correcta. ¡Esto me ahorró mucho tiempo!

Cuestiones relacionadas