MTB Pro Tip: What Does That Straight Line On A Map Mean?

What does that dotted yellow straight line on the map mean?  It’s just a fire trail, right?

But that is not what it means.  Map designers like to lie about their dotted yellow lines.  What is actually means is:

Marc will be…

…walking…

…his…

…fancy…

…mountain…

…bike.

That last hill has an average gradient of over 50%.  It wasn’t so much walking as scrabbling to haul the bike up that.

The rest of the ride didn’t get much better.  Very overgrown, but no where near as steep, only 13% average, rough — too rough for Marc’s mediocre abilities — and lots of fallen branches for variety.  Don’t think I’ll try commuting that route again.

More on the pngimage unit in Delphi XE2

After submitting the issue reported in How not to do exception classes in a Delphi library to Embarcadero (QC102796) they asked me for a test case.  Didn’t make much sense to me but I duly wrote one and am about to submit it.  However, in the process I collected a lot more information about work that should have been done on the Vcl.Imaging.pngimage unit when it was integrated into the Delphi source. Here’s the full list of the exception classes and what should be done with them.

  • EPNGError should inherit from EInvalidGraphicOperation or be eliminated as it raises inappropriate exceptions
  • EPngUnexpectedEnd should inherit from EInvalidGraphic
  • EPngInvalidCRC should inherit from EInvalidGraphic
  • EPngInvalidIHDR should inherit from EInvalidGraphic
  • EPNGMissingMultipleIDAT should inherit from EInvalidGraphic
  • EPNGZLIBError should inherit from EInvalidGraphic
  • EPNGInvalidPalette should inherit from EInvalidGraphic
  • EPNGInvalidFileHeader should inherit from EInvalidGraphic
  • EPNGInvalidFileHeader should inherit from EInvalidGraphic
  • EPNGSizeExceeds should inherit from EInvalidGraphic
  • EPNGMissingPalette is unused and should be deleted
  • EPNGUnknownCriticalChunk should inherit from EInvalidGraphic
  • EPNGUnknownCompression should inherit from EInvalidGraphic
  • EPNGUnknownInterlace should inherit from EInvalidGraphic
  • EPNGNoImageData should inherit from EInvalidGraphic
  • EPNGHeaderNotPresent should inherit from EInvalidGraphic

The following three exceptions are really reimplementations of existing exception classes and should be abolished entirely:

  • EPNGOutMemory should just really be replaced with RaiseLastOSError.  Or, if backward compatibility for this exception is really needed then inherit from EOutOfMemory
  • EPNGNotExists is not used unless USEDELPHI is not defined, which it is…
  • EPNGCouldNotLoadResource masks a number of other exceptions and should if possible be removed entirely.  The code in question re-raises an exception and buries the original error with an entirely unhelpful secondary exception (and what is that exit; doing in there?).
  try 
    ResStream := TResourceStream.Create(Instance, Name, RT_RCDATA); 
  except
    RaiseError(EPNGCouldNotLoadResource, EPNGCouldNotLoadResourceText);   
    exit; 
  end;

Finally, these three need to inherit from EInvalidGraphicOperation:

  • EPNGCannotChangeTransparent should inherit from EInvalidGraphicOperation
  • EPNGInvalidNewSize should inherit from EInvalidGraphicOperation
  • EPNGInvalidSpec should inherit from EInvalidGraphicOperation

In a number of locations EPNGError and Exception are also raised (albeit sometimes in code that is $ifdef‘d out of use), often with blank error messages!  For example:

    case BitDepth of 
      {Only supported by COLOR_PALETTE}
      1: DetectPixelFormat := pf1bit; 
      2, 4: DetectPixelFormat := pf4bit; 
      {8 may be palette or r, g, b values} 
      8, 16: 
        case ColorType of 
          COLOR_RGB, COLOR_GRAYSCALE: DetectPixelFormat := pf24bit; 
          COLOR_PALETTE: DetectPixelFormat := pf8bit; 
          else raise Exception.Create('');
        end {case ColorFormat of} 
        else raise Exception.Create('');
    end {case BitDepth of}

Finally, the unit reimplements a bunch of standard Delphi VCL functionality that is inappropriate to keep within the Delphi VCL codebase, including core classes such as TStream.  While these are not compiled in because they surrounded by $ifdef statements, all this code should really be stripped out for maintenance and code cleanliness/readability reasons.  Thus, all code surrounded by $ifndef UseDelphi should be deleted. This is not a systematic review of the issues in the Vcl.Imaging.pngimage unit; it’s more just a rant and giving a heads up about the quality of this unit.  Embarcadero, please clean this unit up!

Lycra-clad lane hoggers and a lack of common sense

So another complaint about cyclists in a letter to The Mercury today struck me as particularly bizarre.  Not sure who is lacking common sense in this scenario.  So, read the letter:

The thing is, do you know Bowen Bridge?  Here’s a lovely photo of Bowen Bridge with what is a typical amount of traffic on it:

Bowen Bridge – photo by Wiki_Ian (CC BY-SA 3.0)

Bowen Bridge is a wide, straight bridge with great visibility, four lanes, virtually no traffic, and frequently strong cross winds.  There is absolutely no difficulty with changing lanes to pass a cyclist or two on this bridge, and certainly no danger in doing so!  And conversely, there is not enough room to pass safely without changing lanes: attempting to do this is both stupid and dangerous.  It’s not about proving a point, A. Garvey!

There really is no viable alternative for cyclists crossing the river at this point — the single side path on the bridge is rubbish filled and is difficult to access.

Now, there are plenty of roads that the letter writer could have picked on where riding double-file can be an issue, for instance, East Derwent Highway between this very bridge and Risdon Vale. I really am at a loss to understand why the letter writer picked this example!

Further analysis on the TrustedInstaller.exe memory leaks

You may have read my last 2 blog posts about the TrustedInstaller.exe leak that seems to be present in Windows 7 (Does Microsoft’s TrustedInstaller.exe have a leak? and Reproducing the TrustedInstaller.exe leak).  It was not yet clear to me whether this leak that I observed was a bug or if it is by design, so I decided that the next time I had to build a Windows VM and install updates, I would capture some more log information about the update.  I thought about using Process Monitor to capture everything, and this would certainly have captured reams of very interesting data, but this would have slowed the update install process down unacceptably on the day.

So instead, I ran the Handle program, also a part of the SysInternals suite, once a minute, and dumped its output to a text file.  The update process ran as normal, and the handles logging generated a 50mb text file, which was fairly simple to import into a database.  Now I had some data I could play with!

I picked a filename at random to look at in the logs.  I closed my eyes and pointed, and the lucky filename chosen was winlogon!  A simple search in the database came up with 4 different objects matching winlogon in the handle list:

C:\Windows\winsxs\amd64_microsoft-windows-winlogon_31bf3856ad364e35_6.1.7600.16447_none_cbe534e7ee8042ad

C:\Windows\winsxs\amd64_microsoft-windows-winlogon_31bf3856ad364e35_6.1.7600.16447_none_cbe534e7ee8042ad\winlogon.exe

C:\Windows\winsxs\Temp\PendingRenames\0859c097e7b9cc0153330000d0088004.amd64_microsoft-windows-winlogon_31bf3856ad364e35_6.1.7600.16447_none_cbe534e7ee8042ad_winlogon.exe_ac37d0c5

C:\Windows\winsxs\Temp\PendingRenames\aef6bd97e7b9cc0152330000d0088004.amd64_microsoft-windows-winlogon_31bf3856ad364e35_6.1.7600.16447_none_cbe534e7ee8042ad.manifest

The first entry in this list was a directory, in the Windows component store (aka Side-by-Side Store).  The second was a reference to winlogon.exe within this same folder.  The third and fourth entries gave a bit of a clue as to what may be going on, with the PendingRenames temporary folder hinting at a possible reason why the files were being kept open.

OK, so that was a very rough analysis.  But things got a bit more complicated when I started looking a bit deeper.  I picked the second entry, our winlogon.exe in the Windows component store, and had a look at the handles which were opened to that.  Here’s what I found.  Remember that this is based on minute-by-minute snapshots, so this is incomplete, but still paints a curious picture:

  • 41 different handles were logged for this one file.
  • 14 of these handles were still open at the end of the session, when TrustedInstaller.exe had no further CPU or disk activity.  (TrustedInstaller.exe remains in memory until the restart, it seems)

Why does TrustedInstaller.exe need to maintain 14 open handles to a single file until Windows is restarted?  And why does it need to open at least 41 different handles over time to the same file?  This seems horribly inefficient, as the same pattern is manifest for the 2000 or more other objects that were opened by the TrustedInstaller.exe process.

I could understand a requirement to maintain a single open handle for concurrency and replacement (PendingRenames) operations.  I’m sure there’s a reason…  There may be another update to this story yet!

Exploring Ridgeway Dam – a story by Bethany, Hannah and Marc

It was a beautiful sunny summer morning as we started off walking down the road and then onto a fire trail.  Bethany and Hannah were rather worried about snakes!  There were quite a few intersections on the bush walk, and at one intersection we took a trail that led us down a really steep hill.  Hannah was very tired.  But then we saw the dam wall looming over us and so we walked closer.

Bethany felt very scared, like the dam was going to fall on top of her at any moment!  

Bethany washed her hands in a trickle running down the dam wall, a trickle coming from a leak from high up on the wall. 

Hannah thought that it was very hot, but we had lots of water with us.

Daddy just took photos.  He didn’t seem scared.  (But was he?)

After spending some time looking at the dam wall, we climbed up a very steep and slippery path beside the dam wall, all the way to the top! 

All of a sudden, we could see the water in the dam and Bethany longed to dive in.

Unfortunately, a big tall fence stopped us, so we walked right around the dam, back up the hill and stopped at Ridgeway Corner for a picnic lunch.  Bethany was very hungry, so she ate her lunch in a matter of seconds.  Hannah had an olive, salami and cucumber roll.  Yum!

Revisiting the VistaAltFixUnit.pas code

When Windows Vista was introduced, many moons ago now, many Delphi programs ran into a problem where buttons, checkboxes and the like would disappear when the user pressed the Alt key.  This was due to a change in how and when the underscores that displayed shortcuts on these buttons was displayed.

The problem was duly noted on Borland/CodeGear/Embarcadero’s QualityCentral forum, and several workarounds were documented.  The one that became most popular online seemed to be the one known as VistaAltFixUnit.pas.  Due to its popularity, we ended integrated that unit into our code, without spending a lot of time looking at it.  Surely many eyes had already reviewed it?

Now I don’t really want to be harsh but unfortunately there are a number of issues with the unit, ranging from performance to stability issues.  Here’s a rundown.

  1. The most egregious problem is the replacement of each TForm‘s WindowProc procedure.
    constructor TFormObj.Create(aForm: TForm; aRepaintAll: Boolean);
    begin
      inherited Create;
      Form := aForm;
      RepaintAll := aRepaintAll;
      Used := True;
      OrgProc := Form.WindowProc;
      Form.WindowProc := WndProc;
    end;
    
    procedure TFormObj.WndProc(var Message: TMessage);
    begin
      OrgProc(Message);
      if (Message.Msg = WM_UPDATEUISTATE) then
        NeedRepaint := True;
    end;

    Like any naively chained procedure hook, if another component or other code also attempts to replace the WindowProc, the two will end up interfering with each other at some point, as neither component will be aware of the other, and destruction of either component, or attempts to unhook, are likely to end in access violations and tears shortly thereafter.

    Now, we also make use of the TNT Unicode components (as we have not yet moved to a fully Unicode version of Delphi — that’s a big job!), and it turns out that these components also use this approach for some of their own jiggery-pokery.  The TNT Unicode components are more important to us than this one…  guess which component suite got to keep their hook?

  2. Note that, possibly due to instabilities that became evident, the TFormObj class does not attempt to restore the original WindowProc when it is destroyed.
  3. Performance-wise, this component does a lot of work checking form status at application idle time.  As other users noted, the TApplicationEvents approach only works if no other code in the project has already assigned TApplication.OnIdle.

    In the end, we rewrote the component from scratch, and used a Windows CallWndProc hook as this is clean, simple and robust.  We also opted to live with a very minor flicker when the user first presses Alt, as this reduced the complexity of the code significantly, relying on Windows’ existing repaint infrastructure instead of reimplementing it ourselves.

    Any thoughts on the changes?  What have we got wrong?  Feel free to use this code without restrictions, for what it is worth — at your own risk of course!

    unit VistaAltFixUnit2;
    
    interface
    
    uses
      Windows, Classes;
    
    type
      TVistaAltFix2 = class(TComponent)
      private
        FInstalled: Boolean;
        function VistaWithTheme: Boolean;
      public
        constructor Create(AOwner: TComponent); override;
        destructor Destroy; override;
      end;
    
    procedure Register;
    
    implementation
    
    uses
      Messages, Themes;
    
    procedure Register;
    begin
      RegisterComponents('MEP', [TVistaAltFix2]);
    end;
    
    var
      FInstallCount: Integer = 0;
      FCallWndProcHook: Cardinal = 0;
    
    { TVistaAltFix2 }
    
    function CallWndProcFunc(
      nCode: Integer;
      wParam: WPARAM;
      lParam: LPARAM): LRESULT; stdcall;
    var
      p: PCWPSTRUCT;
    begin
      if nCode = HC_ACTION then
      begin
        p := PCWPSTRUCT(lParam);
        if p.message = WM_UPDATEUISTATE then
        begin
          InvalidateRect(p.hwnd, nil, False);
        end;
      end;
      Result := CallNextHookEx(FCallWndProcHook, nCode, wParam, lParam);
    end;
    
    constructor TVistaAltFix2.Create(AOwner: TComponent);
    begin
      inherited;
      if VistaWithTheme and not (csDesigning in ComponentState) then
      begin
        Inc(FInstallCount); // Allow more than 1 instance, assume single threaded as VCL is not thread safe anyway
        if FInstallCount = 1 then
          FCallWndProcHook := SetWindowsHookEx(WH_CALLWNDPROC, CallWndProcFunc, 0, GetCurrentThreadID);
        FInstalled := True;
      end;
    end;
    
    destructor TVistaAltFix2.Destroy;
    begin
      if FInstalled then
      begin
        Dec(FInstallCount);
        if FInstallCount = 0 then
        begin
          UnhookWindowsHookEx(FCallWndProcHook);
          FCallWndProcHook := 0;
        end;
      end;
      inherited Destroy;
    end;
    
    function TVistaAltFix2.VistaWithTheme: Boolean;
    var
      OSVersionInfo: TOSVersionInfo;
    begin
      OSVersionInfo.dwOSVersionInfoSize := SizeOf(OSVersionInfo);
      if GetVersionEx(OSVersionInfo) and
         (OSVersionInfo.dwMajorVersion >= 6) and
         ThemeServices.ThemesEnabled then
        Result := True
      else
        Result := False;
    end;
    
    end.

How not to do exception classes in a Delphi library

The pngimage unit in Delphi includes a bunch of exception classes to handle error conditions when handling PNG files.  That’s great, except for one problem: all the classes inherit from Exception instead of an abstract EPNGException.  Of course it would be even better to inherit from a hierarchy of abstract exception classes.

Frankly I don’t care if the image is corrupt because it has an unknown critical chunk, or if it is corrupt because it has no image data.  All I care about is that my application cannot load an image and I need that condition handled gently.

Basically, not using a hierarchy of classes means that error handling code in applications loading PNG files must either be too broad and generic (on E:Exception), or too specific (on E:EPNGUnknownCriticalChunk).  Future changes to the PNG class library for additional exception types when loading a PNG file would require every developer to add additional exception checks to every location where PNG files are loaded in order to handle that error, when in nearly every case the developer really just wants to handle EInvalidGraphic!

Even worse, this means that generic code for loading images must be overloaded with knowledge about PNG exception types, or else risk masking more serious errors such as access violations with an overarching on E:Exception clause!

So here’s the current complete list that the developer must be aware of:

EPNGOutMemory = class(Exception);
EPngError = class(Exception);
EPngUnexpectedEnd = class(Exception);
EPngInvalidCRC = class(Exception);
EPngInvalidIHDR = class(Exception);
EPNGMissingMultipleIDAT = class(Exception);
EPNGZLIBError = class(Exception);
EPNGInvalidPalette = class(Exception);
EPNGInvalidFileHeader = class(Exception);
EPNGIHDRNotFirst = class(Exception);
EPNGNotExists = class(Exception);
EPNGSizeExceeds = class(Exception);
EPNGMissingPalette = class(Exception);
EPNGUnknownCriticalChunk = class(Exception);
EPNGUnknownCompression = class(Exception);
EPNGUnknownInterlace = class(Exception);
EPNGNoImageData = class(Exception);
EPNGCouldNotLoadResource = class(Exception);
EPNGCannotChangeTransparent = class(Exception);
EPNGHeaderNotPresent = class(Exception);
EPNGInvalidNewSize = class(Exception);
EPNGInvalidSpec = class(Exception);

I’m disappointed that when this code was acquired and integrated into the Delphi source code, that this level of basic tidy up was not done.

Using out parameters in Delphi SOAP transactions

So here’s today’s little gotcha: TRemotable out parameters in Delphi SOAP interface function calls must always be initialised before the call.  If you don’t do this, at some point your client application will crash with an access violation in TValue.Make (System.Rtti.pas).

It turns out that when the TRIO component parses the Run Time Type Information (RTTI), it conflates the var and out modifiers on the parameters, and treats out parameters as var parameters (see function TRttiMethod.GetInvokeInfo).  This means that when the function is called, the TValue.Make function which collects RTTI for the passed parameters will assume that a non-nil object reference is always pointing to a valid and initialised object, even for an out parameter, and will dereference it to get additional RTTI.

The workaround is simple: just initialise all out parameters to nil before the function call.  This is good practice anyway.

I think the proper fix in the Delphi library code would be to treat out and var parameters differently in the SOAP calls, and always clear out parameters to nil within the SOAP framework.

Here’s some example code to reproduce the problem:

unit TestOutParams;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
  Soap.SoapHTTPClient, Soap.InvokeRegistry;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

type
  ITestOutParam = interface(IInvokable)
    ['{343E9171-4300-4523-A926-4904EDD652E1}']
    function TestOutParam(out p5: TSOAPAttachment): Boolean; stdcall;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function GetITestOutParam: ITestOutParam;
var
  RIO: THTTPRIO;
begin
  Result := nil;
  RIO := THTTPRIO.Create(nil);
  try
    Result := (RIO as ITestOutParam);
  finally
    if (Result = nil) then
      RIO.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  FSOAP: ITestOutParam;
  FOutputParameter: TSOAPAttachment;
begin
  FOutputParameter := Pointer(8); // simulate uninitialized local variable pointing to protected non-nil address
  FSOAP := GetITestOutParam;
  Assert(Assigned(FSOAP));
  FSOAP.TestOutParam(FOutputParameter); // this will crash
end;

initialization
  InvRegistry.RegisterInterface(TypeInfo(ITestOutParam));
end.

What’s up with Adobe updaters?

This morning, I turned my computer on to be greeted with notification of yet another update to Adobe Reader.

Now I believe that regular software updates are basically a good thing.  Yes, they are a hassle but at least Adobe is fixing bugs and security vulnerabilities, right?

But that’s where the goodness ends.  The update dialog is pretty vague as to what you are getting in the update.  Fortunately there is a Details link, so let’s click on it to see where it takes us.  Right.  It takes us to a list of all the recent releases of Adobe Reader.  So I still have no idea what is changing in this update, or even which version I am being updated to or from. This little release notes page also has an bit of a catch-22 dependency situation whereby you need to have a PDF reader (presumably Adobe Reader) installed in order to read the release notes.  Not the best dependency to have when you are trying to install Reader in the first place.

Clicking the Details link in the update doesn’t give you details of that update. 
It gives you details of all updates from all time

The Adobe Reader updater has one set of issues.  The Adobe Flash Player updater has a different set.  Oh yes, they are separate applications.  And they both run on start up (how often do you restart your computer these days?  Updaters shouldn’t be running on system start up)

The Flash Player updater is reasonably smooth, apart from the confusion of two dialogs appearing in succession, each with a handy check box.  You must not tick the check box in the first dialog, but you must tick the check box in the second dialog that appears.  Got that?  Now tell me, why do we need two dialogs for the install?  I already said “go ahead” by clicking the first Install button.

You don’t want to tick that check box

But you’ve gotta tick this one.  Now click Install again

Just a note about that license agreement link. I think Adobe must have a policy of making it difficult to find information about their products. Clicking that link takes you to a page with EULAs for all 10 thousand of their products, with each EULA in about 5 million different languages. Good luck finding the correct agreement.

But two update programs isn’t enough for one company.  We need more!  So here’s another.  This one also runs at start up and handles a bunch of other Adobe applications.

A plethora of Adobe application updates

How do you think the Adobe Reader update today finished?  Note that the version I got is now visible, now that I’ve installed it.  I give you the dreaded Restart Now button:

Three days of riding fun

After Christmas we took a family holiday up to Launceston and I brought my bike. Unfortunately I slept quite poorly each night but this meant I was up soon after 5am each morning, with beautiful still warm weather beckoning. So I went riding until my family arose from bed 🙂

Day 1 was a solo ride up along Bridgenorth Rd, pushing a little on the hills but not overly much. Took Notley Hills Rd which turned rather unexpectedly into dirt just at the start of the descent! Another rider caught me between Legana and Launceston, and that encouraged me to ride that little bit faster.

Day 2 saw me turning up at a church car park in central Launceston where a group ride was supposed to depart from at 6am. Six other riders turned up and it was, for me, a tough ride: 3 of the riders pulled away from me on the key climb of the road, and I could not take all my turns in the paceline towards the end of the ride. To finish off, I was dropped at a roundabout where I paused a little too long and I was unable to get back into the group. Still, the ride finished soon after that, with the biggest cup of coffee I’ve had in my life.

With a poor night’s sleep again bringing me out of bed at 5am, I decided on the third day to do another, longer solo ride, this time east towards The Sideling, a mountain pass about 40km from Launceston. Again, a beautiful morning, uneventful and empty roads, and a very enjoyable climb up to a lookout on The Sideling, and thence back to Launceston, somewhat faster than on the way out (downhill…) For some silly reason, I finished off by riding up the crazily steep David St, and rolled down to Stillwater for coffee with my family.

Launceston, very early

Start of The Sideling climb

At the lookout on The Sideling, my turning point

Strava: Bridgenorth   6am bunch   The Sideling