All posts by Marc Durdin

Another go at Longford – Campbell Town

I’m not sure which hurt more: the race, or the ride back.  I know which hurt longer.  Today was the day of the Longford – Campbell Town race, which was the first bike race I ever entered last year.  The day dawned fine, with the hint of rain on the horizon.  I woke early as I have been doing recently, but tiptoed out of bed and quietly ate two big bowls of muesli.  Now happily and heavily bloated, I checked all my gear, and double checked.  Figured if I had my helmet and my shoes I’d be ok.  It was still early, so I drove to Salamanca and had a coffee, read the paper, before I headed over to pick up Barry who would be racing with me today.  Barry was recovering from a nasty cold and had a bung knee, and just wanted to race for the fun of it, without real expectations of great results.

The 180km drive to Longford was uneventful, except that the hint of rain turned into real rain as we drove through the Midlands — both of us fervently hoping it would clear well before 1pm so we’d be able to race on dry roads.  Happily, it did.  The sky cleared up, the roads dried up, and the temperature was about 18 degrees.  Perfect.  Except for the wind.

When we arrived in Longford to get ourselves organised, at about 11am, the wind was a NNW at about 30km/h.  Not too gusty but still pretty strong.  We put our bikes together, pumped our tyres, checked various bits and bobs, ate some more, and headed out for a 4km warmup.  I felt like I was in great form as we headed down the road towards Campbell Town on the warmup, feet and heart barely ticking over and sitting on 40 km/h.  Then we turned to ride back to the start line and I realised it was all down to the wind.

Barry chose the wrong wheels for the day!

As I hadn’t raced for quite some time, I asked the handicapper to help me select a grade.  “What grade do you ride in Hobart?” he asked.  “B”.  “Ok, that’ll be D grade here.”   OK…  I guess?  I went back to the registration desk and told them that Phil has put me in D grade.  “They won’t need transponders, will they?” one of the people at the desk asked the other as Barry and I gave our details.  Great, so the assumption is that we won’t even get a placing.  Way to put my ego back into the box!  Good for me.  I’d say it lit a fire in my belly, except it didn’t.

There were two important pieces of information given at the pre-race briefing: first, that we’d have to walk across a wooden bridge in order to prevent accidents, and second, that riders caught on the wrong side of the road would be fined, disqualified and potentially even banned.  Apparently, over the previous races, there were a number of cars forced off the road by racers taking risky tactics.  I’ve never been one to spend much time on the wrong side of the road, so I wasn’t too bothered by this information.

E grade took off, with my mate Rob and 20 others, and it was a five minute wait for D grade.  Then we started, and the shock of race pace set in.  It wasn’t excruciating, like last year’s B grade start, but we weren’t standing around.  Some sort of organisation of the bunch started, with the front half of the bunch swapping turns on the front, but it was never very tidy.  Along this section, I was working hard but never really in danger of being dropped.

The wind was alternately a tail wind and a cross tail wind.  In the first cross wind section, the bunch split and I made the front selection, riding in the gutter in about 8th position.  I wasn’t very comfortable there and made an effort to form a second echelon, which actually felt easier than trying to focus on riding on the edge of the road with the wind trying to blow me off.  When we arrived at the bridge, I was feeling comfortable and made sure I was at the very front of the group before dismounting to avoid nasty surprises at the other end of the bridge!

After the bridge, I was on the front, and the bunch seemed to lose interest in moving quickly, and I soon found myself about 100m off the front of the bunch.  I wasn’t prepared to try and ride the next 40km solo, so I didn’t put an effort in to establish a real gap, and instead just focused on riding smoothly and consistently.  A couple of minutes later, the bunch closed up the gap and I happily rejoined them.

Each time the road turned a corner and put us into a different wind, a few more riders would disappear until I realised that there were only 4 of us left.  I was starting to feel tired, and I knew I needed to eat something.  It took me probably 5 minutes before I turned that knowledge into action, and in that time, the other three riders went up the road, and I was on my own!

This seemed eerily familiar.  We were only 30km into the race and I was looking at the prospect of riding the rest of it solo, just like last year.  The only difference being, I was near the front of the grade instead of having fallen off the back!  I settled into a rhythm and as the food (gel) made its presence known I found that I was slowly catching the rider ahead of me.  I got onto his wheel and recovered for a couple of minutes, before swapping to the front.  I was surprised a moment later to see that he didn’t stay with me but happy also — I was now in 3rd place on the road!  That’s a podium position…

I caught the next D grade rider (I was passing E grade riders regularly at this point) just before the road made a sharp turn east on the final 15km into Campbell Town.  As we swung around the corner, the road got very bumpy.  And the wind was, for the first time, on the front quarter and not the back quarter.  My speed dropped from 50km/h to under 30km/h, and I was working hard.  We worked together for a while, along with my mate Rob who we caught on this section, as we approached the one small climb in the race, and as we went over the top of the climb I looked back and saw a bunch approaching.  A grade.

A minute later and they swept past us, and I was able to jump into the front half of the bunch.  Exhilerating feeling!  I was now sitting on 60km/h and it wasn’t really hurting.  I didn’t try to take a turn on the front but anxiously checked the numbers on the other riders in this fast moving bunch.  No other D graders — I was happy!  Only one thing annoyed me — this bunch persisted on riding on the wrong side of the road!  Yes, we passed a couple of other riders, but it wasn’t necessary.

I didn’t contest the sprint, happy to roll over the line in the back of the bunch.  Second place in D grade.  My first ever podium finish!  I had to notify the race volunteers that I’d finished with a placing as I had no transponder…  Cloud nine time: my fastest ever 60km; I rode the race at a 45km/h average speed!  I’d won something!  Some cash!  It turns out the first place D grade rider, Glenn Myler, took out the whole race, having caught all of E grade.  Kudos to him — his first ever 1st place finish and he was pretty happy.  Barry was content just to finish, I think, with his head cold and bung knee.

Then Barry and I had to ride back to the car.  The wind was a little stronger, the gusts a little more pronounced.  And we were riding right into it, for the whole 60km.  We averaged a measly 23.5km/h on the return trip.  A couple of other riders came back with us, one of them bonking badly.  He’d had two Weetbix for breakfast — that’s all.  Sounds like what I did for the Grindelwald Challenge!  It was painfully slow and not helped by other cyclists going back in cars and giving us “helpful” comments out the window as they went past!

The only consolation on the return trip was roads devoid of traffic

It took forever, but we finally rolled into Longford.  All in all, a satisfying day!  Big thanks to Barry for the great company and to Iain for lending me some lighter wheels.

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: