2009-04-22

How to fix a broken registry key if Windows XP is not booting

Recently I modified the Windows XP registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Nls\CodePage\OEMCP from 437 to 65001, which resulted an immediate Windows XP system crash, and Windows didn't boot anymore, not even in safe mode. This post describes how I changed the key back without a working Windows on the machine.
  • I downloaded SystemRescueCD 1.1.7 from http://www.sysresccd.org/Download, burnt it to CD, booted the system from it.
  • I pressed Enter at the CD boot menu to boot with the default options.
  • I waited a few minutes for the SystemRescueCD Gentoo system to boot.
  • At the root@sysresccd /root % prompt (I pressed Alt-F2 at the help screen), I listed the partitions with the command fdisk -l. It turned out that my Windows XP partition was /dev/sda1.
  • I created a mount point directory with mkdir /mnt/, and mounted the Windows XP partition with mount -t ntfs-3g /dev/sda1 /mnt/p .
  • I edited the system registry with chntpw -e /mnt/p/WINDOWS/system32/config/system (see the transcript below).
  • I ensured that changes are written to disk sync.
  • I rebooted without the CD, and now my Windows XP worked.
Here is the transcript of the chntpw session:
chntpw version 0.99.5 070923 (decade), (c) Petter N Hagen
Hive name (from header):
ROOT KEY at offset: 0x001020 * Subkey indexing type is: 686c <lh>
Page at 0x54c000 is not 'hbin', assuming file contains garbage at end
File size 5767168 [580000] bytes, containing 1301 pages (+ 1 headerpage)
Used for data: 103727/5482832 blocks/bytes, unused: 2263/25616 blocks/bytes.

Simple registry editor. ? for help.

> ls
Node has 7 subkeys and 0 values
key name
<ControlSet001>
<ControlSet002>
<LastKnownGoodRecovery>
<MountedDevices>
<Select>
<Setup>
<WPA>

> cd \ControlSet001\Control\Nls\CodePage

\ControlSet001\Control\Nls\CodePage> cat OEMCP

Value <OEMCP> of type REG_SZ, data length 12 [0xc]
65001


\ControlSet001\Control\Nls\CodePage> ed OEMCP
EDIT: <OEMCP> of type REG_SZ with length 12 [0xc]
[ 0]: 65001

Now enter new strings, one by one.
Enter nothing to keep old.
[ 0]: 65001
-> 437
newkv->len: 8

\ControlSet001\Control\Nls\CodePage> q

Hives that have changed:
# Name
0 <system>
Write hive files? (y/n) [n] : y
0 <system> - OK
Please note that a similar procedure (with the exact same fdisk, mount, and chntpw comamnds) using the Knoppix 5.3.1 live CD instead of SystemRescueCD.

Please note that it is possible to edit any registry file with the Windows XP regedit. Here are some relevant links how to do this: http://smallvoid.com/article/winnt-offline-registry-edit.html; http://www.hardforum.com/showthread.php?t=1162302; http://www.911cd.net/forums//index.php?showtopic=7066.

Please note that it is possible to edit the registry with the regedit application shipping with the ERD Commander 2005 Windows XP live boot CD. Get the CD from http://www.fullandfree.info/software/erd-commander-2005/ . There is a Linux tool nrg2iso which can convert the .nrg file in the download for burning to CD. On Windows, it is possible to burn the .nrg file using ImgBurn.

Here are some methods which I tried, but they didn't work to edit the registry system registry file:
  • Using kregedit – it crashed opening the system registry file.
  • Running wine's /usr/bin/regedit – I wasn't able to specify which file to edit.
  • Running wine regedit.exe with the Windows XP regedit.exe – it failed to start up because it hasn't found some DLLs. I haven't bothered forcing it.

How to fix Ubuntu Hardy and Intrepid boot hang on a Philips laptop

If you have a Philips laptop and you want to boot Ubuntu Hardy and Intrepid on it, the system might hang indefinitely while booting (not reacting to any keypress, not even the Num Lock key). The reason for the hang may be the non-working driver for the notebook's built-in memory card reader (MMC). This post describes the solution: how to disable the driver for the memory card reader and thus get Ubuntu boot. (But you won't be able to use the memory card in Ubuntu.)

If you have another Linux boot CD at hand (such as Knoppix) which boots, and you are familiar with it, then boot it, open file /etc/modprobe.d/local on your Linux root partition, and add the line blacklist mmc_core . Reboot the machine to Ubuntu. Now it should boot normally, without hanging. By doing this you ensure that that the memory card reader driver kernel module won't ever be loaded in the future at boot time. This is a long-term solution, it survives kernel and distribution upgrades.

If you don't have an alternative boot CD at hand, then do the fixing like this. Reboot the system (power-cycle it if necessary). In the GRUB boot menu (a list of long lines starting with Ubuntu 8, press key E, in the new menu, select the line starting with kernel, press key E, press key Space, type init=/bin/bash rw , press key Enter, press key B. This will start the system boot process, giving you a shell soon. In a minute, you'll get a prompt ending with #, and the cursor blinking after that. Type bash -c 'echo blacklist mmc_core >>/etc/modprobe.d/local', press Enter. Type sync , press Enter. Wait a few seconds. Reboot the machine by pressing Ctrl-Alt-Del (or by any other means). Now Ubuntu should boot normally, without hanging.

If the instructions above don't work for you, here is a brute force, temporary fix, which won't survive some system upgrades. Do exactly as above, up to the # prompt. Then type rm -rf /lib/mmc , press Enter. Type mv -fT /lib/modules/`uname -r`/kernel/drivers/mmc /lib/mmc , press Enter. Continue with sync etc.

2009-04-18

How to set up an external monitor for watching movies with the nvidia proprietary x.org driver

This post describes how to set up your /etc/X11/xorg.conf on Linux if you have a laptop with an NVIDIA video card, and you want to attach an external monitor for watching movies with MPlayer. Please note that the external monitor is not for regular work, so normally you don't want to put windows there, or use the mouse or keyboard to interact with windows on the external monitor.

How to configure the X server

If you enable TwinView in /etc/X11/xorg.conf (possibly using the command nvidia-xconfig, you'll get one big X11 screen (DISPLAY=:0), with windows possibly spanning two two displays. This is not what you want now. What you want is to have two, independent X11 screens, the laptop's built-in LCD display (DISPLAY=:0.0) running your regular X11 session, and the external monitor (DISPLAY=:0.1) showing the movies played. (Sending audio to the external monitor's speakers is not described here.)

To configure the X.Org X11 server for this, you have to modify /etc/X11/xorg.conf the following way. You have to add a new "Monitor" section, a new "Device" section and a new "Screen" section. First make a backup of your config file: sudo cp /etc/X11/xorg.conf{,.single.good}. Then modify the config file like this:
# modifications to /etc/X11/xorg.conf

Section "Device"
# This is the original Section "Device"
Identifier "..."
Driver "nvidia"
Busid ...
Option ...
...
# ADD Screen 0.
Screen 0
EndSection

Section "Device"
Identifier "nvidia1"
Driver "nvidia"
# COPY Busid from original
Busid ...
# COPY Option(s) from original
Option ...
# ADD Screen 1.
Screen 1
EndSection

# ADD this Monitor section.
# The specified HorizSync and VertRefresh ranges are good for most
# external LCD monitors. You may want to widen them for your monitor.
Section "Monitor"
Identifier "monitor1"
Option "DPMS"
HorizSync 28-64
VertRefresh 43-60
EndSection

# ADD this Screen section.
Section "Screen"
Identifier "screen1"
Device "nvidia1"
Monitor "monitor1"
# If it doesn't work with 24, try changing to 32 (and below as well).
DefaultDepth 24
SubSection "Display"
Depth 24
# SET this to the preferred (maximum) resolution of your external monitor.
Modes "1920x1080"
EndSubSection
EndSection

# ADD or modify this ServerLayout section
Section "ServerLayout"
Identifier ...
# Multiple InputDevice entries are OK
InputDevice ...
...
# SET ... to the name of your original Section "Screen".
Screen 0 "..." 0 0
# MAKE sure that the number you specify is larger than
# the maximum width of your screens. Otherwise the mouse
# pointer may accidentally wrap one the edge of one screen
# to another.
Screen 1 "screen1" 1300 0
EndSection
Make sure that the position you specify for Screen 1 in ServerLayout is large enough, i.e. it is larger than the maximum width of your screens. http://users.tkk.fi/spniskan/switchscreen/ gives the same instructions: Define in the ServerLayout section the second screen's position to be farther away than the first screen's width.. Doing this makes sure that the mouse pointer won't accidentaly wrap from one screen to another when you move it out at the edge of any of the screens.

After modifying /etc/X11/xorg.conf, make a backup copy of the new version (sudo cp /etc/X11/xorg.conf{,.twoscreens.try}), close all applications, connect the external monitor, then restart your X11 session by pressing Ctrl-Alt-<BackSpace>. If it doesn't start up again, or you get some display configuration dialog, then there was something wrong with your modifications to /etc/X11/xorg.conf, and you have to fix it. To do so, press Ctrl-Alt-<F1> to switch to text mode, log in, then stop GDM by running sudo /etc/init.d/gdm stop, then have a look at the startup log file /var/log/Xorg.0.log , and edit /etc/X11/xorg.conf accordingly (you may have to copy it back from /etc/X11/xorg.conf.twoscreens.try first). To try your changes, run X (or sudo X), which displays a black-and-white dotted background on both screens, and an X-shaped mouse cursor on screen 0 (the laptop LCD). Exit by pressing Ctrl-Alt-<BackSpace>. If that one works, you may want to try startx to get a more interesting X session. Exit again by pressing Ctrl-Alt-<BackSpace>. Make a backup copy of the config file (sudo cp /etc/X11/xorg.conf{,.twoscreens.good}, and restart GDM: sudo /etc/X11/gdm restart.

How to prevent the GNOME panel and the icons from appearing on the second screen

Sorry, I don't know the right answer. The panels are drawn by gnome-panel. You can remove all but one, and GNOME will remember it upon relogin. If you remove all panels from a screen, GNOME will recreate the panels with the default configuration :-(. The desktop icons are drawn by nautilus. I have no idea how to disable it on the second screen. The window manager is metacity or compiz (use ps x to find out which is running). You can disable compiz on the second screen by appending the line COMPIZ_OPTIONS="$COMPIZ_OPTIONS --only-current-screen" to ~/.config/compiz/compiz-manager .

How to change the background image

Install ImageMagick with sudo apt-get install imagemagick. Then run display -window root -display :0.1 background.jpg. Please note that this will tile (repeat) copies of the image. You may want to resize the image to fit the screen size: display -window root -display :0.1 -resize 1920x1080 background.jpg, but this may ruin the aspect ratio. Use your favorite image editor (such as GIMP) to create an image of the right size. If you use GNOME, this trick might be useful: http://gnome-hacks.org/hacks.html?id=6 (but it sets the background for multiple screens).

How to move the mouse and switch the keyboard focus to the other X11 screen

There is a handy tool for that named switchscreen. Apparently there are two programs named switchscreen, one by Sampo Niskanen (http://users.tkk.fi/spniskan/switchscreen/) and one by David Antliff (http://en.gentoo-wiki.com/wiki/X.Org/Dual_Monitors#Moving_focus_between_screens and http://unlogical.net/files/scripts/switchscreen-0.4.tar.gz; alternate download for switchscreen.c: http://www.math.bme.hu/~pts/switchscreen.c). We are going the use the latter. Compile it with gcc -s -O2 -W -Wall -L/usr/X11R6/lib -lX11 -lXtst -lXext -o switchscreen switchscreen.c. (On Debian Etch and Ubuntu Hardy, you'll have to install some packages first: sudo apt-get install gcc libc6-dev x11-proto-core-dev x11proto-xext-dev x11proto-xext-dev .) Install with sudo cp switchscreen /usr/local/bin/ .

If you use GNOME, run switchscreen by pressing Ctrl-<F2>, and typing switchscreen plus Enter. You can use your desktop environment's configuration or xbindkeys to bind a key combination to switchscreen.

How to play a movie with mplayer on the external monitor

Run mplayer -display :0.1 -osdlevel 3 -fs movie.avi . If you don't see the the number of seconds elapsed, you may have to configure the MPlayer OSD font. If the OSD text is two large, append lines subfont-text-scale = 3 and subfont-osd-scale = 3 to the file ~/.mplayer/config . If the aspect ratio is wrong on the external monitor, but it is good on the LCD display, specify the flag -monitorpixelaspect X in the mplayer command line above, experimenting with values between 0.5 and 2.0 for X.

2009-04-07

How to prevent stderr log messages from interleaving on Linux

Let's suppose you have a program which forks subprocesses, and each subprocess writes log messages to the stderr they share. Since processes run concurrently, it may be possible that the bytes they write interleave (overlap). For example, process A calls write(2, "ABC\n", 4) == 4, and, at the same time process D calls write(2, "DEF\n", 4) == 4. You expect that stderr will contain "ABC\nDEF\n" or "DEF\nABC\n", depending on which write succeeds first. But this is not always the case (!): messages written can interleave, e.g. stderr might contain "ABDCEF\n\n" or something similar. This post gives some recepies how to prevent that, and thus always get either "ABC\nDEF\n" or "DEF\nABC\n".

The instructions given below were tested on Linux 2.6.22 and 2.6.24, but they may probably apply other Linux kernels and other Unices as well.
  • Use the write(2) system call to write your log messages. Avoid anything which can buffer or split the message.

    • In C, don't use printf(3), fwrite(3), fputs(3) etc.; use write(2)

    • In Java 6, don't use System.err.println; use System.err.print, and add a "\n" by hand.

    • In Python, don't use sys.stderr.write or print >>sys.stderr; use os.write(2, ...)
    • .
    • In Ruby, don't use $stderr.write or $stderr <<; use $stderr.syswrite. Don't forget to check the return value.

    • In Perl, don't use print(STDERR ...); use syswrite(STDERR, ...).

  • If stderr is a pipe, make sure you don't write more than 4096 bytes at a time. If you have a longer log message, split it to multiple log messages of at most 4096 bytes (including the newline). This size limit doesn't apply if stderr is a regular file. This size limit has been verified for the kernels above.

  • If stderr is a regular file, make sure that it is in append mode when you are writing it.

    • Without append mode, even data loss is possible, e.g. instead of "ABC\nDEF\n" you may get "ADBEF\n" (losing "C\n").

    • You can ensure append mode by using the append-redirection 2>>file.log instead of 2>file.log when invoking the program.

    • In C you can use fcntl(2) to put a file descriptor to append mode: fcntl(2, F_SETFL, fcntl(2, F_GETFL, 0) | O_APPEND). (Don't forget about checking the return values to detect errors.)

    • In Python you can use fcntl.fcntl to put a file descriptor to append mode: import fcntl; import os; fcntl.fcntl(2, fcntl.F_SETFL, fcntl.fcntl(2, fcntl.F_GETFL) | os.O_APPEND).

    • In Ruby you can use IO#fcntl to put a file descriptor to append mode: require 'fcntl'; $stderr.fcntl(Fcntl::F_SETFL, $stderr.fcntl(Fcntl::F_GETFL) | Fcntl::O_APPEND).

    • In Perl you can use Fcntl to put a file descriptor to append mode: use Fcntl; fcntl(STDERR, Fcntl::F_SETFL, fcntl(STDERR, Fcntl::F_GETFL, 0) | Fcntl::O_APPEND).

As a more generic solution (not specific to Unix), you may also consider using mutexes or semaphores to prevent concurrent writes to the same file.

2009-04-04

How to convert some LaTeX text to a high resolution PNG image

Create the TeX source file dump.tex like this:
\documentclass{article}
\pdfpagewidth2cm
\pdfpageheight1cm
\hoffset-2.3cm
\voffset-2.3cm
\begin{document}
\shipout\hbox{$\infty \sum \int$}
\end{document}

Convert it to PDF:
% pdflatex dump.tex

Make sure that pk files don't appear on the console output of pdflatex. If they happen to appear, choose a different font, e.g. \usepackage{lmodern}.

Convert the PDF to PNG with Ghostscript:
% gs -dBATCH -dNOPAUSE -sDEVICE=pngmono -r1000 -sOutputFile=dump.png dump.pdf

If you need a larger resolution image, increase the number after the -r flag above.

This solution generates a PNG with sharp edges (no smoothing). If you take a screenshot of the PDF in a PDF viewer, or you load the PDF directly into GIMP, you'll most probably get a smoothed (antialiased) image.