Jacob Mulquin

Old Windows Assets

Extracting images, sounds and videos from old versions of Windows

✍️ Jacob Mulquin
📅 10/07/2022

The other day week month I had a random pang of nostalgia for old Windows icons. As a kid I used to love Windows 2000 and clung to it for a while before upgrading to Windows XP. I looked around on the Internet for not that long and couldn't really find a decent pack of all the icons and any other image files, so I decided to do it myself.

My Computer My Documents Recycle Bin Paint Notepad

Here's the gameplan:

  1. Obtain copies of Windows and install
  2. Mount the virtual hard drives
  3. Find cursors, icons, images, sounds and videos in the file hierarchy
  4. Find archive files, extract, find DLLs, cursors, icons, images, sounds and videos inside them
  5. Pass DLLs through to Windows
  6. Use software to extract .ico files from the DLLs
  7. Convert .ico to .png and optimize
  8. Organise the files nicely
  9. Wonder why you spent all that time doing this

Seems easy, right?

Locations of stuff

This section is mainly for my benefit, I'm using this document to copy and paste the commands to ensure that everything is in the correct location. Part of me thinks this should just be a single bash script but this is more fun. Feel free to change the values if you wanted to do this yourself.

1. Obtain copies of Windows and install

This part is pretty easy. Luckily for us, there is an awesome website called WinWorld. This site is run by a person named Duff who wants to preserve and share old software. Now just because Duff calls themself an enthusiast and has created this cool resource that looks totally legit, doesn't mean you should blindly trust them. With this in mind, none of the VMs will have network connections enabled (or audio or USB because they don't need it)


Installing Windows 95

Windows 95, being the oldest operating system, was the most involved to install.

Go through the install steps. You can find serial keys on the WinWorld site.

(Also here)

Restarting the computer will yield a message: "Windows protection error. You need to restart your computer".

Mount the Fast CPU Fix ISO, install and restart.

Installing Windows 98+

Mount the ISO and go for gold

All the operating systems freshly installed

2. Mount the virtual hard drives

I did some searching on how to share files between a Virtualbox guest and host without using network connection and shared folders. Turns out that it's much easier to mount the .vdi images directly using the vboximg-mount command, so I whipped up a little bash script:


# mount_vdi.sh
# $1 -- This is the full path of the .vdi to mount

VDI_FILE="$(basename "$1")"

echo $VDI_FILE

sudo mkdir -p "$MOUNT_DIR"
sudo vboximg-mount -i "$1" -o allow_other "$MOUNT_DIR"
sudo mkdir "$MOUNT_VOL0_DIR"
sudo mount "$MOUNT_DIR"/vol0 "$MOUNT_VOL0_DIR"

And also a corresponding script to unmount:


# unmount_vdi.sh
# $1 -- This is the full path of the .vdi to unmount

VDI_FILE="$(basename "$1")"


sudo umount  "$MOUNT_VOL0_DIR"
sudo umount "$MOUNT_DIR"
sudo rm -R "$MOUNT_VOL0_DIR"
sudo rm -R "$MOUNT_DIR"


With commands to execute mount and unmount:

./mount_vdi.sh "/.vdi"
./unmount_vdi.sh "/.vdi"

3. Find cursors, icons, images, sounds and videos in the file hierarchy

mkdir -p "Assets/"
cd ".vdi_vol0"
find . -iregex '.*\.\(jpg\|jpeg\|gif\|png\|bmp\|tiff\|pdf\|pcx\|ico\|cur\|wav\|wmv\|wma\|\rmi|\mid\|avi\|mpg\|mpeg\)$' -exec cp {} "Assets/" \;
cd "Assets/"
mkdir IconsRaw
find . -iregex '.*\.\(ico\|cur\)$' -exec mv {} IconsRaw \;

4. Find archive files, extract, find DLLs, cursors, icons, images, sounds and videos inside them

mkdir -p "ArchiveFiles/"
cd ".vdi_vol0"
find . -iregex '.*\.\(zip\|cab\)$' -exec cp {} "ArchiveFiles/" \;
cd "ArchiveFiles/"
for z in *; do 7z x -aou -oExtracted $z; done

Interestingly, Windows ME has far more archived files than any of the other operating systems. There's probably a tonne of redundancy

After all the files are extracted, we need to categorise them as either Archives, DLLs, assets or other types of files

cd "ArchiveFiles/"
mkdir DLLs Assets Archive IconsRaw
cd Extracted
find . -iregex '.*\.\(exe\|dll\|ocx\|cpl\)$' -exec mv {} "ArchiveFiles//DLLs" \;
find . -iregex '.*\.\(jpg\|jpeg\|gif\|png\|bmp\|wbf\|tiff\|pdf\|pcx\|wav\|wmv\|wma\|\rmi|\mid\|avi\|mpg\|mpeg\)$' -exec mv {} "ArchiveFiles//Assets" \;
find . -iregex '.*\.\(ico\|cur\)$' -exec mv {} "ArchiveFiles//IconsRaw" \;
find . -iregex '.*\.\(zip\|cab\)$' -exec mv {} "ArchiveFiles//Archive" \;

Then we have to unarchive any nested archive files:

cd "ArchiveFiles//Archive"
for z in *; do 7z x -aou -oExtracted $z; done

And finally categorise those as DLLs, assets or other types of files (I'm not going to bother checking once more for archive files)

cd "ArchiveFiles//Archive/Extracted"
find . -iregex '.*\.\(exe\|dll\|ocx\|cpl\)$' -exec mv {} "ArchiveFiles//DLLs" \;
find . -iregex '.*\.\(jpg\|jpeg\|gif\|png\|bmp\|wbf\|tiff\|pdf\|pcx\|ico\|cur\|wav\|wmv\|wma\|\rmi|\mid\|avi\|mpg\|mpeg\)$' -exec mv {} "ArchiveFiles//Assets" \;

5. Passing the DLLs through to Windows

I tried to copy and paste the files back onto the mounted directories but ran into some issues, so I decided it would be easier to make an ISO file of the DLLs and simply mount this as a CD-ROM inside Windows.

Making an ISO image from a directory is super simple on Linux:

cd ""
mkdir ISO
mkisofs -o "ISO/ Archived DLLs.iso" "ArchiveFiles//DLLs"

6. Use software to extract .ico files from the DLLs

To extract the icons from the DLLs, we are going to use an excellent peice of software from NirSoft: IconsExtract.

As all our virtual machines are not connected to the Internet, we have to put this program into an ISO and mount it on each machine. The program requires msvcrt.dll so will not work on Windows 95 out of the box, simply downloaded the DLL and extract it to the Windows folder before running.

Using the same command as with Step 5, we simply put the executable and msvcrt.dll into an ISO file.

cd "ISO"
mkisofs -o "IconExtract.iso" IconExtract

We mount the ISO for IconExtract, and the ISO for the Archived DLLs.

Then it's a matter of running the ICONSEXTRACT.EXE file on each operating system, directly from the mounted disk as the program would throw an error if it tried to inspect itself.

IconsExtract running on Windows 98

After doing the DLLs in the root directory, I ran it on the other mounted drive for the archived DLLs.

I also ran into an error when searching through the extracted DLL files in Windows ME:

IconsExtract triggering an error on Windows ME

This error seemed to occur after it had analysed the last file on the ISO, after trying to copy everything over to C:\ first to do in batches I noticed that I had run out of hard drive space. I recreated the VM, copied over and and did it in batches. I ran into another strange error where it couldn't create a "folder?", so I just had to output to a couple of different folders then use the move command to put them all together. I can see why Windows ME was so hated, it has been the operating system with the most issues in this whole process.

All Files were saved in "C:\ Icons"

Then we need to copy all the files that were extracted back into our project directory.

cd ""
mkdir IconsRaw && cd IconsRaw
cp -R ".vdi_vol0/ Icons" ""

7. Convert .ico to .png and optimize

After gathering all the .ico files, it's an easy command to convert them to .png:

mogrify -format png *

Ran into some error messages: mogrify-im6.q16: improper image header 'IESHWIZ_30977.ico' @ error/icon.c/ReadICONImage/678.. Damn.

After some searching, I think the easiest solution for these leftover icons will be the open these in GIMP and manually export as .png. GIMP also has a plugins system meaning some industrious people have already figured out how to do batch processes.

To install on Xubuntu, simply sudo apt-get install gimp-plugin-registry, it will then appear on the Filter > Batch menu. I selected the pictures from the errors previously and set them to be output in PNG format.

Honestly, after having to manually select them after Windows 95, I decided to just use the GIMP for the other operating systems because manually selecting them was a really shitty, annoying thing to do. It didn't matter that it was a bit slower.

There were also .ico and .cur files that were extracted from the file hierarchy and inside the archived files that also needed to be converted.

After that I run optipng *.png for modest 0%-1% filesize decreases when using mogrify, up to 25% for those exported by GIMP.

8. Organise the files nicely

The directory structure for each operating system will like like this:

mkdir "Output/"
cd "Output/"
mv "IconsPng/" Icons
mkdir Images Audio Video
find "Assets/" -iregex '.*\.\(jpg\|jpeg\|gif\|png\|bmp\|wbf\|tiff\)$' -exec mv {} "Images" \;
find "ArchiveFiles//Assets" -iregex '.*\.\(jpg\|jpeg\|gif\|png\|bmp\|wbf\|tiff\)$' -exec mv {} "Images" \;

find "Assets/" -iregex '.*\.\(wav\|wma\|mid\)$' -exec mv {} "Audio" \;
find "ArchiveFiles//Assets" -iregex '.*\.\(wav\|wma\|mid\)$' -exec mv {} "Audio" \;

find "Assets/" -iregex '.*\.\(wmv\|avi\|mpg\|mpeg\)$' -exec mv {} "Video" \;
find "ArchiveFiles//Assets" -iregex '.*\.\(wmv\|avi\|mpg\|mpeg\)$' -exec mv {} "Video" \;

In order to figure out how many files exist and the total filesize of each type of file, I whipped up this little one-liner:


# file_count_and_size.sh
# $1 -- Directory to look at

echo -n $(basename "$1")": " && echo -n $(ls "$1" | wc -l)" files, " && du -sh "$1" | awk '{print $1}'

9. Wonder why you spent all that time doing this

This project took much longer than I anticipated, and part of me still feels like I've missed something. I'm feeling fatigued on it so I'm saying it's good enough for now. One day I'll return and do Windows Vista and clean up the process a bit.

Was it fun? Partly. Was it worth it? Maybe. Would I do it again? Probably.

There's a lot of redundant/duplicate files in the output, so figuring out how to dedupe is also on the cards.

Anyway, here's a few pictures that were extracted:

Double click animation

Flag animation

How to move a mouse animation

Picturesque CRT

Microsoft Encarta banner

Age of Empires banner

Home network