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.
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.
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:
- 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.
- Si no se ha encontradado nada, se busca en el espacio no asignado del resto de discos.
- 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.
Una práctica que era común en el desarrollo de software de hace unos años consistía en mezclar el código fuente de la aplicación junto con cadenas de texto y otros recursos (iconos, imágenes, etc.). El siguiente diagrama lo explica gráficamente:

Conforme el mercado comenzó a globalizarse fue surgiendo la necesidad de traducir aplicaciones a múltiples idiomas, y por ende este método acabó siendo completamente descartado por los siguientes motivos:
- Para traducir una aplicación primero hay que crear una o más copias de su código fuente, con el consecuente coste añadido que supone el mantenerlas.
- Los traductores, que por lo general no tienen conocimientos de programación, tienen que manipular el código fuente para traducir las cadenas de texto. Esto puede introducir errores en el funcionamiento de la aplicación.
Es en esta época cuando el uso de una versión en inglés (o en el idioma nativo de la empresa que desarrollara ese programa) sí podía ofrecer ciertas ventajas con respecto al resto de idiomas. La posibilidad de introducir errores en el código mientras se traducía un programa no era algo descabellado, todo ello debido a que la separación entre código fuente y cadenas de texto dependientes del idioma era insuficiente (en este caso particular, inexistente).
Las versiones de Windows anteriores a Vista introdujeron una nueva arquitectura de localización de binarios, con el objetivo de separar el código fuente (las instrucciones que acaba ejecutando el computador) de las cadenas de texto (mensajes informativos, errores, iconos, etc.).

Si bien esta arquitectura es válida y sigue siendo usada por muchísimas aplicaciones hoy en día, presenta algunas deficiencias que se magnifican en una empresa del tamaño de Microsoft: Por ejemplo, si se detecta un fallo de seguridad en un binario y se quiere desarrollar una actualización de seguridad al respecto, como el código fuente y las cadenas de texto están en el mismo fichero (pese a estar separados entre sí), sería necesario generar un par de decenas o más de actualizaciones de seguridad, una para cada idioma en el que está disponible Windows. Esto retarda innecesariamente el desarrollo de actualizaciones de seguridad en varios idiomas, pues por lo general los errores de seguridad afectan únicamente al código de la aplicación, no a las cadenas de texto y otros recursos que pudiera contener.
Con Windows Vista se rediseñó en profundidad la arquitectura MUI (Multilingual User Interface) que ya estaba presente en la versión Professional de Windows XP (entre otros) para que las cadenas de texto y el código de las aplicaciones estuviera completamente separado, esto es, en ficheros diferentes.

Esta arquitectura MUI introducida con Windows Vista no solo beneficia a Microsoft y al usuario, que ya puede instalar un paquete de idiomas en una versión de Windows que no esté en inglés, también beneficia a los desarrolladores de aplicaciones, pues por fín disponen de una arquitectura proporcionada por el sistema operativo para manejar recursos en múltiples idiomas, sin ser ya necesario que se construyan una desde cero.
¿Qué ocurre al instalar Windows Vista/7?
En un artículo de mi antiguo blog tengo información que explica resumidamente en qué consisten las fases de la instalación de Windows Vista. Básicamente lo que ocurre es que en primer lugar se instalan los binarios del sistema (independientes del idioma), y seguidamente se instala uno o varios paquetes de idiomas. Como ve, el inglés no recibe ningún tipo de trato preferencial, se le trata como un idioma más. La fase correspondiente a la instalación del paquete de idiomas inicial se realiza durante la fase "Instalando características".
En Windows Vista la herramienta encargada de instalar un paquete de idiomas es la denominada Package Manager (Pkgmgr.exe). En Windows 7, se usa la herramienta Dism (Deployment Image Servicing and Imaging), que integra todas las funcionalidades de Package Manager y de otras herramientas igualmente relacionadas con la administración de imágenes de instalación.
En este primer artículo se ha explicado cómo ha ido evolucionando la localización del software a lo largo del tiempo y se ha aclarado que en Windows Vista y Windows 7 los binarios están completamente separados de las cadenas de texto, con las ventajas que esto conlleva. Esto implica también que Vista/7 sean sistemas idependientes del idioma en el que se utilicen; el inglés es un idioma como otro cualquiera.
En un siguiente artículo se explicará en detalle en qué consiste exactamente un paquete de idiomas y qué es lo que conforma la infraestructura MUI de Windows Vista/7. Se explicará también cómo el sistema obtiene los recursos en el idioma establecido por el usuario. Este aspecto puede ser importante para la gente que le interese saber cómo solucionar problemas con Windows, pues me he encontrado con algún que otro sistema cuyo síntoma es que una determinada aplicación no muestra ningún tipo de interfaz gráfica (es decir, no se abre) y cuya causa es una configuración incorrecta de los recursos MUI de ese sistema.
En un foro que frecuento un usuario tenía el siguiente problema: Al intentar ejecutar como administrador un programa en Windows 7 usando el comando Runas.exe, le aparecía el siguiente mensaje de error:
740: La operación solicitada requiere elevación.
Ciertamente el usuario estaba proporcionando el nombre de usuario y la contraseña de un usuario con privilegios administrativos así que... ¿dónde estaría el problema?
En primer lugar, vamos a analizar con calma lo que quiere decir el mensaje de error. El mensaje de error "La operación solicitada requiere elevación" está recogido en el fichero de cabecera Ntstatus.h del SDK de Windows Vista y posteriores. Concretamente está definido con el nombre de macro ERROR_ELEVATION_REQUIRED.
¿Cuándo se devuelve ese código de error durante el funcionamiento de Windows?
En Windows los procesos se crean usando la API CreateProcess. Uno de los pasos que se siguen antes de crear un proceso en Windows Vista y posteriores es comprobar si el proceso en cuestión necesita elevar sus privilegios o no. A la hora de determinar este aspecto, entran en juego, entre otros, dos parámetros: El nivel de ejecución (runlevel) impuesto por el manifiesto de la propia aplicación, y el token del usuario que está lanzando ese programa. Existen tres posibles niveles de ejecución para una aplicación:
- asInvoker: El nivel de ejecución es el mismo que el del proceso padre.
- highestAvailable: El nivel de ejecución es el de mayores privilegios posibles, considerando el tipo de cuenta desde la cual se ejecuta el proceso.
- requireAdministrator: El nivel de ejecución es administrativo, independientemente de las demás circunstancias.
Esta tabla recoge de forma básica las posibilidades:
| Nivel de ejecución de la aplicación |
Token del usuario |
Requiere elevación o no |
| AsInvoker |
Cualquiera |
No |
| highestAvailable |
Administrador "elevado" |
No |
| highestAvailable |
Administrador "estándar" |
Sí |
| highestAvailable |
Otro caso |
No |
| requireAdministrator |
Administrador "elevado" |
No |
| requireAdministrator |
Otro caso |
Sí |
Por administrador "elevado" me refiero a aquella cuenta con privilegios administrativos pero que, o bien ya ha elevado explícitamente sus privilegios (a través de un cuadro de UAC), o bien no tiene activada la característica Modo de aprobación del administrador (Admin Approval Mode). Esta característica se puede desactivar desde Directiva de grupo, pero yo personalmente lo desaconsejo. Un ejemplo de este tipo de cuentas es la cuenta "Administrador", creada durante la instalación del sistema operativo. Recuerde que el resto de cuentas con privilegios administrativos poseen dos tokens: uno limitado, con el que "actúan" por defecto, y otro "administrativo", que pueden aplicar si el usuario así lo indica a través de un cuadro de UAC.
Una vez que CreateProcess falla (devuelve un valor distinto de 1) y el último error se establece como ERROR_ELEVATION_REQUIRED (columna "Requiere elevación o no" de la tabla anterior), es asunto del proceso padre el tratar convenientemente este error. Si no lo hace, se registrará en Visor de sucesos, apartado dedicado a UAC, un evento informando de que el proceso padre no trató apropiadamente el error ERROR_ELEVATION_REQUIRED.
¿Qué ocurre cuando se lanza una aplicación desde la línea de comandos?
Imaginemos que el usuario intenta ejecutar el desfragmentador de disco de Windows 7 usando para ello una sintaxis de Runas.exe como esta:
runas /u:UsuarioAdministrador dfrgui.exe
Básicamente la línea de comandos detecta que no se trata de un comando interno, sino que se trata del programa Runas.exe, y por tanto se dispone a ejecutarlo usando CreateProcess. Como Runas.exe no es un programa que está marcado para requerir elevación de privilegios, CreateProcess retorna éxito.
Una vez que el planificador del sistema operativo cede el control al proceso Runas.exe recién creado, este se dispone a analizar su línea de comandos. Se encuentra con una petición de ejecutar Dfrgui.exe como si fuera el usuario administrador pasado como parámetro. Sin embargo, Runas.exe es poco más que un "envoltorio" de la API CreateProcessWithLogonW, que a su vez es poco más que un envoltorio de la API CreateProcess, pero pasando otro perfil de usuario distinto como parámetro.
Durante su ejecución, CreateProcess determina que Dfrgui.exe requiere privilegios administrativos (puesto que así se lo indica su manifiesto), y por ello devuelve falso y establace el último error como ERROR_ELEVATION_REQUIRED. Como Runas.exe es una herramienta que no está diseñada para tratar apropiadamente ese error, simplemente lo devuelve por pantalla de la forma "740: La operación solicitada requiere elevación".
Una vez desvelado el misterio, resta por comentar un aspecto que a estas alturas quizá ya se haya planteado:
¿Cómo es posible que ejecutando Dfrgui.exe desde la línea de comandos -sin usar Runas.exe- sí que aparezca un cuadro de UAC?
El secreto está en que la línea de comandos, antes de llamar a CreateProcess, informa al sistema de que va a tratar los posibles ERROR_ELEVATION_REQUIRED que puedan surgir. Esto lo consigue estableciendo unos atributos no documentados a la estructura STARTUPINFOEX, que se pasa como parámetro a la familia de API CreateProcess. Esto hace que no se registre el correspondiente error en el apartado UAC del Visor de sucesos. Seguidamente, la línea de comandos, sabiendo que se trata de un programa que debe elevar sus privilegios, lo intenta ejecutar mediante la API ShellExecuteEx. Esta API sí muestra el correspondiente cuadro de UAC, así que es la vía apropiada para ejecutar una aplicación que requiera privilegios administrativos.
En resumen, me gustaría resaltar estos puntos del tema del artículo:
- En Windows Vista y Windows 7 la única forma de ejecutar algo con privilegios administrativos es mediante un cuadro de UAC. No vale con poner el nombre de usuario y la contraseña de un administrador en la línea de comandos.
- Todo lo que se ejecute mediante la API CreateProcess, o alguna derivada de ella, no hará que aparezca un cuadro de UAC. Un ejemplo de ello es la utilidad Runas.exe.
- Runas.exe, en Windows Vista/7, sirve para ejecutar una aplicación como si fuera otro usuario, pero no sirve para ejecutarla con mayores privilegios.
- Si quiere que se ejecute una aplicación que requiere privilegios administrativos, use la API ShellExecuteEx, o alguna de sus derivadas. Esta API sí permite la aparición de un cuadro de UAC para que el usuario eleve sus privilegios.
Una de las dudas que más surgen entre los usuarios de Restaurar sistema es cada cuánto tiempo se creará un punto de restauración automático. Este artículo pretende dar una respuesta precisa a esta cuestión para así esclarecer aquellos casos en los que el sistema no haya creado un punto de restauración desde hace tiempo.
Windows XP
En Windows XP cada hora una tarea interna del Programador de tareas se encarga de analizar si el sistema está inactivo, es decir, si no está haciendo uso de la CPU ni del subsistema de E/S. Si se diera el caso, se realizan dos posibles comprobaciones para determinar si se debe crear un punto de restauración automático:
- Si han pasado más de 24 horas desde el último punto de restauración, se crea uno automáticamente. Este parámetro (24 horas) es editable desde el Registro del sistema operativo, concretamente en la clave HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurrentVersion\SystemRestore, valor RPGlobalInterval.
- Si la sesión actual de trabajo con el PC está durando más de X horas y el último punto de restauración es más antiguo, se crea un punto de restauración automático. Por defecto, esta configuración no está establecida, pero puede hacerlo desde el Registro en la clave HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRestore, valor RPSessionInterval.
La comprobación de inactividad se realiza por defecto cada hora pero podría variar dependiendo de los valores de ciertas políticas de energía de su equipo. Eche un vistazo a los valores IdleTimeoutDc, IdleTimeoutAc de esta página de MSDN: http://msdn.microsoft.com/en-us/library/aa373239(VS.85).aspx. Aprovechando la inactividad, Restaurar sistema realiza otras tareas, tales como eliminar aquellos puntos de restauración cuyo tiempo de vida ya haya expirado, y de paso comprimir el almacén usando compresión NTFS. Estas tareas se realizan solo si el equipo está conectado a la corriente eléctrica, para evitar que se agote la batería en el caso de portátiles.
Si quiere profundizar en el funcionamiento de la herramienta Restaurar sistema de Windows XP, eche un vistazo a esta serie de artículos de mi antiguo blog:
http://rinconwindows.blogspot.com/2007/02/cmo-funciona-restaurar-sistema-parte-i.html
http://rinconwindows.blogspot.com/2007/03/cmo-funciona-restaurar-sistema-parte-ii.html
Windows Vista/7
En Windows Vista/7 el nuevo Programador de tareas muestra información detallada acerca de la tarea programada que crea un punto de restauración automático. Abra Programador de tareas, apartado \Microsoft\Windows\SystemRestore. La tarea SR tiene como desencadenantes:
- El inicio del sistema.
- Diariamente a las 12 AM.
En esos instantes se ejecutará el comando %windir%\system32\rundll32.exe /d srrstr.dll,ExecuteScheduledSPPCreation.
El modificador /d de Rundll32.exe ya lo traté ligeramente en mi antiguo blog: Se trata de un modificador que le dice a Rundll32.exe "ejecuta este comando y no captures las posibles excepciones que ocurran". La función ExecuteScheduledSPPCreation es la encargada de verificar si el punto de restauración más antiguo tiene más de 12 horas (la mitad que en el caso de XP) y, si así fuese, creará uno nuevo.
Hay que tener en cuenta otras condiciones adicionales que puede observar en la pestaña Condiciones: El sistema debe estar inactivo durante al menos 10 minutos y además, en el caso de portátiles, debe estar conectado a la red eléctrica.
Espero que este artículo haya aclarado sus dudas con respecto a la creación automática de puntos de restauración por parte de Windows. En resumen, si su sistema no genera periodicamente puntos de restauración puede deberse a:
- El servicio Programador de tareas no está iniciado.
- El sistema no está inactivo durante los periodos de tiempo impuestos por Windows, según lo explicado anteriormente.
Quizá ya se haya dado cuenta de que en Windows Vista/Windows 7 algunos módulos del Panel de control que anteriormente estaban implementados en la clásica forma de un fichero .cpl ahora lo están en la forma de un fichero ejecutable (.exe). El motivo de este cambio es que con la introducción de Control de cuentas de usuario (UAC), se da el caso de que algunos de estos módulos requieren privilegios administrativos para ejecutarse. Veámoslo con un ejemplo:
El ejecutable DPIScaling.exe del directorio \Windows\System32 implementa la opción del Panel de control que permite cambiar la escala DPI del sistema. Este módulo requiere privilegios administrativos para ejecutarse, como así indica su fichero de manifiesto. Para verlo prácticamente, descargue Strings desde http://technet.microsoft.com/en-us/sysinternals/bb897439.aspx y abra una ventana de línea de comandos en el directorio donde la ha extraído. Introduzca este comando y pulse INTRO:
strings %SystemRoot%\System32\DPIScaling.exe | findstr /i requireAdministrator
La salida del comando, level="requireAdministrator", nos indica que el ejecutable en cuestión requerirá privilegios administrativos cuando lo invoquemos. Otros posibles valores para el atributo level son:
asInvoker: El ejecutable no requerirá privilegios administrativos.
highestAvailable: El ejecutable se ejecutará con los máximos privilegios que le permita la cuenta de usuario desde la que ha sido invocado.
Nombres canónicos en Windows Vista/Windows 7
Esta reestructuración de buena parte de los elementos del Panel de control trajo consigo una de las novedades que se introdujeron en Windows Vista y que se han mantenido en Windows 7: la posibilidad de abrir elementos del Panel de control usando un nombre canónico. Un nombre canónico es un nombre en inglés, no traducible, que describe de manera cercana al usuario el cometido de ese elemento del Panel de control. Esto evita que el usuario tenga que aprender el nombre de ficheros .cpl, muchas veces crípticos, y además permite separar el nombre del ítem de su implementación, ya sea en un clásico fichero .cpl o, ya sea en un fichero .dll o .exe.
Por ejemplo, para abrir el panel Agregar o quitar programas de Windows Vista/Windows 7, se puede usar esta sintaxis:
%windir%\system32\control.exe /name Microsoft.ProgramsAndFeatures
¿De dónde proviene ese nombre canónico, Microsoft.ProgramsAndFeatures?
Cuando el ejecutable Control.exe recibe el parámetro /name seguido de un nombre canónico, se invoca a la función IOpenControlPanel::Open, la cual en primer lugar busca el elemento correspondiente del Panel de control al que se está haciendo referencia. Cabe destacar que el Panel de control es un directorio virtual (no reside físicamente en el disco, sino que está implementado por el shell), situado en la clave de Registro HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\NameSpace. El valor (Predeterminado) de cada una de las subclaves de esa rama de Registro contiene el nombre con el que se mostrará en Panel de control (no el nombre canónico). Para encontrar la implementación de, digamos, HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\NameSpace\{0DF44EAA-FF21-4412-828E-260A8728E7F1} (ítem de las propiedades de la barra de tareas y menú Inicio), se accede a la clave de registro HKEY_CLASSES_ROOT\CLSID\{0DF44EAA-FF21-4412-828E-260A8728E7F1}, en la cual existe un valor de registro de nombre System.ApplicationName y cuyo contenido es el nombre canónico: Microsoft.TaskbarAndStartMenu. Así pues, para abrir las propiedades de la barra de tareas y del menú Inicio ya sabemos que bastaría con ejecutar lo siguiente:
%windir%\system32\control.exe /name Microsoft.TaskbarAndStartMenu
Para ver qué es lo que realmente se ejecuta, eche un vistazo a la clave HKEY_CLASSES_ROOT\CLSID\{0DF44EAA-FF21-4412-828E-260A8728E7F1}\Shell\Open\Command.
Cada ítem del Panel de control puede implementar varias páginas
Podemos entender las páginas como subsecciones específicas del ítem del Panel de control. Para indicar una, debe usarse la sintaxis
%windir%\system32\control.exe /name Nombre_canónico /page Página
Veámoslo con un ejemplo:
Con los conocimientos que hemos adquirido, nos resulta sencillo determinar que el ítem Personalizar del Panel de control está implementado en la DLL Themecpl.dll. Es en esta DLL donde encontraremos información acerca de las posibles páginas de este ítem, en la forma, como no, de fichero XML.
Esta vez usaremos la aplicación gráfica Resource Hacker, que puede descargar gratuitamente desde http://www.angusj.com/resourcehacker/. Al abrir el fichero Themecpl.dll en esta aplicación, nos encontramos con dos ficheros XML adicionales al típico fichero de manifiesto (.manifest) que habíamos visto hasta ahora.

Este primer fichero XML especifica una serie de tareas que puede realizar el elemento del Panel de control "Personalizar". Estas tareas (cambiar los colores, el fondo de pantalla, etc.) se muestran como enlaces de texto justo debajo del elemento del Panel de control (suponiendo que esté configurado en la vista por categorías). Y lo que es más importante, estas tareas son indizables por el sistema de búsqueda de Windows Vista. Puede obtener más información en este artículo de MSDN: http://msdn.microsoft.com/en-us/library/bb776840(VS.85).aspx.

Esta segunda imagen hace referencia al segundo fichero XML, que es el que contiene la información acerca de cada una de las páginas que implementa este ítem del Panel de control. Entre las etiquetas <pagedefinition></pagedefinition> nos encontramos con una etiqueta <properties>, que hace referencia a cada una de las páginas. El atributo canonicalName nos ofrece su nombre canónico.
Como vemos, el ítem "Personalizar" del Panel de control admite como sintaxis:
%windir%\system32\control.exe /name Microsoft.Personalization /page pageColorization (para cambiar la configuración de color)
%windir%\system32\control.exe /name Microsoft.Personalization /page pageWallpaper (para cambiar el fondo de escritorio)
Ejercicio
Ahora que ya sabe cómo escudriñar en los ítems del Panel de control con el fin de construir accesos directos lo más directos posibles (valga la redundancia), le propongo como ejercicio que en un sistema Windows 7 averigüe la sintaxis para un acceso directo al Monitor de confiabilidad, que como sabe en Windows 7 está algo escondido dentro del Centro de actividades (Action Center).
Si se rinde, puede ver la solución seleccionando texto a partir de aquí: control.exe /name Microsoft.ActionCenter /page pageReliabilityView
A mucha gente le gusta personalizar su sistema de escritorio al máximo posible. Por ello, Microsoft acostumbra a incorporar en sus sistemas operativos bastantes menús y cuadros de diálogo capaces de personalizar muchos de los detalles de funcionamiento de Windows. Sin embargo, hay ciertos detalles que no son modificables desde la interfaz gráfica, solamente desde el Registro; siempre siguiendo los pasos de algún artículo de la documentación oficial de Microsoft (KB, MSDN LIbrary, Technet Library, etc.). También hay detalles que no están documentados pero que pueden "descubrirse" utilizando herramientas de monitoreo del Registro, como Process Monitor, tal y como se explica en este artículo.
En el caso que nos ocupa, el usuario quería modificar el tiempo de aparición de la vista en miniatura de una aplicación en la barra de tareas de Windows Vista. En Windows Vista, la funcionalidad Windows Aero permite ver, a golpe de ratón, el contenido de todas y cada una de las ventanas minimizadas en la barra de tareas. El usuario intentaba buscar una forma de acortar ese tiempo de aparición de la vista en miniatura, pues le parecía excesivo. En Internet la alternativa que es más popular es la de modificar el valor de Registro MouseHoverTime de la clave de Registro HKEY_CURRENT_USER\Control Panel\Mouse. Sin embargo, este valor influye en el tiempo que tarda en reconocerse un posicionamiento del cursor del ratón, en cualquier parte de la interfaz gráfica de Windows. Era necesario buscar algún valor de Registro más específico, y para ello iba a recurrir a Process Monitor.
Antes de nada hay que comentar que no tenía la garantía de que existiera un valor de Registro que controlara ese aspecto tan específico de la interfaz gráfica de Windows. De existir, suelen ser parámetros que solo se tienen en cuenta en las versiones de depuración (checked) del sistema operativo. De todas formas, abrí Process Monitor y establecí un filtro de aquellos eventos de Registro que contuvieran en su ruta la palabra "Thumbnail". Inicié Explorer.exe y rápidamente me encontré con tres eventos bastante interesantes:

El primer evento indica el momento en que Explorer.exe examina una directiva, TaskbarNoThumbnail, configurable desde Directiva de grupo, encargada de desactivar las vistas en miniatura de la barra de tareas. La lectura de este valor me hizo pensar que los dos valores siguientes podrían estar relacionados con lo que buscaba.
Esos dos eventos siguientes hacen referencia a una búsqueda de cierta rama en el Registro (ExplorerThumbnails), tanto en la rama HKEY_CURRENT_USER como en la rama HKEY_LOCAL_MACHINE. El primer evento hace referencia al SID de mi usuario dentro de la rama HKEY_USERS (HKU) simplemente porque ejecuté Process Monitor desde una cuenta limitada, proporcionando obviamente el nombre de usuario y contraseña del administrador.
¿Qué sería esa rama ExplorerThumbnails? La verdad es que no encontré nada documentado en Internet, pero su nombre era lo suficientemente atractivo como para seguir indagando. Una de las cosas que suelo hacer en casos como este es crear la clave que busca en este caso Explorer.exe y ver qué valores o subclaves de Registro busca a continuación. Eso hice: Abrí Editor del Registro y creé la clave de Registro ExplorerThumbnails. Volví a capturar una traza con Process Monitor y el resultado ofreció otros tres valores tan interesantes como desconocidos:

Los valores InitialThumbnail, InitialTooltip y AutoPopTooltip me hacían pensar que efectivamente estaban relacionados con lo que realmente buscaba: Modificar el tiempo de aparición de la vista en miniatura. En este caso podría haber experimentado introduciendo algunos valores aleatorios para esos valores de Registro y observar los resultados, aunque en este caso recurrí a una lectura del código fuente de Explorer.
Al parecer, el valor InitialThumbnail tiene que ver con el tiempo en milisegundos que tarda en aparecer la vista en miniatura desde que se sitúa el cursor del ratón en la aplicación minimizada en la barra de tareas; InitialTooltip influye en el tiempo de aparición del texto emergente que siempre aparece encima de la vista en miniatura, un tiempo después. Por último, AutoPopTooltip influye en el tiempo que tarda en desaparecer el texto emergente. Por defecto, si no se encuentran esos valores en el Registro, el sistema supone, respectivamente, 500, 1000 y 5000 milisegundos.
Para concluir, codifiqué una aplicación gráfica que facilitara la modificación de estos valores en el Registro: http://winvista.mvps.org/Ficheros/TweakThumbnails.zip
Ya conoce otro posible uso de Process Monitor: Intentar descubrir valores de Registro (o ficheros) no documentados pero que pueden permitirnos configurar aspectos más o menos interesantes del sistema operativo.
Nota: Como indico en el margen izquierdo de este blog, toda la información que no está documentada por Microsoft es muy susceptible de cambiar e incluso de desaparecer en versiones posteriores de Windows. Este es el caso particular de esta rama del Registro, pues no es tenida en cuenta en Windows 7. Adicionalmente, deberá tomar las medidas oportunas si aplica este tip en un entorno de producción, pues de seguro se trata de un parámetro que no está tan probado como el resto de personalizaciones conocidas en el sistema operativo.
En el anterior artículo vimos cómo abrir nuestra aplicación en modo usuario dentro de Windbg y comprendimos mejor qué es lo que ocurre cuando este se hace cargo de nuestra aplicación. Ahora tenemos a nuestra disposición una ventana con salida de texto y una caja de entrada de comandos pero, ¿qué podemos hacer?
Es importante saber que podemos manejar la ventana de Windbg e introducir comandos en su caja de texto porque nuestra aplicación está detenida debido a la excepción STATUS_BREAKPOINT que se recibe por defecto nada más abrir la aplicación en Windbg. Así pues, lo primero que buscamos es una forma de permitir que nuestra aplicación continúe con su ejecución. El comando g (o presionar F5) consigue esto mismo. Este comando hace que la aplicación siga ejecutándose hasta que se encuentre con alguna condición de parada (posteriormente aprenderemos a configurar esto), o bien ocurra algún tipo de excepción (por ejemplo, la aplicación quiere acceder a una posición de memoria incorrecta).
El comando g admite alguna que otra variante. Si, por ejemplo, queremos que nuestra aplicación siga ejecutándose hasta que se alcance una determinada posición de memoria, podemos usar la sintaxis g <Dirección>. Por otra parte, si solo nos interesa que continúe la ejecución hasta que finalice la función en curso, podemos usar el comando gu.
¿Cómo detener la ejecución de la aplicación en los momentos que nos interese?
Uno de los aspectos más importantes en la depuración de aplicaciones es la creación de breakpoints. Windbg nos proporciona los medios necesarios para crear todo tipo de breakpoints, desde los más sencillos hasta los más imaginativos. Saber qué tipo de breakpoint se debe usar en cada caso nos permitirá ahorrar horas de trabajo infructuoso.
Establecer breakpoints en código
El primer tipo de breakpoints que voy a tratar son los clásicos breakpoints en código. Como su nombre indica, son breakpoints que se alcanzan en una determinada dirección de código (típicamente el inicio de una función, pero podría ser cualquier otra cosa). El comando de Windbg para crear este tipo de breakpoints es bp. Este comando recibe como parámetro la dirección en la que queremos detener la ejecución del programa y, opcionalmente, algunas restricciones y comandos que se ejecuten automáticamente cuando se llegue al breakpoint. El abanico de restricciones que se pueden establecer conforma un amplio tipo de breakpoints que se conocen como breakpoints condicionales, que se tratarán más adelante en este artículo. Por ejemplo, si introducimos el comando bp MiAplicacion!MiFuncion "kb" y pulsamos INTRO, lo que va a ocurrir es que cuando reanudemos la ejecución de nuestra aplicación (con el comando g, como ya sabe) y se llegue a la función cuyo símbolo es MiAplicacion!MiFuncion, el depurador informará sobre esto y automáticamente ejecutará el comando kb, que como verá posteriormente, sirve para ver el estado de una estructura de datos muy importante para un proceso/hilo, la pila de ejecución.
Una cosa que quizá se pregunte es, ¿cómo averiguar qué símbolo de función me interesa? Una opción de fuerza bruta consiste en mostrar en pantalla todos los símbolos que cumplan con un determinado patrón y buscar aquella función que puede interesarnos. El comando x consigue esto mismo. Por ejemplo, si quisiera mostrar los símbolos de MiAplicacion que contuvieran la palabra "Window", podríamos usar la sintaxis x MiAplicacion!*Window*. Al pulsar INTRO, WIndbg buscará entre los símbolos disponibles aquellos que coincidan con el patrón establecido y los mostrará en pantalla junto con sus correspondientes direcciones. Si bien esta aproximación de fuerza bruta es útil en algunos casos, lo más probable es que el símbolo en el que quiera detener la ejecución del programa lo obtenga de los resultados que le proporcione Windbg al ejecutar otros comandos.
Por supuesto, también podemos crear múltiples breakpoints sin necesidad de tener que establecerlos uno a uno. Supongamos que nuestra aplicación tiene algún problema a la hora de escribir ciertos archivos en el disco. Podríamos suponer que los símbolos que más nos interesa son los de aquellas funciones que contengan la palabra "Write". Para agregar breakpoints para todos y cada uno de los símbolos que cumplan con este patrón, podemos usar el comando bm, de la siguiente manera: bm MiAplicacion!*Write*
Si la aplicación que se está depurando tiene un cierto grado de complejidad, es bastante probable que haga uso de librerías dinámicas (DLL) cuya carga no se conoce de antemano y se produce en tiempo de ejecución. Por este motivo, si necesitara parar la ejecución en alguna función dentro de esas librerías dinámicas no le sería posible, pues Windbg no conoce la dirección de la función donde debe detenerse. A fin de cuentas, Windbg solo entiende de direcciones de memoria. Para dar solución a este problema, existe el comando bu. Por ejemplo, si nuestra aplicación hiciera uso de una DLL para calcular los primeros dígitos decimales del número pi, podemos detener la ejecución en dicha función ejecutando el comando bu MiDLL!CalcularPI. Una vez introducido el comando lo que ocurre es que Windbg sabe que justo en el momento en que el módulo correspondiente a esa DLL (MiDLL) se cargue en memoria (eche un vistazo al artículo anterior para obtener más información sobre la carga de módulos), debe crear el correspondiente breakpoint, ahora que sabe cuál es su dirección de memoria.
Establecer breakpoints por acceso a un dato
En muchos casos vamos a necesitar parar la ejecución de nuestro programa no cuando se llegue a una porción de código, sino cuando se acceda a un dato. El escenario típico de esto es una aplicación que en apariencia sufre un bug del tipo buffer overrun. Básicamente este tipo de problemas implica que se sobreescriban posiciones de memoria contiguas a las de una porción de datos del programa, por ejemplo un vector. En esta situación, quizá necesitemos indagar sobre todos y cada uno de los accesos que se produzcan hacia este vector. Podemos lograr esto ejecutando el comando ba w4 miVector, suponiendo que el símbolo miVector sea el correspondiente al vector que queremos examinar. Por supuesto, podemos sustituir el símbolo por una dirección de memoria. ¿Qué significa el w4 que aparece como primer parámetro del comando ba? "W" indica que estamos buscando accesos de tipo escritura. Otras posibilidades son "E" (ejecución) y "R" (lectura). El "4" indica el número de bytes que queremos monitorizar. En las arquitecturas de 32 bits este valor puede ser 1, 2 ó 4. En las de 64 bits existe la posibilidad de establecer también 8 bytes como tamaño.
Como habrá podido observar, la creación de breakpoints es un aspecto complejo de Windbg. La capacidad más interesante a mi juicio es la posibilidad de crear breakpoints condicionales. Como vimos, para crear un breakpoint se usa el comando bp. Uno de los parámetros de este comando va entrecomillado y representa una condición adicional a la condición estándar (la llegada a la correspondiente función). Incluso se puede omitir la función y dejar solamente la condición. Supongamos que nuestro programa tiene una variable Contador que va incrementándose cada vez que se itera en un bucle, por ejemplo. Quizá estemos interesados en parar la ejecución de nuestra aplicación cuando la variable Contador adquiera el valor 10, que sabemos que es el valor de finalización del bucle. Para ello podríamos usar esta sintaxis:
bp ".if (poi(Contador)==10) {.echo Fin de cuenta }"
Este comando establece un breakpoint (bp) cuya condición (.if) es que la variable Contador sea igual al número 10. En tal caso, sacamos por pantalla (.echo) la cadena "Fin de cuenta". El comando poi se usa porque de no hacerlo, la variable Contador sería interpretada como una dirección de memoria, y esto no es lo que queremos. Como queremos tener acceso al contenido de esa dirección de memoria, los programadores de C que estén leyendo esto contestarán rápidamente que necesitamos desreferenciar ese acceso. En C esto se hace con el operador * y en Windbg con poi.
Cómo mostrar un listado de los breakpoints que hemos añadido
Una vez que hayamos establecido los breakpoints que necesitemos, es posible que queramos ver un listado de los mismos. Puede usar para ello el comando bl o bien usar la interfaz gráfica de Windbg: Si pulsa F9, se abrirá el cuadro de diálogo Breakpoints, desde el que podrá ver un listado de los breakpoints asociados a la sesión de depuración actual y crear de manera más o menos intuitiva otros nuevos. Mi consejo es usar siempre que sea posible la propia consola de comandos de Windbg, pues suele ofrecer más flexibilidad que la interfaz gráfica, pero comento esta posibilidad por si alguien se siente más cómodo/a usando cuadros de diálogo.
En este artículo hemos aprendido a crear breakpoints básicos y sencillos y otros no tan sencillos. Hemos visto también que la potencia de los breakpoints reside en los breakpoints condicionales, pues el único límite prácticamente es el de nuestra imaginación. La documentación de Windbg (F1) ofrece información más detallada sobre cada uno de los comandos que he tratado aquí, pero espero esto que sirva como punto de partida para sacarle el mayor provecho posible a esta funcionalidad que nos proporciona el sistema operativo en conjunción con Windbg. En los próximos artículos veremos comandos que nos permiten examinar el estado de la máquina. Para comprender mejor la salida de estos comandos, se explicarán también algunos conceptos importantes de la estructura de un computador y del sistema operativo, como son el repertorio de registros, la pila de ejecución o el bloque de control de un proceso/hilo.
Hace unos días en un grupo de noticias que frecuento un usuario que estaba utilizando este script del MVP Enrique Cortés se preguntaba por qué en el fichero de resultados las horas de cada punto de restauración no coincidían con las mostradas en el calendario de Restaurar sistema.
Esto se debe a que en la información que se guarda en el almacén de puntos de restauración (y que es accedida por WMI en el script) las fechas y horas tienen como huso horario +000 (GMT). Así pues, modifiqué el script para que las fechas se conviertan a la zona horaria del sistema en cuestión y aproveché para mostrarlas en un formato más legible. En principio el script es compatible con cualquier versión a partir de XP, pero en Vista y 7 deberá ejecutarlo con privilegios administrativos.
Puede descargar el script modificado desde esta página.
¡Que lo disfuten!
A principios de este mes Technet ha publicado una nueva utilidad que no debería faltar en la «caja de herramientas» de toda persona que se enfrente a un problema con Windows. ProcDump es una herramienta que se adhiere a un proceso de la máquina y genera un volcado de memoria en el momento que se cumplan ciertas condiciones, como por ejemplo un alto consumo de CPU, una ventana que no responde, una excepción no manejada, etc. En este sentido se trata de una herramienta similar al script ADPlus.vbs, aunque considero que ProcDump resulta más intuitiva y algo más sencilla de utilizar.
Puede descargar la versión 1.0 de ProcDump en http://technet.microsoft.com/en-us/sysinternals/dd996900.aspx
En algún artículo posterior espero poder mostrar el uso de esta versátil herramienta para resolver un problema real.
Como quizá sepa, el comando Runas.exe de Windows XP y Windows Server 2003 sirve para ejecutar procesos en el contexto de otra cuenta de usuario. Los usuarios domésticos normalmente lo usan para ejecutar un proceso como administrador desde una cuenta limitada. Echando un vistazo al listado de parámetros de Runas.exe nos encontramos con uno que suele llamar la atención de bastante gente. Sirve para almacenar temporalmente en el administrador de credenciales (Credential Manager) el usuario y contraseña que va a ejecutar el programa. El atractivo de este parámetro es que no tendremos que introducir el nombre de usuario y contraseña para ese programa durante la sesión en curso. Sin embargo, no hay unanimidad con respecto al nombre del parámetro (incluso la propia documentación del sistema operativo creo que presenta alguna inconsistencia al respecto): Unos lo llaman /savecred, otros /savedcred, otros /savedcreds... Incluso en algunos sitios se indica que tienen semántica diferente.
Nada más lejos de la realidad. Runas.exe solo entiende el parámetro /sa (que contiene el mínimo número de letras que diferencian /savecred de los parámetros /smartcard y /showtrustlevels); lo que venga después le es indiferente. Del mismo modo, en cuanto se encuentra con /p supone el parámetro /profile; si se encuentra con /e supone /env, y así sucesivamente.
Nota: Por limitaciones del administrador de credenciales de XP Home Edition, el parámetro /savecred no es tenido en cuenta en esta versión de Windows. Este artículo no es aplicable tampoco a Windows Vista, pues el comando Runas.exe en Windows Vista es bastante diferente del de XP y será tema de un próximo artículo.
Desde que salió a la luz Windows Vista, y ahora con las versiones preliminares de Windows 7, me he dado cuenta de que el número de problemas cuya solución implica el registro de una DLL (mediante el comando regsvr32 nombreDLL) ha descendido notablemente en estos dos últimos sistemas operativos. Una de las causas de esto, para mí, es la inclusión de Windows Resource Protection (WRP), mecanismo que garantiza la integridad de los componentes vitales del sistema operativo y que supone una tremenda mejora con respecto a Windows File Protection (WFP), sistema de protección de archivos de sistema presente en Windows 2000 y XP.
Windows File Protection (WFP)
Windows 2000 y XP incorporaron una característica denominada WFP (Windows File Protection), encargada de proteger los archivos más importantes del sistema operativo para evitar que sean modificados o eliminados.
Su funcionamiento se basa en uno o varios hilos de tipo centinela residentes en el proceso Winlogon e implementados en la DLL Sfc_os.dll. Es decir, estos hilos están al tanto de cualquier tipo de modificación que se realice sobre directorios del sistema (típicamente \System32 y \System32\drivers). Si hubiera cambiado alguna DLL de estos directorios, se registra dicho suceso en una cola destinada a tal efecto. En ese momento se señaliza un evento que despierta a otro hilo encargado de realizar la verificación del correspondiente archivo y su recuperación desde la cache (carpeta oculta \WINDOWS\System32\dllcache). Si no estuviera en cache, se mostrará una interfaz al usuario informándole de tal situación e invitándole a introducir el CD de Windows 2000/XP para intentar recuperar la versión original del archivo.
Windows Resource Protection (WRP)
La llegada de Windows Vista supuso que la estructura interna del sistema operativo cambiara radicalmente. Ahora el sistema operativo está formado por componentes, claves de Registro, manifiestos XML y ficheros binarios, entre otras cosas, por lo que la aproximación empleada en versiones anteriores de Windows ya no podía seguir siendo válida. Este aspecto puede ser interpretado como una ventaja, pues si se desarrolla un sistema de protección para cada uno de los componentes del sistema operativo, ya no solo estaremos protegiendo ejecutables y DLL, como en Windows 2000/XP, sino que estaremos protegiendo también claves de Registro y otro tipo de recursos que son igualmente vitales para el correcto funcionamiento del equipo. Este sistema de protección recibió el nombre de Windows Resource Protection (WRP).
Cada uno de los componentes que conforman el sistema operativo Windows Vista/Windows 7 contiene un fichero denominado manifiesto. Un manifiesto es un fichero de tipo XML que contiene información específica sobre el componente, es decir, archivos que lo componen, archivos de los que depende, claves de Registro, privilegios con los que se ejecutará por defecto, idioma, etc. Uno de estos posibles parámetros (etiquetas XML) es la protección del recurso en cuestión, etiqueta <systemProtection></systemProtection>. Existen distintos valores posibles para el parámetro behavior (comportamiento) de esa etiqueta:
- readOnlyIgnoreWrites: El recurso solo puede ser modificado por el sistema operativo, durante una instalación (servicio TrustedInstaller). Cualquier intento de escritura por parte de una aplicación será descartado; es decir, se le informará de que la escritura se realizó con éxito pero el fichero no se verá modificado.
- readOnlyFailWrites: El recurso solo puede ser modificado por el sistema operativo, durante una instalación (servicio TrustedInstaller). Cualquier intento de escritura por parte de una aplicación tendrá como consecuencia que reciba un error.
- OSOnlyIgnoreWrites: Similar a readOnlyIgnoreWrites, pero las modificaciones las puede hacer cualquier componente del sistema operativo.
- OSOnlyFailWrites: Similar a readOnlyFailWrites, pero las modificaciones las puede hacer cualquier componente del sistema operativo.
- applicationVirtualized: Cualquier cambio que se haga sobre el recurso supondrá que el sistema operativo cree una copia privada a la aplicación que lo ha modificado. El recurso global no se ve modificado.
- userVirtualized: Similar a applicationVirtualized pero la copia privada es por usuario, no por aplicación.
En el mismo fichero de manifiesto se indica también qué descriptor de seguridad usar para dicho componente. Por ejemplo, la carpeta Winsxs de Windows Vista tiene este descriptor de seguridad:
O:S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464
G:S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464
D:PAI
- (A;OICI;FA;;;S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464)
- (A;OICI;0x1200a9;;;BA)
- (A;OICI;0x1200a9;;;SY)
- (A;OICI;0x1200a9;;;BU)"
Donde S-1-5-80-956008885-3418522649-1831038044-1853292631-2271478464 es el SID de TrustedInstaller, un servicio encargado de instalar actualizaciones y componentes en Windows Vista y Windows 7.
Vamos a explicar un poco el descriptor de seguridad: Las dos primeras líneas indican que el propietario (O, de owner) como el grupo (G, de group) es TrustedInstaller. La línea D:PAI quiere decir que el DACL es protegido (es decir, que no hereda listas de control de acceso o ACL) y además se hereda automáticamente. A continuación se indica que TrustedInstaller tiene acceso total al recurso (FA, de full access); el grupo de administradores, sistema y usuario (BA, SY y BU, respectivamente) tienen acceso genérico de lectura/escritura. Así pues, ni siquiera un administrador podrá modificar el contenido del directorio Winsxs. Tan solo TrustedInstaller, con motivo de la instalación/desinstalación de actualizaciones, Service Packs o componentes opcionales de Windows podrá modificar ese directorio.
Si quiere saber más sobre ACL y DACL le recomiendo el libro Windows Internals, escrito por Mark Russinovich y David Solomon, ya sea en su cuarta o su quinta edición.
Veámoslo con un ejemplo
Abriendo el fichero de manifiesto del componente Bloc de notas de Windows Vista podemos observar entre otras cosas lo siguiente:
<dependentAssembly>
<assemblyIdentity name="Microsoft-Windows-Kernel32" version="6.0.6001.18000" processorArchitecture="x86" language="neutral" buildType="release" publicKeyToken="31bf3856ad364e35" versionScope="nonSxS" />
</dependentAssembly>
Aquí se hace referencia a que Bloc de notas depende del componente Microsoft-Windows-Kernel32 (que contiene entre otras cosas la DLL Kernel32.dll) para funcionar correctamente.
<systemProtection xmlns="urn:schemas-microsoft-com:asm.v3" behavior="readOnlyFailWrites" perUserVirtualization="Disabled" />
Aquí se hace referencia a que cualquier intento de escritura sobre el componente Bloc de notas dará como resultado un error y no se llevará a cabo la modificación. La virtualización está desactivada, por tratarse de un componente de Windows.
<shortCut arguments="" destinationPath="$(runtime.documentsSettings)\Default\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Accessories" destinationName="Notepad.lnk" targetPath="$(runtime.system32)\notepad.exe" iconPath="$(runtime.system32)\notepad.exe,0" windowStyle="normal" workingDirectory="%HOMEDRIVE%%HOMEPATH%" description="@%SystemRoot%\system32\Shell32.dll,-22563" displayResource="$(runtime.system32)\shell32.dll,22051" />
Aquí se hace referencia a la configuración del acceso directo al bloc de notas que hay en el menú Inicio.
<registryKey keyName="HKEY_CLASSES_ROOT\Applications\notepad.exe\shell\open\command" owner="false">
<registryValue name="" valueType="REG_EXPAND_SZ" value="%SystemRoot%\system32\NOTEPAD.EXE %1" operationHint="replace" owner="true" />
Aquí se hace referencia a una de las claves de Registro gobernadas por Bloc de notas, la correspondiente a las asociaciones de ficheros.
Como puede observar, la integridad del sistema operativo fue uno de los objetivos principales para Microsoft mientras diseñaba Windows Vista. La protección de todos y cada uno de los recursos vitales del sistema operativo mediante Windows Resource Protection (WRP) hacen que Windows Vista y Windows 7 sean sistemas mucho más estables y robustos que sus predecesores.
Si se hiciera un listado con las consultas más frecuentes en los foros de Windows, seguro que esta ocuparía una posición bastante destacada: ¿Por qué no puedo cambiar el atributo de solo lectura a una carpeta de mi sistema?
Pese a que Microsoft dispone de un artículo al respecto (KB326549), considero que mucha gente aún tiene dudas sobre este tema y por eso me he decidido a escribir este artículo.
Si un usuario hace clic con el botón derecho sobre una carpeta de su sistema y selecciona Propiedades, le aparecerá un cuadro de diálogo similar al siguiente (en un sistema XP):

Como puede observar en la imagen, la casilla Sólo lectura tiene un aspecto particular: No está marcada, pues no aparece la típica marca de verificación en el cuadrado blanco, ni tampoco está desmarcada, pues el color del cuadrado no es blanco sino verdoso. ¿Qué significa esto? Esa casilla es una casilla de tipo triestado; es decir, hay tres posibles estados para esa casilla: Marcada, desmarcada e indeterminada, que es el caso que nos ocupa. Si hace clic varias veces sobre la casilla Sólo lectura podrá ver que va cambiando el estado de la misma. Sin embargo, pese a dejar la casilla en estado marcado y pulsar Aceptar, al volver a abrir las propiedades de la carpeta la casilla vuelve al estado indeterminado.
¿Cuál es la causa de esto?
La causa de este comportamiento es que el atributo de sólo lectura no se puede cambiar, para carpetas, desde la interfaz de Windows. Microsoft tomó esta decisión porque el atributo de sólo lectura aplicado a carpetas tiene una semántica que nada tiene que ver con la del atributo de sólo lectura aplicado a ficheros. El atributo de sólo lectura aplicado a carpetas únicamente quiere decir que la carpeta es una carpeta personalizada (con un icono distintivo, con un fondo, etc.).
Debe quedar claro que el atributo de sólo lectura aplicado a una carpeta no quiere decir que la carpeta no se pueda eliminar o cosas por el estilo.
¿Para qué está la casilla Sólo lectura en las propiedades de una carpeta?
Está presente porque puede aplicarse a los ficheros que contenga esa carpeta. Si desmarca la casilla Sólo lectura en las propiedades de una carpeta y pulsa Aceptar, lo que ocurre es que se quita el atributo de sólo lectura a todos los ficheros que contenga esa carpeta, si es que contiene alguno. De igual forma, si establece el estado de la casilla como marcado (con una marca de verificación en el cuadrado blanco) y pulsa Aceptar, todos los ficheros de esa carpeta pasarán a tomar el atributo de sólo lectura.
Entonces, ¿cómo cambiar el atributo de sólo lectura a una carpeta?
Como ha podido ver, Explorador de Windows no permite que el usuario cambie el atributo de sólo lectura a una carpeta. Esto se debe a que Microsoft no quiere que los usuarios "jueguen" con este atributo, lo que podría suponer que se perdieran las personalizaciones de algunas carpetas del equipo, incluidas algunas carpetas de sistema importantes para Windows. Así pues, si un usuario quiere "jugar" con el atributo de sólo lectura aplicado a una carpeta, debe hacerlo desde la línea de comandos usando el comando Attrib.exe de un modo similar al siguiente:
attrib +r <Ruta_carpeta>
Esto aplicaría el atributo de sólo lectura a la carpeta indicada por <Ruta_carpeta>
Similarmente, el comando
attrib -r <Ruta_carpeta>
desactivaría este atributo.
Espero que este artículo sirva para aclarar de manera definitiva en qué consiste exactamente el atributo de sólo lectura cuando se aplica a una carpeta, por qué Explorador de Windows siempre muestra la casilla correspondiente como indeterminada, y qué ocurre cuando el usuario deja esa casilla en estado marcado o en estado desmarcado y pulsa sobre Aceptar.
En la primera parte de esta serie de artículos aprendió a instalar Windbg y a configurar un aspecto básico, los símbolos de depuración. En este artículo veremos cómo configurar otros aspectos menores de Windbg, pero que le pueden resultar necesarios, y depuraremos la primera aplicación en modo usuario.
Configurar la ruta de código fuente
Si está depurando una aplicación que no haya desarrollado, es probable que no disponga del código fuente de la misma; sin embargo, si estuviera depurando una aplicación de la que dispone el código fuente, es muy buena idea configurar Windbg para que sea capaz de usar toda esa información y mostrar la ejecución paso a paso en formato de instrucciones de código fuente, no instrucciones máquina. Para configurar este aspecto, despliegue el menú File, Source File Path (o pulse Ctrl+P). También puede usar el comando .srcpath <Ruta_código_fuente>
Para que el depurador muestre instrucciones de código fuente y no instrucciones máquina es necesario además que los símbolos de depuración contengan información acerca del fichero fuente y número de línea que se corresponde con un determinado símbolo. Estos símbolos, denominados normalmente símbolos privados, no suelen estar a disposición de los usuarios ajenos a la empresa creadora del software en cuestión.
Configurar la ruta de los módulos
En la mayoría de ocasiones, Windbg es capaz por sí solo de encontrar las imágenes de los ejecutables implicados en una sesión de depuración. En determinados casos, como por ejemplo cuando se está depurando un volcado de memoria pequeño o minidump (la depuración de volcados de memoria se tratará en un posterior artículo), es necesario indicarle al depurador dónde debe buscar los módulos (.exe, .dll, .sys, etc.). Para ello, abra File, Image File Path (o pulse Ctrl+I). Como siempre, si desea lograr esto mediante un comando de Windbg, ejecute .exepath <Ruta_ejecutables>
Ejecutar una aplicación dentro del depurador
Ya está en condiciones de depurar su primera aplicación en Windbg y para ello vamos a ejecutar la calculadora de Windows dentro de Windbg.
Abra File, Open Executable (o pulse Ctrl+E) y busque el ejecutable Calc.exe dentro del directorio \Windows\system32\. En este caso deje desmarcada la casilla Debug child processes also, que sirve para depurar no solo el proceso principal que cree ese ejecutable sino sus procesos hijos también. Haga clic sobre Abrir.
La pantalla de Windbg se rellenará con un texto similar al siguiente:
Microsoft (R) Windows Debugger Version 6.11.0001.404 X86
Copyright (c) Microsoft Corporation. All rights reserved.
CommandLine: C:\WINDOWS\system32\calc.exe
Symbol search path is: SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols
Executable search path is:
ModLoad: 01000000 0101f000 calc.exe
ModLoad: 7c910000 7c9c5000 ntdll.dll
ModLoad: 7c800000 7c903000 C:\WINDOWS\system32\kernel32.dll
ModLoad: 7e6a0000 7eec1000 C:\WINDOWS\system32\SHELL32.dll
ModLoad: 77da0000 77e4c000 C:\WINDOWS\system32\ADVAPI32.dll
ModLoad: 77e50000 77ee2000 C:\WINDOWS\system32\RPCRT4.dll
ModLoad: 77fc0000 77fd1000 C:\WINDOWS\system32\Secur32.dll
ModLoad: 77ef0000 77f39000 C:\WINDOWS\system32\GDI32.dll
ModLoad: 7e390000 7e421000 C:\WINDOWS\system32\USER32.dll
ModLoad: 77be0000 77c38000 C:\WINDOWS\system32\msvcrt.dll
ModLoad: 77f40000 77fb6000 C:\WINDOWS\system32\SHLWAPI.dll
(23c.24c): Break instruction exception - code 80000003 (first chance)
eax=001a1eb4 ebx=7ffdb000 ecx=00000007 edx=00000080 esi=001a1f48 edi=001a1eb4
eip=7c91120e esp=0007fb20 ebp=0007fc94 iopl=0 nv up ei pl nz na po nc
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202
ntdll!DbgBreakPoint:
7c91120e cc int 3
Analicemos detalladamente toda esta información:
La línea CommandLine nos está indicando el archivo que vamos a ejecutar dentro de Windbg, en este caso la calculadora de Windows. A continuación se muestra la ruta establecida para los símbolos y la ruta de búsqueda de módulos ejecutables, que en este caso está vacía porque no la hemos establecido desde la opción File, Image File Path. Seguidamente el depurador ha registrado información sobre la carga de una serie de módulos de los que depende la calculadora de Windows. Para ver las dependencias de un módulo yo recomiendo usar la herramienta Dependency Walker (http://www.dependencywalker.com/).
La siguiente línea, (23c.24c): Break instruction exception - code 80000003 (first chance), da pie a comentar bastantes cosas:
La sintaxis (23c.24c) la va a encontrar no pocas veces en Windbg. Hace referencia a un hilo dentro de un proceso. 23c es el identificador de proceso (PID), en formato hexadecimal. En este caso es el PID del proceso Calc.exe. 24c hace referencia al identificador de hilo (TID), en formato hexadecimal también. La excepción recibida en este caso es "Break instruction" (STATUS_BREAKPOINT), identificada por el código hexadecimal 0x80000003. Vamos a ver qué ocurre "por lo bajo" para explicar por qué ha ocurrido esto:
Cuando hemos seleccionado el ejecutable Calc.exe y hemos hecho clic sobre Abrir, Windbg ha llamado a la API CreateProcess con el sexto parámetro establecido a DEBUG_PROCESS. Esto permite crear un proceso e indicarle a Windows que deseamos depurarlo. Pero depurar un proceso requiere de algo más. Requiere que el programa depurador reciba una serie de eventos procedentes de la ejecución de la aplicación y los muestre al usuario o los trate de manera conveniente. Lo que ocurre durante una sesión de depuración se puede entender como un bucle en el cual el depurador espera eventos de depuración mediante la API WaitForDebugEvent, los trata de manera conveniente, y continua la ejecución del programa mediante la API ContinueDebugEvent. Este bucle se repite indefinidamente hasta que o bien la aplicación que está siendo depurada desaparece de la memoria, o bien finaliza correctamente su ejecución, o bien desacoplamos el depurador mediante el comando Debug, Detach Debugee.
La frase (first chance) hace referencia al comportamiento de las excepciones. Cuando una aplicación genera una excepción y está siendo depurada, el depurador recibe una excepción de primera oportunidad (first chance) y le da la opción de tratarla. En este caso, el depurador trata la excepción STATUS_BREAKPOINT deteniendo la ejecución de la aplicación permitiendo que el usuario introduzca comandos o examine el estado de la imagen de memoria del proceso y el estado del procesador. Si el depurador no capturase la excepción, se comprueba si el código de la aplicación la capturara. Este procedimiento implica verificar en la pila de ejecución si hay algún código manejador de excepciones, desde el marco de activación más reciente hasta al más antiguo. Este procedimiento recibe técnicamente el nombre de stack unwinding. No se preocupe, en posteriores artículos se va a tratar la estructura de datos conocida como pila, pues es de capital importancia a la hora de entender buena parte de la información que nos proporcione Windbg. En caso de que el código no capturase la excepción, se lanza al depurador una excepción de segunda oportunidad (second chance) y se vuelve a comprobar si el código captura la excepción.
Lo que aparece a continuación en la pantalla de Windbg es el estado de los registros del procesador. Para entender esta parte de la salida es necesario disponer de ciertos conocimientos específicos de la máquina que está siendo depurada. En este caso se trata de la arquitectura x86, por lo que la referencia obligada es este documento: http://download.intel.com/design/PentiumII/manuals/24319102.PDF. Cuando veamos algunos casos de estudio verá cómo aplicar la información sobre los registros de la máquina a un caso real.
Para finalizar nos aparece la última instrucción ejecutada en el procesador antes de que se pasara el control al depurador. En este caso se trata de una instrucción dentro de la función DbgBreakPoint dentro del módulo Ntdll.dll. La instrucción en cuestión es la instrucción int 3, identificada mediante el código hexadecimal CC. Esta instrucción lanza una interrupción software. El parámetro 3 indica que ejecutaremos la posición 3 del vector de interrupciones y básicamente se enviará la excepción STATUS_BREAKPOINT al depurador, para que haga con ella lo que considere oportuno. La dirección de memoria que contiene esa instrucción es la 7c91120e (en este ejemplo particular).
Para concluir, puede configurar Windbg para que no informe de ciertos eventos (tales como la finalización de un proceso, la carga de una DLL, etc.). Para ello puede ir al menú Debug, Event Filters.

Si desea hacer uso de la línea de comandos de Windbg, el comando en cuestión es sx y sus derivados sxe, sxd, sxi, sxn. En la documentación de Windbg (Help, About) puede obtener información adicional sobre el uso de estos comandos.
En este artículo hemos aprendido a configurar Windbg para comenzar una sesión de depuración y hemos ejecutado nuestra primera aplicación dentro del depurador. También hemos aprendido qué quiere decir la información que aparece en pantalla y en qué consiste "por lo bajo" la depuración de aplicaciones y el manejo de excepciones. En la siguiente parte veremos algunos comandos para examinar el estado de la máquina y del proceso que está siendo depurado. Se detallarán también algunos aspectos de la arquitectura interna de Windows que son importantes para saber realmente lo que está pasando.
Un problema que le ocurre a no poca gente que usa Windows XP consiste en que al intentar abrir un fichero con extensión MSC (Services.msc, Diskmgmt.msc, etc.) el sistema muestra el siguiente mensaje de error:
MMC no puede abrir el archivo C:\WINDOWS\system32\services.msc.
Puede ser que el archivo no exista, no sea una consola de MMC o fue creado por una versión más reciente de MMC. También puede ser que no tiene suficientes derechos de acceso para abrir el archivo.
El propio mensaje nos explica las posibles causas del problema, pero ciertamente la información que ofrece es algo vaga e inespecífica. El principal problema con el que se encuentra el usuario al recibir este mensaje de error es que, al tratarse de un mensaje de error genérico, es posible que la causa del problema que está experimentando no quede recogida en el texto del mensaje de error.
¿Cómo actuar en casos como este?
Hay muchas formas de actuar ante un mensaje de error de este estilo. Una manera consiste en observar si hay algún tipo de LOG que registre información detallada sobre el error (lo primero que debemos buscar es el código de error exacto). Es bastante probable que, de existir la posibilidad de registrar en un fichero LOG la información correspondiente a un mensaje de error, esta opción deba activarse explícitamente a través del registro del sistema operativo, o mediante algún otro método avanzado similar. En ocasiones, como último recurso para obtener información detallada sobre un mensaje de error tendremos que instalar una versión de depuración del sistema operativo o aplicación (versión checked). Las versiones checked son versiones que incorporan información detallada de depuración (trazas, aserciones, etc.) que son de mucha utilidad a los programadores de aplicaciones. De hecho, para adquirir la versión checked de un sistema operativo de Microsoft debe ser suscriptor de MSDN. Las versiones de depuración de los Service Packs sí están disponibles públicamente desde el Centro de descargas de Microsoft. Por ejemplo, este es el enlace para descargar la versión de depuración del SP3 de Windows XP.
En este artículo se va a describir un método menos complicado que puede sacarnos del atolladero en bastantes casos. De hecho, nos va a sacar del atolladero en el problema concreto que se describe más arriba.
En primer lugar, instale la última versión de Debugging Tools for Windows y configure el depurador Windbg apropiadamente. Para saber cómo hacer esto, siga los pasos de este tutorial.
A continuación, vamos a ejecutar la aplicación desde dentro del depurador. Para ello, haga clic sobre File, Open Executable. En la caja de texto Nombre, escriba lo siguiente: %SystemRoot%\system32\mmc.exe En la caja de texto Arguments, escriba lo siguiente: Services.msc (o el nombre del fichero MSC que no es capaz de abrir). Pulse Abrir.
Asegúrese de que Windbg le informe de que la información sobre los símbolos es correcta y pulse F5 (Go).
Cuando se muestre el mensaje de error en pantalla, active la ventana de Windbg y pulse Ctrl+Pausa o haga clic sobre Debug, Break.
Ahora tendrá que examinar la pila de ejecución de todos y cada uno de los hilos activos de la aplicación para ver si encuentra el código de error como parámetro de alguna de las funciones que allí aparezcan. Para cambiar de hilo, puede hacerlo gráficamente desde el menú View, Processes and Threads. Seleccione con un simple clic el hilo que quiera examinar (quedará marcado en negrita) e introduzca en la caja de texto de Windbg el comando kb para mostrar la pila de ejecución. En mi caso, esta es la pila de ejecución del hilo responsable de abrir el fichero MSC:
0:000> kb
ChildEBP RetAddr Args to Child
0007f030 7c91df4a 7c809590 00000002 0007f05c ntdll!KiFastSystemCallRet
0007f034 7c809590 00000002 0007f05c 00000001 ntdll!ZwWaitForMultipleObjects+0xc
0007f0d0 7e3995f9 00000002 0007f0f8 00000000 kernel32!WaitForMultipleObjectsEx+0x12c
0007f12c 6c6d4b52 00000001 0007f160 ffffffff USER32!RealMsgWaitForMultipleObjectsEx+0x13e
0007f14c 6c6d4cbd 000024ff ffffffff 00000000 DUSER!CoreSC::Wait+0x3a
0007f170 6c6d4eb9 000024ff 00000000 0007f19c DUSER!CoreSC::WaitMessage+0x40
0007f180 7e3d8e33 000024ff 00000000 00000064 DUSER!MphWaitMessageEx+0x22
0007f19c 7c91e473 0007f1ac 00000008 000024ff USER32!__ClientWaitMessageExMPH+0x1e
0007f1b0 7e399418 7e3a770a 00000000 00000000 ntdll!KiUserCallbackDispatcher+0x13
0007f1e8 7e3a49c4 000301b4 00000000 00000001 USER32!NtUserWaitMessage+0xc
0007f210 7e3ba956 7e390000 000c44f8 00000000 USER32!InternalDialogBox+0xd0
0007f4d0 7e3ba2bc 0007f62c 00000001 00000000 USER32!SoftModalMessageBox+0x938
0007f620 7e3e63fd 0007f62c 00000028 00000000 USER32!MessageBoxWorker+0x2ba
0007f678 7e3d0853 00000000 00e76008 00bafeb0 USER32!MessageBoxTimeoutW+0x7a
0007f698 7e3e6579 00000000 00e76008 00bafeb0 USER32!MessageBoxExW+0x1b
0007f6b4 4754f5fe 00000000 00e76008 00bafeb0 USER32!MessageBoxW+0x45
0007f6f0 0107a216 00e76008 00002010 00e86458 mmcbase!MMCErrorBox+0x7f
0007f740 01058ce9 00000003 80040154 00000000 mmc!DisplayFileOpenError+0x191
0007f794 0104093c 0007f748 00000004 00e6e018 mmc!CAMCDoc::OnOpenDocument+0x90
0007f7e0 5f81424a 0007fc14 00000001 00038988 mmc!CAMCMultiDocTemplate::OpenDocumentFile+0x21f
Marcada en negrita está la parte importante de la traza, el error en cuestión (0x80040154). ¿Qué quiere decir ese código de error? El propio Windbg nos lo puede decir:
0:001> !error 80040154
Error code: (HRESULT) 0x80040154 (2147746132) - Clase no registrada
Un error de clase no registrada. Para sabér qué clase es la afectada, puede usar Process Monitor (http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx), monitorizar el sistema mientras intenta volver a abrir el archivo MSC y analizar con calma los resultados NOT FOUND que hagan referencia al Registro del sistema, o bien puede seguir las pautas de este artículo referido a Explorer.exe.
Para no hacerle perder el tiempo, le diré que en este caso la clase afectada está en la librería Msxml3.dll y se puede volver a registrar con el comando regsvr32 msxml3.dll.
Otro código de error que se puede encontrar es el código 0x2 (archivo no encontrado). En este caso lo ideal es hacer uso de Process Monitor (http://technet.microsoft.com/en-us/sysinternals/bb896645.aspx), monitorizar el sistema mientras intenta volver a abrir el archivo MSC y analizar con calma los resultados NOT FOUND que hagan referencia, en esta ocasión, al sistema de archivos. Un caso que he analizado tenía como culpable al virus Vundo, aunque en general podría tratarse de cualquier otro tipo de malware.
Una duda que quizá tenga es, ¿cómo distinguir en la salida del comando kb lo que es un código de error de lo que no? En general yo suelo descartar en primer lugar lo que seguro sé que no es un código de error. Por ejemplo, en la traza de pila del ejemplo puede ver que 7e3a770a es un valor que está cerca de las direcciones de retorno de cada una de las funciones, por lo que probablemente no sea un código de error. Los valores 00bafeb0 y similares, es decir, un número hexadecimal no muy alto, suelen ser punteros a estructuras de datos, por lo que tampoco suelen ser códigos de error. Los valores muy bajos (00000002), o que comiencen por 8 (80040154), sí suelen ser códigos de error. Por supuesto, en este caso el nombre de la función mmc!DisplayFileOpenError+0x191, nos da la pista fundamental.
Espero que este artículo les ayude a investigar a fondo los mensajes de error en Windows en los que no aparece de manera explícita el código de error. En futuros artículos verá cómo atacar un problema similar pero esta vez causado por una excepción de aplicación, o bien por una versión incompatible de una DLL en el sistema, usando para ello la aplicación Dependency Walker.
He añadido a mi página web un artículo que explica lo que ocurre cuando se ejecuta el comando Explorer.exe tanto sin parámetros como con parámetros, en sistemas XP y Vista. Se incluye toda la casuística, lista completa de parámetros soportados, cómo forzar la creación de un nuevo proceso, etc. El artículo lo puede leer en la dirección http://winvista.mvps.org/Tema.aspx?ID=233
Cualquier duda o sugerencia la puede hacer llegar a través de la sección de comentarios de esta entrada o mediante el enlace Contact de la parte izquierda del blog.
More Posts
Next page »