<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>4 bits blog &#187; Windows</title>
	<atom:link href="http://blog.4bits.es/category/windows/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.4bits.es</link>
	<description>Ahora en 16 colores</description>
	<lastBuildDate>Thu, 05 Aug 2010 13:52:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Desbloquear sesiones de Terminal Server</title>
		<link>http://blog.4bits.es/desbloquear-sesiones-de-terminal-server/</link>
		<comments>http://blog.4bits.es/desbloquear-sesiones-de-terminal-server/#comments</comments>
		<pubDate>Mon, 12 Apr 2010 18:14:36 +0000</pubDate>
		<dc:creator>Lek</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=531</guid>
		<description><![CDATA[No todo en la programación es programar. Además hay que instalar en los servidores de los clientes. Supongo que la mayoría estáis familiarizados con el Terminal Server, un componente de control remoto que viene incluido en Windows y que es lo que en mi caso utilizo masivamente con los servidores de esta plataforma (junto al [...]]]></description>
			<content:encoded><![CDATA[<p>No todo en la programación es programar. Además hay que instalar en los servidores de los clientes. Supongo que la mayoría estáis familiarizados con el <a href="http://es.wikipedia.org/wiki/Terminal_Server">Terminal Server,</a> un componente de control remoto que viene incluido en Windows y que es lo que en mi caso utilizo masivamente con los servidores de esta plataforma (junto al VNC).</p>
<p>El problema del TS es que utiliza un sistema de sesiones que impide que haya <strong>más de 2 sesiones de administrador en el equipo</strong>. Si la gente no tiene costumbre de cerrar correctamente su sesión nos podemos encontrar con que no podemos conectar <strong>a pesar de que nadie esté trabajando con el servidor remotamente</strong>. Pues atención, niños y niñas, que nada es imposible en esta vida. A continuación se lista lo que hay que hacer para desbloquear esas sesiones colgadas (al menos para los que trabajéis con Windows):</p>
<ol>
<li>Abrid un terminal de línea de comandos (Inicio -> ejecutar -> cmd)</li>
<li>Ejecutad la siguiente orden (cambiando los valores), pedirá la contraseña del usuario:
<pre>> net use /user:[usuario] \\[ip servidor]\c$</pre>
<p>El 99% de los Windows con los que he trabajado tienen compartido de forma predeterminada todo el disco C a través de C$.</li>
<li>Después hay que ejecutar:
<pre>> query session /server:[ip servidor]</pre>
<p>Nunca me ha funcionado así, sino poniendo la ruta completa, esto es, <code>c:\Winnt\system32\dllcache\query ...</code></li>
<li>Mostrará un listado con las sesiones. Habrá que mirar que la que se quiere desconectar no esté activa (esté en Listen, o Disconnected o algo así). Una vez seleccionada la sesión, hay que ejecutar:
<pre>> reset session [ID] /server:[ip servidor]</pre>
</li>
</ol>
<p>Voilá. Ya podemos ir a nuestro cliente de Terminal y conectarnos al servidor.</p>
<p>Traducido del original en <a href="http://www.howtogeek.com/howto/windows/command-line-hack-for-terminal-server-has-exceeded-the-maximum-number-of-allowed-connections/">How-To Geek</a>, donde además os pone capturas de lo que veréis por pantalla, por si a alguno no le ha quedado clara mi espartana explicación.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/desbloquear-sesiones-de-terminal-server/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Detectar fugas de memoria en Visual Studio</title>
		<link>http://blog.4bits.es/detectar-fugas-de-memoria-en-visual-studio/</link>
		<comments>http://blog.4bits.es/detectar-fugas-de-memoria-en-visual-studio/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 11:58:51 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=480</guid>
		<description><![CDATA[Para los que programen en C con Visual Studio y sientan añoranza de valgrind, aquí están los pasos sobre cómo detectar fugas de memoria (memory leaks) en Visual Studio: Añadir la macro _CRTDBG_MAP_ALLOC del preprocesador, ya sea definiéndola en algún archivo del proyecto o en las opciones de compilación del proyecto. Incluir en el siguiente [...]]]></description>
			<content:encoded><![CDATA[<p>Para los que programen en C con Visual Studio y sientan añoranza de <a href="http://valgrind.org/">valgrind</a>, aquí están los pasos sobre <strong>cómo detectar fugas de memoria (<em>memory leaks</em>) en Visual Studio</strong>:</p>
<ul>
<li>Añadir la macro <code>_CRTDBG_MAP_ALLOC</code> del preprocesador, ya sea definiéndola en algún archivo del proyecto o en las opciones de compilación del proyecto.</li>
<li>Incluir en el siguiente orden <code>stdlib.h</code> y <code>crtdbg.h</code> en los archivos dónde se busquen las fugas de memoria. El archivo <code>crtdgb.h</code> sustituye las funciones <code>malloc</code> y <code>free</code> por unas propias que registran la memoria reservada y liberada.</li>
<li>Añadir la función <code>_CrtDumpMemoryLeaks ()</code> al final del programa en el que se buscan las fugas de memoria. Esta función muestra por la salida de depuración las fugas de memoria detectadas.</li>
</ul>
<p>Todo <strong>esto sólo funcionará cuando el proyecto se compile con la macro <code>_DEBUG</code> definida</strong>, es decir, en lo que debería ser para todos la versión de depuración del programa.</p>
<p>La macro <code>_CRTDBG_MAP_ALLOC</code> sirve para que la función <code>_CrtDumpMemoryLeaks ()</code> muestre información sobre el archivo y la línea en la que se produjo la fuga de memoria.</p>
<p>Un pequeño ejemplo de cómo quedaría todo:</p>
<pre class="brush:c">#define _CRTDBG_MAP_ALLOC
#include &lt;stdlib.h&gt;
#include &lt;crtdbg.h&gt;

int
main (int argc, char *argv[])
{
    /* Código del programa */

    _CrtDumpMemoryLeaks ();

    return 0;
}</pre>
<p>Si este programa tuviera alguna fuga de memoria, al compilarlo en modo depuración y ejecutar el depurador de Visual Studio, se obtendría en la salida de éste un listado con las fugas de memoria del programa.</p>
<p>Para más información, leed el artículo <a href="http://msdn.microsoft.com/en-us/library/e5ewb1h3(v=VS.80).aspx">Enabling Memory Leak Detection</a> de la MSDN.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/detectar-fugas-de-memoria-en-visual-studio/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Applets en XHTML 1.1 compatibles con IE</title>
		<link>http://blog.4bits.es/applets-en-xhtml-1-1-compatibles-con-ie/</link>
		<comments>http://blog.4bits.es/applets-en-xhtml-1-1-compatibles-con-ie/#comments</comments>
		<pubDate>Wed, 26 Aug 2009 13:11:54 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[(X)HTML]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=262</guid>
		<description><![CDATA[Creo que cualquiera que haya tenido que realizar algún tipo de web para un público amplio, ha tenido que lidiar con los problemas que da Internet Explorer (IE) al no cumplir los estándares del W3C. Pero si encima para rematar la faena te toca insertar un applet, quieres que cumpla con XHTML 1.1 y que [...]]]></description>
			<content:encoded><![CDATA[<p>Creo que cualquiera que haya tenido que realizar algún tipo de web para un público amplio, ha tenido que lidiar con los problemas que da Internet Explorer (IE) al no cumplir los estándares del <a href="http://www.w3c.org">W3C</a>.</p>
<p>Pero si encima para rematar la faena te toca <strong>insertar un applet, quieres que cumpla con XHTML 1.1 y que se vea en IE</strong>, pues acojona un poco al ver que <strong>la etiqueta <em>applet</em> dejó de formar parte del estándar hace ya un tiempo.</strong></p>
<p>Sin más dilación, os dejo aquí el código:</p>
<pre class="brush:html">&lt;!--[if !IE]&gt;--&gt;
&lt;object id="applet" name="applet" classid="java:es.4bits.applet.Applet"
 type="application/x-java-applet"
 archive="applets/Applet.jar"&gt;&lt;/object&gt;
&lt;!--&lt;![endif]--&gt;

&lt;!--[if IE]&gt;
&lt;object id="applet" name="applet" code="es.4bits.applet.Applet"
 archive="applets/Applet.jar"&gt;&lt;/object&gt;
&lt;![endif]--&gt;</pre>
<p>Al final, lo único necesario es utilizar los asquerosos <em>hacks</em> de IE, para que no cargue la versión que no entiende de la etiqueta <em>object</em> y cargue la que entiende.</p>
<p>Basado en <a href="http://www.thomasguymer.co.uk/tutorials/xhtml-strict-applets/">XHTML Strict Applets</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/applets-en-xhtml-1-1-compatibles-con-ie/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Cifrar una memoria USB</title>
		<link>http://blog.4bits.es/cifrar-una-memoria-usb/</link>
		<comments>http://blog.4bits.es/cifrar-una-memoria-usb/#comments</comments>
		<pubDate>Thu, 30 Jul 2009 17:59:28 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Seguridad]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=255</guid>
		<description><![CDATA[Hace poco se me ocurrió una forma de aprovechar una memoria USB (o pendrive) antigua (de 256MB) que tenía por ahí. Simplemente, utilizarla para guardar, todo cifrado, un archivo con un listado de contraseñas, documentos personales, claves GPG y/o SSH, &#8230; Así que estuve buscando diferentes opciones, siendo importante que funcionase en Linux y en [...]]]></description>
			<content:encoded><![CDATA[<p>Hace poco se me ocurrió <strong>una forma de aprovechar una memoria USB</strong> (o <em>pendrive</em>) antigua (de 256MB) que tenía por ahí. Simplemente, <strong>utilizarla para guardar, todo cifrado, un archivo con un listado de contraseñas, documentos personales, claves GPG y/o SSH, &#8230;</strong></p>
<p>Así que estuve buscando diferentes opciones, siendo importante que funcionase en Linux y en Windows (por si las moscas). <strong>Al final había dos opciones Truecrypt (el archiconocido) y dm-crypt (un gestor de dispositivos cifrados de Linux)</strong>, me decanté por dm-crypt porque Truecrypt, curiosamente, no está en los repositorios de Debian y porque con dm-crypt no necesitaría de un programa a parte para utilizar mi dispositivo en Linux (aunque sí, en Windows).</p>
<h3>Pasos a seguir</h3>
<p>Directo al grano, estos son los pasos que realicé:</p>
<ol>
<li>Paquetes necesarios:
<pre># apt-get install cryptsetup hashalot dmsetup</pre>
</li>
<li>Rellenar la memoria con datos aleatorios (no es necesario, aunque sí recomendable):
<pre># dd if=/dev/urandom of=/dev/sdX</pre>
</li>
<li>Cargar los siguientes módulos si no lo están ya:
<pre># modprobe aes
# modprobe dm_crypt
# modprobe dm_mod
# modprobe sha256</pre>
</li>
<li>Crear el contenedor cifrado (pedirá la contraseña para poder luego descifrarlo):
<pre># cryptsetup -v --key-size 256 luksFormat /dev/sdX NOMBRE-CONTENEDOR</pre>
</li>
<li>Formatear el contenedor (yo utilicé FAT para que funcione en Windows) para ello primero hay que montar el contenedor utilizando <code>cryptsetup</code>:
<pre># cryptsetup -v luksOpen /dev/sdX NOMBRE-CONTENEDOR
# mkfs.vfat /dev/mapper/NOMBRE-CONTENEDOR</pre>
</li>
<li>Y ya está, ya se puede montar:
<pre># mount -t vfat /dev/mapper/NOMBRE-CONTENEDOR /mnt/usb_cifrado</pre>
</li>
</ol>
<h3>Uso</h3>
<p>Lo bueno de este método es que al enchufar la memoria en Linux, éste pedirá la contraseña y se montará automáticamente, aunque en la versión de GNOME que uso no lo monta. Así que, por si las moscas, siempre lo puedes montar ejecutando:</p>
<pre>$ pmount-hal /dev/sdX</pre>
<p>Y desmontar ejecutando:</p>
<pre>$ pumount /dev/sdX</pre>
<p>Para poder utilizar el dispositivo cifrado en Windows se necesita un programa llamado <a href="http://www.freeotfe.org/">FreeOTFE</a> que es compatible con este tipo de cifrado.</p>
<p>Basado en <a href="http://homer.shacknet.nu/docs/Cifrado.txt">Manual de Cifrado de una particion concreta desde Linux Debian/Ubuntu</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/cifrar-una-memoria-usb/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Windows System Programming</title>
		<link>http://blog.4bits.es/windows-system-programming/</link>
		<comments>http://blog.4bits.es/windows-system-programming/#comments</comments>
		<pubDate>Tue, 30 Jun 2009 14:45:38 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Libros]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=233</guid>
		<description><![CDATA[Windows System Programming es un libro de introducción a la programación sobre Windows (Win32, aunque hay una breve introducción a Win64), con el lenguaje C. He de decir que este libro no me ha sorprendido mucho, ya que en cuanto llevas algo de tiempo programando sobre Win32 y visitando la MSDN a menudo, te acabas [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.4bits.es/wp-content/uploads/2009/06/wsp_3.gif" alt="Windows System Programming" class="alignleft" width="150" height="188" /><strong>Windows System Programming</strong> es un libro de introducción a la programación sobre Windows (<a href="http://en.wikipedia.org/wiki/Windows_API">Win32</a>, aunque hay una breve introducción a Win64), con el lenguaje C.</p>
<p>He de decir que este libro no me ha sorprendido mucho, ya que en cuanto llevas algo de tiempo programando sobre Win32 y visitando la <a href="http://www.msdn.com">MSDN</a> a menudo, te acabas conociendo las partes más utilizadas. Además, <strong>este libro es bastante antiguo (del 2004).</strong></p>
<p>En general, no me convence la forma de explicar los temas por parte del autor, <strong>casi todos los capítulos se limita a copiar las diferentes funciones</strong> que se utilizan para hacer lo que sea, y a explicar cada uno de sus parámetros. Por lo que el libro se transforma en una especie de resumen de la MSDN.</p>
<p>De todo el contenido <strong>del libro me quedaría con los capítulos sobre los servicios de Windows y las estructuras de seguridad</strong> (SIDs, ACLs, ACEs) de Windows.</p>
<p>Aún así, puede servir como punto de partida para empezar a programar sobre Windows utilizando Win32, si no fuera por las pegas que he comentado.</p>
<p><strong>Recomendación:</strong> Baja.<br />
<strong>Nivel:</strong> Medio.<br />
<strong>Idioma:</strong> Inglés.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/windows-system-programming/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Compartir directorios con Samba</title>
		<link>http://blog.4bits.es/compartir-directorios-con-samba/</link>
		<comments>http://blog.4bits.es/compartir-directorios-con-samba/#comments</comments>
		<pubDate>Mon, 08 Jun 2009 13:46:58 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=224</guid>
		<description><![CDATA[En el anterior post explicaba cómo compartir impresoras con Samba. Como sé que os gustó, hoy os explico cómo compartir directorios con Samba. Instrucciones Voy a partir de qué tenemos la siguiente estructura de directorios que se quiere compartir: drwxr-x--- user group dir01 drwxr-x--- user group dir02 drwxr-x--- user group dir03 Como se puede ver, [...]]]></description>
			<content:encoded><![CDATA[<p>En el anterior post explicaba cómo <a href="http://blog.4bits.es/compartir-impresoras-con-samba/">compartir impresoras con Samba</a>. Como sé que os gustó, hoy os explico <strong>cómo compartir directorios con Samba</strong>.</p>
<h3>Instrucciones</h3>
<p>Voy a partir de qué tenemos la siguiente estructura de directorios que se quiere compartir:</p>
<pre>drwxr-x--- user group dir01
drwxr-x--- user group dir02
drwxr-x--- user group dir03</pre>
<p>Como se puede ver, a estos directorios sólo puede acceder el usuario <code>user</code> y los usuarios del grupo <code>group</code>, aunque estos últimos sólo con permisos de lectura sobre los directorios.</p>
<p>Lo primero que se debe hacer es añadir el usuario (o los usuarios) que podrán acceder a nuestros datos compartidos. Para ello se ejecuta:</p>
<pre># smbpasswd -a user</pre>
<p>Nos pedirá una contraseña, ésta puede ser distinta a la que tenga el usuario para acceder a la máquina.</p>
<p>Una vez añadido el usuario (o los usuarios), se podrá configurar Samba para que comparta los directorios. Para ello se modifica el archivo <code>/etc/samba/smb.conf</code> y se añade un elemento del siguiente tipo por cada directorio a compartir:</p>
<pre class="brush:text">[nombre_directorio_a_compartir]
  comment = Comentario del directorio compartido
  path = /ruta/al/directorio
  read only = yes # Indica si el acceso será sólo lectura
  write list = user # Usuarios/grupos que tendrán acceso de escritura
  create mask = 0640 # Máscara de los permisos al crear archivos
  directory mask = 0750 # Máscara de los permisos al crear directorios
  guest ok = no # Acceso sin autenticación</pre>
<p>De este modo, para el ejemplo que he puesto se tendrían que añadir tres elementos de este tipo, quedando el archivo similar a este:</p>
<pre class="brush:text">[global]
  display charset = UTF-8
  server string = NOMBRE-DE-LA-MAQUINA
  workgroup = GRUPO-DE-TRABAJO
  netbios name = NOMBRE-NETBIOS-MAQUINA
  invalid users = root # Para que no se pueda acceder como root

[dir01]
  comment = Directorio 01
  path = /home/user/dir01
  read only = yes
  write list = user
  create mask = 0640
  directory mask = 0750
  guest ok = no

[dir02]
  comment = Directorio 02
  path = /home/user/dir02
  read only = yes
  write list = user
  create mask = 0640
  directory mask = 0750
  guest ok = no

[dir03]
  comment = Directorio 03
  path = /home/user/dir03
  read only = yes
  write list = user
  create mask = 0640
  directory mask = 0750
  guest ok = no</pre>
<p>Después de esto sólo hay que reiniciar Samba y listo, ya se podrá acceder a dichos directorios compartidos utilizando el usuario <code>user</code>.</p>
<pre># /etc/init.d/samba restart</pre>
<p>Basado en <a href="http://lopezivan.blogspot.com/2007/03/compartir-directorios-con-samba.html">Compartir directorios con Samba</a> del blog de Iván López.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/compartir-directorios-con-samba/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Compartir impresoras con Samba</title>
		<link>http://blog.4bits.es/compartir-impresoras-con-samba/</link>
		<comments>http://blog.4bits.es/compartir-impresoras-con-samba/#comments</comments>
		<pubDate>Tue, 26 May 2009 17:28:57 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=211</guid>
		<description><![CDATA[Estos días en el trabajo me ha tocado lidiar con la configuración de un servidor que tenemos para almacenamiento e impresión, con sus directorios compartidos e impresora compartida. Hasta hace poco este servidor utilizaba Windows 2003, hasta que un día decidió morir en extrañas circunstancias, así que como los que nos encargamos de dicho servidor [...]]]></description>
			<content:encoded><![CDATA[<p>Estos días en el trabajo me ha tocado lidiar con la configuración de un servidor que tenemos para almacenamiento e impresión, con sus directorios compartidos e impresora compartida.</p>
<p>Hasta hace poco este servidor utilizaba Windows 2003, hasta que un día decidió morir en extrañas circunstancias, así que como los que nos encargamos de dicho servidor nos manejamos mejor en Linux decidimos <strong>instalar Debian Lenny y utilizar Samba para los directorios compartidos y la impresora compartida</strong>, ya que en nuestra red tenemos variedad de Windows y Linux.</p>
<h3>Instrucciones</h3>
<p>Hay que tener instalado CUPS. Una vez instalado, realizar los siguientes pasos para <strong>configurar CUPS</strong>:</p>
<ol>
<li>Añadir la siguiente línea al archivo <code>/etc/cups/cupsd.conf</code>, suponiendo que nuestra red sea <code>192.168.0.0/255.255.255.0</code>:
<pre>Allow From 192.168.0.*</pre>
</li>
<li>Descomentar la siguiente línea del archivo <code>/etc/cups/mime.convs</code>:
<pre>application/octet-stream application/vnd.cups-raw  0 - </pre>
</li>
</ol>
<p>De este modo, CUPS permitirá compartir remotamente la impresora. Ahora hay que <strong>configurar Samba</strong> para que las máquinas con Windows puedan usar la impresora, así que a seguir los siguientes pasos:</p>
<p>Editar el archivo <code>/etc/samba/smb.conf</code> de modo que quede similar a este que muestro:</p>
<pre class="brush:text">[global]
  workgroup = GRUPO-DE-TRABAJO
  netbios name = NOMBRE-NETBIOS-MAQUINA

  #this section is only to share the printer
  printcap name = cups
  disable spoolss = yes
  show add printer wizard = no
  printing = cups

[printers]
  comment = Printer in Linux
  path = /var/spool/samba
  create mode = 0700
  guest ok = yes
  print ok = yes
  use client driver = yes
  browseable = yes
  public = yes</pre>
<p>El directorio <code>/var/spool/samba</code> se debe crear si no existe y tener permisos 0777.</p>
<p>Con esta configuración se comparte la impresora sin necesidad de autenticarse, ya que el nivel de seguridad lo permite (<code>security = share</code>) y se permite autenticarse como invitado (<code>guest ok = yes</code>). El elemento <code>printers</code> permite que samba comparta automáticamente todas las impresoras conectadas con las propiedades que se le indiquen en dicho elemento.</p>
<p>Si se quisiera obligar a autenticarse para poder usar la impresora, habría que añadir un usuario a samba ejecutando:</p>
<pre># smbpasswd -a usuario</pre>
<p>Además, habría que cambiar el nivel de seguridad (con quitar la propiedad <code>security</code> valdría) y no permitir la autenticación como invitado (<code>guest ok = no</code>).</p>
<p>Para finalizar, sólo habría que reiniciar CUPS y Samba:</p>
<pre># /etc/init.d/cups restart
# /etc/init.d/samba restart</pre>
<p>Basado en  <a href="http://www.debian-administration.org/article/Sharing_a_printer_to_Windows_XP_clients_with_Samba_and_Cups">Sharing a printer to XP clients with Samba and Cups</a> de Debian Administration (en inglés).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/compartir-impresoras-con-samba/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Manejar las señales de control de la consola de Windows</title>
		<link>http://blog.4bits.es/manejar-las-senales-de-control-de-la-consola-de-windows/</link>
		<comments>http://blog.4bits.es/manejar-las-senales-de-control-de-la-consola-de-windows/#comments</comments>
		<pubDate>Wed, 15 Apr 2009 08:45:09 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=191</guid>
		<description><![CDATA[En Windows existen cinco señales de la consola que se emiten cuando se producen varios eventos, todos relacionados con el fin de la aplicación (Ctrl+C o Ctrl+Break), con el cierre de la consola (más llanamente, es el cierre de la ventana del cmd.exe) o con el fin de la sesión en Windows (el cierre de [...]]]></description>
			<content:encoded><![CDATA[<p>En Windows existen cinco señales de la consola que se emiten cuando se producen varios eventos, todos relacionados con el fin de la aplicación (Ctrl+C o Ctrl+Break), con el cierre de la consola (más llanamente, es el cierre de la ventana del cmd.exe) o con el fin de la sesión en Windows (el cierre de una sesión de usuario o el apagado del sistema).</p>
<p>Windows emite estas señales a las aplicaciones correspondientes para que puedan manejarlas y terminar de una forma adecuada, por ejemplo: realizando las operaciones necesarias para no dejar archivos en algún estado catastrófico perdiendo la información de estos.</p>
<h3>Manejando las señales</h3>
<p>Para manejar estas señales las aplicaciones disponen de una lista de manejadores, en la que en principio sólo hay una función que termina la ejecución del proceso. Para añadir/borrar un manejador a la lista se dispone de la función <a href="http://msdn.microsoft.com/en-us/library/ms686016(VS.85).aspx">SetConsoleCtrlHandler</a>:</p>
<pre>BOOL WINAPI SetConsoleCtrlHandler (PHANDLER_ROUTINE HandlerRoutine, BOOL Add);</pre>
<p>Donde los parámetros son:</p>
<ul>
<li><strong>HandlerRoutine:</strong> Es un puntero a la función que manejará las señales recibidas. Tendrá la forma:
<pre>BOOL WINAPI CtrlHandler (DWORD CtrlType)</pre>
</li>
<li><strong>Add:</strong> Si su valor es TRUE indica que la función se añadirá a la lista de manejadores de las señales, en cambio si es FALSE indica que la función se borrará de la lista de manejadores.</li>
</ul>
<h3>La función del manejador</h3>
<p>Como se ha mencionado antes, <a href="http://msdn.microsoft.com/en-us/library/ms683242(VS.85).aspx">la función del manejador</a> tiene la forma:</p>
<pre>BOOL CtrlHandler (DWORD CtrlType);</pre>
<p>La función del manejador deberá tratar las señales que crea conveniente, utilizando el parámetro <strong>CtrlType</strong> que recibirá uno de los siguientes valores:</p>
<ul>
<li>CTRL_C_EVENT: Señal de Ctrl+C.</li>
<li>CTRL_BREAK_EVENT: Señal de Ctrl+Break.</li>
<li>CTRL_CLOSE_EVENT: Señal del cierre de la ventana de la consola.</li>
<li>CTRL_LOGOFF_EVENT: Señal del cierre de la sesión.</li>
<li>CTRL_SHUTDOWN_EVENT: Señal del apagado del sistema</li>
</ul>
<p>Este manejador devolverá TRUE cuando haya tratado la señal, y FALSE cuando no la haya tratado, de modo que pasará a ejecutar el siguiente manejador.</p>
<h3>Ejemplo</h3>
<p>Como todo se entiende mejor con un ejemplo, aquí os dejo <a href="http://msdn.microsoft.com/en-us/library/ms685049(VS.85).aspx">el ejemplo de la MSDN sobre registrar un manejador de señales de control de la consola</a>:</p>
<pre class="brush:c">#include &lt;windows.h&gt;
#include &lt;stdio.h&gt;

BOOL WINAPI CtrlHandler (DWORD CtrlType) {

    switch (CtrlType) {

        // Handle the CTRL-C signal.
        case CTRL_C_EVENT:
            printf ("Ctrl-C event\n\n");
            Beep (750, 300);
            return TRUE;

        // CTRL-CLOSE: confirm that the user wants to exit.
        case CTRL_CLOSE_EVENT:
            printf ("Ctrl-Close event\n\n");
            Beep (600, 200);
            return TRUE;

        // Pass other signals to the next handler.
        case CTRL_BREAK_EVENT:
            printf ("Ctrl-Break event\n\n");
            Beep (900, 200);
            return FALSE;

        case CTRL_LOGOFF_EVENT:
            printf ("Ctrl-Logoff event\n\n");
            Beep (1000, 200);
            return FALSE;

        case CTRL_SHUTDOWN_EVENT:
            printf ("Ctrl-Shutdown event\n\n");
            Beep (750, 500);
            return FALSE;

        default:
            return FALSE;
    }
}

int main (int argc, char *argv[]) {

    BOOL added;

    added = SetConsoleCtrlHandler ((PHANDLER_ROUTINE) CtrlHandler,
                                   TRUE);
    if (added) {
        printf ("\nThe Control Handler is installed.\n");
        printf ("\n -- Now try pressing Ctrl+C or Ctrl+Break, or");
        printf ("\n    try logging off or closing the console...\n");
        printf ("\n(...waiting in a loop for events...)\n\n");

        while (1) {
            Sleep (500);
        }

    } else
        printf ("\nERROR: Could not set control handler");

    return 0;
}</pre>
]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/manejar-las-senales-de-control-de-la-consola-de-windows/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Tuberías en Windows</title>
		<link>http://blog.4bits.es/tuberias-windows/</link>
		<comments>http://blog.4bits.es/tuberias-windows/#comments</comments>
		<pubDate>Sun, 22 Jun 2008 17:54:40 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/?p=61</guid>
		<description><![CDATA[Las tuberías (o pipes, en inglés) son un recurso utilizado para comunicar varios procesos, podríamos decir que es un sistema muy básico de mensajería entre procesos, se trata de un archivo en el que un proceso escribe y otro lee. Gracias a las tuberías podemos redirigir la entrada estándar, la salida estándar y/o la salida [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Las tuberías (o <a href="http://en.wikipedia.org/wiki/Pipe_(Unix)">pipes</a>, en inglés) son un recurso utilizado para comunicar varios procesos</strong>, podríamos decir que es un sistema muy básico de mensajería entre procesos, se trata de un archivo en el que un proceso escribe y otro lee.</p>
<p>Gracias a las tuberías podemos redirigir la entrada estándar, la salida estándar y/o la salida de error de un programa que ejecutemos dentro de nuestro programa, de modo que podamos obtener dicha salida para posteriormente procesarla como queramos.</p>
<p>A continuación, os muestro cómo se <strong>redirige la salida estándar y la salida de error, en Windows, de un proceso</strong> que ejecutemos dentro de nuestro programa.</p>
<pre class="brush:c">#include &lt;windows.h&gt;
#include &lt;stdio.h&gt;

#define BUFSIZE 4096 

HANDLE hChildStdoutRd, hChildStdoutWr, hStdout;

BOOL CreateChildProcess (char *cmdline) {

	PROCESS_INFORMATION piProcInfo;
	STARTUPINFO siStartInfo;
	BOOL bFuncRetn = FALSE;

	// Set up members of the PROCESS_INFORMATION structure.
	ZeroMemory (&#038;piProcInfo, sizeof (PROCESS_INFORMATION));

	// Set up members of the STARTUPINFO structure.
	ZeroMemory (&#038;siStartInfo, sizeof (STARTUPINFO));
	siStartInfo.cb = sizeof (STARTUPINFO);
	siStartInfo.hStdError = hChildStdoutWr;
	siStartInfo.hStdOutput = hChildStdoutWr;
	siStartInfo.dwFlags |= STARTF_USESTDHANDLES;

	// Create the child process.
	bFuncRetn = CreateProcess (NULL, cmdline, NULL, NULL, TRUE, 0, NULL,
							NULL, &#038;siStartInfo, &#038;piProcInfo);

	if (bFuncRetn == 0) {
		printf ("CreateProcess failed\n");
		return FALSE;
	} else {
		CloseHandle (piProcInfo.hProcess);
		CloseHandle (piProcInfo.hThread);
		return bFuncRetn;
	}
}

int ReadFromPipe () {

	DWORD dwRead, dwWritten;
	char chBuf[BUFSIZE];

	// Close the write end of the pipe before reading from the
	// read end of the pipe.
	if (!CloseHandle (hChildStdoutWr)) {
		printf ("Closing handle failed");
		return -1;
	}

	// Read output from the child process, and write to parent's STDOUT.
	for (;;) {

		if (! ReadFile (hChildStdoutRd, chBuf, BUFSIZE, &#038;dwRead, NULL)
			|| dwRead == 0)
		{
			break;
		}

		if (! WriteFile (hStdout, chBuf, dwRead, &#038;dwWritten, NULL))
			break;
	}

	return 0;
}

int main (int argc, char *argv[]) {

	SECURITY_ATTRIBUTES saAttr;
	BOOL fSuccess;

	// Get a handle to the parent's input file.
	if (argc == 1) {
		printf ("Must be a parameter.\n");
		return -1;
	}

	// Set the bInheritHandle flag so pipe handles are inherited.
	saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
	saAttr.bInheritHandle = TRUE;
	saAttr.lpSecurityDescriptor = NULL;

	// Get the handle to the current STDOUT.
	hStdout = GetStdHandle (STD_OUTPUT_HANDLE);

	// Create a pipe for the child process's STDOUT.
 	if (! CreatePipe (&#038;hChildStdoutRd, &#038;hChildStdoutWr, &#038;saAttr, 0))
		return -2;

	// Ensure that the read handle to the child process's pipe for
	// STDOUT is not inherited.
	SetHandleInformation (hChildStdoutRd, HANDLE_FLAG_INHERIT, 0);

	// Now create the child process.
	fSuccess = CreateChildProcess (argv[1]);
	if (! fSuccess)
		return -3;

	printf ("\nContents of %s:\n\n", argv[1]);

	// Read from pipe that is the standard output for child process.
 	ReadFromPipe ();

	return 0;
}</pre>
<p>Código basado en <a href="http://msdn.microsoft.com/en-us/library/ms682499(VS.85).aspx">el ejemplo de la MSDN sobre la creación de tuberías</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/tuberias-windows/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Accediendo al registro de Windows</title>
		<link>http://blog.4bits.es/accediendo-al-registro-de-windows/</link>
		<comments>http://blog.4bits.es/accediendo-al-registro-de-windows/#comments</comments>
		<pubDate>Sat, 23 Feb 2008 13:00:02 +0000</pubDate>
		<dc:creator>Fran</dc:creator>
				<category><![CDATA[C/C++]]></category>
		<category><![CDATA[Windows]]></category>

		<guid isPermaLink="false">http://blog.4bits.es/accediendo-al-registro-de-windows/</guid>
		<description><![CDATA[Desde hace ya unos años no tocaba Windows para nada, y de programar pues ni hablemos, desde la universidad en que programaba en PASCAL programas para la consola, no había vuelto a tocar nada relacionado con Windows, y menos programar en C sobre Windows (¡herejía!). Pero por razones sobrenaturales (trabajo), he tenido que programar en [...]]]></description>
			<content:encoded><![CDATA[<p>Desde hace ya unos años no tocaba Windows para nada, y de programar pues ni hablemos, desde la universidad en que programaba en PASCAL programas para la consola, no había vuelto a tocar nada relacionado con Windows, y menos <strong>programar en C sobre Windows</strong> (¡herejía!).</p>
<p>Pero por razones sobrenaturales (trabajo), he tenido que programar en C sobre Windows. Al principio me dieron el Visual Studio 2005 (o algo así), y nada más ver que era bastante lioso para lo que quería hacer, me decidí a usar DevCpp que es libre, usa MinGW y puedo programar para Windows usando la API Win32.</p>
<p>Después de este rollo que os he soltado, viene lo que pretendía contaros, y es <strong>cómo acceder al registro de Windows usando el lenguaje C</strong>. Puede parecer difícil, pero la verdad es que los señores de Microsoft tienen una buena cosa llamada <a href="http://www.msdn.com">msdn</a>, en la que encuentras cualquier cosa siempre que sepas más o menos donde buscar. Para este caso podemos encontrar toda la información relacionada con el registro <a href="http://msdn2.microsoft.com/en-us/library/ms724875(VS.85).aspx">aquí</a>.</p>
<p>Pero no os voy a dejar a la buena de dios, así que os voy a poner un pequeño ejemplo de <strong>cómo acceder a una clave del registro</strong>, para que podáis saber más o menos cómo funciona.</p>
<pre class="brush:c">#include &lt;windows.h&gt;

const char *ruta_reg = "Ruta\\del\\registro";

char *get_clave (char *clave) {

    DWORD BufferSize = 2048;
    DWORD cbData;
    DWORD dwRet;
    DWORD regType;
    HKEY hkey;

    if (RegOpenKeyEx (HKEY_CURRENT_USER, TEXT (ruta_reg), 0,
                      KEY_READ, &#038;hkey) == ERROR_SUCCESS)
    {

        PPERF_DATA_BLOCK PerfData = (PPERF_DATA_BLOCK) malloc (BufferSize);
        if (PerfData == NULL) {
            printf ("Error\n");
            return NULL;
        }

        cbData = BufferSize;
        dwRet = RegQueryValueEx (hkey, TEXT (type), NULL, &#038;regType,
                                 (LPBYTE) PerfData, &#038;cbData);

        /* Get a buffer that is big enough. */
        while (dwRet == ERROR_MORE_DATA) {
            BufferSize *= 2;
            PerfData = (PPERF_DATA_BLOCK) realloc (PerfData, BufferSize);
            if (PerfData == NULL) {
                printf ("Error\n");
                return NULL;
            }

            cbData = BufferSize;

            /* Conseguimos el valor de la clave */
            dwRet = RegQueryValueEx (hkey, TEXT (clave), NULL, &#038;regType,
                                     (LPBYTE) PerfData, &#038;cbData);
        }

        /* Error */
        if (dwRet != ERROR_SUCCESS) {
            printf ("Error\n");
            return NULL;
        }

        printf ("%s\n", (char *) PerfData);

        return (char *) PerfData;
    }

    return NULL;
}</pre>
<p>Sólo tenéis que cambiar la constante <code>ruta_reg</code> por una válida (que esté en <code>HKEY_CURRENT_USER</code>, ya que creo que si no eres administrador no puedes acceder a otra) y pasar como parámetro <code>clave</code> el nombre de la clave de la que queremos conocer su valor.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.4bits.es/accediendo-al-registro-de-windows/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
