<?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>micolous.id.au &#187; Lanning</title>
	<atom:link href="http://micolous.id.au/archives/category/lanning/feed/" rel="self" type="application/rss+xml" />
	<link>http://micolous.id.au</link>
	<description>the result of a blogging accident</description>
	<lastBuildDate>Wed, 21 Jul 2010 11:08:20 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>portal2 2.8.1 API documentation</title>
		<link>http://micolous.id.au/archives/2010/05/01/portal2-2-8-1-api-documentation/</link>
		<comments>http://micolous.id.au/archives/2010/05/01/portal2-2-8-1-api-documentation/#comments</comments>
		<pubDate>Fri, 30 Apr 2010 20:27:13 +0000</pubDate>
		<dc:creator>micolous</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Lanning]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://micolous.id.au/?p=278</guid>
		<description><![CDATA[There have been some requests that I make portal2&#8217;s API documentation available online and not just available at LANs.  So I have published a copy of the portal2 API v2.8.1.  This covers the (at the time of writing) current version of portal2&#8217;s HTTP GET and XMLRPC APIs.
Unfortunately, there&#8217;s no online &#8220;simulator&#8221; available, but [...]]]></description>
			<content:encoded><![CDATA[<p>There have been some requests that I make <a href="/projects/portal2/">portal2</a>&#8217;s API documentation available online and not just available at LANs.  So I have published a copy of the <a href="/projects/portal2/portal2_api/">portal2 API v2.8.1</a>.  This covers the (at the time of writing) current version of portal2&#8217;s HTTP GET and XMLRPC APIs.</p>
<p>Unfortunately, there&#8217;s no online &#8220;simulator&#8221; available, but that should be trivial for someone to write if they&#8217;re testing their program.</p>
]]></content:encoded>
			<wfw:commentRss>http://micolous.id.au/archives/2010/05/01/portal2-2-8-1-api-documentation/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Linux iSCSI COW Images, and Windows integration.</title>
		<link>http://micolous.id.au/archives/2010/01/23/linux-iscsi-cow-images-and-windows-integration/</link>
		<comments>http://micolous.id.au/archives/2010/01/23/linux-iscsi-cow-images-and-windows-integration/#comments</comments>
		<pubDate>Sat, 23 Jan 2010 10:38:32 +0000</pubDate>
		<dc:creator>micolous</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Computers]]></category>
		<category><![CDATA[Lanning]]></category>

		<guid isPermaLink="false">http://micolous.id.au/?p=164</guid>
		<description><![CDATA[More stuff for RetroLAN PCs, yay!
I&#8217;ve now got all the RetroLAN PCs running out of a copy-on-write image.  This means I now have a single 4GB &#8220;base&#8221; image with an installation of Windows XP, instead of having 10 of them.  It also means it is very trivial to reset the machine&#8217;s disk images, [...]]]></description>
			<content:encoded><![CDATA[<p>More stuff for RetroLAN PCs, yay!</p>
<p>I&#8217;ve now got all the RetroLAN PCs running out of a copy-on-write image.  This means I now have a single 4GB &#8220;base&#8221; image with an installation of Windows XP, instead of having 10 of them.  It also means it is very trivial to reset the machine&#8217;s disk images, which I achieved with a bit of scripting. </p>
<p>First up, I needed to setup the copy-on-write images through `device-mapper`.  This program is designed to let you setup software RAID, but it also allows snapshotting disks to provide a backup of a device at a point in time.  Unfortunately, `dmsetup` doesn&#8217;t support accessing file images, only actual devices, so I need to create some loopback devices first.</p>
<pre lang="bash" line="1"># setup loop0 as the "master" image, and mark it as read-only so no changes ever get written back.
losetup -r /dev/loop0 /store/master.img
# we need to get the size of the image in sectors for use later on.
cow_size=`blockdev --getsize /dev/loop0`</pre>
<p>The next step is to create a blank image file and loopback device to commit changes to.  For my setup, I created 200MB images.  Be aware of things like disk-based caches and automatic defragmentation will use up the allocated space very quickly, and when you run out of space in this file further writes will not be allowed, and Windows will soon crash with a blue screen of death.  (More on dealing with this in a bit)</p>
<pre lang="bash" line="1"># remove any existing COW image
rm /store/pc-1.cow

# create a new 200MB image (it's actually comes out 5% more than stated, but it allows for overheads in the filesystem)
dd if=/dev/zero of=/store/pc-1.cow bs=1M count=200

# now hook it to a loopback device
losetup /dev/loop1 /store/pc-1.cow</pre>
<p>Now we have two devices, `/dev/loop0` which contains the master image, and `/dev/loop1` which will contain any changes made to the disk.  The next step is to use dmsetup to create a `device mapper` which will layer the COW image ontop of the original image.</p>
<pre lang="bash" line="1"># create the cow!
echo "0 ${cow_size} snapshot /dev/loop0 /dev/loop1 p 64" | dmsetup create pc1</pre>
<p>This will create a device called `/dev/mapper/pc1`.  You can use it in your iSCSI setup with something like this in your `/etc/ietd.conf`:</p>
<pre lang="txt" line="1">Target iqn.2010-01.lan.someplace.iscsihost:pc1
        Lun 0 Path=/dev/mapper/pc1,Type=fileio</pre>
<p>You can then start `ietd`.</p>
<p>Now the next part is writing a script to let you reset the COW images.  `ietd` does not like you changing things while it is running, so you&#8217;ll need to make sure your script suspends all disk activity before blanking out the COW image.  Something like this:</p>
<pre lang="bash" line="1"># disconnect the COW image #1
ietadm --op delete --tid 1 --lun 0

# suspend dm activity
dmsetup suspend pc1

# clear the cow cache
dd if=/dev/zero of=/dev/loop1

# reload the cow table
master="/dev/loop0"
cow_size=`blockdev --getsize ${master}`
echo "0 ${cow_size} snapshot ${master} /dev/loop1 p 64" | dmsetup reload pc1

# resume dm activity
dmsetup resume pc1

# reconnect the COW image #1
ietadm --op new --tid 1 --lun 0 --params Path=/dev/mapper/pc1</pre>
<p>You could change this script around so that it allows you to pass in a PC number as a command-line argument, and then hook in a CGI script that will call it to reset it remotely.  In my setup, I&#8217;m using gPXE to boot from iSCSI, but it can also be used to access a URL via HTTP.  So your CGI script reads in the request IP address, and if it is one of the resettable machines, it will reset it&#8217;s COW image.  Then it sends back a gPXE script instructing it to run a DOS .com file that will reboot the computer.  For this to work you need to have your CGI script execute the command as the superuser (root).</p>
<p>One of the things about the COWs is if you reset them or they become full while Windows is running, Windows will very soon crash, and refuse to boot up again.  To better inform both yourself and users about the usage levels, you can read the information from `dmsetup`:</p>
<pre lang="bash" line="1"># dmsetup status pc8
0 8385930 snapshot 55296/409600</pre>
<p>In this example, it is indicating that the full image is 8385930 sectors, and 55296 of 409600 sectors are used in the COW image.  So I wrote a Python CGI script that reports this in a parsable fashion to clients:</p>
<pre lang="python" line="1" escaped="true">#!/usr/bin/env python

print "Content-Type: text/plain\r\n\r"

from os import environ
from subprocess import Popen, PIPE

ip = environ['REMOTE_ADDR']
d = int(ip.split(".")[3])
if d &gt;= 41 and d &lt;= 54:
  machine = d - 40
  try:
    p = Popen(('/sbin/dmsetup', 'status', 'retrocow%d' % machine), stdout=PIPE, stderr=PIPE)
    stdout, stderr = p.communicate()
    use, total = stdout.split(' ')[3].split('/')
    use, total = long(use), long(total)
    print "OK %d %d" % (use, total)
  except:
    print "ERR Problem getting parsing information"
else:
  # return error
  print "ERR Not a RetroLAN Machine"
</pre>
<p>For me, the RetroLAN machines have IPs ending in 41 to 54.  That corresponds to their PC number (retro-01 to retro-14).  This script outputs the following text file when requested via CGI if successful:</p>
<pre>OK 55296 409600</pre>
<p>This isn&#8217;t very usable for the end user, so I wrote a .NET 2.0 app called `CowBell` that runs in the system tray showing the percentage of COW usage, and notifies them if they&#8217;re over 75% usage (which means they will crash soon).  I&#8217;ve made <a href="/static/projects/cowbell/cowbell-1.0-src.7z">source code available for download</a>, which you&#8217;ll need to modify `frmMain.cs` line 37 to include the path to where you put the CGI script, and uncomment the line otherwise it <strong>will not compile</strong>.  If you make modifications to this program I do ask that you share your improvements with me.</p>
<p>This is the message that constantly pops up when you&#8217;re over 75% usage:</p>
<p><img src="http://micolous.id.au/static/projects/cowbell/cowbell.png" alt="" /></p>
<p>The application refreshes it&#8217;s status every 10 seconds, and if you right-click the icon it shows the COW usage in sectors.</p>
]]></content:encoded>
			<wfw:commentRss>http://micolous.id.au/archives/2010/01/23/linux-iscsi-cow-images-and-windows-integration/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamically changing Windows&#8217; wallpaper based on hostname</title>
		<link>http://micolous.id.au/archives/2010/01/20/dynamically-changing-windows-wallpaper-based-on-hostname/</link>
		<comments>http://micolous.id.au/archives/2010/01/20/dynamically-changing-windows-wallpaper-based-on-hostname/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 18:06:12 +0000</pubDate>
		<dc:creator>micolous</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Computers]]></category>
		<category><![CDATA[Lanning]]></category>

		<guid isPermaLink="false">http://micolous.id.au/?p=159</guid>
		<description><![CDATA[I have a situation where I&#8217;ve got 14 machines booting Windows XP over iSCSI, and they&#8217;ve all got the same computer name set, and they each need to have a different wallpaper set on each machine.  This runs the &#8220;RetroLAN&#8221; machines at StreetGeek in the new setup, to make it much easier to roll [...]]]></description>
			<content:encoded><![CDATA[<p>I have a situation where I&#8217;ve got 14 machines booting Windows XP over iSCSI, and they&#8217;ve all got the same computer name set, and they each need to have a different wallpaper set on each machine.  This runs the &#8220;RetroLAN&#8221; machines at StreetGeek in the new setup, to make it much easier to roll out updates to machines.  They&#8217;re all using the same base image, and this will get restored if things get broken.  I&#8217;m using gPXE to boot the machines in the first place, and I&#8217;ve disabled NetBIOS over TCP/IP (to avoid the problem where Windows complains if two computers have the same name), and manually set the DNS search order (because when you boot Windows over iSCSI, Windows&#8217; own DHCP client doesn&#8217;t get activated).</p>
<p>So I hacked together this VBScript that does a reverse DNS lookup on the IP, and uses that to get a specific wallpaper for the machine using a bit of copy-paste from the &#8216;net.  The script requires you use <a href="http://www.jsware.net/jsware/scripts.php5#jssys">JSWare&#8217;s JSSys</a> addin for VBScript, so make sure you have that DLL installed and registered before trying to use my script.  There&#8217;s a way to do it without JSWare using the registry, but it only applies after logging out and logging in again.</p>
<p>In the code it will try to grab the wallpaper from <code>\\logres\wallpapers</code>.  You&#8217;ll need to change this for your setup.  To activate this, I added it to the Startup folder, so about 5 seconds after login, the wallpaper is automatically changed to be for the correct machine.</p>
<p>One minor caveat: Apparently my network card was network card #2, and there was no #1.  You can check what ID your card is in <code>HKLM\Software\Microsoft\Windows NT\CurrentVersion\NetworkCards\</code>, and change the line in the script appropriately.</p>
<pre lang="vb" line="1">' Automatically setup wallpaper (autowallpaper.vbs)

Function GetFQDN(ipaddress)
  set sh = createobject("wscript.shell")
  set fso = createobject("scripting.filesystemobject")
  Set Env = sh.Environment("PROCESS")

  workfile = fso.gettempname
  sh.run "%comspec% /c nslookup " &#038; ipaddress &#038; "  > " &#038; workfile,0,true
  set sh = nothing
  set ts = fso.opentextfile(workfile)
  data = split(ts.readall,vbcr)
  ts.close

  set ts = nothing
  fso.deletefile workfile
  set fso = nothing
  for n = 0 to ubound(data)
    if instr(data(n),"Name") then
      parts = split(data(n),":")
      hostname= trim(cstr(parts(1)))
      Exit For
    end if
    hostname = "could not resolve IP address"
  next

  GetFQDN = hostname
End Function

Const HKCU = &#038;H80000001
Const HKLM = &#038;H80000002

Set objReg = GetObject("winmgmts:\\.\root\default:StdRegProv")

' Get NIC service name
objReg.GetStringValue HKLM, "Software\Microsoft\Windows NT\CurrentVersion\NetworkCards\2", "ServiceName", nicService

' Get IP address
objReg.GetMultiStringValue HKLM, "System\CurrentControlSet\Services\TCPIP\Parameters\Interfaces\" &#038; nicService, "IPAddress", addrs

' Resolve name
fullname = GetFQDN(addrs(0))
shortname = split(fullname, ".")(0)

Dim objOps
Set objOps = CreateObject("JSSys3.Ops")

r = objOps.SetWallpaper("\\logres\wallpapers\" &#038; shortname &#038; ".bmp", "center")
</pre>
]]></content:encoded>
			<wfw:commentRss>http://micolous.id.au/archives/2010/01/20/dynamically-changing-windows-wallpaper-based-on-hostname/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RetroLAN fun!</title>
		<link>http://micolous.id.au/archives/2009/09/30/retrolan-fun/</link>
		<comments>http://micolous.id.au/archives/2009/09/30/retrolan-fun/#comments</comments>
		<pubDate>Wed, 30 Sep 2009 13:35:14 +0000</pubDate>
		<dc:creator>micolous</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Lanning]]></category>

		<guid isPermaLink="false">http://micolous.id.au/?p=151</guid>
		<description><![CDATA[For StreetGeek 9.08, some people may have noticed that I changed the format of the presentation software for that event.  I really should have blogged about this, say&#8230; a month ago&#8230; but I really just ran out of time to talk about it and I really didn&#8217;t want to spoil the surprise before the [...]]]></description>
			<content:encoded><![CDATA[<p>For StreetGeek 9.08, some people may have noticed that I changed the format of the presentation software for that event.  I really should have blogged about this, say&#8230; a month ago&#8230; but I really just ran out of time to talk about it and I really didn&#8217;t want to spoil the surprise before the event. <img src='http://micolous.id.au/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><img src="/static/resc/retro2.png" alt=""/></p>
<p>In SAGAPresenter (the presentation software I wrote for StreetGeek and SAGAfest), I wrote a fully functioning PETSCII telnet server.  This meant that I wasn&#8217;t just pretending to look like a Commodore 64 with downgraded graphics, but I was sending <em>actual</em> command-codes that a Commodore 64 with a network card (and telnet client) could interpret and display.  Unfortunately, we didn&#8217;t have a C64 with a network adaptor for the LAN, so I installed <a href="http://www.paradroid.net/cgterm/">Per Olofsson&#8217;s cgterm</a>, which emulated the C64 on a normal PC without the need for special hardware.  It was also much easier to hook up to a projector for the event.</p>
<p>All the while, the traditional GTK# interface was still running, and the displays all perfectly synchronised with each other.  I used <a href="http://it.toolbox.com/blogs/paytonbyrd/howto-implement-a-text-encoder-in-net-20-13243">this PETSCII .NET encoding handler</a> to do a little bit of the text conversion, however I had to write my own code to handle the text alignment and inserting control characters in the right spot.</p>
<p>All in all it was a fun hack, with not a huge amount of code additions required.  I spent most of the time converting sponsor banners by hand to PETSCII and tweaking to get them just right!</p>
]]></content:encoded>
			<wfw:commentRss>http://micolous.id.au/archives/2009/09/30/retrolan-fun/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Disabling Utility Manager and profiting at the same time</title>
		<link>http://micolous.id.au/archives/2009/09/06/disabling-utility-manager-and-profiting-at-the-same-time/</link>
		<comments>http://micolous.id.au/archives/2009/09/06/disabling-utility-manager-and-profiting-at-the-same-time/#comments</comments>
		<pubDate>Sun, 06 Sep 2009 05:04:28 +0000</pubDate>
		<dc:creator>micolous</dc:creator>
				<category><![CDATA[Coding]]></category>
		<category><![CDATA[Lanning]]></category>

		<guid isPermaLink="false">http://micolous.id.au/?p=142</guid>
		<description><![CDATA[There&#8217;s this accessibility utility in Windows called Utility Manager that has been around for ages, and can be activated at any time during logon by pressing Win+U.  I noticed in Windows 7 there&#8217;s no easy way to actually disable this program (in fact, in most versions of Windows this is the case).  After [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s this accessibility utility in Windows called Utility Manager that has been around for ages, and can be activated at any time during logon by pressing Win+U.  I noticed in Windows 7 there&#8217;s no easy way to actually disable this program (in fact, in most versions of Windows this is the case).  After a certain person decided it&#8217;d be a good idea to turn on FilterKeys (meaning I&#8217;d have to press each key for about 3 seconds to register) and high-contrast theming and have that waiting for when I logged in, I decided to fight back (and discovered how few people set Open Firmware passwords to prevent starting Mac OS X up in single-user mode to be able to get root on it).</p>
<p>There are other programs that either disable it or <a href="http://www.softpedia.com/get/Tweak/System-Tweak/Ease-of-Access-disabler.shtml">give a gentle notification about it</a>.  I felt the need to be a bit more tactless about it, so I wrote this program that gives a nice subtle hint about how I feel when you play with my computer, inspired by a popular wallpaper.  <a href="/static/projects/junkcode/utilman/utilman.png">Here&#8217;s a totally NSFW screenshot of it</a>.</p>
<p>Of course, in a professional scenario, this probably isn&#8217;t appropriate.  Seeing as the only people playing around with it are trying to be sneaky, responding this way sends the message home.</p>
<h4>Download</h4>
<ul>
<li><a href="/static/projects/junkcode/utilman/utilman-1.0-bin.7z">Binaries (executable)</a> (4kB 7z)</li>
<li><a href="/static/projects/junkcode/utilman/utilman-1.0-src.7z">Source Code</a> (12kB 7z)  Requires Visual Studio 2005 or later to build.</li>
</ul>
<h4>Installation Instructions</h4>
<p>This software has been tested on x86\_32 and x86\_64 versions of Windows XP, Vista and 7.  It&#8217;ll probably also work on the server versions (2003 and 2008) too.</p>
<p>On Windows XP and 2003, you&#8217;ll need to also install the .NET Framework, v2.0 or later.  You can download this from <a href="http://msdn.microsoft.com/en-au/netframework/default.aspx">Microsoft&#8217;s .NET Framework website</a>.  Windows Vista, 2008 and 7 come with an appropriate version of .NET out of the box.</p>
<p>You&#8217;ll need to boot into another operating system that can write to your Windows folder.  You cannot have the Windows install you&#8217;re applying this to running while you install it.  You can do this with another installation of Windows on the same computer, plugging your hard drive into another computer in an external enclosure, or by using a Linux LiveCD that has the NTFS-3G driver installed in it (such as recent versions of <a href="http://www.knoppix.net/">Knoppix</a> and <a href="http://www.ubuntu.com/">Ubuntu</a>).</p>
<p>Rename <code>utilman.exe</code> in <code>/Windows/System32</code> to <code>Utilman.exe.old</code>.  In case something goes wrong, you can use this to restore the backup.</p>
<p>Copy <code>utilman.exe</code> from the archive into your <code>/Windows/System32</code> folder.</p>
<p>In Windows XP and 2003, you&#8217;ll also need to do the same to the version of <code>utilman.exe</code> in the hidden folder, <code>/Windows/System32/dllcache</code>, otherwise Windows File Protection will restore the original version.</p>
]]></content:encoded>
			<wfw:commentRss>http://micolous.id.au/archives/2009/09/06/disabling-utility-manager-and-profiting-at-the-same-time/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
