Skip to content

Running Windows XP in Windows 8

I wanted to run some of my old games (notably Riven) on my shiny new Windows 8.1 machine, but it wouldn't even try to install on a 64-bit operating system. Luckily, Oracle offers VirtualBox to run virtual machines, and Microsoft offers a Windows XP virtual hard drive (.vhd file) through its Windows XP mode for Windows 7. Note that it won't run directly on Windows 8, but you can extract the .vhd file as outlined by lifehacker:

Then use 7-Zip open the EXE file as an archive.

Within that archive, find the sources/xpm file within it, and extract that folder to your hard drive.

Finally, in the extracted xpm file, you'll find a file called VirtualXPVHD. Export it and rename it to VirtualXPVHD.vhd

In VirtualBox, create a new virtual machine running Windows XP, and instead of creating a new virtual hard drive, use the one created above.

This will give you a new virtual machine that will require you register within 30 days, which you can't do (since Windows XP isn't supported anymore). We'll fix that later.

Start up the virtual machine, deal with the craziness of mouse capturing (toggle the right control key to get the mouse back) until you install "Guest Additions":

In the "Devices" menu in the virtual machine's menu bar, select "Insert Guest Additions CD image" then run that installer in the virtual machine. Now the mouse should integrate smoothly.

In the VirtualBox Manager, in the Network tab, unclick "Cable Connected". You don't want this virus-friendly operating system talking to the internet!

To activate Windows XP, you can try the file named KEY in the exe file with the virtual hard drive, but the comments on lifehacker indicate it won't work. I got a new bios from vmlite, and install it as:

path\to\VirtualBoxFolder\VBoxManage.exe setextradata your-vm-name "VBoxInternal/Devices/pcbios/0/Config/BiosRom" "path\to\pcbios.bin"

And it all seems to work. I don't feel guilty about using a pirated operating system license, since I am running Windows 8 legally, and Microsoft won't sell me XP.

Installing CD's is a pain, and Riven wants to keep swapping them, but making them virtual images makes it much easier. Install ISORecorder (the Windows 7 version works with Windows 8) and now the contextual menu (right-click) for CD's includes a "Create Image from CD" option. Save with the iso extension, and VirtualBox will mount them just fine.

Unfortunately, I now do not have any time to play anything.

Setting up git

Now that I have my computer working, I want to get back at my github repositories. I could type my password with every push, but it's easier to use SSH with a key pair. Since I'm using Putty for shell access, I use Puttygen that comes with it. The problem is that Puttygen's format is not the right one for git. There are recommendations online to set $GIT_SSH to use plink with Pageant, which does use Puttygen's format, but I read that github won't support that, so I ended up doing the following:

Create a key pair with Puttygen. In the conversion menu, create a file in openSSH format. Create the file ~/.ssh/config:

Host github.com
	User git
	IdentityFile /path/to/openssh-format-privatekey

At github.com add the public key that you created. Back in Powershell, in the directory with the local repository, do

git remote set-url origin git@github.com:username/repo-name.git

to use SSH. Now git push origin master will push the local master branch back up to github without needed a password (if you created the private key with a passphrase, you will have to enter that.

In putty, for each host, set Host Name in the Session tab and select the private key (in Puttygen format!) in the Connection->SSH->Auth tab.

Working with Amazon S3

I use Amazon S3 for static storage, since nearlyfreespeech.net charges for storage. I've written how I've set up my .htaccess and my PHP files to use it. But now my work has decided to block all access to S3 (as "personal storage sites"), so I can't use my bililite.s3.amazonaws.com sites any more.

But I'm smarter than that; I'll just use a CNAME DNS entry to point to the S3 site. They're not blocking cdn.bililite.com. Unfortunately, it's not that simple. Amazon uses the domain to determine the bucket, so cdn.bililite.com has to point to cdn.bililite.com.s3.amazonaws.com. (remember that external CNAME's have to have the extra period at the end!), meaning the bucket called cdn.bililite.com, and I have been using bililite as my bucket name.

You can't rename a bucket. So I have to create a new bucket called cdn.bililite.com, and now I have to copy all the files from the old one. That's also not so simple, since downloading from one bucket and uploading to another takes forever for thousands of small files. Luckily, Amazon has created a command line interface to S3 that lets you do in-the-cloud copying.

Download and install that, then go to Powershell. Enter

aws configure

and enter your AWS keys (you can enter a default region as well). Note that these are kept in plaintext in ~/.aws/credentials, so keep your computer safe!

Then, aws s3 ls will list all of your buckets, and aws s3api get-bucket-location --bucket bucketname will list the region. None as a region name means us-east-1, as far as I can tell.

To copy the entire bucket, do

aws s3 cp s3://source-bucket s3://target-bucket --recursive --region region-of-target-bucket --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers

(if the region is the default region you set up with aws configure, you can leave out the --region option. I wasn't smart enough to include the grants option, which makes the copied objects public (hence read=AllUsers), and I couldn't figure out how to change the permissions with the command line interface, so I had to go back to the online Amazon AWS console and set the permissions there (open the bucket, select all the folders, and select "Make Public"). That took more than an hour, but at least it was in the cloud, not running on my computer.

Now, in order to be able to load things like fonts which obey the cross origin restrictions (why fonts? I don't know. AJAX I can sort-of understand), in the AWS console, under Permissions select Edit CORS Configuration to:

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
    </CORSRule>
</CORSConfiguration>

Now I have Amazon S3 access that is not blocked!

Setting up a New Computer

It's been more than six months since I've posted; I'm still alive and well but haven't had the time to be hacking. Plus our house was robbed and the only thing of value that was taken was my computer, and it's taken me a while to replace it. One of the nice things about the cloud is realizing how little I needed my own machine to get everyday work done; the biggest inconvenience was changing all the passwords that I had stored locally.

But now I have a new Windows 8.1 machine (in my heart I'm a Mac, but I'm cheap). So these next few posts will be my own notes on how to set up a machine that does what I want, so I don't have to remember it all again.

First of all, in Remove Programs, get rid of all the cruft (including the "free trial" software including antivirus). If it's not obvious, you're not gonna use it. Activate Windows Defender.
Go to the Start screen and delete just about everything (a lot of right-clicking). The goal is to create a simple screen of what I want.

Next, install Chocolatey. That makes installing everything so much easier, and lets me rely on open-source-minded people to install useful things without cruft. In a cmd.exe window, run:

@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin

It's kind of annoying that Powershell itself makes running things harder, but Microsoft is trying to save me from myself.

From now on, I want to run in Powershell. Create a shortcut to it in C:\ProgramData\Microsoft\Windows\Start Menu\Programs (that seems to be the only way to pin a shortcut to the Start screen, though I may be wrong. Didn't do enough experimenting on that; this worked, so I was done). Use the properties on that to set the initial directory and the screen colors (I wanted a black background, since the red and green colors that git uses look terrible against the royal blue default), and the initial screen size. Pin that shortcut to the Start screen.

Create a file named profile.ps1 in My Documents/WindowsPowerShell and include a line of $env:Path += ";C:\Program Files (x86)\Git" so that I can use git commands directly from the command line (no more separate git bash). Any other startup code goes there.

Note that scripts, including the profile, will not be run until the Execution Policy is reset below.

Right click that shortcut to Run as Administrator, and start installing:

Set-ExecutionPolicy RemoteSigned

choco install git
choco install putty
choco install filezilla
choco install notepadplusplus
choco install CloudBerryExplorer.S3
choco install gnucash
choco install libreoffice
choco install 7zip

Evidently I could have used

choco install google-chrome-x64
choco install firefox
choco install itunes

But I didn't realize that at the time and downloaded them from their respective websites.

Then find all those programs on the Start screen (just start typing the name) and pin them, then move them where I want.

Then enter the SFTP settings for all my websites in Filezilla and Notepad++ NppFTP, copy over the documents I wanted from my old (thankfully unstolen) computer, and I had a working machine.

One thing to note is that Filezilla stores passwords in ~\AppData\Roaming\FileZilla in plaintext, which is great for changing computers and for finding passwords you've forgotten, but it means that if your computer is stolen or infected, you could lose everything. There are ways to avoid this, but for now I'm relying on hope, which is not a strategy.

Javascript Syntax-Highlighting Code Editor

I suppose everyone knows about this, but I just discovered CodeMirror, a javascript, drop-in (not dependent on any other library) text editor that does syntax highlighting. It's smooth and fast. I'm still going to be playing with my editor (as part of the bililiteRange package), since it's been a useful learning experience, but if you want a professional-level editor, go there. I won't be insulted.

New bililiteRange plugin, ex

There have been lots of times that I've wanted to be able to keep my hand on the keyboard when editing, rather than running off to the mouse all the time. There's an implementation of VIM in Javascript but I figured I would learn something by doing it myself. My goal is vi, not vim, since I don't need anything that sophisticated.

The first step is implementing the line-oriented part of vi, called ex, based on the manual from the sourceforge project. My version is based on bililiteRange, and depends on the bililiteRange utilities and undo plugin.

Use it simply as bililiteRange(textarea).ex('%s/foo/bar/');, passing the ex command to the ex() function. The biggest difference from real ex is that this uses javascript regular expressions, rather than the original ex ones. Thus s/\w/x/ rather than s/[:class:]/x/, and use ?/.../ rather than ?...? to search backwards (the question mark is used in Javascript regular expressions so I don't want to use it as a delimiter).

See a demo.

See the code on github.

Continue reading ›

IE11 bug with Ranges

Try the demo in Internet Explorer 11 and in a real browser.

IE now implements Range objects, representing a range of text that may span several elements. It's the basis for the standards-based part of bililiteRange. And it almost works. It's a little flaky: inserting text that contains '\n' without '\r', what I consider the "normal" way, automatically inserts the '\r'. Then using node.nodeValue returns a string without the '\r', but Range.toString() includes them. But that I can hack around.

The real bug is that ranges cannot end with a '\n'. If you try, the range is truncated. I can't find any way around that, so I had to change the way bililiteRange returned text: I went from range.toString() to element.textContent.slice(). Since that works with no other changes, I suspect that the error is in IE's toString() function itself rather than reflecting an underlying error in the Range.

Now to report that to Microsoft.

Better Javascript testing

Evidently I'm doing test-driven development wrong. Or at least it could be easier. I will have to look at Google's karma to automate the testing (rather than running the test suite in each browser individually). That of course means I need to start using Node's npm package manager (which I probably should anyway, since all the cool kids are). I've been using chocolatey for installing programs, but it explicitly is designed to not overlap with Node and its package manager (though it will install Node itself).

This post will have to be my reminder to start hacking with all of this sooner rather than later. Now I have to see patients...

IE 11 bugs

Turns out Internet Explorer is even worse than imagined. It's right at the bottom of the Uncanny Valley--close enough to a real browser to make it look like it works, but lots of near-impossible-to-track-down bugs that make life miserable. Turns out that Node.normalize is broken (see the bug reports and a workaround), so I had to add a test in bililiteRange to check for that, and not bother normalizing text if it's broken. Normalization just means merging adjacent text nodes, so losing it makes things less efficient but it should still work. I'm not going to lose sleep over Internet Explorer's inefficiencies.

Internet Explorer 11 Mysteries

Trying to debug bililiteRange in IE11; some of the problems were easily fixed with .replace(/\r/g, '') liberally scattered about, since IE really likes its return characters in <div>s (anything that is not a <textarea> or an <input> and will add them even if I am just inserting a newline.

I'm still getting a WrongDocumentError on some tests, but when I run them individually they pass; there must be some subtle global interaction that I am just not getting. I will consider those passed for now, though it is annoying seeing the red when I run the tests.

That leaves one error in find, one error in sendkeys, and whole bunch in ex, which isn't officially working yet anyway. Progress!