Fixing Windows font scaling without restarting

Windows 7 and Windows Server 2008 include the ability for each user to set their font scale. This is fantastic, except for a legacy complication: the old bitmap fonts MS Sans Serif, MS Serif and Courier have specific versions for each font scale, but these are never changed after Windows is installed. In previous versions of Windows, the fonts were replaced with the correct versions for the selected font scale, which is why a system restart was required

This means that these bitmap fonts can be out of sync with the currently selected font scale. This is typically only a problem for legacy applications, but it is ugly in those cases!

More background is available at the MSDN blog http://blogs.msdn.com/b/developingfordynamicsgp/archive/2009/11/25/windows-7-bitmap-fonts-and-microsoft-dynamics-gp.aspx and the follow-up post http://blogs.msdn.com/b/developingfordynamicsgp/archive/2009/12/02/more-on-windows-7-bitmap-fonts-and-dpi-settings.aspx

In our situation, it was even worse: the client was running a Remote Desktop Services environment, where restarting the server was really out of the question.

So I wrote a little fix-it app that dynamically adjusts all the font scaling registry settings and installs the correct fonts for the selected font scale.  You may need to log off and log on again, but in most cases, no restart is required.  It is setup for 100% and 125% only, and I provide this app here only as a useful tool.  No support or warranties, etc, etc.  Use at your own risk!

Download Fontsizefix.zip.

Update 1 Jul: As I discussed this blog with Peter Constable, I realised that I didn’t really describe what the tool did.  So: fontsizefix updates the various metrics in HKCU\Control Panel\Desktop, and a couple of LogPixels registry settings in HKLM\SYSTEM\CurrentControlSet\Hardware Profiles\CurrentSoftware\Fonts and HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontDPI\LogPixels, updates the fonts key in the registry to point to the correct versions of MS Sans Serif, MS Serif and Courier, and then RemoveFontResource and AddFontResource in order to get the correct version of the font loaded.  I’m sure it’s not 100% but it got us over a hurdle with the terminal services environment.  For purposes of support, it was easiest to make a tool that did the whole lot rather than document a bunch of registry tweaks which are easy to trip over on, and then we figured we might as well make it available to other users as well…

Lunch Time Racing

Every Thursday lunch I try to get out with my mates for a hard ride somewhere in the foothills of Mt Wellington. Today’s format was slightly different to most of the rides, and debilitating!  Stu, our resident hard man (although he just went abroad and has come back with a soft centre, but we’ll soon fix him up again), suggested we do interval races: hospital to bridge, about 2.5km, gentle for the first 800m, and then 5.3% for the next 1.6km, recover over the next 4km of climbing (Strickland Ave to Fern Tree Tavern) and race again after that.  I foolishly suggested, as it was a beautiful winter day, that we race up to the Springs at 700m elevation, instead of to Neika at 500m elevation.  We would finish with an individual time trial on Huon Rd of 3.6km.

We met in Hobart city — a small bunch of 4 today — and rode up Macquarie St towards Mt Wellington, just warming up until we got to the hospital.  As soon as we hit the hospital, Stu upped the tempo and shortly after took off up the road.  We let him go.  Rode past the Cascade Brewery, not that we noticed it.

Cascade Brewery

We settled into a decent tempo with Stu about 100m up the road, and discussed if we’d try and drag him back.  There was a distinct lack of enthusiasm from the bunch.  Iain said he was saving himself for the Springs push.  More on that later.  So it was up to me.  I hit out hard, knowing that the only way to get past Stu would be to blow past him too fast for him to jump on.  I tried to keep as quiet as I could so he wouldn’t be ready for me.  I caught Stu in about 20 seconds, travelling at about 33km/h, knowing that I couldn’t keep that pace up very long at all — and indeed I hit threshold almost immediately after that and started to go into the red, really a bit early in the ride for that!  But mission accomplished!  I got to the end of the race section — a bridge — about 20 seconds ahead of Stu, and a good 1 1/2 minutes ahead of the bunch of two.  Shame on you Iain!

Strava tells me I rode from the Cascade Brewery to the bridge at an average speed of 24.8km/h, which is my second best performance on that segment.  But my best was, shall we say, ‘slightly’ wind assisted.

Tempo up Strickland Ave was good, helping my heart rate to come down, but my legs were crying out all the way up, filled with lactic acid and heavy and slow.  I was really wondering about the feasibility of the Springs climb.  But the race was on and I had to go.

Pillinger Drive: Where the pain really starts

Scott turned up Pillinger Drive a little early having decided that riding this hard was not in his plan for today, and the rest of us followed him a minute later.  I led up the initial section, trying to set a hard pace, until we caught Scott and pushed past him.  At around that point I believe we dropped Stu, but I didn’t notice until a little while later Iain rode up alongside me and matched me pedal turn for pedal turn up the climb, at a ferocious and gruelling (for us) pace.  I just kept hoping he would crack but I knew I couldn’t last much longer.  My legs felt like lumps of lead on the pedals and I my breathing was nearly out of control.  Eventually, at just 1.3km into the climb, I just threw in the towel and backed off for a moment.  However Iain kept the pace up just that bit longer, and was away.  A couple of seconds later I got back into the swing of things, and even that 2-3 seconds was enough to rejuvenate me, and I stuck about 20m back for the rest of the climb.  Each time Iain climbed out of the saddle, I followed suit.

Big Bend — that smooth road is deceptive, this corner is the only smooth tarmac on the whole Springs climb

At Big Bend (the picture is from another ride), I pushed hard around the corner, but only closed about 5 metres, not enough to close the gap.  About 1km past Big Bend, the gradient eases from 8% to 4%, and all I could think of was getting there and hopefully pushing my pace up enough to catch Iain’s wheel.  But it was not to be.  As Iain hit the gentle 3-4% gradient section he, obviously, accelerated, and while I was able to match his acceleration, I could not pick up enough speed to catch him.  He sprinted up the final 100m, and I just couldn’t face doing the same, knowing I would not be able to catch him!  It was a phenomenal climb by Iain.  Even with the lactic in my legs from the first segment, I still cracked my previous best by 1:20 on this climb, so I was pretty happy.  I even held the KOM on Strava for the segment, for 5 minutes, until Iain uploaded his ride!

The Springs – a little busier when the Google-Car went through than when we were there!  Yes, that road keeps on going up…

When I reflect on the times that riders such as Cadel Evans and Richie Porte have achieved on this climb, I am amazed.  We averaged about 18.5km/h which I felt really wasn’t too shabby for a 7% gradient.  The road surface is rough and quite damp, both of which make it significantly harder than the raw numbers might indicate.  But from what I understand Cadel was hitting speeds of over 27km/h up the climb and we hadn’t even hit the steep bit of the climb to the summit.

After descending carefully from the Springs to Fern Tree – the road was still damp from the morning frost — we rolled to the Strickland Ave corner and set ourselves up for the final segment — the 3.6km downhill time trial on Huon Rd from Strickland Ave to the Skyline Petrol Station.  This section of road has a 5% gradient (downhill of course!), is smooth, with well cambered gentle bends and is really ideal for this scenario.  I am happy to say I took the line honours on this section, just catching my 10 second man Iain as we reached the petrol station, with an average speed of 58.6km/h.

I did this ride in my Strava gear which was donated by the boys at Strava.  I hope I did it justice!  As always, you can see the ride on Strava:

<br><br><br><br><br><br><br><br><br>The Tour <br>

The Tour of Tasmania is coming to town in a few months, and they’ll be climbing the mountain in a Team Time Trial. Innovative, but a bit of a strange decision, I’d have thought. The winning team will be the one with the best 5 (assuming 5 over the line rule) climbers. An Individual Time Trial would have been more sensible, but a TTT will be a sight to watch!

Notes on a virus

 This morning a coworker logged in and was greeted with a dialog box he did not expect:

There is no disk in the drive. Please insert a disk into drive \Device\Harddisk2\DR6.

This was immediately suspicious.  We quickly fired up Process Explorer to identify what could be causing the problem, and found a cmd.exe process that had been spawned by winlogon.exe, with the following command line:

“C:\Windows\System32\cmd.exe” /c echo [autorun]>>F:\autorun.ini
Alarm bells ringing!  There’d be no reason a legitimate app would be trying to do this…  F: is a card reader on my coworker’s machine, which he has never used, and hence is empty, which is why this message arose in the first place.  He is running the most recent version of F-Prot, with up to date signatures, but that did not pick up this malware.
Now we knew there was something malicious afoot on his computer, we decided to try and capture as much information about the issue as possible.  Unfortunately, we missed the first few steps that the virus was taking, and have no information on how it got onto to the computer in the first place, but here’s the rest of what we found.
The first thing we spotted was that winlogon.exe had a version resource indicating it was created by Microsoft, but it also had no valid certificate, and the details were not consistent:
Curiously enough, we also spotted that it was a .NET application.  I haven’t seen a .NET virus before…  Looking at the process details, we could see it was running from %AppData%, which is certainly not kosher:
We took a look at the folder, and saw a couple of other files, spread.exe and MSNMessengerAPI.dll.  Looks like it may spread through Windows Messenger?
In Process Explorer, sure enough, spread.exe was running.  Then something which was concerning: it appeared to be writing to what I believe is Firefox’s certificate database, accessing cert8.db and key3.db:
We also spotted a third process was spotted, svchosts.exe, which was stored in another folder: %LOCALAPPDATA%\Microsoft.  It may not be related but seems to be similar in construction.  This process was notable for a handle leak; at the time we spotted it, it had over 4700 handles open, mostly thread and duplicate file handles.  Now it was time to kill the processes.  I was expecting, given 3 processes, some complex watchdogging to prevent the processes being killed by the end user, but no, we were able to kill one after the other without any interference.
Now that there seemed to be no suspicious processes running, we took a look at the registry.  It fairly naively installed itself into HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run.

The HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunOnce key also contained a simple reference to winlogon.exe:
And curiously enough, HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows key had a reference to winlogon.exe as well:

At this stage, we zipped up the various virus files and deleted them, restarted, and so far, no residue has been detected.  It appears that the virus did not manage to elevate itself and attain administrator access, which was reassuring.
Finally we ran the following SysInternals command to give us a rough idea of what winlogon.exe references:
strings -n 16 winlogon.exe
This command picked up function import references to sqllite3 and cryptography functions, which strengthened my fears about Firefox’s certificate store.  Very few interesting strings were spotted, which suggests that they may have been encrypted.  We opted to uninstall and reinstall Firefox, creating a new profile and all, but I remain concerned about whether or not Internet Explorer’s certificate store has been compromised.
We have not diagnosed how this virus spreads, but have submitted it to F-Prot for evaluation.  I’ll be interested to see the outcome.

VMWare to Hyper-V: it’s never as easy as promised

Today I took on the task of converting one of our last VMWare Server-based VMs to Hyper-V.  This was an XP VM that is used for accounting, and with lots of software and configuration the idea of reinstalling Windows did not appeal.

So I used vmdk2vhd to convert the disk to Hyper-V format, making sure that I followed the initial preparation steps as noted in various blogs.

No joy, ended up with the dreaded “A disk read error occurred. Press ctrl+alt+del to restart” error.  with some research found sites that suggested using FIXBOOT, FIXMBR and CHKDSK in the XP Recovery Console, but I didn’t expect much success with this route and I didn’t get any.

As a side note, I could not remember the local Administrator password for the box, and ended up using Petter Nordahl-Hagen’s excellent offline password editor.

Finally, found a blog that explains how to resolve the problem using TestDisk by CGSecurity.  Ran that, went through the various steps, and finally ended up with a VM that would at least boot to Safe Mode.  After a few minutes of churn, Windows installed various drivers and I could boot to normal Windows and complete Hyper-V Integration Services install.

Or could I?  Nope.  Windows wanted to be reactivated before I could login — but I no longer had network drivers.  As I was not willing to spend the time on the phone with a Microsoft operator when at home late at night, I booted back into Safe Mode, and ran the Integration Services install from there.

No!  Another error: “Setup cannot upgrade the HAL in this virtual machine”.  Yet another blog post (and comment thereunder) to the rescue.  I ended up having to copy HALACPI.DLL from %windows%\servicepackfiles\i386 into %system%.  Rinse, reboot.  And now follow the primary steps in that same blog post – deleting the “Standard PC” entry, and now finally it’s installing.

Wait, no, it failed.  “An Error has occurred: One of the update processes returned error code 1601.”  Google again.  Wow, a Technet discussion thread returns a possible solution.  So booting into Recovery Console again to delete some VMWare drivers (VMWare Tools would not uninstall because it had a Windows Installer reference to a network drive on a machine that had been decomissioned…  Yuck.)

No way, Jose.  A bit more research and eventlog spelunking and I realised that Integration Services setup was trying to start Windows Installer — which doesn’t run in Safe Mode.  Yay!  Now what: can’t install network drivers in Safe Mode, can’t login in normal mode because I have no network drivers for boot.  Ah!  Turns out adding a legacy network adapter may give me a way forward here.  Gosh, that actually worked.  Reactivated Windows successfully.  Now I am booted in normal Windows mode, should be able to install Integration Services, right?

Well, I could now use Remote Desktop to connect to the machine — great, now I had a mouse again – and am now installing Integration Services.  We’ll see how it goes — but I’m not waiting around for it any longer tonight.

Was it worth all the pain?  Probably not.  At least I collected a few useful Hyper-V resources.  Perhaps a rebuild would have been smarter but I really like to understand the hows and whys of these problems.  And perhaps this may help someone else.

Playing with the Strava API

I had a couple of free evenings – hard to believe but it happened – and decided to try and have some fun with Strava’s API.  Here’s what I came up with…

The site will give a list of all the segments I’ve attempted, grouped by various classes of segment.  In this view, it orders within each segment by my ranking:

I can also filter those segments to show the ones I’ve never had a good crack at, or the ones where I am just slightly behind the leader, for example:

Then I decided to have some fun with the geolocation services built into iPhone and other mobile browsers (and now some desktop browsers as well!)  With this, I hacked up a little page that would show me all the segments within 5km of my current location, plus the all important competitive data to help me decide which segment to go for today!

Main site: http://durdin.net/cookbook/strava/query.php

Mobile site: http://durdin.net/cookbook/strava/nearby.php

No guarantees on these pages – they are setup to work only for my data at present, unless you know the secret incantations to populate the database with your data as well.

Why /cookbook/?  Well, because I already had a database setup and libraries for it.  In other words, I was being lazy 🙂

Bookmarklet for VAM on all segments in Strava

Have you ever created a segment with a short climb that just wasn’t quite long enough to be classified as a categorized climb in Strava?  You make a good time on the climb of the segment but VAM is not calculated…

A good effort, but no VAM to reward!

Well, here’s a little bookmarklet that adds VAM to each segment in your ride.  If it’s a downhill or flat segment, then the number won’t make much sense, but it is great for those short hard climbs.  This bookmarklet only changes the page, not the backend data, so if you reload, the tweaked VAM numbers will be gone.

After clicking the bookmarklet, note the updated VAM column!

Note also that the numbers calculated are based on the displayed elevation, distance and time values, which have been rounded, so VAM may not always come out quite the same as Strava’s more accurate calculations.

To use this bookmarklet:

  1. Right click on the following link and add it to favorites or bookmarks.
  2. When on a Strava ride page, click the bookmarklet.

The link:

Here’s the original, formatted code behind the link.

(function() {
  var t = document.getElementsByTagName(‘tr’);
  for(var i = 0; i < t.length; i++)
  {
    var tr = t[i];
    if(tr.className == ‘segment’)
    {
      var td_dist = tr.cells[3],
          td_elev = tr.cells[4],
          td_vam = tr.cells[7],
          td_time = tr.cells[9];
     
      var tm = td_time.innerHTML.split(‘:’),
          seconds = (parseInt(tm[0],10) * 60 + parseInt(tm[1],10)) * 60 + parseInt(tm[2],10),
          elev = parseInt(td_elev.innerHTML),
          dist = parseFloat(td_dist.innerHTML);
         
      var VAM = Math.round(elev * 3600 / seconds);
      var gradient = (elev / dist / 10).toFixed(1);
     
      var s = VAM.toString() + ‘ (‘ + gradient + ‘%)’;
     
      if(td_vam.innerHTML == ‘-‘ || td_vam.innerHTML.length > 4) td_vam.innerHTML = s;
      else td_vam.innerHTML += ‘ ‘ + s;
    }
  }
})();

Grindelwald Challenge: A Learning Experience

On Saturday, Iain, Chris and I drove up from Hobart to race the Grindelwald Challenge. This is a 75km race over a lumpy course, 4 laps of a riverside circuit with a decent 3% climb, followed by a steep 11% climb to a hilltop finish in the village of Grindelwald.

I didn’t feel very prepared for this race, given lots of sickness and time off the bike in the preceding month. But as opportunities to race are so few and far between, I decided to have a go anyway!

The Saturday dawned bright and cold, with the car thermometer dipping to -3.5 C on the 2.5 hour trip up to Legana where the race was to start.  We had an early start, too, as I picked up Chris at 6:45am before heading past Iain’s place and onward.

We arrived in Legana with an hour and more to spare before registration, so Iain and I decided to ride the circuit to get an idea of what we’d be up against. Chris decided to read the paper.

The circuit did not seem too challenging, with the Brady’s Lookout climb in the second half of the circuit averaging 3% for 3km. We then cut the descent short to scope out the final climb. This was much steeper but less than a kilometre in length.  I noted that my heart rate seemed to be high relative to the effort I was putting in — normally I am about 10 bpm below Iain but was sitting right on the same heart rate as him for most of this part of the ride.

The handicapper put Chris in B grade, myself in C grade, and Iain in D. The time gaps between the grades were 10 for E, 5 for D, 4 for C, and 4 for B. With 90 starters, each of the grades had a decent field, except for A, which it seems was made up almost exclusively of Genesys riders!

Brady’s Lookout summit — first ascent, 4th place I think.  When I was doing OK. (Photo: Gary Woodfall)

C grade started off at quite a manageable pace, unlike my previous race — where we were flat out from the gun.  The pace gradually increased on the road along the river, but I was feeling good and my confidence levels were increasing as I thought that I’d be able to stick the pace.  We hit the climb and I was able to ride it tempo without getting out of breath or feeling my legs.  So far so good.  Had a half-hearted effort at taking KOM points at the top of the climb but as I’d already decided that wasn’t my goal didn’t make the top 3.  I looked at my heart rate on my Garmin a few times and was surprised to see it over 180 given how I was feeling.  Things were looking good.  Second lap was a little slower than the first lap, and I sucked down a gel on the second descent.

A Grade on Rosevears Drv (Photo: Will Swan, The Examiner)

Half way along the river on the third lap I realised that I was not noticing any scenery any more, focusing on following the wheel in front of me and getting off the front of the pace line as quickly as possible.  We hit the climb, and I was sticking in the bunch, the pace was manageable.  Then D grade was spotted up the road.  Up went the pace, and I was breathing hard, struggling to keep pace, let some of the bunch go past me, then suddenly realised that the bunch was smaller than it used to be and I was off the back.

Looked back and B grade were bearing down on me.  I put in some hard effort but I was not getting back those few metres, went over the top of the climb 30 metres behind the bunch and bonking badly.  B grade streamed past me on the descent and I could not pick my pace up enough to pick up a wheel.  I was gone.

The fourth lap was an exercise in fogginess, remembered I had another gel so as I descended, I ate that as well but it was too little too late.  Rode along at 30km/h instead of 40km/h — legs wanting to cramp…  A grade roared past in a blur of orange.  I caught a couple of other riders, one from Hobart I knew vaguely, and then managed to put a bit of effort into the final climb.  Dropped my water bottle just after the turnaround before the climb and decided to stop and pick it up — it wasn’t going to change the outcome at this point!  I started getting out the saddle in the climb and immediately my legs started to cramp.  Sat back down and concentrated on getting up the steep climb without cramping, which I just managed.  Another C grade rider was just ahead of me and I scraped together the last of my energy to sneak past him in the last 200m.

When I got back to the presentations I discovered that Iain had managed to pick up second place in D grade, just pipped to the line because he dropped his chain!  Fantastic effort for a first race and what a shame to miss that first place!  Chris’s experience was similar to mine, he was dropped fairly early from B grade and rode the whole race on his own.  I think in his position I might have just gotten off the bike so kudos to him on soldiering on — it’s not easy.

So learning?  Preparation and food.  I knew my training was not up to scratch — I’d barely done 100km/week for the past month, due to a combination of sickness – both myself and my family, a crash which left me without a bike, some shocking weather, and just family circumstances.  I didn’t sleep enough before the race, again with family circumstances.  I probably didn’t eat enough carbs in the days leading up to the race.  My elevated heart rate (still a little high even now as I write) tells me I’m still working on recovering from the flu and fitness levels aren’t up to scratch.  It is disappointing to be dropped, even more so when my mate does so well in his first race — but I went along to enjoy myself and I’ve got to remember that!

Adding overlay notification icons to Twitter’s taskbar icon in IE9

IE9 allows you to pin sites to the taskbar. I find this feature useful, and various sites, including Twitter and Facebook make use of it to make site functionality more accessible. One feature that Twitter is currently missing, however, is notification of new tweets in the icon itself. So I’ve put together a quick little bookmarklet you can use to add this functionality to the official Twitter site on your machine.

Here’s what it looks like with 1 outstanding tweet. If more than 5 tweets are unread, I class this as an error condition and show a red X error graphic instead (okay, okay, the real story is I couldn’t be bothered making my own icons, so I’ve used some from a sample from the IE9 demo site, and they only go up to 5!)

Right click Twitter Overlay Icon (IE9 only!) and click Add to Favorites to create the bookmarklet.

Formatted code for the bookmarklet:

(function() {

var fLastCount = -1;

window.setInterval(function()
{
  try
  {
   var res = document.title.match(/^\((\d+)\)/);
   if(res) {
      var nNewCount = res[1];
      if(nNewCount != fLastCount) {
        var ico = nNewCount > 5 ? 'error' : 'num_'+nNewCount;
        window.external.msSiteModeSetIconOverlay('http://ie.microsoft.com/testdrive/Browser/tweetfeed/Images/'+ico+'.ico', nNewCount+' unread tweets');
        fLastCount = nNewCount;
      }
    }
    else if(fLastCount != 0) {
      window.external.msSiteModeClearIconOverlay();
      fLastCount = 0;
    }
  } catch(e) { }
}, 1000);

})();

Have fun!