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.

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.

Posted by dmartin | 3 comment(s)

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.

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.

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.

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.

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/

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.

Posted by dmartin | with no comments
Filed under:

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.

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.

Como creo que aún hay bastante gente que le tiene respeto a la utilidad Bcdedit.exe, la cual sirve para editar la lista de arranque de sistemas operativos Windows Vista y posteriores, en este artículo voy a dejar de la manera más clara posible y a modo de referencia qué comandos hay que usar para conseguir realizar las tareas más populares.

En este punto se supone que ha abierto una consola de comandos con privilegios administrativos. Para conseguir esto hay que hacer clic sobre el botón Inicio, Todos los programas, seleccionar Símbolo del sistema con el botón derecho del ratón y hacer clic sobre Ejecutar como administrador.

Nota: Es imprescindible que antes de manipular el almacén BCD del equipo se haga una copia de seguridad del mismo. Para ello, desde la consola de comandos con privilegios administrativos teclee este comando:

bcdedit /export <NombreFichero>

(donde <NombreFichero> es el nombre que le quiera dar a la copia de seguridad).

Eliminar una entrada del inicio

Imaginemos que hemos eliminado físicamente un sistema operativo del equipo, pero aún tenemos su entrada correspondiente en el menú de arranque. Para eliminarla, mi consejo es ver si la herramienta gráfica Msconfig nos permite hacer esto. Abra Inicio, escriba msconfig en la caja de texto y pulse INTRO. Cuando se abra la herramienta, haga clic sobre la pestaña Arranque y observe si aparece la entrada que quiere eliminar.

Nota: Si Msconfig no lista la entrada que quiere eliminar, esto se debe a que Msconfig solo muestra los objetos del almacén BCD cuyo tipo es “Cargador de arranque de Windows”. Puede ver el tipo de cada entrada del almacén tecleando este comando:

bcdedit /enum

En tal caso, tendrá que recurrir a la eliminación “manual”, usando Bcdedit.exe, explicada más adelante.

Pese a que aparezca la entrada que quiere eliminar, es posible que el botón Eliminar esté desactivado (en gris). Este botón se desactiva cuando la entrada que quiere eliminar es el sistema operativo que está iniciado en ese momento. Técnicamente Bcdedit identifica esta entrada con el identificador {current}. Este es un extracto de la salida del comando bcdedit /enum, donde se ve claramente cuál es la entrada identificada como {current}:

Cargador de arranque de Windows
-----------------------------
Identificador           {current}
device                  partition=C:
path                    \Windows\system32\winload.exe
description             Windows 7
locale                  es-ES

Si la entrada tiene simultáneamente las propiedades de ser el sistema operativo iniciado en ese momento y además ser el sistema operativo por defecto (identificador {default}), su identificador será {current}.

Como se ha comentado anteriormente, la herramienta Msconfig es posible que no nos muestre la entrada que queremos quitar. El escenario más común es tener instalado simultánemente un sistema operativo anterior a Windows Vista/7. La entrada de estos objetos en el almacén BCD tiene un tipo distinto de “Cargador de arranque de Windows”, concretamente tienen tipo “Cargador del SO Windows heredado” (pésima traducción, por otra parte).

En estos casos no queda más remedio que remangarse las manos y usar Bcdedit.exe, de la siguiente manera:

Para eliminar la entrada “Versión anterior de Windows”

bcdedit /delete {ntldr} /f

(El modificador /f hay que usarlo siempre que se use un GUID conocido, como {ntldr} y similares. Esto se explicará en detalle más adelante).

Para eliminar cualquier otra entrada

En este caso tenemos que enumerar en primer lugar todos los objetos que forman parte del almacén BCD:

bcdedit /enum

Nos fijamos en el atributo Descripción, que es el texto que muestra el menú de arranque, para identificar la entrada que queremos eliminar. A partir de ahí, anotamos el valor correspondiente a su atributo Identificador. Por ejemplo, si el atributo Identificador contuviera lo siguiente: {afb0516d-f5bd-11dd-8879-98b0f6447174}, para eliminarla del arranque bastaría con ejecutar el siguiente comando:

bcdedit /delete {afb0516d-f5bd-11dd-8879-98b0f6447174}

(Nótese que aquí no es necesario el modificador /f).

Hay gente que utiliza adicionalmente el modificador /cleanup, y el comando quedaría tal que así:

bcdedit /delete {afb0516d-f5bd-11dd-8879-98b0f6447174} /cleanup

Es importante hacer notar que ambos comandos hacen lo mismo, el modificador /cleanup está implícito.

Cambiar el sistema que inicia por defecto

Como sabe, en un entorno con múltiples sistemas operativos instalados, si el usuario no elige ninguno durante un tiempo definido, se inicia uno por defecto. Para cambiar el sistema operativo por defecto, podemos usar Msconfig. Seleccionamos el sistema operativo en cuestión y pulsamos sobre Establecer como predeterminado.

Cambiar el texto de la entrada del menú de inicio

Cambiar el texto descriptivo de un sistema operativo en el almacén BCD es una tarea común, especialmente para la gente que instale varias ediciones de un mismo sistema operativo (por defecto tendrán todas el mismo nombre en el menú).

Para conseguir esto, hay que averiguar el identificador del objeto con el que queremos trabajar, y para ello hay que seguir los mismos pasos del subapartado “Para eliminar cualquier otra entrada”, pero en último lugar hay que ejecutar este otro comando:

bcdedit /set {GUID} /description “Mi nueva descripcion del SO”

(donde {GUID} es el identificador obtenido en el paso anterior; siguiendo con el ejemplo anterior sería {afb0516d-f5bd-11dd-8879-98b0f6447174}).

Cambiar el orden de la lista de sistemas operativos

Para realizar este paso tenemos que recurrir a Bcdedit.exe.

En primer lugar nuevamente hay que averiguar el identificador de los objetos que queremos posicionar en la lista. Una vez obtenidos, podemos ejecutar este comando:

bcdedit /displayorder {802d5e32-0784-11da-bd33-000476eba25f} {cbd971bf-b7b8-4885-951a-fa03044f5d71} {ntldr}

Este comando posicionaría en la lista (en este orden), los sistemas cuyos identificadores son {802d5e32-0784-11da-bd33-000476eba25f}, {cbd971bf-b7b8-4885-951a-fa03044f5d71} y {ntldr}, que representaría un sistema Windows XP, por ejemplo.

También podemos añadir sistemas al principio o al final. Por ejemplo, para añadir el sistema cuyo identificador sea {802d5e32-0784-11da-bd33-000476eba25f} al final de la lista, bastaría con ejecutar:

bcdedit /displayorder {802d5e32-0784-11da-bd33-000476eba25f} /addlast

Y para colocarlo al principio:

bcdedit /displayorder {802d5e32-0784-11da-bd33-000476eba25f} /addfirst

Este artículo ha explicado cómo realizar las tareas no reparativas más comunes con el arranque de los sistemas operativos Vista y 7, usando la herramienta gráfica Msconfig.exe, y la de línea de comandos Bcdedit.exe, ambas incluidas con el sistema operativo.

Ciertamente existen multitud de utilidades de terceras personas que editan de manera gráfica el almacén BCD del equipo; quizá la más popular sea EasyBCD (http://neosmart.net/dl.php?id=1). En cualquier caso, use la herramienta que use, es altamente importante que haya hecho una copia de seguridad del arranque en caso de algo vaya mal.

Si cree que faltara alguna acción en el arranque que sea bastante común, o tuviera algún problema con las herramientas Bcdedit.exe o Msconfig.exe, puede dejar un comentario.

Posted by dmartin | with no comments

Un usuario realizó esta pregunta desde la sección Contact del blog:

Tengo Windows 7 y me gustaría que mi aplicación configurara de manera temporal la profundidad de color de los iconos en 16 bits. El resto de la pantalla tiene que tener profundidad de color de 32 bits. En Windows 2000 esto lo hacía creando el valor de Registro Shell Icon BPP en la clave HKCU\Control Panel\Desktop\WindowMetrics. En Windows 7 escribo ese valor y no tiene efecto, ni siquiera reiniciando Explorer.exe.

La respuesta corta es que Windows Vista y Windows 7 no tienen en cuenta ese valor de registro. De hecho, este valor ya puede considerarse obsoleto incluso en sistemas anteriores, pues en un altísimo porcentaje de los casos ni siquiera era tenido en cuenta. A continuación paso a explicar en detalle cómo se asigna la profundidad de color a los iconos en las distintas versiones de Windows.

Cuando Windows tiene que inicializar los iconos del shell, una de las primeras cosas que hace es comprobar cuál es la configuración de profundidad de color de sistema. Esto tiene un cometido doble: Por un lado, se extraen listas de iconos de la calidad adecuada (las listas de iconos se conocen en la terminología del shell como ImageLists) y por otro lado se determina si la cache de iconos actual sigue siendo válida o no. Este es el motivo por el cual un método para regenerar la cache de iconos es cambiar temporalmente la profundidad de color del sistema.

Windows 95/98

En Windows 95/98, la profundidad de color de los iconos se podía modificar a través del valor de registro Shell Icon BPP de la clave HKCU\Control Panel\Desktop\WindowMetrics, siempre y cuando este valor de registro tuviera un valor inferior o igual al de la profundidad de color general del sistema. De no ser así, el sistema establecía como profundidad de color para los iconos unos paupérrimos 4 bits por píxel (16 colores, VGA).

Windows XP

En Windows XP, el valor de registro Shell Icon BPP tiene poca utilidad. Siempre que el sistema detecte que la profundidad de color es igual o superior a 24 bits por píxel establecerá una profundidad de color para los iconos de 32 bits por píxel (color verdadero). Así pues, el valor de registro solo tiene validez si la profundidad de color del sistema es inferior, concretamente de 16 bits por píxel, pues no puede ser inferior tampoco, porque de ser así el sistema establecerá colores VGA, independientemente de lo que le diga el valor de registro.

Windows Vista y 7

Viendo el lío que causaba entre los usuarios el establecer una profundidad de color para los iconos a través del registro y ver que el sistema no hiciera caso, Microsoft decidió restructurar la configuración de la profundidad de color para los iconos en sus dos últimos sistemas operativos, Vista y 7.

En primer lugar, el valor Shell Icon BPP no tiene ninguna validez en estos sistemas, no sirve absolutamente para nada. Si la profundidad de color general es de 8 bits por píxel o inferior (por algún desajuste en el controlador gráfico, por ejemplo), el shell extraerá iconos con una profundidad de color VGA.

Si la profundidad de color general es de 16 bits por píxel, el sistema extrae iconos con una calidad de 32 bits, siempre y cuando el usuario no exija extraer iconos con una calidad igual a la de la profundidad de color de la pantalla. Esto se puede hacer si establece un valor de registro del cual no encontré referencias en Internet pero que descubrí trazando la inicialización de la cache de iconos con el genial Process Monitor. El valor de registro es de tipo DWORD, tiene como nombre AllowLowerBppSystemImageLists y se situaría en la clave HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced (o en su homóloga en HKLM). Un contenido igual a 1 para ese valor le diría al sistema “sé que mi profundidad de color no es demasiado elevada, pero quiero que extraigas iconos con una profundidad de color igual a la del sistema, no igual a 32 bits por píxel”. Al hacer esto en teoría se ahorra una pequeñísima cantidad de memoria pero a cambio los iconos no lucirán tan bonitos como de costumbre. No es un valor de registro que le merezca la pena tocar a un usuario doméstico.

Para profundidades de color superiores a 24 bits por píxel, se predetermina 32 bits por píxel para los iconos.

Así pues, podemos concluir este artículo diciendo “Shell Icon BPP, R.I.P”.

A día de hoy es mucha la gente que sigue usando Windows XP y de vez en cuando veo a algún usuario de ese sistema que experimenta problemas con Restaurar sistema. Los síntomas son variados, desde imposibilidad para realizar correctamente la restauración, mensajes de error crípticos (mis preferidos :-P), servicios que no se inician o que experimentan muerte súbita, etc.

Como primera medida suelo remitirle a mi artículo http://www.fermu.com/content/view/249/2/lang,es/, que recoge los síntomas y soluciones más comunes. Cuando este artículo no logra solucionar el problema del usuario, es necesario recabar información detallada de ese sistema. Por supuesto, hay que acompañar esta información detallada con una buena descripción de los síntomas que se experimentan (qué pasos se siguen, qué resultados anómalos se obtienen).

Lo que no mucha gente sabe es que Microsoft incluyó en Windows XP una herramienta encargada de recabar información detallada sobre el estado de Restaurar sistema. La herramienta en cuestión se llama Srdiag.exe y está situada en el directorio %SystemRoot%\system32\restore\. Al ejecutarla, aparecerá una ventana de línea de comandos que no debe cerrar, pues por lo bajo se está generando un fichero CAB con toda la información. Cuando termine el proceso y desaparezca la ventana de comandos, acceda al directorio %SystemRoot%\system32\restore\ y allí verá un fichero CAB cuyo nombre coincide con el nombre del equipo concatenado con la fecha y hora. Si prefiriese crear el fichero CAB en otra carpeta de su elección, puede ejecutar la utilidad desde la línea de comandos mediante esta sintaxis:

srdiag.exe /CabName:<NombreCAB>.cab /CabLoc:<RutaFicheroCAB>

Al extraer el mencionado fichero CAB, nos encontramos con distintos ficheros de reporte, de los cuales los más interesantes son los siguientes:

SR-FileList.log

Este fichero contiene una lista con todos los ficheros que componen la herramienta Restaurar sistema, así como su versión, firma digital y demás información complementaria. El contenido de este fichero nos permite saber si los archivos que componen Restaurar sistema están en perfecto estado.

SR-Reg.log

Este fichero contiene las claves registro relacionadas con Restaurar sistema. A partir de este fichero, comparando con un sistema en perfectas condiciones, podemos ver si tanto el servicio de Restaurar sistema, como su controlador asociado (Sr.sys), así como las políticas relacionadas con Restaurar sistema están en correcto estado.

SR-EventLogs.log

Este fichero contiene todos los eventos del Visor de sucesos que tienen relación con Restaurar sistema. Esta información puede incluir códigos de error, mensajes de advertencia o informativos que pueden ser clave para detectar la causa del problema.

SR-ChgLog.log

Este fichero suele ser el más voluminoso de todos. Contiene información detallada acerca de los cambios que ha habido en el disco o discos que están siendo monitorizados por Restaurar sistema. Cada fila de este fichero tiene los siguientes campos:

RPDir: Carpeta que almacena el punto de restauración al cual pertenece este cambio.

Drive: Unidad de disco implicada.

SeqNum: Número de secuencia para la operación en cuestión.

EventString: Tipo de evento (cambio de atributos, creación de fichero, creación de directorio, eliminación de fichero, eliminación de directorio).

Flags: Etiquetas adicionales de la operación.

Attr: Atributos de la operación.

Acl: Si la operación implica un cambio de ACL o no.

AclSize: Tamaño de ACL.

Process: Proceso implicado.

ProcName: Nombre del proceso implicado.

Path1: Ruta implicada en la operación.

SR-RP.log

Este fichero contiene el nombre, fecha y tipo de cada uno de los puntos de restauración almacenados en el equipo.

SR-RstrLog.log

Este fichero contiene un reporte detallado de las operaciones realizadas durante un proceso de restauración. Contiene la misma información que el fichero Rstrlog.dat (pero en modo texto). Ante una restauración que no puede completarse debería examinarse este fichero con todo detenimiento.

Lo ideal es posicionarse en la línea correspondiente a “START UNDO”, que indica que van a empezar a revertirse los cambios que se hayan hecho en la restauración fallida. A partir de ahí examinar hacia arriba el fichero para ver qué operación ha causado el fallo de la restauración. Personalmente me gusta consultar paralelamente el fichero SR-ChgLog.log tomando los números de secuencia como referencia. En este artículo mío tiene información acerca de los errores que pueden abortar una restauración: http://rinconwindows.blogspot.com/2007/03/cmo-funciona-restaurar-sistema-parte-ii.html. La línea correspondiente al error tiene esta forma:

103, 103,42572, DirAdd, Fail, 5, C:\Documents and Settings\All Users\Datos de programa\Symantec\LiveUpdate\Downloads\Tri999, ,

En este caso concreto, debemos centrarnos en la tercera columna, el tipo de operación que se ha realizado (crear un directorio), la cuarta columna, que nos indica que ha ocurrido un fallo, la quinta columna, que nos indica el código de error que se ha devuelto (en este caso, 0x5, acceso denegado) y la sexta columna, que indica qué carpeta o fichero se ha visto implicado en la operación (en este caso, una carpeta de la suite de seguridad de Symantec).

En resumen, estos los los pasos que se deberían seguir para solucionar un problema con Restaurar sistema en Windows XP (no es aplicable a sistemas posteriores):

  1. Seguir los pasos de solución de problemas de este artículo general: http://www.fermu.com/content/view/249/2/lang,es/. Si siguiera el problema, pasar al punto 2.
  2. Generar los reportes mediante la utilidad Srdiag.exe siguiendo los pasos de este mismo artículo.
    1. Si al iniciar Restaurar sistema ocurre algún error, comprobar si el servicio está iniciado. Si no lo está, intentar iniciarlo. Si no es posible iniciarlo, consultar los ficheros SR-FileList.log, SR-Reg.log y SR-EventLogs.log.
    2. Si la restauración no se puede completar, consultar los ficheros SR-RstrLog.log y SR-ChgLog.log.
    3. Si la causa del problema puede ser alguna unidad que está siendo monitorizada por Restaurar sistema, o si estas no aparecieran correctamente en Panel de control, Propiedades de sistema, pestaña Restaurar sistema, consultar el fichero Drivetable.txt.
Posted by dmartin | with no comments

A continuación vamos a ver técnicas para examinar de manera útil y detallada una de las estructuras de datos más importantes: la pila.

¿Qué es una pila?

La pila es una de las estructuras de datos más sencillas que existen. Consta básicamente de dos operaciones: apilar, que introduce elementos en la pila, y desapilar, que quita el elemento que ocupa la primera posición (la cima) de la pila, siempre y cuando tenga alguno. Como ve, se asemeja a una pila de platos o una pila de libros. Los primeros elementos que llegan a la estructura son los últimos que la desocupan; es decir, se trata de una estructura de tipo LIFO (Last In, First Out).

El estudio de esta estructura de datos no es caprichoso: Se trata de la estructura de datos que sustenta, entre otras cosas, las cadenas de llamadas a funciones, por lo que proporciona información muy importante para cualquier persona que esté investigando un problema en Windows (y en general, en cualquier otro sistema operativo).

¿Qué es la pila de ejecución?

La pila de ejecución es una porción de memoria que se le asigna a un hilo de un proceso y que se maneja siguiendo la estructura de datos de una pila. La pila de ejecución se crea cuando nace un nuevo hilo (mediante una llamada a la función CreateThread). Cada hilo tiene una pila de ejecución en modo usuario y una pila de ejecución en modo núcleo (excepto los hilos de sistema o creados por un controlador, que solo disponen de una pila de ejecución en modo núcleo).

Estructura básica de la pila de ejecución

Una buena forma de comprender y ver de manera práctica cuál es la estructura de la pila de ejecución de un hilo es hacer uso de los comandos que desensamblan porciones de código en Windbg.

Abrimos Windbg e iniciamos en él una nueva sesión de depuración (se supone que la información simbólica está correctamente configurada). En la caja de comandos introducimos el siguiente comando para desensamblar, por ejemplo, la función SHCreateFileExtractIcon de Shell32:

0:000> uf SHELL32!SHCreateFileExtractIconW

El comando uf, como ya comenté en un anterior artículo, sirve para desensamblar completamente una función. La salida de este comando podemos dividirla en tres conjuntos de instrucciones bien diferenciados: el prólogo de la función, el contenido de la función y el epílogo de la función. Vamos a prestar especial atención al prólogo de la función, que es el encargado de preparar la pila de ejecución para que la función en curso se ejecute correctamente. Estas son las cuatro primeras instrucciones que aparecen en la salida del comando anterior:

SHELL32!SHCreateFileExtractIconW:
7601877c 8bff            mov     edi,edi
7601877e 55              push    ebp
7601877f 8bec            mov     ebp,esp
76018781 81ecc0020000    sub     esp,2C0h

La primera instrucción le resultará extraña a cualquier programador en ensamblador. Mov edi, edi es una instrucción que aparentemente mueve el contenido del registro edi en el registro edi, es decir, no hace absolutamente nada. Sin embargo, esa instrucción sirve para implementar el mecanismo de hotpaching en Windows. Hotpaching es la capacidad para instalar actualizaciones en Windows sin que sea necesario reiniciar el componente que está siendo actualizado. El secreto reside en que la instrucción mov edi, edi puede ser sustituida por una instrucción de salto (jmp) que apunte a la dirección de hotpaching. Como la instrucción mov edi, edi ocupa solamente 2 bytes, el único salto que se puede realizar es un salto pequeño (hasta 2^7 – 1 bytes hacia arriba o hacia abajo). Sin embargo, si desensamblamos unas cuantas instrucciones anteriores a esta función nos encontramos con algo bastante interesante:

0:000> u SHELL32!SHCreateFileExtractIconW-9
SHELL32!SHCreateLinks+0x1b:
76018773 5d              pop     ebp
76018774 c21400          ret     14h
76018777 90              nop
76018778 90              nop
76018779 90              nop
7601877a 90              nop
7601877b 90              nop
SHELL32!SHCreateFileExtractIconW:

Como ve, hay cinco instrucciones que no hacen nada (no-operaciones, nop), cada una de 1 byte de tamaño. En total tenemos 5 bytes que podemos utilizar para poder realizar, ahora sí, un salto grande a la dirección de hotpaching. En un próximo artículo de este blog explicaré con todo detalle cómo funciona hotpaching en Windows.

La siguiente instrucción del prólogo de la función, push ebp, guarda en la pila de ejecución el contenido del registro ebp. El registro ebp contiene el valor del puntero base, que sirve para poder enlazar los marcos de funciones que se introducen en la pila. Concretamente, el puntero base apunta siempre al comienzo del marco de ejecución de una función (de ahí que también reciba el nombre de puntero al registro de activación) y sirve para poder utilizarlo como referencia cada vez que se quieran hacer desplazamientos relativos. Por este motivo, el contenido de este registro debe poder ser restaurado cada vez que finaliza la ejecución de una función (momento en el cual desaparece su marco de la pila). El registro ebp siempre se guarda en la pila antes de llamar a una función. No solamente debe almacenarse ese registro, cuando se realiza una llamada a una nueva función (en ensamblador, call <NombreFunción>), también debe almacenarse la dirección de retorno de la función, para que el procesador sepa qué instrucción debe ejecutar cuando finalice la función a la que se está llamando.

La instrucción mov ebp, esp almacena en el registro ebp el contenido del registro esp, que como ya comenté en un artículo anterior se trata del puntero de pila. El efecto de esta instrucción es que tanto el registro ebp como el puntero de pila (esp) apunten a la misma dirección de memoria, el comienzo del marco de ejecución de la función en curso.

La última instrucción del prólogo, sub esp, 2C0h, resta 2C0 (704 en decimal) bytes al puntero de pila. Esto se hace para reservar espacio para las variables locales de la función. Se usa la instrucción resta (sub) y no suma (add) porque la pila va creciendo hacia direcciones decrecientes de memoria. Esto es un punto que siempre debe tener presente cuando depure código en Windows.

El epílogo de la función es similar al prólogo, pero básicamente restaurando los cambios realizados en la pila de ejecución. Es decir, se suma al puntero de pila la cantidad de bytes que se restara al comienzo de la ejecución de la función (y por consiguiente, las variables locales desaparecen), se restaura el contenido del valor del puntero de pila con el contenido del valor del registro ebp, se desapila (pop) el valor del registro ebp que se guardó al comienzo de la ejecución de la función, y se pasa a ejecutar a partir de la dirección de retorno, que también fue debidamente guardada antes de llamar a la función que en estos momentos está a punto de finalizar.

Vemos un resumen gráfico de este aparentemente complejo proceso:

Pila

Vemos que en el marco de pila del diagrama, antes de proceder a la llamada de MiFunc2 desde MiFunc se almacenan también en la pila los parámetros que recibe esta función, justo antes de la dirección de retorno. De la manera en la que se almacena información en la pila podemos deducir estas dos reglas bastante útiles:

  • Si queremos acceder a los parámetros de una función, debemos partir del registro ebp y sumar la cantidad de bytes necesaria (@ebp + desp).
  • Si quieremos acceder a las variables locales de una función, debemos partir del registro ebp y restar la cantidad de bytes necesaria (@ebp – desp).

Estas dos reglas no son reglas de oro, pues en ocasiones las optimizaciones que realiza el compilador a la hora de almacenar variables dificulta este tipo de análisis.

La pila de ejecución de un hilo es un tema que podría ocupar buena parte de un libro, así que aquí solo se han resaltado los conceptos principales sobre el puntero de pila, el paso de parámetros, la salvaguarda de la dirección de retorno y la reserva de espacio para variables locales. Estos son los temas principales que debe manejar con soltura cuando se disponga a examinar la pila de ejecución de algún hilo. Vamos a ver qué comandos tiene Windbg para mostrar trazas de pila.

La familia de comandos k*

La familia de comandos k* de Windbg nos permite sacar por pantalla una traza de pila del contexto activo de depuración. ¿Qué es el contexto activo de depuración? Cuando se está depurando código en modo usuario, el contexto activo de depuración es el hilo actual. Para ver qué hilo es el hilo actual, puede usar el comando ~. (nótese que hay un punto al final). Para cambiar el hilo actual, para así poder mostrar la traza de pila de otro de los hilos, puede usar el comando ~<Hilo>s. Por ejemplo, para cambiar el hilo actual por el hilo número 2, podría usar la sintaxis ~2s. También es posible cambiar el hilo actual desde la interfaz gráfica de Windbg. Para ello vaya al menú View y haga clic sobre Processes and Threads (o pulse Alt+9). Haga doble clic sobre algún hilo para hacerlo el hilo actual, que además quedará marcado en negrita.

Una vez que el hilo actual esté establecido en el hilo que desea examinar, ya se puede proceder a mostrar su traza de pila. El comando más básico para conseguir esto es el comando k. Este es un ejemplo de la salida de este comando:

0:005> k
ChildEBP RetAddr 
05b6fb30 774f5e7c ntdll!KiFastSystemCallRet
05b6fb34 774e067b ntdll!NtWaitForWorkViaWorkerFactory+0xc
05b6fc94 77421194 ntdll!TppWorkerThread+0x216
05b6fca0 7750b3f5 kernel32!BaseThreadInitThunk+0xe
05b6fce0 7750b3c8 ntdll!__RtlUserThreadStart+0x70
05b6fcf8 00000000 ntdll!_RtlUserThreadStart+0x1b

En este ejemplo puede ver que el hilo actual es el hilo 5 (0:005). Cada una de las filas de esta tabla de información representa un marco de pila, una ejecución de función en un momento determinado. Se debe leer de abajo hacia arriba, es decir, la función _RtlUserThreadStart de Ntdll llamó a la función __RtlUserThreadStart, la cual llamó a BaseThreadInitThunk de Kernel32, y así sucesivamente. La columna ChildEBP nos dice, para cada marco de pila, cuál es la dirección del registro ebp (recuerde que dicha información queda almacenada en la pila para poder enlazar dinámicamente los marcos de pila). La columna RetAddr nos dice qué dirección de memoria pasará a ejecutarse cuando desaparezca ese marco de pila.

Si disponemos de información simbólica completa (algo que es muy raro si estamos depurando un programa Windows de terceros), podemos aprovecharnos de dicha información para que Windbg nos muestre información detallada sobre todos los parámetros de cada función. Para ello usamos el comando kp (similarmente, kP, pero este muestra los parámetros en una nueva línea).

Si no disponemos de información simbólica completa (lo habitual), podemos decirle a Windbg que nos muestre los 3 primeros parámetros de cada función. El comando que consigue esto , es kb:

0:005> kb
ChildEBP RetAddr  Args to Child             
05b6fb30 774f5e7c 774e067b 00000128 05b6fbe8 ntdll!KiFastSystemCallRet
05b6fb34 774e067b 00000128 05b6fbe8 73e952b4 ntdll!NtWaitForWorkViaWorkerFactory+0xc
05b6fc94 77421194 02efe378 05b6fce0 7750b3f5 ntdll!TppWorkerThread+0x216
05b6fca0 7750b3f5 02efe378 73e952c0 00000000 kernel32!BaseThreadInitThunk+0xe
05b6fce0 7750b3c8 774dd63e 02efe378 00000000 ntdll!__RtlUserThreadStart+0x70
05b6fcf8 00000000 774dd63e 02efe378 00000000 ntdll!_RtlUserThreadStart+0x1b

Las tres columnas correspondientes a Args to Child nos proporciona los tres primeros parámetros de cada función. Estos parámetros pueden ser tipos de datos simples (enteros, etc.), o bien punteros a direcciones de memoria que alberguen tipos más complejos (como estructuras de datos). Dado que el espacio de pila es un bien bastante preciado (y en modo núcleo lo es aún más), difícilmente va a ver estructuras de datos completas pasadas como parámetros a funciones. Tiene pues que utilizar los conceptos sobre interpretación de direcciones de memorias que aprendió en un anterior artículo para poder examinar detalladamente dichos parámetros.

En un siguiente artículo seguiremos viendo los entresijos de la familia de comandos k* y aprenderemos a reconstruir una traza de pila en aquellos casos en los que por diversos motivos Windbg no puede hacer el trabajo por nosotros (es decir, casos del mundo real). Veremos también en qué consisten las distintas convenciones de pasos de parámetros que hay en programación, pues esto tiene influencia en la pila de ejecución resultante.

Posted by dmartin | with no comments
Filed under: ,

Por lo que he ido viendo desde que Windows 7 salió a la luz, mucha gente no tiene totalmente claro a qué se refiere la opción "Ocultar unidades vacías en la carpeta Equipo" que está en el panel Opciones de carpeta, pestaña Ver. De hecho, mucha gente recomienda cambiar el estado de esa casilla cuando la unidad de CD/DVD no se muestra en Equipo.

La respuesta corta es que la funcionalidad que ofrece esa casilla no es aplicable a las unidades de CD/DVD. Solo es aplicable a lectores de tarjetas y dispositivos similares.

Cuando Windows tiene que decidir si debe mostrar o no una unidad en Equipo, en primer lugar comprueba si hay alguna configuración que evite su aparición. Se puede evitar la aparición de una unidad en Equipo de dos formas, mediante una directiva o mediante un valor de Registro por usuario, nuevo en Windows 7.

El nuevo valor de Registro está en la clave de Registro HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced, es de tipo DWORD y su nombre es NeverShowDrivesMask.

La directiva se denomina NoDrives y está presente en versiones anteriores de Windows: http://technet.microsoft.com/en-us/library/cc938267.aspx. En el artículo de Technet puede ver la clave de registro que activa esta directiva.

El contenido de los valores DWORD NeverShowDrivesMask y NoDrives es un campo de 32 bits, de los cuales se usan los 26 de más a la derecha. Basta con poner un 1 binario en la posición correspondiente a la unidad o unidades que queremos ocultar. Por ejemplo, si queremos ocultar las unidades C y D, pondríamos un 1 binario en la tercera y cuarta posición (1100). Por tanto, el valor de tipo decimal que tenemos que poner en este caso es el 12. Puede aplicar simultáneamente la directiva de grupo y el valor de registro por usuario.

Si la unidad no estuviera siendo ocultada por alguna de las configuraciones anteriores, se comprueba si la casilla "Ocultar unidades vacías en la carpeta Equipo" está marcada. Si así fuese, si la unidad está vacía y no es una unidad de CD/DVD, no se muestra en Equipo. Las unidades que entran en juego en este punto son aquellas que son capaces de notificar si tienen contenido o no; es decir, lectores de tarjetas y similares (las unidades lectoras de disquetes no suelen permitir esta característica). Las unidades de CD/DVD también notifican si tienen un disco o no, pero como se ha comentado, no se ven afectadas por esta configuración.

Si en Equipo no se mostrara su unidad de CD/DVD y ha comprobado que no está oculta por alguna de las dos directivas antes mencionadas, lo primero que debería hacer es ejecutar el solucionador de problemas de hardware de Windows 7. Este solucionador de problemas incorpora el método de solución de problemas descrito en este artículo de la KB: http://support.microsoft.com/kb/314060/es. Suele ocurrir cuando software de grabación o similar instala filtros en la unidad de CD/DVD.

Si persistiera el problema y la unidad es reconocida por la BIOS de la máquina (si no la reconociera, casi con total seguridad se trata de un problema de hardware o de configuración de hardware), pruebe a desinstalar desde Administrador de dispositivos el canal IDE del que cuelgue la unidad y reinicie el sistema para forzar a que la reconozca nuevamente.

Espero que este artículo haya aclarado las dudas que hay con respecto a la opción "Ocultar unidades vacías en la carpeta Equipo" para que así evite perder tiempo cambiando opciones que no le van a ayudar a solucionar su problema concreto.

Posted by dmartin | with no comments

Artículos anteriores

En el anterior artículo vimos de forma resumida en qué consiste la nueva arquitectura MUI de Windows Vista/7, así como los beneficios que conlleva el separar físicamente los recursos dependientes del idioma del resto de binarios del sistema. En esta parte vamos a ver que la configuración de idioma va más alla de la interfaz que se le muestra al usuario.

Es importante que resalte un punto que comenté en mi anterior artículo: Cuando se separan los archivos binarios (independientes del idioma) de los archivos de recursos, se corre el riesgo de juntarse con miles de ficheros si la aplicación tiene el calibre de un sistema operativo. Y lo que es más importante, se trata en su mayoría de ficheros muy pequeños (menos de 4 KB), lo que tiene un importante impacto negativo en el sistema pues las reservas de memoria física se hacen con una granularidad de 4 KB (64 KB en el caso de memoria virtual). Por este motivo, Microsoft decidió que un mismo fichero alojara recursos de múltiples idiomas.

Los recursos que forman parte de un módulo de recursos suelen ser los de los componentes adicionales de los que dependa la aplicación (como DLL, por ejemplo), pues el sistema va a requerirlos en algún momento y el tenerlos simultáneamente en memoria ahorra operaciones de E/S, que como son difícilmente optimizables hay que intentar reducirlas a toda costa.

En Windows Vista/7 existen varios ámbitos para un idioma o conjunto de idiomas instalados. En este epígrafe se explicarán cuáles son estos ámbitos, cuándo y dónde se configuran y qué implicaciones prácticas tienen.

Idioma de instalación

También denominado idioma por defecto de la interfaz de sistema, es el idioma que selecciona el usuario al comenzar la instalación del sistema operativo.

La lista de idiomas se genera a partir del fichero \sources\Lang.ini del DVD de instalación. En caso de que el idioma o idiomas no estuviera(n) ya instalado(s) en la imagen WIM de Windows, el programa de instalación lo(s) instala. En Windows Vista esto se realiza llamando a la herramienta Pkgmgr.exe, pero en Windows 7 se usa la nueva herramienta Dism.exe. Concretamente, el parámetro /Add-Package permite instalar paquetes (ya sea paquetes de idiomas o actualizaciones) en una imagen de Windows 7. Puede obtener más información sobre Dism.exe en esta página: http://technet.microsoft.com/en-us/library/dd744382(WS.10).aspx

En caso de que la imagen tenga instalados varios idiomas y la edición de Windows no fuera Ultimate o Enterprise, el resto de idiomas se desinstalan automáticamente al finalizar la instalación, mediante la tarea programada LPRemove.

Resumidamente, el idioma de instalación por así decirlo es el idioma "por defecto" del sistema operativo; es el primer idioma que se configura en el sistema y no se puede cambiar posteriormente. En general, tiene un uso bastante reducido pues se tiene más en cuenta la lista de idiomas por sistema, que se describe a continuación. Si desarrolla aplicaciones y quiere saber qué idioma es el idioma de instalación, puede usar la API GetSystemDefaultUILanguage. Ojo, tenga especialmente en cuenta que el idioma de instalación y el idioma de la interfaz gráfica del usuario pueden ser diferentes.

Lista de idiomas por sistema

La lista de idiomas por sistema contiene el idioma de instalación, el idioma principal de sistema, y una lista de idiomas de apoyo (fallback languages) para el caso en que el idioma principal fuese un idioma parcialmente traducido o un LIP (Language Interface Pack) como el hindi o el catalán.

El idioma de sistema es el idioma que se usa cuando no hay ningún usuario con sesión iniciada o bien cuando el usuario no ha cambiado su configuración de idioma. Se puede cambiar siguiendo los pasos de este artículo de la documentación de Windows 7: http://windows.microsoft.com/es-ES/windows7/Apply-regional-and-language-settings-to-reserved-accounts. Una aplicación no puede cambiar la lista de idiomas por sistema, pero sí consultarla mediante la API de Win32 GetSystemPreferredUILanguages.

Lista de idiomas por usuario

En Windows Vista/7 cada usuario puede establecer un idioma de su elección (si la edición de Windows 7 así lo permite). Para cambiarlo se deben seguir los pasos de este artículo de la documentación de Windows 7: http://windows.microsoft.com/es-ES/windows7/Install-or-change-a-display-language. Como en el caso anterior, para dar el control al usuario las aplicaciones no pueden modificar esta lista de idiomas. Para consultarla puede llamar a la API GetUserPreferredUILanguages. El primer idioma de la lista es el idioma de la interfaz gráfica.

Lista de idiomas por proceso

Cada proceso puede establecer una lista de hasta 5 idiomas. Esta lista se almacena en el bloque de control de proceso (PEB), que es una estructura del núcleo de Windows que mantiene información sobre cada uno de los procesos del sistema. En un próximo artículo se detallará qué información sobre MUI está almacenada en el bloque de control de proceso y de qué forma.

Para consultar el idioma por proceso una aplicación puede llamar a la API GetProcessPreferredUILanguages. Para modificar esa lista, se puede usar la función SetProcessPreferredUILanguages.

Lista de idiomas por hilo

Cada hilo de un proceso puede establecer su lista de 5 idiomas preferidos.  Esta lista se almacena en el bloque de control de hilo (TEB), que es una estructura del núcleo de Windows que mantiene información sobre cada uno de los hilos de un proceso. En un próximo artículo se detallará qué información sobre MUI está almacenada en el hilo de control de proceso y de qué forma.

Para consultar el idioma por proceso una aplicación puede llamar a la API GetThreadPreferredUILanguages. Para modificar esa lista, se puede usar la función SetThreadPreferredUILanguages.

Este diagrama muestra una posible configuración de idioma en Windows 7:

En el ejemplo la lista de idiomas por hilo son el español y el inglés, el idioma por proceso es el alemán, se ha instalado el paquete de idiomas catalán, que junto al idioma español forman la lista de idiomas por usuario; la lista de idiomas por sistema es el árabe, apoyado en el inglés para aquellos recursos que no estén traducidos; y por último, el idioma en el que se instaló el sistema operativo es el inglés. La nueva arquitectura MUI de Windows Vista/7 permite este tipo de escenarios con múltiples idiomas.

¿Es mejor instalar una versión en inglés y aplicarle el MUI en español o instalar directamente una versión en español?

En este punto surge esta duda que asalta a no pocas personas que usan Windows. Realmente, la versión en español y en inglés no son más que una versión independiente del idioma a la que se le ha aplicado el correspondiente paquete de idiomas. Por este motivo, no hay diferencias ni de rendimiento, estabilidad, seguridad, etc.

En cuanto a la versión inglesa con el MUI español aplicado, es una versión casi idéntica a la versión en español; la única diferencia es que en este caso tanto el idioma de instalación como la lista de idiomas por sistema se mantienen en inglés, lo único que cambia es el idioma por usuario. Aunque el idioma de sistema se puede cambiar (tal y como se ha explicado anteriormente), no ocurre lo mismo con el idioma de instalación, que aunque tiene poca relevancia sí que condiciona algunos aspectos de la máquina, como puede ser algunas rutas o nombres de usuarios del sistema. En ningún caso hay diferencias de rendimiento, ni de estabilidad, ni de disponibilidad de actualizaciones.

En general mi consejo es el siguiente:

Si el usuario se maneja nativamente en un idioma, se debería instalar la versión en ese idioma en concreto. Instalar la versión en inglés solo va a complicar el aprendizaje del sistema, sin ningún beneficio por parte del usuario.

Si la máquina la usan personas que hablan distintos idiomas y la versión de Windows 7 lo permite, lo ideal es configurar cada cuenta de usuario para que muestre la interfaz en un idioma distinto, instalando antes los correspondientes paquetes de idiomas. Este es el escenario típico de una multinacional.

En próximos artículos veremos qué estructuras tiene el sistema para almacenar toda la información MUI, así como las caches, tanto en modo usuario como en modo núcleo, que sirven para aligerar la carga de recursos en un determinado idioma por parte de una aplicación o del propio sistema operativo. También veremos en qué consiste el cargador de recursos de Windows, que es el componente encargado de proporcionar a una aplicación un recurso en un determinado idioma.

Microsoft acaba de informarme de que he sido galardonado con el premio MVP para este año 2010. Parece que fue ayer cuando recibí la primera nominación, pero este será ya el quinto año que forme parte de este programa. Espero seguir contribuyendo a la riqueza de contenido de las comunidades técnicas en español sobre Windows. También agradezco la fidelidad de los lectores de este blog en particular, pues poco a poco se ha convertido en un sitio en la red con un tráfico considerable.

Aprovecho también para desear un buen año 2010 a todos.

Posted by dmartin | 7 comment(s)
Filed under:

Antes de la primera beta de Windows 7 publiqué un artículo referido a la partición de sistema que se crea durante la instalación de Windows 7, de 200 MB (reducido a 100 MB en la versión final, como ya anticipé en el artículo), con etiqueta "Reservado para el sistema" y sin letra de unidad asignada. Como aún existen muchas cuestiones sobre qué condiciones tiene que cumplir el disco para que se cree automáticamente dicha partición, este artículo intentará detallar aún más este punto. Como ya sabe, el motivo principal por el cual se le invita al usuario a crear una partición de sistema separada de la partición de arranque es para que la utilidad de Windows 7 Bitlocker funcione correctamente y también para facilitar los escenarios en los que hay dos o más sistemas operativos instalados en una misma máquina.

Durante la instalación de Windows 7, se comprueba si existe una unidad de sistema creada con anterioridad (por ejemplo, porque se esté realizando una actualización, una instalación limpia iniciando el programa de instalación desde otro Windows, o bien se hayan creado las particiones con otra utilidad). Si es el caso, se comprueba si esta cumple con el requisito de tener al menos 100 MB de espacio libre. Si fuera además el volumen donde se va a instalar el sistema operativo, este debe tener espacio también para los archivos de instalación del sistema. Si se cumplen estas condiciones, la unidad queda asignada como volumen de sistema, marcada como activa, y el programa de instalación no hace ninguna modificación.

¿Qué ocurre si no hay ningún volumen de sistema en el equipo?

En el caso de que no haya ningún volumen de sistema en el equipo, normalmente porque se está instalando Windows 7 en un disco vacío, el programa de instalación intenta encontrar la mejor unidad de sistema posible. Para ello se siguen estos pasos, que imponen un orden de preferencia:

  1. Se intenta encontrar una región dentro del espacio no asignado del disco donde se va a instalar el sistema operativo, que cumpla con los requisitos de espacio antes mencionados.
  2. Si no se ha encontradado nada, se busca en el espacio no asignado del resto de discos.
  3. Si aún así no se encontrara un candidato a posible unidad de sistema, se examinaría el espacio asignado en todos los discos.

Queda una última restricción: Si el sistema encontrara una región sin asignar que cumpliera con los requisitos de espacio de la unidad de sistema, esta solo es elegida si en el disco hay menos de 3 particiones.

Una vez que el programa de instalación ha encontrado una región que puede contener la unidad de sistema, consulta al usuario si desea crearla (si procede) y, de contestar afirmativamente, la crea y le da formato NTFS.

Preguntas más frecuentes:

Tengo una partición sin letra de 200 MB o de un tamaño superior, no de 100 MB

Es importante comentar que la versión final de Windows 7, de tener que crear una partición de sistema, siempre creará una de 100 MB. Si observa una partición de 200 MB o de otro tamaño superior, sin letra de unidad, probablemente se trate de una partición activa que ya estaba con anterioridad en ese sistema (quizá por la instalación de una versión beta de Windows 7) y que el programa de instalación de Windows 7 ha aprovechado.

¿Se puede evitar la creación de esa partición de sistema?

Es posible, pero yo personalmente no lo recomiendo. Quizá la forma más sencilla sea pulsar Mayúsculas+F10 en la pantalla de creación de particiones del programa de instalación de Windows 7 para abrir una consola de comandos. En dicha consola, teclear estos comandos para crear una partición activa que ocupe la totalidad del disco. Esta partición activa la usará el programa de instalación como partición de sistema:

Diskpart
Select disk 0
Create part prim
Active
Exit

Es probable que al cerrar la consola tenga que pulsar sobre el botón Actualizar para ver el nuevo esquema de particiones recién creado.

Para concluir, este diagrama de flujo resume los pasos que se siguen para determinar si se debe crear una unidad de sistema durante la instalación de Windows 7:

Una de las novedades de Windows 7 con respecto a la seguridad general del sistema es que en este sistema operativo está desactivada la funcionalidad Autorun para dispositivos USB. La funcionalidad Autorun recientemente ha venido siendo usada por los autores de malware para infectar dispositivos USB y a su vez intentar engañar al usuario para que ejecute código malicioso una vez inserte el dispositivo en su máquina. Por este motivo, Microsoft hizo un anuncio durante la beta de Windows 7 diciendo que la funcionalidad Autorun estaría desactivada para dispositivos USB (http://blogs.msdn.com/e7/archive/2009/04/27/improvements-to-autoplay.aspx).

En un foro una persona preguntaba qué implicaciones tendría esto sobre las posibles personalizaciones que se aplican aprovechando la funcionalidad Autorun de los dispositivos ópticos y extraíbles, tales como cambiar el icono de la unidad y cambiar su etiqueta. Aprovechando la respuesta a esta cuestión voy a describir también en qué consisten los mecanismos Autorun y Autoplay en Windows 7.

Autorun y Autoplay son dos conceptos parecidos pero no iguales, que hay que distinguir. En esta página de la documentación de Windows 7 puede ver cuáles son las diferencias entre Autorun y Autoplay: http://windows.microsoft.com/en-us/windows-vista/Whats-the-difference-between-AutoPlay-and-autorun. Cuando el usuario inserta un DVD en la unidad, un dispositivo USB, etc., una de las primeras cosas que hace el sistema es procesar el posible fichero Autorun.inf de la raíz del dispositivo. El fichero Autorun.inf tiene una serie de opciones de configuración que permiten cambiar el icono de la unidad, su etiqueta, el programa que ejecutará automáticamente, etc. Esta lista recoge los posibles parámetros y los cambios que ha habido en Windows 7 con respecto a sistemas anteriores:

  • Open: Programa que se abrirá automáticamente. En Windows 7 esto solo está soportado en unidades ópticas (CD/DVD).

  • ShellExecute: Similar al caso de la opción Open.

  • Icon: Icono asignado a la unidad. Soportado en Windows 7, y sobre cualquier tipo de unidad compatible con Autorun.

  • Action: En Windows 7 solo se tiene en cuenta para unidades ópticas (CD/DVD).

  • Label: Establece una etiqueta al volumen. Soportado en Windows 7, y sobre cualquier tipo de unidad compatible con Autorun.

Así pues, Windows 7 desactiva Autorun para toda unidad que no sea de CD/DVD, excepto si se trata de los inofensivos parámetros Icon y Label.

Para optimizar el rendimiento, conforme el sistema va analizando el fichero Autorun.inf, va almacenando su información en la rama de Registro HKEY_CURRENT_USER\Software\Microsoft\Windows\Curre ntVersion\Explorer\MountPoints2\{CLSID}\_Autorun (donde CLSID identifica a un dispositivo particular). En Windows 7 y en el caso de dispositivos USB, tampoco se almacena esta información en el Registro, excepto si se trata de los parámetros Icon y Label, como ya se ha comentado.

Una vez analizado el fichero Autorun.inf, el sistema establece en el menú contextual de la unidad el verbo (acción) por defecto, que se mostrará al usuario en letra negrita y será lo que ocurra por defecto al hacer doble clic sobre la unidad. Nótese que esto no ocurre en Windows 7 en el caso de unidades extraíbles.

A continuación se comprueba si Autorun está habilitado o no para esa unidad en particular. Para ello se examina en la clave de Registro HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer si existiera alguna de estas directivas establecidas:

  • NoDriveAutorun
  • NoDrives
  • NoDriveTypeAutorun

La primera directiva desactiva Autorun para una unidad en particular; la segunda oculta la unidad en Explorador de Windows, por lo que automáticamente se desactiva la reproducción automática en la misma, y la tercera desactiva Autorun para un tipo particular de dispositivos (ópticos, USB, etc.).

Si al introducir un CD/DVD/USB en su sistema no se muestra un cuadro de reproducción automática, debería examinar en primer lugar estos tres valores de Registro, tanto en la rama HKCU, como en la HKLM. Programas como VMware Workstation aplican alguna de estas directivas para evitar que la reproducción automática interfiera con el sistema que está siendo virtualizado.

Otro de los factores que se comprueban y que influyen en que la reproducción automática esté desactivada es que haya una aplicación DirectX funcionando a pantalla completa (por ejemplo un juego) o un salvapantallas. Asimismo, hay un valor de Registro que desactiva AutoPlay y que es configurable desde la interfaz gráfica, concretamente desde Inicio, Programas predeterminados, Cambiar configuración de reproducción automática, Usar la reproducción automática para todos los medios y dispositivos. Se trata del valor DisableAutoplay de la clave HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers. Este es otro de los valores de Registro que debería consultar si AutoPlay no funcionara correctamente.

A continuación el sistema queda a la espera de que se mantenga pulsada la tecla Shift (Mayúsculas). El significado de esta tecla en versiones anteriores de Windows era el de desactivar la reproducción automática temporalmente. En Windows Vista y Windows 7 esta tecla cambia radicalmente de significado. Sirve para que temporalmente se aplique la configuración por defecto para la reproducción automática, es decir, el usuario verá un cuadro de diálogo con las posibles acciones, incluso si hay alguna aplicación que esté desactivando la reproducción automática (más adelante se explicará cómo puede ocurrir eso).

Si el sistema detecta que la tecla Shift no está pulsada, comprueba si lo que ha ocurrido es que un programa de instalación ha pedido un CD/DVD al usuario y este lo ha introducido. En este tipo de casos conviene no mostrar el cuadro de reproducción automática al usuario. El sistema comprueba esto viendo desde dónde se está ejecutando la aplicación que hay en primer plano. Si es desde el CD/DVD o desde el directorio temporal del usuario, supone que se trata de una instalación en curso y esto automáticamente desactiva la reproducción automática.

Por último, existe la posibilidad de que la aplicación que esté ejecutándose en primer plano haya desactivado la reproducción automática. Esto es útil por ejemplo en el caso de aplicaciones multimedia, de instalación, de grabación de CD, etc. Para conseguir esto la aplicación en cuestión implementa la interfaz IQueryCancelAutoPlay, tal y como se comenta en MSDN, y se añade a la clave de Registro HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers\CancelAutoplay. También puede administrar el mensaje QueryCancelAutoPlay que le envía el sistema a su ventana y decidir si quiere desactivar la reproducción automática o no. A modo de ejemplo práctico, la utilidad de grabación de imágenes ISO de Windows 7 utiliza este método para desactivar la reproducción automática de la unidad seleccionada, temporalmente.

El sistema de recolección de feedback SQM (Service Quality Metrics) de Microsoft recopila información detallada acerca de las causas por las cuales está desactivada la reproducción automática en Windows, etc., con el fin de enviarlas a Microsoft para que se estudie cómo trabajan millones de usuarios en todo el mundo y así poder mejorar el producto. Es importante comentar que la participación en este programa de feedback, que oficialmente recibe el nombre de Windows Customer Experience Improvement Program es completamente voluntaria y se puede activar desde Inicio, escribiendo CEIP en la caja de búsqueda y seleccionando el ítem de Panel de control ofrecido.

En cuanto a AutoPlay, el sistema inspecciona el contenido del medio recién insertado con el fin de presentar al usuario tareas específicas con el tipo de contenido que está tratando. En un primer momento, el sistema analiza el fichero Autorun.inf por si hubiera alguna guía acerca del contenido de ese dispositivo. El fichero Autorun.inf admite una sección como

[Content]

MusicFiles = True

PictureFiles = False

VideoFiles = False

que le diría al sistema que el medio contiene únicamente archivos de música, por lo que se mostrarían tareas orientadas a tratar con música. Es importante resaltar que la sección [Content] es independiente de lo que haya realmente en el medio: Si el fichero Autorun.inf dice que no hay ficheros de vídeo, la reproducción automática no mostrará tareas relacionadas con el tratamiento de vídeos, pese a que los haya en el medio. Otras dos secciones del fichero Autorun.inf que están relacionadas con Autoplay son [ExclusiveContentPaths], que contiene las rutas que debe analizar el sistema para extraer el tipo de contenido que hay en el medio, e [IgnoreContentPaths], que contiene rutas que no serán analizadas, pese a que sean subcarpetas de una ruta establecida en la sección [ExclusiveContentPaths]. Estas últimas secciones son útiles y recomendables para el caso de medios con una cantidad bastante considerable de contenido, pues el sistema se demorará recorriendo directorios que no contienen datos relevantes desde el punto de vista de la multimedia. Puede obtener más información sobre estas secciones del fichero Autorun.inf en el siguiente artículo de MSDN: http://msdn.microsoft.com/en-us/library/cc144200(VS.85).aspx.

Este artículo pretende ser un repaso general de las funcionalidades Autorun/AutoPlay de Windows 7, clarificando las dudas que hay sobre el fichero Autorun.inf en unidades USB en Windows 7, y haciendo hincapié en aquellos aspectos que pueden desactivar la reproducción automática, por si en algún momento tuviera que abordar un sistema con este problema.

En esta cuarta parte del tutorial sobre Windbg, se van a tratar algunos comandos básicos para conocer el estado de la máquina que estamos depurando. El primer aspecto que se va a tratar es el estado del banco de registros.

Estado del banco de registros

Toda computadora dispone de un conjunto compuesto por un cierto número de registros. El número de registros y su tamaño (en número de bits) es algo que depende de la arquitectura de la plataforma. Los registros principalmente sirven para almacenar de manera temporal pequeños valores que se van necesitando durante la ejecución del código máquina, así como valores de retorno de funciones, flags de estado del procesador, etc. Si ha seguido la parte tres del tutorial (http://msmvps.com/blogs/dmartin/archive/2009/08/13/tutorial-sobre-windbg-parte-iii.aspx), en ella se indicaron algunos comandos que sirven para detener el flujo de ejecución de un programa dentro del depurador. Si en ese estado queremos examinar cuál es el contenido de los registros de la máquina, podemos ejecutar el comando r. Este es un ejemplo de la salida del comando r en un sistema operativo de 32 bits que está siendo depurado:

0:000> r
eax=00000000 ebx=00000000 ecx=0012fb0c edx=779664f4 esi=fffffffe edi=00000000
eip=779be60e esp=0012fb28 ebp=0012fb54 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2c:
779be60e cc              int     3

En la salida del comando se muestra el contenido de los registros de la arquitectura IA-32: Eax (registro acumulador), Ebx (registro base), Ecx (registro contador), Esi (registro origen en operaciones con la memoria), Edi (registro destino en operaciones con la memoria), Eip (registro de instrucciones), Esp (registro que contiene el puntero de pila), Ebp (registro con el puntero base de pila), y algunos flags que están activados en el registro de estado del procesador.

Sin embargo, estos no son todos los registros que componen el banco de registros del procesador. Por defecto, Windbg aplica una máscara al banco de registros que sirve para que solamente se muestren los registros de enteros del procesador. El comando rm devuelve cuál es la máscara que está siendo aplicada:

0:000> rm
Register output mask is 9:
       1 - Integer state (32-bit)
       8 - Segment registers

En este ejemplo vemos que se están mostrando los registros de enteros y los registros de segmento del procesador. Si en nuestra depuración necesitáramos echar un vistazo también a los registros de punto flotante, el comando rm ? nos puede ayudar a descubrir qué máscara aplicar:

0:000> rm ?
       1 - Integer state (32-bit) or
       2 - Integer state (64-bit), 64-bit takes precedence
       4 - Floating-point state
       8 - Segment registers
      10 - MMX registers
      20 - Debug registers and, in kernel, CR4
      40 - SSE XMM registers

Como queremos establecer el bit 0 (registros de enteros), el bit 2 (registros de punto flotante) y el bit 3 (registros de segmento), formamos el número binario 1101, que en hexadecimal es el número D. Ejecutamos rm D y a continuación rm para ver la máscara aplicada:

0:000> rm D
0:000> rm
Register output mask is d:
       1 - Integer state (32-bit)
       4 - Floating-point state
       8 - Segment registers

Comprobamos que efectivamente lo hemos hecho bien:

0:000> r
eax=00000000 ebx=00000000 ecx=0012fb0c edx=777e64f4 esi=fffffffe edi=00000000
eip=7783e60e esp=0012fb28 ebp=0012fb54 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
fpcw=027F: rn 53 puozdi  fpsw=0000: top=0 cc=0000 --------  fptw=FFFF
fopcode=0000  fpip=0000:00000000  fpdp=0000:00000000
st0= 0.000000000000000000000e+0000  st1= 0.000000000000000000000e+0000
st2= 0.000000000000000000000e+0000  st3= 0.000000000000000000000e+0000
st4= 0.000000000000000000000e+0000  st5= 0.000000000000000000000e+0000
st6= 0.000000000000000000000e+0000  st7= 0.000000000000000000000e+0000

Es destacable comentar que en Windbg existe el concepto de pseudo-registros. Dependiendo de la arquitectura de la computadora en la que estemos trabajando, los nombres de los registros pueden cambiar, pese a que su semántica sea la misma. Por ejemplo, en la arquitectura x86 el registro de instrucciones es el registro Eip, mientras que en la arquitectura x64 es el registro Rip. Para evitar tener que memorizar este tipo de cosas, podemos hacer uso del pseudo-registro $ip. Aparte de este, dos de los pseudo-registros que más uso son $ra, que sirve para hacer referencia a la dirección de retorno de la función en curso, y $retreg, que hace referencia al registro que almacena el resultado de una función, una vez que esta ha finalizado (en el caso de la arquitectura x86, se trata del registro físico Eax).

Vista del código en ejecución

Otro aspecto muy importante durante una sesión de depuración es tener acceso al código ensamblador que está siendo ejecutado por el procesador. Windbg nos permite desensamblar el código máquina (binario) presente en la memoria del computador para convertirlo al lenguaje ensamblador, mucho más legible.

Para desensamblar las instrucciones de la función en curso, podemos hacer uso del comando uf . (Unassemble function). El punto que hay después de "uf" sirve como referencia a la instrucción presente en el registro de instrucciones, pero en general después de "uf" puede ponerse cualquier otra dirección de memoria.

Si queremos desensamblar instrucciones a partir de la instrucción actual (para ver qué código va a ejecutar el procesador inmediatamente después), podemos hacer uso del comando u . (o u $ip, haciendo uso de los pseudo-registros comentados anteriormente). Por defecto, si no se indica nada, Windbg desensambla 8 instrucciones.

Si en cambio quisiéramos desensamblar 8 instrucciones anteriores a la instrucción actual, el comando a ejecutar sería ub $ip Esto debería ser uno de los primeros pasos que deberíamos dar si nos hemos encontrado con un estado de la máquina incorrecto y queremos saber por qué la máquina ha llegado a tal estado, es decir, qué se ha estado ejecutando antes de que ocurriera el desastre.

Examinar el contenido de la memoria

La memoria de un computador que está ejecutando un programa contiene regiones con diferentes tipos de información. Pueden contener el código del programa, datos, la pila de ejecución, heap, etc.

La extensión de Windbg !address <Dirección> facilita el saber de qué tipo es la región que engloba a una dirección de memoria determinada. Por ejemplo:

0:000> !address $ip
 ProcessParametrs 007117a8 in range 00710000 00715000
 Environment 00710810 in range 00710000 00715000
    777a0000 : 777a1000 - 000d6000
                    Type     01000000 MEM_IMAGE
                    Protect  00000020 PAGE_EXECUTE_READ
                    State    00001000 MEM_COMMIT
                    Usage    RegionUsageImage
                    FullPath ntdll.dll

Aquí se puede ver, entre otras cosas, como la dirección de memoria que se está ejecutando actualmente contiene código ("RegionUsageImage"), lo que es algo completamente normal.

Veamos qué ocurre si ejecutamos ese mismo comando pero haciendo referencia esta vez al puntero de pila:

0:000> !address @esp
 ProcessParametrs 007117a8 in range 00710000 00715000
 Environment 00710810 in range 00710000 00715000
    00030000 : 0012e000 - 00002000
                    Type     00020000 MEM_PRIVATE
                    Protect  00000004 PAGE_READWRITE
                    State    00001000 MEM_COMMIT
                    Usage    RegionUsageStack
                    Pid.Tid  16fc.c4c

Podemos ver que, obviamente, se trata de una región de la pila ("RegionUsageStack").

El comando !address personalmente lo uso cuando me encuentro con una dirección de memoria involucrada en algún problema y quiero saber qué tipo de contenido tiene. Podría ser que fuera una dirección inválida, o bien que el procesador estuviera intentando ejecutar código desde una región de memoria marcada como contenedora de datos, por culpa de algún puntero que apunte a donde no debe o quién sabe si por algún fallo de hardware. Otro uso que le doy a la extensión !address es saber qué tipo de fuga de memoria tiene un proceso. Si nos encontramos con un proceso que consume memoria de manera desmedida, existe la posibilidad de que tenga una fuga de memoria. Como un proceso puede fugar diversos tipos de memoria, una manera de saber qué tipo de memoria está utilizando sin liberar es ejecutar el comando !address sin parámetros para ver un resumen estadístico del consumo de memoria de un proceso.

Para ver lo que contiene una dirección de memoria, Windbg nos proporciona la familia de comandos d*, que tienen la sintaxis

d<Tipo> <Rango_direcciones>

<Tipo> sirve para ayudar al depurador a interpretar el contenido de la memoria situado en el rango <Rango_direcciones>

En la documentación de Windbg está disponible una lista con todos los tipos de comando d* que se pueden usar, según lo que queramos mostrar sean valores ASCII, Unicode, palabras dobles, valores en punto flotante, etc. Si el resultado de un comando d* es una ristra de símbolos "?", esto quiere decir que Windbg ha intentado acceder a una posición inválida de memoria. Esto merecería una investigación más en profundidad usando alguno de los comandos que se han descrito anteriormente.

En el próximo artículo se tratarán en detalle los comandos de Windbg que nos permiten explorar dos estructuras muy importantes en el estado de una máquina que está siendo depurada: El bloque de control de proceso (y de hilo) y la pila de ejecución.

Posted by dmartin | with no comments
Filed under: ,
More Posts « Previous page - Next page »