Jugando a diseñar un administrador de ventanas

Imagine que es ingenier@ de software y le han encargado la tarea de diseñar un sistema gráfico basado en ventanas para un sistema operativo. ¿Cómo lo haría?

Lo primero que hay que notar es que en este hipotético sistema gráfico el concepto central es el de ventana. Por lo tanto, la estructura de datos principal que lo implemente debe tener en cuenta este hecho. En cualquier momento, el sistema gráfico tendrá que poder acceder como mínimo a una ventana, por lo que estas se deben organizar en una estructura de datos tal que las operaciones más comunes sean lo más eficientes posible. Antes de pensar en dicha estructura de datos, consideremos qué relaciones puede haber entre las ventanas. La relación más obvia que primero se nos ocurre es la de padre e hija. Una ventana padre puede tener una o más hijas, cada una de las cuales aparecerá encuadrada en el área de trabajo de la ventana padre. El uso más claro que podemos hacer de esta relación padre/hijo es el de crear botones, menús, cuadros de texto, etc. dentro de nuestras ventanas. Estos elementos no serán más que ventanas hijas dependientes de una ventana padre, con la salvedad de que tendrán un aspecto un tanto diferente.

Para implementar esta relación podemos pensar en incorporar a cada representación de ventana de nuestro sistema operativo un puntero hacia la ventana padre y un conjunto de punteros hacia las posibles ventanas hijas que pueda tener. ¿Un conjunto de punteros? Ciertamente, nadie nos ha limitado el número de posibles ventanas hijas que podamos crear, por lo que un conjunto de punteros podría limitarnos demasiado. Obviamente se trata de una solución que no escala bien cuando el número de ventanas es grande. Una alternativa sería mantener únicamente un puntero a la primera ventana hija, y mantener el resto de ventanas hija unidas mediante punteros, que podemos llamar hermana. Nos queda en el tintero hacia dónde orientar el puntero padre de las ventanas que son padres. ¿Quién podría ser el padre de estas ventanas? Podemos convenir que hay una ventana que siempre está presente, que la crea el sistema operativo y no el usuario, que no tiene padre y que recibe el nombre de “Escritorio”. De ahí la suposición anterior de que nuestro administrador de ventanas debe mantener al menos una ventana. Este es un esbozo de lo que hemos diseñado hasta el momento:

AdminVentanas

Tenemos una ventana especial, sin padre, denominada “Escritorio”, desde la cual se tiene acceso a la primera ventana padre. El resto de ventanas padre las tenemos unidas mediante una estructura de lista enlazada usando el puntero hermana. A su vez, cada ventana padre puede apuntar a una lista enlazada de ventanas hija, que conforman el tercer nivel de la estructura.

Podemos pensar en otro tipo de relación para nuestro sistema de ventanas. Si nos paramos a pensar, no todas las ventanas son independientes entre sí. Es decir, es posible que ciertas ventanas de aplicaciones creen otras ventanas y que el usuario por ejemplo tenga que cerrar obligatoriamente estas últimas para poder interactuar con las primeras. Esto es típico en los cuadros de diálogo. Se trata de una relación de propiedad: La ventana A es propietaria de la ventana B. Una de las primeras cosas que dan para pensar sobre esta propiedad es si es transitiva o no; es decir, si A es propietaria de B y esta a su vez lo es de C, ¿qué podemos decir de A con respecto a C? Este aspecto lo discutiremos en un próximo artículo. Esta relación de propiedad la podemos representar mediante un puntero que apunte a la ventana que es propietaria de la ventana en cuestión. Podemos imponer como restricción que una ventana hija no puede tener en propiedad ningún tipo de ventana.

Así pues, nuestra jerarquía de ventanas con este último añadido queda como sigue: Una ventana especial denominada “Escritorio”, la cual puede apuntar a una lista de ventanas que llamaremos “de primer nivel”, y un segundo nivel con ventanas “hija”, relacionadas convenientemente con sus respectivas ventanas padre. Nótese que el padre de una ventana hija podría ser otra ventana hija, por lo que el número de niveles es variable. Queda por implementar una cosa: Cuando tengamos abiertas varias ventanas en nuestro sistema, tenemos que pensar en una forma de decidir qué ventanas se muestran completamente (es decir, en primer plano), qué ventanas quedan tapadas parcialmente por ventanas en primer plano (es decir, ventanas en segundo plano), y qué ventanas no se muestran excepto su representación icónica en la barra de tareas (es decir, están minimizadas). La estructura de lista enlazada nos permite implementar estos conceptos. Como vimos, las ventanas de un determinado nivel están unidas entre sí mediante el puntero hermana. Podemos suponer que el orden en el eje Z de una determinada ventana viene dado por su posición en un determinado nivel. Concretamente, la primera ventana de un nivel (la que está más “hacia la izquierda”) “taparía” una ventana que ocupara la tercera posición. Nos gustaría también disponer de ventanas que siempre estuvieran visibles, como por ejemplo la barra de tareas de nuestro sistema operativo. Este tipo de ventanas estarían situadas al principio del nivel, marcadas con un flag especial “siempre visible”, y solamente podrían ser ocultadas por otras ventanas que igualmente tengan el flag “siempre visible”. La estructura enlazada le permite al sistema operativo “mover” de sitio la representación de las ventanas de una manera eficiente.

Ya henemos pensado en la estructura básica de nuestro administrador de ventanas, que como habrá podido intuir, no es del todo ficticio y se trata del administrador de ventanas de Windows. En un próximo artículo veremos qué necesidades surgen a partir de este diseño básico y cómo podemos implementarlas. Asimismo vamos a intentar demostrar por qué usar unas estructuras de datos y no otras, según el tipo de operaciones que realicemos. Y efectivamente, estas operaciones son las que conforman el API de programación del administrador de ventanas de Windows.

Un método más para detectar defectos en extensiones de shell

Una cosa en la que destaca Windows, y en especial su shell, es que se trata de un componente muy extensible por parte de los desarrolladores de aplicaciones. Por ejemplo, se pueden crear manejadores de propiedades para que el usuario pueda verificar el código CRC de un fichero accediendo a sus propiedades; manejadores del menú contextual que nos permitan examinar un fichero o carpeta con un antivirus, etc.

El problema de ser tan extensible es que no siempre el software que extiende el shell cumple con las guías de desarrollo que se explican en la documentación oficial (MSDN Library). Este es el caso por ejemplo de las extensiones del menú contextual, algunas de las cuales implementan incorrectamente uno de sus métodos (concretamente, el método InvokeCommand). Si instalamos una de esas extensiones en nuestro sistema, vamos a experimentar problemas de diversa índole, como por ejemplo no poder abrir Administrar equipo, no poder editar una fotografía, o problemas similares. Hace algún tiempo aporté mi granito de arena advirtiendo del problema en la correspondiente documentación del método InvokeCommand, para intentar mejorar aunque sea un poco el ecosistema de Windows.

Cuando un usuario se encuentra con un problema de este estilo, suele echarle la culpa a Windows, cuando realmente es un componente de terceros el que está causando el problema. En parte no se trata de una reacción fuera de lo normal, pues no es obvio asociar a las extensiones de shell con este tipo de problemas. Es más, aun sabiendo que la culpable es una extensión de shell, saber a ciencia cierta cuál es la culpable es un procedimiento que no es demasiado conocido.

Una alternativa es usar alguna herramienta del estilo de ShellExView (http://www.nirsoft.net/utils/shexview.html) o Autoruns (http://technet.microsoft.com/en-us/sysinternals/bb963902.aspx), las cuales muestran las extensiones del menú contextual instaladas en el equipo, y comenzar por desactivar las extensiones de terceros una a una (suponiendo quizá de manera optimista que las extensiones que desarrolla Microsoft no adolecen de ese problema). El procedimiento completo lo describo en este artículo.

FileTypeVerifier, una ayuda para detectar qué extensión es la culpable

El SDK de Windows 7 es un paquete esencial para cualquier persona que desarrolle aplicaciones para Windows, pero también incorpora ciertas utilidades que pueden resultar muy valiosas a los usuarios finales o profesionales de soporte. Por ejemplo, el SDK incorpora una pequeña herramienta en el directorio C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin denominada FileTypeVerifier.exe. Esta herramienta es de enorme ayuda a la hora de comprobar que el estado de las asociaciones y tipos de archivo de Windows es el adecuado. Nos va a servir también para detectar extensiones del menú contextual mal diseñadas, como describiré a continuación.

En primer lugar, supongamos un sistema con la aplicación CompareIt! instalada. Esta aplicación, a fecha de publicación de este artículo, implementa mal su extensión del menú contextual. Podemos comprobarlo haciendo clic con el botón derecho sobre Equipo y seleccionando Administrar (observamos que no ocurre nada). Abrimos FileTypeVerifier.exe y nos encontramos con una interfaz del tipo asistente Aero con varias opciones:

FileTypeVerifier1 La categoría que se seleccione va a influir en el tipo de tests que realizará la utilidad. La herramienta File Type Verifier está orientada a desarrolladores que quieran probar los tipos de archivo que sus aplicaciones registren en el sistema, de ahí que haya que seleccionar algún tipo de fichero nada más comenzar. Para nuestro problema basta con seleccionar la opción Document (por ejemplo).

La siguiente pantalla muestra una “diana” donde deberemos arrastrar un fichero de texto cualquiera, para que el sistema seguidamente lo analice y nos muestre los resultados:

FileTypeVerifier2 En la lista de resultados, debemos acceder al apartado Verb handler y, si se diera el caso, debemos hacer clic sobre Diagnose context menu handlers para abrir el fichero de reporte completo. Al situarnos en la posición adecuada del fichero de reporte, observamos lo siguiente:

FileTypeVerifier3

Así que ya tenemos detectado al culpable. Con el GUID de la extensión en la mano (el código hexadecimal que aparece entre llaves), podemos aplicar el método 2 de mi artículo, o bien informar al fabricante del defecto de su aplicación.

Espero que este artículo ayude a depurar problemas con las extensiones del menú contextual así como probar el registro de tipos de archivo y vistas previas de archivos usando la herramienta File Type Verifier.

Sobre Stuxnet y la vulnerabilidad de los iconos de los accesos directos

Hoy Microsoft ha liberado la tan ansiada actualización de seguridad que corrige la vulnerabilidad VU#940193, descrita en este artículo. Aprovecho para recomendar que si no lo ha hecho ya, acuda a Windows Update para instalar esta actualización y mantener su sistema al día.

La vulnerabilidad en cuestión se aprovecha de que el manejador de iconos de accesos directos (.lnk y .pif) que incorpora Windows no valida lo suficiente las estructuras del acceso directo a la hora de cargar el correspondiente icono. Más concretamente, la vulnerabilidad se produce cuando el acceso directo está diseñado de tal manera que la DLL Shell32.dll descuidadamente llama a la API LoadLibrary con una DLL maliciosa como parámetro. La API LoadLibrary invoca al método principal (DllMain) de la DLL maliciosa, por lo que ya tenemos un bonito rootkit instalado en nuestro sistema.

La gran repercusión de esta vulnerabilidad se debe principalmente a estos puntos:

  • Estaba siendo explotada por varios virus sin que el fabricante hubiera lanzado la correspondiente actualización de seguridad.
  • La automatización de la vulnerabilidad es bastante elevada. Simplemente con abrir un dispositivo USB infectado (sin necesidad de hacer clic en nada más), el sistema queda infectado.
  • El código malicioso misteriosamente aparece con una firma digital de dos fabricantes de hardware bastante conocidos: JMicron y Realtek Corporation.
  • Control de cuentas de usuario (UAC) mitiga pero no evita que el software malicioso que aprovecha la vulnerabilidad cause daños importantes en el sistema, pese a tener privilegios limitados.

Nos planteamos dos cuestiones principales:

¿La firma digital es garantía de seguridad?

Ciertamente las firmas digitales en el software han venido siendo un indicador de que el fabricante que lo proporciona no intentará hacer nada malo, al menos conscientemente. De hecho, Windows se basa cada vez más en las firmas digitales para ayudar al usuario a decidir si es recomendable ejecutar o instalar cierto software; tómese como ejemplo la implementación de Control de cuentas de usuario (UAC), que muestra un color diferente dependiendo de si el ejecutable lleva firma digital, no la lleva, o es parte de Windows.

Lo que es cierto es que los autores de malware son conscientes de este hecho y cada vez más intentan incorporar una firma digital en su código malicioso. El asunto es más goloso si cabe puesto que el software antivirus suele hacer la vista gorda cada vez que se encuentra con un fichero firmado digitalmente. La cruda realidad es que actualmente ya hay varias cepas de malware que incluyen de alguna forma una firma digital. El caso más sencillo es el malware que adjunta una firma digital inválida, copiada de algún fabricante de renombre. La firma digital será catalogada como no válida, obviamente, pero el usuario puede que solo se dé cuenta de ello al intentar ejecutar el programa, al ver el correspondiente aviso en la ventana de Control de cuentas de usuario.

Otra manera que usan los autores de malware es conseguir que su código sea firmado por una autoridad de certificación con un nombre de empresa. Lamentablemente, pese a que las autoridades de certificación digan lo contrario, se han dado bastantes casos de certificados otorgados a autores de malware. Afortunadamente, las políticas de control de certificación de código en modo núcleo son bastante más estrictas, por lo que incluir un controlador malicioso en un sistema Windows Vista/7 de 64 bits es tarea complicada.

La última forma, y la que quizá podría haber aprovechado Stuxnet, consiste en robar la clave privada Authenticode a una empresa de desarrollo de software. Existe malware especializado en obtener certificados, como por ejemplo Ursnif o Zeus. Los desarrolladores de aplicaciones suelen usar la misma máquina para desarrollar y para acceder a Internet, por lo que no es raro que esas máquinas acaben infectándose y permitiendo que el atacante acceda ilegítimamente a esos certificados digitales. En el caso de Stuxnet aún hay dudas al respecto principalmente porque se da la casualidad de que las empresas cuyos certificados han sido robados (Realtek y JMicron) comparten ciudad, por lo que podría tratarse de algún tipo de filtración humana.

¿Control de cuentas de usuario es la solución a los virus?

Ni Control de cuentas de usuario, ni el uso de una cuenta de usuario limitado nos garantizan que nuestro sistema no se infecte, ni tampoco que si se infecta los daños sean poco importantes. Es cierto que un entorno sin privilegios administrativos evita que los programas maliciosos tengan el control total de máquina (crear servicios, instalar software adicional, instalar controladores, etc.), pero no es menos cierto que los autores de malware están centrándose en elaborar código malicioso que haga el máximo daño posible sin necesidad de privilegios administrativos. Recuerdo cierto virus que cifraba los documentos personales del usuario y posteriormente le pedía dinero para poder recuperarlos. En concreto, Stuxnet inyecta “ganchos” en ciertas funciones de algunas DLL del sistema (como Ntdll.dll o Kernel32.dll), con el objetivo de engañar al sistema cuando, por ejemplo, intente listar los ficheros de un directorio. En este vídeo se puede ver como el virus se oculta automáticamente incluso en una cuenta con privilegios limitados.

Stuxnet se ha propagado a una gran velocidad y con solo abrir un dispositivo USB infectado, pero si algo podríamos aprender de este virus es que por sí solo un usuario con privilegios limitados aún es vulnerable a daños importantes en su equipo, y que la firma digital en el software no es indicador de ausencia de peligro. Como siempre, la recomendación es mantener unas estrictas políticas de restricción de software (especialmente en empresas), unidas a unas prácticas de sentido común y complementadas con un antivirus/cortafuegos, así como con un sistema operativo y aplicaciones actualizados.

¿Los botones Atrás y Adelante de Internet Explorer 8 no funcionan correctamente?

En estos días he estado investigando un problema que he visto en algunos sistemas que tienen Windows 7 instalado con Internet Explorer 8 (podría ocurrir en otros sistemas también). Consiste en que en ocasiones los botones Atrás y Adelante, que sirven para acceder a la página anterior o posterior que se haya visitado en el navegador, no funcionan. O bien es posible que sí funcionen, pero después de hacer 5, 6 o incluso más clics de ratón sobre el botón. Al desplegar la lista del historial haciendo clic con el botón derecho del ratón, se puede elegiir cualquier página y todo funciona correctamente.

¿Alguno de los lectores ha experimentado o está experimentando un problema similar? Me interesaría recuperar información para dar con el culpable del problema. En principio no creo que se trate de algún complemento instalado en el navegador. ¿Por casualidad el sistema en el que ocurre el problema es un sistema que hiberna regularmente y apenas es apagado?

Le agradecería que usara la sección de comentarios de esta entrada para discutir sobre el problema.

Actualización (25/07/2010): En un caso particular de este problema el análisis revelaba un error de memoria insuficiente al ejecutar la función que implementa el ir hacia atrás en Internet Explorer. Al eliminar todos los procesos Iexplore.exe de la máquina y abrir de nuevo el navegador, el problema quedó resuelto. Sin embargo, creo que hay casos particulares en los que esto no soluciona el problema y es necesario un reinicio de la máquina. Si experimenta uno de esos casos, póngase en contacto conmigo a través de la sección “Contact” del blog para que lo analice.

¿En qué consiste una versión localizada de Windows Vista/7? [Parte III]

Artículos anteriores

En esta tercera parte de la saga de artículos dedicados a la tecnología MUI de Windows Vista y Windows 7, vamos a ver qué caches incorporan estos sistemas para que no se penalice excesivamente durante el acceso a los recursos en etapas críticas en lo que a rendimiento se refiere (por ejemplo, al iniciar el equipo).

Cache en modo núcleo

El núcleo de Windows dispone de una cache por proceso en la que se almacena cierta información sobre los idiomas que forman parte del sistema. Concretamente, esta cache contiene datos tales como los idiomas permitidos por la licencia del sistema operativo, los idiomas instalados, políticas de idioma por usuario y por máquina, así como la lista de idiomas “de apoyo”, para el caso en que el idioma principal no sea un idioma 100% traducido.

Los datos que conforman esta cache provienen del registro, concretamente de claves como HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\MUI, HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\Language o HKEY_CURRENT_USER\Control Panel\Desktop\MuiCached. Las políticas relacionadas con MUI se establecen en las claves de registro HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Control Panel\Desktop y HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\MUI\Settings.

Cache de recursos en modo usuario

Windows Vista/7 incorporan una nueva utilidad en el directorio \Windows\System32 denominada Mcbuilder.exe (MUI cache builder). Esta herramienta se encarga de generar la cache de recursos en modo usuario del sistema operativo. Por defecto, esta cache se sitúa en el directorio C:\Windows\Rescache, y el registro contiene información de configuración, así como estadísticas de uso tales como su tamaño, su uso en los últimos días, etc. en la clave HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\CMF\.

Los archivos que forman parte de la cache son archivos de recursos (.mui) del propio sistema operativo, tales como %SystemRoot%\System32\%idioma%\csrss.exe.mui y demás componentes relacionados con el arranque, así como aplicaciones como Windows Media Player, Internet Explorer, o incluso los juegos que incorpora de serie el sistema operativo. Esta información queda recogida en el fichero ResCache.mni. Cabe destacar que este fichero contiene información sobre todos los archivos MUI que pueden formar parte de la cache, no solo los que actualmente están en ella.

El hecho de hablar de una cache es también incorrecto, pues el sistema dispone de 3 caches, identificadas por un índice diferente (subdirectorio R000<índice>). Cada una de las cuales incorpora, entre otras, estas estructuras:

Directorio de la cache

El directorio de la cache contiene referencias a todos los archivos que forman parte de la misma. El cargador de recursos de Windows (Resource Loader), que será tema del próximo artículo, se encarga de “mapear” la cache del sistema como solo lectura en la memoria de cada proceso que quiera acceder a recursos, para que así su acceso a los mismos sea muy eficiente. El directorio de la cache queda almacenado en el fichero ResCache.dir.

Fichero de aciertos de la cache

La cache incorpora un fichero opcional, ResCache.hit, que almacena una determinada fecha por cada entrada disponible en el directorio de la cache. Inicialmente esta fecha es la fecha de creación de la cache, pero cada vez que el cargador de recursos encuentra un recurso en ella (acierto de cache), se establece la fecha actual en la correspondiente entrada.

Segmentos de cache

La cache está formada por un conjunto de segmentos de cache de nombre Segment<indice>.cmf. Los segmentos representan los datos de un subconjunto de los ficheros que forman parte de la cache. El cargador de recursos de Windows “mapea” segmentos de cache en el espacio de memoria de aquellos procesos que los vayan a utilizar.

Tabla de contenidos (TOC) de segmentos

La tabla de contenidos de segmentos, recogida en el fichero Segment<indice>.cmf, contiene los ficheros que forman parte de un segmento determinado. Al crearse, la tabla de contenidos de segmentos se “mapea” en memoria también.

¿Qué ocurre si una aplicación muestra recursos obsoletos, o bien no muestra interfaz gráfica al arrancar?

Este tipo de problemas pueden deberse a que el sistema está obteniendo recursos desde la cache MUI y estos por algún motivo no están todo lo actualizados que debieran o bien no son los indicados. Es un caso raro, pero podría darse. El secreto para saber si la aplicación está obteniendo recursos desde la cache es pasar el manejador que devuelva la API LoadResource a la API GetMappedFileName. Si el resultado es un error o bien un fichero con extensión .cmf, entonces el recurso proviene de un segmento de la cache.

Otro caso posible es que la aplicación no muestre ningún tipo de interfaz gráfica al ser arrancada. Una de las causas posibles de este problema es que el sistema no es capaz de encontrar recursos para esa aplicación y por consiguiente esta no consigue crear su ventana principal. Aquí el uso de depuradores como Windbg está muy aconsejado porque estos síntomas tienen múltiples causas, por lo que siempre hay que analizar cada caso individualmente. Para poder abordar con éxito este problema debemos saber qué ubicaciones consulta Windows para encontrar ficheros .mui con recursos, cosa que describiremos en el próximo artículo.

Sobre la lista de fondos recientemente utilizados de Windows 7

Hace poco me llamó la atención un problema con Windows 7 que describe Sergio Calderón en su blog: http://geeks.ms/blogs/checho/archive/2010/04/06/191-es-esto-un-peque-241-o-bug-en-windows-7.aspx. En resumen, el problema es de tipo estético y consiste en que al eliminar un determinado tema en el nuevo formato de Windows 7 Themepack, es posible que queden referencias a carpetas que no existan en la lista desplegable de fondos de escritorio. La respuesta corta es que este problema no es un “bug” de Windows 7, es más bien un comportamiento por diseño o una limitación, como lo vea cada uno, pues esa lista contiene rutas recientemente utilizadas (MRU) y no necesariamente deben estar en sincronismo con las carpetas a las que apuntan (aunque si bien se podría dar la opción al usuario de eliminarlas de la lista si hace clic en ellas y por consiguiente recibe un error de “ruta no encontrada”).

Para dar la respuesta larga vamos a describir el contexto del problema y cuál el motivo de su aparición.

Los archivos con extensión .themepack

Windows 7 introduce un nuevo formato para personalizar gráficamente la interfaz del usuario mediante temas (extensión .themepack). Los temas son una característica que solo es aplicable a Windows 7 Home Premium o superior y que básicamente consisten en un fichero con extensión .CAB que engloba ficheros de diverso tipo (imágenes, sonidos, cursores, y un fichero con extensión .theme que trataremos más adelante). Aquí vemos un ejemplo del contenido del tema Bing’s Best tras haberle cambiado su extensión a .CAB:

BingsBest

¿Qué ocurre al hacer doble clic sobre un fichero con extensión .themepack?

Al hacer doble clic sobre un fichero con extensión .themepack, el sistema invoca al siguiente comando:

rundll32.exe %SystemRoot%\system32\shell32.dll,Control_RunDLL %SystemRoot%\system32\desk.cpl desk,@Themes /Action:OpenTheme /file:<Nombre del archivo>

Si está permitido el cambio de temas (es decir, si el sistema es Windows 7 Home Premium o superior y además no está establecida la directiva “NoThemesTab” (http://technet.microsoft.com/en-us/library/cc780116(WS.10).aspx)), el sistema se dispone a instalarlo. Primeramente se enumeran todos los temas que haya disponibles en el sistema. Los temas son ficheros con extensión .theme y pueden estar en estos directorios:

  • %SystemRoot%\Resources
  • %LocalAppData%\Microsoft\Windows\Themes
  • Subdirectorios de %SystemRoot%\Resources\Themes
  • Subdirectorios de %SystemRoot%\Resources\Ease of Access Themes
  • Subdirectorios de %SystemRoot%\Resources\OEM Theme
  • Carpetas que aparezcan en la clave de registro HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\InstalledThemes\MCT

El sistema determina cuál es el tema actual examinando la clave de registro HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes, valor CurrentTheme. Si la configuración visual actual de la máquina fuese diferente de la del tema actual, el sistema creará un tema denominado Custom.theme en el directorio %LocalAppData%\Microsoft\Windows\Themes con la información visual actual de la máquina. Este tema gráficamente aparece con el nombre de “Tema sin guardar”.

La instalación del tema propiamente dicha consiste en extraer el contenido del fichero con extensión .themepack y localizar el fichero.theme que contenga. Este fichero .theme no puede ser demasiado grande, el sistema lo descarta si es mayor de 5 MB (el fichero .themepack también es descartado si excede los 2 GB). Posteriormente, el sistema el sistema lo aplica al sistema copiándolo al directorio de temas (%LocalAppData%\Microsoft\Windows\Themes) y estableciéndolo en el registro como actual (clave HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes, valor CurrentTheme). El proceso acaba cuando se muestra al usuario la ventana de Personalización de Windows 7.

Nota: En Windows 7 existe una sintaxis específica para aplicar temas (ficheros .theme) desde la línea de comandos:

control.exe /name Microsoft.Personalization /page ?Theme=<Ruta al fichero .theme>

La lista desplegable Ubicación de la imagen

Ya hemos visto qué es lo que ocurre cuando se instala un tema en Windows 7. Ahora vamos a centrarnos en la lista desplegable que nos ofrece la opción de seleccionar un fondo de escritorio:

Fondos_escritorio

Veamos qué incluye cada categoría:

  • Fondos de escritorio de Windows: Incluye los fondos de escritorio referenciados en las claves de registro HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Wallpapers\Knownfolders y HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Wallpapers\Knownfolders
  • Biblioteca de imágenes: Como su propio nombre indica, incluye las imágenes de la correspondiente biblioteca de imágenes.
  • Fotografías con mejor clasificación: Incluye solamente aquellas fotos calificadas con 4 o más estrellas.
  • Colores sólidos: Listado de colores para establecer como fondo de escritorio.

Estas cuatro categorías aparecen por defecto. Existe una cuarta categoría que podríamos decir que incluye “rutas del usuario”. Hay dos tipos de rutas de usuario que considera Windows:

  • La ruta que contiene al fondo de escritorio actual o a la presentación, si es que no está ya en alguna de las categorías anteriores.
  • Fondos de escritorio recientemente utilizados (MRU).

La primera de las dos subcategorías anteriores está bastante clara. La segunda indica que Windows mantiene un listado de los directorios de fondos de escritorio usados recientemente. Concretamente, se almacenan hasta 3 directorios dentro de la clave de registro HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Wallpapers\Images.

Cuando se aplica un tema y se establece el nuevo fondo de escritorio (o presentación), en dicha clave de registro se almacena un valor de nombre “ID-1” que contiene la ruta temporal del fondo de escritorio del usuario. Hay hasta un máximo de 2 rutas temporales (“ID-1” y “ID-2”). En el momento en que el usuario abre el panel Fondo de escritorio, dichos valores temporales desaparecen del registro y las correspondientes rutas se cargan en la lista desplegable Ubicación de la imagen. Al cerrar el panel Fondo de escritorio, incluso haciendo clic sobre el botón Cancelar, se almacenan como máximo hasta 3 rutas de usuario, incluyendo aquellas carpetas a las que hayamos apuntado haciendo clic sobre el botón Examinar.

El problema surge porque al eliminar un tema no se toca para nada la lista de fondos de escritorio recientemente utilizados, únicamente se elimina físicamente la ruta donde está instalado el tema y se notifica al sistema de su desaparición, para que lo elimine de la lista. Por este motivo, la lista desplegable Ubicación de la imagen sigue mostrando rutas de temas que puede que ya ni existan.

El mismo problema puede reproducirse si se crea una carpeta y se apunta a ella haciendo clic sobre el botón Examinar del panel Fondo de escritorio. Una vez hecho esto, cerramos dicho panel y seguidamente borramos la carpeta que acabamos de crear. Al abrir de nuevo Fondo de escritorio vemos que la carpeta eliminada sigue apareciendo en la lista desplegable Ubicación de la imagen.

Próximamente en www.wintecnico.com aparecerá una utilidad capaz de eliminar individualmente rutas de la lista desplegable Ubicación de la imagen.

¿Por qué alguna carpeta tiene un icono de candado en Windows 7?

En un foro que frecuento a un usuario le aparecía un icono de candado sobre una de sus carpetas. Esta imagen detalla la situación:

Icono_privado

Raymond Chen, de Microsoft, ya explicó en su blog en qué consiste el mencionado icono. En este artículo voy a completar un poco su explicación.

Ese icono es un icono de overlay registrado en la clave de registro HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers\SharingPrivate e implementado en la DLL Ntshrui.dll.

Como comenté en un anterior artículo, el shell invoca al método IsMemberOf de los manejadores de iconos de overlay pasándoles como parámetro la ruta de un archivo o carpeta. Este método determina si se debe incluir un icono de overlay en ese fichero o carpeta o no. En primer lugar hay que comentar que un fichero o carpeta puede estar en tres estados con respecto a su estado de compartición:

  • Compartido
  • Privado
  • No compartido

“No compartido” no es lo mismo que “Privado”, para el sistema es un estado diferente. Para que aparezca el susodicho candado deben cumplirse estos puntos:

  • Debe tratarse de un archivo o carpeta no cifrado, ni con atributos de sistema u ocultos. Es decir, que tenga el atributo FILE_ATTRIBUTE_NORMAL.
  • Su estado de compartición debe ser “privado”.
  • El estado de compartición de la carpeta contenedora no debe ser “privado”.

El que el estado de compartición de un elemento sea “privado” puede ocurrir por diversos motivos. Y es esta diversidad la que yo creo que ha causado confusión entre algunos usuarios de Windows 7.

Una forma de hacer “privado” un elemento es la que comenta Raymond: desde el menú contextual, opción Compartir con, Nadie. Esta opción establece explícitamente el estado del fichero o carpeta como “Privado”, por lo que aparecerá el correspondiente candado, siempre y cuando la carpeta “padre” no esté en estado “Privado”.

Una carpeta puede estar compartida mediante SMB, protocolo explicado en esta página: http://samba.anu.edu.au/cifs/docs/what-is-smb.html, o bien compartida desde un perfil de usuario, siempre y cuando la directiva “Impedir que los usuarios compartan archivos dentro de su perfil” (Configuración del usuario\Plantillas administrativas\Componentes de Windows\Uso compartido de red) no esté habilitada. La clave está en que a la hora de determinar si una carpeta es “privada” se deben tener en cuenta también las entradas de permisos (ACE, Access Control Entries) aplicadas a esa carpeta. Si no hay ningún o solo hay una ACE que no sea de sistema y que tenga acceso sobre la carpeta, esta será considerada “privada”. Los ACE “de sistema” son el grupo Administradores, SYSTEM, TrustedInstaller, etc. Una carpeta es considerada “compartida” si algún usuario, excepto el propietario y el usuario que haya iniciado sesión, tiene permisos de acceso sobre la carpeta. Aquí nuevamente se excluyen las entradas de permisos de SYSTEM y Administradores que pudieran estar siendo heredados por el archivo o carpeta en cuestión.

Ciertamente todo el tema de permisos es algo complejo, pero espero que este artículo haya aclarado un poco las dudas de por qué Windows 7 pone un candado sobre ciertas carpetas del sistema.

Actualización (3 de junio de 2010): Acabo de ver que en Internet hay otros artículos que también tratan esta cuestión, como el blog del MVP Ramesh Srinivasan (en inglés): http://www.winhelponline.com/blog/lock-padlock-icon-files-folders-windows-7/

Nuevos foros sobre Windows

En mi nueva web, www.wintecnico.com, he abierto unos foros gratuitos para consultas técnicas sobre Windows XP, Windows Vista o Windows 7. La dirección es: www.wintecnico.com/foros

Personalmente espero poder echarles un vistazo regularmente para responder cuestiones, contribuir con nuevos temas, etc. Dependiendo de las necesidades y de la afluencia de gente, se podrán crear nuevos foros, como por ejemplo alguno dedicado a la arquitectura de Windows, otro a debugging, y en general cualquier tema que pueda resultar interesante.

Sobre las superposiciones (overlays) en iconos

Desde hace ya tiempo, el shell de Windows ofrece la posibilidad de añadir una imagen de fondo transparente que se posicione en la esquina inferior izquierda de ciertos iconos y que sirva para añadir información acerca del icono en cuestión. Por ejemplo, el sistema añade por defecto el icono de una flecha sobre aquellos iconos que representen un acceso directo. Adicionalmente, varios clientes de Subversion como por ejemplo Tortoise SVN hacen uso de estos iconos para mostrar de manera rápida al usuario el estado de los directorios/archivos (en correcto estado, con conflictos, no actualizados con respecto a la copia del servidor SVN, etc.). Véase la siguiente imagen como ejemplo:

Imagen de Tortoise SVN

El shell limita por diseño el número de este tipo de iconos a 15 (en las primeras versiones de Windows estaban limitados a 4). De esos 15 lugares disponibles, hay 4 posiciones que están reservadas para el sistema.

La primera posición la ocupa la imagen que se agrega a los recursos compartidos:

Compartidos

La segunda posición la ocupa la clásica flecha de los accesos directos:

 

AccesoDirecto

La tercera posición en un principio la ocupaba una marca de solo lectura que estuvo presente en las primeras versiones de Windows 95 y que en versiones posteriores desapareció (aunque se mantiene como reservada por motivos de compatibilidad). En Windows 7 según he podido comprobar la posición tercera ya no está reservada y la ocupa una nueva marca que hay por ejemplo en el panel Impresoras y dispositivos para indicar que se trata del elemento por defecto de un conjunto:

ImpresoraPorDefecto

La cuarta posición la ocupa el icono que representa archivos cuyo acceso se considera lento, por residir en una cinta, por ejemplo:

AccesoLento

A partir de Windows Vista, la información de los iconos de shell definidos por el sistema es pública y extraíble a partir de la API SHGetStockIconInfo. Simplemente pasando como primer parámetro a esta función el ID de un icono de sistema, recibiremos información adicional de dicho icono en una estructura SHSTOCKICONINFO. Una de las primeras comprobaciones que se realiza antes de extraer información adicional sobre el icono es ver si este no ha sido “redirigido” por el usuario. Un usuario puede “redirigir” los iconos de shell para que se usen otros diferentes. Para ello se debe crear una clave de registro de nombre HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Icons y en ella valores de cadena cuyo nombre sea el índice que identifica a ese icono de shell y cuyo contenido sea la ruta del nuevo icono que queremos usar en su lugar. Este procedimiento se suele usar para quitar el icono de flecha de los accesos directos, sustituyéndolo por un icono transparente. La lista de iconos de shell está presente en MSDN. Si el icono de shell no ha sido redirigido, este se obtiene desde alguna de las DLL de sistema que contienen iconos de shell, a saber: Shell32.dll, Imageres.dll, Imagesp1.dll y Mydocs.dll (que únicamente contiene el icono de “Documentos”). Para evitar acceder a disco excesivamente, estos iconos forman parte de la cache de iconos, mantenida por el shell.

Cuando Explorer se está inicializando, debe construir la lista de imágenes del sistema. Una lista de imágenes (image list) es básicamente un bitmap grande que contiene un cierto número de imágenes del mismo tamaño, accesibles a partir de un índice entero. Las listas de imágenes permiten marcar ciertas imágenes como superposiciones (overlays), es decir, como imágenes que se mostrarán en la esquina inferior izquierda de ciertos iconos. El shell inicializa un componente que administra todas estas superposiciones denominado overlay manager. Básicamente este componente se encarga de listar aquellas superposiciones de terceros que haya registradas, hasta un máximo de 11 (15 en total menos las 4 que están reservadas por el sistema). Las superposiciones de terceros están registradas en la clave de registro HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers. Posteriormente, el sistema se encarga de invocar el método IShellIconOverlayIdentifier::GetOverlayInfo de cada una de ellas (técnicamente reciben el nombre de icon overlay handlers). La extensión de shell implementará este método de manera que le devuelva al sistema la ruta y el índice correspondientes al icono que desea agregar como superposición a la lista de imágenes del sistema.

Generalmente, las superposiciones solo se muestran para cierto tipo de ficheros (por ejemplo, aquellos que tengan una cierta extensión). El sistema llama al método IsMemberOf de la extensión de shell y le aporta como parámetro el objeto de shell en cuestión para que la extensión decida si agregar la superposición o no. Si se diera el caso de que varias superposiciones pueden mostrarse para un cierto fichero, el sistema da prioridad a las superposiciones reservadas, y dentro de ellas la superposición de acceso directo tiene cierta preferencia sobre las demás. Si estas reglas no fueran capaz de decidir qué superposición mostrar, entra en juego el concepto de prioridad. Las extensiones de shell capaces de manejar superposiciones pueden registrarse con una prioridad entre 0 y 100, siendo 0 la más prioritaria. Si hubiera varias superposiciones posibles para un mismo objeto de shell, ganará la más prioritaria de todas.

Como conclusión, el hecho de que Microsoft restrinja el uso de superposiciones a un máximo de 15 quiere hacernos indicar que las superposiciones no son una forma idónea de agregar información a un icono. Uno de los motivos principales que se indica es que solo pueden presentar simultáneamente una única información, de las muchas que pudiera haber disponibles para ese elemento.

Práctica: Ver cómo ciertas aplicaciones cancelan la reproducción automática usando Spy++

En un artículo anterior en el que expliqué cómo funciona la reproducción automática en Windows 7 comenté que hay aplicaciones que deciden cancelar la reproducción automática bajo ciertas circunstancias. Un ejemplo de este tipo de aplicaciones es la aplicación de grabación de imágenes ISO de Windows 7 (Isoburn.exe), que cancela la reproducción automática si el dispositivo de grabación que está seleccionado en la lista desplegable es el responsable del evento de la reproducción automática. Vamos a verlo gráficamente.

Spy++ es una herramienta de Microsoft presente en Visual Studio. Esta herramienta muestra de manera jerárquica la relación entre ventanas, procesos e hilos del sistema a la vez que muestra información detallada sobre las ventanas y los mensajes asociados. Nada más abrir la herramienta nos encontramos con esta visualización gráfica del árbol de ventanas (cuya raíz es el escritorio):

Spy

Lo primero que notamos es que el número de ventanas que aparecen en el árbol es mucho mayor que el que aparece, por ejemplo, en la pestaña Aplicaciones de Administrador de tareas. Esto se debe a que la pestaña Aplicaciones de Administrador de tareas no muestra todas las ventanas existentes. Entre otras, no muestra ni la ventana correspondiente al propio Administrador de tareas (como es lógico), ni aquella cuyo título es “Program Manager” (lo que actualmente es Explorer.exe), ni las que tengan título en blanco (no tiene sentido mostrar una aplicación sin título en Administrador de tareas). Tampoco se muestran las ventanas que no tengan el atributo visible establecido, las que no aparezcan en la barra de tareas, o las que tengan el estilo WS_EX_TOOLWINDOW.

Abrimos la herramienta de grabación de imágenes de Windows 7 y cambiamos el árbol de visualización para que muestre procesos (menú Spy, Processes, o pulsar Ctrl+P), desplegamos el proceso Isoburn.exe y desplegamos el único hilo asociado (el responsable de la interfaz gráfica):

HiloIsoBurn

Ahora vamos a monitorizar los mensajes que estén relacionados con la ventana primera (la responsable de crear el cuadro de diálogo). Para ello la seleccionamos con el botón derecho y hacemos clic sobre Messages.

Vemos cómo Spy++ abre una nueva ventana para mostrarnos los mensajes involucrados con la ventana correspondiente al cuadro de diálogo de la herramienta de grabación de imágenes de Windows 7. Con dicha ventana en primer plano, introducimos un dispositivo USB y observamos que la pantalla de reproducción automática se muestra. Esto se debe a que la unidad seleccionada era la H: (la unidad de grabación en mi sistema), mientras que la unidad responsable de la reproducción automática era la de mi dispositivo de almacenamiento USB. Vemos que el sistema ha enviado un mensaje interesante: QueryCancelAutoPlay.

CancelAutoplay

Vemos que no se trata de un mensaje de sistema, sino uno registrado expresamente con ese nombre mediante una llamada a la función RegisterWindowMessage. Cuando una aplicación registra un mensaje, el sistema le otorga un identificador de mensaje único situado en el rango hexadecimal 0xC000 – 0xFFFF. Vemos que en este caso el sistema le ha otorgado el identificador 0xC234 al mensaje “QueryCancelAutoplay”. El mensaje justo a continuación es un mensaje de respuesta (marcado con una “R”), cuyo resultado, 0x0, le hace saber al sistema “no, no debes cancelar la reproducción automática”.

Veamos qué ocurre si introducimos un DVD en la unidad H. Lo primero que notamos es que la reproducción automática no se activa. Echamos un vistazo a la ventana de Microsoft Spy++:

CancelAutoplay2

En esta ocasión la respuesta enviada le hace saber al sistema que debe cancelar la reproducción automática, como así ocurre.

En este artículo hemos visto de qué manera ciertas aplicaciones manejan la reproducción automática en Windows mediante el tratamiento de ciertos mensajes enviados a sus ventanas. También hemos visto en qué consiste la herramienta Spy++ de Microsoft, que es muy útil para depurar aplicaciones gráficas Win32 y para aprender cómo funciona el sistema de ventanas y mensajes, cuya importancia es tal que ha dado nombre al sistema operativo.